1: // Copyright (C) 1984-1998 by Symantec
   2: // Copyright (C) 2000-2011 by Digital Mars
   3: // All Rights Reserved
   4: // http://www.digitalmars.com
   5: // Written by Walter Bright
   6: /*
   7:  * This source file is made available for personal use
   8:  * only. The license is in /dmd/src/dmd/backendlicense.txt
   9:  * or /dm/src/dmd/backendlicense.txt
  10:  * For any other uses, please contact Digital Mars.
  11:  */
  12: 
  13: 
  14: #if !SPP
  15: 
  16: #include        <stdio.h>
  17: #include        <string.h>
  18: #include        <time.h>
  19: 
  20: #include        "cc.h"
  21: #include        "oper.h"
  22: #include        "global.h"
  23: #include        "type.h"
  24: #include        "filespec.h"
  25: #include        "code.h"
  26: #include        "cgcv.h"
  27: #include        "go.h"
  28: #include        "dt.h"
  29: #if SCPP
  30: #include        "parser.h"
  31: #include        "cpp.h"
  32: #include        "el.h"
  33: #endif
  34: 
  35: static char __file__[] = __FILE__;      /* for tassert.h                */
  36: #include        "tassert.h"
  37: 
  38: static  int addrparam;  /* see if any parameters get their address taken */
  39: 
  40: /**********************************
  41:  * We put out an external definition.
  42:  */
  43: 
  44: #if SCPP
  45: 
  46: void out_extdef(symbol *s)
  47: {
  48:     pstate.STflags |= PFLextdef;
  49:     if (//config.flags2 & CFG2phgen ||
  50:         (config.flags2 & (CFG2phauto | CFG2phautoy) &&
  51:             !(pstate.STflags & (PFLhxwrote | PFLhxdone)))
  52:        )
  53: 
  54:         synerr(EM_data_in_pch,prettyident(s));          // data or code in precompiled header
  55: }
  56: 
  57: #endif
  58: 
  59: #if TX86
  60: #if SCPP
  61: /********************************
  62:  * Put out code segment name record.
  63:  */
  64: 
  65: void outcsegname(char *csegname)
  66: {
  67:     obj_codeseg(csegname,0);
  68: }
  69: #endif
  70: #endif
  71: 
  72: /***********************************
  73:  * Output function thunk.
  74:  */
  75: 
  76: #if SCPP
  77: 
  78: void outthunk(symbol *sthunk,symbol *sfunc,unsigned p,tym_t thisty,
  79:         targ_size_t d,int i,targ_size_t d2)
  80: {
  81:     cod3_thunk(sthunk,sfunc,p,thisty,d,i,d2);
  82:     sthunk->Sfunc->Fflags &= ~Fpending;
  83:     sthunk->Sfunc->Fflags |= Foutput;   /* mark it as having been output */
  84: }
  85: 
  86: #endif
  87: 
  88: /***************************
  89:  * Write out statically allocated data.
  90:  * Input:
  91:  *      s               symbol to be initialized
  92:  */
  93: 
  94: #if TX86
  95: 
  96: void outdata(symbol *s)
  97: {
  98: #if HTOD
  99:     return;
 100: #endif
 101:     dt_t *dtstart,*dt;
 102:     targ_size_t datasize,a;
 103:     int seg;
 104:     targ_size_t offset;
 105:     int flags;
 106:     tym_t ty;
 107: 
 108:     symbol_debug(s);
 109: #ifdef DEBUG
 110:     debugy && dbg_printf("outdata('%s')\n",s->Sident);
 111: #endif
 112:     //printf("outdata('%s', ty=x%x)\n",s->Sident,s->Stype->Tty);
 113:     //symbol_print(s);
 114: 
 115:     // Data segment variables are always live on exit from a function
 116:     s->Sflags |= SFLlivexit;
 117: 
 118:     dtstart = s->Sdt;
 119:     s->Sdt = NULL;                      // it will be free'd
 120: #if OMFOBJ
 121:     int tls = 0;
 122: #endif
 123: #if SCPP && TARGET_WINDOS
 124:     if (eecontext.EEcompile)
 125:     {   s->Sfl = (s->ty() & mTYfar) ? FLfardata : FLextern;
 126:         s->Sseg = UNKNOWN;
 127:         goto Lret;                      // don't output any data
 128:     }
 129: #endif
 130:     datasize = 0;
 131:     ty = s->ty();
 132:     if (ty & mTYexport && config.wflags & WFexpdef && s->Sclass != SCstatic)
 133:         obj_export(s,0);        // export data definition
 134:     for (dt = dtstart; dt; dt = dt->DTnext)
 135:     {
 136:         //printf("dt = %p, dt = %d\n",dt,dt->dt);
 137:         switch (dt->dt)
 138:         {   case DT_abytes:
 139:             {   // Put out the data for the string, and
 140:                 // reserve a spot for a pointer to that string
 141: #if ELFOBJ || MACHOBJ
 142:                 datasize += size(dt->Dty);
 143:                 dt->DTabytes += elf_data_cdata(dt->DTpbytes,dt->DTnbytes,&dt->DTseg);
 144: #else
 145:                 targ_size_t *poffset;
 146:                 datasize += size(dt->Dty);
 147:                 if (tybasic(dt->Dty) == TYcptr)
 148:                 {   seg = cseg;
 149:                     poffset = &Coffset;
 150:                 }
 151: #if SCPP
 152:                 else if (tybasic(dt->Dty) == TYfptr &&
 153:                          dt->DTnbytes > config.threshold)
 154:                 {
 155:                     seg = obj_fardata(s->Sident,dt->DTnbytes,&offset);
 156:                     poffset = &offset;
 157:                 }
 158: #endif
 159:                 else
 160:                 {   seg = DATA;
 161:                     poffset = &Doffset;
 162:                 }
 163:                 dt->DTseg = seg;
 164:                 dt->DTabytes += *poffset;
 165:                 obj_bytes(seg,*poffset,dt->DTnbytes,dt->DTpbytes);
 166:                 *poffset += dt->DTnbytes;
 167: #endif
 168:                 break;
 169:             }
 170:             case DT_ibytes:
 171:                 datasize += dt->DTn;
 172:                 break;
 173:             case DT_nbytes:
 174:                 //printf("DT_nbytes %d\n", dt->DTnbytes);
 175:                 datasize += dt->DTnbytes;
 176:                 break;
 177:             case DT_symsize:
 178: #if MARS
 179:                 assert(0);
 180: #else
 181:                 dt->DTazeros = type_size(s->Stype);
 182: #endif
 183:                 goto case_azeros;
 184:             case DT_azeros:
 185:                 /* A block of zeros
 186:                  */
 187:                 //printf("DT_azeros %d\n", dt->DTazeros);
 188:             case_azeros:
 189:                 datasize += dt->DTazeros;
 190:                 if (dt == dtstart && !dt->DTnext && s->Sclass != SCcomdat)
 191:                 {   /* first and only, so put in BSS segment
 192:                      */
 193:                     switch (ty & mTYLINK)
 194:                     {
 195: #if OMFOBJ
 196:                         case mTYfar:                    // if far data
 197:                             seg = obj_fardata(s->Sident,datasize,&s->Soffset);
 198:                             s->Sfl = FLfardata;
 199:                             break;
 200: #endif
 201:                         case mTYcs:
 202: #if OMFOBJ
 203:                             seg = cseg;
 204: #endif
 205:                             Coffset = align(datasize,Coffset);
 206:                             s->Soffset = Coffset;
 207:                             Coffset += datasize;
 208:                             s->Sfl = FLcsdata;
 209:                             break;
 210:                         case mTYthread:
 211:                         {   seg_data *pseg = obj_tlsseg_bss();
 212: #if ELFOBJ || MACHOBJ
 213:                             s->Sseg = pseg->SDseg;
 214:                             elf_data_start(s, datasize, pseg->SDseg);
 215:                             obj_lidata(pseg->SDseg, pseg->SDoffset, datasize);
 216: #else
 217:                             targ_size_t TDoffset = pseg->SDoffset;
 218:                             TDoffset = align(datasize,TDoffset);
 219:                             s->Soffset = TDoffset;
 220:                             TDoffset += datasize;
 221:                             pseg->SDoffset = TDoffset;
 222:                             seg = pseg->SDseg;
 223:                             tls = 1;
 224: #endif
 225:                             s->Sfl = FLtlsdata;
 226:                             break;
 227:                         }
 228:                         default:
 229: #if ELFOBJ || MACHOBJ
 230:                             elf_data_start(s,datasize,UDATA);
 231:                             obj_lidata(s->Sseg,s->Soffset,datasize);
 232: #else
 233:                             seg = UDATA;
 234:                             UDoffset = align(datasize,UDoffset);
 235:                             s->Soffset = UDoffset;
 236:                             UDoffset += datasize;
 237: #endif
 238:                             s->Sfl = FLudata;           // uninitialized data
 239:                             break;
 240:                     }
 241: #if ELFOBJ || MACHOBJ
 242:                     assert(s->Sseg != UNKNOWN);
 243:                     if (s->Sclass == SCglobal || s->Sclass == SCstatic)
 244:                         objpubdef(s->Sseg,s,s->Soffset);        /* do the definition    */
 245:                                             /* if a pubdef to be done */
 246: #else
 247:                     s->Sseg = seg;
 248:                     if (s->Sclass == SCglobal)          /* if a pubdef to be done */
 249:                         objpubdef(seg,s,s->Soffset);    /* do the definition    */
 250: #endif
 251:                     searchfixlist(s);
 252:                     if (config.fulltypes &&
 253:                         !(s->Sclass == SCstatic && funcsym_p)) // not local static
 254:                         cv_outsym(s);
 255: #if SCPP
 256:                     out_extdef(s);
 257: #endif
 258:                     goto Lret;
 259:                 }
 260:                 break;
 261:             case DT_common:
 262:                 assert(!dt->DTnext);
 263:                 outcommon(s,dt->DTazeros);
 264:                 goto Lret;
 265: 
 266:             case DT_xoff:
 267:             {   symbol *sb = dt->DTsym;
 268: 
 269:                 if (tyfunc(sb->ty()))
 270: #if SCPP
 271:                     nwc_mustwrite(sb);
 272: #else
 273:                     ;
 274: #endif
 275:                 else if (sb->Sdt)               // if initializer for symbol
 276:                     outdata(sb);                // write out data for symbol
 277:             }
 278:             case DT_coff:
 279:                 datasize += size(dt->Dty);
 280:                 break;
 281:             case DT_1byte:
 282:                 datasize++;
 283:                 break;
 284:             default:
 285: #ifdef DEBUG
 286:                 dbg_printf("dt = %p, dt = %d\n",dt,dt->dt);
 287: #endif
 288:                 assert(0);
 289:         }
 290:     }
 291: 
 292:     if (s->Sclass == SCcomdat)          // if initialized common block
 293:     {
 294:         seg = obj_comdat(s);
 295: #if ELFOBJ || OMFOBJ
 296:         s->Soffset = 0;
 297: #endif
 298:         switch (ty & mTYLINK)
 299:         {
 300: #if OMFOBJ
 301:             case mTYfar:                // if far data
 302:                 s->Sfl = FLfardata;
 303:                 break;
 304: #endif
 305:             case mTYcs:
 306:                 s->Sfl = FLcsdata;
 307:                 break;
 308:             case mTYnear:
 309:             case 0:
 310:                 s->Sfl = FLdata;        // initialized data
 311:                 break;
 312:             case mTYthread:
 313:                 s->Sfl = FLtlsdata;
 314: #if OMFOBJ
 315:                 tls = 1;
 316: #endif
 317:                 break;
 318: 
 319:             default:
 320:                 assert(0);
 321:         }
 322:     }
 323:     else
 324:     {
 325:       switch (ty & mTYLINK)
 326:       {
 327: #if OMFOBJ
 328:         case mTYfar:                    // if far data
 329:             seg = obj_fardata(s->Sident,datasize,&s->Soffset);
 330:             s->Sfl = FLfardata;
 331:             break;
 332: #endif
 333:         case mTYcs:
 334:             assert(OMFOBJ);
 335:             seg = cseg;
 336:             Coffset = align(datasize,Coffset);
 337:             s->Soffset = Coffset;
 338:             s->Sfl = FLcsdata;
 339:             break;
 340:         case mTYthread:
 341:         {   seg_data *pseg = obj_tlsseg();
 342: #if ELFOBJ || MACHOBJ
 343:             s->Sseg = pseg->SDseg;
 344:             elf_data_start(s, datasize, s->Sseg);
 345: //          s->Soffset = pseg->SDoffset;
 346: #else
 347:             targ_size_t TDoffset = pseg->SDoffset;
 348:             TDoffset = align(datasize,TDoffset);
 349:             s->Soffset = TDoffset;
 350:             tls = 1;
 351: #endif
 352:             seg = pseg->SDseg;
 353:             s->Sfl = FLtlsdata;
 354:             break;
 355:         }
 356:         case mTYnear:
 357:         case 0:
 358: #if ELFOBJ || MACHOBJ
 359:             seg = elf_data_start(s,datasize,DATA);
 360: #else
 361:             seg = DATA;
 362:             alignOffset(DATA, datasize);
 363:             s->Soffset = Doffset;
 364: #endif
 365:             s->Sfl = FLdata;            // initialized data
 366:             break;
 367:         default:
 368:             assert(0);
 369:       }
 370:     }
 371: #if ELFOBJ || MACHOBJ
 372:     if (s->Sseg == UNKNOWN)
 373:         s->Sseg = seg;
 374:     else
 375:         seg = s->Sseg;
 376:     if (s->Sclass == SCglobal || s->Sclass == SCstatic)
 377:     {
 378:         objpubdef(s->Sseg,s,s->Soffset);        // do the definition
 379:     }
 380: #else
 381:     s->Sseg = seg;
 382:     if (s->Sclass == SCglobal)          /* if a pubdef to be done       */
 383:         objpubdef(seg,s,s->Soffset);    /* do the definition            */
 384: #endif
 385:     if (config.fulltypes &&
 386:         !(s->Sclass == SCstatic && funcsym_p)) // not local static
 387:         cv_outsym(s);
 388:     searchfixlist(s);
 389: 
 390:     /* Go back through list, now that we know its size, and send out    */
 391:     /* the data.                                                        */
 392: 
 393:     offset = s->Soffset;
 394: 
 395:     for (dt = dtstart; dt; dt = dt->DTnext)
 396:     {
 397:         switch (dt->dt)
 398:         {   case DT_abytes:
 399:                 if (tyreg(dt->Dty))
 400:                     flags = CFoff;
 401:                 else
 402:                     flags = CFoff | CFseg;
 403:                 if (I64)
 404:                     flags |= CFoffset64;
 405:                 if (tybasic(dt->Dty) == TYcptr)
 406:                     reftocodseg(seg,offset,dt->DTabytes);
 407: #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
 408:                 else
 409:                     reftodatseg(seg,offset,dt->DTabytes,dt->DTseg,flags);
 410: #else
 411:                 else if (dt->DTseg == DATA)
 412:                     reftodatseg(seg,offset,dt->DTabytes,DATA,flags);
 413:                 else
 414:                     reftofarseg(seg,offset,dt->DTabytes,dt->DTseg,flags);
 415: #endif
 416:                 offset += size(dt->Dty);
 417:                 break;
 418:             case DT_ibytes:
 419:                 obj_bytes(seg,offset,dt->DTn,dt->DTdata);
 420:                 offset += dt->DTn;
 421:                 break;
 422:             case DT_nbytes:
 423:                 obj_bytes(seg,offset,dt->DTnbytes,dt->DTpbytes);
 424:                 offset += dt->DTnbytes;
 425:                 break;
 426:             case DT_azeros:
 427:                 //printf("obj_lidata(seg = %d, offset = %d, azeros = %d)\n", seg, offset, dt->DTazeros);
 428:                 obj_lidata(seg,offset,dt->DTazeros);
 429:                 offset += dt->DTazeros;
 430:                 break;
 431:             case DT_xoff:
 432:             {
 433:                 symbol *sb = dt->DTsym;          // get external symbol pointer
 434:                 a = dt->DToffset; // offset from it
 435:                 if (tyreg(dt->Dty))
 436:                     flags = CFoff;
 437:                 else
 438:                     flags = CFoff | CFseg;
 439:                 if (I64)
 440:                     flags |= CFoffset64;
 441:                 offset += reftoident(seg,offset,sb,a,flags);
 442:                 break;
 443:             }
 444:             case DT_coff:
 445:                 reftocodseg(seg,offset,dt->DToffset);
 446:                 offset += intsize;
 447:                 break;
 448:             case DT_1byte:
 449:                 obj_byte(seg,offset++,dt->DTonebyte);
 450:                 break;
 451:             default:
 452: #ifdef DEBUG
 453:                 dbg_printf("dt = %p, dt = %d\n",dt,dt->dt);
 454: #endif
 455:                 assert(0);
 456:         }
 457:     }
 458: #if ELFOBJ || MACHOBJ
 459:     Offset(seg) = offset;
 460: #elif OMFOBJ
 461:     if (seg == DATA)
 462:         Doffset = offset;
 463:     else if (seg == cseg)
 464:         Coffset = offset;
 465:     else if (tls && s->Sclass != SCcomdat)
 466:     {
 467:         obj_tlsseg()->SDoffset = offset;
 468:     }
 469: #else
 470: #error "obj format?"
 471: #endif
 472: #if SCPP
 473:     out_extdef(s);
 474: #endif
 475: Lret:
 476:     dt_free(dtstart);
 477: }
 478: 
 479: 
 480: 
 481: /******************************
 482:  * Output n bytes of a common block, n > 0.
 483:  */
 484: 
 485: void outcommon(symbol *s,targ_size_t n)
 486: {
 487:     //printf("outcommon('%s',%d)\n",s->Sident,n);
 488:     if (n != 0)
 489:     {
 490:         assert(s->Sclass == SCglobal);
 491:         if (s->ty() & mTYcs) // if store in code segment
 492:         {
 493:             /* COMDEFs not supported in code segment
 494:              * so put them out as initialized 0s
 495:              */
 496:             dtnzeros(&s->Sdt,n);
 497:             outdata(s);
 498: #if SCPP
 499:             out_extdef(s);
 500: #endif
 501:         }
 502:         else if (s->ty() & mTYthread) // if store in thread local segment
 503:         {
 504: #if ELFOBJ
 505:             s->Sclass = SCcomdef;
 506:             obj_comdef(s, 0, n, 1);
 507: #else
 508:             /* COMDEFs not supported in tls segment
 509:              * so put them out as COMDATs with initialized 0s
 510:              */
 511:             s->Sclass = SCcomdat;
 512:             dtnzeros(&s->Sdt,n);
 513:             outdata(s);
 514: #if SCPP && OMFOBJ
 515:             out_extdef(s);
 516: #endif
 517: #endif
 518:         }
 519:         else
 520:         {
 521: #if ELFOBJ || MACHOBJ
 522:             s->Sclass = SCcomdef;
 523:             obj_comdef(s, 0, n, 1);
 524: #else
 525:             s->Sclass = SCcomdef;
 526:             s->Sxtrnnum = obj_comdef(s,(s->ty() & mTYfar) == 0,n,1);
 527:             s->Sseg = UNKNOWN;
 528:             if (s->ty() & mTYfar)
 529:                 s->Sfl = FLfardata;
 530:             else
 531:                 s->Sfl = FLextern;
 532:             pstate.STflags |= PFLcomdef;
 533: #if SCPP
 534:             ph_comdef(s);               // notify PH that a COMDEF went out
 535: #endif
 536: #endif
 537:         }
 538:         if (config.fulltypes)
 539:             cv_outsym(s);
 540:     }
 541: }
 542: #endif // TX86
 543: 
 544: /******************************
 545:  * Walk expression tree, converting it from a PARSER tree to
 546:  * a code generator tree.
 547:  */
 548: 
 549: STATIC void outelem(elem *e)
 550: {
 551:     symbol *s;
 552:     tym_t tym;
 553:     elem *e1;
 554: #if SCPP
 555:     type *t;
 556: #endif
 557: 
 558: again:
 559:     assert(e);
 560:     elem_debug(e);
 561: 
 562: #ifdef DEBUG
 563:     if (EBIN(e))
 564:         assert(e->E1 && e->E2);
 565: //    else if (EUNA(e))
 566: //      assert(e->E1 && !e->E2);
 567: #endif
 568: 
 569: #if SCPP
 570:     t = e->ET;
 571:     assert(t);
 572:     type_debug(t);
 573:     tym = t->Tty;
 574:     switch (tybasic(tym))
 575:     {   case TYstruct:
 576:             t->Tcount++;
 577:             break;
 578: 
 579:         case TYarray:
 580:             t->Tcount++;
 581:             break;
 582: 
 583:         case TYbool:
 584:         case TYwchar_t:
 585:         case TYchar16:
 586:         case TYmemptr:
 587:         case TYvtshape:
 588:         case TYnullptr:
 589:             tym = tym_conv(t);
 590:             e->ET = NULL;
 591:             break;
 592: 
 593:         case TYenum:
 594:             tym = tym_conv(t->Tnext);
 595:             e->ET = NULL;
 596:             break;
 597: 
 598:         default:
 599:             e->ET = NULL;
 600:             break;
 601:     }
 602:     e->Nflags = 0;
 603:     e->Ety = tym;
 604: #endif
 605: 
 606:     switch (e->Eoper)
 607:     {
 608:     default:
 609:     Lop:
 610: #if DEBUG
 611:         //if (!EOP(e)) dbg_printf("e->Eoper = x%x\n",e->Eoper);
 612: #endif
 613:         if (EBIN(e))
warning C6385: Invalid data: accessing 'unsigned char const * const optab1', the readable size is '183' bytes, but '1022' bytes might be read: Lines: 551, 552, 553, 558, 559, 606, 608, 609, 613
614: { outelem(e->E1); 615: e = e->E2; 616: } 617: else if (EUNA(e)) 618: { 619: e = e->E1; 620: } 621: else 622: break; 623: #if SCPP 624: type_free(t); 625: #endif 626: goto again; /* iterate instead of recurse */ 627: case OPaddr: 628: e1 = e->E1; 629: if (e1->Eoper == OPvar) 630: { // Fold into an OPrelconst 631: #if SCPP 632: el_copy(e,e1); 633: e->ET = t; 634: #else 635: tym = e->Ety; 636: el_copy(e,e1); 637: e->Ety = tym; 638: #endif 639: e->Eoper = OPrelconst; 640: el_free(e1); 641: goto again; 642: } 643: goto Lop; 644: 645: case OPrelconst: 646: case OPvar: 647: L6:
warning C4102: 'L6' : unreferenced label
648: s = e->EV.sp.Vsym; 649: assert(s); 650: symbol_debug(s); 651: switch (s->Sclass) 652: { 653: case SCregpar: 654: case SCparameter: 655: if (e->Eoper == OPrelconst) 656: addrparam = TRUE; // taking addr of param list 657: break; 658: 659: case SCstatic: 660: case SClocstat: 661: case SCextern: 662: case SCglobal: 663: case SCcomdat: 664: case SCcomdef: 665: #if PSEUDO_REGS 666: case SCpseudo: 667: #endif 668: case SCinline: 669: case SCsinline: 670: case SCeinline: 671: s->Sflags |= SFLlivexit; 672: /* FALL-THROUGH */ 673: case SCauto: 674: case SCregister: 675: case SCfastpar: 676: case SCbprel: 677: case SCtmp: 678: if (e->Eoper == OPrelconst) 679: { 680: s->Sflags &= ~(SFLunambig | GTregcand); 681: } 682: #if SCPP && TX86 && OMFOBJ 683: else if (s->ty() & mTYfar) 684: e->Ety |= mTYfar; 685: #endif 686: break; 687: #if SCPP 688: case SCmember: 689: err_noinstance(s->Sscope,s); 690: goto L5; 691: case SCstruct: 692: cpperr(EM_no_instance,s->Sident); // no instance of class 693: L5: 694: e->Eoper = OPconst; 695: e->Ety = TYint; 696: return; 697: 698: case SCfuncalias: 699: e->EV.sp.Vsym = s->Sfunc->Falias; 700: goto L6; 701: case SCstack: 702: break; 703: case SCfunctempl: 704: cpperr(EM_no_template_instance, s->Sident); 705: break; 706: default: 707: #ifdef DEBUG 708: symbol_print(s); 709: WRclass((enum SC) s->Sclass); 710: #endif 711: assert(0); 712: #endif 713: } 714: #if SCPP 715: if (tyfunc(s->ty())) 716: { 717: #if SCPP 718: nwc_mustwrite(s); /* must write out function */ 719: #else 720: ; 721: #endif 722: } 723: else if (s->Sdt) /* if initializer for symbol */ 724: outdata(s); // write out data for symbol 725: #if ELFOBJ || MACHOBJ 726: if (config.flags3 & CFG3pic) 727: { 728: elfobj_gotref(s); 729: } 730: #endif 731: #endif 732: break; 733: case OPstring: 734: case OPconst: 735: case OPstrthis: 736: break; 737: case OPsizeof: 738: #if SCPP 739: e->Eoper = OPconst; 740: e->EV.Vlong = type_size(e->EV.sp.Vsym->Stype); 741: #else 742: assert(0); 743: #endif 744: break; 745: 746: #if SCPP 747: case OPstreq: 748: case OPstrpar: 749: case OPstrctor: 750: type_size(e->E1->ET); 751: goto Lop; 752: 753: case OPasm: 754: break; 755: 756: case OPctor: 757: nwc_mustwrite(e->EV.eop.Edtor); 758: case OPdtor: 759: // Don't put 'this' pointers in registers if we need 760: // them for EH stack cleanup. 761: e1 = e->E1; 762: elem_debug(e1); 763: if (e1->Eoper == OPadd) 764: e1 = e1->E1; 765: if (e1->Eoper == OPvar) 766: e1->EV.sp.Vsym->Sflags &= ~GTregcand; 767: goto Lop; 768: case OPmark: 769: break; 770: #endif 771: } 772: #if SCPP 773: type_free(t); 774: #endif 775: } 776: 777: /************************************* 778: * Determine register candidates. 779: */ 780: 781: STATIC void out_regcand_walk(elem *e); 782: 783: void out_regcand(symtab_t *psymtab) 784: { 785: block *b; 786: SYMIDX si; 787: int ifunc; 788: 789: //printf("out_regcand()\n"); 790: ifunc = (tybasic(funcsym_p->ty()) == TYifunc); 791: for (si = 0; si < psymtab->top; si++) 792: { symbol *s = psymtab->tab[si]; 793: 794: symbol_debug(s); 795: //assert(sytab[s->Sclass] & SCSS); // only stack variables 796: s->Ssymnum = si; // Ssymnum trashed by cpp_inlineexpand 797: if (!(s->ty() & mTYvolatile) && 798: #if TX86 799: !(ifunc && (s->Sclass == SCparameter || s->Sclass == SCregpar)) && 800: #endif 801: s->Sclass != SCstatic) 802: s->Sflags |= (GTregcand | SFLunambig); // assume register candidate 803: else 804: s->Sflags &= ~(GTregcand | SFLunambig); 805: } 806: 807: addrparam = FALSE; // haven't taken addr of param yet 808: for (b = startblock; b; b = b->Bnext) 809: { 810: if (b->Belem) 811: out_regcand_walk(b->Belem); 812: 813: // Any assembler blocks make everything ambiguous 814: if (b->BC == BCasm) 815: for (si = 0; si < psymtab->top; si++) 816: psymtab->tab[si]->Sflags &= ~(SFLunambig | GTregcand); 817: } 818: 819: // If we took the address of one parameter, assume we took the 820: // address of all non-register parameters. 821: if (addrparam) // if took address of a parameter 822: { 823: for (si = 0; si < psymtab->top; si++) 824: if (psymtab->tab[si]->Sclass == SCparameter) 825: psymtab->tab[si]->Sflags &= ~(SFLunambig | GTregcand); 826: } 827: 828: } 829: 830: STATIC void out_regcand_walk(elem *e) 831: { symbol *s; 832: 833: while (1) 834: { elem_debug(e); 835: 836: if (EBIN(e)) 837: { if (e->Eoper == OPstreq) 838: { if (e->E1->Eoper == OPvar) 839: { s = e->E1->EV.sp.Vsym; 840: s->Sflags &= ~(SFLunambig | GTregcand); 841: } 842: if (e->E2->Eoper == OPvar) 843: { s = e->E2->EV.sp.Vsym; 844: s->Sflags &= ~(SFLunambig | GTregcand); 845: } 846: } 847: out_regcand_walk(e->E1); 848: e = e->E2; 849: } 850: else if (EUNA(e)) 851: { 852: // Don't put 'this' pointers in registers if we need 853: // them for EH stack cleanup. 854: if (e->Eoper == OPctor) 855: { elem *e1 = e->E1; 856: 857: if (e1->Eoper == OPadd) 858: e1 = e1->E1; 859: if (e1->Eoper == OPvar) 860: e1->EV.sp.Vsym->Sflags &= ~GTregcand; 861: } 862: e = e->E1; 863: } 864: else 865: { if (e->Eoper == OPrelconst) 866: { 867: s = e->EV.sp.Vsym; 868: assert(s); 869: symbol_debug(s); 870: switch (s->Sclass) 871: { 872: case SCregpar: 873: case SCparameter: 874: addrparam = TRUE; // taking addr of param list 875: break; 876: case SCauto: 877: case SCregister: 878: case SCtmp: 879: case SCfastpar: 880: case SCbprel: 881: s->Sflags &= ~(SFLunambig | GTregcand); 882: break; 883: } 884: } 885: else if (e->Eoper == OPvar) 886: { 887: if (e->EV.sp.Voffset) 888: { if (!(e->EV.sp.Voffset == 1 && tybyte(e->Ety))) 889: e->EV.sp.Vsym->Sflags &= ~GTregcand; 890: } 891: } 892: break; 893: } 894: } 895: } 896: 897: /************************** 898: * Optimize function, 899: * generate code for it, 900: * and write it out. 901: */ 902: 903: STATIC void writefunc2(symbol *sfunc); 904: 905: void writefunc(symbol *sfunc) 906: { 907: #if HTOD 908: return; 909: #elif SCPP 910: writefunc2(sfunc); 911: #else 912: cstate.CSpsymtab = &globsym; 913: writefunc2(sfunc); 914: cstate.CSpsymtab = NULL; 915: #endif 916: } 917: 918: STATIC void writefunc2(symbol *sfunc) 919: { 920: block *b; 921: unsigned nsymbols; 922: SYMIDX si; 923: int anyasm; 924: #if OMFOBJ 925: int csegsave; 926: targ_size_t coffsetsave; 927: #endif 928: func_t *f = sfunc->Sfunc; 929: tym_t tyf; 930: 931: //printf("writefunc(%s)\n",sfunc->Sident); 932: debug(debugy && dbg_printf("writefunc(%s)\n",sfunc->Sident)); 933: #if SCPP 934: if (CPP) 935: { 936: 937: // If constructor or destructor, make sure it has been fixed. 938: if (f->Fflags & (Fctor | Fdtor)) 939: assert(errcnt || f->Fflags & Ffixed); 940: 941: // If this function is the 'trigger' to output the vtbl[], do so 942: if (f->Fflags3 & Fvtblgen && !eecontext.EEcompile) 943: { Classsym *stag; 944: 945: stag = (Classsym *) sfunc->Sscope; 946: { 947: enum SC scvtbl; 948: 949: scvtbl = (enum SC) ((config.flags2 & CFG2comdat) ? SCcomdat : SCglobal); 950: n2_genvtbl(stag,scvtbl,1); 951: #if VBTABLES 952: n2_genvbtbl(stag,scvtbl,1); 953: #endif 954: #if TX86 && OMFOBJ 955: if (config.fulltypes == CV4) 956: cv4_struct(stag,2); 957: #endif 958: } 959: } 960: } 961: #endif 962: 963: /* Signify that function has been output */ 964: /* (before inline_do() to prevent infinite recursion!) */ 965: f->Fflags &= ~Fpending; 966: f->Fflags |= Foutput; 967: 968: if ( 969: #if SCPP 970: errcnt || 971: #endif 972: (eecontext.EEcompile && eecontext.EEfunc != sfunc)) 973: return; 974: 975: /* Copy local symbol table onto main one, making sure */ 976: /* that the symbol numbers are adjusted accordingly */ 977: //dbg_printf("f->Flocsym.top = %d\n",f->Flocsym.top); 978: nsymbols = f->Flocsym.top; 979: if (nsymbols > globsym.symmax)
warning C4018: '>' : signed/unsigned mismatch
980: { /* Reallocate globsym.tab[] */ 981: globsym.symmax = nsymbols; 982: globsym.tab = symtab_realloc(globsym.tab, globsym.symmax); 983: } 984: debug(debugy && dbg_printf("appending symbols to symtab...\n")); 985: assert(globsym.top == 0); 986: memcpy(&globsym.tab[0],&f->Flocsym.tab[0],nsymbols * sizeof(symbol *)); 987: globsym.top = nsymbols; 988: 989: assert(startblock == NULL); 990: if (f->Fflags & Finline) // if keep function around 991: { // Generate copy of function 992: block *bf; 993: block **pb; 994: 995: pb = &startblock; 996: for (bf = f->Fstartblock; bf; bf = bf->Bnext) 997: { 998: b = block_calloc(); 999: *pb = b; 1000: pb = &b->Bnext; 1001: 1002: *b = *bf; 1003: assert(!b->Bsucc); 1004: assert(!b->Bpred); 1005: b->Belem = el_copytree(b->Belem); 1006: } 1007: } 1008: else 1009: { startblock = sfunc->Sfunc->Fstartblock; 1010: sfunc->Sfunc->Fstartblock = NULL; 1011: } 1012: assert(startblock); 1013: 1014: /* Do any in-line expansion of function calls inside sfunc */ 1015: #if SCPP 1016: inline_do(sfunc); 1017: #endif 1018: 1019: #if SCPP 1020: /* If function is _STIxxxx, add in the auto destructors */ 1021: #if NEWSTATICDTOR 1022: if (cpp_stidtors && memcmp("__SI",sfunc->Sident,4) == 0) 1023: #else 1024: if (cpp_stidtors && memcmp("_STI",sfunc->Sident,4) == 0) 1025: #endif 1026: { list_t el; 1027: 1028: assert(startblock->Bnext == NULL); 1029: el = cpp_stidtors; 1030: do 1031: { 1032: startblock->Belem = el_combine(startblock->Belem,list_elem(el)); 1033: el = list_next(el); 1034: } while (el); 1035: list_free(&cpp_stidtors,FPNULL); 1036: } 1037: #endif 1038: assert(funcsym_p == NULL); 1039: funcsym_p = sfunc; 1040: tyf = tybasic(sfunc->ty()); 1041: 1042: #if SCPP 1043: out_extdef(sfunc); 1044: #endif 1045: 1046: // TX86 computes parameter offsets in stackoffsets() 1047: //printf("globsym.top = %d\n", globsym.top); 1048: for (si = 0; si < globsym.top; si++) 1049: { symbol *s = globsym.tab[si]; 1050: 1051: symbol_debug(s); 1052: //printf("symbol %d '%s'\n",si,s->Sident); 1053: 1054: type_size(s->Stype); // do any forward template instantiations 1055: 1056: s->Ssymnum = si; // Ssymnum trashed by cpp_inlineexpand 1057: s->Sflags &= ~(SFLunambig | GTregcand); 1058: switch (s->Sclass) 1059: { 1060: #if SCPP 1061: case SCfastpar: 1062: Lfp: 1063: s->Spreg = (tyf == TYmfunc) ? CX : AX; 1064: case SCauto: 1065: case SCregister: 1066: s->Sfl = FLauto; 1067: goto L3; 1068: case SCtmp: 1069: s->Sfl = FLtmp; 1070: goto L3; 1071: case SCbprel: 1072: s->Sfl = FLbprel; 1073: goto L3; 1074: case SCregpar: 1075: case SCparameter: 1076: if (tyf == TYjfunc && si == 0 && 1077: type_jparam(s->Stype)) 1078: { s->Sclass = SCfastpar; // put last parameter into register 1079: goto Lfp; 1080: } 1081: #else 1082: case SCfastpar: 1083: case SCauto: 1084: case SCregister: 1085: s->Sfl = FLauto; 1086: goto L3; 1087: case SCtmp: 1088: s->Sfl = FLtmp; 1089: goto L3; 1090: case SCbprel: 1091: s->Sfl = FLbprel; 1092: goto L3; 1093: case SCregpar: 1094: case SCparameter: 1095: #endif 1096: s->Sfl = FLpara; 1097: if (tyf == TYifunc) 1098: { s->Sflags |= SFLlivexit; 1099: break; 1100: } 1101: L3: 1102: if (!(s->ty() & mTYvolatile)) 1103: s->Sflags |= GTregcand | SFLunambig; // assume register candidate */ 1104: break; 1105: #if PSEUDO_REGS 1106: case SCpseudo: 1107: s->Sfl = FLpseudo; 1108: break; 1109: #endif 1110: case SCstatic: 1111: break; // already taken care of by datadef() 1112: case SCstack: 1113: s->Sfl = FLstack; 1114: break; 1115: default: 1116: #ifdef DEBUG 1117: symbol_print(s); 1118: #endif 1119: assert(0); 1120: } 1121: } 1122: 1123: addrparam = FALSE; // haven't taken addr of param yet 1124: anyasm = 0; 1125: numblks = 0; 1126: for (b = startblock; b; b = b->Bnext) 1127: { 1128: numblks++; // redo count 1129: memset(&b->_BLU,0,sizeof(b->_BLU)); 1130: if (b->Belem) 1131: { outelem(b->Belem); 1132: #if SCPP 1133: if (el_noreturn(b->Belem) && !(config.flags3 & CFG3eh)) 1134: { b->BC = BCexit; 1135: list_free(&b->Bsucc,FPNULL); 1136: } 1137: #endif 1138: #if MARS 1139: if (b->Belem->Eoper == OPhalt) 1140: { b->BC = BCexit; 1141: list_free(&b->Bsucc,FPNULL); 1142: } 1143: #endif 1144: } 1145: if (b->BC == BCasm) 1146: anyasm = 1; 1147: if (sfunc->Sflags & SFLexit && (b->BC == BCret || b->BC == BCretexp)) 1148: { b->BC = BCexit; 1149: list_free(&b->Bsucc,FPNULL); 1150: } 1151: assert(b != b->Bnext); 1152: } 1153: PARSER = 0; 1154: if (eecontext.EEelem) 1155: { unsigned marksi = globsym.top; 1156: 1157: eecontext.EEin++; 1158: outelem(eecontext.EEelem); 1159: eecontext.EEelem = doptelem(eecontext.EEelem,TRUE); 1160: eecontext.EEin--; 1161: eecontext_convs(marksi); 1162: } 1163: maxblks = 3 * numblks; // allow for increase in # of blocks 1164: // If we took the address of one parameter, assume we took the 1165: // address of all non-register parameters. 1166: if (addrparam | anyasm) // if took address of a parameter 1167: { 1168: for (si = 0; si < globsym.top; si++) 1169: if (anyasm || globsym.tab[si]->Sclass == SCparameter) 1170: globsym.tab[si]->Sflags &= ~(SFLunambig | GTregcand); 1171: } 1172: 1173: block_pred(); // compute predecessors to blocks 1174: block_compbcount(); // eliminate unreachable blocks 1175: if (mfoptim) 1176: { OPTIMIZER = 1; 1177: optfunc(); /* optimize function */ 1178: assert(dfo); 1179: OPTIMIZER = 0; 1180: } 1181: else 1182: { 1183: //dbg_printf("blockopt()\n"); 1184: blockopt(0); /* optimize */ 1185: } 1186: 1187: #if SCPP 1188: if (CPP) 1189: { 1190: // Look for any blocks that return nothing. 1191: // Do it after optimization to eliminate any spurious 1192: // messages like the implicit return on { while(1) { ... } } 1193: if (tybasic(funcsym_p->Stype->Tnext->Tty) != TYvoid && 1194: !(funcsym_p->Sfunc->Fflags & (Fctor | Fdtor | Finvariant)) 1195: #if DEBUG_XSYMGEN 1196: /* the internal dataview function is allowed to lie about its return value */ 1197: && compile_state != kDataView 1198: #endif 1199: ) 1200: { char err; 1201: 1202: err = 0; 1203: for (b = startblock; b; b = b->Bnext) 1204: { if (b->BC == BCasm) // no errors if any asm blocks 1205: err |= 2; 1206: else if (b->BC == BCret) 1207: err |= 1; 1208: } 1209: if (err == 1) 1210: func_noreturnvalue(); 1211: } 1212: } 1213: #endif 1214: assert(funcsym_p == sfunc); 1215: if (eecontext.EEcompile != 1) 1216: { 1217: #if TX86 1218: if (symbol_iscomdat(sfunc)) 1219: { 1220: #if OMFOBJ 1221: csegsave = cseg; 1222: coffsetsave = Coffset; 1223: #endif 1224: obj_comdat(sfunc); 1225: } 1226: else 1227: if (config.flags & CFGsegs) // if user set switch for this 1228: { 1229: #if SCPP || TARGET_WINDOS 1230: obj_codeseg(cpp_mangle(funcsym_p),1); 1231: #else 1232: obj_codeseg(funcsym_p->Sident, 1); 1233: #endif 1234: // generate new code segment 1235: } 1236: cod3_align(); // align start of function 1237: #if ELFOBJ || MACHOBJ 1238: elf_func_start(sfunc); 1239: #else 1240: sfunc->Sseg = cseg; // current code seg 1241: #endif 1242: #endif 1243: sfunc->Soffset = Coffset; // offset of start of function 1244: searchfixlist(sfunc); // backpatch any refs to this function 1245: } 1246: 1247: //dbg_printf("codgen()\n"); 1248: #if SCPP 1249: if (!errcnt) 1250: #endif 1251: codgen(); // generate code 1252: //dbg_printf("after codgen for %s Coffset %x\n",sfunc->Sident,Coffset); 1253: blocklist_free(&startblock); 1254: #if SCPP 1255: PARSER = 1; 1256: #endif 1257: #if ELFOBJ || MACHOBJ 1258: elf_func_term(sfunc); 1259: #endif 1260: #if MARS 1261: /* This is to make uplevel references to SCfastpar variables 1262: * from nested functions work. 1263: */ 1264: for (si = 0; si < globsym.top; si++) 1265: { 1266: Symbol *s = globsym.tab[si]; 1267: 1268: switch (s->Sclass) 1269: { case SCfastpar: 1270: s->Sclass = SCauto; 1271: break; 1272: } 1273: } 1274: #endif 1275: if (eecontext.EEcompile == 1) 1276: goto Ldone; 1277: if (sfunc->Sclass == SCglobal) 1278: { 1279: #if OMFOBJ 1280: if (!(config.flags4 & CFG4allcomdat)) 1281: objpubdef(cseg,sfunc,sfunc->Soffset); // make a public definition 1282: #endif 1283: 1284: #if SCPP && _WIN32 1285: char *id; 1286: // Determine which startup code to reference 1287: if (!CPP || !isclassmember(sfunc)) // if not member function 1288: { static char *startup[] = 1289: { "__acrtused","__acrtused_winc","__acrtused_dll", 1290: "__acrtused_con","__wacrtused","__wacrtused_con", 1291: }; 1292: int i; 1293: 1294: id = sfunc->Sident; 1295: switch (id[0]) 1296: { 1297: case 'D': if (strcmp(id,"DllMain")) 1298: break; 1299: if (config.exe == EX_NT) 1300: { i = 2; 1301: goto L2; 1302: } 1303: break; 1304: 1305: case 'm': if (strcmp(id,"main")) 1306: break; 1307: if (config.exe == EX_NT) 1308: i = 3; 1309: else if (config.wflags & WFwindows) 1310: i = 1; 1311: else 1312: i = 0; 1313: goto L2; 1314: 1315: case 'w': if (strcmp(id,"wmain") == 0) 1316: { 1317: if (config.exe == EX_NT) 1318: { i = 5; 1319: goto L2; 1320: } 1321: break; 1322: } 1323: case 'W': if (stricmp(id,"WinMain") == 0) 1324: { 1325: i = 0; 1326: goto L2; 1327: } 1328: if (stricmp(id,"wWinMain") == 0) 1329: { 1330: if (config.exe == EX_NT) 1331: { i = 4; 1332: goto L2; 1333: } 1334: } 1335: break; 1336: 1337: case 'L': 1338: case 'l': if (stricmp(id,"LibMain")) 1339: break; 1340: if (config.exe != EX_NT && config.wflags & WFwindows) 1341: { i = 2; 1342: goto L2; 1343: } 1344: break; 1345: 1346: L2: objextdef(startup[i]); // pull in startup code 1347: break; 1348: } 1349: } 1350: #endif 1351: } 1352: if (config.wflags & WFexpdef && 1353: sfunc->Sclass != SCstatic && 1354: sfunc->Sclass != SCsinline && 1355: !(sfunc->Sclass == SCinline && !(config.flags2 & CFG2comdat)) && 1356: sfunc->ty() & mTYexport) 1357: obj_export(sfunc,Poffset); // export function definition 1358: 1359: if (config.fulltypes) 1360: cv_func(sfunc); // debug info for function 1361: 1362: #if MARS 1363: /* After codgen() and writing debug info for the locals, 1364: * readjust the offsets of all stack variables so they 1365: * are relative to the frame pointer. 1366: * Necessary for nested function access to lexically enclosing frames. 1367: */ 1368: cod3_adjSymOffsets(); 1369: #endif 1370: 1371: #if OMFOBJ 1372: if (symbol_iscomdat(sfunc)) // if generated a COMDAT 1373: obj_setcodeseg(csegsave,coffsetsave); // reset to real code seg 1374: #endif 1375: 1376: /* Check if function is a constructor or destructor, by */ 1377: /* seeing if the function name starts with _STI or _STD */ 1378: { 1379: #if _M_I86 1380: short *p; 1381: 1382: p = (short *) sfunc->Sident; 1383: if (p[0] == 'S_' && (p[1] == 'IT' || p[1] == 'DT')) 1384: #else 1385: char *p; 1386: 1387: p = sfunc->Sident; 1388: if (p[0] == '_' && p[1] == 'S' && p[2] == 'T' && 1389: (p[3] == 'I' || p[3] == 'D')) 1390: #endif 1391: obj_funcptr(sfunc); 1392: } 1393: 1394: Ldone: 1395: funcsym_p = NULL; 1396: 1397: #if SCPP 1398: // Free any added symbols 1399: freesymtab(globsym.tab,nsymbols,globsym.top); 1400: #endif 1401: globsym.top = 0; 1402: 1403: //dbg_printf("done with writefunc()\n"); 1404: #if TX86 1405: util_free(dfo); 1406: #else 1407: MEM_PARF_FREE(dfo); 1408: #endif 1409: dfo = NULL; 1410: } 1411: 1412: /************************* 1413: * Align segment offset. 1414: * Input: 1415: * seg segment to be aligned 1416: * datasize size in bytes of object to be aligned 1417: */ 1418: 1419: void alignOffset(int seg,targ_size_t datasize) 1420: { 1421: targ_size_t alignbytes; 1422: 1423: alignbytes = align(datasize,Offset(seg)) - Offset(seg); 1424: //dbg_printf("seg %d datasize = x%x, Offset(seg) = x%x, alignbytes = x%x\n", 1425: //seg,datasize,Offset(seg),alignbytes); 1426: if (alignbytes) 1427: obj_lidata(seg,Offset(seg),alignbytes); 1428: #if OMFOBJ 1429: Offset(seg) += alignbytes; /* offset of start of data */ 1430: #endif 1431: } 1432: 1433: 1434: /*************************************** 1435: * Write data into read-only data segment. 1436: * Return symbol for it. 1437: */ 1438: 1439: #define ROMAX 32 1440: struct Readonly 1441: { 1442: symbol *sym; 1443: size_t length; 1444: unsigned char p[ROMAX]; 1445: }; 1446: 1447: #define RMAX 16 1448: static Readonly readonly[RMAX]; 1449: static size_t readonly_length; 1450: static size_t readonly_i; 1451: 1452: void out_reset() 1453: { 1454: readonly_length = 0; 1455: readonly_i = 0; 1456: } 1457: 1458: symbol *out_readonly_sym(tym_t ty, void *p, int len) 1459: { 1460: #if 0 1461: printf("out_readonly_sym(ty = x%x)\n", ty); 1462: for (int i = 0; i < len; i++) 1463: printf(" [%d] = %02x\n", i, ((unsigned char*)p)[i]); 1464: #endif 1465: // Look for previous symbol we can reuse 1466: for (int i = 0; i < readonly_length; i++)
warning C4018: '<' : signed/unsigned mismatch
1467: { 1468: Readonly *r = &readonly[i]; 1469: if (r->length == len && memcmp(p, r->p, len) == 0)
warning C6385: Invalid data: accessing 'argument 2', the readable size is '32' bytes, but '355' bytes might be read: Lines: 1466, 1468, 1469
1470: return r->sym; 1471: } 1472: 1473: symbol *s; 1474: 1475: #if ELFOBJ 1476: /* MACHOBJ can't go here, because the const data segment goes into 1477: * the _TEXT segment, and one cannot have a fixup from _TEXT to _TEXT. 1478: */ 1479: s = elf_sym_cdata(ty, (char *)p, len); 1480: #else 1481: unsigned sz = tysize(ty); 1482: 1483: alignOffset(DATA, sz); 1484: s = symboldata(Doffset,ty | mTYconst); 1485: obj_write_bytes(SegData[DATA], len, p); 1486: //printf("s->Sseg = %d:x%x\n", s->Sseg, s->Soffset); 1487: #endif 1488: if (len <= ROMAX) 1489: { Readonly *r; 1490: 1491: if (readonly_length < RMAX) 1492: { 1493: r = &readonly[readonly_length]; 1494: readonly_length++; 1495: } 1496: else 1497: { r = &readonly[readonly_i]; 1498: readonly_i++; 1499: if (readonly_i >= RMAX) 1500: readonly_i = 0; 1501: } 1502: r->length = len; 1503: r->sym = s; 1504: memcpy(r->p, p, len); 1505: } 1506: return s; 1507: } 1508: 1509: void Srcpos::print(const char *func) 1510: { 1511: printf("%s(", func); 1512: #if MARS 1513: printf("Sfilename = %s", Sfilename ? Sfilename : "null"); 1514: #else 1515: Sfile *sf = Sfilptr ? *Sfilptr : NULL; 1516: printf("Sfilptr = %p (filename = %s)", sf, sf ? sf->SFname : "null"); 1517: #endif 1518: printf(", Slinnum = %u", Slinnum); 1519: #if SOURCE_OFFSETS 1520: printf(", Sfiloff = %d", Sfiloff); 1521: #endif 1522: printf(")\n"); 1523: } 1524: 1525: 1526: #endif /* !SPP */ 1527: 1528: