diff --git a/clang/lib/Interpreter/CMakeLists.txt b/clang/lib/Interpreter/CMakeLists.txt
index 9065f998f73c4..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,6 +24,8 @@ add_clang_library(clangInterpreter
   Interpreter.cpp
   InterpreterUtils.cpp
   Value.cpp
+  ${WASM_SRC}
+  PARTIAL_SOURCES_INTENDED
 
   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 7a95278914276..49dc92d60233a 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -15,6 +15,9 @@
 #include "IncrementalExecutor.h"
 #include "IncrementalParser.h"
 #include "InterpreterUtils.h"
+#ifdef __EMSCRIPTEN__
+#include "Wasm.h"
+#endif // __EMSCRIPTEN__
 
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Mangle.h"
@@ -186,6 +189,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();
@@ -426,8 +435,12 @@ llvm::Error Interpreter::CreateExecutor() {
   }
 
   llvm::Error Err = llvm::Error::success();
+#ifdef __EMSCRIPTEN__
+  auto Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx);
+#else
   auto Executor =
       std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, 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..1001410aa0f27
--- /dev/null
+++ b/clang/lib/Interpreter/Wasm.cpp
@@ -0,0 +1,114 @@
+//===----------------- 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",
+                                          "-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..b1fd88024f14d
--- /dev/null
+++ b/clang/lib/Interpreter/Wasm.h
@@ -0,0 +1,37 @@
+//===------------------ 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
+
+#ifndef __EMSCRIPTEN__
+#error "This requires emscripten."
+#endif // __EMSCRIPTEN__
+
+#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