Mercurial > projects > ldc
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 } |