diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -438,6 +438,8 @@ VALUE_LANGOPT(FuchsiaAPILevel, 32, 0, "Fuchsia API level") +BENIGN_VALUE_LANGOPT(MaxBitIntWidth, 32, 128, "Maximum width of a _BitInt") + #undef LANGOPT #undef COMPATIBLE_LANGOPT #undef BENIGN_LANGOPT diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h --- a/clang/include/clang/Basic/TargetInfo.h +++ b/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" @@ -235,6 +236,8 @@ unsigned MaxOpenCLWorkGroupSize; + unsigned MaxBitIntWidth; + Optional DarwinTargetVariantTriple; // TargetInfo Constructor. Default initializes all fields. @@ -595,11 +598,17 @@ // Different targets may support a different maximum width for the _BitInt // type, depending on what operations are supported. virtual size_t getMaxBitIntWidth() const { + // Consider -fexperimental_max_bitint_width first. + if (MaxBitIntWidth) + return std::min(MaxBitIntWidth, + llvm::IntegerType::MAX_INT_BITS); + // 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. + // backends currently have a bug where they only support float to int + // conversion (and vice versa) on types that are <= 128 bits and crash + // otherwise. We're setting the max supported value to 128 to be + // conservative. return 128; } diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -5945,6 +5945,13 @@ def fobjc_gc : Flag<["-"], "fobjc-gc">, Group, HelpText<"Enable Objective-C garbage collection">; +def fexperimental_max_bitint_width_EQ: + Joined<["-"], "fexperimental-max-bitint-width=">, Group, + MetaVarName<"">, + Flags<[CC1Option, NoDriverOption]>, + HelpText<"Set the maximum bitwidth for _BitInt (experimental)">, + MarshallingInfoInt, "0">; + //===----------------------------------------------------------------------===// // Header Search Options //===----------------------------------------------------------------------===// diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -150,6 +150,9 @@ PlatformMinVersion = VersionTuple(); MaxOpenCLWorkGroupSize = 1024; + + MaxBitIntWidth = 0; + ProgramAddrSpace = 0; } @@ -478,6 +481,9 @@ Diags.Report(diag::err_opt_not_valid_on_target) << "-fprotect-parens"; Opts.ProtectParens = false; } + + if (Opts.MaxBitIntWidth) + MaxBitIntWidth = Opts.MaxBitIntWidth; } bool TargetInfo::initFeatureMap( diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/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); diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/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; diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/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) diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp b/clang/lib/Driver/ToolChains/Hexagon.cpp --- a/clang/lib/Driver/ToolChains/Hexagon.cpp +++ b/clang/lib/Driver/ToolChains/Hexagon.cpp @@ -453,6 +453,8 @@ // Libraries //---------------------------------------------------------------------------- if (IncStdLib && IncDefLibs) { + addBitIntRuntime(HTC, CmdArgs, Args); + if (D.CCCIsCXX()) { if (HTC.ShouldLinkCXXStdlib(Args)) HTC.AddCXXStdlibLibArgs(Args, CmdArgs); diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/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) { diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -312,7 +312,7 @@ #define BENIGN_LANGOPT(Name, Bits, Default, Description) #define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) -#define BENIGN_VALUE_LANGOPT(Name, Type, Bits, Default, Description) +#define BENIGN_VALUE_LANGOPT(Name, Bits, Default, Description) #include "clang/Basic/LangOptions.def" if (ExistingLangOpts.ModuleFeatures != LangOpts.ModuleFeatures) { diff --git a/clang/test/Driver/linux-ld.c b/clang/test/Driver/linux-ld.c --- a/clang/test/Driver/linux-ld.c +++ b/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 diff --git a/clang/test/Sema/large-bit-int.c b/clang/test/Sema/large-bit-int.c new file mode 100644 --- /dev/null +++ b/clang/test/Sema/large-bit-int.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fexperimental-max-bitint-width=1024 -fsyntax-only -verify %s -Wno-unused -triple x86_64-gnu-linux + +void f() { + _Static_assert(__BITINT_MAXWIDTH__ == 1024, "Macro value is unexpected."); + + _BitInt(1024) a; + unsigned _BitInt(1024) b; + + _BitInt(8388609) c; // expected-error {{signed _BitInt of bit sizes greater than 1024 not supported}} + unsigned _BitInt(0xFFFFFFFFFF) d; // expected-error {{unsigned _BitInt of bit sizes greater than 1024 not supported}} +}