native: better raw output and more arm64 cleanup

pull/9900/head
pancake 2021-04-26 23:35:32 +02:00 committed by Delyan Angelov
parent 9a3869c521
commit 9b07278930
5 changed files with 134 additions and 107 deletions

View File

@ -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:'))
}

View File

@ -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')
}

View File

@ -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()
}

View File

@ -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 {`

View File

@ -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)