This revision was automatically updated to reflect the committed changes.
Closed by commit rG5a1d9c0f5ac8: Fix x86/x86_64 calling convention for _ExtInt 
(authored by erichkeane).
Herald added a project: clang.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D78785/new/

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,51 @@
 };
 
 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 %{{.+}})
+_ExtInt(63) ReturnPassing(){}
+// LIN64: define i64 @ReturnPassing(
+// WIN64: define dso_local i63 @ReturnPassing(
+// LIN32: define i63 @ReturnPassing(
+// WIN32: define dso_local i64 @ReturnPassing(
+_ExtInt(64) ReturnPassing2(){}
+// LIN64: define i64 @ReturnPassing2(
+// WIN64: define dso_local i64 @ReturnPassing2(
+// LIN32: define i64 @ReturnPassing2(
+// WIN32: define dso_local i64 @ReturnPassing2(
+_ExtInt(127) ReturnPassing3(){}
+// LIN64: define { i64, i64 } @ReturnPassing3(
+// WIN64: define dso_local void @ReturnPassing3(i127* noalias sret
+// LIN32: define i127 @ReturnPassing3(
+// WIN32: define dso_local i127 @ReturnPassing3(
+_ExtInt(128) ReturnPassing4(){}
+// LIN64: define { i64, i64 } @ReturnPassing4(
+// WIN64: define dso_local void @ReturnPassing4(i128* noalias sret
+// LIN32: define i128 @ReturnPassing4(
+// WIN32: define dso_local i64 @ReturnPassing4(
+_ExtInt(129) ReturnPassing5(){}
+// LIN64: define void @ReturnPassing5(i129* noalias sret
+// WIN64: define dso_local void @ReturnPassing5(i129* noalias sret
+// LIN32: define i129 @ReturnPassing5(
+// WIN32: define dso_local i129 @ReturnPassing5(
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.
 
@@ -2959,8 +2977,9 @@
     if (const EnumType *EnumTy = Ty->getAs<EnumType>())
       Ty = EnumTy->getDecl()->getIntegerType();
 
-    return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty)
-                                          : ABIArgInfo::getDirect());
+    if (!Ty->isExtIntType())
+      return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty)
+                                            : ABIArgInfo::getDirect());
   }
 
   return getNaturalAlignIndirect(Ty);
@@ -2992,7 +3011,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 +4103,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