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

native, builder: enable processing of .v files in the builtin module (for now most functions there are blacklisted) (#18735)

This commit is contained in:
Spydr 2023-07-02 13:16:15 +02:00 committed by GitHub
parent 0ce3e46823
commit f3942417c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 119 additions and 35 deletions

View File

@ -13,9 +13,16 @@ pub fn start() {
} }
pub fn compile_native(mut b builder.Builder) { pub fn compile_native(mut b builder.Builder) {
// v.files << v.v_files_from_dir(os.join_path(v.pref.vlib_path,'builtin','bare')) if b.pref.is_verbose {
files := [b.pref.path] println('all .v files before:')
}
mut files := b.get_builtin_files()
files << b.get_user_files()
b.set_module_lookup_paths() b.set_module_lookup_paths()
if b.pref.is_verbose {
println('all .v files:')
println(files)
}
build_native(mut b, files, b.pref.out_name) build_native(mut b, files, b.pref.out_name)
} }

View File

@ -2560,7 +2560,7 @@ fn (mut c Amd64) multi_assign_stmt(node ast.AssignStmt) {
}) })
} }
else { else {
c.g.n_error('Unsupported assign instruction') c.g.n_error('Unsupported assign instruction (${node.op})')
} }
} }
} else if left_type.is_pure_float() { } else if left_type.is_pure_float() {
@ -2640,7 +2640,7 @@ fn (mut c Amd64) assign_stmt(node ast.AssignStmt) {
}) })
} }
else { else {
c.g.n_error('Unsupported assign instruction') c.g.n_error('Unsupported assign instruction (${node.op})')
} }
} }
} else if typ.is_pure_float() { } else if typ.is_pure_float() {
@ -2679,7 +2679,7 @@ fn (mut c Amd64) assign_stmt(node ast.AssignStmt) {
} }
} else { } else {
if node.op !in [.assign, .decl_assign] { if node.op !in [.assign, .decl_assign] {
c.g.n_error('Unsupported assign instruction') c.g.n_error('Unsupported assign instruction (${node.op})')
} }
ts := c.g.table.sym(typ) ts := c.g.table.sym(typ)
match ts.kind { match ts.kind {

View File

@ -0,0 +1,37 @@
// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module native
// this is a TEMPORARY system used to enable/disable parts of the
// builtin module until more of `builtin` is supported by native
/*
already compiling functions:
string.+
string.clone
string.free
ArrayFlags.set
ArrayFlags.clear
u8.vstring_with_len
Error.msg
Error.code
MessageError.code
MessageError.free
u64.hex
VAssertMetaInfo.free"
__new_array
new_array_from_c_array
new_array_from_c_array_no_alloc
...
*/
// false: whitelist function
// true: blacklist function
const whitelist = {
'main.main': false
}
fn (g Gen) is_blacklisted(name string, is_builtin bool) bool {
return native.whitelist[name] or { is_builtin }
}

View File

@ -116,6 +116,9 @@ fn (mut g Gen) expr(node ast.Expr) {
ast.TypeOf { ast.TypeOf {
g.gen_typeof_expr(node, false) g.gen_typeof_expr(node, false)
} }
ast.SizeOf {
g.gen_sizeof_expr(node)
}
else { else {
g.n_error('expr: unhandled node type: ${node.type_name()}') g.n_error('expr: unhandled node type: ${node.type_name()}')
} }
@ -283,6 +286,14 @@ fn (mut g Gen) gen_typeof_expr(node ast.TypeOf, newline bool) {
g.code_gen.learel(g.code_gen.main_reg(), g.allocate_string('${str}${nl}', 3, .rel32)) g.code_gen.learel(g.code_gen.main_reg(), g.allocate_string('${str}${nl}', 3, .rel32))
} }
fn (mut g Gen) gen_sizeof_expr(node ast.SizeOf) {
ts := g.table.sym(node.typ)
if ts.language == .v && ts.kind in [.placeholder, .any] {
g.v_error('unknown type `${ts.name}`', node.pos)
}
g.code_gen.mov64(g.code_gen.main_reg(), g.get_type_size(node.typ))
}
fn (mut g Gen) gen_print_from_expr(expr ast.Expr, typ ast.Type, name string) { fn (mut g Gen) gen_print_from_expr(expr ast.Expr, typ ast.Type, name string) {
newline := name in ['println', 'eprintln'] newline := name in ['println', 'eprintln']
fd := if name in ['eprint', 'eprintln'] { 2 } else { 1 } fd := if name in ['eprint', 'eprintln'] { 2 } else { 1 }

View File

@ -128,6 +128,17 @@ mut:
type Register = Amd64Register | Arm64Register type Register = Amd64Register | Arm64Register
fn (r Register) str() string {
return match r {
Amd64Register {
'${r as Amd64Register}'
}
Arm64Register {
'${r as Arm64Register}'
}
}
}
enum RelocType { enum RelocType {
rel8 rel8
rel16 rel16
@ -322,6 +333,7 @@ pub fn gen(files []&ast.File, table &ast.Table, out_name string, pref_ &pref.Pre
structs: []Struct{len: table.type_symbols.len} structs: []Struct{len: table.type_symbols.len}
eval: eval.new_eval(table, pref_) eval: eval.new_eval(table, pref_)
} }
g.code_gen.g = g g.code_gen.g = g
g.generate_header() g.generate_header()
g.init_builtins() g.init_builtins()
@ -976,10 +988,7 @@ fn (mut g Gen) fn_decl(node ast.FnDecl) {
} else { } else {
node.name node.name
} }
if node.no_body || !g.is_used_by_main(node) { if node.no_body || !g.is_used_by_main(node) || g.is_blacklisted(name, node.is_builtin) {
if g.pref.is_verbose {
println(term.italic(term.green('\n-> skipping unused function `${name}`')))
}
return return
} }
if g.pref.is_verbose { if g.pref.is_verbose {
@ -988,9 +997,6 @@ fn (mut g Gen) fn_decl(node ast.FnDecl) {
if node.is_deprecated { if node.is_deprecated {
g.warning('fn_decl: ${name} is deprecated', node.pos) g.warning('fn_decl: ${name} is deprecated', node.pos)
} }
if node.is_builtin {
g.warning('fn_decl: ${name} is builtin', node.pos)
}
g.stack_var_pos = 0 g.stack_var_pos = 0
g.stack_depth = 0 g.stack_depth = 0

View File

@ -70,15 +70,22 @@ fn (mut g Gen) stmt(node ast.Stmt) {
} }
ast.HashStmt { ast.HashStmt {
words := node.val.split(' ') words := node.val.split(' ')
mut unsupported := false
for word in words { for word in words {
if word.len != 2 { if word.len != 2 {
g.n_error('opcodes format: xx xx xx xx\nhash statements are not allowed with the native backend, use the C backend for extended C interoperability.') unsupported = true
break
} }
b := unsafe { C.strtol(&char(word.str), 0, 16) } b := unsafe { C.strtol(&char(word.str), 0, 16) }
// b := word.u8() // b := word.u8()
// println('"$word" $b') // println('"$word" $b')
g.write8(b) g.write8(b)
} }
if unsupported {
g.warning('opcodes format: xx xx xx xx\nhash statements are not allowed with the native backend, use the C backend for extended C interoperability.',
node.pos)
}
} }
ast.Module {} ast.Module {}
ast.Return { ast.Return {
@ -90,10 +97,14 @@ fn (mut g Gen) stmt(node ast.Stmt) {
ast.AssertStmt { ast.AssertStmt {
g.code_gen.gen_assert(node) g.code_gen.gen_assert(node)
} }
ast.GlobalDecl {
g.warning('globals are not supported yet', node.pos)
}
ast.Import {} // do nothing here ast.Import {} // do nothing here
ast.StructDecl {} ast.StructDecl {}
ast.EnumDecl {} ast.EnumDecl {}
ast.TypeDecl {} ast.TypeDecl {}
ast.InterfaceDecl {}
else { else {
eprintln('native.stmt(): bad node: ' + node.type_name()) eprintln('native.stmt(): bad node: ' + node.type_name())
} }
@ -119,9 +130,15 @@ fn (mut g Gen) gen_forc_stmt(node ast.ForCStmt) {
.gt { .gt {
jump_addr = g.code_gen.cjmp(.jle) jump_addr = g.code_gen.cjmp(.jle)
} }
.ge {
jump_addr = g.code_gen.cjmp(.jl)
}
.lt { .lt {
jump_addr = g.code_gen.cjmp(.jge) jump_addr = g.code_gen.cjmp(.jge)
} }
.le {
jump_addr = g.code_gen.cjmp(.jg)
}
else { else {
g.n_error('unsupported conditional in for-c loop') g.n_error('unsupported conditional in for-c loop')
} }

View File

@ -1,38 +1,47 @@
// because of an issue with checker, all C.* functions have to be declared first // because of an issue with checker, all C.* functions have to be declared first
fn C.isalpha(c int) int fn C.isalpha(c int) int
fn C.isdigit(c int) int fn C.isdigit(c int) int
fn C.malloc(n u64) voidptr
fn C.free(ptr voidptr)
fn C.memset(ptr voidptr, c int, n u64) voidptr
fn main() { fn main() {
charutil() charutil()
memory()
} }
fn charutil() { fn charutil() {
// only linux supports linking right now
$if linux { $if linux {
// ascii for `V` // ascii for `V`
v_is_alpha := C.isalpha(86) v_is_alpha := C.isalpha(86)
if v_is_alpha != 0 { assert v_is_alpha != 0
println('ok 1')
} else {
assert false
}
null_is_alpha := C.isalpha(0) null_is_alpha := C.isalpha(0)
if null_is_alpha == 0 { assert null_is_alpha == 0
println('ok 2')
} else {
assert false
}
// ascii for `3` // ascii for `3`
three_is_digit := C.isdigit(51) three_is_digit := C.isdigit(51)
if three_is_digit != 0 { assert three_is_digit != 0
println('ok 3')
} else {
assert false
}
} $else {
println('ok 1')
println('ok 2')
println('ok 3')
} }
} }
fn memory() {
$if linux {
// allocate some memory
buf := &int(C.malloc(100))
assert buf != unsafe { nil }
C.memset(buf, 0, 100)
assert *buf == 0
unsafe {
*buf = 123456
*(buf + sizeof(int)) = 100
}
assert *buf == 123456
assert *(buf + sizeof(int)) == 100
C.free(voidptr(buf))
}
}

View File

@ -1,3 +0,0 @@
ok 1
ok 2
ok 3