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.
 
 
 
 
 
 

1638 lines
47 KiB

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1989 Microsoft Corporation
Module Name:
ilcore.cxx
Abstract:
Intermediate Language translator for core typegraph
Notes:
Author:
GregJen Dec-24-1993 Created.
Notes:
----------------------------------------------------------------------------*/
/****************************************************************************
* include files
***************************************************************************/
#include "becls.hxx"
#pragma hdrstop
#include "ilxlat.hxx"
#include "ilreg.hxx"
/****************************************************************************
* local data
***************************************************************************/
/****************************************************************************
* externs
***************************************************************************/
extern CMD_ARG * pCommand;
extern BOOL IsTempName( char *);
extern REUSE_DICT * pReUseDict;
extern REUSE_DICT * pLocalReUseDict;
/****************************************************************************
* definitions
***************************************************************************/
// #define trace_cg
//--------------------------------------------------------------------
//
// node_href::ILxlate
//
// Notes:
//
//
//
//--------------------------------------------------------------------
CG_CLASS *
node_href::ILxlate( XLAT_CTXT * pContext )
{
#ifdef trace_cg
printf("..node_href\n");
#endif
assert( GetChild() && "unsatisfied node_href encountered" );
return GetChild()->ILxlate( pContext );
}
//--------------------------------------------------------------------
//
// node_forward::ILxlate
//
// Notes:
//
//
//
//--------------------------------------------------------------------
CG_CLASS *
node_forward::ILxlate( XLAT_CTXT * pContext )
{
#ifdef trace_cg
printf("..node_forward\n");
#endif
assert( GetChild() && "unsatisfied node_forward encountered" );
if ( !GetChild() )
SemError( this, *pContext, UNSATISFIED_FORWARD, GetSymName() );
// forward interface definitions return null
if ( ( pContext->GetParent()->IsInterfaceOrObject() ) &&
( GetChild()->NodeKind() == NODE_INTERFACE_REFERENCE ) )
return NULL;
// pass it on to the child...
return GetChild()->ILxlate( pContext );
};
//--------------------------------------------------------------------
//
// node_id::ILxlate
//
// Notes:
//
//
//
//--------------------------------------------------------------------
CG_CLASS *
node_id::ILxlate( XLAT_CTXT * pContext )
{
#ifdef trace_cg
printf("..node_id\n");
#endif
XLAT_CTXT MyContext( this, pContext );
CG_CLASS * pCG;
node_constant_attr * pID = (node_constant_attr *)MyContext.ExtractAttribute(ATTR_ID);
node_constant_attr * pHC = (node_constant_attr *)MyContext.ExtractAttribute(ATTR_HELPCONTEXT);
node_constant_attr * pHSC = (node_constant_attr *)MyContext.ExtractAttribute(ATTR_HELPSTRINGCONTEXT);
node_text_attr * pHelpStr = (node_text_attr *)MyContext.ExtractAttribute(ATTR_HELPSTRING);
MyContext.ExtractAttribute(ATTR_HIDDEN);
while(MyContext.ExtractAttribute(ATTR_CUSTOM));
pCG = GetChild()->ILxlate( &MyContext );
if (NODE_MODULE == pContext->GetParent()->NodeKind())
{
CG_ID * pID = new CG_ID (this, MyContext);
pID->SetChild(pCG);
pCG = pID;
}
pContext->ReturnSize( MyContext );
return pCG;
};
//--------------------------------------------------------------------
//
// node_field::ILxlate
//
// Notes:
//
//
//
//--------------------------------------------------------------------
CG_CLASS *
node_field::ILxlate( XLAT_CTXT * pContext )
{
CG_NDR * pCG;
CG_CLASS * pChildCG;
XLAT_CTXT MyContext( this, pContext );
BOOL fUnionField;
CG_CASE * pFirstCase;
CG_CASE * pCurCase;
expr_node * pSwitchExpr = NULL;
node_su_base * pParent = (node_su_base *)pContext->GetParent();
BOOL fConfFld = FALSE;
#ifdef MIDL_INTERNAL
char * pDbgName = GetSymName();
UNUSED( pDbgName );
#endif
MyContext.ExtractAttribute(ATTR_ID);
MyContext.ExtractAttribute(ATTR_IDLDESCATTR);
MyContext.ExtractAttribute(ATTR_VARDESCATTR);
MyContext.ExtractAttribute(ATTR_HELPSTRING);
MyContext.ExtractAttribute(ATTR_HELPSTRINGCONTEXT);
MyContext.ExtractAttribute(ATTR_HELPCONTEXT);
MyContext.ExtractAttribute(ATTR_HIDDEN);
while(MyContext.ExtractAttribute(ATTR_CUSTOM));
while (MyContext.ExtractAttribute(ATTR_MEMBER));
#ifdef trace_cg
printf("..node_field: %s\n", GetSymName());
#endif
if (fUnionField = ( MyContext.FInSummary( ATTR_CASE ) ||
MyContext.FInSummary( ATTR_DEFAULT ) ) )
{
CG_CASE * pPrevCase = NULL;
node_case * pCaseAttr;
expr_list * pExprList;
expr_node * pExpr;
pCG = new CG_UNION_FIELD( this, MyContext );
// for each case attribute, make a CG_CASE for each expr in the attr
while ( pCaseAttr = (node_case *)
MyContext.ExtractAttribute( ATTR_CASE ) )
{
pExprList = pCaseAttr->GetExprList();
pExprList->Init();
while ( pExprList->GetPeer( &pExpr ) == STATUS_OK )
{
pCurCase = new CG_CASE( this, pExpr );
pCurCase->SetChild( pCG );
if ( pPrevCase )
pPrevCase->SetSibling( pCurCase );
else
pFirstCase = pCurCase;
pPrevCase = pCurCase;
}
}
// now process the default, if any
if ( MyContext.ExtractAttribute( ATTR_DEFAULT ) )
{
pCurCase = new CG_DEFAULT_CASE( this );
pCurCase->SetChild( pCG );
if ( pPrevCase )
pPrevCase->SetSibling( pCurCase );
else
pFirstCase = pCurCase;
pPrevCase = pCurCase;
}
// mark the last case for this arm
pCurCase->SetLastCase( TRUE );
}
// if we have a switch_is expr, fetch it..
if ( MyContext.FInSummary( ATTR_SWITCH_IS ) )
{
node_switch_is * pAttr = (node_switch_is *)
MyContext.ExtractAttribute( ATTR_SWITCH_IS );
pSwitchExpr = pAttr->GetExpr();
}
// process the child of the field
pChildCG = GetChild()->ILxlate( &MyContext );
// can't use attribute list after here...
MyContext.AdjustForZP(); // fix up alignments for current ZP
MyContext.GetOffset( *pContext ); // offset in parent struct/union
node_skl * pBasic = GetBasicType();
if ( pParent->HasConformance() &&
IsLastField() &&
( pBasic->NodeKind() != NODE_STRUCT ) &&
!fUnionField) // if I'm a conf. field
{
fConfFld = TRUE;
MyContext.AlignConfOffset(); // round mem, not wire up to alignment
}
else if ( pBasic->IsEncapsulatedStruct() ||
( pBasic->NodeKind() == NODE_UNION ) )
{
MyContext.AlignEmbeddedUnion();
}
else
{
MyContext.AlignOffset(); // round up to alignment
}
if (fUnionField )
{
pCG->SetChild( pChildCG );
pCG = pFirstCase;
pContext->ReturnUnionSize( MyContext ); // return size and alignment
}
else
{
pCG = new CG_FIELD( this, MyContext );
pCG->SetChild( pChildCG );
( (CG_FIELD *)pCG )->SetSwitchExpr( pSwitchExpr );
pContext->ReturnOffset( MyContext ); // return rounded-up offset
if ( fConfFld )
pContext->ReturnConfSize( MyContext ); // don't munge wire size!
else
pContext->ReturnSize( MyContext ); // return size and alignment
}
if ( HasUnknownRepAs() )
((CG_FIELD *)pCG)->SetHasEmbeddedUnknownRepAs();
if ( fConfFld )
{
pCG->SetMemorySize( 0 );
pCG->SetWireSize( 0 );
}
return pCG;
};
//--------------------------------------------------------------------
//
// node_bitfield::ILxlate
//
// Notes:
//
//
//
//--------------------------------------------------------------------
CG_CLASS *
node_bitfield::ILxlate( XLAT_CTXT * pContext )
{
#ifdef trace_cg
printf("..node_bitfield\n");
#endif
assert(!"bitfield being IL translated!");
return NULL;
};
//--------------------------------------------------------------------
//
// node_enum::ILxlate
//
// Notes:
//
//
//
//--------------------------------------------------------------------
CG_CLASS *
node_enum::ILxlate( XLAT_CTXT * pContext )
{
CG_ENUM * pCG;
BOOL fV1Enum = (BOOL)
pContext->ExtractAttribute( ATTR_V1_ENUM );
pContext->ExtractAttribute(ATTR_TYPEDESCATTR);
#ifdef trace_cg
printf("..node_enum\n");
#endif
pContext->EnumTypeSizes( this, fV1Enum );
pCG = new CG_ENUM( this, *pContext );
return pCG;
};
//--------------------------------------------------------------------
//
// node_struct::ILxlate
//
// Notes:
//
//
//
//--------------------------------------------------------------------
CG_CLASS *
node_struct::ILxlate( XLAT_CTXT * pContext )
{
MEM_ITER MemIter( this );
node_field * pN;
CG_STRUCT * pCG;
CG_CLASS * pChildCG = NULL;
CG_CLASS * pPrevChildCG = NULL;
CG_CLASS * pFirstChildCG = NULL;
XLAT_CTXT MyContext( this, pContext );
REUSE_INFO * pSaved;
BOOL fHasMovedFields = FALSE; // has fields with diff mem/wire offsets
MyContext.ExtractAttribute(ATTR_TYPEDESCATTR);
while(MyContext.ExtractAttribute(ATTR_CUSTOM));
#ifdef MIDL_INTERNAL
char * pDbgName = GetSymName();
UNUSED( pDbgName );
#endif
#ifdef trace_cg
printf("..node_struct\n");
#endif
MyContext.ExtractAttribute( ATTR_STRING );
// process any context_handle attributes from param nodes
if ( MyContext.ExtractAttribute( ATTR_CONTEXT ) )
{
CG_NDR * pChildCG;
MyContext.ContextHandleSizes( this );
pContext->ReturnSize( MyContext );
pChildCG = new CG_CONTEXT_HANDLE( this, NULL, MyContext );
return pChildCG;
}
// clear member attributes
while (MyContext.ExtractAttribute(ATTR_MEMBER));
// at this point, there should be no more attributes...
assert( !MyContext.HasAttributes() );
// store our own zp value for below
MyContext.GetZeePee() = GetZeePee();
// see if we were already generated
if (MyContext.AnyAncestorBits(IL_IN_LOCAL))
{
if ( pLocalReUseDict->GetReUseEntry( pSaved, this ) )
{
// reuse found...
pSaved->FetchInfo( &MyContext, pChildCG );
pContext->ReturnSize( MyContext );
return pChildCG;
}
}
else
{
if ( pReUseDict->GetReUseEntry( pSaved, this ) )
{
// reuse found...
pSaved->FetchInfo( &MyContext, pChildCG );
pContext->ReturnSize( MyContext );
return pChildCG;
}
}
// manufature the CG node (to allow for recursion)
switch (Complexity)
{
case FLD_PLAIN:
{
pCG = new CG_STRUCT( this,
MyContext,
HasAtLeastOnePointer()
);
break;
}
case FLD_CONF:
{
pCG = new CG_CONFORMANT_STRUCT( this,
MyContext,
HasAtLeastOnePointer(),
NULL
);
break;
}
case FLD_CONF_VAR:
{
pCG = new CG_CONFORMANT_VARYING_STRUCT( this,
MyContext,
HasAtLeastOnePointer(),
NULL
);
break;
}
case FLD_VAR:
default:
{
pCG = new CG_COMPLEX_STRUCT( this,
MyContext,
HasAtLeastOnePointer(),
NULL
);
break;
}
}
// save our CG node so that recursive use can find it
pSaved->SaveInfo( &MyContext, pCG);
//
// for each of the fields, call the core transformer.
//
while ( pN = (node_field *) MemIter.GetNext() )
{
pChildCG = pN->ILxlate( &MyContext );
// adjust the size and current offset of the struct, special
// case the conformant field ( last one )
if ( fHasConformance &&
!pN->GetSibling() &&
( pN->GetBasicType()->NodeKind() != NODE_STRUCT ) )
{
MyContext.AdjustConfSize();
}
else
{
MyContext.AdjustSize();
}
if ( !MyContext.SameOffsets() )
fHasMovedFields = TRUE;
// add the field to the list of fields
if( pPrevChildCG )
{
pPrevChildCG->SetSibling( pChildCG );
}
else
{
pFirstChildCG = pChildCG;
};
pPrevChildCG = pChildCG;
// get the type of the field to determine kind of struct
}
// conformant structs don't get trailing padding
if ( !fHasConformance )
MyContext.AdjustTotalSize();
pContext->ReturnSize( MyContext );
pCG->SetChild( pFirstChildCG );
// sizes aren't determined until after the fields have been made, so we have
// to set them manually
pCG->SetSizesAndAlignments( MyContext );
// this picks up whatever is the last field...
if ( fHasConformance )
((CG_CONFORMANT_STRUCT *) pCG)->SetConformantField( pChildCG );
// make offlining decision
// semantically to be offlined, or memsize != wiresize
// OffLine |= ( MyContext.GetWireSize() != MyContext.GetMemSize() );
if ( IsOffline() )
{
pCG->SetOffline();
}
if ( fHasMovedFields )
{
pCG->SetHasMovedFields();
}
pSaved->SaveInfo( &MyContext, pCG);
return pCG;
};
//--------------------------------------------------------------------
//
// node_en_struct::ILxlate
//
// Notes:
//
//
//
//--------------------------------------------------------------------
CG_CLASS *
node_en_struct::ILxlate( XLAT_CTXT * pContext )
{
MEM_ITER MemIter( this );
node_skl * pN;
CG_STRUCT * pCG;
CG_CLASS * pChildCG = NULL;
CG_CLASS * pPrevChildCG = NULL;
CG_CLASS * pFirstChildCG = NULL;
XLAT_CTXT MyContext( this, pContext );
REUSE_INFO * pSaved;
#ifdef MIDL_INTERNAL
char * pDbgName = GetSymName();
UNUSED( pDbgName );
#endif
#ifdef trace_cg
printf("..node_en_struct\n");
#endif
// store our own zp value for below
MyContext.GetZeePee() = GetZeePee();
while(MyContext.ExtractAttribute(ATTR_CUSTOM));
// process any context_handle attributes from param nodes
if ( MyContext.ExtractAttribute( ATTR_CONTEXT ) )
{
CG_HANDLE * pHdlCG;
MyContext.ContextHandleSizes( this );
pContext->ReturnSize( MyContext );
pHdlCG = new CG_CONTEXT_HANDLE( this, NULL, MyContext );
return pHdlCG;
}
// at this point, there should be no more attributes...
assert( !MyContext.HasAttributes() );
if (MyContext.AnyAncestorBits(IL_IN_LOCAL))
{
if ( pLocalReUseDict->GetReUseEntry( pSaved, this ) )
{
// reuse found...
pSaved->FetchInfo( &MyContext, pChildCG );
pContext->ReturnSize( MyContext );
return pChildCG;
}
}
else
{
if ( pReUseDict->GetReUseEntry( pSaved, this ) )
{
// reuse found...
pSaved->FetchInfo( &MyContext, pChildCG );
pContext->ReturnSize( MyContext );
return pChildCG;
}
}
// manufature the CG node (to allow for recursion)
pCG = new CG_ENCAPSULATED_STRUCT( this,
MyContext,
HasAtLeastOnePointer()
);
// set that struct is encapsulated
// pCG->SetIsEncapsulated();
// save our CG node so that recursive use can find it
pSaved->SaveInfo( &MyContext, pCG);
//
// for each of the fields, call the core transformer.
//
while ( pN = MemIter.GetNext() )
{
pChildCG = pN->ILxlate( &MyContext );
MyContext.AdjustSize();
if( pPrevChildCG )
{
pPrevChildCG->SetSibling( pChildCG );
}
else
{
pFirstChildCG = pChildCG;
};
pPrevChildCG = pChildCG;
}
MyContext.AdjustTotalSize();
pContext->ReturnSize( MyContext );
pCG->SetChild( pFirstChildCG );
// set sizes manually, since they weren't known at constructor time
pCG->SetSizesAndAlignments( MyContext );
pCG->SetOffline();
pSaved->SaveInfo( &MyContext, pCG);
return pCG;
};
//--------------------------------------------------------------------
//
// node_union::ILxlate
//
// Notes:
//
//
//
//--------------------------------------------------------------------
CG_CLASS *
node_union::ILxlate( XLAT_CTXT * pContext )
{
XLAT_CTXT MyContext( this, pContext );
MEM_ITER MemIter( this );
CG_CASE * pCurCaseCG;
CG_CASE * pFirstCaseCG = NULL;
CG_CASE * pLastCaseCG = NULL;
CG_UNION * pUnionCG;
node_field * pCurField;
REUSE_INFO * pSaved;
BOOL fMSUnion;
BOOL fEncap = IsEncapsulatedUnion();
node_switch_type * pSwTypeAttr = ( node_switch_type *)
MyContext.ExtractAttribute( ATTR_SWITCH_TYPE );
MyContext.ExtractAttribute(ATTR_TYPEDESCATTR);
while(MyContext.ExtractAttribute(ATTR_CUSTOM));
#ifdef MIDL_INTERNAL
char * pDbgName = GetSymName();
UNUSED( pDbgName );
#endif
#ifdef trace_cg
printf("..node_union\n");
#endif
// process any context_handle attributes from param nodes
if ( MyContext.ExtractAttribute( ATTR_CONTEXT ) )
{
CG_NDR * pChildCG;
MyContext.ContextHandleSizes( this );
pContext->ReturnSize( MyContext );
pChildCG = new CG_CONTEXT_HANDLE( this, NULL, MyContext );
return pChildCG;
}
// decide if we are a MS union or a DCE union
fMSUnion = (BOOL) MyContext.ExtractAttribute( ATTR_MS_UNION );
fMSUnion = fMSUnion ||
GetMyInterfaceNode()->FInSummary( ATTR_MS_UNION ) ||
pCommand->IsSwitchDefined( SWITCH_MS_UNION );
fMSUnion = fMSUnion && !fEncap;
// store our own zp value for below
MyContext.GetZeePee() = GetZeePee();
if (MyContext.AnyAncestorBits(IL_IN_LOCAL))
{
if ( pLocalReUseDict->GetReUseEntry( pSaved, this ) )
{
CG_CLASS * pCG;
// reuse found...
pSaved->FetchInfo( &MyContext, pCG );
pContext->ReturnSize( MyContext );
return pCG;
}
}
else
{
if ( pReUseDict->GetReUseEntry( pSaved, this ) )
{
CG_CLASS * pCG;
// reuse found...
pSaved->FetchInfo( &MyContext, pCG );
pContext->ReturnSize( MyContext );
return pCG;
}
}
pUnionCG = new CG_UNION( this,
MyContext,
HasAtLeastOnePointer()
);
// save our CG node so that recursive use can find it
pSaved->SaveInfo( &MyContext, pUnionCG);
// process the union arms
while ( pCurField = (node_field *) MemIter.GetNext() )
{
pCurCaseCG = (CG_CASE *) pCurField->ILxlate( &MyContext );
// MyContext.AdjustSize();
// add all the cases for the given field to the list
if( pLastCaseCG )
{
pLastCaseCG->SetSibling( pCurCaseCG );
}
else
{
pFirstCaseCG = pCurCaseCG;
};
// advance pLastCaseCG to the end of the list
pLastCaseCG = pCurCaseCG;
assert( pLastCaseCG && "Null case list" );
while ( pLastCaseCG->GetSibling() )
pLastCaseCG = (CG_CASE *) pLastCaseCG->GetSibling();
}
// add a definition for the switch type to the CG node
if ( pSwTypeAttr )
{
node_skl * pNode = pSwTypeAttr->GetType();
// it gets its own context, so I doesn't mess up our sizing
XLAT_CTXT SwTypeCtxt( &MyContext );
CG_NDR * pSwCG = (CG_NDR *) pNode->ILxlate( &SwTypeCtxt );
pUnionCG->SetSwitchType( pSwCG );
}
// add the case list to the union node and set all the union entries
pUnionCG->SetChild( pFirstCaseCG );
MyContext.AlignEmbeddedUnion();
pUnionCG->SetSizesAndAlignments( MyContext );
pUnionCG->SetUnionFlavor( (fMSUnion) ?
UNION_NONENCAP_MS :
UNION_NONENCAP_DCE );
pUnionCG->SetOffline();
pSaved->SaveInfo( &MyContext, pUnionCG);
pContext->ReturnSize( MyContext );
return pUnionCG;
};
//--------------------------------------------------------------------
//
// node_en_union::ILxlate
//
// Notes:
//
//
// for an encapsulated union, we return the following tree:
// CG_ENCAP_STRUCT ( with switch field )
// |
// CG_ENCAP_UNION
// |
// CG_CASE - CG_CASE - CG_CASE - CG_CASE
// | | |
// CG_UNION_FLD CG_UNION_FLD CG_UNION_FLD
// |
// etc.
//
//--------------------------------------------------------------------
CG_CLASS *
node_en_union::ILxlate( XLAT_CTXT * pContext )
{
CG_UNION * pUnionCG;
#ifdef trace_cg
printf("..node_en_union\n");
#endif
// call non-encap union processor
pUnionCG = (CG_UNION *) node_union::ILxlate( pContext );
pUnionCG->SetUnionFlavor( UNION_ENCAP );
return pUnionCG;
};
//--------------------------------------------------------------------
//
// node_def::ILxlate
//
// Notes:
//
//
//
//--------------------------------------------------------------------
CG_CLASS *
node_def::ILxlate( XLAT_CTXT * pContext )
{
CG_CLASS * pChildCG = NULL;
XLAT_CTXT MyContext( this, pContext );
node_transmit * pTransmitAttr = (node_transmit *)
MyContext.ExtractAttribute( ATTR_TRANSMIT );
node_wire_marshal * pWireMarshalAttr= (node_wire_marshal *)
MyContext.ExtractAttribute( ATTR_WIRE_MARSHAL );
node_represent_as * pRepresentAttr = (node_represent_as *)
MyContext.ExtractAttribute( ATTR_REPRESENT_AS );
node_user_marshal * pUserMarshalAttr= (node_user_marshal *)
MyContext.ExtractAttribute( ATTR_USER_MARSHAL );
BOOL fEncode = (BOOL)
MyContext.ExtractAttribute( ATTR_ENCODE );
BOOL fDecode = (BOOL)
MyContext.ExtractAttribute( ATTR_DECODE );
BOOL fOpaque = (BOOL)
MyContext.ExtractAttribute( ATTR_OPAQUE );
node_guid * pGUID = (node_guid *)MyContext.ExtractAttribute(ATTR_GUID);
node_version * pVer = (node_version *)MyContext.ExtractAttribute(ATTR_VERSION);
node_constant_attr * pHC = (node_constant_attr *)MyContext.ExtractAttribute(ATTR_HELPCONTEXT);
node_constant_attr * pHSC = (node_constant_attr *)MyContext.ExtractAttribute(ATTR_HELPSTRINGCONTEXT);
node_text_attr * pHelpStr = (node_text_attr *)MyContext.ExtractAttribute(ATTR_HELPSTRING);
XLAT_CTXT * pIntfCtxt = (XLAT_CTXT *) MyContext.GetInterfaceContext();
char * pName = GetSymName();
BOOL fIsHRESULT = IsHResultOrSCode();
REUSE_INFO * pSaved;
while(MyContext.ExtractAttribute(ATTR_CUSTOM));
#ifdef trace_cg
printf("..node_def: %s\n", GetSymName());
#endif
fEncode |= pIntfCtxt->FInSummary( ATTR_ENCODE );
fDecode |= pIntfCtxt->FInSummary( ATTR_DECODE );
// only direct children of the interface get these bits
if ( !pContext->GetParent()->IsInterfaceOrObject() )
{
fEncode = FALSE;
fDecode = FALSE;
}
BOOL fInLibrary = MyContext.AnyAncestorBits(IL_IN_LIBRARY);
BOOL fHidden = (BOOL) MyContext.ExtractAttribute(ATTR_HIDDEN);
BOOL fPublic = FALSE;
MyContext.ExtractAttribute(ATTR_TYPEDESCATTR);
// check for public attribute
node_type_attr * pTA;
while (pTA = (node_type_attr *)MyContext.ExtractAttribute(ATTR_TYPE))
{
switch (pTA->GetAttr())
{
case TATTR_PUBLIC:
fPublic = TRUE;
break;
default:
// assert(!"Illegal attribute found on node_def during ILxlate");
break;
}
}
// clear member attributes
while (MyContext.ExtractAttribute(ATTR_MEMBER));
BOOL fNeedsCGTYPEDEF = fInLibrary &&
(fPublic || NULL != pGUID || NULL != pVer || NULL != pHC || NULL != pHelpStr || fHidden)
&&
!(fEncode || fDecode || pRepresentAttr || pTransmitAttr ||
pUserMarshalAttr || pWireMarshalAttr);
if (fNeedsCGTYPEDEF)
{
// see if we're already generated
if (MyContext.AnyAncestorBits(IL_IN_LOCAL))
{
if (pLocalReUseDict->GetReUseEntry(pSaved, this))
{
// reuse found...
pSaved->FetchInfo(&MyContext, pChildCG);
pContext->ReturnSize(MyContext);
return pChildCG;
}
}
else
{
if (pReUseDict->GetReUseEntry(pSaved, this))
{
// reuse found...
pSaved->FetchInfo(&MyContext, pChildCG);
pContext->ReturnSize(MyContext);
return pChildCG;
}
}
}
// process handle stuff
if ( GetHandleKind() == HDL_CTXT )
{
MyContext.ExtractAttribute( ATTR_CONTEXT );
}
else if (GetHandleKind() == HDL_GEN)
{
MyContext.ExtractAttribute( ATTR_HANDLE );
}
if ( fOpaque )
{
CG_OPAQUE_BLOCK * pOpaqueBlock;
CG_CLASS * pCGByte;
node_skl * pNodeByte;
long MemSize = GetSize( 0 );
unsigned short MemAlign = GetNdrAlign();
expr_node * pSizeExpr = new expr_constant( MemSize );
FIELD_ATTR_INFO FA;
// make the child node ( CG_BASETYPE with byte )
GetBaseTypeNode( &pNodeByte, SIGN_UNDEF, SIZE_UNDEF, TYPE_BYTE );
pCGByte = pNodeByte->ILxlate( &MyContext );
// store the size expr
FA.SetSizeIs( pSizeExpr );
// make the opaque block node
// set the memory and wire alignments properly
MyContext.GetMemAlign() = MemAlign;
MyContext.GetWireAlign() = MemAlign;
pOpaqueBlock = new CG_OPAQUE_BLOCK( this, &FA, MyContext );
pOpaqueBlock->SetPtrType( PTR_REF );
pOpaqueBlock->SetChild( pCGByte );
MyContext.ArraySize( pNodeByte, &FA );
pContext->ReturnSize( MyContext );
return pOpaqueBlock;
}
////////////////////////////////////////////////////////////////////////
// process the child, except for context handles and transmit_as types
if ( ( GetHandleKind() != HDL_CTXT ) && !pTransmitAttr && !pWireMarshalAttr)
{
pChildCG = (CG_CLASS *) GetChild()->ILxlate( &MyContext );
if (NULL != pChildCG && !IsTempName( GetSymName() ) )
{
switch ( pChildCG->GetCGID() )
{
// special case transmit_as to set the presented type
case ID_CG_TRANSMIT_AS:
((CG_TRANSMIT_AS *) pChildCG)->SetPresentedType( this );
break;
case ID_CG_COCLASS:
break;
// acf attributes are NOT transitive
case ID_CG_REPRESENT_AS:
case ID_CG_USER_MARSHAL:
// odl attributes are also NOT transitive
case ID_CG_TYPEDEF:
break;
// idl attributes ARE transitive
case ID_CG_CONTEXT_HDL:
case ID_CG_GENERIC_HDL:
default:
((CG_NDR *)pChildCG)->SetType( this );
}
}
// an HRESULT return type should be a CG_HRESULT
if ( fIsHRESULT )
{
if ( !MyContext.FindAncestorContext( NODE_PARAM ) )
{
node_proc * pProc;
WALK_CTXT * pProcCtxt =
MyContext.FindAncestorContext( NODE_PROC );
if ( pProcCtxt )
{
pProc = (node_proc *)pProcCtxt->GetParent();
if ( pProc->FInSummary( ATTR_OBJECT ) ||
pProc->GetMyInterfaceNode()->FInSummary( ATTR_OBJECT ) )
{
pChildCG = new CG_HRESULT( this, MyContext );
}
}
}
} // HRESULT tests
}
else if ( pTransmitAttr )
{
node_skl * pXmit;
CG_TRANSMIT_AS * pTransCG;
pXmit = pTransmitAttr->GetTransmitAsType();
// get rid of dangling attributes from the non-transmitted side
// we've already picked up the attributes that go with our node
MyContext.ClearAttributes();
pChildCG = (CG_CLASS *) pXmit->ILxlate( &MyContext );
MyContext.FixMemSizes( this );
// if the child had generic handle, skip that...
if ( pChildCG->GetCGID() == ID_CG_GENERIC_HDL )
pChildCG = (CG_CLASS*) pChildCG->GetChild();
pTransCG = new CG_TRANSMIT_AS( pXmit, this, MyContext );
pTransCG->SetChild( pChildCG );
pChildCG = pTransCG;
}
else if ( pWireMarshalAttr )
{
// Note that this is a node like for a transmit_as attribute,
// but we map it into CG_USER_MARSHAL like for a user_marshal node.
// "this" is the node for the presented type.
node_skl * pXmit = pWireMarshalAttr->GetWireMarshalType();
// get rid of dangling attributes from the non-transmitted side
// we've already picked up the attributes that go with our node
MyContext.ClearAttributes();
pChildCG = (CG_CLASS *) pXmit->ILxlate( &MyContext );
MyContext.FixMemSizes( this );
// no support for user_marshal with Oi or Oi1.
// Have to use Oi2 or Os.
if ( (pCommand->GetOptimizationFlags() & OPTIMIZE_INTERPRETER) &&
! (pCommand->GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2)
)
SemError( this, MyContext, REQUIRES_I2, "[wire_marshal]" );
CG_USER_MARSHAL * pUserCG = new CG_USER_MARSHAL(
pXmit,
GetSymName(), // pres type name
this,
MyContext,
TRUE // from transmit_as
);
pUserCG->SetChild( pChildCG );
pChildCG = pUserCG;
}
if ( GetHandleKind() != HDL_NONE )
{
CG_NDR * pCG;
if ( GetHandleKind() == HDL_CTXT )
{
MyContext.ContextHandleSizes( this );
// remaining attributes are not needed e.g. pointer attrs
MyContext.ClearAttributes();
pCG = new CG_CONTEXT_HANDLE( this, NULL, MyContext );
}
else // HDL_GEN
{
pCG = new CG_GENERIC_HANDLE( this, NULL, MyContext );
}
pCG->SetChild( pChildCG );
pChildCG = pCG;
}
if ( pRepresentAttr )
{
node_skl * pRepT = pRepresentAttr->GetRepresentationType();
if (pRepT)
{
MyContext.FixMemSizes( pRepT );
}
CG_REPRESENT_AS * pRepCG = new CG_REPRESENT_AS(
this,
pRepresentAttr->GetRepresentationName(),
pRepT,
MyContext
);
pRepCG->SetChild( pChildCG );
pChildCG = pRepCG;
}
else if ( pUserMarshalAttr )
{
node_skl * pUserT = pUserMarshalAttr->GetRepresentationType();
if (pUserT)
{
MyContext.FixMemSizes( pUserT );
}
// no support for user_marshal with Oi or Oi1.
// Have to use Oi2 or Os.
if ( (pCommand->GetOptimizationFlags() & OPTIMIZE_INTERPRETER) &&
! (pCommand->GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2)
)
SemError( this, MyContext, REQUIRES_I2, "[user_marshal]" );
CG_USER_MARSHAL * pUserCG = new CG_USER_MARSHAL(
this,
pUserMarshalAttr->GetRepresentationName(),
pUserT,
MyContext,
FALSE // not from transmit_as
);
pUserCG->SetChild( pChildCG );
pChildCG = pUserCG;
}
// wire marshal has to be under transmit as.
if ( fEncode || fDecode )
{
CG_TYPE_ENCODE * pPickleCG;
CG_PARAM * pParamCG;
CG_PROC * pProcCG;
pPickleCG = new CG_TYPE_ENCODE( this, fEncode, fDecode );
pPickleCG->SetChild( pChildCG );
pParamCG = new CG_PARAM( this,
0,
MyContext,
NULL,
0);
pParamCG->SetChild( pPickleCG );
pProcCG = new CG_TYPE_ENCODE_PROC( 0,
this,
NULL,
NULL,
0,
0,
0,
0,
0,
NULL,
OPTIMIZE_INTERPRETER,
0 );
pProcCG->SetChild( pParamCG );
pChildCG = (CG_CLASS *)pProcCG;
}
if (fNeedsCGTYPEDEF)
{
if (NULL == pChildCG)
{
// The only way we should be able to get here is if we had a typedef
// that contained a forward reference to an interface, dispinterface, etc.
// MKTYPLIB disallowed this but we're gonna go ahead and allow it.
assert(NODE_FORWARD == GetChild()->NodeKind());
assert(GetChild()->GetChild()->IsInterfaceOrObject());
pChildCG = ((node_interface *)(GetChild()->GetChild()))->GetCG(TRUE);
}
CG_TYPEDEF * pTD = new CG_TYPEDEF(this, MyContext);
pTD->SetChild(pChildCG);
pChildCG = (CG_CLASS *) pTD;
// remember this node so we don't generate two of these
pSaved->SaveInfo(&MyContext, pChildCG);
}
pContext->ReturnSize( MyContext );
return pChildCG;
};
//--------------------------------------------------------------------
//
// node_pointer::ILxlate
//
// Notes:
//
//
//
//--------------------------------------------------------------------
CG_CLASS *
node_pointer::ILxlate( XLAT_CTXT * pContext )
{
CG_CLASS * pChildCG = NULL;
CG_NDR * pCG = NULL;
XLAT_CTXT MyContext( this, pContext );
PTRTYPE PtrKind = PTR_UNKNOWN;
FIELD_ATTR_INFO FAInfo;
node_allocate * pAlloc;
short AllocDetails = 0;
node_byte_count * pCountAttr;
while(MyContext.ExtractAttribute(ATTR_CUSTOM));
#ifdef trace_cg
printf("..node_pointer\n");
#endif
////////////////////////////////////////////////////////////////////////
// process misc attributes
if ( pAlloc = (node_allocate *) MyContext.ExtractAttribute( ATTR_ALLOCATE ) )
{
AllocDetails = pAlloc->GetAllocateDetails();
}
////////////////////////////////////////////////////////////////////////
// process pointer attributes
PtrKind = MyContext.GetPtrKind();
// see if a param or return type context attr reached us...
pCountAttr = (node_byte_count *)
MyContext.ExtractAttribute( ATTR_BYTE_COUNT );
////////////////////////////////////////////////////////////////////////
// process field attributes
// see if we have any field attributes (are conformant or varying)
FAInfo.SetControl( TRUE, GetBasicType()->IsPtrOrArray() );
MyContext.ExtractFieldAttributes( &FAInfo );
FAInfo.Normalize();
switch ( FAInfo.Kind )
{
case FA_NONE:
{
//BUGBUG: If child is interface_reference,
//then create a CG_INTERFACE_POINTER node.
if (GetBasicType()->IsInterfaceOrObject() && MyContext.AnyAncestorBits(IL_IN_LIBRARY))
{
//This is an interface pointer without an [iid_is] attribute but in a type library.
// we don't care about the pointee
pCG = new CG_INTERFACE_POINTER( this,
GetBasicType(),
FAInfo.pIIDIsExpr );
}
else if ( pCountAttr )
{
pCG = new CG_BYTE_COUNT_POINTER( this,
PtrKind,
pCountAttr->GetByteCountParam()
);
}
else
{
pCG = new CG_POINTER( this,
PtrKind,
AllocDetails );
}
break;
}
case FA_VARYING:
{
pCG = new CG_LENGTH_POINTER( this,
PtrKind,
AllocDetails,
&FAInfo );
break;
}
case FA_CONFORMANT:
{
pCG = new CG_SIZE_POINTER( this,
PtrKind,
AllocDetails,
&FAInfo );
break;
}
case FA_CONFORMANT_VARYING:
{
pCG = new CG_SIZE_LENGTH_POINTER( this,
PtrKind,
AllocDetails,
&FAInfo );
break;
}
case FA_STRING:
{
pCG = new CG_STRING_POINTER( this,
PtrKind,
AllocDetails );
if (FAInfo.StringKind == STR_BSTRING)
{
((CG_STRING_POINTER *) pCG)->SetBStr();
}
break;
}
case FA_CONFORMANT_STRING:
{
if (FAInfo.StringKind == STR_STRING)
{
pCG = new CG_SIZE_STRING_POINTER( this,
PtrKind,
AllocDetails,
&FAInfo );
}
break;
}
case FA_INTERFACE:
{
//This is an interface pointer with an [iid_is] attribute.
// we don't care about the pointee
pCG = new CG_INTERFACE_POINTER( this,
GetBasicType(),
FAInfo.pIIDIsExpr );
break;
}
default: // string + varying combinations
{
assert (!"Invalid pointer kind");
break;
}
}
// process any context_handle attributes from param nodes
if ( MyContext.FInSummary( ATTR_CONTEXT ) )
if ( GetBasicType()->NodeKind() != NODE_POINTER )
{
MyContext.ExtractAttribute( ATTR_CONTEXT );
MyContext.ContextHandleSizes( this );
pContext->ReturnSize( MyContext );
pCG = new CG_CONTEXT_HANDLE( this, NULL, MyContext );
#ifdef trace_cg
printf("..node_pointer return 1\n");
#endif
return pCG;
}
// ignore pointers do not need to be rpc-able
if ( MyContext.ExtractAttribute( ATTR_IGNORE ) )
{
MyContext.IgnoredPtrSizes();
pContext->ReturnSize( MyContext );
pCG = new CG_IGNORED_POINTER( this );
return pCG;
}
////////////////////////////////////////////////////////////////////////
// process child
// if ( FAInfo.Kind != FA_INTERFACE)
if ( (!GetBasicType()->IsInterfaceOrObject()) &&
FAInfo.Kind != FA_INTERFACE &&
pCG->GetCGID() != ID_CG_INTERFACE_PTR)
pChildCG = GetChild()->ILxlate( &MyContext );
// if we are the pointer above an interface, we should get changed
// into an interface pointer
if ( ( ( GetBasicType()->NodeKind() == NODE_INTERFACE_REFERENCE ) ||
( GetBasicType()->IsInterfaceOrObject() ) ) &&
( pCG->GetCGID() != ID_CG_INTERFACE_PTR ) )
{
pCG = (CG_NDR *)pChildCG;
pChildCG = NULL;
}
// update sizes with the size of the pointer
pContext->BaseTypeSizes( this );
pCG->SetSizesAndAlignments( *pContext );
pCG->SetChild( pChildCG );
#ifdef trace_cg
printf("..node_pointer return 2\n");
#endif
return pCG;
};
//--------------------------------------------------------------------
//
// node_array::ILxlate
//
// Notes:
//
//
//
//--------------------------------------------------------------------
CG_CLASS *
node_array::ILxlate( XLAT_CTXT * pContext )
{
CG_CLASS * pChildCG;
CG_ARRAY * pCG;
unsigned short Dimensions;
PTRTYPE PtrKind = PTR_UNKNOWN;
XLAT_CTXT MyContext( this, pContext );
FIELD_ATTR_INFO FAInfo;
while(MyContext.ExtractAttribute(ATTR_CUSTOM));
#ifdef trace_cg
printf("..node_array\n");
#endif
// process any context_handle attributes from param nodes
if ( MyContext.ExtractAttribute( ATTR_CONTEXT ) )
{
CG_NDR * pCG;
MyContext.ContextHandleSizes( this );
pContext->ReturnSize( MyContext );
pCG = new CG_CONTEXT_HANDLE( this, NULL, MyContext );
return pCG;
}
////////////////////////////////////////////////////////////////////////
// process pointer attributes
PtrKind = MyContext.GetPtrKind();
assert( PtrKind != PTR_UNKNOWN );
// see if we have any field attributes (are conformant or varying)
FAInfo.SetControl( FALSE, GetChild()->IsPtrOrArray() );
MyContext.ExtractFieldAttributes( &FAInfo );
FAInfo.Normalize( pLowerBound, pUpperBound );
// if we are multi-dimensional, absorb parent information
if ( MyContext.AnyAncestorBits( IL_IN_MULTIDIM_CONF ) )
FAInfo.Kind |= FA_CONFORMANT;
// don't propogate varying down into a string
if ( MyContext.AnyAncestorBits( IL_IN_MULTIDIM_VAR ) &&
( ( FAInfo.Kind & FA_STRING ) == 0 ))
FAInfo.Kind |= FA_VARYING;
// if our child is also an array, tell it about us
if ( GetBasicType()->NodeKind() == NODE_ARRAY )
{
if ( FAInfo.Kind & FA_CONFORMANT )
MyContext.SetAncestorBits( IL_IN_MULTIDIM_CONF );
if ( FAInfo.Kind & FA_VARYING )
MyContext.SetAncestorBits( IL_IN_MULTIDIM_VAR );
}
else
{
MyContext.ClearAncestorBits( IL_IN_MULTIDIM_CONF | IL_IN_MULTIDIM_VAR );
}
// process the child
pChildCG = GetChild()->ILxlate( &MyContext );
MyContext.ArraySize( this, &FAInfo );
// fetch # of dimensions from child;
if ( pChildCG->IsArray() )
{
Dimensions = ( (CG_ARRAY *) pChildCG )->GetDimensions() + 1;
// force all inner dimensions to be REF
( (CG_ARRAY *) pChildCG )->SetPtrType( PTR_REF );
}
else
{
Dimensions = 1;
}
// force embedded arrays to be REF
if ( PtrKind != PTR_REF )
{
WALK_CTXT * pUpperCtxt = MyContext.GetParentContext();
while ( pUpperCtxt )
{
NODE_T Kind = pUpperCtxt->GetParent()->NodeKind();
if ( Kind == NODE_PARAM )
break;
else if ( Kind == NODE_DEF )
{
node_def * pNode = (node_def *) pUpperCtxt->GetParent();
if ( pNode->FInSummary( ATTR_TRANSMIT ) ||
pNode->FInSummary( ATTR_REPRESENT_AS ) )
{
PtrKind = PTR_REF;
break;
}
// else go up another level
}
else
{
PtrKind = PTR_REF;
break;
}
pUpperCtxt = pUpperCtxt->GetParentContext();
}
}
switch ( FAInfo.Kind )
{
case FA_NONE:
{
pCG = new CG_FIXED_ARRAY( this,
&FAInfo,
Dimensions,
MyContext );
break;
}
case FA_VARYING:
{
pCG = new CG_VARYING_ARRAY( this,
&FAInfo,
Dimensions,
MyContext );
break;
}
case FA_CONFORMANT:
{
pCG = new CG_CONFORMANT_ARRAY( this,
&FAInfo,
Dimensions,
MyContext );
break;
}
case FA_CONFORMANT_VARYING:
{
pCG = new CG_CONFORMANT_VARYING_ARRAY( this,
&FAInfo,
Dimensions,
MyContext );
break;
}
case FA_STRING:
{
pCG = new CG_STRING_ARRAY( this,
&FAInfo,
Dimensions,
MyContext );
break;
}
case FA_CONFORMANT_STRING:
{
pCG = new CG_CONFORMANT_STRING_ARRAY( this,
&FAInfo,
Dimensions,
MyContext );
break;
}
default: // string + varying combinations
{
assert (!"invalid conf/var combination");
break;
}
}
pContext->ReturnSize( MyContext );
pCG->SetPtrType( PtrKind );
pCG->SetChild( pChildCG );
return pCG;
};