36
36
static bool canRewriteAsInt (Type* t)
37
37
{
38
38
unsigned size = t->size ();
39
- return size <= 8 &&
40
- (size == 1 || size == 2 || size == 4 || size == 8 ) &&
41
- (t->ty == Tstruct || t->ty == Tsarray);
39
+ return size == 1 || size == 2 || size == 4 || size == 8 ;
40
+ }
41
+
42
+ // Returns true if the D type is a composite (struct or static array).
43
+ static bool isComposite (const Type* t)
44
+ {
45
+ return t->ty == Tstruct || t->ty == Tsarray;
46
+ }
42
47
48
+ // Returns true if the D type is passed byval (the callee getting a pointer
49
+ // to a dedicated hidden copy).
50
+ static bool isPassedWithByvalSemantics (Type* t)
51
+ {
52
+ return
53
+ // * structs and static arrays which can NOT be rewritten as integers
54
+ (isComposite (t) && !canRewriteAsInt (t)) ||
55
+ // * 80-bit real and ireal
56
+ (t->ty == Tfloat80 || t->ty == Timaginary80) ||
57
+ // * cdouble and creal
58
+ (t->ty == Tcomplex64 || t->ty == Tcomplex80);
43
59
}
44
60
45
61
// FIXME: This should actually be handled by LLVM and the ByVal arg attribute.
46
- // Implements byval argument passing for scalar non-struct types.
47
62
struct Win64_byval_rewrite : ABIRewrite
48
63
{
49
64
// Get instance from pointer.
@@ -60,8 +75,9 @@ struct Win64_byval_rewrite : ABIRewrite
60
75
DtoStore (DtoLoad (ptr), lval); // *lval = *ptr
61
76
}
62
77
63
- // Turn an instance into a pointer (to a private copy for the callee,
64
- // allocated by the caller).
78
+ // Convert the caller's instance to a pointer for the callee.
79
+ // The pointer points to a dedicated copy for the callee which
80
+ // is allocated by the caller.
65
81
LLValue* put (Type* dty, DValue* v)
66
82
{
67
83
/* NOTE: probably not safe
@@ -71,12 +87,25 @@ struct Win64_byval_rewrite : ABIRewrite
71
87
*/
72
88
73
89
LLValue* original = v->getRVal ();
74
- LLValue* copy = DtoRawAlloca (original->getType (), 16 , " copy_for_callee" );
75
- DtoStore (original, copy); // *copy = *original
90
+ LLValue* copy;
91
+
92
+ llvm::Type* type = original->getType ();
93
+ if (type->isPointerTy ())
94
+ {
95
+ type = type->getPointerElementType ();
96
+ copy = DtoRawAlloca (type, 16 , " copy_for_callee" );
97
+ DtoStore (DtoLoad (original), copy); // *copy = *original
98
+ }
99
+ else
100
+ {
101
+ copy = DtoRawAlloca (type, 16 , " copy_for_callee" );
102
+ DtoStore (original, copy); // *copy = original
103
+ }
104
+
76
105
return copy;
77
106
}
78
107
79
- // / should return the transformed type for this rewrite
108
+ // T => T*
80
109
LLType* type (Type* dty, LLType* t)
81
110
{
82
111
return getPtrToType (DtoType (dty));
@@ -134,22 +163,17 @@ bool Win64TargetABI::returnInArg(TypeFunction* tf)
134
163
// everything <= 64 bits and of a size that is a power of 2
135
164
// is returned in a register (RAX, or XMM0 for single float/
136
165
// double) - except for cfloat
137
- // real/ireal is returned on top of the x87 stack: ST(0)
166
+ // 80-bit real/ireal is returned on top of the x87 stack: ST(0)
138
167
// complex numbers are returned in XMM0 & XMM1 (cfloat, cdouble)
139
168
// or ST(1) & ST(0) (creal)
140
169
// all other structs and static arrays are returned by struct-return (sret)
141
- return (rt->ty == Tstruct
142
- || rt->ty == Tsarray
143
- ) && !canRewriteAsInt (rt);
170
+ return isComposite (rt) && !canRewriteAsInt (rt);
144
171
}
145
172
146
173
bool Win64TargetABI::passByVal (Type* t)
147
174
{
148
175
t = t->toBasetype ();
149
-
150
- // structs and static arrays are passed byval unless they can be
151
- // rewritten as integers
152
- return (t->ty == Tstruct || t->ty == Tsarray) && !canRewriteAsInt (t);
176
+ return isPassedWithByvalSemantics (t);
153
177
}
154
178
155
179
void Win64TargetABI::rewriteFunctionType (TypeFunction* tf, IrFuncTy &fty)
@@ -168,7 +192,7 @@ void Win64TargetABI::rewriteFunctionType(TypeFunction* tf, IrFuncTy &fty)
168
192
// the other complex number types are returned via XMM0 = re and XMM1 = im
169
193
fty.ret ->rewrite = &swapComplex;
170
194
}
171
- else if (canRewriteAsInt (rt))
195
+ else if (isComposite (rt) && canRewriteAsInt (rt))
172
196
{
173
197
fty.ret ->rewrite = &compositeToInt;
174
198
fty.ret ->ltype = compositeToInt.type (fty.ret ->type , fty.ret ->ltype );
@@ -195,12 +219,13 @@ void Win64TargetABI::rewriteFunctionType(TypeFunction* tf, IrFuncTy &fty)
195
219
arg.rewrite = &cfloatToInt;
196
220
arg.ltype = cfloatToInt.type (arg.type , arg.ltype );
197
221
}
198
- else if (canRewriteAsInt (ty))
222
+ else if (isComposite (ty) && canRewriteAsInt (ty))
199
223
{
200
224
arg.rewrite = &compositeToInt;
201
225
arg.ltype = compositeToInt.type (arg.type , arg.ltype );
202
226
}
203
- else if (ty->iscomplex () || ty->ty == Tfloat80 || ty->ty == Timaginary80)
227
+ // FIXME: this should actually be handled by LLVM and the ByVal arg attribute
228
+ else if (isPassedWithByvalSemantics (ty))
204
229
{
205
230
// these types are passed byval:
206
231
// the caller allocates a copy and then passes a pointer to the copy
0 commit comments