Hi everyone,
I need some advice for the following intended transformation:
int foo(int p) { return 2*p; }
int bar (void) {
int var = 42 + foo(foo(42)); /*1*/
return var;
}
I want to check the return value from foo:
int bar (void) {
int temp1 = foo(42);
int temp2 foo(temp1);
// perform some checks on temp1 and temp2
int var = 42 + temp2;
return var;
}
How should I dissect and translate the expr /*1*/ with a Rewriter?
Thanks for your help
Marcel
(Greetings from the Black Forest in Germany ;- ) )
I would think (in fact, I KNOW) that the compiler already does the transformation to temp1 = foo(42) and temp2 = foo(temp1) already. So it’d just be a case, at the LLVM-IR level at least, to insert some code to inspect temp1 and temp2.
Of course, it may be a slightly more interesting challenge to find your “interesting functions” (particularly if interesting functions aren’t a well defined set of functions) when looking at the LLVM-IR - including the fact that for example member functions gets mangled during compilation.
Also interesting/challenging is function pointers:
pf = foo;
var = 42 + pf(pf(42));
Consider where pf is passed into the function you’re currently looking at, or comes from a table of function pointers, with a non-constant determining the index into the table.
A similar problem is of course virtual function calls - they are just function pointer tables after all [but the table itself is the variable part there, rather than the index, unless we’re talking virtual member function pointers, which isn’t a common creature by any means]
I would think (in fact, I _KNOW_) that the compiler already does the transformation to temp1 = foo(42) and temp2 = foo(temp1) already. So it'd just be a case, at the LLVM-IR level at least, to insert some code to inspect temp1 and temp2.
Good hint. I'll check that.
Of course, it may be a slightly more interesting challenge to find your "interesting functions" (particularly if interesting functions aren't a well defined set of functions) when looking at the LLVM-IR - including the fact that for example member functions gets mangled during compilation.
"Interesting functions" are marked by the developer.
Also interesting/challenging is function pointers:
pf = foo;
var = 42 + pf(pf(42));
Consider where pf is passed into the function you're currently looking at, or comes from a table of function pointers, with a non-constant determining the index into the table.
A similar problem is of course virtual function calls - they are just function pointer tables after all [but the table itself is the variable part there, rather than the index, unless we're talking virtual member function pointers, which isn't a common creature by any means]
At the first shot I'll attack the trivial cases. So function pointer are on my list but come at a later point in time. Because the target are embedded devices, which in my case are programmed exclusively in plain "C"
I'll ignore for the moment vtables.
Anyway I would like to implement the dissecting of the expression my self with the clang frontend. Any hints on that?
Sorry, not sure how to actually do that - I work on my own compiler project (a Pascal compiler), and dabble in changing Clang on the odd occasion, but I don’t work with the parts that would be useful here.
If I wanted to do this, I would probably look for “CallExpr” (or something similar) in the AST, and then go from there - but you may have to introduce your own temporary variables, as those are probably not present at the AST level - they certainly aren’t in my compiler, the return value is just “used” as is, without being stored. Adding variables may not be trivial, as you need to do that in a way that matches the behavious expected by the rest of the compiler - you can’t necessarily introduce new variables inside a function call for example - so you perhaps can’t do int temp2 = foo(int temp1 = foo(42));
, even if that’s what you conceptually would like to have. I’m not sure exactly how you actually go about writing code for this…