From 9b0727893024263ca2f0e2dfa42d9e7f6edf5b01 Mon Sep 17 00:00:00 2001 From: pancake Date: Mon, 26 Apr 2021 23:35:32 +0200 Subject: [PATCH] native: better raw output and more arm64 cleanup --- vlib/v/gen/native/amd64.v | 6 ++- vlib/v/gen/native/arm64.v | 95 +++++++++++++++++++++++++++++++++++++- vlib/v/gen/native/elf.v | 17 ++----- vlib/v/gen/native/gen.v | 27 +++++++++-- vlib/v/gen/native/macho.v | 96 ++++----------------------------------- 5 files changed, 134 insertions(+), 107 deletions(-) diff --git a/vlib/v/gen/native/amd64.v b/vlib/v/gen/native/amd64.v index d1eaa51e94..25d7cabb89 100644 --- a/vlib/v/gen/native/amd64.v +++ b/vlib/v/gen/native/amd64.v @@ -223,7 +223,7 @@ fn (mut g Gen) call(addr int) { // println('call addr=$addr.hex2() rel_addr=$rel.hex2() pos=$g.buf.len') g.write8(0xe8) g.write32(rel) - // g.println('fn call') + g.println('call $addr') } fn (mut g Gen) syscall() { @@ -589,6 +589,10 @@ fn (mut g Gen) for_stmt(node ast.ForStmt) { } fn (mut g Gen) fn_decl(node ast.FnDecl) { + if g.pref.arch == .arm64 { + g.fn_decl_arm64(node) + return + } if g.pref.is_verbose { println(term.green('\n$node.name:')) } diff --git a/vlib/v/gen/native/arm64.v b/vlib/v/gen/native/arm64.v index d87f0cde56..c0974648ca 100644 --- a/vlib/v/gen/native/arm64.v +++ b/vlib/v/gen/native/arm64.v @@ -1,11 +1,102 @@ module native -pub struct Aarch64 { +import v.ast + +enum Arm64Register { + x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 + x12 + x13 + x14 + x15 + x16 +} + +pub struct Arm64 { mut: // arm64 specific stuff for code generation g Gen } -pub fn (mut x Aarch64) allocate_var(name string, size int, initial_val int) { +pub fn (mut x Arm64) allocate_var(name string, size int, initial_val int) { eprintln('TODO: allocating var on arm64 ($name) = $size = $initial_val') } + +fn (mut g Gen) mov_arm(reg Arm64Register, val u64) { + // m := u64(0xffff) + // x := u64(val) + // println('========') + // println(x & ~m) + // println(x & ~(m << 16)) + // g.write32(0x777777) + r := int(reg) + if r == 0 && val == 1 { + g.write32(0xd2800020) + g.println('mov x0, 1') + } else if r == 0 { + g.write32(0xd2800000) + g.println('mov x0, 0') + } else if r == 16 { + g.write32(0xd2800030) + g.println('mov x16, 1') + } + /* + if 1 ^ (x & ~m) != 0 { + // println('yep') + g.write32(int(u64(0x52800000) | u64(r) | x << 5)) + g.write32(0x88888888) + g.write32(int(u64(0x52800000) | u64(r) | x >> 11)) + } else if 1 ^ (x & ~(m << 16)) != 0 { + // g.write32(int(u64(0x52800000) | u64(r) | x >> 11)) + // println('yep2') + // g.write32(0x52a00000 | r | val >> 11) + } + */ +} + +pub fn (mut g Gen) fn_decl_arm64(node ast.FnDecl) { + // TODO +} + +fn (mut g Gen) gen_arm64_helloworld() { + // ADD THE CODE HERE THIS GOES INTO THE STMTS THING + // g.write32(0x77777777) + // assembly + g.mov_arm(.x0, 1) + g.adr() + g.bl() + g.mov_arm(.x0, 0) + g.mov_arm(.x16, 1) + g.svc() + // + g.write_string('Hello World!\n') + g.write8(0) // padding? + g.write8(0) + g.write8(0) +} + +fn (mut g Gen) adr() { + g.write32(0x100000a0) + g.println('adr x0, 0x14') +} + +fn (mut g Gen) bl() { + // g.write32(0xa9400000) + g.write32(0x94000000) + g.println('bl 0') +} + +fn (mut g Gen) svc() { + g.write32(0xd4001001) + g.println('svc') +} diff --git a/vlib/v/gen/native/elf.v b/vlib/v/gen/native/elf.v index 1e31837fc4..7e6239dbfc 100644 --- a/vlib/v/gen/native/elf.v +++ b/vlib/v/gen/native/elf.v @@ -3,8 +3,6 @@ // that can be found in the LICENSE file. module native -import os - const ( mag0 = byte(0x7f) mag1 = `E` @@ -72,11 +70,13 @@ pub fn (mut g Gen) generate_elf_header() { g.write64(0x1000) // p_align // user code starts here at // address: 00070 and a half - println('code_start_pos = $g.buf.len.hex()') + if g.pref.is_verbose { + eprintln('code_start_pos = $g.buf.len.hex()') + } g.code_start_pos = i64(g.buf.len) g.debug_pos = g.buf.len 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') + g.println('; call fn main') } pub fn (mut g Gen) generate_elf_footer() { @@ -103,12 +103,5 @@ pub fn (mut g Gen) generate_elf_footer() { // +1 is for "e8" // -5 is for "e8 00 00 00 00" g.write32_at(g.code_start_pos + 1, int(g.main_fn_addr - g.code_start_pos) - 5) - // Create the binary - mut f := os.create(g.out_name) or { panic(err) } - os.chmod(g.out_name, 0o775) // make it an executable - unsafe { f.write_ptr(g.buf.data, g.buf.len) } - f.close() - if g.pref.is_verbose { - println('\nnative elf binary has been successfully generated') - } + g.create_executable() } diff --git a/vlib/v/gen/native/gen.v b/vlib/v/gen/native/gen.v index 1158efd27e..ef4796312a 100644 --- a/vlib/v/gen/native/gen.v +++ b/vlib/v/gen/native/gen.v @@ -3,6 +3,7 @@ // that can be found in the LICENSE file. module native +import os import v.ast import v.util import v.token @@ -49,7 +50,7 @@ enum Size { fn (g Gen) get_backend(pref &pref.Preferences) CodeGen { if pref.arch == .arm64 { - return Aarch64{} + return Arm64{} } return Amd64{} } @@ -86,13 +87,28 @@ pub fn (mut g Gen) generate_header() { .linux { g.generate_elf_header() } - .raw {} + .raw { + if g.pref.arch == .arm64 { + g.gen_arm64_helloworld() + } + } else { verror('Error: only `raw`, `linux` and `macos` are supported for -os in -native') } } } +pub fn (mut g Gen) create_executable() { + // Create the binary // should be .o ? + mut f := os.create(g.out_name) or { panic(err) } + os.chmod(g.out_name, 0o775) // make it executable + unsafe { f.write_ptr(g.buf.data, g.buf.len) } + f.close() + if g.pref.is_verbose { + println('\narm64 mach-o binary has been successfully generated') + } +} + pub fn (mut g Gen) generate_footer() { match g.pref.os { .macos { @@ -101,9 +117,10 @@ pub fn (mut g Gen) generate_footer() { .linux { g.generate_elf_footer() } - else { - g.generate_macho_footer() + .raw { + g.create_executable() } + else {} } } @@ -221,7 +238,7 @@ pub fn (mut g Gen) register_function_address(name string) { } fn (mut g Gen) for_in_stmt(node ast.ForInStmt) { - eprintln('for-in statement is not yet implemented') + verror('for-in statement is not yet implemented') /* if node.is_range { // `for x in 1..10 {` diff --git a/vlib/v/gen/native/macho.v b/vlib/v/gen/native/macho.v index dca8b4e2e3..7005263cc5 100644 --- a/vlib/v/gen/native/macho.v +++ b/vlib/v/gen/native/macho.v @@ -3,8 +3,6 @@ // that can be found in the LICENSE file. module native -import os - const ( s_attr_some_instructions = 0x00000400 s_attr_pure_instructions = 0x80000000 @@ -99,33 +97,19 @@ pub fn (mut g Gen) generate_macho_header() { for _ in 0 .. 12 { g.write32(0) } - // ADD THE CODE HERE THIS GOES INTO THE STMTS THING - // g.write32(0x77777777) - // assembly - g.mov_arm(.x0, 1) - g.adr() - g.bl() - g.mov_arm(.x0, 0) - g.mov_arm(.x16, 1) - g.svc() - // - g.write_string('Hello World!\n') - g.write8(0) // padding? - g.write8(0) - g.write8(0) + + if g.pref.arch == .arm64 { + g.gen_arm64_helloworld() + } + +} + +pub fn (mut g Gen) generate_macho_footer() { g.write_relocs() g.sym_table() g.sym_string_table() g.write8(0) -} - -pub fn (mut g Gen) generate_macho_footer() { - // Create the binary // should be .o ? - mut f := os.create(g.out_name) or { panic(err) } - os.chmod(g.out_name, 0o775) // make it executable - unsafe { f.write_ptr(g.buf.data, g.buf.len) } - f.close() - // println('\narm64 mach-o binary has been successfully generated') + g.create_executable() } fn (mut g Gen) sym_table_command() { @@ -184,68 +168,6 @@ pub fn (mut g Gen) zeroes(n int) { } } -enum Register2 { - x0 - x1 - x2 - x3 - x4 - x5 - x6 - x7 - x8 - x9 - x10 - x11 - x12 - x13 - x14 - x15 - x16 -} - -fn (mut g Gen) mov_arm(reg Register2, val u64) { - // m := u64(0xffff) - // x := u64(val) - // println('========') - // println(x & ~m) - // println(x & ~(m << 16)) - // g.write32(0x777777) - r := int(reg) - if r == 0 && val == 1 { - g.write32(0xd2800020) - } else if r == 0 { - g.write32(0xd2800000) - } else if r == 16 { - g.write32(0xd2800030) - } - /* - if 1 ^ (x & ~m) != 0 { - // println('yep') - g.write32(int(u64(0x52800000) | u64(r) | x << 5)) - g.write32(0x88888888) - g.write32(int(u64(0x52800000) | u64(r) | x >> 11)) - } else if 1 ^ (x & ~(m << 16)) != 0 { - // g.write32(int(u64(0x52800000) | u64(r) | x >> 11)) - // println('yep2') - // g.write32(0x52a00000 | r | val >> 11) - } - */ -} - -fn (mut g Gen) adr() { - g.write32(0x100000a0) -} - -fn (mut g Gen) bl() { - // g.write32(0xa9400000) - g.write32(0x94000000) -} - -fn (mut g Gen) svc() { - g.write32(0xd4001001) -} - fn (mut g Gen) write_relocs() { g.write32(0x8) g.write32(0x2d000003)