aboutsummaryrefslogtreecommitdiffstats
path: root/compile.c
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2019-11-26 12:20:53 +0900
committerKoichi Sasada <ko1@atdot.net>2019-11-27 03:55:28 +0900
commita3e6f52c17061f012c4e638b3343b57752ed7603 (patch)
treebd1ddd4d72d2ed9a653ebf8e3270af4eb359a725 /compile.c
parent9e01fcd0cb79a05daa50d99c888cc7eeb9c79426 (diff)
downloadruby-a3e6f52c17061f012c4e638b3343b57752ed7603.tar.gz
rename __builtin_inline!(code) and introduce others.
rename __builtin_inline!(code) to __builtin_cstmt(code). Also this commit introduce the following inlining C code features. * __builtin_cstmt!(STMT) (renamed from __builtin_inline!) Define a function which run STMT implicitly and call this function at evatuation time. Note that you need to return some value in STMT. If there is a local variables (includes method parameters), you can read these values. static VALUE func(ec, self) { VALUE x = ...; STMT } Usage: def double a # a is readable from C code. __builtin_cstmt! 'return INT2FIX(FIX2INT(a) * 2);' end * __builtin_cexpr!(EXPR) Define a function which invoke EXPR implicitly like `__builtin_cstmt!`. Different from cstmt!, which compiled with `return EXPR;`. (`return` and `;` are added implicitly) static VALUE func(ec, self) { VALUE x = ...; return EXPPR; } Usage: def double a __builtin_cexpr! 'INT2FIX(FIX2INT(a) * 2)' end * __builtin_cconst!(EXPR) Define a function which invoke EXPR implicitly like cexpr!. However, the function is called once at compile time, not evaluated time. Any local variables are not accessible (because there is no local variable at compile time). Usage: GCC = __builtin_cconst! '__GNUC__' * __builtin_cinit!(STMT) STMT are writtein in auto-generated code. This code does not return any value. Usage: __builtin_cinit! '#include <zlib.h>' def no_compression? __builtin_cconst! 'Z_NO_COMPRESSION ? Qtrue : Qfalse' end
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/compile.c b/compile.c
index b73b9854f4..1d5aa843dd 100644
--- a/compile.c
+++ b/compile.c
@@ -6920,17 +6920,30 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
}
else {
char inline_func[0x20];
+ bool cconst = false;
retry:;
const struct rb_builtin_function *bf = iseq_builtin_function_lookup(iseq, builtin_func);
if (bf == NULL) {
- if (strcmp("inline!", builtin_func) == 0) {
+ if (strcmp("cstmt!", builtin_func) == 0 ||
+ strcmp("cexpr!", builtin_func) == 0) {
+ inlinec:;
int inline_index = GET_VM()->builtin_inline_index++;
- snprintf(inline_func, 0x20, "rb_compiled_inline%d", inline_index);
+ snprintf(inline_func, 0x20, "builtin_inline%d", inline_index);
builtin_func = inline_func;
args_node = NULL;
goto retry;
}
+ else if (strcmp("cconst!", builtin_func) == 0) {
+ cconst = true;
+ goto inlinec;
+ }
+ else if (strcmp("cinit!", builtin_func) == 0) {
+ // ignore
+ GET_VM()->builtin_inline_index++;
+ return COMPILE_OK;
+ }
+
if (1) {
rb_bug("can't find builtin function:%s", builtin_func);
}
@@ -6940,6 +6953,13 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
return COMPILE_NG;
}
+ if (cconst) {
+ typedef VALUE(*builtin_func0)(void *, VALUE);
+ VALUE const_val = (*(builtin_func0)bf->func_ptr)(NULL, Qnil);
+ ADD_INSN1(ret, line, putobject, const_val);
+ return COMPILE_OK;
+ }
+
// fprintf(stderr, "func_name:%s -> %p\n", builtin_func, bf->func_ptr);
argc = setup_args(iseq, args, args_node, &flag, &keywords);