compile.c: separate compile_builtin_function_call (#3711)
This commit is contained in:
parent
8f9c113f35
commit
fb3c711df3
Notes:
git
2020-10-28 10:22:59 +09:00
Merged-By: mrkn <mrkn@ruby-lang.org>
168
compile.c
168
compile.c
@ -7204,6 +7204,92 @@ delegate_call_p(const rb_iseq_t *iseq, unsigned int argc, const LINK_ANCHOR *arg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int line, int popped,
|
||||||
|
const rb_iseq_t *parent_block, LINK_ANCHOR *args, const char *builtin_func)
|
||||||
|
{
|
||||||
|
NODE *args_node = node->nd_args;
|
||||||
|
|
||||||
|
if (parent_block != NULL) {
|
||||||
|
COMPILE_ERROR(iseq, line, "should not call builtins here.");
|
||||||
|
return COMPILE_NG;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# define BUILTIN_INLINE_PREFIX "_bi"
|
||||||
|
char inline_func[DECIMAL_SIZE_OF_BITS(sizeof(int) * CHAR_BIT) + sizeof(BUILTIN_INLINE_PREFIX)];
|
||||||
|
bool cconst = false;
|
||||||
|
retry:;
|
||||||
|
const struct rb_builtin_function *bf = iseq_builtin_function_lookup(iseq, builtin_func);
|
||||||
|
|
||||||
|
if (bf == NULL) {
|
||||||
|
if (strcmp("cstmt!", builtin_func) == 0 ||
|
||||||
|
strcmp("cexpr!", builtin_func) == 0) {
|
||||||
|
// ok
|
||||||
|
}
|
||||||
|
else if (strcmp("cconst!", builtin_func) == 0) {
|
||||||
|
cconst = true;
|
||||||
|
}
|
||||||
|
else if (strcmp("cinit!", builtin_func) == 0) {
|
||||||
|
// ignore
|
||||||
|
GET_VM()->builtin_inline_index++;
|
||||||
|
return COMPILE_OK;
|
||||||
|
}
|
||||||
|
else if (strcmp("attr!", builtin_func) == 0) {
|
||||||
|
// There's only "inline" attribute for now
|
||||||
|
iseq->body->builtin_inline_p = true;
|
||||||
|
return COMPILE_OK;
|
||||||
|
}
|
||||||
|
else if (1) {
|
||||||
|
rb_bug("can't find builtin function:%s", builtin_func);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
COMPILE_ERROR(ERROR_ARGS "can't find builtin function:%s", builtin_func);
|
||||||
|
return COMPILE_NG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GET_VM()->builtin_inline_index == INT_MAX) {
|
||||||
|
rb_bug("builtin inline function index overflow:%s", builtin_func);
|
||||||
|
}
|
||||||
|
int inline_index = GET_VM()->builtin_inline_index++;
|
||||||
|
snprintf(inline_func, sizeof(inline_func), BUILTIN_INLINE_PREFIX "%d", inline_index);
|
||||||
|
builtin_func = inline_func;
|
||||||
|
args_node = NULL;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
unsigned int flag = 0;
|
||||||
|
struct rb_callinfo_kwarg *keywords = NULL;
|
||||||
|
VALUE 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)",
|
||||||
|
builtin_func, bf->argc, FIX2INT(argc));
|
||||||
|
return COMPILE_NG;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int start_index;
|
||||||
|
if (delegate_call_p(iseq, FIX2INT(argc), args, &start_index)) {
|
||||||
|
ADD_INSN2(ret, line, opt_invokebuiltin_delegate, bf, INT2FIX(start_index));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ADD_SEQ(ret, args);
|
||||||
|
ADD_INSN1(ret,line, invokebuiltin, bf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (popped) ADD_INSN(ret, line, pop);
|
||||||
|
return COMPILE_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, const enum node_type type, int line, int popped)
|
compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, const enum node_type type, int line, int popped)
|
||||||
{
|
{
|
||||||
@ -7289,91 +7375,13 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
const char *builtin_func;
|
|
||||||
NODE *args_node = node->nd_args;
|
|
||||||
|
|
||||||
|
const char *builtin_func;
|
||||||
if (UNLIKELY(iseq_has_builtin_function_table(iseq)) &&
|
if (UNLIKELY(iseq_has_builtin_function_table(iseq)) &&
|
||||||
(builtin_func = iseq_builtin_function_name(type, node->nd_recv, mid)) != NULL) {
|
(builtin_func = iseq_builtin_function_name(type, node->nd_recv, mid)) != NULL) {
|
||||||
|
return compile_builtin_function_call(iseq, ret, node, line, popped, parent_block, args, builtin_func);
|
||||||
if (parent_block != NULL) {
|
|
||||||
COMPILE_ERROR(iseq, line, "should not call builtins here.");
|
|
||||||
return COMPILE_NG;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
# define BUILTIN_INLINE_PREFIX "_bi"
|
|
||||||
char inline_func[DECIMAL_SIZE_OF_BITS(sizeof(int) * CHAR_BIT) + sizeof(BUILTIN_INLINE_PREFIX)];
|
|
||||||
bool cconst = false;
|
|
||||||
retry:;
|
|
||||||
const struct rb_builtin_function *bf = iseq_builtin_function_lookup(iseq, builtin_func);
|
|
||||||
|
|
||||||
if (bf == NULL) {
|
|
||||||
if (strcmp("cstmt!", builtin_func) == 0 ||
|
|
||||||
strcmp("cexpr!", builtin_func) == 0) {
|
|
||||||
// ok
|
|
||||||
}
|
|
||||||
else if (strcmp("cconst!", builtin_func) == 0) {
|
|
||||||
cconst = true;
|
|
||||||
}
|
|
||||||
else if (strcmp("cinit!", builtin_func) == 0) {
|
|
||||||
// ignore
|
|
||||||
GET_VM()->builtin_inline_index++;
|
|
||||||
return COMPILE_OK;
|
|
||||||
}
|
|
||||||
else if (strcmp("attr!", builtin_func) == 0) {
|
|
||||||
// There's only "inline" attribute for now
|
|
||||||
iseq->body->builtin_inline_p = true;
|
|
||||||
return COMPILE_OK;
|
|
||||||
}
|
|
||||||
else if (1) {
|
|
||||||
rb_bug("can't find builtin function:%s", builtin_func);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
COMPILE_ERROR(ERROR_ARGS "can't find builtin function:%s", builtin_func);
|
|
||||||
return COMPILE_NG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GET_VM()->builtin_inline_index == INT_MAX) {
|
|
||||||
rb_bug("builtin inline function index overflow:%s", builtin_func);
|
|
||||||
}
|
|
||||||
int inline_index = GET_VM()->builtin_inline_index++;
|
|
||||||
snprintf(inline_func, sizeof(inline_func), BUILTIN_INLINE_PREFIX "%d", inline_index);
|
|
||||||
builtin_func = inline_func;
|
|
||||||
args_node = NULL;
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (FIX2INT(argc) != bf->argc) {
|
|
||||||
COMPILE_ERROR(ERROR_ARGS "argc is not match for builtin function:%s (expect %d but %d)",
|
|
||||||
builtin_func, bf->argc, FIX2INT(argc));
|
|
||||||
return COMPILE_NG;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int start_index;
|
|
||||||
if (delegate_call_p(iseq, FIX2INT(argc), args, &start_index)) {
|
|
||||||
ADD_INSN2(ret, line, opt_invokebuiltin_delegate, bf, INT2FIX(start_index));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ADD_SEQ(ret, args);
|
|
||||||
ADD_INSN1(ret,line, invokebuiltin, bf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (popped) ADD_INSN(ret, line, pop);
|
|
||||||
return COMPILE_OK;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* receiver */
|
/* receiver */
|
||||||
if (type == NODE_CALL || type == NODE_OPCALL || type == NODE_QCALL) {
|
if (type == NODE_CALL || type == NODE_OPCALL || type == NODE_QCALL) {
|
||||||
int idx, level;
|
int idx, level;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user