From 241a7b760d062bf1976f3fda5f59ed56cbf7d1a0 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Sun, 18 Jul 2021 22:59:52 +0300 Subject: [PATCH] strconv,checker,cgen: fix -cstrict compilation of hello_world.v --- vlib/v/ast/comptime_const_values.v | 108 ++++++++++++++++++--------- vlib/v/checker/checker.v | 5 +- vlib/v/checker/comptime_const_eval.v | 56 ++++++++------ vlib/v/gen/c/cgen.v | 24 +++++- vlib/v/gen/native/macho.v | 4 +- 5 files changed, 136 insertions(+), 61 deletions(-) diff --git a/vlib/v/ast/comptime_const_values.v b/vlib/v/ast/comptime_const_values.v index e11571fe8b..a1050e16ee 100644 --- a/vlib/v/ast/comptime_const_values.v +++ b/vlib/v/ast/comptime_const_values.v @@ -1,6 +1,6 @@ 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 { return EmptyExpr{} @@ -8,14 +8,21 @@ pub fn empty_comptime_const_expr() ComptTimeConstValue { pub fn (val ComptTimeConstValue) i64() ?i64 { match val { - i64, byte { + byte { + return i64(val) + } + i64 { return i64(val) } f64 { if -9223372036854775808.0 <= val && val <= 9223372036854775807.0 { return i64(val) } - return none + } + u64 { + if val <= 9223372036854775807 { + return i64(val) + } } string { return val.i64() @@ -23,26 +30,27 @@ pub fn (val ComptTimeConstValue) i64() ?i64 { rune { return int(val) } - EmptyExpr { - return none - } + EmptyExpr {} } return none } pub fn (val ComptTimeConstValue) int() ?int { match val { + u64 { + if val <= 2147483647 { + return int(val) + } + } f64 { if -2147483648.0 <= val && val <= 2147483647.0 { return int(val) } - return none } i64 { if -2147483648 <= val && val <= 2147483647 { return int(val) } - return none } byte { return int(val) @@ -50,51 +58,82 @@ pub fn (val ComptTimeConstValue) int() ?int { string { return val.int() } - rune { - return none - } - EmptyExpr { - return none - } + rune, EmptyExpr {} } return none } pub fn (val ComptTimeConstValue) string() ?string { 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() } string { return val } - rune { - return val.str() - } - EmptyExpr { - return none - } + EmptyExpr {} } return none } pub fn (val ComptTimeConstValue) f64() ?f64 { match val { + i64 { + return f64(val) + } + u64 { + return f64(val) + } + byte { + return f64(val) + } f64 { return val } - i64, byte { - return f64(val) - } string { return val.f64() } - rune { - return none + rune {} + EmptyExpr {} + } + return none +} + +pub fn (val ComptTimeConstValue) u64() ?u64 { + match val { + i64 { + if val >= 0 { + return u64(val) + } } - EmptyExpr { - return none + u64 { + return val } + byte { + return u64(val) + } + f64 { + if val <= 18446744073709551615.0 { + return u64(val) + } + } + string { + return val.u64() + } + rune {} + EmptyExpr {} } return none } @@ -104,35 +143,34 @@ pub fn (val ComptTimeConstValue) byte() ?byte { byte { return val } + u64 { + if val <= 255 { + return byte(val) + } + } f64 { if 0 <= val && val <= 255 { return byte(val) } - return none } i64 { if 0 <= val && val <= 255 { return byte(val) } - return none } string { x := val.int() if 0 <= x && x <= 255 { return byte(x) } - return none } rune { x := u32(val) if 0 <= x && x <= 255 { return byte(x) } - return none - } - EmptyExpr { - return none } + EmptyExpr {} } return none } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 6a8c54a889..eec5754c71 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3611,9 +3611,12 @@ pub fn (mut c Checker) const_decl(mut node ast.ConstDecl) { for i, mut field in node.fields { c.const_decl = 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) { field.comptime_expr_value = ct_value + if ct_value is u64 { + typ = ast.u64_type + } } node.fields[i].typ = c.table.mktyp(typ) for cd in c.const_deps { diff --git a/vlib/v/checker/comptime_const_eval.v b/vlib/v/checker/comptime_const_eval.v index d514e08a97..b44ca9ebb0 100644 --- a/vlib/v/checker/comptime_const_eval.v +++ b/vlib/v/checker/comptime_const_eval.v @@ -7,34 +7,40 @@ fn eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.ComptTimeConstValue // protect against a too deep comptime eval recursion return none } - x := expr match expr { ast.IntegerLiteral { + x := expr.val.u64() + if x > 9223372036854775807 { + return x + } return expr.val.i64() } ast.StringLiteral { 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 { cast_expr_value := eval_comptime_const_expr(expr.expr, nlevel + 1) or { return none } if expr.typ == ast.byte_type { return cast_expr_value.byte() or { return none } } if expr.typ == ast.int_type { - match cast_expr_value { - byte { - eprintln('>>>>>>> byte cast_expr_value: $cast_expr_value | x: $x') - return i64(cast_expr_value) - } - 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 + return i64(cast_expr_value.int() or { return none }) + } + if expr.typ == ast.u64_type { + return cast_expr_value.u64() or { return none } } } ast.InfixExpr { @@ -49,6 +55,20 @@ fn eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.ComptTimeConstValue 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 { match expr.op { .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 { // eprintln('>>> nlevel: $nlevel | another $expr.type_name() | $expr ') return none diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index b7280eb044..9682a67788 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -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 { mut styp := g.typ(typ) cname := '_const_$name' - // eprintln('>> cname: $cname | styp: $styp | $ct_value.type_name() | $ct_value') match ct_value { byte { g.const_decl_write_precomputed(styp, cname, ct_value.str()) } 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 { + 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()) } + u64 { + g.const_decl_write_precomputed(styp, cname, ct_value.str() + 'U') + } f64 { g.const_decl_write_precomputed(styp, cname, ct_value.str()) } diff --git a/vlib/v/gen/native/macho.v b/vlib/v/gen/native/macho.v index 6e7ebd3648..b25bf05a1d 100644 --- a/vlib/v/gen/native/macho.v +++ b/vlib/v/gen/native/macho.v @@ -174,7 +174,7 @@ fn (mut g Gen) macho_dylibs() { } 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(addr) // entrypoint g.write32(0) // initial_stacksize @@ -242,7 +242,7 @@ pub fn (mut g Gen) generate_macho_object_header() { g.write32(0x4) // alignment g.write32(0x160) // relocation offset 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)