comparison gen/abi.cpp @ 989:420ef073448d

Forgot new files that were supposed to be in last commit.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Thu, 26 Feb 2009 14:13:27 +0100
parents
children 223a679053dd
comparison
equal deleted inserted replaced
988:2667e3a145be 989:420ef073448d
1 #include "gen/llvm.h"
2
3 #include "mars.h"
4
5 #include "gen/irstate.h"
6 #include "gen/llvmhelpers.h"
7 #include "gen/tollvm.h"
8 #include "gen/abi.h"
9
10 //////////////////////////////////////////////////////////////////////////////
11 //////////////////////////////////////////////////////////////////////////////
12 ///////////////////// baseclass ////////////////////////////
13 //////////////////////////////////////////////////////////////////////////////
14 //////////////////////////////////////////////////////////////////////////////
15
16 // FIXME: Would be nice to come up a better and faster way to do this, right
17 // now I'm more worried about actually making this abstraction work at all ...
18 // It's definitely way overkill with the amount of return value rewrites we
19 // have right now, but I expect this to change with proper x86-64 abi support
20
21 TargetABI::TargetABI()
22 {
23 }
24
25 llvm::Value* TargetABI::getRet(TypeFunction* tf, llvm::Value* io)
26 {
27 if (ABIRetRewrite* r = findRetRewrite(tf))
28 {
29 return r->get(io);
30 }
31 return io;
32 }
33
34 llvm::Value* TargetABI::putRet(TypeFunction* tf, llvm::Value* io)
35 {
36 if (ABIRetRewrite* r = findRetRewrite(tf))
37 {
38 return r->put(io);
39 }
40 return io;
41 }
42
43 const llvm::Type* TargetABI::getRetType(TypeFunction* tf, const llvm::Type* t)
44 {
45 if (ABIRetRewrite* r = findRetRewrite(tf))
46 {
47 return r->type(t);
48 }
49 return t;
50 }
51
52 ABIRetRewrite * TargetABI::findRetRewrite(TypeFunction * tf)
53 {
54 size_t n = retOps.size();
55 if (n)
56 for (size_t i = 0; i < n; i++)
57 {
58 if (retOps[i]->test(tf))
59 return retOps[i];
60 }
61 return NULL;
62 }
63
64 //////////////////////////////////////////////////////////////////////////////
65 //////////////////////////////////////////////////////////////////////////////
66 ///////////////////// X86 ////////////////////////////
67 //////////////////////////////////////////////////////////////////////////////
68 //////////////////////////////////////////////////////////////////////////////
69
70 // simply swap of real/imag parts for proper x87 complex abi
71 struct X87_complex_swap : ABIRetRewrite
72 {
73 LLValue* get(LLValue* v)
74 {
75 return DtoAggrPairSwap(v);
76 }
77 LLValue* put(LLValue* v)
78 {
79 return DtoAggrPairSwap(v);
80 }
81 const LLType* type(const LLType* t)
82 {
83 return t;
84 }
85 bool test(TypeFunction* tf)
86 {
87 return (tf->next->toBasetype()->iscomplex());
88 }
89 };
90
91 //////////////////////////////////////////////////////////////////////////////
92
93 struct X86TargetABI : TargetABI
94 {
95 X86TargetABI()
96 {
97 retOps.push_back(new X87_complex_swap);
98 }
99
100 bool returnInArg(Type* t)
101 {
102 Type* rt = t->toBasetype();
103 return (rt->ty == Tstruct);
104 }
105
106 bool passByRef(Type* t)
107 {
108 t = t->toBasetype();
109 return (t->ty == Tstruct || t->ty == Tsarray);
110 }
111 };
112
113 //////////////////////////////////////////////////////////////////////////////
114 //////////////////////////////////////////////////////////////////////////////
115 /////////////////// X86-64 //////////////////////////
116 //////////////////////////////////////////////////////////////////////////////
117 //////////////////////////////////////////////////////////////////////////////
118
119 struct X86_64_cfloat_rewrite : ABIRetRewrite
120 {
121 // {double} -> {float,float}
122 LLValue* get(LLValue* in)
123 {
124 // extract double
125 LLValue* v = gIR->ir->CreateExtractValue(in, 0);
126 // cast to i64
127 v = gIR->ir->CreateBitCast(v, LLType::Int64Ty);
128
129 // extract real part
130 LLValue* rpart = gIR->ir->CreateTrunc(v, LLType::Int32Ty);
131 rpart = gIR->ir->CreateBitCast(rpart, LLType::FloatTy, ".re");
132
133 // extract imag part
134 LLValue* ipart = gIR->ir->CreateLShr(v, LLConstantInt::get(LLType::Int64Ty, 32, false));
135 ipart = gIR->ir->CreateTrunc(ipart, LLType::Int32Ty);
136 ipart = gIR->ir->CreateBitCast(ipart, LLType::FloatTy, ".im");
137
138 // return {float,float} aggr pair with same bits
139 return DtoAggrPair(rpart, ipart, ".final_cfloat");
140 }
141
142 // {float,float} -> {double}
143 LLValue* put(LLValue* v)
144 {
145 // extract real
146 LLValue* r = gIR->ir->CreateExtractValue(v, 0);
147 // cast to i32
148 r = gIR->ir->CreateBitCast(r, LLType::Int32Ty);
149 // zext to i64
150 r = gIR->ir->CreateZExt(r, LLType::Int64Ty);
151
152 // extract imag
153 LLValue* i = gIR->ir->CreateExtractValue(v, 1);
154 // cast to i32
155 i = gIR->ir->CreateBitCast(i, LLType::Int32Ty);
156 // zext to i64
157 i = gIR->ir->CreateZExt(i, LLType::Int64Ty);
158 // shift up
159 i = gIR->ir->CreateShl(i, LLConstantInt::get(LLType::Int64Ty, 32, false));
160
161 // combine
162 v = gIR->ir->CreateOr(r, i);
163
164 // cast to double
165 v = gIR->ir->CreateBitCast(v, LLType::DoubleTy);
166
167 // return {double}
168 const LLType* t = LLStructType::get(LLType::DoubleTy, 0);
169 LLValue* undef = llvm::UndefValue::get(t);
170 return gIR->ir->CreateInsertValue(undef, v, 0);
171 }
172
173 // {float,float} -> {double}
174 const LLType* type(const LLType* t)
175 {
176 return LLStructType::get(LLType::DoubleTy, 0);
177 }
178
179 // test if rewrite applies to function
180 bool test(TypeFunction* tf)
181 {
182 return (tf->next->toBasetype() == Type::tcomplex32);
183 }
184 };
185
186 //////////////////////////////////////////////////////////////////////////////
187
188 struct X86_64TargetABI : TargetABI
189 {
190 X86_64TargetABI()
191 {
192 retOps.push_back(new X86_64_cfloat_rewrite);
193 }
194
195 bool returnInArg(Type* t)
196 {
197 Type* rt = t->toBasetype();
198 return (rt->ty == Tstruct);
199 }
200
201 bool passByRef(Type* t)
202 {
203 t = t->toBasetype();
204 return (t->ty == Tstruct || t->ty == Tsarray);
205 }
206 };
207
208 //////////////////////////////////////////////////////////////////////////////
209 //////////////////////////////////////////////////////////////////////////////
210 //////////////////////////////////////////////////////////////////////////////
211 //////////////////////////////////////////////////////////////////////////////
212 //////////////////////////////////////////////////////////////////////////////
213
214 TargetABI * TargetABI::getTarget()
215 {
216 switch(global.params.cpu)
217 {
218 case ARCHx86:
219 return new X86TargetABI;
220 case ARCHx86_64:
221 return new X86_64TargetABI;
222 default:
223 return NULL;
224 }
225 }