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+
2647struct 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