comparison gen/abi.cpp @ 1047:6bb04dbee21f

Some calling convention work for x86-64: - Implement x86-64 extern(C), hopefully correctly. - Tried to be a bit smarter about extern(D) while I was there. Interestingly, this code seems to be generating more efficient code than gcc and llvm-gcc in some edge cases, like returning a `{ [7 x i8] }` loaded from a stack slot from an extern(C) function. (gcc generates 7 1-byte loads, while this code generates a 4-byte, a 2-byte and a 1-byte load) I also added some changes to make sure structs being returned from functions or passed in as parameters are stored in memory where the rest of the backend seems to expect them to be. These should be removed when support for first-class aggregates improves.
author Frits van Bommel <fvbommel wxs.nl>
date Fri, 06 Mar 2009 16:00:47 +0100
parents 0485751a40ae
children 32ead42679d1
comparison
equal deleted inserted replaced
1046:cc6489f32519 1047:6bb04dbee21f
259 ////////////////////////////////////////////////////////////////////////////// 259 //////////////////////////////////////////////////////////////////////////////
260 /////////////////// X86-64 ////////////////////////// 260 /////////////////// X86-64 //////////////////////////
261 ////////////////////////////////////////////////////////////////////////////// 261 //////////////////////////////////////////////////////////////////////////////
262 ////////////////////////////////////////////////////////////////////////////// 262 //////////////////////////////////////////////////////////////////////////////
263 263
264 struct X86_64_cfloat_rewrite : ABIRewrite 264 #include "gen/abi-x86-64.h"
265 {
266 // {double} -> {float,float}
267 LLValue* get(Type*, DValue* dv)
268 {
269 LLValue* in = dv->getRVal();
270
271 // extract double
272 LLValue* v = gIR->ir->CreateExtractValue(in, 0);
273 // cast to i64
274 v = gIR->ir->CreateBitCast(v, LLType::Int64Ty);
275
276 // extract real part
277 LLValue* rpart = gIR->ir->CreateTrunc(v, LLType::Int32Ty);
278 rpart = gIR->ir->CreateBitCast(rpart, LLType::FloatTy, ".re");
279
280 // extract imag part
281 LLValue* ipart = gIR->ir->CreateLShr(v, LLConstantInt::get(LLType::Int64Ty, 32, false));
282 ipart = gIR->ir->CreateTrunc(ipart, LLType::Int32Ty);
283 ipart = gIR->ir->CreateBitCast(ipart, LLType::FloatTy, ".im");
284
285 // return {float,float} aggr pair with same bits
286 return DtoAggrPair(rpart, ipart, ".final_cfloat");
287 }
288
289 // {float,float} -> {double}
290 LLValue* put(Type*, DValue* dv)
291 {
292 LLValue* v = dv->getRVal();
293
294 // extract real
295 LLValue* r = gIR->ir->CreateExtractValue(v, 0);
296 // cast to i32
297 r = gIR->ir->CreateBitCast(r, LLType::Int32Ty);
298 // zext to i64
299 r = gIR->ir->CreateZExt(r, LLType::Int64Ty);
300
301 // extract imag
302 LLValue* i = gIR->ir->CreateExtractValue(v, 1);
303 // cast to i32
304 i = gIR->ir->CreateBitCast(i, LLType::Int32Ty);
305 // zext to i64
306 i = gIR->ir->CreateZExt(i, LLType::Int64Ty);
307 // shift up
308 i = gIR->ir->CreateShl(i, LLConstantInt::get(LLType::Int64Ty, 32, false));
309
310 // combine
311 v = gIR->ir->CreateOr(r, i);
312
313 // cast to double
314 v = gIR->ir->CreateBitCast(v, LLType::DoubleTy);
315
316 // return {double}
317 const LLType* t = LLStructType::get(LLType::DoubleTy, NULL);
318 LLValue* undef = llvm::UndefValue::get(t);
319 return gIR->ir->CreateInsertValue(undef, v, 0);
320 }
321
322 // {float,float} -> {double}
323 const LLType* type(Type*, const LLType* t)
324 {
325 return LLStructType::get(LLType::DoubleTy, NULL);
326 }
327 };
328
329 //////////////////////////////////////////////////////////////////////////////
330
331 struct X86_64TargetABI : TargetABI
332 {
333 X86_64_cfloat_rewrite cfloat_rewrite;
334
335 bool returnInArg(TypeFunction* tf)
336 {
337 Type* rt = tf->next->toBasetype();
338 return (rt->ty == Tstruct);
339 }
340
341 bool passByVal(Type* t)
342 {
343 return t->toBasetype()->ty == Tstruct;
344 }
345
346 void rewriteFunctionType(TypeFunction* tf)
347 {
348 IrFuncTy* fty = tf->fty;
349 Type* rt = fty->ret->type->toBasetype();
350
351 // rewrite cfloat return for !extern(D)
352 if (tf->linkage != LINKd && rt == Type::tcomplex32)
353 {
354 fty->ret->rewrite = &cfloat_rewrite;
355 fty->ret->ltype = cfloat_rewrite.type(fty->ret->type, fty->ret->ltype);
356 }
357 }
358 };
359 265
360 ////////////////////////////////////////////////////////////////////////////// 266 //////////////////////////////////////////////////////////////////////////////
361 ////////////////////////////////////////////////////////////////////////////// 267 //////////////////////////////////////////////////////////////////////////////
362 /////////////////// Unknown targets ////////////////////////// 268 /////////////////// Unknown targets //////////////////////////
363 ////////////////////////////////////////////////////////////////////////////// 269 //////////////////////////////////////////////////////////////////////////////
393 switch(global.params.cpu) 299 switch(global.params.cpu)
394 { 300 {
395 case ARCHx86: 301 case ARCHx86:
396 return new X86TargetABI; 302 return new X86TargetABI;
397 case ARCHx86_64: 303 case ARCHx86_64:
398 return new X86_64TargetABI; 304 return getX86_64TargetABI();
399 default: 305 default:
400 Logger::cout() << "WARNING: Unknown ABI, guessing...\n"; 306 Logger::cout() << "WARNING: Unknown ABI, guessing...\n";
401 return new UnknownTargetABI; 307 return new UnknownTargetABI;
402 } 308 }
403 } 309 }