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) call_addr := g.call(0)
g.println('call builtin `${name}`') g.println('call builtin `${name}`')
return call_addr 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 g.labels.addrs[loop_label] = loop_start
// after all was converted, reverse the string // 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.mov_reg(reg, .r12)
g.call_builtin('reverse_string') g.call_builtin(.reverse_string)
g.labels.addrs[end_label] = g.pos() g.labels.addrs[end_label] = g.pos()
g.println('; label ${end_label}') g.println('; label ${end_label}')

View File

@ -5,6 +5,13 @@ module native
import term import term
enum Builtin {
int_to_string
bool_to_string
reverse_string
compare_strings
}
struct BuiltinFn { struct BuiltinFn {
body fn (builtin BuiltinFn, mut g Gen) body fn (builtin BuiltinFn, mut g Gen)
arg_regs []Register arg_regs []Register
@ -18,19 +25,20 @@ pub fn (mut g Gen) init_builtins() {
g.builtins = { g.builtins = {
// longer algorithms and internal functions inaccessible to the user // longer algorithms and internal functions inaccessible to the user
// used to keep executable size small and the bytecode distraction-free // 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) { body: fn (builtin BuiltinFn, mut g Gen) {
g.convert_int_to_string(builtin.arg_regs[0], builtin.arg_regs[1]) g.convert_int_to_string(builtin.arg_regs[0], builtin.arg_regs[1])
} }
arg_regs: [.rcx, .rdi] arg_regs: [.rcx, .rdi]
} }
'bool_to_string': BuiltinFn{ .bool_to_string: BuiltinFn{
body: fn (builtin BuiltinFn, mut g Gen) { body: fn (builtin BuiltinFn, mut g Gen) {
g.convert_bool_to_string(builtin.arg_regs[0]) g.convert_bool_to_string(builtin.arg_regs[0])
} }
arg_regs: [.rax] arg_regs: [.rax]
} }
'reverse_string': BuiltinFn{ .reverse_string: BuiltinFn{
body: fn (builtin BuiltinFn, mut g Gen) { body: fn (builtin BuiltinFn, mut g Gen) {
g.reverse_string(builtin.arg_regs[0]) 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}') } builtin := g.builtins[name] or { panic('undefined builtin function ${name}') }
if index >= builtin.arg_regs.len { 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] 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 { 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 { } else {
g.builtins[name].calls << g.call_builtin_amd64(name) g.builtins[name].calls << g.call_builtin_amd64(name)
} }

View File

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