1 /** 2 * Compiler implementation of the 3 * $(LINK2 http://www.dlang.org, D programming language). 4 * 5 * Copyright: Copyright (C) 1985-1998 by Symantec 6 * Copyright (C) 2000-2020 by The D Language Foundation, All Rights Reserved 7 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 8 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 9 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/code.d, backend/_code.d) 10 */ 11 12 module dmd.backend.code; 13 14 // Online documentation: https://dlang.org/phobos/dmd_backend_code.html 15 16 import dmd.backend.barray; 17 import dmd.backend.cc; 18 import dmd.backend.cdef; 19 import dmd.backend.code_x86; 20 import dmd.backend.codebuilder : CodeBuilder; 21 import dmd.backend.el : elem; 22 import dmd.backend.oper : OPMAX; 23 import dmd.backend.outbuf; 24 import dmd.backend.ty; 25 import dmd.backend.type; 26 27 extern (C++): 28 29 nothrow: 30 31 alias segidx_t = int; // index into SegData[] 32 33 /********************************** 34 * Code data type 35 */ 36 37 struct _Declaration; 38 struct _LabelDsymbol; 39 40 union evc 41 { 42 targ_int Vint; /// also used for tmp numbers (FLtmp) 43 targ_uns Vuns; 44 targ_long Vlong; 45 targ_llong Vllong; 46 targ_size_t Vsize_t; 47 struct 48 { 49 targ_size_t Vpointer; 50 int Vseg; /// segment the pointer is in 51 } 52 Srcpos Vsrcpos; /// source position for OPlinnum 53 elem *Vtor; /// OPctor/OPdtor elem 54 block *Vswitch; /// when FLswitch and we have a switch table 55 code *Vcode; /// when code is target of a jump (FLcode) 56 block *Vblock; /// when block " (FLblock) 57 struct 58 { 59 targ_size_t Voffset; /// offset from symbol 60 Symbol *Vsym; /// pointer to symbol table (FLfunc,FLextern) 61 } 62 63 struct 64 { 65 targ_size_t Vdoffset; /// offset from symbol 66 _Declaration *Vdsym; /// pointer to D symbol table 67 } 68 69 struct 70 { 71 targ_size_t Vloffset; /// offset from symbol 72 _LabelDsymbol *Vlsym; /// pointer to D Label 73 } 74 75 struct 76 { 77 size_t len; 78 char *bytes; 79 } // asm node (FLasm) 80 } 81 82 /********************** PUBLIC FUNCTIONS *******************/ 83 84 code *code_calloc(); 85 void code_free(code *); 86 void code_term(); 87 88 code *code_next(code *c) { return c.next; } 89 90 code *code_chunk_alloc(); 91 extern __gshared code *code_list; 92 93 code *code_malloc() 94 { 95 //printf("code %d\n", sizeof(code)); 96 code *c = code_list ? code_list : code_chunk_alloc(); 97 code_list = code_next(c); 98 //printf("code_malloc: %p\n",c); 99 return c; 100 } 101 102 extern __gshared con_t regcon; 103 104 /************************************ 105 * Register save state. 106 */ 107 108 struct REGSAVE 109 { 110 targ_size_t off; // offset on stack 111 uint top; // high water mark 112 uint idx; // current number in use 113 int alignment; // 8 or 16 114 115 nothrow: 116 void reset() { off = 0; top = 0; idx = 0; alignment = _tysize[TYnptr]/*REGSIZE*/; } 117 void save(ref CodeBuilder cdb, reg_t reg, uint *pidx) { REGSAVE_save(this, cdb, reg, *pidx); } 118 void restore(ref CodeBuilder cdb, reg_t reg, uint idx) { REGSAVE_restore(this, cdb, reg, idx); } 119 } 120 121 void REGSAVE_save(ref REGSAVE regsave, ref CodeBuilder cdb, reg_t reg, out uint idx); 122 void REGSAVE_restore(const ref REGSAVE regsave, ref CodeBuilder cdb, reg_t reg, uint idx); 123 124 extern __gshared REGSAVE regsave; 125 126 /************************************ 127 * Local sections on the stack 128 */ 129 struct LocalSection 130 { 131 targ_size_t offset; // offset of section from frame pointer 132 targ_size_t size; // size of section 133 int alignment; // alignment size 134 135 nothrow: 136 void init() // initialize 137 { offset = 0; 138 size = 0; 139 alignment = 0; 140 } 141 } 142 143 /******************************* 144 * As we generate code, collect information about 145 * what parts of NT exception handling we need. 146 */ 147 148 extern __gshared uint usednteh; 149 150 enum 151 { 152 NTEH_try = 1, // used _try statement 153 NTEH_except = 2, // used _except statement 154 NTEHexcspec = 4, // had C++ exception specification 155 NTEHcleanup = 8, // destructors need to be called 156 NTEHtry = 0x10, // had C++ try statement 157 NTEHcpp = (NTEHexcspec | NTEHcleanup | NTEHtry), 158 EHcleanup = 0x20, // has destructors in the 'code' instructions 159 EHtry = 0x40, // has BCtry or BC_try blocks 160 NTEHjmonitor = 0x80, // uses Mars monitor 161 NTEHpassthru = 0x100, 162 } 163 164 /********************** Code Generator State ***************/ 165 166 struct CGstate 167 { 168 int stackclean; // if != 0, then clean the stack after function call 169 170 LocalSection funcarg; // where function arguments are placed 171 targ_size_t funcargtos; // current high water level of arguments being moved onto 172 // the funcarg section. It is filled from top to bottom, 173 // as if they were 'pushed' on the stack. 174 // Special case: if funcargtos==~0, then no 175 // arguments are there. 176 bool accessedTLS; // set if accessed Thread Local Storage (TLS) 177 } 178 179 // nteh.c 180 void nteh_prolog(ref CodeBuilder cdb); 181 void nteh_epilog(ref CodeBuilder cdb); 182 void nteh_usevars(); 183 void nteh_filltables(); 184 void nteh_gentables(Symbol *sfunc); 185 void nteh_setsp(ref CodeBuilder cdb, opcode_t op); 186 void nteh_filter(ref CodeBuilder cdb, block *b); 187 void nteh_framehandler(Symbol *, Symbol *); 188 void nteh_gensindex(ref CodeBuilder, int); 189 enum GENSINDEXSIZE = 7; 190 void nteh_monitor_prolog(ref CodeBuilder cdb,Symbol *shandle); 191 void nteh_monitor_epilog(ref CodeBuilder cdb,regm_t retregs); 192 code *nteh_patchindex(code* c, int index); 193 void nteh_unwind(ref CodeBuilder cdb,regm_t retregs,uint index); 194 195 // cgen.c 196 code *code_last(code *c); 197 void code_orflag(code *c,uint flag); 198 void code_orrex(code *c,uint rex); 199 code *setOpcode(code *c, code *cs, opcode_t op); 200 code *cat(code *c1, code *c2); 201 code *gen (code *c , code *cs ); 202 code *gen1 (code *c , opcode_t op ); 203 code *gen2 (code *c , opcode_t op , uint rm ); 204 code *gen2sib(code *c,opcode_t op,uint rm,uint sib); 205 code *genc2 (code *c , opcode_t op , uint rm , targ_size_t EV2 ); 206 code *genc (code *c , opcode_t op , uint rm , uint FL1 , targ_size_t EV1 , uint FL2 , targ_size_t EV2 ); 207 code *genlinnum(code *,Srcpos); 208 void cgen_prelinnum(code **pc,Srcpos srcpos); 209 code *gennop(code *); 210 void gencodelem(ref CodeBuilder cdb,elem *e,regm_t *pretregs,bool constflag); 211 bool reghasvalue (regm_t regm , targ_size_t value , reg_t *preg ); 212 void regwithvalue(ref CodeBuilder cdb, regm_t regm, targ_size_t value, reg_t *preg, regm_t flags); 213 214 // cgreg.c 215 void cgreg_init(); 216 void cgreg_term(); 217 void cgreg_reset(); 218 void cgreg_used(uint bi,regm_t used); 219 void cgreg_spillreg_prolog(block *b,Symbol *s,ref CodeBuilder cdbstore,ref CodeBuilder cdbload); 220 void cgreg_spillreg_epilog(block *b,Symbol *s,ref CodeBuilder cdbstore,ref CodeBuilder cdbload); 221 int cgreg_assign(Symbol *retsym); 222 void cgreg_unregister(regm_t conflict); 223 224 // cgsched.c 225 void cgsched_block(block *b); 226 227 alias IDXSTR = uint; 228 alias IDXSEC = uint; 229 alias IDXSYM = uint; 230 231 struct seg_data 232 { 233 segidx_t SDseg; // index into SegData[] 234 targ_size_t SDoffset; // starting offset for data 235 int SDalignment; // power of 2 236 237 static if (TARGET_WINDOS) 238 { 239 bool isfarseg; 240 int segidx; // internal object file segment number 241 int lnameidx; // lname idx of segment name 242 int classidx; // lname idx of class name 243 uint attr; // segment attribute 244 targ_size_t origsize; // original size 245 int seek; // seek position in output file 246 void* ledata; // (Ledatarec) current one we're filling in 247 } 248 249 //ELFOBJ || MACHOBJ 250 IDXSEC SDshtidx; // section header table index 251 Outbuffer *SDbuf; // buffer to hold data 252 Outbuffer *SDrel; // buffer to hold relocation info 253 254 //ELFOBJ 255 IDXSYM SDsymidx; // each section is in the symbol table 256 IDXSEC SDrelidx; // section header for relocation info 257 targ_size_t SDrelmaxoff; // maximum offset encountered 258 int SDrelindex; // maximum offset encountered 259 int SDrelcnt; // number of relocations added 260 IDXSEC SDshtidxout; // final section header table index 261 Symbol *SDsym; // if !=NULL, comdat symbol 262 segidx_t SDassocseg; // for COMDATs, if !=0, this is the "associated" segment 263 264 uint SDaranges_offset; // if !=0, offset in .debug_aranges 265 266 Barray!(linnum_data) SDlinnum_data; // array of line number / offset data 267 268 nothrow: 269 version (Windows) 270 int isCode() { return seg_data_isCode(this); } 271 version (OSX) 272 int isCode() { return seg_data_isCode(this); } 273 } 274 275 extern int seg_data_isCode(const ref seg_data sd) @system; 276 277 struct linnum_data 278 { 279 const(char) *filename; 280 uint filenumber; // corresponding file number for DW_LNS_set_file 281 282 Barray!(LinOff) linoff; // line numbers and offsets 283 } 284 285 struct LinOff 286 { 287 uint lineNumber; 288 uint offset; 289 } 290 291 extern __gshared Rarray!(seg_data*) SegData; 292 293 ref targ_size_t Offset(int seg) { return SegData[seg].SDoffset; } 294 ref targ_size_t Doffset() { return Offset(DATA); } 295 ref targ_size_t CDoffset() { return Offset(CDATA); } 296 297 /**************************************************/ 298 299 /* Allocate registers to function parameters 300 */ 301 302 struct FuncParamRegs 303 { 304 //this(tym_t tyf); 305 static FuncParamRegs create(tym_t tyf) { return FuncParamRegs_create(tyf); } 306 307 int alloc(type *t, tym_t ty, ubyte *reg1, ubyte *reg2) 308 { return FuncParamRegs_alloc(this, t, ty, reg1, reg2); } 309 310 private: 311 public: // for the moment 312 tym_t tyf; // type of function 313 int i; // ith parameter 314 int regcnt; // how many general purpose registers are allocated 315 int xmmcnt; // how many fp registers are allocated 316 uint numintegerregs; // number of gp registers that can be allocated 317 uint numfloatregs; // number of fp registers that can be allocated 318 const(ubyte)* argregs; // map to gp register 319 const(ubyte)* floatregs; // map to fp register 320 } 321 322 extern FuncParamRegs FuncParamRegs_create(tym_t tyf) @system; 323 extern int FuncParamRegs_alloc(ref FuncParamRegs fpr, type *t, tym_t ty, reg_t *preg1, reg_t *preg2) @system; 324 325 extern __gshared 326 { 327 regm_t msavereg,mfuncreg,allregs; 328 329 int BPRM; 330 regm_t FLOATREGS; 331 regm_t FLOATREGS2; 332 regm_t DOUBLEREGS; 333 //const char datafl[],stackfl[],segfl[],flinsymtab[]; 334 char needframe,gotref; 335 targ_size_t localsize, 336 funcoffset, 337 framehandleroffset; 338 segidx_t cseg; 339 int STACKALIGN; 340 int TARGET_STACKALIGN; 341 LocalSection Para; 342 LocalSection Fast; 343 LocalSection Auto; 344 LocalSection EEStack; 345 LocalSection Alloca; 346 } 347 348 /* cgcod.c */ 349 extern __gshared int pass; 350 enum 351 { 352 PASSinitial, // initial pass through code generator 353 PASSreg, // register assignment pass 354 PASSfinal, // final pass 355 } 356 357 extern __gshared int dfoidx; 358 extern __gshared bool floatreg; 359 extern __gshared targ_size_t prolog_allocoffset; 360 extern __gshared targ_size_t startoffset; 361 extern __gshared targ_size_t retoffset; 362 extern __gshared targ_size_t retsize; 363 extern __gshared uint stackpush; 364 extern __gshared int stackchanged; 365 extern __gshared int refparam; 366 extern __gshared int reflocal; 367 extern __gshared bool anyiasm; 368 extern __gshared char calledafunc; 369 extern __gshared bool calledFinally; 370 371 void stackoffsets(int); 372 void codgen(Symbol *); 373 374 debug 375 { 376 reg_t findreg(regm_t regm , int line, const(char)* file); 377 extern (D) reg_t findreg(regm_t regm , int line = __LINE__, string file = __FILE__) 378 { return findreg(regm, line, file.ptr); } 379 } 380 else 381 { 382 reg_t findreg(regm_t regm); 383 } 384 385 reg_t findregmsw(uint regm) { return findreg(regm & mMSW); } 386 reg_t findreglsw(uint regm) { return findreg(regm & (mLSW | mBP)); } 387 void freenode(elem *e); 388 int isregvar(elem *e, regm_t *pregm, reg_t *preg); 389 void allocreg(ref CodeBuilder cdb, regm_t *pretregs, reg_t *preg, tym_t tym, int line, const(char)* file); 390 void allocreg(ref CodeBuilder cdb, regm_t *pretregs, reg_t *preg, tym_t tym); 391 reg_t allocScratchReg(ref CodeBuilder cdb, regm_t regm); 392 regm_t lpadregs(); 393 void useregs (regm_t regm); 394 void getregs(ref CodeBuilder cdb, regm_t r); 395 void getregsNoSave(regm_t r); 396 void getregs_imm(ref CodeBuilder cdb, regm_t r); 397 void cse_flush(ref CodeBuilder, int); 398 bool cse_simple(code *c, elem *e); 399 bool cssave (elem *e , regm_t regm , uint opsflag ); 400 bool evalinregister(elem *e); 401 regm_t getscratch(); 402 void codelem(ref CodeBuilder cdb, elem *e, regm_t *pretregs, uint constflag); 403 void scodelem(ref CodeBuilder cdb, elem *e, regm_t *pretregs, regm_t keepmsk, bool constflag); 404 const(char)* regm_str(regm_t rm); 405 int numbitsset(regm_t); 406 407 /* cdxxx.c: functions that go into cdxxx[] table */ 408 void cdabs(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 409 void cdaddass(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 410 void cdasm(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 411 void cdbscan(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 412 void cdbswap(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 413 void cdbt(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 414 void cdbtst(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 415 void cdbyteint(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 416 void cdcmp(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 417 void cdcmpxchg(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 418 void cdcnvt(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 419 void cdcom(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 420 void cdcomma(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 421 void cdcond(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 422 void cdconvt87(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 423 void cdctor(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 424 void cddctor(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 425 void cdddtor(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 426 void cddtor(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 427 void cdeq(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 428 void cderr(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 429 void cdfar16(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 430 void cdframeptr(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 431 void cdfunc(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 432 void cdgot(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 433 void cdhalt(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 434 void cdind(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 435 void cdinfo(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 436 void cdlngsht(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 437 void cdloglog(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 438 void cdmark(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 439 void cdmemcmp(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 440 void cdmemcpy(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 441 void cdmemset(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 442 void cdmsw(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 443 void cdmul(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 444 void cddiv(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 445 void cdmulass(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 446 void cddivass(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 447 void cdneg(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 448 void cdnot(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 449 void cdorth(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 450 void cdpair(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 451 void cdpopcnt(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 452 void cdport(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 453 void cdpost(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 454 void cdprefetch(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 455 void cdrelconst(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 456 void cdrndtol(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 457 void cdscale(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 458 void cdsetjmp(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 459 void cdshass(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 460 void cdshift(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 461 void cdshtlng(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 462 void cdstrcmp(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 463 void cdstrcpy(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 464 void cdstreq(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 465 void cdstrlen(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 466 void cdstrthis(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 467 void cdtoprec(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 468 void cdvecfill(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 469 void cdvecsto(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 470 void cdvector(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 471 void cdvoid(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 472 void loaddata(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 473 474 /* cod1.c */ 475 extern __gshared int clib_inited; 476 477 bool regParamInPreg(Symbol* s); 478 int isscaledindex(elem *); 479 int ssindex(int op,targ_uns product); 480 void buildEA(code *c,int base,int index,int scale,targ_size_t disp); 481 uint buildModregrm(int mod, int reg, int rm); 482 void andregcon (con_t *pregconsave); 483 void genEEcode(); 484 void docommas(ref CodeBuilder cdb,elem **pe); 485 uint gensaverestore(regm_t, ref CodeBuilder cdbsave, ref CodeBuilder cdbrestore); 486 void genstackclean(ref CodeBuilder cdb,uint numpara,regm_t keepmsk); 487 void logexp(ref CodeBuilder cdb, elem *e, int jcond, uint fltarg, code *targ); 488 uint getaddrmode(regm_t idxregs); 489 void setaddrmode(code *c, regm_t idxregs); 490 void fltregs(ref CodeBuilder cdb, code *pcs, tym_t tym); 491 void tstresult(ref CodeBuilder cdb, regm_t regm, tym_t tym, uint saveflag); 492 void fixresult(ref CodeBuilder cdb, elem *e, regm_t retregs, regm_t *pretregs); 493 void callclib(ref CodeBuilder cdb, elem *e, uint clib, regm_t *pretregs, regm_t keepmask); 494 void pushParams(ref CodeBuilder cdb,elem *, uint, tym_t tyf); 495 void offsetinreg(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 496 void argtypes(type* t, ref type* arg1type, ref type* arg2type); 497 498 /* cod2.c */ 499 bool movOnly(const elem *e); 500 regm_t idxregm(const code *c); 501 void opdouble(ref CodeBuilder cdb, elem *e, regm_t *pretregs, uint clib); 502 void WRcodlst(code *c); 503 void getoffset(ref CodeBuilder cdb, elem *e, reg_t reg); 504 505 /* cod3.c */ 506 507 int cod3_EA(code *c); 508 regm_t cod3_useBP(); 509 void cod3_initregs(); 510 void cod3_setdefault(); 511 void cod3_set32(); 512 void cod3_set64(); 513 void cod3_align_bytes(int seg, size_t nbytes); 514 void cod3_align(int seg); 515 void cod3_buildmodulector(Outbuffer* buf, int codeOffset, int refOffset); 516 void cod3_stackadj(ref CodeBuilder cdb, int nbytes); 517 void cod3_stackalign(ref CodeBuilder cdb, int nbytes); 518 regm_t regmask(tym_t tym, tym_t tyf); 519 void cgreg_dst_regs(reg_t* dst_integer_reg, reg_t* dst_float_reg); 520 void cgreg_set_priorities(tym_t ty, const(reg_t)** pseq, const(reg_t)** pseqmsw); 521 void outblkexitcode(ref CodeBuilder cdb, block *bl, ref int anyspill, const(char)* sflsave, Symbol** retsym, const regm_t mfuncregsave ); 522 void outjmptab(block *b); 523 void outswitab(block *b); 524 int jmpopcode(elem *e); 525 void cod3_ptrchk(ref CodeBuilder cdb,code *pcs,regm_t keepmsk); 526 void genregs(ref CodeBuilder cdb, opcode_t op, uint dstreg, uint srcreg); 527 void gentstreg(ref CodeBuilder cdb, uint reg); 528 void genpush(ref CodeBuilder cdb, reg_t reg); 529 void genpop(ref CodeBuilder cdb, reg_t reg); 530 void gen_storecse(ref CodeBuilder cdb, tym_t tym, reg_t reg, size_t slot); 531 void gen_testcse(ref CodeBuilder cdb, tym_t tym, uint sz, size_t i); 532 void gen_loadcse(ref CodeBuilder cdb, tym_t tym, reg_t reg, size_t slot); 533 code *genmovreg(uint to, uint from); 534 void genmovreg(ref CodeBuilder cdb, uint to, uint from); 535 void genmovreg(ref CodeBuilder cdb, uint to, uint from, tym_t tym); 536 void genmulimm(ref CodeBuilder cdb,uint r1,uint r2,targ_int imm); 537 void genshift(ref CodeBuilder cdb); 538 void movregconst(ref CodeBuilder cdb,reg_t reg,targ_size_t value,regm_t flags); 539 void genjmp(ref CodeBuilder cdb, opcode_t op, uint fltarg, block *targ); 540 void prolog(ref CodeBuilder cdb); 541 void epilog (block *b); 542 void gen_spill_reg(ref CodeBuilder cdb, Symbol *s, bool toreg); 543 void load_localgot(ref CodeBuilder cdb); 544 targ_size_t cod3_spoff(); 545 void makeitextern (Symbol *s ); 546 void fltused(); 547 int branch(block *bl, int flag); 548 void cod3_adjSymOffsets(); 549 void assignaddr(block *bl); 550 void assignaddrc(code *c); 551 targ_size_t cod3_bpoffset(Symbol *s); 552 void pinholeopt (code *c , block *bn ); 553 void simplify_code(code *c); 554 void jmpaddr (code *c); 555 int code_match(code *c1,code *c2); 556 uint calcblksize (code *c); 557 uint calccodsize(code *c); 558 uint codout(int seg, code *c); 559 size_t addtofixlist(Symbol *s , targ_size_t soffset , int seg , targ_size_t val , int flags ); 560 void searchfixlist(Symbol *s) {} 561 void outfixlist(); 562 void code_hydrate(code **pc); 563 void code_dehydrate(code **pc); 564 regm_t allocretregs(tym_t ty, type *t, tym_t tyf, reg_t *reg1, reg_t *reg2); 565 566 extern __gshared 567 { 568 int hasframe; /* !=0 if this function has a stack frame */ 569 bool enforcealign; /* enforced stack alignment */ 570 targ_size_t spoff; 571 targ_size_t Foff; // BP offset of floating register 572 targ_size_t CSoff; // offset of common sub expressions 573 targ_size_t NDPoff; // offset of saved 8087 registers 574 targ_size_t pushoff; // offset of saved registers 575 bool pushoffuse; // using pushoff 576 int BPoff; // offset from BP 577 int EBPtoESP; // add to EBP offset to get ESP offset 578 } 579 580 void prolog_ifunc(ref CodeBuilder cdb, tym_t* tyf); 581 void prolog_ifunc2(ref CodeBuilder cdb, tym_t tyf, tym_t tym, bool pushds); 582 void prolog_16bit_windows_farfunc(ref CodeBuilder cdb, tym_t* tyf, bool* pushds); 583 void prolog_frame(ref CodeBuilder cdb, bool farfunc, ref uint xlocalsize, out bool enter, out int cfa_offset); 584 void prolog_frameadj(ref CodeBuilder cdb, tym_t tyf, uint xlocalsize, bool enter, bool* pushalloc); 585 void prolog_frameadj2(ref CodeBuilder cdb, tym_t tyf, uint xlocalsize, bool* pushalloc); 586 void prolog_setupalloca(ref CodeBuilder cdb); 587 void prolog_saveregs(ref CodeBuilder cdb, regm_t topush, int cfa_offset); 588 void prolog_stackalign(ref CodeBuilder cdb); 589 void prolog_trace(ref CodeBuilder cdb, bool farfunc, uint* regsaved); 590 void prolog_gen_win64_varargs(ref CodeBuilder cdb); 591 void prolog_genvarargs(ref CodeBuilder cdb, Symbol* sv, regm_t namedargs); 592 void prolog_loadparams(ref CodeBuilder cdb, tym_t tyf, bool pushalloc, out regm_t namedargs); 593 594 /* cod4.c */ 595 extern __gshared 596 { 597 const reg_t[4] dblreg; 598 int cdcmp_flag; 599 } 600 601 int doinreg(Symbol *s, elem *e); 602 void modEA(ref CodeBuilder cdb, code *c); 603 void longcmp(ref CodeBuilder,elem *,bool,uint,code *); 604 605 /* cod5.c */ 606 void cod5_prol_epi(); 607 void cod5_noprol(); 608 609 /* cgxmm.c */ 610 bool isXMMstore(opcode_t op); 611 void orthxmm(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 612 void xmmeq(ref CodeBuilder cdb, elem *e, opcode_t op, elem *e1, elem *e2, regm_t *pretregs); 613 void xmmcnvt(ref CodeBuilder cdb,elem *e,regm_t *pretregs); 614 void xmmopass(ref CodeBuilder cdb,elem *e, regm_t *pretregs); 615 void xmmpost(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 616 void xmmneg(ref CodeBuilder cdb,elem *e, regm_t *pretregs); 617 void xmmabs(ref CodeBuilder cdb,elem *e, regm_t *pretregs); 618 void cloadxmm(ref CodeBuilder cdb,elem *e, regm_t *pretregs); 619 uint xmmload(tym_t tym, bool aligned = true); 620 uint xmmstore(tym_t tym, bool aligned = true); 621 bool xmmIsAligned(elem *e); 622 void checkSetVex3(code *c); 623 void checkSetVex(code *c, tym_t ty); 624 625 /* cg87.c */ 626 void note87(elem *e, uint offset, int i); 627 void pop87(int, const(char)*); 628 void pop87(); 629 void push87(ref CodeBuilder cdb); 630 void save87(ref CodeBuilder cdb); 631 void save87regs(ref CodeBuilder cdb, uint n); 632 void gensaverestore87(regm_t, ref CodeBuilder cdbsave, ref CodeBuilder cdbrestore); 633 //code *genfltreg(code *c,opcode_t opcode,uint reg,targ_size_t offset); 634 void genfwait(ref CodeBuilder cdb); 635 void comsub87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 636 void fixresult87(ref CodeBuilder cdb, elem *e, regm_t retregs, regm_t *pretregs); 637 void fixresult_complex87(ref CodeBuilder cdb,elem *e,regm_t retregs,regm_t *pretregs); 638 void orth87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 639 void load87(ref CodeBuilder cdb, elem *e, uint eoffset, regm_t *pretregs, elem *eleft, int op); 640 int cmporder87 (elem *e ); 641 void eq87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 642 void complex_eq87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 643 void opass87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 644 void cdnegass87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 645 void post87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 646 void cnvt87(ref CodeBuilder cdb, elem *e , regm_t *pretregs ); 647 void neg87(ref CodeBuilder cdb, elem *e , regm_t *pretregs); 648 void neg_complex87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 649 void cdind87(ref CodeBuilder cdb,elem *e,regm_t *pretregs); 650 void cload87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 651 void cdd_u64(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 652 void cdd_u32(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 653 void loadPair87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 654 655 /* iasm.c */ 656 //void iasm_term(); 657 regm_t iasm_regs(block *bp); 658 659 660 /********************************** 661 * Set value in regimmed for reg. 662 * NOTE: For 16 bit generator, this is always a (targ_short) sign-extended 663 * value. 664 */ 665 666 void regimmed_set(int reg, targ_size_t e) 667 { 668 regcon.immed.value[reg] = e; 669 regcon.immed.mval |= 1 << (reg); 670 //printf("regimmed_set %s %d\n", regm_str(1 << reg), cast(int)e); 671 } 672 673 674 675 676