Revert "[clang-repl] Re-implement clang-interpreter as a test case."

This reverts commit 319ce98011 because it fails
on various platforms.
This commit is contained in:
Vassil Vassilev 2021-09-01 06:49:17 +00:00
parent d396d09fc2
commit 04bbd189a9
16 changed files with 168 additions and 168 deletions

View File

@ -59,6 +59,11 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 04, 2021 13:01:37
- `1`
- `0`
- :good:`100%`
* - clang/examples/clang-interpreter
- `1`
- `0`
- `1`
- :none:`0%`
* - clang/examples/PrintFunctionNames
- `1`
- `0`

View File

@ -3,6 +3,7 @@ if(NOT CLANG_BUILD_EXAMPLES)
set(EXCLUDE_FROM_ALL ON)
endif()
add_subdirectory(clang-interpreter)
add_subdirectory(PrintFunctionNames)
add_subdirectory(AnnotateFunctions)
add_subdirectory(Attribute)

View File

@ -0,0 +1,93 @@
set(LLVM_LINK_COMPONENTS
Core
ExecutionEngine
MC
MCJIT
Object
OrcJit
Option
RuntimeDyld
Support
native
)
add_clang_executable(clang-interpreter
main.cpp
)
add_dependencies(clang-interpreter
clang-resource-headers
)
clang_target_link_libraries(clang-interpreter
PRIVATE
clangBasic
clangCodeGen
clangDriver
clangFrontend
clangSerialization
)
export_executable_symbols(clang-interpreter)
if (MSVC)
# Is this a CMake bug that even with export_executable_symbols, Windows
# needs to explictly export the type_info vtable
set_property(TARGET clang-interpreter
APPEND_STRING PROPERTY LINK_FLAGS " /EXPORT:??_7type_info@@6B@")
endif()
function(clang_enable_exceptions TARGET)
# Really have to jump through hoops to enable exception handling independent
# of how LLVM is being built.
if (NOT LLVM_REQUIRES_EH AND NOT LLVM_REQUIRES_RTTI)
if (MSVC)
# /EHs to allow throwing from extern "C"
set(excptnExceptions_ON "/D _HAS_EXCEPTIONS=1 /EHs /wd4714")
set(excptnExceptions_OFF "/D _HAS_EXCEPTIONS=0 /EHs-c-")
set(excptnRTTI_ON "/GR")
set(excptnRTTI_OFF "/GR-")
set(excptnEHRTTIRegEx "(/EHs(-c-?)|_HAS_EXCEPTIONS=(0|1))")
else()
set(excptnExceptions_ON "-fexceptions")
set(excptnExceptions_OFF "-fno-exceptions")
set(excptnRTTI_ON "-frtti")
set(excptnRTTI_OFF "-fno-rtti")
set(excptnEHRTTIRegEx "-f(exceptions|no-exceptions)")
endif()
if (LLVM_REQUIRES_EH)
set(excptnExceptions_DFLT ${excptnExceptions_ON})
else()
set(excptnExceptions_DFLT ${excptnExceptions_OFF})
endif()
if (LLVM_REQUIRES_RTTI)
set(excptnRTTI_DFLT ${excptnRTTI_ON})
else()
set(excptnRTTI_DFLT ${excptnRTTI_OFF})
endif()
# Strip the exception & rtti flags from the target
get_property(addedFlags TARGET ${TARGET} PROPERTY COMPILE_FLAGS)
string(REGEX REPLACE ${excptnEHRTTIRegEx} "" editedFlags "${addedFlags}")
string(REPLACE ${excptnRTTI_OFF} "" editedFlags "${editedFlags}")
set_property(TARGET ${TARGET} PROPERTY COMPILE_FLAGS "${editedFlags}")
get_property(addedFlags TARGET ${TARGET} PROPERTY COMPILE_DEFINITIONS)
string(REGEX REPLACE ${excptnEHRTTIRegEx} "" editedFlags "${addedFlags}")
string(REPLACE ${excptnRTTI_OFF} "" editedFlags "${editedFlags}")
set_property(TARGET ${TARGET} PROPERTY COMPILE_DEFINITIONS "${editedFlags}")
# Re-add the exception & rtti flags from LLVM
set_property(SOURCE main.cpp APPEND_STRING PROPERTY COMPILE_FLAGS
" ${excptnExceptions_DFLT} ${excptnRTTI_DFLT} ")
set_property(SOURCE Manager.cpp APPEND_STRING PROPERTY COMPILE_FLAGS
" ${excptnExceptions_DFLT} ${excptnRTTI_DFLT} ")
# Invoke with exceptions & rtti
set_property(SOURCE Invoke.cpp APPEND_STRING PROPERTY COMPILE_FLAGS
" ${excptnExceptions_ON} ${excptnRTTI_ON} ")
endif()
endfunction(clang_enable_exceptions)
clang_enable_exceptions(clang-interpreter)

View File

@ -0,0 +1,20 @@
This is an example of Clang based interpreter, for executing standalone C/C++
programs.
It demonstrates the following features:
1. Parsing standard compiler command line arguments using the Driver library.
2. Constructing a Clang compiler instance, using the appropriate arguments
derived in step #1.
3. Invoking the Clang compiler to lex, parse, syntax check, and then generate
LLVM code.
4. Use the LLVM JIT functionality to execute the final module.
5. Intercepting a Win64 library call to allow throwing and catching exceptions
in and from the JIT.
The implementation has many limitations and is not designed to be a full fledged
interpreter. It is designed to demonstrate a simple but functional use of the
Clang compiler libraries.

View File

@ -0,0 +1,33 @@
//===-- examples/clang-interpreter/Test.cxx - Clang C Interpreter Example -===//
//
// 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
//
//===----------------------------------------------------------------------===//
// Example throwing in and from the JIT (particularly on Win64).
//
// ./bin/clang-interpreter <src>/tools/clang/examples/clang-interpreter/Test.cxx
#include <stdexcept>
#include <stdio.h>
static void ThrowerAnError(const char* Name) {
throw std::runtime_error(Name);
}
int main(int argc, const char** argv) {
for (int I = 0; I < argc; ++I)
printf("arg[%d]='%s'\n", I, argv[I]);
try {
ThrowerAnError("In JIT");
} catch (const std::exception& E) {
printf("Caught: '%s'\n", E.what());
} catch (...) {
printf("Unknown exception\n");
}
ThrowerAnError("From JIT");
return 0;
}

View File

@ -16,7 +16,6 @@
#include "clang/Interpreter/PartialTranslationUnit.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/Support/Error.h"
#include <memory>
@ -66,8 +65,6 @@ public:
return Execute(*PTU);
return llvm::Error::success();
}
llvm::Expected<llvm::JITTargetAddress>
getSymbolAddress(llvm::StringRef UnmangledName) const;
};
} // namespace clang

View File

@ -60,12 +60,4 @@ llvm::Error IncrementalExecutor::runCtors() const {
return Jit->initialize(Jit->getMainJITDylib());
}
llvm::Expected<llvm::JITTargetAddress>
IncrementalExecutor::getSymbolAddress(llvm::StringRef UnmangledName) const {
auto Sym = Jit->lookup(UnmangledName);
if (!Sym)
return Sym.takeError();
return Sym->getAddress();
}
} // end namespace clang

View File

@ -41,8 +41,6 @@ public:
llvm::Error addModule(std::unique_ptr<llvm::Module> M);
llvm::Error runCtors() const;
llvm::Expected<llvm::JITTargetAddress>
getSymbolAddress(llvm::StringRef UnmangledName) const;
};
} // end namespace clang

View File

@ -35,7 +35,8 @@
using namespace clang;
// FIXME: Figure out how to unify with namespace init_convenience from
// tools/clang-import-test/clang-import-test.cpp
// tools/clang-import-test/clang-import-test.cpp and
// examples/clang-interpreter/main.cpp
namespace {
/// Retrieves the clang CC1 specific flags out of the compilation's jobs.
/// \returns NULL on error.
@ -222,13 +223,3 @@ llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
return llvm::Error::success();
}
llvm::Expected<llvm::JITTargetAddress>
Interpreter::getSymbolAddress(llvm::StringRef UnmangledName) const {
if (!IncrExecutor)
return llvm::make_error<llvm::StringError>("Operation failed. "
"No execution engine",
std::error_code());
return IncrExecutor->getSymbolAddress(UnmangledName);
}

View File

@ -96,6 +96,7 @@ if (CLANG_BUILD_EXAMPLES)
Attribute
AnnotateFunctions
CallSuperAttr
clang-interpreter
PrintFunctionNames
)
endif ()

View File

@ -0,0 +1,10 @@
// RUN: clang-interpreter %s | FileCheck %s
// REQUIRES: native, examples
int printf(const char *, ...);
int main() {
// CHECK: {{Hello world!}}
printf("Hello world!\n");
return 0;
}

View File

@ -71,6 +71,7 @@ tools = [
if config.clang_examples:
config.available_features.add('examples')
tools.append('clang-interpreter')
def have_host_jit_support():
clang_repl_exe = lit.util.which('clang-repl', config.clang_tools_dir)

View File

@ -12,8 +12,3 @@ target_link_libraries(ClangReplInterpreterTests PUBLIC
clangInterpreter
clangFrontend
)
# Exceptions on Windows are not yet supported.
if(NOT WIN32)
add_subdirectory(ExceptionTests)
endif()

View File

@ -1,18 +0,0 @@
# The interpreter can throw an exception from user input. The test binary needs
# to be compiled with exception support to expect and catch the thrown
# exception.
set(LLVM_REQUIRES_EH ON)
set(LLVM_REQUIRES_RTTI ON)
add_clang_unittest(ClangReplInterpreterExceptionTests
InterpreterExceptionTest.cpp
)
llvm_update_compile_flags(ClangReplInterpreterExceptionTests)
target_link_libraries(ClangReplInterpreterExceptionTests PUBLIC
clangAST
clangBasic
clangInterpreter
clangFrontend
)
add_dependencies(ClangReplInterpreterExceptionTests clang-resource-headers)

View File

@ -1,121 +0,0 @@
//===- unittests/Interpreter/InterpreterExceptionTest.cpp -----------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Unit tests for Clang's Interpreter library.
//
//===----------------------------------------------------------------------===//
#include "clang/Interpreter/Interpreter.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclGroup.h"
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/Support/TargetSelect.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
using namespace clang;
namespace {
using Args = std::vector<const char *>;
static std::unique_ptr<Interpreter>
createInterpreter(const Args &ExtraArgs = {},
DiagnosticConsumer *Client = nullptr) {
Args ClangArgs = {"-Xclang", "-emit-llvm-only"};
ClangArgs.insert(ClangArgs.end(), ExtraArgs.begin(), ExtraArgs.end());
auto CI = cantFail(clang::IncrementalCompilerBuilder::create(ClangArgs));
if (Client)
CI->getDiagnostics().setClient(Client, /*ShouldOwnClient=*/false);
return cantFail(clang::Interpreter::create(std::move(CI)));
}
// This function isn't referenced outside its translation unit, but it
// can't use the "static" keyword because its address is used for
// GetMainExecutable (since some platforms don't support taking the
// address of main, and some platforms can't implement GetMainExecutable
// without being given the address of a function in the main executable).
std::string GetExecutablePath(const char *Argv0, void *MainAddr) {
return llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
}
static std::string MakeResourcesPath() {
// Dir is bin/ or lib/, depending on where BinaryPath is.
void *MainAddr = (void *)(intptr_t)GetExecutablePath;
std::string BinaryPath = GetExecutablePath(/*Argv0=*/nullptr, MainAddr);
// build/tools/clang/unittests/Interpreter/Executable -> build/
llvm::StringRef Dir = llvm::sys::path::parent_path(BinaryPath);
Dir = llvm::sys::path::parent_path(Dir);
Dir = llvm::sys::path::parent_path(Dir);
Dir = llvm::sys::path::parent_path(Dir);
Dir = llvm::sys::path::parent_path(Dir);
Dir = llvm::sys::path::parent_path(Dir);
SmallString<128> P(Dir);
llvm::sys::path::append(P, Twine("lib") + CLANG_LIBDIR_SUFFIX, "clang",
CLANG_VERSION_STRING);
return std::string(P.str());
}
TEST(InterpreterTest, CatchException) {
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
{
auto J = llvm::orc::LLJITBuilder().create();
if (!J) {
// The platform does not support JITs.
// We can't use llvm::consumeError as it needs typeinfo for ErrorInfoBase.
auto E = J.takeError();
(void)E;
return;
}
}
const char ExceptionCode[] =
R"(
#include <stdexcept>
#include <stdio.h>
static void ThrowerAnError(const char* Name) {
throw std::runtime_error(Name);
}
extern "C" int throw_exception() {
try {
ThrowerAnError("In JIT");
} catch (const std::exception& E) {
printf("Caught: '%s'\n", E.what());
} catch (...) {
printf("Unknown exception\n");
}
ThrowerAnError("From JIT");
return 0;
}
)";
std::string ResourceDir = MakeResourcesPath();
std::unique_ptr<Interpreter> Interp =
createInterpreter({"-resource-dir", ResourceDir.c_str()});
// Adjust the resource-dir
llvm::cantFail(Interp->ParseAndExecute(ExceptionCode));
testing::internal::CaptureStdout();
auto ThrowException =
(int (*)())llvm::cantFail(Interp->getSymbolAddress("throw_exception"));
EXPECT_THROW(ThrowException(), std::exception);
std::string CapturedStdOut = testing::internal::GetCapturedStdout();
EXPECT_EQ(CapturedStdOut, "Caught: 'In JIT'\n");
}
} // end anonymous namespace

View File

@ -17,6 +17,8 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvm/ADT/ArrayRef.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"