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