How to use the get_param_types() method
I have a variable of FunctionType and I want to iterate its parameter types, I find the get_param_types() method might be useful, however I failed to call it with the right argument:
# the generated bindings
def get_param_types(self, arg0):
"""See LLVMGetParamTypes"""
return libLLVMCoverageso50.LLVMGetParamTypes(self.in_ptr(), ([x.in_ptr() for x in arg0] if type(arg0) is list else arg0.out_ptr()))
# my code
f = module.get_named_function("foo") # suppose foo(arg1, arg2, arg3)
l = ?
f.type_of().get_param_types(l)
I don't know how to construct the l argument. I tried the following:
l=[llvm.ffi.new("LLVMTypeRef *")]*3
>>> f.type_of().get_param_types(l)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/xiangchen/.cache/llvmcpy/a1fe60d12ca6bf5e9ef034da2a85c1ad88886fe0b2023124da7efad7adf41914-5.0.0/llvmcpyimpl.py", line 1840, in get_param_types
return libLLVMLTO.LLVMGetParamTypes(self.in_ptr(), ([x.in_ptr() for x in arg0] if type(arg0) is list else arg0.out_ptr()))
File "/home/xiangchen/.cache/llvmcpy/a1fe60d12ca6bf5e9ef034da2a85c1ad88886fe0b2023124da7efad7adf41914-5.0.0/llvmcpyimpl.py", line 1840, in <listcomp>
return libLLVMLTO.LLVMGetParamTypes(self.in_ptr(), ([x.in_ptr() for x in arg0] if type(arg0) is list else arg0.out_ptr()))
AttributeError: cdata 'struct LLVMOpaqueType * *' has no attribute 'in_ptr
- Please report an easy to run reproducer, including a module. Also, report the LLVM version you're using.
- The second argument of
LLVMGetParamTypesis an out argument. The generated bindings can't distinguish very well between out arguments and arguments pointing to an array. If you pass in a list, you're suggesting it's an argument pointing to an array. The correct usage should be
Clearly, this is not ideal, we should devise a better way to distinguish pointer-to-array arguments from out arguments.llvm = llvmcpy.LLVMCPy x = llvm.Type() f.type_of().get_param_types(x)
Thanks for your reply! I am using LLVM-5.0.0, here's the reproducer. First assemble the following ir to foo.bc
define void @foo(i32, i8 signext, i8*) {
ret void
}
then run the python script
from llvmcpy import LLVMCPy
llvm = LLVMCPy()
buffer = llvm.create_memory_buffer_with_contents_of_file("foo.bc")
module = buffer.get_bitcode_module()
foo = module.get_named_function("foo")
t = llvm.Type()
foo.type_of().get_param_types(t)
print(t.print_type_to_string())
And the output is:
File "<stdin>", line 1, in <module>
File "/home/xiangchen/.cache/llvmcpy/a1fe60d12ca6bf5e9ef034da2a85c1ad88886fe0b2023124da7efad7adf41914-5.0.0/llvmcpyimpl.py", line 1831, in get_element
return Type(libLLVMLTO.LLVMGetElementType(self.in_ptr()))
File "/home/xiangchen/.cache/llvmcpy/a1fe60d12ca6bf5e9ef034da2a85c1ad88886fe0b2023124da7efad7adf41914-5.0.0/llvmcpyimpl.py", line 1764, in in_ptr
raise RuntimeError("in_ptr called on uninitialized object")
RuntimeError: in_ptr called on uninitialized object
We have a couple of issues:
-
I understand why you were doing
[llvm.ffi.new("LLVMTypeRef *")]*3: theLLVMGetElementTypegets an output array not just an output argument. We don't support that in our automatic wrapping, but we could work on it. -
The bigger problem is that
foo.type_of().dump()printsptr, i.e., an opaque pointer, from which you cannot obtain the pointee. This is the results of the whole opaque pointers effort. Unfortunately, there doesn't seem to be a way to callFunction->getFunctionType()via the LLVM-C API, which would be the proper way of getting the type of the function. This said, since you're using a very old LLVM version, you are not affected by this.Something like:
t = [llvm.ffi.new("LLVMOpaqueType *"), llvm.ffi.new("LLVMOpaqueType *"), llvm.ffi.new("LLVMOpaqueType *")] llvm.libLLVMXRay.LLVMGetParamTypes(llvm.libLLVMXRay.LLVMGetElementType(foo.type_of().in_ptr()), t)However, I could't test this right now, I don't have access to an old enough LLVM version.