| author | |
| committer | |
| log | b560f46c871f234a8b2f762c03984eef963f360a |
| tree | 4c82363776185796842c5b4a505444381a77e67e |
| parent | a130eac7857512db50320fb1c64079b0d696885d |
7 files changed, 91 insertions(+), 26 deletions(-)
src/Module.zig+7-2| ... | ... | @@ -3464,11 +3464,16 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 3464 | 3464 | queue_linker_work = true; |
| 3465 | 3465 | } |
| 3466 | 3466 | }, |
| 3467 | .array, .@"struct", .@"union" => { | |
| 3467 | ||
| 3468 | .generic_poison => unreachable, | |
| 3469 | .unreachable_value => unreachable, | |
| 3470 | ||
| 3471 | .function => {}, | |
| 3472 | ||
| 3473 | else => { | |
| 3468 | 3474 | log.debug("send global const to linker: {*} ({s})", .{ decl, decl.name }); |
| 3469 | 3475 | queue_linker_work = true; |
| 3470 | 3476 | }, |
| 3471 | else => {}, | |
| 3472 | 3477 | } |
| 3473 | 3478 | |
| 3474 | 3479 | decl.ty = try decl_tv.ty.copy(&decl_arena.allocator); |
src/Sema.zig+4-2| ... | ... | @@ -4800,8 +4800,10 @@ fn zirOptionalPayload( |
| 4800 | 4800 | if (val.isNull()) { |
| 4801 | 4801 | return sema.fail(block, src, "unable to unwrap null", .{}); |
| 4802 | 4802 | } |
| 4803 | const sub_val = val.castTag(.opt_payload).?.data; | |
| 4804 | return sema.addConstant(result_ty, sub_val); | |
| 4803 | if (val.castTag(.opt_payload)) |payload| { | |
| 4804 | return sema.addConstant(result_ty, payload.data); | |
| 4805 | } | |
| 4806 | return sema.addConstant(result_ty, val); | |
| 4805 | 4807 | } |
| 4806 | 4808 | |
| 4807 | 4809 | try sema.requireRuntimeBlock(block, src); |
src/arch/wasm/CodeGen.zig+5| ... | ... | @@ -848,6 +848,11 @@ pub fn gen(self: *Self, ty: Type, val: Value) InnerError!Result { |
| 848 | 848 | try self.emitConstant(val, ty); |
| 849 | 849 | return Result.appended; |
| 850 | 850 | }, |
| 851 | .Bool => { | |
| 852 | const int_byte: u8 = @boolToInt(val.toBool()); | |
| 853 | try self.code.append(int_byte); | |
| 854 | return Result.appended; | |
| 855 | }, | |
| 851 | 856 | .Struct => { |
| 852 | 857 | // TODO write the fields for real |
| 853 | 858 | const abi_size = try std.math.cast(usize, ty.abiSize(self.target)); |
src/codegen.zig+56| ... | ... | @@ -286,6 +286,62 @@ pub fn generateSymbol( |
| 286 | 286 | } |
| 287 | 287 | return Result{ .appended = {} }; |
| 288 | 288 | }, |
| 289 | .Enum => { | |
| 290 | // TODO populate .debug_info for the enum | |
| 291 | var int_buffer: Value.Payload.U64 = undefined; | |
| 292 | const int_val = typed_value.enumToInt(&int_buffer); | |
| 293 | ||
| 294 | const target = bin_file.options.target; | |
| 295 | const info = typed_value.ty.intInfo(target); | |
| 296 | if (info.bits <= 8) { | |
| 297 | const x = @intCast(u8, int_val.toUnsignedInt()); | |
| 298 | try code.append(x); | |
| 299 | return Result{ .appended = {} }; | |
| 300 | } | |
| 301 | if (info.bits > 64) { | |
| 302 | return Result{ | |
| 303 | .fail = try ErrorMsg.create( | |
| 304 | bin_file.allocator, | |
| 305 | src_loc, | |
| 306 | "TODO implement generateSymbol for big int enums ('{}')", | |
| 307 | .{typed_value.ty}, | |
| 308 | ), | |
| 309 | }; | |
| 310 | } | |
| 311 | const endian = target.cpu.arch.endian(); | |
| 312 | switch (info.signedness) { | |
| 313 | .unsigned => { | |
| 314 | if (info.bits <= 16) { | |
| 315 | const x = @intCast(u16, int_val.toUnsignedInt()); | |
| 316 | mem.writeInt(u16, try code.addManyAsArray(2), x, endian); | |
| 317 | } else if (info.bits <= 32) { | |
| 318 | const x = @intCast(u32, int_val.toUnsignedInt()); | |
| 319 | mem.writeInt(u32, try code.addManyAsArray(4), x, endian); | |
| 320 | } else { | |
| 321 | const x = int_val.toUnsignedInt(); | |
| 322 | mem.writeInt(u64, try code.addManyAsArray(8), x, endian); | |
| 323 | } | |
| 324 | }, | |
| 325 | .signed => { | |
| 326 | if (info.bits <= 16) { | |
| 327 | const x = @intCast(i16, int_val.toSignedInt()); | |
| 328 | mem.writeInt(i16, try code.addManyAsArray(2), x, endian); | |
| 329 | } else if (info.bits <= 32) { | |
| 330 | const x = @intCast(i32, int_val.toSignedInt()); | |
| 331 | mem.writeInt(i32, try code.addManyAsArray(4), x, endian); | |
| 332 | } else { | |
| 333 | const x = int_val.toSignedInt(); | |
| 334 | mem.writeInt(i64, try code.addManyAsArray(8), x, endian); | |
| 335 | } | |
| 336 | }, | |
| 337 | } | |
| 338 | return Result{ .appended = {} }; | |
| 339 | }, | |
| 340 | .Bool => { | |
| 341 | const x: u8 = @boolToInt(typed_value.val.toBool()); | |
| 342 | try code.append(x); | |
| 343 | return Result{ .appended = {} }; | |
| 344 | }, | |
| 289 | 345 | .Struct => { |
| 290 | 346 | const field_vals = typed_value.val.castTag(.@"struct").?.data; |
| 291 | 347 | _ = field_vals; // TODO write the fields for real |
src/codegen/c.zig+1-4| ... | ... | @@ -772,10 +772,7 @@ pub const DeclGen = struct { |
| 772 | 772 | const target = dg.module.getTarget(); |
| 773 | 773 | |
| 774 | 774 | switch (t.zigTypeTag()) { |
| 775 | .NoReturn => { | |
| 776 | try w.writeAll("zig_noreturn void"); | |
| 777 | }, | |
| 778 | .Void => try w.writeAll("void"), | |
| 775 | .NoReturn, .Void => try w.writeAll("void"), | |
| 779 | 776 | .Bool => try w.writeAll("bool"), |
| 780 | 777 | .Int => { |
| 781 | 778 | switch (t.tag()) { |
test/behavior/optional.zig+18| ... | ... | @@ -118,3 +118,21 @@ fn test_cmp_optional_non_optional() !void { |
| 118 | 118 | break :blk2 @as(?f64, 5.0); |
| 119 | 119 | }; |
| 120 | 120 | } |
| 121 | ||
| 122 | test "unwrap function call with optional pointer return value" { | |
| 123 | const S = struct { | |
| 124 | fn entry() !void { | |
| 125 | try expect(foo().?.* == 1234); | |
| 126 | try expect(bar() == null); | |
| 127 | } | |
| 128 | const global: i32 = 1234; | |
| 129 | fn foo() ?*const i32 { | |
| 130 | return &global; | |
| 131 | } | |
| 132 | fn bar() ?*i32 { | |
| 133 | return null; | |
| 134 | } | |
| 135 | }; | |
| 136 | try S.entry(); | |
| 137 | comptime try S.entry(); | |
| 138 | } |
test/behavior/optional_stage1.zig-18| ... | ... | @@ -3,24 +3,6 @@ const testing = std.testing; |
| 3 | 3 | const expect = testing.expect; |
| 4 | 4 | const expectEqual = testing.expectEqual; |
| 5 | 5 | |
| 6 | test "unwrap function call with optional pointer return value" { | |
| 7 | const S = struct { | |
| 8 | fn entry() !void { | |
| 9 | try expect(foo().?.* == 1234); | |
| 10 | try expect(bar() == null); | |
| 11 | } | |
| 12 | const global: i32 = 1234; | |
| 13 | fn foo() ?*const i32 { | |
| 14 | return &global; | |
| 15 | } | |
| 16 | fn bar() ?*i32 { | |
| 17 | return null; | |
| 18 | } | |
| 19 | }; | |
| 20 | try S.entry(); | |
| 21 | comptime try S.entry(); | |
| 22 | } | |
| 23 | ||
| 24 | 6 | test "nested orelse" { |
| 25 | 7 | const S = struct { |
| 26 | 8 | fn entry() !void { |