x64: rename to `native` to not conflict with the x64 comptime variable

pull/9900/head
pancake 2021-04-26 15:39:38 +02:00 committed by Delyan Angelov
parent 7587458521
commit 6750ed254f
33 changed files with 90 additions and 85 deletions

View File

@ -398,7 +398,7 @@ jobs:
./v build-module vlib/v/gen/c
./v build-module vlib/v/depgraph
./v build-module vlib/os/cmdline
- name: x64 machine code generation
- name: native machine code generation
run: |
exit
./v -o vprod -prod cmd/v
@ -407,12 +407,12 @@ jobs:
../../vprod gen1m.v
./gen1m > 1m.v
echo "Building it..."
../../vprod -backend x64 -o 1m 1m.v
../../vprod -backend native -o 1m 1m.v
echo "Running it..."
ls
# ./1m
#run: echo "TODO" #cd examples/x64 && ../../v -x64 hello_world.v && ./hello_world
#run: echo "TODO" #cd examples/native && ../../v -native hello_world.v && ./hello_world
# - name: Coveralls GitHub Action
# uses: coverallsapp/github-action@v1.0.1
# with:
@ -482,7 +482,7 @@ jobs:
./v build-module vlib/v/gen/c
./v build-module vlib/v/depgraph
./v build-module vlib/os/cmdline
- name: x64 machine code generation
- name: native machine code generation
run: |
exit
./v -o vprod -prod cmd/v
@ -491,7 +491,7 @@ jobs:
../../vprod gen1m.v
./gen1m > 1m.v
echo "Building it..."
../../vprod -backend x64 -o 1m 1m.v
../../vprod -backend native -o 1m 1m.v
echo "Running it..."
ls

View File

@ -33,7 +33,7 @@ The main files are:
- Constructs the compiler object (`struct V`).
- Creates a list of .v files that need to be parsed.
- Creates a parser object for each file and runs `parse()` on them.
- The correct backend is called (C, JS, x64), and a binary is compiled.
- The correct backend is called (C, JS, native), and a binary is compiled.
2. `v/scanner` The scanner's job is to parse a list of characters and convert
them to tokens.
@ -60,11 +60,11 @@ compiled with Clang, GCC, Visual Studio, and TCC.
supports comptime code generation, and it will be possible to do this using the
language's tools.
9. `v/gen/x64` is the directory with all the machine code generation logic. It
9. `v/gen/native` is the directory with all the machine code generation logic. It
defines a set of functions that translate assembly instructions to machine code
and build the binary from scratch byte by byte. It manually builds all headers,
segments, sections, symtable, relocations, etc. Right now it only has basic
support of the x64 platform/ELF format.
support of the native platform (ELF, MACHO format).
The rest of the directories are vlib modules: `builtin/` (strings, arrays,
maps), `time/`, `os/`, etc. Their documentation is pretty clear.

View File

@ -27,7 +27,7 @@
- Simplicity: the language can be learned in less than an hour
- Fast compilation: ≈110k loc/s with a Clang backend,
≈1 million loc/s with x64 and tcc backends *(Intel i5-7500, SSD, no optimization)* ([demo video](https://www.youtube.com/watch?v=pvP6wmcl_Sc))
≈1 million loc/s with native and tcc backends *(Intel i5-7500, SSD, no optimization)* ([demo video](https://www.youtube.com/watch?v=pvP6wmcl_Sc))
- Easy to develop: V compiles itself in less than a second
- Performance: as fast as C (V's main backend compiles to human readable C)
- Safety: no null, no globals, no undefined behavior, immutability by default

View File

@ -44,7 +44,7 @@ fn main() {
tcc_path = '/usr/local/bin/tcc'
}
diff2 := measure('$vdir/vprod -cc $tcc_path -o v2 $vdir/cmd/v', 'v2')
diff3 := 0 // measure('$vdir/vprod -x64 $vdir/cmd/tools/1mil.v', 'x64 1mil')
diff3 := 0 // measure('$vdir/vprod -native $vdir/cmd/tools/1mil.v', 'native 1mil')
diff4 := measure('$vdir/vprod -cc clang $vdir/examples/hello_world.v', 'hello.v')
vc_size := os.file_size('v.c') / 1000
// scan/parse/check/cgen

View File

@ -53,7 +53,7 @@ Source code: <a target=blank href='https://github.com/vlang/v/blob/master/cmd/to
<td>commit message</td>
<td style='width:120px'>v -o v.c</td>
<td style='width:120px'>v -o v</td>
<td style='width:130px'>v -x64 1mil.v</td>
<td style='width:130px'>v -native 1mil.v</td>
<td style='width:120px'>v hello.v</td>
<td style='width:85px'>v.c size</td>
<td style='width:55px'>parse</td>

View File

@ -125,7 +125,7 @@ const (
'-usecache',
'-prealloc',
'-parallel',
'-x64',
'-native',
'-W',
'-keepc',
'-w',

View File

@ -73,7 +73,7 @@ const (
'vlib/v/fmt/',
'vlib/v/gen/c/',
'vlib/v/gen/js/',
'vlib/v/gen/x64/',
'vlib/v/gen/native/',
'vlib/v/live/',
'vlib/v/markused/',
'vlib/v/parser/',

View File

@ -3881,7 +3881,7 @@ If a file has an environment-specific suffix, it will only be compiled for that
- `.js.v` => will be used only by the JS backend. These files can contain JS. code.
- `.c.v` => will be used only by the C backend. These files can contain C. code.
- `.x64.v` => will be used only by V's x64 backend.
- `.native.v` => will be used only by V's native backend.
- `_nix.c.v` => will be used only on Unix systems (non Windows).
- `_${os}.c.v` => will be used only on the specific `os` system.
For example, `_windows.c.v` will be used only when compiling on Windows, or with `-os windows`.

View File

@ -5,11 +5,11 @@
//}
fn main() {
println('x64 test')
println('native test')
// i := 0
// for i < 5 {
for _ in 1 .. 5 {
println('Hello world from V x64 machine code generator!')
println('Hello world from V native machine code generator!')
// i++
}
/*

View File

@ -42,7 +42,7 @@ pub fn compile(command string, pref &pref.Preferences) {
match pref.backend {
.c { b.compile_c() }
.js { b.compile_js() }
.x64 { b.compile_x64() }
.native { b.compile_native() }
}
if pref.is_stats {
compilation_time_micros := 1 + sw.elapsed().microseconds()

View File

@ -3,12 +3,12 @@ module builder
import v.parser
import v.pref
import v.util
import v.gen.x64
import v.gen.native
import v.markused
pub fn (mut b Builder) build_x64(v_files []string, out_file string) {
pub fn (mut b Builder) build_native(v_files []string, out_file string) {
$if !linux && !macos {
eprintln('Warning: v -x64 can only generate macOS and Linux binaries for now')
eprintln('Warning: v -native can only generate macOS and Linux binaries for now')
}
util.timing_start('PARSE')
b.parsed_files = parser.parse_files(v_files, b.table, b.pref, b.global_scope)
@ -24,14 +24,14 @@ pub fn (mut b Builder) build_x64(v_files []string, out_file string) {
if b.pref.skip_unused {
markused.mark_used(mut b.table, b.pref, b.parsed_files)
}
util.timing_start('x64 GEN')
b.stats_lines, b.stats_bytes = x64.gen(b.parsed_files, b.table, out_file, b.pref)
util.timing_measure('x64 GEN')
util.timing_start('Native GEN')
b.stats_lines, b.stats_bytes = native.gen(b.parsed_files, b.table, out_file, b.pref)
util.timing_measure('Native GEN')
}
pub fn (mut b Builder) compile_x64() {
pub fn (mut b Builder) compile_native() {
// v.files << v.v_files_from_dir(os.join_path(v.pref.vlib_path,'builtin','bare'))
files := [b.pref.path]
b.set_module_lookup_paths()
b.build_x64(files, b.pref.out_name)
b.build_native(files, b.pref.out_name)
}

View File

@ -1,4 +1,4 @@
module x64
module native
import term
import v.ast
@ -459,16 +459,16 @@ pub fn (mut g Gen) call_fn(node ast.CallExpr) {
match expr {
ast.IntegerLiteral {
// `foo(2)` => `mov edi,0x2`
g.mov(x64.fn_arg_registers[i], expr.val.int())
g.mov(native.fn_arg_registers[i], expr.val.int())
}
ast.Ident {
// `foo(x)` => `mov edi,DWORD PTR [rbp-0x8]`
var_offset := g.get_var_offset(expr.name)
if g.pref.is_verbose {
println('i=$i fn name= $name offset=$var_offset')
println(int(x64.fn_arg_registers[i]))
println(int(native.fn_arg_registers[i]))
}
g.mov_var_to_reg(x64.fn_arg_registers[i], var_offset)
g.mov_var_to_reg(native.fn_arg_registers[i], var_offset)
}
else {
verror('unhandled call_fn (name=$name) node: ' + expr.type_name())
@ -514,7 +514,7 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
}
}
else {
g.error_with_pos('x64 assign_stmt unhandled expr: ' + right.type_name(),
g.error_with_pos('native assign_stmt unhandled expr: ' + right.type_name(),
right.position())
}
}
@ -616,7 +616,7 @@ fn (mut g Gen) fn_decl(node ast.FnDecl) {
g.allocate_var(name, 4, 0)
// `mov DWORD PTR [rbp-0x4],edi`
offset += 4
g.mov_reg_to_rbp(offset, x64.fn_arg_registers[i])
g.mov_reg_to_rbp(offset, native.fn_arg_registers[i])
}
//
g.stmts(node.stmts)
@ -634,7 +634,10 @@ fn (mut g Gen) fn_decl(node ast.FnDecl) {
}
pub fn (mut x Amd64) allocate_var(name string, size int, initial_val int) {
mut g := x.g
// do nothing as interface call is crashing
}
pub fn (mut g Gen) allocate_var(name string, size int, initial_val int) {
// `a := 3` =>
// `move DWORD [rbp-0x4],0x3`
match size {

View File

@ -1,4 +1,4 @@
module x64
module native
pub struct Aarch64 {
mut:

View File

@ -1,7 +1,7 @@
// Copyright (c) 2019-2021 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 x64
module native
import os
@ -35,22 +35,22 @@ const (
)
pub fn (mut g Gen) generate_elf_header() {
g.buf << [byte(x64.mag0), x64.mag1, x64.mag2, x64.mag3]
g.buf << x64.elfclass64 // file class
g.buf << x64.elfdata2lsb // data encoding
g.buf << x64.ev_current // file version
g.buf << [byte(native.mag0), native.mag1, native.mag2, native.mag3]
g.buf << native.elfclass64 // file class
g.buf << native.elfdata2lsb // data encoding
g.buf << native.ev_current // file version
g.buf << 1 // elf_osabi
g.write64(0) // et_rel) // et_rel for .o
g.write16(2) // e_type
if g.pref.arch == .aarch64 {
g.write16(x64.e_machine_aarch64)
g.write16(native.e_machine_aarch64)
} else {
g.write16(x64.e_machine_amd64)
g.write16(native.e_machine_amd64)
}
g.write32(x64.ev_current) // e_version
g.write32(native.ev_current) // e_version
eh_size := 0x40
phent_size := 0x38
g.write64(x64.segment_start + eh_size + phent_size) // e_entry
g.write64(native.segment_start + eh_size + phent_size) // e_entry
g.write64(0x40) // e_phoff
g.write64(0) // e_shoff
g.write32(0) // e_flags
@ -64,8 +64,8 @@ pub fn (mut g Gen) generate_elf_header() {
g.write32(1) // p_type
g.write32(5) // p_flags
g.write64(0) // p_offset
g.write64(x64.segment_start) // p_vaddr addr:050
g.write64(x64.segment_start) //
g.write64(native.segment_start) // p_vaddr addr:050
g.write64(native.segment_start) //
g.file_size_pos = i64(g.buf.len)
g.write64(0) // p_filesz PLACEHOLDER, set to file_size later // addr: 060
g.write64(0) // p_memsz
@ -75,7 +75,7 @@ pub fn (mut g Gen) generate_elf_header() {
println('code_start_pos = $g.buf.len.hex()')
g.code_start_pos = i64(g.buf.len)
g.debug_pos = g.buf.len
g.call(x64.placeholder) // call main function, it's not guaranteed to be the first, we don't know its address yet
g.call(native.placeholder) // call main function, it's not guaranteed to be the first, we don't know its address yet
g.println('call fn main')
}
@ -89,7 +89,7 @@ pub fn (mut g Gen) generate_elf_footer() {
// Strings table
// Loop thru all strings and set the right addresses
for i, s in g.strings {
g.write64_at(x64.segment_start + g.buf.len, int(g.str_pos[i]))
g.write64_at(native.segment_start + g.buf.len, int(g.str_pos[i]))
g.write_string(s)
g.write8(0)
}
@ -109,6 +109,6 @@ pub fn (mut g Gen) generate_elf_footer() {
unsafe { f.write_ptr(g.buf.data, g.buf.len) }
f.close()
if g.pref.is_verbose {
println('\nx64 elf binary has been successfully generated')
println('\nnative elf binary has been successfully generated')
}
}

View File

@ -1,7 +1,7 @@
// Copyright (c) 2019-2021 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 x64
module native
/*
This file is unused right now, since binaries without sections

View File

@ -1,7 +1,7 @@
// Copyright (c) 2019-2021 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 x64
module native
import v.ast
import v.util
@ -88,7 +88,7 @@ pub fn (mut g Gen) generate_header() {
}
.raw {}
else {
verror('Error: only `raw`, `linux` and `macos` are supported for -os in -x64')
verror('Error: only `raw`, `linux` and `macos` are supported for -os in -native')
}
}
}
@ -281,7 +281,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
}
ast.StructDecl {}
else {
println('x64.stmt(): bad node: ' + node.type_name())
println('native.stmt(): bad node: ' + node.type_name())
}
}
}
@ -313,14 +313,16 @@ fn (mut g Gen) expr(node ast.Expr) {
ast.StringLiteral {}
ast.StructInit {}
else {
println(term.red('x64.expr(): unhandled node: ' + node.type_name()))
println(term.red('native.expr(): unhandled node: ' + node.type_name()))
}
}
}
/*
fn (mut g Gen) allocate_var(name string, size int, initial_val int) {
g.cgen.allocate_var(name, size, initial_val)
}
*/
fn (mut g Gen) postfix_expr(node ast.PostfixExpr) {
if node.expr !is ast.Ident {
@ -334,7 +336,7 @@ fn (mut g Gen) postfix_expr(node ast.PostfixExpr) {
}
fn verror(s string) {
util.verror('x64 gen error', s)
util.verror('native gen error', s)
}
pub fn (mut g Gen) error_with_pos(s string, pos token.Position) {

View File

@ -1,7 +1,7 @@
// Copyright (c) 2019-2021 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 x64
module native
import os
@ -73,7 +73,7 @@ pub fn (mut g Gen) generate_macho_header() {
g.write32(0x4) // alignment
g.write32(0x160) // relocation offset
g.write32(0x1) // # of relocations
g.write32(x64.s_attr_some_instructions | x64.s_attr_pure_instructions)
g.write32(native.s_attr_some_instructions | native.s_attr_pure_instructions)
g.write32(0)
g.write32(0)
g.write32(0)
@ -88,8 +88,8 @@ pub fn (mut g Gen) generate_macho_header() {
// lc_symtab
g.sym_table_command()
//
g.write32(x64.lc_dymsymtab)
g.write32(x64.macho_d_size)
g.write32(native.lc_dymsymtab)
g.write32(native.macho_d_size)
g.write32(0)
g.write32(2)
g.write32(2)
@ -166,8 +166,8 @@ fn (mut g Gen) sym_table_command() {
name: 'ltmp1'
is_ext: false
}
g.write32(x64.lc_symtab)
g.write32(x64.macho_symcmd_size)
g.write32(native.lc_symtab)
g.write32(native.macho_symcmd_size)
sym_table_offset := 0x168
g.write32(sym_table_offset)
g_syms_len := 4

View File

@ -1,9 +1,9 @@
import v.gen.x64
import v.gen.native
import v.pref
import v.ast
fn test_macho() {
mut g := x64.Gen{
mut g := native.Gen{
pref: &pref.Preferences{}
out_name: 'test.bin'
table: &ast.Table{}

View File

@ -0,0 +1,3 @@
fn main() {
println('hello from native V')
}

View File

@ -0,0 +1 @@
hello from native V

View File

@ -3,26 +3,26 @@ import benchmark
import term
// TODO some logic copy pasted from valgrind_test.v and compiler_test.v, move to a module
fn test_x64() {
fn test_native() {
$if !amd64 {
return
}
if os.user_os() != 'linux' {
eprintln('x64 tests can only be run on Linux for now.')
eprintln('native tests can only be run on Linux for now.')
exit(0)
}
mut bench := benchmark.new_benchmark()
vexe := os.getenv('VEXE')
vroot := os.dir(vexe)
dir := os.join_path(vroot, 'vlib/v/gen/x64/tests')
dir := os.join_path(vroot, 'vlib/v/gen/native/tests')
files := os.ls(dir) or { panic(err) }
//
wrkdir := os.join_path(os.temp_dir(), 'vtests', 'x64')
wrkdir := os.join_path(os.temp_dir(), 'vtests', 'native')
os.mkdir_all(wrkdir) or { panic(err) }
os.chdir(wrkdir)
tests := files.filter(it.ends_with('.vv'))
if tests.len == 0 {
println('no x64 tests found')
println('no native tests found')
assert false
}
bench.set_total_expected_steps(tests.len)
@ -32,10 +32,10 @@ fn test_x64() {
relative_test_path := full_test_path.replace(vroot + '/', '')
work_test_path := '$wrkdir/x.v'
os.cp(full_test_path, work_test_path) or {}
res_x64 := os.execute('$vexe -o exe -x64 $work_test_path')
if res_x64.exit_code != 0 {
res_native := os.execute('$vexe -o exe -native $work_test_path')
if res_native.exit_code != 0 {
bench.fail()
eprintln(bench.step_message_fail('x64 $test failed'))
eprintln(bench.step_message_fail('native $test failed'))
continue
}
res := os.execute('./exe')
@ -64,7 +64,7 @@ fn test_x64() {
}
bench.stop()
eprintln(term.h_divider('-'))
eprintln(bench.total_message('x64'))
eprintln(bench.total_message('native'))
if bench.nfail > 0 {
exit(1)
}

View File

@ -1,5 +1,5 @@
fn print_greeting(){
println('hello from x64')
println('hello from native V')
}
fn print_123() {

View File

@ -0,0 +1,4 @@
start
hello from native V
123
end

View File

@ -1,3 +0,0 @@
fn main() {
println('hello from x64')
}

View File

@ -1 +0,0 @@
hello from x64

View File

@ -1,4 +0,0 @@
start
hello from x64
123
end

View File

@ -47,7 +47,7 @@ pub enum ColorOutput {
pub enum Backend {
c // The (default) C backend
js // The JavaScript backend
x64 // The x64 backend
native // The Native backend
}
pub enum CompilerType {
@ -429,8 +429,8 @@ pub fn parse_args(known_external_commands []string, args []string) (&Preferences
'-parallel' {
res.is_parallel = true
}
'-x64' {
res.backend = .x64
'-native' {
res.backend = .native
res.build_options << arg
}
'-W' {
@ -700,7 +700,7 @@ pub fn backend_from_string(s string) ?Backend {
match s {
'c' { return .c }
'js' { return .js }
'x64' { return .x64 }
'native' { return .native }
else { return error('Unknown backend type $s') }
}
}

View File

@ -109,7 +109,7 @@ fn fname_without_platform_postfix(file string) string {
'_',
'solaris.c.v',
'_',
'x64.v',
'native.v',
'_',
])
return res
@ -126,7 +126,7 @@ pub fn (prefs &Preferences) should_compile_c(file string) bool {
if prefs.os == .all {
return true
}
if prefs.backend != .x64 && file.ends_with('_x64.v') {
if prefs.backend != .native && file.ends_with('_native.v') {
return false
}
if prefs.os != .windows && (file.ends_with('_windows.c.v') || file.ends_with('_windows.v')) {