|
38 | 38 | llvm_f, _ = create_function(T_int32, param_types)
|
39 | 39 | mod = LLVM.parent(llvm_f)
|
40 | 40 |
|
41 |
| - # generate IR |
42 | 41 | IRBuilder() do builder
|
43 | 42 | entry = BasicBlock(llvm_f, "entry")
|
44 | 43 | position!(builder, entry)
|
45 | 44 |
|
| 45 | + # `printf` needs to be invoked very specifically, e.g., the format string needs |
| 46 | + # to be a pointer to a string, and arguments need to match exactly what is |
| 47 | + # expected by the format string, so we cannot rely on how the arguments to this |
| 48 | + # function have been passed in (by `llvmcall`). |
| 49 | + T_actual_args = LLVMType[] |
| 50 | + actual_args = LLVM.Value[] |
| 51 | + for (_, (arg, argtyp)) in enumerate(zip(parameters(llvm_f), arg_types)) |
| 52 | + if argtyp <: LLVMPtr |
| 53 | + # passed as i8* |
| 54 | + T,AS = argtyp.parameters |
| 55 | + actual_typ = LLVM.PointerType(convert(LLVMType, T), AS) |
| 56 | + actual_arg = bitcast!(builder, arg, actual_typ) |
| 57 | + elseif argtyp <: Ptr |
| 58 | + T = eltype(argtyp) |
| 59 | + if T === Nothing |
| 60 | + T = Int8 |
| 61 | + end |
| 62 | + actual_typ = LLVM.PointerType(convert(LLVMType, T)) |
| 63 | + actual_arg = if value_type(arg) isa LLVM.PointerType |
| 64 | + # passed as i8* or ptr |
| 65 | + bitcast!(builder, arg, actual_typ) |
| 66 | + else |
| 67 | + # passed as i64 |
| 68 | + inttoptr!(builder, arg, actual_typ) |
| 69 | + end |
| 70 | + elseif argtyp <: Bool |
| 71 | + # passed as i8 |
| 72 | + T = eltype(argtyp) |
| 73 | + actual_typ = LLVM.Int1Type() |
| 74 | + actual_arg = trunc!(builder, arg, actual_typ) |
| 75 | + else |
| 76 | + actual_typ = convert(LLVMType, argtyp) |
| 77 | + actual_arg = arg |
| 78 | + end |
| 79 | + push!(T_actual_args, actual_typ) |
| 80 | + push!(actual_args, actual_arg) |
| 81 | + end |
| 82 | + |
46 | 83 | str = globalstring_ptr!(builder, String(fmt); addrspace=AS.Constant)
|
47 | 84 |
|
48 | 85 | # invoke printf and return
|
49 | 86 | printf_typ = LLVM.FunctionType(T_int32, [T_pint8]; vararg=true)
|
50 | 87 | printf = LLVM.Function(mod, "printf", printf_typ)
|
51 | 88 | push!(function_attributes(printf), EnumAttribute("nobuiltin"))
|
52 |
| - chars = call!(builder, printf_typ, printf, [str, parameters(llvm_f)...]) |
| 89 | + chars = call!(builder, printf_typ, printf, [str, actual_args...]) |
53 | 90 |
|
54 | 91 | ret!(builder, chars)
|
55 | 92 | end
|
|
0 commit comments