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/Basic/DiagnosticDriverKinds.td =================================================================== --- include/clang/Basic/DiagnosticDriverKinds.td +++ include/clang/Basic/DiagnosticDriverKinds.td @@ -350,6 +350,12 @@ "ignoring '-mgpopt' option as it cannot be used with %select{|the implicit" " usage of }0-mabicalls">, InGroup; +def warn_drv_unsupported_g : Warning< + "ignoring '-G' option as -msmall-data-limit= in the command line">, + InGroup; +def warn_drv_unsupported_sdata : Warning< + "ignoring '-msmall-data-limit=' for -fpic or RV64 with -mcmodel=large">, + InGroup; def warn_drv_unsupported_longcalls : Warning< "ignoring '-mlong-calls' option as it is not currently supported with " "%select{|the implicit usage of }0-mabicalls">, 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, + 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 @@ -1784,6 +1784,7 @@ void Clang::AddRISCVTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { + const Driver &D = getToolChain().getDriver(); // FIXME: currently defaults to the soft-float ABIs. Will need to be // expanded to select ilp32f, ilp32d, lp64f, lp64d when appropriate. const char *ABIName = nullptr; @@ -1799,6 +1800,37 @@ CmdArgs.push_back("-target-abi"); CmdArgs.push_back(ABIName); + + // Default small data limitation is eight. + const char *SmallDataLimit = "8"; + // Get small data limitation. + if (Args.getLastArg(options::OPT_shared, options::OPT_fpic, + options::OPT_fPIC)) { + // Not support linker relaxation for PIC. + SmallDataLimit = "0"; + if (Args.hasArg(options::OPT_msmall_data_limit_EQ)) { + D.Diag(diag::warn_drv_unsupported_sdata); + } + } else if (Args.getLastArgValue(options::OPT_mcmodel_EQ) + .equals_lower("large") && + (Triple.getArch() == llvm::Triple::riscv64)) { + // Not support linker relaxation for RV64 with large code model. + SmallDataLimit = "0"; + if (Args.hasArg(options::OPT_msmall_data_limit_EQ)) { + D.Diag(diag::warn_drv_unsupported_sdata); + } + } else if (Arg *A = Args.getLastArg(options::OPT_msmall_data_limit_EQ)) { + SmallDataLimit = A->getValue(); + // Ignore -G because -msmall-data-limit= has higher priority. + if (Args.hasArg(options::OPT_G)) { + D.Diag(diag::warn_drv_unsupported_g); + } + } else if (Arg *A = Args.getLastArg(options::OPT_G)) { + SmallDataLimit = A->getValue(); + } + // Forward the -msmall-data-limit= option. + CmdArgs.push_back("-msmall-data-limit"); + CmdArgs.push_back(SmallDataLimit); } void Clang::AddSparcTargetArgs(const ArgList &Args, 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} Index: test/Driver/riscv-G-warning.c =================================================================== --- /dev/null +++ test/Driver/riscv-G-warning.c @@ -0,0 +1,4 @@ +// REQUIRES: riscv-registered-target +// RUN: %clang -S -target riscv32-unknown-elf -G4 -msmall-data-limit=8 %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-G %s +// CHECK-G: warning: ignoring '-G' option as -msmall-data-limit= in the command line Index: test/Driver/riscv-sdata-warning.c =================================================================== --- /dev/null +++ test/Driver/riscv-sdata-warning.c @@ -0,0 +1,8 @@ +// REQUIRES: riscv-registered-target +// RUN: %clang -S -target riscv32-unknown-elf -fpic -msmall-data-limit=8 %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-PIC-SDATA %s +// CHECK-PIC-SDATA: warning: ignoring '-msmall-data-limit=' for -fpic or RV64 with -mcmodel=large + +// RUN: %clang -S -target riscv64-unknown-elf -mcmodel=large -msmall-data-limit=8 %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-RV64-LARGE-SDATA %s +// CHECK-RV64-LARGE-SDATA: warning: ignoring '-msmall-data-limit=' for -fpic or RV64 with -mcmodel=large