Hi John,
Thank you for the email. I tried both static inline and also inline but neither of them worked. I am listing a code snippet to
illustrate precisely the approach I tried. My overall objective is to instrument stores in a program. I am instrumenting stores in the program by inserting the store_inst_prologue function in the IR.
My source program:
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
inline void store_inst_prologue(unsigned long ptr, int len);
void foo(unsigned long ptr, int len);
__thread uint8_t instrument=0;
void foo(unsigned long ptr, int len)
{
printf("store address: %p, len: %d\n", ptr, len);
}
inline void store_inst_prologue(unsigned long ptr, int len)
{
if (instrument!=0)
foo(ptr, len);
}
int a=10;
int main()
{
int b=20;
//explicit call to prologue fn to avoid dead code elimination
store_inst_prologue (100, 42);
a =42;
b =a*2;
return 0;
}
I am generating an IR using the following command
$llvm-gcc -emit-llvm -S test.c -o test.ll
Then I am running my parser built using the LLVM API to instrument stores in the test.ll to form test_instrumented.ll
My parser takes the test.ll file and iterates over all the instructions and inserts a call instruction before every store instruction in IR.
In my parser code, while creating the signature for the store prologue fn, I set its attribute to "AlwaysInline" using the addFnattr() method.
I can send you the parser code if you think it helps.
//input to parser (test.ll)
….
….
define i32 @main() nounwind {
entry:
%retval = alloca i32 ; <i32*> [#uses=2]
%0 = alloca i32 ; <i32*> [#uses=2]
%b = alloca i32 ; <i32*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store i32 20, i32* %b, align 4
call void @store_inst_prologue(i64 100, i32 42) nounwind inlinehint
store i32 42, i32* @a, align 4
%1 = load i32* @a, align 4 ; <i32> [#uses=1]
%2 = mul nsw i32 %1, 2 ; <i32> [#uses=1]
store i32 %2, i32* %b, align 4
store i32 0, i32* %0, align 4
%3 = load i32* %0, align 4 ; <i32> [#uses=1]
store i32 %3, i32* %retval, align 4
br label %return
return: ; preds = %entry
%retval1 = load i32* %retval ; <i32> [#uses=1]
ret i32 %retval1
}
//output from parser (test_instrumented.ll)
….
….
define i32 @main() nounwind {
entry:
%retval = alloca i32 ; <i32*> [#uses=3]
%0 = alloca i32 ; <i32*> [#uses=3]
%b = alloca i32 ; <i32*> [#uses=4]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
%1 = ptrtoint i32* %b to i64 ; <i64> [#uses=1]
=> call void @store_inst_prologue(i64 %1, i32 4) nounwind
store i32 20, i32* %b, align 4
call void @store_inst_prologue(i64 100, i32 42) nounwind inlinehint
=> call void @store_inst_prologue(i64 ptrtoint (i32* @a to i64), i32 4) nounwind
store i32 42, i32* @a, align 4
%2 = load i32* @a, align 4 ; <i32> [#uses=1]
%3 = mul nsw i32 %2, 2 ; <i32> [#uses=1]
%4 = ptrtoint i32* %b to i64 ; <i64> [#uses=1]
=> call void @store_inst_prologue(i64 %4, i32 4) nounwind
store i32 %3, i32* %b, align 4
%5 = ptrtoint i32* %0 to i64 ; <i64> [#uses=1]
=> call void @store_inst_prologue(i64 %5, i32 4) nounwind
store i32 0, i32* %0, align 4
%6 = load i32* %0, align 4 ; <i32> [#uses=1]
%7 = ptrtoint i32* %retval to i64 ; <i64> [#uses=1]
=> call void @store_inst_prologue(i64 %7, i32 4) nounwind
store i32 %6, i32* %retval, align 4
br label %return
return: ; preds = %entry
%retval1 = load i32* %retval ; <i32> [#uses=1]
ret i32 %retval1
}
I am correctly able to instrument the stores. I am now using opt to make the store_inst_prologue function calls inlined.
I used the following command
$opt -always-inline -inline test_instrumented.ll -S -o test_instrumented.s
However, in the test_instrumented.s file the calls still remain as opposed to being inlined. I was wondering if I am doing something wrong or what would would be the best way to make the store_inst_prologue inline. I really appreciate your help.
Thanks,
--Hari