mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
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:
@@ -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)
|
||||
|
||||
@@ -1173,9 +1173,6 @@ struct AddExp : BinExp
|
||||
Identifier *opId_r();
|
||||
|
||||
elem *toElem(IRState *irs);
|
||||
|
||||
// LLVMDC
|
||||
bool llvmFieldIndex;
|
||||
};
|
||||
|
||||
struct MinExp : BinExp
|
||||
|
||||
@@ -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);
|
||||
|
||||
15
gen/aa.cpp
15
gen/aa.cpp
@@ -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);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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;
|
||||
|
||||
108
gen/complex.cpp
108
gen/complex.cpp
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
30
gen/dvalue.h
30
gen/dvalue.h
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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)
|
||||
|
||||
89
gen/toir.cpp
89
gen/toir.cpp
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
8
tests/mini/complex4.d
Normal file
@@ -0,0 +1,8 @@
|
||||
module complex4;
|
||||
|
||||
void main()
|
||||
{
|
||||
cfloat c = 2f + 3fi;
|
||||
float r = cast(float)c;
|
||||
ifloat i = cast(ifloat)c;
|
||||
}
|
||||
Reference in New Issue
Block a user