mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
parent
c78dc5043b
commit
434f017aee
@ -397,7 +397,10 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
|
||||
buf_resize(&entry->name, 0);
|
||||
buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name));
|
||||
|
||||
if (child_type->id == TypeTableEntryIdPointer ||
|
||||
if (child_type->zero_bits) {
|
||||
entry->type_ref = LLVMInt1Type();
|
||||
entry->di_type = g->builtin_types.entry_bool->di_type;
|
||||
} else if (child_type->id == TypeTableEntryIdPointer ||
|
||||
child_type->id == TypeTableEntryIdFn)
|
||||
{
|
||||
// this is an optimization but also is necessary for calling C
|
||||
@ -2958,7 +2961,8 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
|
||||
assert(type_entry->data.enumeration.complete);
|
||||
return type_entry->data.enumeration.gen_field_count != 0;
|
||||
case TypeTableEntryIdMaybe:
|
||||
return type_entry->data.maybe.child_type->id != TypeTableEntryIdPointer &&
|
||||
return !type_entry->data.maybe.child_type->zero_bits &&
|
||||
type_entry->data.maybe.child_type->id != TypeTableEntryIdPointer &&
|
||||
type_entry->data.maybe.child_type->id != TypeTableEntryIdFn;
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
return handle_is_ptr(type_entry->data.type_decl.canonical_type);
|
||||
@ -3632,7 +3636,11 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
|
||||
case TypeTableEntryIdNullLit:
|
||||
zig_panic("TODO");
|
||||
case TypeTableEntryIdMaybe:
|
||||
zig_panic("TODO");
|
||||
if (a->data.x_maybe == nullptr || b->data.x_maybe == nullptr) {
|
||||
return (a->data.x_maybe == nullptr && b->data.x_maybe == nullptr);
|
||||
} else {
|
||||
return const_values_equal(a->data.x_maybe, b->data.x_maybe);
|
||||
}
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
zig_panic("TODO");
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
|
||||
@ -1755,12 +1755,16 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru
|
||||
static LLVMValueRef gen_non_null_bit(CodeGen *g, TypeTableEntry *maybe_type, LLVMValueRef maybe_handle) {
|
||||
assert(maybe_type->id == TypeTableEntryIdMaybe);
|
||||
TypeTableEntry *child_type = maybe_type->data.maybe.child_type;
|
||||
bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn);
|
||||
if (maybe_is_ptr) {
|
||||
return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), "");
|
||||
if (child_type->zero_bits) {
|
||||
return maybe_handle;
|
||||
} else {
|
||||
LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, "");
|
||||
return LLVMBuildLoad(g->builder, maybe_field_ptr, "");
|
||||
bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn);
|
||||
if (maybe_is_ptr) {
|
||||
return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), "");
|
||||
} else {
|
||||
LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, "");
|
||||
return LLVMBuildLoad(g->builder, maybe_field_ptr, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1779,7 +1783,6 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
|
||||
TypeTableEntry *maybe_type = ptr_type->data.pointer.child_type;
|
||||
assert(maybe_type->id == TypeTableEntryIdMaybe);
|
||||
TypeTableEntry *child_type = maybe_type->data.maybe.child_type;
|
||||
bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn);
|
||||
LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value);
|
||||
LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, is_volatile);
|
||||
if (ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on) {
|
||||
@ -1793,11 +1796,16 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, ok_block);
|
||||
}
|
||||
if (maybe_is_ptr) {
|
||||
return maybe_ptr;
|
||||
if (child_type->zero_bits) {
|
||||
return nullptr;
|
||||
} else {
|
||||
LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, is_volatile);
|
||||
return LLVMBuildStructGEP(g->builder, maybe_struct_ref, maybe_child_index, "");
|
||||
bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn);
|
||||
if (maybe_is_ptr) {
|
||||
return maybe_ptr;
|
||||
} else {
|
||||
LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, is_volatile);
|
||||
return LLVMBuildStructGEP(g->builder, maybe_struct_ref, maybe_child_index, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2319,6 +2327,10 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I
|
||||
|
||||
TypeTableEntry *child_type = wanted_type->data.maybe.child_type;
|
||||
|
||||
if (child_type->zero_bits) {
|
||||
return LLVMConstInt(LLVMInt1Type(), 1, false);
|
||||
}
|
||||
|
||||
LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
|
||||
if (child_type->id == TypeTableEntryIdPointer ||
|
||||
child_type->id == TypeTableEntryIdFn)
|
||||
@ -2806,7 +2818,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
|
||||
case TypeTableEntryIdMaybe:
|
||||
{
|
||||
TypeTableEntry *child_type = canon_type->data.maybe.child_type;
|
||||
if (child_type->id == TypeTableEntryIdPointer ||
|
||||
if (child_type->zero_bits) {
|
||||
return LLVMConstInt(LLVMInt1Type(), const_val->data.x_maybe ? 1 : 0, false);
|
||||
} else if (child_type->id == TypeTableEntryIdPointer ||
|
||||
child_type->id == TypeTableEntryIdFn)
|
||||
{
|
||||
if (const_val->data.x_maybe) {
|
||||
@ -4322,7 +4336,10 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {
|
||||
case TypeTableEntryIdMaybe:
|
||||
{
|
||||
TypeTableEntry *child_type = type_entry->data.maybe.child_type;
|
||||
if (child_type->id == TypeTableEntryIdPointer ||
|
||||
if (child_type->zero_bits) {
|
||||
buf_init_from_str(out_buf, "bool");
|
||||
return;
|
||||
} else if (child_type->id == TypeTableEntryIdPointer ||
|
||||
child_type->id == TypeTableEntryIdFn)
|
||||
{
|
||||
return get_c_type(g, child_type, out_buf);
|
||||
|
||||
@ -51,11 +51,21 @@ fn rhsMaybeUnwrapReturn() {
|
||||
fn maybeReturn() {
|
||||
@setFnTest(this);
|
||||
|
||||
maybeReturnImpl();
|
||||
comptime maybeReturnImpl();
|
||||
}
|
||||
|
||||
fn maybeReturnImpl() {
|
||||
assert(??foo(1235));
|
||||
assert(if (const _ ?= foo(null)) false else true);
|
||||
assert(!??foo(1234));
|
||||
}
|
||||
|
||||
fn foo(x: ?i32) -> ?bool {
|
||||
const value = ?return x;
|
||||
return value > 1234;
|
||||
}
|
||||
|
||||
|
||||
fn ifVarMaybePointer() {
|
||||
@setFnTest(this);
|
||||
@ -97,12 +107,6 @@ const here_is_a_null_literal = SillyStruct {
|
||||
};
|
||||
|
||||
|
||||
// TODO test static eval maybe return
|
||||
fn foo(x: ?i32) -> ?bool {
|
||||
const value = ?return x;
|
||||
return value > 1234;
|
||||
}
|
||||
|
||||
fn testNullRuntime() {
|
||||
@setFnTest(this);
|
||||
|
||||
@ -112,3 +116,23 @@ fn testTestNullRuntime(x: ?i32) {
|
||||
assert(x == null);
|
||||
assert(!(x != null));
|
||||
}
|
||||
|
||||
fn nullableVoid() {
|
||||
@setFnTest(this);
|
||||
|
||||
nullableVoidImpl();
|
||||
comptime nullableVoidImpl();
|
||||
}
|
||||
|
||||
fn nullableVoidImpl() {
|
||||
assert(bar(null) == null);
|
||||
assert(bar({}) != null);
|
||||
}
|
||||
|
||||
fn bar(x: ?void) -> ?void {
|
||||
if (const _ ?= x) {
|
||||
return {};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user