This maybe a rookie question but is there a way to integrate my LLVM modulepass to be called by default during the transformation phase?
Right now I am using this syntax to load my pass and register it
~/llvm/llvm/build/Debug+Asserts/bin/clang -Xclang -load -Xclang ~/llvm/llvm/build/Debug+Asserts/lib/SOMEPASSLIB.so
(The problem is when I want to build some package with this pass, the compiler accepts it when I say, pass the loading part as CFLAGS env variable, but some makefiles use CFLAGS for linking too, and the linker has no idea what it can do with this information and fails the build :\ )
There are couple of files you need to modify in order to define your pass inside LLVM core:
i) inside your pass: loadable pass is registered like this (assuming your pass name is FunctionInfo):
char FunctionInfo::ID = 0;
RegisterPass<FunctionInfo> X("function-info", "Functions Information");
you need to change it to be like this:
char FunctionInfo::ID = 0;
INITIALIZE_PASS_BEGIN(FunctionInfo, "function-info", "Gathering Function info", false, false)
INITIALIZE_PASS_DEPENDENCY(DominatorTree)
INITIALIZE_PASS_DEPENDENCY(LoopInfo)
.... // initialize all passes which your pass needs
INITIALIZE_PASS_END(FunctionInfo, "function-info", "gathering function info", false, false)
ModulePass *llvm::createFunctionInfoPass() { return new FunctionInfo(); }
ii) you need to register your pass inside llvm as well, at least in InitializePasses.h and LinkAllPasses.h.
in LinkAllPasses.h you should add :
(void)llvm::createFunctionInfoPass();
and in InitializePasses.h add :
void initializeFunctionInfoPass(PassRegistry &);
iii) beside this modifications you might need to change another file depend on where you are going to add your pass. for instance if you are going to add it in lib/Analysis/ you also need to add one line to Analysis.cpp as below :
initializeFunctionInfoPass(Registry);
or if you are going to add it as new Scalar Transform you need to modify both Scalar.h and Scalar.cpp likewise.
Related
I want to get loopinfo in each function by iterating through functions in Module Pass. My code is as follows:
for (auto &F:M) {
if(!F.isDeclaration()){
LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>(F).getLoopInfo();
}
}
However, there is an error, I think my variable Settings should conform to the first function definition, how should I resolve.
clang-12: /llvmtest/llvm/lib/IR/LegacyPassManager.cpp:1645: virtual
std::tuple<llvm::Pass*, bool>
{anonymous}::MPPassManager::getOnTheFlyPass(llvm::Pass*,
llvm::AnalysisID, llvm::Function&): Assertion `FPP && “Unable to find
on the fly pass”’ failed. PLEASE submit a bug report to
https://bugs.llvm.org/ and include the crash backtrace, preprocessed
source, and associated run script.
You can not do this with the legacy pass manager. In the legacy pass manager, every pass could only get info from same-scoped passes -- module from module, function from function, loop from loop, plus one exception allowing function passes to get data from module passes.
With the new pass manager, you'd create a LoopAnalysisManager and add the analysis pass you want and run it. See https://llvm.org/docs/NewPassManager.html#using-analyses .
Note that most of LLVM is presently written to support both pass managers at once. If you do this, you'll need to write your pass differently from most of LLVM's passes, you can't use the types with names like "WrapperPass" that exist to support both legacy and new pass managers.
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.
Let me elaborate on the title:
I want to implement a system that would allow me to enable/disable/modify the general behavior of my program. Here are some examples:
I could switch off and on logging
I could change if my graphing program should use floating or pixel coordinates
I could change if my calculations should be based upon some method or some other method
I could enable/disable certain aspects like maybe a extension api
I could enable/disable some basic integrated profiler (if I had one)
These are some made-up examples.
Now I want to know what the most common solution for this sort of thing is.
I could imagine this working with some sort of singelton class that gets instanced globally or in some other globally available object. Another thing that would be possible would be just constexpr or other variables floating around in a namespace, again globally.
However doing something like that, globally, feels like bad practise.
second part of the question
This might sound like I cant decide what I want, but I want a way to modify all these switches/flags or whatever they are actually called in a single location, without tying any of my classes to it. I don't know if this is possible however.
Why don't I want to do that? Well I like to make my classes somewhat reusable and I don't like tying classes together, unless its required by the DRY principle and or inheritance. I basically couldn't get rid of the flags without modifying the possible hundreds of classes that used them.
What I have tried in the past
Having it all as compiler defines. This worked reasonably well, however I didnt like that I couldnt make it so if the flag file was gone there were some sort of default settings that would make the classes themselves still operational and changeable (through these default values)
Having it as a class and instancing it globally (system class). Worked ok, however I didnt like instancing anything globally. Also same problem as above
Instancing the system class locally and passing it to the classes on construction. This was kinda cool, since I could make multiple instruction sets. However at the same time that kinda ruined the point since it would lead to things that needed to have one flag set the same to have them set differently and therefore failing to properly work together. Also passing it on every construction was a pain.
A static class. This one worked ok for the longest time, however there is still the problem when there are missing dependencies.
Summary
Basically I am looking for a way to have a single "place" where I can mess with some values (bools, floats etc.) and that will change the behaviour of all classes using them for whatever, where said values either overwrite default values or get replaced by default values if said "place" isnt defined.
If a Singleton class does not work for you , maybe using a DI container may fit in your third approach? It may help with the construction and make the code more testable.
There are some DI frameworks for c++, like https://github.com/google/fruit/wiki or https://github.com/boost-experimental/di which you can use.
If you decide to use switch/flags, pay attention for "cyclometric complexity".
If you do not change the skeleton of your algorithm but only his behaviour according to the objets in parameter, have a look at "template design pattern". This method allow you to define a generic algorithm and specify particular step for a particular situation.
Here's an approach I found useful; I don't know if it's what you're looking for, but maybe it will give you some ideas.
First, I created a BehaviorFlags.h file that declares the following function:
// Returns true iff the given feature/behavior flag was specified for us to use
bool IsBehaviorFlagEnabled(const char * flagName);
The idea being that any code in any of your classes could call this function to find out if a particular behavior should be enabled or not. For example, you might put this code at the top of your ExtensionsAPI.cpp file:
#include "BehaviorFlags.h"
static const enableExtensionAPI = IsBehaviorFlagEnabled("enable_extensions_api");
[...]
void DoTheExtensionsAPIStuff()
{
if (enableExtensionsAPI == false) return;
[... otherwise do the extensions API stuff ...]
}
Note that the IsBehaviorFlagEnabled() call is only executed once at program startup, for best run-time efficiency; but you also have the option of calling IsBehaviorFlagEnabled() on every call to DoTheExtensionsAPIStuff(), if run-time efficiency is less important that being able to change your program's behavior without having to restart your program.
As far as how the IsBehaviorFlagEnabled() function itself is implemented, it looks something like this (simplified version for demonstration purposes):
bool IsBehaviorFlagEnabled(const char * fileName)
{
// Note: a real implementation would find the user's home directory
// using the proper API and not just rely on ~ to expand to the home-dir path
std::string filePath = "~/MyProgram_Settings/";
filePath += fileName;
FILE * fpIn = fopen(filePath.c_str(), "r"); // i.e. does the file exist?
bool ret = (fpIn != NULL);
fclose(fpIn);
return ret;
}
The idea being that if you want to change your program's behavior, you can do so by creating a file (or folder) in the ~/MyProgram_Settings directory with the appropriate name. E.g. if you want to enable your Extensions API, you could just do a
touch ~/MyProgram_Settings/enable_extensions_api
... and then re-start your program, and now IsBehaviorFlagEnabled("enable_extensions_api") returns true and so your Extensions API is enabled.
The benefits I see of doing it this way (as opposed to parsing a .ini file at startup or something like that) are:
There's no need to modify any "central header file" or "registry file" every time you add a new behavior-flag.
You don't have to put a ParseINIFile() function at the top of main() in order for your flags-functionality to work correctly.
You don't have to use a text editor or memorize a .ini syntax to change the program's behavior
In a pinch (e.g. no shell access) you can create/remove settings simply using the "New Folder" and "Delete" functionality of the desktop's window manager.
The settings are persistent across runs of the program (i.e. no need to specify the same command line arguments every time)
The settings are persistent across reboots of the computer
The flags can be easily modified by a script (via e.g. touch ~/MyProgram_Settings/blah or rm -f ~/MyProgram_Settings/blah) -- much easier than getting a shell script to correctly modify a .ini file
If you have code in multiple different .cpp files that needs to be controlled by the same flag-file, you can just call IsBehaviorFlagEnabled("that_file") from each of them; no need to have every call site refer to the same global boolean variable if you don't want them to.
Extra credit: If you're using a bug-tracker and therefore have bug/feature ticket numbers assigned to various issues, you can creep the elegance a little bit further by also adding a class like this one:
/** This class encapsulates a feature that can be selectively disabled/enabled by putting an
* "enable_behavior_xxxx" or "disable_behavior_xxxx" file into the ~/MyProgram_Settings folder.
*/
class ConditionalBehavior
{
public:
/** Constructor.
* #param bugNumber Bug-Tracker ID number associated with this bug/feature.
* #param defaultState If true, this beheavior will be enabled by default (i.e. if no corresponding
* file exists in ~/MyProgram_Settings). If false, it will be disabled by default.
* #param switchAtVersion If specified, this feature's default-enabled state will be inverted if
* GetMyProgramVersion() returns any version number greater than this.
*/
ConditionalBehavior(int bugNumber, bool defaultState, int switchAtVersion = -1)
{
if ((switchAtVersion >= 0)&&(GetMyProgramVersion() >= switchAtVersion)) _enabled = !_enabled;
std::string fn = defaultState ? "disable" : "enable";
fn += "_behavior_";
fn += to_string(bugNumber);
if ((IsBehaviorFlagEnabled(fn))
||(IsBehaviorFlagEnabled("enable_everything")))
{
_enabled = !_enabled;
printf("Note: %s Behavior #%i\n", _enabled?"Enabling":"Disabling", bugNumber);
}
}
/** Returns true iff this feature should be enabled. */
bool IsEnabled() const {return _enabled;}
private:
bool _enabled;
};
Then, in your ExtensionsAPI.cpp file, you might have something like this:
// Extensions API feature is tracker #4321; disabled by default for now
// but you can try it out via "touch ~/MyProgram_Settings/enable_feature_4321"
static const ConditionalBehavior _feature4321(4321, false);
// Also tracker #4222 is now enabled-by-default, but you can disable
// it manually via "touch ~/MyProgram_Settings/disable_feature_4222"
static const ConditionalBehavior _feature4222(4222, true);
[...]
void DoTheExtensionsAPIStuff()
{
if (_feature4321.IsEnabled() == false) return;
[... otherwise do the extensions API stuff ...]
}
... or if you know that you are planning to make your Extensions API enabled-by-default starting with version 4500 of your program, you can set it so that Extensions API will be enabled-by-default only if GetMyProgramVersion() returns 4500 or greater:
static ConditionalBehavior _feature4321(4321, false, 4500);
[...]
... also, if you wanted to get more elaborate, the API could be extended so that IsBehaviorFlagEnabled() can optionally return a string to the caller containing the contents of the file it found (if any), so that you could do shell commands like:
echo "opengl" > ~/MyProgram_Settings/graphics_renderer
... to tell your program to use OpenGL for its 3D graphics, or etc:
// In Renderer.cpp
std::string rendererType;
if (IsDebugFlagEnabled("graphics_renderer", &rendererType))
{
printf("The user wants me to use [%s] for rendering 3D graphics!\n", rendererType.c_str());
}
else printf("The user didn't specify what renderer to use.\n");
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.
I want to build a control flow graph diagram in llvm in one of my passes. I currently use the following to show the CFG
block->getParent()->viewCFG(); //block is a basic block
The problem is that it pops up a windows. I just want to dump the cfg at that particular program point, as a dot file (or jpg if possible), not to show up in a window. How can I do the same? I am using llvm 3.1.
NOTE: I am modifying the cfg in my pass, before that program point. Hence I cannot use the opt -view-cfg.
Update:
Thanks to Mishr, I was able to draw to graph with this
WriteGraph(File, (const llvm::Function*) &fun, true, "test"); //I have also tired with false
The CFG is shown. But the nodes are blank. How can I show the contents of the node
Take a look at this, read the comment before the viewCFG() function.
http://llvm.org/docs/doxygen/html/CFGPrinter_8cpp_source.html
The viewCFG() function is intended for printing the CFG in a new window. To dump the CFG in a file you have to use CFGPrinter pass which can be invoked by the handle dot-cfg.
Let me add something to ssubbotin's answer.
The question is about
DOTGraphTraits<const Function*>
provided by CFGPrinter.
In my case I had to use the call like that:
WriteGraph<const llvm::Function*>(...)
to make it work.
The function template definition is like the following:
template<typename GraphType>
raw_ostream &WriteGraph(raw_ostream &O, const GraphType &G,
bool ShortNames = false,
const Twine &Title = "")
so GraphType gets non-const with implicit template call.
You need to add include:
#include <llvm\Analysis\CFGPrinter.h>
It has getEdgeSourceLabel implementation inside which provides correct node labels.
In the same time, make sure you don't have <llvm\Support\CFG.h> file included since it provides empty labels by default.