LLVM 3.4 tag modified instructions - llvm

I'm would like to be able to detect which part of a program has been modified by a previous LLVM pass.
How can I tag instruction / basic blocks and function such as I can retrieve that a pass P1 has previously modified this part of the code ?
I would like to achieve something like:
// First pass
...
tag<bool>(instruction, "modified");
// Second pass
if(has_tag<bool>(instruction, "modified"))
do_something...
Is there a feature in LLVM allowing to make such tag system ?

You may wish to look at the LLVM diff engine in its the toolset:
https://github.com/llvm/llvm-project/blob/main/llvm/tools/llvm-diff/llvm-diff.cpp

Related

How to customise pragma in C?

I want to ask what is the simplest way to build a parser to recognise my customised pragmas in C/C++ code. Yes, a simple bash script can do but I am wondering if there is any formal way to do through Clang or LLVM? I tried to check Clang AST but I cannot find any pragmas.
For instance:
int foo1(){
#pragma hi k=1
...
}
int foo2(){
#pragma hello k=7
...
}
I want the pass returns the following:
function foo1 has hi and k=1
function foo2 has hello and k=7
Thanks.
Pragma handling needs to be done in the following parts:
Add a handler in ParsePragma.cpp file (there are examples how to do that). In this step you can parse the pragma token by token and store corresponding information in the AST (possibly the best way to transfer data from this stage to the later stages).
If you need to handle this information in the passes working on LLVM IR, then you need to attach the information previously stored into AST into an IR related classes, in your case it seems the llvm::Function is the place where to keep that. During this process it is needed to update 'lib/AsmParser/LLParser.cpp', 'lib/AsmParser/LLLexer.cpp' and 'lib/IR/AsmWriter.cpp' files. This will allow to read and write the information stored in IR.
Finally if you need to write extra information kept in IR into the assembler file then you will need to update 'lib/CodeGen/AsmPrinter/AsmPrinter.cpp' file correspondingly.

LLVM GetAnalysis() failing with required passes

I have a custom set of passes created using LLVM to run on some bitcode.
I've managed to get it to compile, but whenever I try to run it with a pass that calls getAnalysis() on another pass type it fails with:
Assertion `ResultPass && "getAnalysis*() called on an analysis that was not " "'required' by pass!"' failed.
The custom pass that is calling getAnalysis() requires its type, specifically;
bool Operators::doInitialization(){
ParseConfig &parseConfig = getAnalysis<ParseConfig>(); // Fails here.
}
.
.
.
void Operators::getAnalysisUsage(AnalysisUsage &AU) const{
AU.addRequired<ParseConfig>();
return;
}
I've spent a few days on this and am quite lost. I know the following is true:
ParseConfig is registered successfully via the RegisterPass<> template, and I have stepped through it in GDB to find that it does get registered.
Also using GDB I have found that when looking into getAnalysis() that the list of registered passes is always empty (which causes the assertion).
Important Note: I will eventually be using this on a Fortran project which is compiled with Flang, thus the LLVM library version I'm using is the Flang fork (found here). That fork is right around LLVM 7.1, but the specific files associated with registering passes seems to not be different from the current LLVM library.
Move getAnalysis function from doInitialization to runOnFunction would make it work.
From LLVM page
This method call getAnalysis* returns a reference to the pass desired. You may get a runtime assertion failure if you attempt to get an analysis that you did not declare as required in your getAnalysisUsage implementation. This method can be called by your run* method implementation, or by any other local method invoked by your run* method.

Running standard optimization passes on a LLVM module

Say I have a valid LLVM module:
std::unique_ptr<llvm::Module> module;
I want to run LLVM traditional optimization passes on it:
llvm::PassBuilder passBuilder;
llvm::ModulePassManager modulePassManager = passBuilder.buildPerModuleDefaultPipeline(llvm::PassBuilder::OptimizationLevel::O3);
llvm::ModuleAnalysisManager moduleAnalysisManager;
passBuilder.registerModuleAnalyses(moduleAnalysisManager);
modulePassManager.run(*module, moduleAnalysisManager);
Unfortunately, the call crashes and debugging shows that the moduleAnalysisManager has only the module passes, but
not the function ones that are wrapped with the proxy class.
How should I setup modulePassManager to handle all (module) passes of a specific level? I don't have individual functions, so I can't run the function passes just on them.
The proper LLVM way is to create all analysisManagers and then link all of them together. Let's start by creating them:
llvm::PassBuilder passBuilder;
llvm::LoopAnalysisManager loopAnalysisManager(true); // true is just to output debug info
llvm::FunctionAnalysisManager functionAnalysisManager(true);
llvm::CGSCCAnalysisManager cGSCCAnalysisManager(true);
llvm::ModuleAnalysisManager moduleAnalysisManager(true);
Then we register each manager individually, and then we cross register them. This means that the number of managers here is fixed by design and if LLVM (7 at this time) changes the number of managers, this will need to be adapted:
passBuilder.registerModuleAnalyses(moduleAnalysisManager);
passBuilder.registerCGSCCAnalyses(cGSCCAnalysisManager);
passBuilder.registerFunctionAnalyses(functionAnalysisManager);
passBuilder.registerLoopAnalyses(loopAnalysisManager);
// This is the important line:
passBuilder.crossRegisterProxies(
loopAnalysisManager, functionAnalysisManager, cGSCCAnalysisManager, moduleAnalysisManager);
Once the passBuilder is created, we can finally make the optimization passes for the module with a call to the moduleAnalysisManager.
llvm::ModulePassManager modulePassManager =
passBuilder.buildPerModuleDefaultPipeline(llvm::PassBuilder::OptimizationLevel::O3);
modulePassManager.run(*module, moduleAnalysisManager);
This will run module level passes as well as all inner passes that LLVM can run on pieces of the module (function level, loop level...).

llvm irbuilder call instruction throwing exception on function inlining pass

I'm new to LLVM. I am using the clang c++ API to compile multiple stub files (in c) to IR, and then stick them together using IR builder (after linking them) to eventually run via JIT.
All this works great, unless I add a functionInlining pass to my optimizations, at which point one of these function calls made in IR builder will trigger the following exception when the pass manager is run:
Assertion failed: (New->getType() == getType() && "replaceAllUses of value with new value of different type!"), function replaceAllUsesWith, file /Users/mike/Development/llvm/llvm/lib/IR/Value.cpp, line 356.
This is how I make the call instruction (pretty straight forward):
Function *kernelFunc = mModule->getFunction( (kernel->Name() + StringRef("_") + StringRef(funcName)).str());
if (kernelFunc){
CallInst* newInst = builder.CreateCall(kernelFunc, args);
}
Later the module is optimized:
legacy::PassManager passMan;
PassManagerBuilder Builder;
Builder.OptLevel = 3;
//Builder.Inliner = llvm::createFunctionInliningPass(); //commenting this back in trigger the exception
Builder.populateModulePassManager(passMan);
passMan.run( *mModule ); //exception occurs before this call returns
Any ideas what to look for?
Try running llvm::verifyModule on your module to see if it's correct. You might have an error and have been getting lucky beforehand but it tripped something up in the inliner.
In general assertions check a subset of things that can be wrong with your module but verify checks a lot more.
It could be a bug in LLVM but more than likely it's a bad module, it's easy to happen.
So I finally setup my dev environment so I could inspect the assertion call in the debugger. I turns out the basic block being replaced had a different context set than the one it was being replaced with. going back and making sure IRBuilder was using the same context as the IR parsers solved the problem.

How do I use compiled stylesheets in saxon/c?

I downloaded the latest beta release of Saxon/C but I can't quite figure out how to use the compile stylesheet functionality. There's a function in the class XsltProcessor.h :-
void compile(const char* stylesheet);
that claims to compile a stylesheet but I can't see anything that would apply this compiled stylesheet to an actual source file.
The compile method allows you to supply the stylesheet as a string representation which is then compiled and cached internally for later use.
To execute the stylesheet call the method xslt->xsltApplyStylesheet("sample.xml", NULL) but supply NULL in the argument where you would pass the file name.
You could also supply the source document as a string using the methods parseXmlString and setSourceValue. In the xsltApplyStylesheet you pass NULL for the source file argument.
We will make the usability better in next release.
Have you tried the sample code here? It uses XsltProcessor.xsltApplyStylesheet(), which is documented here.
The sample code seems to have a typo in that it says test->xsltApplyStylesheet() when it means xslt->xsltApplyStylesheet().
I'm not sure what the compile() method does with its results, or how to use them.