|
49 | 49 |
|
50 | 50 | # create functions |
51 | 51 | param_types = LLVMType[convert(LLVMType, typ) for typ in arg_types] |
52 | | - llvm_f, llvm_ft = create_function(T_void, param_types) |
53 | | - push!(function_attributes(llvm_f), EnumAttribute("alwaysinline", 0)) |
54 | | - |
| 52 | + llvm_f, llvm_ft = create_function(T_void, LLVMType[]; vararg=true) |
55 | 53 | mod = LLVM.parent(llvm_f) |
56 | 54 |
|
57 | 55 | # generate IR |
|
60 | 58 | position!(builder, entry) |
61 | 59 |
|
62 | 60 | str = globalstring_ptr!(builder, String(fmt), addrspace=2) |
63 | | - argsize = 0 |
64 | | - |
65 | | - # construct and fill args buffer |
66 | | - if isempty(argspec) |
67 | | - buffer = LLVM.PointerNull(T_pint8) |
68 | | - else |
69 | | - argtypes = LLVM.StructType("os_log_args") |
70 | | - elements!(argtypes, param_types) |
71 | | - |
72 | | - args = alloca!(builder, argtypes) |
73 | | - for (i, param) in enumerate(parameters(llvm_f)) |
74 | | - p = struct_gep!(builder, argtypes, args, i-1) |
75 | | - store!(builder, param, p) |
76 | | - end |
77 | 61 |
|
78 | | - dl = datalayout(mod) |
79 | | - argsize = sizeof(dl, argtypes) |
80 | | - buffer = bitcast!(builder, args, T_pint8) |
81 | | - end |
| 62 | + # compute argsize |
| 63 | + argtypes = LLVM.StructType("os_log_args") |
| 64 | + elements!(argtypes, param_types) |
| 65 | + dl = datalayout(mod) |
| 66 | + argsize = sizeof(dl, argtypes) |
| 67 | + |
| 68 | + # argbuffer |
| 69 | + alloc = alloca!(builder, T_pint8) |
| 70 | + buffer = bitcast!(builder, alloc, T_pint8) |
| 71 | + |
| 72 | + va_start_fty = LLVM.FunctionType(T_void, [T_pint8]) |
| 73 | + va_start = LLVM.Function(mod, "llvm.va_start", va_start_fty) |
| 74 | + call!(builder, va_start_fty, va_start, [buffer]) |
82 | 75 |
|
83 | 76 | # invoke @air.os_log and return |
84 | 77 | subsystem_str = globalstring_ptr!(builder, MTLLOG_SUBSYSTEM, addrspace=2) |
85 | | - # subsystem_str = LLVM.PointerNull(T_pint8a2) |
86 | | - # intptr = LLVM.ConstantInt(T_int64, Int64(-1)) |
87 | | - # category_str = const_inttoptr(intptr, T_pint8a2) |
88 | 78 | category_str = globalstring_ptr!(builder, MTLLOG_CATEGRORY, addrspace=2) |
89 | 79 | log_type = LLVM.ConstantInt(T_int32, __METAL_OS_LOG_TYPE_DEBUG__) |
90 | | - arg_size = LLVM.ConstantInt(T_int64, Int64(argsize)) |
91 | | - |
92 | 80 | os_log_fty = LLVM.FunctionType(T_void, [T_pint8a2, T_pint8a2, T_int32, T_pint8a2, T_pint8, T_int64]) |
93 | 81 | os_log = LLVM.Function(mod, "air.os_log", os_log_fty) |
94 | | - call!(builder, os_log_fty, os_log, [subsystem_str, category_str, log_type, str, buffer, arg_size]) |
| 82 | + |
| 83 | + arg_size = LLVM.ConstantInt(T_int64, Int64(argsize)) |
| 84 | + |
| 85 | + arg_ptr = load!(builder, T_pint8, alloc) |
| 86 | + |
| 87 | + call!(builder, os_log_fty, os_log, [subsystem_str, category_str, log_type, str, arg_ptr, arg_size]) |
| 88 | + |
| 89 | + va_end_fty = LLVM.FunctionType(T_void, [T_pint8]) |
| 90 | + va_end = LLVM.Function(mod, "llvm.va_end", va_end_fty) |
| 91 | + call!(builder, va_end_fty, va_end, [buffer]) |
| 92 | + |
| 93 | + ret!(builder) |
| 94 | + end |
| 95 | + |
| 96 | + |
| 97 | + wrapper_f, wrapper_ft = create_function(T_void, param_types) |
| 98 | + |
| 99 | + @dispose builder=IRBuilder() begin |
| 100 | + entry = BasicBlock(wrapper_f, "entry") |
| 101 | + position!(builder, entry) |
| 102 | + |
| 103 | + call!(builder, llvm_ft, llvm_f, collect(parameters(wrapper_f))) |
| 104 | + |
95 | 105 | ret!(builder) |
96 | 106 | end |
97 | 107 |
|
98 | | - call_function(llvm_f, Nothing, Tuple{arg_types...}, arg_exprs...) |
| 108 | + call_function(wrapper_f, Nothing, Tuple{arg_types...}, arg_exprs...) |
99 | 109 | end |
100 | 110 | end |
101 | 111 |
|
|
0 commit comments