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)
|
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}')
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user