|
| 1 | +# This file is mostly generated by `generate_builtins.jl` with some additional @static checks |
| 2 | +# for recently added builtins. |
| 3 | + |
| 4 | +function getargs(args, frame) |
| 5 | + nargs = length(args)-1 # skip f |
| 6 | + callargs = resize!(frame.framedata.callargs, nargs) |
| 7 | + for i = 1:nargs |
| 8 | + callargs[i] = @lookup(frame, args[i+1]) |
| 9 | + end |
| 10 | + return callargs |
| 11 | +end |
| 12 | + |
| 13 | +""" |
| 14 | + ret = maybe_evaluate_builtin(frame, call_expr, expand::Bool) |
| 15 | +
|
| 16 | +If `call_expr` is to a builtin function, evaluate it, returning the result inside a `Some` wrapper. |
| 17 | +Otherwise, return `call_expr`. |
| 18 | +
|
| 19 | +If `expand` is true, `Core._apply` calls will be resolved as a call to the applied function. |
| 20 | +""" |
| 21 | +function maybe_evaluate_builtin(frame, call_expr, expand::Bool) |
| 22 | + # By having each call appearing statically in the "switch" block below, |
| 23 | + # each gets call-site optimized. |
| 24 | + args = call_expr.args |
| 25 | + nargs = length(args) - 1 |
| 26 | + fex = args[1] |
| 27 | + if isa(fex, QuoteNode) |
| 28 | + f = fex.value |
| 29 | + else |
| 30 | + f = @lookup(frame, fex) |
| 31 | + end |
| 32 | + # Builtins and intrinsics have empty method tables. We can circumvent |
| 33 | + # a long "switch" check by looking for this. |
| 34 | + mt = typeof(f).name.mt |
| 35 | + if isa(mt, Core.MethodTable) |
| 36 | + isempty(mt) || return call_expr |
| 37 | + end |
| 38 | + # Builtins |
| 39 | + if f === <: |
| 40 | + if nargs == 2 |
| 41 | + return Some{Any}(<:(@lookup(frame, args[2]), @lookup(frame, args[3]))) |
| 42 | + else |
| 43 | + return Some{Any}(<:(getargs(args, frame)...)) |
| 44 | + end |
| 45 | + elseif f === === |
| 46 | + if nargs == 2 |
| 47 | + return Some{Any}(===(@lookup(frame, args[2]), @lookup(frame, args[3]))) |
| 48 | + else |
| 49 | + return Some{Any}(===(getargs(args, frame)...)) |
| 50 | + end |
| 51 | + elseif f === Core._apply |
| 52 | + argswrapped = getargs(args, frame) |
| 53 | + if !expand |
| 54 | + return Some{Any}(Core._apply(argswrapped...)) |
| 55 | + end |
| 56 | + new_expr = Expr(:call, argswrapped[1]) |
| 57 | + popfirst!(argswrapped) |
| 58 | + argsflat = Base.append_any(argswrapped...) |
| 59 | + for x in argsflat |
| 60 | + push!(new_expr.args, (isa(x, Symbol) || isa(x, Expr) || isa(x, QuoteNode)) ? QuoteNode(x) : x) |
| 61 | + end |
| 62 | + return new_expr |
| 63 | + elseif f === Core._apply_latest |
| 64 | + argswrapped = getargs(args, frame) |
| 65 | + if !expand |
| 66 | + return Some{Any}(Core._apply_latest(argswrapped...)) |
| 67 | + end |
| 68 | + new_expr = Expr(:call, argswrapped[1]) |
| 69 | + popfirst!(argswrapped) |
| 70 | + argsflat = Base.append_any(argswrapped...) |
| 71 | + for x in argsflat |
| 72 | + push!(new_expr.args, (isa(x, Symbol) || isa(x, Expr) || isa(x, QuoteNode)) ? QuoteNode(x) : x) |
| 73 | + end |
| 74 | + return new_expr |
| 75 | + elseif f === Core._apply_pure |
| 76 | + return Some{Any}(Core._apply_pure(getargs(args, frame)...)) |
| 77 | + elseif f === Core._expr |
| 78 | + return Some{Any}(Core._expr(getargs(args, frame)...)) |
| 79 | + elseif @static isdefined(Core, :_typevar) ? f === Core._typevar : false |
| 80 | + if nargs == 3 |
| 81 | + return Some{Any}(Core._typevar(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4]))) |
| 82 | + else |
| 83 | + return Some{Any}(Core._typevar(getargs(args, frame)...)) |
| 84 | + end |
| 85 | + elseif f === Core.apply_type |
| 86 | + return Some{Any}(Core.apply_type(getargs(args, frame)...)) |
| 87 | + elseif f === Core.arrayref |
| 88 | + if nargs == 0 |
| 89 | + return Some{Any}(Core.arrayref()) |
| 90 | + elseif nargs == 1 |
| 91 | + return Some{Any}(Core.arrayref(@lookup(frame, args[2]))) |
| 92 | + elseif nargs == 2 |
| 93 | + return Some{Any}(Core.arrayref(@lookup(frame, args[2]), @lookup(frame, args[3]))) |
| 94 | + elseif nargs == 3 |
| 95 | + return Some{Any}(Core.arrayref(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4]))) |
| 96 | + elseif nargs == 4 |
| 97 | + return Some{Any}(Core.arrayref(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4]), @lookup(frame, args[5]))) |
| 98 | + elseif nargs == 5 |
| 99 | + return Some{Any}(Core.arrayref(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4]), @lookup(frame, args[5]), @lookup(frame, args[6]))) |
| 100 | + else |
| 101 | + return Some{Any}(Core.arrayref(getargs(args, frame)...)) |
| 102 | + end |
| 103 | + elseif f === Core.arrayset |
| 104 | + if nargs == 0 |
| 105 | + return Some{Any}(Core.arrayset()) |
| 106 | + elseif nargs == 1 |
| 107 | + return Some{Any}(Core.arrayset(@lookup(frame, args[2]))) |
| 108 | + elseif nargs == 2 |
| 109 | + return Some{Any}(Core.arrayset(@lookup(frame, args[2]), @lookup(frame, args[3]))) |
| 110 | + elseif nargs == 3 |
| 111 | + return Some{Any}(Core.arrayset(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4]))) |
| 112 | + elseif nargs == 4 |
| 113 | + return Some{Any}(Core.arrayset(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4]), @lookup(frame, args[5]))) |
| 114 | + elseif nargs == 5 |
| 115 | + return Some{Any}(Core.arrayset(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4]), @lookup(frame, args[5]), @lookup(frame, args[6]))) |
| 116 | + elseif nargs == 6 |
| 117 | + return Some{Any}(Core.arrayset(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4]), @lookup(frame, args[5]), @lookup(frame, args[6]), @lookup(frame, args[7]))) |
| 118 | + else |
| 119 | + return Some{Any}(Core.arrayset(getargs(args, frame)...)) |
| 120 | + end |
| 121 | + elseif f === Core.arraysize |
| 122 | + if nargs == 2 |
| 123 | + return Some{Any}(Core.arraysize(@lookup(frame, args[2]), @lookup(frame, args[3]))) |
| 124 | + else |
| 125 | + return Some{Any}(Core.arraysize(getargs(args, frame)...)) |
| 126 | + end |
| 127 | + elseif @static isdefined(Core, :const_arrayref) ? f === Core.const_arrayref : false |
| 128 | + return Some{Any}(Core.const_arrayref(getargs(args, frame)...)) |
| 129 | + elseif f === Core.sizeof |
| 130 | + if nargs == 1 |
| 131 | + return Some{Any}(Core.sizeof(@lookup(frame, args[2]))) |
| 132 | + else |
| 133 | + return Some{Any}(Core.sizeof(getargs(args, frame)...)) |
| 134 | + end |
| 135 | + elseif f === Core.svec |
| 136 | + return Some{Any}(Core.svec(getargs(args, frame)...)) |
| 137 | + elseif f === applicable |
| 138 | + return Some{Any}(applicable(getargs(args, frame)...)) |
| 139 | + elseif f === fieldtype |
| 140 | + if nargs == 2 |
| 141 | + return Some{Any}(fieldtype(@lookup(frame, args[2]), @lookup(frame, args[3]))) |
| 142 | + elseif nargs == 3 |
| 143 | + return Some{Any}(fieldtype(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4]))) |
| 144 | + else |
| 145 | + return Some{Any}(fieldtype(getargs(args, frame)...)) |
| 146 | + end |
| 147 | + elseif f === getfield |
| 148 | + if nargs == 2 |
| 149 | + return Some{Any}(getfield(@lookup(frame, args[2]), @lookup(frame, args[3]))) |
| 150 | + elseif nargs == 3 |
| 151 | + return Some{Any}(getfield(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4]))) |
| 152 | + else |
| 153 | + return Some{Any}(getfield(getargs(args, frame)...)) |
| 154 | + end |
| 155 | + elseif f === ifelse |
| 156 | + if nargs == 3 |
| 157 | + return Some{Any}(ifelse(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4]))) |
| 158 | + else |
| 159 | + return Some{Any}(ifelse(getargs(args, frame)...)) |
| 160 | + end |
| 161 | + elseif f === invoke |
| 162 | + argswrapped = getargs(args, frame) |
| 163 | + if !expand |
| 164 | + return Some{Any}(invoke(argswrapped...)) |
| 165 | + end |
| 166 | + return Expr(:call, invoke, argswrapped...) |
| 167 | + elseif f === isa |
| 168 | + if nargs == 2 |
| 169 | + return Some{Any}(isa(@lookup(frame, args[2]), @lookup(frame, args[3]))) |
| 170 | + else |
| 171 | + return Some{Any}(isa(getargs(args, frame)...)) |
| 172 | + end |
| 173 | + elseif f === isdefined |
| 174 | + if nargs == 1 |
| 175 | + return Some{Any}(isdefined(@lookup(frame, args[2]))) |
| 176 | + elseif nargs == 2 |
| 177 | + return Some{Any}(isdefined(@lookup(frame, args[2]), @lookup(frame, args[3]))) |
| 178 | + else |
| 179 | + return Some{Any}(isdefined(getargs(args, frame)...)) |
| 180 | + end |
| 181 | + elseif f === nfields |
| 182 | + if nargs == 1 |
| 183 | + return Some{Any}(nfields(@lookup(frame, args[2]))) |
| 184 | + else |
| 185 | + return Some{Any}(nfields(getargs(args, frame)...)) |
| 186 | + end |
| 187 | + elseif f === setfield! |
| 188 | + if nargs == 3 |
| 189 | + return Some{Any}(setfield!(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4]))) |
| 190 | + else |
| 191 | + return Some{Any}(setfield!(getargs(args, frame)...)) |
| 192 | + end |
| 193 | + elseif f === throw |
| 194 | + if nargs == 1 |
| 195 | + return Some{Any}(throw(@lookup(frame, args[2]))) |
| 196 | + else |
| 197 | + return Some{Any}(throw(getargs(args, frame)...)) |
| 198 | + end |
| 199 | + elseif f === tuple |
| 200 | + return Some{Any}(ntuple(i->@lookup(frame, args[i+1]), length(args)-1)) |
| 201 | + elseif f === typeassert |
| 202 | + if nargs == 2 |
| 203 | + return Some{Any}(typeassert(@lookup(frame, args[2]), @lookup(frame, args[3]))) |
| 204 | + else |
| 205 | + return Some{Any}(typeassert(getargs(args, frame)...)) |
| 206 | + end |
| 207 | + elseif f === typeof |
| 208 | + if nargs == 1 |
| 209 | + return Some{Any}(typeof(@lookup(frame, args[2]))) |
| 210 | + else |
| 211 | + return Some{Any}(typeof(getargs(args, frame)...)) |
| 212 | + end |
| 213 | + # Intrinsics |
| 214 | + elseif f === Base.cglobal |
| 215 | + if nargs == 1 |
| 216 | + return Some{Any}(Core.eval(moduleof(frame), call_expr)) |
| 217 | + elseif nargs == 2 |
| 218 | + call_expr = copy(call_expr) |
| 219 | + call_expr.args[3] = @lookup(frame, args[3]) |
| 220 | + return Some{Any}(Core.eval(moduleof(frame), call_expr)) |
| 221 | + end |
| 222 | + elseif f === Base.llvmcall |
| 223 | + return Some{Any}(Base.llvmcall(getargs(args, frame)...)) |
| 224 | + end |
| 225 | + if isa(f, Core.IntrinsicFunction) |
| 226 | + cargs = getargs(args, frame) |
| 227 | + return Some{Any}(ccall(:jl_f_intrinsic_call, Any, (Any, Ptr{Any}, UInt32), f, cargs, length(cargs))) |
| 228 | + end |
| 229 | + if isa(f, getfield(Core, Symbol("#kw##invoke"))) |
| 230 | + return Some{Any}(getfield(Core, Symbol("#kw##invoke"))(getargs(args, frame)...)) |
| 231 | + end |
| 232 | + return call_expr |
| 233 | +end |
0 commit comments