mgehre-amd created this revision.
mgehre-amd added reviewers: aaron.ballman, erichkeane.
Herald added subscribers: luke957, s.egerton, mstorsjo, simoncook, 
fedor.sergeev, dschuff.
Herald added a project: All.
mgehre-amd requested review of this revision.
Herald added subscribers: pcwang-thead, aheejin.
Herald added a project: clang.

According to the RFC [0], this review contains the clang parts of large integer 
divison for _BitInt.

It contains the following parts:

- Driver: Gnu, MinGW: Link libbitint when available
- clang/Basic/TargetInfo: Increase getMaxBitIntWidth to 
llvm::IntegerType::MAX_INT_BITS
- Sema: Diagnose when converting _BitInt to/from floating point for bit width > 
128 because that breaks in the backend
- Lex: Speedup parsing of large integer literals with a power-of-two radix, so 
parsing a hex literal with 2097152 digits (=MAX_INT_BITS) doesn't take forever

[0] 
https://discourse.llvm.org/t/rfc-add-support-for-division-of-large-bitint-builtins-selectiondag-globalisel-clang/60329


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D122234

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TargetInfo.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Driver/ToolChains/CommonArgs.cpp
  clang/lib/Driver/ToolChains/CommonArgs.h
  clang/lib/Driver/ToolChains/Gnu.cpp
  clang/lib/Driver/ToolChains/MinGW.cpp
  clang/lib/Lex/LiteralSupport.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaCast.cpp
  clang/test/CodeGen/ext-int-cc.c
  clang/test/Driver/linux-ld.c
  clang/test/Lexer/bitint-constants.c
  clang/test/Preprocessor/init-aarch64.c
  clang/test/Preprocessor/init.c
  clang/test/Sema/ext-int.c
  clang/test/SemaCXX/ext-int.cpp

Index: clang/test/SemaCXX/ext-int.cpp
===================================================================
--- clang/test/SemaCXX/ext-int.cpp
+++ clang/test/SemaCXX/ext-int.cpp
@@ -17,7 +17,7 @@
   unsigned _BitInt(5) e = 5;
   _BitInt(5) unsigned f;
 
-  _BitInt(-3) g; // expected-error{{signed _BitInt of bit sizes greater than 128 not supported}}
+  _BitInt(-3) g; // expected-error{{signed _BitInt of bit sizes greater than 8388608 not supported}}
   _BitInt(0) h; // expected-error{{signed _BitInt must have a bit size of at least 2}}
   _BitInt(1) i; // expected-error{{signed _BitInt must have a bit size of at least 2}}
   _BitInt(2) j;;
@@ -29,12 +29,12 @@
   constexpr _BitInt(7) o = 33;
 
   // Check imposed max size.
-  _BitInt(129) p;               // expected-error {{signed _BitInt of bit sizes greater than 128 not supported}}
-  unsigned _BitInt(0xFFFFFFFFFF) q; // expected-error {{unsigned _BitInt of bit sizes greater than 128 not supported}}
+  _BitInt(8388609) p;                // expected-error {{signed _BitInt of bit sizes greater than 8388608 not supported}}
+  unsigned _BitInt(0xFFFFFFFFFF) q; // expected-error {{unsigned _BitInt of bit sizes greater than 8388608 not supported}}
 
 // Ensure template params are instantiated correctly.
-  // expected-error@5{{signed _BitInt of bit sizes greater than 128 not supported}}
-  // expected-error@6{{unsigned _BitInt of bit sizes greater than 128 not supported}}
+  // expected-error@5{{signed _BitInt of bit sizes greater than 8388608 not supported}}
+  // expected-error@6{{unsigned _BitInt of bit sizes greater than 8388608 not supported}}
   // expected-note@+1{{in instantiation of template class }}
   HasExtInt<-1> r;
   // expected-error@5{{signed _BitInt must have a bit size of at least 2}}
@@ -285,3 +285,16 @@
 void FromPaper2(_BitInt(8) a1, _BitInt(24) a2) {
   static_assert(is_same<decltype(a1 * (_BitInt(32))a2), _BitInt(32)>::value, "");
 }
+
+void LargeBitIntToFloat(_BitInt(129) a) {
+  float fa = a; // expected-error {{cannot convert '_BitInt' operands of more than 128 bits to floating point}}
+  fa = static_cast<float>(a); // expected-error {{cannot convert '_BitInt' operands of more than 128 bits to floating point}}
+  fa = a + 0.1; // expected-error {{cannot convert '_BitInt' operands of more than 128 bits to floating point}}
+}
+
+_BitInt(129) LargeBitIntFromFloat(float f) {
+  _BitInt(129) a = f; // expected-error {{cannot convert floating point operands to a '_BitInt' of more than 128 bits}}
+  a = f; // expected-error {{cannot convert floating point operands to a '_BitInt' of more than 128 bits}}
+  a = static_cast<_BitInt(129)>(f); // expected-error {{cannot convert floating point operands to a '_BitInt' of more than 128 bits}}
+  return f; // expected-error {{cannot convert floating point operands to a '_BitInt' of more than 128 bits}}
+}
Index: clang/test/Sema/ext-int.c
===================================================================
--- clang/test/Sema/ext-int.c
+++ clang/test/Sema/ext-int.c
@@ -73,3 +73,16 @@
 void FromPaper2(_BitInt(8) a1, _BitInt(24) a2) {
   _Static_assert(EXPR_HAS_TYPE(a1 * (_BitInt(32))a2, _BitInt(32)), "");
 }
+
+
+void LargeBitIntToFloat(_BitInt(129) a) {
+  float fa = a; // expected-error {{cannot convert '_BitInt' operands of more than 128 bits to floating point}}
+  fa = (float)a; // expected-error {{cannot convert '_BitInt' operands of more than 128 bits to floating point}}
+  fa = a + 0.1; // expected-error {{cannot convert '_BitInt' operands of more than 128 bits to floating point}}
+}
+
+_BitInt(129) LargeBitIntFromFloat(float f) {
+  _BitInt(129) b = f; // expected-error {{cannot convert floating point operands to a '_BitInt' of more than 128 bits}}
+  b = (_BitInt(129))f; // expected-error {{cannot convert floating point operands to a '_BitInt' of more than 128 bits}}
+  return f; // expected-error {{cannot convert floating point operands to a '_BitInt' of more than 128 bits}}
+}
Index: clang/test/Preprocessor/init.c
===================================================================
--- clang/test/Preprocessor/init.c
+++ clang/test/Preprocessor/init.c
@@ -1515,7 +1515,7 @@
 // WEBASSEMBLY-NEXT:#define __ATOMIC_RELEASE 3
 // WEBASSEMBLY-NEXT:#define __ATOMIC_SEQ_CST 5
 // WEBASSEMBLY-NEXT:#define __BIGGEST_ALIGNMENT__ 16
-// WEBASSEMBLY-NEXT:#define __BITINT_MAXWIDTH__ 128
+// WEBASSEMBLY-NEXT:#define __BITINT_MAXWIDTH__ 8388608
 // WEBASSEMBLY-NEXT:#define __BOOL_WIDTH__ 8
 // WEBASSEMBLY-NEXT:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
 // WEBASSEMBLY-NEXT:#define __CHAR16_TYPE__ unsigned short
Index: clang/test/Preprocessor/init-aarch64.c
===================================================================
--- clang/test/Preprocessor/init-aarch64.c
+++ clang/test/Preprocessor/init-aarch64.c
@@ -40,7 +40,7 @@
 // AARCH64-NEXT: #define __ATOMIC_SEQ_CST 5
 // AARCH64:      #define __BIGGEST_ALIGNMENT__ 16
 // AARCH64_BE-NEXT: #define __BIG_ENDIAN__ 1
-// AARCH64-NEXT: #define __BITINT_MAXWIDTH__ 128
+// AARCH64-NEXT: #define __BITINT_MAXWIDTH__ 8388608
 // AARCH64-NEXT: #define __BOOL_WIDTH__ 8
 // AARCH64_BE-NEXT: #define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
 // AARCH64_LE-NEXT: #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
Index: clang/test/Lexer/bitint-constants.c
===================================================================
--- clang/test/Lexer/bitint-constants.c
+++ clang/test/Lexer/bitint-constants.c
@@ -137,10 +137,28 @@
   // the width of BITINT_MAXWIDTH. When this value changes in the future, the
   // test cases should pick a new value that can't be represented by a _BitInt,
   // but also add a test case that a 129-bit literal still behaves as-expected.
-  _Static_assert(__BITINT_MAXWIDTH__ <= 128,
-	             "Need to pick a bigger constant for the test case below.");
-  0xFFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'1wb; // expected-error {{integer literal is too large to be represented in any signed integer type}}
-  0xFFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'1uwb; // expected-error {{integer literal is too large to be represented in any integer type}}
+  0xFFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'1wb; // 129 bits are fine
+  0xFFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'1uwb; // 129 bit unsigned are fine
+
+  #define CONCAT(X,Y) X ## Y
+  #define REPEAT2(X) CONCAT(X,X)
+  #define REPEAT4(X) REPEAT2(REPEAT2(X))
+  #define REPEAT16(X) REPEAT4(REPEAT4(X))
+  #define REPEAT256(X) REPEAT16(REPEAT16(X))
+  #define REPEAT65536(X) REPEAT256(REPEAT256(X))
+  #define REPEAT2097152(X)  REPEAT65536(REPEAT16(REPEAT2(X)))
+  #define _LITERAL(X, Suffix) 0x ## X ## Suffix
+  #define LITERAL(X, Suffix) _LITERAL(X, Suffix)
+
+  _Static_assert(__BITINT_MAXWIDTH__ <= 8388608,
+                "Need to pick a bigger constant for the test case below.");
+
+  // 8388608 bits are represented by 2097152 hex digits
+  LITERAL(REPEAT2097152(7), wb); // 262143 bits plus one sign bit are fine
+  LITERAL(REPEAT2097152(F), wb); // expected-error {{integer literal is too large to be represented in any signed integer type}}
+
+  LITERAL(REPEAT2097152(F), uwb); // 262144 bits unsigned are fine
+  LITERAL(REPEAT2097152(F), 1uwb); // expected-error {{integer literal is too large to be represented in any integer type}}
 }
 
 void TestTypes(void) {
Index: clang/test/Driver/linux-ld.c
===================================================================
--- clang/test/Driver/linux-ld.c
+++ clang/test/Driver/linux-ld.c
@@ -174,7 +174,7 @@
 // RUN:     --sysroot=%S/Inputs/basic_linux_tree \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANG-NO-LIBGCC-STATIC %s
 // CHECK-CLANG-NO-LIBGCC-STATIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
-// CHECK-CLANG-NO-LIBGCC-STATIC: "--start-group" "-lgcc" "-lgcc_eh" "-lc" "--end-group"
+// CHECK-CLANG-NO-LIBGCC-STATIC: "--start-group" "{{[^"]*}}/libclang_rt.bitint{{[^"]*}}" "-lgcc" "-lgcc_eh" "-lc" "--end-group"
 //
 // RUN: %clang -static-pie -no-canonical-prefixes %s -### -o %t.o 2>&1 \
 // RUN:     --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \
@@ -189,7 +189,7 @@
 // CHECK-CLANG-LD-STATIC-PIE: "text"
 // CHECK-CLANG-LD-STATIC-PIE: "-m" "elf_x86_64"
 // CHECK-CLANG-LD-STATIC-PIE: "{{.*}}rcrt1.o"
-// CHECK-CLANG-LD-STATIC-PIE: "--start-group" "-lgcc" "-lgcc_eh" "-lc" "--end-group"
+// CHECK-CLANG-LD-STATIC-PIE: "--start-group" "{{[^"]*}}/libclang_rt.bitint{{[^"]*}}" "-lgcc" "-lgcc_eh" "-lc" "--end-group"
 //
 // RUN: %clang -static-pie -pie -no-canonical-prefixes %s -no-pie -### -o %t.o 2>&1 \
 // RUN:     --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \
@@ -204,7 +204,7 @@
 // CHECK-CLANG-LD-STATIC-PIE-PIE: "text"
 // CHECK-CLANG-LD-STATIC-PIE-PIE: "-m" "elf_x86_64"
 // CHECK-CLANG-LD-STATIC-PIE-PIE: "{{.*}}rcrt1.o"
-// CHECK-CLANG-LD-STATIC-PIE-PIE: "--start-group" "-lgcc" "-lgcc_eh" "-lc" "--end-group"
+// CHECK-CLANG-LD-STATIC-PIE-PIE: "--start-group" "{{[^"]*}}/libclang_rt.bitint{{[^"]*}}" "-lgcc" "-lgcc_eh" "-lc" "--end-group"
 //
 // RUN: %clang -static-pie -static -no-canonical-prefixes %s -no-pie -### -o %t.o 2>&1 \
 // RUN:     --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \
@@ -219,7 +219,7 @@
 // CHECK-CLANG-LD-STATIC-PIE-STATIC: "text"
 // CHECK-CLANG-LD-STATIC-PIE-STATIC: "-m" "elf_x86_64"
 // CHECK-CLANG-LD-STATIC-PIE-STATIC: "{{.*}}rcrt1.o"
-// CHECK-CLANG-LD-STATIC-PIE-STATIC: "--start-group" "-lgcc" "-lgcc_eh" "-lc" "--end-group"
+// CHECK-CLANG-LD-STATIC-PIE-STATIC: "--start-group" "{{[^"]*}}/libclang_rt.bitint{{[^"]*}}" "-lgcc" "-lgcc_eh" "-lc" "--end-group"
 //
 // RUN: %clang -static-pie -nopie -no-canonical-prefixes %s -no-pie -### -o %t.o 2>&1 \
 // RUN:     --target=x86_64-unknown-linux -rtlib=platform \
@@ -318,7 +318,7 @@
 // CHECK-LD-64-STATIC: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-unknown-linux/10.2.0/../../../../x86_64-unknown-linux/lib"
 // CHECK-LD-64-STATIC: "-L[[SYSROOT]]/lib"
 // CHECK-LD-64-STATIC: "-L[[SYSROOT]]/usr/lib"
-// CHECK-LD-64-STATIC: "--start-group" "-lgcc" "-lgcc_eh" "-lc" "--end-group"
+// CHECK-LD-64-STATIC: "--start-group" "{{[^"]*}}/libclang_rt.bitint{{[^"]*}}" "-lgcc" "-lgcc_eh" "-lc" "--end-group"
 
 // RUN: %clang -no-pie -### %s --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform -shared -static \
 // RUN:   --gcc-toolchain= --sysroot=%S/Inputs/basic_linux_tree 2>&1 | FileCheck --check-prefix=CHECK-LD-SHARED-STATIC %s
Index: clang/test/CodeGen/ext-int-cc.c
===================================================================
--- clang/test/CodeGen/ext-int-cc.c
+++ clang/test/CodeGen/ext-int-cc.c
@@ -123,33 +123,33 @@
 // are negated. This will give an error when a target does support larger
 // _BitInt widths to alert us to enable the test.
 void ParamPassing4(_BitInt(129) a) {}
-// LIN64-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
-// WIN64-NOT: define dso_local void @ParamPassing4(i129* %{{.+}})
-// LIN32-NOT: define{{.*}} void @ParamPassing4(i129* %{{.+}})
-// WIN32-NOT: define dso_local void @ParamPassing4(i129* %{{.+}})
-// NACL-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
-// NVPTX64-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
-// NVPTX-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
-// SPARCV9-NOT: define{{.*}} void @ParamPassing4(i129* %{{.+}})
-// SPARC-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
-// MIPS64-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
-// MIPS-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
-// SPIR64-NOT: define{{.*}} spir_func void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
-// SPIR-NOT: define{{.*}} spir_func void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
-// HEX-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
-// LANAI-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 4 %{{.+}})
-// R600-NOT: define{{.*}} void @ParamPassing4(i129 addrspace(5)* byval(i129) align 8 %{{.+}})
-// ARC-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 4 %{{.+}})
-// XCORE-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 4 %{{.+}})
-// RISCV64-NOT: define{{.*}} void @ParamPassing4(i129* %{{.+}})
-// RISCV32-NOT: define{{.*}} void @ParamPassing4(i129* %{{.+}})
-// WASM-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
-// SYSTEMZ-NOT: define{{.*}} void @ParamPassing4(i129* %{{.+}})
-// PPC64-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
-// PPC32-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
-// AARCH64-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
-// AARCH64DARWIN-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
-// ARM-NOT: define{{.*}} arm_aapcscc void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
+// LIN64: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
+// WIN64: define dso_local void @ParamPassing4(i129* %{{.+}})
+// LIN32: define{{.*}} void @ParamPassing4(i129* %{{.+}})
+// WIN32: define dso_local void @ParamPassing4(i129* %{{.+}})
+// NACL: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
+// NVPTX64: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
+// NVPTX: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
+// SPARCV9: define{{.*}} void @ParamPassing4(i129* %{{.+}})
+// SPARC: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
+// MIPS64: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
+// MIPS: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
+// SPIR64: define{{.*}} spir_func void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
+// SPIR: define{{.*}} spir_func void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
+// HEX: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
+// LANAI: define{{.*}} void @ParamPassing4(i129* byval(i129) align 4 %{{.+}})
+// R600: define{{.*}} void @ParamPassing4(i129 addrspace(5)* byval(i129) align 8 %{{.+}})
+// ARC: define{{.*}} void @ParamPassing4(i129* byval(i129) align 4 %{{.+}})
+// XCORE: define{{.*}} void @ParamPassing4(i129* byval(i129) align 4 %{{.+}})
+// RISCV64: define{{.*}} void @ParamPassing4(i129* %{{.+}})
+// RISCV32: define{{.*}} void @ParamPassing4(i129* %{{.+}})
+// WASM: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
+// SYSTEMZ: define{{.*}} void @ParamPassing4(i129* %{{.+}})
+// PPC64: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
+// PPC32: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
+// AARCH64: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
+// AARCH64DARWIN: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
+// ARM: define{{.*}} arm_aapcscc void @ParamPassing4(i129* byval(i129) align 8 %{{.+}})
 #endif
 
 _BitInt(63) ReturnPassing(void){}
@@ -272,38 +272,38 @@
 
 #if __BITINT_MAXWIDTH__ > 128
 _BitInt(129) ReturnPassing5(void){}
-// LIN64-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret
-// WIN64-NOT: define dso_local void @ReturnPassing5(i129* noalias sret
-// LIN32-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret
-// WIN32-NOT: define dso_local void @ReturnPassing5(i129* noalias sret
-// NACL-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret
-// NVPTX64-NOT: define{{.*}} i129 @ReturnPassing5(
-// NVPTX-NOT: define{{.*}} i129 @ReturnPassing5(
-// SPARCV9-NOT: define{{.*}} i129 @ReturnPassing5(
-// SPARC-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret
-// MIPS64-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret
-// MIPS-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret
-// SPIR64-NOT: define{{.*}} spir_func void @ReturnPassing5(i129* noalias sret
-// SPIR-NOT: define{{.*}} spir_func void @ReturnPassing5(i129* noalias sret
-// HEX-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret
-// LANAI-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret
-// R600-NOT: define{{.*}} void @ReturnPassing5(i129 addrspace(5)* noalias sret
-// ARC-NOT: define{{.*}} void @ReturnPassing5(i129* inreg noalias sret
-// XCORE-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret
-// RISCV64-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret
-// RISCV32-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret
-// WASM-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret
-// SYSTEMZ-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret
-// PPC64-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret
-// PPC32-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret
-// AARCH64-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret
-// AARCH64DARWIN-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret
-// ARM-NOT: define{{.*}} arm_aapcscc void @ReturnPassing5(i129* noalias sret
+// LIN64: define{{.*}} void @ReturnPassing5(i129* noalias sret
+// WIN64: define dso_local void @ReturnPassing5(i129* noalias sret
+// LIN32: define{{.*}} void @ReturnPassing5(i129* noalias sret
+// WIN32: define dso_local void @ReturnPassing5(i129* noalias sret
+// NACL: define{{.*}} void @ReturnPassing5(i129* noalias sret
+// NVPTX64: define{{.*}} i129 @ReturnPassing5(
+// NVPTX: define{{.*}} i129 @ReturnPassing5(
+// SPARCV9: define{{.*}} i129 @ReturnPassing5(
+// SPARC: define{{.*}} void @ReturnPassing5(i129* noalias sret
+// MIPS64: define{{.*}} void @ReturnPassing5(i129* noalias sret
+// MIPS: define{{.*}} void @ReturnPassing5(i129* noalias sret
+// SPIR64: define{{.*}} spir_func void @ReturnPassing5(i129* noalias sret
+// SPIR: define{{.*}} spir_func void @ReturnPassing5(i129* noalias sret
+// HEX: define{{.*}} void @ReturnPassing5(i129* noalias sret
+// LANAI: define{{.*}} void @ReturnPassing5(i129* noalias sret
+// R600: define{{.*}} void @ReturnPassing5(i129 addrspace(5)* noalias sret
+// ARC: define{{.*}} void @ReturnPassing5(i129* inreg noalias sret
+// XCORE: define{{.*}} void @ReturnPassing5(i129* noalias sret
+// RISCV64: define{{.*}} void @ReturnPassing5(i129* noalias sret
+// RISCV32: define{{.*}} void @ReturnPassing5(i129* noalias sret
+// WASM: define{{.*}} void @ReturnPassing5(i129* noalias sret
+// SYSTEMZ: define{{.*}} void @ReturnPassing5(i129* noalias sret
+// PPC64: define{{.*}} void @ReturnPassing5(i129* noalias sret
+// PPC32: define{{.*}} void @ReturnPassing5(i129* noalias sret
+// AARCH64: define{{.*}} void @ReturnPassing5(i129* noalias sret
+// AARCH64DARWIN: define{{.*}} void @ReturnPassing5(i129* noalias sret
+// ARM: define{{.*}} arm_aapcscc void @ReturnPassing5(i129* noalias sret
 
 // SparcV9 is odd in that it has a return-size limit of 256, not 128 or 64
 // like other platforms, so test to make sure this behavior will still work.
 _BitInt(256) ReturnPassing6(void) {}
-// SPARCV9-NOT: define{{.*}} i256 @ReturnPassing6(
+// SPARCV9: define{{.*}} i256 @ReturnPassing6(
 _BitInt(257) ReturnPassing7(void) {}
-// SPARCV9-NOT: define{{.*}} void @ReturnPassing7(i257* noalias sret
+// SPARCV9: define{{.*}} void @ReturnPassing7(i257* noalias sret
 #endif
Index: clang/lib/Sema/SemaCast.cpp
===================================================================
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -3136,6 +3136,9 @@
   if (SrcExpr.isInvalid())
     return;
 
+  Self.diagnoseBitIntToFloating(Kind, SrcExpr.get());
+  Self.diagnoseFloatingToBitInt(Kind, DestType, SrcExpr.get());
+
   if (Kind == CK_BitCast)
     checkCastAlign();
 }
Index: clang/lib/Sema/Sema.cpp
===================================================================
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -625,6 +625,25 @@
       << FixItHint::CreateReplacement(E->getSourceRange(), "nullptr");
 }
 
+void Sema::diagnoseBitIntToFloating(CastKind Kind, const Expr *E) {
+  if (Kind != CK_IntegralToFloating)
+    return;
+
+  auto Ty = E->getType();
+  if (Ty->isBitIntType() && getASTContext().getIntWidth(Ty) > 128) {
+    Diag(E->getBeginLoc(), diag::err_int_to_float_bit_int_max_size) << 128;
+  }
+}
+
+void Sema::diagnoseFloatingToBitInt(CastKind Kind, QualType Ty, const Expr *E) {
+  if (Kind != CK_FloatingToIntegral)
+    return;
+
+  if (Ty->isBitIntType() && getASTContext().getIntWidth(Ty) > 128) {
+    Diag(E->getBeginLoc(), diag::err_float_to_int_bit_int_max_size) << 128;
+  }
+}
+
 /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
 /// If there is already an implicit cast, merge into the existing one.
 /// The result is of the given category.
@@ -656,6 +675,8 @@
 
   diagnoseNullableToNonnullConversion(Ty, E->getType(), E->getBeginLoc());
   diagnoseZeroToNullptrConversion(Kind, E);
+  diagnoseBitIntToFloating(Kind, E);
+  diagnoseFloatingToBitInt(Kind, Ty, E);
 
   QualType ExprTy = Context.getCanonicalType(E->getType());
   QualType TypeTy = Context.getCanonicalType(Ty);
Index: clang/lib/Lex/LiteralSupport.cpp
===================================================================
--- clang/lib/Lex/LiteralSupport.cpp
+++ clang/lib/Lex/LiteralSupport.cpp
@@ -1227,9 +1227,32 @@
     return Val.getZExtValue() != N;
   }
 
-  Val = 0;
   const char *Ptr = DigitsBegin;
 
+  if (llvm::isPowerOf2_32(radix)) {
+    unsigned BitsPerDigit = llvm::Log2(radix);
+    unsigned BitPos = NumDigits * BitsPerDigit;
+
+    llvm::APInt Temp(BitPos, 0);
+
+    while (Ptr < SuffixBegin) {
+      if (isDigitSeparator(*Ptr)) {
+        ++Ptr;
+        continue;
+      }
+      unsigned C = llvm::hexDigitValue(*Ptr++);
+      BitPos -= BitsPerDigit;
+      Temp.insertBits(C, BitPos, BitsPerDigit);
+    }
+
+    // Due to digit separators, BitPos might be greater than zero.
+    Temp.lshrInPlace(BitPos);
+
+    Val = Temp.zextOrTrunc(Val.getBitWidth());
+    return Temp.getActiveBits() > Val.getBitWidth();
+  }
+
+  Val = 0;
   llvm::APInt RadixVal(Val.getBitWidth(), radix);
   llvm::APInt CharVal(Val.getBitWidth(), 0);
   llvm::APInt OldVal = Val;
Index: clang/lib/Driver/ToolChains/MinGW.cpp
===================================================================
--- clang/lib/Driver/ToolChains/MinGW.cpp
+++ clang/lib/Driver/ToolChains/MinGW.cpp
@@ -64,6 +64,8 @@
     CmdArgs.push_back("-lmingwthrd");
   CmdArgs.push_back("-lmingw32");
 
+  addBitIntRuntime(getToolChain(), CmdArgs, Args);
+
   // Make use of compiler-rt if --rtlib option is used
   ToolChain::RuntimeLibType RLT = getToolChain().GetRuntimeLibType(Args);
   if (RLT == ToolChain::RLT_Libgcc) {
Index: clang/lib/Driver/ToolChains/Gnu.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Gnu.cpp
+++ clang/lib/Driver/ToolChains/Gnu.cpp
@@ -610,6 +610,8 @@
         // FIXME: Does this really make sense for all GNU toolchains?
         WantPthread = true;
 
+      addBitIntRuntime(getToolChain(), CmdArgs, Args);
+
       AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
 
       if (WantPthread && !isAndroid)
Index: clang/lib/Driver/ToolChains/CommonArgs.h
===================================================================
--- clang/lib/Driver/ToolChains/CommonArgs.h
+++ clang/lib/Driver/ToolChains/CommonArgs.h
@@ -45,6 +45,9 @@
 void linkXRayRuntimeDeps(const ToolChain &TC,
                          llvm::opt::ArgStringList &CmdArgs);
 
+void addBitIntRuntime(const ToolChain &TC, llvm::opt::ArgStringList &CmdArgs,
+                      const llvm::opt::ArgList &Args);
+
 void AddRunTimeLibs(const ToolChain &TC, const Driver &D,
                     llvm::opt::ArgStringList &CmdArgs,
                     const llvm::opt::ArgList &Args);
Index: clang/lib/Driver/ToolChains/CommonArgs.cpp
===================================================================
--- clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -987,6 +987,16 @@
   return !StaticRuntimes.empty() || !NonWholeStaticRuntimes.empty();
 }
 
+void tools::addBitIntRuntime(const ToolChain &TC, ArgStringList &CmdArgs,
+                             const ArgList &Args) {
+  std::string BitIntPath = TC.getCompilerRT(Args, "bitint");
+
+  // While building compiler-rt itself, this library is not available,
+  // so we don't try to link it.
+  if (TC.getVFS().exists(BitIntPath))
+    CmdArgs.push_back(Args.MakeArgString(BitIntPath));
+}
+
 bool tools::addXRayRuntime(const ToolChain&TC, const ArgList &Args, ArgStringList &CmdArgs) {
   if (Args.hasArg(options::OPT_shared))
     return false;
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -5027,6 +5027,10 @@
   /// Warn when implicitly casting 0 to nullptr.
   void diagnoseZeroToNullptrConversion(CastKind Kind, const Expr *E);
 
+  /// Error out when casting a floating point value to a large _BitInt
+  void diagnoseBitIntToFloating(CastKind Kind, const Expr *E);
+  void diagnoseFloatingToBitInt(CastKind Kind, QualType Ty, const Expr *E);
+
   ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) {
     return DelayedDiagnostics.push(pool);
   }
Index: clang/include/clang/Basic/TargetInfo.h
===================================================================
--- clang/include/clang/Basic/TargetInfo.h
+++ clang/include/clang/Basic/TargetInfo.h
@@ -31,6 +31,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/Frontend/OpenMP/OMPGridValues.h"
+#include "llvm/IR/DerivedTypes.h"
 #include "llvm/Support/DataTypes.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/VersionTuple.h"
@@ -595,12 +596,8 @@
   // Different targets may support a different maximum width for the _BitInt
   // type, depending on what operations are supported.
   virtual size_t getMaxBitIntWidth() const {
-    // FIXME: this value should be llvm::IntegerType::MAX_INT_BITS, which is
-    // maximum bit width that LLVM claims its IR can support. However, most
-    // backends currently have a bug where they only support division
-    // operations on types that are <= 128 bits and crash otherwise. We're
-    // setting the max supported value to 128 to be conservative.
-    return 128;
+    // TODO: Return 128 for targets that don't link libbitint?
+    return llvm::IntegerType::MAX_INT_BITS;
   }
 
   /// Determine whether _Float16 is supported on this target.
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8419,6 +8419,12 @@
   "__builtin_mul_overflow does not support 'signed _BitInt' operands of more "
   "than %0 bits">;
 
+def err_int_to_float_bit_int_max_size : Error<
+  "cannot convert '_BitInt' operands of more than %0 bits to floating point">;
+
+def err_float_to_int_bit_int_max_size : Error<
+  "cannot convert floating point operands to a '_BitInt' of more than %0 bits">;
+
 def err_atomic_load_store_uses_lib : Error<
   "atomic %select{load|store}0 requires runtime support that is not "
   "available for this target">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to