Index: docs/ClangCommandLineReference.rst =================================================================== --- docs/ClangCommandLineReference.rst +++ docs/ClangCommandLineReference.rst @@ -2754,6 +2754,10 @@ Enable linker relaxation +.. option:: -msmall-data-limit= + +Put global and static data smaller than the limitation into a special section (RISCV only) + Optimization level ~~~~~~~~~~~~~~~~~~ Index: include/clang/Basic/CodeGenOptions.def =================================================================== --- include/clang/Basic/CodeGenOptions.def +++ include/clang/Basic/CodeGenOptions.def @@ -282,6 +282,9 @@ /// or 0 if unspecified. VALUE_CODEGENOPT(NumRegisterParameters, 32, 0) +/// The threshold to put data into small data section. +VALUE_CODEGENOPT(SmallDataLimit, 32, 0) + /// The lower bound for a buffer to be considered for stack protection. VALUE_CODEGENOPT(SSPBufferSize, 32, 0) Index: include/clang/Driver/CC1Options.td =================================================================== --- include/clang/Driver/CC1Options.td +++ include/clang/Driver/CC1Options.td @@ -290,6 +290,8 @@ HelpText<"Do not put zero initialized data in the BSS">; def mregparm : Separate<["-"], "mregparm">, HelpText<"Limit the number of registers available for integer arguments">; +def msmall_data_limit : Separate<["-"], "msmall-data-limit">, + HelpText<"Put global and static data smaller than the limitation into a special section">; def munwind_tables : Flag<["-"], "munwind-tables">, HelpText<"Generate unwinding tables for all functions">; def mconstructor_aliases : Flag<["-"], "mconstructor-aliases">, Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -2099,6 +2099,8 @@ HelpText<"Enable linker relaxation">; def mno_relax : Flag<["-"], "mno-relax">, Group, HelpText<"Disable linker relaxation">; +def msmall_data_limit_EQ : Joined<["-"], "msmall-data-limit=">, Group, Alias, + HelpText<"Put global and static data smaller than the limitation into a special section">; def munaligned_access : Flag<["-"], "munaligned-access">, Group, HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64 only)">; Index: lib/CodeGen/CodeGenModule.h =================================================================== --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -1429,6 +1429,10 @@ /// Emits target specific Metadata for global declarations. void EmitTargetMetadata(); + /// Emit the module flag metadata used to pass options controlling the + /// the backend to LLVM. + void EmitBackendOptionsMetadata(const CodeGenOptions CodeGenOpts); + /// Emits OpenCL specific Metadata e.g. OpenCL version. void EmitOpenCLMetadata(); Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -593,6 +593,8 @@ EmitCommandLineMetadata(); EmitTargetMetadata(); + + EmitBackendOptionsMetadata(getCodeGenOpts()); } void CodeGenModule::EmitOpenCLMetadata() { @@ -5276,6 +5278,17 @@ } } +void CodeGenModule::EmitBackendOptionsMetadata(const CodeGenOptions CodeGenOpts) { + switch (getTriple().getArch()) { + default: break; + case llvm::Triple::riscv32: + case llvm::Triple::riscv64: + getModule().addModuleFlag(llvm::Module::ModFlagBehaviorFirstVal, + "SmallDataLimit", CodeGenOpts.SmallDataLimit); + break; + } +} + void CodeGenModule::EmitCoverageFile() { if (getCodeGenOpts().CoverageDataFile.empty() && getCodeGenOpts().CoverageNotesFile.empty()) Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -1799,6 +1799,27 @@ CmdArgs.push_back("-target-abi"); CmdArgs.push_back(ABIName); + + // Forward the -msmall-data-limit= option. + if (Arg *A = Args.getLastArg(options::OPT_G)) { + CmdArgs.push_back("-msmall-data-limit"); + CmdArgs.push_back(A->getValue()); + // Not support linker relaxation for PIC. + } else if (Args.getLastArg(options::OPT_shared, options::OPT_fpic, + options::OPT_fPIC)) { + CmdArgs.push_back("-msmall-data-limit"); + CmdArgs.push_back("0"); + // Not support linker relaxation for RV64 with large code model. + } else if (Args.getLastArgValue(options::OPT_mcmodel_EQ) + .equals_lower("large") && + (Triple.getArch() == llvm::Triple::riscv64)) { + CmdArgs.push_back("-msmall-data-limit"); + CmdArgs.push_back("0"); + // Passing 8 as default small data limitation. + } else { + CmdArgs.push_back("-msmall-data-limit"); + CmdArgs.push_back("8"); + } } void Clang::AddSparcTargetArgs(const ArgList &Args, Index: lib/Driver/ToolChains/RISCVToolchain.h =================================================================== --- lib/Driver/ToolChains/RISCVToolchain.h +++ lib/Driver/ToolChains/RISCVToolchain.h @@ -33,6 +33,7 @@ llvm::opt::ArgStringList &CC1Args) const override; protected: + bool HasNativeLLVMSupport() const override { return true; } Tool *buildLinker() const override; private: Index: lib/Driver/ToolChains/RISCVToolchain.cpp =================================================================== --- lib/Driver/ToolChains/RISCVToolchain.cpp +++ lib/Driver/ToolChains/RISCVToolchain.cpp @@ -114,6 +114,13 @@ {options::OPT_T_Group, options::OPT_e, options::OPT_s, options::OPT_t, options::OPT_Z_Flag, options::OPT_r}); + if (D.isUsingLTO()) { + assert(!Inputs.empty() && "Must have at least one input."); + AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0], + D.getLTOMode() == LTOK_Thin); + + } + AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); // TODO: add C++ includes and libs if compiling C++. Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -849,6 +849,7 @@ Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss); Opts.NumRegisterParameters = getLastArgIntValue(Args, OPT_mregparm, 0, Diags); + Opts.SmallDataLimit = getLastArgIntValue(Args, OPT_msmall_data_limit, 0, Diags); Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack); Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings); Opts.EnableSegmentedStacks = Args.hasArg(OPT_split_stacks); Index: test/CodeGen/riscv-sdata-module-flag.c =================================================================== --- /dev/null +++ test/CodeGen/riscv-sdata-module-flag.c @@ -0,0 +1,31 @@ +// RUN: %clang -target riscv32-unknown-elf %s -S -emit-llvm -o - \ +// RUN: | FileCheck %s -check-prefix=RV32-DEFAULT +// RUN: %clang -target riscv32-unknown-elf %s -S -emit-llvm -G4 -o - \ +// RUN: | FileCheck %s -check-prefix=RV32-G4 +// RUN: %clang -target riscv32-unknown-elf %s -S -emit-llvm -msmall-data-limit=0 -o - \ +// RUN: | FileCheck %s -check-prefix=RV32-S0 +// RUN: %clang -target riscv32-unknown-elf %s -S -emit-llvm -fpic -o - \ +// RUN: | FileCheck %s -check-prefix=RV32-PIC + +// RUN: %clang -target riscv64-unknown-elf %s -S -emit-llvm -o - \ +// RUN: | FileCheck %s -check-prefix=RV64-DEFAULT +// RUN: %clang -target riscv64-unknown-elf %s -S -emit-llvm -G4 -o - \ +// RUN: | FileCheck %s -check-prefix=RV64-G4 +// RUN: %clang -target riscv64-unknown-elf %s -S -emit-llvm -msmall-data-limit=0 -o - \ +// RUN: | FileCheck %s -check-prefix=RV64-S0 +// RUN: %clang -target riscv64-unknown-elf %s -S -emit-llvm -fpic -o - \ +// RUN: | FileCheck %s -check-prefix=RV64-PIC +// RUN: %clang -target riscv64-unknown-elf %s -S -emit-llvm -mcmodel=large -o - \ +// RUN: | FileCheck %s -check-prefix=RV64-LARGE + + +// RV32-DEFAULT: !{i32 1, !"SmallDataLimit", i32 8} +// RV32-G4: !{i32 1, !"SmallDataLimit", i32 4} +// RV32-S0: !{i32 1, !"SmallDataLimit", i32 0} +// RV32-PIC: !{i32 1, !"SmallDataLimit", i32 0} + +// RV64-DEFAULT: !{i32 1, !"SmallDataLimit", i32 8} +// RV64-G4: !{i32 1, !"SmallDataLimit", i32 4} +// RV64-S0: !{i32 1, !"SmallDataLimit", i32 0} +// RV64-PIC: !{i32 1, !"SmallDataLimit", i32 0} +// RV64-LARGE: !{i32 1, !"SmallDataLimit", i32 0}