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);