summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compile.c25
-rw-r--r--tool/mk_builtin_loader.rb23
2 files changed, 38 insertions, 10 deletions
diff --git a/compile.c b/compile.c
index 6316985b3d..13df6a0062 100644
--- a/compile.c
+++ b/compile.c
@@ -7039,18 +7039,30 @@ iseq_builtin_function_lookup(const rb_iseq_t *iseq, const char *name)
}
static const char *
-iseq_builtin_function_name(ID mid)
+iseq_builtin_function_name(const enum node_type type, const NODE *recv, ID mid)
{
const char *name = rb_id2name(mid);
static const char prefix[] = "__builtin_";
const size_t prefix_len = sizeof(prefix) - 1;
- if (UNLIKELY(strncmp(prefix, name, prefix_len) == 0)) {
- return &name[prefix_len];
+ if (type == NODE_CALL) {
+ if (recv) {
+ switch (nd_type(recv)) {
+ case NODE_VCALL:
+ if (recv->nd_mid == rb_intern("__builtin")) {
+ return name;
+ }
+ break;
+ default: break;
+ }
+ }
}
- else {
- return NULL;
+ else if (type == NODE_VCALL || type == NODE_FCALL) {
+ if (UNLIKELY(strncmp(prefix, name, prefix_len) == 0)) {
+ return &name[prefix_len];
+ }
}
+ return NULL;
}
static int
@@ -7204,8 +7216,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
NODE *args_node = node->nd_args;
if (UNLIKELY(iseq_has_builtin_function_table(iseq)) &&
- (type == NODE_VCALL || type == NODE_FCALL) &&
- (builtin_func = iseq_builtin_function_name(mid)) != NULL) {
+ (builtin_func = iseq_builtin_function_name(type, node->nd_recv, mid)) != NULL) {
if (parent_block != NULL) {
COMPILE_ERROR(iseq, line, "should not call builtins here.");
diff --git a/tool/mk_builtin_loader.rb b/tool/mk_builtin_loader.rb
index 505a256ba8..ae6c3b3812 100644
--- a/tool/mk_builtin_loader.rb
+++ b/tool/mk_builtin_loader.rb
@@ -72,7 +72,7 @@ end
def collect_builtin base, tree, name, bs, inlines, params = nil
while tree
- call = sep = mid = args = nil
+ call = recv = sep = mid = args = nil
case tree.first
when :def
params = collect_params(tree[2])
@@ -93,6 +93,8 @@ def collect_builtin base, tree, name, bs, inlines, params = nil
when :method_add_arg
_, mid, (_, (_, args)) = tree
case mid.first
+ when :call
+ _, recv, sep, mid = mid
when :fcall
_, mid = mid
else
@@ -102,12 +104,27 @@ def collect_builtin base, tree, name, bs, inlines, params = nil
_, mid = tree
when :command # FCALL
_, mid, (_, args) = tree
+ when :call, :command_call # CALL
+ _, recv, sep, mid, (_, args) = tree
end
if mid
raise "unknown sexp: #{mid.inspect}" unless mid.first == :@ident
_, mid, (lineno,) = mid
- if /\A__builtin_(.+)/ =~ mid
- cfunc_name = func_name = $1
+ if recv
+ func_name = nil
+ case recv.first
+ when :vcall
+ _, recv = recv
+ if recv.first == :@ident and recv[1] == "__builtin"
+ func_name = mid.to_s
+ end
+ end
+ collect_builtin(base, recv, name, bs, inlines) unless func_name
+ else
+ func_name = mid[/\A__builtin_(.+)/, 1]
+ end
+ if func_name
+ cfunc_name = func_name
args.pop unless (args ||= []).last
argc = args.size