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