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-2021 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 (1) // for Windows 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 int isCode() { return config.objfmt == OBJ_MACH ? mach_seg_data_isCode(this) : mscoff_seg_data_isCode(this); } 270 } 271 272 extern int mach_seg_data_isCode(const ref seg_data sd) @system; 273 extern int mscoff_seg_data_isCode(const ref seg_data sd) @system; 274 275 struct linnum_data 276 { 277 const(char) *filename; 278 uint filenumber; // corresponding file number for DW_LNS_set_file 279 280 Barray!(LinOff) linoff; // line numbers and offsets 281 } 282 283 struct LinOff 284 { 285 uint lineNumber; 286 uint offset; 287 } 288 289 extern __gshared Rarray!(seg_data*) SegData; 290 291 ref targ_size_t Offset(int seg) { return SegData[seg].SDoffset; } 292 ref targ_size_t Doffset() { return Offset(DATA); } 293 ref targ_size_t CDoffset() { return Offset(CDATA); } 294 295 /**************************************************/ 296 297 /* Allocate registers to function parameters 298 */ 299 300 struct FuncParamRegs 301 { 302 //this(tym_t tyf); 303 static FuncParamRegs create(tym_t tyf) { return FuncParamRegs_create(tyf); } 304 305 int alloc(type *t, tym_t ty, ubyte *reg1, ubyte *reg2) 306 { return FuncParamRegs_alloc(this, t, ty, reg1, reg2); } 307 308 private: 309 public: // for the moment 310 tym_t tyf; // type of function 311 int i; // ith parameter 312 int regcnt; // how many general purpose registers are allocated 313 int xmmcnt; // how many fp registers are allocated 314 uint numintegerregs; // number of gp registers that can be allocated 315 uint numfloatregs; // number of fp registers that can be allocated 316 const(ubyte)* argregs; // map to gp register 317 const(ubyte)* floatregs; // map to fp register 318 } 319 320 extern FuncParamRegs FuncParamRegs_create(tym_t tyf) @system; 321 extern int FuncParamRegs_alloc(ref FuncParamRegs fpr, type *t, tym_t ty, reg_t *preg1, reg_t *preg2) @system; 322 323 extern __gshared 324 { 325 regm_t msavereg,mfuncreg,allregs; 326 327 int BPRM; 328 regm_t FLOATREGS; 329 regm_t FLOATREGS2; 330 regm_t DOUBLEREGS; 331 //const char datafl[],stackfl[],segfl[],flinsymtab[]; 332 char needframe,gotref; 333 targ_size_t localsize, 334 funcoffset, 335 framehandleroffset; 336 segidx_t cseg; 337 int STACKALIGN; 338 int TARGET_STACKALIGN; 339 LocalSection Para; 340 LocalSection Fast; 341 LocalSection Auto; 342 LocalSection EEStack; 343 LocalSection Alloca; 344 } 345 346 /* cgcod.c */ 347 extern __gshared int pass; 348 enum 349 { 350 PASSinitial, // initial pass through code generator 351 PASSreg, // register assignment pass 352 PASSfinal, // final pass 353 } 354 355 extern __gshared int dfoidx; 356 extern __gshared bool floatreg; 357 extern __gshared targ_size_t prolog_allocoffset; 358 extern __gshared targ_size_t startoffset; 359 extern __gshared targ_size_t retoffset; 360 extern __gshared targ_size_t retsize; 361 extern __gshared uint stackpush; 362 extern __gshared int stackchanged; 363 extern __gshared int refparam; 364 extern __gshared int reflocal; 365 extern __gshared bool anyiasm; 366 extern __gshared char calledafunc; 367 extern __gshared bool calledFinally; 368 369 void codgen(Symbol *); 370 371 debug 372 { 373 reg_t findreg(regm_t regm , int line, const(char)* file); 374 extern (D) reg_t findreg(regm_t regm , int line = __LINE__, string file = __FILE__) 375 { return findreg(regm, line, file.ptr); } 376 } 377 else 378 { 379 reg_t findreg(regm_t regm); 380 } 381 382 reg_t findregmsw(uint regm) { return findreg(regm & mMSW); } 383 reg_t findreglsw(uint regm) { return findreg(regm & (mLSW | mBP)); } 384 void freenode(elem *e); 385 int isregvar(elem *e, regm_t *pregm, reg_t *preg); 386 void allocreg(ref CodeBuilder cdb, regm_t *pretregs, reg_t *preg, tym_t tym, int line, const(char)* file); 387 void allocreg(ref CodeBuilder cdb, regm_t *pretregs, reg_t *preg, tym_t tym); 388 reg_t allocScratchReg(ref CodeBuilder cdb, regm_t regm); 389 regm_t lpadregs(); 390 void useregs (regm_t regm); 391 void getregs(ref CodeBuilder cdb, regm_t r); 392 void getregsNoSave(regm_t r); 393 void getregs_imm(ref CodeBuilder cdb, regm_t r); 394 void cse_flush(ref CodeBuilder, int); 395 bool cse_simple(code *c, elem *e); 396 bool cssave (elem *e , regm_t regm , uint opsflag ); 397 bool evalinregister(elem *e); 398 regm_t getscratch(); 399 void codelem(ref CodeBuilder cdb, elem *e, regm_t *pretregs, uint constflag); 400 void scodelem(ref CodeBuilder cdb, elem *e, regm_t *pretregs, regm_t keepmsk, bool constflag); 401 const(char)* regm_str(regm_t rm); 402 int numbitsset(regm_t); 403 404 /* cdxxx.c: functions that go into cdxxx[] table */ 405 void cdabs(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 406 void cdaddass(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 407 void cdasm(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 408 void cdbscan(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 409 void cdbswap(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 410 void cdbt(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 411 void cdbtst(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 412 void cdbyteint(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 413 void cdcmp(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 414 void cdcmpxchg(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 415 void cdcnvt(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 416 void cdcom(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 417 void cdcomma(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 418 void cdcond(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 419 void cdconvt87(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 420 void cdctor(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 421 void cddctor(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 422 void cdddtor(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 423 void cddtor(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 424 void cdeq(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 425 void cderr(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 426 void cdfar16(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 427 void cdframeptr(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 428 void cdfunc(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 429 void cdgot(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 430 void cdhalt(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 431 void cdind(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 432 void cdinfo(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 433 void cdlngsht(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 434 void cdloglog(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 435 void cdmark(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 436 void cdmemcmp(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 437 void cdmemcpy(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 438 void cdmemset(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 439 void cdmsw(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 440 void cdmul(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 441 void cddiv(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 442 void cdmulass(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 443 void cddivass(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 444 void cdneg(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 445 void cdnot(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 446 void cdorth(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 447 void cdpair(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 448 void cdpopcnt(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 449 void cdport(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 450 void cdpost(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 451 void cdprefetch(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 452 void cdrelconst(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 453 void cdrndtol(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 454 void cdscale(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 455 void cdsetjmp(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 456 void cdshass(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 457 void cdshift(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 458 void cdshtlng(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 459 void cdstrcmp(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 460 void cdstrcpy(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 461 void cdstreq(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 462 void cdstrlen(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 463 void cdstrthis(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 464 void cdtoprec(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 465 void cdvecfill(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 466 void cdvecsto(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 467 void cdvector(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 468 void cdvoid(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 469 void loaddata(ref CodeBuilder cdb, elem* e, regm_t* pretregs); 470 471 /* cod1.c */ 472 extern __gshared int clib_inited; 473 474 bool regParamInPreg(Symbol* s); 475 int isscaledindex(elem *); 476 int ssindex(int op,targ_uns product); 477 void buildEA(code *c,int base,int index,int scale,targ_size_t disp); 478 uint buildModregrm(int mod, int reg, int rm); 479 void andregcon (con_t *pregconsave); 480 void genEEcode(); 481 void docommas(ref CodeBuilder cdb,elem **pe); 482 uint gensaverestore(regm_t, ref CodeBuilder cdbsave, ref CodeBuilder cdbrestore); 483 void genstackclean(ref CodeBuilder cdb,uint numpara,regm_t keepmsk); 484 void logexp(ref CodeBuilder cdb, elem *e, int jcond, uint fltarg, code *targ); 485 uint getaddrmode(regm_t idxregs); 486 void setaddrmode(code *c, regm_t idxregs); 487 void fltregs(ref CodeBuilder cdb, code *pcs, tym_t tym); 488 void tstresult(ref CodeBuilder cdb, regm_t regm, tym_t tym, uint saveflag); 489 void fixresult(ref CodeBuilder cdb, elem *e, regm_t retregs, regm_t *pretregs); 490 void callclib(ref CodeBuilder cdb, elem *e, uint clib, regm_t *pretregs, regm_t keepmask); 491 void pushParams(ref CodeBuilder cdb,elem *, uint, tym_t tyf); 492 void offsetinreg(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 493 void argtypes(type* t, ref type* arg1type, ref type* arg2type); 494 495 /* cod2.c */ 496 bool movOnly(const elem *e); 497 regm_t idxregm(const code *c); 498 void opdouble(ref CodeBuilder cdb, elem *e, regm_t *pretregs, uint clib); 499 void WRcodlst(code *c); 500 void getoffset(ref CodeBuilder cdb, elem *e, reg_t reg); 501 502 /* cod3.c */ 503 504 int cod3_EA(code *c); 505 regm_t cod3_useBP(); 506 void cod3_initregs(); 507 void cod3_setdefault(); 508 void cod3_set32(); 509 void cod3_set64(); 510 void cod3_align_bytes(int seg, size_t nbytes); 511 void cod3_align(int seg); 512 void cod3_buildmodulector(Outbuffer* buf, int codeOffset, int refOffset); 513 void cod3_stackadj(ref CodeBuilder cdb, int nbytes); 514 void cod3_stackalign(ref CodeBuilder cdb, int nbytes); 515 regm_t regmask(tym_t tym, tym_t tyf); 516 void cgreg_dst_regs(reg_t* dst_integer_reg, reg_t* dst_float_reg); 517 void cgreg_set_priorities(tym_t ty, const(reg_t)** pseq, const(reg_t)** pseqmsw); 518 void outblkexitcode(ref CodeBuilder cdb, block *bl, ref int anyspill, const(char)* sflsave, Symbol** retsym, const regm_t mfuncregsave ); 519 void outjmptab(block *b); 520 void outswitab(block *b); 521 int jmpopcode(elem *e); 522 void cod3_ptrchk(ref CodeBuilder cdb,code *pcs,regm_t keepmsk); 523 void genregs(ref CodeBuilder cdb, opcode_t op, uint dstreg, uint srcreg); 524 void gentstreg(ref CodeBuilder cdb, uint reg); 525 void genpush(ref CodeBuilder cdb, reg_t reg); 526 void genpop(ref CodeBuilder cdb, reg_t reg); 527 void gen_storecse(ref CodeBuilder cdb, tym_t tym, reg_t reg, size_t slot); 528 void gen_testcse(ref CodeBuilder cdb, tym_t tym, uint sz, size_t i); 529 void gen_loadcse(ref CodeBuilder cdb, tym_t tym, reg_t reg, size_t slot); 530 code *genmovreg(uint to, uint from); 531 void genmovreg(ref CodeBuilder cdb, uint to, uint from); 532 void genmovreg(ref CodeBuilder cdb, uint to, uint from, tym_t tym); 533 void genmulimm(ref CodeBuilder cdb,uint r1,uint r2,targ_int imm); 534 void genshift(ref CodeBuilder cdb); 535 void movregconst(ref CodeBuilder cdb,reg_t reg,targ_size_t value,regm_t flags); 536 void genjmp(ref CodeBuilder cdb, opcode_t op, uint fltarg, block *targ); 537 void prolog(ref CodeBuilder cdb); 538 void epilog (block *b); 539 void gen_spill_reg(ref CodeBuilder cdb, Symbol *s, bool toreg); 540 void load_localgot(ref CodeBuilder cdb); 541 targ_size_t cod3_spoff(); 542 void makeitextern (Symbol *s ); 543 void fltused(); 544 int branch(block *bl, int flag); 545 void cod3_adjSymOffsets(); 546 void assignaddr(block *bl); 547 void assignaddrc(code *c); 548 targ_size_t cod3_bpoffset(Symbol *s); 549 void pinholeopt (code *c , block *bn ); 550 void simplify_code(code *c); 551 void jmpaddr (code *c); 552 int code_match(code *c1,code *c2); 553 uint calcblksize (code *c); 554 uint calccodsize(code *c); 555 uint codout(int seg, code *c); 556 size_t addtofixlist(Symbol *s , targ_size_t soffset , int seg , targ_size_t val , int flags ); 557 void searchfixlist(Symbol *s) {} 558 void outfixlist(); 559 void code_hydrate(code **pc); 560 void code_dehydrate(code **pc); 561 regm_t allocretregs(const tym_t ty, type* t, const tym_t tyf, out reg_t reg1, out reg_t reg2); 562 563 extern __gshared 564 { 565 int hasframe; /* !=0 if this function has a stack frame */ 566 bool enforcealign; /* enforced stack alignment */ 567 targ_size_t spoff; 568 targ_size_t Foff; // BP offset of floating register 569 targ_size_t CSoff; // offset of common sub expressions 570 targ_size_t NDPoff; // offset of saved 8087 registers 571 targ_size_t pushoff; // offset of saved registers 572 bool pushoffuse; // using pushoff 573 int BPoff; // offset from BP 574 int EBPtoESP; // add to EBP offset to get ESP offset 575 } 576 577 void prolog_ifunc(ref CodeBuilder cdb, tym_t* tyf); 578 void prolog_ifunc2(ref CodeBuilder cdb, tym_t tyf, tym_t tym, bool pushds); 579 void prolog_16bit_windows_farfunc(ref CodeBuilder cdb, tym_t* tyf, bool* pushds); 580 void prolog_frame(ref CodeBuilder cdb, bool farfunc, ref uint xlocalsize, out bool enter, out int cfa_offset); 581 void prolog_frameadj(ref CodeBuilder cdb, tym_t tyf, uint xlocalsize, bool enter, bool* pushalloc); 582 void prolog_frameadj2(ref CodeBuilder cdb, tym_t tyf, uint xlocalsize, bool* pushalloc); 583 void prolog_setupalloca(ref CodeBuilder cdb); 584 void prolog_saveregs(ref CodeBuilder cdb, regm_t topush, int cfa_offset); 585 void prolog_stackalign(ref CodeBuilder cdb); 586 void prolog_trace(ref CodeBuilder cdb, bool farfunc, uint* regsaved); 587 void prolog_gen_win64_varargs(ref CodeBuilder cdb); 588 void prolog_genvarargs(ref CodeBuilder cdb, Symbol* sv, regm_t namedargs); 589 void prolog_loadparams(ref CodeBuilder cdb, tym_t tyf, bool pushalloc, out regm_t namedargs); 590 591 /* cod4.c */ 592 extern __gshared 593 { 594 const reg_t[4] dblreg; 595 int cdcmp_flag; 596 } 597 598 int doinreg(Symbol *s, elem *e); 599 void modEA(ref CodeBuilder cdb, code *c); 600 void longcmp(ref CodeBuilder,elem *,bool,uint,code *); 601 602 /* cod5.c */ 603 void cod5_prol_epi(); 604 void cod5_noprol(); 605 606 /* cgxmm.c */ 607 bool isXMMstore(opcode_t op); 608 void orthxmm(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 609 void xmmeq(ref CodeBuilder cdb, elem *e, opcode_t op, elem *e1, elem *e2, regm_t *pretregs); 610 void xmmcnvt(ref CodeBuilder cdb,elem *e,regm_t *pretregs); 611 void xmmopass(ref CodeBuilder cdb,elem *e, regm_t *pretregs); 612 void xmmpost(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 613 void xmmneg(ref CodeBuilder cdb,elem *e, regm_t *pretregs); 614 void xmmabs(ref CodeBuilder cdb,elem *e, regm_t *pretregs); 615 void cloadxmm(ref CodeBuilder cdb,elem *e, regm_t *pretregs); 616 uint xmmload(tym_t tym, bool aligned = true); 617 uint xmmstore(tym_t tym, bool aligned = true); 618 bool xmmIsAligned(elem *e); 619 void checkSetVex3(code *c); 620 void checkSetVex(code *c, tym_t ty); 621 622 /* cg87.c */ 623 void note87(elem *e, uint offset, int i); 624 void pop87(int, const(char)*); 625 void pop87(); 626 void push87(ref CodeBuilder cdb); 627 void save87(ref CodeBuilder cdb); 628 void save87regs(ref CodeBuilder cdb, uint n); 629 void gensaverestore87(regm_t, ref CodeBuilder cdbsave, ref CodeBuilder cdbrestore); 630 //code *genfltreg(code *c,opcode_t opcode,uint reg,targ_size_t offset); 631 void genfwait(ref CodeBuilder cdb); 632 void comsub87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 633 void fixresult87(ref CodeBuilder cdb, elem *e, regm_t retregs, regm_t *pretregs, bool isReturnValue = false); 634 void fixresult_complex87(ref CodeBuilder cdb,elem *e,regm_t retregs,regm_t *pretregs, bool isReturnValue = false); 635 void orth87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 636 void load87(ref CodeBuilder cdb, elem *e, uint eoffset, regm_t *pretregs, elem *eleft, int op); 637 int cmporder87 (elem *e ); 638 void eq87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 639 void complex_eq87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 640 void opass87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 641 void cdnegass87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 642 void post87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 643 void cnvt87(ref CodeBuilder cdb, elem *e , regm_t *pretregs ); 644 void neg87(ref CodeBuilder cdb, elem *e , regm_t *pretregs); 645 void neg_complex87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 646 void cdind87(ref CodeBuilder cdb,elem *e,regm_t *pretregs); 647 void cload87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 648 void cdd_u64(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 649 void cdd_u32(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 650 void loadPair87(ref CodeBuilder cdb, elem *e, regm_t *pretregs); 651 652 /* iasm.c */ 653 //void iasm_term(); 654 regm_t iasm_regs(block *bp); 655 656 657 /********************************** 658 * Set value in regimmed for reg. 659 * NOTE: For 16 bit generator, this is always a (targ_short) sign-extended 660 * value. 661 */ 662 663 void regimmed_set(int reg, targ_size_t e) 664 { 665 regcon.immed.value[reg] = e; 666 regcon.immed.mval |= 1 << (reg); 667 //printf("regimmed_set %s %d\n", regm_str(1 << reg), cast(int)e); 668 } 669 670 671 672 673