1 //===----------------- Wasm.cpp - Wasm Interpreter --------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements interpreter support for code execution in WebAssembly.
11 //===----------------------------------------------------------------------===//
14 #include "IncrementalExecutor.h"
16 #include <llvm/IR/LegacyPassManager.h>
17 #include <llvm/IR/Module.h>
18 #include <llvm/MC/TargetRegistry.h>
19 #include <llvm/Target/TargetMachine.h>
21 #include <clang/Interpreter/Interpreter.h>
27 bool link(llvm::ArrayRef
<const char *> args
, llvm::raw_ostream
&stdoutOS
,
28 llvm::raw_ostream
&stderrOS
, bool exitEarly
, bool disableOutput
);
36 WasmIncrementalExecutor::WasmIncrementalExecutor(
37 llvm::orc::ThreadSafeContext
&TSC
)
38 : IncrementalExecutor(TSC
) {}
40 llvm::Error
WasmIncrementalExecutor::addModule(PartialTranslationUnit
&PTU
) {
41 std::string ErrorString
;
43 const llvm::Target
*Target
= llvm::TargetRegistry::lookupTarget(
44 PTU
.TheModule
->getTargetTriple(), ErrorString
);
46 return llvm::make_error
<llvm::StringError
>("Failed to create Wasm Target: ",
47 llvm::inconvertibleErrorCode());
50 llvm::TargetOptions TO
= llvm::TargetOptions();
51 llvm::TargetMachine
*TargetMachine
= Target
->createTargetMachine(
52 PTU
.TheModule
->getTargetTriple(), "", "", TO
, llvm::Reloc::Model::PIC_
);
53 PTU
.TheModule
->setDataLayout(TargetMachine
->createDataLayout());
54 std::string OutputFileName
= PTU
.TheModule
->getName().str() + ".wasm";
56 std::error_code Error
;
57 llvm::raw_fd_ostream
OutputFile(llvm::StringRef(OutputFileName
), Error
);
59 llvm::legacy::PassManager PM
;
60 if (TargetMachine
->addPassesToEmitFile(PM
, OutputFile
, nullptr,
61 llvm::CodeGenFileType::ObjectFile
)) {
62 return llvm::make_error
<llvm::StringError
>(
63 "Wasm backend cannot produce object.", llvm::inconvertibleErrorCode());
66 if (!PM
.run(*PTU
.TheModule
)) {
68 return llvm::make_error
<llvm::StringError
>("Failed to emit Wasm object.",
69 llvm::inconvertibleErrorCode());
74 std::vector
<const char *> LinkerArgs
= {"wasm-ld",
82 OutputFileName
.c_str(),
84 OutputFileName
.c_str()};
86 lld::wasm::link(LinkerArgs
, llvm::outs(), llvm::errs(), false, false);
88 return llvm::make_error
<llvm::StringError
>(
89 "Failed to link incremental module", llvm::inconvertibleErrorCode());
91 void *LoadedLibModule
=
92 dlopen(OutputFileName
.c_str(), RTLD_NOW
| RTLD_GLOBAL
);
93 if (LoadedLibModule
== nullptr) {
94 llvm::errs() << dlerror() << '\n';
95 return llvm::make_error
<llvm::StringError
>(
96 "Failed to load incremental module", llvm::inconvertibleErrorCode());
99 return llvm::Error::success();
102 llvm::Error
WasmIncrementalExecutor::removeModule(PartialTranslationUnit
&PTU
) {
103 return llvm::make_error
<llvm::StringError
>("Not implemented yet",
104 llvm::inconvertibleErrorCode());
107 llvm::Error
WasmIncrementalExecutor::runCtors() const {
108 // This seems to be automatically done when using dlopen()
109 return llvm::Error::success();
112 llvm::Error
WasmIncrementalExecutor::cleanUp() const {
113 // Can't call cleanUp through IncrementalExecutor as it
114 // tries to deinitialize JIT which hasn't been initialized
115 return llvm::Error::success();
118 WasmIncrementalExecutor::~WasmIncrementalExecutor() = default;