<div dir="ltr">Hello list,<div><br></div><div>I am trying to interface some JIT'd code I generate (via the llvm-c API) with a module I've compiled alongside the jit, which contains certain runtime functions.</div><div>
<br></div><div>I generate runtime.bc with the same clang invocation as the rest of the application, except using -O0 and -emit-llvm. This is loaded at runtime and my I insert new functions into that module as I need them. For runtime functions that just use scalars, this works well.</div>
<div><br></div><div>I'm having problems with structs, and my clang-generated module seems to define the struct as I'd expect, but functions that either take this struct as an arg, or return it seem to fall apart.</div>
<div><br></div><div>I have:</div><div><div> typedef struct {</div><div> uint32_t value;</div><div> uint32_t carryOut;</div><div> uint32_t overflow;</div><div> } CarryOp_Result;</div></div><div><br></div><div>This was once upon a time defined at the top of the module as { i32, i32, i32 } as expected, but I've since changed things and now thats not emitted in my runtime.bc anymore. I guess it's not used/needed.</div>
<div><br></div><div>I also have a function in this runtime.bc module:</div><div> CarryOp_Result addWithCarry( a, b, carryIn);</div><div><br></div><div>Which is defined to return { i64, i32 }. I suspect this is because clang knows the ABI of my host PC and bakes the calling convention into the IR (x86_64-apple-darwin11.4.2). I know enough not to expect to be able to use the same .bc on different arches for reasons such as this, at least :)</div>
<div><br></div><div>Because two struct fields are merged, it's not trivial to get the one I'm interested in. Even if I do emit the required masks and shifts, what if it all changes tomorrow when I want this to work after recompiling everything for say, 32b Linux, or ARM with a different calling convention?</div>
<div><br></div><div>So I had the bright idea to add some accessors to the runtime, which I could feed with the LLVMValue I have, regardless of the actual representation. This way for a given compile of the runtime everything would be self-consistent and "just work", neatly sidestepping struct ABI packing issues ...</div>
<div> uint32_t carryOpValue(CarryOpResult r) { return r.value; }</div><div><br></div><div>... or so I thought, anyway. This actually generates:</div><div> define i32 @CarryOpValue(i64 %v.coerce0, i32 %v.coerce1) #0 { ... }<br>
</div><div>which takes two arguments, where I expected a single { i64, i32 } argument.</div><div><br></div><div>So now, even for my jit to emit </div><div> LLVMValueRef sum = CarryOpValue(addWithCarry(a, b, c)); </div>
<div><br></div><div>The call site needs to know to unpack the single LLVMValue (representing the struct) into two arguments, in order to pass them to the accessor. So still I need to poke around in the innards of the struct, still knowing how the compiler felt like packing the struct on a given platform.</div>
<div><br></div><div>Is there a way I can have Clang simply use {i32, i32, i32} for that struct in a way that GEP/ExtractValue with indices 0, 1, 2 reliably works as expected?</div><div><br></div><div>Alternatively, could I cast between {i64, i32} and {i32, i32, i32} in a reliable way, would that be safe?</div>
<div>Or any other solution?</div><div><br></div><div>If worse comes to worst, I *can* end up writing addWithCarry either by hand or with the builder API to do exactly what I want, but that's annoying enough to be the reason I went down the "runtime-module full of helpers" path in the first place and have clang do the annoying work for me!</div>
<div><br></div><div>Thanks in advance,</div><div>DavidM</div><div><br></div><div><br></div><div><br></div></div>