24
24
// / Removes padding fields for (non-union-containing!) structs
25
25
struct RemoveStructPadding : ABIRewrite {
26
26
// / get a rewritten value back to its original form
27
- virtual LLValue* get (Type* dty, DValue* v) {
27
+ LLValue* get (Type* dty, DValue* v) {
28
28
LLValue* lval = DtoAlloca (dty, " .rewritetmp" );
29
29
getL (dty, v, lval);
30
30
return lval;
31
31
}
32
32
33
33
// / get a rewritten value back to its original form and store result in provided lvalue
34
34
// / this one is optional and defaults to calling the one above
35
- virtual void getL (Type* dty, DValue* v, llvm::Value * lval) {
35
+ void getL (Type* dty, DValue* v, LLValue * lval) {
36
36
// Make sure the padding is zero, so struct comparisons work.
37
37
// TODO: Only do this if there's padding, and/or only initialize padding.
38
38
DtoMemSetZero (lval, DtoConstSize_t (getTypePaddedSize (DtoType (dty))));
39
39
DtoPaddedStruct (dty->toBasetype (), v->getRVal (), lval);
40
40
}
41
41
42
42
// / put out rewritten value
43
- virtual LLValue* put (Type* dty, DValue* v) {
43
+ LLValue* put (Type* dty, DValue* v) {
44
44
return DtoUnpaddedStruct (dty->toBasetype (), v->getRVal ());
45
45
}
46
46
47
47
// / return the transformed type for this rewrite
48
- virtual LLType* type (Type* dty, LLType* t) {
48
+ LLType* type (Type* dty, LLType* t) {
49
49
return DtoUnpaddedStructType (dty->toBasetype ());
50
50
}
51
51
};
52
52
53
53
// ////////////////////////////////////////////////////////////////////////////
54
54
55
- // simply swap of real/imag parts for proper x87 complex abi
56
- struct X87_complex_swap : ABIRewrite
57
- {
58
- LLValue* get (Type*, DValue* v)
59
- {
60
- return DtoAggrPairSwap (v->getRVal ());
61
- }
62
- LLValue* put (Type*, DValue* v)
63
- {
64
- return DtoAggrPairSwap (v->getRVal ());
65
- }
66
- LLType* type (Type*, LLType* t)
67
- {
68
- return t;
69
- }
70
- };
71
-
72
- // ////////////////////////////////////////////////////////////////////////////
73
-
74
- // Rewrites a cfloat (2x32 bits) as 64-bit integer.
75
- // Assumes a little-endian byte order.
76
- struct CfloatToInt : ABIRewrite
77
- {
78
- // i64 -> {float,float}
79
- LLValue* get (Type*, DValue* dv)
80
- {
81
- LLValue* in = dv->getRVal ();
82
-
83
- // extract real part
84
- LLValue* rpart = gIR ->ir ->CreateTrunc (in, LLType::getInt32Ty (gIR ->context ()));
85
- rpart = gIR ->ir ->CreateBitCast (rpart, LLType::getFloatTy (gIR ->context ()), " .re" );
86
-
87
- // extract imag part
88
- LLValue* ipart = gIR ->ir ->CreateLShr (in, LLConstantInt::get (LLType::getInt64Ty (gIR ->context ()), 32 , false ));
89
- ipart = gIR ->ir ->CreateTrunc (ipart, LLType::getInt32Ty (gIR ->context ()));
90
- ipart = gIR ->ir ->CreateBitCast (ipart, LLType::getFloatTy (gIR ->context ()), " .im" );
91
-
92
- // return {float,float} aggr pair with same bits
93
- return DtoAggrPair (rpart, ipart, " .final_cfloat" );
94
- }
95
-
96
- // {float,float} -> i64
97
- LLValue* put (Type*, DValue* dv)
98
- {
99
- LLValue* v = dv->getRVal ();
100
-
101
- // extract real
102
- LLValue* r = gIR ->ir ->CreateExtractValue (v, 0 );
103
- // cast to i32
104
- r = gIR ->ir ->CreateBitCast (r, LLType::getInt32Ty (gIR ->context ()));
105
- // zext to i64
106
- r = gIR ->ir ->CreateZExt (r, LLType::getInt64Ty (gIR ->context ()));
107
-
108
- // extract imag
109
- LLValue* i = gIR ->ir ->CreateExtractValue (v, 1 );
110
- // cast to i32
111
- i = gIR ->ir ->CreateBitCast (i, LLType::getInt32Ty (gIR ->context ()));
112
- // zext to i64
113
- i = gIR ->ir ->CreateZExt (i, LLType::getInt64Ty (gIR ->context ()));
114
- // shift up
115
- i = gIR ->ir ->CreateShl (i, LLConstantInt::get (LLType::getInt64Ty (gIR ->context ()), 32 , false ));
116
-
117
- // combine and return
118
- return v = gIR ->ir ->CreateOr (r, i);
119
- }
120
-
121
- // {float,float} -> i64
122
- LLType* type (Type*, LLType* t)
123
- {
124
- return LLType::getInt64Ty (gIR ->context ());
125
- }
126
- };
127
-
128
- // ////////////////////////////////////////////////////////////////////////////
129
-
130
55
/* *
131
56
* Rewrites a composite type parameter to an integer of the same size.
132
57
*
133
58
* This is needed in order to be able to use LLVM's inreg attribute to put
134
59
* struct and static array parameters into registers, because the attribute has
135
60
* slightly different semantics. For example, LLVM would store a [4 x i8] inreg
136
61
* in four registers (zero-extended), instead of a single 32bit one.
137
- *
138
- * The LLVM value in dv is expected to be a pointer to the parameter, as
139
- * generated when lowering struct/static array paramters to LLVM byval.
140
62
*/
141
63
struct CompositeToInt : ABIRewrite
142
64
{
143
65
LLValue* get (Type* dty, DValue* dv)
144
66
{
145
67
Logger::println (" rewriting integer -> %s" , dty->toChars ());
146
- LLValue* mem = DtoAlloca (dty, " .int_to_composite" );
147
- LLValue* v = dv->getRVal ();
148
- DtoStore (v, DtoBitCast (mem, getPtrToType (v->getType ())));
149
- return DtoLoad (mem);
68
+
69
+ LLValue* address = 0 ; // of passed Int
70
+
71
+ if (dv->isLVal ()) // dv is already in memory:
72
+ address = dv->getLVal (); // address = &<passed Int>
73
+ else { // dump dv to memory:
74
+ LLValue* v = dv->getRVal (); // v = <passed Int>
75
+ address = DtoRawAlloca (v->getType (), 0 , " .int_to_composite" ); // address = new Int
76
+ DtoStore (v, address); // *address = v
77
+ }
78
+
79
+ LLType* pTy = getPtrToType (DtoType (dty));
80
+ return DtoLoad (DtoBitCast (address, pTy), " get-result" ); // *(Type*)address
150
81
}
151
82
152
- void getL (Type* dty, DValue* dv, llvm::Value * lval)
83
+ void getL (Type* dty, DValue* dv, LLValue * lval)
153
84
{
154
85
Logger::println (" rewriting integer -> %s" , dty->toChars ());
155
- LLValue* v = dv->getRVal ();
156
- DtoStore (v, DtoBitCast (lval, getPtrToType (v->getType ())));
86
+ LLValue* v = dv->getRVal (); // v = <passed Int>
87
+ DtoStore (v, DtoBitCast (lval, getPtrToType (v->getType ()))); // *(Int*)lval = v
157
88
}
158
89
159
90
LLValue* put (Type* dty, DValue* dv)
160
91
{
161
92
Logger::println (" rewriting %s -> integer" , dty->toChars ());
162
- LLType* t = LLIntegerType::get (gIR ->context (), dty->size () * 8 );
163
- return DtoLoad (DtoBitCast (dv->getRVal (), getPtrToType (t)));
93
+
94
+ LLValue* address = 0 ; // of original parameter dv
95
+
96
+ if (dv->getRVal ()->getType ()->isPointerTy ()) // dv has been lowered to a pointer to the struct/static array:
97
+ address = dv->getRVal (); // address = dv
98
+ else if (dv->isLVal ()) // dv is already in memory:
99
+ address = dv->getLVal (); // address = &dv
100
+ else { // dump dv to memory:
101
+ address = DtoAlloca (dty, " .composite_to_int" ); // address = new Type
102
+ DtoStore (dv->getRVal (), address); // *address = dv
103
+ }
104
+
105
+ LLType* intType = type (dty, 0 );
106
+ return DtoLoad (DtoBitCast (address, getPtrToType (intType)), " put-result" ); // *(Int*)address
164
107
}
165
108
166
109
LLType* type (Type* t, LLType*)
@@ -170,4 +113,58 @@ struct CompositeToInt : ABIRewrite
170
113
}
171
114
};
172
115
116
+ // ////////////////////////////////////////////////////////////////////////////
117
+
118
+ // FIXME: This should actually be handled by LLVM and the ByVal arg attribute.
119
+ struct byval_rewrite : ABIRewrite
120
+ {
121
+ const size_t alignment;
122
+
123
+ byval_rewrite (size_t alignment = 16 ) : alignment(alignment)
124
+ { }
125
+
126
+ // Get instance from pointer.
127
+ LLValue* get (Type* dty, DValue* v)
128
+ {
129
+ LLValue* ptr = v->getRVal ();
130
+ return DtoLoad (ptr); // *ptr
131
+ }
132
+
133
+ // Convert the caller's instance to a pointer for the callee.
134
+ // The pointer points to a dedicated copy for the callee which
135
+ // is allocated by the caller.
136
+ LLValue* put (Type* dty, DValue* v)
137
+ {
138
+ /* NOTE: probably not safe
139
+ // optimization: do not copy if parameter is not mutable
140
+ if (!dty->isMutable() && v->isLVal())
141
+ return v->getLVal();
142
+ */
143
+
144
+ LLValue* original = v->getRVal ();
145
+ LLValue* copy;
146
+
147
+ LLType* type = original->getType ();
148
+ if (type->isPointerTy ())
149
+ {
150
+ type = type->getPointerElementType ();
151
+ copy = DtoRawAlloca (type, alignment, " copy_for_callee" );
152
+ DtoStore (DtoLoad (original), copy); // *copy = *original
153
+ }
154
+ else
155
+ {
156
+ copy = DtoRawAlloca (type, alignment, " copy_for_callee" );
157
+ DtoStore (original, copy); // *copy = original
158
+ }
159
+
160
+ return copy;
161
+ }
162
+
163
+ // T => T*
164
+ LLType* type (Type* dty, LLType* t)
165
+ {
166
+ return getPtrToType (DtoType (dty));
167
+ }
168
+ };
169
+
173
170
#endif
0 commit comments