Skip to content

[lld][WebAssembly] Introduce Ctx::arg #119829

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

Merged
merged 1 commit into from
Dec 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions lld/wasm/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ enum class BuildIdKind { None, Fast, Sha1, Hexstring, Uuid };
// Most fields are direct mapping from the command line options
// and such fields have the same name as the corresponding options.
// Most fields are initialized by the driver.
struct Configuration {
struct Config {
bool allowMultipleDefinition;
bool bsymbolic;
bool checkFeatures;
Expand Down Expand Up @@ -126,11 +126,18 @@ struct Configuration {
llvm::SmallVector<uint8_t, 0> buildIdVector;
};

struct ConfigWrapper {
Config c;
Config *operator->() { return &c; }
};

// The only instance of Configuration struct.
extern Configuration *config;
extern ConfigWrapper config;

// The Ctx object hold all other (non-configuration) global state.
struct Ctx {
Config &arg;

llvm::SmallVector<ObjFile *, 0> objectFiles;
llvm::SmallVector<StubFile *, 0> stubFiles;
llvm::SmallVector<SharedFile *, 0> sharedFiles;
Expand All @@ -156,6 +163,7 @@ struct Ctx {
0>
whyExtractRecords;

Ctx();
void reset();
};

Expand Down
61 changes: 35 additions & 26 deletions lld/wasm/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ using namespace llvm::sys;
using namespace llvm::wasm;

namespace lld::wasm {
Configuration *config;
ConfigWrapper config;
Ctx ctx;

void errorOrWarn(const llvm::Twine &msg) {
Expand All @@ -54,7 +54,11 @@ void errorOrWarn(const llvm::Twine &msg) {
error(msg);
}

Ctx::Ctx() : arg(config.c) {}

void Ctx::reset() {
arg.~Config();
new (&arg) Config();
objectFiles.clear();
stubFiles.clear();
sharedFiles.clear();
Expand Down Expand Up @@ -92,13 +96,16 @@ static void initLLVM() {

class LinkerDriver {
public:
LinkerDriver(Ctx &);
void linkerMain(ArrayRef<const char *> argsArr);

private:
void createFiles(opt::InputArgList &args);
void addFile(StringRef path);
void addLibrary(StringRef name);

Ctx &ctx;

// True if we are in --whole-archive and --no-whole-archive.
bool inWholeArchive = false;

Expand All @@ -122,19 +129,19 @@ static bool hasZOption(opt::InputArgList &args, StringRef key) {
bool link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput) {
// This driver-specific context will be freed later by unsafeLldMain().
auto *ctx = new CommonLinkerContext;
auto *context = new CommonLinkerContext;

ctx->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput);
ctx->e.cleanupCallback = []() { wasm::ctx.reset(); };
ctx->e.logName = args::getFilenameWithoutExe(args[0]);
ctx->e.errorLimitExceededMsg = "too many errors emitted, stopping now (use "
"-error-limit=0 to see all errors)";
context->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput);
context->e.cleanupCallback = []() { ctx.reset(); };
context->e.logName = args::getFilenameWithoutExe(args[0]);
context->e.errorLimitExceededMsg =
"too many errors emitted, stopping now (use "
"-error-limit=0 to see all errors)";

config = make<Configuration>();
symtab = make<SymbolTable>();

initLLVM();
LinkerDriver().linkerMain(args);
LinkerDriver(ctx).linkerMain(args);

return errorCount() == 0;
}
Expand Down Expand Up @@ -1256,6 +1263,8 @@ static void checkZOptions(opt::InputArgList &args) {
warn("unknown -z value: " + StringRef(arg->getValue()));
}

LinkerDriver::LinkerDriver(Ctx &ctx) : ctx(ctx) {}

void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
WasmOptTable parser;
opt::InputArgList args = parser.parse(argsArr.slice(1));
Expand Down Expand Up @@ -1324,10 +1333,10 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
// Fail early if the output file or map file is not writable. If a user has a
// long link, e.g. due to a large LTO link, they do not wish to run it and
// find that it failed because there was a mistake in their command-line.
if (auto e = tryCreateFile(config->outputFile))
error("cannot open output file " + config->outputFile + ": " + e.message());
if (auto e = tryCreateFile(config->mapFile))
error("cannot open map file " + config->mapFile + ": " + e.message());
if (auto e = tryCreateFile(ctx.arg.outputFile))
error("cannot open output file " + ctx.arg.outputFile + ": " + e.message());
if (auto e = tryCreateFile(ctx.arg.mapFile))
error("cannot open map file " + ctx.arg.mapFile + ": " + e.message());
if (errorCount())
return;

Expand All @@ -1336,11 +1345,11 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
symtab->trace(arg->getValue());

for (auto *arg : args.filtered(OPT_export_if_defined))
config->exportedSymbols.insert(arg->getValue());
ctx.arg.exportedSymbols.insert(arg->getValue());

for (auto *arg : args.filtered(OPT_export)) {
config->exportedSymbols.insert(arg->getValue());
config->requiredExports.push_back(arg->getValue());
ctx.arg.exportedSymbols.insert(arg->getValue());
ctx.arg.requiredExports.push_back(arg->getValue());
}

createSyntheticSymbols();
Expand All @@ -1358,28 +1367,28 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {

// Handle the `--export <sym>` options
// This works like --undefined but also exports the symbol if its found
for (auto &iter : config->exportedSymbols)
for (auto &iter : ctx.arg.exportedSymbols)
handleUndefined(iter.first(), "--export");

Symbol *entrySym = nullptr;
if (!config->relocatable && !config->entry.empty()) {
entrySym = handleUndefined(config->entry, "--entry");
if (!ctx.arg.relocatable && !ctx.arg.entry.empty()) {
entrySym = handleUndefined(ctx.arg.entry, "--entry");
if (entrySym && entrySym->isDefined())
entrySym->forceExport = true;
else
error("entry symbol not defined (pass --no-entry to suppress): " +
config->entry);
ctx.arg.entry);
}

// If the user code defines a `__wasm_call_dtors` function, remember it so
// that we can call it from the command export wrappers. Unlike
// `__wasm_call_ctors` which we synthesize, `__wasm_call_dtors` is defined
// by libc/etc., because destructors are registered dynamically with
// `__cxa_atexit` and friends.
if (!config->relocatable && !config->shared &&
if (!ctx.arg.relocatable && !ctx.arg.shared &&
!WasmSym::callCtors->isUsedInRegularObj &&
WasmSym::callCtors->getName() != config->entry &&
!config->exportedSymbols.count(WasmSym::callCtors->getName())) {
WasmSym::callCtors->getName() != ctx.arg.entry &&
!ctx.arg.exportedSymbols.count(WasmSym::callCtors->getName())) {
if (Symbol *callDtors =
handleUndefined("__wasm_call_dtors", "<internal>")) {
if (auto *callDtorsFunc = dyn_cast<DefinedFunction>(callDtors)) {
Expand Down Expand Up @@ -1437,7 +1446,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
writeWhyExtract();

// Bail out if normal linked output is skipped due to LTO.
if (config->thinLTOIndexOnly)
if (ctx.arg.thinLTOIndexOnly)
return;

createOptionalSymbols();
Expand All @@ -1452,13 +1461,13 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
if (!wrapped.empty())
wrapSymbols(wrapped);

for (auto &iter : config->exportedSymbols) {
for (auto &iter : ctx.arg.exportedSymbols) {
Symbol *sym = symtab->find(iter.first());
if (sym && sym->isDefined())
sym->forceExport = true;
}

if (!config->relocatable && !ctx.isPic) {
if (!ctx.arg.relocatable && !ctx.isPic) {
// Add synthetic dummies for weak undefined functions. Must happen
// after LTO otherwise functions may not yet have signatures.
symtab->handleWeakUndefines();
Expand Down
Loading