Complex number should now follow the D ABI on x86. They're also treated as first class values now. Big change.

This commit is contained in:
Tomas Lindquist Olsen
2008-09-09 16:49:47 -07:00
parent 4e0b6b4bf0
commit 8e9b957bce
21 changed files with 179 additions and 229 deletions

View File

@@ -7929,7 +7929,6 @@ Expression *XorAssignExp::semantic(Scope *sc)
AddExp::AddExp(Loc loc, Expression *e1, Expression *e2)
: BinExp(loc, TOKadd, sizeof(AddExp), e1, e2)
{
llvmFieldIndex = false;
}
Expression *AddExp::semantic(Scope *sc)

View File

@@ -1173,9 +1173,6 @@ struct AddExp : BinExp
Identifier *opId_r();
elem *toElem(IRState *irs);
// LLVMDC
bool llvmFieldIndex;
};
struct MinExp : BinExp

View File

@@ -4456,18 +4456,17 @@ L1:
// *(&e + offset)
accessCheck(e->loc, sc, e, d);
// LLVMDC we don't want dot exprs turned into pointer arithmetic. it complicates things for no apparent gain
#ifndef IN_LLVM
b = new AddrExp(e->loc, e);
b->type = e->type->pointerTo();
b = new AddExp(e->loc, b, new IntegerExp(e->loc, v->offset, Type::tint32));
#if IN_LLVM
// LLVMDC modification
// this is *essential*
((AddExp*)b)->llvmFieldIndex = true;
#endif
b->type = v->type->pointerTo();
e = new PtrExp(e->loc, b);
e->type = v->type;
return e;
#endif
}
de = new DotVarExp(e->loc, e, d);

View File

@@ -23,13 +23,8 @@ static LLValue* to_pkey(Loc& loc, DValue* key)
pkey = key->getRVal();
}
else if (DVarValue* var = key->isVar()) {
if (var->lval) {
pkey = key->getLVal();
needmem = false;
}
else {
pkey = key->getRVal();
}
pkey = key->getLVal();
needmem = false;
}
else if (key->isConst()) {
needmem = true;
@@ -37,8 +32,8 @@ static LLValue* to_pkey(Loc& loc, DValue* key)
}
else {
LLValue* tmp = DtoAlloca(DtoType(keytype), "aatmpkeystorage");
DVarValue* var = new DVarValue(keytype, tmp, true);
DtoAssign(loc, var, key);
DVarValue var(keytype, tmp);
DtoAssign(loc, &var, key);
return tmp;
}
@@ -96,7 +91,7 @@ DValue* DtoAAIndex(Loc& loc, Type* type, DValue* aa, DValue* key, bool lvalue)
if (ret->getType() != targettype)
ret = DtoBitCast(ret, targettype);
return new DVarValue(type, ret, true);
return new DVarValue(type, ret);
}
/////////////////////////////////////////////////////////////////////////////////////

View File

@@ -116,10 +116,10 @@ void DtoArrayInit(Loc& loc, DValue* array, DValue* value)
LLValue* val;
// give slices and complex values storage (and thus an address to pass)
if (value->isSlice() || value->isComplex())
if (value->isSlice())
{
val = DtoAlloca(DtoType(value->getType()), ".tmpparam");
DVarValue lval(value->getType(), val, true);
DVarValue lval(value->getType(), val);
DtoAssign(loc, &lval, value);
}
else
@@ -526,7 +526,7 @@ DSliceValue* DtoCatAssignElement(DValue* array, Expression* exp)
LLValue* ptr = slice->ptr;
ptr = llvm::GetElementPtrInst::Create(ptr, idx, "tmp", gIR->scopebb());
DValue* dptr = new DVarValue(exp->type, ptr, true);
DValue* dptr = new DVarValue(exp->type, ptr);
DValue* e = exp->toElem(gIR);
@@ -631,7 +631,7 @@ DSliceValue* DtoCatArrayElement(Type* type, Expression* exp1, Expression* exp2)
DSliceValue* slice = DtoNewDynArray(type, lenval, false);
LLValue* mem = slice->ptr;
DVarValue* memval = new DVarValue(e1->getType(), mem, true);
DVarValue* memval = new DVarValue(e1->getType(), mem);
DtoAssign(exp1->loc, memval, e1);
src1 = DtoArrayPtr(e2);
@@ -662,7 +662,7 @@ DSliceValue* DtoCatArrayElement(Type* type, Expression* exp1, Expression* exp2)
DtoMemCpy(mem,src1,bytelen);
mem = gIR->ir->CreateGEP(mem,len1,"tmp");
DVarValue* memval = new DVarValue(e2->getType(), mem, true);
DVarValue* memval = new DVarValue(e2->getType(), mem);
DtoAssign(exp1->loc, memval, e2);
return slice;

View File

@@ -8,20 +8,15 @@
#include "gen/llvmhelpers.h"
#include "gen/irstate.h"
#include "gen/dvalue.h"
#include "gen/logger.h"
//////////////////////////////////////////////////////////////////////////////////////////
const llvm::StructType* DtoComplexType(Type* type)
{
Type* t = type->toBasetype();
const LLType* base = DtoComplexBaseType(t);
std::vector<const LLType*> types;
types.push_back(base);
types.push_back(base);
return llvm::StructType::get(types);
return llvm::StructType::get(base, base, NULL);
}
const LLType* DtoComplexBaseType(Type* t)
@@ -47,19 +42,6 @@ const LLType* DtoComplexBaseType(Type* t)
//////////////////////////////////////////////////////////////////////////////////////////
LLConstant* DtoConstComplex(Type* ty, LLConstant* re, LLConstant* im)
{
assert(0);
const LLType* base = DtoComplexBaseType(ty);
std::vector<LLConstant*> inits;
inits.push_back(re);
inits.push_back(im);
const llvm::VectorType* vt = llvm::VectorType::get(base, 2);
return llvm::ConstantVector::get(vt, inits);
}
LLConstant* DtoConstComplex(Type* _ty, long double re, long double im)
{
TY ty = _ty->toBasetype()->ty;
@@ -108,7 +90,7 @@ DValue* DtoComplex(Loc& loc, Type* to, DValue* val)
{
Type* t = val->getType()->toBasetype();
if (val->isComplex() || t->iscomplex()) {
if (t->iscomplex()) {
return DtoCastComplex(loc, val, to);
}
@@ -127,27 +109,27 @@ DValue* DtoComplex(Loc& loc, Type* to, DValue* val)
baserety = Type::tfloat80;
baseimty = Type::timaginary80;
}
else {
assert(0);
}
const LLType* complexTy = DtoType(to);
LLValue* res;
if (t->isimaginary()) {
return new DComplexValue(to, LLConstant::getNullValue(DtoType(baserety)), DtoCastFloat(loc, val, baseimty)->getRVal());
res = DtoAggrPair(complexTy, LLConstant::getNullValue(DtoType(baserety)), DtoCastFloat(loc, val, baseimty)->getRVal());
}
else if (t->isfloating()) {
return new DComplexValue(to, DtoCastFloat(loc, val, baserety)->getRVal(), LLConstant::getNullValue(DtoType(baseimty)));
else if (t->isfloating() || t->isintegral()) {
res = DtoAggrPair(complexTy, DtoCastFloat(loc, val, baserety)->getRVal(), LLConstant::getNullValue(DtoType(baseimty)));
}
else if (t->isintegral()) {
return new DComplexValue(to, DtoCastInt(loc, val, baserety)->getRVal(), LLConstant::getNullValue(DtoType(baseimty)));
else {
assert(0);
}
assert(0);
return new DImValue(to, res);
}
//////////////////////////////////////////////////////////////////////////////////////////
void DtoComplexAssign(LLValue* l, LLValue* r)
{
DtoStore(DtoLoad(DtoGEPi(r, 0,0, "tmp")), DtoGEPi(l,0,0,"tmp"));
DtoStore(DtoLoad(DtoGEPi(r, 0,1, "tmp")), DtoGEPi(l,0,1,"tmp"));
}
void DtoComplexSet(LLValue* c, LLValue* re, LLValue* im)
{
DtoStore(re, DtoGEPi(c,0,0,"tmp"));
@@ -158,15 +140,10 @@ void DtoComplexSet(LLValue* c, LLValue* re, LLValue* im)
void DtoGetComplexParts(DValue* c, LLValue*& re, LLValue*& im)
{
// get LLValues
if (DComplexValue* cx = c->isComplex()) {
re = cx->re;
im = cx->im;
}
else {
re = DtoLoad(DtoGEPi(c->getRVal(),0,0,"tmp"));
im = DtoLoad(DtoGEPi(c->getRVal(),0,1,"tmp"));
}
LLValue* v = c->getRVal();
Logger::cout() << "extracting real and imaginary parts from: " << *v << '\n';
re = gIR->ir->CreateExtractValue(v, 0, ".re_part");
im = gIR->ir->CreateExtractValue(v, 1, ".im_part");
}
DValue* resolveLR(DValue* val, bool getlval)
@@ -232,7 +209,8 @@ DValue* DtoComplexAdd(Loc& loc, Type* type, DValue* lhs, DValue* rhs)
else // either hasIm(rhstype) or no im at all (then use any)
res_im = rhs_im;
return new DComplexValue(type, res_re, res_im);
LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im);
return new DImValue(type, res);
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -262,7 +240,8 @@ DValue* DtoComplexSub(Loc& loc, Type* type, DValue* lhs, DValue* rhs)
else
res_im = lhs_im;
return new DComplexValue(type, res_re, res_im);
LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im);
return new DImValue(type, res);
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -314,7 +293,8 @@ DValue* DtoComplexMul(Loc& loc, Type* type, DValue* lhs, DValue* rhs)
else
res_im = hasRe(lhstype) ? rhs_im : lhs_re; // null!
return new DComplexValue(type, res_re, res_im);
LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im);
return new DImValue(type, res);
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -390,7 +370,8 @@ DValue* DtoComplexDiv(Loc& loc, Type* type, DValue* lhs, DValue* rhs)
res_im = gIR->ir->CreateFDiv(res_im, denom, "res_im");
}
return new DComplexValue(type, res_re, res_im);
LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im);
return new DImValue(type, res);
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -408,7 +389,8 @@ DValue* DtoComplexNeg(Loc& loc, Type* type, DValue* val)
re = gIR->ir->CreateNeg(a, "tmp");
im = gIR->ir->CreateNeg(b, "tmp");
return new DComplexValue(type, re, im);
LLValue* res = DtoAggrPair(DtoType(type), re, im);
return new DImValue(type, res);
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -462,35 +444,35 @@ DValue* DtoCastComplex(Loc& loc, DValue* val, Type* _to)
re = gIR->ir->CreateFPTrunc(re, toty, "tmp");
im = gIR->ir->CreateFPTrunc(im, toty, "tmp");
}
else if (to->size() > vty->size()) {
else {
re = gIR->ir->CreateFPExt(re, toty, "tmp");
im = gIR->ir->CreateFPExt(im, toty, "tmp");
}
else {
return val;
LLValue* pair = DtoAggrPair(DtoType(_to), re, im);
DValue* rval = new DImValue(_to, pair);
// if the value we're casting is not a lvalue, the cast value can't be either
if (!val->isLVal()) {
return rval;
}
if (val->isComplex())
return new DComplexValue(_to, re, im);
// unfortunately at this point, the cast value can show up as the lvalue for += and similar expressions.
// so we need to give it storage, or fix the system that handles this stuff (DLRValue)
LLValue* mem = DtoAlloca(DtoType(_to), "castcomplextmp");
DtoComplexSet(mem, re, im);
return new DLRValue(val, new DImValue(_to, mem));
// so we need to maintain the storage
return new DLRValue(val, rval);
}
else if (to->isimaginary()) {
if (val->isComplex())
return new DImValue(to, val->isComplex()->im);
// FIXME: this loads both values, even when we only need one
LLValue* v = val->getRVal();
DImValue* im = new DImValue(to, DtoLoad(DtoGEPi(v,0,1,"tmp")));
LLValue* impart = gIR->ir->CreateExtractValue(v, 1, ".im_part");
DImValue* im = new DImValue(to, impart);
return DtoCastFloat(loc, im, to);
}
else if (to->isfloating()) {
if (val->isComplex())
return new DImValue(to, val->isComplex()->re);
// FIXME: this loads both values, even when we only need one
LLValue* v = val->getRVal();
DImValue* re = new DImValue(to, DtoLoad(DtoGEPi(v,0,0,"tmp")));
LLValue* repart = gIR->ir->CreateExtractValue(v, 0, ".re_part");
DImValue* re = new DImValue(to, repart);
return DtoCastFloat(loc, re, to);
}
else

View File

@@ -4,7 +4,6 @@
const llvm::StructType* DtoComplexType(Type* t);
const LLType* DtoComplexBaseType(Type* t);
LLConstant* DtoConstComplex(Type* t, LLConstant* re, LLConstant* im);
LLConstant* DtoConstComplex(Type* t, long double re, long double im);
LLConstant* DtoComplexShuffleMask(unsigned a, unsigned b);
@@ -13,7 +12,6 @@ LLValue* DtoRealPart(DValue* val);
LLValue* DtoImagPart(DValue* val);
DValue* DtoComplex(Loc& loc, Type* to, DValue* val);
void DtoComplexAssign(LLValue* l, LLValue* r);
void DtoComplexSet(LLValue* c, LLValue* re, LLValue* im);
void DtoGetComplexParts(DValue* c, LLValue*& re, LLValue*& im);

View File

@@ -4,60 +4,40 @@
#include "gen/irstate.h"
#include "gen/logger.h"
#include "gen/dvalue.h"
#include "gen/llvmhelpers.h"
#include "declaration.h"
/////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
DVarValue::DVarValue(Type* t, VarDeclaration* vd, LLValue* llvmValue, bool lvalue)
DVarValue::DVarValue(Type* t, VarDeclaration* vd, LLValue* llvmValue)
{
var = vd;
val = llvmValue;
rval = 0;
lval = lvalue;
type = t;
}
DVarValue::DVarValue(Type* t, LLValue* lv, LLValue* rv)
{
var = 0;
val = lv;
rval = rv;
lval = true;
type = t;
}
DVarValue::DVarValue(Type* t, LLValue* llvmValue, bool lvalue)
DVarValue::DVarValue(Type* t, LLValue* llvmValue)
{
var = 0;
val = llvmValue;
rval = 0;
lval = lvalue;
type = t;
}
LLValue* DVarValue::getLVal()
{
assert(val && lval);
assert(val);
return val;
}
LLValue* DVarValue::getRVal()
{
assert(rval || val);
if (DtoIsPassedByRef(type)) {
if (rval) return rval;
assert(val);
Type* bt = type->toBasetype();
if (DtoIsPassedByRef(bt))
return val;
}
else {
if (rval) return rval;
//Logger::cout() << "val: " << *val << '\n';
if (!isField() && DtoCanLoad(val)) {
return DtoLoad(val);
}
return val;
}
return DtoLoad(val);
}
/////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -31,7 +31,6 @@ struct DFuncValue;
struct DSliceValue;
struct DArrayLenValue;
struct DLRValue;
struct DComplexValue;
// base class for d-values
struct DValue : Object
@@ -51,7 +50,6 @@ struct DValue : Object
virtual DSliceValue* isSlice() { return NULL; }
virtual DFuncValue* isFunc() { return NULL; }
virtual DArrayLenValue* isArrayLen() { return NULL; }
virtual DComplexValue* isComplex() { return NULL; }
virtual DLRValue* isLRValue() { return NULL; }
protected:
@@ -101,14 +99,11 @@ struct DVarValue : DValue
Type* type;
VarDeclaration* var;
LLValue* val;
LLValue* rval;
bool lval;
DVarValue(Type* t, VarDeclaration* vd, LLValue* llvmValue, bool lvalue);
DVarValue(Type* t, LLValue* lv, LLValue* rv);
DVarValue(Type* t, LLValue* llvmValue, bool lvalue);
DVarValue(Type* t, VarDeclaration* vd, LLValue* llvmValue);
DVarValue(Type* t, LLValue* llvmValue);
virtual bool isLVal() { return val && lval; }
virtual bool isLVal() { return true; }
virtual LLValue* getLVal();
virtual LLValue* getRVal();
@@ -119,7 +114,7 @@ struct DVarValue : DValue
// field d-value
struct DFieldValue : DVarValue
{
DFieldValue(Type* t, LLValue* llvmValue, bool l) : DVarValue(t, llvmValue, l) {}
DFieldValue(Type* t, LLValue* llvmValue) : DVarValue(t, llvmValue) {}
virtual DFieldValue* isField() { return this; }
};
@@ -173,21 +168,4 @@ struct DLRValue : DValue
virtual DLRValue* isLRValue() { return this; }
};
// complex number immediate d-value (much like slice)
struct DComplexValue : DValue
{
Type* type;
LLValue* re;
LLValue* im;
DComplexValue(Type* t, LLValue* r, LLValue* i) {
type = t;
re = r;
im = i;
}
virtual Type*& getType() { assert(type); return type; }
virtual DComplexValue* isComplex() { return this; }
};
#endif // LLVMDC_GEN_DVALUE_H

View File

@@ -122,7 +122,13 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, co
bool refOrOut = ((arg->storageClass & STCref) || (arg->storageClass & STCout));
const LLType* at = DtoType(argT);
if (isaStruct(at)) {
// FIXME: using the llvm type for these is a bad idea... aggregates are first class now and we're starting to use it ...
if (argT->iscomplex()) {
goto Lbadstuff;
}
else if (isaStruct(at)) {
Logger::println("struct param");
paramvec.push_back(getPtrToType(at));
if (!refOrOut)
@@ -140,6 +146,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, co
paramvec.push_back(getPtrToType(at));
}
else {
Lbadstuff:
if (refOrOut) {
Logger::println("by ref param");
at = getPtrToType(at);
@@ -866,10 +873,10 @@ DValue* DtoArgument(Argument* fnarg, Expression* argexp)
arg = new DImValue(argexp->type, arg->getRVal());
}
// byval arg, but expr has no storage yet
else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isComplex() || arg->isNull()))
else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isNull()))
{
LLValue* alloc = DtoAlloca(DtoType(argexp->type), ".tmp_arg");
DVarValue* vv = new DVarValue(argexp->type, alloc, true);
DVarValue* vv = new DVarValue(argexp->type, alloc);
DtoAssign(argexp->loc, vv, arg);
arg = vv;
}
@@ -883,7 +890,7 @@ void DtoVariadicArgument(Expression* argexp, LLValue* dst)
{
Logger::println("DtoVariadicArgument");
LOG_SCOPE;
DVarValue vv(argexp->type, dst, true);
DVarValue vv(argexp->type, dst);
DtoAssign(argexp->loc, &vv, argexp->toElem(gIR));
}

View File

@@ -360,7 +360,7 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd)
if (vdparent == irfunc->decl)
{
LLValue* val = vd->ir.getIrValue();
return new DVarValue(astype, vd, val, true);
return new DVarValue(astype, vd, val);
}
// get it from the nested context
@@ -381,7 +381,7 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd)
val = DtoLoad(val);
assert(vd->ir.irLocal->value);
val = DtoBitCast(val, vd->ir.irLocal->value->getType(), vd->toChars());
return new DVarValue(astype, vd, val, true);
return new DVarValue(astype, vd, val);
}
LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
@@ -486,21 +486,15 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs)
DtoStore(r, l);
}
else if (t->iscomplex()) {
assert(!lhs->isComplex());
LLValue* dst;
if (DLRValue* lr = lhs->isLRValue()) {
dst = lr->getLVal();
rhs = DtoCastComplex(loc, rhs, lr->getLType());
}
else {
dst = lhs->getRVal();
dst = lhs->getLVal();
}
if (DComplexValue* cx = rhs->isComplex())
DtoComplexSet(dst, cx->re, cx->im);
else
DtoComplexAssign(dst, rhs->getRVal());
DtoStore(rhs->getRVal(), dst);
}
else {
LLValue* l = lhs->getLVal();
@@ -538,7 +532,8 @@ DValue* DtoNullValue(Type* type)
if (basetype->iscomplex())
{
const LLType* basefp = DtoComplexBaseType(basetype);
return new DComplexValue(type, LLConstant::getNullValue(basefp), LLConstant::getNullValue(basefp));
LLValue* res = DtoAggrPair(DtoType(type), LLConstant::getNullValue(basefp), LLConstant::getNullValue(basefp));
return new DImValue(type, res);
}
// integer, floating, pointer and class have no special representation
else if (basetype->isintegral() || basetype->isfloating() || basety == Tpointer || basety == Tclass)
@@ -790,7 +785,7 @@ void DtoLazyStaticInit(bool istempl, LLValue* gvar, Initializer* init, Type* t)
gIR->scope() = IRScope(initbb,endinitbb);
DValue* ie = DtoInitializer(gvar, init);
DVarValue dst(t, gvar, true);
DVarValue dst(t, gvar);
DtoAssign(init->loc, &dst, ie);
gIR->ir->CreateStore(DtoConstBool(true), gflag);
@@ -1177,7 +1172,7 @@ DValue* DtoDeclarationExp(Dsymbol* declaration)
DValue* ie = DtoInitializer(vd->ir.irLocal->value, vd->init);
}
return new DVarValue(vd->type, vd, vd->ir.getIrValue(), true);
return new DVarValue(vd->type, vd, vd->ir.getIrValue());
}
// struct declaration
else if (StructDeclaration* s = declaration->isStructDeclaration())

View File

@@ -62,7 +62,7 @@ void ReturnStatement::toIR(IRState* p)
if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum);
DValue* rvar = new DVarValue(f->type->next, f->decl->ir.irFunc->retArg, true);
DValue* rvar = new DVarValue(f->type->next, f->decl->ir.irFunc->retArg);
DValue* e = exp->toElem(p);
@@ -687,7 +687,7 @@ static LLValue* call_string_switch_runtime(llvm::GlobalVariable* table, Expressi
{
// give storage
llval = DtoAlloca(DtoType(e->type), "tmp");
DVarValue* vv = new DVarValue(e->type, llval, true);
DVarValue* vv = new DVarValue(e->type, llval);
DtoAssign(e->loc, vv, val);
}
else
@@ -1002,9 +1002,9 @@ void ForeachStatement::toIR(IRState* p)
value->ir.irLocal->value = DtoGEP1(val,loadedKey);
if (!value->isRef() && !value->isOut()) {
DValue* dst = new DVarValue(value->type, valvar, true);
DValue* src = new DVarValue(value->type, value->ir.irLocal->value, true);
DtoAssign(loc, dst, src);
DVarValue dst(value->type, valvar);
DVarValue src(value->type, value->ir.irLocal->value);
DtoAssign(loc, &dst, &src);
value->ir.irLocal->value = valvar;
}
@@ -1151,7 +1151,8 @@ void WithStatement::toIR(IRState* p)
DValue* e = exp->toElem(p);
assert(!wthis->ir.isSet());
wthis->ir.irLocal = new IrLocal(wthis);
wthis->ir.irLocal->value = e->getRVal();
wthis->ir.irLocal->value = DtoAlloca(DtoType(wthis->type), wthis->toChars());
DtoStore(e->getRVal(), wthis->ir.irLocal->value);
body->toIR(p);
}

View File

@@ -60,6 +60,10 @@ LLValue* DtoIndexStruct(LLValue* ptr, StructDeclaration* sd, Type* t, unsigned o
const LLType* llt = getPtrToType(DtoType(t));
const LLType* st = getPtrToType(DtoType(sd->type));
Logger::cout() << "ptr = " << *ptr << '\n';
Logger::cout() << "st = " << *st << '\n';
if (ptr->getType() != st) {
assert(sd->ir.irStruct->hasUnions);
ptr = gIR->ir->CreateBitCast(ptr, st, "tmp");

View File

@@ -314,6 +314,8 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
LLValue* arg = argval->getRVal();
if (fnarg) // can fnarg ever be null in this block?
{
Logger::cout() << "arg: " << *arg << '\n';
Logger::cout() << "expects: " << *callableTy->getParamType(j) << '\n';
if (arg->getType() != callableTy->getParamType(j))
arg = DtoBitCast(arg, callableTy->getParamType(j));
if (fnarg->llvmAttrs)

View File

@@ -64,14 +64,14 @@ DValue* VarExp::toElem(IRState* p)
{
Logger::println("Id::_arguments");
LLValue* v = p->func()->_arguments;
return new DVarValue(type, vd, v, true);
return new DVarValue(type, vd, v);
}
// _argptr
else if (vd->ident == Id::_argptr && p->func()->_argptr)
{
Logger::println("Id::_argptr");
LLValue* v = p->func()->_argptr;
return new DVarValue(type, vd, v, true);
return new DVarValue(type, vd, v);
}
// _dollar
else if (vd->ident == Id::dollar)
@@ -79,7 +79,7 @@ DValue* VarExp::toElem(IRState* p)
Logger::println("Id::dollar");
assert(!p->arrays.empty());
LLValue* tmp = DtoArrayLen(p->arrays.back());
return new DVarValue(type, vd, tmp, false);
return new DImValue(type, tmp);
}
// typeinfo
else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration())
@@ -88,12 +88,10 @@ DValue* VarExp::toElem(IRState* p)
DtoForceDeclareDsymbol(tid);
assert(tid->ir.getIrValue());
const LLType* vartype = DtoType(type);
LLValue* m;
if (tid->ir.getIrValue()->getType() != getPtrToType(vartype))
m = p->ir->CreateBitCast(tid->ir.getIrValue(), vartype, "tmp");
else
m = tid->ir.getIrValue();
return new DVarValue(type, vd, m, true);
LLValue* m = tid->ir.getIrValue();
if (m->getType() != getPtrToType(vartype))
m = p->ir->CreateBitCast(m, vartype, "tmp");
return new DImValue(type, m);
}
// classinfo
else if (ClassInfoDeclaration* cid = vd->isClassInfoDeclaration())
@@ -101,7 +99,7 @@ DValue* VarExp::toElem(IRState* p)
Logger::println("ClassInfoDeclaration: %s", cid->cd->toChars());
DtoForceDeclareDsymbol(cid->cd);
assert(cid->cd->ir.irStruct->classInfo);
return new DVarValue(type, vd, cid->cd->ir.irStruct->classInfo, true);
return new DVarValue(type, vd, cid->cd->ir.irStruct->classInfo);
}
// nested variable
else if (vd->nestedref) {
@@ -117,7 +115,7 @@ DValue* VarExp::toElem(IRState* p)
return DtoNestedVariable(loc, type, vd);
}
else if (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type) || llvm::isa<llvm::AllocaInst>(vd->ir.getIrValue())) {
return new DVarValue(type, vd, vd->ir.getIrValue(), true);
return new DVarValue(type, vd, vd->ir.getIrValue());
}
else if (llvm::isa<llvm::Argument>(vd->ir.getIrValue())) {
return new DImValue(type, vd->ir.getIrValue());
@@ -125,6 +123,7 @@ DValue* VarExp::toElem(IRState* p)
else assert(0);
}
else {
Logger::println("a normal variable");
// take care of forward references of global variables
if (vd->isDataseg() || (vd->storage_class & STCextern)) {
vd->toObjFile(0); // TODO: multiobj
@@ -135,7 +134,7 @@ DValue* VarExp::toElem(IRState* p)
Logger::cout() << "unresolved global had type: " << *DtoType(vd->type) << '\n';
fatal();
}
return new DVarValue(type, vd, vd->ir.getIrValue(), true);
return new DVarValue(type, vd, vd->ir.getIrValue());
}
}
else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
@@ -158,7 +157,7 @@ DValue* VarExp::toElem(IRState* p)
assert(ts->sym);
DtoForceConstInitDsymbol(ts->sym);
assert(ts->sym->ir.irStruct->init);
return new DVarValue(type, ts->sym->ir.irStruct->init, true);
return new DVarValue(type, ts->sym->ir.irStruct->init);
}
else
{
@@ -281,6 +280,7 @@ DValue* ComplexExp::toElem(IRState* p)
Logger::print("ComplexExp::toElem(): %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
LLConstant* c = toConstElem(p);
LLValue* res;
if (c->isNullValue()) {
Type* t = type->toBasetype();
@@ -292,10 +292,13 @@ DValue* ComplexExp::toElem(IRState* p)
c = DtoConstFP(Type::tfloat80, 0);
else
assert(0);
return new DComplexValue(type, c, c);
res = DtoAggrPair(DtoType(type), c, c);
}
else {
res = DtoAggrPair(DtoType(type), c->getOperand(0), c->getOperand(1));
}
return new DComplexValue(type, c->getOperand(0), c->getOperand(1));
return new DImValue(type, res);
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -360,12 +363,12 @@ DValue* StringExp::toElem(IRState* p)
LLConstant* clen = llvm::ConstantInt::get(DtoSize_t(),len,false);
LLValue* tmpmem = DtoAlloca(DtoType(dtype),"tempstring");
DtoSetArray(tmpmem, clen, arrptr);
return new DVarValue(type, tmpmem, true);
return new DVarValue(type, tmpmem);
}
else if (dtype->ty == Tsarray) {
const LLType* dstType = getPtrToType(LLArrayType::get(ct, len));
LLValue* emem = (gvar->getType() == dstType) ? gvar : DtoBitCast(gvar, dstType);
return new DVarValue(type, emem, true);
return new DVarValue(type, emem);
}
else if (dtype->ty == Tpointer) {
return new DImValue(type, arrptr);
@@ -456,7 +459,7 @@ DValue* AssignExp::toElem(IRState* p)
Logger::println("performing array.length assignment");
ArrayLengthExp *ale = (ArrayLengthExp *)e1;
DValue* arr = ale->e1->toElem(p);
DVarValue arrval(ale->e1->type, arr->getLVal(), true);
DVarValue arrval(ale->e1->type, arr->getLVal());
DValue* newlen = e2->toElem(p);
DSliceValue* slice = DtoResizeDynArray(arrval.getType(), &arrval, newlen);
DtoAssign(loc, &arrval, slice);
@@ -469,7 +472,7 @@ DValue* AssignExp::toElem(IRState* p)
DValue* r = e2->toElem(p);
DtoAssign(loc, l, r);
if (l->isSlice() || l->isComplex())
if (l->isSlice())
return l;
#if 0
@@ -503,7 +506,7 @@ DValue* AddExp::toElem(IRState* p)
Type* e2type = e2->type->toBasetype();
if (e1type != e2type) {
if (llvmFieldIndex) {
/*if (llvmFieldIndex) {
assert(e1type->ty == Tpointer && e1next && e1next->ty == Tstruct);
Logger::println("add to AddrExp of struct");
assert(r->isConst());
@@ -512,9 +515,9 @@ DValue* AddExp::toElem(IRState* p)
TypeStruct* ts = (TypeStruct*)e1next;
DStructIndexVector offsets;
LLValue* v = DtoIndexStruct(l->getRVal(), ts->sym, t->next, cofs->getZExtValue(), offsets);
return new DFieldValue(type, v, true);
return new DFieldValue(type, v);
}
else if (e1type->ty == Tpointer) {
else*/ if (e1type->ty == Tpointer) {
Logger::println("add to pointer");
if (r->isConst()) {
llvm::ConstantInt* cofs = llvm::cast<llvm::ConstantInt>(r->isConst()->c);
@@ -848,7 +851,9 @@ DValue* AddrExp::toElem(IRState* p)
return v;
}
Logger::println("is nothing special");
return new DFieldValue(type, v->getLVal(), false);
LLValue* lval = v->getLVal();
Logger::cout() << "lval: " << *lval << '\n';
return new DImValue(type, v->getLVal());
}
LLConstant* AddrExp::toConstElem(IRState* p)
@@ -893,12 +898,18 @@ DValue* PtrExp::toElem(IRState* p)
DValue* a = e1->toElem(p);
// this should be deterministic but right now lvalue casts don't propagate lvalueness !?!
// this is *so* ugly.. I'd really like to figure out some way to avoid this badness...
LLValue* lv = a->getRVal();
LLValue* v = lv;
if (DtoCanLoad(v))
Type* bt = type->toBasetype();
// we can't load function pointers, but they aren't passed by reference either
// FIXME: maybe a MayLoad function isn't a bad idea after all ...
if (!DtoIsPassedByRef(bt) && bt->ty != Tfunction)
v = DtoLoad(v);
return new DLRValue(new DVarValue(type, lv, true), new DImValue(type, v));
return new DLRValue(new DVarValue(type, lv), new DImValue(type, v));
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -951,7 +962,7 @@ DValue* DotVarExp::toElem(IRState* p)
assert(0);
//Logger::cout() << "mem: " << *arrptr << '\n';
return new DVarValue(type, vd, arrptr, true);
return new DVarValue(type, vd, arrptr);
}
else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
{
@@ -1021,7 +1032,7 @@ DValue* ThisExp::toElem(IRState* p)
{
LLValue* v = p->func()->thisArg;
assert(v);
return new DVarValue(type, v, true);
return new DVarValue(type, v);
}
// regular this expr
else if (VarDeclaration* vd = var->isVarDeclaration()) {
@@ -1034,7 +1045,7 @@ DValue* ThisExp::toElem(IRState* p)
Logger::println("normal this exp");
v = p->func()->thisArg;
}
return new DVarValue(type, vd, v, true);
return new DVarValue(type, vd, v);
}
// anything we're not yet handling ?
@@ -1082,7 +1093,7 @@ DValue* IndexExp::toElem(IRState* p)
Logger::println("invalid index exp! e1type: %s", e1type->toChars());
assert(0);
}
return new DVarValue(type, arrptr, true);
return new DVarValue(type, arrptr);
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -1479,7 +1490,7 @@ DValue* NewExp::toElem(IRState* p)
{
// allocate
LLValue* mem = DtoNew(newtype);
DVarValue tmpvar(newtype, mem, true);
DVarValue tmpvar(newtype, mem);
// default initialize
Expression* exp = newtype->defaultInit(loc);
@@ -1508,7 +1519,7 @@ DValue* DeleteExp::toElem(IRState* p)
{
LLValue* rval = dval->getRVal();
DtoDeleteMemory(rval);
if (dval->isVar() && dval->isVar()->lval)
if (dval->isVar())
DtoStore(llvm::Constant::getNullValue(rval->getType()), dval->getLVal());
}
// class
@@ -1531,7 +1542,7 @@ DValue* DeleteExp::toElem(IRState* p)
LLValue* rval = dval->getRVal();
DtoDeleteClass(rval);
}
if (dval->isVar() && dval->isVar()->lval) {
if (dval->isVar()) {
LLValue* lval = dval->getLVal();
DtoStore(llvm::Constant::getNullValue(lval->getType()->getContainedType(0)), lval);
}
@@ -1957,7 +1968,7 @@ DValue* CondExp::toElem(IRState* p)
// allocate a temporary for the final result. failed to come up with a better way :/
llvm::BasicBlock* entryblock = &p->topfunc()->front();
LLValue* resval = DtoAlloca(resty,"condtmp");
DVarValue* dvv = new DVarValue(type, resval, true);
DVarValue* dvv = new DVarValue(type, resval);
llvm::BasicBlock* oldend = p->scopeend();
llvm::BasicBlock* condtrue = llvm::BasicBlock::Create("condtrue", gIR->topfunc(), oldend);
@@ -2115,10 +2126,10 @@ DValue* FuncExp::toElem(IRState* p)
LLValue* castfptr = DtoBitCast(fd->ir.irFunc->func, fptr->getType()->getContainedType(0));
DtoStore(castfptr, fptr);
return new DVarValue(type, lval, true);
return new DVarValue(type, lval);
} else if(fd->tok == TOKfunction) {
return new DVarValue(type, fd->ir.irFunc->func, false);
return new DImValue(type, fd->ir.irFunc->func);
}
assert(0 && "fd->tok must be TOKfunction or TOKdelegate");
@@ -2159,7 +2170,7 @@ DValue* ArrayLiteralExp::toElem(IRState* p)
LLValue* elemAddr = DtoGEPi(dstMem,0,i,"tmp",p->scopebb());
// emulate assignment
DVarValue* vv = new DVarValue(expr->type, elemAddr, true);
DVarValue* vv = new DVarValue(expr->type, elemAddr);
DValue* e = expr->toElem(p);
DtoAssign(loc, vv, e);
}
@@ -2248,7 +2259,7 @@ DValue* StructLiteralExp::toElem(IRState* p)
Logger::cout() << "getting index " << j << " of " << *sptr << '\n';
LLValue* arrptr = DtoGEPi(sptr,0,j);
DValue* darrptr = new DVarValue(vx->type, arrptr, true);
DValue* darrptr = new DVarValue(vx->type, arrptr);
DValue* ve = vx->toElem(p);
DtoAssign(loc, darrptr, ve);
@@ -2324,7 +2335,7 @@ DValue* AssocArrayLiteralExp::toElem(IRState* p)
// it should be possible to avoid the temporary in some cases
LLValue* tmp = DtoAlloca(aalltype,"aaliteral");
DValue* aa = new DVarValue(type, tmp, true);
DValue* aa = new DVarValue(type, tmp);
DtoStore(LLConstant::getNullValue(aalltype), tmp);
const size_t n = keys->dim;

View File

@@ -25,14 +25,14 @@ bool DtoIsPassedByRef(Type* type)
{
Type* typ = type->toBasetype();
TY t = typ->ty;
return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex());
return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray);
}
bool DtoIsReturnedInArg(Type* type)
{
Type* typ = type->toBasetype();
TY t = typ->ty;
return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex());
return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray);
}
unsigned DtoShouldExtend(Type* type)
@@ -541,15 +541,6 @@ void DtoStore(LLValue* src, LLValue* dst)
//st->setVolatile(gIR->func()->inVolatile);
}
bool DtoCanLoad(LLValue* ptr)
{
if (isaPointer(ptr->getType())) {
const LLType* data = ptr->getType()->getContainedType(0);
return data->isFirstClassType() && !(isaStruct(data) || isaArray(data));
}
return false;
}
//////////////////////////////////////////////////////////////////////////////////////////
LLValue* DtoBitCast(LLValue* v, const LLType* t, const char* name)
@@ -770,3 +761,12 @@ const LLStructType* DtoModuleReferenceType()
gIR->module->addTypeName("ModuleReference", st);
return st;
}
//////////////////////////////////////////////////////////////////////////////////////////
LLValue* DtoAggrPair(const LLType* type, LLValue* V1, LLValue* V2, const char* name)
{
LLValue* res = llvm::UndefValue::get(type);
res = gIR->ir->CreateInsertValue(res, V1, 0, "tmp");
return gIR->ir->CreateInsertValue(res, V2, 1, name?name:"tmp");
}

View File

@@ -60,7 +60,6 @@ LLConstant* DtoConstStringPtr(const char* str, const char* section = 0);
LLConstant* DtoConstBool(bool);
// llvm wrappers
bool DtoCanLoad(LLValue* ptr);
LLValue* DtoLoad(LLValue* src, const char* name=0);
void DtoStore(LLValue* src, LLValue* dst);
LLValue* DtoBitCast(LLValue* v, const LLType* t, const char* name=0);
@@ -93,6 +92,9 @@ size_t getABITypeSize(const LLType* t);
unsigned char getABITypeAlign(const LLType* t);
unsigned char getPrefTypeAlign(const LLType* t);
// pair type helpers
LLValue* DtoAggrPair(const LLType* type, LLValue* V1, LLValue* V2, const char* name = 0);
/**
* Generates a call to llvm.memset.i32 (or i64 depending on architecture).
* @param dst Destination memory.

View File

@@ -7,12 +7,8 @@ void main()
cfloat cf3 = func();
auto c1 = cf1 + cf2;
auto c2 = cf2 - cf3;
{
auto c3 = cf1 * cf3;
{
auto c4 = cf2 / cf3;
}
}
}
cfloat func()

View File

@@ -4,11 +4,7 @@ void main()
{
cdouble c = 3.0 + 0i;
cdouble d = 2.0 + 0i;
{
cdouble c1 = c + 3.0;
cdouble c2 = c - 3.0i;
}
{
cdouble c1 = c / 2.0;
}
cdouble c1 = c + 3.0;
cdouble c2 = c - 3.0i;
cdouble c3 = c / 2.0;
}

View File

@@ -5,5 +5,5 @@ void main()
cfloat c1 = 1f + 0i;
cfloat c2 = 0f + 0i;
c2 += 1f + 0i;
//assert(c1 == c2);
assert(c1 == c2);
}

8
tests/mini/complex4.d Normal file
View File

@@ -0,0 +1,8 @@
module complex4;
void main()
{
cfloat c = 2f + 3fi;
float r = cast(float)c;
ifloat i = cast(ifloat)c;
}