Commit 55852ebc authored by Naman Dixit's avatar Naman Dixit

Added LLVM IR compiler and interpreter

parents
#!/usr/bin/env bash
function buildDepend () {
$@
echo "Entering directory \`$(pwd)'"
}
function cleanTarget () {
if [ -f "${NTarget}" ] ; then rm "${1}" ; fi
}
function emitOutput () {
printf "\033[36;1m${1}\033[0m\n"
}
if [ -z ${BuildPlatform+x} ]; then
BuildPlatform=linux
fi
if [ -z ${BuildArchitecture+x} ]; then
BuildArchitecture=x64
fi
ProjectRoot="$( cd "$(dirname "$0")" ; pwd -P)" # Directory in which the script is located
pushd ${ProjectRoot}
echo "Entering directory \`$(pwd)'"
BuildDirectory="bin/${BuildPlatform}/${BuildArchitecture}"
mkdir -p ${BuildDirectory}
VersionNumberOld=$(< ./version.${BuildPlatform})
VersionNumber=$((${VersionNumberOld} + 1))
echo ${VersionNumber} > ./version.${BuildPlatform}
#######################################################################
# BUILD
#######################################################################
Source="src/main.cpp"
Target="bin/${BuildPlatform}/${BuildArchitecture}/gazelle-native"
CompilerFlags="-iquote ${ProjectRoot}/src $(llvm-config-13 --cxxflags) \
-g3 -O0 -fno-strict-aliasing -fwrapv -msse2 \
"
LanguageFlags="--std=c++17 -DBUILD_INTERNAL -DBUILD_SLOW -DBUILD_DEBUG -D_GNU_SOURCE \
-DBUILD_NUMBER=${VersionNumber} \
-D_POSIX_C_SOURCE=200809L -D_DEFAULT_SOURCE \
"
WarningFlags="-Weverything -Wpedantic -pedantic-errors -Werror \
-Wno-c++98-compat \
"
LinkerFlags="-static-libgcc -pthread -ldl $(llvm-config-13 --ldflags --libs) -lncurses \
-lclangFrontendTool -lclangFrontend -lclangDriver -lclangSerialization -lclangCodeGen \
-lclangParse -lclangSema -lclangStaticAnalyzerFrontend -lclangStaticAnalyzerCheckers \
-lclangStaticAnalyzerCore -lclangAnalysis -lclangARCMigrate -lclangRewriteFrontend \
-lclangEdit -lclangAST -lclangLex -lclangBasic \
-Wl,-rpath=\${ORIGIN} -Wl,-z,origin -Wl,--enable-new-dtags \
"
cleanTarget ${Target}
clang++-13 ${CompilerFlags} ${LanguageFlags} ${WarningFlags} \
${Source} \
-o ${Target} \
${LinkerFlags}
popd
/*
* Creator: Naman Dixit
* Notice: © Copyright 2022 Naman Dixit
*/
#include <cerrno>
#include <iostream>
#include <string>
#include <vector>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreserved-id-macro"
#pragma clang diagnostic ignored "-Wunused-parameter"
#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
#pragma clang diagnostic ignored "-Wold-style-cast"
#pragma clang diagnostic ignored "-Wshadow-field-in-constructor"
#pragma clang diagnostic ignored "-Wundef"
#pragma clang diagnostic ignored "-Wmissing-variable-declarations"
#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
#pragma clang diagnostic ignored "-Wsign-conversion"
#pragma clang diagnostic ignored "-Wimplicit-int-conversion"
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
#pragma clang diagnostic ignored "-Wshadow-field"
#pragma clang diagnostic ignored "-Wpadded"
#pragma clang diagnostic ignored "-Wcomma"
#pragma clang diagnostic ignored "-Wextra-semi-stmt"
#pragma clang diagnostic ignored "-Wshadow"
#pragma clang diagnostic ignored "-Wmissing-noreturn"
#pragma clang diagnostic ignored "-Wsigned-enum-bitfield"
#pragma clang diagnostic ignored "-Wswitch-enum"
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
#pragma clang diagnostic ignored "-Wextra-semi"
#pragma clang diagnostic ignored "-Wdeprecated-copy-with-dtor"
#pragma clang diagnostic ignored "-Wexit-time-destructors"
#pragma clang diagnostic ignored "-Wglobal-constructors"
#pragma clang diagnostic ignored "-Wheader-hygiene"
#pragma clang diagnostic ignored "-Wsuggest-destructor-override"
#pragma clang diagnostic ignored "-Winconsistent-missing-destructor-override"
#pragma clang diagnostic ignored "-Wshift-sign-overflow"
#pragma clang diagnostic ignored "-Wweak-vtables"
#pragma clang diagnostic ignored "-Wundefined-func-template"
#pragma clang diagnostic ignored "-Wformat-nonliteral"
#pragma clang diagnostic ignored "-Wreserved-identifier"
#pragma clang diagnostic ignored "-Wenum-enum-conversion"
#pragma clang diagnostic ignored "-Wcast-align"
#pragma clang diagnostic ignored "-Wduplicate-enum"
#pragma clang diagnostic ignored "-Wbitfield-enum-conversion"
#include <llvm/ADT/StringExtras.h>
#include <llvm/ADT/Triple.h>
#include <llvm/Bitcode/BitcodeReader.h>
#include <llvm/CodeGen/CommandFlags.h>
#include <llvm/CodeGen/LinkAllCodegenComponents.h>
#include <llvm/Config/llvm-config.h>
#include <llvm/ExecutionEngine/GenericValue.h>
#include <llvm/ExecutionEngine/Interpreter.h>
#include <llvm/ExecutionEngine/JITEventListener.h>
#include <llvm/ExecutionEngine/JITSymbol.h>
#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/ExecutionEngine/ObjectCache.h>
#include <llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h>
#include <llvm/ExecutionEngine/Orc/DebugUtils.h>
#include <llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h>
#include <llvm/ExecutionEngine/Orc/EPCEHFrameRegistrar.h>
#include <llvm/ExecutionEngine/Orc/ExecutionUtils.h>
#include <llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h>
#include <llvm/ExecutionEngine/Orc/LLJIT.h>
#include <llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h>
#include <llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h>
#include <llvm/ExecutionEngine/Orc/SymbolStringPool.h>
#include <llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h>
#include <llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h>
#include <llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Type.h>
#include <llvm/IR/Verifier.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/Object/Archive.h>
#include <llvm/Object/ObjectFile.h>
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/Debug.h>
#include <llvm/Support/DynamicLibrary.h>
#include <llvm/Support/Format.h>
#include <llvm/Support/InitLLVM.h>
#include <llvm/Support/ManagedStatic.h>
#include <llvm/Support/MathExtras.h>
#include <llvm/Support/Memory.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/Support/Path.h>
#include <llvm/Support/PluginLoader.h>
#include <llvm/Support/Process.h>
#include <llvm/Support/Program.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/WithColor.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Transforms/Instrumentation.h>
#include <llvm/IR/AssemblyAnnotationWriter.h>
#include <clang/Lex/PreprocessorOptions.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Basic/DiagnosticOptions.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
#include <clang/CodeGen/CodeGenAction.h>
#include <clang/Basic/TargetInfo.h>
#pragma clang diagnostic pop
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wglobal-constructors"
#pragma clang diagnostic ignored "-Wexit-time-destructors"
static llvm::codegen::RegisterCodeGenFlags CGF;
static llvm::ExitOnError ExitOnErr;
#pragma clang diagnostic pop
int main(int argc, char *argv[], char * const *envp) {
llvm::InitLLVM X(argc, argv);
ExitOnErr.setBanner("Error: ");
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetAsmParser();
llvm::InitializeAllTargets();
std::string code_name = "test.c";
std::string code = R"END(
#include <stdio.h>
int main (void)
{
printf("Hello, World!\n");
return 42;
}
)END";
// Prepare compilation arguments
std::vector<const char *> args;
args.push_back(code_name.c_str());
// Prepare DiagnosticEngine
clang::DiagnosticOptions DiagOpts;
clang::TextDiagnosticPrinter *textDiagPrinter =
new clang::TextDiagnosticPrinter(llvm::errs(),
&DiagOpts);
clang::IntrusiveRefCntPtr<clang::DiagnosticIDs> pDiagIDs;
clang::DiagnosticsEngine *pDiagnosticsEngine =
new clang::DiagnosticsEngine(pDiagIDs,
&DiagOpts,
textDiagPrinter);
// Initialize CompilerInvocation
clang::CompilerInvocation *CI = new clang::CompilerInvocation();
args.push_back("-resource-dir");
args.push_back("/usr/lib/llvm-10/lib/clang/10.0.0");
args.push_back("-internal-isystem");
args.push_back("/usr/local/include");
args.push_back("-internal-isystem");
args.push_back("/usr/lib/llvm-10/lib/clang/10.0.0/include");
args.push_back("-internal-externc-isystem");
args.push_back("/usr/include/x86_64-linux-gnu");
args.push_back("-internal-externc-isystem");
args.push_back("/include");
args.push_back("-internal-externc-isystem");
args.push_back("/usr/include");
llvm::ArrayRef<const char*> args_array(args);
clang::CompilerInvocation::CreateFromArgs(*CI, args_array, *pDiagnosticsEngine);
// Map code filename to a memoryBuffer
llvm::StringRef code_data(code);
std::unique_ptr<llvm::MemoryBuffer> buffer = llvm::MemoryBuffer::getMemBufferCopy(code_data);
CI->getPreprocessorOpts().addRemappedFile(code_name, buffer.get());
// Create and initialize CompilerInstance
clang::CompilerInstance Clang;
std::shared_ptr<clang::CompilerInvocation> CI_shared_ptr(CI);
Clang.setInvocation(CI_shared_ptr);
Clang.createDiagnostics();
// Set target (I guess I can initialize only the BPF target, but I don't know how)
const std::shared_ptr<clang::TargetOptions> targetOptions = std::make_shared<clang::TargetOptions>();
targetOptions->Triple = std::string("bpf");
clang::TargetInfo *pTargetInfo = clang::TargetInfo::CreateTargetInfo(*pDiagnosticsEngine,targetOptions);
Clang.setTarget(pTargetInfo);
// Create and execute action
clang::CodeGenAction *compilerAction = new clang::EmitLLVMOnlyAction();
//clang::CodeGenAction *compilerAction = new clang::EmitAssemblyAction();
Clang.ExecuteAction(*compilerAction);
llvm::LLVMContext Context;
llvm::SMDiagnostic Err;
std::unique_ptr<llvm::Module> Owner = compilerAction->takeModule();
llvm::Module *Mod = Owner.get();
if (!Mod) {
Err.print(code_name.c_str(), llvm::errs());
exit(1);
}
{
llvm::ExitOnError eoe(std::string(code_name) +
": bitcode didn't read correctly: ");
eoe(Mod->materializeAll());
}
std::unique_ptr<llvm::AssemblyAnnotationWriter> Annotator;
std::string dis_str;
llvm::raw_string_ostream dis_stream(dis_str);
Mod->print(dis_stream, Annotator.get());
std::cout << std::endl << std::endl << "\033[1;34m" << dis_str << std::endl << "\033[0m" << std::endl;
std::string ErrorMsg;
llvm::EngineBuilder builder(std::move(Owner));
builder.setErrorStr(&ErrorMsg);
builder.setMArch(llvm::codegen::getMArch());
builder.setMCPU(llvm::codegen::getCPUStr());
builder.setMAttrs(llvm::codegen::getFeatureList());
if (auto RM = llvm::codegen::getExplicitRelocModel()) {
builder.setRelocationModel(RM.getValue());
}
if (auto CM = llvm::codegen::getExplicitCodeModel()) {
builder.setCodeModel(CM.getValue());
}
builder.setEngineKind(llvm::EngineKind::Interpreter);
builder.setOptLevel(llvm::CodeGenOpt::None);
llvm::TargetOptions Options = llvm::codegen::InitTargetOptionsFromCodeGenFlags(llvm::Triple());
if (llvm::codegen::getFloatABIForCalls() != llvm::FloatABI::Default) {
Options.FloatABIType = llvm::codegen::getFloatABIForCalls();
}
builder.setTargetOptions(Options);
std::unique_ptr<llvm::ExecutionEngine> EE(builder.create());
if (!EE) {
if (!ErrorMsg.empty())
llvm::WithColor::error(llvm::errs(), code_name)
<< "error creating EE: " << ErrorMsg << "\n";
else
llvm::WithColor::error(llvm::errs(), code_name) << "unknown error creating EE!\n";
exit(1);
}
EE->DisableLazyCompilation(false);
if (llvm::StringRef(code_name).endswith(".bc"))
code_name.erase(code_name.length() - 3);
llvm::Function *EntryFn = Mod->getFunction("main");
if (!EntryFn) {
llvm::WithColor::error(llvm::errs(), code_name.c_str())
<< '\'' << "main" << "\' function not found in module.\n";
return -1;
}
errno = 0;
int Result = -1;
llvm::FunctionCallee Exit = Mod->getOrInsertFunction("exit",
llvm::Type::getVoidTy(Context),
llvm::Type::getInt32Ty(Context));
EE->runStaticConstructorsDestructors(false);
(void)EE->getPointerToFunction(EntryFn);
// Run main.
Result = EE->runFunctionAsMain(EntryFn, std::vector<std::string>(), envp);
// Run static destructors.
EE->runStaticConstructorsDestructors(true);
if (llvm::Function *ExitF =
llvm::dyn_cast<llvm::Function>(Exit.getCallee()->stripPointerCasts())) {
if (ExitF->getFunctionType() == Exit.getFunctionType()) {
std::vector<llvm::GenericValue> Args;
llvm::GenericValue ResultGV;
ResultGV.IntVal = llvm::APInt(32, static_cast<uint64_t>(Result));
Args.push_back(ResultGV);
EE->runFunction(ExitF, Args);
llvm::WithColor::error(llvm::errs(), code_name.c_str())
<< "exit(" << Result << ") returned!\n";
abort();
}
llvm::WithColor::error(llvm::errs(), code_name.c_str()) << "exit defined with wrong prototype!\n";
abort();
}
return Result;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment