Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1015 lines
37 KiB

#define SCCSID "@(#)cod3216b.c 13.21 90/08/28"
/*
* Thunk Compiler - Routines for Dealing with Types.
*
* This is a Win32 specific file
* Microsoft Confidential
*
* Copyright (c) Microsoft Corporation 1987, 1988, 1989, 1990
*
* All Rights Reserved
*
* Written 12/03/88 by Kevin Ross for OS/2 2.x
* 11.06.90 Kevin Ruddell adapted to Win32
*/
#include <stdio.h>
#include "error.h"
#include "thunk.h"
#include "types.h"
#include "symtab.h"
#include "codegen.h"
#include "cod3216.h"
unsigned int fgOutputFlag = 0;
unsigned int gEDI,gESI;
unsigned int iTransferBytes = 0;
extern int fReAlignmentNeeded;
extern void cod32_UnHandleBoundaryCross(unsigned int, TypeNode *, unsigned int);
extern void cod32_UnHandleFixedSize(unsigned int,TypeNode *);
/*** cod_UnpackStruct32(pMNode)
*
* This function will unwind any pointer manipulation done to make
* the call.
*
* Entry: pMNode - pointer to a MapNode.
*
* Exit: generates code to unpack structures.
*
* History:
* 28-Nov-1988 JulieB Created it.
*/
cod_UnpackStruct32(MapNode *pMNode)
{
unsigned int NullLabel;
TypeNode *pFromList, *pToList;
printf("\n; ****> BEGIN Pointer/Structure Unpack Section\n\n");
pFromList = pMNode->pFromNode->ParamList;
pToList = pMNode->pToNode->ParamList;
while (pFromList && pToList) {
if (pFromList->iPointerType) {
fgOutputFlag = pFromList->fSemantics & SEMANTIC_OUTPUT;
printf("\n;Undo Pointer %s --> %s\n",
typ_NonNull(pFromList->pchIdent),typ_NonNull(pToList->pchIdent));
/*
* Load source address into esi.
*/
printf("\n\n\tmov\tesi,[ebp-%u]\t\t;%s temp address\n",
pFromList->iTempOffset,typ_NonNull(pFromList->pchIdent));
printf("\tor\tesi,esi\n");
printf("\tjz\tL%u\n\n",NullLabel=gen_LabelCount++);
/*
* Load destination address into edi.
*/
printf("\n\n\tmov\tedi,[ebp+%u]\t\t;%s original address\n",
pFromList->iOffset,typ_NonNull(pFromList->pchIdent));
cod32_UnHandlePointer(pFromList,pToList);
printf("\nL%u:\t\t;No action required\n",NullLabel);
}
pFromList = pFromList->pNextNode;
pToList = pToList->pNextNode;
}
printf("\n; ****> END Pointer/Structure Unpack Section\n\n");
}
/*** cod32_UnHandlePointer(pFrom, pTo)
*
* This function generates code for unhandling the pointers.
*
* Entry: pFrom and pTo are the type nodes.
*
* Exit: unhandle pointer code is generated.
*/
int cod32_UnHandlePointer(TypeNode *pFrom,
TypeNode *pTo)
{
int iItemSize = -1;
TypeNode *pSizeP;
unsigned int NullLabel;
unsigned int ErrorLabel;
unsigned int AliasedLabel;
unsigned int JumpLabel;
unsigned int SizeOkLabel;
unsigned int iTemp1, iTemp2;
iTemp1 = typ_TypeIdentical(pFrom,pTo);
iTemp2 = cod_CountPointerParameters(pFrom->pStructElems,FALSE);
if (pFrom->iBaseType == TYPE_STRUCT) {
printf("\n;Structures %s Identical\n",(iTemp1)?"are":"are not");
printf(";Structures %s pointers\n",(iTemp2)?"have":"don't have");
printf(";Structure %s output semantics\n",
(fgOutputFlag)?"has":"doesn't have");
}
if ((pFrom->iBaseType == TYPE_STRUCT) && (!iTemp1 || iTemp2)) {
if (pFrom->pSizeParam)
cod32_UnHandleStructureBuffer(pFrom,pTo);
else
cod32_UnStructureRepack(pFrom, pTo);
}
else if (pFrom->iBaseType != pTo->iBaseType) {
/*
* If there is no size parameter, then we are passing a long or a
* short. If the conversion is LONG to SHORT, then we can just use
* the existing long value as the buffer for the short. We will
* need to insure that the copy out routine correctly extends the
* value.
*/
if ((pFrom->pSizeParam) || (pFrom->iArraySize > 1) ||
(pFrom->iBaseDataSize < pTo->iBaseDataSize))
cod32_UnCopyConvertBuffer(pFrom,pTo);
else {
printf("\n;This item is either on the stack, or is still\n");
printf(";in its original position.\n");
if (pFrom->fSemantics & SEMANTIC_OUTPUT) {
printf(";Output semantics convert in place\n\n");
switch(pFrom->iBaseType)
{
case TYPE_ULONG:
printf("\tmovzx\teax,WORD PTR[esi]\n");
printf("\tmov\t[edi],eax\n");
break;
case TYPE_LONG:
printf("\tmovsx\teax,WORD PTR[esi]\n");
printf("\tmov\t[edi],eax\n");
break;
default:
fatal("cod32_UnHandlePointer: Type assertion failed");
}
}
}
}
else {
/*
* If not a structure, or structure requires no repacking, then
* consider all other instances of pointers as buffers. If a
* pointer type has a Size Parameter, which is defined in a
* semantic block, then the size parameter will either be the
* size in bytes, or a count of the number items. If it is the
* count, then the size will be determined by multiplying the
* count by the size of the item.
*/
if (pFrom->iBaseType == TYPE_STRUCT)
printf(";Treat structure same as buffer\n");
printf(";Types are identical and no imbedded pointers exist\n");
printf(";This means that we treated the pointer as a buffer\n");
printf(";If temp address == original address then no work required\n");
printf("\tcmp\tesi,edi\n");
printf("\tje\tL%u\n",gen_LabelCount-1);
if (pSizeP = pFrom->pSizeParam) {
if (fgOutputFlag) {
ErrorLabel = gen_LabelCount++;
printf("\n\ttest\tBYTE PTR[ebp-%u],1\t\t;Check for errors A\n",
iErrorOffset);
printf("\tjnz\tL%u\t\t\t;No copy if error\n",ErrorLabel);
printf("\n;Get size for copy out\n");
if (pSizeP->iPointerType) {
/*
* The original size parameter pointer is not null. This
* is implicit in the fact that the address of the
* temporary pointer is different than the original
* pointer. This also implies that the original size
* is non zero.
*/
printf("\n;Size was referenced by a pointer.\n");
printf(";Since only shorts/longs are used as sizeof\n");
printf(";parameters, the space allocated for the temporary\n");
printf(";location is on the stack. It still exists, so it\n");
printf(";is still safe to use the temporary pointer\n\n");
printf("\tmov\tecx,[ebp-%u]\t\t;Get Size Pointer\n",
pSizeP->iTempOffset);
if (pSizeP->iBaseDataSize == WORD_SIZE)
printf("\tmovzx\tecx,WORD PTR [ecx]\t\t;Get Size\n");
else
printf("\tmov\tecx,[ecx]\t\t;Get Size\n");
}
else
printf("\tmov\tecx,[ebp+%u]\t\t;Get Size \n",
pSizeP->iOffset);
if (pSizeP->fSemantics & SEMANTIC_SIZE)
printf(";ECX holds size in bytes\n");
else if (pSizeP->fSemantics & SEMANTIC_COUNT) {
printf(";ECX holds count of items\n");
printf("\tmov\teax,%d\t\t;Size of target data type\n",
typ_FullSize(pFrom));
printf("\tmul\tcx\n");
printf("\tmovzx\tecx,ax\n\n");
}
else
fatal("Internal Error: Size semantic not sizeof or countof");
}
/*
* Do a deallocate for variable sized data.
*/
cod32_UnHandleBoundaryCross(SIZE_VARIABLE,pFrom,0);
if (fgOutputFlag)
printf("\n\nL%u:\t\t\t;ErrorLabel A\n",ErrorLabel);
}
else {
/*
* No size parameter, assume fixed size parameter.
*/
switch(pFrom->iBaseType)
{
case TYPE_STRING:
printf(";Handle String Parameters\n");
printf(";Strings are never copied out\n");
/*
* Ensure that we don't try to copy out a string.
*/
iTemp1 = fgOutputFlag;
fgOutputFlag = FALSE;
cod32_UnHandleBoundaryCross(SIZE_VARIABLE,pFrom,0);
fgOutputFlag = iTemp1;
break;
default:
/*
* Static size.
*/
printf("\n;Item is fixed size\n");
cod32_UnHandleBoundaryCross(SIZE_FIXED,pFrom,typ_FullSize(pFrom));
}
}
}
}
/*** cod32_HandleStructureBuffer(pFrom,pTo)
*
* This routine handles a buffer full of structures. The buffer has a
* variable length size which is given by either a sizeof semantic or
* by a countof semantic. This routine will convert the structure.
*
* This routine is only called when the structures are not identical,
* and therefore the buffer needs conversion.
*
* Entry: pFrom and pTo are the type nodes.
*
* Exit: structure is converted.
*/
cod32_UnHandleStructureBuffer(TypeNode *pFrom,
TypeNode *pTo)
{
TypeNode *pSizeP;
FixupRec *pFixupList = NULL;
unsigned int NullLabel;
unsigned int LoopLabel;
unsigned int iESI,iEDI;
iESI = gESI = 0;
iEDI = gEDI = 0;
pSizeP = pFrom->pSizeParam;
if (pFrom->fSemantics & SEMANTIC_OUTPUT) {
/*
* At this point, we know that the previous label handles the case
* where the buffer was empty (or pointer was NULL).
* Therefore, if we set out NullLabel to current -1, we get the
* correct fixup.
*/
NullLabel = gen_LabelCount - 1;
printf("\n;Parameter has size semantics. This is a buffer of structs.\n");
printf(";If temp address == original address then no work required\n");
printf("\tcmp\tesi,edi\t\t\t;if temp address == original address\n");
printf("\tje\tL%u\t\t\t; skip deallocation\n",NullLabel);
/*
* The fact that we are in this routine means that there is a size
* parameter. Now the job is to figure out what type of size
* parameter it is, and calculate the appropriate buffer size.
*/
printf("\tmov\teax,[ebp+%u]\t\t;Get Size Parameter\n", pSizeP->iOffset);
if (pSizeP->iPointerType)
printf("\n;Check for NULL pointer\n");
printf("\tor\teax,eax\n");
printf("\tjz\tL%u\t\t;Nothing to check\n", NullLabel);
if (pSizeP->iPointerType) {
printf("\t\t\t\t;eax has pointer to size\n");
if (pSizeP->iBaseDataSize == WORD_SIZE)
printf("\tmovzx\teax,WORD PTR [eax]\t\t;Get Size\n");
else
printf("\tmov\teax,[eax]\t\t;Get Size\n");
printf("\tor\teax,eax\n");
printf("\tjz\tL%u\t\t;Nothing to check\n", NullLabel);
}
if (pSizeP->fSemantics & SEMANTIC_SIZE) {
printf(";EAX holds size in bytes\n");
printf(";We need to figure out the number of structures\n");
printf(";that will fit\n");
printf("\txor\tedx,edx\n");
printf("\tmov\tecx,%u\t\t;Source struct size\n",typ_FullSize(pFrom));
printf("\tdiv\tecx\n");
}
else if (pSizeP->fSemantics & SEMANTIC_COUNT)
printf(";EAX holds count of items\n");
else
fatal("cod32_UnHandleStructureBuffer: Size semantic not sizeof|countof");
printf("\n\tmov\tecx,eax\t\t;Move count into ecx\n");
/*
* At this point, we know the following facts:
* 1 - The structures in this buffer contain no pointers
* and therefore will require no internal fixups.
* 2 - ESI holds the source address, EDI holds the destination.
* 3 - ECX holds the count of structures to be converted.
*/
gTransferBytes = 0;
LoopLabel = gen_LabelCount++;
printf("\n;Array of structures\n");
printf("\nL%u:\n", LoopLabel);
printf("\tpush\tecx\t\t;Save array count\n");
cod32_UnRepackElements(pFrom,pTo, pFrom->pStructElems,
pTo->pStructElems, &pFixupList);
iESI = gESI;
iEDI = gEDI;
cod_AdjustReg("edi", &iEDI, pFrom->iStructOffset + pFrom->iBaseDataSize);
cod_AdjustReg("esi", &iESI, pTo->iStructOffset + pTo->iBaseDataSize);
printf("\n\tpop\tecx\t\t;Restore array count\n");
printf("\n\tloop\tL%u\n", LoopLabel);
gEDI = pFrom->iStructOffset + typ_FullSize(pFrom);
gESI = pTo->iStructOffset + typ_FullSize(pTo);
printf("\n\tmov\tesi,[ebp-%u]\n",pFrom->iTempOffset);
}
printf("\tpush\t%d\t\t;Alloc Flag Offset\n", - iAliasOffset);
printf("\tmov\tedx,%lu\n",(long)1<<pFrom->iPointerNumber);
printf("\n\tcall\tTHK32DEALLOC\n\n");
}
/*** cod32_UnHandleBoundaryCross(fSize,pFrom,iSize)
*
* Emits code to unhandle boundary crossing of pFrom.
*
* Entry: fSize - either SIZE_FIXED or SIZE_VARIABLE.
* pFrom - typenode for From pointer.
* iSize - size of item with SIZE_FIXED, or maximum length of
* item when SIZE_VARIABLE.
*
* Exit: unhandle boundary crossing code is generated.
*/
extern unsigned int iCopyLabel;
extern unsigned int iNoCopyLabel,iNextSize;
void
cod32_UnHandleBoundaryCross(unsigned int fSize,
TypeNode *pFrom,
unsigned int iSize)
{
unsigned int DoneLabel, AliasedLabel;
AliasedLabel = gen_LabelCount++;
DoneLabel = gen_LabelCount++;
iCopyLabel = gen_LabelCount++;
/*
* If iSize = 0, then assume largest possible size.
*/
if (iSize == 0)
iSize = iSize - 1;
if (fSize == SIZE_FIXED) {
cod32_UnHandleFixedSize(iSize,pFrom);
return;
}
else {
if (fgOutputFlag) {
if (iSize > (unsigned short) MEDIUM_ITEM) {
printf("\n;If aliased, then skip over possible copyout\n");
printf("\ttest\t%s PTR[ebp-%u],%lu\t\t;Test Alias Flag\n",
(pFrom->iPointerNumber >7)?"DWORD":"BYTE",
iAliasOffset, (long) 1 << pFrom->iPointerNumber);
printf("\tjnz\tL%u",AliasedLabel);
}
printf("\n;Copy out ecx bytes\n");
printf("\tpush\tesi\t\t;Save ptr to temp object\n");
cod32_VariableLengthCopy();
printf("\tpop\tesi\t\t;Get ptr to temp object\n");
}
if (iSize == 0) /* Make iSize huge */
iSize--;
if (pGlobal_To->fInlineCode) {
printf("\ttest\t%s PTR[ebp-%u],%lu\t\t;Test Stack Alloc Flag\n",
(pFrom->iPointerNumber >7)?"DWORD":"BYTE",
iAllocOffset, (long) 1 << pFrom->iPointerNumber);
printf("\n; DeAllocate space on stack: Done implicitly\n");
printf("\tjnz\tL%u\n\n",DoneLabel);
if (iSize >= MEDIUM_ITEM) {
printf("\ttest\t%s PTR [ebp-%u],%lu\t\t;Test BMP Flag\n",
(pFrom->iPointerNumber >7)?"DWORD":"BYTE",
iBMPOffset,(long) 1 << pFrom->iPointerNumber);
if (iSize >= LARGE_ITEM) {
iNextSize=gen_LabelCount++;
printf("\tjz\tL%u\n\n",iNextSize);
}
else
printf("\tjz\tL%u\n\n",DoneLabel);
printf("; DeAllocate space in BMP area\n");
printf("; ESI holds address of block\n");
printf("\tcall\tThk32FreeBlock\n");
if (iSize >= LARGE_ITEM)
printf("\tjmp\tL%u\n\n",DoneLabel);
}
/*
* The operation of freeing a linear alias is the same as
* freeing a large buffer allocated for a huge (> 60k) copy.
*/
if (iSize >= LARGE_ITEM) {
if (fgOutputFlag)
printf("L%u:\t\t\t;Aliased Label\n",AliasedLabel);
printf("L%u:\n",iNextSize);
printf(";Free Linear Alias/ Large Buffer \n");
printf("\tcall\tThk32FreeAlias\n");
}
printf("\nL%u:\t\t;Deallocation Done Label\n\n",DoneLabel);
}
else {
if (fgOutputFlag && (iSize > (unsigned short) MEDIUM_ITEM))
printf("L%u:\t\t\t;Aliased Label\n",AliasedLabel);
printf("\tpush\t%d\t\t;Alloc Flag Offset\n", - iAliasOffset);
printf("\tmov\tedx,%lu\n",(long)1<<pFrom->iPointerNumber);
printf("\n\tcall\tTHK32DEALLOC\n\n");
}
}
}
/*** cod32_UnHandleFixedSize(iSize,pFrom)
*
* This worker routine to HandleBoundaryCrossing will output code
* to handle fixed size items that cross boundaries.
*
* Entry: iSize - fixed size of item.
* pFrom - pointer to type node.
*
* Exit: generates code for fixed size item boundary crossing.
*/
void
cod32_UnHandleFixedSize(unsigned int iSize,
TypeNode *pFrom)
{
unsigned int ErrorLabel;
if (fgOutputFlag) {
ErrorLabel = gen_LabelCount++;
printf("\n\ttest\tBYTE PTR[ebp-%u],1\t\t;Check for errors C\n",iErrorOffset);
printf("\tjnz\tL%u\t\t\t;No copy if error\n",ErrorLabel);
}
if (! iSize)
fatal("cod32_UnHandleFixedSize: iSize = 0 \n");
if ((iSize <= SMALL_ITEM) && fgOutputFlag) {
printf("\n;Space was allocated on stack\n");
cod32_TransferBlock(iSize);
}
else if (fgOutputFlag && (iSize <= MEDIUM_ITEM)) {
printf("\n;Copy out ecx bytes\n");
printf("\tpush\tesi\t\t;Save ptr to temp object\n");
cod32_TransferBlock(iSize);
printf("\tpop\tesi\t\t;Get ptr to temp object\n");
}
if (fgOutputFlag)
printf("\nL%u:\t\t\t;ErrorLabel C\n",ErrorLabel);
if (iSize <= SMALL_ITEM)
printf(";stack deallocated implicitly\n");
else if(iSize <= MEDIUM_ITEM) {
printf("; DeAllocate space in BMP area\n");
printf("; ESI holds address of block\n");
printf("\tcall\tThk32FreeBlock\n");
}
else if (iSize <= LARGE_ITEM) {
printf(";Free Linear Alias\n");
printf("; ESI holds address of block\n");
printf("\tcall\tThk32FreeAlias\n");
return;
}
else {
fprintf(stderr,"Fixed sized item > 60k\n");
printf(".err Fixed sized item > 60k\n");
}
}
/*** cod32_UnStructureRepack(pFrom,pTo)
*
* This function generates the code that converts one structure
* to another structure. Specifically, it unpacks structures back to
* their original positions.
*
* Entry: pFrom - pointer to the 32-bit structure
* pTo - pointer to the 16-bit structure
*
* Exit: structure unpacking code is generated.
*
* History:
* 10-Jan-1989 KevinRo Created It.
*/
int cod32_UnStructureRepack(TypeNode *pBaseFrom,
TypeNode *pBaseTo)
{
unsigned int NullLabel;
unsigned int ErrorLabel;
FixupRec *pFixupList = NULL, *pCurrent;
TypeNode *pFrom,*pTo;
TypeNode *ptFrom,*ptTo;
pFrom = pBaseFrom->pStructElems;
pTo = pBaseTo->pStructElems;
gEDI = 0;
gESI = 0;
printf(";Return structure to original area\n\n");
if (fgOutputFlag) {
ErrorLabel = gen_LabelCount++;
printf("\n\ttest\tBYTE PTR[ebp-%u],1\t\t;Check for errors D\n",iErrorOffset);
printf("\tjnz\tL%u\t\t\t;No copy if error\n",ErrorLabel);
}
cod32_UnRepackElements(pBaseFrom,pBaseTo,pFrom,pTo,&pFixupList);
if (fgOutputFlag)
printf("\nL%u:\t\t\t;ErrorLabel D\n",ErrorLabel);
/*
* Now, handle the fixups.
*/
while (pCurrent = cod_GetFixupRecord(&pFixupList)) {
printf("\n\n;Unpack imbedded pointer %s\n\n",
typ_NonNull(pCurrent->pFrom->pchIdent));
printf("\tmov\tesi,[ebp-%u]\t\t;Get pointer to temporary\n",
pCurrent->pFrom->iTempOffset);
printf("\tor\tesi,esi\t\t;Ignore if NULL\n");
printf("\tjz\tL%u\n\n",NullLabel=gen_LabelCount++);
printf("\tmov\tedi,[ebp+%u]\t\t;Get parents original pointer\n",
pCurrent->pParentFrom->iOffset);
printf("\tmov\tedi,[edi+%u]\t\t;Get Fixups original address\n",
pCurrent->pFrom->iStructOffset);
cod32_UnHandlePointer(pCurrent->pFrom,pCurrent->pTo);
printf("L%u:\n\n",NullLabel);
free(pCurrent);
}
printf(";Deallocate Temporary Structure \n\n");
cod32_DeAllocFixedSize(typ_FullSize(pBaseTo),pBaseFrom);
}
/*** cod32_UnRepackElements(pParentFrom,pParentTo,pFrom,pTo,pFixupList)
*
* This function generates the code that undoes the repacking of
* the elements.
*
* Entry: pParentFrom - pointer to parent of 'from' node.
* pParentTo - pointer to parent of 'to' node.
* pFrom - pointer to 'from' node.
* pTo - pointer to 'to' node.
* pFixupList - pointer to fixup record list.
*
* Exit: code for undoing repacking of elements is generated.
*/
cod32_UnRepackElements(TypeNode *pParentFrom,
TypeNode *pParentTo,
TypeNode *pFrom,
TypeNode *pTo,
FixupRec **pFixupList)
{
TypeNode *pToNode,*pFromNode;
unsigned int iEDI,iESI;
unsigned int JumpLabel;
pToNode = pTo;
pFromNode = pFrom;
fReAlignmentNeeded = 0;
if (!fgOutputFlag) {
while (pFromNode) {
if (pFromNode->iPointerType) {
cod_AddFixupRecord(pFixupList,
cod_MakeFixupRecord(pParentFrom,pParentTo,
pFromNode,pToNode));
}
else if (pFromNode->iBaseType == TYPE_STRUCT) {
cod32_UnRepackElements(pParentFrom,pParentTo,
pFromNode->pStructElems,
pToNode->pStructElems,pFixupList);
}
pFromNode = pFromNode->pNextNode;
pToNode = pToNode->pNextNode;
}
}
else {
while (pFromNode) {
printf("\n;Element %s --> %s\n", typ_NonNull(pToNode->pchIdent),
typ_NonNull(pFromNode->pchIdent));
/*
* If the fReAlignmentNeeded flag is set, then the previous
* operation was a CopyConvert. The adjustment of the registers
* in that routine was moved here to optimize the increment of
* the registers. At the end of a CopyConvert, we only want to
* increment the registers in the cases when there are more
* elements in the structure. The fact that we have reached
* this statement implies that there are more elements in the
* structure.
*/
if (fReAlignmentNeeded) {
if (gTransferBytes)
fatal("RepackElements: gTransferBytes = %u",gTransferBytes);
printf("\n;Adjust registers after conversion\n");
cod_AdjustReg("esi",&gESI,pToNode->iStructOffset);
cod_AdjustReg("edi",&gEDI,pFromNode->iStructOffset);
fReAlignmentNeeded = 0;
}
/*
* This assignment optimizes the way that bytes are transferred,
* so that we don't need adjustments when bytes items preceed
* larger sized items. This statement only has effect when a
* realignment is about to occur. This value is reset again a
* few lines down.
*/
gTransferBytes = MIN((pFromNode->iStructOffset - gEDI),
pToNode->iStructOffset - gESI);
/*
* If either the TO or FROM node is deleted, then we need to
* realign ESI and EDI.
*/
if ( (pFromNode->iDeleted) || (pToNode->iDeleted)) {
printf(";Deleted structure element\n");
if (gTransferBytes) {
printf(";Alignment Change\n");
cod32_TransferBlock(gTransferBytes);
gTransferBytes = 0;
printf("\n;ReAlignment\n");
}
if (pToNode->iDeleted) {
printf(";Source element is deleted\n");
switch(pToNode->fSemantics & SEMANTIC_INOUT)
{
case SEMANTIC_INOUT:
case SEMANTIC_INPUT:
printf(";Parameter had input semantic\n");
printf(";Do not copy it out.\n");
break;
case SEMANTIC_OUTPUT:
printf(";\n");
printf("\tmov\teax,%u",pToNode->iFillValue);
switch (pFromNode->iBaseType) {
case TYPE_USHORT:
case TYPE_SHORT:
printf("\t\t;Need a 16-bit value\n");
printf("\tstosw\n");
break;
case TYPE_LONG:
case TYPE_ULONG:
printf("\t\t;Need a 32-bit value\n");
printf("\tstosd\n");
break;
default:
fatal("Bad type for deleted struct element\n");
}
}
}
else {
/* In this case, the To node is deleted. This means
* that we don't want to copy the current element.
*/
switch (pToNode->iBaseType) {
case TYPE_USHORT:
case TYPE_SHORT:
printf(";Deleting a 16-bit value\n");
break;
case TYPE_LONG:
case TYPE_ULONG:
printf(";Deleting a 32-bit value\n");
break;
default:
fatal("Bad type for deleted struct element\n");
}
}
goto DoneWithNodes; /** Avoid the rest of this loop **/
}
/*
* If the alignment is going to shift, then execute a block
* transfer, and realign ESI and EDI. Alignment here will
* always shift when a pointer is encountered.
*/
if ((pFromNode->iStructOffset - gEDI) !=
(pToNode->iStructOffset - gESI) ||
(pFromNode->iPointerType)) {
if (gTransferBytes) {
printf(";Alignment Change\n");
cod32_TransferBlock(gTransferBytes);
gTransferBytes = 0;
printf("\n;ReAlignment\n");
}
cod_AdjustReg("esi",&gESI,pToNode->iStructOffset);
cod_AdjustReg("edi",&gEDI,pFromNode->iStructOffset);
}
switch (pFromNode->iPointerType)
{
/*
* If we find a pointer type, then it is an imbedded pointer.
* The data can be included into a block copy, since we are
* going to handle it later.
*/
case TYPE_NEAR32:
case TYPE_FAR16:
printf(";Pointer elements not copied out\n");
cod32_TransferBlock(gTransferBytes);
gTransferBytes = 0;
cod_AdjustReg("esi",&gESI,pToNode->iStructOffset + DWORD_SIZE);
cod_AdjustReg("edi",&gEDI,pFromNode->iStructOffset + DWORD_SIZE);
cod_AddFixupRecord(pFixupList,
cod_MakeFixupRecord(pParentFrom,pParentTo,pFromNode,pToNode));
break;
default:
/*
* If it wasn't one of the pointer types above, then it
* must be a non pointer parameter. Thus, it will be a
* long, short, ulong, ushort, or char
*/
if (pFromNode->iBaseType == TYPE_STRUCT) {
unsigned int LoopLabel;
unsigned int iESI=gESI,iEDI=gEDI;
if (pFromNode->iArraySize > 1) {
cod32_TransferBlock(gTransferBytes);
gTransferBytes = 0;
cod_AdjustReg("esi",&gESI,pToNode->iStructOffset);
cod_AdjustReg("edi",&gEDI,pFromNode->iStructOffset);
LoopLabel = gen_LabelCount++;
printf("\n;Array of structures\n");
printf("\n\tmov\tecx,%u\n",pFromNode->iArraySize);
printf("\nL%u:\n",LoopLabel);
printf("\tpush\tecx\t\t;Save array count\n");
}
cod32_UnRepackElements(pParentFrom,pParentTo,
pFromNode->pStructElems,
pToNode->pStructElems,pFixupList);
iESI = gESI;
iEDI = gEDI;
if (pFromNode->iArraySize > 1) {
cod_AdjustReg("esi",&iESI,
pToNode->iStructOffset +
pToNode->iBaseDataSize);
cod_AdjustReg("edi",&iEDI,
pFromNode->iStructOffset +
pFromNode->iBaseDataSize);
printf("\n\tpop\tecx\t\t;Restore array count\n");
printf("\n\tloop\tL%u\n",LoopLabel);
gESI = pToNode->iStructOffset +
typ_FullSize(pToNode);
gEDI = pFromNode->iStructOffset +
typ_FullSize(pFromNode);
}
}
else {
fReAlignmentNeeded = 0;
/*
* Reversing the parameters allows CopyConvert to
* be used for both pack and repack.
*/
cod32_CopyConvert(pToNode,pFromNode);
}
}
DoneWithNodes:
if (pToNode->pNextNode == NULL) {
cod32_TransferBlock(gTransferBytes);
gTransferBytes = 0;
}
pToNode = pToNode->pNextNode;
pFromNode = pFromNode->pNextNode;
}
}
}
/*** cod32_UnCopyConvertBuffer(pFrom,pTo)
*
* This function will perform a copy/convert of a buffer.
* The buffer is presumed to be in the formal parameter list of the
* API declaration.
*
* Entry: pFrom and pTo are the type nodes.
*
* Exit: copy/convert of a buffer is performed.
*/
cod32_UnCopyConvertBuffer(TypeNode *pFrom,
TypeNode *pTo)
{
TypeNode *pSizeP;
unsigned int JumpLabel;
unsigned int NullLabel;
unsigned int ErrorLabel;
unsigned int DoneLabel;
unsigned int iNextSize;
/*
* If there is a size parameter, then the buffer size is determined at
* run time. Otherwise, the buffer size is static.
*/
NullLabel = gen_LabelCount;
/*
* The previous label handles NULL and zero lens.
*/
NullLabel--;
printf("\n;We have two buffers with different types in them\n");
printf("\n;If the buffer was output, then we need to copy out\n");
if (pSizeP = pFrom->pSizeParam) { /* Runtime */
if (fgOutputFlag) {
ErrorLabel = gen_LabelCount++;
printf("\n\ttest\tBYTE PTR[ebp-%u],1\t\t;Check for errors E\n",iErrorOffset);
printf("\tjnz\tL%u\t\t\t;No copy if error\n",ErrorLabel);
}
if (pSizeP->iPointerType) {
/*
* The original size parameter pointer is not null. This is
* implicit in the fact that the address of the temporary
* pointer is different than the original pointer. This also
* implies that the original size is non zero.
*/
printf("\n;Size was referenced by a pointer.\n");
printf(";Since only shorts/longs are used as sizeof\n");
printf(";parameters, the space allocated for the temporary\n");
printf(";location is on the stack. It still exists, so it is\n");
printf(";still safe to use the temporary pointer\n\n");
printf("\tmov\tecx,[ebp-%u]\t\t;Get Size Pointer\n",
pSizeP->iTempOffset);
if (pSizeP->iBaseDataSize == WORD_SIZE)
printf("\tmovzx\tecx,WORD PTR [ecx]\t\t;Get Size\n");
else
printf("\tmov\tecx,[ecx]\t\t;Get Size\n");
}
else
printf("\tmov\tecx,[ebp+%u]\t\t;Get Size \n",pSizeP->iOffset);
if (pSizeP->fSemantics & SEMANTIC_SIZE) {
printf(";ECX holds size in bytes\n");
printf(";We need to figure out the number of elements\n");
printf(";that will fit\n");
printf("\n\tmov\teax,ecx\n");
printf("\txor\tedx,edx\n");
printf("\tmov\tecx,%u\t\t;Source size\n",typ_FullSize(pFrom));
printf("\tdiv\tcx\n");
printf("\tmov\tecx,eax\t;The count\n",iTempStoreOffset);
}
if (pSizeP->fSemantics & SEMANTIC_COUNT)
printf(";ECX holds count of items\n");
gEDI = 0;
gESI = 0;
JumpLabel = gen_LabelCount++;
printf("\nL%u:\n",JumpLabel);
switch (pTo->iBaseType)
{
case TYPE_SHORT: /* SHORT --> LONG */
printf("\n;SHORT --> LONG\n\n");
printf("\tmovsx\teax,WORD PTR[esi]\n");
printf("\tmov\t[edi],eax\n");
break;
case TYPE_USHORT: /* USHORT --> ULONG */
printf("\n;USHORT --> ULONG\n\n");
printf("\tmovzx\teax,WORD PTR[esi]\n");
printf("\tmov\t[edi],eax\n");
break;
case TYPE_LONG: /* LONG --> SHORT */
case TYPE_ULONG: /* ULONG --> USHORT */
printf("\n;U/LONG --> U/SHORT\n\n");
printf("\tmov\teax,DWORD PTR [esi]\n");
printf("\tmov\tWORD PTR [edi],ax\n");
break;
default:
fatal("cod32_CopyConvertBuffer: Tried converted %d to %d",
pTo->iBaseType,pFrom->iBaseType);
}
printf("\tadd\tesi,%u\n",pTo->iBaseDataSize);
printf("\tadd\tedi,%u\n",pFrom->iBaseDataSize);
printf("\tloop\tL%u\n",JumpLabel);
if (fgOutputFlag)
printf("\n\nL%u:\t\t\t;ErrorLabel E\n",ErrorLabel);
printf("\n\n;Deallocate Variable Size Block\n");
printf("\tmov\tesi,[ebp-%u]\n",pFrom->iTempOffset);
printf("\tpush\t%d\t\t;Alloc Flag Offset\n", - iAliasOffset);
printf("\tmov\tedx,%lu\n",(long)1<<pFrom->iPointerNumber);
printf("\n\tcall\tTHK32DEALLOC\n\n");
}
else { /* Static */
gEDI = 0;
gESI = 0;
/*
* Reversing the order for a CopyConvert is OK.
*/
if (fgOutputFlag) {
ErrorLabel = gen_LabelCount++;
printf("\n\ttest\tBYTE PTR[ebp-%u],1\t\t;Check for errors F\n",iErrorOffset);
printf("\tjnz\tL%u\t\t\t;No copy if error\n",ErrorLabel);
}
cod32_CopyConvert(pTo,pFrom);
if (fgOutputFlag)
printf("\n\nL%u:\t\t\t;ErrorLabel F\n",ErrorLabel);
cod32_DeAllocFixedSize(typ_FullSize(pTo),pFrom);
}
}