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) {
// v.files << v.v_files_from_dir(os.join_path(v.pref.vlib_path,'builtin','bare'))
files := [b.pref.path]
if b.pref.is_verbose {
println('all .v files before:')
}
mut files := b.get_builtin_files()
files << b.get_user_files()
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)
}

View File

@ -2560,7 +2560,7 @@ fn (mut c Amd64) multi_assign_stmt(node ast.AssignStmt) {
})
}
else {
c.g.n_error('Unsupported assign instruction')
c.g.n_error('Unsupported assign instruction (${node.op})')
}
}
} else if left_type.is_pure_float() {
@ -2640,7 +2640,7 @@ fn (mut c Amd64) assign_stmt(node ast.AssignStmt) {
})
}
else {
c.g.n_error('Unsupported assign instruction')
c.g.n_error('Unsupported assign instruction (${node.op})')
}
}
} else if typ.is_pure_float() {
@ -2679,7 +2679,7 @@ fn (mut c Amd64) assign_stmt(node ast.AssignStmt) {
}
} else {
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)
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 {
g.gen_typeof_expr(node, false)
}
ast.SizeOf {
g.gen_sizeof_expr(node)
}
else {
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))
}
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) {
newline := name in ['println', 'eprintln']
fd := if name in ['eprint', 'eprintln'] { 2 } else { 1 }

View File

@ -128,6 +128,17 @@ mut:
type Register = Amd64Register | Arm64Register
fn (r Register) str() string {
return match r {
Amd64Register {
'${r as Amd64Register}'
}
Arm64Register {
'${r as Arm64Register}'
}
}
}
enum RelocType {
rel8
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}
eval: eval.new_eval(table, pref_)
}
g.code_gen.g = g
g.generate_header()
g.init_builtins()
@ -976,10 +988,7 @@ fn (mut g Gen) fn_decl(node ast.FnDecl) {
} else {
node.name
}
if node.no_body || !g.is_used_by_main(node) {
if g.pref.is_verbose {
println(term.italic(term.green('\n-> skipping unused function `${name}`')))
}
if node.no_body || !g.is_used_by_main(node) || g.is_blacklisted(name, node.is_builtin) {
return
}
if g.pref.is_verbose {
@ -988,9 +997,6 @@ fn (mut g Gen) fn_decl(node ast.FnDecl) {
if node.is_deprecated {
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_depth = 0

View File

@ -70,15 +70,22 @@ fn (mut g Gen) stmt(node ast.Stmt) {
}
ast.HashStmt {
words := node.val.split(' ')
mut unsupported := false
for word in words {
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 := word.u8()
// println('"$word" $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.Return {
@ -90,10 +97,14 @@ fn (mut g Gen) stmt(node ast.Stmt) {
ast.AssertStmt {
g.code_gen.gen_assert(node)
}
ast.GlobalDecl {
g.warning('globals are not supported yet', node.pos)
}
ast.Import {} // do nothing here
ast.StructDecl {}
ast.EnumDecl {}
ast.TypeDecl {}
ast.InterfaceDecl {}
else {
eprintln('native.stmt(): bad node: ' + node.type_name())
}
@ -119,9 +130,15 @@ fn (mut g Gen) gen_forc_stmt(node ast.ForCStmt) {
.gt {
jump_addr = g.code_gen.cjmp(.jle)
}
.ge {
jump_addr = g.code_gen.cjmp(.jl)
}
.lt {
jump_addr = g.code_gen.cjmp(.jge)
}
.le {
jump_addr = g.code_gen.cjmp(.jg)
}
else {
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
fn C.isalpha(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() {
charutil()
memory()
}
fn charutil() {
// only linux supports linking right now
$if linux {
// ascii for `V`
v_is_alpha := C.isalpha(86)
if v_is_alpha != 0 {
println('ok 1')
} else {
assert false
}
assert v_is_alpha != 0
null_is_alpha := C.isalpha(0)
if null_is_alpha == 0 {
println('ok 2')
} else {
assert false
}
assert null_is_alpha == 0
// ascii for `3`
three_is_digit := C.isdigit(51)
if three_is_digit != 0 {
println('ok 3')
} else {
assert false
}
} $else {
println('ok 1')
println('ok 2')
println('ok 3')
assert three_is_digit != 0
}
}
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