mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 22:35:24 +00:00
C backend: implement ?void, and other zero sized types
This commit is contained in:
parent
325bae7fc0
commit
674932e503
@ -308,6 +308,11 @@ pub const DeclGen = struct {
|
||||
if (ty.isPtrLikeOptional()) {
|
||||
return dg.renderValue(writer, payload_type, val);
|
||||
}
|
||||
const target = dg.module.getTarget();
|
||||
if (payload_type.abiSize(target) == 0) {
|
||||
const is_null = val.castTag(.opt_payload) == null;
|
||||
return writer.print("{}", .{is_null});
|
||||
}
|
||||
try writer.writeByte('(');
|
||||
try dg.renderType(writer, ty);
|
||||
try writer.writeAll("){");
|
||||
@ -588,10 +593,13 @@ pub const DeclGen = struct {
|
||||
.Optional => {
|
||||
var opt_buf: Type.Payload.ElemType = undefined;
|
||||
const child_type = t.optionalChild(&opt_buf);
|
||||
const target = dg.module.getTarget();
|
||||
if (t.isPtrLikeOptional()) {
|
||||
return dg.renderType(w, child_type);
|
||||
} else if (dg.typedefs.get(t)) |some| {
|
||||
return w.writeAll(some.name);
|
||||
} else if (child_type.abiSize(target) == 0) {
|
||||
return w.writeAll("bool");
|
||||
}
|
||||
|
||||
var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
|
||||
@ -2100,14 +2108,21 @@ fn airIsNull(
|
||||
const un_op = f.air.instructions.items(.data)[inst].un_op;
|
||||
const writer = f.object.writer();
|
||||
const operand = try f.resolveInst(un_op);
|
||||
const target = f.object.dg.module.getTarget();
|
||||
|
||||
const local = try f.allocLocal(Type.initTag(.bool), .Const);
|
||||
try writer.writeAll(" = (");
|
||||
try f.writeCValue(writer, operand);
|
||||
|
||||
if (f.air.typeOf(un_op).isPtrLikeOptional()) {
|
||||
const ty = f.air.typeOf(un_op);
|
||||
var opt_buf: Type.Payload.ElemType = undefined;
|
||||
const payload_type = ty.optionalChild(&opt_buf);
|
||||
|
||||
if (ty.isPtrLikeOptional()) {
|
||||
// operand is a regular pointer, test `operand !=/== NULL`
|
||||
try writer.print("){s} {s} NULL;\n", .{ deref_suffix, operator });
|
||||
} else if (payload_type.abiSize(target) == 0) {
|
||||
try writer.print("){s} {s} true;\n", .{ deref_suffix, operator });
|
||||
} else {
|
||||
try writer.print("){s}.is_null {s} true;\n", .{ deref_suffix, operator });
|
||||
}
|
||||
|
||||
@ -1805,7 +1805,13 @@ pub const Type = extern union {
|
||||
.void,
|
||||
=> 0,
|
||||
|
||||
.@"struct" => return self.structFieldOffset(self.structFieldCount(), target),
|
||||
.@"struct" => {
|
||||
const field_count = self.structFieldCount();
|
||||
if (field_count == 0) {
|
||||
return 0;
|
||||
}
|
||||
return self.structFieldOffset(field_count, target);
|
||||
},
|
||||
.enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {
|
||||
var buffer: Payload.Bits = undefined;
|
||||
const int_tag_ty = self.intTagType(&buffer);
|
||||
|
||||
@ -6,6 +6,7 @@ test {
|
||||
_ = @import("behavior/bool.zig");
|
||||
_ = @import("behavior/if.zig");
|
||||
_ = @import("behavior/truncate.zig");
|
||||
_ = @import("behavior/null.zig");
|
||||
|
||||
if (builtin.object_format != .c) {
|
||||
// Tests that pass for stage1 and stage2 but not the C backend.
|
||||
@ -48,7 +49,7 @@ test {
|
||||
_ = @import("behavior/math.zig");
|
||||
_ = @import("behavior/maximum_minimum.zig");
|
||||
_ = @import("behavior/member_func.zig");
|
||||
_ = @import("behavior/null.zig");
|
||||
_ = @import("behavior/null_llvm.zig");
|
||||
_ = @import("behavior/optional.zig");
|
||||
_ = @import("behavior/pointers.zig");
|
||||
_ = @import("behavior/popcount.zig");
|
||||
|
||||
@ -59,18 +59,6 @@ fn foo(x: ?i32) ?bool {
|
||||
return value > 1234;
|
||||
}
|
||||
|
||||
test "null literal outside function" {
|
||||
const is_null = here_is_a_null_literal.context == null;
|
||||
try expect(is_null);
|
||||
|
||||
const is_non_null = here_is_a_null_literal.context != null;
|
||||
try expect(!is_non_null);
|
||||
}
|
||||
const SillyStruct = struct {
|
||||
context: ?i32,
|
||||
};
|
||||
const here_is_a_null_literal = SillyStruct{ .context = null };
|
||||
|
||||
test "test null runtime" {
|
||||
try testTestNullRuntime(null);
|
||||
}
|
||||
@ -97,23 +85,23 @@ fn bar(x: ?void) ?void {
|
||||
}
|
||||
}
|
||||
|
||||
const StructWithOptional = struct {
|
||||
field: ?i32,
|
||||
};
|
||||
const Empty = struct {};
|
||||
|
||||
var struct_with_optional: StructWithOptional = undefined;
|
||||
test "optional struct{}" {
|
||||
_ = try optionalEmptyStructImpl();
|
||||
_ = comptime try optionalEmptyStructImpl();
|
||||
}
|
||||
|
||||
test "unwrap optional which is field of global var" {
|
||||
struct_with_optional.field = null;
|
||||
if (struct_with_optional.field) |payload| {
|
||||
_ = payload;
|
||||
unreachable;
|
||||
}
|
||||
struct_with_optional.field = 1234;
|
||||
if (struct_with_optional.field) |payload| {
|
||||
try expect(payload == 1234);
|
||||
fn optionalEmptyStructImpl() !void {
|
||||
try expect(baz(null) == null);
|
||||
try expect(baz(Empty{}) != null);
|
||||
}
|
||||
|
||||
fn baz(x: ?Empty) ?Empty {
|
||||
if (x) |_| {
|
||||
return Empty{};
|
||||
} else {
|
||||
unreachable;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
36
test/behavior/null_llvm.zig
Normal file
36
test/behavior/null_llvm.zig
Normal file
@ -0,0 +1,36 @@
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
|
||||
test "null literal outside function" {
|
||||
const is_null = here_is_a_null_literal.context == null;
|
||||
try expect(is_null);
|
||||
|
||||
const is_non_null = here_is_a_null_literal.context != null;
|
||||
try expect(!is_non_null);
|
||||
}
|
||||
|
||||
const SillyStruct = struct {
|
||||
context: ?i32,
|
||||
};
|
||||
|
||||
const here_is_a_null_literal = SillyStruct{ .context = null };
|
||||
|
||||
const StructWithOptional = struct {
|
||||
field: ?i32,
|
||||
};
|
||||
|
||||
var struct_with_optional: StructWithOptional = undefined;
|
||||
|
||||
test "unwrap optional which is field of global var" {
|
||||
struct_with_optional.field = null;
|
||||
if (struct_with_optional.field) |payload| {
|
||||
_ = payload;
|
||||
unreachable;
|
||||
}
|
||||
struct_with_optional.field = 1234;
|
||||
if (struct_with_optional.field) |payload| {
|
||||
try expect(payload == 1234);
|
||||
} else {
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user