I was wondering if someone could explain why CallInst::getCalledFunc behaves the way it does.
For simple, direct call instructions in my IR, that method behaves just as one would expect.
However, for instructions like this:
%25 = call i32 (%struct._IO_FILE*, …)* bitcast (i32 (…)* @close to i32 (%struct._IO_FILE*, …))(%struct._IO_FILE %24), !dbg !695
getCalledFunc returns null.
I know getCalledFunc is expected to return null on indirect calls, but I would have thought naming the callee via a constant expression like the one here would be considered a direct call.
The getCalledFunc() method is not very sophisticated. It turns NULL if the called value is not trivially a function constant. I’m not sure for the reasoning behind this. My best guess is that a constant expression could do all sorts of interesting things. For example, a constant expression can select one of several values or pull a value out of an array using a constant expression GEP. You’ll need to do what SAFECode does; use getCalledValue()->stripPointerCasts() to get the called value and remove any casts that stand between you and the function value. It’s inconvenient, but it works. Alternatively, you could see if the CallSite() class provides a smarter method of getting the called function, but I’m not sure if it has such a method. Regards, John Criswell
I would think so, yes. No. A direct call at the C/C++ source level can end up being a call in which the argument to the CallInst or InvokeInst is not a function constant. Examples include: 1) Cases in which a function is used with a different number of arguments than the declared type. This is common when a C function prototype has no arguments but the function definition has arguments. 2) An optimization changes an if/then/else to a predicated instruction. For example, it is possible that: if (flag) foo(5); else bar(5); … could become something like (in a combined LLVM/C notation): call ((flag) ? foo : bar) (5) Note that I don’t know if this optimization will happen, but in theory, it can happen. In short, if you want to handle C/C++ code, you need to handle whatever the frontend spits out in LLVM IR. That includes function constants, casted function constants, function arguments that are a select instruction between several constants, etc. You may want to grep the DSA code in the poolalloc project for getCalledValue() to see what kind of CallInsts it handles. That way, you can piggy-back off the experiences we’ve had updating DSA to handle what the newer LLVM front-ends do. Regards, John Criswell