1: 
  2: // Compiler implementation of the D programming language
  3: // Copyright (c) 1999-2011 by Digital Mars
  4: // All Rights Reserved
  5: // written by Walter Bright
  6: // http://www.digitalmars.com
  7: // License for redistribution is by either the Artistic License
  8: // in artistic.txt, or the GNU General Public License in gnu.txt.
  9: // See the included readme.txt for details.
 10: 
 11: #include        <stdio.h>
 12: #include        <string.h>
 13: #include        <stddef.h>
 14: 
 15: #include        "mars.h"
 16: 
 17: #include        "cc.h"
 18: #include        "global.h"
 19: #include        "oper.h"
 20: #include        "code.h"
 21: #include        "type.h"
 22: #include        "dt.h"
 23: #include        "cgcv.h"
 24: 
 25: static char __file__[] = __FILE__;      /* for tassert.h                */
 26: #include        "tassert.h"
 27: 
 28: extern void ph_init();
 29: 
 30: extern Global global;
 31: extern int REALSIZE;
 32: 
 33: Config config;
 34: Configv configv;
 35: 
 36: struct Environment;
 37: 
 38: /**************************************
 39:  * Initialize config variables.
 40:  */
 41: 
 42: void out_config_init()
 43: {
 44:     //printf("out_config_init()\n");
 45:     Param *params = &global.params;
 46: 
 47:     if (!config.target_cpu)
 48:     {   config.target_cpu = TARGET_PentiumPro;
 49:         config.target_scheduler = config.target_cpu;
 50:     }
 51:     config.fulltypes = CVNONE;
 52:     config.inline8087 = 1;
 53:     config.memmodel = 0;
 54:     config.flags |= CFGuchar;   // make sure TYchar is unsigned
 55: #if TARGET_WINDOS
 56:     if (params->is64bit)
 57:         config.exe = EX_WIN64;
 58:     else
 59:         config.exe = EX_NT;
 60: 
 61:     // Win32 eh
 62:     config.flags2 |= CFG2seh;
 63: 
 64:     if (params->run)
 65:         config.wflags |= WFexe;         // EXE file only optimizations
 66:     else if (params->link && !global.params.deffile)
 67:         config.wflags |= WFexe;         // EXE file only optimizations
 68:     else if (params->exefile)           // if writing out EXE file
 69:     {   size_t len = strlen(params->exefile);
 70:         if (len >= 4 && stricmp(params->exefile + len - 3, "exe") == 0)
warning C4996: 'stricmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _stricmp. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(246) : see declaration of 'stricmp'
71: config.wflags |= WFexe; 72: } 73: config.flags4 |= CFG4underscore; 74: #endif 75: #if TARGET_LINUX 76: if (params->is64bit) 77: config.exe = EX_LINUX64; 78: else 79: config.exe = EX_LINUX; 80: config.flags |= CFGnoebp; 81: config.flags |= CFGalwaysframe; 82: if (params->pic) 83: config.flags3 |= CFG3pic; 84: #endif 85: #if TARGET_OSX 86: if (params->is64bit) 87: config.exe = EX_OSX64; 88: else 89: config.exe = EX_OSX; 90: config.flags |= CFGnoebp; 91: config.flags |= CFGalwaysframe; 92: if (params->pic) 93: config.flags3 |= CFG3pic; 94: #endif 95: #if TARGET_FREEBSD 96: if (params->is64bit) 97: config.exe = EX_FREEBSD64; 98: else 99: config.exe = EX_FREEBSD; 100: config.flags |= CFGnoebp; 101: config.flags |= CFGalwaysframe; 102: if (params->pic) 103: config.flags3 |= CFG3pic; 104: #endif 105: #if TARGET_OPENBSD 106: if (params->is64bit) 107: config.exe = EX_OPENBSD64; 108: else 109: config.exe = EX_OPENBSD; 110: config.flags |= CFGnoebp; 111: config.flags |= CFGalwaysframe; 112: if (params->pic) 113: config.flags3 |= CFG3pic; 114: #endif 115: #if TARGET_SOLARIS 116: if (params->is64bit) 117: config.exe = EX_SOLARIS64; 118: else 119: config.exe = EX_SOLARIS; 120: config.flags |= CFGnoebp; 121: config.flags |= CFGalwaysframe; 122: if (params->pic) 123: config.flags3 |= CFG3pic; 124: #endif 125: config.flags2 |= CFG2nodeflib; // no default library 126: config.flags3 |= CFG3eseqds; 127: #if 0 128: if (env->getEEcontext()->EEcompile != 2) 129: config.flags4 |= CFG4allcomdat; 130: if (env->nochecks()) 131: config.flags4 |= CFG4nochecks; // no runtime checking 132: #elif TARGET_OSX 133: #else 134: config.flags4 |= CFG4allcomdat; 135: #endif 136: if (params->trace) 137: config.flags |= CFGtrace; // turn on profiler 138: if (params->nofloat) 139: config.flags3 |= CFG3wkfloat; 140: 141: configv.verbose = params->verbose; 142: 143: if (params->optimize) 144: go_flag((char *)"-o"); 145: 146: if (params->symdebug) 147: { 148: #if ELFOBJ || MACHOBJ 149: configv.addlinenumbers = 1; 150: config.fulltypes = (params->symdebug == 1) ? CVDWARF_D : CVDWARF_C; 151: #endif 152: #if OMFOBJ 153: configv.addlinenumbers = 1; 154: config.fulltypes = CV4; 155: #endif 156: if (!params->optimize) 157: config.flags |= CFGalwaysframe; 158: } 159: else 160: { 161: configv.addlinenumbers = 0; 162: config.fulltypes = CVNONE; 163: //config.flags &= ~CFGalwaysframe; 164: } 165: 166: if (params->is64bit) 167: { 168: util_set64(); 169: cod3_set64(); 170: } 171: else 172: { 173: util_set32(); 174: cod3_set32(); 175: } 176: 177: rtlsym_init(); 178: 179: #ifdef DEBUG 180: debugb = params->debugb; 181: debugc = params->debugc; 182: debugf = params->debugf; 183: debugr = params->debugr; 184: debugw = params->debugw; 185: debugx = params->debugx; 186: debugy = params->debugy; 187: #endif 188: } 189: 190: /******************************* 191: * Redo tables from 8086/286 to ILP32 192: */ 193: 194: void util_set32() 195: { 196: _tyrelax[TYenum] = TYlong; 197: _tyrelax[TYint] = TYlong; 198: _tyrelax[TYuint] = TYlong; 199: 200: tyequiv[TYint] = TYlong; 201: tyequiv[TYuint] = TYulong; 202: 203: for (int i = 0; i < 0x100; i += 0x40) 204: { tysize[TYenum + i] = LONGSIZE; 205: tysize[TYint + i] = LONGSIZE; 206: tysize[TYuint + i] = LONGSIZE; 207: tysize[TYjhandle + i] = LONGSIZE; 208: tysize[TYnptr + i] = LONGSIZE; 209: tysize[TYsptr + i] = LONGSIZE; 210: tysize[TYcptr + i] = LONGSIZE; 211: tysize[TYnref + i] = LONGSIZE; 212: tysize[TYfptr + i] = 6; 213: tysize[TYvptr + i] = 6; 214: tysize[TYfref + i] = 6; 215: } 216: 217: for (int i = 0; i < 0x100; i += 0x40) 218: { tyalignsize[TYenum + i] = LONGSIZE; 219: tyalignsize[TYint + i] = LONGSIZE; 220: tyalignsize[TYuint + i] = LONGSIZE; 221: tyalignsize[TYnullptr + i] = LONGSIZE; 222: tyalignsize[TYnptr + i] = LONGSIZE; 223: tyalignsize[TYsptr + i] = LONGSIZE; 224: tyalignsize[TYcptr + i] = LONGSIZE; 225: tyalignsize[TYnref + i] = LONGSIZE; 226: } 227: } 228: 229: /******************************* 230: * Redo tables from 8086/286 to LP64. 231: */ 232: 233: void util_set64() 234: { 235: _tyrelax[TYenum] = TYlong; 236: _tyrelax[TYint] = TYlong; 237: _tyrelax[TYuint] = TYlong; 238: 239: tyequiv[TYint] = TYlong; 240: tyequiv[TYuint] = TYulong; 241: 242: for (int i = 0; i < 0x100; i += 0x40) 243: { tysize[TYenum + i] = LONGSIZE; 244: tysize[TYint + i] = LONGSIZE; 245: tysize[TYuint + i] = LONGSIZE; 246: tysize[TYnptr + i] = 8; 247: tysize[TYsptr + i] = 8; 248: tysize[TYcptr + i] = 8; 249: tysize[TYnref + i] = 8; 250: tysize[TYfptr + i] = 10; // NOTE: There are codgen test that check 251: tysize[TYvptr + i] = 10; // tysize[x] == tysize[TYfptr] so don't set 252: tysize[TYfref + i] = 10; // tysize[TYfptr] to tysize[TYnptr] 253: tysize[TYldouble + i] = REALSIZE; 254: tysize[TYildouble + i] = REALSIZE; 255: tysize[TYcldouble + i] = 2 * REALSIZE; 256: 257: tyalignsize[TYenum + i] = LONGSIZE; 258: tyalignsize[TYint + i] = LONGSIZE; 259: tyalignsize[TYuint + i] = LONGSIZE; 260: tyalignsize[TYnullptr + i] = 8; 261: tyalignsize[TYnptr + i] = 8; 262: tyalignsize[TYsptr + i] = 8; 263: tyalignsize[TYcptr + i] = 8; 264: tyalignsize[TYnref + i] = 8; 265: tyalignsize[TYfptr + i] = 8; 266: tyalignsize[TYvptr + i] = 8; 267: tyalignsize[TYfref + i] = 8; 268: #if TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS 269: tyalignsize[TYldouble + i] = 16; 270: tyalignsize[TYildouble + i] = 16; 271: tyalignsize[TYcldouble + i] = 16; 272: #else 273: assert(0); 274: #endif 275: tytab[TYjfunc + i] &= ~TYFLpascal; // set so caller cleans the stack (as in C) 276: } 277: 278: TYptrdiff = TYllong; 279: TYsize = TYullong; 280: TYsize_t = TYullong; 281: } 282: 283: /*********************************** 284: * Return aligned 'offset' if it is of size 'size'. 285: */ 286: 287: targ_size_t align(targ_size_t size, targ_size_t offset) 288: { 289: switch (size) 290: { 291: case 1: 292: break; 293: case 2: 294: case 4: 295: case 8: 296: offset = (offset + size - 1) & ~(size - 1); 297: break; 298: default: 299: if (size >= 16) 300: offset = (offset + 15) & ~15; 301: else 302: offset = (offset + REGSIZE - 1) & ~(REGSIZE - 1); 303: break; 304: } 305: return offset; 306: } 307: 308: /******************************* 309: * Get size of ty 310: */ 311: 312: targ_size_t size(tym_t ty) 313: { 314: int sz = (tybasic(ty) == TYvoid) ? 1 : tysize(ty); 315: #ifdef DEBUG 316: if (sz == -1) 317: WRTYxx(ty); 318: #endif 319: assert(sz!= -1); 320: return sz; 321: } 322: 323: /******************************* 324: * Replace (e) with ((stmp = e),stmp) 325: */ 326: 327: elem *exp2_copytotemp(elem *e) 328: { 329: //printf("exp2_copytotemp()\n"); 330: elem_debug(e); 331: Symbol *stmp = symbol_genauto(e); 332: elem *eeq = el_bin(OPeq,e->Ety,el_var(stmp),e); 333: elem *er = el_bin(OPcomma,e->Ety,eeq,el_var(stmp)); 334: if (tybasic(e->Ety) == TYstruct || tybasic(e->Ety) == TYarray) 335: { 336: eeq->Eoper = OPstreq; 337: eeq->ET = e->ET; 338: eeq->E1->ET = e->ET; 339: er->ET = e->ET; 340: er->E2->ET = e->ET; 341: } 342: return er; 343: } 344: 345: /**************************** 346: * Generate symbol of type ty at DATA:offset 347: */ 348: 349: symbol *symboldata(targ_size_t offset,tym_t ty) 350: { 351: symbol *s = symbol_generate(SClocstat, type_fake(ty)); 352: s->Sfl = FLdata; 353: s->Soffset = offset; 354: s->Sseg = DATA; 355: symbol_keep(s); // keep around 356: return s; 357: } 358: 359: /************************************ 360: * Add symbol to slist. 361: */ 362: 363: static list_t slist; 364: 365: void slist_add(Symbol *s) 366: { 367: list_prepend(&slist,s); 368: } 369: 370: /************************************* 371: */ 372: 373: void slist_reset() 374: { 375: //printf("slist_reset()\n"); 376: for (list_t sl = slist; sl; sl = list_next(sl)) 377: { Symbol *s = list_symbol(sl); 378: 379: #if MACHOBJ 380: s->Soffset = 0; 381: #endif 382: s->Sxtrnnum = 0; 383: s->Stypidx = 0; 384: s->Sflags &= ~(STRoutdef | SFLweak); 385: if (s->Sclass == SCglobal || s->Sclass == SCcomdat || 386: s->Sfl == FLudata || s->Sclass == SCstatic) 387: { s->Sclass = SCextern; 388: s->Sfl = FLextern; 389: } 390: } 391: } 392: 393: 394: /************************************** 395: */ 396: 397: void backend_init() 398: { 399: ph_init(); 400: block_init(); 401: type_init(); 402: 403: fregsaved = I64 ? mBP | mBX | mR12 | mR13 | mR14 | mR15 | mES : mES | mBP | mBX | mSI | mDI; 404: } 405: 406: void backend_term() 407: { 408: } 409: