Author: Vassil Vassilev Date: 2021-09-03T13:18:09Z New Revision: 8859640461149065ece1fbcdfed78f17f04a4926
URL: https://github.com/llvm/llvm-project/commit/8859640461149065ece1fbcdfed78f17f04a4926 DIFF: https://github.com/llvm/llvm-project/commit/8859640461149065ece1fbcdfed78f17f04a4926.diff LOG: Revert "Reland "[clang-repl] Re-implement clang-interpreter as a test case."" This reverts commit 6fe2beba7d2a41964af658c8c59dd172683ef739 which fails on clang-hexagon-elf Added: clang/examples/clang-interpreter/CMakeLists.txt clang/examples/clang-interpreter/README.txt clang/examples/clang-interpreter/Test.cxx clang/test/Misc/interpreter.c Modified: clang/docs/ClangFormattedStatus.rst clang/examples/CMakeLists.txt clang/include/clang/Interpreter/Interpreter.h clang/lib/Interpreter/IncrementalExecutor.cpp clang/lib/Interpreter/IncrementalExecutor.h clang/lib/Interpreter/Interpreter.cpp clang/test/CMakeLists.txt clang/test/lit.cfg.py clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/InterpreterTest.cpp Removed: clang/unittests/Interpreter/ExceptionTests/CMakeLists.txt clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp ################################################################################ diff --git a/clang/docs/ClangFormattedStatus.rst b/clang/docs/ClangFormattedStatus.rst index 77320cd2b6550..beca555ebc016 100644 --- a/clang/docs/ClangFormattedStatus.rst +++ b/clang/docs/ClangFormattedStatus.rst @@ -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` diff --git a/clang/examples/CMakeLists.txt b/clang/examples/CMakeLists.txt index 8a4139f5d8c11..300d8d795c674 100644 --- a/clang/examples/CMakeLists.txt +++ b/clang/examples/CMakeLists.txt @@ -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) diff --git a/clang/examples/clang-interpreter/CMakeLists.txt b/clang/examples/clang-interpreter/CMakeLists.txt new file mode 100644 index 0000000000000..11056aa379ae8 --- /dev/null +++ b/clang/examples/clang-interpreter/CMakeLists.txt @@ -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) diff --git a/clang/examples/clang-interpreter/README.txt b/clang/examples/clang-interpreter/README.txt new file mode 100644 index 0000000000000..b4f8a935cef83 --- /dev/null +++ b/clang/examples/clang-interpreter/README.txt @@ -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. diff --git a/clang/examples/clang-interpreter/Test.cxx b/clang/examples/clang-interpreter/Test.cxx new file mode 100644 index 0000000000000..ed7fc86f9e5fc --- /dev/null +++ b/clang/examples/clang-interpreter/Test.cxx @@ -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; +} diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index 9f5b64ce21243..020cbe2db3d06 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -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 @@ class Interpreter { return Execute(*PTU); return llvm::Error::success(); } - llvm::Expected<llvm::JITTargetAddress> - getSymbolAddress(llvm::StringRef UnmangledName) const; }; } // namespace clang diff --git a/clang/lib/Interpreter/IncrementalExecutor.cpp b/clang/lib/Interpreter/IncrementalExecutor.cpp index 230b49167f347..9a368d9122bcf 100644 --- a/clang/lib/Interpreter/IncrementalExecutor.cpp +++ b/clang/lib/Interpreter/IncrementalExecutor.cpp @@ -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 diff --git a/clang/lib/Interpreter/IncrementalExecutor.h b/clang/lib/Interpreter/IncrementalExecutor.h index b626ebedcdc30..b4c6ddec10472 100644 --- a/clang/lib/Interpreter/IncrementalExecutor.h +++ b/clang/lib/Interpreter/IncrementalExecutor.h @@ -41,8 +41,6 @@ class IncrementalExecutor { 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 diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 69224ddc947ec..3e8d3884049ba 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -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. @@ -217,13 +218,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); -} diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt index abc04228ce971..9bf791f93f32e 100644 --- a/clang/test/CMakeLists.txt +++ b/clang/test/CMakeLists.txt @@ -96,6 +96,7 @@ if (CLANG_BUILD_EXAMPLES) Attribute AnnotateFunctions CallSuperAttr + clang-interpreter PrintFunctionNames ) endif () diff --git a/clang/test/Misc/interpreter.c b/clang/test/Misc/interpreter.c new file mode 100644 index 0000000000000..42e1645b7c61b --- /dev/null +++ b/clang/test/Misc/interpreter.c @@ -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; +} diff --git a/clang/test/lit.cfg.py b/clang/test/lit.cfg.py index 5a9a1abf4531a..3a820943bd0f6 100644 --- a/clang/test/lit.cfg.py +++ b/clang/test/lit.cfg.py @@ -71,6 +71,7 @@ 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) diff --git a/clang/unittests/Interpreter/CMakeLists.txt b/clang/unittests/Interpreter/CMakeLists.txt index 3f8cc201ac239..ec5e62b989ccf 100644 --- a/clang/unittests/Interpreter/CMakeLists.txt +++ b/clang/unittests/Interpreter/CMakeLists.txt @@ -1,8 +1,5 @@ set(LLVM_LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} Core - OrcJIT - Support ) add_clang_unittest(ClangReplInterpreterTests @@ -15,8 +12,3 @@ target_link_libraries(ClangReplInterpreterTests PUBLIC clangInterpreter clangFrontend ) - -# Exceptions on Windows are not yet supported. -if(NOT WIN32) - add_subdirectory(ExceptionTests) -endif() diff --git a/clang/unittests/Interpreter/ExceptionTests/CMakeLists.txt b/clang/unittests/Interpreter/ExceptionTests/CMakeLists.txt deleted file mode 100644 index c3c576bf21cd1..0000000000000 --- a/clang/unittests/Interpreter/ExceptionTests/CMakeLists.txt +++ /dev/null @@ -1,25 +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) - -set(LLVM_LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} - Core - OrcJIT - Support - ) - -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) diff --git a/clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp b/clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp deleted file mode 100644 index af01a443137e7..0000000000000 --- a/clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp +++ /dev/null @@ -1,127 +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/ASTContext.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclGroup.h" -#include "clang/Basic/Version.h" -#include "clang/Basic/TargetInfo.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 "llvm/Support/ManagedStatic.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))); -} - -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; - } - } - -#define Stringify(s) Stringifyx(s) -#define Stringifyx(s) #s - - // We define a custom exception to avoid #include-ing the <exception> header - // which would require this test to know about the libstdc++ location. - // its own header file. -#define CUSTOM_EXCEPTION \ - struct custom_exception { \ - custom_exception(const char* Msg) : Message(Msg) {} \ - const char* Message; \ - }; - - CUSTOM_EXCEPTION; - - std::string ExceptionCode = Stringify(CUSTOM_EXCEPTION); - ExceptionCode += - R"( -extern "C" int printf(const char*, ...); -static void ThrowerAnError(const char* Name) { - throw custom_exception(Name); -} - -extern "C" int throw_exception() { - try { - ThrowerAnError("In JIT"); - } catch (const custom_exception& E) { - printf("Caught: '%s'\n", E.Message); - } catch (...) { - printf("Unknown exception\n"); - } - ThrowerAnError("From JIT"); - return 0; -} - )"; - std::unique_ptr<Interpreter> Interp = createInterpreter(); - // FIXME: Re-enable the excluded target triples. - const clang::CompilerInstance *CI = Interp->getCompilerInstance(); - const llvm::Triple &Triple = CI->getASTContext().getTargetInfo().getTriple(); - // FIXME: PPC fails due to `Symbols not found: [DW.ref.__gxx_personality_v0]` - // The current understanding is that the JIT should emit this symbol if it was - // not (eg. the way passing clang -fPIC does it). - if (Triple.isPPC()) - return; - - // FIXME: ARM fails due to `Not implemented relocation type!` - if (Triple.isARM()) - return; - - // FIXME: Hexagon fails due to `No available targets are compatible with - // triple "x86_64-unknown-linux-gnu"` - if (Triple.getArch() == llvm::Triple::hexagon) - return; - - // Adjust the resource-dir - llvm::cantFail(Interp->ParseAndExecute(ExceptionCode)); - testing::internal::CaptureStdout(); - auto ThrowException = - (int (*)())llvm::cantFail(Interp->getSymbolAddress("throw_exception")); - EXPECT_ANY_THROW(ThrowException()); - std::string CapturedStdOut = testing::internal::GetCapturedStdout(); - EXPECT_EQ(CapturedStdOut, "Caught: 'In JIT'\n"); - - llvm::llvm_shutdown(); -} - -} // end anonymous namespace diff --git a/clang/unittests/Interpreter/InterpreterTest.cpp b/clang/unittests/Interpreter/InterpreterTest.cpp index dc045a40a699d..6ce43748ae049 100644 --- a/clang/unittests/Interpreter/InterpreterTest.cpp +++ b/clang/unittests/Interpreter/InterpreterTest.cpp @@ -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" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits