Skip to content

Commit b565e94

Browse files
committed
gen/abi: add more s390x ABI rewrites
1 parent 2b3e053 commit b565e94

File tree

1 file changed

+51
-3
lines changed

1 file changed

+51
-3
lines changed

gen/abi/systemz.cpp

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,38 @@
2323
#include "gen/llvmhelpers.h"
2424
#include "gen/tollvm.h"
2525

26+
using namespace dmd;
27+
28+
struct StructSimpleFlattenRewrite : BaseBitcastABIRewrite {
29+
LLType *type(Type *ty) override {
30+
const size_t type_size = size(ty);
31+
// "A struct or a union of 1, 2, 4, or 8 bytes"
32+
switch (type_size) {
33+
case 1:
34+
return LLType::getInt8Ty(gIR->context());
35+
case 2:
36+
return LLType::getInt16Ty(gIR->context());
37+
case 4:
38+
return LLType::getInt32Ty(gIR->context());
39+
case 8:
40+
return LLType::getInt64Ty(gIR->context());
41+
default:
42+
return DtoType(ty);
43+
}
44+
}
45+
};
46+
2647
struct SystemZTargetABI : TargetABI {
2748
IndirectByvalRewrite indirectByvalRewrite{};
49+
StructSimpleFlattenRewrite structSimpleFlattenRewrite{};
2850

2951
explicit SystemZTargetABI() {}
3052

3153
bool isSystemZVaList(Type *t) {
3254
// look for a __va_list struct in a `std` C++ namespace
3355
if (auto ts = t->isTypeStruct()) {
3456
auto sd = ts->sym;
35-
if (strcmp(sd->ident->toChars(), "__va_list") == 0) {
57+
if (strcmp(sd->ident->toChars(), "__va_list_tag") == 0) {
3658
if (auto ns = sd->parent->isNspace()) {
3759
return strcmp(ns->toChars(), "std") == 0;
3860
}
@@ -47,10 +69,33 @@ struct SystemZTargetABI : TargetABI {
4769
return false;
4870
}
4971
Type *rt = tf->next->toBasetype();
50-
return DtoIsInMemoryOnly(rt);
72+
if (rt->ty == TY::Tstruct) {
73+
return true;
74+
}
75+
if (rt->isTypeVector() && size(rt) > 16) {
76+
return true;
77+
}
78+
return shouldPassByVal(tf->next);
5179
}
5280

5381
bool passByVal(TypeFunction *, Type *t) override {
82+
// LLVM's byval attribute is not compatible with the SystemZ ABI
83+
// due to how SystemZ's stack is setup
84+
return false;
85+
}
86+
87+
bool shouldPassByVal(Type *t) {
88+
if (t->ty == TY::Tstruct && size(t) <= 8) {
89+
return false;
90+
}
91+
// "A struct or union of any other size, a complex type, an __int128, a long
92+
// double, a _Decimal128, or a vector whose size exceeds 16 bytes"
93+
if (size(t) > 16 || t->iscomplex() || t->isimaginary()) {
94+
return true;
95+
}
96+
if (t->ty == TY::Tint128 || t->ty == TY::Tcomplex80) {
97+
return true;
98+
}
5499
return DtoIsInMemoryOnly(t);
55100
}
56101

@@ -67,7 +112,7 @@ struct SystemZTargetABI : TargetABI {
67112
}
68113

69114
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override {
70-
if (!isPOD(arg.type)) {
115+
if (!isPOD(arg.type) || shouldPassByVal(arg.type)) {
71116
// non-PODs should be passed in memory
72117
indirectByvalRewrite.applyTo(arg);
73118
return;
@@ -84,6 +129,9 @@ struct SystemZTargetABI : TargetABI {
84129
arg.attrs.addAttribute(ty->isunsigned() ? LLAttribute::ZExt
85130
: LLAttribute::SExt);
86131
}
132+
if (ty->isTypeStruct() && size(ty) <= 8) {
133+
structSimpleFlattenRewrite.applyToIfNotObsolete(arg);
134+
}
87135
}
88136

89137
Type *vaListType() override {

0 commit comments

Comments
 (0)