[svn r12] fixed accessing aggregate fields of aggregates

removed some useless branches for successive scopes ala {}{}{}
This commit is contained in:
Tomas Lindquist Olsen
2007-09-27 06:03:06 +02:00
parent 2fe995a0c7
commit 1609cb80d4
8 changed files with 95 additions and 31 deletions

View File

@@ -18,6 +18,8 @@
#include "root.h"
#include "dsymbol.h"
#include <vector>
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<unsigned>& 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<unsigned>& result);
ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
};

View File

@@ -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<llvm::ConstantInt>(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<unsigned> 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<unsigned> 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<unsigned> 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);

View File

@@ -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<unsigned> 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<unsigned>& src, const std::string& var, llvm::BasicBlock* bb)
{
size_t n = src.size();
std::vector<llvm::Value*> dst(n);
Logger::cout() << "indices:";
for (size_t i=0; i<n; ++i)
{
Logger::cout() << ' ' << i;
dst[i] = llvm::ConstantInt::get(llvm::Type::Int32Ty, src[i], false);
}
Logger::cout() << '\n';
return new llvm::GetElementPtrInst(ptr, dst.begin(), dst.end(), var, bb);
}

View File

@@ -37,5 +37,6 @@ llvm::Function* LLVM_DeclareMemCpy32();
llvm::Function* LLVM_DeclareMemCpy64();
llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, llvm::Value* i0, llvm::Value* i1, const std::string& var, llvm::BasicBlock* bb);
llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, const std::vector<unsigned>& src, const std::string& var, llvm::BasicBlock* bb);
#include "enums.h"

View File

@@ -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<unsigned>& result)
{
unsigned vos = 0;
for (unsigned i=0; i<fields.dim; ++i) {
VarDeclaration* vd = (VarDeclaration*)fields.data[i];
if (os == vd->offset)
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<unsigned>& 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
}
/* ================================================================== */

View File

@@ -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");
}

10
test/scope1.d Normal file
View File

@@ -0,0 +1,10 @@
module scope1;
void main()
{
printf("1\n");
{
scope(exit) printf("2\n");
}
printf("3\n");
}

View File

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