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:
Kai Nacke 2016-03-26 00:48:40 +01:00
parent c8dae96434
commit c1c7846e74
8 changed files with 203 additions and 58 deletions

View file

@ -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;

View file

@ -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

View file

@ -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);
}

View file

@ -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
View 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
View 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

View file

@ -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,11 +182,12 @@ 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 (num <= maxFloats) {
if (rewriteType) {
llvm::Type *floatType = nullptr;
switch (floatSize) {
@ -205,6 +207,7 @@ bool TargetABI::isHFA(TypeStruct *t, llvm::Type **rewriteType) {
}
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:

View file

@ -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: