[flang] Add dependent-lib option to flang -fc1 on Windows (#72121)

This patch adds a --dependent-lib option to flang -fc1 on Windows to
embed library link options into the object file. This is needed to
properly select the Windows CRT to link against.
This commit is contained in:
David Truby
2023-11-15 15:26:43 +00:00
committed by GitHub
parent b6f51787f6
commit 77ecb9a49b
6 changed files with 71 additions and 3 deletions

View File

@@ -6796,9 +6796,6 @@ def vectorize_loops : Flag<["-"], "vectorize-loops">,
def vectorize_slp : Flag<["-"], "vectorize-slp">,
HelpText<"Run the SLP vectorization passes">,
MarshallingInfoFlag<CodeGenOpts<"VectorizeSLP">>;
def dependent_lib : Joined<["--"], "dependent-lib=">,
HelpText<"Add dependent library">,
MarshallingInfoStringVector<CodeGenOpts<"DependentLibraries">>;
def linker_option : Joined<["--"], "linker-option=">,
HelpText<"Add linker option">,
MarshallingInfoStringVector<CodeGenOpts<"LinkerOptions">>;
@@ -7369,6 +7366,11 @@ def pic_is_pie : Flag<["-"], "pic-is-pie">,
HelpText<"File is for a position independent executable">,
MarshallingInfoFlag<LangOpts<"PIE">>;
def dependent_lib : Joined<["--"], "dependent-lib=">,
HelpText<"Add dependent library">,
MarshallingInfoStringVector<CodeGenOpts<"DependentLibraries">>;
} // let Visibility = [CC1Option, FC1Option]
let Visibility = [CC1Option] in {

View File

@@ -70,6 +70,9 @@ public:
/// The format used for serializing remarks (default: YAML)
std::string OptRecordFormat;
/// Options to add to the linker for the object file
std::vector<std::string> DependentLibs;
// The RemarkKind enum class and OptRemark struct are identical to what Clang
// has
// TODO: Share with clang instead of re-implementing here

View File

@@ -1054,6 +1054,27 @@ static bool parseVScaleArgs(CompilerInvocation &invoc, llvm::opt::ArgList &args,
return true;
}
static bool parseLinkerOptionsArgs(CompilerInvocation &invoc,
llvm::opt::ArgList &args,
clang::DiagnosticsEngine &diags) {
llvm::Triple triple = llvm::Triple(invoc.getTargetOpts().triple);
// TODO: support --dependent-lib on other platforms when MLIR supports
// !llvm.dependent.lib
if (args.hasArg(clang::driver::options::OPT_dependent_lib) &&
!triple.isOSWindows()) {
const unsigned diagID =
diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
"--dependent-lib is only supported on Windows");
diags.Report(diagID);
return false;
}
invoc.getCodeGenOpts().DependentLibs =
args.getAllArgValues(clang::driver::options::OPT_dependent_lib);
return true;
}
bool CompilerInvocation::createFromArgs(
CompilerInvocation &res, llvm::ArrayRef<const char *> commandLineArgs,
clang::DiagnosticsEngine &diags, const char *argv0) {
@@ -1163,6 +1184,8 @@ bool CompilerInvocation::createFromArgs(
success &= parseVScaleArgs(res, args, diags);
success &= parseLinkerOptionsArgs(res, args, diags);
// Set the string to be used as the return value of the COMPILER_OPTIONS
// intrinsic of iso_fortran_env. This is either passed in from the parent
// compiler driver invocation with an environment variable, or failing that

View File

@@ -203,6 +203,26 @@ static void setMLIRDataLayout(mlir::ModuleOp &mlirModule,
mlirModule->setAttr(mlir::DLTIDialect::kDataLayoutAttrName, dlSpec);
}
static void addDepdendentLibs(mlir::ModuleOp &mlirModule,
CompilerInstance &ci) {
const std::vector<std::string> &libs =
ci.getInvocation().getCodeGenOpts().DependentLibs;
if (libs.empty()) {
return;
}
// dependent-lib is currently only supported on Windows, so the list should be
// empty on non-Windows platforms
assert(
llvm::Triple(ci.getInvocation().getTargetOpts().triple).isOSWindows() &&
"--dependent-lib is only supported on Windows");
// Add linker options specified by --dependent-lib
auto builder = mlir::OpBuilder(mlirModule.getRegion());
for (const std::string &lib : libs) {
builder.create<mlir::LLVM::LinkerOptionsOp>(
mlirModule.getLoc(), builder.getStrArrayAttr({"/DEFAULTLIB:", lib}));
}
}
bool CodeGenAction::beginSourceFileAction() {
llvmCtx = std::make_unique<llvm::LLVMContext>();
CompilerInstance &ci = this->getInstance();
@@ -304,6 +324,9 @@ bool CodeGenAction::beginSourceFileAction() {
Fortran::parser::Program &parseTree{*ci.getParsing().parseTree()};
lb.lower(parseTree, ci.getInvocation().getSemanticsContext());
// Add dependent libraries
addDepdendentLibs(*mlirModule, ci);
// run the default passes.
mlir::PassManager pm((*mlirModule)->getName(),
mlir::OpPassManager::Nesting::Implicit);

View File

@@ -0,0 +1,16 @@
! REQUIRES aarch64-registered-target && x86-registered-target
! DEFINE: %{triple} =
! DEFINE: %{compile} = %flang_fc1 -emit-mlir -triple %{triple} --dependent-lib=libtest %s -o - 2>&1
! REDEFINE: %{triple} = aarch64-pc-windows-msvc
! RUN: %{compile} | FileCheck %s
! REDEFINE: %{triple} = x86_64-pc-windows-msvc
! RUN: %{compile} | FileCheck %s
! REDEFINE: %{triple} = x86_64-linux-unknown-gnu
! RUN: not %{compile} | FileCheck %s --check-prefixes=CHECK-NOWIN
! REDEFINE: %{triple} = aarch64-apple-darwin
! RUN: not %{compile} | FileCheck %s --check-prefixes=CHECK-NOWIN
! CHECK: llvm.linker_options ["/DEFAULTLIB:", "libtest"]
program test
end program test
! CHECK-NOWIN: --dependent-lib is only supported on Windows

View File

@@ -141,6 +141,7 @@
! HELP-FC1-EMPTY:
! HELP-FC1-NEXT:OPTIONS:
! HELP-FC1-NEXT: -cpp Enable predefined and command line preprocessor macros
! HELP-FC1-NEXT: --dependent-lib=<value> Add dependent library
! HELP-FC1-NEXT: -D <macro>=<value> Define <macro> to <value> (or 1 if <value> omitted)
! HELP-FC1-NEXT: -emit-fir Build the parse tree, then lower it to FIR
! HELP-FC1-NEXT: -emit-hlfir Build the parse tree, then lower it to HLFIR