erichkeane created this revision.
erichkeane added a reviewer: craig.topper.

After speaking with Craig Topper about some recent defects, he pointed
out that _ExtInts should be passed indirectly if larger than the largest
int register, and like ints when smaller than that.  This patch
implements that.

Note that this changed the way vaargs worked quite a bit, but they still
work.


Repository:
  rC Clang

https://reviews.llvm.org/D78785

Files:
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGen/ext-int-sanitizer.cpp
  clang/test/CodeGen/ext-int.c
  clang/test/CodeGenCXX/ext-int.cpp

Index: clang/test/CodeGenCXX/ext-int.cpp
===================================================================
--- clang/test/CodeGenCXX/ext-int.cpp
+++ clang/test/CodeGenCXX/ext-int.cpp
@@ -98,7 +98,7 @@
 };
 
 void UnderlyingTypeUsage(AsEnumUnderlyingType Param) {
-  // LIN: define void @_Z19UnderlyingTypeUsage20AsEnumUnderlyingType(i9 %
+  // LIN: define void @_Z19UnderlyingTypeUsage20AsEnumUnderlyingType(i16 %
   // WIN: define dso_local void @"?UnderlyingTypeUsage@@YAXW4AsEnumUnderlyingType@@@Z"(i9 %
   AsEnumUnderlyingType Var;
   // CHECK: alloca i9, align 2
@@ -106,13 +106,13 @@
 }
 
 unsigned _ExtInt(33) ManglingTestRetParam(unsigned _ExtInt(33) Param) {
-// LIN: define i33 @_Z20ManglingTestRetParamU7_ExtIntILi33EEj(i33 %
+// LIN: define i64 @_Z20ManglingTestRetParamU7_ExtIntILi33EEj(i64 %
 // WIN: define dso_local i33 @"?ManglingTestRetParam@@YAU?$_UExtInt@$0CB@@__clang@@U12@@Z"(i33
   return 0;
 }
 
 _ExtInt(33) ManglingTestRetParam(_ExtInt(33) Param) {
-// LIN: define i33 @_Z20ManglingTestRetParamU7_ExtIntILi33EEi(i33 %
+// LIN: define i64 @_Z20ManglingTestRetParamU7_ExtIntILi33EEi(i64 %
 // WIN: define dso_local i33 @"?ManglingTestRetParam@@YAU?$_ExtInt@$0CB@@__clang@@U12@@Z"(i33
   return 0;
 }
@@ -155,13 +155,14 @@
 
   _ExtInt(92) A = __builtin_va_arg(args, _ExtInt(92));
   // LIN: %[[AD1:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], [1 x %struct.__va_list_tag]* %[[ARGS]]
-  // LIN: %[[OFA_P1:.+]] = getelementptr inbounds %struct.__va_list_tag, %struct.__va_list_tag* %[[AD1]], i32 0, i32 2
-  // LIN: %[[OFA1:.+]] = load i8*, i8** %[[OFA_P1]]
-  // LIN: %[[BC1:.+]] = bitcast i8* %[[OFA1]] to i92*
-  // LIN: %[[OFANEXT1:.+]] = getelementptr i8, i8* %[[OFA1]], i32 16
-  // LIN: store i8* %[[OFANEXT1]], i8** %[[OFA_P1]]
+  // LIN: %[[OFA_P1:.+]] = getelementptr inbounds %struct.__va_list_tag, %struct.__va_list_tag* %[[AD1]], i32 0, i32 0
+  // LIN: %[[GPOFFSET:.+]] = load i32, i32* %[[OFA_P1]]
+  // LIN: %[[FITSINGP:.+]] = icmp ule i32 %[[GPOFFSET]], 32
+  // LIN: br i1 %[[FITSINGP]]
+  // LIN: %[[BC1:.+]] = phi i92*
   // LIN: %[[LOAD1:.+]] = load i92, i92* %[[BC1]]
   // LIN: store i92 %[[LOAD1]], i92*
+
   // WIN: %[[CUR1:.+]] = load i8*, i8** %[[ARGS]]
   // WIN: %[[NEXT1:.+]] = getelementptr inbounds i8, i8* %[[CUR1]], i64 16
   // WIN: store i8* %[[NEXT1]], i8** %[[ARGS]]
@@ -171,15 +172,16 @@
 
   _ExtInt(31) B = __builtin_va_arg(args, _ExtInt(31));
   // LIN: %[[AD2:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], [1 x %struct.__va_list_tag]* %[[ARGS]]
-  // LIN: %[[OFA_P2:.+]] = getelementptr inbounds %struct.__va_list_tag, %struct.__va_list_tag* %[[AD2]], i32 0, i32 2
-  // LIN: %[[OFA2:.+]] = load i8*, i8** %[[OFA_P2]]
-  // LIN: %[[BC2:.+]] = bitcast i8* %[[OFA2]] to i31*
-  // LIN: %[[OFANEXT2:.+]] = getelementptr i8, i8* %[[OFA2]], i32 8
-  // LIN: store i8* %[[OFANEXT2]], i8** %[[OFA_P2]]
-  // LIN: %[[LOAD2:.+]] = load i31, i31* %[[BC2]]
-  // LIN: store i31 %[[LOAD2]], i31*
+  // LIN: %[[OFA_P2:.+]] = getelementptr inbounds %struct.__va_list_tag, %struct.__va_list_tag* %[[AD2]], i32 0, i32 0
+  // LIN: %[[GPOFFSET:.+]] = load i32, i32* %[[OFA_P2]]
+  // LIN: %[[FITSINGP:.+]] = icmp ule i32 %[[GPOFFSET]], 40
+  // LIN: br i1 %[[FITSINGP]]
+  // LIN: %[[BC1:.+]] = phi i31*
+  // LIN: %[[LOAD1:.+]] = load i31, i31* %[[BC1]]
+  // LIN: store i31 %[[LOAD1]], i31*
+
   // WIN: %[[CUR2:.+]] = load i8*, i8** %[[ARGS]]
-  // WIN: %[[NEXT2:.+]] = getelementptr inbounds i8, i8* %[[CUR2]], i64 8 
+  // WIN: %[[NEXT2:.+]] = getelementptr inbounds i8, i8* %[[CUR2]], i64 8
   // WIN: store i8* %[[NEXT2]], i8** %[[ARGS]]
   // WIN: %[[BC2:.+]] = bitcast i8* %[[CUR2]] to i31*
   // WIN: %[[LOADV2:.+]] = load i31, i31* %[[BC2]]
@@ -187,13 +189,14 @@
 
   _ExtInt(16) C = __builtin_va_arg(args, _ExtInt(16));
   // LIN: %[[AD3:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], [1 x %struct.__va_list_tag]* %[[ARGS]]
-  // LIN: %[[OFA_P3:.+]] = getelementptr inbounds %struct.__va_list_tag, %struct.__va_list_tag* %[[AD3]], i32 0, i32 2
-  // LIN: %[[OFA3:.+]] = load i8*, i8** %[[OFA_P3]]
-  // LIN: %[[BC3:.+]] = bitcast i8* %[[OFA3]] to i16*
-  // LIN: %[[OFANEXT3:.+]] = getelementptr i8, i8* %[[OFA3]], i32 8
-  // LIN: store i8* %[[OFANEXT3]], i8** %[[OFA_P3]]
-  // LIN: %[[LOAD3:.+]] = load i16, i16* %[[BC3]]
-  // LIN: store i16 %[[LOAD3]], i16*
+  // LIN: %[[OFA_P3:.+]] = getelementptr inbounds %struct.__va_list_tag, %struct.__va_list_tag* %[[AD3]], i32 0, i32 0
+  // LIN: %[[GPOFFSET:.+]] = load i32, i32* %[[OFA_P3]]
+  // LIN: %[[FITSINGP:.+]] = icmp ule i32 %[[GPOFFSET]], 40
+  // LIN: br i1 %[[FITSINGP]]
+  // LIN: %[[BC1:.+]] = phi i16*
+  // LIN: %[[LOAD1:.+]] = load i16, i16* %[[BC1]]
+  // LIN: store i16 %[[LOAD1]], i16*
+
   // WIN: %[[CUR3:.+]] = load i8*, i8** %[[ARGS]]
   // WIN: %[[NEXT3:.+]] = getelementptr inbounds i8, i8* %[[CUR3]], i64 8
   // WIN: store i8* %[[NEXT3]], i8** %[[ARGS]]
@@ -210,8 +213,9 @@
   // LIN: store i8* %[[OFANEXT4]], i8** %[[OFA_P4]]
   // LIN: %[[LOAD4:.+]] = load i129, i129* %[[BC4]]
   // LIN: store i129 %[[LOAD4]], i129*
+
   // WIN: %[[CUR4:.+]] = load i8*, i8** %[[ARGS]]
-  // WIN: %[[NEXT4:.+]] = getelementptr inbounds i8, i8* %[[CUR4]], i64 24 
+  // WIN: %[[NEXT4:.+]] = getelementptr inbounds i8, i8* %[[CUR4]], i64 24
   // WIN: store i8* %[[NEXT4]], i8** %[[ARGS]]
   // WIN: %[[BC4:.+]] = bitcast i8* %[[CUR4]] to i129*
   // WIN: %[[LOADV4:.+]] = load i129, i129* %[[BC4]]
@@ -226,6 +230,7 @@
   // LIN: store i8* %[[OFANEXT5]], i8** %[[OFA_P5]]
   // LIN: %[[LOAD5:.+]] = load i16777200, i16777200* %[[BC5]]
   // LIN: store i16777200 %[[LOAD5]], i16777200*
+
   // WIN: %[[CUR5:.+]] = load i8*, i8** %[[ARGS]]
   // WIN: %[[NEXT5:.+]] = getelementptr inbounds i8, i8* %[[CUR5]], i64 2097152
   // WIN: store i8* %[[NEXT5]], i8** %[[ARGS]]
@@ -268,7 +273,7 @@
 }
 
 void ExplicitCasts() {
-  // LIN: define void @_Z13ExplicitCastsv() 
+  // LIN: define void @_Z13ExplicitCastsv()
   // WIN: define dso_local void @"?ExplicitCasts@@YAXXZ"()
 
   _ExtInt(33) a;
@@ -292,7 +297,7 @@
 };
 
 void OffsetOfTest() {
-  // LIN: define void @_Z12OffsetOfTestv() 
+  // LIN: define void @_Z12OffsetOfTestv()
   // WIN: define dso_local void @"?OffsetOfTest@@YAXXZ"()
 
   auto A = __builtin_offsetof(S,A);
@@ -318,7 +323,7 @@
 
   // UB in C/C++, Defined in OpenCL.
   Ext << 29;
-  // CHECK: shl i28 %{{.+}}, 29 
+  // CHECK: shl i28 %{{.+}}, 29
   Ext >> 29;
   // CHECK: ashr i28 %{{.+}}, 29
 }
Index: clang/test/CodeGen/ext-int.c
===================================================================
--- clang/test/CodeGen/ext-int.c
+++ clang/test/CodeGen/ext-int.c
@@ -1,5 +1,7 @@
-// RUN: %clang_cc1 -triple x86_64-gnu-linux -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK
-// RUN: %clang_cc1 -triple x86_64-windows-pc -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -triple x86_64-gnu-linux -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,LIN64,CHECK64
+// RUN: %clang_cc1 -triple x86_64-windows-pc -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,WIN64,CHECK64
+// RUN: %clang_cc1 -triple i386-gnu-linux -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,LIN32,CHECK32
+// RUNX: %clang_cc1 -triple i386-windows-pc -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,WIN32,CHECK32
 
 
 void GenericTest(_ExtInt(3) a, unsigned _ExtInt(3) b, _ExtInt(4) c) {
@@ -15,14 +17,14 @@
 void VLATest(_ExtInt(3) A, _ExtInt(99) B, _ExtInt(123456) C) {
   // CHECK: define {{.*}}void @VLATest
   int AR1[A];
-  // CHECK: %[[A:.+]] = zext i3 %{{.+}} to i64
-  // CHECK: %[[VLA1:.+]] = alloca i32, i64 %[[A]]
+  // CHECK: %[[A:.+]] = zext i3 %{{.+}} to i[[INDXSIZE:[0-9]+]]
+  // CHECK: %[[VLA1:.+]] = alloca i32, i[[INDXSIZE]] %[[A]]
   int AR2[B];
-  // CHECK: %[[B:.+]] = trunc i99 %{{.+}} to i64
-  // CHECK: %[[VLA2:.+]] = alloca i32, i64 %[[B]]
+  // CHECK: %[[B:.+]] = trunc i99 %{{.+}} to i[[INDXSIZE]]
+  // CHECK: %[[VLA2:.+]] = alloca i32, i[[INDXSIZE]] %[[B]]
   int AR3[C];
-  // CHECK: %[[C:.+]] = trunc i123456 %{{.+}} to i64
-  // CHECK: %[[VLA3:.+]] = alloca i32, i64 %[[C]]
+  // CHECK: %[[C:.+]] = trunc i123456 %{{.+}} to i[[INDXSIZE]]
+  // CHECK: %[[VLA3:.+]] = alloca i32, i[[INDXSIZE]] %[[C]]
 }
 
 struct S {
@@ -32,13 +34,27 @@
 };
 
 void OffsetOfTest() {
-  // CHECK: define {{.*}}void @OffsetOfTest 
+  // CHECK: define {{.*}}void @OffsetOfTest
   int A = __builtin_offsetof(struct S,A);
   // CHECK: store i32 0, i32* %{{.+}}
   int B = __builtin_offsetof(struct S,B);
-  // CHECK: store i32 8, i32* %{{.+}}
+  // CHECK64: store i32 8, i32* %{{.+}}
+  // CHECK32: store i32 4, i32* %{{.+}}
   int C = __builtin_offsetof(struct S,C);
-  // CHECK: store i32 2097160, i32* %{{.+}}
+  // CHECK64: store i32 2097160, i32* %{{.+}}
+  // CHECK32: store i32 2097156, i32* %{{.+}}
 }
 
+// Make sure 128 and 64 bit versions are passed like integers, and that >128
+// is passed indirectly.
+void ParamPassing(_ExtInt(129) a, _ExtInt(128) b, _ExtInt(64) c) {}
+// LIN64: define void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i64 %{{.+}}, i64 %{{.+}}, i64 %{{.+}})
+// WIN64: define dso_local void @ParamPassing(i129* %{{.+}}, i128* %{{.+}}, i64 %{{.+}})
+// LIN32: define void @ParamPassing(i129* %{{.+}}, i128* %{{.+}}, i64 %{{.+}})
+// WIN32: define dso_local void @ParamPassing(i129* %{{.+}}, i128* %{{.+}}, i64 %{{.+}})
+void ParamPassing2(_ExtInt(129) a, _ExtInt(127) b, _ExtInt(63) c) {}
+// LIN64: define void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i64 %{{.+}}, i64 %{{.+}}, i64 %{{.+}})
+// WIN64: define dso_local void @ParamPassing2(i129* %{{.+}}, i127* %{{.+}}, i63 %{{.+}})
+// LIN32: define void @ParamPassing2(i129* %{{.+}}, i127* %{{.+}}, i63 %{{.+}})
+// WIN32: define dso_local void @ParamPassing2(i129* %{{.+}}, i127* %{{.+}}, i63 %{{.+}})
 
Index: clang/test/CodeGen/ext-int-sanitizer.cpp
===================================================================
--- clang/test/CodeGen/ext-int-sanitizer.cpp
+++ clang/test/CodeGen/ext-int-sanitizer.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-gnu-linux -fsanitize=array-bounds,enum,float-cast-overflow,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,unsigned-integer-overflow,signed-integer-overflow,shift-base,shift-exponent -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s 
+// RUN: %clang_cc1 -triple x86_64-gnu-linux -fsanitize=array-bounds,enum,float-cast-overflow,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,unsigned-integer-overflow,signed-integer-overflow,shift-base,shift-exponent -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s
 
 
 // CHECK: define void @_Z6BoundsRA10_KiU7_ExtIntILi15EEi
@@ -56,9 +56,11 @@
 
   i = E;
   // CHECK: %[[LOADE:.+]] = load i35
-  // CHECK: %[[CONV:.+]] = trunc i35 %[[LOADE]] to i32
+  // CHECK: store i35 %[[LOADE]], i35* %[[EADDR:.+]]
+  // CHECK: %[[LOADE2:.+]] = load i35, i35* %[[EADDR]]
+  // CHECK: %[[CONV:.+]] = trunc i35 %[[LOADE2]] to i32
   // CHECK: %[[EXT:.+]] = zext i32 %[[CONV]] to i35
-  // CHECK: %[[CHECK:.+]] = icmp eq i35 %[[EXT]], %[[LOADE]]
+  // CHECK: %[[CHECK:.+]] = icmp eq i35 %[[EXT]], %[[LOADE2]]
   // CHECK: br i1 %[[CHECK]]
   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
 
@@ -76,9 +78,11 @@
 
   j = E;
   // CHECK: %[[LOADE:.+]] = load i35
-  // CHECK: %[[CONV:.+]] = trunc i35 %[[LOADE]] to i32
+  // CHECK: store i35 %[[LOADE]], i35* %[[EADDR:.+]]
+  // CHECK: %[[LOADE2:.+]] = load i35, i35* %[[EADDR]]
+  // CHECK: %[[CONV:.+]] = trunc i35 %[[LOADE2]] to i32
   // CHECK: %[[EXT:.+]] = zext i32 %[[CONV]] to i35
-  // CHECK: %[[CHECK:.+]] = icmp eq i35 %[[EXT]], %[[LOADE]]
+  // CHECK: %[[CHECK:.+]] = icmp eq i35 %[[EXT]], %[[LOADE2]]
   // CHECK: br i1 %[[CHECK]]
   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
 
@@ -118,16 +122,19 @@
 // CHECK: define void @_Z15SignChangeCheckU7_ExtIntILi39EEjU7_ExtIntILi39EEi
 void SignChangeCheck(unsigned _ExtInt(39) UE, _ExtInt(39) E) {
   UE = E;
+  // CHECK: %[[LOADEU:.+]] = load i39
   // CHECK: %[[LOADE:.+]] = load i39
-  // CHECK: %[[NEG:.+]] = icmp slt i39 %[[LOADE]], 0
+  // CHECK: store i39 %[[LOADE]], i39* %[[EADDR:.+]]
+  // CHECK: %[[LOADE2:.+]] = load i39, i39* %[[EADDR]]
+  // CHECK: %[[NEG:.+]] = icmp slt i39 %[[LOADE2]], 0
   // CHECK: %[[SIGNCHECK:.+]] = icmp eq i1 %[[NEG]], false
   // CHECK: br i1 %[[SIGNCHECK]]
   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
 
-
   E = UE;
-  // CHECK: %[[LOADUE:.+]] = load i39
-  // CHECK: %[[NEG:.+]] = icmp slt i39 %[[LOADUE]], 0
+  // CHECK: store i39 %[[LOADE2]], i39* %[[UEADDR:.+]]
+  // CHECK: %[[LOADUE2:.+]] = load i39, i39* %[[UEADDR]]
+  // CHECK: %[[NEG:.+]] = icmp slt i39 %[[LOADUE2]], 0
   // CHECK: %[[SIGNCHECK:.+]] = icmp eq i1 false, %[[NEG]]
   // CHECK: br i1 %[[SIGNCHECK]]
   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
@@ -138,8 +145,10 @@
 
   // Also triggers signed integer overflow.
   E / E;
-  // CHECK: %[[E:.+]] = load i11, i11*
-  // CHECK: %[[E2:.+]] = load i11, i11*
+  // CHECK: %[[E1LOAD:.+]] = load i11
+  // CHECK: store i11 %[[E1LOAD]], i11* %[[EADDR:.+]]
+  // CHECK: %[[E:.+]] = load i11, i11* %[[EADDR]]
+  // CHECK: %[[E2:.+]] = load i11, i11* %[[EADDR]]
   // CHECK: %[[NEZERO:.+]] = icmp ne i11 %[[E2]], 0
   // CHECK: %[[NEMIN:.+]] = icmp ne i11 %[[E]], -1024
   // CHECK: %[[NENEG1:.+]] = icmp ne i11 %[[E2]], -1
@@ -154,8 +163,10 @@
 // CHECK: define void @_Z6ShiftsU7_ExtIntILi9EEi
 void Shifts(_ExtInt(9) E) {
   E >> E;
-  // CHECK: %[[LHSE:.+]] = load i9, i9*
-  // CHECK: %[[RHSE:.+]] = load i9, i9*
+  // CHECK: %[[E1LOAD:.+]] = load i9, i9*
+  // CHECK: store i9 %[[E1LOAD]], i9* %[[EADDR:.+]]
+  // CHECK: %[[LHSE:.+]] = load i9, i9* %[[EADDR]]
+  // CHECK: %[[RHSE:.+]] = load i9, i9* %[[EADDR]]
   // CHECK: %[[CMP:.+]] = icmp ule i9 %[[RHSE]], 8
   // CHECK: br i1 %[[CMP]]
   // CHECK: call void @__ubsan_handle_shift_out_of_bounds_abort
@@ -179,8 +190,10 @@
                            _ExtInt(4) SmallestE,
                            _ExtInt(31) JustRightE) {
   BiggestE + BiggestE;
-  // CHECK: %[[LOAD1:.+]] = load i93, i93*
-  // CHECK: %[[LOAD2:.+]] = load i93, i93*
+  // CHECK: %[[LOADBIGGESTE2:.+]] = load i93
+  // CHECK: store i93 %[[LOADBIGGESTE2]], i93* %[[BIGGESTEADDR:.+]]
+  // CHECK: %[[LOAD1:.+]] = load i93, i93* %[[BIGGESTEADDR]]
+  // CHECK: %[[LOAD2:.+]] = load i93, i93* %[[BIGGESTEADDR]]
   // CHECK: %[[OFCALL:.+]] = call { i93, i1 } @llvm.sadd.with.overflow.i93(i93 %[[LOAD1]], i93 %[[LOAD2]])
   // CHECK: %[[EXRESULT:.+]] = extractvalue { i93, i1 } %[[OFCALL]], 0
   // CHECK: %[[OFRESULT:.+]] = extractvalue { i93, i1 } %[[OFCALL]], 1
@@ -214,8 +227,10 @@
                              unsigned _ExtInt(23) SmallE,
                              unsigned _ExtInt(35) BigE) {
   u = SmallE + SmallE;
-  // CHECK: %[[LOADE1:.+]] = load i23, i23*
-  // CHECK: %[[LOADE2:.+]] = load i23, i23*
+  // CHECK: %[[LOADBIGGESTE2:.+]] = load i23
+  // CHECK: store i23 %[[LOADBIGGESTE2]], i23* %[[BIGGESTEADDR:.+]]
+  // CHECK: %[[LOADE1:.+]] = load i23, i23* %[[BIGGESTEADDR]]
+  // CHECK: %[[LOADE2:.+]] = load i23, i23* %[[BIGGESTEADDR]]
   // CHECK: %[[OFCALL:.+]] = call { i23, i1 } @llvm.uadd.with.overflow.i23(i23 %[[LOADE1]], i23 %[[LOADE2]])
   // CHECK: %[[EXRESULT:.+]] = extractvalue { i23, i1 } %[[OFCALL]], 0
   // CHECK: %[[OFRESULT:.+]] = extractvalue { i23, i1 } %[[OFCALL]], 1
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -1822,6 +1822,15 @@
     return ABIArgInfo::getExtend(Ty);
   }
 
+  if (const auto * EIT = Ty->getAs<ExtIntType>()) {
+    if (EIT->getNumBits() <= 64) {
+      if (InReg)
+        return ABIArgInfo::getDirectInReg();
+      return ABIArgInfo::getDirect();
+    }
+    return getIndirectResult(Ty, /*ByVal=*/false, State);
+  }
+
   if (InReg)
     return ABIArgInfo::getDirectInReg();
   return ABIArgInfo::getDirect();
@@ -2785,6 +2794,15 @@
     return;
   }
 
+  if (const auto *EITy = Ty->getAs<ExtIntType>()) {
+    if (EITy->getNumBits() <= 64)
+      Current = Integer;
+    else if (EITy->getNumBits() <= 128)
+      Lo = Hi = Integer;
+    // Larger values need to get passed in memory.
+    return;
+  }
+
   if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) {
     // Arrays are treated like structures.
 
@@ -2992,7 +3010,8 @@
   // the argument in the free register. This does not seem to happen currently,
   // but this code would be much safer if we could mark the argument with
   // 'onstack'. See PR12193.
-  if (!isAggregateTypeForABI(Ty) && !IsIllegalVectorType(Ty)) {
+  if (!isAggregateTypeForABI(Ty) && !IsIllegalVectorType(Ty) &&
+      !Ty->isExtIntType()) {
     // Treat an enum type as its underlying type.
     if (const EnumType *EnumTy = Ty->getAs<EnumType>())
       Ty = EnumTy->getDecl()->getIntegerType();
@@ -4083,6 +4102,17 @@
     }
   }
 
+  if (Ty->isExtIntType()) {
+    // MS x64 ABI requirement: "Any argument that doesn't fit in 8 bytes, or is
+    // not 1, 2, 4, or 8 bytes, must be passed by reference."
+    // However, non-power-of-two _ExtInts will be passed as 1,2,4 or 8 bytes
+    // anyway as long is it fits in them, so we don't have to check the power of
+    // 2.
+    if (Width <= 64)
+      return ABIArgInfo::getDirect();
+    return ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
+  }
+
   return ABIArgInfo::getDirect();
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to