comparison dmd/inline.c @ 1482:d9c5f5a43403

Run `semantic3` on imported modules, and emit new symbols with `available_externally` linkage. This allows the inliner to inline functions from other modules while telling the code generator to ignore those functions (treat them as declarations) Still generates a few extra `TypeInfo`s and strings... Disabled when generating debug info because I don't really understand it, and it doesn't like this.
author Frits van Bommel <fvbommel wxs.nl>
date Sun, 07 Jun 2009 16:00:13 +0200
parents 8026319762be
children def7a1d494fd
comparison
equal deleted inserted replaced
1481:e0f03e11cdf8 1482:d9c5f5a43403
81 81
82 int IfStatement::inlineCost(InlineCostState *ics) 82 int IfStatement::inlineCost(InlineCostState *ics)
83 { 83 {
84 int cost; 84 int cost;
85 85
86 #if !IN_LLVM
86 /* Can't declare variables inside ?: expressions, so 87 /* Can't declare variables inside ?: expressions, so
87 * we cannot inline if a variable is declared. 88 * we cannot inline if a variable is declared.
88 */ 89 */
89 if (arg) 90 if (arg)
90 return COST_MAX; 91 return COST_MAX;
92 #endif
91 93
92 cost = condition->inlineCost(ics); 94 cost = condition->inlineCost(ics);
93 95
96 #if !IN_LLVM
94 /* Specifically allow: 97 /* Specifically allow:
95 * if (condition) 98 * if (condition)
96 * return exp1; 99 * return exp1;
97 * else 100 * else
98 * return exp2; 101 * return exp2;
106 cost += ifbody->inlineCost(ics); 109 cost += ifbody->inlineCost(ics);
107 cost += elsebody->inlineCost(ics); 110 cost += elsebody->inlineCost(ics);
108 //printf("cost = %d\n", cost); 111 //printf("cost = %d\n", cost);
109 } 112 }
110 else 113 else
114 #endif
111 { 115 {
112 ics->nested += 1; 116 ics->nested += 1;
113 if (ifbody) 117 if (ifbody)
114 cost += ifbody->inlineCost(ics); 118 cost += ifbody->inlineCost(ics);
115 if (elsebody) 119 if (elsebody)
119 return cost; 123 return cost;
120 } 124 }
121 125
122 int ReturnStatement::inlineCost(InlineCostState *ics) 126 int ReturnStatement::inlineCost(InlineCostState *ics)
123 { 127 {
128 #if !IN_LLVM
124 // Can't handle return statements nested in if's 129 // Can't handle return statements nested in if's
125 if (ics->nested) 130 if (ics->nested)
126 return COST_MAX; 131 return COST_MAX;
132 #endif
127 return exp ? exp->inlineCost(ics) : 0; 133 return exp ? exp->inlineCost(ics) : 0;
128 } 134 }
129 135
130 /* -------------------------- */ 136 /* -------------------------- */
131 137
155 return 1; 161 return 1;
156 } 162 }
157 163
158 int ThisExp::inlineCost(InlineCostState *ics) 164 int ThisExp::inlineCost(InlineCostState *ics)
159 { 165 {
166 #if !IN_LLVM
160 FuncDeclaration *fd = ics->fd; 167 FuncDeclaration *fd = ics->fd;
161 if (!ics->hdrscan) 168 if (!ics->hdrscan)
162 if (fd->isNested() || !ics->hasthis) 169 if (fd->isNested() || !ics->hasthis)
163 return COST_MAX; 170 return COST_MAX;
171 #endif
164 return 1; 172 return 1;
165 } 173 }
166 174
167 int SuperExp::inlineCost(InlineCostState *ics) 175 int SuperExp::inlineCost(InlineCostState *ics)
168 { 176 {
177 #if !IN_LLVM
169 FuncDeclaration *fd = ics->fd; 178 FuncDeclaration *fd = ics->fd;
170 if (!ics->hdrscan) 179 if (!ics->hdrscan)
171 if (fd->isNested() || !ics->hasthis) 180 if (fd->isNested() || !ics->hasthis)
172 return COST_MAX; 181 return COST_MAX;
182 #endif
173 return 1; 183 return 1;
174 } 184 }
175 185
176 int TupleExp::inlineCost(InlineCostState *ics) 186 int TupleExp::inlineCost(InlineCostState *ics)
177 { 187 {
193 return 1 + arrayInlineCost(ics, elements); 203 return 1 + arrayInlineCost(ics, elements);
194 } 204 }
195 205
196 int FuncExp::inlineCost(InlineCostState *ics) 206 int FuncExp::inlineCost(InlineCostState *ics)
197 { 207 {
208 // This breaks on LDC too, since nested functions have internal linkage
209 // and thus can't be referenced from other objects.
198 // Right now, this makes the function be output to the .obj file twice. 210 // Right now, this makes the function be output to the .obj file twice.
199 return COST_MAX; 211 return COST_MAX;
200 } 212 }
201 213
202 int DelegateExp::inlineCost(InlineCostState *ics) 214 int DelegateExp::inlineCost(InlineCostState *ics)
203 { 215 {
216 // This breaks on LDC too, since nested functions have internal linkage
217 // and thus can't be referenced from other objects.
204 return COST_MAX; 218 return COST_MAX;
205 } 219 }
206 220
207 int DeclarationExp::inlineCost(InlineCostState *ics) 221 int DeclarationExp::inlineCost(InlineCostState *ics)
208 { int cost = 0; 222 { int cost = 0;
227 return COST_MAX; 241 return COST_MAX;
228 } 242 }
229 return td->objects->dim; 243 return td->objects->dim;
230 #endif 244 #endif
231 } 245 }
246 // This breaks on LDC too, since nested static variables have internal
247 // linkage and thus can't be referenced from other objects.
232 if (!ics->hdrscan && vd->isDataseg()) 248 if (!ics->hdrscan && vd->isDataseg())
233 return COST_MAX; 249 return COST_MAX;
234 cost += 1; 250 cost += 1;
235 251
236 // Scan initializer (vd->init) 252 // Scan initializer (vd->init)
244 } 260 }
245 } 261 }
246 } 262 }
247 263
248 // These can contain functions, which when copied, get output twice. 264 // These can contain functions, which when copied, get output twice.
265 // These break on LDC too, since nested static variables and functions have
266 // internal linkage and thus can't be referenced from other objects.
249 if (declaration->isStructDeclaration() || 267 if (declaration->isStructDeclaration() ||
250 declaration->isClassDeclaration() || 268 declaration->isClassDeclaration() ||
251 declaration->isFuncDeclaration() || 269 declaration->isFuncDeclaration() ||
252 declaration->isTypedefDeclaration() || 270 declaration->isTypedefDeclaration() ||
253 declaration->isTemplateMixin()) 271 declaration->isTemplateMixin())
1267 } 1285 }
1268 1286
1269 if (type) 1287 if (type)
1270 { assert(type->ty == Tfunction); 1288 { assert(type->ty == Tfunction);
1271 TypeFunction *tf = (TypeFunction *)(type); 1289 TypeFunction *tf = (TypeFunction *)(type);
1290 #if IN_LLVM
1291 // LDC: Only extern(C) varargs count.
1292 if (tf->linkage != LINKd)
1293 #endif
1272 if (tf->varargs == 1) // no variadic parameter lists 1294 if (tf->varargs == 1) // no variadic parameter lists
1273 goto Lno; 1295 goto Lno;
1274 1296
1275 /* Don't inline a function that returns non-void, but has 1297 /* Don't inline a function that returns non-void, but has
1276 * no return expression. 1298 * no return expression.
1278 if (tf->next && tf->next->ty != Tvoid && 1300 if (tf->next && tf->next->ty != Tvoid &&
1279 !(hasReturnExp & 1) && 1301 !(hasReturnExp & 1) &&
1280 !hdrscan) 1302 !hdrscan)
1281 goto Lno; 1303 goto Lno;
1282 } 1304 }
1305 #if !IN_LLVM
1306 // LDC: Only extern(C) varargs count, and ctors use extern(D).
1283 else 1307 else
1284 { CtorDeclaration *ctor = isCtorDeclaration(); 1308 { CtorDeclaration *ctor = isCtorDeclaration();
1285 1309
1286 if (ctor && ctor->varargs == 1) 1310 if (ctor && ctor->varargs == 1)
1287 goto Lno; 1311 goto Lno;
1288 } 1312 }
1313 #endif
1289 1314
1290 if ( 1315 if (
1291 !fbody || 1316 !fbody ||
1292 !hdrscan && 1317 !hdrscan &&
1293 ( 1318 (
1297 // to: 1322 // to:
1298 // return this; 1323 // return this;
1299 #endif 1324 #endif
1300 isSynchronized() || 1325 isSynchronized() ||
1301 isImportedSymbol() || 1326 isImportedSymbol() ||
1327 #if !IN_LLVM
1302 #if DMDV2 1328 #if DMDV2
1303 closureVars.dim || // no nested references to this frame 1329 closureVars.dim || // no nested references to this frame
1304 #else 1330 #else
1305 nestedFrameRef || // no nested references to this frame 1331 nestedFrameRef || // no nested references to this frame
1306 #endif 1332 #endif
1333 #endif // !IN_LLVM
1307 (isVirtual() && !isFinal()) 1334 (isVirtual() && !isFinal())
1308 )) 1335 ))
1309 { 1336 {
1310 goto Lno; 1337 goto Lno;
1311 } 1338 }
1312 1339
1340 #if !IN_LLVM
1313 /* If any parameters are Tsarray's (which are passed by reference) 1341 /* If any parameters are Tsarray's (which are passed by reference)
1314 * or out parameters (also passed by reference), don't do inlining. 1342 * or out parameters (also passed by reference), don't do inlining.
1315 */ 1343 */
1316 if (parameters) 1344 if (parameters)
1317 { 1345 {
1320 VarDeclaration *v = (VarDeclaration *)parameters->data[i]; 1348 VarDeclaration *v = (VarDeclaration *)parameters->data[i];
1321 if (v->isOut() || v->isRef() || v->type->toBasetype()->ty == Tsarray) 1349 if (v->isOut() || v->isRef() || v->type->toBasetype()->ty == Tsarray)
1322 goto Lno; 1350 goto Lno;
1323 } 1351 }
1324 } 1352 }
1353 #endif
1325 1354
1326 memset(&ics, 0, sizeof(ics)); 1355 memset(&ics, 0, sizeof(ics));
1327 ics.hasthis = hasthis; 1356 ics.hasthis = hasthis;
1328 ics.fd = this; 1357 ics.fd = this;
1329 ics.hdrscan = hdrscan; 1358 ics.hdrscan = hdrscan;
1332 printf("cost = %d\n", cost); 1361 printf("cost = %d\n", cost);
1333 #endif 1362 #endif
1334 if (cost >= COST_MAX) 1363 if (cost >= COST_MAX)
1335 goto Lno; 1364 goto Lno;
1336 1365
1366 #if !IN_LLVM
1337 if (!hdrscan) // Don't scan recursively for header content scan 1367 if (!hdrscan) // Don't scan recursively for header content scan
1338 inlineScan(); 1368 inlineScan();
1369 #endif
1339 1370
1340 Lyes: 1371 Lyes:
1341 if (!hdrscan) // Don't modify inlineStatus for header content scan 1372 if (!hdrscan) // Don't modify inlineStatus for header content scan
1342 inlineStatus = ILSyes; 1373 inlineStatus = ILSyes;
1343 #if CANINLINE_LOG 1374 #if CANINLINE_LOG