Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -5276,11 +5276,6 @@ "Note this may change .s semantics and shouldn't generally be used " "on compiler-generated code.">, MarshallingInfoFlag>; -def mrelocation_model : Separate<["-"], "mrelocation-model">, - HelpText<"The relocation model to use">, Values<"static,pic,ropi,rwpi,ropi-rwpi,dynamic-no-pic">, - NormalizedValuesScope<"llvm::Reloc">, - NormalizedValues<["Static", "PIC_", "ROPI", "RWPI", "ROPI_RWPI", "DynamicNoPIC"]>, - MarshallingInfoEnum, "PIC_">; def fno_math_builtin : Flag<["-"], "fno-math-builtin">, HelpText<"Disable implicit builtin knowledge of math functions">, MarshallingInfoFlag>; @@ -5956,6 +5951,13 @@ Flags<[CC1Option, CC1AsOption, FC1Option, NoDriverOption]>, MarshallingInfoFlag>; +def mrelocation_model : Separate<["-"], "mrelocation-model">, + HelpText<"The relocation model to use">, Values<"static,pic,ropi,rwpi,ropi-rwpi,dynamic-no-pic">, + Flags<[CC1Option, CC1AsOption, FC1Option, NoDriverOption]>, + NormalizedValuesScope<"llvm::Reloc">, + NormalizedValues<["Static", "PIC_", "ROPI", "RWPI", "ROPI_RWPI", "DynamicNoPIC"]>, + MarshallingInfoEnum, "PIC_">; + def main_file_name : Separate<["-"], "main-file-name">, HelpText<"Main file name to use for debug info and source if missing">, Flags<[CC1Option, CC1AsOption, NoDriverOption]>, @@ -6005,12 +6007,6 @@ def function_alignment : Separate<["-"], "function-alignment">, HelpText<"default alignment for functions">, MarshallingInfoInt>; -def pic_level : Separate<["-"], "pic-level">, - HelpText<"Value for __PIC__">, - MarshallingInfoInt>; -def pic_is_pie : Flag<["-"], "pic-is-pie">, - HelpText<"File is for a position independent executable">, - MarshallingInfoFlag>; def fhalf_no_semantic_interposition : Flag<["-"], "fhalf-no-semantic-interposition">, HelpText<"Like -fno-semantic-interposition but don't use local aliases">, MarshallingInfoFlag>; @@ -6321,6 +6317,12 @@ CodeGenOpts<"DebugPassManager">, DefaultFalse, PosFlag, NegFlag>; +def pic_level : Separate<["-"], "pic-level">, + HelpText<"Value for __PIC__">, + MarshallingInfoInt>; +def pic_is_pie : Flag<["-"], "pic-is-pie">, + HelpText<"File is for a position independent executable">, + MarshallingInfoFlag>; } // let Flags = [CC1Option, FC1Option, NoDriverOption] Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -1152,23 +1152,6 @@ } } -static const char *RelocationModelName(llvm::Reloc::Model Model) { - switch (Model) { - case llvm::Reloc::Static: - return "static"; - case llvm::Reloc::PIC_: - return "pic"; - case llvm::Reloc::DynamicNoPIC: - return "dynamic-no-pic"; - case llvm::Reloc::ROPI: - return "ropi"; - case llvm::Reloc::RWPI: - return "rwpi"; - case llvm::Reloc::ROPI_RWPI: - return "ropi-rwpi"; - } - llvm_unreachable("Unknown Reloc::Model kind"); -} static void handleAMDGPUCodeObjectVersionOptions(const Driver &D, const ArgList &Args, ArgStringList &CmdArgs, Index: clang/lib/Driver/ToolChains/CommonArgs.h =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.h +++ clang/lib/Driver/ToolChains/CommonArgs.h @@ -93,6 +93,8 @@ llvm::opt::ArgStringList &CmdArgs, const InputInfo &Output, const InputInfo &Input, bool IsThinLTO); +const char *RelocationModelName(llvm::Reloc::Model Model); + std::tuple ParsePICArgs(const ToolChain &ToolChain, const llvm::opt::ArgList &Args); Index: clang/lib/Driver/ToolChains/CommonArgs.cpp =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.cpp +++ clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1200,6 +1200,24 @@ options::OPT_fauto_profile_EQ); } +const char *tools::RelocationModelName(llvm::Reloc::Model Model) { + switch (Model) { + case llvm::Reloc::Static: + return "static"; + case llvm::Reloc::PIC_: + return "pic"; + case llvm::Reloc::DynamicNoPIC: + return "dynamic-no-pic"; + case llvm::Reloc::ROPI: + return "ropi"; + case llvm::Reloc::RWPI: + return "rwpi"; + case llvm::Reloc::ROPI_RWPI: + return "ropi-rwpi"; + } + llvm_unreachable("Unknown Reloc::Model kind"); +} + /// Parses the various -fpic/-fPIC/-fpie/-fPIE arguments. Then, /// smooshes them together with platform defaults, to decide whether /// this compile should be using PIC mode or not. Returns a tuple of Index: clang/lib/Driver/ToolChains/Flang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Flang.cpp +++ clang/lib/Driver/ToolChains/Flang.cpp @@ -117,6 +117,23 @@ if (D.getDiags().getDiagnosticOptions().ShowColors) CmdArgs.push_back("-fcolor-diagnostics"); + // -fPIC/-fPIE and their variants. Similar to clang. + llvm::Reloc::Model RelocationModel; + unsigned PICLevel; + bool IsPIE; + std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(TC, Args); + + if (auto *RMName = RelocationModelName(RelocationModel)) { + CmdArgs.push_back("-mrelocation-model"); + CmdArgs.push_back(RMName); + } + if (PICLevel > 0) { + CmdArgs.push_back("-pic-level"); + CmdArgs.push_back(PICLevel == 1 ? "1" : "2"); + if (IsPIE) + CmdArgs.push_back("-pic-is-pie"); + } + // Add other compile options AddOtherOptions(Args, CmdArgs); Index: clang/lib/Driver/ToolChains/Linux.cpp =================================================================== --- clang/lib/Driver/ToolChains/Linux.cpp +++ clang/lib/Driver/ToolChains/Linux.cpp @@ -699,11 +699,8 @@ } bool Linux::isPIEDefault(const llvm::opt::ArgList &Args) const { - // TODO: Remove the special treatment for Flang once its frontend driver can - // generate position independent code. - return !getDriver().IsFlangMode() && - (CLANG_DEFAULT_PIE_ON_LINUX || getTriple().isAndroid() || - getTriple().isMusl() || getSanitizerArgs(Args).requiresPIE()); + return CLANG_DEFAULT_PIE_ON_LINUX || getTriple().isAndroid() || + getTriple().isMusl() || getSanitizerArgs(Args).requiresPIE(); } bool Linux::IsAArch64OutlineAtomicsDefault(const ArgList &Args) const { Index: flang/include/flang/Frontend/FrontendOptions.h =================================================================== --- flang/include/flang/Frontend/FrontendOptions.h +++ flang/include/flang/Frontend/FrontendOptions.h @@ -17,6 +17,7 @@ #include "flang/Parser/characters.h" #include "flang/Parser/unparse.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/CodeGen.h" #include "llvm/Support/MemoryBuffer.h" #include #include @@ -286,6 +287,13 @@ /// should only be used for debugging and experimental features. std::vector mlirArgs; + /// Some targets need the pic levels. These are stored as + /// LLVM module flags. + llvm::Optional PICLevel; + llvm::Optional PIELevel; + /// For setting up the target machine. + llvm::Optional RelocModel; + // Return the appropriate input kind for a file extension. For example, /// "*.f" would return Language::Fortran. /// Index: flang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- flang/lib/Frontend/CompilerInvocation.cpp +++ flang/lib/Frontend/CompilerInvocation.cpp @@ -147,6 +147,22 @@ opts.needProvenanceRangeToCharBlockMappings = true; } +static llvm::Reloc::Model getRelocationFromName(llvm::StringRef model) { + if (model.equals("static")) + return llvm::Reloc::Static; + if (model.equals("pic")) + return llvm::Reloc::PIC_; + if (model.equals("dynamic-no-pic")) + return llvm::Reloc::DynamicNoPIC; + if (model.equals("ropi")) + return llvm::Reloc::ROPI; + if (model.equals("rwpi")) + return llvm::Reloc::RWPI; + if (model.equals("ropi-rwpi")) + return llvm::Reloc::ROPI_RWPI; + llvm_unreachable("Unknown relocation model."); +} + static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args, clang::DiagnosticsEngine &diags) { unsigned numErrorsBefore = diags.getNumErrors(); @@ -271,6 +287,19 @@ } } + // Parse the PIC related -pic-level/-pic-is-pie/-mrelocation-model options. + if (int PICLevel = getLastArgIntValue( + args, clang::driver::options::OPT_pic_level, 0, diags)) { + opts.PICLevel = static_cast(PICLevel); + if (args.hasArg(clang::driver::options::OPT_pic_is_pie)) + opts.PIELevel = static_cast(PICLevel); + } + if (args.hasArg(clang::driver::options::OPT_mrelocation_model)) { + llvm::StringRef model = + args.getLastArgValue(clang::driver::options::OPT_mrelocation_model); + opts.RelocModel = getRelocationFromName(model); + } + // Parsing -load option and storing shared object path if (llvm::opt::Arg *a = args.getLastArg(clang::driver::options::OPT_load)) { opts.plugins.push_back(a->getValue()); Index: flang/lib/Frontend/FrontendActions.cpp =================================================================== --- flang/lib/Frontend/FrontendActions.cpp +++ flang/lib/Frontend/FrontendActions.cpp @@ -528,6 +528,12 @@ llvmModule = mlir::translateModuleToLLVMIR( *mlirModule, *llvmCtx, moduleName ? *moduleName : "FIRModule"); + // Set PIC/PIE level LLVM module flags. + if (auto PICLevel = ci.getInvocation().getFrontendOpts().PICLevel) + llvmModule->setPICLevel(*PICLevel); + if (auto PIELevel = ci.getInvocation().getFrontendOpts().PIELevel) + llvmModule->setPIELevel(*PIELevel); + if (!llvmModule) { unsigned diagID = ci.getDiagnostics().getCustomDiagID( clang::DiagnosticsEngine::Error, "failed to create the LLVM module"); @@ -574,7 +580,8 @@ getCGOptLevel(ci.getInvocation().getCodeGenOpts()); tm.reset(theTarget->createTargetMachine( theTriple, /*CPU=*/"", - /*Features=*/"", llvm::TargetOptions(), /*Reloc::Model=*/llvm::None, + /*Features=*/"", llvm::TargetOptions(), + /*Reloc::Model=*/ci.getInvocation().getFrontendOpts().RelocModel, /*CodeModel::Model=*/llvm::None, OptLevel)); assert(tm && "Failed to create TargetMachine"); } Index: flang/test/Driver/driver-help.f90 =================================================================== --- flang/test/Driver/driver-help.f90 +++ flang/test/Driver/driver-help.f90 @@ -128,9 +128,13 @@ ! HELP-FC1-NEXT: -mmlir Additional arguments to forward to MLIR's option processing ! HELP-FC1-NEXT: -module-dir Put MODULE files in ! HELP-FC1-NEXT: -module-suffix Use as the suffix for module files (the default value is `.mod`) +! HELP-FC1-NEXT: -mrelocation-model +! HELP-FC1-NEXT: The relocation model to use ! HELP-FC1-NEXT: -nocpp Disable predefined and command line preprocessor macros ! HELP-FC1-NEXT: -o Write output to ! HELP-FC1-NEXT: -pedantic Warn on language extensions +! HELP-FC1-NEXT: -pic-is-pie File is for a position independent executable +! HELP-FC1-NEXT: -pic-level Value for __PIC__ ! HELP-FC1-NEXT: -plugin Use the named plugin action instead of the default action (use "help" to list available options) ! HELP-FC1-NEXT: -P Disable linemarker output in -E mode ! HELP-FC1-NEXT: -std= Language standard to compile for Index: flang/test/Driver/pic-flags.f90 =================================================================== --- flang/test/Driver/pic-flags.f90 +++ flang/test/Driver/pic-flags.f90 @@ -1,18 +1,36 @@ ! Verify that in contrast to Clang, Flang does not default to generating position independent executables/code -! RUN: %flang -### %s --target=aarch64-linux-gnu 2>&1 | FileCheck %s --check-prefix=CHECK-NOPIE -! RUN: %flang -### %s --target=aarch64-linux-gnu -fno-pie 2>&1 | FileCheck %s --check-prefix=CHECK-NOPIE - -! RUN: %flang -### %s --target=aarch64-linux-gnu -fpie 2>&1 | FileCheck %s --check-prefix=CHECK-PIE - -! CHECK-NOPIE: "-fc1" -! CHECk-NOPIE-NOT: "-fpic" -! CHECK-NOPIE: "{{.*}}ld" -! CHECK-NOPIE-NOT: "-pie" - -! CHECK-PIE: "-fc1" -!! TODO Once Flang supports `-fpie`, it //should// use -fpic when invoking `flang -fc1`. Update the following line once `-fpie` is -! available. -! CHECk-PIE-NOT: "-fpic" -! CHECK-PIE: "{{.*}}ld" -! CHECK-PIE-NOT: "-pie" +! RUN: %flang -v -S -emit-llvm -o - %s --target=aarch64-linux-gnu -fno-pie 2>&1 | FileCheck %s --check-prefix=CHECK-NOPIE + +! RUN: %flang -v -S -emit-llvm -o - %s --target=aarch64-linux-gnu 2>&1 | FileCheck %s --check-prefixes=CHECK-PIC,CHECK-PIE-LEVEL2 +! RUN: %flang -v -S -emit-llvm -o - %s --target=aarch64-linux-gnu -fpie 2>&1 | FileCheck %s --check-prefixes=CHECK-PIC,CHECK-PIE-LEVEL1 +! RUN: %flang -v -S -emit-llvm -o - %s --target=aarch64-linux-gnu -fPIE 2>&1 | FileCheck %s --check-prefixes=CHECK-PIC,CHECK-PIE-LEVEL2 + +! RUN: %flang -v -S -emit-llvm -o - %s --target=aarch64-linux-gnu -fpic 2>&1 | FileCheck %s --check-prefixes=CHECK-PIC,CHECK-PIC-LEVEL1 +! RUN: %flang -v -S -emit-llvm -o - %s --target=aarch64-linux-gnu -fPIC 2>&1 | FileCheck %s --check-prefixes=CHECK-PIC,CHECK-PIC-LEVEL2 + +! CHECK-NOPIE: -fc1 +! CHECK-NOPIE: -mrelocation-model static +! CHECK-NOPIE-NOT: pic-level + +! CHECK-PIC: -fc1 + +! CHECK-PIC-LEVEL1: -mrelocation-model pic -pic-level 1 +! CHECK-PIC-LEVEL1-NOT: -pic-is-pie +! CHECK-PIC-LEVEL1-NOT: "PIE Level" +! CHECK-PIC-LEVEL1: !"PIC Level", i32 1} +! CHECK-PIC-LEVEL1-NOT: "PIE Level" + +! CHECK-PIC-LEVEL2: -mrelocation-model pic -pic-level 2 +! CHECK-PIC-LEVEL2-NOT: -pic-is-pie +! CHECK-PIC-LEVEL1-NOT: "PIE Level" +! CHECK-PIC-LEVEL2: !"PIC Level", i32 2} +! CHECK-PIC-LEVEL1-NOT: "PIE Level" + +! CHECK-PIE-LEVEL1: -mrelocation-model pic -pic-level 1 -pic-is-pie +! CHECK-PIE-LEVEL1: !"PIC Level", i32 1} +! CHECK-PIE-LEVEL1: !"PIE Level", i32 1} +! CHECK-PIE-LEVEL2: -mrelocation-model pic -pic-level 2 -pic-is-pie +! CHECK-PIE-LEVEL2: !"PIC Level", i32 2} +! CHECK-PIE-LEVEL2: !"PIE Level", i32 2} +