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