mirror of
https://github.com/vlang/v.git
synced 2025-09-08 23:07:19 -04:00
native: support C constants (#24660)
This commit is contained in:
parent
c61dda3425
commit
f5bf1b591e
@ -311,6 +311,9 @@ fn (mut c Amd64) cmp_var_reg(var Var, reg Register, config VarConfig) {
|
|||||||
// TODO
|
// TODO
|
||||||
// g.cmp()
|
// g.cmp()
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.cmp_var_reg(var_object as ExternVar, reg, config)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LocalVar {
|
LocalVar {
|
||||||
@ -330,6 +333,9 @@ fn (mut c Amd64) cmp_var_reg(var Var, reg Register, config VarConfig) {
|
|||||||
GlobalVar {
|
GlobalVar {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.g.n_error('${@LOCATION} unsupported var type ${var}')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,6 +354,9 @@ fn (mut c Amd64) cmp_var(var Var, val i32, config VarConfig) {
|
|||||||
// TODO
|
// TODO
|
||||||
// g.cmp()
|
// g.cmp()
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.cmp_var(var_object as ExternVar, val, config)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LocalVar {
|
LocalVar {
|
||||||
@ -367,6 +376,9 @@ fn (mut c Amd64) cmp_var(var Var, val i32, config VarConfig) {
|
|||||||
GlobalVar {
|
GlobalVar {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.g.n_error('${@LOCATION} unsupported var type ${var}')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,6 +398,9 @@ fn (mut c Amd64) dec_var(var Var, config VarConfig) {
|
|||||||
// TODO
|
// TODO
|
||||||
// g.dec()
|
// g.dec()
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.dec_var(var_object as ExternVar, config)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LocalVar {
|
LocalVar {
|
||||||
@ -405,6 +420,9 @@ fn (mut c Amd64) dec_var(var Var, config VarConfig) {
|
|||||||
GlobalVar {
|
GlobalVar {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.g.n_error('${@LOCATION} unsupported var type ${var}')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,6 +443,9 @@ fn (mut c Amd64) inc_var(var Var, config VarConfig) {
|
|||||||
// TODO
|
// TODO
|
||||||
// g.inc()
|
// g.inc()
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.inc_var(var_object as ExternVar, config)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LocalVar {
|
LocalVar {
|
||||||
@ -468,6 +489,9 @@ fn (mut c Amd64) inc_var(var Var, config VarConfig) {
|
|||||||
c.g.n_error('${@LOCATION} Global variables incrementation is not supported yet')
|
c.g.n_error('${@LOCATION} Global variables incrementation is not supported yet')
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.g.n_error('${@LOCATION} unsupported var type ${var}')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -662,6 +686,9 @@ fn (mut c Amd64) mov_reg_to_var(var Var, r Register, config VarConfig) {
|
|||||||
// TODO
|
// TODO
|
||||||
c.g.n_error('${@LOCATION} unsupported Ident Register')
|
c.g.n_error('${@LOCATION} unsupported Ident Register')
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.mov_reg_to_var(var_object as ExternVar, reg, config)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LocalVar {
|
LocalVar {
|
||||||
@ -743,6 +770,9 @@ fn (mut c Amd64) mov_reg_to_var(var Var, r Register, config VarConfig) {
|
|||||||
// TODO
|
// TODO
|
||||||
c.g.n_error('${@LOCATION} Unsupported GlobalVar')
|
c.g.n_error('${@LOCATION} Unsupported GlobalVar')
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.g.n_error('${@LOCATION} unsupported var type ${var}')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -760,6 +790,9 @@ fn (mut c Amd64) mov_int_to_var(var Var, integer i32, config VarConfig) {
|
|||||||
Register {
|
Register {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.mov_int_to_var(var_object as ExternVar, integer, config)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LocalVar {
|
LocalVar {
|
||||||
@ -822,6 +855,9 @@ fn (mut c Amd64) mov_int_to_var(var Var, integer i32, config VarConfig) {
|
|||||||
GlobalVar {
|
GlobalVar {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.g.n_error('${@LOCATION} unsupported var type ${var}')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -868,6 +904,9 @@ fn (mut c Amd64) mov_var_to_reg(reg Register, var Var, config VarConfig) {
|
|||||||
Register {
|
Register {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.mov_var_to_reg(reg, var_object as ExternVar, config)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LocalVar {
|
LocalVar {
|
||||||
@ -933,6 +972,9 @@ fn (mut c Amd64) mov_var_to_reg(reg Register, var Var, config VarConfig) {
|
|||||||
GlobalVar {
|
GlobalVar {
|
||||||
c.g.n_error('${@LOCATION} Unsupported GlobalVar')
|
c.g.n_error('${@LOCATION} Unsupported GlobalVar')
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.g.n_error('${@LOCATION} unsupported var type ${var}')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2077,19 +2119,34 @@ fn (mut c Amd64) assign_var(var IdentVar, raw_type ast.Type) {
|
|||||||
size := c.g.get_type_size(typ)
|
size := c.g.get_type_size(typ)
|
||||||
if typ.is_pure_float() {
|
if typ.is_pure_float() {
|
||||||
match var {
|
match var {
|
||||||
LocalVar { c.mov_ssereg_to_var(var as LocalVar, .xmm0) }
|
LocalVar {
|
||||||
GlobalVar { c.mov_ssereg_to_var(var as GlobalVar, .xmm0) }
|
c.mov_ssereg_to_var(var as LocalVar, .xmm0)
|
||||||
|
}
|
||||||
|
GlobalVar {
|
||||||
|
c.mov_ssereg_to_var(var as GlobalVar, .xmm0)
|
||||||
|
}
|
||||||
// Amd64Register { c.g.mov_ssereg(var as Amd64Register, .xmm0) }
|
// Amd64Register { c.g.mov_ssereg(var as Amd64Register, .xmm0) }
|
||||||
else {}
|
else {
|
||||||
|
c.g.n_error('${@LOCATION} unsupported var type ${var}')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if info is ast.Struct && !typ.is_any_kind_of_pointer()
|
} else if info is ast.Struct && !typ.is_any_kind_of_pointer()
|
||||||
&& !raw_type.is_any_kind_of_pointer() {
|
&& !raw_type.is_any_kind_of_pointer() {
|
||||||
c.assign_struct_var(var, typ, size)
|
c.assign_struct_var(var, typ, size)
|
||||||
} else if int(size) in [1, 2, 4, 8] {
|
} else if int(size) in [1, 2, 4, 8] {
|
||||||
match var {
|
match var {
|
||||||
LocalVar { c.mov_reg_to_var(var as LocalVar, Amd64Register.rax) }
|
LocalVar {
|
||||||
GlobalVar { c.mov_reg_to_var(var as GlobalVar, Amd64Register.rax) }
|
c.mov_reg_to_var(var as LocalVar, Amd64Register.rax)
|
||||||
Register { c.mov_reg(var as Amd64Register, Amd64Register.rax) }
|
}
|
||||||
|
GlobalVar {
|
||||||
|
c.mov_reg_to_var(var as GlobalVar, Amd64Register.rax)
|
||||||
|
}
|
||||||
|
Register {
|
||||||
|
c.mov_reg(var as Amd64Register, Amd64Register.rax)
|
||||||
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.mov_reg_to_var(var as ExternVar, Amd64Register.rax)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c.g.n_error('${@LOCATION} error assigning type ${typ} with size ${size}: ${info}')
|
c.g.n_error('${@LOCATION} error assigning type ${typ} with size ${size}: ${info}')
|
||||||
@ -2121,6 +2178,12 @@ fn (mut c Amd64) assign_ident_int_lit(node ast.AssignStmt, i i32, int_lit ast.In
|
|||||||
c.div_reg(.rax, .rdx)
|
c.div_reg(.rax, .rdx)
|
||||||
c.mov_reg_to_var(left, Amd64Register.rax)
|
c.mov_reg_to_var(left, Amd64Register.rax)
|
||||||
}
|
}
|
||||||
|
.mod_assign {
|
||||||
|
c.mov_var_to_reg(Amd64Register.rax, left)
|
||||||
|
c.mov64(Amd64Register.rdx, i64(int_lit.val.int()))
|
||||||
|
c.mod_reg(.rax, .rdx)
|
||||||
|
c.mov_reg_to_var(left, Amd64Register.rax)
|
||||||
|
}
|
||||||
.decl_assign {
|
.decl_assign {
|
||||||
c.allocate_var(left.name, 8, i64(int_lit.val.int()))
|
c.allocate_var(left.name, 8, i64(int_lit.val.int()))
|
||||||
}
|
}
|
||||||
@ -2241,11 +2304,19 @@ fn (mut c Amd64) assign_ident_right_expr(node ast.AssignStmt, i i32, right ast.E
|
|||||||
val := enum_info.fields[right.val] or {
|
val := enum_info.fields[right.val] or {
|
||||||
c.g.n_error('${@LOCATION} enum field not found ${right.val}')
|
c.g.n_error('${@LOCATION} enum field not found ${right.val}')
|
||||||
}
|
}
|
||||||
if node.op == .decl_assign {
|
match val {
|
||||||
c.allocate_var(ident.name, enum_info.size, val)
|
Number {
|
||||||
} else {
|
if node.op == .decl_assign {
|
||||||
c.mov64(Amd64Register.rax, val)
|
c.allocate_var(ident.name, enum_info.size, val)
|
||||||
c.mov_reg_to_var(ident, Amd64Register.rax)
|
} else {
|
||||||
|
c.mov64(Amd64Register.rax, val)
|
||||||
|
c.mov_reg_to_var(ident, Amd64Register.rax)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast.Expr {
|
||||||
|
c.g.expr(val)
|
||||||
|
c.mov_reg_to_var(ident, Amd64Register.rax)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.FloatLiteral {
|
ast.FloatLiteral {
|
||||||
@ -2777,14 +2848,35 @@ fn (mut c Amd64) assign_stmt(node ast.AssignStmt) {
|
|||||||
c.pop(.rdx) // effective address of left expr
|
c.pop(.rdx) // effective address of left expr
|
||||||
c.gen_type_promotion(node.right_types[0], var_type)
|
c.gen_type_promotion(node.right_types[0], var_type)
|
||||||
|
|
||||||
|
size := match c.g.get_type_size(var_type) {
|
||||||
|
1 { Size._8 }
|
||||||
|
2 { Size._16 }
|
||||||
|
4 { Size._32 }
|
||||||
|
else { Size._64 }
|
||||||
|
}
|
||||||
match node.op {
|
match node.op {
|
||||||
.decl_assign, .assign {
|
.decl_assign, .assign {
|
||||||
c.mov_store(.rdx, .rax, match c.g.get_type_size(var_type) {
|
c.mov_store(.rdx, .rax, size)
|
||||||
1 { ._8 }
|
}
|
||||||
2 { ._16 }
|
.plus_assign {
|
||||||
4 { ._32 }
|
c.mov_deref(Amd64Register.rcx, Amd64Register.rdx, var_type)
|
||||||
else { ._64 }
|
c.add_reg(.rax, .rcx)
|
||||||
})
|
c.mov_store(.rdx, .rax, size)
|
||||||
|
}
|
||||||
|
.minus_assign {
|
||||||
|
c.mov_deref(Amd64Register.rcx, Amd64Register.rdx, var_type)
|
||||||
|
c.sub_reg(.rax, .rcx)
|
||||||
|
c.mov_store(.rdx, .rax, size)
|
||||||
|
}
|
||||||
|
.and_assign {
|
||||||
|
c.mov_deref(Amd64Register.rcx, Amd64Register.rdx, var_type)
|
||||||
|
c.bitand_reg(.rax, .rcx)
|
||||||
|
c.mov_store(.rdx, .rax, size)
|
||||||
|
}
|
||||||
|
.mod_assign {
|
||||||
|
c.mov_deref(Amd64Register.rcx, Amd64Register.rdx, var_type)
|
||||||
|
c.mod_reg(.rax, .rcx)
|
||||||
|
c.mov_store(.rdx, .rax, size)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
c.g.n_error('${@LOCATION} Unsupported assign instruction (${node.op})')
|
c.g.n_error('${@LOCATION} Unsupported assign instruction (${node.op})')
|
||||||
@ -3676,6 +3768,9 @@ fn (mut c Amd64) init_struct(var Var, init ast.StructInit) {
|
|||||||
// TODO
|
// TODO
|
||||||
// c.g.cmp()
|
// c.g.cmp()
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.init_struct(var_object as ExternVar, init)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LocalVar {
|
LocalVar {
|
||||||
@ -3718,6 +3813,9 @@ fn (mut c Amd64) init_struct(var Var, init ast.StructInit) {
|
|||||||
GlobalVar {
|
GlobalVar {
|
||||||
c.g.n_error('${@LOCATION} GlobalVar not implemented for ast.StructInit')
|
c.g.n_error('${@LOCATION} GlobalVar not implemented for ast.StructInit')
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.g.n_error('${@LOCATION} unsupported var type ${var}')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3766,6 +3864,9 @@ fn (mut c Amd64) init_array(var Var, node ast.ArrayInit) {
|
|||||||
// TODO
|
// TODO
|
||||||
// c.g.cmp()
|
// c.g.cmp()
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.init_array(var_object as ExternVar, node)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LocalVar {
|
LocalVar {
|
||||||
@ -3779,6 +3880,9 @@ fn (mut c Amd64) init_array(var Var, node ast.ArrayInit) {
|
|||||||
GlobalVar {
|
GlobalVar {
|
||||||
c.g.n_error('${@LOCATION} GlobalVar not implemented for ast.ArrayInit')
|
c.g.n_error('${@LOCATION} GlobalVar not implemented for ast.ArrayInit')
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.g.n_error('${@LOCATION} unsupported var type ${var}')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4075,6 +4179,9 @@ fn (mut c Amd64) mov_ssereg_to_var(var Var, reg Amd64SSERegister, config VarConf
|
|||||||
c.mov_ssereg_to_var(var_object as GlobalVar, reg, config)
|
c.mov_ssereg_to_var(var_object as GlobalVar, reg, config)
|
||||||
}
|
}
|
||||||
Register {}
|
Register {}
|
||||||
|
ExternVar {
|
||||||
|
c.mov_ssereg_to_var(var_object as ExternVar, reg, config)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LocalVar {
|
LocalVar {
|
||||||
@ -4100,6 +4207,9 @@ fn (mut c Amd64) mov_ssereg_to_var(var Var, reg Amd64SSERegister, config VarConf
|
|||||||
GlobalVar {
|
GlobalVar {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.g.n_error('${@LOCATION} unsupported var type ${var}')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4119,6 +4229,9 @@ fn (mut c Amd64) mov_var_to_ssereg(reg Amd64SSERegister, var Var, config VarConf
|
|||||||
c.mov_var_to_ssereg(reg, var_object as GlobalVar, config)
|
c.mov_var_to_ssereg(reg, var_object as GlobalVar, config)
|
||||||
}
|
}
|
||||||
Register {}
|
Register {}
|
||||||
|
ExternVar {
|
||||||
|
c.mov_var_to_ssereg(reg, var_object as ExternVar, config)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LocalVar {
|
LocalVar {
|
||||||
@ -4144,6 +4257,9 @@ fn (mut c Amd64) mov_var_to_ssereg(reg Amd64SSERegister, var Var, config VarConf
|
|||||||
GlobalVar {
|
GlobalVar {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
c.g.n_error('${@LOCATION} unsupported var type ${var}')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,36 @@ already compiling functions:
|
|||||||
|
|
||||||
// false: whitelist function
|
// false: whitelist function
|
||||||
// true: blacklist function
|
// true: blacklist function
|
||||||
const whitelist = {
|
const blacklist = {
|
||||||
|
'main.main': false
|
||||||
|
'c_error_number_str': false
|
||||||
|
'exit': false
|
||||||
|
'gc_is_enabled': false
|
||||||
|
'int_max': false
|
||||||
|
'int_min': false
|
||||||
|
'flush_stdout': false
|
||||||
|
'flush_stderr': false
|
||||||
|
'print_character': true
|
||||||
|
'u8.is_alnum': false
|
||||||
|
'u8.is_bin_digit': false
|
||||||
|
'u8.is_capital': false
|
||||||
|
'u8.is_digit': false
|
||||||
|
'u8.is_hex_digit': false
|
||||||
|
'u8.is_letter': false
|
||||||
|
'u8.is_oct_digit': false
|
||||||
|
'u8.is_space': false
|
||||||
|
'string.is_capital': false
|
||||||
|
'string.is_ascii': false
|
||||||
|
'string.is_identifier': false
|
||||||
|
'string.is_blank': false
|
||||||
|
'string.indent_width': false
|
||||||
|
'string.index_u8': false
|
||||||
|
'string.last_index': true
|
||||||
|
'string.last_index_u8': false
|
||||||
|
'string.contains_u8': false
|
||||||
|
}
|
||||||
|
|
||||||
|
const windows_blacklist = {
|
||||||
'main.main': false
|
'main.main': false
|
||||||
'c_error_number_str': false
|
'c_error_number_str': false
|
||||||
'exit': false
|
'exit': false
|
||||||
@ -55,5 +84,9 @@ const whitelist = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn (g &Gen) is_blacklisted(name string, is_builtin bool) bool {
|
fn (g &Gen) is_blacklisted(name string, is_builtin bool) bool {
|
||||||
return whitelist[name] or { is_builtin }
|
if g.pref.os == .windows {
|
||||||
|
return windows_blacklist[name] or { is_builtin }
|
||||||
|
} else {
|
||||||
|
return blacklist[name] or { is_builtin }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -614,7 +614,7 @@ fn (mut g Gen) gen_section_data(sections []Section) {
|
|||||||
|
|
||||||
for rela in data {
|
for rela in data {
|
||||||
g.write64(rela.offset)
|
g.write64(rela.offset)
|
||||||
g.fn_addr[rela.name] = rela.offset
|
g.fn_addr[rela.name] = rela.offset // that's wierd it's the call offset, not the fn
|
||||||
g.fn_names << rela.name
|
g.fn_names << rela.name
|
||||||
g.write64(rela.info)
|
g.write64(rela.info)
|
||||||
g.write64(rela.addend)
|
g.write64(rela.addend)
|
||||||
@ -686,7 +686,7 @@ pub fn (mut g Gen) symtab_get_index(symbols []SymbolTableSection, name string) i
|
|||||||
return i32(i)
|
return i32(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0
|
panic('sym not found')
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut g Gen) generate_linkable_elf_header() {
|
pub fn (mut g Gen) generate_linkable_elf_header() {
|
||||||
@ -847,6 +847,10 @@ pub fn (mut g Gen) gen_rela_section() {
|
|||||||
relocations << g.create_rela_section(symbol, call_pos - g.code_start_pos + 2,
|
relocations << g.create_rela_section(symbol, call_pos - g.code_start_pos + 2,
|
||||||
g.symtab_get_index(g.symbol_table, symbol[2..]), elf_r_amd64_gotpcrelx, -4)
|
g.symtab_get_index(g.symbol_table, symbol[2..]), elf_r_amd64_gotpcrelx, -4)
|
||||||
}
|
}
|
||||||
|
for var_pos, symbol in g.extern_vars {
|
||||||
|
relocations << g.create_rela_section(symbol, var_pos - g.code_start_pos + 2, g.symtab_get_index(g.symbol_table,
|
||||||
|
symbol[2..]), elf_r_amd64_64, 0)
|
||||||
|
}
|
||||||
g.elf_rela_section.data = relocations
|
g.elf_rela_section.data = relocations
|
||||||
g.gen_section_data([g.elf_rela_section])
|
g.gen_section_data([g.elf_rela_section])
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ module native
|
|||||||
|
|
||||||
import v.ast
|
import v.ast
|
||||||
import v.util
|
import v.util
|
||||||
|
import v.errors
|
||||||
|
|
||||||
fn (mut g Gen) expr(node ast.Expr) {
|
fn (mut g Gen) expr(node ast.Expr) {
|
||||||
match node {
|
match node {
|
||||||
@ -47,6 +48,9 @@ fn (mut g Gen) expr(node ast.Expr) {
|
|||||||
LocalVar {
|
LocalVar {
|
||||||
g.local_var_ident(node, var)
|
g.local_var_ident(node, var)
|
||||||
}
|
}
|
||||||
|
ExternVar {
|
||||||
|
g.extern_var_ident(var)
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
g.n_error('${@LOCATION} Unsupported variable kind')
|
g.n_error('${@LOCATION} Unsupported variable kind')
|
||||||
}
|
}
|
||||||
@ -115,7 +119,14 @@ fn (mut g Gen) expr(node ast.Expr) {
|
|||||||
val := g.enum_vals[type_name].fields[node.val] or {
|
val := g.enum_vals[type_name].fields[node.val] or {
|
||||||
g.n_error('${@LOCATION} enum field not found ${node.val}')
|
g.n_error('${@LOCATION} enum field not found ${node.val}')
|
||||||
}
|
}
|
||||||
g.code_gen.mov64(g.code_gen.main_reg(), val)
|
match val {
|
||||||
|
Number {
|
||||||
|
g.code_gen.mov64(g.code_gen.main_reg(), val)
|
||||||
|
}
|
||||||
|
ast.Expr {
|
||||||
|
g.expr(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast.UnsafeExpr {
|
ast.UnsafeExpr {
|
||||||
g.expr(node.expr)
|
g.expr(node.expr)
|
||||||
@ -148,7 +159,12 @@ fn (mut g Gen) expr(node ast.Expr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g.n_error('${@LOCATION} expr: unhandled node type: ${node.type_name()}')
|
util.show_compiler_message('error', errors.CompilerMessage{
|
||||||
|
message: 'detail'
|
||||||
|
file_path: g.current_file.path
|
||||||
|
pos: node.pos()
|
||||||
|
})
|
||||||
|
g.n_error('${@LOCATION} expr: unhandled node type: ${node.type_name()} ${node}')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,6 +190,17 @@ fn (mut g Gen) local_var_ident(ident ast.Ident, var LocalVar) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) extern_var_ident(var ExternVar) {
|
||||||
|
if g.pref.os == .linux {
|
||||||
|
main_reg := g.code_gen.main_reg()
|
||||||
|
g.extern_vars[g.pos()] = var.name
|
||||||
|
g.code_gen.mov64(main_reg, Number(i64(0)))
|
||||||
|
g.code_gen.mov_deref(main_reg, main_reg, ast.u64_type_idx)
|
||||||
|
} else {
|
||||||
|
g.n_error('${@LOCATION} unsupported os for ${var}')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) condition(expr ast.Expr, neg bool) i32 {
|
fn (mut g Gen) condition(expr ast.Expr, neg bool) i32 {
|
||||||
g.println('; condition cjmp if ${neg}:')
|
g.println('; condition cjmp if ${neg}:')
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
|
@ -35,6 +35,7 @@ mut:
|
|||||||
extern_symbols []string
|
extern_symbols []string
|
||||||
linker_include_paths []string
|
linker_include_paths []string
|
||||||
linker_libs []string
|
linker_libs []string
|
||||||
|
extern_vars map[i64]string
|
||||||
extern_fn_calls map[i64]string
|
extern_fn_calls map[i64]string
|
||||||
fn_addr map[string]i64
|
fn_addr map[string]i64
|
||||||
fn_names []string
|
fn_names []string
|
||||||
@ -211,9 +212,11 @@ type Number = u64 | i64
|
|||||||
struct Enum {
|
struct Enum {
|
||||||
size i32 // size of the type of the enum in bytes
|
size i32 // size of the type of the enum in bytes
|
||||||
mut:
|
mut:
|
||||||
fields map[string]Number
|
fields map[string]EnumVal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type EnumVal = Number | ast.Expr
|
||||||
|
|
||||||
struct MultiReturn {
|
struct MultiReturn {
|
||||||
mut:
|
mut:
|
||||||
offsets []i32
|
offsets []i32
|
||||||
@ -235,6 +238,11 @@ struct LocalVar {
|
|||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ExternVar {
|
||||||
|
typ ast.Type
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
struct GlobalVar {}
|
struct GlobalVar {}
|
||||||
|
|
||||||
@[params]
|
@[params]
|
||||||
@ -244,9 +252,9 @@ pub:
|
|||||||
typ ast.Type // type of the value you want to process e.g. struct fields.
|
typ ast.Type // type of the value you want to process e.g. struct fields.
|
||||||
}
|
}
|
||||||
|
|
||||||
type Var = GlobalVar | LocalVar | ast.Ident
|
type Var = GlobalVar | ExternVar | LocalVar | ast.Ident
|
||||||
|
|
||||||
type IdentVar = GlobalVar | LocalVar | Register
|
type IdentVar = GlobalVar | ExternVar | LocalVar | Register
|
||||||
|
|
||||||
enum JumpOp {
|
enum JumpOp {
|
||||||
je
|
je
|
||||||
@ -270,6 +278,9 @@ fn byt(n i32, s i32) u8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) get_var_from_ident(ident ast.Ident) IdentVar {
|
fn (mut g Gen) get_var_from_ident(ident ast.Ident) IdentVar {
|
||||||
|
if ident.name in g.extern_symbols {
|
||||||
|
return ExternVar{ident.info.typ, ident.name}
|
||||||
|
}
|
||||||
mut obj := ident.obj
|
mut obj := ident.obj
|
||||||
if obj !in [ast.Var, ast.ConstField, ast.GlobalField, ast.AsmRegister] {
|
if obj !in [ast.Var, ast.ConstField, ast.GlobalField, ast.AsmRegister] {
|
||||||
obj = ident.scope.find(ident.name) or {
|
obj = ident.scope.find(ident.name) or {
|
||||||
@ -302,6 +313,9 @@ fn (mut g Gen) get_type_from_var(var Var) ast.Type {
|
|||||||
GlobalVar {
|
GlobalVar {
|
||||||
g.n_error('${@LOCATION} cannot get type from GlobalVar yet')
|
g.n_error('${@LOCATION} cannot get type from GlobalVar yet')
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
g.n_error('${@LOCATION} unsupported var type ${var}')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,22 +562,33 @@ pub fn (mut g Gen) calculate_enum_fields() {
|
|||||||
size: i32(enum_size)
|
size: i32(enum_size)
|
||||||
}
|
}
|
||||||
mut value := Number(if decl.is_flag { i64(1) } else { i64(0) })
|
mut value := Number(if decl.is_flag { i64(1) } else { i64(0) })
|
||||||
|
mut has_expr := false
|
||||||
for field in decl.fields {
|
for field in decl.fields {
|
||||||
if field.has_expr {
|
if field.has_expr {
|
||||||
str_val := g.eval.expr(field.expr, ast.int_type_idx).string()
|
if field.expr.is_literal() { // does not depend on other declarations (C compile time csts)
|
||||||
if str_val.len >= 0 && str_val[0] == `-` {
|
str_val := g.eval.expr(field.expr, ast.int_type_idx).string()
|
||||||
value = str_val.i64()
|
if str_val.len >= 0 && str_val[0] == `-` {
|
||||||
|
value = str_val.i64()
|
||||||
|
} else {
|
||||||
|
value = str_val.u64()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
value = str_val.u64()
|
enum_vals.fields[field.name] = field.expr
|
||||||
|
has_expr = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if has_expr {
|
||||||
|
g.n_error('${@LOCATION} unsupported auto incr after C consts')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match value {
|
match value {
|
||||||
// Dereferences the sumtype (it would get assigned by address and messed up)
|
// Dereferences the sumtype (it would get assigned by address and messed up)
|
||||||
i64 {
|
i64 {
|
||||||
enum_vals.fields[field.name] = value as i64
|
enum_vals.fields[field.name] = Number(value as i64)
|
||||||
}
|
}
|
||||||
u64 {
|
u64 {
|
||||||
enum_vals.fields[field.name] = value as u64
|
enum_vals.fields[field.name] = Number(value as u64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if decl.is_flag {
|
if decl.is_flag {
|
||||||
|
@ -5,6 +5,7 @@ module native
|
|||||||
|
|
||||||
import v.ast
|
import v.ast
|
||||||
import v.util
|
import v.util
|
||||||
|
import v.errors
|
||||||
|
|
||||||
fn C.strtol(str &char, endptr &&char, base i32) i32
|
fn C.strtol(str &char, endptr &&char, base i32) i32
|
||||||
|
|
||||||
@ -76,9 +77,13 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match node.kind {
|
match node.kind {
|
||||||
'include', 'preinclude', 'postinclude', 'define', 'insert' {
|
'include' {}
|
||||||
g.v_error('#${node.kind} is not supported with the native backend',
|
'preinclude', 'postinclude', 'define', 'insert' {
|
||||||
node.pos)
|
util.show_compiler_message('notice', errors.CompilerMessage{
|
||||||
|
message: '#${node.kind} is not supported with the native backend'
|
||||||
|
file_path: node.source_file
|
||||||
|
pos: node.pos
|
||||||
|
})
|
||||||
}
|
}
|
||||||
'flag' {
|
'flag' {
|
||||||
// do nothing; flags are already handled when dispatching extern dependencies
|
// do nothing; flags are already handled when dispatching extern dependencies
|
||||||
|
@ -3,6 +3,26 @@ fn main() {
|
|||||||
test_fp()
|
test_fp()
|
||||||
test_unsafe()
|
test_unsafe()
|
||||||
test_alias(100, 9)
|
test_alias(100, 9)
|
||||||
|
test_plus_assign()
|
||||||
|
test_minus_assign()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_minus_assign() {
|
||||||
|
mut a := 3
|
||||||
|
a -= 3
|
||||||
|
assert a == 0
|
||||||
|
n := 2300
|
||||||
|
a -= n
|
||||||
|
assert a == -2300
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_plus_assign() {
|
||||||
|
mut a := 3
|
||||||
|
a += 3
|
||||||
|
assert a == 6
|
||||||
|
n := 2300
|
||||||
|
a += n
|
||||||
|
assert a == 2306
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_int() {
|
fn test_int() {
|
||||||
|
@ -127,10 +127,6 @@ println(f64_max(-32.32, 32.32))
|
|||||||
println(f64_min(32.32, -32.32))
|
println(f64_min(32.32, -32.32))
|
||||||
println(f64_min(-32.32, 32.32))
|
println(f64_min(-32.32, 32.32))
|
||||||
*/
|
*/
|
||||||
/* uncomment when C variables are working like C.stdout
|
|
||||||
flush_stderr()
|
|
||||||
flush_stdout()
|
|
||||||
*/
|
|
||||||
|
|
||||||
gc_is_enabled() // not yet enabled so only calling it
|
gc_is_enabled() // not yet enabled so only calling it
|
||||||
|
|
||||||
@ -139,7 +135,7 @@ println(int_max(-32, 32))
|
|||||||
println(int_min(32, -32))
|
println(int_min(32, -32))
|
||||||
println(int_min(-32, 32))
|
println(int_min(-32, 32))
|
||||||
|
|
||||||
// print_character(`a`) enable when C vars will work
|
//print_character(`a`) enable when C vars will work
|
||||||
|
|
||||||
// assert u8(`a`).ascii_str() == 'a' when ptr index will work
|
// assert u8(`a`).ascii_str() == 'a' when ptr index will work
|
||||||
// assert u8(`b`).ascii_str() != 'a'
|
// assert u8(`b`).ascii_str() != 'a'
|
||||||
|
@ -16,6 +16,13 @@ fn test_for_c_in_string() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_c_extern_vars() {
|
||||||
|
C.fprintf(C.stdout, 'abc'.str, 3)
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
test_for_c_in_string()
|
test_for_c_in_string()
|
||||||
|
test_c_extern_vars()
|
||||||
|
flush_stderr()
|
||||||
|
flush_stdout()
|
||||||
}
|
}
|
||||||
|
@ -4,3 +4,4 @@
|
|||||||
98
|
98
|
||||||
2
|
2
|
||||||
99
|
99
|
||||||
|
abc
|
||||||
|
Loading…
x
Reference in New Issue
Block a user