@@ -234,7 +234,12 @@ void X86_64ABIInfo::classify(Type Ty, uint64_t OffsetBase, Class &Lo, Class &Hi,
234
234
if (/* isBuitinType=*/ true ) {
235
235
if (isa<VoidType>(Ty)) {
236
236
Current = Class::NoClass;
237
- } else if (isa<IntType>(Ty)) {
237
+ } else if (auto IntTy = dyn_cast<IntType>(Ty)) {
238
+ if (IntTy.getWidth () == 128 ) {
239
+ Lo = Class::Integer;
240
+ Hi = Class::Integer;
241
+ return ;
242
+ }
238
243
239
244
// FIXME(cir): Clang's BuiltinType::Kind allow comparisons (GT, LT, etc).
240
245
// We should implement this in CIR to simplify the conditions below.
@@ -456,6 +461,50 @@ Type X86_64ABIInfo::GetINTEGERTypeAtOffset(Type DestTy, unsigned IROffset,
456
461
std::min (TySizeInBytes - SourceOffset, 8U ) * 8 , isSigned);
457
462
}
458
463
464
+ // / GetX86_64ByValArgumentPair - Given a high and low type that can ideally
465
+ // / be used as elements of a two register pair to pass or return, return a
466
+ // / first class aggregate to represent them. For example, if the low part of
467
+ // / a by-value argument should be passed as i32* and the high part as float,
468
+ // / return {i32*, float}.
469
+ static mlir::Type GetX86_64ByValArgumentPair (mlir::Type lo, mlir::Type hi,
470
+ const ::cir::CIRDataLayout &td) {
471
+ // In order to correctly satisfy the ABI, we need to the high part to start
472
+ // at offset 8. If the high and low parts we inferred are both 4-byte types
473
+ // (e.g. i32 and i32) then the resultant struct type ({i32,i32}) won't have
474
+ // the second element at offset 8. Check for this:
475
+ unsigned loSize = (unsigned )td.getTypeAllocSize (lo);
476
+ llvm::Align highAlign = td.getABITypeAlign (hi);
477
+ unsigned highStart = llvm::alignTo (loSize, highAlign);
478
+ assert (highStart != 0 && highStart <= 8 && " Invalid x86-64 argument pair!" );
479
+
480
+ // To handle this, we have to increase the size of the low part so that the
481
+ // second element will start at an 8 byte offset. We can't increase the size
482
+ // of the second element because it might make us access off the end of the
483
+ // struct.
484
+ if (highStart != 8 ) {
485
+ // There are usually two sorts of types the ABI generation code can produce
486
+ // for the low part of a pair that aren't 8 bytes in size: half, float or
487
+ // i8/i16/i32. This can also include pointers when they are 32-bit (X32 and
488
+ // NaCl).
489
+ // Promote these to a larger type.
490
+ if (isa<FP16Type, SingleType>(lo))
491
+ lo = DoubleType::get (lo.getContext ());
492
+ else {
493
+ assert ((isa<IntType, PointerType>(lo)) && " Invalid/unknown lo type" );
494
+ // TODO(cir): does the sign of the int64 type matter here?
495
+ lo = IntType::get (lo.getContext (), 64 , true );
496
+ }
497
+ }
498
+
499
+ auto result = StructType::get (lo.getContext (), {lo, hi}, /* packed=*/ false ,
500
+ StructType::Struct);
501
+
502
+ // Verify that the second element is at an 8-byte offset.
503
+ assert (td.getStructLayout (result)->getElementOffset (1 ) == 8 &&
504
+ " Invalid x86-64 argument pair!" );
505
+ return result;
506
+ }
507
+
459
508
::cir::ABIArgInfo X86_64ABIInfo::classifyReturnType (Type RetTy) const {
460
509
// AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
461
510
// classification algorithm.
@@ -507,6 +556,12 @@ ::cir::ABIArgInfo X86_64ABIInfo::classifyReturnType(Type RetTy) const {
507
556
case Class::NoClass:
508
557
break ;
509
558
559
+ case Class::Integer:
560
+ HighPart = GetINTEGERTypeAtOffset (RetTy, 8 , RetTy, 8 );
561
+ if (Lo == Class::NoClass) // Return HighPart at offset 8 in memory.
562
+ return ABIArgInfo::getDirect (HighPart, 8 );
563
+ break ;
564
+
510
565
default :
511
566
cir_cconv_unreachable (" NYI" );
512
567
}
@@ -515,7 +570,7 @@ ::cir::ABIArgInfo X86_64ABIInfo::classifyReturnType(Type RetTy) const {
515
570
// known to pass in the high eightbyte of the result. We do this by forming
516
571
// a first class struct aggregate with the high and low part: {low, high}
517
572
if (HighPart)
518
- cir_cconv_unreachable ( " NYI " );
573
+ resType = GetX86_64ByValArgumentPair (resType, HighPart, getDataLayout () );
519
574
520
575
return ABIArgInfo::getDirect (resType);
521
576
}
@@ -580,12 +635,25 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(Type Ty, unsigned freeIntRegs,
580
635
switch (Hi) {
581
636
case Class::NoClass:
582
637
break ;
638
+
639
+ case Class::Integer:
640
+ ++neededInt;
641
+ // Pick an 8-byte type based on the preferred type.
642
+ HighPart = GetINTEGERTypeAtOffset (Ty, 8 , Ty, 8 );
643
+
644
+ if (Lo == Class::NoClass) // Pass HighPart at offset 8 in memory.
645
+ return ABIArgInfo::getDirect (HighPart, 8 );
646
+ break ;
647
+
583
648
default :
584
649
cir_cconv_unreachable (" NYI" );
585
650
}
586
651
652
+ // If a high part was specified, merge it together with the low part. It is
653
+ // known to pass in the high eightbyte of the result. We do this by forming a
654
+ // first class struct aggregate with the high and low part: {low, high}
587
655
if (HighPart)
588
- cir_cconv_unreachable ( " NYI " );
656
+ ResType = GetX86_64ByValArgumentPair ( ResType , HighPart, getDataLayout () );
589
657
590
658
return ABIArgInfo::getDirect (ResType );
591
659
}
0 commit comments