Rename GetLanguageInfo to GetLanguageSpecificData (#117012)
[llvm-project.git] / clang / lib / Interpreter / Wasm.cpp
blob79efbaa03982d01a53a6a77a77b2caae2a52e753
1 //===----------------- Wasm.cpp - Wasm Interpreter --------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements interpreter support for code execution in WebAssembly.
11 //===----------------------------------------------------------------------===//
13 #include "Wasm.h"
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>
23 #include <string>
25 namespace lld {
26 namespace wasm {
27 bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
28 llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
29 } // namespace wasm
30 } // namespace lld
32 #include <dlfcn.h>
34 namespace clang {
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);
45 if (!Target) {
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());
72 OutputFile.close();
74 std::vector<const char *> LinkerArgs = {"wasm-ld",
75 "-shared",
76 "--import-memory",
77 "--no-entry",
78 "--export-all",
79 "--experimental-pic",
80 "--stack-first",
81 "--allow-undefined",
82 OutputFileName.c_str(),
83 "-o",
84 OutputFileName.c_str()};
85 int Result =
86 lld::wasm::link(LinkerArgs, llvm::outs(), llvm::errs(), false, false);
87 if (!Result)
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;
120 } // namespace clang