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:

  1. visit each alloca inst in pass , follow users.
  2. follow casts of alloca gep instructions find store instructions on boundptr.
  3. 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

Popular posts from this blog

Hatching array of circles in AutoCAD using c# -

ios - UITEXTFIELD InputView Uipicker not working in swift -

Python Pig Latin Translator -