[svn r108] Now basic suppport for complex types. =,+,-,*,/ are supported.

This commit is contained in:
Tomas Lindquist Olsen 2007-11-19 02:58:58 +01:00
parent 6da09c01b3
commit 5e9f5034ff
11 changed files with 592 additions and 392 deletions

View file

@ -3,26 +3,35 @@
#include "declaration.h"
#include "gen/irstate.h"
#include "gen/tollvm.h"
#include "gen/dvalue.h"
//////////////////////////////////////////////////////////////////////////////
DValue* DtoBinAdd(DValue* lhs, DValue* rhs)
{
llvm::Value* v = gIR->ir->CreateAdd(lhs->getRVal(), rhs->getRVal(), "tmp");
return new DImValue( lhs->getType(), v );
}
//////////////////////////////////////////////////////////////////////////////
DValue* DtoBinSub(DValue* lhs, DValue* rhs)
{
llvm::Value* v = gIR->ir->CreateSub(lhs->getRVal(), rhs->getRVal(), "tmp");
return new DImValue( lhs->getType(), v );
}
//////////////////////////////////////////////////////////////////////////////
DValue* DtoBinMul(DValue* lhs, DValue* rhs)
{
llvm::Value* v = gIR->ir->CreateMul(lhs->getRVal(), rhs->getRVal(), "tmp");
return new DImValue( lhs->getType(), v );
}
//////////////////////////////////////////////////////////////////////////////
DValue* DtoBinDiv(DValue* lhs, DValue* rhs)
{
Type* t = lhs->getType();
@ -39,6 +48,8 @@ DValue* DtoBinDiv(DValue* lhs, DValue* rhs)
return new DImValue( lhs->getType(), res );
}
//////////////////////////////////////////////////////////////////////////////
DValue* DtoBinRem(DValue* lhs, DValue* rhs)
{
Type* t = lhs->getType();

358
gen/complex.cpp Normal file
View file

@ -0,0 +1,358 @@
#include "gen/llvm.h"
#include "mtype.h"
#include "declaration.h"
#include "gen/complex.h"
#include "gen/tollvm.h"
#include "gen/irstate.h"
#include "gen/dvalue.h"
//////////////////////////////////////////////////////////////////////////////////////////
const llvm::StructType* DtoComplexType(Type* type)
{
Type* t = DtoDType(type);
const llvm::Type* base = DtoComplexBaseType(t);
std::vector<const llvm::Type*> types;
types.push_back(base);
types.push_back(base);
return llvm::StructType::get(types);
}
const llvm::Type* DtoComplexBaseType(Type* t)
{
TY ty = DtoDType(t)->ty;
const llvm::Type* base;
if (ty == Tcomplex32) {
return llvm::Type::FloatTy;
}
else if (ty == Tcomplex64 || ty == Tcomplex80) {
return llvm::Type::DoubleTy;
}
else {
assert(0);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Constant* DtoConstComplex(Type* ty, llvm::Constant* re, llvm::Constant* im)
{
assert(0);
const llvm::Type* base = DtoComplexBaseType(ty);
std::vector<llvm::Constant*> inits;
inits.push_back(re);
inits.push_back(im);
const llvm::VectorType* vt = llvm::VectorType::get(base, 2);
return llvm::ConstantVector::get(vt, inits);
}
llvm::Constant* DtoConstComplex(Type* _ty, long double re, long double im)
{
TY ty = DtoDType(_ty)->ty;
llvm::ConstantFP* fre;
llvm::ConstantFP* fim;
const llvm::Type* base;
if (ty == Tcomplex32) {
fre = DtoConstFP(Type::tfloat32, re);
fim = DtoConstFP(Type::tfloat32, im);
base = llvm::Type::FloatTy;
}
else if (ty == Tcomplex64 || ty == Tcomplex80) {
fre = DtoConstFP(Type::tfloat64, re);
fim = DtoConstFP(Type::tfloat64, im);
base = llvm::Type::DoubleTy;
}
else
assert(0);
std::vector<llvm::Constant*> inits;
inits.push_back(fre);
inits.push_back(fim);
return llvm::ConstantStruct::get(DtoComplexType(_ty), inits);
}
llvm::Constant* DtoUndefComplex(Type* _ty)
{
assert(0);
TY ty = DtoDType(_ty)->ty;
const llvm::Type* base;
if (ty == Tcomplex32) {
base = llvm::Type::FloatTy;
}
else if (ty == Tcomplex64 || ty == Tcomplex80) {
base = llvm::Type::DoubleTy;
}
else
assert(0);
std::vector<llvm::Constant*> inits;
inits.push_back(llvm::UndefValue::get(base));
inits.push_back(llvm::UndefValue::get(base));
const llvm::VectorType* vt = llvm::VectorType::get(base, 2);
return llvm::ConstantVector::get(vt, inits);
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* DtoRealPart(DValue* val)
{
assert(0);
return gIR->ir->CreateExtractElement(val->getRVal(), DtoConstUint(0), "tmp");
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* DtoImagPart(DValue* val)
{
assert(0);
return gIR->ir->CreateExtractElement(val->getRVal(), DtoConstUint(1), "tmp");
}
//////////////////////////////////////////////////////////////////////////////////////////
DValue* DtoComplex(Type* to, DValue* val)
{
Type* t = DtoDType(val->getType());
TY ty = t->ty;
if (val->isComplex() || t->iscomplex()) {
assert(DtoDType(to) == t);
return val;
}
const llvm::Type* base = DtoComplexBaseType(to);
llvm::Constant* undef = llvm::UndefValue::get(base);
llvm::Constant* zero;
if (ty == Tfloat32 || ty == Timaginary32 || ty == Tcomplex32)
zero = llvm::ConstantFP::get(llvm::Type::FloatTy, float(0));
else if (ty == Tfloat64 || ty == Timaginary64 || ty == Tcomplex64 || ty == Tfloat80 || ty == Timaginary80 || ty == Tcomplex80)
zero = llvm::ConstantFP::get(llvm::Type::DoubleTy, double(0));
if (t->isimaginary()) {
return new DComplexValue(to, zero, val->getRVal());
}
else if (t->isfloating()) {
return new DComplexValue(to, val->getRVal(), zero);
}
else
assert(0);
}
//////////////////////////////////////////////////////////////////////////////////////////
void DtoComplexAssign(llvm::Value* l, llvm::Value* 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(llvm::Value* c, llvm::Value* re, llvm::Value* im)
{
DtoStore(re, DtoGEPi(c,0,0,"tmp"));
DtoStore(im, DtoGEPi(c,0,1,"tmp"));
}
//////////////////////////////////////////////////////////////////////////////////////////
DValue* DtoComplexAdd(Type* type, DValue* lhs, DValue* rhs)
{
lhs = DtoComplex(type, lhs);
rhs = DtoComplex(type, rhs);
llvm::Value *a, *b, *c, *d, *re, *im;
// lhs values
if (DComplexValue* cx = lhs->isComplex()) {
a = cx->re;
b = cx->im;
}
else {
a = DtoLoad(DtoGEPi(lhs->getRVal(),0,0,"tmp"));
b = DtoLoad(DtoGEPi(lhs->getRVal(),0,1,"tmp"));
}
// rhs values
if (DComplexValue* cx = rhs->isComplex()) {
c = cx->re;
d = cx->im;
}
else {
c = DtoLoad(DtoGEPi(rhs->getRVal(),0,0,"tmp"));
d = DtoLoad(DtoGEPi(rhs->getRVal(),0,1,"tmp"));
}
// add up
re = gIR->ir->CreateAdd(a, c, "tmp");
im = gIR->ir->CreateAdd(b, d, "tmp");
return new DComplexValue(type, re, im);
}
//////////////////////////////////////////////////////////////////////////////////////////
DValue* DtoComplexSub(Type* type, DValue* lhs, DValue* rhs)
{
lhs = DtoComplex(type, lhs);
rhs = DtoComplex(type, rhs);
llvm::Value *a, *b, *c, *d, *re, *im;
// lhs values
if (DComplexValue* cx = lhs->isComplex()) {
a = cx->re;
b = cx->im;
}
else {
a = DtoLoad(DtoGEPi(lhs->getRVal(),0,0,"tmp"));
b = DtoLoad(DtoGEPi(lhs->getRVal(),0,1,"tmp"));
}
// rhs values
if (DComplexValue* cx = rhs->isComplex()) {
c = cx->re;
d = cx->im;
}
else {
c = DtoLoad(DtoGEPi(rhs->getRVal(),0,0,"tmp"));
d = DtoLoad(DtoGEPi(rhs->getRVal(),0,1,"tmp"));
}
// add up
re = gIR->ir->CreateSub(a, c, "tmp");
im = gIR->ir->CreateSub(b, d, "tmp");
return new DComplexValue(type, re, im);
}
//////////////////////////////////////////////////////////////////////////////////////////
DValue* DtoComplexMul(Type* type, DValue* lhs, DValue* rhs)
{
lhs = DtoComplex(type, lhs);
rhs = DtoComplex(type, rhs);
llvm::Value *a, *b, *c, *d, *re, *im;
// lhs values
if (DComplexValue* cx = lhs->isComplex()) {
a = cx->re;
b = cx->im;
}
else {
a = DtoLoad(DtoGEPi(lhs->getRVal(),0,0,"tmp"));
b = DtoLoad(DtoGEPi(lhs->getRVal(),0,1,"tmp"));
}
// rhs values
if (DComplexValue* cx = rhs->isComplex()) {
c = cx->re;
d = cx->im;
}
else {
c = DtoLoad(DtoGEPi(rhs->getRVal(),0,0,"tmp"));
d = DtoLoad(DtoGEPi(rhs->getRVal(),0,1,"tmp"));
}
llvm::Value *tmp1, *tmp2;
tmp1 = gIR->ir->CreateMul(a, c, "tmp");
tmp2 = gIR->ir->CreateMul(b, d, "tmp");
re = gIR->ir->CreateSub(tmp1, tmp2, "tmp");
tmp1 = gIR->ir->CreateMul(b, c, "tmp");
tmp2 = gIR->ir->CreateMul(a, d, "tmp");
im = gIR->ir->CreateAdd(tmp1, tmp2, "tmp");
return new DComplexValue(type, re, im);
}
//////////////////////////////////////////////////////////////////////////////////////////
DValue* DtoComplexDiv(Type* type, DValue* lhs, DValue* rhs)
{
lhs = DtoComplex(type, lhs);
rhs = DtoComplex(type, rhs);
llvm::Value *a, *b, *c, *d, *re, *im;
// lhs values
if (DComplexValue* cx = lhs->isComplex()) {
a = cx->re;
b = cx->im;
}
else {
a = DtoLoad(DtoGEPi(lhs->getRVal(),0,0,"tmp"));
b = DtoLoad(DtoGEPi(lhs->getRVal(),0,1,"tmp"));
}
// rhs values
if (DComplexValue* cx = rhs->isComplex()) {
c = cx->re;
d = cx->im;
}
else {
c = DtoLoad(DtoGEPi(rhs->getRVal(),0,0,"tmp"));
d = DtoLoad(DtoGEPi(rhs->getRVal(),0,1,"tmp"));
}
llvm::Value *tmp1, *tmp2, *denom;
tmp1 = gIR->ir->CreateMul(c, c, "tmp");
tmp2 = gIR->ir->CreateMul(d, d, "tmp");
denom = gIR->ir->CreateAdd(tmp1, tmp2, "tmp");
tmp1 = gIR->ir->CreateMul(a, c, "tmp");
tmp2 = gIR->ir->CreateMul(b, d, "tmp");
re = gIR->ir->CreateAdd(tmp1, tmp2, "tmp");
re = gIR->ir->CreateFDiv(re, denom, "tmp");
tmp1 = gIR->ir->CreateMul(b, c, "tmp");
tmp2 = gIR->ir->CreateMul(a, d, "tmp");
im = gIR->ir->CreateSub(tmp1, tmp2, "tmp");
im = gIR->ir->CreateFDiv(im, denom, "tmp");
return new DComplexValue(type, re, im);
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* DtoComplexEquals(TOK op, DValue* lhs, DValue* rhs)
{
llvm::Value* lvec = lhs->getRVal();
llvm::Value* rvec = rhs->getRVal();
llvm::FCmpInst::Predicate cmpop;
switch(op)
{
case TOKequal:
cmpop = llvm::FCmpInst::FCMP_OEQ;
break;
case TOKnotequal:
cmpop = llvm::FCmpInst::FCMP_UNE;
break;
default:
assert(0);
}
llvm::Value* l1 = gIR->ir->CreateExtractElement(lvec, DtoConstUint(0), "re");
llvm::Value* r1 = gIR->ir->CreateExtractElement(rvec, DtoConstUint(0), "re");
llvm::Value* b1 = new llvm::FCmpInst(cmpop, l1, r1, "tmp", gIR->scopebb());
llvm::Value* l2 = gIR->ir->CreateExtractElement(lvec, DtoConstUint(1), "im");
llvm::Value* r2 = gIR->ir->CreateExtractElement(rvec, DtoConstUint(1), "im");
llvm::Value* b2 = new llvm::FCmpInst(cmpop, l2, r2, "tmp", gIR->scopebb());
return gIR->ir->CreateAnd(b1,b2,"tmp");
}

27
gen/complex.h Normal file
View file

@ -0,0 +1,27 @@
#ifndef LLVMDC_GEN_COMPLEX_H
#define LLVMDC_GEN_COMPLEX_H
const llvm::StructType* DtoComplexType(Type* t);
const llvm::Type* DtoComplexBaseType(Type* t);
llvm::Constant* DtoConstComplex(Type* t, llvm::Constant* re, llvm::Constant* im);
llvm::Constant* DtoConstComplex(Type* t, long double re, long double im);
llvm::Constant* DtoUndefComplex(Type* _ty);
llvm::Constant* DtoComplexShuffleMask(unsigned a, unsigned b);
llvm::Value* DtoRealPart(DValue* val);
llvm::Value* DtoImagPart(DValue* val);
DValue* DtoComplex(Type* to, DValue* val);
void DtoComplexAssign(llvm::Value* l, llvm::Value* r);
void DtoComplexSet(llvm::Value* c, llvm::Value* re, llvm::Value* im);
DValue* DtoComplexAdd(Type* type, DValue* lhs, DValue* rhs);
DValue* DtoComplexSub(Type* type, DValue* lhs, DValue* rhs);
DValue* DtoComplexMul(Type* type, DValue* lhs, DValue* rhs);
DValue* DtoComplexDiv(Type* type, DValue* lhs, DValue* rhs);
llvm::Value* DtoComplexEquals(TOK op, DValue* lhs, DValue* rhs);
#endif // LLVMDC_GEN_COMPLEX_H

View file

@ -32,6 +32,7 @@ struct DFuncValue;
struct DSliceValue;
struct DArrayLenValue;
struct DLValueCast;
struct DComplexValue;
// base class for d-values
struct DValue : Object
@ -51,6 +52,7 @@ struct DValue : Object
virtual DFuncValue* isFunc() { return NULL; }
virtual DArrayLenValue* isArrayLen() { return NULL; }
virtual DLValueCast* isLValueCast() { return NULL; }
virtual DComplexValue* isComplex() { return NULL; };
virtual bool inPlace() { return false; }
@ -190,4 +192,21 @@ struct DLValueCast : DValue
virtual DLValueCast* isLValueCast() { return this; }
};
// complex number immediate d-value (much like slice)
struct DComplexValue : DValue
{
Type* type;
llvm::Value* re;
llvm::Value* im;
DComplexValue(Type* t, llvm::Value* r, llvm::Value* 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

@ -28,7 +28,7 @@
#include "gen/structs.h"
#include "gen/classes.h"
#include "gen/typeinf.h"
#include "gen/complex.h"
#include "gen/dvalue.h"
//////////////////////////////////////////////////////////////////////////////////////////
@ -291,13 +291,7 @@ llvm::Constant* RealExp::toConstElem(IRState* p)
Logger::print("RealExp::toConstElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
Type* t = DtoDType(type);
const llvm::Type* fty = DtoType(t);
if (t->ty == Tfloat32 || t->ty == Timaginary32)
return llvm::ConstantFP::get(fty,float(value));
else if (t->ty == Tfloat64 || t->ty == Timaginary64 || t->ty == Tfloat80 || t->ty == Timaginary80)
return llvm::ConstantFP::get(fty,double(value));
assert(0);
return NULL;
return DtoConstFP(t, value);
}
//////////////////////////////////////////////////////////////////////////////////////////
@ -334,7 +328,18 @@ DValue* ComplexExp::toElem(IRState* p)
{
Logger::print("ComplexExp::toElem(): %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
assert(0 && "no complex yet");
llvm::Constant* c = toConstElem(p);
if (c->isNullValue()) {
Type* t = DtoDType(type);
if (t->ty == Tcomplex32)
c = DtoConstFP(Type::tfloat32, 0);
else
c = DtoConstFP(Type::tfloat64, 0);
return new DComplexValue(type, c, c);
}
return new DComplexValue(type, c->getOperand(0), c->getOperand(1));
}
//////////////////////////////////////////////////////////////////////////////////////////
@ -343,7 +348,7 @@ llvm::Constant* ComplexExp::toConstElem(IRState* p)
{
Logger::print("ComplexExp::toConstElem(): %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
assert(0 && "no complex yet");
return DtoConstComplex(type, value.re, value.im);
}
//////////////////////////////////////////////////////////////////////////////////////////
@ -484,164 +489,6 @@ DValue* AssignExp::toElem(IRState* p)
}
return l;
/*
if (l->type == DValue::ARRAYLEN)
{
DtoResizeDynArray(l->mem, r->getValue());
delete r;
delete l;
return 0;
}
Type* e1type = DtoDType(e1->type);
Type* e2type = DtoDType(e2->type);
TY e1ty = e1type->ty;
TY e2ty = e2type->ty;
DValue* e = new DValue(this);
e->type = DValue::VAR;
// struct
if (e1ty == Tstruct) {
e->mem = l->mem;
// struct + struct
if (e2ty == Tstruct) {
// struct literals do the assignment themselvs (in place)
if (!r->inplace) {
DtoStructCopy(l->mem,r->getValue());
}
else {
e->inplace = true;
}
}
// struct + const int
else if (e2type->isintegral()){
IntegerExp* iexp = (IntegerExp*)e2;
assert(iexp->value == 0 && "Only integral struct initializer allowed is zero");
DtoStructZeroInit(l->mem);
}
// :x
else
assert(0 && "struct = unknown");
}
else if (e1ty == Tsarray) {
assert(0 && "static array not supported");
}
else if (e1ty == Tarray) {
if (e2type->isscalar() || e2type->ty == Tclass){
if (l->type == DValue::SLICE) {
DtoArrayInit(l->mem, l->arg, r->getValue());
}
else {
DtoArrayInit(l->mem, r->getValue());
}
}
else if (e2ty == Tarray) {
//new llvm::StoreInst(r->val,l->val,p->scopebb());
if (r->type == DValue::NUL) {
llvm::Constant* c = llvm::cast<llvm::Constant>(r->val);
assert(c->isNullValue());
DtoNullArray(l->mem);
e->mem = l->mem;
}
else if (r->type == DValue::SLICE) {
if (l->type == DValue::SLICE) {
DtoArrayCopy(l,r);
e->type = DValue::SLICE;
e->mem = l->mem;
e->arg = l->arg;
}
else {
DtoSetArray(l->mem,r->arg,r->mem);
e->mem = l->mem;
}
}
else {
// new expressions write directly to the array reference
// so do string literals
e->mem = l->mem;
if (!r->inplace) {
assert(r->mem);
DtoArrayAssign(l->mem, r->mem);
}
else {
e->inplace = true;
}
}
}
else
assert(0);
}
else if (e1ty == Tpointer) {
e->mem = l->mem;
if (e2ty == Tpointer) {
llvm::Value* v = r->field ? r->mem : r->getValue();
Logger::cout() << "*=*: " << *v << ", " << *l->mem << '\n';
new llvm::StoreInst(v, l->mem, p->scopebb());
}
else
assert(0);
}
else if (e1ty == Tclass) {
if (e2ty == Tclass) {
llvm::Value* tmp = r->getValue();
Logger::cout() << "tmp: " << *tmp << " ||| " << *l->mem << '\n';
// assignment to this in constructor special case
if (l->isthis) {
FuncDeclaration* fdecl = p->func().decl;
// respecify the this param
if (!llvm::isa<llvm::AllocaInst>(fdecl->llvmThisVar))
fdecl->llvmThisVar = new llvm::AllocaInst(tmp->getType(), "newthis", p->topallocapoint());
new llvm::StoreInst(tmp, fdecl->llvmThisVar, p->scopebb());
e->mem = fdecl->llvmThisVar;
}
// regular class ref -> class ref assignment
else {
new llvm::StoreInst(tmp, l->mem, p->scopebb());
e->mem = l->mem;
}
}
else
assert(0);
}
else if (e1ty == Tdelegate) {
Logger::println("Assigning to delegate");
if (e2ty == Tdelegate) {
if (r->type == DValue::NUL) {
llvm::Constant* c = llvm::cast<llvm::Constant>(r->val);
if (c->isNullValue()) {
DtoNullDelegate(l->mem);
e->mem = l->mem;
}
else
assert(0);
}
else if (r->inplace) {
// do nothing
e->inplace = true;
e->mem = l->mem;
}
else {
DtoDelegateCopy(l->mem, r->getValue());
e->mem = l->mem;
}
}
else
assert(0);
}
// !struct && !array && !pointer && !class
else {
Logger::cout() << *l->mem << '\n';
new llvm::StoreInst(r->getValue(),l->mem,p->scopebb());
e->mem = l->mem;
}
delete r;
delete l;
return e;
*/
}
//////////////////////////////////////////////////////////////////////////////////////////
@ -682,8 +529,14 @@ DValue* AddExp::toElem(IRState* p)
llvm::Value* v = new llvm::GetElementPtrInst(l->getRVal(), r->getRVal(), "tmp", p->scopebb());
return new DImValue(type, v);
}
else if (t->iscomplex()) {
return DtoComplexAdd(type, l, r);
}
assert(0);
}
else if (t->iscomplex()) {
return DtoComplexAdd(type, l, r);
}
else {
return DtoBinAdd(l,r);
}
@ -701,39 +554,22 @@ DValue* AddAssignExp::toElem(IRState* p)
DValue* r = e2->toElem(p);
p->exps.pop_back();
Type* t = DtoDType(type);
DValue* res;
if (DtoDType(e1->type)->ty == Tpointer) {
llvm::Value* gep = new llvm::GetElementPtrInst(l->getRVal(),r->getRVal(),"tmp",p->scopebb());
res = new DImValue(type, gep);
}
else if (t->iscomplex()) {
res = DtoComplexAdd(type, l, r);
}
else {
res = DtoBinAdd(l,r);
}
DtoAssign(l, res);
return l;
/*
Type* e1type = DtoDType(e1->type);
DValue* e = new DValue(this);
llvm::Value* val = 0;
if (e1type->ty == Tpointer) {
val = e->mem = new llvm::GetElementPtrInst(l->getValue(),r->getValue(),"tmp",p->scopebb());
}
else {
val = e->val = llvm::BinaryOperator::createAdd(l->getValue(),r->getValue(),"tmp",p->scopebb());
}
assert(l->mem);
new llvm::StoreInst(val,l->mem,p->scopebb());
e->type = DValue::VAR;
delete l;
delete r;
return e;
*/
}
//////////////////////////////////////////////////////////////////////////////////////////
@ -746,6 +582,8 @@ DValue* MinExp::toElem(IRState* p)
DValue* l = e1->toElem(p);
DValue* r = e2->toElem(p);
Type* t = DtoDType(type);
if (DtoDType(e1->type)->ty == Tpointer) {
llvm::Value* lv = l->getRVal();
llvm::Value* rv = r->getRVal();
@ -759,34 +597,12 @@ DValue* MinExp::toElem(IRState* p)
diff = p->ir->CreateIntToPtr(diff, DtoType(type));
return new DImValue(type, diff);
}
else if (t->iscomplex()) {
return DtoComplexSub(type, l, r);
}
else {
return DtoBinSub(l,r);
}
/*
llvm::Value* left = l->getValue();
if (isaPointer(left->getType()))
left = new llvm::PtrToIntInst(left,DtoSize_t(),"tmp",p->scopebb());
llvm::Value* right = r->getValue();
if (isaPointer(right->getType()))
right = new llvm::PtrToIntInst(right,DtoSize_t(),"tmp",p->scopebb());
e->val = llvm::BinaryOperator::createSub(left,right,"tmp",p->scopebb());
e->type = DValue::VAL;
const llvm::Type* totype = DtoType(type);
if (e->val->getType() != totype) {
assert(0);
assert(isaPointer(e->val->getType()));
assert(llvm::isa<llvm::IntegerType>(totype));
e->val = new llvm::IntToPtrInst(e->val,totype,"tmp",p->scopebb());
}
delete l;
delete r;
return e;
*/
}
//////////////////////////////////////////////////////////////////////////////////////////
@ -799,6 +615,8 @@ DValue* MinAssignExp::toElem(IRState* p)
DValue* l = e1->toElem(p);
DValue* r = e2->toElem(p);
Type* t = DtoDType(type);
DValue* res;
if (DtoDType(e1->type)->ty == Tpointer) {
llvm::Value* tmp = r->getRVal();
@ -807,212 +625,113 @@ DValue* MinAssignExp::toElem(IRState* p)
tmp = new llvm::GetElementPtrInst(l->getRVal(),tmp,"tmp",p->scopebb());
res = new DImValue(type, tmp);
}
else if (t->iscomplex()) {
res = DtoComplexSub(type, l, r);
}
else {
res = DtoBinSub(l,r);
}
DtoAssign(l, res);
return l;
/*
Type* e1type = DtoDType(e1->type);
llvm::Value* tmp = 0;
if (e1type->ty == Tpointer) {
tmp = r->getValue();
llvm::Value* zero = llvm::ConstantInt::get(tmp->getType(),0,false);
tmp = llvm::BinaryOperator::createSub(zero,tmp,"tmp",p->scopebb());
tmp = new llvm::GetElementPtrInst(l->getValue(),tmp,"tmp",p->scopebb());
}
else {
tmp = llvm::BinaryOperator::createSub(l->getValue(),r->getValue(),"tmp",p->scopebb());
}
assert(l->mem);
new llvm::StoreInst(tmp, l->mem, p->scopebb());
delete l;
delete r;
DValue* e = new DValue(this);
e->val = tmp;
e->type = DValue::VAR;
return e;
*/
}
//////////////////////////////////////////////////////////////////////////////////////////
DValue* MulExp::toElem(IRState* p)
{
Logger::print("MulExp::toElem: %s\n", toChars());
Logger::print("MulExp::toElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
DValue* l = e1->toElem(p);
DValue* r = e2->toElem(p);
if (type->iscomplex()) {
return DtoComplexMul(type, l, r);
}
return DtoBinMul(l,r);
/*
if (l->dvalue && r->dvalue) {
Logger::println("DVALUE PATH");
e->dvalue = DtoBinMul(l->dvalue, r->dvalue);
e->val = e->dvalue->getRVal();
}
else {
llvm::Value* vl = l->getValue();
llvm::Value* vr = r->getValue();
Logger::cout() << "mul: " << *vl << ", " << *vr << '\n';
e->val = llvm::BinaryOperator::createMul(vl,vr,"tmp",p->scopebb());
e->dvalue = new DImValue(type, e->val);
}
e->type = DValue::VAL;
delete l;
delete r;
return e;
*/
}
//////////////////////////////////////////////////////////////////////////////////////////
DValue* MulAssignExp::toElem(IRState* p)
{
Logger::print("MulAssignExp::toElem: %s\n", toChars());
Logger::print("MulAssignExp::toElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
DValue* l = e1->toElem(p);
DValue* r = e2->toElem(p);
DValue* res = DtoBinMul(l,r);
DValue* res;
if (type->iscomplex()) {
res = DtoComplexMul(type, l, r);
}
else {
res = DtoBinMul(l,r);
}
DtoAssign(l, res);
return l;
/*
llvm::Value* vl = l->getValue();
llvm::Value* vr = r->getValue();
Logger::cout() << "mulassign: " << *vl << ", " << *vr << '\n';
llvm::Value* tmp = llvm::BinaryOperator::createMul(vl,vr,"tmp",p->scopebb());
assert(l->mem);
new llvm::StoreInst(tmp,l->mem,p->scopebb());
delete l;
delete r;
DValue* e = new DValue(this);
e->val = tmp;
e->type = DValue::VAR;
return e;
*/
}
//////////////////////////////////////////////////////////////////////////////////////////
DValue* DivExp::toElem(IRState* p)
{
Logger::print("DivExp::toElem: %s\n", toChars());
Logger::print("DivExp::toElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
DValue* l = e1->toElem(p);
DValue* r = e2->toElem(p);
if (type->iscomplex()) {
return DtoComplexDiv(type, l, r);
}
return DtoBinDiv(l, r);
/*
Type* t = DtoDType(type);
if (t->isunsigned())
e->val = llvm::BinaryOperator::createUDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
else if (t->isintegral())
e->val = llvm::BinaryOperator::createSDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
else if (t->isfloating())
e->val = llvm::BinaryOperator::createFDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
else
assert(0);
e->type = DValue::VAL;
delete l;
delete r;
return e;
*/
}
//////////////////////////////////////////////////////////////////////////////////////////
DValue* DivAssignExp::toElem(IRState* p)
{
Logger::print("DivAssignExp::toElem: %s\n", toChars());
Logger::print("DivAssignExp::toElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
DValue* l = e1->toElem(p);
DValue* r = e2->toElem(p);
DValue* res = DtoBinDiv(l,r);
DValue* res;
if (type->iscomplex()) {
res = DtoComplexDiv(type, l, r);
}
else {
res = DtoBinDiv(l,r);
}
DtoAssign(l, res);
return l;
/*
Type* t = DtoDType(type);
llvm::Value* tmp;
if (t->isunsigned())
tmp = llvm::BinaryOperator::createUDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
else if (t->isintegral())
tmp = llvm::BinaryOperator::createSDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
else if (t->isfloating())
tmp = llvm::BinaryOperator::createFDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
else
assert(0);
assert(l->mem);
new llvm::StoreInst(tmp,l->mem,p->scopebb());
delete l;
delete r;
DValue* e = new DValue(this);
e->val = tmp;
e->type = DValue::VAR;
return e;
*/
}
//////////////////////////////////////////////////////////////////////////////////////////
DValue* ModExp::toElem(IRState* p)
{
Logger::print("ModExp::toElem: %s\n", toChars());
Logger::print("ModExp::toElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
DValue* l = e1->toElem(p);
DValue* r = e2->toElem(p);
return DtoBinRem(l, r);
/*
Type* t = DtoDType(type);
if (t->isunsigned())
e->val = llvm::BinaryOperator::createURem(l->getValue(),r->getValue(),"tmp",p->scopebb());
else if (t->isintegral())
e->val = llvm::BinaryOperator::createSRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
else if (t->isfloating())
e->val = llvm::BinaryOperator::createFRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
else
assert(0);
e->type = DValue::VAL;
delete l;
delete r;
return e;
*/
}
//////////////////////////////////////////////////////////////////////////////////////////
DValue* ModAssignExp::toElem(IRState* p)
{
Logger::print("ModAssignExp::toElem: %s\n", toChars());
Logger::print("ModAssignExp::toElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
DValue* l = e1->toElem(p);
@ -1022,39 +741,13 @@ DValue* ModAssignExp::toElem(IRState* p)
DtoAssign(l, res);
return l;
/*
Type* t = DtoDType(type);
llvm::Value* tmp;
if (t->isunsigned())
tmp = llvm::BinaryOperator::createURem(l->getValue(),r->getValue(),"tmp",p->scopebb());
else if (t->isintegral())
tmp = llvm::BinaryOperator::createSRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
else if (t->isfloating())
tmp = llvm::BinaryOperator::createFRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
else
assert(0);
assert(l->mem);
new llvm::StoreInst(tmp,l->mem,p->scopebb());
delete l;
delete r;
DValue* e = new DValue(this);
e->val = tmp;
e->type = DValue::VAR;
return e;
*/
}
//////////////////////////////////////////////////////////////////////////////////////////
DValue* CallExp::toElem(IRState* p)
{
Logger::print("CallExp::toElem: %s\n", toChars());
Logger::print("CallExp::toElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
DValue* fn = e1->toElem(p);
@ -1880,6 +1573,11 @@ DValue* EqualExp::toElem(IRState* p)
}
eval = new llvm::ICmpInst(cmpop, l->getRVal(), r->getRVal(), "tmp", p->scopebb());
}
else if (t->iscomplex())
{
Logger::println("complex");
eval = DtoComplexEquals(op, l, r);
}
else if (t->isfloating())
{
Logger::println("floating");
@ -2439,9 +2137,9 @@ DValue* NegExp::toElem(IRState* p)
if (t->isintegral())
zero = llvm::ConstantInt::get(val->getType(), 0, true);
else if (t->isfloating()) {
if (t->ty == Tfloat32)
if (t->ty == Tfloat32 || t->ty == Timaginary32)
zero = llvm::ConstantFP::get(val->getType(), float(0));
else if (t->ty == Tfloat64 || t->ty == Tfloat80)
else if (t->ty == Tfloat64 || t->ty == Tfloat80 || t->ty == Timaginary64 || t->ty == Timaginary80)
zero = llvm::ConstantFP::get(val->getType(), double(0));
else
assert(0);

View file

@ -18,11 +18,13 @@
#include "gen/structs.h"
#include "gen/classes.h"
#include "gen/typeinf.h"
#include "gen/complex.h"
bool DtoIsPassedByRef(Type* type)
{
TY t = DtoDType(type)->ty;
return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray);
Type* typ = DtoDType(type);
TY t = typ->ty;
return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex());
}
Type* DtoDType(Type* t)
@ -72,10 +74,9 @@ const llvm::Type* DtoType(Type* t)
// complex
case Tcomplex32:
return DtoComplexType(llvm::Type::FloatTy);
case Tcomplex64:
case Tcomplex80:
return DtoComplexType(llvm::Type::DoubleTy);
return DtoComplexType(t);
// pointers
case Tpointer: {
@ -196,16 +197,6 @@ const llvm::StructType* DtoDelegateType(Type* t)
//////////////////////////////////////////////////////////////////////////////////////////
const llvm::StructType* DtoComplexType(const llvm::Type* base)
{
std::vector<const llvm::Type*> types;
types.push_back(base);
types.push_back(base);
return llvm::StructType::get(types);
}
//////////////////////////////////////////////////////////////////////////////////////////
static llvm::Function* LLVM_DeclareMemIntrinsic(const char* name, int bits, bool set=false)
{
assert(bits == 32 || bits == 64);
@ -902,6 +893,15 @@ void DtoAssign(DValue* lhs, DValue* rhs)
DtoStore(rhs->getRVal(), lhs->getLVal());
}
}
else if (t->iscomplex()) {
assert(!lhs->isComplex());
if (DComplexValue* cx = rhs->isComplex()) {
DtoComplexSet(lhs->getRVal(), cx->re, cx->im);
}
else {
DtoComplexAssign(lhs->getRVal(), rhs->getRVal());
}
}
else {
llvm::Value* r = rhs->getRVal();
llvm::Value* l = lhs->getLVal();
@ -990,6 +990,9 @@ DValue* DtoCastPtr(DValue* val, Type* to)
DValue* DtoCastFloat(DValue* val, Type* to)
{
if (val->getType() == to)
return val;
const llvm::Type* tolltype = DtoType(to);
Type* totype = DtoDType(to);
@ -1001,7 +1004,11 @@ DValue* DtoCastFloat(DValue* val, Type* to)
llvm::Value* rval;
if (totype->isfloating()) {
if (totype->iscomplex()) {
assert(0);
//return new DImValue(to, DtoComplex(to, val));
}
else if (totype->isfloating()) {
if ((fromtype->ty == Tfloat80 || fromtype->ty == Tfloat64) && (totype->ty == Tfloat80 || totype->ty == Tfloat64)) {
rval = val->getRVal();
}
@ -1030,6 +1037,25 @@ DValue* DtoCastFloat(DValue* val, Type* to)
return new DImValue(to, rval);
}
DValue* DtoCastComplex(DValue* val, Type* _to)
{
Type* to = DtoDType(_to);
llvm::Value* v = val->getRVal();
if (to->iscomplex()) {
assert(0);
}
else if (to->isimaginary()) {
DImValue* im = new DImValue(to, gIR->ir->CreateExtractElement(v, DtoConstUint(1), "im"));
return DtoCastFloat(im, to);
}
else if (to->isfloating()) {
DImValue* re = new DImValue(to, gIR->ir->CreateExtractElement(v, DtoConstUint(0), "re"));
return DtoCastFloat(re, to);
}
else
assert(0);
}
DValue* DtoCastClass(DValue* val, Type* _to)
{
const llvm::Type* tolltype = DtoType(_to);
@ -1045,6 +1071,9 @@ DValue* DtoCast(DValue* val, Type* to)
if (fromtype->isintegral()) {
return DtoCastInt(val, to);
}
else if (fromtype->iscomplex()) {
return DtoCastComplex(val, to);
}
else if (fromtype->isfloating()) {
return DtoCastFloat(val, to);
}
@ -1081,6 +1110,16 @@ llvm::Constant* DtoConstBool(bool b)
return llvm::ConstantInt::get(llvm::Type::Int1Ty, b, false);
}
llvm::ConstantFP* DtoConstFP(Type* t, long double value)
{
TY ty = DtoDType(t)->ty;
if (ty == Tfloat32 || ty == Timaginary32)
return llvm::ConstantFP::get(llvm::Type::FloatTy, float(value));
else if (ty == Tfloat64 || ty == Timaginary64 || ty == Tfloat80 || ty == Timaginary80)
return llvm::ConstantFP::get(llvm::Type::DoubleTy, double(value));
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Constant* DtoConstString(const char* str)
@ -1165,6 +1204,8 @@ bool DtoCanLoad(llvm::Value* ptr)
return false;
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t)
{
if (v->getType() == t)
@ -1172,6 +1213,8 @@ llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t)
return gIR->ir->CreateBitCast(v, t, "tmp");
}
//////////////////////////////////////////////////////////////////////////////////////////
const llvm::PointerType* isaPointer(llvm::Value* v)
{
return llvm::dyn_cast<llvm::PointerType>(v->getType());

View file

@ -22,8 +22,6 @@ llvm::Value* DtoBoolean(llvm::Value* val);
const llvm::Type* DtoSize_t();
const llvm::StructType* DtoComplexType(const llvm::Type* base);
llvm::Constant* DtoConstInitializer(Type* type, Initializer* init);
llvm::Constant* DtoConstFieldInitializer(Type* type, Initializer* init);
DValue* DtoInitializer(Initializer* init);
@ -50,6 +48,8 @@ llvm::Value* DtoNestedVariable(VarDeclaration* vd);
llvm::ConstantInt* DtoConstSize_t(size_t);
llvm::ConstantInt* DtoConstUint(unsigned i);
llvm::ConstantInt* DtoConstInt(int i);
llvm::ConstantFP* DtoConstFP(Type* t, long double value);
llvm::Constant* DtoConstString(const char*);
llvm::Constant* DtoConstStringPtr(const char* str, const char* section = 0);
llvm::Constant* DtoConstBool(bool);
@ -98,6 +98,7 @@ void DtoAssign(DValue* lhs, DValue* rhs);
DValue* DtoCastInt(DValue* val, Type* to);
DValue* DtoCastPtr(DValue* val, Type* to);
DValue* DtoCastFloat(DValue* val, Type* to);
DValue* DtoCastComplex(DValue* val, Type* to);
DValue* DtoCastClass(DValue* val, Type* to);
DValue* DtoCast(DValue* val, Type* to);

View file

@ -105,6 +105,8 @@ gen/arrays.h
gen/binops.cpp
gen/classes.cpp
gen/classes.h
gen/complex.cpp
gen/complex.h
gen/dvalue.cpp
gen/dvalue.h
gen/dwarftypes.cpp
@ -142,6 +144,7 @@ lphobos/internal/aApply.d
lphobos/internal/aApplyR.d
lphobos/internal/adi.d
lphobos/internal/arrays.d
lphobos/internal/cmath2.d
lphobos/internal/contract.d
lphobos/internal/mem.d
lphobos/internal/moduleinit.d
@ -317,6 +320,8 @@ test/classinfo1.d
test/classinfo2.d
test/comma.d
test/complex1.d
test/complex2.d
test/complex3.d
test/cond.d
test/cond1.d
test/condexp.d

View file

@ -2,5 +2,20 @@ module complex1;
void main()
{
cfloat c1;
cfloat cf1 = 3f + 0i;
cfloat cf2 = 4f + 1i;
cfloat cf3 = func();
auto c1 = cf1 + cf2;
auto c2 = cf2 - cf3;
{
auto c3 = cf1 * cf3;
{
auto c4 = cf2 / cf3;
}
}
}
cfloat func()
{
return 3f + 1i;
}

14
test/complex2.d Normal file
View file

@ -0,0 +1,14 @@
module complex2;
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;
}
}

9
test/complex3.d Normal file
View file

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