mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
native: support simple library calls (#15958)
This commit is contained in:
parent
9fc64de94b
commit
6ac9552d39
@ -866,6 +866,20 @@ fn (mut g Gen) call(addr int) i64 {
|
|||||||
return c_addr
|
return c_addr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) extern_call(addr int) {
|
||||||
|
match g.pref.os {
|
||||||
|
.linux {
|
||||||
|
g.write8(0xff)
|
||||||
|
g.write8(0x15)
|
||||||
|
g.write32(0)
|
||||||
|
g.println('call *@GOTPCREL(%rip)')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g.n_error('extern calls are not implemented for $g.pref.os')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) syscall() {
|
fn (mut g Gen) syscall() {
|
||||||
// g.write(0x050f)
|
// g.write(0x050f)
|
||||||
g.write8(0x0f)
|
g.write8(0x0f)
|
||||||
@ -1725,7 +1739,10 @@ pub fn (mut g Gen) call_fn_amd64(node ast.CallExpr) {
|
|||||||
for i in 0 .. reg_size {
|
for i in 0 .. reg_size {
|
||||||
g.pop(native.fn_arg_registers[i])
|
g.pop(native.fn_arg_registers[i])
|
||||||
}
|
}
|
||||||
if addr == 0 {
|
if node.name in g.extern_symbols {
|
||||||
|
g.extern_fn_calls[g.pos()] = node.name
|
||||||
|
g.extern_call(int(addr))
|
||||||
|
} else if addr == 0 {
|
||||||
g.delay_fn_call(n)
|
g.delay_fn_call(n)
|
||||||
g.call(int(0))
|
g.call(int(0))
|
||||||
} else {
|
} else {
|
||||||
|
@ -87,7 +87,7 @@ const (
|
|||||||
elf_sh_symtab_entsize = elf_symtab_size
|
elf_sh_symtab_entsize = elf_symtab_size
|
||||||
elf_sh_symtab_align = 8
|
elf_sh_symtab_align = 8
|
||||||
|
|
||||||
// elf symbol bining
|
// elf symbol binding
|
||||||
elf_stb_local = u8(0)
|
elf_stb_local = u8(0)
|
||||||
elf_stb_global = u8(1)
|
elf_stb_global = u8(1)
|
||||||
|
|
||||||
@ -123,6 +123,7 @@ const (
|
|||||||
elf_r_amd64_gotpc32 = 26
|
elf_r_amd64_gotpc32 = 26
|
||||||
elf_r_amd64_size32 = 32
|
elf_r_amd64_size32 = 32
|
||||||
elf_r_amd64_size64 = 33
|
elf_r_amd64_size64 = 33
|
||||||
|
elf_r_amd64_gotpcrelx = 0x29
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -288,6 +289,8 @@ mut:
|
|||||||
info int // Extra section information.
|
info int // Extra section information.
|
||||||
addralign i64 // Section Alignment (must be power of two).
|
addralign i64 // Section Alignment (must be power of two).
|
||||||
entsize i64 // Section entry size.
|
entsize i64 // Section entry size.
|
||||||
|
|
||||||
|
pos i64 // not part of the actual data
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SymbolTableSection {
|
struct SymbolTableSection {
|
||||||
@ -301,13 +304,14 @@ mut:
|
|||||||
size i64 // Symbol size.
|
size i64 // Symbol size.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) create_symbol_table_section(str_name string, info u8, bind u8, other i8, value i64, size i64) SymbolTableSection {
|
fn (mut g Gen) create_symbol_table_section(str_name string, info u8, bind u8, other i8, value i64, size i64, shndx i16) SymbolTableSection {
|
||||||
return SymbolTableSection{
|
return SymbolTableSection{
|
||||||
str_name: str_name
|
str_name: str_name
|
||||||
info: i8(info | bind << 4)
|
info: i8(info | bind << 4)
|
||||||
other: other
|
other: other
|
||||||
value: value
|
value: value
|
||||||
size: size
|
size: size
|
||||||
|
shndx: shndx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,14 +334,16 @@ fn (mut g Gen) create_progbits_section(bytes []u8) ProgBitsSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct RelASection {
|
struct RelASection {
|
||||||
|
name string // not in the actual data
|
||||||
mut:
|
mut:
|
||||||
offset i64 // Location at which to apply the relocation action.
|
offset i64 // Location at which to apply the relocation action.
|
||||||
info i64 // Symbol table index and type of relocation to apply.
|
info i64 // Symbol table index and type of relocation to apply.
|
||||||
addend i64 // Constant addent for computing the value of the relocation field.
|
addend i64 // Constant addent for computing the value of the relocation field.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) create_rela_section(offset i64, sym u32, typ u32, addend i64) RelASection {
|
fn (mut g Gen) create_rela_section(name string, offset i64, sym int, typ u32, addend i64) RelASection {
|
||||||
return RelASection{
|
return RelASection{
|
||||||
|
name: name
|
||||||
offset: offset
|
offset: offset
|
||||||
info: i64((u64(sym) << 32) + typ)
|
info: i64((u64(sym) << 32) + typ)
|
||||||
addend: addend
|
addend: addend
|
||||||
@ -426,11 +432,11 @@ type SectionData = DynSymSection
|
|||||||
| NoBitsSection
|
| NoBitsSection
|
||||||
| NoteSection
|
| NoteSection
|
||||||
| ProgBitsSection
|
| ProgBitsSection
|
||||||
| RelASection
|
|
||||||
| RelSection
|
| RelSection
|
||||||
| ShLibSection
|
| ShLibSection
|
||||||
| StringTableSection
|
| StringTableSection
|
||||||
| []DynamicSection
|
| []DynamicSection
|
||||||
|
| []RelASection
|
||||||
| []SymbolTableSection
|
| []SymbolTableSection
|
||||||
|
|
||||||
struct Section {
|
struct Section {
|
||||||
@ -476,15 +482,15 @@ fn (mut g Gen) create_shstrtab(mut sections []Section) {
|
|||||||
fn (mut g Gen) create_symtab(mut sections []Section, mut table []SymbolTableSection) {
|
fn (mut g Gen) create_symtab(mut sections []Section, mut table []SymbolTableSection) {
|
||||||
mut names := []string{len: table.len}
|
mut names := []string{len: table.len}
|
||||||
mut offset := 1
|
mut offset := 1
|
||||||
|
mut local_symbols := 0
|
||||||
text_section := g.find_section_header('.text', sections)
|
|
||||||
|
|
||||||
for i, mut entry in table {
|
for i, mut entry in table {
|
||||||
names[i] = entry.str_name
|
names[i] = entry.str_name
|
||||||
|
|
||||||
entry.name = offset
|
entry.name = offset
|
||||||
if entry.name != 1 {
|
|
||||||
entry.shndx = i16(text_section) // i16(sections.len + 1)
|
if (entry.info >> 4) == native.elf_stb_local {
|
||||||
|
local_symbols++
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += entry.str_name.len + 1
|
offset += entry.str_name.len + 1
|
||||||
@ -493,10 +499,18 @@ fn (mut g Gen) create_symtab(mut sections []Section, mut table []SymbolTableSect
|
|||||||
sections << g.create_section('.strtab', native.elf_sht_strtab, 0, 0, 1, 0, g.create_string_table_section(names))
|
sections << g.create_section('.strtab', native.elf_sht_strtab, 0, 0, 1, 0, g.create_string_table_section(names))
|
||||||
|
|
||||||
sections << // index of .strtab
|
sections << // index of .strtab
|
||||||
g.create_section('.symtab', native.elf_sht_symtab, sections.len - 1, table.len - 1,
|
g.create_section('.symtab', native.elf_sht_symtab, sections.len - 1, local_symbols,
|
||||||
native.elf_sh_symtab_align, native.elf_sh_symtab_entsize, table)
|
native.elf_sh_symtab_align, native.elf_sh_symtab_entsize, table)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) create_relocation(name string, mut sections []Section, table []RelASection) Section {
|
||||||
|
mut section := g.create_section(name, native.elf_sht_rela, g.find_section_header('.symtab',
|
||||||
|
sections), 1, 8, 24, table)
|
||||||
|
section.header.flags = i64(native.elf_shf_info_link)
|
||||||
|
sections << section
|
||||||
|
return section
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) create_progbits(name string, flags u64, data []u8) Section {
|
fn (mut g Gen) create_progbits(name string, flags u64, data []u8) Section {
|
||||||
mut section := g.create_section(name, native.elf_sht_progbits, 0, 0, 1, data.len,
|
mut section := g.create_section(name, native.elf_sht_progbits, 0, 0, 1, data.len,
|
||||||
ProgBitsSection{data})
|
ProgBitsSection{data})
|
||||||
@ -514,7 +528,7 @@ fn (mut g Gen) find_section_header(name string, sections []Section) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) gen_section_header(mut sh SectionHeader) {
|
fn (mut g Gen) gen_section_header(mut sh SectionHeader) {
|
||||||
sh_offset := g.pos()
|
sh.pos = g.pos()
|
||||||
|
|
||||||
g.write32(sh.name) // sh_name
|
g.write32(sh.name) // sh_name
|
||||||
g.println('; sh_name')
|
g.println('; sh_name')
|
||||||
@ -525,8 +539,8 @@ fn (mut g Gen) gen_section_header(mut sh SectionHeader) {
|
|||||||
g.write64(sh.addr) // sh_addr
|
g.write64(sh.addr) // sh_addr
|
||||||
g.println('; sh_name')
|
g.println('; sh_name')
|
||||||
if sh.offset == 0 {
|
if sh.offset == 0 {
|
||||||
g.write64(sh_offset)
|
g.write64(sh.pos)
|
||||||
sh.offset = sh_offset
|
sh.offset = sh.pos
|
||||||
} else {
|
} else {
|
||||||
g.write64(sh.offset)
|
g.write64(sh.offset)
|
||||||
} // sh_offset
|
} // sh_offset
|
||||||
@ -566,7 +580,7 @@ fn (mut g Gen) gen_symtab_data(section Section, data []SymbolTableSection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size := native.elf_symtab_size * data.len
|
size := native.elf_symtab_size * data.len
|
||||||
g.write64_at(section.header.offset + 32, i64(size))
|
g.write64_at(section.header.pos + 32, i64(size))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) gen_section_data(sections []Section) {
|
fn (mut g Gen) gen_section_data(sections []Section) {
|
||||||
@ -574,7 +588,7 @@ fn (mut g Gen) gen_section_data(sections []Section) {
|
|||||||
data := section.data
|
data := section.data
|
||||||
|
|
||||||
// write the actual offset of the section data
|
// write the actual offset of the section data
|
||||||
g.write64_at(section.header.offset + 24, i64(g.pos()))
|
g.write64_at(section.header.pos + 24, i64(g.pos()))
|
||||||
|
|
||||||
match data {
|
match data {
|
||||||
StringTableSection {
|
StringTableSection {
|
||||||
@ -589,7 +603,7 @@ fn (mut g Gen) gen_section_data(sections []Section) {
|
|||||||
g.write8(0) // null-postfixed
|
g.write8(0) // null-postfixed
|
||||||
|
|
||||||
size := g.pos() - start
|
size := g.pos() - start
|
||||||
g.write64_at(section.header.offset + 32, i64(size))
|
g.write64_at(section.header.pos + 32, i64(size))
|
||||||
}
|
}
|
||||||
[]SymbolTableSection {
|
[]SymbolTableSection {
|
||||||
g.gen_symtab_data(section, data)
|
g.gen_symtab_data(section, data)
|
||||||
@ -597,14 +611,21 @@ fn (mut g Gen) gen_section_data(sections []Section) {
|
|||||||
ProgBitsSection {
|
ProgBitsSection {
|
||||||
// progbits have to be handled by the user.
|
// progbits have to be handled by the user.
|
||||||
}
|
}
|
||||||
RelASection {
|
[]RelASection {
|
||||||
g.write64(data.offset)
|
if data.len == 0 {
|
||||||
g.write64(data.info)
|
continue
|
||||||
g.write64(data.addend)
|
}
|
||||||
g.println('; SHT_RELA ($data.offset, $data.info, $data.addend)')
|
|
||||||
|
|
||||||
size := native.elf_rela_size
|
for rela in data {
|
||||||
g.write64_at(section.header.offset + 32, i64(size))
|
g.write64(rela.offset)
|
||||||
|
g.fn_addr[rela.name] = rela.offset
|
||||||
|
g.write64(rela.info)
|
||||||
|
g.write64(rela.addend)
|
||||||
|
g.println('; SHT_RELA `$rela.name` ($rela.offset, $rela.info, $rela.addend)')
|
||||||
|
}
|
||||||
|
|
||||||
|
size := native.elf_rela_size * data.len
|
||||||
|
g.write64_at(section.header.pos + 32, i64(size))
|
||||||
}
|
}
|
||||||
HashSection {
|
HashSection {
|
||||||
// TODO
|
// TODO
|
||||||
@ -618,7 +639,7 @@ fn (mut g Gen) gen_section_data(sections []Section) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size := native.elf_dynamic_size * data.len
|
size := native.elf_dynamic_size * data.len
|
||||||
g.write64_at(section.header.offset + 32, i64(size))
|
g.write64_at(section.header.pos + 32, i64(size))
|
||||||
}
|
}
|
||||||
NoteSection {
|
NoteSection {
|
||||||
start := g.pos()
|
start := g.pos()
|
||||||
@ -636,7 +657,7 @@ fn (mut g Gen) gen_section_data(sections []Section) {
|
|||||||
g.write8(0)
|
g.write8(0)
|
||||||
|
|
||||||
size := g.pos() - start
|
size := g.pos() - start
|
||||||
g.write64_at(section.header.offset + 32, i64(size))
|
g.write64_at(section.header.pos + 32, i64(size))
|
||||||
}
|
}
|
||||||
NoBitsSection {
|
NoBitsSection {
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
@ -647,13 +668,13 @@ fn (mut g Gen) gen_section_data(sections []Section) {
|
|||||||
g.println('; SHT_REL ($data.offset, $data.info)')
|
g.println('; SHT_REL ($data.offset, $data.info)')
|
||||||
|
|
||||||
size := native.elf_rel_size
|
size := native.elf_rel_size
|
||||||
g.write64_at(section.header.offset + 32, i64(size))
|
g.write64_at(section.header.pos + 32, i64(size))
|
||||||
}
|
}
|
||||||
ShLibSection {
|
ShLibSection {
|
||||||
g.write(data.data)
|
g.write(data.data)
|
||||||
|
|
||||||
size := data.data.len
|
size := data.data.len
|
||||||
g.write64_at(section.header.offset + 32, i64(size))
|
g.write64_at(section.header.pos + 32, i64(size))
|
||||||
}
|
}
|
||||||
DynSymSection {
|
DynSymSection {
|
||||||
g.gen_symtab_data(section, data.symbols)
|
g.gen_symtab_data(section, data.symbols)
|
||||||
@ -662,6 +683,15 @@ fn (mut g Gen) gen_section_data(sections []Section) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut g Gen) symtab_get_index(symbols []SymbolTableSection, name string) int {
|
||||||
|
for i, sym in symbols {
|
||||||
|
if sym.str_name == name {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (mut g Gen) generate_linkable_elf_header() {
|
pub fn (mut g Gen) generate_linkable_elf_header() {
|
||||||
elf_type := native.elf_type_rel // PIE (use _exec for non-relocatable executables)
|
elf_type := native.elf_type_rel // PIE (use _exec for non-relocatable executables)
|
||||||
|
|
||||||
@ -676,16 +706,20 @@ pub fn (mut g Gen) generate_linkable_elf_header() {
|
|||||||
g.create_progbits('.bss', native.elf_shf_write | native.elf_shf_alloc, []),
|
g.create_progbits('.bss', native.elf_shf_write | native.elf_shf_alloc, []),
|
||||||
]
|
]
|
||||||
|
|
||||||
mut symbols := [
|
g.symbol_table = [
|
||||||
SymbolTableSection{}, // first is null
|
SymbolTableSection{}, // first is null
|
||||||
g.create_symbol_table_section('test.v', native.elf_stt_file, native.elf_stb_local,
|
g.create_symbol_table_section('main', native.elf_stt_notype, native.elf_stb_global,
|
||||||
native.elf_stv_default, 0, 0), // source file TODO: replace test.v with actual source file name
|
native.elf_stv_default, 0, 0, i16(g.find_section_header('.text', sections))), // main label points to entry point address
|
||||||
g.create_symbol_table_section('.text', native.elf_stt_section, native.elf_stb_local,
|
g.create_symbol_table_section('_GLOBAL_OFFSET_TABLE_', native.elf_stt_notype,
|
||||||
native.elf_stv_default, 0, 0), // .text section
|
native.elf_stb_global, native.elf_stv_default, 0, 0, 0),
|
||||||
g.create_symbol_table_section('main', native.elf_stt_func, native.elf_stb_global,
|
|
||||||
native.elf_stv_default, 0, 0), // main label points to entry point address
|
|
||||||
]
|
]
|
||||||
g.create_symtab(mut sections, mut symbols) // create the .symtab section
|
|
||||||
|
for symbol in g.extern_symbols {
|
||||||
|
g.symbol_table << g.create_symbol_table_section(symbol[2..], native.elf_stt_notype,
|
||||||
|
native.elf_stb_global, native.elf_stv_default, 0, 0, 0)
|
||||||
|
}
|
||||||
|
g.create_symtab(mut sections, mut g.symbol_table) // create the .symtab section
|
||||||
|
g.create_relocation('.rela.text', mut sections, [])
|
||||||
g.create_shstrtab(mut sections) // create the .shstrtab section (this must be the last section!)
|
g.create_shstrtab(mut sections) // create the .shstrtab section (this must be the last section!)
|
||||||
|
|
||||||
mut elf_header := g.default_elf_header()
|
mut elf_header := g.default_elf_header()
|
||||||
@ -709,6 +743,8 @@ pub fn (mut g Gen) generate_linkable_elf_header() {
|
|||||||
// write sections
|
// write sections
|
||||||
g.gen_section_data(sections)
|
g.gen_section_data(sections)
|
||||||
|
|
||||||
|
g.elf_rela_section = sections[g.find_section_header('.rela.text', sections)]
|
||||||
|
|
||||||
// user code starts here
|
// user code starts here
|
||||||
if g.pref.is_verbose {
|
if g.pref.is_verbose {
|
||||||
eprintln('code_start_pos = $g.buf.len.hex()')
|
eprintln('code_start_pos = $g.buf.len.hex()')
|
||||||
@ -717,7 +753,7 @@ pub fn (mut g Gen) generate_linkable_elf_header() {
|
|||||||
g.code_start_pos = g.pos()
|
g.code_start_pos = g.pos()
|
||||||
g.debug_pos = int(g.pos())
|
g.debug_pos = int(g.pos())
|
||||||
// if g.start_symbol_addr > 0 {
|
// if g.start_symbol_addr > 0 {
|
||||||
// g.write64_at(g.start_symbol_addr + native.elf_symtab_size - 16, g.code_start_pos + native.segment_start)
|
// g.write64_at(g.start_symbol_addr + native.elf_symtab_size - 16, g.code_start_pos)
|
||||||
//}
|
//}
|
||||||
|
|
||||||
text_section := sections[g.find_section_header('.text', sections)]
|
text_section := sections[g.find_section_header('.text', sections)]
|
||||||
@ -733,7 +769,6 @@ pub fn (mut g Gen) generate_linkable_elf_header() {
|
|||||||
g.ret()
|
g.ret()
|
||||||
g.println('; return 0')
|
g.println('; return 0')
|
||||||
|
|
||||||
g.write64_at(g.start_symbol_addr + native.elf_symtab_size - 8, g.pos() - g.code_start_pos) // write 'main' function size
|
|
||||||
g.debug_pos = g.buf.len
|
g.debug_pos = g.buf.len
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -787,7 +822,7 @@ pub fn (mut g Gen) generate_simple_elf_header() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) elf_string_table() {
|
pub fn (mut g Gen) elf_string_table() {
|
||||||
for _, s in g.strs {
|
for _, s in g.strs {
|
||||||
match s.typ {
|
match s.typ {
|
||||||
.abs64 {
|
.abs64 {
|
||||||
@ -805,9 +840,29 @@ fn (mut g Gen) elf_string_table() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut g Gen) gen_rela_section() {
|
||||||
|
mut relocations := []RelASection{}
|
||||||
|
for call_pos, symbol in g.extern_fn_calls {
|
||||||
|
relocations << g.create_rela_section(symbol, call_pos - g.code_start_pos + 2,
|
||||||
|
g.symtab_get_index(g.symbol_table, symbol[2..]), native.elf_r_amd64_gotpcrelx,
|
||||||
|
-4)
|
||||||
|
}
|
||||||
|
g.elf_rela_section.data = relocations
|
||||||
|
g.gen_section_data([g.elf_rela_section])
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (mut g Gen) generate_elf_footer() {
|
pub fn (mut g Gen) generate_elf_footer() {
|
||||||
g.elf_string_table()
|
g.elf_string_table()
|
||||||
// file_size holds the address at the end of the code and const strings table
|
|
||||||
|
// write size of text section into section header
|
||||||
|
if g.elf_text_header_addr != -1 {
|
||||||
|
g.write64_at(g.elf_text_header_addr + 32, g.pos() - g.code_start_pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.extern_symbols.len != 0 {
|
||||||
|
g.gen_rela_section()
|
||||||
|
}
|
||||||
|
|
||||||
file_size := g.buf.len
|
file_size := g.buf.len
|
||||||
g.write64_at(g.file_size_pos, file_size) // set file size 64 bit value
|
g.write64_at(g.file_size_pos, file_size) // set file size 64 bit value
|
||||||
g.write64_at(g.file_size_pos + 8, file_size)
|
g.write64_at(g.file_size_pos + 8, file_size)
|
||||||
@ -824,11 +879,6 @@ pub fn (mut g Gen) generate_elf_footer() {
|
|||||||
g.write32_at(g.code_start_pos + 1, int(g.main_fn_addr - g.code_start_pos) - 5)
|
g.write32_at(g.code_start_pos + 1, int(g.main_fn_addr - g.code_start_pos) - 5)
|
||||||
}
|
}
|
||||||
|
|
||||||
// write size of text section into section header
|
|
||||||
if g.elf_text_header_addr != -1 {
|
|
||||||
g.write64_at(g.elf_text_header_addr + 32, g.pos() - g.code_start_pos)
|
|
||||||
}
|
|
||||||
|
|
||||||
g.create_executable()
|
g.create_executable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,10 +36,14 @@ mut:
|
|||||||
offset i64
|
offset i64
|
||||||
file_size_pos i64
|
file_size_pos i64
|
||||||
elf_text_header_addr i64 = -1
|
elf_text_header_addr i64 = -1
|
||||||
|
elf_rela_section Section
|
||||||
main_fn_addr i64
|
main_fn_addr i64
|
||||||
main_fn_size i64
|
main_fn_size i64
|
||||||
start_symbol_addr i64
|
start_symbol_addr i64
|
||||||
code_start_pos i64 // location of the start of the assembly instructions
|
code_start_pos i64 // location of the start of the assembly instructions
|
||||||
|
symbol_table []SymbolTableSection
|
||||||
|
extern_symbols []string
|
||||||
|
extern_fn_calls map[i64]string
|
||||||
fn_addr map[string]i64
|
fn_addr map[string]i64
|
||||||
var_offset map[string]int // local var stack offset
|
var_offset map[string]int // local var stack offset
|
||||||
var_alloc_size map[string]int // local var allocation size
|
var_alloc_size map[string]int // local var allocation size
|
||||||
@ -259,27 +263,25 @@ pub fn (mut g Gen) typ(a int) &ast.TypeSymbol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut g Gen) ast_has_external_functions() bool {
|
pub fn (mut g Gen) ast_has_external_functions() bool {
|
||||||
mut has_external_fn := false
|
|
||||||
|
|
||||||
for file in g.files {
|
for file in g.files {
|
||||||
walker.inspect(file, unsafe { &mut has_external_fn }, fn (node &ast.Node, data voidptr) bool {
|
walker.inspect(file, unsafe { &mut g }, fn (node &ast.Node, data voidptr) bool {
|
||||||
if node is ast.Expr && (node as ast.Expr) is ast.CallExpr
|
if node is ast.Expr && (node as ast.Expr) is ast.CallExpr
|
||||||
&& ((node as ast.Expr) as ast.CallExpr).language != .v {
|
&& ((node as ast.Expr) as ast.CallExpr).language != .v {
|
||||||
|
call := node as ast.CallExpr
|
||||||
unsafe {
|
unsafe {
|
||||||
*&bool(data) = true // an external function was found
|
mut g := &Gen(data)
|
||||||
|
if call.name !in g.extern_symbols {
|
||||||
|
g.extern_symbols << call.name
|
||||||
}
|
}
|
||||||
return false
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
if has_external_fn {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return has_external_fn
|
return g.extern_symbols.len != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut g Gen) generate_header() {
|
pub fn (mut g Gen) generate_header() {
|
||||||
@ -878,19 +880,15 @@ g.expr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) extern_fn_decl(node ast.FnDecl) {
|
|
||||||
// declarations like: fn C.malloc()
|
|
||||||
// TODO: implement extern function calls here
|
|
||||||
// Must store an address where the function label is located in the RelA elf section
|
|
||||||
panic('C. functions are not implemented yet')
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (mut g Gen) fn_decl(node ast.FnDecl) {
|
fn (mut g Gen) fn_decl(node ast.FnDecl) {
|
||||||
name := if node.is_method {
|
name := if node.is_method {
|
||||||
'${g.table.get_type_name(node.receiver.typ)}.$node.name'
|
'${g.table.get_type_name(node.receiver.typ)}.$node.name'
|
||||||
} else {
|
} else {
|
||||||
node.name
|
node.name
|
||||||
}
|
}
|
||||||
|
if node.no_body {
|
||||||
|
return
|
||||||
|
}
|
||||||
if g.pref.is_verbose {
|
if g.pref.is_verbose {
|
||||||
println(term.green('\n$name:'))
|
println(term.green('\n$name:'))
|
||||||
}
|
}
|
||||||
@ -900,10 +898,6 @@ fn (mut g Gen) fn_decl(node ast.FnDecl) {
|
|||||||
if node.is_builtin {
|
if node.is_builtin {
|
||||||
g.warning('fn_decl: $name is builtin', node.pos)
|
g.warning('fn_decl: $name is builtin', node.pos)
|
||||||
}
|
}
|
||||||
if node.no_body {
|
|
||||||
g.extern_fn_decl(node)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
g.stack_var_pos = 0
|
g.stack_var_pos = 0
|
||||||
g.register_function_address(name)
|
g.register_function_address(name)
|
||||||
|
38
vlib/v/gen/native/tests/libc.vv
Normal file
38
vlib/v/gen/native/tests/libc.vv
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// 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 main() {
|
||||||
|
charutil()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn charutil() {
|
||||||
|
$if linux {
|
||||||
|
// ascii for `V`
|
||||||
|
v_is_alpha := C.isalpha(86)
|
||||||
|
if v_is_alpha != 0 {
|
||||||
|
println('ok 1')
|
||||||
|
} else {
|
||||||
|
assert false
|
||||||
|
}
|
||||||
|
|
||||||
|
null_is_alpha := C.isalpha(0)
|
||||||
|
if null_is_alpha == 0 {
|
||||||
|
println('ok 2')
|
||||||
|
} else {
|
||||||
|
assert false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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')
|
||||||
|
}
|
||||||
|
}
|
3
vlib/v/gen/native/tests/libc.vv.out
Normal file
3
vlib/v/gen/native/tests/libc.vv.out
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
ok 1
|
||||||
|
ok 2
|
||||||
|
ok 3
|
Loading…
x
Reference in New Issue
Block a user