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:
parent
49277f7aa8
commit
41dd8985fc
@ -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}')
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user