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