-
Notifications
You must be signed in to change notification settings - Fork 10.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[flang] Generate main only when a Fortran program statement is present #89938
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1191,118 +1191,10 @@ bool tools::addOpenMPRuntime(const Compilation &C, ArgStringList &CmdArgs, | |
return true; | ||
} | ||
|
||
/// Determines if --whole-archive is active in the list of arguments. | ||
static bool isWholeArchivePresent(const ArgList &Args) { | ||
bool WholeArchiveActive = false; | ||
for (auto *Arg : Args.filtered(options::OPT_Wl_COMMA)) { | ||
if (Arg) { | ||
for (StringRef ArgValue : Arg->getValues()) { | ||
if (ArgValue == "--whole-archive") | ||
WholeArchiveActive = true; | ||
if (ArgValue == "--no-whole-archive") | ||
WholeArchiveActive = false; | ||
} | ||
} | ||
} | ||
|
||
return WholeArchiveActive; | ||
} | ||
|
||
/// Determine if driver is invoked to create a shared object library (-static) | ||
static bool isSharedLinkage(const ArgList &Args) { | ||
return Args.hasArg(options::OPT_shared); | ||
} | ||
|
||
/// Determine if driver is invoked to create a static object library (-shared) | ||
static bool isStaticLinkage(const ArgList &Args) { | ||
return Args.hasArg(options::OPT_static); | ||
} | ||
|
||
/// Add Fortran runtime libs for MSVC | ||
static void addFortranRuntimeLibsMSVC(const ArgList &Args, | ||
llvm::opt::ArgStringList &CmdArgs) { | ||
unsigned RTOptionID = options::OPT__SLASH_MT; | ||
if (auto *rtl = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) { | ||
RTOptionID = llvm::StringSwitch<unsigned>(rtl->getValue()) | ||
.Case("static", options::OPT__SLASH_MT) | ||
.Case("static_dbg", options::OPT__SLASH_MTd) | ||
.Case("dll", options::OPT__SLASH_MD) | ||
.Case("dll_dbg", options::OPT__SLASH_MDd) | ||
.Default(options::OPT__SLASH_MT); | ||
} | ||
switch (RTOptionID) { | ||
case options::OPT__SLASH_MT: | ||
CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static.lib"); | ||
break; | ||
case options::OPT__SLASH_MTd: | ||
CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static_dbg.lib"); | ||
break; | ||
case options::OPT__SLASH_MD: | ||
CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic.lib"); | ||
break; | ||
case options::OPT__SLASH_MDd: | ||
CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic_dbg.lib"); | ||
break; | ||
} | ||
} | ||
|
||
// Add FortranMain runtime lib | ||
static void addFortranMain(const ToolChain &TC, const ArgList &Args, | ||
llvm::opt::ArgStringList &CmdArgs) { | ||
// 0. Shared-library linkage | ||
// If we are attempting to link a library, we should not add | ||
// -lFortran_main.a to the link line, as the `main` symbol is not | ||
// required for a library and should also be provided by one of | ||
// the translation units of the code that this shared library | ||
// will be linked against eventually. | ||
if (isSharedLinkage(Args) || isStaticLinkage(Args)) { | ||
return; | ||
} | ||
|
||
// 1. MSVC | ||
if (TC.getTriple().isKnownWindowsMSVCEnvironment()) { | ||
addFortranRuntimeLibsMSVC(Args, CmdArgs); | ||
return; | ||
} | ||
|
||
// 2. GNU and similar | ||
const Driver &D = TC.getDriver(); | ||
const char *FortranMainLinkFlag = "-lFortran_main"; | ||
|
||
// Warn if the user added `-lFortran_main` - this library is an implementation | ||
// detail of Flang and should be handled automaticaly by the driver. | ||
for (const char *arg : CmdArgs) { | ||
if (strncmp(arg, FortranMainLinkFlag, strlen(FortranMainLinkFlag)) == 0) | ||
D.Diag(diag::warn_drv_deprecated_custom) | ||
<< FortranMainLinkFlag | ||
<< "see the Flang driver documentation for correct usage"; | ||
} | ||
Comment on lines
-1272
to
-1279
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removing the Fortran_main library could also break existing builds, but I think it is more reasonable because it was deprecated since the last release. |
||
|
||
// The --whole-archive option needs to be part of the link line to make | ||
// sure that the main() function from Fortran_main.a is pulled in by the | ||
// linker. However, it shouldn't be used if it's already active. | ||
// TODO: Find an equivalent of `--whole-archive` for Darwin and AIX. | ||
if (!isWholeArchivePresent(Args) && !TC.getTriple().isMacOSX() && | ||
!TC.getTriple().isOSAIX()) { | ||
CmdArgs.push_back("--whole-archive"); | ||
CmdArgs.push_back(FortranMainLinkFlag); | ||
CmdArgs.push_back("--no-whole-archive"); | ||
return; | ||
} | ||
|
||
CmdArgs.push_back(FortranMainLinkFlag); | ||
} | ||
|
||
/// Add Fortran runtime libs | ||
void tools::addFortranRuntimeLibs(const ToolChain &TC, const ArgList &Args, | ||
llvm::opt::ArgStringList &CmdArgs) { | ||
// 1. Link FortranMain | ||
// FortranMain depends on FortranRuntime, so needs to be listed first. If | ||
// -fno-fortran-main has been passed, skip linking Fortran_main.a | ||
if (!Args.hasArg(options::OPT_no_fortran_main)) | ||
addFortranMain(TC, Args, CmdArgs); | ||
|
||
// 2. Link FortranRuntime and FortranDecimal | ||
// Link FortranRuntime and FortranDecimal | ||
// These are handled earlier on Windows by telling the frontend driver to | ||
// add the correct libraries to link against as dependents in the object | ||
// file. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
//===-- Main.h - generate main runtime API calls ----------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef FORTRAN_OPTIMIZER_BUILDER_RUNTIME_MAIN_H | ||
#define FORTRAN_OPTIMIZER_BUILDER_RUNTIME_MAIN_H | ||
|
||
namespace mlir { | ||
class Location; | ||
} // namespace mlir | ||
|
||
namespace fir { | ||
class FirOpBuilder; | ||
class GlobalOp; | ||
} // namespace fir | ||
|
||
namespace fir::runtime { | ||
|
||
void genMain(fir::FirOpBuilder &builder, mlir::Location loc, | ||
fir::GlobalOp &env); | ||
|
||
} | ||
|
||
#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_MAIN_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ add_flang_library(FIRBuilder | |
Runtime/Execute.cpp | ||
Runtime/Inquiry.cpp | ||
Runtime/Intrinsics.cpp | ||
Runtime/Main.cpp | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this list is in alphabetical order? |
||
Runtime/Numeric.cpp | ||
Runtime/Pointer.cpp | ||
Runtime/Ragged.cpp | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
//===-- Main.cpp - generate main runtime API calls --------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "flang/Optimizer/Builder/Runtime/Main.h" | ||
#include "flang/Optimizer/Builder/BoxValue.h" | ||
#include "flang/Optimizer/Builder/FIRBuilder.h" | ||
#include "flang/Optimizer/Builder/Runtime/RTBuilder.h" | ||
#include "flang/Optimizer/Dialect/FIROps.h" | ||
#include "flang/Optimizer/Dialect/FIRType.h" | ||
#include "flang/Runtime/main.h" | ||
#include "flang/Runtime/stop.h" | ||
|
||
using namespace Fortran::runtime; | ||
|
||
/// Create a `int main(...)` that calls the Fortran entry point | ||
void fir::runtime::genMain(fir::FirOpBuilder &builder, mlir::Location loc, | ||
fir::GlobalOp &env) { | ||
auto *context = builder.getContext(); | ||
auto argcTy = builder.getDefaultIntegerType(); | ||
auto ptrTy = mlir::LLVM::LLVMPointerType::get(context); | ||
|
||
// void ProgramStart(int argc, char** argv, char** envp, | ||
// _QQEnvironmentDefaults* env) | ||
auto startFn = builder.createFunction( | ||
loc, RTNAME_STRING(ProgramStart), | ||
mlir::FunctionType::get(context, {argcTy, ptrTy, ptrTy, ptrTy}, {})); | ||
// void ProgramStop() | ||
auto stopFn = | ||
builder.createFunction(loc, RTNAME_STRING(ProgramEndStatement), | ||
mlir::FunctionType::get(context, {}, {})); | ||
|
||
// int main(int argc, char** argv, char** envp) | ||
auto mainFn = builder.createFunction( | ||
loc, "main", | ||
mlir::FunctionType::get(context, {argcTy, ptrTy, ptrTy}, argcTy)); | ||
// void _QQmain() | ||
auto qqMainFn = builder.createFunction( | ||
loc, "_QQmain", mlir::FunctionType::get(context, {}, {})); | ||
|
||
mainFn.setPublic(); | ||
|
||
auto *block = mainFn.addEntryBlock(); | ||
mlir::OpBuilder::InsertionGuard insertGuard(builder); | ||
builder.setInsertionPointToStart(block); | ||
|
||
llvm::SmallVector<mlir::Value, 4> args(block->getArguments()); | ||
auto envAddr = | ||
builder.create<fir::AddrOfOp>(loc, env.getType(), env.getSymbol()); | ||
args.push_back(envAddr); | ||
|
||
builder.create<fir::CallOp>(loc, startFn, args); | ||
builder.create<fir::CallOp>(loc, qqMainFn); | ||
builder.create<fir::CallOp>(loc, stopFn); | ||
|
||
mlir::Value ret = builder.createIntegerConstant(loc, argcTy, 0); | ||
builder.create<mlir::func::ReturnOp>(loc, ret); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this break existing build systems configured to use this flag?