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