compile.c: separate compile_builtin_function_call (#3711)

This commit is contained in:
Kenta Murata 2020-10-28 10:22:28 +09:00 коммит произвёл GitHub
Родитель 8f9c113f35
Коммит fb3c711df3
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
1 изменённых файлов: 88 добавлений и 80 удалений

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
compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, const enum node_type type, int line, int popped)
{
@ -7289,90 +7375,12 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
}
}
#endif
const char *builtin_func;
NODE *args_node = node->nd_args;
const char *builtin_func;
if (UNLIKELY(iseq_has_builtin_function_table(iseq)) &&
(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.");
return COMPILE_NG;
return compile_builtin_function_call(iseq, ret, node, line, popped, parent_block, args, builtin_func);
}
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 */
if (type == NODE_CALL || type == NODE_OPCALL || type == NODE_QCALL) {