strconv,checker,cgen: fix -cstrict compilation of hello_world.v
parent
48546d0f45
commit
241a7b760d
|
@ -1,6 +1,6 @@
|
||||||
module ast
|
module ast
|
||||||
|
|
||||||
pub type ComptTimeConstValue = EmptyExpr | byte | f64 | i64 | rune | string
|
pub type ComptTimeConstValue = EmptyExpr | byte | f64 | i64 | rune | string | u64
|
||||||
|
|
||||||
pub fn empty_comptime_const_expr() ComptTimeConstValue {
|
pub fn empty_comptime_const_expr() ComptTimeConstValue {
|
||||||
return EmptyExpr{}
|
return EmptyExpr{}
|
||||||
|
@ -8,14 +8,21 @@ pub fn empty_comptime_const_expr() ComptTimeConstValue {
|
||||||
|
|
||||||
pub fn (val ComptTimeConstValue) i64() ?i64 {
|
pub fn (val ComptTimeConstValue) i64() ?i64 {
|
||||||
match val {
|
match val {
|
||||||
i64, byte {
|
byte {
|
||||||
|
return i64(val)
|
||||||
|
}
|
||||||
|
i64 {
|
||||||
return i64(val)
|
return i64(val)
|
||||||
}
|
}
|
||||||
f64 {
|
f64 {
|
||||||
if -9223372036854775808.0 <= val && val <= 9223372036854775807.0 {
|
if -9223372036854775808.0 <= val && val <= 9223372036854775807.0 {
|
||||||
return i64(val)
|
return i64(val)
|
||||||
}
|
}
|
||||||
return none
|
}
|
||||||
|
u64 {
|
||||||
|
if val <= 9223372036854775807 {
|
||||||
|
return i64(val)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
string {
|
string {
|
||||||
return val.i64()
|
return val.i64()
|
||||||
|
@ -23,26 +30,27 @@ pub fn (val ComptTimeConstValue) i64() ?i64 {
|
||||||
rune {
|
rune {
|
||||||
return int(val)
|
return int(val)
|
||||||
}
|
}
|
||||||
EmptyExpr {
|
EmptyExpr {}
|
||||||
return none
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (val ComptTimeConstValue) int() ?int {
|
pub fn (val ComptTimeConstValue) int() ?int {
|
||||||
match val {
|
match val {
|
||||||
|
u64 {
|
||||||
|
if val <= 2147483647 {
|
||||||
|
return int(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
f64 {
|
f64 {
|
||||||
if -2147483648.0 <= val && val <= 2147483647.0 {
|
if -2147483648.0 <= val && val <= 2147483647.0 {
|
||||||
return int(val)
|
return int(val)
|
||||||
}
|
}
|
||||||
return none
|
|
||||||
}
|
}
|
||||||
i64 {
|
i64 {
|
||||||
if -2147483648 <= val && val <= 2147483647 {
|
if -2147483648 <= val && val <= 2147483647 {
|
||||||
return int(val)
|
return int(val)
|
||||||
}
|
}
|
||||||
return none
|
|
||||||
}
|
}
|
||||||
byte {
|
byte {
|
||||||
return int(val)
|
return int(val)
|
||||||
|
@ -50,51 +58,82 @@ pub fn (val ComptTimeConstValue) int() ?int {
|
||||||
string {
|
string {
|
||||||
return val.int()
|
return val.int()
|
||||||
}
|
}
|
||||||
rune {
|
rune, EmptyExpr {}
|
||||||
return none
|
|
||||||
}
|
|
||||||
EmptyExpr {
|
|
||||||
return none
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (val ComptTimeConstValue) string() ?string {
|
pub fn (val ComptTimeConstValue) string() ?string {
|
||||||
match val {
|
match val {
|
||||||
i64, f64, byte {
|
u64 {
|
||||||
|
return val.str()
|
||||||
|
}
|
||||||
|
i64 {
|
||||||
|
return val.str()
|
||||||
|
}
|
||||||
|
f64 {
|
||||||
|
return val.str()
|
||||||
|
}
|
||||||
|
byte {
|
||||||
|
return val.str()
|
||||||
|
}
|
||||||
|
rune {
|
||||||
return val.str()
|
return val.str()
|
||||||
}
|
}
|
||||||
string {
|
string {
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
rune {
|
EmptyExpr {}
|
||||||
return val.str()
|
|
||||||
}
|
|
||||||
EmptyExpr {
|
|
||||||
return none
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (val ComptTimeConstValue) f64() ?f64 {
|
pub fn (val ComptTimeConstValue) f64() ?f64 {
|
||||||
match val {
|
match val {
|
||||||
|
i64 {
|
||||||
|
return f64(val)
|
||||||
|
}
|
||||||
|
u64 {
|
||||||
|
return f64(val)
|
||||||
|
}
|
||||||
|
byte {
|
||||||
|
return f64(val)
|
||||||
|
}
|
||||||
f64 {
|
f64 {
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
i64, byte {
|
|
||||||
return f64(val)
|
|
||||||
}
|
|
||||||
string {
|
string {
|
||||||
return val.f64()
|
return val.f64()
|
||||||
}
|
}
|
||||||
rune {
|
rune {}
|
||||||
return none
|
EmptyExpr {}
|
||||||
|
}
|
||||||
|
return none
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (val ComptTimeConstValue) u64() ?u64 {
|
||||||
|
match val {
|
||||||
|
i64 {
|
||||||
|
if val >= 0 {
|
||||||
|
return u64(val)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EmptyExpr {
|
u64 {
|
||||||
return none
|
return val
|
||||||
}
|
}
|
||||||
|
byte {
|
||||||
|
return u64(val)
|
||||||
|
}
|
||||||
|
f64 {
|
||||||
|
if val <= 18446744073709551615.0 {
|
||||||
|
return u64(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string {
|
||||||
|
return val.u64()
|
||||||
|
}
|
||||||
|
rune {}
|
||||||
|
EmptyExpr {}
|
||||||
}
|
}
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
|
@ -104,35 +143,34 @@ pub fn (val ComptTimeConstValue) byte() ?byte {
|
||||||
byte {
|
byte {
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
u64 {
|
||||||
|
if val <= 255 {
|
||||||
|
return byte(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
f64 {
|
f64 {
|
||||||
if 0 <= val && val <= 255 {
|
if 0 <= val && val <= 255 {
|
||||||
return byte(val)
|
return byte(val)
|
||||||
}
|
}
|
||||||
return none
|
|
||||||
}
|
}
|
||||||
i64 {
|
i64 {
|
||||||
if 0 <= val && val <= 255 {
|
if 0 <= val && val <= 255 {
|
||||||
return byte(val)
|
return byte(val)
|
||||||
}
|
}
|
||||||
return none
|
|
||||||
}
|
}
|
||||||
string {
|
string {
|
||||||
x := val.int()
|
x := val.int()
|
||||||
if 0 <= x && x <= 255 {
|
if 0 <= x && x <= 255 {
|
||||||
return byte(x)
|
return byte(x)
|
||||||
}
|
}
|
||||||
return none
|
|
||||||
}
|
}
|
||||||
rune {
|
rune {
|
||||||
x := u32(val)
|
x := u32(val)
|
||||||
if 0 <= x && x <= 255 {
|
if 0 <= x && x <= 255 {
|
||||||
return byte(x)
|
return byte(x)
|
||||||
}
|
}
|
||||||
return none
|
|
||||||
}
|
|
||||||
EmptyExpr {
|
|
||||||
return none
|
|
||||||
}
|
}
|
||||||
|
EmptyExpr {}
|
||||||
}
|
}
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
|
|
|
@ -3611,9 +3611,12 @@ pub fn (mut c Checker) const_decl(mut node ast.ConstDecl) {
|
||||||
for i, mut field in node.fields {
|
for i, mut field in node.fields {
|
||||||
c.const_decl = field.name
|
c.const_decl = field.name
|
||||||
c.const_deps << field.name
|
c.const_deps << field.name
|
||||||
typ := c.check_expr_opt_call(field.expr, c.expr(field.expr))
|
mut typ := c.check_expr_opt_call(field.expr, c.expr(field.expr))
|
||||||
if ct_value := eval_comptime_const_expr(field.expr, 0) {
|
if ct_value := eval_comptime_const_expr(field.expr, 0) {
|
||||||
field.comptime_expr_value = ct_value
|
field.comptime_expr_value = ct_value
|
||||||
|
if ct_value is u64 {
|
||||||
|
typ = ast.u64_type
|
||||||
|
}
|
||||||
}
|
}
|
||||||
node.fields[i].typ = c.table.mktyp(typ)
|
node.fields[i].typ = c.table.mktyp(typ)
|
||||||
for cd in c.const_deps {
|
for cd in c.const_deps {
|
||||||
|
|
|
@ -7,34 +7,40 @@ fn eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.ComptTimeConstValue
|
||||||
// protect against a too deep comptime eval recursion
|
// protect against a too deep comptime eval recursion
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
x := expr
|
|
||||||
match expr {
|
match expr {
|
||||||
ast.IntegerLiteral {
|
ast.IntegerLiteral {
|
||||||
|
x := expr.val.u64()
|
||||||
|
if x > 9223372036854775807 {
|
||||||
|
return x
|
||||||
|
}
|
||||||
return expr.val.i64()
|
return expr.val.i64()
|
||||||
}
|
}
|
||||||
ast.StringLiteral {
|
ast.StringLiteral {
|
||||||
return expr.val
|
return expr.val
|
||||||
}
|
}
|
||||||
|
ast.CharLiteral {
|
||||||
|
runes := expr.val.runes()
|
||||||
|
if runes.len > 0 {
|
||||||
|
return runes[0]
|
||||||
|
}
|
||||||
|
return none
|
||||||
|
}
|
||||||
|
ast.Ident {
|
||||||
|
if expr.obj is ast.ConstField {
|
||||||
|
// an existing constant?
|
||||||
|
return eval_comptime_const_expr(expr.obj.expr, nlevel + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
ast.CastExpr {
|
ast.CastExpr {
|
||||||
cast_expr_value := eval_comptime_const_expr(expr.expr, nlevel + 1) or { return none }
|
cast_expr_value := eval_comptime_const_expr(expr.expr, nlevel + 1) or { return none }
|
||||||
if expr.typ == ast.byte_type {
|
if expr.typ == ast.byte_type {
|
||||||
return cast_expr_value.byte() or { return none }
|
return cast_expr_value.byte() or { return none }
|
||||||
}
|
}
|
||||||
if expr.typ == ast.int_type {
|
if expr.typ == ast.int_type {
|
||||||
match cast_expr_value {
|
return i64(cast_expr_value.int() or { return none })
|
||||||
byte {
|
}
|
||||||
eprintln('>>>>>>> byte cast_expr_value: $cast_expr_value | x: $x')
|
if expr.typ == ast.u64_type {
|
||||||
return i64(cast_expr_value)
|
return cast_expr_value.u64() or { return none }
|
||||||
}
|
|
||||||
i64 {
|
|
||||||
eprintln('>>>>>>> i64 cast_expr_value: $cast_expr_value | x: $x')
|
|
||||||
if int_min <= cast_expr_value && cast_expr_value <= int_max {
|
|
||||||
return i64(cast_expr_value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {}
|
|
||||||
}
|
|
||||||
return none
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.InfixExpr {
|
ast.InfixExpr {
|
||||||
|
@ -49,6 +55,20 @@ fn eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.ComptTimeConstValue
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if left is u64 && right is u64 {
|
||||||
|
match expr.op {
|
||||||
|
.plus { return left + right }
|
||||||
|
.minus { return left - right }
|
||||||
|
.mul { return left * right }
|
||||||
|
.div { return left / right }
|
||||||
|
.mod { return left % right }
|
||||||
|
.xor { return left ^ right }
|
||||||
|
.pipe { return left | right }
|
||||||
|
.amp { return left & right }
|
||||||
|
.left_shift { return left << right }
|
||||||
|
.right_shift { return left >> right }
|
||||||
|
else { return none }
|
||||||
|
}
|
||||||
} else if left is i64 && right is i64 {
|
} else if left is i64 && right is i64 {
|
||||||
match expr.op {
|
match expr.op {
|
||||||
.plus { return left + right }
|
.plus { return left + right }
|
||||||
|
@ -79,12 +99,6 @@ fn eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.ComptTimeConstValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.Ident {
|
|
||||||
if expr.obj is ast.ConstField {
|
|
||||||
// an existing constant?
|
|
||||||
return eval_comptime_const_expr(expr.obj.expr, nlevel + 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
// eprintln('>>> nlevel: $nlevel | another $expr.type_name() | $expr ')
|
// eprintln('>>> nlevel: $nlevel | another $expr.type_name() | $expr ')
|
||||||
return none
|
return none
|
||||||
|
|
|
@ -4917,17 +4917,37 @@ fn is_simple_define_const(obj ast.ScopeObject) bool {
|
||||||
fn (mut g Gen) const_decl_precomputed(mod string, name string, ct_value ast.ComptTimeConstValue, typ ast.Type) bool {
|
fn (mut g Gen) const_decl_precomputed(mod string, name string, ct_value ast.ComptTimeConstValue, typ ast.Type) bool {
|
||||||
mut styp := g.typ(typ)
|
mut styp := g.typ(typ)
|
||||||
cname := '_const_$name'
|
cname := '_const_$name'
|
||||||
// eprintln('>> cname: $cname | styp: $styp | $ct_value.type_name() | $ct_value')
|
|
||||||
match ct_value {
|
match ct_value {
|
||||||
byte {
|
byte {
|
||||||
g.const_decl_write_precomputed(styp, cname, ct_value.str())
|
g.const_decl_write_precomputed(styp, cname, ct_value.str())
|
||||||
}
|
}
|
||||||
rune {
|
rune {
|
||||||
g.const_decl_write_precomputed(styp, cname, ct_value.str())
|
rune_code := u32(ct_value)
|
||||||
|
if rune_code <= 255 {
|
||||||
|
if rune_code in [`"`, `\\`, `\'`] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
escval := util.smart_quote(byte(rune_code).ascii_str(), false)
|
||||||
|
g.const_decl_write_precomputed(styp, cname, "'$escval'")
|
||||||
|
} else {
|
||||||
|
g.const_decl_write_precomputed(styp, cname, u32(ct_value).str())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
i64 {
|
i64 {
|
||||||
|
if typ == ast.int_type {
|
||||||
|
// TODO: use g.const_decl_write_precomputed here too.
|
||||||
|
// For now, use #define macros, so existing code compiles
|
||||||
|
// with -cstrict. Add checker errors for overflows instead,
|
||||||
|
// so V can catch them earlier, instead of relying on the
|
||||||
|
// C compiler for that.
|
||||||
|
g.const_decl_simple_define(name, ct_value.str())
|
||||||
|
return true
|
||||||
|
}
|
||||||
g.const_decl_write_precomputed(styp, cname, ct_value.str())
|
g.const_decl_write_precomputed(styp, cname, ct_value.str())
|
||||||
}
|
}
|
||||||
|
u64 {
|
||||||
|
g.const_decl_write_precomputed(styp, cname, ct_value.str() + 'U')
|
||||||
|
}
|
||||||
f64 {
|
f64 {
|
||||||
g.const_decl_write_precomputed(styp, cname, ct_value.str())
|
g.const_decl_write_precomputed(styp, cname, ct_value.str())
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,7 +174,7 @@ fn (mut g Gen) macho_dylibs() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) macho_main(addr int) {
|
fn (mut g Gen) macho_main(addr int) {
|
||||||
g.write32(native.lc_main) // LC_MAIN
|
g.write32(int(native.lc_main)) // LC_MAIN
|
||||||
g.write32(24) // cmdsize
|
g.write32(24) // cmdsize
|
||||||
g.write32(addr) // entrypoint
|
g.write32(addr) // entrypoint
|
||||||
g.write32(0) // initial_stacksize
|
g.write32(0) // initial_stacksize
|
||||||
|
@ -242,7 +242,7 @@ pub fn (mut g Gen) generate_macho_object_header() {
|
||||||
g.write32(0x4) // alignment
|
g.write32(0x4) // alignment
|
||||||
g.write32(0x160) // relocation offset
|
g.write32(0x160) // relocation offset
|
||||||
g.write32(0x1) // # of relocations
|
g.write32(0x1) // # of relocations
|
||||||
g.write32(native.s_attr_some_instructions | native.s_attr_pure_instructions)
|
g.write32(int(native.s_attr_some_instructions | native.s_attr_pure_instructions))
|
||||||
g.write32(0)
|
g.write32(0)
|
||||||
g.write32(0)
|
g.write32(0)
|
||||||
g.write32(0)
|
g.write32(0)
|
||||||
|
|
Loading…
Reference in New Issue