Mercurial > projects > ldc
comparison gen/naked.cpp @ 959:7e669954db7d
Implement implicit return after inline asm on x86_64
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Sun, 15 Feb 2009 18:04:22 +0100 |
parents | e048e36bc155 |
children | 2667e3a145be |
comparison
equal
deleted
inserted
replaced
958:89729c76b8ff | 959:7e669954db7d |
---|---|
166 gIR->functions.pop_back(); | 166 gIR->functions.pop_back(); |
167 } | 167 } |
168 | 168 |
169 ////////////////////////////////////////////////////////////////////////////////////////// | 169 ////////////////////////////////////////////////////////////////////////////////////////// |
170 | 170 |
171 static LLValue* x86_64_cfloatRetFixup(IRBuilderHelper b, LLValue* orig) { | |
172 assert(orig->getType() == LLType::DoubleTy); | |
173 LLType* retty = LLStructType::get(LLType::DoubleTy, NULL); | |
174 LLValue* undef = llvm::UndefValue::get(retty); | |
175 return b->CreateInsertValue(undef, orig, 0, "asm.ret"); | |
176 } | |
177 | |
171 void emitABIReturnAsmStmt(IRAsmBlock* asmblock, Loc loc, FuncDeclaration* fdecl) | 178 void emitABIReturnAsmStmt(IRAsmBlock* asmblock, Loc loc, FuncDeclaration* fdecl) |
172 { | 179 { |
173 Logger::println("emitABIReturnAsmStmt(%s)", fdecl->mangle()); | 180 Logger::println("emitABIReturnAsmStmt(%s)", fdecl->mangle()); |
174 LOG_SCOPE; | 181 LOG_SCOPE; |
175 | 182 |
177 | 184 |
178 const LLType* llretTy = DtoType(fdecl->type->nextOf()); | 185 const LLType* llretTy = DtoType(fdecl->type->nextOf()); |
179 asmblock->retty = llretTy; | 186 asmblock->retty = llretTy; |
180 asmblock->retn = 1; | 187 asmblock->retn = 1; |
181 | 188 |
182 // x86 or x86_64 | 189 // x86 |
183 if (global.params.cpu == ARCHx86 || global.params.cpu == ARCHx86_64) | 190 if (global.params.cpu == ARCHx86) |
184 { | 191 { |
185 LINK l = fdecl->linkage; | 192 LINK l = fdecl->linkage; |
186 assert((l == LINKd || l == LINKc || l == LINKwindows) && "invalid linkage for asm implicit return"); | 193 assert((l == LINKd || l == LINKc || l == LINKwindows) && "invalid linkage for asm implicit return"); |
187 | 194 |
188 Type* rt = fdecl->type->nextOf()->toBasetype(); | 195 Type* rt = fdecl->type->nextOf()->toBasetype(); |
236 error(loc, "unimplemented return type '%s' for implicit abi return", rt->toChars()); | 243 error(loc, "unimplemented return type '%s' for implicit abi return", rt->toChars()); |
237 fatal(); | 244 fatal(); |
238 } | 245 } |
239 } | 246 } |
240 | 247 |
248 // x86_64 | |
249 else if (global.params.cpu == ARCHx86_64) | |
250 { | |
251 LINK l = fdecl->linkage; | |
252 /* TODO: Check if this works with extern(Windows), completely untested. | |
253 * In particular, returning cdouble may not work with | |
254 * extern(Windows) since according to X86CallingConv.td it | |
255 * doesn't allow XMM1 to be used. | |
256 * (So is extern(C), but that should be fine as the calling convention | |
257 * is identical to that of extern(D)) | |
258 */ | |
259 assert((l == LINKd || l == LINKc || l == LINKwindows) && "invalid linkage for asm implicit return"); | |
260 | |
261 Type* rt = fdecl->type->nextOf()->toBasetype(); | |
262 if (rt->isintegral() || rt->ty == Tpointer || rt->ty == Tclass || rt->ty == Taarray) | |
263 { | |
264 as->out_c = "={ax},"; | |
265 } | |
266 else if (rt->isfloating()) | |
267 { | |
268 if (rt == Type::tcomplex80) { | |
269 // On x87 stack, re=st, im=st(1) | |
270 as->out_c = "={st},={st(1)},"; | |
271 asmblock->retn = 2; | |
272 } else if (rt == Type::tfloat80 || rt == Type::timaginary80) { | |
273 // On x87 stack | |
274 as->out_c = "={st},"; | |
275 } else if (l != LINKd && rt == Type::tcomplex32) { | |
276 // LLVM and GCC disagree on how to return {float, float}. | |
277 // For compatibility, use the GCC/LLVM-GCC way for extern(C/Windows) | |
278 // extern(C) cfloat -> %xmm0 (extract two floats) | |
279 #if 0 | |
280 // Disabled because "regular" extern(C) functions aren't | |
281 // ABI-compatible with GCC yet. | |
282 // TODO: enable when "extern(C) cfloat foo();" compiles to "declare { double } @foo();" | |
283 as->out_c = "={xmm0},"; | |
284 asmblock->retty = LLStructType::get(LLType::DoubleTy, NULL);; | |
285 asmblock->retfixup = &x86_64_cfloatRetFixup; | |
286 #else | |
287 error(loc, "unimplemented return type '%s' for implicit abi return", rt->toChars()); | |
288 fatal(); | |
289 #endif | |
290 } else if (rt->iscomplex()) { | |
291 // cdouble and extern(D) cfloat -> re=%xmm0, im=%xmm1 | |
292 as->out_c = "={xmm0},={xmm1},"; | |
293 asmblock->retn = 2; | |
294 } else { | |
295 // Plain float/double/ifloat/idouble | |
296 as->out_c = "={xmm0},"; | |
297 } | |
298 } | |
299 else if (rt->ty == Tarray || rt->ty == Tdelegate) | |
300 { | |
301 as->out_c = "={ax},={dx},"; | |
302 asmblock->retn = 2; | |
303 } | |
304 else | |
305 { | |
306 error(loc, "unimplemented return type '%s' for implicit abi return", rt->toChars()); | |
307 fatal(); | |
308 } | |
309 } | |
310 | |
241 // unsupported | 311 // unsupported |
242 else | 312 else |
243 { | 313 { |
244 error(loc, "this target (%s) does not implement inline asm falling off the end of the function", global.params.targetTriple); | 314 error(loc, "this target (%s) does not implement inline asm falling off the end of the function", global.params.targetTriple); |
245 fatal(); | 315 fatal(); |