# HG changeset patch # User lindquist # Date 1193819658 -3600 # Node ID 714057ff2dbb015cc3b48d7f82cea29c249d27fa # Parent 9e1bd80a7e983cdcb2948d00b2b9207f1073e775 [svn r81] Fixed: Union support was very buggy. Should be fairly solid now. diff -r 9e1bd80a7e98 -r 714057ff2dbb dmd/aggregate.h --- a/dmd/aggregate.h Wed Oct 31 07:24:02 2007 +0100 +++ b/dmd/aggregate.h Wed Oct 31 09:34:18 2007 +0100 @@ -104,7 +104,6 @@ llvm::ConstantStruct* llvmConstVtbl; llvm::Constant* llvmInitZ; bool llvmHasUnions; - virtual size_t offsetToIndex(Type* t, unsigned os, std::vector& result); // converts a DMD field offsets to LLVM struct index vector AggregateDeclaration *isAggregateDeclaration() { return this; } }; @@ -240,7 +239,7 @@ Symbol *vtblsym; - virtual size_t offsetToIndex(Type* t, unsigned os, std::vector& result); + void offsetToIndex(Type* t, unsigned os, std::vector& result); ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; } }; diff -r 9e1bd80a7e98 -r 714057ff2dbb gen/toir.c --- a/gen/toir.c Wed Oct 31 07:24:02 2007 +0100 +++ b/gen/toir.c Wed Oct 31 09:34:18 2007 +0100 @@ -640,9 +640,8 @@ llvm::ConstantInt* cofs = llvm::cast(r->val); TypeStruct* ts = (TypeStruct*)e1type->next; - std::vector offsets(1,0); - ts->sym->offsetToIndex(t->next, cofs->getZExtValue(), offsets); - e->mem = LLVM_DtoGEP(l->getValue(), offsets, "tmp", p->scopebb()); + std::vector offsets; + e->mem = LLVM_DtoIndexStruct(l->getValue(), ts->sym, t->next, cofs->getZExtValue(), offsets); e->type = elem::VAR; e->field = true; } @@ -1454,8 +1453,9 @@ e->mem = p->ir->CreateBitCast(llvalue, llt, "tmp"); } else { - std::vector dst(1,0); - size_t fo = vdt->sym->offsetToIndex(tnext, offset, dst); + std::vector dst; + e->mem = LLVM_DtoIndexStruct(llvalue,vdt->sym, tnext, offset, dst); + /*size_t fo = vdt->sym->offsetToIndex(tnext, offset, dst); llvm::Value* ptr = llvalue; assert(ptr); e->mem = LLVM_DtoGEP(ptr,dst,"tmp"); @@ -1469,7 +1469,7 @@ } else if (fo) { e->mem = new llvm::GetElementPtrInst(e->mem, LLVM_DtoConstUint(fo), "tmp", p->scopebb()); - } + }*/ } e->type = elem::VAL; e->field = true; @@ -1564,25 +1564,26 @@ Logger::print("e1->type=%s\n", e1type->toChars()); if (VarDeclaration* vd = var->isVarDeclaration()) { - std::vector vdoffsets(1,0); - llvm::Value* src = 0; + llvm::Value* arrptr; if (e1type->ty == Tpointer) { assert(e1type->next->ty == Tstruct); TypeStruct* ts = (TypeStruct*)e1type->next; - ts->sym->offsetToIndex(vd->type, vd->offset, vdoffsets); Logger::println("Struct member offset:%d", vd->offset); - src = l->val ? l->val : l->mem; + llvm::Value* src = l->val ? l->val : l->mem; + std::vector vdoffsets; + arrptr = LLVM_DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets); } else if (e1->type->ty == Tclass) { TypeClass* tc = (TypeClass*)e1type; Logger::println("Class member offset: %d", vd->offset); + std::vector vdoffsets(1,0); tc->sym->offsetToIndex(vd->type, vd->offset, vdoffsets); - src = l->getValue(); + llvm::Value* src = l->getValue(); + Logger::cout() << "src: " << *src << '\n'; + arrptr = LLVM_DtoGEP(src,vdoffsets,"tmp",p->scopebb()); } - assert(vdoffsets.size() != 1); - assert(src != 0); - Logger::cout() << "src: " << *src << '\n'; - llvm::Value* arrptr = LLVM_DtoGEP(src,vdoffsets,"tmp",p->scopebb()); + else + assert(0); e->mem = arrptr; Logger::cout() << "mem: " << *e->mem << '\n'; e->type = elem::VAR; @@ -1698,7 +1699,10 @@ } const llvm::StructType* t = llvm::StructType::get(tys); if (t != llt) { - assert(gTargetData->getTypeSize(t) == gTargetData->getTypeSize(llt)); + if (gTargetData->getTypeSize(t) != gTargetData->getTypeSize(llt)) { + Logger::cout() << "got size " << gTargetData->getTypeSize(t) << ", expected " << gTargetData->getTypeSize(llt) << '\n'; + assert(0 && "type size mismatch"); + } sptr = p->ir->CreateBitCast(sptr, llvm::PointerType::get(t), "tmp"); Logger::cout() << "sptr type is now: " << *t << '\n'; } diff -r 9e1bd80a7e98 -r 714057ff2dbb gen/tollvm.c --- a/gen/tollvm.c Wed Oct 31 07:24:02 2007 +0100 +++ b/gen/tollvm.c Wed Oct 31 09:34:18 2007 +0100 @@ -1387,3 +1387,62 @@ new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); } + +////////////////////////////////////////////////////////////////////////////////////////// + +llvm::Value* LLVM_DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector& idxs) +{ + Logger::println("checking for offset %u type %s:", os, t->toChars()); + LOG_SCOPE; + + if (idxs.empty()) + idxs.push_back(0); + + const llvm::Type* llt = llvm::PointerType::get(LLVM_DtoType(t)); + + for (unsigned i=0; ifields.dim; ++i) { + VarDeclaration* vd = (VarDeclaration*)sd->fields.data[i]; + Type* vdtype = LLVM_DtoDType(vd->type); + Logger::println("found %u type %s", vd->offset, vdtype->toChars()); + assert(vd->llvmFieldIndex >= 0); + if (os == vd->offset && vdtype == t) { + idxs.push_back(vd->llvmFieldIndex); + ptr = LLVM_DtoGEP(ptr, idxs, "tmp"); + if (ptr->getType() != llt) + ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); + if (vd->llvmFieldIndexOffset) + ptr = new llvm::GetElementPtrInst(ptr, LLVM_DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb()); + return ptr; + } + else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) { + TypeStruct* ts = (TypeStruct*)vdtype; + StructDeclaration* ssd = ts->sym; + idxs.push_back(vd->llvmFieldIndex); + if (vd->llvmFieldIndexOffset) { + Logger::println("has union field offset"); + ptr = LLVM_DtoGEP(ptr, idxs, "tmp"); + if (ptr->getType() != llt) + ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); + ptr = new llvm::GetElementPtrInst(ptr, LLVM_DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb()); + std::vector tmp; + return LLVM_DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp); + } + else { + const llvm::Type* sty = llvm::PointerType::get(LLVM_DtoType(vd->type)); + if (ptr->getType() != sty) { + ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp"); + std::vector tmp; + return LLVM_DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp); + } + else { + return LLVM_DtoIndexStruct(ptr, ssd, t, os-vd->offset, idxs); + } + } + } + } + + size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0)); + assert(os % llt_sz == 0); + ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); + return new llvm::GetElementPtrInst(ptr, LLVM_DtoConstUint(os / llt_sz), "tmp", gIR->scopebb()); +} diff -r 9e1bd80a7e98 -r 714057ff2dbb gen/tollvm.h --- a/gen/tollvm.h Wed Oct 31 07:24:02 2007 +0100 +++ b/gen/tollvm.h Wed Oct 31 09:34:18 2007 +0100 @@ -65,4 +65,6 @@ void LLVM_DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes); +llvm::Value* LLVM_DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector& idxs); + #include "enums.h" diff -r 9e1bd80a7e98 -r 714057ff2dbb gen/toobj.c --- a/gen/toobj.c Wed Oct 31 07:24:02 2007 +0100 +++ b/gen/toobj.c Wed Oct 31 09:34:18 2007 +0100 @@ -148,67 +148,6 @@ /* ================================================================== */ -/// Returns the LLVM style index from a DMD style offset -size_t AggregateDeclaration::offsetToIndex(Type* t, unsigned os, std::vector& result) -{ - Logger::println("checking for offset %u type %s:", os, t->toChars()); - LOG_SCOPE; - for (unsigned i=0; itype); - Logger::println("found %u type %s", vd->offset, vdtype->toChars()); - if (os == vd->offset && vdtype == t) { - assert(vd->llvmFieldIndex >= 0); - result.push_back(vd->llvmFieldIndex); - return vd->llvmFieldIndexOffset; - } - else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) { - TypeStruct* ts = (TypeStruct*)vdtype; - StructDeclaration* sd = ts->sym; - result.push_back(i); - return sd->offsetToIndex(t, os - vd->offset, result); - } - } - //assert(0 && "Offset not found in any aggregate field"); - return (size_t)-1; -} - -/* ================================================================== */ - -static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx) -{ - // start at the bottom of the inheritance chain - if (cd->baseClass != 0) { - unsigned o = LLVM_ClassOffsetToIndex(cd->baseClass, os, idx); - if (o != (unsigned)-1) - return o; - } - - // check this class - unsigned i; - for (i=0; ifields.dim; ++i) { - VarDeclaration* vd = (VarDeclaration*)cd->fields.data[i]; - if (os == vd->offset) - return i+idx; - } - idx += i; - - return (unsigned)-1; -} - -/// Returns the LLVM style index from a DMD style offset -/// Handles class inheritance -size_t ClassDeclaration::offsetToIndex(Type* t, 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"); - result.push_back(r+1); // vtable is 0 - return 0; -} - -/* ================================================================== */ - void InterfaceDeclaration::toObjFile() { Logger::println("Ignoring InterfaceDeclaration::toObjFile for %s", toChars()); @@ -271,7 +210,7 @@ const llvm::Type* t = LLVM_DtoType(i->second.var->type); size_t s = gTargetData->getTypeSize(t); if (s > prevsize) { - fieldpad = s - prevsize; + fieldpad += s - prevsize; prevsize = s; } llvmHasUnions = true; @@ -396,6 +335,37 @@ /* ================================================================== */ +static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx) +{ + // start at the bottom of the inheritance chain + if (cd->baseClass != 0) { + unsigned o = LLVM_ClassOffsetToIndex(cd->baseClass, os, idx); + if (o != (unsigned)-1) + return o; + } + + // check this class + unsigned i; + for (i=0; ifields.dim; ++i) { + VarDeclaration* vd = (VarDeclaration*)cd->fields.data[i]; + if (os == vd->offset) + return i+idx; + } + idx += i; + + return (unsigned)-1; +} + +void ClassDeclaration::offsetToIndex(Type* t, 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"); + result.push_back(r+1); // vtable is 0 +} + +/* ================================================================== */ + static void LLVM_AddBaseClassData(BaseClasses* bcs) { // add base class data members first