mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-12 02:43:14 +01:00
[svn r58] Fixed cond expression resulting in a non-basic type.
Fixed identity expression for dynamic arrays. Revamped the system to keep track of lvalues and rvalues and their relations. Typedef declaration now generate the custom typeinfo. Other bugfixes.
This commit is contained in:
@@ -40,6 +40,7 @@ namespace llvm
|
||||
class Type;
|
||||
class Value;
|
||||
class Constant;
|
||||
class ConstantStruct;
|
||||
}
|
||||
|
||||
struct AggregateDeclaration : ScopeDsymbol
|
||||
@@ -98,6 +99,7 @@ struct AggregateDeclaration : ScopeDsymbol
|
||||
bool llvmInProgress;
|
||||
llvm::Type* llvmType;
|
||||
llvm::Value* llvmVtbl;
|
||||
llvm::ConstantStruct* llvmConstVtbl;
|
||||
llvm::Constant* llvmInitZ;
|
||||
virtual void offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result); // converts a DMD field offsets to LLVM struct index vector
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
|
||||
|
||||
llvmType = NULL;
|
||||
llvmVtbl = NULL;
|
||||
llvmConstVtbl = NULL;
|
||||
llvmInitZ = NULL;
|
||||
llvmInProgress = false;
|
||||
}
|
||||
|
||||
25
gen/arrays.c
25
gen/arrays.c
@@ -100,6 +100,7 @@ void LLVM_DtoArrayAssign(llvm::Value* dst, llvm::Value* src)
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::cout() << "array assignment type dont match: " << *dst->getType() << '\n' << *src->getType() << '\n';
|
||||
if (!llvm::isa<llvm::ArrayType>(src->getType()->getContainedType(0)))
|
||||
{
|
||||
Logger::cout() << "invalid: " << *src << '\n';
|
||||
@@ -109,7 +110,7 @@ void LLVM_DtoArrayAssign(llvm::Value* dst, llvm::Value* src)
|
||||
llvm::Type* dstty = llvm::PointerType::get(arrty->getElementType());
|
||||
|
||||
llvm::Value* dstlen = LLVM_DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
|
||||
llvm::Value* srclen = llvm::ConstantInt::get(LLVM_DtoSize_t(), arrty->getNumElements(), false);
|
||||
llvm::Value* srclen = LLVM_DtoConstSize_t(arrty->getNumElements());
|
||||
new llvm::StoreInst(srclen, dstlen, gIR->scopebb());
|
||||
|
||||
llvm::Value* dstptr = LLVM_DtoGEPi(dst,0,1,"tmp",gIR->scopebb());
|
||||
@@ -551,3 +552,25 @@ llvm::Value* LLVM_DtoArrayCastLength(llvm::Value* len, const llvm::Type* elemty,
|
||||
args.push_back(llvm::ConstantInt::get(LLVM_DtoSize_t(), gTargetData->getTypeSize(newelemty), false));
|
||||
return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
llvm::Value* LLVM_DtoDynArrayIs(TOK op, llvm::Value* l, llvm::Value* r)
|
||||
{
|
||||
assert(l->getType() == r->getType());
|
||||
|
||||
llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
|
||||
|
||||
llvm::Value* ll = gIR->ir->CreateLoad(LLVM_DtoGEPi(l, 0,0, "tmp"),"tmp");
|
||||
llvm::Value* rl = gIR->ir->CreateLoad(LLVM_DtoGEPi(r, 0,0, "tmp"),"tmp");
|
||||
llvm::Value* b1 = gIR->ir->CreateICmp(pred,ll,rl,"tmp");
|
||||
|
||||
llvm::Value* lp = gIR->ir->CreateLoad(LLVM_DtoGEPi(l, 0,1, "tmp"),"tmp");
|
||||
llvm::Value* rp = gIR->ir->CreateLoad(LLVM_DtoGEPi(r, 0,1, "tmp"),"tmp");
|
||||
llvm::Value* b2 = gIR->ir->CreateICmp(pred,lp,rp,"tmp");
|
||||
|
||||
llvm::Value* b = gIR->ir->CreateAnd(b1,b2,"tmp");
|
||||
if (op == TOKnotidentity)
|
||||
return gIR->ir->CreateNot(b,"tmp");
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@ void LLVM_DtoCatArrayElement(llvm::Value* arr, Expression* exp);
|
||||
void LLVM_DtoStaticArrayCopy(llvm::Value* dst, llvm::Value* src);
|
||||
|
||||
llvm::Value* LLVM_DtoStaticArrayCompare(TOK op, llvm::Value* l, llvm::Value* r);
|
||||
|
||||
llvm::Value* LLVM_DtoDynArrayCompare(TOK op, llvm::Value* l, llvm::Value* r);
|
||||
llvm::Value* LLVM_DtoDynArrayIs(TOK op, llvm::Value* l, llvm::Value* r);
|
||||
|
||||
llvm::Value* LLVM_DtoArrayCastLength(llvm::Value* len, const llvm::Type* elemty, const llvm::Type* newelemty);
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@ IRState::IRState()
|
||||
{
|
||||
dmodule = 0;
|
||||
module = 0;
|
||||
inLvalue = false;
|
||||
emitMain = false;
|
||||
mainFunc = 0;
|
||||
ir.state = this;
|
||||
@@ -71,10 +70,9 @@ IRStruct& IRState::topstruct()
|
||||
return structs.back();
|
||||
}
|
||||
|
||||
llvm::Value* IRState::toplval()
|
||||
IRExp* IRState::topexp()
|
||||
{
|
||||
assert(!lvals.empty() && "Lval vector is empty!");
|
||||
return lvals.back();
|
||||
return exps.empty() ? NULL : &exps.back();
|
||||
}
|
||||
|
||||
IRScope& IRState::scope()
|
||||
@@ -153,3 +151,18 @@ IRFunction::IRFunction(FuncDeclaration* fd)
|
||||
func = NULL;
|
||||
allocapoint = NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IRExp::IRExp()
|
||||
{
|
||||
e1 = e2 = NULL;
|
||||
v = NULL;
|
||||
}
|
||||
|
||||
IRExp::IRExp(Expression* l, Expression* r, llvm::Value* val)
|
||||
{
|
||||
e1 = l;
|
||||
e2 = r;
|
||||
v = val;
|
||||
}
|
||||
|
||||
@@ -88,6 +88,15 @@ struct IRBuilderHelper
|
||||
LLVMBuilder* operator->();
|
||||
};
|
||||
|
||||
struct IRExp
|
||||
{
|
||||
Expression* e1;
|
||||
Expression* e2;
|
||||
llvm::Value* v;
|
||||
IRExp();
|
||||
IRExp(Expression* l, Expression* r, llvm::Value* val);
|
||||
};
|
||||
|
||||
// represents the module
|
||||
struct IRState
|
||||
{
|
||||
@@ -119,11 +128,10 @@ struct IRState
|
||||
bool emitMain;
|
||||
llvm::Function* mainFunc;
|
||||
|
||||
// L-values
|
||||
bool inLvalue;
|
||||
typedef std::vector<llvm::Value*> LvalVec;
|
||||
LvalVec lvals;
|
||||
llvm::Value* toplval();
|
||||
// expression l/r value handling
|
||||
typedef std::vector<IRExp> ExpVec;
|
||||
ExpVec exps;
|
||||
IRExp* topexp();
|
||||
|
||||
// basic block scopes
|
||||
std::vector<IRScope> scopes;
|
||||
@@ -141,7 +149,7 @@ struct IRState
|
||||
// might be a better way but it works. problem is I only get a
|
||||
// VarDeclaration for __dollar, but I can't see how to get the
|
||||
// array pointer from this :(
|
||||
LvalVec arrays;
|
||||
std::vector<llvm::Value*> arrays;
|
||||
|
||||
// builder helper
|
||||
IRBuilderHelper ir;
|
||||
|
||||
@@ -51,10 +51,10 @@ void ReturnStatement::toIR(IRState* p)
|
||||
Logger::println("ReturnStatement::toIR(%d): %s", rsi++, toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
IRFunction::FinallyVec& fin = p->func().finallys;
|
||||
|
||||
if (exp)
|
||||
{
|
||||
Logger::println("return type is: %s", exp->type->toChars());
|
||||
|
||||
Type* exptype = LLVM_DtoDType(exp->type);
|
||||
TY expty = exptype->ty;
|
||||
if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
|
||||
@@ -63,28 +63,36 @@ void ReturnStatement::toIR(IRState* p)
|
||||
TypeFunction* f = p->topfunctype();
|
||||
assert(f->llvmRetInPtr && f->llvmRetArg);
|
||||
|
||||
p->lvals.push_back(f->llvmRetArg);
|
||||
p->exps.push_back(IRExp(NULL,exp,f->llvmRetArg));
|
||||
elem* e = exp->toElem(p);
|
||||
p->lvals.pop_back();
|
||||
p->exps.pop_back();
|
||||
|
||||
if (expty == Tstruct) {
|
||||
if (!e->inplace) {
|
||||
assert(e->mem);
|
||||
LLVM_DtoStructCopy(f->llvmRetArg,e->mem);
|
||||
}
|
||||
if (!e->inplace)
|
||||
LLVM_DtoStructCopy(f->llvmRetArg,e->getValue());
|
||||
}
|
||||
else if (expty == Tdelegate) {
|
||||
LLVM_DtoDelegateCopy(f->llvmRetArg,e->mem);
|
||||
if (!e->inplace)
|
||||
LLVM_DtoDelegateCopy(f->llvmRetArg,e->getValue());
|
||||
}
|
||||
else if (expty == Tarray) {
|
||||
if (e->type == elem::SLICE) {
|
||||
assert(e->mem);
|
||||
LLVM_DtoSetArray(f->llvmRetArg,e->arg,e->mem);
|
||||
}
|
||||
// else the return value is a variable and should already have been assigned by now
|
||||
else if (!e->inplace) {
|
||||
if (e->type == elem::NUL) {
|
||||
LLVM_DtoNullArray(f->llvmRetArg);
|
||||
}
|
||||
else {
|
||||
LLVM_DtoArrayAssign(f->llvmRetArg, e->getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
|
||||
IRFunction::FinallyVec& fin = p->func().finallys;
|
||||
if (fin.empty())
|
||||
new llvm::ReturnInst(p->scopebb());
|
||||
else {
|
||||
@@ -98,6 +106,8 @@ void ReturnStatement::toIR(IRState* p)
|
||||
llvm::Value* v = e->getValue();
|
||||
delete e;
|
||||
Logger::cout() << "return value is '" <<*v << "'\n";
|
||||
|
||||
IRFunction::FinallyVec& fin = p->func().finallys;
|
||||
if (fin.empty()) {
|
||||
new llvm::ReturnInst(v, p->scopebb());
|
||||
}
|
||||
@@ -113,6 +123,7 @@ void ReturnStatement::toIR(IRState* p)
|
||||
else
|
||||
{
|
||||
if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
|
||||
IRFunction::FinallyVec& fin = p->func().finallys;
|
||||
if (fin.empty()) {
|
||||
new llvm::ReturnInst(p->scopebb());
|
||||
}
|
||||
|
||||
110
gen/toir.c
110
gen/toir.c
@@ -377,19 +377,16 @@ elem* StringExp::toElem(IRState* p)
|
||||
|
||||
if (dtype->ty == Tarray) {
|
||||
llvm::Constant* clen = llvm::ConstantInt::get(LLVM_DtoSize_t(),len,false);
|
||||
if (p->lvals.empty() || !p->toplval()) {
|
||||
if (!p->topexp() || p->topexp()->e2 != this) {
|
||||
llvm::Value* tmpmem = new llvm::AllocaInst(LLVM_DtoType(dtype),"tmp",p->topallocapoint());
|
||||
LLVM_DtoSetArray(tmpmem, clen, arrptr);
|
||||
e->mem = tmpmem;
|
||||
}
|
||||
else if (llvm::Value* arr = p->toplval()) {
|
||||
if (llvm::isa<llvm::GlobalVariable>(arr)) {
|
||||
e->val = LLVM_DtoConstantSlice(clen, arrptr);
|
||||
}
|
||||
else {
|
||||
LLVM_DtoSetArray(arr, clen, arrptr);
|
||||
e->inplace = true;
|
||||
}
|
||||
else if (p->topexp()->e2 == this) {
|
||||
llvm::Value* arr = p->topexp()->v;
|
||||
assert(arr);
|
||||
LLVM_DtoSetArray(arr, clen, arrptr);
|
||||
e->inplace = true;
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
@@ -453,14 +450,13 @@ elem* AssignExp::toElem(IRState* p)
|
||||
Logger::print("AssignExp::toElem: %s | %s = %s\n", toChars(), e1->type->toChars(), e2->type->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
assert(e1 && e2);
|
||||
p->inLvalue = true;
|
||||
elem* l = e1->toElem(p);
|
||||
p->inLvalue = false;
|
||||
p->exps.push_back(IRExp(e1,e2,NULL));
|
||||
|
||||
p->lvals.push_back(l->mem);
|
||||
elem* r = e2->toElem(p);
|
||||
p->lvals.pop_back();
|
||||
elem* l = e1->toElem(p);
|
||||
p->topexp()->v = l->mem;
|
||||
elem* r = e2->toElem(p);
|
||||
|
||||
p->exps.pop_back();
|
||||
|
||||
if (l->type == elem::ARRAYLEN)
|
||||
{
|
||||
@@ -1066,11 +1062,14 @@ elem* CallExp::toElem(IRState* p)
|
||||
|
||||
Logger::println("hidden struct return");
|
||||
|
||||
IRExp* topexp = p->topexp();
|
||||
|
||||
// hidden struct return arguments
|
||||
if (retinptr) {
|
||||
if (!p->lvals.empty() && p->toplval()) {
|
||||
assert(llvm::isa<llvm::StructType>(p->toplval()->getType()->getContainedType(0)));
|
||||
llargs[j] = p->toplval();
|
||||
if (topexp && topexp->e2 == this) {
|
||||
assert(topexp->v);
|
||||
assert(llvm::isa<llvm::StructType>(topexp->v->getType()->getContainedType(0)));
|
||||
llargs[j] = topexp->v;
|
||||
if (LLVM_DtoIsPassedByRef(tf->next)) {
|
||||
e->inplace = true;
|
||||
}
|
||||
@@ -1534,17 +1533,19 @@ elem* StructLiteralExp::toElem(IRState* p)
|
||||
llvm::Value* sptr = 0;
|
||||
|
||||
// if there is no lval, this is probably a temporary struct literal. correct?
|
||||
if (p->lvals.empty() || !p->toplval())
|
||||
if (!p->topexp() || p->topexp()->e2 != this)
|
||||
{
|
||||
sptr = new llvm::AllocaInst(LLVM_DtoType(type),"tmpstructliteral",p->topallocapoint());
|
||||
e->mem = sptr;
|
||||
e->type = elem::VAR;
|
||||
}
|
||||
// already has memory
|
||||
else
|
||||
else if (p->topexp()->e2 == this)
|
||||
{
|
||||
sptr = p->toplval();
|
||||
sptr = p->topexp()->v;
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
|
||||
assert(sptr);
|
||||
|
||||
@@ -1558,9 +1559,9 @@ elem* StructLiteralExp::toElem(IRState* p)
|
||||
|
||||
Expression* vx = (Expression*)elements->data[i];
|
||||
if (vx != 0) {
|
||||
p->lvals.push_back(arrptr);
|
||||
p->exps.push_back(IRExp(NULL,vx,arrptr));
|
||||
elem* ve = vx->toElem(p);
|
||||
p->lvals.pop_back();
|
||||
p->exps.pop_back();
|
||||
|
||||
if (!ve->inplace) {
|
||||
llvm::Value* val = ve->getValue();
|
||||
@@ -2042,7 +2043,8 @@ elem* NewExp::toElem(IRState* p)
|
||||
if (arguments->dim == 1) {
|
||||
elem* sz = ((Expression*)arguments->data[0])->toElem(p);
|
||||
llvm::Value* dimval = sz->getValue();
|
||||
LLVM_DtoNewDynArray(p->toplval(), dimval, ntype->next);
|
||||
assert(p->topexp() && p->topexp()->e2 == this && p->topexp()->v);
|
||||
LLVM_DtoNewDynArray(p->topexp()->v, dimval, ntype->next);
|
||||
delete sz;
|
||||
}
|
||||
else {
|
||||
@@ -2161,7 +2163,7 @@ elem* ArrayLengthExp::toElem(IRState* p)
|
||||
elem* e = new elem;
|
||||
elem* u = e1->toElem(p);
|
||||
|
||||
if (p->inLvalue)
|
||||
if (p->topexp() && p->topexp()->e1 == this)
|
||||
{
|
||||
e->mem = u->mem;
|
||||
e->type = elem::ARRAYLEN;
|
||||
@@ -2372,26 +2374,27 @@ elem* DelegateExp::toElem(IRState* p)
|
||||
|
||||
elem* e = new elem;
|
||||
elem* u = e1->toElem(p);
|
||||
|
||||
|
||||
llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
|
||||
llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
|
||||
|
||||
|
||||
const llvm::Type* int8ptrty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
|
||||
llvm::Value* lval = p->toplval();
|
||||
assert(p->topexp() && p->topexp()->e2 == this && p->topexp()->v);
|
||||
llvm::Value* lval = p->topexp()->v;
|
||||
|
||||
llvm::Value* context = LLVM_DtoGEP(lval,zero,zero,"tmp",p->scopebb());
|
||||
llvm::Value* castcontext = new llvm::BitCastInst(u->getValue(),int8ptrty,"tmp",p->scopebb());
|
||||
new llvm::StoreInst(castcontext, context, p->scopebb());
|
||||
|
||||
|
||||
llvm::Value* fptr = LLVM_DtoGEP(lval,zero,one,"tmp",p->scopebb());
|
||||
|
||||
|
||||
assert(func->llvmValue);
|
||||
llvm::Value* castfptr = new llvm::BitCastInst(func->llvmValue,fptr->getType()->getContainedType(0),"tmp",p->scopebb());
|
||||
new llvm::StoreInst(castfptr, fptr, p->scopebb());
|
||||
|
||||
|
||||
e->inplace = true;
|
||||
|
||||
|
||||
delete u;
|
||||
return e;
|
||||
}
|
||||
@@ -2415,8 +2418,16 @@ elem* IdentityExp::toElem(IRState* p)
|
||||
else
|
||||
r = v->getValue();
|
||||
|
||||
llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
|
||||
e->val = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb());
|
||||
Type* t1 = LLVM_DtoDType(e1->type);
|
||||
|
||||
if (t1->ty == Tarray) {
|
||||
assert(l->getType() == r->getType());
|
||||
e->val = LLVM_DtoDynArrayIs(op,l,r);
|
||||
}
|
||||
else {
|
||||
llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
|
||||
e->val = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb());
|
||||
}
|
||||
e->type = elem::VAL;
|
||||
|
||||
delete u;
|
||||
@@ -2445,7 +2456,8 @@ elem* CondExp::toElem(IRState* p)
|
||||
Logger::print("CondExp::toElem: %s | %s\n", toChars(), type->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
const llvm::Type* resty = LLVM_DtoType(type);
|
||||
Type* dtype = LLVM_DtoDType(type);
|
||||
const llvm::Type* resty = LLVM_DtoType(dtype);
|
||||
|
||||
// allocate a temporary for the final result. failed to come up with a better way :/
|
||||
llvm::BasicBlock* entryblock = &p->topfunc()->front();
|
||||
@@ -2463,21 +2475,21 @@ elem* CondExp::toElem(IRState* p)
|
||||
|
||||
p->scope() = IRScope(condtrue, condfalse);
|
||||
elem* u = e1->toElem(p);
|
||||
new llvm::StoreInst(u->getValue(),resval,p->scopebb());
|
||||
LLVM_DtoAssign(dtype, resval, u->getValue());
|
||||
new llvm::BranchInst(condend,p->scopebb());
|
||||
delete u;
|
||||
|
||||
p->scope() = IRScope(condfalse, condend);
|
||||
elem* v = e2->toElem(p);
|
||||
new llvm::StoreInst(v->getValue(),resval,p->scopebb());
|
||||
LLVM_DtoAssign(dtype, resval, v->getValue());
|
||||
new llvm::BranchInst(condend,p->scopebb());
|
||||
delete v;
|
||||
|
||||
p->scope() = IRScope(condend, oldend);
|
||||
|
||||
elem* e = new elem;
|
||||
e->val = new llvm::LoadInst(resval,"tmp",p->scopebb());
|
||||
e->type = elem::VAL;
|
||||
e->mem = resval;
|
||||
e->type = elem::VAR;
|
||||
return e;
|
||||
}
|
||||
|
||||
@@ -2589,12 +2601,13 @@ elem* ArrayLiteralExp::toElem(IRState* p)
|
||||
Logger::cout() << "array literal has llvm type: " << *t << '\n';
|
||||
|
||||
llvm::Value* mem = 0;
|
||||
if (p->lvals.empty() || !p->toplval()) {
|
||||
if (!p->topexp() || p->topexp()->e2 != this) {
|
||||
assert(LLVM_DtoDType(type)->ty == Tsarray);
|
||||
mem = new llvm::AllocaInst(t,"tmparrayliteral",p->topallocapoint());
|
||||
}
|
||||
else {
|
||||
mem = p->toplval();
|
||||
else if (p->topexp()->e2 == this) {
|
||||
mem = p->topexp()->v;
|
||||
assert(mem);
|
||||
if (!llvm::isa<llvm::PointerType>(mem->getType()) ||
|
||||
!llvm::isa<llvm::ArrayType>(mem->getType()->getContainedType(0)))
|
||||
{
|
||||
@@ -2602,6 +2615,8 @@ elem* ArrayLiteralExp::toElem(IRState* p)
|
||||
fatal();
|
||||
}
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
|
||||
for (unsigned i=0; i<elements->dim; ++i)
|
||||
{
|
||||
@@ -2657,14 +2672,17 @@ elem* FuncExp::toElem(IRState* p)
|
||||
fd->toObjFile();
|
||||
|
||||
llvm::Value* lval = NULL;
|
||||
if (p->lvals.empty() || p->toplval() == NULL) {
|
||||
if (!p->topexp() || p->topexp()->e2 != this) {
|
||||
const llvm::Type* dgty = LLVM_DtoType(type);
|
||||
Logger::cout() << "delegate without explicit storage:" << '\n' << *dgty << '\n';
|
||||
lval = new llvm::AllocaInst(dgty,"dgstorage",p->topallocapoint());
|
||||
}
|
||||
else {
|
||||
lval = p->toplval();
|
||||
else if (p->topexp()->e2 == this) {
|
||||
lval = p->topexp()->v;
|
||||
assert(lval);
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
|
||||
elem* e = new elem;
|
||||
|
||||
|
||||
32
gen/tollvm.c
32
gen/tollvm.c
@@ -1100,14 +1100,14 @@ llvm::Value* LLVM_DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expr
|
||||
{
|
||||
llvm::Value* retval = 0;
|
||||
|
||||
bool haslvals = !gIR->lvals.empty();
|
||||
bool haslvals = !gIR->exps.empty();
|
||||
if (haslvals)
|
||||
gIR->lvals.push_back(NULL);
|
||||
gIR->exps.push_back(IRExp(NULL,NULL,NULL));
|
||||
|
||||
elem* arg = argexp->toElem(gIR);
|
||||
|
||||
if (haslvals)
|
||||
gIR->lvals.pop_back();
|
||||
gIR->exps.pop_back();
|
||||
|
||||
if (arg->inplace) {
|
||||
assert(arg->mem != 0);
|
||||
@@ -1254,3 +1254,29 @@ void LLVM_DtoAssign(Type* t, llvm::Value* lhs, llvm::Value* rhs)
|
||||
gIR->ir->CreateStore(rhs, lhs);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
llvm::ConstantInt* LLVM_DtoConstSize_t(size_t i)
|
||||
{
|
||||
return llvm::ConstantInt::get(LLVM_DtoSize_t(), i, false);
|
||||
}
|
||||
llvm::ConstantInt* LLVM_DtoConstUint(unsigned i)
|
||||
{
|
||||
return llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
llvm::Constant* LLVM_DtoConstString(const char* str)
|
||||
{
|
||||
std::string s(str);
|
||||
llvm::Constant* init = llvm::ConstantArray::get(s, true);
|
||||
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(
|
||||
init->getType(), true,llvm::GlobalValue::InternalLinkage, init, "stringliteral", gIR->module);
|
||||
llvm::Constant* idxs[2] = { LLVM_DtoConstUint(0), LLVM_DtoConstUint(0) };
|
||||
return LLVM_DtoConstantSlice(
|
||||
LLVM_DtoConstSize_t(s.length()),
|
||||
llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -59,4 +59,8 @@ llvm::Value* LLVM_DtoNestedVariable(VarDeclaration* vd);
|
||||
|
||||
void LLVM_DtoAssign(Type* lhsType, llvm::Value* lhs, llvm::Value* rhs);
|
||||
|
||||
llvm::ConstantInt* LLVM_DtoConstSize_t(size_t);
|
||||
llvm::ConstantInt* LLVM_DtoConstUint(unsigned i);
|
||||
llvm::Constant* LLVM_DtoConstString(const char*);
|
||||
|
||||
#include "enums.h"
|
||||
|
||||
37
gen/toobj.c
37
gen/toobj.c
@@ -363,10 +363,10 @@ void ClassDeclaration::toObjFile()
|
||||
ts->llvmType = structtype;
|
||||
llvmType = structtype;
|
||||
|
||||
bool define_vtable = false;
|
||||
bool needs_definition = false;
|
||||
if (parent->isModule()) {
|
||||
gIR->module->addTypeName(mangle(),ts->llvmType);
|
||||
define_vtable = (getModule() == gIR->dmodule);
|
||||
needs_definition = (getModule() == gIR->dmodule);
|
||||
}
|
||||
else {
|
||||
assert(0 && "class parent is not a module");
|
||||
@@ -418,9 +418,9 @@ void ClassDeclaration::toObjFile()
|
||||
gIR->module->addTypeName(styname, svtbl_ty);
|
||||
svtblVar = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module);
|
||||
|
||||
if (define_vtable) {
|
||||
svtblVar->setInitializer(llvm::ConstantStruct::get(svtbl_ty, sinits));
|
||||
}
|
||||
llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(svtbl_ty, sinits));
|
||||
if (needs_definition)
|
||||
svtblVar->setInitializer(llvmConstVtbl);
|
||||
llvmVtbl = svtblVar;
|
||||
}
|
||||
|
||||
@@ -441,25 +441,25 @@ void ClassDeclaration::toObjFile()
|
||||
assert(svtblVar != 0);
|
||||
gIR->topstruct().inits[0] = svtblVar;
|
||||
|
||||
_init = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits);
|
||||
llvmInitZ = _init = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits);
|
||||
assert(_init);
|
||||
|
||||
std::string initname("_D");
|
||||
initname.append(mangle());
|
||||
initname.append("6__initZ");
|
||||
//Logger::cout() << *_init << '\n';
|
||||
llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, 0, initname, gIR->module);
|
||||
llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, NULL, initname, gIR->module);
|
||||
ts->llvmInit = initvar;
|
||||
if (define_vtable) {
|
||||
initvar->setInitializer(_init);
|
||||
}
|
||||
|
||||
// generate member function definitions
|
||||
gIR->topstruct().queueFuncs = false;
|
||||
IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs;
|
||||
size_t n = mfs.size();
|
||||
for (size_t i=0; i<n; ++i) {
|
||||
mfs[i]->toObjFile();
|
||||
if (needs_definition) {
|
||||
initvar->setInitializer(_init);
|
||||
// generate member functions
|
||||
gIR->topstruct().queueFuncs = false;
|
||||
IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs;
|
||||
size_t n = mfs.size();
|
||||
for (size_t i=0; i<n; ++i) {
|
||||
mfs[i]->toObjFile();
|
||||
}
|
||||
}
|
||||
|
||||
gIR->classes.pop_back();
|
||||
@@ -525,9 +525,7 @@ void VarDeclaration::toObjFile()
|
||||
// if extern don't emit initializer
|
||||
if (!(storage_class & STCextern))
|
||||
{
|
||||
gIR->lvals.push_back(gvar);
|
||||
_init = LLVM_DtoConstInitializer(t, init);
|
||||
gIR->lvals.pop_back();
|
||||
|
||||
//Logger::cout() << "initializer: " << *_init << '\n';
|
||||
if (_type != _init->getType()) {
|
||||
@@ -628,7 +626,8 @@ void TypedefDeclaration::toObjFile()
|
||||
LOG_SCOPE;
|
||||
|
||||
// generate typeinfo
|
||||
type->getTypeInfo(NULL);
|
||||
if (!type->builtinTypeInfo())
|
||||
type->getTypeInfo(NULL);
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
|
||||
104
gen/typinf.c
104
gen/typinf.c
@@ -30,6 +30,8 @@
|
||||
#include "gen/irstate.h"
|
||||
#include "gen/logger.h"
|
||||
#include "gen/runtime.h"
|
||||
#include "gen/tollvm.h"
|
||||
#include "gen/arrays.h"
|
||||
|
||||
/*******************************************
|
||||
* Get a canonicalized form of the TypeInfo for use with the internal
|
||||
@@ -242,10 +244,20 @@ void TypeInfoDeclaration::toObjFile()
|
||||
if (llvmTouched) return;
|
||||
else llvmTouched = true;
|
||||
|
||||
Logger::println("Getting typeinfo var: %s", mangle());
|
||||
llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangle());
|
||||
assert(llvmValue);
|
||||
Logger::cout() << "Got:" << '\n' << *llvmValue << '\n';
|
||||
Logger::println("typeinfo mangle: %s", mangle());
|
||||
|
||||
if (tinfo->builtinTypeInfo()) {
|
||||
// this is a declaration of a builtin __initZ var
|
||||
llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangle());
|
||||
assert(llvmValue);
|
||||
Logger::cout() << "Got typeinfo var:" << '\n' << *llvmValue << '\n';
|
||||
}
|
||||
else {
|
||||
toDt(NULL);
|
||||
// this is a specialized typeinfo
|
||||
//std::vector<const llvm::Type*> stypes;
|
||||
//stypes.push_back(
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
@@ -257,7 +269,89 @@ void TypeInfoDeclaration::toDt(dt_t **pdt)
|
||||
|
||||
void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
|
||||
{
|
||||
assert(0 && "TypeInfoTypedefDeclaration");
|
||||
Logger::println("TypeInfoTypedefDeclaration::toDt() %s", toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
ClassDeclaration* base = Type::typeinfotypedef;
|
||||
base->toObjFile();
|
||||
|
||||
llvm::Constant* initZ = base->llvmInitZ;
|
||||
assert(initZ);
|
||||
const llvm::StructType* stype = llvm::cast<llvm::StructType>(initZ->getType());
|
||||
|
||||
std::vector<llvm::Constant*> sinits;
|
||||
sinits.push_back(initZ->getOperand(0));
|
||||
|
||||
assert(tinfo->ty == Ttypedef);
|
||||
TypeTypedef *tc = (TypeTypedef *)tinfo;
|
||||
TypedefDeclaration *sd = tc->sym;
|
||||
|
||||
// TypeInfo base
|
||||
//const llvm::PointerType* basept = llvm::cast<llvm::PointerType>(initZ->getOperand(1)->getType());
|
||||
//sinits.push_back(llvm::ConstantPointerNull::get(basept));
|
||||
Logger::println("generating base typeinfo");
|
||||
//sd->basetype = sd->basetype->merge();
|
||||
sd->basetype->getTypeInfo(NULL); // generate vtinfo
|
||||
assert(sd->basetype->vtinfo);
|
||||
if (!sd->basetype->vtinfo->llvmValue)
|
||||
sd->basetype->vtinfo->toObjFile();
|
||||
assert(llvm::isa<llvm::Constant>(sd->basetype->vtinfo->llvmValue));
|
||||
llvm::Constant* castbase = llvm::cast<llvm::Constant>(sd->basetype->vtinfo->llvmValue);
|
||||
castbase = llvm::ConstantExpr::getBitCast(castbase, initZ->getOperand(1)->getType());
|
||||
sinits.push_back(castbase);
|
||||
|
||||
// char[] name
|
||||
char *name = sd->toPrettyChars();
|
||||
sinits.push_back(LLVM_DtoConstString(name));
|
||||
assert(sinits.back()->getType() == initZ->getOperand(2)->getType());
|
||||
|
||||
// void[] init
|
||||
//const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
//sinits.push_back(LLVM_DtoConstantSlice(LLVM_DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
|
||||
sinits.push_back(initZ->getOperand(3));
|
||||
|
||||
// create the symbol
|
||||
llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits);
|
||||
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::InternalLinkage,tiInit,toChars(),gIR->module);
|
||||
|
||||
llvmValue = gvar;
|
||||
|
||||
/*
|
||||
dtxoff(pdt, Type::typeinfotypedef->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Typedef
|
||||
dtdword(pdt, 0); // monitor
|
||||
|
||||
assert(tinfo->ty == Ttypedef);
|
||||
|
||||
TypeTypedef *tc = (TypeTypedef *)tinfo;
|
||||
TypedefDeclaration *sd = tc->sym;
|
||||
//printf("basetype = %s\n", sd->basetype->toChars());
|
||||
|
||||
// Put out:
|
||||
// TypeInfo base;
|
||||
// char[] name;
|
||||
// void[] m_init;
|
||||
|
||||
sd->basetype = sd->basetype->merge();
|
||||
sd->basetype->getTypeInfo(NULL); // generate vtinfo
|
||||
assert(sd->basetype->vtinfo);
|
||||
dtxoff(pdt, sd->basetype->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for basetype
|
||||
|
||||
char *name = sd->toPrettyChars();
|
||||
size_t namelen = strlen(name);
|
||||
dtdword(pdt, namelen);
|
||||
dtabytes(pdt, TYnptr, 0, namelen + 1, name);
|
||||
|
||||
// void[] init;
|
||||
if (tinfo->isZeroInit() || !sd->init)
|
||||
{ // 0 initializer, or the same as the base type
|
||||
dtdword(pdt, 0); // init.length
|
||||
dtdword(pdt, 0); // init.ptr
|
||||
}
|
||||
else
|
||||
{
|
||||
dtdword(pdt, sd->type->size()); // init.length
|
||||
dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr
|
||||
*/
|
||||
}
|
||||
|
||||
void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
|
||||
|
||||
@@ -433,8 +433,6 @@ class TypeInfo
|
||||
OffsetTypeInfo[] offTi() { return null; }
|
||||
}
|
||||
|
||||
/+
|
||||
|
||||
class TypeInfo_Typedef : TypeInfo
|
||||
{
|
||||
char[] toString() { return name; }
|
||||
@@ -455,7 +453,7 @@ class TypeInfo_Typedef : TypeInfo
|
||||
size_t tsize() { return base.tsize(); }
|
||||
void swap(void *p1, void *p2) { return base.swap(p1, p2); }
|
||||
|
||||
TypeInfo next() { return base.next(); }
|
||||
TypeInfo next() { return base; }
|
||||
uint flags() { return base.flags(); }
|
||||
void[] init() { return m_init.length ? m_init : base.init(); }
|
||||
|
||||
@@ -468,6 +466,8 @@ class TypeInfo_Enum : TypeInfo_Typedef
|
||||
{
|
||||
}
|
||||
|
||||
/+
|
||||
|
||||
class TypeInfo_Pointer : TypeInfo
|
||||
{
|
||||
char[] toString() { return m_next.toString() ~ "*"; }
|
||||
|
||||
14
test/bug32.d
Normal file
14
test/bug32.d
Normal file
@@ -0,0 +1,14 @@
|
||||
module bug32;
|
||||
|
||||
struct S
|
||||
{
|
||||
char[] getName() { return name; }
|
||||
char[] name;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
S s = S("Kyle");
|
||||
char[] name = s.name;
|
||||
printf("%.*s\n", name.length, name.ptr);
|
||||
}
|
||||
33
test/bug33.d
Normal file
33
test/bug33.d
Normal file
@@ -0,0 +1,33 @@
|
||||
module bug33;
|
||||
|
||||
extern(C) int memcmp(void*,void*,size_t);
|
||||
|
||||
private int string_cmp(char[] s1, char[] s2)
|
||||
{
|
||||
auto len = s1.length;
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
int result = memcmp(s1.ptr, s2.ptr, len);
|
||||
if (result == 0)
|
||||
result = cast(int)(cast(ptrdiff_t)s1.length - cast(ptrdiff_t)s2.length);
|
||||
return result;
|
||||
}
|
||||
|
||||
struct S
|
||||
{
|
||||
char[] toString()
|
||||
{
|
||||
return "S";
|
||||
}
|
||||
}
|
||||
|
||||
int func()
|
||||
{
|
||||
S a,b;
|
||||
return string_cmp(a.toString(),b.toString());
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
assert(func() == 0);
|
||||
}
|
||||
12
test/condexp1.d
Normal file
12
test/condexp1.d
Normal file
@@ -0,0 +1,12 @@
|
||||
module condexp1;
|
||||
|
||||
void main()
|
||||
{
|
||||
char[] a = "hello";
|
||||
char[] b = "world";
|
||||
int i = 42;
|
||||
{
|
||||
char[] c = i > 50 ? b : a;
|
||||
assert(c is a);
|
||||
}
|
||||
}
|
||||
13
test/typeinfo3.d
Normal file
13
test/typeinfo3.d
Normal file
@@ -0,0 +1,13 @@
|
||||
module typeinfo3;
|
||||
|
||||
typedef int int_t;
|
||||
|
||||
void main()
|
||||
{
|
||||
int_t i;
|
||||
auto ti = typeid(typeof(i));
|
||||
printf("%s\n",ti.toString.ptr);
|
||||
assert(ti.toString() == "typeinfo3.int_t");
|
||||
assert(ti.next !is null);
|
||||
assert(ti.next.toString() == "int");
|
||||
}
|
||||
Reference in New Issue
Block a user