Mercurial > projects > ldc
diff gen/abi.cpp @ 1018:e8c6dbcd33d1
- Fixed x86-32 C ABI for complex number return values.
- Removed unused code from the ABI class.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Sun, 01 Mar 2009 19:01:05 +0100 |
parents | c749648ed2b8 |
children | 9167d492cbc2 |
line wrap: on
line diff
--- a/gen/abi.cpp Sun Mar 01 11:04:05 2009 +0100 +++ b/gen/abi.cpp Sun Mar 01 19:01:05 2009 +0100 @@ -85,7 +85,65 @@ } bool test(TypeFunction* tf) { - return (tf->next->toBasetype()->iscomplex()); + // extern(D) && is(T:creal) + return (tf->linkage == LINKd && tf->next->toBasetype()->iscomplex()); + } +}; + +////////////////////////////////////////////////////////////////////////////// + +struct X86_cfloat_rewrite : ABIRetRewrite +{ + // i64 -> {float,float} + LLValue* get(LLValue* in) + { + // extract real part + LLValue* rpart = gIR->ir->CreateTrunc(in, LLType::Int32Ty); + rpart = gIR->ir->CreateBitCast(rpart, LLType::FloatTy, ".re"); + + // extract imag part + LLValue* ipart = gIR->ir->CreateLShr(in, LLConstantInt::get(LLType::Int64Ty, 32, false)); + ipart = gIR->ir->CreateTrunc(ipart, LLType::Int32Ty); + ipart = gIR->ir->CreateBitCast(ipart, LLType::FloatTy, ".im"); + + // return {float,float} aggr pair with same bits + return DtoAggrPair(rpart, ipart, ".final_cfloat"); + } + + // {float,float} -> i64 + LLValue* put(LLValue* v) + { + // extract real + LLValue* r = gIR->ir->CreateExtractValue(v, 0); + // cast to i32 + r = gIR->ir->CreateBitCast(r, LLType::Int32Ty); + // zext to i64 + r = gIR->ir->CreateZExt(r, LLType::Int64Ty); + + // extract imag + LLValue* i = gIR->ir->CreateExtractValue(v, 1); + // cast to i32 + i = gIR->ir->CreateBitCast(i, LLType::Int32Ty); + // zext to i64 + i = gIR->ir->CreateZExt(i, LLType::Int64Ty); + // shift up + i = gIR->ir->CreateShl(i, LLConstantInt::get(LLType::Int64Ty, 32, false)); + + // combine and return + return v = gIR->ir->CreateOr(r, i); + } + + // {float,float} -> i64 + const LLType* type(const LLType* t) + { + return LLType::Int64Ty; + } + + // test if rewrite applies to function + bool test(TypeFunction* tf) + { + return (tf->linkage != LINKd) + && (tf->next->toBasetype() == Type::tcomplex32); } }; @@ -96,18 +154,19 @@ X86TargetABI() { retOps.push_back(new X87_complex_swap); + retOps.push_back(new X86_cfloat_rewrite); } - bool returnInArg(Type* t) + bool returnInArg(TypeFunction* tf) { - Type* rt = t->toBasetype(); - return (rt->ty == Tstruct); - } - - bool passByRef(Type* t) - { - t = t->toBasetype(); - return (t->ty == Tstruct || t->ty == Tsarray); + Type* rt = tf->next->toBasetype(); + // D only returns structs on the stack + if (tf->linkage == LINKd) + return (rt->ty == Tstruct); + // other ABI's follow C, which is cdouble and creal returned on the stack + // as well as structs + else + return (rt->ty == Tstruct || rt->ty == Tcomplex64 || rt->ty == Tcomplex80); } }; @@ -194,17 +253,11 @@ retOps.push_back(new X86_64_cfloat_rewrite); } - bool returnInArg(Type* t) + bool returnInArg(TypeFunction* tf) { - Type* rt = t->toBasetype(); + Type* rt = tf->next->toBasetype(); return (rt->ty == Tstruct); } - - bool passByRef(Type* t) - { - t = t->toBasetype(); - return (t->ty == Tstruct || t->ty == Tsarray); - } }; ////////////////////////////////////////////////////////////////////////////// @@ -221,17 +274,11 @@ // Don't push anything into retOps, assume defaults will be fine. } - bool returnInArg(Type* t) + bool returnInArg(TypeFunction* tf) { - Type* rt = t->toBasetype(); + Type* rt = tf->next->toBasetype(); return (rt->ty == Tstruct); } - - bool passByRef(Type* t) - { - t = t->toBasetype(); - return (t->ty == Tstruct || t->ty == Tsarray); - } }; //////////////////////////////////////////////////////////////////////////////