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