home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 40 / IOPROG_40.ISO / SOFT / NETFrameworkSDK.exe / comsdk.cab / samples1.exe / smc / CORexp.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  127.2 KB  |  4,428 lines

  1. /*****************************************************************************/
  2.  
  3. #include "smcPCH.h"
  4. #pragma hdrstop
  5.  
  6. #include "genIL.h"
  7.  
  8. //////////////////////////////////////////////////////////////////////////////
  9. //
  10. //  The following flags have not yet been converted to the new format (custom
  11. //  atrributes):
  12. //
  13. //      System.Runtime.InteropServices.ComImportAttribute     tdImport
  14. //      System.Runtime.InteropServices.DllImportAttribute     PInvoke stuff
  15. //      System.Runtime.InteropServices.MethodImplAttribute    miOLE, miSynchronized, etc
  16. //
  17. //  The following one needs to be done in comp.cpp:
  18. //
  19. //      System.Runtime.InteropServices.GuidAttribute          guid in ModuleRec
  20.  
  21. /*****************************************************************************
  22.  *
  23.  *  Map the access level of a type / member to MD flags.
  24.  */
  25.  
  26. unsigned            ACCtoFlags(SymDef sym)
  27. {
  28.     static
  29.     unsigned        accFlags[] =
  30.     {
  31.         0,              // ACL_ERROR
  32.         mdPublic,       // ACL_PUBLIC
  33.         mdFamily,       // ACL_PROTECTED
  34.         mdFamORAssem,   // ACL_DEFAULT
  35.         mdPrivate,      // ACL_PRIVATE
  36.     };
  37.  
  38.     assert(accFlags[ACL_PRIVATE  ] == mdPrivate);
  39.     assert(accFlags[ACL_DEFAULT  ] == mdFamORAssem);
  40.     assert(accFlags[ACL_PROTECTED] == mdFamily);
  41.     assert(accFlags[ACL_PUBLIC   ] == mdPublic);
  42.  
  43.     assert(sym->sdAccessLevel != ACL_ERROR);
  44.     assert(sym->sdAccessLevel < arraylen(accFlags));
  45.  
  46.     return  accFlags[sym->sdAccessLevel];
  47. }
  48.  
  49. /*****************************************************************************
  50.  *
  51.  *  Map our type to a metadata type.
  52.  */
  53.  
  54. BYTE                intrinsicSigs[] =
  55. {
  56.     ELEMENT_TYPE_END,       // TYP_UNDEF
  57.     ELEMENT_TYPE_VOID,      // TYP_VOID
  58.     ELEMENT_TYPE_BOOLEAN,   // TYP_BOOL
  59.     ELEMENT_TYPE_CHAR,      // TYP_WCHAR
  60.  
  61.     ELEMENT_TYPE_I1,        // TYP_CHAR
  62.     ELEMENT_TYPE_U1,        // TYP_UCHAR
  63.     ELEMENT_TYPE_I2,        // TYP_SHORT
  64.     ELEMENT_TYPE_U2,        // TYP_USHORT
  65.     ELEMENT_TYPE_I4,        // TYP_INT
  66.     ELEMENT_TYPE_U4,        // TYP_UINT
  67.     ELEMENT_TYPE_I,         // TYP_NATINT
  68.     ELEMENT_TYPE_U,         // TYP_NATUINT
  69.     ELEMENT_TYPE_I8,        // TYP_LONG
  70.     ELEMENT_TYPE_U8,        // TYP_ULONG
  71.     ELEMENT_TYPE_R4,        // TYP_FLOAT
  72.     ELEMENT_TYPE_R8,        // TYP_DOUBLE
  73.     ELEMENT_TYPE_R8,        // TYP_LONGDBL
  74.     ELEMENT_TYPE_TYPEDBYREF,// TYP_REFANY
  75. };
  76.  
  77. #if 0
  78. unsigned        cycles()
  79. {
  80. __asm   push    EDX
  81. __asm   _emit   0x0F
  82. __asm   _emit   0x31
  83. __asm   pop     EDX
  84. };
  85. #endif
  86.  
  87. /*****************************************************************************
  88.  *
  89.  *  Attach the given security specification to the typedef/methoddef token.
  90.  */
  91.  
  92. void                compiler::cmpSecurityMD(mdToken token, SymXinfo infoList)
  93. {
  94.     while (infoList)
  95.     {
  96.         SecurityInfo    secInfo;
  97.         CorDeclSecurity secKind;
  98.         ConstStr        secStr;
  99.  
  100.         wchar    *      strStr;
  101.         size_t          strLen;
  102.  
  103.         mdPermission    secTok;
  104.  
  105.         wchar           secBuff[300];
  106.  
  107.         /* Ignore the entry if it's not a security thing */
  108.  
  109.         if  (infoList->xiKind != XI_SECURITY)
  110.             goto NEXT;
  111.  
  112.         /* Get hold of the descriptor and the action kind */
  113.  
  114.         secInfo = ((SymXinfoSec)infoList)->xiSecInfo;
  115.         secKind = secInfo->sdSpec;
  116.  
  117.         /* What kind of a security thing do we have? */
  118.  
  119.         if  (secInfo->sdIsPerm)
  120.         {
  121.             const   char *  name;
  122.             PairList        list;
  123.  
  124.             /* Form the fully qualified name of the class */
  125.  
  126.             name = cmpGlobalST->stTypeName(NULL, secInfo->sdPerm.sdPermCls, NULL, NULL, true);
  127.  
  128.             /* Start creating the monstrosity */
  129.  
  130.             wcscpy(secBuff                  , L"<PermissionSpecification><PermissionSet><Permission><Class><Name>");
  131.             wcscpy(secBuff + wcslen(secBuff), cmpUniConv(name, strlen(name) + 1));
  132.             wcscpy(secBuff + wcslen(secBuff), L"</Name></Class><StateData>");
  133.  
  134.             for (list = secInfo->sdPerm.sdPermVal; list; list = list->plNext)
  135.             {
  136.                 wcscpy(secBuff + wcslen(secBuff), L"<Param><Name>");
  137.                 wcscpy(secBuff + wcslen(secBuff), cmpUniConv(list->plName));
  138.                 wcscpy(secBuff + wcslen(secBuff), L"</Name><Value>");
  139.                 wcscpy(secBuff + wcslen(secBuff), list->plValue ? L"true" : L"false");
  140.                 wcscpy(secBuff + wcslen(secBuff), L"</Value></Param>");
  141.             }
  142.  
  143.             wcscpy(secBuff + wcslen(secBuff), L"</StateData></Permission></PermissionSet></PermissionSpecification>");
  144.         }
  145.         else
  146.         {
  147.             secStr = secInfo->sdCapbStr;
  148.             strLen = secStr->csLen;
  149.             strStr = cmpUniConv(secStr->csStr, strLen+1);
  150.  
  151.             wcscpy(secBuff          , L"<PermissionSpecification><CapabilityRef>");
  152.  
  153.             if  (*strStr == '{')
  154.             {
  155.                 wcscpy(secBuff + wcslen(secBuff), L"<GUID>");
  156.                 wcscpy(secBuff + wcslen(secBuff), strStr);
  157.                 wcscpy(secBuff + wcslen(secBuff), L"</GUID>");
  158.             }
  159.             else
  160.             {
  161.                 wcscpy(secBuff + wcslen(secBuff), L"<URL>");
  162.                 wcscpy(secBuff + wcslen(secBuff), strStr);
  163.                 wcscpy(secBuff + wcslen(secBuff), L"</URL>");
  164.             }
  165.  
  166.             wcscpy(secBuff + wcslen(secBuff), L"</CapabilityRef></PermissionSpecification>");
  167.         }
  168.  
  169.         assert(wcslen(secBuff) < arraylen(secBuff));
  170.  
  171. //      printf("Permission string [%u]: '%ls\n", wcslen(secBuff), secBuff);
  172.  
  173.         cycleCounterPause();
  174.  
  175. //      unsigned beg = cycles();
  176. //      static unsigned tot;
  177.  
  178. #if     1
  179.  
  180.         if  (FAILED(cmpWmde->DefinePermissionSet(token,
  181.                                                  secKind,
  182.                                                  secBuff,
  183.                                                  wcslen(secBuff)*sizeof(*secBuff),
  184.                                                  &secTok)))
  185.         {
  186. #ifdef  DEBUG
  187.             printf("Bad news - permission set string didn't pass muster:\n");
  188.             printf("    '%ls'\n", secBuff);
  189. #endif
  190.             cmpFatal(ERRmetadata);
  191.         }
  192.  
  193. #endif
  194.  
  195. //      unsigned end = cycles();
  196. //      tot += end - beg - 10;
  197. //      printf("cycle count = %u (%6.3lf sec)\n", end - beg - 10, (end - beg)/450000000.0);
  198. //      printf("total count = %u (%6.3lf sec)\n",            tot,        tot /450000000.0);
  199.  
  200.         cycleCounterResume();
  201.  
  202.     NEXT:
  203.  
  204.         infoList = infoList->xiNext;
  205.     }
  206. }
  207.  
  208. /*****************************************************************************
  209.  *
  210.  *  Attach a simple custom attribute to the given token.
  211.  */
  212.  
  213. void                compiler::cmpAttachMDattr(mdToken       target,
  214.                                               wideStr       oldName,
  215.                                               AnsiStr       newName,
  216.                                               mdToken     * newTokPtr,
  217.                                               unsigned      valTyp,
  218.                                               const void  * valPtr,
  219.                                               size_t        valSiz)
  220. {
  221.     /* Have we created the appropriate token yet ? */
  222.  
  223.     if  (*newTokPtr == 0)
  224.     {
  225.         wchar               nameBuff[MAX_CLASS_NAME];
  226.         mdToken             tref;
  227.  
  228.         unsigned            sigSize;
  229.         COR_SIGNATURE       sigBuff[6];
  230.  
  231.         // HACK: Should use real class here, the following might create dups!
  232.  
  233. #if 0
  234.         wcscpy(nameBuff, L"System/Attributes/");
  235.         wcscat(nameBuff, oldName);
  236. #else
  237.         wcscpy(nameBuff, oldName);
  238. #endif
  239.  
  240.         cycleCounterPause();
  241.  
  242.         if  (cmpWmde->DefineTypeRefByName(mdTokenNil, nameBuff, &tref))
  243.             cmpFatal(ERRmetadata);
  244.  
  245.         cycleCounterResume();
  246.  
  247.         // Temp hack: if no arguments are needed, just use the typeref
  248.  
  249.         if  (valTyp)
  250.         {
  251.             /* Form the signature - one or no arguments */
  252.  
  253.             sigBuff[0] = IMAGE_CEE_CS_CALLCONV_DEFAULT|IMAGE_CEE_CS_CALLCONV_HASTHIS;
  254.             sigBuff[1] = 0;
  255.             sigBuff[2] = ELEMENT_TYPE_VOID;
  256.  
  257.             sigSize = 3;
  258.  
  259.             if  (valTyp)
  260.             {
  261.                 sigBuff[1] = 1;
  262.                 sigBuff[3] = valTyp; sigSize++;
  263.             }
  264.  
  265.             /* Create the methodref for the constructor */
  266.  
  267.             cycleCounterPause();
  268.  
  269.             if  (cmpWmde->DefineMemberRef(tref, L".ctor", sigBuff, sigSize, newTokPtr))
  270.                 cmpFatal(ERRmetadata);
  271.  
  272.             cycleCounterResume();
  273.         }
  274.         else
  275.         {
  276.             *newTokPtr = tref;
  277.         }
  278.     }
  279.  
  280.     /* Add the custom attribute to the target token */
  281.  
  282.     cycleCounterPause();
  283.  
  284.     if  (cmpWmde->DefineCustomAttribute(target, *newTokPtr, valPtr, valSiz, NULL))
  285.         cmpFatal(ERRmetadata);
  286.  
  287.     cycleCounterResume();
  288. }
  289.  
  290. /*****************************************************************************
  291.  *
  292.  *  Attach any custom attributes in the given list to the given token.
  293.  */
  294.  
  295. void                compiler::cmpAddCustomAttrs(SymXinfo infoList, mdToken owner)
  296. {
  297.     cycleCounterPause();
  298.  
  299.     while (infoList)
  300.     {
  301.         if  (infoList->xiKind == XI_ATTRIBUTE)
  302.         {
  303.             mdToken         ctrTok;
  304.  
  305.             SymXinfoAttr    entry   = (SymXinfoAttr)infoList;
  306.             SymDef          ctorSym = entry->xiAttrCtor;
  307.  
  308.             /* Careful - we need to avoid out-of-order methoddef emission */
  309.  
  310.             if  (ctorSym->sdIsImport || ctorSym->sdFnc.sdfMDtoken)
  311.             {
  312.                 ctrTok = cmpILgen->genMethodRef(ctorSym, false);
  313.             }
  314.             else
  315.             {
  316.                 /*
  317.                     The following is just plain horrible. We need to get
  318.                     the token for the ctor, but if the ctor is defined
  319.                     locally and its methoddef hasn't been generated yet,
  320.                     we have to create a (redundant) methodref instead.
  321.                  */
  322.  
  323.                 if  (cmpFakeXargsVal == NULL)
  324.                      cmpFakeXargsVal = cmpCreateExprNode(NULL, TN_NONE, cmpTypeVoid);
  325.  
  326.                 ctrTok = cmpGenFncMetadata(ctorSym, cmpFakeXargsVal);
  327.  
  328.                 assert(ctorSym->sdFnc.sdfMDtoken == ctrTok); ctorSym->sdFnc.sdfMDtoken = 0;
  329.             }
  330.  
  331.             if  (cmpWmde->DefineCustomAttribute(owner,
  332.                                                 ctrTok,
  333.                                                 entry->xiAttrAddr,
  334.                                                 entry->xiAttrSize,
  335.                                                 NULL))
  336.             {
  337.                 cmpFatal(ERRmetadata);
  338.             }
  339.         }
  340.  
  341.         infoList = infoList->xiNext;
  342.     }
  343.  
  344.     cycleCounterResume();
  345. }
  346.  
  347. /*****************************************************************************
  348.  *
  349.  *  Generate metadata for the given function symbol (and, if the symbol is
  350.  *  a method of a class, make sure the metadata for that class is also
  351.  *  generated).
  352.  *
  353.  *  If the "xargs" value is non-zero, we're supposed to create a varargs
  354.  *  signature and the "xargs" value gives the arguments passed to "...".
  355.  */
  356.  
  357. mdToken             compiler::cmpGenFncMetadata(SymDef fncSym, Tree xargs)
  358. {
  359.     WMetaDataEmit * emitIntf;
  360.  
  361.     SymXinfoLnk     linkInfo;
  362.  
  363.     bool            isIntfFnc;
  364.     SymDef          ownerSym;
  365.     mdTypeDef       ownerTD;
  366.  
  367.     PCOR_SIGNATURE  sigPtr;
  368.     size_t          sigLen;
  369.  
  370.     wchar   *       fncName;
  371.     mdToken         fncTok;
  372.     TypDef          fncTyp;
  373.  
  374.     bool            mangle;
  375.  
  376.     bool            genref = false;
  377.  
  378.     unsigned        flags;
  379.  
  380.     /* Don't do this twice for the same method */
  381.  
  382.     if  (fncSym->sdFnc.sdfMDtoken && !xargs)
  383.         return  fncSym->sdFnc.sdfMDtoken;
  384.  
  385.     /* Is this method conditionally disabled? */
  386.  
  387.     if  (fncSym->sdFnc.sdfDisabled)
  388.     {
  389.         fncSym->sdFnc.sdfMDtoken = -1;
  390.         return  -1;
  391.     }
  392.  
  393.     /* Get hold of the function type */
  394.  
  395.     fncTyp = fncSym->sdType; assert(fncTyp->tdTypeKind == TYP_FNC);
  396.  
  397.     /* Get hold of any linkage information that may be present */
  398.  
  399.     linkInfo  = cmpFindLinkInfo(fncSym->sdFnc.sdfExtraInfo);
  400.  
  401.     /* Figure out the owning type, whether we need to mangle the name, etc. */
  402.  
  403.     ownerSym  = fncSym->sdParent;
  404.     isIntfFnc = false;
  405.  
  406.     if  (ownerSym->sdSymKind == SYM_CLASS)
  407.     {
  408.         if  (xargs)
  409.         {
  410.             if  (xargs == cmpFakeXargsVal)
  411.             {
  412.                 mdToken         savedTD;
  413.  
  414.                 /*
  415.                     This is the awful case where we have a reference to
  416.                     a method that is defined in the current compilation
  417.                     but we haven't generated it's methoddef yet; we can
  418.                     not simply ask for the methoddef right now because
  419.                     that would cause metadata output ordering  to get
  420.                     messed up. Rather, we just emit a (redundant) ref
  421.                     for the method (and if necessary a typeref for its
  422.                     class as well).
  423.                  */
  424.  
  425.                 xargs = NULL;
  426.  
  427.                 // HACK! The following is pretty gross .....
  428.  
  429.                 savedTD = ownerSym->sdClass.sdcMDtypedef;
  430.                           ownerSym->sdClass.sdcMDtypedef = 0;
  431.  
  432.                 ownerTD = cmpGenClsMetadata(ownerSym, true);
  433.  
  434.                           ownerSym->sdClass.sdcMDtypedef = savedTD;
  435.  
  436. //              printf("Stupid ref [%08X] to '%s'\n", ownerTD, cmpGlobalST->stTypeName(fncSym->sdType, fncSym, NULL, NULL, true));
  437.  
  438.                 genref  = true;
  439.             }
  440.             else
  441.             {
  442.                 /* Is the method an external import ? */
  443.  
  444.                 if  (fncSym->sdIsImport)
  445.                 {
  446.                     /* Generate a typeref for the containing class */
  447.  
  448.                     ownerTD = ownerSym->sdClass.sdcMDtypeImp;
  449.  
  450.                     if  (!ownerTD)
  451.                     {
  452.                         cmpMakeMDimpTref(ownerSym);
  453.                         ownerTD = ownerSym->sdClass.sdcMDtypeImp;
  454.                     }
  455.                 }
  456.                 else
  457.                 {
  458.                     /* Class defined locally, just use its typedef token */
  459.  
  460.                     ownerTD = fncSym->sdFnc.sdfMDtoken;
  461.                 }
  462.             }
  463.  
  464.             assert(ownerTD);
  465.         }
  466.         else
  467.         {
  468.             /* Get hold of the appropriate class token */
  469.  
  470.             ownerTD = ownerSym->sdClass.sdcMDtypedef;
  471.  
  472.             if  (!ownerTD)
  473.             {
  474.                 /* Generate metadata for the containing class */
  475.  
  476.                 cmpGenClsMetadata(ownerSym);
  477.  
  478.                 /* The class should now have a typedef */
  479.  
  480.                 ownerTD = ownerSym->sdClass.sdcMDtypedef; assert(ownerTD);
  481.             }
  482.  
  483.             /* May have called recursively */
  484.  
  485.             if  (fncSym->sdFnc.sdfMDtoken && !xargs)
  486.                 return  fncSym->sdFnc.sdfMDtoken;
  487.         }
  488.  
  489.         mangle = false;
  490.  
  491.         if  (ownerSym->sdClass.sdcFlavor == STF_INTF)
  492.             isIntfFnc = true;
  493.     }
  494.     else
  495.     {
  496.         /* This is a global/namespace function */
  497.  
  498.         ownerTD = 0;
  499.         mangle  = false;
  500.  
  501.         /* Has this function been defined or is it external? */
  502.  
  503.         if  (!fncSym->sdIsDefined && !linkInfo && !xargs)
  504.         {
  505.             /* Is this a fake function? */
  506.  
  507.             if  ((hashTab::getIdentFlags(fncSym->sdName) & IDF_PREDEF) && fncSym->sdParent == cmpGlobalNS)
  508.             {
  509.                 return  (fncSym->sdFnc.sdfMDtoken = -1);
  510.             }
  511.         }
  512.     }
  513.  
  514.     /* Figure out the flags */
  515.  
  516.     flags  = 0;
  517.  
  518.     if  (fncSym->sdIsMember && !mangle)
  519.     {
  520.         flags |= ACCtoFlags(fncSym);
  521.  
  522. #if STATIC_UNMANAGED_MEMBERS
  523.         if  (!ownerSym->sdType->tdIsManaged)
  524.         {
  525.             flags |= mdStatic;
  526.         }
  527.         else
  528. #endif
  529.         if  (fncSym->sdIsStatic)
  530.         {
  531.             assert(fncSym->sdFnc.sdfVirtual == false);
  532.             assert(fncSym->sdIsAbstract     == false);
  533.  
  534.             flags |= mdStatic;
  535.         }
  536.         else
  537.         {
  538.             if  (fncSym->sdIsAbstract)
  539.                 flags |= mdAbstract;
  540.  
  541.             if  (fncSym->sdFnc.sdfVirtual && fncSym->sdAccessLevel != ACL_PRIVATE)
  542.                 flags |= mdVirtual;
  543.  
  544.             if  (fncSym->sdIsSealed)
  545.             {
  546.                 flags |= mdFinal;
  547.  
  548.             }
  549.         }
  550.     }
  551.     else
  552.     {
  553.         flags |= mdStatic|mdPublic;
  554.     }
  555.  
  556. #ifndef __SMC__
  557. //  if  (!strcmp(fncSym->sdSpelling(), "cmpError") && !xargs)
  558. //      printf("Define method def for [%08X] '%s'\n", fncSym, cmpGlobalST->stTypeName(NULL, fncSym, NULL, NULL, true));
  559. //  if  (!strcmp(      fncSym->sdSpelling(), "cmpGenError") && xargs)
  560. //  if  (!strcmp(cmpCurFncSym->sdSpelling(), "cmpDeclClass"))
  561. //      printf("This is the bug, set a breakpoint at %s(%u)\n", __FILE__, __LINE__);
  562. //  if  (!strcmp(fncSym->sdSpelling(), "")) forceDebugBreak();
  563. #endif
  564.  
  565.     /* Create a signature for the method */
  566.  
  567.     sigPtr = (PCOR_SIGNATURE)cmpGenMemberSig(fncSym, xargs, fncTyp, NULL, &sigLen);
  568.  
  569.     /* Get hold of the function name, or make one up */
  570.  
  571.     if  (fncSym)
  572.     {
  573.         const   char *  symName;
  574.  
  575.         if  (fncSym->sdFnc.sdfCtor)
  576.         {
  577.             symName = fncSym->sdIsStatic ? OVOP_STR_CTOR_STAT
  578.                                          : OVOP_STR_CTOR_INST;
  579.  
  580.             flags |= mdSpecialName;
  581.         }
  582.         else
  583.         {
  584.             flags |= mdSpecialName;
  585.  
  586.             if  (fncSym->sdFnc.sdfOper == OVOP_NONE)
  587.             {
  588.                 symName = fncSym->sdName->idSpelling();
  589.  
  590.                 if  (!fncSym->sdFnc.sdfProperty)
  591.                     flags &= ~mdSpecialName;
  592.             }
  593.             else
  594.             {
  595.                 assert(cmpConfig.ccNewMDnames);
  596.  
  597. //              printf("Setting 'special name' bit for '%s' -> '%s'\n", fncSym->sdSpelling(), MDovop2name(fncSym->sdFnc.sdfOper));
  598.  
  599.                 symName = MDovop2name(fncSym->sdFnc.sdfOper); assert(symName);
  600.             }
  601.         }
  602.  
  603.         fncName = cmpUniConv(symName, strlen(symName)+1);
  604.     }
  605.     else
  606.     {
  607.         fncName = L"fptr";
  608.     }
  609.  
  610.     /* Create the method metadata definition */
  611.  
  612.     emitIntf = cmpWmde;
  613.  
  614.     if  (xargs || genref)
  615.     {
  616.         cycleCounterPause();
  617.  
  618. #if 1
  619.         if  (FAILED(emitIntf->DefineMemberRef(ownerTD,  // owning typedef
  620.                                               fncName,  // function name
  621.                                               sigPtr,   // signature addr
  622.                                               sigLen,   // signature len
  623.                                               &fncTok)))// the resulting token
  624.         {
  625.             cmpFatal(ERRmetadata);
  626.         }
  627. #else
  628.         int ret =   emitIntf->DefineMemberRef(ownerTD,  // owning typedef
  629.                                               fncName,  // function name
  630.                                               sigPtr,   // signature addr
  631.                                               sigLen,   // signature len
  632.                                               &fncTok); // the resulting token
  633.         if  (FAILED(ret))
  634.             cmpFatal(ERRmetadata);
  635.         if  (ret)
  636.             printf("Duplicate member ref %04X for '%s'\n", fncTok, cmpGlobalST->stTypeName(fncSym->sdType, fncSym, NULL, NULL, true));
  637. #endif
  638.  
  639.         cycleCounterResume();
  640.  
  641.         if  (!xargs)
  642.             fncSym->sdFnc.sdfMDtoken = fncTok;
  643.     }
  644.     else
  645.     {
  646.         bool            genArgNames;
  647.         unsigned        implFlags;
  648.         SymXinfo        funcInfo;
  649.  
  650.         SymXinfoAtc     clsMeth;
  651.         MethArgInfo     clsArgs;
  652.  
  653.         /* Get hold of any "extra" information attached to the function */
  654.  
  655.         funcInfo  = fncSym->sdFnc.sdfExtraInfo;
  656.  
  657.         /* Is this a fake method supplied by the runtime? */
  658.  
  659.         implFlags = fncSym->sdFnc.sdfRThasDef ? miRuntime
  660.                                               : miIL;
  661.  
  662.         /* Do we have a linkage specification for the function? */
  663.  
  664.         if  (linkInfo)
  665.             flags |= mdPinvokeImpl;
  666.  
  667.         /* Does the method belong to an "OLE" class/interface? */
  668.  
  669.         if  (ownerSym->sdSymKind == SYM_CLASS)
  670.         {
  671.             atCommFlavors   flavor = (ownerSym->sdClass.sdcFlavor == STF_INTF)
  672.                                         ? AC_COM_INTF
  673.                                         : AC_COM_REGISTER;
  674.  
  675.             if  (cmpFindATCentry(ownerSym->sdClass.sdcExtraInfo, flavor))
  676.                 implFlags |= miOLE;
  677.         }
  678.  
  679.         /* Do we have explicit method argument info? */
  680.  
  681.         clsMeth = NULL;
  682.         clsArgs = NULL;
  683.  
  684.         if  (funcInfo)
  685.         {
  686.             SymXinfoAtc     clsTemp;
  687.  
  688.             /* Look for a @com.method entry */
  689.  
  690.             clsMeth = cmpFindATCentry(funcInfo, AC_COM_METHOD);
  691.  
  692.             /* Look for a @com.params entry */
  693.  
  694.             clsTemp = cmpFindATCentry(funcInfo, AC_COM_PARAMS);
  695.             if  (clsTemp)
  696.                clsArgs = clsTemp->xiAtcInfo->atcInfo.atcParams;
  697.         }
  698.  
  699.         /* Is this a native method? */
  700.  
  701.         if  (fncSym->sdFnc.sdfNative && !linkInfo)
  702.             implFlags |= miInternalCall;
  703.  
  704.         /* Has the function been marked for exclusive access? */
  705.  
  706.         if  (fncSym->sdFnc.sdfExclusive)
  707.             implFlags |= miSynchronized;
  708.  
  709. //      printf("NOTE: define method MD for '%s'\n", cmpGlobalST->stTypeName(fncSym->sdType, fncSym, NULL, NULL, true)); fflush(stdout);
  710.  
  711. //      static int x; if (++x == 0) forceDebugBreak();
  712.  
  713.         cycleCounterPause();
  714.  
  715.         if  (emitIntf->DefineMethod    (ownerTD,    // owning typedef
  716.                                         fncName,    // function name
  717.                                         flags,      // method attrs
  718.                                         sigPtr,     // signature addr
  719.                                         sigLen,     // signature len
  720.                                         0,          // RVA (fill in later)
  721.                                         implFlags,  // impl flags
  722.                                         &fncTok))   // the resulting token
  723.         {
  724.             cmpFatal(ERRmetadata);
  725.         }
  726.  
  727.         if  (fncSym->sdFnc.sdfIntfImpl)
  728.         {
  729.             SymDef          ifncSym;
  730.             mdToken         ifncTok;
  731.  
  732.             /* Get hold of the method being implemented */
  733.  
  734.             ifncSym = fncSym->sdFnc.sdfIntfImpSym; assert(ifncSym);
  735.             ifncTok = ifncSym->sdFnc.sdfMDtoken;   assert(ifncTok);
  736.  
  737.             if  (emitIntf->DefineMethodImpl(ownerTD,    // owning typedef
  738.                                             fncTok,     // Method Body
  739.                                             ifncTok))   // interface method token
  740.             {
  741.                 cmpFatal(ERRmetadata);
  742.             }
  743.         }
  744.  
  745.         cycleCounterResume();
  746.  
  747.         fncSym->sdFnc.sdfMDtoken = fncTok;
  748.  
  749.         /* Do we need to generate extended argument attributes? */
  750.  
  751.         genArgNames = (linkInfo || cmpConfig.ccParamNames
  752.                                 || cmpConfig.ccGenDebug
  753.                                 || (implFlags & miOLE)
  754.                                 || fncTyp->tdFnc.tdfArgs.adAttrs);
  755.  
  756.         if  (fncTyp->tdFnc.tdfArgs.adExtRec || genArgNames)
  757.         {
  758.             ArgDef          argList;
  759.             MarshalInfo     argInfo;
  760.  
  761.             unsigned        argNum = 1;
  762.             bool            argExt = fncTyp->tdFnc.tdfArgs.adExtRec;
  763.  
  764.             /* Should we generate marshalling info for the return type? */
  765.  
  766.             if  (isIntfFnc || clsArgs)
  767.             {
  768.                 MethArgInfo     argTemp;
  769.                 mdToken         argTok;
  770.  
  771.                 /* Output the return type entry (as argument #0) */
  772.  
  773.                 cycleCounterPause();
  774.  
  775.                 if  (emitIntf->DefineParam(fncTok,            // method
  776.                                            0,                 // argument #
  777.                                            NULL,              // argument name
  778.                                            pdRetval|pdOut,    // attributes
  779.                                            ELEMENT_TYPE_VOID, // default val type
  780.                                            NULL,              // default val value
  781.                                            -1,
  782.                                            &argTok))          // the resulting token
  783.                 {
  784.                     cmpFatal(ERRmetadata);
  785.                 }
  786.  
  787.                 cycleCounterResume();
  788.  
  789.                 /* Generate marshalling info */
  790.  
  791.                 argInfo = NULL;
  792.  
  793.                 for (argTemp = clsArgs; argTemp; argTemp = argTemp->methArgNext)
  794.                 {
  795.                     if  (!argTemp->methArgName)
  796.                         continue;
  797.  
  798.                     if  (hashTab::tokenOfIdent(argTemp->methArgName) == tkRETURN)
  799.                     {
  800.                         argInfo = &argTemp->methArgDesc;
  801.                         break;
  802.                     }
  803.                 }
  804.  
  805.                 cmpGenMarshalInfo(argTok, fncTyp->tdFnc.tdfRett, argInfo);
  806.             }
  807.  
  808.             /* Are we adding an explicit "this" argument ? */
  809.  
  810. #if STATIC_UNMANAGED_MEMBERS
  811.  
  812.             if  (!fncSym->sdIsManaged && fncSym->sdIsMember)
  813.             {
  814.                 if  (genArgNames) // || argExt)
  815.                 {
  816.                     mdToken         argTok;
  817.  
  818.                     cycleCounterPause();
  819.  
  820.                     if  (emitIntf->DefineParam(fncTok,            // method
  821.                                                argNum,            // argument #
  822.                                                L"this",           // argument name
  823.                                                0,                 // attributes
  824.                                                ELEMENT_TYPE_VOID, // default val type
  825.                                                NULL,              // default val value
  826.                                                0,                 // default value length
  827.                                                &argTok))          // the resulting token
  828.                     {
  829.                         cmpFatal(ERRmetadata);
  830.                     }
  831.  
  832.                     cycleCounterResume();
  833.                 }
  834.  
  835.                 argNum++;
  836.             }
  837.  
  838. #endif
  839.  
  840.             /* Process the "real" arguments */
  841.  
  842.             for (argList = fncTyp->tdFnc.tdfArgs.adArgs;
  843.                  argList;
  844.                  argList = argList->adNext, argNum++)
  845.             {
  846.                 wchar   *       argName  = NULL;
  847.                 unsigned        argFlags;
  848.                 unsigned        argDefTp = ELEMENT_TYPE_VOID;
  849.                 void    *       argDefVP = NULL;
  850.  
  851.                 /* Figure out the argument mode */
  852.  
  853.                 argFlags = 0;
  854.  
  855.                 if  (argExt)
  856.                 {
  857.                     unsigned        tmpFlags;
  858.                     ArgExt          argXdsc = (ArgExt)argList;
  859.  
  860.                     assert(argList->adIsExt);
  861.  
  862.                     tmpFlags = argXdsc->adFlags;
  863.  
  864.                     if      (tmpFlags & (ARGF_MODE_OUT|ARGF_MODE_INOUT))
  865.                     {
  866.                         if  (tmpFlags & ARGF_MODE_INOUT)
  867.                             argFlags = pdOut|pdIn;
  868.                         else
  869.                             argFlags = pdOut;
  870.                     }
  871.                     else if (tmpFlags & ARGF_MARSH_ATTR)
  872.                     {
  873.                         SymXinfo        attr = argXdsc->adAttrs;
  874.  
  875.                         assert(attr && attr->xiNext == NULL
  876.                                     && attr->xiKind == XI_MARSHAL);
  877.  
  878.                         SymXinfoCOM     desc = (SymXinfoCOM)attr;
  879.                         MarshalInfo     info = desc->xiCOMinfo;
  880.  
  881. //                      printf("Arg mode = %d/%d\n", info->marshModeIn, info->marshModeOut);
  882.  
  883.                         if  (info->marshModeIn ) argFlags = pdIn;
  884.                         if  (info->marshModeOut) argFlags = pdOut;
  885.                     }
  886.  
  887.                     /* Is there a default value? */
  888.  
  889. //                  if  (argXdsc->adFlags & ARGF_DEFVAL)
  890. //                  {
  891. //                      argFlags |= pdHasDefault;
  892. //                  }
  893.                 }
  894.  
  895.                 /* Do we have explicit marshalling info for the argument? */
  896.  
  897.                 if  (clsArgs)
  898.                 {
  899.                     /* Replace the mode value with the info given */
  900.  
  901.                     argFlags &= ~(pdIn|pdOut);
  902.  
  903.                     if  (clsArgs->methArgDesc.marshModeIn ) argFlags |= pdIn;
  904.                     if  (clsArgs->methArgDesc.marshModeOut) argFlags |= pdOut;
  905.                 }
  906.  
  907.                 /* If we need to, output the argument name */
  908.  
  909.                 if  (genArgNames && argList->adName)
  910.                     argName = cmpUniConv(argList->adName);
  911.  
  912.                 /* Do we have anything worth saying about this parameter? */
  913.  
  914.                 if  (argName  != NULL ||
  915.                      argFlags != 0    ||
  916.                      argDefVP != NULL || linkInfo || clsArgs || fncTyp->tdFnc.tdfArgs.adAttrs)
  917.                 {
  918.                     mdToken         argTok;
  919.  
  920.                     cycleCounterPause();
  921.  
  922.                     if  (emitIntf->DefineParam(fncTok,        // method
  923.                                                argNum,        // argument #
  924.                                                argName,       // argument name
  925.                                                argFlags,      // attributes
  926.                                                argDefTp,      // default val type
  927.                                                argDefVP,      // default val value
  928.                                                -1,
  929.                                                &argTok))      // the resulting token
  930.                     {
  931.                         cmpFatal(ERRmetadata);
  932.                     }
  933.  
  934.                     cycleCounterResume();
  935.  
  936.                     /* Do we have explicit marshalling info for the argument? */
  937.  
  938.                     if  (clsArgs)
  939.                     {
  940.                         /* Output native marshalling information */
  941.  
  942.                         cmpGenMarshalInfo(argTok, argList->adType, &clsArgs->methArgDesc);
  943.  
  944.                         /* Skip past the current argument */
  945.  
  946.                         clsArgs = clsArgs->methArgNext;
  947.                     }
  948.                     else if (fncTyp->tdFnc.tdfArgs.adAttrs)
  949.                     {
  950.                         ArgExt          argXdsc  = (ArgExt)argList;
  951.                         unsigned        argFlags = argXdsc->adFlags;
  952.  
  953.                         assert(argExt && argList->adIsExt);
  954.  
  955.                         if  (argFlags & ARGF_MARSH_ATTR)
  956.                         {
  957.                             SymXinfo        attr = argXdsc->adAttrs;
  958.  
  959.                             assert(attr && attr->xiNext == NULL
  960.                                         && attr->xiKind == XI_MARSHAL);
  961.  
  962.                             SymXinfoCOM     desc = (SymXinfoCOM)attr;
  963.                             MarshalInfo     info = desc->xiCOMinfo;
  964.  
  965.                             if  (argFlags & (ARGF_MODE_OUT|ARGF_MODE_INOUT))
  966.                             {
  967.                                 info->marshModeOut = true;
  968.  
  969.                                 if  (argFlags & ARGF_MODE_INOUT)
  970.                                     info->marshModeIn = true;
  971.                             }
  972.  
  973.                             cmpGenMarshalInfo(argTok, argList->adType, info);
  974.                         }
  975.                     }
  976.                 }
  977.             }
  978.         }
  979.  
  980.         /* Has the function been marked as "deprecated" ? */
  981.  
  982.         if  (fncSym->sdIsDeprecated)
  983.         {
  984.             cmpAttachMDattr(fncTok, L"Deprecated",
  985.                                      "Deprecated", &cmpAttrDeprec); // , ELEMENT_TYPE_STRING);
  986.         }
  987.  
  988.         /* Do we have a linkage specification for the function? */
  989.  
  990.         if  (linkInfo)
  991.         {
  992.             const   char *  DLLname;
  993.             size_t          DLLnlen;
  994.             const   char *  SYMname;
  995.             size_t          SYMnlen;
  996.  
  997.             mdModuleRef     modRef;
  998.             unsigned        flags;
  999.  
  1000.             /* Get hold of the name strings */
  1001.  
  1002.             DLLname = linkInfo->xiLink.ldDLLname; assert(DLLname);
  1003.             DLLnlen = strlen(DLLname);
  1004.             SYMname = linkInfo->xiLink.ldSYMname; if (!SYMname) SYMname = fncSym->sdSpelling();
  1005.             SYMnlen = strlen(SYMname);
  1006.  
  1007.             /* Get hold of a module ref for the DLL */
  1008.  
  1009.             cycleCounterPause();
  1010.  
  1011.             if  (FAILED(emitIntf->DefineModuleRef(cmpUniConv(DLLname, DLLnlen+1),
  1012.                                                   &modRef)))
  1013.             {
  1014.                 cmpFatal(ERRmetadata);
  1015.             }
  1016.  
  1017.             cycleCounterResume();
  1018.  
  1019.             /* Figure out the attributes */
  1020.  
  1021.             switch (linkInfo->xiLink.ldStrings)
  1022.             {
  1023.             default: flags = pmCharSetNotSpec; break;
  1024.             case  1: flags = pmCharSetAuto   ; break;
  1025.             case  2: flags = pmCharSetAnsi   ; break;
  1026.             case  3: flags = pmCharSetUnicode; break;
  1027.             case  4: flags = pmPinvokeOLE    ; break;
  1028.             }
  1029.  
  1030.             if  (linkInfo->xiLink.ldLastErr)
  1031.                 flags |= pmSupportsLastError;
  1032.  
  1033.             // UNDONE: Don't hard-wire calling convention
  1034.  
  1035. #if 1
  1036.  
  1037.             if  (!strcmp(DLLname, "msvcrt.dll"))
  1038.             {
  1039.                 flags |= pmCallConvCdecl;
  1040.  
  1041. //              if  (linkInfo->xiLink.ldCallCnv != CCNV_CDECL)
  1042. //                  printf("WARNING: %s::%s isn't cdecl \n", DLLname, SYMname);
  1043.             }
  1044.             else
  1045.             {
  1046.                 flags |= pmCallConvStdcall;
  1047.  
  1048. //              if  (linkInfo->xiLink.ldCallCnv != CCNV_WINAPI)
  1049. //                  printf("WARNING: %s::%s isn't winapi\n", DLLname, SYMname);
  1050.             }
  1051.  
  1052. #else
  1053.  
  1054.             switch (linkInfo->xiLink.ldCallCnv)
  1055.             {
  1056.             case CCNV_CDECL  : flags |= pmCallConvCdecl  ; break;
  1057.             case CCNV_WINAPI : flags |= pmCallConvWinapi ; break;
  1058.             case CCNV_STDCALL: flags |= pmCallConvStdcall; break;
  1059.             default:         /* ??????????????????????? */ break;
  1060.             }
  1061.  
  1062. #endif
  1063.  
  1064.             /* Now set the PInvoke info on the method */
  1065.  
  1066.             cycleCounterPause();
  1067.  
  1068.             if  (emitIntf->DefinePinvokeMap(fncTok,
  1069.                                             flags,
  1070.                                             cmpUniConv(SYMname, SYMnlen+1),
  1071.                                             modRef))
  1072.             {
  1073.                 cmpFatal(ERRmetadata);
  1074.             }
  1075.  
  1076.             cycleCounterResume();
  1077.         }
  1078.  
  1079.         /* Do we have any security specifications for the function? */
  1080.  
  1081.         if  (cmpFindSecSpec(funcInfo))
  1082.             cmpSecurityMD(fncSym->sdFnc.sdfMDtoken, funcInfo);
  1083.  
  1084.         /* Do we have a vtable slot specification for the method? */
  1085.  
  1086.         if  (clsMeth)
  1087.         {
  1088.             assert(clsMeth->xiAtcInfo);
  1089.             assert(clsMeth->xiAtcInfo->atcFlavor == AC_COM_METHOD);
  1090.  
  1091. //          printf("VTslot=%2d, DISPID=%2d for '%s'\n", clsMeth->xiAtcInfo->atcInfo.atcMethod.atcVToffs,
  1092. //                                                      clsMeth->xiAtcInfo->atcInfo.atcMethod.atcDispid,
  1093. //                                                      fncSym->sdSpelling());
  1094.         }
  1095.  
  1096.         /* Look for any custom attributes that the method might have */
  1097.  
  1098.         if  (funcInfo)
  1099.             cmpAddCustomAttrs(funcInfo, fncTok);
  1100.     }
  1101.  
  1102.     return  fncTok;
  1103. }
  1104.  
  1105. /*****************************************************************************
  1106.  *
  1107.  *  Generate metadata for the given function signature.
  1108.  */
  1109.  
  1110. mdSignature         compiler::cmpGenSigMetadata(TypDef fncTyp, TypDef pref)
  1111. {
  1112.     assert(fncTyp->tdTypeKind == TYP_FNC);
  1113.  
  1114.     if  (!fncTyp->tdFnc.tdfPtrSig)
  1115.     {
  1116.         PCOR_SIGNATURE  sigPtr;
  1117.         size_t          sigLen;
  1118.         mdSignature     sigTok;
  1119.  
  1120.         /* Create a signature for the method */
  1121.  
  1122.         sigPtr = (PCOR_SIGNATURE)cmpGenMemberSig(NULL, NULL, fncTyp, pref, &sigLen);
  1123.  
  1124.         /* Get a token for the signature */
  1125.  
  1126.         cycleCounterPause();
  1127.  
  1128.         if  (FAILED(cmpWmde->GetTokenFromSig(sigPtr, sigLen, &sigTok)))
  1129.             cmpFatal(ERRmetadata);
  1130.  
  1131.         cycleCounterResume();
  1132.  
  1133.         fncTyp->tdFnc.tdfPtrSig = sigTok;
  1134.     }
  1135.  
  1136.     return  fncTyp->tdFnc.tdfPtrSig;
  1137. }
  1138.  
  1139. /*****************************************************************************
  1140.  *
  1141.  *  Generate metadata for the given global / static data member symbol (and,
  1142.  *  if the symbol is a member of a class, make sure the metadata for that
  1143.  *  class is also generated).
  1144.  */
  1145.  
  1146. void                compiler::cmpGenFldMetadata(SymDef fldSym)
  1147. {
  1148.     SymDef          ownerSym;
  1149.     mdTypeDef       ownerTD;
  1150.  
  1151.     __int32         ival;
  1152.     __int64         lval;
  1153.     float           fval;
  1154.     double          dval;
  1155.  
  1156.     wchar   *       constBuf;
  1157.     unsigned        constTyp;
  1158.     void    *       constPtr;
  1159.  
  1160.     PCOR_SIGNATURE  sigPtr;
  1161.     size_t          sigLen;
  1162.  
  1163.     unsigned        flags;
  1164.  
  1165.     bool            mangle;
  1166.  
  1167.     __int32         eval;
  1168.  
  1169.     mdToken         ftok;
  1170.  
  1171.     /* Figure out the owning type */
  1172.  
  1173.     ownerSym = fldSym->sdParent;
  1174.  
  1175.     if  (ownerSym->sdSymKind == SYM_CLASS)
  1176.     {
  1177.         assert(fldSym->sdSymKind == SYM_VAR);
  1178.         assert(fldSym->sdVar.sdvGenSym == NULL || fldSym->sdIsStatic);
  1179.  
  1180.         /* Don't do this twice for the same field */
  1181.  
  1182.         if  (fldSym->sdVar.sdvMDtoken)
  1183.             return;
  1184.  
  1185.         ownerTD = ownerSym->sdClass.sdcMDtypedef;
  1186.         if  (!ownerTD)
  1187.         {
  1188.             /* Generate metadata for the containing class */
  1189.  
  1190.             cmpGenClsMetadata(ownerSym);
  1191.  
  1192.             /* May have called recursively */
  1193.  
  1194.             if  (fldSym->sdVar.sdvMDtoken)
  1195.                 return;
  1196.  
  1197.             /* The class should now have a typedef */
  1198.  
  1199.             ownerTD = ownerSym->sdClass.sdcMDtypedef; assert(ownerTD);
  1200.         }
  1201.  
  1202.         mangle = false;
  1203.     }
  1204.     else if (fldSym->sdSymKind == SYM_ENUMVAL)
  1205.     {
  1206.         TypDef          type = fldSym->sdType; assert(type->tdTypeKind == TYP_ENUM);
  1207.         SymDef          esym = type->tdEnum.tdeSymbol;
  1208.  
  1209.         ownerTD = esym->sdEnum.sdeMDtypedef; assert(ownerTD);
  1210.         mangle  = false;
  1211.     }
  1212.     else
  1213.     {
  1214.         ownerTD = 0;
  1215.         mangle  = false;
  1216.     }
  1217.  
  1218.     /* Figure out the flags */
  1219.  
  1220.     flags = ACCtoFlags(fldSym);
  1221.  
  1222.     if  (fldSym->sdIsMember)
  1223.     {
  1224.         /* This is a (data) member of a class */
  1225.  
  1226.         if  (fldSym->sdIsStatic)
  1227.             flags |= fdStatic;
  1228.     }
  1229.     else
  1230.     {
  1231.         if  (fldSym->sdIsStatic || ownerSym == cmpGlobalNS)
  1232.         {
  1233.             /* Must be a global (or local static) unmanaged variable */
  1234.  
  1235.             flags |= fdStatic|fdHasFieldRVA;
  1236.  
  1237.             if  (ownerSym->sdSymKind == SYM_SCOPE)
  1238.                 flags = fdPrivateScope|fdStatic|fdHasFieldRVA;
  1239.         }
  1240.     }
  1241.  
  1242.     if  (fldSym->sdIsSealed)
  1243.         flags |= fdInitOnly;
  1244.  
  1245.     /* Is there a constant value we need to attach to the member? */
  1246.  
  1247.     constTyp = ELEMENT_TYPE_VOID;
  1248.     constPtr = NULL;
  1249.     constBuf = NULL;
  1250.  
  1251.     switch (fldSym->sdSymKind)
  1252.     {
  1253.         var_types       vtp;
  1254.  
  1255.     case SYM_VAR:
  1256.  
  1257.         if  (fldSym->sdVar.sdvConst)
  1258.         {
  1259.             ConstVal        cval = fldSym->sdVar.sdvCnsVal;
  1260.             var_types       vtyp = (var_types)cval->cvVtyp;
  1261.  
  1262.             assert(fldSym->sdCompileState >= CS_CNSEVALD);
  1263.  
  1264.             /* What's the type of the constant? */
  1265.  
  1266.         GEN_CNS:
  1267.  
  1268.             flags |=  fdLiteral|fdStatic;
  1269.             flags &= ~fdInitOnly;
  1270.  
  1271.             switch (vtyp)
  1272.             {
  1273.             case TYP_BOOL:
  1274.             case TYP_CHAR:
  1275.             case TYP_UCHAR:
  1276.             case TYP_WCHAR:
  1277.             case TYP_SHORT:
  1278.             case TYP_USHORT:
  1279.             case TYP_INT:
  1280.             case TYP_UINT:
  1281.                 ival = cval->cvValue.cvIval; constPtr = &ival;
  1282.                 break;
  1283.  
  1284.             case TYP_LONG:
  1285.             case TYP_ULONG:
  1286.                 lval = cval->cvValue.cvLval; constPtr = &lval;
  1287.                 break;
  1288.  
  1289.             case TYP_FLOAT:
  1290.                 fval = cval->cvValue.cvFval; constPtr = &fval;
  1291.                 break;
  1292.  
  1293.             case TYP_DOUBLE:
  1294.                 dval = cval->cvValue.cvDval; constPtr = &dval;
  1295.                 break;
  1296.  
  1297.             case TYP_ENUM:
  1298.                 vtyp = cval->cvType->tdEnum.tdeIntType->tdTypeKindGet();
  1299.                 goto GEN_CNS;
  1300.  
  1301.             case TYP_PTR:
  1302.             case TYP_REF:
  1303.  
  1304.                 /* Must be either a string or "null" */
  1305.  
  1306.                 if  (cval->cvIsStr)
  1307.                 {
  1308.                     size_t          len = cval->cvValue.cvSval->csLen;
  1309.  
  1310.                     constBuf = (wchar*)SMCgetMem(this, roundUp((len+1)*sizeof(*constBuf)));
  1311.  
  1312.                     mbstowcs(constBuf, cval->cvValue.cvSval->csStr, len+1);
  1313.  
  1314.                     constTyp = ELEMENT_TYPE_STRING;
  1315.                     constPtr = constBuf;
  1316.                     goto DONE_CNS;
  1317.                 }
  1318.                 else
  1319.                 {
  1320.                     ival = 0; constPtr = &ival;
  1321.  
  1322.                     constTyp = ELEMENT_TYPE_I4;
  1323.                     goto DONE_CNS;
  1324.                 }
  1325.                 break;
  1326.  
  1327.             case TYP_UNDEF:
  1328.                 break;
  1329.  
  1330.             default:
  1331. #ifdef  DEBUG
  1332.                 printf("\nConstant type: '%s'\n", cmpGlobalST->stTypeName(cval->cvType, NULL, NULL, NULL, false));
  1333. #endif
  1334.                 UNIMPL(!"unexpected const type");
  1335.             }
  1336.  
  1337.             assert(vtyp < arraylen(intrinsicSigs)); constTyp = intrinsicSigs[vtyp];
  1338.         }
  1339.         break;
  1340.  
  1341.     case SYM_ENUMVAL:
  1342.  
  1343.         flags |=  fdLiteral|fdStatic;
  1344.         flags &= ~fdInitOnly;
  1345.  
  1346.         assert(fldSym->sdType->tdTypeKind == TYP_ENUM);
  1347.  
  1348.         vtp = fldSym->sdType->tdEnum.tdeIntType->tdTypeKindGet();
  1349.  
  1350.         if  (vtp < TYP_LONG)
  1351.         {
  1352.             eval     =  fldSym->sdEnumVal.sdEV.sdevIval;
  1353.  
  1354.             constTyp = ELEMENT_TYPE_I4;
  1355.             constPtr = &eval;
  1356.         }
  1357.         else
  1358.         {
  1359.             lval     = *fldSym->sdEnumVal.sdEV.sdevLval;
  1360.  
  1361.             constTyp = ELEMENT_TYPE_I8;
  1362.             constPtr = &lval;
  1363.         }
  1364.         break;
  1365.     }
  1366.  
  1367. DONE_CNS:
  1368.  
  1369.     /* Create a signature for the member */
  1370.  
  1371.     sigPtr  = (PCOR_SIGNATURE)cmpGenMemberSig(fldSym, NULL, NULL, NULL, &sigLen);
  1372.  
  1373.     /* Create the member metadata definition */
  1374.  
  1375. #ifndef __IL__
  1376. //  if  (!strcmp(fldSym->sdSpelling(), "e_cblp")) __asm int 3
  1377. #endif
  1378.  
  1379. //  printf("NOTE: define field  MD for '%s'\n", cmpGlobalST->stTypeName(NULL, fldSym, NULL, NULL, true)); fflush(stdout);
  1380.  
  1381.     cycleCounterPause();
  1382.  
  1383.     if  (cmpWmde->DefineField(ownerTD,                      // owning typedef
  1384.                               cmpUniConv(fldSym->sdName),   // member name
  1385.                               flags,                        // member attrs
  1386.                               sigPtr,                       // signature addr
  1387.                               sigLen,                       // signature len
  1388.                               constTyp,                     // constant type
  1389.                               constPtr,                     // constant value
  1390.                               -1,                           // optional length
  1391.                               &ftok))                       // resulting token
  1392.     {
  1393.         cmpFatal(ERRmetadata);
  1394.     }
  1395.  
  1396.     /* Has the member been marked as "deprecated" ? */
  1397.  
  1398.     if  (fldSym->sdIsDeprecated)
  1399.     {
  1400.         cmpAttachMDattr(ftok, L"Deprecated"            ,
  1401.                                "Deprecated"            , &cmpAttrDeprec);
  1402.     }
  1403.  
  1404.     if  (fldSym->sdIsTransient)
  1405.     {
  1406.         cmpAttachMDattr(ftok, L"NonSerializedAttribute",
  1407.                                "NonSerializedAttribute", &cmpAttrNonSrlz);
  1408.     }
  1409.  
  1410.     cycleCounterResume();
  1411.  
  1412.     /* Look for any custom attributes that the member might have */
  1413.  
  1414.     SymXinfo        fldInfo = NULL;
  1415.  
  1416.     if  (fldSym->sdSymKind == SYM_VAR)
  1417.     {
  1418.         if  (!fldSym->sdVar.sdvConst    &&
  1419.              !fldSym->sdVar.sdvBitfield &&
  1420.              !fldSym->sdVar.sdvLocal)
  1421.         {
  1422.             fldInfo = fldSym->sdVar.sdvFldInfo;
  1423.         }
  1424.     }
  1425.     else
  1426.     {
  1427.         if  (fldSym->sdSymKind == SYM_ENUMVAL)
  1428.             fldInfo = fldSym->sdEnumVal.sdeExtraInfo;
  1429.     }
  1430.  
  1431.     if  (fldInfo)
  1432.     {
  1433.         cmpAddCustomAttrs(fldInfo, ftok);
  1434.  
  1435.         do
  1436.         {
  1437.             if  (fldInfo->xiKind == XI_MARSHAL)
  1438.             {
  1439.                 SymXinfoCOM     desc = (SymXinfoCOM)fldInfo;
  1440.                 MarshalInfo     info = desc->xiCOMinfo;
  1441.  
  1442.                 cmpGenMarshalInfo(ftok, fldSym->sdType, info);
  1443.             }
  1444.  
  1445.             fldInfo = fldInfo->xiNext;
  1446.         }
  1447.         while (fldInfo);
  1448.     }
  1449.  
  1450.     if  (fldSym->sdSymKind == SYM_VAR)
  1451.         fldSym->sdVar.sdvMDtoken = ftok;
  1452.  
  1453.     if  (constBuf)
  1454.         SMCrlsMem(this, constBuf);
  1455. }
  1456.  
  1457. /*****************************************************************************
  1458.  *
  1459.  *  Return a typedef/typeref token for the given class/enum type.
  1460.  */
  1461.  
  1462. mdToken             compiler::cmpClsEnumToken(TypDef type)
  1463. {
  1464.     SymDef          tsym;
  1465.     mdToken         token;
  1466.  
  1467. AGAIN:
  1468.  
  1469.     if  (type->tdTypeKind == TYP_CLASS)
  1470.     {
  1471.         tsym = type->tdClass.tdcSymbol;
  1472.  
  1473.         /* Is this an imported class? */
  1474.  
  1475.         if  (tsym->sdIsImport)
  1476.         {
  1477.             /* Do we have a typeref for the class yet? */
  1478.  
  1479.             if  (!tsym->sdClass.sdcMDtypeImp)
  1480.             {
  1481.                 cmpMakeMDimpTref(tsym);
  1482.  
  1483.                 if  (tsym->sdClass.sdcAssemIndx)
  1484.                     cmpAssemblySymDef(tsym);
  1485.             }
  1486.  
  1487.             token = tsym->sdClass.sdcMDtypeImp;
  1488.         }
  1489.         else
  1490.         {
  1491.             /* Make sure metadata for the class has been emitted */
  1492.  
  1493.             if  (!tsym->sdClass.sdcMDtypedef)
  1494.                 cmpGenClsMetadata(tsym);
  1495.  
  1496.             token = tsym->sdClass.sdcMDtypedef;
  1497.         }
  1498.     }
  1499.     else
  1500.     {
  1501.         if  (type->tdTypeKind != TYP_ENUM)
  1502.         {
  1503.             if  (type->tdTypeKind == TYP_TYPEDEF)
  1504.             {
  1505.                 type = type->tdTypedef.tdtType;
  1506.                 goto AGAIN;
  1507.             }
  1508.  
  1509.             /* Must have had errors, return any random value */
  1510.  
  1511.             assert(type->tdTypeKind == TYP_UNDEF);
  1512.             return  1;
  1513.         }
  1514.  
  1515.         tsym = type->tdEnum.tdeSymbol;
  1516.  
  1517.         /* Is this an imported enum? */
  1518.  
  1519.         if  (tsym->sdIsImport)
  1520.         {
  1521.             /* Do we have a typeref for the class yet? */
  1522.  
  1523.             if  (!tsym->sdEnum.sdeMDtypeImp)
  1524.             {
  1525.                 cmpMakeMDimpEref (tsym);
  1526.  
  1527.                 if  (tsym->sdEnum.sdeAssemIndx)
  1528.                     cmpAssemblySymDef(tsym);
  1529.             }
  1530.  
  1531.             token = tsym->sdEnum.sdeMDtypeImp;
  1532.         }
  1533.         else
  1534.         {
  1535.             /* Make sure metadata for the enum has been emitted */
  1536.  
  1537.             if  (!tsym->sdEnum.sdeMDtypedef)
  1538.                 cmpGenClsMetadata(tsym);
  1539.  
  1540.             token = tsym->sdEnum.sdeMDtypedef;
  1541.         }
  1542.     }
  1543.  
  1544.     return  token;
  1545. }
  1546.  
  1547. /*****************************************************************************
  1548.  *
  1549.  *  Return a metadata token to represent the given string literal.
  1550.  */
  1551.  
  1552. mdToken             compiler::cmpMDstringLit(wchar *str, size_t len)
  1553. {
  1554.     mdToken         strTok;
  1555.  
  1556.     cycleCounterPause();
  1557.  
  1558.     if  (cmpWmde->DefineUserString(str, len, &strTok))
  1559.         cmpFatal(ERRmetadata);
  1560.  
  1561.     cycleCounterResume();
  1562.  
  1563.     return  strTok;
  1564. }
  1565.  
  1566. /*****************************************************************************
  1567.  *
  1568.  *  Low-level helpers used to construct signature blobs.
  1569.  */
  1570.  
  1571. void                compiler::cmpMDsigStart()
  1572. {
  1573.     assert(cmpMDsigUsed == false);
  1574. #ifndef NDEBUG
  1575.     cmpMDsigUsed = true;
  1576. #endif
  1577.     cmpMDsigNext = cmpMDsigBase;
  1578. }
  1579.  
  1580. void                compiler::cmpMDsigExpand(size_t more)
  1581. {
  1582.     char    *       buff;
  1583.     size_t          size;
  1584.     size_t          osiz;
  1585.  
  1586.     /* Figure out the size to allocate; we double the buffer, at least */
  1587.  
  1588.     size = cmpMDsigSize + more;
  1589.     if  (more < cmpMDsigSize)
  1590.          size = 2 * cmpMDsigSize;
  1591.  
  1592.     /* Round up the size to just under a page multiple */
  1593.  
  1594.     size +=  (OS_page_size-1);
  1595.     size &= ~(OS_page_size-1);
  1596.     size -= 32;
  1597.  
  1598.     /* Allocate the new buffer */
  1599.  
  1600. #if MGDDATA
  1601.     buff = new managed char [size];
  1602. #else
  1603.     buff = (char *)LowLevelAlloc(size);
  1604. #endif
  1605.  
  1606.     /* Copy the current buffer contents to the new location */
  1607.  
  1608.     osiz = cmpMDsigNext - cmpMDsigBase;
  1609.  
  1610.     assert(osiz <= cmpMDsigSize + 4 && osiz + more <= size);
  1611.  
  1612.     memcpy(buff, cmpMDsigBase, osiz);
  1613.  
  1614.     /* Free up the previous buffer if it's on the heap */
  1615.  
  1616.     if  (cmpMDsigHeap)
  1617.         LowLevelFree(cmpMDsigHeap);
  1618.  
  1619.     /* Switch to the new buffer and we're ready to continue */
  1620.  
  1621.     cmpMDsigBase =
  1622.     cmpMDsigHeap = buff;
  1623.     cmpMDsigSize = size - 4;
  1624.     cmpMDsigNext = buff + osiz;
  1625.     cmpMDsigEndp = buff + cmpMDsigSize;
  1626. }
  1627.  
  1628. PCOR_SIGNATURE      compiler::cmpMDsigEnd(size_t *sizePtr)
  1629. {
  1630.     assert(cmpMDsigNext <= cmpMDsigEndp);
  1631.  
  1632.     *sizePtr = cmpMDsigNext-cmpMDsigBase;
  1633.  
  1634. #ifndef NDEBUG
  1635.     cmpMDsigUsed = false;
  1636. #endif
  1637.  
  1638.     return  (PCOR_SIGNATURE)cmpMDsigBase;
  1639. }
  1640.  
  1641. void                compiler::cmpMDsigAddStr(const char *str, size_t len)
  1642. {
  1643.     assert(len);
  1644.  
  1645.     if  (cmpMDsigNext + len > cmpMDsigEndp)
  1646.         cmpMDsigExpand(len);
  1647.  
  1648.     memcpy(cmpMDsigNext, str, len);
  1649.            cmpMDsigNext   +=  len;
  1650. }
  1651.  
  1652. inline
  1653. void                compiler::cmpMDsigAdd_I1(int val)
  1654. {
  1655.     if  (cmpMDsigNext >= cmpMDsigEndp)
  1656.         cmpMDsigExpand(1);
  1657.  
  1658.     *cmpMDsigNext++ = val;
  1659. }
  1660.  
  1661. void                compiler::cmpMDsigAddCU4(unsigned val)
  1662. {
  1663.     if  (val <= 0x7F)
  1664.     {
  1665.         cmpMDsigAdd_I1(val);
  1666.     }
  1667.     else
  1668.     {
  1669.         char            buff[8];
  1670.  
  1671.         if  (cmpMDsigNext + 8 >= cmpMDsigEndp)
  1672.             cmpMDsigExpand(8);
  1673.  
  1674.         cmpMDsigAddStr(buff, CorSigCompressData(val, buff));
  1675.     }
  1676. }
  1677.  
  1678. void                compiler::cmpMDsigAddTok(mdToken tok)
  1679. {
  1680.     char            buff[8];
  1681.  
  1682.     if  (cmpMDsigNext + 8 >= cmpMDsigEndp)
  1683.         cmpMDsigExpand(8);
  1684.  
  1685.     cmpMDsigAddStr(buff, CorSigCompressToken(tok, buff));
  1686. }
  1687.  
  1688. /*****************************************************************************
  1689.  *
  1690.  *  Generate a signature for the given type.
  1691.  */
  1692.  
  1693. PCOR_SIGNATURE      compiler::cmpTypeSig(TypDef type, size_t *lenPtr)
  1694. {
  1695.             cmpMDsigStart ();
  1696.             cmpMDsigAddTyp(type);
  1697.     return  cmpMDsigEnd   (lenPtr);
  1698. }
  1699.  
  1700. /*****************************************************************************
  1701.  *
  1702.  *  Append a signature of the given type to the current signature blob.
  1703.  */
  1704.  
  1705. void                compiler::cmpMDsigAddTyp(TypDef type)
  1706. {
  1707.     var_types       vtyp;
  1708.  
  1709. AGAIN:
  1710.  
  1711.     vtyp = type->tdTypeKindGet();
  1712.  
  1713.     if  (vtyp <= TYP_lastIntrins)
  1714.     {
  1715.     INTRINS:
  1716.  
  1717.         assert(vtyp < arraylen(intrinsicSigs));
  1718.  
  1719.         cmpMDsigAdd_I1(intrinsicSigs[vtyp]);
  1720.         return;
  1721.     }
  1722.  
  1723.     switch (vtyp)
  1724.     {
  1725.         mdToken         token;
  1726.  
  1727.     case TYP_REF:
  1728.  
  1729.         type = cmpActualType(type->tdRef.tdrBase);
  1730.         if  (type->tdTypeKind != TYP_CLASS || type->tdClass.tdcValueType)
  1731.         {
  1732.             cmpMDsigAdd_I1(ELEMENT_TYPE_BYREF);
  1733.             goto AGAIN;
  1734.         }
  1735.  
  1736.         // It's a reference to a class, so fall through ...
  1737.  
  1738.     case TYP_CLASS:
  1739.  
  1740.         if  (type->tdClass.tdcSymbol == cmpClassString)
  1741.         {
  1742.             cmpMDsigAdd_I1(ELEMENT_TYPE_STRING);
  1743.             return;
  1744.         }
  1745.  
  1746.         if  (type->tdClass.tdcValueType || !type->tdIsManaged)
  1747.         {
  1748.             if  (type->tdClass.tdcIntrType != TYP_UNDEF)
  1749.             {
  1750.                 vtyp = (var_types)type->tdClass.tdcIntrType;
  1751.                 goto INTRINS;
  1752.             }
  1753.  
  1754.             token = cmpClsEnumToken(type); assert(token);
  1755.  
  1756.             cmpMDsigAddCU4(ELEMENT_TYPE_VALUECLASS);
  1757.             cmpMDsigAddTok(token);
  1758.             return;
  1759.         }
  1760.  
  1761.         token = cmpClsEnumToken(type); assert(token);
  1762.  
  1763.         cmpMDsigAddCU4(ELEMENT_TYPE_CLASS);
  1764.         cmpMDsigAddTok(token);
  1765.  
  1766.         return;
  1767.  
  1768.     case TYP_ENUM:
  1769.  
  1770.         if  (cmpConfig.ccIntEnums)
  1771.         {
  1772.             type = type->tdEnum.tdeIntType;
  1773.             goto AGAIN;
  1774.         }
  1775.  
  1776.         token = cmpClsEnumToken(type); assert(token);
  1777.  
  1778.         cmpMDsigAddCU4(ELEMENT_TYPE_VALUECLASS);
  1779.         cmpMDsigAddTok(token);
  1780.         return;
  1781.  
  1782.     case TYP_TYPEDEF:
  1783.  
  1784.         type = type->tdTypedef.tdtType;
  1785.         goto AGAIN;
  1786.  
  1787.     case TYP_PTR:
  1788.         type = cmpActualType(type->tdRef.tdrBase);
  1789.         if  (type->tdTypeKind == TYP_FNC)
  1790.         {
  1791.             cmpMDsigAdd_I1(ELEMENT_TYPE_I4);
  1792.             return;
  1793.         }
  1794.         cmpMDsigAdd_I1(ELEMENT_TYPE_PTR);
  1795.         goto AGAIN;
  1796.  
  1797.     case TYP_ARRAY:
  1798.  
  1799.         assert(type->tdIsValArray == (type->tdIsManaged && isMgdValueType(cmpActualType(type->tdArr.tdaElem))));
  1800.  
  1801.         if  (type->tdIsManaged)
  1802.         {
  1803.             TypDef          elem = cmpDirectType(type->tdArr.tdaElem);
  1804.             DimDef          dims = type->tdArr.tdaDims; assert(dims);
  1805.  
  1806.             if  (dims->ddNext)
  1807.             {
  1808.                 cmpMDsigAddCU4(ELEMENT_TYPE_ARRAY);
  1809.                 cmpMDsigAddTyp(elem);
  1810.                 cmpMDsigAddCU4(type->tdArr.tdaDcnt);
  1811.                 cmpMDsigAddCU4(0);
  1812.                 cmpMDsigAddCU4(0);
  1813.             }
  1814.             else
  1815.             {
  1816.                 cmpMDsigAddCU4(ELEMENT_TYPE_SZARRAY);
  1817.                 cmpMDsigAddTyp(elem);
  1818.             }
  1819.         }
  1820.         else
  1821.         {
  1822.             assert(type->tdIsValArray  == false);
  1823.  
  1824.             if  (!type->tdArr.tdaTypeSig)
  1825.             {
  1826.                 WMetaDataEmit * emitIntf;
  1827.  
  1828.                 mdTypeDef       tdef;
  1829.                 char            name[16];
  1830.  
  1831.                 size_t          sz;
  1832.                 size_t          al;
  1833.  
  1834.                 sz = cmpGetTypeSize(type, &al);
  1835.  
  1836.                 /* For now we use a fake struct with the right size */
  1837.  
  1838.                 static
  1839.                 unsigned        arrCnt;
  1840.  
  1841.                 sprintf(name, "$ARR%08X", arrCnt++);    // HACK!!!!!!
  1842.  
  1843.                 emitIntf = cmpWmde;
  1844.  
  1845.                 cycleCounterPause();
  1846.  
  1847.                 /* Create the fake struct type */
  1848.  
  1849.                 if  (emitIntf->DefineTypeDef(cmpUniConv(name, strlen(name)+1),
  1850.                                              NULL,
  1851.                                              tdLayoutSequential|tdValueType|tdSealed,
  1852.                                              0,
  1853.                                              NULL,
  1854.                                              &tdef))
  1855.                 {
  1856.                     cmpFatal(ERRmetadata);
  1857.                 }
  1858.  
  1859.                 /* Don't forget to set the alignment and size */
  1860.  
  1861.                 if  (emitIntf->SetClassLayout(tdef, al, NULL, sz))
  1862.                     cmpFatal(ERRmetadata);
  1863.  
  1864.                 cycleCounterResume();
  1865.  
  1866.                 type->tdArr.tdaTypeSig = tdef;
  1867.             }
  1868.  
  1869.             cmpMDsigAddCU4(ELEMENT_TYPE_VALUECLASS);
  1870.             cmpMDsigAddTok(type->tdArr.tdaTypeSig);
  1871.         }
  1872.         return;
  1873.  
  1874.     default:
  1875.  
  1876. #ifdef  DEBUG
  1877.         printf("Type '%s'\n", cmpGlobalST->stTypeName(type, NULL, NULL, NULL, false));
  1878. #endif
  1879.         UNIMPL(!"output user type sig");
  1880.     }
  1881. }
  1882.  
  1883. /*****************************************************************************
  1884.  *
  1885.  *  Recursively generates signatures for all local variables contained within
  1886.  *  the given scope.
  1887.  */
  1888.  
  1889. void                compiler::cmpGenLocalSigRec(SymDef scope)
  1890. {
  1891.     SymDef          child;
  1892.  
  1893.     for (child = scope->sdScope.sdScope.sdsChildList;
  1894.          child;
  1895.          child = child->sdNextInScope)
  1896.     {
  1897.         if  (child->sdSymKind == SYM_SCOPE)
  1898.         {
  1899.             cmpGenLocalSigRec(child);
  1900.         }
  1901.         else
  1902.         {
  1903.             if  (child->sdIsStatic)
  1904.                 continue;
  1905.             if  (child->sdVar.sdvConst && !child->sdIsSealed)
  1906.                 continue;
  1907.  
  1908.             assert(child->sdSymKind == SYM_VAR);
  1909.             assert(child->sdVar.sdvLocal);
  1910.  
  1911.             if  (child->sdVar.sdvArgument)
  1912.                 continue;
  1913.             if  (child->sdIsImplicit)
  1914.                 continue;
  1915.  
  1916. //          printf("Add local to sig [%2u/%2u]: '%s'\n", child->sdVar.sdvILindex, cmpGenLocalSigLvx, cmpGlobalST->stTypeName(NULL, child, NULL, NULL, false));
  1917.  
  1918. #ifdef  DEBUG
  1919.             assert(child->sdVar.sdvILindex == cmpGenLocalSigLvx); cmpGenLocalSigLvx++;
  1920. #endif
  1921.  
  1922.             cmpMDsigAddTyp(child->sdType);
  1923.         }
  1924.     }
  1925. }
  1926.  
  1927. /*****************************************************************************
  1928.  *
  1929.  *  Generate metadata signature for the local variables declared within
  1930.  *  the given scope.
  1931.  */
  1932.  
  1933. mdSignature         compiler::cmpGenLocalSig(SymDef scope, unsigned count)
  1934. {
  1935.     PCOR_SIGNATURE  sigPtr;
  1936.     size_t          sigLen;
  1937.  
  1938.     mdSignature     sigTok;
  1939.  
  1940.     genericRef      tmpLst;
  1941.  
  1942. #ifdef  DEBUG
  1943.     cmpGenLocalSigLvx = 0;
  1944. #endif
  1945.  
  1946.     /* Construct the signature for all non-argument locals */
  1947.  
  1948.     cmpMDsigStart();
  1949.  
  1950.     /* First thing is the magic value and count of locals */
  1951.  
  1952.     cmpMDsigAdd_I1(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG);
  1953.     cmpMDsigAddCU4(count);
  1954.  
  1955.     /* Next come the signatures for all the user-declared locals */
  1956.  
  1957.     cmpGenLocalSigRec(scope);
  1958.  
  1959.     /* Next we add signatures for amy temps created during IL gen */
  1960.  
  1961.     tmpLst = cmpILgen->genTempIterBeg();
  1962.  
  1963.     if  (tmpLst)
  1964.     {
  1965.         do
  1966.         {
  1967.             TypDef          tmpTyp;
  1968.  
  1969. //          printf("Type of temp #%02X is '%s'\n", cmpGenLocalSigLvx, symTab::stIntrinsicTypeName(((ILtemp)tmpLst)->tmpType->tdTypeKindGet()));
  1970.  
  1971. #ifdef  DEBUG
  1972.             assert(((ILtemp)tmpLst)->tmpNum == cmpGenLocalSigLvx); cmpGenLocalSigLvx++;
  1973. #endif
  1974.  
  1975.             /* Get the type of the current temp and advance the iterator */
  1976.  
  1977.             tmpLst = cmpILgen->genTempIterNxt(tmpLst, tmpTyp);
  1978.  
  1979.             // HACK: map 'void' to ELEMENT_BYREF / int
  1980.  
  1981.             if  (tmpTyp->tdTypeKind == TYP_VOID)
  1982.             {
  1983.                 cmpMDsigAdd_I1(ELEMENT_TYPE_BYREF);
  1984.                 cmpMDsigAdd_I1(ELEMENT_TYPE_I4);
  1985.                 continue;
  1986.             }
  1987.  
  1988.             /* Append this temp to the signature */
  1989.  
  1990.             cmpMDsigAddTyp(tmpTyp);
  1991.         }
  1992.         while (tmpLst);
  1993.     }
  1994.  
  1995.     sigPtr = cmpMDsigEnd(&sigLen);
  1996.  
  1997.     /* Make sure we found the expected number of locals and temps */
  1998.  
  1999.     assert(cmpGenLocalSigLvx == count);
  2000.  
  2001.     /* Now create a metadata token from the signature and return it */
  2002.  
  2003.     if  (sigLen > 2)
  2004.     {
  2005.         cycleCounterPause();
  2006.  
  2007.         if  (FAILED(cmpWmde->GetTokenFromSig(sigPtr, sigLen, &sigTok)))
  2008.             cmpFatal(ERRmetadata);
  2009.  
  2010.         cycleCounterResume();
  2011.  
  2012.         return  sigTok;
  2013.     }
  2014.     else
  2015.         return  0;
  2016. }
  2017.  
  2018. /*****************************************************************************
  2019.  *
  2020.  *  Create a dotted unicode name for the given symbol.
  2021.  */
  2022.  
  2023. wchar   *           compiler::cmpArrayClsPref(SymDef sym,
  2024.                                               wchar *dest,
  2025.                                               int    delim, bool fullPath)
  2026. {
  2027.     wchar   *       name;
  2028.     SymDef          parent = sym->sdParent; assert(parent);
  2029.  
  2030.     if  ((parent->sdSymKind == sym->sdSymKind || fullPath) && parent != cmpGlobalNS)
  2031.     {
  2032.         dest = cmpArrayClsPref(parent, dest, delim, fullPath); *dest++ = delim;
  2033.     }
  2034.  
  2035.     name = cmpUniConv(sym->sdName);
  2036.  
  2037.     wcscpy(dest, name);
  2038.  
  2039.     return  dest + wcslen(name);
  2040. }
  2041.  
  2042. /*****************************************************************************
  2043.  *
  2044.  *  Create a fake array class name of the form "System.Integer2[]".
  2045.  */
  2046.  
  2047. wchar   *           compiler::cmpArrayClsName(TypDef type,
  2048.                                               bool   nonAbstract, wchar *dest,
  2049.                                                                   wchar *nptr)
  2050. {
  2051.     SymDef          csym;
  2052.     SymDef          psym;
  2053.  
  2054.     var_types       vtyp = type->tdTypeKindGet();
  2055.  
  2056.     if  (vtyp <= TYP_lastIntrins)
  2057.     {
  2058.         /* Locate the appropriate built-in value type */
  2059.  
  2060.         type = cmpFindStdValType(vtyp); assert(type);
  2061.     }
  2062.     else
  2063.     {
  2064.         switch (vtyp)
  2065.         {
  2066.         case TYP_ARRAY:
  2067.  
  2068.             assert(type->tdIsManaged);
  2069.  
  2070.              dest = cmpArrayClsName(type->tdArr.tdaElem, nonAbstract, dest, nptr);
  2071.             *dest++ = '[';
  2072.  
  2073.             if  (type->tdIsGenArray && !nonAbstract)
  2074.             {
  2075.                 *dest++ = '?';
  2076.             }
  2077.             else
  2078.             {
  2079.                 DimDef          dims;
  2080.  
  2081.                 for (dims = type->tdArr.tdaDims;;)
  2082.                 {
  2083.                     dims = dims->ddNext;
  2084.                     if  (!dims)
  2085.                         break;
  2086.                     *dest++ = ',';
  2087.                 }
  2088.             }
  2089.  
  2090.             *dest++ = ']';
  2091.  
  2092.             return  dest;
  2093.  
  2094.         case TYP_REF:
  2095.  
  2096.             type = type->tdRef.tdrBase;
  2097.             break;
  2098.  
  2099.         case TYP_CLASS:
  2100.             break;
  2101.  
  2102.         default:
  2103.             NO_WAY(!"unexpected array element type");
  2104.         }
  2105.     }
  2106.  
  2107.     assert(type->tdTypeKind == TYP_CLASS);
  2108.     assert(type->tdIsManaged);
  2109.  
  2110.     csym = type->tdClass.tdcSymbol;
  2111.     psym = csym->sdParent;
  2112.  
  2113.     while (psym->sdSymKind == SYM_CLASS)
  2114.         psym = psym->sdParent;
  2115.  
  2116.     assert(psym && psym->sdSymKind == SYM_NAMESPACE);
  2117.  
  2118.     /* Form the namespace and class name */
  2119.  
  2120.     if  (psym != cmpGlobalNS)
  2121.         nptr = cmpArrayClsPref(psym, nptr, '.');
  2122.  
  2123.     *nptr = 0;
  2124.  
  2125.     return  cmpArrayClsPref(csym, dest, '$');
  2126. }
  2127.  
  2128. /*****************************************************************************
  2129.  *
  2130.  *  Return a typeref token for the given managed array type.
  2131.  */
  2132.  
  2133. mdToken             compiler::cmpArrayTpToken(TypDef type, bool nonAbstract)
  2134. {
  2135.     if  (!nonAbstract || !type->tdIsGenArray)
  2136.         type = cmpGetBaseArray(type);
  2137.  
  2138.     assert(type);
  2139.     assert(type->tdIsManaged);
  2140.     assert(type->tdTypeKind == TYP_ARRAY);
  2141.  
  2142.     if  (!type->tdArr.tdaTypeSig)
  2143.     {
  2144.         mdTypeSpec      arrTok;
  2145.         PCOR_SIGNATURE  sigPtr;
  2146.         size_t          sigLen;
  2147.  
  2148.                  cmpMDsigStart ();
  2149.                  cmpMDsigAddTyp(type);
  2150.         sigPtr = cmpMDsigEnd   (&sigLen);
  2151.  
  2152.         cycleCounterPause();
  2153.  
  2154.         if  (FAILED(cmpWmde->GetTokenFromTypeSpec(sigPtr, sigLen, &arrTok)))
  2155.             cmpFatal(ERRmetadata);
  2156.  
  2157.         cycleCounterResume();
  2158.  
  2159.         type->tdArr.tdaTypeSig = arrTok;
  2160.     }
  2161.  
  2162.     return  type->tdArr.tdaTypeSig;
  2163. }
  2164.  
  2165. /*****************************************************************************
  2166.  *
  2167.  *  Return a methodref token for a constructor that will allocate the given
  2168.  *  managed array type.
  2169.  */
  2170.  
  2171. mdToken             compiler::cmpArrayCTtoken(TypDef  arrType,
  2172.                                               TypDef elemType, unsigned dimCnt)
  2173. {
  2174.     PCOR_SIGNATURE  sigPtr;
  2175.     size_t          sigLen;
  2176.  
  2177.     mdToken         fncTok;
  2178.  
  2179.     bool            loBnds = (bool)arrType->tdIsGenArray;
  2180.  
  2181.     // UNDONE: Look for an existing methodref token to reuse ....
  2182.  
  2183.     cmpMDsigStart();
  2184.     cmpMDsigAdd_I1(IMAGE_CEE_CS_CALLCONV_DEFAULT|IMAGE_CEE_CS_CALLCONV_HASTHIS);
  2185.     cmpMDsigAddCU4(loBnds ? 2*dimCnt : dimCnt);
  2186.     cmpMDsigAdd_I1(ELEMENT_TYPE_VOID);
  2187.  
  2188.     do
  2189.     {
  2190.         cmpMDsigAdd_I1(ELEMENT_TYPE_I4);
  2191.         if  (loBnds)
  2192.             cmpMDsigAdd_I1(ELEMENT_TYPE_I4);
  2193.     }
  2194.     while (--dimCnt);
  2195.  
  2196.     char tempSigBuff[256];
  2197.     sigPtr = (PCOR_SIGNATURE) tempSigBuff;
  2198.     PCOR_SIGNATURE  tempSig = cmpMDsigEnd(&sigLen);
  2199.     assert(sigLen < 256);           // FIX this limitation, or at least fail
  2200.     memcpy(sigPtr, tempSig, sigLen);
  2201.  
  2202.     cycleCounterPause();
  2203.  
  2204.     if  (FAILED(cmpWmde->DefineMemberRef(cmpArrayTpToken(arrType, true),
  2205.                                          L".ctor",    // s/b OVOP_STR_CTOR_INST
  2206.                                          sigPtr,
  2207.                                          sigLen,
  2208.                                          &fncTok)))
  2209.     {
  2210.         cmpFatal(ERRmetadata);
  2211.     }
  2212.  
  2213.     cycleCounterResume();
  2214.  
  2215.     return  fncTok;
  2216. }
  2217.  
  2218. /*****************************************************************************
  2219.  *
  2220.  *  Return a methodref token of the element accessor method for the given
  2221.  *  managed array type.
  2222.  */
  2223.  
  2224. mdToken             compiler::cmpArrayEAtoken(TypDef        arrType,
  2225.                                               unsigned      dimCnt,
  2226.                                               bool          store,
  2227.                                               bool          addr)
  2228. {
  2229.     TypDef          elemTp = arrType->tdArr.tdaElem;
  2230.  
  2231.     PCOR_SIGNATURE  sigPtr;
  2232.     size_t          sigLen;
  2233.  
  2234.     mdToken         fncTok;
  2235.     wchar   *       fncName;
  2236.  
  2237.     // UNDONE: Look for an existing methodref token to reuse ....
  2238.  
  2239.     cmpMDsigStart();
  2240.     cmpMDsigAdd_I1(IMAGE_CEE_CS_CALLCONV_DEFAULT|IMAGE_CEE_CS_CALLCONV_HASTHIS);
  2241.     cmpMDsigAddCU4(dimCnt + (int)store);
  2242.  
  2243.     if      (store)
  2244.     {
  2245.         fncName = L"Set";
  2246.  
  2247.         cmpMDsigAdd_I1(ELEMENT_TYPE_VOID);
  2248.     }
  2249.     else
  2250.     {
  2251.         if (addr)
  2252.         {
  2253.             fncName = L"Address";
  2254.             cmpMDsigAdd_I1(ELEMENT_TYPE_BYREF);
  2255.         }
  2256.         else
  2257.         {
  2258.             fncName = L"Get";
  2259.         }
  2260.  
  2261.         cmpMDsigAddTyp(elemTp);
  2262.     }
  2263.  
  2264.     do
  2265.     {
  2266.         cmpMDsigAdd_I1(ELEMENT_TYPE_I4);
  2267.     }
  2268.     while (--dimCnt);
  2269.  
  2270.     if  (store)
  2271.         cmpMDsigAddTyp(elemTp);
  2272.  
  2273.     char tempSigBuff[256];
  2274.     sigPtr = (PCOR_SIGNATURE) tempSigBuff;
  2275.     PCOR_SIGNATURE  tempSig = cmpMDsigEnd(&sigLen);
  2276.     assert(sigLen < 256);           // FIX this limitation, or at least fail
  2277.     memcpy(sigPtr, tempSig, sigLen);
  2278.  
  2279.     cycleCounterPause();
  2280.  
  2281.     if  (FAILED(cmpWmde->DefineMemberRef(cmpArrayTpToken(arrType),
  2282.                                          fncName,
  2283.                                          sigPtr,
  2284.                                          sigLen,
  2285.                                          &fncTok)))
  2286.     {
  2287.         cmpFatal(ERRmetadata);
  2288.     }
  2289.  
  2290.     cycleCounterResume();
  2291.  
  2292.     return  fncTok;
  2293. }
  2294.  
  2295. /*****************************************************************************
  2296.  *
  2297.  *  Create a metadata type signature for the given pointer type.
  2298.  */
  2299.  
  2300. mdToken             compiler::cmpPtrTypeToken(TypDef type)
  2301. {
  2302.     mdTypeSpec      ptrTok;
  2303.  
  2304.     PCOR_SIGNATURE  sigPtr;
  2305.     size_t          sigLen;
  2306.  
  2307.              cmpMDsigStart ();
  2308.              cmpMDsigAddTyp(type);
  2309.     sigPtr = cmpMDsigEnd   (&sigLen);
  2310.  
  2311.     cycleCounterPause();
  2312.     if  (FAILED(cmpWmde->GetTokenFromTypeSpec(sigPtr, sigLen, &ptrTok)))
  2313.         cmpFatal(ERRmetadata);
  2314.     cycleCounterResume();
  2315.  
  2316.     return  ptrTok;
  2317. }
  2318.  
  2319. /*****************************************************************************
  2320.  *
  2321.  *  Create a metadata signature for the given function/data member.
  2322.  */
  2323.  
  2324. PCOR_SIGNATURE      compiler::cmpGenMemberSig(SymDef memSym,
  2325.                                               Tree   xargs,
  2326.                                               TypDef memTyp,
  2327.                                               TypDef prefTp, size_t *lenPtr)
  2328. {
  2329.     unsigned        call;
  2330.     ArgDef          args;
  2331.  
  2332.     /* Get hold of the member type, if we have a symbol */
  2333.  
  2334.     if  (memSym)
  2335.     {
  2336.         assert(memTyp == NULL || memTyp == memSym->sdType);
  2337.  
  2338.         memTyp = memSym->sdType;
  2339.     }
  2340.     else
  2341.     {
  2342.         assert(memTyp != NULL);
  2343.     }
  2344.  
  2345.     /* Start generating the member signature */
  2346.  
  2347.     cmpMDsigStart();
  2348.  
  2349.     /* Do we have a data or function member? */
  2350.  
  2351.     if  (memTyp->tdTypeKind == TYP_FNC)
  2352.     {
  2353.         unsigned        argCnt;
  2354.         TypDef          retTyp = memTyp->tdFnc.tdfRett;
  2355.         bool            argExt = memTyp->tdFnc.tdfArgs.adExtRec;
  2356.  
  2357.         /* Compute and emit the calling convention value */
  2358.  
  2359.         call = IMAGE_CEE_CS_CALLCONV_DEFAULT;
  2360.  
  2361.         if  (memTyp->tdFnc.tdfArgs.adVarArgs)
  2362.             call  = IMAGE_CEE_CS_CALLCONV_VARARG;
  2363.         if  (memSym && memSym->sdSymKind == SYM_PROP)
  2364.             call |= IMAGE_CEE_CS_CALLCONV_PROPERTY;
  2365.  
  2366.         if  (memSym && memSym->sdIsMember && !memSym->sdIsStatic)
  2367.         {
  2368. #if STATIC_UNMANAGED_MEMBERS
  2369.             if  (!memSym->sdIsManaged)
  2370.             {
  2371.                 assert(prefTp == NULL);
  2372.                 prefTp = memSym->sdParent->sdType->tdClass.tdcRefTyp;
  2373.                 assert(prefTp->tdTypeKind == TYP_PTR);
  2374.             }
  2375.             else
  2376. #endif
  2377.                 call |= IMAGE_CEE_CS_CALLCONV_HASTHIS;
  2378.         }
  2379.  
  2380.         argCnt = memTyp->tdFnc.tdfArgs.adCount;
  2381.  
  2382.         cmpMDsigAdd_I1(call);
  2383.  
  2384.         /* Output the argument count */
  2385.  
  2386.         if  (xargs)
  2387.         {
  2388.             Tree            xtemp;
  2389.  
  2390.             /* Hack to force memberrefs to always be used for vararg calls */
  2391.  
  2392.             if  (xargs->tnOper != TN_LIST)
  2393.             {
  2394.                 xargs = NULL;
  2395.             }
  2396.             else
  2397.             {
  2398.                 for (xtemp = xargs; xtemp; xtemp = xtemp->tnOp.tnOp2)
  2399.                 {
  2400.                     assert(xtemp->tnOper == TN_LIST);
  2401.                     argCnt++;
  2402.                 }
  2403.             }
  2404.         }
  2405.  
  2406.         if  (prefTp)
  2407.             argCnt++;
  2408.  
  2409.         cmpMDsigAddCU4(argCnt);
  2410.  
  2411.         /* Output the return type signature */
  2412.  
  2413.         cmpMDsigAddTyp(retTyp);
  2414.  
  2415.         /* Output the argument types */
  2416.  
  2417.         if  (prefTp)
  2418.             cmpMDsigAddTyp(prefTp);
  2419.  
  2420.         for (args = memTyp->tdFnc.tdfArgs.adArgs; args; args = args->adNext)
  2421.         {
  2422.             TypDef          argType = args->adType;
  2423.  
  2424.             /* Do we have extended parameter attributes? */
  2425.  
  2426.             if  (argExt)
  2427.             {
  2428.                 unsigned        flags;
  2429.  
  2430.                 assert(args->adIsExt);
  2431.  
  2432.                 flags = ((ArgExt)args)->adFlags;
  2433.  
  2434. #if 0
  2435.  
  2436.                 if      (flags & (ARGF_MODE_OUT|ARGF_MODE_INOUT))
  2437.                 {
  2438.                     /* This is a byref argument */
  2439.  
  2440.                     cmpMDsigAdd_I1(ELEMENT_TYPE_BYREF);
  2441.                 }
  2442.                 else if (flags & ARGF_MODE_REF)
  2443.                 {
  2444.                     /* HACK: map "raw" byref args onto "int" */
  2445.  
  2446.                     argType = cmpTypeInt;
  2447.                 }
  2448.  
  2449. #else
  2450.  
  2451.                 if      (flags & (ARGF_MODE_OUT|ARGF_MODE_INOUT|ARGF_MODE_REF))
  2452. //              if      (flags & ARGF_MODE_REF)
  2453.                 {
  2454.                     /* This is a byref argument */
  2455.  
  2456.                     cmpMDsigAdd_I1(ELEMENT_TYPE_BYREF);
  2457.                 }
  2458.  
  2459. #endif
  2460.  
  2461.             }
  2462.  
  2463.             cmpMDsigAddTyp(argType);
  2464.         }
  2465.  
  2466.         /* Append any "extra" argument types */
  2467.  
  2468.         if  (xargs)
  2469.         {
  2470.             cmpMDsigAdd_I1(ELEMENT_TYPE_SENTINEL);
  2471.  
  2472.             do
  2473.             {
  2474.                 TypDef          argType;
  2475.  
  2476.                 assert(xargs->tnOper == TN_LIST);
  2477.  
  2478.                 argType = xargs->tnOp.tnOp1->tnType;
  2479.  
  2480.                 // HACK: managed arrays don't work with varargs, pass as Object
  2481.  
  2482.                 if  (argType->tdTypeKind == TYP_ARRAY && argType->tdIsManaged)
  2483.                     argType = cmpRefTpObject;
  2484.  
  2485.                 cmpMDsigAddTyp(argType);
  2486.  
  2487.                 xargs = xargs->tnOp.tnOp2;
  2488.             }
  2489.             while (xargs);
  2490.         }
  2491.     }
  2492.     else
  2493.     {
  2494.         assert(xargs == NULL);
  2495.  
  2496.         /* Emit the calling convention value */
  2497.  
  2498.         cmpMDsigAdd_I1(IMAGE_CEE_CS_CALLCONV_FIELD);
  2499.  
  2500.         /* Output the member type signature */
  2501.  
  2502.         cmpMDsigAddTyp(memTyp);
  2503.     }
  2504.  
  2505.     /* We're done, return the result */
  2506.  
  2507.     return  cmpMDsigEnd(lenPtr);
  2508. }
  2509.  
  2510. static
  2511. BYTE                intrnsNativeSigs[] =
  2512. {
  2513.     NATIVE_TYPE_END,        // TYP_UNDEF
  2514.     NATIVE_TYPE_VOID,       // TYP_VOID
  2515.     NATIVE_TYPE_BOOLEAN,    // TYP_BOOL
  2516.     NATIVE_TYPE_END,        // TYP_WCHAR        used to be _SYSCHAR
  2517.  
  2518.     NATIVE_TYPE_I1,         // TYP_CHAR
  2519.     NATIVE_TYPE_U1,         // TYP_UCHAR
  2520.     NATIVE_TYPE_I2,         // TYP_SHORT
  2521.     NATIVE_TYPE_U2,         // TYP_USHORT
  2522.     NATIVE_TYPE_I4,         // TYP_INT
  2523.     NATIVE_TYPE_U4,         // TYP_UINT
  2524.     NATIVE_TYPE_I4,         // TYP_NATINT       s/b naturalint !!!
  2525.     NATIVE_TYPE_U4,         // TYP_NATUINT      s/b naturaluint!!!
  2526.     NATIVE_TYPE_I8,         // TYP_LONG
  2527.     NATIVE_TYPE_U8,         // TYP_ULONG
  2528.     NATIVE_TYPE_R4,         // TYP_FLOAT
  2529.     NATIVE_TYPE_R8,         // TYP_DOUBLE
  2530.     NATIVE_TYPE_R8,         // TYP_LONGDBL
  2531.     NATIVE_TYPE_VOID,       // TYP_REFANY
  2532. };
  2533.  
  2534. /*****************************************************************************
  2535.  *
  2536.  *  Create a marshalling signature blob, given a type and an optional
  2537.  *  marshalling spec.
  2538.  */
  2539.  
  2540. PCOR_SIGNATURE      compiler::cmpGenMarshalSig(TypDef       type,
  2541.                                                MarshalInfo  info,
  2542.                                                size_t     * lenPtr)
  2543. {
  2544.     var_types       vtyp;
  2545.  
  2546.     cmpMDsigStart();
  2547.  
  2548.     if  (info && info->marshType != NATIVE_TYPE_END)
  2549.     {
  2550.         switch (info->marshType)
  2551.         {
  2552.             marshalExt *    iext;
  2553.             wchar           nam1[MAX_CLASS_NAME];
  2554.              char           nam2[MAX_CLASS_NAME];
  2555.  
  2556.         case NATIVE_TYPE_MAX:
  2557.  
  2558.             /* This is "CUSTOM", just hack it */
  2559.  
  2560. //          printf("WARNING: not sure what to do with 'custom' attribute (arg type is '%s'),\n", cmpGlobalST->stTypeName(type, NULL, NULL, NULL, true));
  2561. //          printf("         simply generating 'NATIVE_TYPE_BSTR' for now.\n");
  2562.  
  2563.             cmpMDsigAdd_I1(NATIVE_TYPE_BSTR);
  2564.             goto DONE;
  2565.  
  2566.         case NATIVE_TYPE_CUSTOMMARSHALER:
  2567.  
  2568.             iext = (marshalExt*)info;
  2569.  
  2570.             cmpMDsigAdd_I1(NATIVE_TYPE_CUSTOMMARSHALER);
  2571.  
  2572.             assert(iext->marshCustG);
  2573.             cmpMDsigAddStr(iext->marshCustG, strlen(iext->marshCustG));
  2574.             cmpMDsigAdd_I1(0);
  2575.  
  2576.             assert(iext->marshCustT);
  2577.             cmpArrayClsPref(iext->marshCustT, nam1, '.', true);
  2578.             wcstombs(nam2, nam1, sizeof(nam2)-1);
  2579.             cmpMDsigAddStr(nam2, strlen(nam2));
  2580.             cmpMDsigAdd_I1(0);
  2581.  
  2582.             if  (iext->marshCustC)
  2583.                 cmpMDsigAddStr(iext->marshCustC, strlen(iext->marshCustC));
  2584.  
  2585.             cmpMDsigAdd_I1(0);
  2586.             goto DONE;
  2587.  
  2588.         default:
  2589.  
  2590.             assert(info->marshType && info->marshType < NATIVE_TYPE_MAX);
  2591.  
  2592.             cmpMDsigAdd_I1(info->marshType);
  2593.  
  2594.             if  (info->marshSize  && (int )info->marshSize  != (int) -1)
  2595.                 cmpMDsigAddCU4(info->marshSize);
  2596.  
  2597.             if  (info->marshSubTp && (BYTE)info->marshSubTp != (BYTE)-1)
  2598.                 cmpMDsigAdd_I1(info->marshSubTp);
  2599.  
  2600.             goto DONE;
  2601.         }
  2602.     }
  2603.  
  2604.     vtyp = type->tdTypeKindGet();
  2605.  
  2606.     if  (vtyp <= TYP_lastIntrins)
  2607.     {
  2608.         assert(vtyp < arraylen(intrnsNativeSigs));
  2609.         assert(intrnsNativeSigs[vtyp] != NATIVE_TYPE_END);
  2610.  
  2611.         cmpMDsigAdd_I1(intrnsNativeSigs[vtyp]);
  2612.     }
  2613.     else
  2614.     {
  2615.         switch (vtyp)
  2616.         {
  2617.             SymDef          clsSym;
  2618.  
  2619.         case TYP_ARRAY:
  2620.  
  2621.             // ISSUE: This sure doesn't seem quite right ....
  2622.  
  2623.             cmpMDsigAdd_I1(NATIVE_TYPE_ARRAY);
  2624.             cmpMDsigAdd_I1(1);
  2625.             goto DONE;
  2626.  
  2627.         case TYP_PTR:
  2628.             cmpMDsigAdd_I1(NATIVE_TYPE_LPVOID);
  2629.             goto DONE;
  2630.  
  2631.         case TYP_REF:
  2632.  
  2633.             /* Does this look like an embedded struct? */
  2634.  
  2635.             type = type->tdRef.tdrBase;
  2636.  
  2637.             if  (type->tdTypeKind != TYP_CLASS)
  2638.                 break;
  2639.  
  2640.         case TYP_CLASS:
  2641.  
  2642.             clsSym = type->tdClass.tdcSymbol;
  2643.  
  2644.             /* Special cases: String and Variant */
  2645.  
  2646.             if  (clsSym->sdParent == cmpNmSpcSystem)
  2647.             {
  2648.                 if  (clsSym->sdName == cmpIdentVariant)
  2649.                 {
  2650.                     cmpMDsigAdd_I1(NATIVE_TYPE_VARIANT);
  2651.                     goto DONE;
  2652.                 }
  2653.  
  2654.                 if  (clsSym->sdName == cmpIdentString)
  2655.                 {
  2656.                     cmpMDsigAdd_I1(NATIVE_TYPE_LPSTR);
  2657.                     goto DONE;
  2658.                 }
  2659.             }
  2660.  
  2661.             goto DONE;
  2662.  
  2663.         case TYP_ENUM:
  2664.             cmpMDsigAdd_I1(intrnsNativeSigs[type->tdEnum.tdeIntType->tdTypeKind]);
  2665.             goto DONE;
  2666.         }
  2667.  
  2668. #ifdef  DEBUG
  2669.         printf("%s: ", cmpGlobalST->stTypeName(type, NULL, NULL, NULL, true));
  2670. #endif
  2671.         NO_WAY(!"unexpected @dll.struct type");
  2672.     }
  2673.  
  2674. DONE:
  2675.  
  2676.     return  cmpMDsigEnd(lenPtr);
  2677. }
  2678.  
  2679. /*****************************************************************************
  2680.  *
  2681.  *  Add a reference to the given assembly.
  2682.  */
  2683.  
  2684. mdAssemblyRef       compiler::cmpAssemblyAddRef(mdAssembly      ass,
  2685.                                                 WAssemblyImport*imp)
  2686. {
  2687.     mdAssemblyRef   assRef;
  2688.    ASSEMBLYMETADATA assData;
  2689.  
  2690.     const   void *  origPtr;
  2691.     ULONG           origSiz;
  2692.  
  2693.     wchar           anameBuff[_MAX_PATH];
  2694.     wchar           aliasBuff[_MAX_PATH];
  2695.     wchar           titleBuff[256];
  2696.  
  2697.     DWORD           flags;
  2698.  
  2699.     cycleCounterPause();
  2700.  
  2701.     /* Get the properties of the referenced assembly */
  2702.  
  2703.     memset(&assData, 0, sizeof(assData));
  2704.  
  2705.     if  (FAILED(imp->GetAssemblyProps(ass,
  2706.                                       &origPtr,
  2707.                                       &origSiz,
  2708.                                       NULL,             // hash algorithm
  2709.                                       anameBuff, arraylen(anameBuff), NULL,
  2710.                                       &assData,
  2711.                                       titleBuff, arraylen(titleBuff), NULL,
  2712.                                       NULL, 0, NULL,    // description
  2713.                                       aliasBuff, arraylen(aliasBuff), NULL,
  2714.                                       &flags)))
  2715.     {
  2716.         cmpFatal(ERRmetadata);
  2717.     }
  2718.  
  2719. //  printf("Assembly name returned from GetAssemblyProps: '%ls'\n", anameBuff);
  2720.  
  2721.     /* Allocate any non-empty arrays */
  2722.  
  2723.     assert(assData.rOS     == NULL);
  2724.  
  2725.     if  (assData.ulOS)
  2726.         assData.rOS     = (OSINFO *)malloc(assData.ulOS     * sizeof(*assData.rOS    ));
  2727.  
  2728.     /* Now create the assembly reference */
  2729.  
  2730.     assert(cmpWase);
  2731.  
  2732.     if  (FAILED(cmpWase->DefineAssemblyRef(NULL, 0,     // originator blob
  2733.                                            anameBuff,   // name
  2734.                                            &assData,    // metadata
  2735.                                            NULL, 0,     // hash
  2736.                                            mdExecutionLocationNil,
  2737.                                            flags,
  2738.                                            &assRef)))
  2739.     {
  2740.         cmpFatal(ERRmetadata);
  2741.     }
  2742.  
  2743. #ifndef __SMC__ // temp hack
  2744.  
  2745.     if  (assData.rOS)
  2746.         delete (void*)assData.rOS;
  2747.  
  2748. #endif
  2749.  
  2750.     cycleCounterResume();
  2751.  
  2752.     return  assRef;
  2753. }
  2754.  
  2755. /*****************************************************************************
  2756.  *
  2757.  *  Add a definition for the given type (which may be a locally defined type
  2758.  *  (when 'tdefTok' is non-zero) or a type imported from another assembly).
  2759.  */
  2760.  
  2761. mdComType           compiler::cmpAssemblySymDef(SymDef sym, mdTypeDef tdefTok)
  2762. {
  2763.     mdComType       typeTok;
  2764.     mdToken         implTok;
  2765.     unsigned        flags;
  2766.  
  2767.     wchar           nameBuff[MAX_CLASS_NAME];
  2768.  
  2769.     assert(sym->sdSymKind == SYM_CLASS ||
  2770.            sym->sdSymKind == SYM_ENUM);
  2771.  
  2772.     /* Make sure we have a reference to the appropriate assembly */
  2773.  
  2774.     if  (tdefTok == 0)
  2775.     {
  2776.         flags   = tdNotPublic;
  2777.  
  2778.         tdefTok = mdTypeDefNil;
  2779.         implTok = cmpAssemblyRefRec((sym->sdSymKind == SYM_CLASS)
  2780.                                         ? sym->sdClass.sdcAssemIndx
  2781.                                         : sym->sdEnum .sdeAssemIndx);
  2782.     }
  2783.     else
  2784.     {
  2785.         if  (cmpConfig.ccAsmNoPubTp)
  2786.             return  0;
  2787.  
  2788.         /* If we've done this already, return the ComType */
  2789.  
  2790.         if  (sym->sdSymKind == SYM_CLASS)
  2791.         {
  2792.             if  (sym->sdClass.sdcAssemRefd)
  2793.                 return  sym->sdClass.sdcComTypeX;
  2794.         }
  2795.         else
  2796.         {
  2797.             if  (sym->sdEnum .sdeAssemRefd)
  2798.                 return  sym->sdEnum .sdeComTypeX;
  2799.         }
  2800.  
  2801.         implTok = 0;
  2802.  
  2803.         flags   = (sym->sdAccessLevel == ACL_PUBLIC) ? tdPublic
  2804.                                                      : tdNotPublic;
  2805.         /* Do we have a nested class/enum ? */
  2806.  
  2807.         if  (sym->sdParent->sdSymKind == SYM_CLASS)
  2808.         {
  2809.             flags   = tdNestedPublic;
  2810.             implTok = sym->sdParent->sdClass.sdcComTypeX; assert(implTok);
  2811.         }
  2812.     }
  2813.  
  2814.     /* Now add an entry for this type to our assembly */
  2815.  
  2816.     assert(cmpWase);
  2817.  
  2818.     /* Form the fully qualified name for the type */
  2819.  
  2820.     if  (sym->sdParent->sdSymKind == SYM_CLASS)
  2821.     {
  2822.         SymDef          nst = sym;
  2823.         SymDef          nsp;
  2824.  
  2825.         wchar_t     *   nxt;
  2826.  
  2827.         while (nst->sdParent->sdSymKind == SYM_CLASS)
  2828.             nst = nst->sdParent;
  2829.  
  2830.         nsp = nst->sdParent;
  2831.  
  2832.         if  (nsp != cmpGlobalNS)
  2833.         {
  2834.             cmpArrayClsPref(nsp, nameBuff, '.', true);
  2835.             nxt = nameBuff + wcslen(nameBuff);
  2836.             *nxt++ = '.';
  2837.         }
  2838.         else
  2839.         {
  2840.             nxt = nameBuff; nameBuff[0] = 0;
  2841.         }
  2842.  
  2843.         /* The following is a truly horrendous HACK */
  2844.  
  2845.         nsp = nst->sdParent; nst->sdParent = cmpGlobalNS;
  2846.         cmpArrayClsPref(sym, nxt, '$', true);
  2847.         nst->sdParent = nsp;
  2848.     }
  2849.     else
  2850.         cmpArrayClsPref(sym, nameBuff, '.', true);
  2851.  
  2852. //  printf("Adding ref for ComType '%ls'\n", nameBuff);
  2853.  
  2854.     /* Create the type definition token */
  2855.  
  2856.     if  (FAILED(cmpWase->DefineComType(nameBuff, // cmpUniConv(sym->sdName),
  2857.                                        NULL,        // description
  2858.                                        implTok,     // owner assembly
  2859.                                        tdefTok,     // typedef
  2860.                                        mdExecutionLocationNil,
  2861.                                        flags,       // type flags
  2862.                                        &typeTok)))
  2863.     {
  2864.         cmpFatal(ERRmetadata);
  2865.     }
  2866.  
  2867.     /* A reference for this type has been added */
  2868.  
  2869.     if  (sym->sdSymKind == SYM_CLASS)
  2870.     {
  2871.         sym->sdClass.sdcAssemRefd = true;
  2872.         if  (tdefTok != mdTypeDefNil)
  2873.             sym->sdClass.sdcComTypeX = typeTok;
  2874.     }
  2875.     else
  2876.     {
  2877.         sym->sdEnum .sdeAssemRefd = true;
  2878.         if  (tdefTok != mdTypeDefNil)
  2879.             sym->sdEnum .sdeComTypeX = typeTok;
  2880.     }
  2881.  
  2882.     return  typeTok;
  2883. }
  2884.  
  2885. /*****************************************************************************
  2886.  *
  2887.  *  Add the given file to our assembly.
  2888.  */
  2889.  
  2890. mdToken             compiler::cmpAssemblyAddFile(wideStr    fileName,
  2891.                                                  bool       doHash,
  2892.                                                  unsigned   flags)
  2893. {
  2894.     mdToken         fileTok;
  2895.  
  2896.     BYTE            hashBuff[128];
  2897.     char            nameBuff[_MAX_PATH ];
  2898.     char               fname[_MAX_FNAME];
  2899.     char               fext [_MAX_EXT  ];
  2900.  
  2901.     const   void *  hashAddr = NULL;
  2902.     DWORD           hashSize = 0;
  2903.  
  2904. //  printf("Add ref for file '%ls\n", fileName);
  2905.  
  2906.     /* Convert the filename to Ascii */
  2907.  
  2908.     assert(wcslen(fileName) < sizeof(nameBuff));
  2909.     wcstombs(nameBuff, fileName, sizeof(nameBuff)-1);
  2910.  
  2911.     /* Are we supposed to compute the hash ? */
  2912.  
  2913.     if  (doHash)
  2914.     {
  2915.         unsigned        hashAlg = 0;
  2916.         BYTE    *       hashPtr = hashBuff;
  2917.  
  2918.         /* Compute the hash for the file */
  2919.  
  2920.         cycleCounterPause();
  2921.  
  2922.         if  (FAILED(WRAPPED_GetHashFromFile(nameBuff,
  2923.                                            &hashAlg,
  2924.                                             hashPtr,
  2925.                                             arraylen(hashBuff),
  2926.                                            &hashSize)))
  2927.         {
  2928.             cmpFatal(ERRopenCOR);
  2929.         }
  2930.  
  2931.         cycleCounterResume();
  2932.  
  2933.         assert(hashPtr  == hashBuff);
  2934.         assert(hashSize <= arraylen(hashBuff));
  2935.  
  2936.         hashAddr = hashBuff;
  2937.     }
  2938.  
  2939.     /* Strip drive/directory from the filename */
  2940.  
  2941.     _splitpath(nameBuff, NULL, NULL, fname, fext);
  2942.      _makepath(nameBuff, NULL, NULL, fname, fext);
  2943.  
  2944.     /* Add the output file to the assembly */
  2945.  
  2946.     if  (!flags)
  2947.         flags = ffContainsMetaData;
  2948.  
  2949.     assert(cmpWase);
  2950.  
  2951.     cycleCounterPause();
  2952.  
  2953.     if  (FAILED(cmpWase->DefineFile(cmpUniConv(nameBuff, strlen(nameBuff)),
  2954.                                     hashAddr,
  2955.                                     hashSize,
  2956.                                     flags,
  2957.                                     &fileTok)))
  2958.     {
  2959.         cmpFatal(ERRopenCOR);
  2960.     }
  2961.  
  2962.     cycleCounterResume();
  2963.  
  2964.     return  fileTok;
  2965. }
  2966.  
  2967. /*****************************************************************************
  2968.  *
  2969.  *  Add a definition for the given type to our assembly.
  2970.  */
  2971.  
  2972. void                compiler::cmpAssemblyAddType(wideStr  typeName,
  2973.                                                  mdToken  defTok,
  2974.                                                  mdToken  scpTok,
  2975.                                                  unsigned flags)
  2976. {
  2977.     mdToken         typeTok;
  2978.  
  2979.     assert(cmpWase);
  2980.  
  2981.     cycleCounterPause();
  2982.  
  2983.     if  (FAILED(cmpWase->DefineComType(typeName,
  2984.                                        NULL,        // description
  2985.                                        scpTok,      // owner token
  2986.                                        defTok,      // typedef
  2987.                                        mdExecutionLocationNil,
  2988.                                        flags,       // type flags
  2989.                                        &typeTok)))
  2990.     {
  2991.         cmpFatal(ERRmetadata);
  2992.     }
  2993.  
  2994.     cycleCounterResume();
  2995. }
  2996.  
  2997. /*****************************************************************************
  2998.  *
  2999.  *  Add the given resource to our assembly (as an internal/external assembly
  3000.  *  resource).
  3001.  */
  3002.  
  3003. void                compiler::cmpAssemblyAddRsrc(AnsiStr fileName, bool internal)
  3004. {
  3005.     WCHAR           name[_MAX_PATH ];
  3006.     char            path[_MAX_PATH ];
  3007.     char            fnam[_MAX_FNAME];
  3008.     char            fext[_MAX_EXT  ];
  3009.  
  3010.     mdToken         fileTok;
  3011.     mdToken         rsrcTok;
  3012.  
  3013.     wcscpy(name, cmpUniConv(fileName, strlen(fileName)));
  3014.  
  3015.     fileTok = cmpAssemblyAddFile(name, true, ffContainsNoMetaData);
  3016.  
  3017.     _splitpath(fileName, NULL, NULL, fnam, fext);
  3018.      _makepath(path    , NULL, NULL, fnam, fext);
  3019.  
  3020.     assert(cmpWase);
  3021.  
  3022.     cycleCounterPause();
  3023.  
  3024.     if  (FAILED(cmpWase->DefineManifestResource(cmpUniConv(path, strlen(path)),
  3025.                                                 NULL,
  3026.                                                 fileTok,
  3027.                                                 0,
  3028.                                                 NULL,
  3029.                                                 L"",
  3030.                                                 0,
  3031.                                                 &rsrcTok)))
  3032.     {
  3033.         cmpFatal(ERRmetadata);
  3034.     }
  3035.  
  3036.     cycleCounterResume();
  3037. }
  3038.  
  3039. /*****************************************************************************
  3040.  *
  3041.  *  Mark our assembly as non-CLS compliant.
  3042.  */
  3043.  
  3044. void                compiler::cmpAssemblyNonCLS()
  3045. {
  3046.     mdToken         toss = 0;
  3047.  
  3048.     cmpAttachMDattr(cmpCurAssemblyTok,
  3049.                    L"System.NonCLSCompliantAttribute",
  3050.                     "System.NonCLSCompliantAttribute",
  3051.                     &toss);
  3052. }
  3053.  
  3054. /*****************************************************************************
  3055.  *
  3056.  *  Attach a marshalling thingamabobber to the given token.
  3057.  */
  3058.  
  3059. void                compiler::cmpGenMarshalInfo(mdToken token, TypDef       type,
  3060.                                                                MarshalInfo  info)
  3061. {
  3062.     PCOR_SIGNATURE  sigPtr;
  3063.     size_t          sigLen;
  3064.  
  3065.     /* Weird special case: don't generate anything for wchar */
  3066.  
  3067.     if  (type->tdTypeKind == TYP_WCHAR)
  3068.         return;
  3069.  
  3070.     /* Create the marshalling signature */
  3071.  
  3072.     sigPtr = cmpGenMarshalSig(type, info, &sigLen);
  3073.  
  3074.     /* Attach the signature to the token, if non-empty */
  3075.  
  3076.     if  (sigLen)
  3077.     {
  3078.         cycleCounterPause();
  3079.         if  (cmpWmde->SetFieldMarshal(token, sigPtr, sigLen))
  3080.             cmpFatal(ERRmetadata);
  3081.         cycleCounterResume();
  3082.     }
  3083. }
  3084.  
  3085. /*****************************************************************************
  3086.  *
  3087.  *  Create a Unicode fully qualified metadata name for the given class or
  3088.  *  namespace.
  3089.  */
  3090.  
  3091. wchar   *           compiler::cmpGenMDname(SymDef sym,
  3092.                                            bool  full, wchar  *     buffAddr,
  3093.                                                        size_t       buffSize,
  3094.                                                        wchar  *   * buffHeapPtr)
  3095. {
  3096.     wchar   *       heapBuff = NULL;
  3097.     wchar   *       fullName;
  3098.  
  3099.     size_t          nameLen;
  3100.     SymDef          tempSym;
  3101.     wchar   *       nameDst;
  3102.  
  3103.     wchar           delim;
  3104.  
  3105.     symbolKinds     symKind = sym->sdSymKindGet();
  3106.  
  3107.     /* Do we need to prefix the name? */
  3108.  
  3109.     if  (sym == cmpGlobalNS)
  3110.     {
  3111.         fullName = NULL;
  3112.         goto DONE;
  3113.     }
  3114.  
  3115.     if  (sym->sdParent->sdSymKindGet() != symKind && !full)
  3116.     {
  3117.         /*
  3118.             We can only use the cmpUniConv() buffer once, so we'll
  3119.             use it for classes and save namespace names elsewhere.
  3120.          */
  3121.  
  3122.         if  (symKind == SYM_CLASS && sym->sdClass.sdcSpecific)
  3123.         {
  3124.             stringBuff      instName;
  3125.  
  3126.             /* Construct the class instance name and convert to Unicode */
  3127.  
  3128.             instName = cmpGlobalST->stTypeName(NULL, sym, NULL, NULL, false);
  3129.  
  3130.             fullName = cmpUniConv(instName, strlen(instName)+1);
  3131.         }
  3132.         else
  3133.             fullName = cmpUniConv(sym->sdName);
  3134.  
  3135.         if  (symKind != SYM_CLASS)
  3136.         {
  3137.             /* Use the local buffer */
  3138.  
  3139.             assert(strlen(sym->sdSpelling()) < buffSize);
  3140.  
  3141.             wcscpy(buffAddr, fullName); fullName = buffAddr;
  3142.         }
  3143.  
  3144.         goto DONE;
  3145.     }
  3146.  
  3147.     /* Compute the length of the qualified name */
  3148.  
  3149.     nameLen = 0;
  3150.     tempSym = sym;
  3151.     for (;;)
  3152.     {
  3153.         size_t          nlen;
  3154.  
  3155.         if  (tempSym->sdSymKind == SYM_CLASS && tempSym->sdClass.sdcSpecific)
  3156.             nlen = strlen(cmpGlobalST->stTypeName(NULL, tempSym, NULL, NULL, false));
  3157.         else
  3158.             nlen = tempSym->sdSpellLen();
  3159.  
  3160.         nameLen += nlen;
  3161.  
  3162.     SKIP:
  3163.  
  3164.         tempSym  = tempSym->sdParent;
  3165.         if  (tempSym == NULL)
  3166.             break;
  3167.  
  3168.         if  (full)
  3169.         {
  3170.             if  (tempSym->sdSymKind == SYM_CLASS)
  3171.                 goto SKIP;
  3172.         }
  3173.  
  3174.         if  (tempSym->sdSymKindGet() != symKind || tempSym == cmpGlobalNS)
  3175.         {
  3176.             if  (!full)
  3177.                 break;
  3178.         }
  3179.  
  3180.         nameLen++;
  3181.     }
  3182.  
  3183.     if  (nameLen < buffSize)
  3184.     {
  3185.         fullName = buffAddr;
  3186.     }
  3187.     else
  3188.     {
  3189.         heapBuff =
  3190.         fullName = (wchar*)SMCgetMem(this, roundUp((nameLen+1)*sizeof(*heapBuff)));
  3191.     }
  3192.  
  3193.     /* Now add the names to the buffer, in reverse order */
  3194.  
  3195.     delim   = (sym->sdSymKind == SYM_NAMESPACE || full) ? '.' : '$';
  3196.  
  3197.     nameDst = fullName + nameLen;
  3198.     tempSym = sym;
  3199.     for (;;)
  3200.     {
  3201.         size_t          thisLen = tempSym->sdSpellLen();
  3202.         wchar   *       uniName = cmpUniConv(tempSym->sdName);
  3203.  
  3204.         if  (tempSym->sdSymKind == SYM_CLASS && tempSym->sdClass.sdcSpecific)
  3205.         {
  3206.             const   char *  instName;
  3207.  
  3208.             instName = cmpGlobalST->stTypeName(NULL, tempSym, NULL, NULL, false);
  3209.  
  3210.             thisLen = strlen(instName);
  3211.             uniName = cmpUniConv(instName, thisLen+1);
  3212.         }
  3213.         else
  3214.         {
  3215.             thisLen = tempSym->sdSpellLen();
  3216.             uniName = cmpUniConv(tempSym->sdName);
  3217.         }
  3218.  
  3219.         *nameDst  = delim;
  3220.          nameDst -= thisLen;
  3221.  
  3222.         memcpy(nameDst, uniName, 2*thisLen);
  3223.  
  3224.         tempSym  = tempSym->sdParent;
  3225.         if  (tempSym->sdSymKindGet() != symKind || tempSym == cmpGlobalNS)
  3226.             break;
  3227.  
  3228.         nameDst--;
  3229.     }
  3230.     fullName[nameLen] = 0;
  3231.  
  3232.     fullName = nameDst; assert(nameDst == fullName);
  3233.  
  3234. DONE:
  3235.  
  3236.     *buffHeapPtr = heapBuff;
  3237.  
  3238.     return  fullName;
  3239. }
  3240.  
  3241. /*****************************************************************************
  3242.  *
  3243.  *  Generate metadata for the given class/enum (unless it's already been done).
  3244.  */
  3245.  
  3246. mdToken             compiler::cmpGenClsMetadata(SymDef clsSym, bool extref)
  3247. {
  3248.     bool            isClass;
  3249.  
  3250.     TypDef          clsTyp;
  3251.  
  3252.     SymDef          nspSym;
  3253.  
  3254.     GUID            GUIDbuf;
  3255.     GUID    *       GUIDptr = NULL;
  3256.     SymXinfoAtc     clsGUID = NULL;
  3257.  
  3258.     mdToken         intfTmp[55];
  3259.     mdToken *       intfTab = NULL;
  3260.     mdToken         baseTok = 0;
  3261.  
  3262.     unsigned        flags;
  3263.  
  3264.     mdTypeDef       tdef;
  3265.  
  3266.     wchar           nspBuff[MAX_PACKAGE_NAME];
  3267.     wchar   *       nspName;
  3268.     wchar   *       nspHeap = NULL;
  3269.  
  3270.     wchar           clsBuff[MAX_CLASS_NAME];
  3271.     wchar   *       clsName;
  3272.     wchar   *       clsHeap = NULL;
  3273.  
  3274.     wchar           fullName[MAX_PACKAGE_NAME + MAX_CLASS_NAME + 1];
  3275.  
  3276.     mdToken         clsToken;
  3277.  
  3278.     WMetaDataEmit * emitIntf;
  3279.  
  3280.     assert(clsSym);
  3281.     assert(clsSym->sdIsImport == false || extref);
  3282.  
  3283.     /* Get hold of the class/enum type */
  3284.  
  3285.     clsTyp = clsSym->sdType;
  3286.  
  3287.     /* Is this a class or enum? */
  3288.  
  3289.     if  (clsSym->sdSymKind  == SYM_CLASS)
  3290.     {
  3291.         /* If the class has no method bodies, it will be external */
  3292.  
  3293.         if  (!clsSym->sdClass.sdcHasBodies && !extref)
  3294.         {
  3295.             // HACK: Being managed or no methods at all is the same as methods with bodies
  3296.  
  3297.             if  (!clsSym->sdClass.sdcHasMeths || clsSym->sdIsManaged || clsSym->sdClass.sdcHasLinks)
  3298.                 clsSym->sdClass.sdcHasBodies = true;
  3299.             else
  3300.                 extref = true;
  3301.         }
  3302.  
  3303.         /* Bail if we already have a typedef/ref */
  3304.  
  3305.         if  (clsSym->sdClass.sdcMDtypedef)
  3306.             return  clsSym->sdClass.sdcMDtypedef;
  3307.  
  3308.         /* Get hold of the token for the base class */
  3309.  
  3310.         if  (clsTyp->tdClass.tdcBase && clsTyp->tdIsManaged)
  3311.         {
  3312.             baseTok = cmpClsEnumToken(clsTyp->tdClass.tdcBase);
  3313.  
  3314.             /* Set the base class token to nil for interfaces */
  3315.  
  3316.             if  (clsTyp->tdClass.tdcFlavor == STF_INTF)
  3317.                 baseTok = mdTypeRefNil;
  3318.         }
  3319.  
  3320.         /* Does the class implement any interfaces? */
  3321.  
  3322.         if  (clsTyp->tdClass.tdcIntf)
  3323.         {
  3324.             TypList     intfLst;
  3325.             unsigned    intfNum;
  3326.  
  3327.             /* Create the interface table */
  3328.  
  3329.             for (intfLst = clsTyp->tdClass.tdcIntf, intfNum = 0;
  3330.                  intfLst;
  3331.                  intfLst = intfLst->tlNext        , intfNum++)
  3332.             {
  3333.                 if  (intfNum == arraylen(intfTmp) - 1)
  3334.                 {
  3335.                     UNIMPL("oops, too many interfaces - allocate a buffer on the heap to keep the lot");
  3336.                 }
  3337.  
  3338.                 intfTmp[intfNum] = cmpClsEnumToken(intfLst->tlType);
  3339.             }
  3340.  
  3341.             intfTmp[intfNum] = 0; intfTab = intfTmp;
  3342.         }
  3343.  
  3344.         isClass = true;
  3345.     }
  3346.     else
  3347.     {
  3348.         assert(clsSym->sdSymKind == SYM_ENUM);
  3349.  
  3350.         if  (cmpConfig.ccIntEnums)
  3351.             clsSym->sdEnum.sdeMDtypedef = -1;
  3352.  
  3353.         /* Bail if we already have a typedef/ref */
  3354.  
  3355.         if  (clsSym->sdEnum.sdeMDtypedef)
  3356.             return  clsSym->sdEnum.sdeMDtypedef;
  3357.  
  3358.         isClass = false;
  3359.  
  3360.         /* For managed enums, pretend we inherit from Object */
  3361.  
  3362.         if  (clsSym->sdIsManaged)
  3363.             baseTok = cmpClsEnumToken(cmpClassObject->sdType);
  3364.     }
  3365.  
  3366.     /* Convert the namespace and class names */
  3367.  
  3368.     if  (cmpConfig.ccTestMask & 1)
  3369.     {
  3370.         /* Make sure the containing class has been processed */
  3371.  
  3372.         nspName = NULL;
  3373.         clsName = cmpGenMDname(clsSym, true, clsBuff, arraylen(clsBuff), &clsHeap);
  3374.  
  3375. //      printf("New-style type name: '%ls'\n", clsName);
  3376.  
  3377.         goto CAT_NAME;
  3378.     }
  3379.  
  3380.     for (nspSym = clsSym->sdParent;
  3381.          nspSym->sdSymKind == SYM_CLASS;
  3382.          nspSym = nspSym->sdParent)
  3383.     {
  3384.         assert(nspSym && nspSym != cmpGlobalNS);
  3385.     }
  3386.  
  3387.     nspName = cmpGenMDname(nspSym, false, nspBuff, arraylen(nspBuff), &nspHeap);
  3388.     clsName = cmpGenMDname(clsSym, false, clsBuff, arraylen(clsBuff), &clsHeap);
  3389.  
  3390. //  printf("NSP name = '%ls'\n", nspName);
  3391. //  printf("CLS name = '%ls'\n", clsName);
  3392. //  printf("\n");
  3393.  
  3394. CAT_NAME:
  3395.  
  3396.     // @todo:  This might need some cleanup.
  3397. #ifdef DEBUG
  3398.     ULONG ulFullNameLen;
  3399.     ulFullNameLen = 0;
  3400.     if (nspName)
  3401.         ulFullNameLen = wcslen(nspName) + 2;
  3402.     ulFullNameLen += wcslen(clsName) + 1;
  3403.     assert(ulFullNameLen <= (MAX_PACKAGE_NAME + MAX_CLASS_NAME + 1));
  3404. #endif
  3405.  
  3406.     fullName[0] = 0;
  3407.     if (nspName)
  3408.     {
  3409.         wcscpy(fullName, nspName);
  3410.         wcscat(fullName, L".");
  3411.     }
  3412.     wcscat(fullName, clsName);
  3413.  
  3414. //  printf("Full type name: '%ls'\n", fullName);
  3415.  
  3416.     /* Is this an external reference? */
  3417.  
  3418.     if  (extref)
  3419.     {
  3420.         mdToken         tref;
  3421.         mdToken         oref = mdTokenNil;
  3422.  
  3423.         if  (clsSym->sdParent->sdSymKind == SYM_CLASS)
  3424.         {
  3425.             oref = cmpGenClsMetadata(clsSym->sdParent);
  3426.         }
  3427.  
  3428.         cycleCounterPause();
  3429.  
  3430.         if  (FAILED(cmpWmde->DefineTypeRefByName(oref, fullName, &tref)))
  3431.             cmpFatal(ERRmetadata);
  3432.  
  3433.         cycleCounterResume();
  3434.  
  3435.         /* Are we creating an assembly ? */
  3436.  
  3437.         if  (cmpConfig.ccAssembly)
  3438.         {
  3439.             /* Is the type an assembly import ? */
  3440.  
  3441.             if  (clsSym->sdSymKind == SYM_CLASS)
  3442.             {
  3443.                 if  (clsSym->sdClass.sdcAssemIndx != 0 &&
  3444.                      clsSym->sdClass.sdcAssemRefd == false)
  3445.                 {
  3446.                     cmpAssemblySymDef(clsSym);
  3447.                 }
  3448.             }
  3449.             else
  3450.             {
  3451.                 if  (clsSym->sdEnum .sdeAssemIndx != 0 &&
  3452.                      clsSym->sdEnum .sdeAssemRefd == false)
  3453.                 {
  3454.                     cmpAssemblySymDef(clsSym);
  3455.                 }
  3456.             }
  3457.         }
  3458.  
  3459.         clsSym->sdClass.sdcMDtypedef = clsToken = tref;
  3460.  
  3461.         goto DONE;
  3462.     }
  3463.  
  3464.     /* Get hold of the emitter interface we need to use */
  3465.  
  3466.     emitIntf = cmpWmde;
  3467.  
  3468.     /* Construct the appropriate "flags" value */
  3469.  
  3470.     if  (clsSym->sdParent->sdSymKind == SYM_CLASS)
  3471.     {
  3472.         static
  3473.         unsigned        nestedClsAccFlags[] =
  3474.         {
  3475.             0,                      // ACL_ERROR
  3476.             tdNestedPublic,         // ACL_PUBLIC
  3477.             tdNestedFamily,         // ACL_PROTECTED
  3478.             tdNestedFamORAssem,     // ACL_DEFAULT
  3479.             tdNestedPrivate,        // ACL_PRIVATE
  3480.         };
  3481.  
  3482.         assert(nestedClsAccFlags[ACL_PUBLIC   ] == tdNestedPublic);
  3483.         assert(nestedClsAccFlags[ACL_PROTECTED] == tdNestedFamily);
  3484.         assert(nestedClsAccFlags[ACL_DEFAULT  ] == tdNestedFamORAssem);
  3485.         assert(nestedClsAccFlags[ACL_PRIVATE  ] == tdNestedPrivate);
  3486.  
  3487.         assert(clsSym->sdAccessLevel != ACL_ERROR);
  3488.         assert(clsSym->sdAccessLevel < arraylen(nestedClsAccFlags));
  3489.  
  3490.         flags = nestedClsAccFlags[clsSym->sdAccessLevel];
  3491.     }
  3492.     else
  3493.     {
  3494.         switch (clsSym->sdAccessLevel)
  3495.         {
  3496.         case ACL_DEFAULT:
  3497.             flags = 0;
  3498.             break;
  3499.  
  3500.         case ACL_PUBLIC:
  3501.             flags = tdPublic;
  3502.             break;
  3503.  
  3504.         default:
  3505.             flags = 0;
  3506.             break;
  3507.         }
  3508.     }
  3509.  
  3510.     if  (isClass)
  3511.     {
  3512.         assert(clsSym->sdClass.sdcFlavor == clsTyp->tdClass.tdcFlavor);
  3513.  
  3514.         /* Is this a managed class? */
  3515.  
  3516.         if  (!clsTyp->tdIsManaged)
  3517.             flags |= tdSealed|tdLayoutSequential|tdUnmanagedValueType;
  3518.  
  3519.         /* Is this a value type? */
  3520.  
  3521.         if  (clsTyp->tdClass.tdcValueType)
  3522.         {
  3523.             flags |= tdValueType|tdSealed;
  3524.  
  3525.             /* Set the base type to "System::ValueType" */
  3526.  
  3527.             assert(cmpClassValType && cmpClassValType->sdSymKind == SYM_CLASS);
  3528.  
  3529.             if  (clsTyp->tdIsManaged)
  3530.                 baseTok = cmpClsEnumToken(cmpClassValType->sdType);
  3531.         }
  3532.  
  3533.         /* Has the class been marked as "@dll.struct" ? */
  3534.  
  3535.         if  (clsSym->sdClass.sdcMarshInfo)
  3536.             flags |= tdLayoutSequential;
  3537.  
  3538.         /* Is this an interface? */
  3539.  
  3540.         if  (clsTyp->tdClass.tdcFlavor == STF_INTF)
  3541.             flags |= tdInterface;
  3542.  
  3543.         /* Is the class sealed? */
  3544.  
  3545.         if  (clsSym->sdIsSealed)
  3546.             flags |= tdSealed;
  3547.  
  3548.         /* Is the class abstract? */
  3549.  
  3550.         if  (clsSym->sdIsAbstract)
  3551.             flags |= tdAbstract;
  3552.  
  3553.         /* Do we have a GUID specification for the class? */
  3554.  
  3555.         if  (clsSym->sdClass.sdcExtraInfo)
  3556.         {
  3557.             atCommFlavors   flavor;
  3558.  
  3559.             flavor  = (clsTyp->tdClass.tdcFlavor == STF_INTF) ? AC_COM_INTF
  3560.                                                               : AC_COM_REGISTER;
  3561.  
  3562.             clsGUID = cmpFindATCentry(clsSym->sdClass.sdcExtraInfo, flavor);
  3563.             if  (clsGUID)
  3564.             {
  3565.                 const   char *  GUIDstr;
  3566.  
  3567.                 assert(clsGUID->xiAtcInfo);
  3568.                 assert(clsGUID->xiAtcInfo->atcFlavor == flavor);
  3569.  
  3570.                 GUIDstr = clsGUID->xiAtcInfo->atcInfo.atcReg.atcGUID->csStr;
  3571.  
  3572. //              printf("GUID='%s'\n", GUIDstr);
  3573.  
  3574.                 if  (parseGUID(GUIDstr, &GUIDbuf, false))
  3575.                     cmpGenError(ERRbadGUID, GUIDstr);
  3576.  
  3577.                 GUIDptr = &GUIDbuf;
  3578.  
  3579.                 /* Strange thing - mark interfaces as "import" (why?) */
  3580.  
  3581.                 if  (clsSym->sdClass.sdcFlavor == STF_INTF)
  3582.                     flags |= tdImport;
  3583.             }
  3584.  
  3585.             /* Do we have ansi/unicode/etc information? */
  3586.  
  3587.             if  (clsSym->sdClass.sdcMarshInfo)
  3588.             {
  3589.                 SymXinfoAtc     clsStr;
  3590.  
  3591.                 clsStr = cmpFindATCentry(clsSym->sdClass.sdcExtraInfo, AC_DLL_STRUCT);
  3592.                 if  (clsStr)
  3593.                 {
  3594.                     assert(clsStr->xiAtcInfo);
  3595.                     assert(clsStr->xiAtcInfo->atcFlavor == AC_DLL_STRUCT);
  3596.  
  3597.                     switch (clsStr->xiAtcInfo->atcInfo.atcStruct.atcStrings)
  3598.                     {
  3599.                     case  2: flags |= tdAnsiClass   ; break;
  3600.                     case  3: flags |= tdUnicodeClass; break;
  3601.                     case  4: flags |= tdAutoClass   ; break;
  3602.                     default: /* ??? warning ???? */   break;
  3603.                     }
  3604.                 }
  3605.             }
  3606.         }
  3607.     }
  3608.     else
  3609.     {
  3610.         /* This is an enum type */
  3611.  
  3612.         flags  |= tdEnum|tdValueType|tdSealed;
  3613.  
  3614.         /* Set the base type to "System::Enum" */
  3615.  
  3616.         assert(cmpClassEnum && cmpClassEnum->sdSymKind == SYM_CLASS);
  3617.  
  3618.         baseTok = cmpClsEnumToken(cmpClassEnum->sdType);
  3619.     }
  3620.  
  3621. //  printf("NOTE: Define MD for class '%s'\n", clsSym->sdSpelling()); fflush(stdout);
  3622.  
  3623.     /* Ready to create the typedef for the class */
  3624.  
  3625.     assert(extref == false);
  3626.  
  3627.     cycleCounterPause();
  3628.  
  3629.     /* Is this a type nested within a class? */
  3630.  
  3631.     if  (clsSym->sdParent->sdSymKind == SYM_CLASS)
  3632.     {
  3633.         if  (emitIntf->DefineNestedType(fullName,       // class     name
  3634.                                         NULL,           // version
  3635.                                         flags,          // attributes
  3636.                                         baseTok,        // base class
  3637.                                         intfTab,        // interfaces
  3638.                                         clsSym->sdParent->sdClass.sdcMDtypedef,    // enclosing class
  3639.                                         &tdef))         // resulting token
  3640.         {
  3641.             cmpFatal(ERRmetadata);
  3642.         }
  3643.     }
  3644.     else
  3645.     {
  3646.         if  (emitIntf->DefineTypeDef(fullName,      // class     name
  3647.                                      NULL,          // version
  3648.                                      flags,         // attributes
  3649.                                      baseTok,       // base class
  3650.                                      intfTab,       // interfaces
  3651.                                      &tdef))        // resulting token
  3652.         {
  3653.             cmpFatal(ERRmetadata);
  3654.         }
  3655.     }
  3656.  
  3657.     cycleCounterResume();
  3658.  
  3659.     /* Are we processing a class or enum type ? */
  3660.  
  3661.     if  (isClass)
  3662.     {
  3663.         /* Save the typedef token in the class */
  3664.  
  3665.         clsSym->sdClass.sdcMDtypedef = tdef;
  3666.  
  3667.         /* Append this type to the list of generated typedefs */
  3668.  
  3669.         if  (cmpTypeDefList)
  3670.             cmpTypeDefLast->sdClass.sdNextTypeDef = clsSym;
  3671.         else
  3672.             cmpTypeDefList                        = clsSym;
  3673.  
  3674.         cmpTypeDefLast = clsSym;
  3675.  
  3676.         /* Is this an unmanaged class with an explicit layout ? */
  3677.  
  3678.         if  (!clsTyp->tdIsManaged && clsTyp->tdClass.tdcLayoutDone)
  3679.         {
  3680.             size_t          sz;
  3681.             size_t          al;
  3682.  
  3683.             assert(clsSym->sdClass.sdcMarshInfo == false);
  3684.  
  3685.             /* Set the layout for the class type */
  3686.  
  3687.             sz = cmpGetTypeSize(clsTyp, &al);
  3688.  
  3689. //          printf("Packing = %u for [%08X] '%ls'\n", al, tdef, clsName);
  3690.  
  3691.             cycleCounterPause();
  3692.  
  3693.             if  (emitIntf->SetClassLayout(tdef, al, NULL, sz))
  3694.                 cmpFatal(ERRmetadata);
  3695.  
  3696.             cycleCounterResume();
  3697.         }
  3698.  
  3699.         /* Has the class been marked as "deprecated" ? */
  3700.  
  3701.         if  (clsSym->sdIsDeprecated)
  3702.         {
  3703.             cmpAttachMDattr(tdef, L"Deprecated"           ,
  3704.                                    "Deprecated"           , &cmpAttrDeprec);
  3705.         }
  3706.  
  3707.         /* Is the class serializable? */
  3708.  
  3709.         if  (clsSym->sdClass.sdcSrlzable)
  3710.         {
  3711.             cmpAttachMDattr(tdef, L"SerializableAttribute",
  3712.                                    "SerializableAttribute", &cmpAttrSerlzb);
  3713.         }
  3714.  
  3715.         /* Is this a non-dual interface? */
  3716.  
  3717.         if  (clsGUID && !clsGUID->xiAtcInfo->atcInfo.atcReg.atcDual
  3718.                      && clsSym->sdClass.sdcFlavor == STF_INTF)
  3719.         {
  3720.             unsigned        nondual = 0x00010001;
  3721.  
  3722.             cmpAttachMDattr(tdef, L"System.Runtime.InteropServices.InterfaceTypeAttribute",
  3723.                                    "System.Runtime.InteropServices.InterfaceTypeAttribute",
  3724.                                    &cmpAttrIsDual,
  3725.                                    ELEMENT_TYPE_I2,
  3726.                                    &nondual,
  3727.                                    2 + sizeof(unsigned short));
  3728.         }
  3729.  
  3730.         /* Do we have a security specification for the class? */
  3731.  
  3732.         if  (cmpFindSecSpec(clsSym->sdClass.sdcExtraInfo))
  3733.             cmpSecurityMD(tdef, clsSym->sdClass.sdcExtraInfo);
  3734.  
  3735.         /* Look for any custom attributes that the class might have */
  3736.  
  3737.         if  (clsSym->sdClass.sdcExtraInfo)
  3738.             cmpAddCustomAttrs(clsSym->sdClass.sdcExtraInfo, tdef);
  3739.     }
  3740.     else
  3741.     {
  3742.         clsSym->sdEnum .sdeMDtypedef = tdef;
  3743.  
  3744.         /* Append this type to the list of generated typedefs */
  3745.  
  3746.         if  (cmpTypeDefList)
  3747.             cmpTypeDefLast->sdEnum.sdNextTypeDef = clsSym;
  3748.         else
  3749.             cmpTypeDefList                       = clsSym;
  3750.  
  3751.         cmpTypeDefLast = clsSym;
  3752.  
  3753.         /* Look for any custom attributes that the enum  might have */
  3754.  
  3755.         if  (clsSym->sdEnum .sdeExtraInfo)
  3756.             cmpAddCustomAttrs(clsSym->sdEnum .sdeExtraInfo, tdef);
  3757.     }
  3758.  
  3759.     /* Are we creating an assembly and do we have a public type ? */
  3760.  
  3761. // temp hack: create manifest entries for all types, not just public ones;
  3762. //            note that there is a matching hack in cmpAssemblySymDef()
  3763.  
  3764.     if  (cmpConfig.ccAssembly) // && clsSym->sdAccessLevel == ACL_PUBLIC)
  3765.         cmpAssemblySymDef(clsSym, tdef);
  3766.  
  3767.     clsToken = tdef;
  3768.  
  3769. DONE:
  3770.  
  3771.     if  (nspHeap) SMCrlsMem(this, nspHeap);
  3772.     if  (clsHeap) SMCrlsMem(this, clsHeap);
  3773.  
  3774.     return  clsToken;
  3775. }
  3776.  
  3777. /*****************************************************************************
  3778.  *
  3779.  *  Generate metadata for any types defined within the given symbol.
  3780.  */
  3781.  
  3782. void                compiler::cmpGenTypMetadata(SymDef sym)
  3783. {
  3784.     if  (sym->sdIsImport && sym->sdSymKind != SYM_NAMESPACE)
  3785.         return;
  3786.  
  3787.     if  (sym->sdCompileState < CS_DECLARED)
  3788.     {
  3789.         /* If this is a nested class, declare it now */
  3790.  
  3791.         if  (sym->sdSymKind == SYM_CLASS)
  3792.         {
  3793.             cmpDeclSym(sym);
  3794.  
  3795.             if  (sym->sdCompileState < CS_DECLARED)
  3796.                 goto KIDS;
  3797.         }
  3798.         else
  3799.             goto KIDS;
  3800.     }
  3801.  
  3802.     switch (sym->sdSymKind)
  3803.     {
  3804.     case SYM_CLASS:
  3805.  
  3806.         // HORRENDOUS HACK -- force base class / interfaces to be generated first
  3807.  
  3808.         if  (sym->sdType->tdClass.tdcBase)
  3809.         {
  3810.             SymDef          baseSym = sym->sdType->tdClass.tdcBase->tdClass.tdcSymbol;
  3811.  
  3812.             if  (!baseSym->sdIsImport)
  3813.                 cmpGenClsMetadata(baseSym);
  3814.         }
  3815.  
  3816.         if  (sym->sdType->tdClass.tdcIntf)
  3817.         {
  3818.             TypList     intfLst;
  3819.  
  3820.             for (intfLst = sym->sdType->tdClass.tdcIntf;
  3821.                  intfLst;
  3822.                  intfLst = intfLst->tlNext)
  3823.             {
  3824.                 SymDef          intfSym = intfLst->tlType->tdClass.tdcSymbol;
  3825.  
  3826.                 if  (!intfSym->sdIsImport)
  3827.                     cmpGenClsMetadata(intfSym);
  3828.             }
  3829.         }
  3830.  
  3831.         cmpGenClsMetadata(sym);
  3832.         break;
  3833.  
  3834.     case SYM_ENUM:
  3835.         cmpGenClsMetadata(sym);
  3836.         return;
  3837.     }
  3838.  
  3839. KIDS:
  3840.  
  3841.     /* Process any children the type might have */
  3842.  
  3843.     if  (sym->sdHasScope())
  3844.     {
  3845.         SymDef          child;
  3846.  
  3847.         for (child = sym->sdScope.sdScope.sdsChildList;
  3848.              child;
  3849.              child = child->sdNextInScope)
  3850.         {
  3851.             if  (child->sdHasScope())
  3852.                 cmpGenTypMetadata(child);
  3853.         }
  3854.     }
  3855. }
  3856.  
  3857. /*****************************************************************************
  3858.  *
  3859.  *  Generate metadata for any global functions and variables contained within
  3860.  *  the given namespace.
  3861.  */
  3862.  
  3863. void                compiler::cmpGenGlbMetadata(SymDef sym)
  3864. {
  3865.     SymDef          child;
  3866.  
  3867.     assert(sym->sdSymKind == SYM_NAMESPACE);
  3868.  
  3869.     /* Process all children */
  3870.  
  3871.     for (child = sym->sdScope.sdScope.sdsChildList;
  3872.          child;
  3873.          child = child->sdNextInScope)
  3874.     {
  3875.         switch (child->sdSymKind)
  3876.         {
  3877.             SymDef          ovl;
  3878.  
  3879.         case SYM_FNC:
  3880.  
  3881.             if  (child->sdIsImport)
  3882.                 continue;
  3883.  
  3884.             for (ovl = child; ovl; ovl = ovl->sdFnc.sdfNextOvl)
  3885.             {
  3886.                 if  (!ovl->sdIsImplicit)
  3887.                 {
  3888. //                  printf("Gen metadata for global fnc '%s'\n", ovl->sdSpelling());
  3889.                     cmpGenFncMetadata(ovl);
  3890.                 }
  3891.             }
  3892.             break;
  3893.  
  3894.         case SYM_VAR:
  3895.  
  3896. //          if  (!strcmp(child->sdSpelling(), "CORtypeToSMCtype")) printf("yo!\n");
  3897.  
  3898.             if  (child->sdIsImport)
  3899.                 continue;
  3900.  
  3901.             if  (child->sdIsMember && !child->sdIsStatic)
  3902.                 break;
  3903.  
  3904. //          printf("Gen metadata for global var '%s'\n", child->sdSpelling());
  3905.             cmpGenFldMetadata(child);
  3906.             break;
  3907.  
  3908.         case SYM_NAMESPACE:
  3909.             cmpGenGlbMetadata(child);
  3910.             break;
  3911.         }
  3912.     }
  3913. }
  3914.  
  3915. /*****************************************************************************
  3916.  *
  3917.  *  Generate metadata for the members of the given class/enum.
  3918.  */
  3919.  
  3920. void                compiler::cmpGenMemMetadata(SymDef sym)
  3921. {
  3922.     TypDef          type;
  3923.     SymDef          memSym;
  3924.  
  3925.     assert(sym->sdIsImport == false);
  3926.  
  3927.     type = sym->sdType; assert(type);
  3928.  
  3929.     if  (sym->sdSymKind == SYM_CLASS)
  3930.     {
  3931.         unsigned        packing;
  3932.         bool            hasProps;
  3933.  
  3934.         bool            isIntf = (sym->sdClass.sdcFlavor == STF_INTF);
  3935.  
  3936. //      printf("genMDbeg(%d) '%s'\n", doMembers, sym->sdSpelling());
  3937.  
  3938.         /* Do we have packing/etc information for the class? */
  3939.  
  3940.         packing = 0;
  3941.  
  3942.         if  (sym->sdClass.sdcExtraInfo)
  3943.         {
  3944.             SymXinfoAtc     clsStr;
  3945.  
  3946.             clsStr = cmpFindATCentry(sym->sdClass.sdcExtraInfo, AC_DLL_STRUCT);
  3947.             if  (clsStr)
  3948.             {
  3949.                 assert(clsStr->xiAtcInfo);
  3950.                 assert(clsStr->xiAtcInfo->atcFlavor == AC_DLL_STRUCT);
  3951.  
  3952.                 packing = clsStr->xiAtcInfo->atcInfo.atcStruct.atcPack;
  3953.  
  3954.                 if  (packing == 0) packing = 8; // HACK for VC bug!!!!!!!!!!!!
  3955.             }
  3956.         }
  3957.  
  3958. //      printf("Gen metadata for members of '%s'\n", sym->sdSpelling());
  3959.  
  3960. #ifndef __IL__
  3961. //      if  (!strcmp(sym->sdSpelling(), "hashTab")) __asm int 3
  3962. #endif
  3963.  
  3964.         /* Do we need to create the silly layout table? */
  3965.  
  3966.         COR_FIELD_OFFSET *  fldTab = NULL;
  3967.         COR_FIELD_OFFSET *  fldPtr = NULL;
  3968.         unsigned            fldCnt = 0;
  3969.  
  3970.         if  (!type->tdIsManaged && cmpConfig.ccGenDebug)
  3971.         {
  3972.             /* Count non-static data members */
  3973.  
  3974.             for (memSym = sym->sdScope.sdScope.sdsChildList, fldCnt = 0;
  3975.                  memSym;
  3976.                  memSym = memSym->sdNextInScope)
  3977.             {
  3978.                 if  (memSym->sdSymKind == SYM_VAR && !memSym->sdIsStatic
  3979.                                                   && !memSym->sdVar.sdvGenSym)
  3980.                 {
  3981.                     fldCnt++;
  3982.                 }
  3983.             }
  3984.  
  3985.             if  (fldCnt)
  3986.             {
  3987.                 /* Allocate the field layout table */
  3988.  
  3989.                 fldTab =
  3990.                 fldPtr = (COR_FIELD_OFFSET*)SMCgetMem(this, (fldCnt+1)*sizeof(*fldTab));
  3991.             }
  3992.         }
  3993.  
  3994.         /* Generate metadata for all members */
  3995.  
  3996.         for (memSym = sym->sdScope.sdScope.sdsChildList, hasProps = false;
  3997.              memSym;
  3998.              memSym = memSym->sdNextInScope)
  3999.         {
  4000.             switch (memSym->sdSymKind)
  4001.             {
  4002.                 SymDef          ovlSym;
  4003.  
  4004.             case SYM_VAR:
  4005.  
  4006.                 /* Skip any instance members of generic instance classes */
  4007.  
  4008.                 if  (memSym->sdVar.sdvGenSym && !memSym->sdIsStatic)
  4009.                     break;
  4010.  
  4011.                 /* Ignore any non-static members of unmanaged classes */
  4012.  
  4013.                 if  (memSym->sdIsManaged == false &&
  4014.                      memSym->sdIsMember  != false &&
  4015.                      memSym->sdIsStatic  == false)
  4016.                      break;
  4017.  
  4018.                 /* Generate metadata for the data member */
  4019.  
  4020.                 cmpGenFldMetadata(memSym);
  4021.  
  4022.                 /* Are we generating field layout/marshalling info? */
  4023.  
  4024.                 if  (memSym->sdIsStatic)
  4025.                     break;
  4026.  
  4027.                 if  (sym->sdClass.sdcMarshInfo)
  4028.                 {
  4029.                     SymXinfoCOM     marsh;
  4030.  
  4031.                     /* Get hold of the marshalling info descriptor */
  4032.  
  4033.                     marsh = NULL;
  4034.                     if  (!memSym->sdVar.sdvConst)
  4035.                         marsh = cmpFindMarshal(memSym->sdVar.sdvFldInfo);
  4036.  
  4037.                     /* Generate marshalling info for the field */
  4038.  
  4039.                     cmpGenMarshalInfo(memSym->sdVar.sdvMDtoken,
  4040.                                       memSym->sdType,
  4041.                                       marsh ? marsh->xiCOMinfo : NULL);
  4042.                 }
  4043.                 else if (fldPtr)
  4044.                 {
  4045.                     /* Here we must have an unmanaged class member */
  4046.  
  4047.                     assert(type->tdIsManaged == false && cmpConfig.ccGenDebug);
  4048.  
  4049.                     /* Append an entry to the field layout table */
  4050.  
  4051.                     fldPtr->ridOfField = memSym->sdVar.sdvMDtoken;
  4052.                     fldPtr->ulOffset   = memSym->sdVar.sdvOffset;
  4053.  
  4054.                     fldPtr++;
  4055.                 }
  4056.                 break;
  4057.  
  4058.             case SYM_FNC:
  4059.  
  4060.                 for (ovlSym = memSym; ovlSym; ovlSym = ovlSym->sdFnc.sdfNextOvl)
  4061.                     cmpGenFncMetadata(ovlSym);
  4062.  
  4063.                 /* Special case: System::Attribute needs an attribute of itself */
  4064.  
  4065.                 if  (sym == cmpAttrClsSym || sym == cmpAuseClsSym)
  4066.                 {
  4067.                     for (ovlSym = memSym; ovlSym; ovlSym = ovlSym->sdFnc.sdfNextOvl)
  4068.                     {
  4069.                         if  (ovlSym->sdFnc.sdfCtor)
  4070.                         {
  4071.                             if  (ovlSym->sdType->tdFnc.tdfArgs.adCount == 1)
  4072.                             {
  4073.                                 unsigned short  blob[3];
  4074.  
  4075.                                 /* Add the custom attribute to the target token */
  4076.  
  4077.                                 assert(sym->sdClass.sdcMDtypedef);
  4078.                                 assert(ovlSym->sdFnc.sdfMDtoken);
  4079.  
  4080.                                 blob[0] = 1;
  4081.                                 blob[1] = 4;
  4082.                                 blob[2] = 0;
  4083.  
  4084.                                 cycleCounterPause();
  4085.  
  4086.                                 if  (cmpWmde->DefineCustomAttribute(sym->sdClass.sdcMDtypedef,
  4087.                                                                     ovlSym->sdFnc.sdfMDtoken,
  4088.                                                                     &blob,
  4089.                                                                     sizeof(short) + sizeof(int),
  4090.                                                                     NULL))
  4091.                                     cmpFatal(ERRmetadata);
  4092.  
  4093.                                 cycleCounterResume();
  4094.  
  4095.                                 break;
  4096.                             }
  4097.                         }
  4098.                     }
  4099.                 }
  4100.  
  4101.                 break;
  4102.  
  4103.             case SYM_PROP:
  4104.  
  4105.                 hasProps = true;
  4106.                 break;
  4107.  
  4108.             case SYM_CLASS:
  4109.                 break;
  4110.  
  4111.             default:
  4112. #ifdef  DEBUG
  4113.                 printf("'%s': ", cmpGlobalST->stTypeName(NULL, memSym, NULL, NULL, true));
  4114. #endif
  4115.                 NO_WAY(!"unexpected member");
  4116.             }
  4117.         }
  4118.  
  4119.         /*
  4120.             Do any of the fields of the class have marshalling info,
  4121.             do we have packing information for the class, or is this
  4122.             an unmanaged class and are we generating debug info ?
  4123.          */
  4124.  
  4125.         if  (fldTab || packing)
  4126.         {
  4127.             if  (!type->tdIsManaged && cmpConfig.ccGenDebug)
  4128.             {
  4129.                 assert(fldPtr == fldCnt + fldTab);
  4130.  
  4131.                 fldPtr->ridOfField = mdFieldDefNil;
  4132.                 fldPtr->ulOffset   = 0;
  4133.  
  4134.                 if  (!packing)
  4135.                     packing = sizeof(int);
  4136.             }
  4137.             else
  4138.             {
  4139.                 fldTab = NULL;
  4140.             }
  4141.  
  4142. //          printf("Packing = %u for [%08X] '%s'\n", packing, sym->sdClass.sdcMDtypedef, sym->sdSpelling());
  4143.  
  4144.             cycleCounterPause();
  4145.  
  4146.             if  (cmpWmde->SetClassLayout(sym->sdClass.sdcMDtypedef, packing, fldTab, 0))
  4147.                 cmpFatal(ERRmetadata);
  4148.  
  4149.             cycleCounterResume();
  4150.  
  4151.             /* If we allocated a field table, free it now */
  4152.  
  4153.             if  (fldTab)
  4154.                 SMCrlsMem(this, fldTab);
  4155.         }
  4156.  
  4157.         /* Did we encounter any properties? */
  4158.  
  4159.         if  (hasProps)
  4160.         {
  4161.             for (memSym = sym->sdScope.sdScope.sdsChildList;
  4162.                  memSym;
  4163.                  memSym = memSym->sdNextInScope)
  4164.             {
  4165.                 SymDef          opmSym;
  4166.  
  4167.                 if  (memSym->sdSymKind != SYM_PROP)
  4168.                     continue;
  4169.  
  4170.                 for (opmSym = memSym; opmSym; opmSym = opmSym->sdProp.sdpNextOvl)
  4171.                 {
  4172.                     TypDef          memTyp = opmSym->sdType;;
  4173.  
  4174.                     PCOR_SIGNATURE  sigPtr;
  4175.                     size_t          sigLen;
  4176.  
  4177.                     mdMethodDef     mtokGet;
  4178.                     mdMethodDef     mtokSet;
  4179.  
  4180.                     mdProperty      propTok;
  4181.  
  4182.                     unsigned        flags;
  4183.  
  4184.                     assert(opmSym->sdSymKind == SYM_PROP);
  4185.                     assert(opmSym->sdProp.sdpMDtoken == 0);
  4186.  
  4187.                     /* Generate the property member's signature */
  4188.  
  4189.                     if  (memTyp->tdTypeKind == TYP_FNC)
  4190.                     {
  4191.                         sigPtr = (PCOR_SIGNATURE)cmpGenMemberSig(opmSym, NULL, NULL, NULL, &sigLen);
  4192.                     }
  4193.                     else
  4194.                     {
  4195.                         unsigned        flags;
  4196.  
  4197.                         // HACK: pretend it's a method
  4198.  
  4199.                         flags = IMAGE_CEE_CS_CALLCONV_DEFAULT|
  4200.                                 IMAGE_CEE_CS_CALLCONV_PROPERTY;
  4201.  
  4202.                         if  (!opmSym->sdIsStatic)
  4203.                             flags |= IMAGE_CEE_CS_CALLCONV_HASTHIS;
  4204.  
  4205.                         cmpMDsigStart();
  4206.                         cmpMDsigAdd_I1(flags);
  4207.                         cmpMDsigAddCU4(0);
  4208.                         cmpMDsigAddTyp(memTyp);
  4209.  
  4210.                         sigPtr = cmpMDsigEnd(&sigLen);
  4211.                     }
  4212.  
  4213.                     /* Get hold of the getter/setter accessor tokens, if any */
  4214.  
  4215.                     mtokGet = 0;
  4216.                     if  (opmSym->sdProp.sdpGetMeth)
  4217.                     {
  4218.                         assert(opmSym->sdProp.sdpGetMeth->sdSymKind == SYM_FNC);
  4219.                         assert(opmSym->sdProp.sdpGetMeth->sdFnc.sdfMDtoken);
  4220.  
  4221.                         mtokGet = opmSym->sdProp.sdpGetMeth->sdFnc.sdfMDtoken;
  4222.                     }
  4223.  
  4224.                     mtokSet = 0;
  4225.                     if  (opmSym->sdProp.sdpSetMeth)
  4226.                     {
  4227.                         assert(opmSym->sdProp.sdpSetMeth->sdSymKind == SYM_FNC);
  4228.                         assert(opmSym->sdProp.sdpSetMeth->sdFnc.sdfMDtoken);
  4229.  
  4230.                         mtokSet = opmSym->sdProp.sdpSetMeth->sdFnc.sdfMDtoken;
  4231.                     }
  4232.  
  4233.                     flags = 0;
  4234.  
  4235.                     /* We're ready to generate metadata for the property */
  4236.  
  4237.                     cycleCounterPause();
  4238.  
  4239.                     if  (cmpWmde->DefineProperty(sym->sdClass.sdcMDtypedef,
  4240.                                                  cmpUniConv(opmSym->sdName),
  4241.                                                  flags,
  4242.                                                  sigPtr,
  4243.                                                  sigLen,
  4244.                                                  ELEMENT_TYPE_VOID,
  4245.                                                  NULL,
  4246.                                                  -1,
  4247.                                                  mtokSet,
  4248.                                                  mtokGet,
  4249.                                                  NULL,
  4250.                                                  mdTokenNil,
  4251.                                                  &propTok))
  4252.                     {
  4253.                         cmpFatal(ERRmetadata);
  4254.                     }
  4255.  
  4256.                     cycleCounterResume();
  4257.  
  4258.                     /* Has the property been marked as "deprecated" ? */
  4259.  
  4260.                     if  (memSym->sdIsDeprecated)
  4261.                     {
  4262.                         cmpAttachMDattr(propTok, L"Deprecated"            ,
  4263.                                                   "Deprecated"            , &cmpAttrDeprec);
  4264.                     }
  4265.  
  4266.                     /* Is the property "default" ? */
  4267.  
  4268.                     if  (memSym->sdIsDfltProp)
  4269.                     {
  4270.                         cmpAttachMDattr(propTok, L"DefaultMemberAttribute",
  4271.                                                   "DefaultMemberAttribute", &cmpAttrDefProp);
  4272.                     }
  4273.  
  4274.                     /* Output any custom properties */
  4275.  
  4276.                     if  (opmSym->sdProp.sdpExtraInfo)
  4277.                         cmpAddCustomAttrs(opmSym->sdProp.sdpExtraInfo, propTok);
  4278.  
  4279. //                  printf("MD for prop [%08X] '%s'\n", propTok, cmpGlobalST->stTypeName(opmSym->sdType, opmSym, NULL, NULL, true));
  4280.  
  4281.                     opmSym->sdProp.sdpMDtoken = propTok;
  4282.                 }
  4283.             }
  4284.         }
  4285.  
  4286. //      printf("genMDend(%d) '%s'\n", doMembers, sym->sdSpelling());
  4287.     }
  4288.     else
  4289.     {
  4290.         assert(sym->sdSymKind == SYM_ENUM);
  4291.  
  4292.         PCOR_SIGNATURE      sigPtr;
  4293.         size_t              sigLen;
  4294.  
  4295.         mdTypeSpec          fakeTok;
  4296.  
  4297.         if  (cmpConfig.ccIntEnums)
  4298.             return;
  4299.  
  4300.         /* Create a signature for the underlying integer type */
  4301.  
  4302.                  cmpMDsigStart ();
  4303.                  cmpMDsigAdd_I1(IMAGE_CEE_CS_CALLCONV_FIELD);
  4304.                  cmpMDsigAddTyp(sym->sdType->tdEnum.tdeIntType);
  4305.         sigPtr = cmpMDsigEnd   (&sigLen);
  4306.  
  4307. //      printf("Gen metadata for enumids of '%s'\n", sym->sdSpelling());
  4308.  
  4309.         cycleCounterPause();
  4310.  
  4311.         if  (cmpWmde->DefineField(sym->sdEnum.sdeMDtypedef,
  4312.                                   L"value__",
  4313.                                   fdPublic,
  4314.                                   sigPtr,
  4315.                                   sigLen,
  4316.                                   ELEMENT_TYPE_VOID,
  4317.                                   NULL,
  4318.                                   -1,
  4319.                                   &fakeTok))
  4320.         {
  4321.             cmpFatal(ERRmetadata);
  4322.         }
  4323.  
  4324.         cycleCounterResume();
  4325.  
  4326.         if  (!sym->sdIsManaged && !cmpConfig.ccGenDebug)
  4327.             return;
  4328.  
  4329.         /* Generate metadata for the actual enumerator values */
  4330.  
  4331.         for (memSym = type->tdEnum.tdeValues;
  4332.              memSym;
  4333.              memSym = memSym->sdEnumVal.sdeNext)
  4334.         {
  4335.             assert(memSym->sdSymKind == SYM_ENUMVAL);
  4336.  
  4337.             cmpGenFldMetadata(memSym);
  4338.         }
  4339.     }
  4340. }
  4341.  
  4342. /*****************************************************************************
  4343.  *
  4344.  *  Set RVA's (in metadata) for all global variables.
  4345.  */
  4346.  
  4347. void                compiler::cmpSetGlobMDoffsR(SymDef scope, unsigned dataOffs)
  4348. {
  4349.     SymDef          sym;
  4350.  
  4351.     for (sym = scope->sdScope.sdScope.sdsChildList;
  4352.          sym;
  4353.          sym = sym->sdNextInScope)
  4354.     {
  4355.         switch (sym->sdSymKind)
  4356.         {
  4357.         case SYM_VAR:
  4358.  
  4359. #ifndef __IL__
  4360. //          if  (!strcmp(sym->sdSpelling(), "optionInfo")) __asm int 3
  4361. #endif
  4362.  
  4363.             if  (sym->sdIsImport == false &&
  4364.                  sym->sdIsMember == false)
  4365.             {
  4366.                 assert(sym->sdVar.sdvMDtoken);
  4367.  
  4368. //              printf("Set RVA to %08X for '%s'\n", sym->sdVar.sdvOffset + dataOffs, sym->sdSpelling());
  4369.  
  4370.                 if  (FAILED(cmpWmde->SetFieldRVA(sym->sdVar.sdvMDtoken, sym->sdVar.sdvOffset + dataOffs)))
  4371.                     cmpFatal(ERRmetadata);
  4372.             }
  4373.             break;
  4374.  
  4375.         case SYM_CLASS:
  4376.             if  (!sym->sdIsManaged)
  4377.             {
  4378.                 SymDef          mem;
  4379.  
  4380.                 for (mem = sym->sdScope.sdScope.sdsChildList;
  4381.                      mem;
  4382.                      mem = mem->sdNextInScope)
  4383.                 {
  4384.                     if  (mem->sdSymKind == SYM_VAR && mem->sdIsStatic)
  4385.                     {
  4386. //                      printf("Set RVA to %08X for '%s'\n", mem->sdVar.sdvOffset + dataOffs, mem->sdSpelling());
  4387.  
  4388.                         if  (FAILED(cmpWmde->SetFieldRVA(mem->sdVar.sdvMDtoken, mem->sdVar.sdvOffset + dataOffs)))
  4389.                             cmpFatal(ERRmetadata);
  4390.                     }
  4391.                 }
  4392.             }
  4393.             break;
  4394.  
  4395.         case SYM_NAMESPACE:
  4396.             cmpSetGlobMDoffsR(sym, dataOffs);
  4397.             break;
  4398.         }
  4399.     }
  4400. }
  4401.  
  4402. void                compiler::cmpSetGlobMDoffs(unsigned dataOffs)
  4403. {
  4404.  
  4405.     SymList         list;
  4406.  
  4407.     /* Set RVA's for all static local variables of all functions */
  4408.  
  4409.     for (list = cmpLclStatListP; list; list = list->slNext)
  4410.     {
  4411.         SymDef         varSym = list->slSym;
  4412.  
  4413.         assert(varSym->sdSymKind == SYM_VAR);
  4414.         assert(varSym->sdVar.sdvLocal == false);
  4415.         assert(varSym->sdIsStatic);
  4416.         assert(varSym->sdType && !varSym->sdIsManaged);
  4417.  
  4418.         if  (FAILED(cmpWmde->SetFieldRVA(varSym->sdVar.sdvMDtoken, varSym->sdVar.sdvOffset + dataOffs)))
  4419.             cmpFatal(ERRmetadata);
  4420.     }
  4421.  
  4422.     /* Set RVA's for all global variables (recursively) */
  4423.  
  4424.     cmpSetGlobMDoffsR(cmpGlobalNS, dataOffs);
  4425. }
  4426.  
  4427. /*****************************************************************************/
  4428.