Mercurial > projects > ldc
comparison gen/toir.cpp @ 100:5071469303d4 trunk
[svn r104] TONS OF FIXES.
Split up declaration, constant initializer gen and definition for globals, structs, classes and functions.
Improved ClassInfo support (not complete), not in vtable yet.
Fixed a bunch of forward reference problems.
Much more. Major commit! :)
author | lindquist |
---|---|
date | Fri, 16 Nov 2007 08:21:47 +0100 |
parents | a676a7743642 |
children | 169fda3a77d4 |
comparison
equal
deleted
inserted
replaced
99:a676a7743642 | 100:5071469303d4 |
---|---|
24 #include "gen/logger.h" | 24 #include "gen/logger.h" |
25 #include "gen/tollvm.h" | 25 #include "gen/tollvm.h" |
26 #include "gen/runtime.h" | 26 #include "gen/runtime.h" |
27 #include "gen/arrays.h" | 27 #include "gen/arrays.h" |
28 #include "gen/structs.h" | 28 #include "gen/structs.h" |
29 #include "gen/classes.h" | |
29 | 30 |
30 #include "gen/dvalue.h" | 31 #include "gen/dvalue.h" |
31 | 32 |
32 ////////////////////////////////////////////////////////////////////////////////////////// | 33 ////////////////////////////////////////////////////////////////////////////////////////// |
33 | 34 |
50 { | 51 { |
51 Logger::println("vdtype = %s", vd->type->toChars()); | 52 Logger::println("vdtype = %s", vd->type->toChars()); |
52 // referenced by nested delegate? | 53 // referenced by nested delegate? |
53 if (vd->nestedref) { | 54 if (vd->nestedref) { |
54 Logger::println("has nestedref set"); | 55 Logger::println("has nestedref set"); |
55 vd->llvmValue = p->func().decl->llvmNested; | 56 vd->llvmValue = p->func()->decl->llvmNested; |
56 assert(vd->llvmValue); | 57 assert(vd->llvmValue); |
57 assert(vd->llvmNestedIndex >= 0); | 58 assert(vd->llvmNestedIndex >= 0); |
58 } | 59 } |
59 // normal stack variable | 60 // normal stack variable |
60 else { | 61 else { |
117 // _arguments | 118 // _arguments |
118 if (vd->ident == Id::_arguments) | 119 if (vd->ident == Id::_arguments) |
119 { | 120 { |
120 Logger::println("Id::_arguments"); | 121 Logger::println("Id::_arguments"); |
121 if (!vd->llvmValue) | 122 if (!vd->llvmValue) |
122 vd->llvmValue = p->func().decl->llvmArguments; | 123 vd->llvmValue = p->func()->decl->llvmArguments; |
123 assert(vd->llvmValue); | 124 assert(vd->llvmValue); |
124 return new DVarValue(vd, vd->llvmValue, true); | 125 return new DVarValue(vd, vd->llvmValue, true); |
125 } | 126 } |
126 // _argptr | 127 // _argptr |
127 else if (vd->ident == Id::_argptr) | 128 else if (vd->ident == Id::_argptr) |
128 { | 129 { |
129 Logger::println("Id::_argptr"); | 130 Logger::println("Id::_argptr"); |
130 if (!vd->llvmValue) | 131 if (!vd->llvmValue) |
131 vd->llvmValue = p->func().decl->llvmArgPtr; | 132 vd->llvmValue = p->func()->decl->llvmArgPtr; |
132 assert(vd->llvmValue); | 133 assert(vd->llvmValue); |
133 return new DVarValue(vd, vd->llvmValue, true); | 134 return new DVarValue(vd, vd->llvmValue, true); |
134 } | 135 } |
135 // _dollar | 136 // _dollar |
136 else if (vd->ident == Id::dollar) | 137 else if (vd->ident == Id::dollar) |
152 m = p->ir->CreateBitCast(tid->llvmValue, vartype, "tmp"); | 153 m = p->ir->CreateBitCast(tid->llvmValue, vartype, "tmp"); |
153 else | 154 else |
154 m = tid->llvmValue; | 155 m = tid->llvmValue; |
155 return new DVarValue(vd, m, true); | 156 return new DVarValue(vd, m, true); |
156 } | 157 } |
158 // classinfo | |
159 else if (ClassInfoDeclaration* cid = vd->isClassInfoDeclaration()) | |
160 { | |
161 Logger::println("ClassInfoDeclaration: %s", cid->cd->toChars()); | |
162 assert(cid->cd->llvmClass); | |
163 return new DVarValue(vd, cid->cd->llvmClass, true); | |
164 } | |
157 // nested variable | 165 // nested variable |
158 else if (vd->nestedref) { | 166 else if (vd->nestedref) { |
159 Logger::println("nested variable"); | 167 Logger::println("nested variable"); |
160 return new DVarValue(vd, DtoNestedVariable(vd), true); | 168 return new DVarValue(vd, DtoNestedVariable(vd), true); |
161 } | 169 } |
163 else if (vd->isParameter()) { | 171 else if (vd->isParameter()) { |
164 Logger::println("function param"); | 172 Logger::println("function param"); |
165 if (!vd->llvmValue) { | 173 if (!vd->llvmValue) { |
166 // TODO: determine this properly | 174 // TODO: determine this properly |
167 // this happens when the DMD frontend generates by pointer wrappers for struct opEquals(S) and opCmp(S) | 175 // this happens when the DMD frontend generates by pointer wrappers for struct opEquals(S) and opCmp(S) |
168 vd->llvmValue = &p->func().func->getArgumentList().back(); | 176 vd->llvmValue = &p->func()->func->getArgumentList().back(); |
169 } | 177 } |
170 if (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type) || llvm::isa<llvm::AllocaInst>(vd->llvmValue)) { | 178 if (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type) || llvm::isa<llvm::AllocaInst>(vd->llvmValue)) { |
171 return new DVarValue(vd, vd->llvmValue, true); | 179 return new DVarValue(vd, vd->llvmValue, true); |
172 } | 180 } |
173 else if (llvm::isa<llvm::Argument>(vd->llvmValue)) { | 181 else if (llvm::isa<llvm::Argument>(vd->llvmValue)) { |
175 } | 183 } |
176 else assert(0); | 184 else assert(0); |
177 } | 185 } |
178 else { | 186 else { |
179 // take care of forward references of global variables | 187 // take care of forward references of global variables |
180 if (!vd->llvmTouched && (vd->isDataseg() || (vd->storage_class & STCextern))) // !vd->onstack) | 188 if (vd->isDataseg() || (vd->storage_class & STCextern)) { |
181 vd->toObjFile(); | 189 vd->toObjFile(); |
182 if (!vd->llvmValue) { | 190 DtoConstInitGlobal(vd); |
191 } | |
192 if (!vd->llvmValue || vd->llvmValue->getType()->isAbstract()) { | |
183 Logger::println("global variable not resolved :/ %s", vd->toChars()); | 193 Logger::println("global variable not resolved :/ %s", vd->toChars()); |
184 assert(0); | 194 assert(0); |
185 } | 195 } |
186 return new DVarValue(vd, vd->llvmValue, true); | 196 return new DVarValue(vd, vd->llvmValue, true); |
187 } | 197 } |
222 // this seems to be the static initialiser for structs | 232 // this seems to be the static initialiser for structs |
223 Type* sdecltype = DtoDType(sdecl->type); | 233 Type* sdecltype = DtoDType(sdecl->type); |
224 Logger::print("Sym: type=%s\n", sdecltype->toChars()); | 234 Logger::print("Sym: type=%s\n", sdecltype->toChars()); |
225 assert(sdecltype->ty == Tstruct); | 235 assert(sdecltype->ty == Tstruct); |
226 TypeStruct* ts = (TypeStruct*)sdecltype; | 236 TypeStruct* ts = (TypeStruct*)sdecltype; |
237 ts->sym->toObjFile(); | |
238 DtoConstInitStruct(ts->sym); | |
227 assert(ts->sym->llvmInitZ); | 239 assert(ts->sym->llvmInitZ); |
228 return ts->sym->llvmInitZ; | 240 return ts->sym->llvmInitZ; |
229 } | 241 } |
230 assert(0 && "Only supported const VarExp is of a SymbolDeclaration"); | 242 assert(0 && "Only supported const VarExp is of a SymbolDeclaration"); |
231 return NULL; | 243 return NULL; |
1218 ++argiter; | 1230 ++argiter; |
1219 } | 1231 } |
1220 // nested call | 1232 // nested call |
1221 else if (dfn && dfn->func && dfn->func->isNested()) { | 1233 else if (dfn && dfn->func && dfn->func->isNested()) { |
1222 Logger::println("Nested Call"); | 1234 Logger::println("Nested Call"); |
1223 llvm::Value* contextptr = p->func().decl->llvmNested; | 1235 llvm::Value* contextptr = p->func()->decl->llvmNested; |
1224 assert(contextptr); | 1236 assert(contextptr); |
1225 llargs[j] = p->ir->CreateBitCast(contextptr, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp"); | 1237 llargs[j] = p->ir->CreateBitCast(contextptr, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp"); |
1226 ++j; | 1238 ++j; |
1227 ++argiter; | 1239 ++argiter; |
1228 } | 1240 } |
1328 call->setCallingConv(DtoCallingConv(dlink)); | 1340 call->setCallingConv(DtoCallingConv(dlink)); |
1329 } | 1341 } |
1330 else if (dfn && dfn->cc != (unsigned)-1) { | 1342 else if (dfn && dfn->cc != (unsigned)-1) { |
1331 call->setCallingConv(dfn->cc); | 1343 call->setCallingConv(dfn->cc); |
1332 } | 1344 } |
1345 else if (llvm::isa<llvm::LoadInst>(funcval)) { | |
1346 call->setCallingConv(DtoCallingConv(dlink)); | |
1347 } | |
1333 | 1348 |
1334 return new DImValue(type, retllval, isInPlace); | 1349 return new DImValue(type, retllval, isInPlace); |
1335 } | 1350 } |
1336 | 1351 |
1337 ////////////////////////////////////////////////////////////////////////////////////////// | 1352 ////////////////////////////////////////////////////////////////////////////////////////// |
1443 Logger::print("AddrExp::toElem: %s | %s\n", toChars(), type->toChars()); | 1458 Logger::print("AddrExp::toElem: %s | %s\n", toChars(), type->toChars()); |
1444 LOG_SCOPE; | 1459 LOG_SCOPE; |
1445 DValue* v = e1->toElem(p); | 1460 DValue* v = e1->toElem(p); |
1446 if (v->isField()) | 1461 if (v->isField()) |
1447 return v; | 1462 return v; |
1448 if (DFuncValue* fv = v->isFunc()) | 1463 else if (DFuncValue* fv = v->isFunc()) { |
1449 { | 1464 //Logger::println("FuncDeclaration"); |
1450 Logger::println("FuncDeclaration"); | |
1451 FuncDeclaration* fd = fv->func; | 1465 FuncDeclaration* fd = fv->func; |
1452 assert(fd); | 1466 assert(fd); |
1453 if (fd->llvmValue == 0) | 1467 if (fd->llvmValue == 0) |
1454 fd->toObjFile(); | 1468 fd->toObjFile(); |
1455 return new DFuncValue(fd, fd->llvmValue); | 1469 return new DFuncValue(fd, fd->llvmValue); |
1560 { | 1574 { |
1561 Logger::print("ThisExp::toElem: %s | %s\n", toChars(), type->toChars()); | 1575 Logger::print("ThisExp::toElem: %s | %s\n", toChars(), type->toChars()); |
1562 LOG_SCOPE; | 1576 LOG_SCOPE; |
1563 | 1577 |
1564 if (VarDeclaration* vd = var->isVarDeclaration()) { | 1578 if (VarDeclaration* vd = var->isVarDeclaration()) { |
1565 llvm::Value* v = p->func().decl->llvmThisVar; | 1579 llvm::Value* v = p->func()->decl->llvmThisVar; |
1566 if (llvm::isa<llvm::AllocaInst>(v)) | 1580 if (llvm::isa<llvm::AllocaInst>(v)) |
1567 v = new llvm::LoadInst(v, "tmp", p->scopebb()); | 1581 v = new llvm::LoadInst(v, "tmp", p->scopebb()); |
1568 return new DThisValue(vd, v); | 1582 return new DThisValue(vd, v); |
1569 } | 1583 } |
1570 | 1584 |
2021 Expression* ex = (Expression*)arguments->data[i]; | 2035 Expression* ex = (Expression*)arguments->data[i]; |
2022 Argument* fnarg = Argument::getNth(tf->parameters, i); | 2036 Argument* fnarg = Argument::getNth(tf->parameters, i); |
2023 llvm::Value* a = DtoArgument(fn->getFunctionType()->getParamType(i+1), fnarg, ex); | 2037 llvm::Value* a = DtoArgument(fn->getFunctionType()->getParamType(i+1), fnarg, ex); |
2024 ctorargs.push_back(a); | 2038 ctorargs.push_back(a); |
2025 } | 2039 } |
2026 emem = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb()); | 2040 llvm::CallInst* call = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb()); |
2041 call->setCallingConv(DtoCallingConv(LINKd)); | |
2042 emem = call; | |
2027 } | 2043 } |
2028 } | 2044 } |
2029 else if (ntype->ty == Tstruct) { | 2045 else if (ntype->ty == Tstruct) { |
2030 TypeStruct* ts = (TypeStruct*)ntype; | 2046 TypeStruct* ts = (TypeStruct*)ntype; |
2031 if (ts->isZeroInit()) { | 2047 if (ts->isZeroInit()) { |
2503 temp = true; | 2519 temp = true; |
2504 } | 2520 } |
2505 | 2521 |
2506 llvm::Value* context = DtoGEPi(lval,0,0,"tmp",p->scopebb()); | 2522 llvm::Value* context = DtoGEPi(lval,0,0,"tmp",p->scopebb()); |
2507 const llvm::PointerType* pty = isaPointer(context->getType()->getContainedType(0)); | 2523 const llvm::PointerType* pty = isaPointer(context->getType()->getContainedType(0)); |
2508 llvm::Value* llvmNested = p->func().decl->llvmNested; | 2524 llvm::Value* llvmNested = p->func()->decl->llvmNested; |
2509 if (llvmNested == NULL) { | 2525 if (llvmNested == NULL) { |
2510 llvm::Value* nullcontext = llvm::ConstantPointerNull::get(pty); | 2526 llvm::Value* nullcontext = llvm::ConstantPointerNull::get(pty); |
2511 p->ir->CreateStore(nullcontext, context); | 2527 p->ir->CreateStore(nullcontext, context); |
2512 } | 2528 } |
2513 else { | 2529 else { |
2537 Type* ty = DtoDType(type); | 2553 Type* ty = DtoDType(type); |
2538 const llvm::Type* t = DtoType(ty); | 2554 const llvm::Type* t = DtoType(ty); |
2539 Logger::cout() << "array literal has llvm type: " << *t << '\n'; | 2555 Logger::cout() << "array literal has llvm type: " << *t << '\n'; |
2540 | 2556 |
2541 llvm::Value* mem = 0; | 2557 llvm::Value* mem = 0; |
2558 bool inplace_slice = false; | |
2559 | |
2542 if (!p->topexp() || p->topexp()->e2 != this) { | 2560 if (!p->topexp() || p->topexp()->e2 != this) { |
2543 assert(DtoDType(type)->ty == Tsarray); | 2561 assert(DtoDType(type)->ty == Tsarray); |
2544 mem = new llvm::AllocaInst(t,"arrayliteral",p->topallocapoint()); | 2562 mem = new llvm::AllocaInst(t,"arrayliteral",p->topallocapoint()); |
2545 } | 2563 } |
2546 else if (p->topexp()->e2 == this) { | 2564 else if (p->topexp()->e2 == this) { |
2547 DValue* tlv = p->topexp()->v; | 2565 DValue* tlv = p->topexp()->v; |
2548 if (DSliceValue* sv = tlv->isSlice()) { | 2566 if (DSliceValue* sv = tlv->isSlice()) { |
2549 assert(sv->len == 0); | 2567 assert(sv->len == 0); |
2550 mem = sv->ptr; | 2568 mem = sv->ptr; |
2569 inplace_slice = true; | |
2551 } | 2570 } |
2552 else { | 2571 else { |
2553 mem = p->topexp()->v->getLVal(); | 2572 mem = p->topexp()->v->getLVal(); |
2554 } | 2573 } |
2555 assert(mem); | 2574 assert(mem); |
2556 if (!isaPointer(mem->getType()) || | 2575 if (!isaPointer(mem->getType()) || |
2557 !isaArray(mem->getType()->getContainedType(0))) | 2576 !isaArray(mem->getType()->getContainedType(0))) |
2558 { | 2577 { |
2578 assert(!inplace_slice); | |
2559 assert(ty->ty == Tarray); | 2579 assert(ty->ty == Tarray); |
2560 // we need to give this array literal storage | 2580 // we need to give this array literal storage |
2561 const llvm::ArrayType* arrty = llvm::ArrayType::get(DtoType(ty->next), elements->dim); | 2581 const llvm::ArrayType* arrty = llvm::ArrayType::get(DtoType(ty->next), elements->dim); |
2562 mem = new llvm::AllocaInst(arrty, "arrayliteral", p->topallocapoint()); | 2582 mem = new llvm::AllocaInst(arrty, "arrayliteral", p->topallocapoint()); |
2563 } | 2583 } |
2580 if (!im || !im->inPlace()) { | 2600 if (!im || !im->inPlace()) { |
2581 DtoAssign(vv, e); | 2601 DtoAssign(vv, e); |
2582 } | 2602 } |
2583 } | 2603 } |
2584 | 2604 |
2585 if (ty->ty == Tsarray) | 2605 if (ty->ty == Tsarray || (ty->ty == Tarray && inplace_slice)) |
2586 return new DImValue(type, mem, true); | 2606 return new DImValue(type, mem, true); |
2587 else if (ty->ty == Tarray) | 2607 else if (ty->ty == Tarray) |
2588 return new DSliceValue(type, DtoConstSize_t(elements->dim), DtoGEPi(mem,0,0,"tmp")); | 2608 return new DSliceValue(type, DtoConstSize_t(elements->dim), DtoGEPi(mem,0,0,"tmp")); |
2589 else { | 2609 else { |
2590 assert(0); | 2610 assert(0); |