Commit 3aeea185 authored by Naman Dixit's avatar Naman Dixit

Partial port of opt to gazelle

parent 55852ebc
### NOTES
See src/pass_plugin_demo/README.txt for a simple opt based pass.
......@@ -8,14 +8,13 @@
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <memory>
#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"
......@@ -34,72 +33,88 @@
#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"
#pragma clang diagnostic ignored "-Wused-but-marked-unused"
#pragma clang diagnostic ignored "-Wdocumentation"
#pragma clang diagnostic ignored "-Wformat-nonliteral"
#define DONT_GET_PLUGIN_LOADER_OPTION
#include <llvm/ADT/StringExtras.h>
#include <llvm/ADT/Triple.h>
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/RegionPass.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/AsmParser/Parser.h"
#include <llvm/Bitcode/BitcodeReader.h>
#include <llvm/CodeGen/CommandFlags.h>
#include <llvm/CodeGen/LinkAllCodegenComponents.h>
#include "llvm/CodeGen/TargetPassConfig.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/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/LLVMContext.h>
#include "llvm/IR/LLVMRemarkStreamer.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/LegacyPassNameParser.h"
#include <llvm/IR/Module.h>
#include <llvm/IR/Type.h>
#include <llvm/IR/Verifier.h>
#include <llvm/IR/AssemblyAnnotationWriter.h>
#include <llvm/IRReader/IRReader.h>
#include "llvm/InitializePasses.h"
#include "llvm/LinkAllIR.h"
#include "llvm/LinkAllPasses.h"
#include "llvm/MC/SubtargetFeature.h"
#include <llvm/Object/Archive.h>
#include <llvm/Object/ObjectFile.h>
#include "llvm/Remarks/HotnessThresholdParser.h"
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/Debug.h>
#include <llvm/Support/DynamicLibrary.h>
#include "llvm/Support/FileSystem.h"
#include <llvm/Support/Format.h>
#include "llvm/Support/Host.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/PluginLoader.h"
#include <llvm/Support/Process.h>
#include <llvm/Support/Program.h>
#include <llvm/Support/SourceMgr.h>
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/TargetRegistry.h"
#include <llvm/Support/TargetSelect.h>
#include "llvm/Support/ToolOutputFile.h"
#include <llvm/Support/WithColor.h>
#include <llvm/Support/raw_ostream.h>
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/Coroutines.h"
#include <llvm/Transforms/Instrumentation.h>
#include <llvm/IR/AssemblyAnnotationWriter.h>
#include "llvm/Transforms/IPO/AlwaysInliner.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/IPO/WholeProgramDevirt.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Debugify.h"
#include <clang/Lex/PreprocessorOptions.h>
#include <clang/Frontend/CompilerInstance.h>
......@@ -108,27 +123,40 @@
#include <clang/CodeGen/CodeGenAction.h>
#include <clang/Basic/TargetInfo.h>
#undef DONT_GET_PLUGIN_LOADER_OPTION
#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;
static llvm::codegen::RegisterCodeGenFlags GLOBAL_code_gen_flags;
#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();
static
llvm::TargetMachine* GetTargetMachine (llvm::Triple TheTriple,
[[maybe_unused]] llvm::StringRef CPUStr,
[[maybe_unused]] llvm::StringRef FeaturesStr,
const llvm::TargetOptions &Options)
{
std::string Error;
const llvm::Target *TheTarget =
llvm::TargetRegistry::lookupTarget(llvm::codegen::getMArch(), TheTriple, Error);
// Some modules don't specify a triple, and this is okay.
if (!TheTarget) {
return nullptr;
}
return TheTarget->createTargetMachine(TheTriple.getTriple(),
llvm::codegen::getCPUStr(),
llvm::codegen::getFeaturesStr(),
Options,
llvm::codegen::getExplicitRelocModel(),
llvm::codegen::getExplicitCodeModel(),
llvm::CodeGenOpt::None);
}
int main(int argc, char *argv[], char * const *envp) {
std::string code_name = "test.c";
std::string code = R"END(
#include <stdio.h>
......@@ -139,83 +167,226 @@ int main (void)
}
)END";
llvm::InitLLVM llvm(argc, argv);
llvm::EnableDebugBuffering = true;
llvm::ExitOnError exit_on_err;
exit_on_err.setBanner("Error: ");
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetAsmParser();
// Prepare compilation arguments
std::vector<const char *> args;
args.push_back(code_name.c_str());
std::vector<const char *> compiler_args;
compiler_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
clang::DiagnosticOptions diagnostics_options;
clang::TextDiagnosticPrinter *diagnostics_printer = new clang::TextDiagnosticPrinter(llvm::errs(),
&diagnostics_options);
clang::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagnostics_id_ptr;
clang::DiagnosticsEngine *diagnostics_engine = new clang::DiagnosticsEngine(diagnostics_id_ptr,
&diagnostics_options,
diagnostics_printer);
clang::CompilerInvocation *compiler_invoke = new clang::CompilerInvocation();
compiler_args.push_back("-resource-dir");
compiler_args.push_back("/usr/lib/llvm-10/lib/clang/10.0.0");
compiler_args.push_back("-internal-isystem");
compiler_args.push_back("/usr/local/include");
compiler_args.push_back("-internal-isystem");
compiler_args.push_back("/usr/lib/llvm-10/lib/clang/10.0.0/include");
compiler_args.push_back("-internal-externc-isystem");
compiler_args.push_back("/usr/include/x86_64-linux-gnu");
compiler_args.push_back("-internal-externc-isystem");
compiler_args.push_back("/include");
compiler_args.push_back("-internal-externc-isystem");
compiler_args.push_back("/usr/include");
llvm::ArrayRef<const char*> compiler_args_array(compiler_args);
clang::CompilerInvocation::CreateFromArgs(*compiler_invoke, compiler_args_array, *diagnostics_engine);
llvm::StringRef code_data(code);
std::unique_ptr<llvm::MemoryBuffer> buffer = llvm::MemoryBuffer::getMemBufferCopy(code_data);
CI->getPreprocessorOpts().addRemappedFile(code_name, buffer.get());
std::unique_ptr<llvm::MemoryBuffer> compiler_buffer = llvm::MemoryBuffer::getMemBufferCopy(code_data);
compiler_invoke->getPreprocessorOpts().addRemappedFile(code_name, compiler_buffer.get());
clang::CompilerInstance compiler_instance;
std::shared_ptr<clang::CompilerInvocation> compiler_invoke_shared_ptr(compiler_invoke);
compiler_instance.setInvocation(compiler_invoke_shared_ptr);
compiler_instance.createDiagnostics();
const std::shared_ptr<clang::TargetOptions> compiler_target_options = std::make_shared<clang::TargetOptions>();
compiler_target_options->Triple = std::string("bpf");
clang::TargetInfo *compiler_target_info = clang::TargetInfo::CreateTargetInfo(*diagnostics_engine,
compiler_target_options);
compiler_instance.setTarget(compiler_target_info);
// Create and initialize CompilerInstance
clang::CompilerInstance Clang;
std::shared_ptr<clang::CompilerInvocation> CI_shared_ptr(CI);
Clang.setInvocation(CI_shared_ptr);
Clang.createDiagnostics();
clang::CodeGenAction *compiler_action = new clang::EmitLLVMOnlyAction();
compiler_instance.ExecuteAction(*compiler_action);
// 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::InitializeAllTargets();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmPrinters();
llvm::InitializeAllAsmParsers();
// Initialize passes
llvm::PassRegistry &Registry = *llvm::PassRegistry::getPassRegistry();
llvm::initializeCore(Registry);
llvm::initializeCoroutines(Registry);
llvm::initializeScalarOpts(Registry);
llvm::initializeObjCARCOpts(Registry);
llvm::initializeVectorization(Registry);
llvm::initializeIPO(Registry);
llvm::initializeAnalysis(Registry);
llvm::initializeTransformUtils(Registry);
llvm::initializeInstCombine(Registry);
llvm::initializeAggressiveInstCombine(Registry);
llvm::initializeInstrumentation(Registry);
llvm::initializeTarget(Registry);
// For codegen passes, only passes that do IR to IR transformation are
// supported.
llvm::initializeExpandMemCmpPassPass(Registry);
llvm::initializeScalarizeMaskedMemIntrinLegacyPassPass(Registry);
llvm::initializeCodeGenPreparePass(Registry);
llvm::initializeAtomicExpandPass(Registry);
llvm::initializeRewriteSymbolsLegacyPassPass(Registry);
llvm::initializeWinEHPreparePass(Registry);
llvm::initializeDwarfEHPrepareLegacyPassPass(Registry);
llvm::initializeSafeStackLegacyPassPass(Registry);
llvm::initializeSjLjEHPreparePass(Registry);
llvm::initializePreISelIntrinsicLoweringLegacyPassPass(Registry);
llvm::initializeGlobalMergePass(Registry);
llvm::initializeIndirectBrExpandPassPass(Registry);
llvm::initializeInterleavedLoadCombinePass(Registry);
llvm::initializeInterleavedAccessPass(Registry);
llvm::initializeEntryExitInstrumenterPass(Registry);
llvm::initializePostInlineEntryExitInstrumenterPass(Registry);
llvm::initializeUnreachableBlockElimLegacyPassPass(Registry);
llvm::initializeExpandReductionsPass(Registry);
llvm::initializeExpandVectorPredicationPass(Registry);
llvm::initializeWasmEHPreparePass(Registry);
llvm::initializeWriteBitcodePassPass(Registry);
llvm::initializeHardwareLoopsPass(Registry);
llvm::initializeTypePromotionPass(Registry);
llvm::initializeReplaceWithVeclibLegacyPass(Registry);
llvm::LLVMContext Context;
Context.setDiscardValueNames(false);
Context.enableDebugTypeODRUniquing();
llvm::SMDiagnostic Err;
std::unique_ptr<llvm::Module> Owner = compilerAction->takeModule();
std::unique_ptr<llvm::Module> Owner = compiler_action->takeModule();
llvm::Module *Mod = Owner.get();
if (!Mod) {
Err.print(code_name.c_str(), llvm::errs());
exit(1);
}
if (llvm::verifyModule(*Mod, &llvm::errs())) {
llvm::errs() << "error: input module is broken!\n";
return 1;
}
{
llvm::ExitOnError eoe(std::string(code_name) +
": bitcode didn't read correctly: ");
eoe(Mod->materializeAll());
}
llvm::updateVCallVisibilityInModule(*Mod,
/* WholeProgramVisibilityEnabledInLTO */ false,
/* DynamicExportSymbols */ {});
llvm::Triple ModuleTriple(Mod->getTargetTriple());
const llvm::TargetOptions Options = llvm::codegen::InitTargetOptionsFromCodeGenFlags(ModuleTriple);
std::string CPUStr, FeaturesStr;
llvm::TargetMachine *Machine = nullptr;
if (ModuleTriple.getArch()) {
CPUStr = llvm::codegen::getCPUStr();
FeaturesStr = llvm::codegen::getFeaturesStr();
Machine = GetTargetMachine(ModuleTriple, CPUStr, FeaturesStr, Options);
} else if (ModuleTriple.getArchName() != "unknown" &&
ModuleTriple.getArchName() != "") {
llvm::errs() << "unrecognized architecture '"
<< ModuleTriple.getArchName() << "' provided.\n";
return 1;
}
std::unique_ptr<llvm::TargetMachine> TM(Machine);
llvm::codegen::setFunctionAttributes(CPUStr, FeaturesStr, *Mod);
llvm::TargetLibraryInfoImpl TLII(ModuleTriple);
{ // Simplify LibCalls
llvm::LibFunc F;
// TODO(naman): Explore this, what does disabling functions actually means?
std::list<std::string> DisableBuiltins = {}; // Empty for now, further research necessary
for (auto &FuncName : DisableBuiltins)
if (TLII.getLibFunc(FuncName, F))
TLII.setUnavailable(F);
else {
llvm::errs() << "cannot disable nonexistent builtin function "
<< FuncName << '\n';
return 1;
}
}
llvm::DebugifyCustomPassManager Passes;
DebugifyStatsMap DIStatsMap;
DebugInfoPerPassMap DIPreservationMap;
Passes.add(new llvm::TargetLibraryInfoWrapperPass(TLII));
Passes.add(createTargetTransformInfoWrapperPass(TM ?
TM->getTargetIRAnalysis()
: llvm::TargetIRAnalysis()));
if (TM) {
// FIXME: We should dyn_cast this when supported.
auto &LTM = static_cast<llvm::LLVMTargetMachine &>(*TM);
llvm::Pass *TPC = LTM.createPassConfig(Passes);
Passes.add(TPC);
}
std::list<const PassInfo *> PassList;
for (unsigned i = 0; i < PassList.size(); ++i) {
const llvm::PassInfo *PassInf = PassList[i];
llvm::Pass *P = nullptr;
if (PassInf->getNormalCtor())
P = PassInf->getNormalCtor()();
else
llvm::errs() << argv[0] << ": cannot create pass: "
<< PassInf->getPassName() << "\n";
if (P) {
Passes.add(P);
}
}
std::unique_ptr<llvm::AssemblyAnnotationWriter> Annotator;
......@@ -250,12 +421,12 @@ int main (void)
builder.setOptLevel(llvm::CodeGenOpt::None);
llvm::TargetOptions Options = llvm::codegen::InitTargetOptionsFromCodeGenFlags(llvm::Triple());
llvm::TargetOptions Options_EE = llvm::codegen::InitTargetOptionsFromCodeGenFlags(llvm::Triple());
if (llvm::codegen::getFloatABIForCalls() != llvm::FloatABI::Default) {
Options.FloatABIType = llvm::codegen::getFloatABIForCalls();
Options_EE.FloatABIType = llvm::codegen::getFloatABIForCalls();
}
builder.setTargetOptions(Options);
builder.setTargetOptions(Options_EE);
std::unique_ptr<llvm::ExecutionEngine> EE(builder.create());
......@@ -308,9 +479,10 @@ int main (void)
<< "exit(" << Result << ") returned!\n";
abort();
}
llvm::WithColor::error(llvm::errs(), code_name.c_str()) << "exit defined with wrong prototype!\n";
abort();
}
return Result;
llvm::WithColor::error(llvm::errs(), code_name.c_str()) << "exit defined with wrong prototype!\n";
abort();
//return Result;
}
clang-13 -emit-llvm test.c -c -o test.bc
clang++-13 -fPIC -shared pass.cpp $(llvm-config-13 --ldflags --libs) -o pass.so
opt-13 -disable-output -enable-new-pm=0 -load ./pass.so -hello < test.bc
/*
* Creator: Naman Dixit
* Notice: © Copyright 2022 Naman Dixit
*/
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/IR/CallSite.h"
//#include "llvm/IR/Instruction.h"
using namespace llvm;
namespace {
//struct FunctionsNames : public FunctionPass {
class FunctionsNames : public FunctionPass {
public:
static char ID;
FunctionsNames() : FunctionPass(ID) {}
bool runOnFunction(Function &F) override {
// Print name of function
outs() << "*";
outs().write_escaped(F.getName()) << '\n';
for (auto& B : F) { // Iterate over each Basic Blocks in Functions
for (auto& I : B) { // Iterate over each Instructions in Basic Blocks
// Dynamically cast Instruction to CallInst.
// This step will return false for any instruction which is
// not a CallInst
if(CallBase *CI = dyn_cast<CallBase>(&I)) {
// Print out the function name
outs() << " |-" << CI->getCalledFunction()->getName() << "\n";
} else {
outs() << "Not a function\n";
}
}
}
return false;
}
}; // end of struct FunctionsNames
} // end of anonymous namespace
char FunctionsNames::ID = 0;
static RegisterPass<FunctionsNames> X("hello", "Display Function Names",
false /* Only looks at CFG */,
false /* Analysis Pass */);
static RegisterStandardPasses Y(
PassManagerBuilder::EP_EarlyAsPossible,
[](const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM) { PM.add(new FunctionsNames()); });
#include <stdio.h>
void a (void)
{
return;
}
int main() {
printf("hello world\n");
a();
return 0;
}
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