mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-05 09:31:03 +03:00
Introduce new ABI class for PPC64LE.
The ABI for PPC/PPC64 big-endian is quite similar. But the ABI for PPC64 little-endian is more like the ARM ABI.
This commit is contained in:
parent
c8dae96434
commit
c1c7846e74
8 changed files with 203 additions and 58 deletions
|
@ -16,32 +16,6 @@
|
|||
#include "gen/abi-generic.h"
|
||||
#include "gen/abi-aarch64.h"
|
||||
|
||||
namespace {
|
||||
struct CompositeToArray64 : ABIRewrite {
|
||||
LLValue *get(Type *dty, LLValue *v) override {
|
||||
Logger::println("rewriting i64 array -> as %s", dty->toChars());
|
||||
LLValue *lval = DtoRawAlloca(v->getType(), 0);
|
||||
DtoStore(v, lval);
|
||||
|
||||
LLType *pTy = getPtrToType(DtoType(dty));
|
||||
return DtoLoad(DtoBitCast(lval, pTy), "get-result");
|
||||
}
|
||||
|
||||
LLValue *put(DValue *dv) override {
|
||||
Type *dty = dv->getType();
|
||||
Logger::println("rewriting %s -> as i64 array", dty->toChars());
|
||||
LLType *t = type(dty, nullptr);
|
||||
return DtoLoad(DtoBitCast(dv->getRVal(), getPtrToType(t)));
|
||||
}
|
||||
|
||||
LLType *type(Type *t, LLType *) override {
|
||||
// An i64 array that will hold Type 't'
|
||||
size_t sz = (t->size() + 7) / 8;
|
||||
return LLArrayType::get(LLIntegerType::get(gIR->context(), 64), sz);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
struct AArch64TargetABI : TargetABI {
|
||||
HFAToArray hfaToArray;
|
||||
CompositeToArray64 compositeToArray64;
|
||||
|
|
|
@ -241,6 +241,10 @@ struct ExplicitByvalRewrite : ABIRewrite {
|
|||
* float type.
|
||||
*/
|
||||
struct HFAToArray : ABIRewrite {
|
||||
const int maxFloats = 4;
|
||||
|
||||
HFAToArray(const int max = 4) : maxFloats(max) {}
|
||||
|
||||
LLValue *get(Type *dty, LLValue *v) override {
|
||||
Logger::println("rewriting array -> as HFA %s", dty->toChars());
|
||||
LLValue *lval = DtoRawAlloca(v->getType(), 0);
|
||||
|
@ -260,10 +264,37 @@ struct HFAToArray : ABIRewrite {
|
|||
LLType *type(Type *dty, LLType *) override {
|
||||
assert(dty->ty == Tstruct);
|
||||
LLType *floatArrayType = nullptr;
|
||||
if (TargetABI::isHFA((TypeStruct *)dty, &floatArrayType))
|
||||
if (TargetABI::isHFA((TypeStruct *)dty, &floatArrayType, maxFloats))
|
||||
return floatArrayType;
|
||||
llvm_unreachable("Type dty should be an HFA");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Rewrite a composite as array of i64.
|
||||
*/
|
||||
struct CompositeToArray64 : ABIRewrite {
|
||||
LLValue *get(Type *dty, LLValue *v) override {
|
||||
Logger::println("rewriting i64 array -> as %s", dty->toChars());
|
||||
LLValue *lval = DtoRawAlloca(v->getType(), 0);
|
||||
DtoStore(v, lval);
|
||||
|
||||
LLType *pTy = getPtrToType(DtoType(dty));
|
||||
return DtoLoad(DtoBitCast(lval, pTy), "get-result");
|
||||
}
|
||||
|
||||
LLValue *put(DValue *dv) override {
|
||||
Type *dty = dv->getType();
|
||||
Logger::println("rewriting %s -> as i64 array", dty->toChars());
|
||||
LLType *t = type(dty, nullptr);
|
||||
return DtoLoad(DtoBitCast(dv->getRVal(), getPtrToType(t)));
|
||||
}
|
||||
|
||||
LLType *type(Type *t, LLType *) override {
|
||||
// An i64 array that will hold Type 't'
|
||||
size_t sz = (t->size() + 7) / 8;
|
||||
return LLArrayType::get(LLIntegerType::get(gIR->context(), 64), sz);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,25 +7,32 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The ABI implementation used for 32/64 bit big-endian PowerPC targets.
|
||||
//
|
||||
// The System V Application Binary Interface PowerPC Processor Supplement can be
|
||||
// found here:
|
||||
// http://refspecs.linuxfoundation.org/elf/elfspec_ppc.pdf
|
||||
//
|
||||
// The PowerOpen 64bit ABI can be found here:
|
||||
// http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html
|
||||
// http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.pdf
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "gen/abi.h"
|
||||
#include "gen/abi-generic.h"
|
||||
#include "gen/abi-ppc64.h"
|
||||
#include "gen/abi-ppc.h"
|
||||
#include "gen/dvalue.h"
|
||||
#include "gen/irstate.h"
|
||||
#include "gen/llvmhelpers.h"
|
||||
#include "gen/tollvm.h"
|
||||
|
||||
struct PPC64TargetABI : TargetABI {
|
||||
struct PPCTargetABI : TargetABI {
|
||||
ExplicitByvalRewrite byvalRewrite;
|
||||
IntegerRewrite integerRewrite;
|
||||
const bool Is64Bit;
|
||||
|
||||
explicit PPC64TargetABI(const bool Is64Bit) : Is64Bit(Is64Bit) {}
|
||||
explicit PPCTargetABI(const bool Is64Bit) : Is64Bit(Is64Bit) {}
|
||||
|
||||
bool returnInArg(TypeFunction *tf) override {
|
||||
if (tf->isref) {
|
||||
|
@ -81,6 +88,6 @@ struct PPC64TargetABI : TargetABI {
|
|||
};
|
||||
|
||||
// The public getter for abi.cpp
|
||||
TargetABI *getPPC64TargetABI(bool Is64Bit) {
|
||||
return new PPC64TargetABI(Is64Bit);
|
||||
TargetABI *getPPCTargetABI(bool Is64Bit) {
|
||||
return new PPCTargetABI(Is64Bit);
|
||||
}
|
|
@ -7,15 +7,15 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The ABI implementation used for 64 bit PowerPC targets.
|
||||
// The ABI implementation used for 32/64 bit big-endian PowerPC targets.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LDC_GEN_ABI_PPC64_H
|
||||
#define LDC_GEN_ABI_PPC64_H
|
||||
#ifndef LDC_GEN_ABI_PPC_H
|
||||
#define LDC_GEN_ABI_PPC_H
|
||||
|
||||
struct TargetABI;
|
||||
|
||||
TargetABI *getPPC64TargetABI(bool Is64Bit);
|
||||
TargetABI *getPPCTargetABI(bool Is64Bit);
|
||||
|
||||
#endif
|
107
gen/abi-ppc64le.cpp
Normal file
107
gen/abi-ppc64le.cpp
Normal file
|
@ -0,0 +1,107 @@
|
|||
//===-- abi-ppc64.cpp -----------------------------------------------------===//
|
||||
//
|
||||
// LDC - the LLVM D compiler
|
||||
//
|
||||
// This file is distributed under the BSD-style LDC license. See the LICENSE
|
||||
// file for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The ABI implementation used for 64 bit little-endian PowerPC targets.
|
||||
//
|
||||
// The PowerOpen 64bit ELF v2 ABI can be found here:
|
||||
// https://members.openpowerfoundation.org/document/dl/576
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "gen/abi.h"
|
||||
#include "gen/abi-generic.h"
|
||||
#include "gen/abi-ppc64le.h"
|
||||
#include "gen/dvalue.h"
|
||||
#include "gen/irstate.h"
|
||||
#include "gen/llvmhelpers.h"
|
||||
#include "gen/tollvm.h"
|
||||
|
||||
struct PPC64LETargetABI : TargetABI {
|
||||
HFAToArray hfaToArray;
|
||||
CompositeToArray64 compositeToArray64;
|
||||
IntegerRewrite integerRewrite;
|
||||
|
||||
explicit PPC64LETargetABI() : hfaToArray(8) {}
|
||||
|
||||
bool returnInArg(TypeFunction *tf) override {
|
||||
if (tf->isref) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Type *rt = tf->next->toBasetype();
|
||||
|
||||
// FIXME: The return value of this function translates
|
||||
// to RETstack or RETregs in function retStyle(), which
|
||||
// directly influences if NRVO is possible or not
|
||||
// (false -> RETregs -> nrvo_can = false). Depending on
|
||||
// NRVO, the postblit constructor is called or not.
|
||||
// Thus using the rules of the C ABI here (as mandated by
|
||||
// the D specification) leads to crashes.
|
||||
if (tf->linkage == LINKd)
|
||||
return rt->ty == Tsarray || rt->ty == Tstruct;
|
||||
|
||||
return rt->ty == Tsarray || (rt->ty == Tstruct && rt->size() > 16 &&
|
||||
!isHFA((TypeStruct *)rt, nullptr, 8));
|
||||
}
|
||||
|
||||
bool passByVal(Type *t) override {
|
||||
t = t->toBasetype();
|
||||
return t->ty == Tsarray || (t->ty == Tstruct && t->size() > 16 &&
|
||||
!isHFA((TypeStruct *)t, nullptr, 8));
|
||||
}
|
||||
|
||||
void rewriteFunctionType(TypeFunction *tf, IrFuncTy &fty) override {
|
||||
// RETURN VALUE
|
||||
Type *retTy = fty.ret->type->toBasetype();
|
||||
if (!fty.ret->byref) {
|
||||
if (retTy->ty == Tstruct || retTy->ty == Tsarray) {
|
||||
if (retTy->ty == Tstruct &&
|
||||
isHFA((TypeStruct *)retTy, &fty.ret->ltype, 8)) {
|
||||
fty.ret->rewrite = &hfaToArray;
|
||||
fty.ret->ltype = hfaToArray.type(fty.ret->type, fty.ret->ltype);
|
||||
} else if (canRewriteAsInt(retTy, true)) {
|
||||
fty.ret->rewrite = &integerRewrite;
|
||||
fty.ret->ltype = integerRewrite.type(fty.ret->type, fty.ret->ltype);
|
||||
} else {
|
||||
fty.ret->rewrite = &compositeToArray64;
|
||||
fty.ret->ltype =
|
||||
compositeToArray64.type(fty.ret->type, fty.ret->ltype);
|
||||
}
|
||||
} else if (retTy->isintegral())
|
||||
fty.ret->attrs.add(retTy->isunsigned() ? LLAttribute::ZExt
|
||||
: LLAttribute::SExt);
|
||||
}
|
||||
|
||||
// EXPLICIT PARAMETERS
|
||||
for (auto arg : fty.args) {
|
||||
if (!arg->byref) {
|
||||
rewriteArgument(fty, *arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
|
||||
Type *ty = arg.type->toBasetype();
|
||||
if (ty->ty == Tstruct || ty->ty == Tsarray) {
|
||||
if (ty->ty == Tstruct && isHFA((TypeStruct *)ty, &arg.ltype, 8)) {
|
||||
arg.rewrite = &hfaToArray;
|
||||
arg.ltype = hfaToArray.type(arg.type, arg.ltype);
|
||||
} else if (canRewriteAsInt(ty, true)) {
|
||||
arg.rewrite = &integerRewrite;
|
||||
arg.ltype = integerRewrite.type(arg.type, arg.ltype);
|
||||
} else {
|
||||
arg.rewrite = &compositeToArray64;
|
||||
arg.ltype = compositeToArray64.type(arg.type, arg.ltype);
|
||||
}
|
||||
} else if (ty->isintegral())
|
||||
arg.attrs.add(ty->isunsigned() ? LLAttribute::ZExt : LLAttribute::SExt);
|
||||
}
|
||||
};
|
||||
|
||||
// The public getter for abi.cpp
|
||||
TargetABI *getPPC64LETargetABI() { return new PPC64LETargetABI(); }
|
21
gen/abi-ppc64le.h
Normal file
21
gen/abi-ppc64le.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
//===-- gen/abi-ppc-64.h - PPC64 ABI description ----------------*- C++ -*-===//
|
||||
//
|
||||
// LDC – the LLVM D compiler
|
||||
//
|
||||
// This file is distributed under the BSD-style LDC license. See the LICENSE
|
||||
// file for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The ABI implementation used for 64 bit little-endian PowerPC targets.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LDC_GEN_ABI_PPC64LE_H
|
||||
#define LDC_GEN_ABI_PPC64LE_H
|
||||
|
||||
struct TargetABI;
|
||||
|
||||
TargetABI *getPPC64LETargetABI();
|
||||
|
||||
#endif
|
47
gen/abi.cpp
47
gen/abi.cpp
|
@ -14,7 +14,8 @@
|
|||
#include "gen/abi-aarch64.h"
|
||||
#include "gen/abi-arm.h"
|
||||
#include "gen/abi-mips64.h"
|
||||
#include "gen/abi-ppc64.h"
|
||||
#include "gen/abi-ppc.h"
|
||||
#include "gen/abi-ppc64le.h"
|
||||
#include "gen/abi-win64.h"
|
||||
#include "gen/abi-x86-64.h"
|
||||
#include "gen/abi-x86.h"
|
||||
|
@ -166,8 +167,8 @@ bool isNestedHFA(const TypeStruct *t, d_uns64 &floatSize, int &num,
|
|||
else if (sz != floatSize) // different float size, reject
|
||||
return false;
|
||||
|
||||
if (n > 4)
|
||||
return false; // too many floats for HFA, reject
|
||||
//if (n > 4)
|
||||
// return false; // too many floats for HFA, reject
|
||||
} else {
|
||||
return false; // reject all other types
|
||||
}
|
||||
|
@ -181,29 +182,31 @@ bool isNestedHFA(const TypeStruct *t, d_uns64 &floatSize, int &num,
|
|||
}
|
||||
}
|
||||
|
||||
bool TargetABI::isHFA(TypeStruct *t, llvm::Type **rewriteType) {
|
||||
bool TargetABI::isHFA(TypeStruct *t, llvm::Type **rewriteType, const int maxFloats) {
|
||||
d_uns64 floatSize = 0;
|
||||
int num = 0;
|
||||
|
||||
if (isNestedHFA(t, floatSize, num, 1)) {
|
||||
if (rewriteType) {
|
||||
llvm::Type *floatType = nullptr;
|
||||
switch (floatSize) {
|
||||
case 4:
|
||||
floatType = llvm::Type::getFloatTy(gIR->context());
|
||||
break;
|
||||
case 8:
|
||||
floatType = llvm::Type::getDoubleTy(gIR->context());
|
||||
break;
|
||||
case 16:
|
||||
floatType = llvm::Type::getFP128Ty(gIR->context());
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Unexpected size for float type");
|
||||
if (num <= maxFloats) {
|
||||
if (rewriteType) {
|
||||
llvm::Type *floatType = nullptr;
|
||||
switch (floatSize) {
|
||||
case 4:
|
||||
floatType = llvm::Type::getFloatTy(gIR->context());
|
||||
break;
|
||||
case 8:
|
||||
floatType = llvm::Type::getDoubleTy(gIR->context());
|
||||
break;
|
||||
case 16:
|
||||
floatType = llvm::Type::getFP128Ty(gIR->context());
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Unexpected size for float type");
|
||||
}
|
||||
*rewriteType = LLArrayType::get(floatType, num);
|
||||
}
|
||||
*rewriteType = LLArrayType::get(floatType, num);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -336,9 +339,11 @@ TargetABI *TargetABI::getTarget() {
|
|||
case llvm::Triple::mips64:
|
||||
case llvm::Triple::mips64el:
|
||||
return getMIPS64TargetABI(global.params.is64bit);
|
||||
case llvm::Triple::ppc:
|
||||
case llvm::Triple::ppc64:
|
||||
return getPPCTargetABI(global.params.targetTriple.isArch64Bit());
|
||||
case llvm::Triple::ppc64le:
|
||||
return getPPC64TargetABI(global.params.targetTriple.isArch64Bit());
|
||||
return getPPC64LETargetABI();
|
||||
#if LDC_LLVM_VER == 305
|
||||
case llvm::Triple::arm64:
|
||||
case llvm::Triple::arm64_be:
|
||||
|
|
|
@ -154,7 +154,7 @@ struct TargetABI {
|
|||
/// Check if struct 't' is a Homogeneous Floating-point Aggregate (HFA)
|
||||
/// consisting of up to 4 of same floating point type. If so, optionally
|
||||
/// produce the rewriteType: an array of that floating point type
|
||||
static bool isHFA(TypeStruct *t, llvm::Type **rewriteType = nullptr);
|
||||
static bool isHFA(TypeStruct *t, llvm::Type **rewriteType = nullptr, const int maxFloats = 4);
|
||||
|
||||
protected:
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue