I need to dump the block liveness of source code using clang's API. I have tried printing the block liveness but got no success. Below is the code that I have tried
bool MyASTVisitor::VisitFunctionDecl(FunctionDecl *f) {
std::cout<<"Dump Liveness\n";
clang::AnalysisDeclContextManager adcm;
clang::AnalysisDeclContext *adc = adcm.getContext(llvm::cast<clang::Decl>(f));
//clang::LiveVariables *lv = clang::LiveVariables::create(*adc);
//clang::LiveVariables *lv = clang::LiveVariables::computeLiveness(*adc,false);
clang::LiveVariables *lv = adc->getAnalysis<LiveVariables>();
clang::LiveVariables::Observer *obs = new clang::LiveVariables::Observer();
lv->runOnAllBlocks(*obs);
lv->dumpBlockLiveness((f->getASTContext()).getSourceManager());
return true;
}
I have override Visitor Functions and have tried printing the liveness of a function. I have tried using create, computeLiveness and getAnalysis methods to get the LiveVariables object, but all the approaches failed. However no Liveness Information is displayed except the block numbers.
When I use command line arguments of clang to print the liveness it displays the output correctly.
I am using the following source code as test case taken from Live Variable Analysis Wikipedia
.
int main(int argc, char *argv[])
{
int a,b,c,d,x;
a = 3;
b = 5;
d = 4;
x = 100;
if(a>b){
c = a+b;
d = 2;
}
c = 4;
return b * d + c;
}
Could someone please point out where could I be wrong?
Thanks in advance.
I had the same issue, after some debugging of clang -cc1 -analyze -analyzer-checker=debug.DumpLiveVars I finally found the answer !
The issue is that the LiveVariables analysis does not explores sub-expressions (such as DeclRefExpr) by itself. It only relies on the CFG enumeration. By default the CFG only enumerates top-level statements.
You must call adc->getCFGBuildOptions().setAllAlwaysAdd() before getting any analysis from your AnalysisDeclContext. This will create elements for all sub-expressions in the CFGBlocks of the control-flow-graph.
Related
I am trying to test some code that has been generated from Matlab into C++.
To do this I am attempting to integrate and run the generated C++ code back into Matlab.
Here's the function I am trying to use (in Matlab pre-autogen)
function out = getRotationMatrix(aStruct)
out = aStruct.bank_rad*aStruct.heading_rad+aStruct.pitch_rad;
end
I autogenerate it using this ...
function varargout = AutoGenCode(varargin)
% Here we are attempting to generate a C++ class from a matlab function via a
% hosting function
% initialise
varargout = {};
% create instance of config object
cfg = coder.config('LIB');
% config options
cfg.MaxIdLength = int32(64);
cfg.TargetLang = 'C++';
cfg.CppPreserveClasses = 1;
cfg.EnableCustomReplacementTypes = true;
cfg.ReplacementTypes.uint32 = 'uint32_t';
cfg.CppInterfaceStyle = 'Methods';
cfg.CppInterfaceClassName = 'FrameTransformation';
cfg.FilePartitionMethod = 'MapMFileToCFile'; % or 'MapMFileToCFile' SingleFile
cfg.EnableVariableSizing = false;
%cfg.PreserveVariableNames = 'UserNames'; % Worse
%cfg.IncludeInitializeFcn = true;
cfg.PassStructByReference = true;
thisStruct.bank_rad = 2.1;
thisStruct.heading_rad = 3.1;
thisStruct.pitch_rad = 3.1;
codegen -config cfg getRotationMatrix -args {thisStruct} -report -preservearraydims -std:c++11
end
To move to another area (\unzipped) I use packNGo
load([pwd,'\codegen\lib\getRotationMatrix\buildInfo.mat'])
packNGo(buildInfo,'packType', 'hierarchical','fileName','portzingbit')
Now when i try to re-integrate it i am using clib
cd 'D:\thoros\Components\Frame Transformation Service\FT_V2\unzippedCode'
clibgen.generateLibraryDefinition('FrameTransformation.h','Libraries',{'getRotationMatrix.lib'})
build(defineFrameTransformation)
addpath('D:\thoros\Components\Frame Transformation Service\FT_V2\unzippedCode\FrameTransformation')
Where I had to define the < SHAPE > parameter in the defineFrameTransformation.mlx manually to be 1
When i try and use the function I cant pass a structure without an error
A = clib.FrameTransformation.FrameTransformation()
thisStruct.bank_rad = 2.1;
thisStruct.heading_rad = 3.1;
thisStruct.pitch_rad = 3.1;
>> A.getRotationMatrix(thisStruct)
I get the following error
Unrecognized method, property, or field 'getRotationMatrix' for class 'clib.FrameTransformation.FrameTransformation'.
The problem disappears if rewrite and regenerate the function to accept non-structure input e.g. double.
By using the summary function i can see that the call to getRotationMatrix should be of type clib.FrameTransformation.struct0_T
However i can't seem to create a variable of this type.
summary(defineFrameTransformation)
MATLAB Interface to FrameTransformation Library
Class clib.FrameTransformation.struct0_T
No Constructors defined
No Methods defined
No Properties defined
Class clib.FrameTransformation.FrameTransformation
Constructors:
clib.FrameTransformation.FrameTransformation()
clib.FrameTransformation.FrameTransformation(clib.FrameTransformation.FrameTransformation)
Methods:
double getRotationMatrix(clib.FrameTransformation.struct0_T)
No Properties defined
So how is one supposed to pass structures to C++ libraries in Matlab ??? what am i doing wrong.
Note Matlab 2020B, windows, Visual studio 2019
Ah, you were so close to the solution :)
There was a small catch there.
When you are using clibgen.generateLibraryDefinition() you have to make sure that all the type definition are included in the header file. In your case the definition of struct0_T was presnet inside getRotationMatrix_types.h file.
So you will have to include both the headers using below command :
clibgen.generateLibraryDefinition(["FrameTransformation.h","getRotationMatrix_types.h"],"PackageName","mylib",'Libraries',{'getRotationMatrix.lib'})
Now you will have to fill the additional details required in the definition file.
Once you finish that step, you can use below commands to successfully use the interface
build(definemylib)
addpath('\\mathworks\home\dramakan\MLAnswers\CLIB_With_Codegen\ToPort\portzingbit\mylib')
A = clib.mylib.FrameTransformation
s = clib.mylib.struct0_T
s.bank_rad =2.1;
s.heading_rad =3.1;
s.pitch_rad=3.1;
A.getRotationMatrix(s)
I could get below output in R2021b
>> A.getRotationMatrix(s)
ans =
9.6100
Additionally check if you can use MATLAB Coder MEX instead of doing all these circus. You can call the generated code directly in MATLAB using MEX. You can refer below documentation :
https://www.mathworks.com/help/coder/gs/generating-mex-functions-from-matlab-code-at-the-command-line.html
If you have Embedded Coder (the line cfg.ReplacementTypes.uint32 = 'uint32_t' suggests you do), then you can use SIL to do what you're proposing with just a few lines of code:
cfg.VerificationMode = 'SIL';
thisStruct.bank_rad = 2.1;
thisStruct.heading_rad = 3.1;
thisStruct.pitch_rad = 3.1;
codegen ...
% Now test the generated code. This calls your actual generated code
% and automatically does all of the necessary data conversion. The code
% is run in a separate process and outputs are returned back
% to MATLAB
getRotationMatrix_sil(thisStruct)
More info is in the doc. If you have tests / scripts already exercising your MATLAB code, you can reuse those with SIL by checking out coder.runTest and the codegen -test option.
I'm writing tests with Googletest in Eclipse Oxygen 4.7.0 and I'm using Value-Parameterization. There is some weird behavior going on that I cannot explain so I hoped someone here might know what is going on.
The fixture class for value-parameterization should create 256 tests for each TEST_P. However, upon running the test for the first time after booting my computer, at least one TEST_P creates less tests than it should. Sometimes it is only 40, sometimes it is 180 or any number just not 256. The tests that do run pass and I don't get an error message. When I hit run again, all tests run as they should.
Here is what the fixture, one TEST_P and the instantiation look like:
typedef struct mystruct
{
mystruct()
{
myparam = new FooStruct;
bool1 = true;
bool2 = true;
bool3 = false;
bool4 = true;
bool5 = true;
bool6 = true;
uint8_t1 = 0;
uint8_t2 = 2;
uint8_t3 = 2;
int32_t1 = 0;
int32_t2 = 0;
int32_t3 = 0;
int32_t4 = 0;
}
~mystruct()
{
delete myparam;
myparam = NULL;
}
void setInt32_t(int32_t newint1, int32_t newint2, int32_t newint3, int32_t newint4)
{
int32_t1 = newint1;
int32_t2 = newint2;
int32_t3 = newint3;
int32_t4 = newint4;
}
FooStruct *myparam;
bool bool1, bool2, bool3, bool4, bool5, bool6;
uint8_t uint8_t1, uint8_t2, uint8_t3;
int32_t int32_t1, int32_t2, int32_t3, int32_t4;
}MYSTRUCT_T;
class MyTest : public testing::TestWithParam
< ::std::tr1::tuple<uint8_t, uint8_t, uint8_t, bool, bool, bool, bool> >
{
public:
MYSTRUCT_T *testparams;
protected:
virtual void SetUp()
{
_Initializer();
testparams = new mystruct();
testparams->uint8_t1 = ::std::tr1::get<0>(GetParam());
testparams->uint8_t2 = ::std::tr1::get<1>(GetParam());
testparams->uint8_t3 = ::std::tr1::get<2>(GetParam());
testparams->bool1 = ::std::tr1::get<3>(GetParam());
testparams->bool2 = ::std::tr1::get<4>(GetParam());
testparams->bool3 = ::std::tr1::get<5>(GetParam());
testparams->bool4 = ::std::tr1::get<6>(GetParam());
//bool5 and bool6 are unused here
}
virtual void TearDown()
{
delete testparams;
}
};
TEST_P(MyTest, NameOfTheTest)
{
testparams->bool1
? (testparams->uint8_t3 == 2)
? testparams->setInt32_t(0, 0, 0, 0)
: testparams->limits(1, 1, 1, 1)
: (testparams->uint8_t3 == 2)
? testparams->setInt32_t(2, 2, 2, 2)
: testparams->setInt32_t(3, 3, 3, 3);
int bar = 0;
_SetParam(testparams);
if(!_CheckAndSetParam(testparams, bar))
{
FAIL();
return;
}
_DoSomething(bar);
EXPECT_EQ(0, Global_Var[bar].status());
int32_t baz = 1;
_DoMore(bar, baz, testparams->bool2);
EXPECT_EQ(1, Global_Var[bar].status());
}
using testing::Bool;
using testing::Values;
using testing::Range;
INSTANTIATE_TEST_CASE_P(InstantiationName, MyTest,
::testing::Combine(Range((uint8_t)0, (uint8_t) 4), Range((uint8_t)0, (uint8_t)2), Range((uint8_t)2, (uint8_t)4), Bool(), Bool(), Bool(), Bool()));
I am utterly clueless as to why this keeps happening. A colleague just cloned the repository and on his machine the tests ran without a problem first try.
If any further detail or more information about my computer is needed, I am happy to provide it.
EDIT: I now noticed that there is an error that is being displayed when this behaviour occurs. Above the Console there is a small status bar (I don't know what it is called or how to best describe it) that continuously shows which test is currently running. When the tests get interrupted it says there: "I/O error: Pipe closed". Unfortunately, I couldn't find anything so far regarding that output. So the question is still unanswered
Another Edit : Coming back because the issue has arisen again when I thought it was already solved. I haven't read too much about pipe usage in the GoogleTest Documentation but will do now as I remember seeing it being mentioned at some point. Maybe that will lead me to a clue. The reason, however, I am editing this question again is to describe what I see when the error occurs.
Only one thing is constant among the crashes: the error type which is
I/O Error: : Pipe closed
Here is how I can invoke it: I edit something in the .cpp where the tests sit and start a run/debug. If there were changes and a build is made, there will likely be a crash.
The crash will after any amount of tests run which seems random. Usually, it happens after around 1800-2600 tests (out of ~2800). With an increasing amount of tests, there seems to be an increased chance in the run crashing. So I assume there will be a point where I can't run the tests anymore because this error will definitely happen.
In the C/C++ Unit view I see all the tests that ran. All of them have the green check even the last one that seems to make the run crash- at least most of the time. Sometimes it shows the blue "play"-button as if the test were still running, yet in the debug view it states "terminated".
That is about everything I know so far and have observed so any help is greatly appreciated.
I am trying to use llvm::PassBuilder and FunctionPassManager to optimize a function in a module, what I have done is:
mod = ...load module from LLVM IR bitcode file...
auto lift_func = mod->getFunction("go_back");
if (not lift_func) {
llvm::errs() << "Error: cannot get function\n";
return 0;
}
auto pass_builder = llvm::PassBuilder{};
auto fa_manager = llvm::FunctionAnalysisManager{};
pass_builder.registerFunctionAnalyses(fa_manager);
auto fp_manager = pass_builder.buildFunctionSimplificationPipeline(llvm::PassBuilder::OptimizationLevel::O2);
fp_manager.run(*lift_func, fa_manager);
but the program crashes always at fp_manager.run. I tried several ways with pass_builder, fa_manager, fp_manager but nothing works.
Strange enough, the LLVM's opt tool (which uses legacy optimization interface) works without any problem, i.e. if I run
opt -O2 go_back.bc -o go_back_o2.bc
then I get a new module where the (single) function go_back is optimized.
Many thanks for any response.
NB. The (disassembled) LLVM bitcode file is given here if anyone wants to take a look.
Update: I've somehow managed to pass the fp_manager.run with:
auto loop_manager = llvm::LoopAnalysisManager{};
auto cgscc_manager = llvm::CGSCCAnalysisManager{};
auto mod_manager = llvm::ModuleAnalysisManager{};
pass_builder.registerModuleAnalyses(mod_manager);
pass_builder.registerCGSCCAnalyses(cgscc_manager);
pass_builder.registerFunctionAnalyses(fa_manager);
pass_builder.registerLoopAnalyses(loop_manager);
pass_builder.crossRegisterProxies(loop_manager, fa_manager, cgscc_manager, mod_manager);
auto fp_manager = pass_builder.buildFunctionSimplificationPipeline(llvm::PassBuilder::OptimizationLevel::O2, llvm::PassBuilder::ThinLTOPhase::None, true);
fp_manager.run(*lift_func, fa_manager);
...print mod...
But the program crashes when the fa_manager object is destroyed, still do not understand why!!!
Well, after debugging and reading LLVM source code, I've managed to make it works, as following
mod = ...load module from LLVM IR bitcode file...
auto lift_func = mod->getFunction("go_back");
if (not lift_func) {
llvm::errs() << "Error: cannot get function\n";
return 0;
}
auto pass_builder = llvm::PassBuilder{};
auto loop_manager = llvm::LoopAnalysisManager{};
auto cgscc_manager = llvm::CGSCCAnalysisManager{};
auto mod_manager = llvm::ModuleAnalysisManager{};
auto fa_manager = llvm::FunctionAnalysisManager{}; // magic: it's must be here
pass_builder.registerModuleAnalyses(mod_manager);
pass_builder.registerCGSCCAnalyses(cgscc_manager);
pass_builder.registerFunctionAnalyses(fa_manager);
pass_builder.registerLoopAnalyses(loop_manager);
pass_builder.crossRegisterProxies(loop_manager, fa_manager, cgscc_manager, mod_manager);
auto fp_manager = pass_builder.buildFunctionSimplificationPipeline(llvm::PassBuilder::OptimizationLevel::O2, llvm::PassBuilder::ThinLTOPhase::None, true);
fp_manager.run(*lift_func, fa_manager);
...anything...
The fa_manager should be initialized as late as possible, I still don't know why!!!
I am building a game in cocos2dx in which i have to create menu item label. I am creating them in a loop and then adding them in menu:
auto menuForNumberButtons = Menu::create();
menuForNumberButtons->setPosition(Vec2(0,0));
this->addChild(menuForNumberButtons, 3);
for (int yy = 0; yy < 3; yy++ )
{
for (int xx = 0; xx < 3; xx++)
{
counterOfNumers++;
MenuItemLabel *numberButton=MenuItemLabel::create(Label::createWithTTF(String::createWithFormat("%d",counterOfNumers)->getCString(), "arial.ttf", visibleSize.width*0.05), this, menu_selector(BSHSuDokuKeypad::numberButtonPressed));
numberButton->setScaleX(widthOfNumberCell*0.5 / numberButton->getBoundingBox().size.width);
numberButton->setScaleY(heightOfNumberCell*0.5 / numberButton->getBoundingBox().size.height);
numberButton->setPosition(Vec2(visibleSize.width*0.005+widthOfNumberCell*xx + numberButton->getBoundingBox().size.width*0.5, visibleSize.height*0.7+ heightOfNumberCell*yy + numberButton->getBoundingBox().size.height*0.5));
menuForNumberButtons->addChild(numberButton);}}
but when i click on any number. it gives me an error saying assertion failed without calling the callback function.
Any help?
Well it sounds like some precondition/ postcondition is failing when some function is called. Since you're dealing with quite a few objects, I'm betting that your issue originates in the failed creation of your MenuItemLabel.
I'd recommend further inspection of this line:
MenuItemLabel *numberButton=MenuItemLabel::create(Label::createWithTTF(String::createWithFormat("%d",counterOfNumers)->getCString(), "arial.ttf", visibleSize.width*0.05), this, menu_selector(BSHSuDokuKeypad::numberButtonPressed));
Now, I'm not familiar with this language so I can't tell you much about syntax but looking at the API I've discovere that this line format should be formatted:
static MenuItemLabel * create (Node *label, Ref *target, SEL_MenuHandler selector)
Wish I could do more for ya, but hopefully I pointed you in the direction of progress
I'm attempting to implement a simple JIT compiler using the LLVM C API. So far, I have no problems generating IR code and executing it, that is: until I start disposing objects and recreating them.
What I basically would like to do is to clean up the JIT'ted resources the moment they're no longer used by the engine. What I'm basically attempting to do is something like this:
while (true)
{
// Initialize module & builder
InitializeCore(GetGlobalPassRegistry());
module = ModuleCreateWithName(some_unique_name);
builder = CreateBuilder();
// Initialize target & execution engine
InitializeNativeTarget();
engine = CreateExecutionEngineForModule(...);
passmgr = CreateFunctionPassManagerForModule(module);
AddTargetData(GetExecutionEngineTargetData(engine), passmgr);
InitializeFunctionPassManager(passmgr);
// [... my fancy JIT code ...] --** Will give a serious error the second iteration
// Destroy
DisposePassManager(passmgr);
DisposeExecutionEngine(engine);
DisposeBuilder(builder);
// DisposeModule(module); //--> Commented out: Deleted by execution engine
Shutdown();
}
However, this doesn't seem to be working correctly: the second iteration of the loop I get a pretty bad error...
So to summarize: what's the correct way to destroy and re-create the LLVM API?
Posting this as Answer because the code's too long. If possible and no other constraints, try to use LLVM like this. I am pretty sure the Shutdown() inside the loop is the culprit here. And I dont think it would hurt to keep the Builder outside, too. This reflects well the way I use LLVM in my JIT.
InitializeCore(GetGlobalPassRegistry());
InitializeNativeTarget();
builder = CreateBuilder();
while (true)
{
// Initialize module & builder
module = ModuleCreateWithName(some_unique_name);
// Initialize target & execution engine
engine = CreateExecutionEngineForModule(...);
passmgr = CreateFunctionPassManagerForModule(module);
AddTargetData(GetExecutionEngineTargetData(engine), passmgr);
InitializeFunctionPassManager(passmgr);
// [... my fancy JIT code ...] --** Will give a serious error the second iteration
// Destroy
DisposePassManager(passmgr);
DisposeExecutionEngine(engine);
}
DisposeBuilder(builder);
Shutdown();
/* program init */
LLVMInitializeNativeTarget();
LLVMInitializeNativeAsmPrinter();
LLVMInitializeNativeAsmParser();
LLVMLinkInMCJIT();
ctx->context = LLVMContextCreate();
ctx->builder = LLVMCreateBuilderInContext(ctx->context);
LLVMParseBitcodeInContext2(ctx->context, module_template_buf, &module) // create module
do IR code creation
{
function = LLVMAddFunction(ctx->module, "my_func")
LLVMAppendBasicBlockInContext(ctx->context, ...
LLVMBuild...
...
}
optional optimization
{
LLVMPassManagerBuilderRef pass_builder = LLVMPassManagerBuilderCreate();
LLVMPassManagerBuilderSetOptLevel(pass_builder, 3);
LLVMPassManagerBuilderSetSizeLevel(pass_builder, 0);
LLVMPassManagerBuilderUseInlinerWithThreshold(pass_builder, 1000);
LLVMPassManagerRef function_passes = LLVMCreateFunctionPassManagerForModule(ctx->module);
LLVMPassManagerRef module_passes = LLVMCreatePassManager();
LLVMPassManagerBuilderPopulateFunctionPassManager(pass_builder, function_passes);
LLVMPassManagerBuilderPopulateModulePassManager(pass_builder, module_passes);
LLVMPassManagerBuilderDispose(pass_builder);
LLVMInitializeFunctionPassManager(function_passes);
for (LLVMValueRef value = LLVMGetFirstFunction(ctx->module); value;
value = LLVMGetNextFunction(value))
{
LLVMRunFunctionPassManager(function_passes, value);
}
LLVMFinalizeFunctionPassManager(function_passes);
LLVMRunPassManager(module_passes, ctx->module);
LLVMDisposePassManager(function_passes);
LLVMDisposePassManager(module_passes);
}
optional for debug
{
LLVMVerifyModule(ctx->module, LLVMAbortProcessAction, &error);
LLVMPrintModule
}
if (LLVMCreateJITCompilerForModule(&ctx->engine, ctx->module, 0, &error) != 0)
my_func = (exec_func_t)(uintptr_t)LLVMGetFunctionAddress(ctx->engine, "my_func");
LLVMRemoveModule(ctx->engine, ctx->module, &ctx->module, &error);
LLVMDisposeModule(ctx->module);
LLVMDisposeBuilder(ctx->builder);
do
{
my_func(...);
}
LLVMDisposeExecutionEngine(ctx->engine);
LLVMContextDispose(ctx->context);
/* program finit */
LLVMShutdown();