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();