1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

native: use enum values instead of strings for identifying builtin functions (#16450)

This commit is contained in:
Spydr 2022-11-17 06:44:08 +01:00 committed by GitHub
parent 49277f7aa8
commit 41dd8985fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 21 deletions

View File

@ -1846,7 +1846,7 @@ pub fn (mut g Gen) call_fn_amd64(node ast.CallExpr) {
}
}
fn (mut g Gen) call_builtin_amd64(name string) i64 {
fn (mut g Gen) call_builtin_amd64(name Builtin) i64 {
call_addr := g.call(0)
g.println('call builtin `${name}`')
return call_addr
@ -3363,9 +3363,9 @@ fn (mut g Gen) convert_int_to_string(r1 Register, r2 Register) {
g.labels.addrs[loop_label] = loop_start
// after all was converted, reverse the string
reg := g.get_builtin_arg_reg('reverse_string', 0)
reg := g.get_builtin_arg_reg(.reverse_string, 0)
g.mov_reg(reg, .r12)
g.call_builtin('reverse_string')
g.call_builtin(.reverse_string)
g.labels.addrs[end_label] = g.pos()
g.println('; label ${end_label}')

View File

@ -5,6 +5,13 @@ module native
import term
enum Builtin {
int_to_string
bool_to_string
reverse_string
compare_strings
}
struct BuiltinFn {
body fn (builtin BuiltinFn, mut g Gen)
arg_regs []Register
@ -18,19 +25,20 @@ pub fn (mut g Gen) init_builtins() {
g.builtins = {
// longer algorithms and internal functions inaccessible to the user
// used to keep executable size small and the bytecode distraction-free
'int_to_string': BuiltinFn{
.int_to_string: BuiltinFn{
// 32-bit signed integer to string conversion
body: fn (builtin BuiltinFn, mut g Gen) {
g.convert_int_to_string(builtin.arg_regs[0], builtin.arg_regs[1])
}
arg_regs: [.rcx, .rdi]
}
'bool_to_string': BuiltinFn{
.bool_to_string: BuiltinFn{
body: fn (builtin BuiltinFn, mut g Gen) {
g.convert_bool_to_string(builtin.arg_regs[0])
}
arg_regs: [.rax]
}
'reverse_string': BuiltinFn{
.reverse_string: BuiltinFn{
body: fn (builtin BuiltinFn, mut g Gen) {
g.reverse_string(builtin.arg_regs[0])
}
@ -70,17 +78,17 @@ pub fn (mut g Gen) generate_builtins() {
}
}
pub fn (mut g Gen) get_builtin_arg_reg(name string, index int) Register {
pub fn (mut g Gen) get_builtin_arg_reg(name Builtin, index int) Register {
builtin := g.builtins[name] or { panic('undefined builtin function ${name}') }
if index >= builtin.arg_regs.len {
g.n_error('builtin ${name} does only have ${builtin.arg_regs.len} arguments, wanted ${index}')
g.n_error('builtin ${name} does only have ${builtin.arg_regs.len} arguments, requested ${index}')
}
return builtin.arg_regs[index]
}
pub fn (mut g Gen) call_builtin(name string) {
pub fn (mut g Gen) call_builtin(name Builtin) {
if g.pref.arch == .arm64 {
g.n_error('builtin calls are not implemented for amd64')
g.n_error('builtin calls are not implemented for arm64')
} else {
g.builtins[name].calls << g.call_builtin_amd64(name)
}

View File

@ -58,7 +58,7 @@ mut:
strs []String
labels &LabelTable = unsafe { nil }
defer_stmts []ast.DeferStmt
builtins map[string]BuiltinFn
builtins map[Builtin]BuiltinFn
structs []Struct
eval eval.Eval
enum_vals map[string]Enum
@ -723,21 +723,21 @@ fn (mut g Gen) eval_escape_codes(str_lit ast.StringLiteral) string {
fn (mut g Gen) gen_to_string(reg Register, typ ast.Type) {
if typ.is_int() {
buffer := g.allocate_array('itoa-buffer', 1, 32) // 32 characters should be enough
g.lea_var_to_reg(g.get_builtin_arg_reg('int_to_string', 1), buffer)
g.lea_var_to_reg(g.get_builtin_arg_reg(.int_to_string, 1), buffer)
arg0_reg := g.get_builtin_arg_reg('int_to_string', 0)
arg0_reg := g.get_builtin_arg_reg(.int_to_string, 0)
if arg0_reg != reg {
g.mov_reg(arg0_reg, reg)
}
g.call_builtin('int_to_string')
g.call_builtin(.int_to_string)
g.lea_var_to_reg(.rax, buffer)
} else if typ.is_bool() {
arg_reg := g.get_builtin_arg_reg('bool_to_string', 0)
arg_reg := g.get_builtin_arg_reg(.bool_to_string, 0)
if arg_reg != reg {
g.mov_reg(arg_reg, reg)
}
g.call_builtin('bool_to_string')
g.call_builtin(.bool_to_string)
} else if typ.is_string() {
if reg != .rax {
g.mov_reg(.rax, reg)
@ -751,13 +751,13 @@ fn (mut g Gen) gen_var_to_string(reg Register, var Var, config VarConfig) {
typ := g.get_type_from_var(var)
if typ.is_int() {
buffer := g.allocate_array('itoa-buffer', 1, 32) // 32 characters should be enough
g.mov_var_to_reg(g.get_builtin_arg_reg('int_to_string', 0), var, config)
g.lea_var_to_reg(g.get_builtin_arg_reg('int_to_string', 1), buffer)
g.call_builtin('int_to_string')
g.mov_var_to_reg(g.get_builtin_arg_reg(.int_to_string, 0), var, config)
g.lea_var_to_reg(g.get_builtin_arg_reg(.int_to_string, 1), buffer)
g.call_builtin(.int_to_string)
g.lea_var_to_reg(reg, buffer)
} else if typ.is_bool() {
g.mov_var_to_reg(g.get_builtin_arg_reg('bool_to_string', 0), var, config)
g.call_builtin('bool_to_string')
g.mov_var_to_reg(g.get_builtin_arg_reg(.bool_to_string, 0), var, config)
g.call_builtin(.bool_to_string)
} else if typ.is_string() {
g.mov_var_to_reg(.rax, var, config)
} else {