Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/Interpreter/Wasm.cpp
35233 views
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.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "Wasm.h"
14
#include "IncrementalExecutor.h"
15
16
#include <llvm/IR/LegacyPassManager.h>
17
#include <llvm/IR/Module.h>
18
#include <llvm/MC/TargetRegistry.h>
19
#include <llvm/Target/TargetMachine.h>
20
21
#include <clang/Interpreter/Interpreter.h>
22
23
#include <string>
24
25
namespace lld {
26
enum Flavor {
27
Invalid,
28
Gnu, // -flavor gnu
29
MinGW, // -flavor gnu MinGW
30
WinLink, // -flavor link
31
Darwin, // -flavor darwin
32
Wasm, // -flavor wasm
33
};
34
35
using Driver = bool (*)(llvm::ArrayRef<const char *>, llvm::raw_ostream &,
36
llvm::raw_ostream &, bool, bool);
37
38
struct DriverDef {
39
Flavor f;
40
Driver d;
41
};
42
43
struct Result {
44
int retCode;
45
bool canRunAgain;
46
};
47
48
Result lldMain(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
49
llvm::raw_ostream &stderrOS, llvm::ArrayRef<DriverDef> drivers);
50
51
namespace wasm {
52
bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
53
llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
54
} // namespace wasm
55
} // namespace lld
56
57
#include <dlfcn.h>
58
59
namespace clang {
60
61
WasmIncrementalExecutor::WasmIncrementalExecutor(
62
llvm::orc::ThreadSafeContext &TSC)
63
: IncrementalExecutor(TSC) {}
64
65
llvm::Error WasmIncrementalExecutor::addModule(PartialTranslationUnit &PTU) {
66
std::string ErrorString;
67
68
const llvm::Target *Target = llvm::TargetRegistry::lookupTarget(
69
PTU.TheModule->getTargetTriple(), ErrorString);
70
if (!Target) {
71
return llvm::make_error<llvm::StringError>("Failed to create Wasm Target: ",
72
llvm::inconvertibleErrorCode());
73
}
74
75
llvm::TargetOptions TO = llvm::TargetOptions();
76
llvm::TargetMachine *TargetMachine = Target->createTargetMachine(
77
PTU.TheModule->getTargetTriple(), "", "", TO, llvm::Reloc::Model::PIC_);
78
PTU.TheModule->setDataLayout(TargetMachine->createDataLayout());
79
std::string ObjectFileName = PTU.TheModule->getName().str() + ".o";
80
std::string BinaryFileName = PTU.TheModule->getName().str() + ".wasm";
81
82
std::error_code Error;
83
llvm::raw_fd_ostream ObjectFileOutput(llvm::StringRef(ObjectFileName), Error);
84
85
llvm::legacy::PassManager PM;
86
if (TargetMachine->addPassesToEmitFile(PM, ObjectFileOutput, nullptr,
87
llvm::CodeGenFileType::ObjectFile)) {
88
return llvm::make_error<llvm::StringError>(
89
"Wasm backend cannot produce object.", llvm::inconvertibleErrorCode());
90
}
91
92
if (!PM.run(*PTU.TheModule)) {
93
94
return llvm::make_error<llvm::StringError>("Failed to emit Wasm object.",
95
llvm::inconvertibleErrorCode());
96
}
97
98
ObjectFileOutput.close();
99
100
std::vector<const char *> LinkerArgs = {"wasm-ld",
101
"-shared",
102
"--import-memory",
103
"--experimental-pic",
104
"--stack-first",
105
"--allow-undefined",
106
ObjectFileName.c_str(),
107
"-o",
108
BinaryFileName.c_str()};
109
110
const lld::DriverDef WasmDriver = {lld::Flavor::Wasm, &lld::wasm::link};
111
std::vector<lld::DriverDef> WasmDriverArgs;
112
WasmDriverArgs.push_back(WasmDriver);
113
lld::Result Result =
114
lld::lldMain(LinkerArgs, llvm::outs(), llvm::errs(), WasmDriverArgs);
115
116
if (Result.retCode)
117
return llvm::make_error<llvm::StringError>(
118
"Failed to link incremental module", llvm::inconvertibleErrorCode());
119
120
void *LoadedLibModule =
121
dlopen(BinaryFileName.c_str(), RTLD_NOW | RTLD_GLOBAL);
122
if (LoadedLibModule == nullptr) {
123
llvm::errs() << dlerror() << '\n';
124
return llvm::make_error<llvm::StringError>(
125
"Failed to load incremental module", llvm::inconvertibleErrorCode());
126
}
127
128
return llvm::Error::success();
129
}
130
131
llvm::Error WasmIncrementalExecutor::removeModule(PartialTranslationUnit &PTU) {
132
return llvm::make_error<llvm::StringError>("Not implemented yet",
133
llvm::inconvertibleErrorCode());
134
}
135
136
llvm::Error WasmIncrementalExecutor::runCtors() const {
137
// This seems to be automatically done when using dlopen()
138
return llvm::Error::success();
139
}
140
141
llvm::Error WasmIncrementalExecutor::cleanUp() {
142
// Can't call cleanUp through IncrementalExecutor as it
143
// tries to deinitialize JIT which hasn't been initialized
144
return llvm::Error::success();
145
}
146
147
WasmIncrementalExecutor::~WasmIncrementalExecutor() = default;
148
149
} // namespace clang
150