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