aboutsummaryrefslogtreecommitdiffstats
path: root/compile.c
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2019-11-11 16:38:46 +0900
committerKoichi Sasada <ko1@atdot.net>2019-11-11 16:47:50 +0900
commit31416423809f64d4b5ea6b9651cced3179cc5ced (patch)
tree5cf4b7d9b19019d5f665ca0b0c3902f8100cd597 /compile.c
parent05a5c69e1a06a3853afb3744fa9925910b78904f (diff)
downloadruby-31416423809f64d4b5ea6b9651cced3179cc5ced.tar.gz
__builtin_inline!
Add an experimental `__builtin_inline!(c_expression)` special intrinsic which run a C code snippet. In `c_expression`, you can access the following variables: * ec (rb_execution_context_t *) * self (const VALUE) * local variables (const VALUE) Not that you can read these variables, but you can not write them. You need to return from this expression and return value will be a result of __builtin_inline!(). Examples: `def foo(x) __builtin_inline!('return rb_p(x);'); end` calls `p(x)`. `def double(x) __builtin_inline!('return INT2NUM(NUM2INT(x) * 2);')` returns x*2.
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/compile.c b/compile.c
index 131f82a47d..e0b850556e 100644
--- a/compile.c
+++ b/compile.c
@@ -6740,8 +6740,7 @@ iseq_builtin_function_lookup(const rb_iseq_t *iseq, const char *name)
{
int i;
const struct rb_builtin_function *table = ISEQ_COMPILE_DATA(iseq)->builtin_function_table;
- for (i=0; table[i].name != NULL; i++) {
- // fprintf(stderr, "table[%d].name:%s, name:%s\n", i, table[i].name, name);
+ for (i=0; table[i].index != -1; i++) {
if (strcmp(table[i].name, name) == 0) {
return &table[i];
}
@@ -6886,6 +6885,8 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
}
#endif
const char *builtin_func;
+ NODE *args_node = node->nd_args;
+
if (UNLIKELY(iseq_has_builtin_function_table(iseq)) &&
(builtin_func = iseq_builtin_function_name(mid)) != NULL) {
@@ -6894,9 +6895,18 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
return COMPILE_NG;
}
else {
+ char inline_func[0x20];
+ retry:;
const struct rb_builtin_function *bf = iseq_builtin_function_lookup(iseq, builtin_func);
if (bf == NULL) {
+ if (strcmp("inline!", builtin_func) == 0) {
+ int inline_index = GET_VM()->builtin_inline_index++;
+ snprintf(inline_func, 0x20, "__builtin_inline%d", inline_index);
+ builtin_func = inline_func;
+ args_node = NULL;
+ goto retry;
+ }
if (1) {
rb_bug("can't find builtin function:%s", builtin_func);
}
@@ -6908,7 +6918,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
// fprintf(stderr, "func_name:%s -> %p\n", builtin_func, bf->func_ptr);
- argc = setup_args(iseq, args, node->nd_args, &flag, &keywords);
+ argc = setup_args(iseq, args, args_node, &flag, &keywords);
if (FIX2INT(argc) != bf->argc) {
COMPILE_ERROR(ERROR_ARGS "argc is not match for builtin function:%s (expect %d but %d)",