c - Is there a standard way to reconstruct lowered struct function arguments? -
i have structure type:
typedef struct boundptr { uint8_t *ptr; size_t size; } boundptr;
and want catch arguments of function of type. e.g. in function:
boundptr sample_function_stub(boundptr lp, boundptr lp2);
on 64bit machine, clang translates signature to:
define { i8*, i64 } @sample_function_stub(i8* %lp.coerce0, i64 %lp.coerce1, i8* %lp2.coerce0, i64 %lp2.coerce1) #0 {
question:
is there better way reconstruct such arguments?
is possible forbid such argument lowering, while keeping same abi external calls?
some more context:
so in llvm ir, guess, according platform abi, compiler broke down structure separate fields (which not worst case, see 1). btw, reconstructs original 2 parameters lp
, lp2
later in function body.
now analysis, want 2 parameters lp
, lp2
in full, out of these 4(lp.coerce0
, lp.coerce1
, lp2.coerce0
, lp2.coerce1
). in case, can rely on names (.coerce0
means first field, .coerce1
- second).
i not approach:
- i not sure, clang keep convention in later versions
- it depends on abi, there may different breakdown on platform.
on other side, can not use reconstruction code in beginning of function, because may confuse user code local variable.
i use clang 3.4.2
based on llvm 3.4.2
target x86_64-pc-linux-gnu
.
p.s. here another example, showing how wildly clang can mess function arguments.
i assume compiling not o0
. afaik, clang reassemble original type when not optimizing code. clang breaks down structure pass them through registers (at least on x86) called function. said, depends on abi used.
here dummy example use case:
#include <cstddef> typedef struct boundptr { void *ptr; size_t size; } boundptr; boundptr foo(boundptr ptr1, boundptr ptr2) { return {ptr1.ptr, ptr2.size}; } int main() { boundptr p1, p2; boundptr p3 = foo(p1, p2); return 0; }
compiling clang -o0 -std=c++11 -emit-llvm -s -c test.cpp
generates foo
:
define { i8*, i64 } @_z3foo8boundptrs_(i8* %ptr1.coerce0, i64 %ptr1.coerce1, i8* %ptr2.coerce0, i64 %ptr2.coerce1) #0 { %1 = alloca %struct.boundptr, align 8 %ptr1 = alloca %struct.boundptr, align 8 %ptr2 = alloca %struct.boundptr, align 8 %2 = bitcast %struct.boundptr* %ptr1 { i8*, i64 }* %3 = getelementptr { i8*, i64 }, { i8*, i64 }* %2, i32 0, i32 0 store i8** %ptr1.coerce0, i8** %3 %4 = getelementptr { i8*, i64 }, { i8*, i64 }* %2, i32 0, i32 1 store i64 %ptr1.coerce1, i64* %4 %5 = bitcast %struct.boundptr* %ptr2 { i8*, i64 }* %6 = getelementptr { i8*, i64 }, { i8*, i64 }* %5, i32 0, i32 0 store i8** %ptr2.coerce0, i8** %6 %7 = getelementptr { i8**, i64 }, { i8**, i64 }* %5, i32 0, i32 1 store i64 %ptr2.coerce1, i64* %7 %8 = getelementptr inbounds %struct.boundptr, %struct.boundptr* %1, i32 0, i32 0 %9 = getelementptr inbounds %struct.boundptr, %struct.boundptr* %ptr1, i32 0, i32 0 %10 = load i8*, i8** %9, align 8 store i8* %10, i8** %8, align 8 %11 = getelementptr inbounds %struct.boundptr, %struct.boundptr* %1, i32 0, i32 1 %12 = getelementptr inbounds %struct.boundptr, %struct.boundptr* %ptr2, i32 0, i32 1 %13 = load i64, i64* %12, align 8 store i64 %13, i64* %11, align 8 %14 = bitcast %struct.boundptr* %1 { i8*, i64 }* %15 = load { i8*, i64 }, { i8*, i64 }* %14, align 8 ret { i8*, i64 } %15 }
boundptr
reconstructed on called function stack (this depends on used calling convention).
now find out of boundptr
parameters can following:
- visit each
alloca
inst in pass , follow users. - follow casts of
alloca
gep instructions find store instructions onboundptr
. - inspect value stored. if function arguments , match types , names have found reassembled
boundptr
.
of course can other way around starting functions arguments.
is future proof? no definitively not. clang/llvm not designed keep backward compatibility. compatibility abi important.
drawback: have pass optimizer after code generation. 01
remove these stack allocations of boundptr
. have modify clang
execute pass during optimization , cannot make standalone pass (e.g., used opt
).
a better solution: since clang has modified somehow, can add metadata identifying parameters of boundptr
type. can "pack" fragments of boundptr
identify them boundptr
. survive optimizer.
Comments
Post a Comment