https://github.com/argentite updated https://github.com/llvm/llvm-project/pull/86402
>From 4434ceeef152b95998ebd0a3b09a56d105490c4d Mon Sep 17 00:00:00 2001 From: Anubhab Ghosh <anubhabghosh...@gmail.com> Date: Sat, 23 Mar 2024 15:13:57 +0000 Subject: [PATCH 1/3] [clang-repl] Support wasm execution. This commit introduces support for running clang-repl and executing C++ code interactively inside a Javascript engine using WebAssembly when built with Emscripten. This is achieved by producing WASM "shared libraries" that can be loaded by the Emscripten runtime using dlopen() More discussion is available in https://reviews.llvm.org/D158140 --- clang/lib/Interpreter/CMakeLists.txt | 1 + clang/lib/Interpreter/IncrementalExecutor.cpp | 2 + clang/lib/Interpreter/IncrementalExecutor.h | 11 +- clang/lib/Interpreter/Interpreter.cpp | 11 ++ clang/lib/Interpreter/WASM.cpp | 107 ++++++++++++++++++ clang/lib/Interpreter/WASM.h | 33 ++++++ 6 files changed, 161 insertions(+), 4 deletions(-) create mode 100644 clang/lib/Interpreter/WASM.cpp create mode 100644 clang/lib/Interpreter/WASM.h diff --git a/clang/lib/Interpreter/CMakeLists.txt b/clang/lib/Interpreter/CMakeLists.txt index 9065f998f73c4..a8a287edf5b04 100644 --- a/clang/lib/Interpreter/CMakeLists.txt +++ b/clang/lib/Interpreter/CMakeLists.txt @@ -20,6 +20,7 @@ add_clang_library(clangInterpreter Interpreter.cpp InterpreterUtils.cpp Value.cpp + WASM.cpp DEPENDS intrinsics_gen diff --git a/clang/lib/Interpreter/IncrementalExecutor.cpp b/clang/lib/Interpreter/IncrementalExecutor.cpp index 6f036107c14a9..1824a5b4570a9 100644 --- a/clang/lib/Interpreter/IncrementalExecutor.cpp +++ b/clang/lib/Interpreter/IncrementalExecutor.cpp @@ -36,6 +36,8 @@ LLVM_ATTRIBUTE_USED void linkComponents() { } namespace clang { +IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC) + : TSCtx(TSC) {} llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> IncrementalExecutor::createDefaultJITBuilder( diff --git a/clang/lib/Interpreter/IncrementalExecutor.h b/clang/lib/Interpreter/IncrementalExecutor.h index b4347209e14fe..7954cde36588b 100644 --- a/clang/lib/Interpreter/IncrementalExecutor.h +++ b/clang/lib/Interpreter/IncrementalExecutor.h @@ -43,16 +43,19 @@ class IncrementalExecutor { llvm::DenseMap<const PartialTranslationUnit *, llvm::orc::ResourceTrackerSP> ResourceTrackers; +protected: + IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC); + public: enum SymbolNameKind { IRName, LinkerName }; IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC, llvm::orc::LLJITBuilder &JITBuilder, llvm::Error &Err); - ~IncrementalExecutor(); + virtual ~IncrementalExecutor(); - llvm::Error addModule(PartialTranslationUnit &PTU); - llvm::Error removeModule(PartialTranslationUnit &PTU); - llvm::Error runCtors() const; + virtual llvm::Error addModule(PartialTranslationUnit &PTU); + virtual llvm::Error removeModule(PartialTranslationUnit &PTU); + virtual llvm::Error runCtors() const; llvm::Error cleanUp(); llvm::Expected<llvm::orc::ExecutorAddr> getSymbolAddress(llvm::StringRef Name, SymbolNameKind NameKind) const; diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index cf31456b6950a..7d572b20cd828 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -15,6 +15,7 @@ #include "IncrementalExecutor.h" #include "IncrementalParser.h" #include "InterpreterUtils.h" +#include "WASM.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Mangle.h" @@ -183,6 +184,12 @@ IncrementalCompilerBuilder::CreateCpp() { std::vector<const char *> Argv; Argv.reserve(5 + 1 + UserArgs.size()); Argv.push_back("-xc++"); +#ifdef __EMSCRIPTEN__ + Argv.push_back("-target"); + Argv.push_back("wasm32-unknown-emscripten"); + Argv.push_back("-pie"); + Argv.push_back("-shared"); +#endif Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end()); std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple(); @@ -400,7 +407,11 @@ llvm::Error Interpreter::CreateExecutor() { if (!JB) return JB.takeError(); llvm::Error Err = llvm::Error::success(); +#ifdef __EMSCRIPTEN__ + auto Executor = std::make_unique<WASMIncrementalExecutor>(*TSCtx, **JB, Err); +#else auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, **JB, Err); +#endif if (!Err) IncrExecutor = std::move(Executor); diff --git a/clang/lib/Interpreter/WASM.cpp b/clang/lib/Interpreter/WASM.cpp new file mode 100644 index 0000000000000..d21d0ada1eafa --- /dev/null +++ b/clang/lib/Interpreter/WASM.cpp @@ -0,0 +1,107 @@ +//===----------------- 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 <dlfcn.h> + +namespace clang { + +WASMIncrementalExecutor::WASMIncrementalExecutor( + llvm::orc::ThreadSafeContext &TSC) + : IncrementalExecutor(TSC) {} + +llvm::Error WASMIncrementalExecutor::addModule(PartialTranslationUnit &PTU) { + PTU.TheModule->dump(); + + 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::CGFT_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", + "-pie", + "--import-memory", + "--no-entry", + "--export-all", + "--experimental-pic", + "--no-export-dynamic", + "--stack-first", + 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(); +} + +WASMIncrementalExecutor::~WASMIncrementalExecutor() = default; + +} // namespace clang diff --git a/clang/lib/Interpreter/WASM.h b/clang/lib/Interpreter/WASM.h new file mode 100644 index 0000000000000..07719fd5fe4f4 --- /dev/null +++ b/clang/lib/Interpreter/WASM.h @@ -0,0 +1,33 @@ +//===------------------ WASM.h - 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. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_INTERPRETER_WASM_H +#define LLVM_CLANG_LIB_INTERPRETER_WASM_H + +#include "IncrementalExecutor.h" + +namespace clang { + +class WASMIncrementalExecutor : public IncrementalExecutor { +public: + WASMIncrementalExecutor(llvm::orc::ThreadSafeContext &TSC); + + llvm::Error addModule(PartialTranslationUnit &PTU) override; + llvm::Error removeModule(PartialTranslationUnit &PTU) override; + llvm::Error runCtors() const override; + + ~WASMIncrementalExecutor() override; +}; + +} // namespace clang + +#endif // LLVM_CLANG_LIB_INTERPRETER_WASM_H >From 0a59db801f9c62363f1ccc0ad57162bd167556e4 Mon Sep 17 00:00:00 2001 From: Vassil Vassilev <v.g.vassi...@gmail.com> Date: Sat, 23 Mar 2024 15:32:53 +0000 Subject: [PATCH 2/3] Address comments --- clang/lib/Interpreter/CMakeLists.txt | 2 +- clang/lib/Interpreter/Interpreter.cpp | 4 ++-- clang/lib/Interpreter/{WASM.cpp => Wasm.cpp} | 24 ++++++++++++-------- clang/lib/Interpreter/{WASM.h => Wasm.h} | 8 +++---- 4 files changed, 21 insertions(+), 17 deletions(-) rename clang/lib/Interpreter/{WASM.cpp => Wasm.cpp} (87%) rename clang/lib/Interpreter/{WASM.h => Wasm.h} (79%) diff --git a/clang/lib/Interpreter/CMakeLists.txt b/clang/lib/Interpreter/CMakeLists.txt index a8a287edf5b04..9d302d995801d 100644 --- a/clang/lib/Interpreter/CMakeLists.txt +++ b/clang/lib/Interpreter/CMakeLists.txt @@ -20,7 +20,7 @@ add_clang_library(clangInterpreter Interpreter.cpp InterpreterUtils.cpp Value.cpp - WASM.cpp + Wasm.cpp DEPENDS intrinsics_gen diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 7d572b20cd828..f959fab49cfcc 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -15,7 +15,7 @@ #include "IncrementalExecutor.h" #include "IncrementalParser.h" #include "InterpreterUtils.h" -#include "WASM.h" +#include "Wasm.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Mangle.h" @@ -408,7 +408,7 @@ llvm::Error Interpreter::CreateExecutor() { return JB.takeError(); llvm::Error Err = llvm::Error::success(); #ifdef __EMSCRIPTEN__ - auto Executor = std::make_unique<WASMIncrementalExecutor>(*TSCtx, **JB, Err); + auto Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx, **JB, Err); #else auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, **JB, Err); #endif diff --git a/clang/lib/Interpreter/WASM.cpp b/clang/lib/Interpreter/Wasm.cpp similarity index 87% rename from clang/lib/Interpreter/WASM.cpp rename to clang/lib/Interpreter/Wasm.cpp index d21d0ada1eafa..859d54233081b 100644 --- a/clang/lib/Interpreter/WASM.cpp +++ b/clang/lib/Interpreter/Wasm.cpp @@ -1,4 +1,4 @@ -//===----------------- WASM.cpp - WASM Interpreter --------------*- 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. @@ -10,7 +10,9 @@ // //===----------------------------------------------------------------------===// -#include "WASM.h" +#ifdef __EMSCRIPTEN__ + +#include "Wasm.h" #include "IncrementalExecutor.h" #include <llvm/IR/LegacyPassManager.h> @@ -24,11 +26,11 @@ namespace clang { -WASMIncrementalExecutor::WASMIncrementalExecutor( +WasmIncrementalExecutor::WasmIncrementalExecutor( llvm::orc::ThreadSafeContext &TSC) : IncrementalExecutor(TSC) {} -llvm::Error WASMIncrementalExecutor::addModule(PartialTranslationUnit &PTU) { +llvm::Error WasmIncrementalExecutor::addModule(PartialTranslationUnit &PTU) { PTU.TheModule->dump(); std::string ErrorString; @@ -36,7 +38,7 @@ llvm::Error WASMIncrementalExecutor::addModule(PartialTranslationUnit &PTU) { const llvm::Target *Target = llvm::TargetRegistry::lookupTarget( PTU.TheModule->getTargetTriple(), ErrorString); if (!Target) { - return llvm::make_error<llvm::StringError>("Failed to create WASM Target: ", + return llvm::make_error<llvm::StringError>("Failed to create Wasm Target: ", llvm::inconvertibleErrorCode()); } @@ -53,12 +55,12 @@ llvm::Error WASMIncrementalExecutor::addModule(PartialTranslationUnit &PTU) { if (TargetMachine->addPassesToEmitFile(PM, OutputFile, nullptr, llvm::CGFT_ObjectFile)) { return llvm::make_error<llvm::StringError>( - "WASM backend cannot produce object.", llvm::inconvertibleErrorCode()); + "Wasm backend cannot produce object.", llvm::inconvertibleErrorCode()); } if (!PM.run(*PTU.TheModule)) { - return llvm::make_error<llvm::StringError>("Failed to emit WASM object.", + return llvm::make_error<llvm::StringError>("Failed to emit Wasm object.", llvm::inconvertibleErrorCode()); } @@ -92,16 +94,18 @@ llvm::Error WASMIncrementalExecutor::addModule(PartialTranslationUnit &PTU) { return llvm::Error::success(); } -llvm::Error WASMIncrementalExecutor::removeModule(PartialTranslationUnit &PTU) { +llvm::Error WasmIncrementalExecutor::removeModule(PartialTranslationUnit &PTU) { return llvm::make_error<llvm::StringError>("Not implemented yet", llvm::inconvertibleErrorCode()); } -llvm::Error WASMIncrementalExecutor::runCtors() const { +llvm::Error WasmIncrementalExecutor::runCtors() const { // This seems to be automatically done when using dlopen() return llvm::Error::success(); } -WASMIncrementalExecutor::~WASMIncrementalExecutor() = default; +WasmIncrementalExecutor::~WasmIncrementalExecutor() = default; } // namespace clang + +#endif // __EMSCRIPTEN__ diff --git a/clang/lib/Interpreter/WASM.h b/clang/lib/Interpreter/Wasm.h similarity index 79% rename from clang/lib/Interpreter/WASM.h rename to clang/lib/Interpreter/Wasm.h index 07719fd5fe4f4..98acd4c14e240 100644 --- a/clang/lib/Interpreter/WASM.h +++ b/clang/lib/Interpreter/Wasm.h @@ -1,4 +1,4 @@ -//===------------------ WASM.h - WASM Interpreter ---------------*- C++ -*-===// +//===------------------ Wasm.h - 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. @@ -17,15 +17,15 @@ namespace clang { -class WASMIncrementalExecutor : public IncrementalExecutor { +class WasmIncrementalExecutor : public IncrementalExecutor { public: - WASMIncrementalExecutor(llvm::orc::ThreadSafeContext &TSC); + WasmIncrementalExecutor(llvm::orc::ThreadSafeContext &TSC); llvm::Error addModule(PartialTranslationUnit &PTU) override; llvm::Error removeModule(PartialTranslationUnit &PTU) override; llvm::Error runCtors() const override; - ~WASMIncrementalExecutor() override; + ~WasmIncrementalExecutor() override; }; } // namespace clang >From 7b0a1c590113011ad33e1c318377f243ab004ac4 Mon Sep 17 00:00:00 2001 From: Anubhab Ghosh <anubhabghosh...@gmail.com> Date: Sat, 1 Jun 2024 13:10:06 +0530 Subject: [PATCH 3/3] Address more comments --- clang/lib/Interpreter/CMakeLists.txt | 7 ++++++- clang/lib/Interpreter/Interpreter.cpp | 2 +- clang/lib/Interpreter/Wasm.cpp | 17 ++++++++++------- clang/lib/Interpreter/Wasm.h | 4 ++++ 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/clang/lib/Interpreter/CMakeLists.txt b/clang/lib/Interpreter/CMakeLists.txt index 9d302d995801d..6a069659ebb8d 100644 --- a/clang/lib/Interpreter/CMakeLists.txt +++ b/clang/lib/Interpreter/CMakeLists.txt @@ -12,6 +12,10 @@ set(LLVM_LINK_COMPONENTS TargetParser ) +if (EMSCRIPTEN AND "lld" IN_LIST LLVM_ENABLE_PROJECTS) + set(WASM_SRC Wasm.cpp) +endif() + add_clang_library(clangInterpreter DeviceOffload.cpp CodeCompletion.cpp @@ -20,7 +24,8 @@ add_clang_library(clangInterpreter Interpreter.cpp InterpreterUtils.cpp Value.cpp - Wasm.cpp + ${WASM_SRC} + PARTIAL_SOURCES_INTENDED DEPENDS intrinsics_gen diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index f959fab49cfcc..4146b5036c505 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -408,7 +408,7 @@ llvm::Error Interpreter::CreateExecutor() { return JB.takeError(); llvm::Error Err = llvm::Error::success(); #ifdef __EMSCRIPTEN__ - auto Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx, **JB, Err); + auto Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx); #else auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, **JB, Err); #endif diff --git a/clang/lib/Interpreter/Wasm.cpp b/clang/lib/Interpreter/Wasm.cpp index 859d54233081b..1001410aa0f27 100644 --- a/clang/lib/Interpreter/Wasm.cpp +++ b/clang/lib/Interpreter/Wasm.cpp @@ -10,8 +10,6 @@ // //===----------------------------------------------------------------------===// -#ifdef __EMSCRIPTEN__ - #include "Wasm.h" #include "IncrementalExecutor.h" @@ -22,6 +20,15 @@ #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 { @@ -31,8 +38,6 @@ WasmIncrementalExecutor::WasmIncrementalExecutor( : IncrementalExecutor(TSC) {} llvm::Error WasmIncrementalExecutor::addModule(PartialTranslationUnit &PTU) { - PTU.TheModule->dump(); - std::string ErrorString; const llvm::Target *Target = llvm::TargetRegistry::lookupTarget( @@ -53,7 +58,7 @@ llvm::Error WasmIncrementalExecutor::addModule(PartialTranslationUnit &PTU) { llvm::legacy::PassManager PM; if (TargetMachine->addPassesToEmitFile(PM, OutputFile, nullptr, - llvm::CGFT_ObjectFile)) { + llvm::CodeGenFileType::ObjectFile)) { return llvm::make_error<llvm::StringError>( "Wasm backend cannot produce object.", llvm::inconvertibleErrorCode()); } @@ -107,5 +112,3 @@ llvm::Error WasmIncrementalExecutor::runCtors() const { WasmIncrementalExecutor::~WasmIncrementalExecutor() = default; } // namespace clang - -#endif // __EMSCRIPTEN__ diff --git a/clang/lib/Interpreter/Wasm.h b/clang/lib/Interpreter/Wasm.h index 98acd4c14e240..b1fd88024f14d 100644 --- a/clang/lib/Interpreter/Wasm.h +++ b/clang/lib/Interpreter/Wasm.h @@ -13,6 +13,10 @@ #ifndef LLVM_CLANG_LIB_INTERPRETER_WASM_H #define LLVM_CLANG_LIB_INTERPRETER_WASM_H +#ifndef __EMSCRIPTEN__ +#error "This requires emscripten." +#endif // __EMSCRIPTEN__ + #include "IncrementalExecutor.h" namespace clang { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits