I have ConstantInt and ConstantFP values that I want to add using fadd. However, I'm having trouble casting the ConstantInt into a floating point number that fadd will accept.
Here is an excerpt of the code:
Value* left = ConstantInt::get(Type::getInt64Ty(getGlobalContext()), 12, true);
Value* right = ConstantFP::get(Type::getFloatTy(getGlobalContext()), 11.6);
Instruction* cast = CastInst::Create(Instruction::SIToFP, left, left->getType(), "", currentBlock());
left = cast->getOperand(0);
BinaryOperator::Create(Instruction::FAdd, left, right, "", currentBlock());
where currentBlock() returns a BasicBlock. After trying to generate the opcode for this, LLVM complains that it can't add the two values because they are not the same.
I'm rather new to LLVM, so I'll take any advice if this code makes no sense.
My usual approach with these things is see what Clang generates - both the LLVM IR and the C++ API calls (C++ backend). You can use the online instance for simplicity. So, compiling this C code:
float foo(int a, float b) {
return a + b;
}
Gives me this LLVM IR:
define float #foo(i32 %a, float %b) #0 {
entry:
%conv = sitofp i32 %a to float
%add = fadd float %conv, %b
ret float %add
}
And this is the C++ API calls required to recreate that:
// Function: foo (func_foo)
{
Function::arg_iterator args = func_foo->arg_begin();
Value* int32_a = args++;
int32_a->setName("a");
Value* float_b = args++;
float_b->setName("b");
BasicBlock* label_entry = BasicBlock::Create(mod->getContext(), "entry",func_foo,0);
// Block entry (label_entry)
CastInst* float_conv = new SIToFPInst(int32_a, Type::getFloatTy(mod->getContext()), "conv", label_entry);
BinaryOperator* float_add = BinaryOperator::Create(Instruction::FAdd, float_conv, float_b, "add", label_entry);
ReturnInst::Create(mod->getContext(), float_add, label_entry);
}
You're free to tweak the input C code (i.e. replacing vars with constants, etc) and seeing what Clang/LLVM emit. This is the best/quickest way to find your way around the IR and API when you're not too familiar with it.
The problem is here:
Instruction* cast = CastInst::Create(Instruction::SIToFP, left, left->getType(), "", currentBlock());
You casted left to left->getType(), i.e., you did nothing. Cast to right->getType() instead:
Instruction* cast = CastInst::Create(Instruction::SIToFP, left, right->getType(), "", currentBlock());
LLVM 12
Value *cg_binary(BinaryAst *ast)
{
auto l = codegen(ast->left);
auto r = codegen(ast->right);
switch (ast->op)
{
case parser::token::PLUS:
{
if (l->getType()->getTypeID() == Type::TypeID::DoubleTyID || r->getType()->getTypeID() == Type::TypeID::DoubleTyID)
return b->CreateFAdd(b->CreateSIToFP(l, b->getDoubleTy()), b->CreateSIToFP(r, b->getDoubleTy()));
else
return b->CreateAdd(l, r);
}
}
}
Related
I've never seen anything like this; I can't seem to wrap my head around it. What does this code even do? It looks super fancy, and I'm pretty sure this stuff is not described anywhere in my C book. :(
union u;
typedef union u (*funcptr)();
union u {
funcptr f;
int i;
};
typedef union u $;
int main() {
int printf(const char *, ...);
$ fact =
($){.f = ({
$ lambda($ n) {
return ($){.i = n.i == 0 ? 1 : n.i * fact.f(($){.i = n.i - 1}).i};
}
lambda;
})};
$ make_adder = ($){.f = ({
$ lambda($ n) {
return ($){.f = ({
$ lambda($ x) {
return ($){.i = n.i + x.i};
}
lambda;
})};
}
lambda;
})};
$ add1 = make_adder.f(($){.i = 1});
$ mul3 = ($){.f = ({
$ lambda($ n) { return ($){.i = n.i * 3}; }
lambda;
})};
$ compose = ($){
.f = ({
$ lambda($ f, $ g) {
return ($){.f = ({
$ lambda($ n) {
return ($){.i = f.f(($){.i = g.f(($){.i = n.i}).i}).i};
}
lambda;
})};
}
lambda;
})};
$ mul3add1 = compose.f(mul3, add1);
printf("%d\n", fact.f(($){.i = 5}).i);
printf("%d\n", mul3.f(($){.i = add1.f(($){.i = 10}).i}).i);
printf("%d\n", mul3add1.f(($){.i = 10}).i);
return 0;
}
This example primarily builds on two GCC extensions: nested functions, and statement expressions.
The nested function extension allows you to define a function within the body of another function. Regular block scoping rules apply, so the nested function has access to the local variables of the outer function when it is called:
void outer(int x) {
int inner(int y) {
return x + y;
}
return inner(6);
}
...
int z = outer(4)' // z == 10
The statement expression extension allows you to wrap up a C block statement (any code you would normally be able to place within braces: variable declarations, for loops, etc.) for use in a value-producing context. It looks like a block statement in parentheses:
int foo(x) {
return 5 + ({
int y = 0;
while (y < 10) ++y;
x + y;
});
}
...
int z = foo(6); // z == 20
The last statement in the wrapped block provides the value. So it works pretty much like you might imagine an inlined function body.
These two extensions used in combination let you define a function body with access to the variables of the surrounding scope, and use it immediately in an expression, creating a kind of basic lambda expression. Since a statement expression can contain any statement, and a nested function definition is a statement, and a function's name is a value, a statement expression can define a function and immediately return a pointer to that function to the surrounding expression:
int foo(int x) {
int (*f)(int) = ({ // statement expression
int nested(int y) { // statement 1: function definition
return x + y;
}
nested; // statement 2 (value-producing): function name
}); // f == nested
return f(6); // return nested(6) == return x + 6
}
The code in the example is dressing this up further by using the dollar sign as a shortened identifier for a return type (another GCC extension, much less important to the functionality of the example). lambda in the example isn't a keyword or macro (but the dollar is supposed to make it look like one), it's just the name of the function (reused several times) being defined within the statement expression's scope. C's rules of scope nesting mean it's perfectly OK to reuse the same name within a deeper scope (nested "lambdas"), especially when there's no expectation of the body code using the name for any other purpose (lambdas are normally anonymous, so the functions aren't expected to "know" that they're actually called lambda).
If you read the GCC documentation for nested functions, you'll see that this technique is quite limited, though. Nested functions expire when the lifetime of their containing frame ends. That means they can't be returned, and they can't really be stored usefully. They can be passed up by pointer into other functions called from the containing frame that expect a normal function pointer, so they are fairly useful still. But they don't have anywhere near the flexibility of true lambdas, which take ownership (shared or total depends on the language) of the variables they close over, and can be passed in all directions as true values or stored for later use by a completely unrelated part of the program. The syntax is also fairly ungainly, even if you wrap it up in a lot of helper macros.
C will most likely be getting true lambdas in the next version of the language, currently called C2x. You can read more about the proposed form here - it doesn't really look much like this (it copies the anonymous function syntax and semantics found in Objective-C). The functions created this way have lifetimes that can exceed their creating scope; the function bodies are true expressions, without the need for a statement-containing hack; and the functions themselves are truly anonymous, no intermediate names like lambda required.
A C2x version of the above example will most likely look something like this:
#include <stdio.h>
int main(void) {
typedef int (^ F)(int);
__block F fact; // needs to be mutable - block can't copy-capture
// its own variable before initializing it
fact = ^(int n) {
return n == 0 ? 1 : n * fact(n - 1);
};
F (^ make_adder)(int) = ^(int n) {
return _Closure_copy(^(int x) { return n + x; });
};
F add1 = make_adder(1);
F mul3 = ^(int n) { return n * 3; };
F (^ compose)(F, F) = ^(F f, F g) {
return _Closure_copy(^(int n) { return f(g(n)); });
};
F mul3add1 = compose(mul3, add1);
printf("%d\n", fact(5));
printf("%d\n", mul3(add1(10)));
printf("%d\n", mul3add1(10));
_Closure_free(add1);
_Closure_free(mul3add1);
return 0;
}
Much simpler without all that union stuff.
(You can compile and run this modified example in Clang right now - use the -fblocks flag to enable the lambda extension, add #include <Block.h> to the top of the file, and replace _Closure_copy and _Closure_free with Block_copy and Block_release respectively.)
Given a C file, I want to compute the backward slice for some criteria and compare the slice to the original code. Because I don't want to implement a slicing program from cratch, I've already tried to get used to Frama-C which seems to help with this task.
However, my problem is, that Frama-C's slicing plugin changes the preprocessed input code, so that it makes it harder to identify which lines of the original also appear in the slice.
Example:
Input file test1.c:
double func1(double param) {
return 2+param;
}
int main() {
int a=3;
double c=4.0;
double d=10.0;
if(a<c)
c=(double)a/4.0;
double res = func1(c);
return 0;
}
Preprocessed file (yielded by frama-c test1.c -print -ocode test1_norm.c):
/* Generated by Frama-C */
double func1(double param)
{
double __retres;
__retres = (double)2 + param;
return __retres;
}
int main(void)
{
int __retres;
int a;
double c;
double d;
double res;
a = 3;
c = 4.0;
d = 10.0;
if ((double)a < c) c = (double)a / 4.0;
res = func1(c);
__retres = 0;
return __retres;
}
Slice (yielded by frama-c -slice-calls func1 test1.c -then-on 'Slicing export' -print):
/* Generated by Frama-C */
double func1_slice_1(double param)
{
double __retres;
__retres = (double)2 + param;
return __retres;
}
void main(void)
{
int a;
double c;
double res;
a = 3;
c = 4.0;
c = (double)a / 4.0;
res = func1_slice_1(c);
return;
}
Note that the signature of main differs and that the name of func1 was changed to func1_slice_1.
Is there a way to suppress that behaviour in order to make the slice and the (preprocessed) original more easily comparable (in terms of a computable diff)?
First, to clarify a simpler question that you don't need answering but that someone searching for the same keywords could, you cannot have the sliced program printed as a selection of the lines of the original program (most of the differences between the two corresponds to lost information, basically. If the information was there, it would be used to print the most resembling program possible).
What you can do is print Frama-C's representation of the original program, which you are already doing with frama-c test2.c -print -ocode test2_norm.c.
To solve your problem of func1 being renamed to func1_slice_1, you can try playing with option -slicing-level 0:
$ frama-c -slicing-level 0 -slice-calls func1 test1.c -then-on 'Slicing export' -print
...
/* Generated by Frama-C */
double func1(double param)
{
double __retres;
__retres = (double)2 + param;
return __retres;
}
void main(void)
{
int a;
double c;
double res;
a = 3;
c = 4.0;
c = (double)a / 4.0;
res = func1(c);
return;
}
I think this will prevent the slicer from slicing inside func1 at all. The help says:
-slicing-level <n> set the default level of slicing used to propagate to the
calls
0 : don't slice the called functions
1 : don't slice the called functions but propagate the
marks anyway
2 : try to use existing slices, create at most one
3 : most precise slices
I'm new programing in C. I have a main code with 781 lines that is out of control because garbage value is stored in vectors. A short part of the main code is shown below where it calls a subroutine called diff_conv_intermedia1.
diff_conv_intermedia1(&factorteta,&N,ID,DIFF,X1_intermedia,Y1_intermedia,X1C_intermedia,Y1C_intermedia,CU1_intermedia,CV1_intermedia,AW1_intermedia,AE1_intermedia,AS1_intermedia,AN1_intermedia,AP1_intermedia,Q1_intermedia,FXI1,FYI1,FI_intermedia1,1,2,1,1);
int q,w;
for(q=1;q<(*factorteta_Ptr)*2+1;q++)
{
for(w=1;w<(*N_Ptr)+1;w++)
{
printf("%lf\n",AP1_intermedia[q][w]);
}
}
So the subroutine shown below. When I print the results inside the subroutine, everything is OK, but when I print the results outside the subroutine, in the main code, garbage is stored in the vectors as AP1_intermedia. I don't know what could be wrong. I repeat the same procedure with other subroutines and I don't have any errors.
int diff_conv_intermedia1(int *factorteta_Ptr,
int *N_Ptr,
int ID,
double DIFF,
double X[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double Y[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double XC[(*factorteta_Ptr)*2+2][*N_Ptr+2],
double YC[(*factorteta_Ptr)*2+2][*N_Ptr+2],
double CU[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double CV[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double AW[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double AE[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double AS[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double AN[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double AP[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double Q[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double FX[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double FY[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double FI[(*factorteta_Ptr)*2+1][*N_Ptr+1],
int WBC,int EBC,int SBC,int NBC)
{
int i,j;
double value,* valuePtr;
double AED, AWD, AND, ASD;
double AEC, AWC, ANC, ASC;
valuePtr = &value;
// Diffusive coefficients
for(i=1;i<(*factorteta_Ptr)*2+1;i++)
{
for(j=1;j<*N_Ptr+1;j++)
{
AWD = -DIFF*(Y[i][j-1]-Y[i-1][j-1])/(XC[i][j]-XC[i][j-1]);
AED = -DIFF*(Y[i][j]-Y[i-1][j])/(XC[i][j+1]-XC[i][j]);
AND = -DIFF*(X[i][j]-X[i][j-1])/(YC[i+1][j]-YC[i][j]);
ASD = -DIFF*(X[i-1][j]-X[i-1][j-1])/(YC[i][j]-YC[i-1][j]);
// Convection term
if(ID==2)
{
max1_or_min2(CU[i][j-1],1,&value);
AWC=-*valuePtr;
max1_or_min2(CU[i][j],2,&value);
AEC=*valuePtr;
max1_or_min2(CV[i-1][j],1,&value);
ASC=-*valuePtr;
max1_or_min2(CV[i][j],2,&value);
ANC=*valuePtr;
}
if(ID==1)
{
AWC =-CU[i][j-1]*(1.0-FX[i][j-1]);
AEC =CU[i][j]*FX[i][j];
ASC =-CV[i-1][j]*(1.0-FY[i-1][j]);
ANC =CV[i][j]*FY[i][j];
}
// Set Coefficients matrix
AW[i][j] = AWD+AWC;
AE[i][j] = AED+AEC;
AS[i][j] = ASD+ASC;
AN[i][j] = AND+ANC;
AP[i][j] = -(AE[i][j]+AW[i][j]+AN[i][j]+AS[i][j]);
Q[i][j] = 0.0;
}
}
// West Boundary - Inlet B.C
for(i=1;i<(*factorteta_Ptr)*2+1;i++)
{
if(WBC==1) Q[i][1] = Q[i][1]-AW[i][1]*FI[i][0];
if(WBC==2) AP[i][1] = AP[i][1] + AW[i][1];
AW[i][1] = 0.0;
// East Boundary - (1)Dirichlet (2)ZERP-GRAD Outflow B.C
if(EBC==1) Q[i][*N_Ptr] = Q[i][*N_Ptr] - AE[i][*N_Ptr]*FI[i][*N_Ptr+1];
if(EBC==2) AP[i][*N_Ptr] = AP[i][*N_Ptr] + AE[i][*N_Ptr];
AE[i][*N_Ptr] = 0.0;
}
// South Boundary - (1)Dirichlet (2)ZERO-GRAD
for(j=1;j<*N_Ptr+1;j++)
{
if(SBC==1) Q[1][j] = Q[1][j] - AS[1][j]*FI[0][j];
if(SBC==2) AP[1][j] = AP[1][j] + AS[1][j];
AS[1][j] = 0.0;
// North Boundary - (1)Dirichlet (2)ZERO-GRAD
if(NBC==1) Q[(*factorteta_Ptr)*2][j] = Q[(*factorteta_Ptr)*2][j] - AN[(*factorteta_Ptr)*2][j]*FI[(*factorteta_Ptr)*2+1][j];
if(NBC==2) AP[(*factorteta_Ptr)*2][j] = AP[(*factorteta_Ptr)*2][j] + AN[(*factorteta_Ptr)*2][j];
AN[(*factorteta_Ptr)*2][j] = 0.0;
}
// Print
int l,k;
for(l=1;l<(*factorteta_Ptr)*2+1;l++)
{
for(k=1;k<*N_Ptr+1;k++)
{
printf("%lf %lf %lf %lf\n",AP[l][k],AS[l][k],AN[l][k],FI[l][k]);
}
}
return 0;
}
If anybody wants I can send all code, but have many extensions.
In your function declaration:
double AP[(*factorteta_Ptr)*2+1][*N_Ptr+1]
I don't quite think this is doing what you think it is doing. While I haven't seen something like this myself before, I believe that this is telling the compiler to create a variable length 2D array for you based on the other given parameters. Then, you fill in these values in your function. But, because you don't return this value nor do you declare it as pass by reference, it is thrown away when you return, thus the work is lost and you have garbage in your array in main(). Better form would be to create this array in main(), then pass it in by reference something like double *AP[][], or return this array upon exit, or hack things up even worse than this function and just make it a global so that you can see it anywhere.
Having successfully built LLVM using MinGW I am now trying to use the C API to implement the program.
As just a starter application to see if the build has been successful I have converted the llvmpy example found here http://www.llvmpy.org/llvmpy-doc/0.9/doc/firstexample.html into (what I think is the) C equivalent however I'm not getting the output I expect from the print function.
My C program is:
#include "llvm-c/Core.h"
#include "stdio.h"
int main(int argc, char* argv[])
{
LLVMInitializeCore(LLVMGetGlobalPassRegistry());
LLVMModuleRef my_module = LLVMModuleCreateWithName("my_module");
LLVMTypeRef ty_int = LLVMInt32Type();
LLVMTypeRef* ParamTypes = new LLVMTypeRef[2];
ParamTypes[0] = ty_int;
ParamTypes[1] = ty_int;
LLVMTypeRef ty_func = LLVMFunctionType(ty_int, ParamTypes, 2, false);
delete[] ParamTypes;
LLVMValueRef f_sum = LLVMAddFunction(my_module, "sum", ty_func);
LLVMValueRef* Params = new LLVMValueRef[2];
LLVMGetParams(f_sum, Params);
LLVMSetValueName(Params[0], "a");
LLVMSetValueName(Params[1], "b");
LLVMBasicBlockRef bb = LLVMAppendBasicBlock(f_sum, "entry");
LLVMBuilderRef builder = LLVMCreateBuilder();
LLVMPositionBuilderAtEnd(builder, bb);
LLVMValueRef tmp = LLVMBuildAdd(builder, Params[0], Params[1], "tmp");
delete[] Params;
LLVMBuildRet(builder, tmp);
printf(LLVMPrintModuleToString(my_module));
//do shutdown
LLVMDisposeBuilder(builder);
LLVMDisposeModule(my_module);
LLVMShutdown();
return 0;
}
The output I get is:
; ModuleID = 'my_module'
define i32 #sum(i32 0x1.74bb00p-1012, i32 b) {
entry:
tmp = add i32 0x1.95bc40p+876, b
ret i32 tmp
}
Note that 0x1.74bb00p-1012 and 0x1.95bc40p+876 should read "%a"
I can only think that is some kind of memory corruption however I don't know the likely cause. How could I change the code so this works?
As it turns out this is a problem with LLVMPrintModuleToStringNw, it uses the C printf function to print to the string and so the percentages are either removed or spew false values out of whatever is on the stack.
See for why %a came out as "0x1.74bb00p-1012" -Aka hexadecimal floating point format.
http://www.cplusplus.com/reference/cstdio/printf/
In the end LLVMPrintModuleToString should be replaced with a function that doesn't use the C print family of functions.
I am writing an interface to a C-library using external declarations in OCaml. I used ctypes for testing but it involved a 100% overhead for fast calls (measured by a core_bench micro benchmark).
The functions look like this:
/* external _create_var : float -> int -> int -> int -> _npnum = "ocaml_tnp_number_create_var" ;; */
value ocaml_tnp_number_create_var(value v, value nr, value p, value o) {
//CAMLparam4(v, nr, p, o);
const int params = Int_val(p);
const int order = Int_val(o);
const int number = Int_val(nr);
const double value = Double_val(v);
return CTYPES_FROM_PTR(tnp_number_create_variable(value, number, params, order));
}
/* external _delete : _npnum -> unit = "ocaml_tnp_number_delete" ;; */
value ocaml_tnp_number_delete(value num) {
//CAMLparam1(num);
struct tnp_number* n = CTYPES_TO_PTR(num);
tnp_number_delete(n);
return Val_unit;
}
I borrowed the CTYPES_* macros, so I am basically moving pointers around as Int64 values.
#define CTYPES_FROM_PTR(P) caml_copy_int64((intptr_t)P)
#define CTYPES_TO_PTR(I64) ((void *)Int64_val(I64))
#define CTYPES_PTR_PLUS(I64, I) caml_copy_int64(Int64_val(I64) + I)
AFAIK, those values are represented as boxes which are tagged as "custom", which should be left untouched by the GC.
Do I need to uncomment the CAMLparamX macros to notify the GC about my usage or is it legal to omit them?
According to the comment in byterun/memory.h your function must start with a CAMLparamN macro with all value parameters.