Files
clang-p2996/clang/lib/Interpreter/Wasm.cpp
Anutosh Bhat 752dbd6112 [clang-repl] Improve flags responsible for generating shared wasm binaries (#116735)
There are a couple changes in this PR that help getting clang-repl to
run in the browser. Using a jupyterlite instance for the example pasted
below

1) Updating flags responsible for generating shared wasm binaries that
need to be dynamically loaded Most Importantly as can be seen in the
changes `shared` and `allow-undefined` are crucial.



![image](https://github.com/user-attachments/assets/1183fd44-8951-496a-899a-e4af39a48447)

2) While exiting we encounter this.



![image](https://github.com/user-attachments/assets/9487a3f4-7200-471d-ba88-09e98ccbc47a)


Now as can be seen here 


cd418030de/clang/lib/Interpreter/Interpreter.cpp (L421-L430)

We call cleanUP in the destructor. Now cleanUP through
IncrementalExecutor tries to deinitialize the JIT which wasn't even
intialized as runCtors in wasm.cpp is a no-op


cd418030de/clang/lib/Interpreter/IncrementalExecutor.cpp (L94-L101)


cd418030de/clang/lib/Interpreter/Wasm.cpp (L107-L109)
2024-11-19 09:07:40 +01:00

121 lines
4.3 KiB
C++

//===----------------- Wasm.cpp - Wasm Interpreter --------------*- 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
//
//===----------------------------------------------------------------------===//
//
// This file implements interpreter support for code execution in WebAssembly.
//
//===----------------------------------------------------------------------===//
#include "Wasm.h"
#include "IncrementalExecutor.h"
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/IR/Module.h>
#include <llvm/MC/TargetRegistry.h>
#include <llvm/Target/TargetMachine.h>
#include <clang/Interpreter/Interpreter.h>
#include <string>
namespace lld {
namespace wasm {
bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
} // namespace wasm
} // namespace lld
#include <dlfcn.h>
namespace clang {
WasmIncrementalExecutor::WasmIncrementalExecutor(
llvm::orc::ThreadSafeContext &TSC)
: IncrementalExecutor(TSC) {}
llvm::Error WasmIncrementalExecutor::addModule(PartialTranslationUnit &PTU) {
std::string ErrorString;
const llvm::Target *Target = llvm::TargetRegistry::lookupTarget(
PTU.TheModule->getTargetTriple(), ErrorString);
if (!Target) {
return llvm::make_error<llvm::StringError>("Failed to create Wasm Target: ",
llvm::inconvertibleErrorCode());
}
llvm::TargetOptions TO = llvm::TargetOptions();
llvm::TargetMachine *TargetMachine = Target->createTargetMachine(
PTU.TheModule->getTargetTriple(), "", "", TO, llvm::Reloc::Model::PIC_);
PTU.TheModule->setDataLayout(TargetMachine->createDataLayout());
std::string OutputFileName = PTU.TheModule->getName().str() + ".wasm";
std::error_code Error;
llvm::raw_fd_ostream OutputFile(llvm::StringRef(OutputFileName), Error);
llvm::legacy::PassManager PM;
if (TargetMachine->addPassesToEmitFile(PM, OutputFile, nullptr,
llvm::CodeGenFileType::ObjectFile)) {
return llvm::make_error<llvm::StringError>(
"Wasm backend cannot produce object.", llvm::inconvertibleErrorCode());
}
if (!PM.run(*PTU.TheModule)) {
return llvm::make_error<llvm::StringError>("Failed to emit Wasm object.",
llvm::inconvertibleErrorCode());
}
OutputFile.close();
std::vector<const char *> LinkerArgs = {"wasm-ld",
"-shared",
"--import-memory",
"--no-entry",
"--export-all",
"--experimental-pic",
"--stack-first",
"--allow-undefined",
OutputFileName.c_str(),
"-o",
OutputFileName.c_str()};
int Result =
lld::wasm::link(LinkerArgs, llvm::outs(), llvm::errs(), false, false);
if (!Result)
return llvm::make_error<llvm::StringError>(
"Failed to link incremental module", llvm::inconvertibleErrorCode());
void *LoadedLibModule =
dlopen(OutputFileName.c_str(), RTLD_NOW | RTLD_GLOBAL);
if (LoadedLibModule == nullptr) {
llvm::errs() << dlerror() << '\n';
return llvm::make_error<llvm::StringError>(
"Failed to load incremental module", llvm::inconvertibleErrorCode());
}
return llvm::Error::success();
}
llvm::Error WasmIncrementalExecutor::removeModule(PartialTranslationUnit &PTU) {
return llvm::make_error<llvm::StringError>("Not implemented yet",
llvm::inconvertibleErrorCode());
}
llvm::Error WasmIncrementalExecutor::runCtors() const {
// This seems to be automatically done when using dlopen()
return llvm::Error::success();
}
llvm::Error WasmIncrementalExecutor::cleanUp() const {
// Can't call cleanUp through IncrementalExecutor as it
// tries to deinitialize JIT which hasn't been initialized
return llvm::Error::success();
}
WasmIncrementalExecutor::~WasmIncrementalExecutor() = default;
} // namespace clang