strconv,checker,cgen: fix -cstrict compilation of hello_world.v
parent
48546d0f45
commit
241a7b760d
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue