diff --git a/dmd/aggregate.h b/dmd/aggregate.h index 2307ff49..58475d63 100644 --- a/dmd/aggregate.h +++ b/dmd/aggregate.h @@ -18,6 +18,8 @@ #include "root.h" #include "dsymbol.h" +#include + struct Identifier; struct Type; struct TypeFunction; @@ -97,7 +99,7 @@ struct AggregateDeclaration : ScopeDsymbol llvm::Type* llvmType; llvm::Value* llvmVtbl; llvm::Constant* llvmInitZ; - virtual unsigned offsetToIndex(unsigned os); // converts a DMD field offsets to LLVM struct index + virtual void offsetToIndex(unsigned os, std::vector& result); // converts a DMD field offsets to LLVM struct index vector AggregateDeclaration *isAggregateDeclaration() { return this; } }; @@ -232,7 +234,7 @@ struct ClassDeclaration : AggregateDeclaration Symbol *vtblsym; - virtual unsigned offsetToIndex(unsigned os); + virtual void offsetToIndex(unsigned os, std::vector& result); ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; } }; diff --git a/gen/toir.c b/gen/toir.c index 2d2607e7..bddbe1b9 100644 --- a/gen/toir.c +++ b/gen/toir.c @@ -434,15 +434,15 @@ elem* AddExp::toElem(IRState* p) if (e1->type != e2->type) { if (e1->type->ty == Tpointer && e1->type->next->ty == Tstruct) { - assert(l->field); + //assert(l->field); llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); assert(r->type == elem::CONST); llvm::ConstantInt* cofs = llvm::cast(r->val); TypeStruct* ts = (TypeStruct*)e1->type->next; - llvm::Value* offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, ts->sym->offsetToIndex(cofs->getZExtValue()), false); - - e->mem = LLVM_DtoGEP(l->getValue(), zero, offset, "tmp", p->scopebb()); + std::vector offsets(1,0); + ts->sym->offsetToIndex(cofs->getZExtValue(), offsets); + e->mem = LLVM_DtoGEP(l->getValue(), offsets, "tmp", p->scopebb()); e->type = elem::VAR; e->field = true; } @@ -1126,12 +1126,11 @@ elem* SymOffExp::toElem(IRState* p) if (vd->type->ty == Tstruct && !(type->ty == Tpointer && type->next == vd->type)) { TypeStruct* vdt = (TypeStruct*)vd->type; e = new elem; - llvm::Value* idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); - llvm::Value* idx1 = llvm::ConstantInt::get(llvm::Type::Int32Ty, (uint64_t)vdt->sym->offsetToIndex(offset), false); - //const llvm::Type* _typ = llvm::GetElementPtrInst::getIndexedType(LLVM_DtoType(type), idx1); + std::vector dst(1,0); + vdt->sym->offsetToIndex(offset, dst); llvm::Value* ptr = vd->llvmValue; assert(ptr); - e->mem = LLVM_DtoGEP(ptr,idx0,idx1,"tmp",p->scopebb()); + e->mem = LLVM_DtoGEP(ptr,dst,"tmp",p->scopebb()); e->type = elem::VAL; e->field = true; } @@ -1210,26 +1209,24 @@ elem* DotVarExp::toElem(IRState* p) Logger::print("e1->type=%s\n", e1->type->toChars()); if (VarDeclaration* vd = var->isVarDeclaration()) { - size_t vdoffset = (size_t)-1; + std::vector vdoffsets(1,0); llvm::Value* src = 0; if (e1->type->ty == Tpointer) { assert(e1->type->next->ty == Tstruct); TypeStruct* ts = (TypeStruct*)e1->type->next; - vdoffset = ts->sym->offsetToIndex(vd->offset); - Logger::println("Struct member offset:%d index:%d", vd->offset, vdoffset); + ts->sym->offsetToIndex(vd->offset, vdoffsets); + Logger::println("Struct member offset:%d", vd->offset); src = l->val; } else if (e1->type->ty == Tclass) { TypeClass* tc = (TypeClass*)e1->type; Logger::println("Class member offset: %d", vd->offset); - vdoffset = tc->sym->offsetToIndex(vd->offset); + tc->sym->offsetToIndex(vd->offset, vdoffsets); src = l->getValue(); } - assert(vdoffset != (size_t)-1); + assert(vdoffsets.size() != 1); assert(src != 0); - llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); - llvm::Value* offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, vdoffset, false); - llvm::Value* arrptr = LLVM_DtoGEP(src,zero,offset,"tmp",p->scopebb()); + llvm::Value* arrptr = LLVM_DtoGEP(src,vdoffsets,"tmp",p->scopebb()); e->mem = arrptr; Logger::cout() << "mem: " << *e->mem << '\n'; e->type = elem::VAR; @@ -2588,12 +2585,17 @@ void ScopeStatement::toIR(IRState* p) llvm::BasicBlock* oldend = gIR->scopeend(); IRScope irs; - irs.begin = new llvm::BasicBlock("scope", gIR->topfunc(), oldend); + // remove useless branches by clearing and reusing the current basicblock + llvm::BasicBlock* bb = gIR->scopebegin(); + if (bb->empty()) { + irs.begin = bb; + } + else { + irs.begin = new llvm::BasicBlock("scope", gIR->topfunc(), oldend); + new llvm::BranchInst(irs.begin, gIR->scopebegin()); + } irs.end = new llvm::BasicBlock("endscope", gIR->topfunc(), oldend); - // pass the previous BB into this - new llvm::BranchInst(irs.begin, gIR->scopebegin()); - gIR->scope() = irs; statement->toIR(p); diff --git a/gen/tollvm.c b/gen/tollvm.c index 85ab7aac..b4e094a7 100644 --- a/gen/tollvm.c +++ b/gen/tollvm.c @@ -460,7 +460,11 @@ llvm::Constant* LLVM_DtoStructInitializer(StructInitializer* si) VarDeclaration* vd = (VarDeclaration*)si->vars.data[i]; assert(vd); Logger::println("vars[%d] = %s", i, vd->toChars()); - unsigned idx = si->ad->offsetToIndex(vd->offset); + + std::vector idxs; + si->ad->offsetToIndex(vd->offset, idxs); + assert(idxs.size() == 1); + unsigned idx = idxs[0]; llvm::Constant* v = 0; @@ -819,3 +823,17 @@ llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, llvm::Value* i0, llvm::Value* i1, con v[1] = i1; return new llvm::GetElementPtrInst(ptr, v.begin(), v.end(), var, bb); } + +llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, const std::vector& src, const std::string& var, llvm::BasicBlock* bb) +{ + size_t n = src.size(); + std::vector dst(n); + Logger::cout() << "indices:"; + for (size_t i=0; i& src, const std::string& var, llvm::BasicBlock* bb); #include "enums.h" diff --git a/gen/toobj.c b/gen/toobj.c index 9a7551f6..aa20a9b6 100644 --- a/gen/toobj.c +++ b/gen/toobj.c @@ -139,15 +139,27 @@ void Declaration::toObjFile() /* ================================================================== */ /// Returns the LLVM style index from a DMD style offset -unsigned AggregateDeclaration::offsetToIndex(unsigned os) +void AggregateDeclaration::offsetToIndex(unsigned os, std::vector& result) { + unsigned vos = 0; for (unsigned i=0; ioffset) - return i; + if (vd->type->ty == Tstruct) { + if (vos + vd->type->size() > os) { + TypeStruct* ts = (TypeStruct*)vd->type; + StructDeclaration* sd = ts->sym; + result.push_back(i); + sd->offsetToIndex(os - vos, result); + return; + } + } + else if (os == vd->offset) { + result.push_back(i); + return; + } + vos += vd->offset; } assert(0 && "Offset not found in any aggregate field"); - return 0; } /* ================================================================== */ @@ -175,12 +187,12 @@ static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsig /// Returns the LLVM style index from a DMD style offset /// Handles class inheritance -unsigned ClassDeclaration::offsetToIndex(unsigned os) +void ClassDeclaration::offsetToIndex(unsigned os, std::vector& result) { unsigned idx = 0; unsigned r = LLVM_ClassOffsetToIndex(this, os, idx); assert(r != (unsigned)-1 && "Offset not found in any aggregate field"); - return r+1; // vtable is 0 + result.push_back(r+1); // vtable is 0 } /* ================================================================== */ diff --git a/test/classes5.d b/test/classes5.d index 864730b2..ce333048 100644 --- a/test/classes5.d +++ b/test/classes5.d @@ -13,5 +13,11 @@ class C void main() { - //C c = new C; + C c = new C; + long* lp = void; + {c.s.l = 64;} + {assert(c.s.l == 64);} + {lp = &c.s.l;} + {assert(*lp == 64);} + printf("classes5 success\n"); } diff --git a/test/scope1.d b/test/scope1.d new file mode 100644 index 00000000..c74670ed --- /dev/null +++ b/test/scope1.d @@ -0,0 +1,10 @@ +module scope1; + +void main() +{ + printf("1\n"); + { + scope(exit) printf("2\n"); + } + printf("3\n"); +} diff --git a/test/structs3.d b/test/structs3.d index beb8af8b..79e72f1b 100644 --- a/test/structs3.d +++ b/test/structs3.d @@ -2,8 +2,8 @@ module structs3; struct S { - float l; char c; + float f; } struct T @@ -14,4 +14,17 @@ struct T void main() { + T t; + float f = void; + float* fp = void; + {f = t.s.f;} + {t.s.f = 0.0;} + {fp = &t.s.f;} + {*fp = 1.0;} + {assert(t.s.f == 1.0);} + {assert(*(&t.s.f) == 1.0);} + {t.s.c = 'a';} + {assert(t.s.c == 'a');} + {t.l = 64;} + {assert(t.l == 64);} }