authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-20 01:46:49-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-20 01:46:49-04:00
logf5a67dba08b81c7109c52f6ad957aefdd646b56e
treefa89431ab0e1c1149ff86cde8ab6c4aff1c79dcb
parent33fbd8c1d333922efa696b5b9384859a2664f8de

self-hosted: implicit cast comptime ints to other ints

we now have successful exit codes from main linking against libc

4 files changed, 110 insertions(+), 2 deletions(-)

src-self-hosted/ir.zig+38-1
......@@ -139,7 +139,15 @@ pub const Inst = struct {
139139 }
140140 }
141141
142 fn copyVal(base: *Inst, comp: *Compilation) !*Value {
143 if (base.parent.?.ref_count == 0) {
144 return base.val.KnownValue.derefAndCopy(comp);
145 }
146 return base.val.KnownValue.copy(comp);
147 }
148
142149 fn getAsParam(param: *Inst) !*Inst {
150 param.ref_count -= 1;
143151 const child = param.child orelse return error.SemanticAnalysisFailed;
144152 switch (child.val) {
145153 IrVal.Unknown => return error.SemanticAnalysisFailed,
......@@ -1715,8 +1723,37 @@ const Analyze = struct {
17151723 // }
17161724 //}
17171725
1726 // cast from comptime-known integer to another integer where the value fits
1727 if (target.isCompTime() and (from_type.id == Type.Id.Int or from_type.id == Type.Id.ComptimeInt)) cast: {
1728 const target_val = target.val.KnownValue;
1729 const from_int = &target_val.cast(Value.Int).?.big_int;
1730 const fits = fits: {
1731 if (dest_type.cast(Type.ComptimeInt)) |ctint| {
1732 break :fits true;
1733 }
1734 if (dest_type.cast(Type.Int)) |int| {
1735 break :fits (from_int.positive or from_int.eqZero() or int.key.is_signed) and
1736 int.key.bit_count >= from_int.bitcount();
1737 }
1738 break :cast;
1739 };
1740 if (!fits) {
1741 try ira.addCompileError(
1742 source_instr.span,
1743 "integer value '{}' cannot be stored in type '{}'",
1744 from_int,
1745 dest_type.name,
1746 );
1747 return error.SemanticAnalysisFailed;
1748 }
1749
1750 const new_val = try target.copyVal(ira.irb.comp);
1751 new_val.setType(dest_type, ira.irb.comp);
1752 return ira.irb.buildConstValue(source_instr.scope, source_instr.span, new_val);
1753 }
1754
17181755 // cast from number literal to another type
1719 //// cast from number literal to *const integer
1756 // cast from number literal to *const integer
17201757 //if (actual_type->id == TypeTableEntryIdComptimeFloat ||
17211758 // actual_type->id == TypeTableEntryIdComptimeInt)
17221759 //{
src-self-hosted/value.zig+49
......@@ -5,6 +5,7 @@ const Compilation = @import("compilation.zig").Compilation;
55const ObjectFile = @import("codegen.zig").ObjectFile;
66const llvm = @import("llvm.zig");
77const Buffer = std.Buffer;
8const assert = std.debug.assert;
89
910/// Values are ref-counted, heap-allocated, and copy-on-write
1011/// If there is only 1 ref then write need not copy
......@@ -34,6 +35,12 @@ pub const Value = struct {
3435 }
3536 }
3637
38 pub fn setType(base: *Value, new_type: *Type, comp: *Compilation) void {
39 base.typeof.base.deref(comp);
40 new_type.base.ref();
41 base.typeof = new_type;
42 }
43
3744 pub fn getRef(base: *Value) *Value {
3845 base.ref();
3946 return base;
......@@ -60,6 +67,28 @@ pub const Value = struct {
6067 }
6168 }
6269
70 pub fn derefAndCopy(self: *Value, comp: *Compilation) (error{OutOfMemory}!*Value) {
71 if (self.ref_count.get() == 1) {
72 // ( ͡° ͜ʖ ͡°)
73 return self;
74 }
75
76 assert(self.ref_count.decr() != 1);
77 return self.copy(comp);
78 }
79
80 pub fn copy(base: *Value, comp: *Compilation) (error{OutOfMemory}!*Value) {
81 switch (base.id) {
82 Id.Type => unreachable,
83 Id.Fn => unreachable,
84 Id.Void => unreachable,
85 Id.Bool => unreachable,
86 Id.NoReturn => unreachable,
87 Id.Ptr => unreachable,
88 Id.Int => return &(try @fieldParentPtr(Int, "base", base).copy(comp)).base,
89 }
90 }
91
6392 pub const Id = enum {
6493 Type,
6594 Fn,
......@@ -256,6 +285,26 @@ pub const Value = struct {
256285 }
257286 }
258287
288 pub fn copy(old: *Int, comp: *Compilation) !*Int {
289 old.base.typeof.base.ref();
290 errdefer old.base.typeof.base.deref(comp);
291
292 const new = try comp.gpa().create(Value.Int{
293 .base = Value{
294 .id = Value.Id.Int,
295 .typeof = old.base.typeof,
296 .ref_count = std.atomic.Int(usize).init(1),
297 },
298 .big_int = undefined,
299 });
300 errdefer comp.gpa().destroy(new);
301
302 new.big_int = try old.big_int.clone();
303 errdefer new.big_int.deinit();
304
305 return new;
306 }
307
259308 pub fn destroy(self: *Int, comp: *Compilation) void {
260309 self.big_int.deinit();
261310 comp.gpa().destroy(self);
std/math/big/int.zig+17-1
......@@ -118,7 +118,7 @@ pub const Int = struct {
118118
119119 fn bitcount(self: Int) usize {
120120 const u_bit_count = (self.len - 1) * Limb.bit_count + (Limb.bit_count - @clz(self.limbs[self.len - 1]));
121 return usize(@boolToInt(!self.positive)) + u_bit_count;
121 return @boolToInt(!self.positive) + u_bit_count;
122122 }
123123
124124 pub fn sizeInBase(self: Int, base: usize) usize {
......@@ -275,6 +275,7 @@ pub const Int = struct {
275275 self.positive = positive;
276276 }
277277
278 /// TODO make this call format instead of the other way around
278279 pub fn toString(self: Int, allocator: *Allocator, base: u8) ![]const u8 {
279280 if (base < 2 or base > 16) {
280281 return error.InvalidBase;
......@@ -357,6 +358,21 @@ pub const Int = struct {
357358 return s;
358359 }
359360
361 /// for the std lib format function
362 /// TODO make this non-allocating
363 pub fn format(
364 self: Int,
365 comptime fmt: []const u8,
366 context: var,
367 comptime FmtError: type,
368 output: fn (@typeOf(context), []const u8) FmtError!void,
369 ) FmtError!void {
370 // TODO look at fmt and support other bases
371 const str = self.toString(self.allocator, 10) catch @panic("TODO make this non allocating");
372 defer self.allocator.free(str);
373 return output(context, str);
374 }
375
360376 // returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.
361377 pub fn cmpAbs(a: Int, b: Int) i8 {
362378 if (a.len < b.len) {
test/stage2/compile_errors.zig+6
......@@ -21,4 +21,10 @@ pub fn addCases(ctx: *TestContext) !void {
2121 \\ defer return;
2222 \\}
2323 , "1.zig", 2, 11, "cannot return from defer expression");
24
25 try ctx.testCompileError(
26 \\export fn entry() c_int {
27 \\ return 36893488147419103232;
28 \\}
29 , "1.zig", 2, 12, "integer value '36893488147419103232' cannot be stored in type 'c_int'");
2430}