0
|
1 module dmd.IRState;
|
|
2
|
114
|
3 import dmd.common;
|
0
|
4 import dmd.Statement;
|
|
5 import dmd.Module;
|
|
6 import dmd.Dsymbol;
|
|
7 import dmd.Identifier;
|
|
8 import dmd.Array;
|
|
9 import dmd.FuncDeclaration;
|
|
10 import dmd.Global;
|
|
11 import dmd.Loc;
|
|
12
|
|
13 import dmd.backend.Symbol;
|
|
14 import dmd.backend.Blockx;
|
|
15 import dmd.backend.block;
|
|
16 import dmd.backend.elem;
|
|
17 import dmd.backend.Util;
|
|
18 import dmd.backend.TYM;
|
|
19 import dmd.backend.OPER;
|
|
20
|
|
21 struct IRState
|
|
22 {
|
|
23 IRState* prev;
|
|
24 Statement statement;
|
|
25 Module m; // module
|
|
26 Dsymbol symbol;
|
|
27 Identifier ident;
|
|
28 Symbol* shidden; // hidden parameter to function
|
|
29 Symbol* sthis; // 'this' parameter to function (member and nested)
|
|
30 Symbol* sclosure; // pointer to closure instance
|
|
31 Blockx* blx;
|
|
32 Array deferToObj; // array of Dsymbol's to run toObjFile(int multiobj) on later
|
|
33 elem* ehidden; // transmit hidden pointer to CallExp::toElem()
|
|
34 Symbol* startaddress;
|
|
35
|
|
36 block* breakBlock;
|
|
37 block* contBlock;
|
|
38 block* switchBlock;
|
|
39 block* defaultBlock;
|
|
40
|
|
41 this(IRState* irs, Statement s)
|
|
42 {
|
|
43 prev = irs;
|
|
44 statement = s;
|
|
45 if (irs)
|
|
46 {
|
|
47 m = irs.m;
|
|
48 shidden = irs.shidden;
|
|
49 sclosure = irs.sclosure;
|
|
50 sthis = irs.sthis;
|
|
51 blx = irs.blx;
|
|
52 deferToObj = irs.deferToObj;
|
|
53 }
|
|
54 }
|
|
55
|
|
56 this(IRState* irs, Dsymbol s)
|
|
57 {
|
|
58 assert(false);
|
|
59 }
|
|
60
|
|
61 this(Module m, Dsymbol s)
|
|
62 {
|
|
63 this.m = m;
|
|
64 symbol = s;
|
|
65 }
|
|
66
|
|
67 block* getBreakBlock(Identifier ident)
|
|
68 {
|
|
69 for (IRState* bc = &this; bc; bc = bc.prev)
|
|
70 {
|
|
71 if (ident)
|
|
72 {
|
|
73 if (bc.prev && bc.prev.ident == ident)
|
|
74 return bc.breakBlock;
|
|
75 }
|
|
76 else if (bc.breakBlock)
|
|
77 return bc.breakBlock;
|
|
78 }
|
|
79 return null;
|
|
80 }
|
|
81
|
|
82 block* getContBlock(Identifier ident)
|
|
83 {
|
|
84 IRState* bc;
|
|
85
|
|
86 for (bc = &this; bc; bc = bc.prev)
|
|
87 {
|
|
88 if (ident)
|
|
89 {
|
|
90 if (bc.prev && bc.prev.ident == ident)
|
|
91 return bc.contBlock;
|
|
92 }
|
|
93 else if (bc.contBlock)
|
|
94 return bc.contBlock;
|
|
95 }
|
|
96 return null;
|
|
97 }
|
|
98
|
|
99 block* getSwitchBlock()
|
|
100 {
|
|
101 for (IRState* bc = &this; bc; bc = bc.prev)
|
|
102 {
|
|
103 if (bc.switchBlock)
|
|
104 return bc.switchBlock;
|
|
105 }
|
|
106 return null;
|
|
107 }
|
|
108
|
|
109 block* getDefaultBlock()
|
|
110 {
|
|
111 for (IRState* bc = &this; bc; bc = bc.prev)
|
|
112 {
|
|
113 if (bc.defaultBlock)
|
|
114 return bc.defaultBlock;
|
|
115 }
|
|
116 return null;
|
|
117 }
|
|
118
|
|
119 FuncDeclaration getFunc()
|
|
120 {
|
|
121 IRState* bc;
|
|
122 for (bc = &this; bc.prev; bc = bc.prev)
|
|
123 {
|
|
124 }
|
|
125 return cast(FuncDeclaration)(bc.symbol);
|
|
126 }
|
|
127 }
|
|
128
|
|
129 /*********************************************
|
|
130 * Produce elem which increments the usage count for a particular line.
|
|
131 * Used to implement -cov switch (coverage analysis).
|
|
132 */
|
|
133
|
|
134 elem *incUsageElem(IRState *irs, Loc loc)
|
|
135 {
|
|
136 uint linnum = loc.linnum;
|
|
137
|
|
138 if (!irs.blx.module_.cov || !linnum || loc.filename != irs.blx.module_.srcfile.toChars())
|
|
139 return null;
|
|
140
|
|
141 //printf("cov = %p, covb = %p, linnum = %u\n", irs->blx->module->cov, irs->blx->module->covb, p, linnum);
|
|
142
|
|
143 linnum--; // from 1-based to 0-based
|
|
144
|
|
145 /* Set bit in covb[] indicating this is a valid code line number
|
|
146 */
|
|
147 uint* p = irs.blx.module_.covb;
|
|
148 if (p) // covb can be NULL if it has already been written out to its .obj file
|
|
149 {
|
|
150 p += linnum / ((*p).sizeof * 8);
|
|
151 *p |= 1 << (linnum & ((*p).sizeof * 8 - 1));
|
|
152 }
|
|
153
|
|
154 elem* e;
|
|
155 e = el_ptr(irs.blx.module_.cov);
|
|
156 e = el_bin(OPER.OPadd, TYM.TYnptr, e, el_long(TYM.TYuint, linnum * 4));
|
|
157 e = el_una(OPER.OPind, TYM.TYuint, e);
|
|
158 e = el_bin(OPER.OPaddass, TYM.TYuint, e, el_long(TYM.TYuint, 1));
|
|
159
|
|
160 return e;
|
|
161 }
|
|
162
|
|
163 /**************************************
|
|
164 * Add in code to increment usage count for linnum.
|
|
165 */
|
|
166 void incUsage(IRState* irs, Loc loc)
|
|
167 {
|
|
168 if (global.params.cov && loc.linnum)
|
|
169 {
|
|
170 block_appendexp(irs.blx.curblock, incUsageElem(irs, loc));
|
|
171 }
|
|
172 } |