Mercurial > projects > ldc
comparison gen/toir.cpp @ 797:340acf1535d0
Removed KDevelop3 project files, CMake can generate them just fine!
Fixed function literals in static initializers.
Changed alignment of delegates from 2*PTRSIZE to just PTRSIZE.
Changed errors to go to stderr instead of stdout.
Fairly major rewriting of struct/union/class handling, STILL A BIT BUGGY !!!
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Sat, 29 Nov 2008 21:25:43 +0100 |
parents | 4adf0f742896 |
children | 28ce72c60a21 |
comparison
equal
deleted
inserted
replaced
796:6e7a4c3b64d2 | 797:340acf1535d0 |
---|---|
133 } | 133 } |
134 else assert(0); | 134 else assert(0); |
135 } | 135 } |
136 else { | 136 else { |
137 Logger::println("a normal variable"); | 137 Logger::println("a normal variable"); |
138 | |
138 // take care of forward references of global variables | 139 // take care of forward references of global variables |
139 if (vd->isDataseg() || (vd->storage_class & STCextern)) { | 140 if (vd->isDataseg() || (vd->storage_class & STCextern)) { |
140 vd->toObjFile(0); // TODO: multiobj | 141 vd->toObjFile(0); // TODO: multiobj |
141 } | 142 } |
142 if (!vd->ir.isSet() || !vd->ir.getIrValue()) { | 143 |
144 LLValue* val; | |
145 | |
146 if (!vd->ir.isSet() || !(val = vd->ir.getIrValue())) { | |
143 error("variable %s not resolved", vd->toChars()); | 147 error("variable %s not resolved", vd->toChars()); |
144 if (Logger::enabled()) | 148 if (Logger::enabled()) |
145 Logger::cout() << "unresolved variable had type: " << *DtoType(vd->type) << '\n'; | 149 Logger::cout() << "unresolved variable had type: " << *DtoType(vd->type) << '\n'; |
146 fatal(); | 150 fatal(); |
147 } | 151 } |
152 | |
148 if (vd->isDataseg() || (vd->storage_class & STCextern)) { | 153 if (vd->isDataseg() || (vd->storage_class & STCextern)) { |
149 DtoConstInitGlobal(vd); | 154 DtoConstInitGlobal(vd); |
155 val = DtoBitCast(val, DtoType(type->pointerTo())); | |
150 } | 156 } |
151 return new DVarValue(type, vd, vd->ir.getIrValue()); | 157 |
158 return new DVarValue(type, vd, val); | |
152 } | 159 } |
153 } | 160 } |
154 else if (FuncDeclaration* fdecl = var->isFuncDeclaration()) | 161 else if (FuncDeclaration* fdecl = var->isFuncDeclaration()) |
155 { | 162 { |
156 Logger::println("FuncDeclaration"); | 163 Logger::println("FuncDeclaration"); |
367 assert(0); | 374 assert(0); |
368 | 375 |
369 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage; | 376 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage; |
370 if (Logger::enabled()) | 377 if (Logger::enabled()) |
371 Logger::cout() << "type: " << *at << "\ninit: " << *_init << '\n'; | 378 Logger::cout() << "type: " << *at << "\ninit: " << *_init << '\n'; |
372 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,".stringliteral",gIR->module); | 379 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,".str",gIR->module); |
373 | 380 |
374 llvm::ConstantInt* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false); | 381 llvm::ConstantInt* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false); |
375 LLConstant* idxs[2] = { zero, zero }; | 382 LLConstant* idxs[2] = { zero, zero }; |
376 LLConstant* arrptr = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2); | 383 LLConstant* arrptr = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2); |
377 | 384 |
441 { | 448 { |
442 return _init; | 449 return _init; |
443 } | 450 } |
444 | 451 |
445 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage; | 452 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage; |
446 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_init->getType(),true,_linkage,_init,".stringliteral",gIR->module); | 453 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_init->getType(),true,_linkage,_init,".str",gIR->module); |
447 | 454 |
448 llvm::ConstantInt* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false); | 455 llvm::ConstantInt* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false); |
449 LLConstant* idxs[2] = { zero, zero }; | 456 LLConstant* idxs[2] = { zero, zero }; |
450 LLConstant* arrptr = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2); | 457 LLConstant* arrptr = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2); |
451 | 458 |
1006 // normal virtual call | 1013 // normal virtual call |
1007 else if (fdecl->isAbstract() || (!fdecl->isFinal() && fdecl->isVirtual())) { | 1014 else if (fdecl->isAbstract() || (!fdecl->isFinal() && fdecl->isVirtual())) { |
1008 assert(fdecl->vtblIndex > 0); | 1015 assert(fdecl->vtblIndex > 0); |
1009 assert(e1type->ty == Tclass); | 1016 assert(e1type->ty == Tclass); |
1010 | 1017 |
1011 LLValue* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false); | 1018 LLValue* zero = DtoConstUint(0); |
1012 LLValue* vtblidx = llvm::ConstantInt::get(LLType::Int32Ty, (size_t)fdecl->vtblIndex, false); | 1019 size_t vtblidx = fdecl->vtblIndex; |
1013 if (Logger::enabled()) | 1020 if (Logger::enabled()) |
1014 Logger::cout() << "vthis: " << *vthis << '\n'; | 1021 Logger::cout() << "vthis: " << *vthis << '\n'; |
1015 funcval = DtoGEP(vthis, zero, zero); | 1022 funcval = vthis; |
1023 if (!fdecl->isMember2()->isInterfaceDeclaration()) | |
1024 funcval = DtoGEP(funcval, zero, zero); | |
1016 funcval = DtoLoad(funcval); | 1025 funcval = DtoLoad(funcval); |
1017 funcval = DtoGEP(funcval, zero, vtblidx, toChars()); | 1026 Logger::println("vtblidx = %lu", vtblidx); |
1027 funcval = DtoGEP(funcval, zero, DtoConstUint(vtblidx), toChars()); | |
1018 funcval = DtoLoad(funcval); | 1028 funcval = DtoLoad(funcval); |
1019 #if OPAQUE_VTBLS | 1029 |
1020 funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type))); | 1030 funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type))); |
1021 if (Logger::enabled()) | 1031 if (Logger::enabled()) |
1022 Logger::cout() << "funcval casted: " << *funcval << '\n'; | 1032 Logger::cout() << "funcval casted: " << *funcval << '\n'; |
1023 #endif | |
1024 } | 1033 } |
1025 // static call | 1034 // static call |
1026 else { | 1035 else { |
1027 DtoForceDeclareDsymbol(fdecl); | 1036 DtoForceDeclareDsymbol(fdecl); |
1028 funcval = fdecl->ir.irFunc->func; | 1037 funcval = fdecl->ir.irFunc->func; |
2141 assert(0 && "fd->tok must be TOKfunction or TOKdelegate"); | 2150 assert(0 && "fd->tok must be TOKfunction or TOKdelegate"); |
2142 } | 2151 } |
2143 | 2152 |
2144 ////////////////////////////////////////////////////////////////////////////////////////// | 2153 ////////////////////////////////////////////////////////////////////////////////////////// |
2145 | 2154 |
2155 LLConstant* FuncExp::toConstElem(IRState* p) | |
2156 { | |
2157 Logger::print("FuncExp::toConstElem: %s | %s\n", toChars(), type->toChars()); | |
2158 LOG_SCOPE; | |
2159 | |
2160 assert(fd); | |
2161 assert(fd->tok == TOKfunction); | |
2162 | |
2163 DtoForceDefineDsymbol(fd); | |
2164 assert(fd->ir.irFunc->func); | |
2165 | |
2166 return fd->ir.irFunc->func; | |
2167 } | |
2168 | |
2169 ////////////////////////////////////////////////////////////////////////////////////////// | |
2170 | |
2146 DValue* ArrayLiteralExp::toElem(IRState* p) | 2171 DValue* ArrayLiteralExp::toElem(IRState* p) |
2147 { | 2172 { |
2148 Logger::print("ArrayLiteralExp::toElem: %s | %s\n", toChars(), type->toChars()); | 2173 Logger::print("ArrayLiteralExp::toElem: %s | %s\n", toChars(), type->toChars()); |
2149 LOG_SCOPE; | 2174 LOG_SCOPE; |
2150 | 2175 |
2250 return DtoConstSlice(DtoConstSize_t(elements->dim), globalstorePtr); | 2275 return DtoConstSlice(DtoConstSize_t(elements->dim), globalstorePtr); |
2251 } | 2276 } |
2252 | 2277 |
2253 ////////////////////////////////////////////////////////////////////////////////////////// | 2278 ////////////////////////////////////////////////////////////////////////////////////////// |
2254 | 2279 |
2280 void addZeros(std::vector<llvm::Value*>& inits, unsigned pos, unsigned offset); | |
2281 | |
2255 DValue* StructLiteralExp::toElem(IRState* p) | 2282 DValue* StructLiteralExp::toElem(IRState* p) |
2256 { | 2283 { |
2257 Logger::print("StructLiteralExp::toElem: %s | %s\n", toChars(), type->toChars()); | 2284 Logger::print("StructLiteralExp::toElem: %s | %s\n", toChars(), type->toChars()); |
2258 LOG_SCOPE; | 2285 LOG_SCOPE; |
2259 | 2286 |
2260 const LLType* llt = DtoType(type); | 2287 // get arrays |
2261 | 2288 size_t n = elements->dim; |
2262 LLValue* mem = 0; | 2289 Expression** exprs = (Expression**)elements->data; |
2263 | 2290 |
2264 LLValue* sptr = DtoAlloca(llt,"tmpstructliteral"); | 2291 assert(sd->fields.dim == n); |
2265 | 2292 VarDeclaration** vars = (VarDeclaration**)sd->fields.data; |
2266 // default init the struct to take care of padding | 2293 |
2267 // and unspecified members | 2294 // vector of values to build aggregate from |
2268 TypeStruct* ts = (TypeStruct*)type->toBasetype(); | 2295 std::vector<llvm::Value*> values; |
2269 assert(ts->sym); | 2296 |
2270 DtoForceConstInitDsymbol(ts->sym); | 2297 // trackers |
2271 assert(ts->sym->ir.irStruct->init); | 2298 size_t lastoffset = 0; |
2272 DtoAggrCopy(sptr, ts->sym->ir.irStruct->init); | 2299 size_t lastsize = 0; |
2273 | 2300 |
2274 // num elements in literal | 2301 // for through each field and build up the struct, padding with zeros |
2275 unsigned n = elements->dim; | 2302 for (size_t i=0; i<n; i++) |
2276 | 2303 { |
2277 // unions might have different types for each literal | 2304 Expression* e = exprs[i]; |
2278 if (sd->ir.irStruct->hasUnions) { | 2305 VarDeclaration* var = vars[i]; |
2279 // build the type of the literal | 2306 |
2280 std::vector<const LLType*> tys; | 2307 // field is skipped |
2281 for (unsigned i=0; i<n; ++i) { | 2308 if (!e) |
2282 Expression* vx = (Expression*)elements->data[i]; | 2309 continue; |
2283 if (!vx) continue; | 2310 |
2284 tys.push_back(DtoType(vx->type)); | 2311 // add any 0 padding needed before this field |
2285 } | 2312 if (var->offset > lastoffset + lastsize) |
2286 const LLStructType* t = LLStructType::get(tys, sd->ir.irStruct->packed); | 2313 { |
2287 if (t != llt) { | 2314 addZeros(values, lastoffset + lastsize, var->offset); |
2288 if (getABITypeSize(t) != getABITypeSize(llt)) { | 2315 } |
2289 if (Logger::enabled()) | 2316 |
2290 Logger::cout() << "got size " << getABITypeSize(t) << ", expected " << getABITypeSize(llt) << '\n'; | 2317 // add the expression value |
2291 assert(0 && "type size mismatch"); | 2318 DValue* v = e->toElem(p); |
2292 } | 2319 values.push_back(v->getRVal()); |
2293 sptr = DtoBitCast(sptr, getPtrToType(t)); | 2320 |
2294 if (Logger::enabled()) | 2321 // update offsets |
2295 Logger::cout() << "sptr type is now: " << *t << '\n'; | 2322 lastoffset = var->offset; |
2296 } | 2323 lastsize = var->type->size(); |
2297 } | 2324 } |
2298 | 2325 |
2299 // build | 2326 // add any 0 padding needed at the end of the literal |
2300 unsigned j = 0; | 2327 const LLType* structtype = DtoType(sd->type); |
2301 for (unsigned i=0; i<n; ++i) | 2328 size_t structsize = getABITypeSize(structtype); |
2302 { | 2329 |
2303 Expression* vx = (Expression*)elements->data[i]; | 2330 if (structsize > lastoffset+lastsize) |
2304 if (!vx) continue; | 2331 { |
2305 | 2332 addZeros(values, lastoffset + lastsize, structsize); |
2306 if (Logger::enabled()) | 2333 } |
2307 Logger::cout() << "getting index " << j << " of " << *sptr << '\n'; | 2334 |
2308 LLValue* arrptr = DtoGEPi(sptr,0,j); | 2335 // get the struct type from the values |
2309 DValue* darrptr = new DVarValue(vx->type, arrptr); | 2336 n = values.size(); |
2310 | 2337 std::vector<const LLType*> types(n, NULL); |
2311 DValue* ve = vx->toElem(p); | 2338 |
2312 DtoAssign(loc, darrptr, ve); | 2339 for (size_t i=0; i<n; i++) |
2313 | 2340 { |
2314 j++; | 2341 types[i] = values[i]->getType(); |
2315 } | 2342 } |
2316 | 2343 |
2317 return new DImValue(type, sptr); | 2344 const LLStructType* sty = LLStructType::get(types, sd->ir.irStruct->packed); |
2318 } | 2345 |
2319 | 2346 // allocate storage for the struct literal on the stack |
2320 ////////////////////////////////////////////////////////////////////////////////////////// | 2347 LLValue* mem = DtoAlloca(sty, "tmpstructliteral"); |
2348 | |
2349 // put all the values into the storage | |
2350 for (size_t i=0; i<n; i++) | |
2351 { | |
2352 LLValue* ptr = DtoGEPi(mem, 0, i); | |
2353 DtoStore(values[i], ptr); | |
2354 } | |
2355 | |
2356 // cast the alloca pointer to the "formal" struct type | |
2357 mem = DtoBitCast(mem, getPtrToType(structtype)); | |
2358 | |
2359 // return as a var | |
2360 return new DVarValue(type, mem); | |
2361 } | |
2362 | |
2363 ////////////////////////////////////////////////////////////////////////////////////////// | |
2364 | |
2365 void addZeros(std::vector<llvm::Constant*>& inits, unsigned pos, unsigned offset); | |
2321 | 2366 |
2322 LLConstant* StructLiteralExp::toConstElem(IRState* p) | 2367 LLConstant* StructLiteralExp::toConstElem(IRState* p) |
2323 { | 2368 { |
2324 Logger::print("StructLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars()); | 2369 Logger::print("StructLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars()); |
2325 LOG_SCOPE; | 2370 LOG_SCOPE; |
2326 | 2371 |
2327 unsigned n = elements->dim; | 2372 // get arrays |
2328 std::vector<LLConstant*> vals(n, NULL); | 2373 size_t n = elements->dim; |
2329 | 2374 Expression** exprs = (Expression**)elements->data; |
2330 for (unsigned i=0; i<n; ++i) | 2375 |
2331 { | 2376 assert(sd->fields.dim == n); |
2332 Expression* vx = (Expression*)elements->data[i]; | 2377 VarDeclaration** vars = (VarDeclaration**)sd->fields.data; |
2333 vals[i] = vx->toConstElem(p); | 2378 |
2334 } | 2379 // vector of values to build aggregate from |
2335 | 2380 std::vector<llvm::Constant*> values; |
2336 assert(type->toBasetype()->ty == Tstruct); | 2381 |
2337 const LLType* t = DtoType(type); | 2382 // trackers |
2338 const LLStructType* st = isaStruct(t); | 2383 size_t lastoffset = 0; |
2339 return llvm::ConstantStruct::get(st,vals); | 2384 size_t lastsize = 0; |
2385 | |
2386 // for through each field and build up the struct, padding with zeros | |
2387 for (size_t i=0; i<n; i++) | |
2388 { | |
2389 Expression* e = exprs[i]; | |
2390 VarDeclaration* var = vars[i]; | |
2391 | |
2392 // field is skipped | |
2393 if (!e) | |
2394 continue; | |
2395 | |
2396 // add any 0 padding needed before this field | |
2397 if (var->offset > lastoffset + lastsize) | |
2398 { | |
2399 addZeros(values, lastoffset + lastsize, var->offset); | |
2400 } | |
2401 | |
2402 // add the expression value | |
2403 values.push_back(e->toConstElem(p)); | |
2404 | |
2405 // update offsets | |
2406 lastoffset = var->offset; | |
2407 lastsize = var->type->size(); | |
2408 } | |
2409 | |
2410 // add any 0 padding needed at the end of the literal | |
2411 const LLType* structtype = DtoType(sd->type); | |
2412 size_t structsize = getABITypeSize(structtype); | |
2413 | |
2414 if (structsize > lastoffset+lastsize) | |
2415 { | |
2416 addZeros(values, lastoffset + lastsize, structsize); | |
2417 } | |
2418 | |
2419 // return constant struct | |
2420 return LLConstantStruct::get(values, sd->ir.irStruct->packed); | |
2340 } | 2421 } |
2341 | 2422 |
2342 ////////////////////////////////////////////////////////////////////////////////////////// | 2423 ////////////////////////////////////////////////////////////////////////////////////////// |
2343 | 2424 |
2344 DValue* InExp::toElem(IRState* p) | 2425 DValue* InExp::toElem(IRState* p) |