23
23
#include " gen/llvmhelpers.h"
24
24
#include " gen/tollvm.h"
25
25
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
+
26
47
struct SystemZTargetABI : TargetABI {
27
48
IndirectByvalRewrite indirectByvalRewrite{};
49
+ StructSimpleFlattenRewrite structSimpleFlattenRewrite{};
28
50
29
51
explicit SystemZTargetABI () {}
30
52
31
53
bool isSystemZVaList (Type *t) {
32
54
// look for a __va_list struct in a `std` C++ namespace
33
55
if (auto ts = t->isTypeStruct ()) {
34
56
auto sd = ts->sym ;
35
- if (strcmp (sd->ident ->toChars (), " __va_list " ) == 0 ) {
57
+ if (strcmp (sd->ident ->toChars (), " __va_list_tag " ) == 0 ) {
36
58
if (auto ns = sd->parent ->isNspace ()) {
37
59
return strcmp (ns->toChars (), " std" ) == 0 ;
38
60
}
@@ -47,10 +69,33 @@ struct SystemZTargetABI : TargetABI {
47
69
return false ;
48
70
}
49
71
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 );
51
79
}
52
80
53
81
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
+ }
54
99
return DtoIsInMemoryOnly (t);
55
100
}
56
101
@@ -67,7 +112,7 @@ struct SystemZTargetABI : TargetABI {
67
112
}
68
113
69
114
void rewriteArgument (IrFuncTy &fty, IrFuncTyArg &arg) override {
70
- if (!isPOD (arg.type )) {
115
+ if (!isPOD (arg.type ) || shouldPassByVal (arg. type ) ) {
71
116
// non-PODs should be passed in memory
72
117
indirectByvalRewrite.applyTo (arg);
73
118
return ;
@@ -84,6 +129,9 @@ struct SystemZTargetABI : TargetABI {
84
129
arg.attrs .addAttribute (ty->isunsigned () ? LLAttribute::ZExt
85
130
: LLAttribute::SExt);
86
131
}
132
+ if (ty->isTypeStruct () && size (ty) <= 8 ) {
133
+ structSimpleFlattenRewrite.applyToIfNotObsolete (arg);
134
+ }
87
135
}
88
136
89
137
Type *vaListType () override {
0 commit comments