How to access file given to cilly in my CIL module - ocaml

I have added a new feature to CIL(C Intermediate Language). I am able to execute my new module using
$cilly --dotestmodule --save-temps -D HAPPY_MOOD -o test test.c
Now, in my testmodule, I want to call Cfg.computeFileCFG for test.c file. But I don't know how to access test.c file in my module.
I tried using Cil.file. but it says "Unbound value Cil.file".
my code:
open Pretty
open Cfg
open Cil
module RD = Reachingdefs
let () = Cfg.computeFileCFG Cil.file
let rec fact n = if n < 2 then 1 else n * fact(n-1)
let doIt n = fact n
let feature : featureDescr =
{ fd_name = "testmodule";
fd_enabled = ref false;
fd_description = "simple test 1240";
fd_extraopt = [];
fd_doit = (function (f: file) -> ignore (doIt 10));
fd_post_check = true;
}
please tell me how to compute the Cfg for test.c file.

I am not a CIL expert, but here are a few remarks:
the CIL online documentation states that Cil.file is an Ocaml type. Passing a type as an argument to a function is probably not what you want to do here;
it seems like the fd_doit function in your feature descriptor takes the file you are looking to process as its argument f;
according to the Cilly manual, the type of f is Cil.file. Conveniently, this seems to be the type of the argument required by the function computeFileCFG.
Hopefully you can take it from here. Good luck!

Related

How to pass structures into re-integrated autogenerated C++ code in Matlab

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.

How to write custom ppx decorator to rescript?

I need to generate a value with a different type from my passed type. This is the first time I write on ocaml-like, and for example, in a familiar me haskell I would use Data.Generics.
How I have understood I need to use decorator and ppx. I wrote simple example
let recordHandler = (loc: Location.t, _recFlag: rec_flag, _t: type_declaration, fields: list(label_declaration)) => {
let (module Builder) = Ast_builder.make(loc);
let test = [%str
let schema: Schema = { name: "", _type: String, properties: [] }
]
let moduleExpr = Builder.pmod_structure(test);
[%str
module S = [%m moduleExpr]
]
}
let str_gen = (~loc, ~path as _, (_rec: rec_flag, t: list(type_declaration))) => {
let t = List.hd(t)
switch t.ptype_kind {
| Ptype_record(fields) => recordHandler(loc, _rec, t, fields);
| _ => Location.raise_errorf(~loc, "schema is used only for records.");
};
};
let name = "my_schema";
let () = {
let str_type_decl = Deriving.Generator.make_noarg(str_gen);
Deriving.add(name, ~str_type_decl) |> Deriving.ignore;
};
And
open Ppxlib;
let _ = Driver.run_as_ppx_rewriter()
But in using in rescript code
module User = {
#deriving(my_schema)
type my_typ = {
foo: int,
};
};
I caught:
schema is not supported
. And I made myself sure me to connect it right when I had changed #deriving(my_schema) for #deriving(abcd) and #deriving(sschema).
I got different error
Ppxlib.Deriving: 'abcd' is not a supported type deriving generator.
And my last experiment was to copy past existing library deriving accessors .
ppx_accessor
I copied-pasted it and renamed for accessors_2. And I got same error such as experiment.
accessors_2 is not supported
Also I haven't found examples "ppx rescript". Can you please help me.
What am I doing wrong (ALL , I know)
I have found answer in the article
Dropping support for custom PPXes such as ppx_deriving (the deriving
attribute is now exclusively interpreted as bs.deriving)

Function optimization pass

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!!!

Z3's OCaml library throws segmentation fault

Consider the following OCaml code snippet that uses Z3 module to interface with the Z3 solver. The code tries to define a new TPair datatype in Z3 with a single constructor T that accepts two integer arguments:
open Z3
open Z3.SMT
open Z3.Expr
open Z3.Symbol
open Z3.Datatype
open Z3.FuncDecl
open Z3.Arithmetic
open Z3.Arithmetic.Integer
open Z3.Quantifier
let _ =
let cfg = [("model", "true"); ("proof", "false")] in
let ctx = (mk_context cfg) in
let sym = Symbol.mk_string ctx in
let s_Int = mk_sort ctx in
(* (declare-datatypes () ((TPair (T Int Int) )))*)
let s_T = mk_constructor_s ctx "T" (sym "isT")
[sym "left"; sym "right"]
[Some s_Int; Some s_Int] [0; 0] in
let s_TPair = mk_sort_s ctx "TPair" [s_T] in
let _::s_content::_ = Constructor.get_accessor_decls s_T in
let s_isT = Constructor.get_tester_decl s_T in
let solver = Solver.mk_solver ctx None in
begin
Printf.printf "***** CONTEXT ******\n";
print_string ## Solver.to_string solver;
Printf.printf "\n*********************\n"
end
The calls to get_tester_decl and get_accessor_decls both throw segmentation fault. What could be the reason?
No code, written in pure OCaml, can cause a segmentation fault. This is because OCaml is a memory safe language. The problem is somewhere in the plumbing, either in the place where OCaml is bound to the underlying library, on in the z3 library itself.
Only library (or bindings) authors can help you in debugging and fixing this issue. So please, create an issue in the upstream repository.

Dump Block Liveness of source code using Clang

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.