mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-20 23:03:14 +01:00
[svn r12] fixed accessing aggregate fields of aggregates
removed some useless branches for successive scopes ala {}{}{}
This commit is contained in:
@@ -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; }
|
||||
};
|
||||
|
||||
42
gen/toir.c
42
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<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);
|
||||
|
||||
20
gen/tollvm.c
20
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<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);
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
24
gen/toobj.c
24
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<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
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
|
||||
@@ -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
10
test/scope1.d
Normal file
@@ -0,0 +1,10 @@
|
||||
module scope1;
|
||||
|
||||
void main()
|
||||
{
|
||||
printf("1\n");
|
||||
{
|
||||
scope(exit) printf("2\n");
|
||||
}
|
||||
printf("3\n");
|
||||
}
|
||||
@@ -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);}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user