simple async function call working
parent
54e716afdc
commit
72e983670e
|
@ -426,7 +426,6 @@ set(ZIG_MAIN_SRC "${CMAKE_SOURCE_DIR}/src/main.cpp")
|
||||||
set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/userland.cpp")
|
set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/userland.cpp")
|
||||||
|
|
||||||
set(ZIG_SOURCES
|
set(ZIG_SOURCES
|
||||||
"${CMAKE_SOURCE_DIR}/src/glibc.cpp"
|
|
||||||
"${CMAKE_SOURCE_DIR}/src/analyze.cpp"
|
"${CMAKE_SOURCE_DIR}/src/analyze.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/src/ast_render.cpp"
|
"${CMAKE_SOURCE_DIR}/src/ast_render.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/src/bigfloat.cpp"
|
"${CMAKE_SOURCE_DIR}/src/bigfloat.cpp"
|
||||||
|
@ -438,6 +437,7 @@ set(ZIG_SOURCES
|
||||||
"${CMAKE_SOURCE_DIR}/src/compiler.cpp"
|
"${CMAKE_SOURCE_DIR}/src/compiler.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/src/errmsg.cpp"
|
"${CMAKE_SOURCE_DIR}/src/errmsg.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/src/error.cpp"
|
"${CMAKE_SOURCE_DIR}/src/error.cpp"
|
||||||
|
"${CMAKE_SOURCE_DIR}/src/glibc.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/src/ir.cpp"
|
"${CMAKE_SOURCE_DIR}/src/ir.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/src/ir_print.cpp"
|
"${CMAKE_SOURCE_DIR}/src/ir_print.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/src/libc_installation.cpp"
|
"${CMAKE_SOURCE_DIR}/src/libc_installation.cpp"
|
||||||
|
|
|
@ -1251,6 +1251,7 @@ enum ZigTypeId {
|
||||||
ZigTypeIdBoundFn,
|
ZigTypeIdBoundFn,
|
||||||
ZigTypeIdArgTuple,
|
ZigTypeIdArgTuple,
|
||||||
ZigTypeIdOpaque,
|
ZigTypeIdOpaque,
|
||||||
|
ZigTypeIdCoroFrame,
|
||||||
ZigTypeIdVector,
|
ZigTypeIdVector,
|
||||||
ZigTypeIdEnumLiteral,
|
ZigTypeIdEnumLiteral,
|
||||||
};
|
};
|
||||||
|
@ -1265,6 +1266,11 @@ struct ZigTypeOpaque {
|
||||||
Buf *bare_name;
|
Buf *bare_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ZigTypeCoroFrame {
|
||||||
|
ZigFn *fn;
|
||||||
|
ZigType *locals_struct;
|
||||||
|
};
|
||||||
|
|
||||||
struct ZigType {
|
struct ZigType {
|
||||||
ZigTypeId id;
|
ZigTypeId id;
|
||||||
Buf name;
|
Buf name;
|
||||||
|
@ -1290,6 +1296,7 @@ struct ZigType {
|
||||||
ZigTypeBoundFn bound_fn;
|
ZigTypeBoundFn bound_fn;
|
||||||
ZigTypeVector vector;
|
ZigTypeVector vector;
|
||||||
ZigTypeOpaque opaque;
|
ZigTypeOpaque opaque;
|
||||||
|
ZigTypeCoroFrame frame;
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
// use these fields to make sure we don't duplicate type table entries for the same type
|
// use these fields to make sure we don't duplicate type table entries for the same type
|
||||||
|
@ -1340,6 +1347,7 @@ struct ZigFn {
|
||||||
ScopeBlock *def_scope; // parent is child_scope
|
ScopeBlock *def_scope; // parent is child_scope
|
||||||
Buf symbol_name;
|
Buf symbol_name;
|
||||||
ZigType *type_entry; // function type
|
ZigType *type_entry; // function type
|
||||||
|
ZigType *frame_type; // coro frame type
|
||||||
// in the case of normal functions this is the implicit return type
|
// in the case of normal functions this is the implicit return type
|
||||||
// in the case of async functions this is the implicit return type according to the
|
// in the case of async functions this is the implicit return type according to the
|
||||||
// zig source code, not according to zig ir
|
// zig source code, not according to zig ir
|
||||||
|
@ -1356,6 +1364,7 @@ struct ZigFn {
|
||||||
|
|
||||||
ZigList<IrInstructionAllocaGen *> alloca_gen_list;
|
ZigList<IrInstructionAllocaGen *> alloca_gen_list;
|
||||||
ZigList<ZigVar *> variable_list;
|
ZigList<ZigVar *> variable_list;
|
||||||
|
ZigList<IrBasicBlock *> resume_blocks;
|
||||||
|
|
||||||
Buf *section_name;
|
Buf *section_name;
|
||||||
AstNode *set_alignstack_node;
|
AstNode *set_alignstack_node;
|
||||||
|
@ -1365,6 +1374,7 @@ struct ZigFn {
|
||||||
ZigList<GlobalExport> export_list;
|
ZigList<GlobalExport> export_list;
|
||||||
|
|
||||||
LLVMValueRef valgrind_client_request_array;
|
LLVMValueRef valgrind_client_request_array;
|
||||||
|
LLVMBasicBlockRef preamble_llvm_block;
|
||||||
|
|
||||||
FnInline fn_inline;
|
FnInline fn_inline;
|
||||||
FnAnalState anal_state;
|
FnAnalState anal_state;
|
||||||
|
@ -1512,6 +1522,7 @@ enum PanicMsgId {
|
||||||
PanicMsgIdBadEnumValue,
|
PanicMsgIdBadEnumValue,
|
||||||
PanicMsgIdFloatToInt,
|
PanicMsgIdFloatToInt,
|
||||||
PanicMsgIdPtrCastNull,
|
PanicMsgIdPtrCastNull,
|
||||||
|
PanicMsgIdBadResume,
|
||||||
|
|
||||||
PanicMsgIdCount,
|
PanicMsgIdCount,
|
||||||
};
|
};
|
||||||
|
@ -1755,6 +1766,7 @@ struct CodeGen {
|
||||||
ZigType *entry_global_error_set;
|
ZigType *entry_global_error_set;
|
||||||
ZigType *entry_arg_tuple;
|
ZigType *entry_arg_tuple;
|
||||||
ZigType *entry_enum_literal;
|
ZigType *entry_enum_literal;
|
||||||
|
ZigType *entry_frame_header;
|
||||||
} builtin_types;
|
} builtin_types;
|
||||||
ZigType *align_amt_type;
|
ZigType *align_amt_type;
|
||||||
ZigType *stack_trace_type;
|
ZigType *stack_trace_type;
|
||||||
|
@ -2119,6 +2131,8 @@ struct IrBasicBlock {
|
||||||
size_t ref_count;
|
size_t ref_count;
|
||||||
// index into the basic block list
|
// index into the basic block list
|
||||||
size_t index;
|
size_t index;
|
||||||
|
// for coroutines, the resume_index which corresponds to this block
|
||||||
|
size_t resume_index;
|
||||||
LLVMBasicBlockRef llvm_block;
|
LLVMBasicBlockRef llvm_block;
|
||||||
LLVMBasicBlockRef llvm_exit_block;
|
LLVMBasicBlockRef llvm_exit_block;
|
||||||
// The instruction that referenced this basic block and caused us to
|
// The instruction that referenced this basic block and caused us to
|
||||||
|
@ -2297,6 +2311,8 @@ enum IrInstructionId {
|
||||||
IrInstructionIdEndExpr,
|
IrInstructionIdEndExpr,
|
||||||
IrInstructionIdPtrOfArrayToSlice,
|
IrInstructionIdPtrOfArrayToSlice,
|
||||||
IrInstructionIdUnionInitNamedField,
|
IrInstructionIdUnionInitNamedField,
|
||||||
|
IrInstructionIdSuspendBegin,
|
||||||
|
IrInstructionIdSuspendBr,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IrInstruction {
|
struct IrInstruction {
|
||||||
|
@ -3511,6 +3527,18 @@ struct IrInstructionPtrOfArrayToSlice {
|
||||||
IrInstruction *result_loc;
|
IrInstruction *result_loc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct IrInstructionSuspendBegin {
|
||||||
|
IrInstruction base;
|
||||||
|
|
||||||
|
IrBasicBlock *resume_block;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IrInstructionSuspendBr {
|
||||||
|
IrInstruction base;
|
||||||
|
|
||||||
|
IrBasicBlock *resume_block;
|
||||||
|
};
|
||||||
|
|
||||||
enum ResultLocId {
|
enum ResultLocId {
|
||||||
ResultLocIdInvalid,
|
ResultLocIdInvalid,
|
||||||
ResultLocIdNone,
|
ResultLocIdNone,
|
||||||
|
@ -3593,6 +3621,8 @@ static const size_t maybe_null_index = 1;
|
||||||
static const size_t err_union_err_index = 0;
|
static const size_t err_union_err_index = 0;
|
||||||
static const size_t err_union_payload_index = 1;
|
static const size_t err_union_payload_index = 1;
|
||||||
|
|
||||||
|
static const size_t coro_resume_index_index = 0;
|
||||||
|
|
||||||
// TODO call graph analysis to find out what this number needs to be for every function
|
// TODO call graph analysis to find out what this number needs to be for every function
|
||||||
// MUST BE A POWER OF TWO.
|
// MUST BE A POWER OF TWO.
|
||||||
static const size_t stack_trace_ptr_count = 32;
|
static const size_t stack_trace_ptr_count = 32;
|
||||||
|
|
137
src/analyze.cpp
137
src/analyze.cpp
|
@ -228,6 +228,8 @@ AstNode *type_decl_node(ZigType *type_entry) {
|
||||||
return type_entry->data.enumeration.decl_node;
|
return type_entry->data.enumeration.decl_node;
|
||||||
case ZigTypeIdUnion:
|
case ZigTypeIdUnion:
|
||||||
return type_entry->data.unionation.decl_node;
|
return type_entry->data.unionation.decl_node;
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
|
return type_entry->data.frame.fn->proto_node;
|
||||||
case ZigTypeIdOpaque:
|
case ZigTypeIdOpaque:
|
||||||
case ZigTypeIdMetaType:
|
case ZigTypeIdMetaType:
|
||||||
case ZigTypeIdVoid:
|
case ZigTypeIdVoid:
|
||||||
|
@ -262,6 +264,20 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
|
||||||
return type_entry->data.structure.resolve_status >= status;
|
return type_entry->data.structure.resolve_status >= status;
|
||||||
case ZigTypeIdUnion:
|
case ZigTypeIdUnion:
|
||||||
return type_entry->data.unionation.resolve_status >= status;
|
return type_entry->data.unionation.resolve_status >= status;
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
|
switch (status) {
|
||||||
|
case ResolveStatusInvalid:
|
||||||
|
zig_unreachable();
|
||||||
|
case ResolveStatusUnstarted:
|
||||||
|
case ResolveStatusZeroBitsKnown:
|
||||||
|
return true;
|
||||||
|
case ResolveStatusAlignmentKnown:
|
||||||
|
case ResolveStatusSizeKnown:
|
||||||
|
return type_entry->data.frame.locals_struct != nullptr;
|
||||||
|
case ResolveStatusLLVMFwdDecl:
|
||||||
|
case ResolveStatusLLVMFull:
|
||||||
|
return type_entry->llvm_type != nullptr;
|
||||||
|
}
|
||||||
case ZigTypeIdEnum:
|
case ZigTypeIdEnum:
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case ResolveStatusUnstarted:
|
case ResolveStatusUnstarted:
|
||||||
|
@ -345,6 +361,25 @@ static const char *ptr_len_to_star_str(PtrLen ptr_len) {
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigType *get_coro_frame_type(CodeGen *g, ZigFn *fn) {
|
||||||
|
if (fn->frame_type != nullptr) {
|
||||||
|
return fn->frame_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigType *entry = new_type_table_entry(ZigTypeIdCoroFrame);
|
||||||
|
buf_resize(&entry->name, 0);
|
||||||
|
buf_appendf(&entry->name, "@Frame(%s)", buf_ptr(&fn->symbol_name));
|
||||||
|
|
||||||
|
entry->data.frame.fn = fn;
|
||||||
|
|
||||||
|
// Coroutine frames are always non-zero bits because they always have a resume index.
|
||||||
|
entry->abi_size = SIZE_MAX;
|
||||||
|
entry->size_in_bits = SIZE_MAX;
|
||||||
|
|
||||||
|
fn->frame_type = entry;
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
|
ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
|
||||||
bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
|
bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
|
||||||
uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero)
|
uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero)
|
||||||
|
@ -1039,6 +1074,7 @@ static Error emit_error_unless_type_allowed_in_packed_struct(CodeGen *g, ZigType
|
||||||
case ZigTypeIdBoundFn:
|
case ZigTypeIdBoundFn:
|
||||||
case ZigTypeIdArgTuple:
|
case ZigTypeIdArgTuple:
|
||||||
case ZigTypeIdOpaque:
|
case ZigTypeIdOpaque:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
add_node_error(g, source_node,
|
add_node_error(g, source_node,
|
||||||
buf_sprintf("type '%s' not allowed in packed struct; no guaranteed in-memory representation",
|
buf_sprintf("type '%s' not allowed in packed struct; no guaranteed in-memory representation",
|
||||||
buf_ptr(&type_entry->name)));
|
buf_ptr(&type_entry->name)));
|
||||||
|
@ -1127,6 +1163,7 @@ bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
|
||||||
case ZigTypeIdBoundFn:
|
case ZigTypeIdBoundFn:
|
||||||
case ZigTypeIdArgTuple:
|
case ZigTypeIdArgTuple:
|
||||||
case ZigTypeIdVoid:
|
case ZigTypeIdVoid:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
return false;
|
return false;
|
||||||
case ZigTypeIdOpaque:
|
case ZigTypeIdOpaque:
|
||||||
case ZigTypeIdUnreachable:
|
case ZigTypeIdUnreachable:
|
||||||
|
@ -1297,6 +1334,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
|
||||||
case ZigTypeIdUnion:
|
case ZigTypeIdUnion:
|
||||||
case ZigTypeIdFn:
|
case ZigTypeIdFn:
|
||||||
case ZigTypeIdVector:
|
case ZigTypeIdVector:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
switch (type_requires_comptime(g, type_entry)) {
|
switch (type_requires_comptime(g, type_entry)) {
|
||||||
case ReqCompTimeNo:
|
case ReqCompTimeNo:
|
||||||
break;
|
break;
|
||||||
|
@ -1392,6 +1430,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
|
||||||
case ZigTypeIdUnion:
|
case ZigTypeIdUnion:
|
||||||
case ZigTypeIdFn:
|
case ZigTypeIdFn:
|
||||||
case ZigTypeIdVector:
|
case ZigTypeIdVector:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
switch (type_requires_comptime(g, fn_type_id.return_type)) {
|
switch (type_requires_comptime(g, fn_type_id.return_type)) {
|
||||||
case ReqCompTimeInvalid:
|
case ReqCompTimeInvalid:
|
||||||
return g->builtin_types.entry_invalid;
|
return g->builtin_types.entry_invalid;
|
||||||
|
@ -1825,6 +1864,39 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
|
||||||
return ErrorNone;
|
return ErrorNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {
|
||||||
|
assert(frame_type->data.frame.locals_struct == nullptr);
|
||||||
|
|
||||||
|
ZigFn *fn = frame_type->data.frame.fn;
|
||||||
|
switch (fn->anal_state) {
|
||||||
|
case FnAnalStateInvalid:
|
||||||
|
return ErrorSemanticAnalyzeFail;
|
||||||
|
case FnAnalStateComplete:
|
||||||
|
break;
|
||||||
|
case FnAnalStateReady:
|
||||||
|
analyze_fn_body(g, fn);
|
||||||
|
if (fn->anal_state == FnAnalStateInvalid)
|
||||||
|
return ErrorSemanticAnalyzeFail;
|
||||||
|
break;
|
||||||
|
case FnAnalStateProbing:
|
||||||
|
add_node_error(g, fn->proto_node,
|
||||||
|
buf_sprintf("cannot resolve '%s': function not fully analyzed yet",
|
||||||
|
buf_ptr(&frame_type->name)));
|
||||||
|
return ErrorSemanticAnalyzeFail;
|
||||||
|
}
|
||||||
|
// TODO iterate over fn->alloca_gen_list
|
||||||
|
ZigList<ZigType *> field_types = {};
|
||||||
|
ZigList<const char *> field_names = {};
|
||||||
|
|
||||||
|
field_names.append("resume_index");
|
||||||
|
field_types.append(g->builtin_types.entry_usize);
|
||||||
|
|
||||||
|
assert(field_names.length == field_types.length);
|
||||||
|
frame_type->data.frame.locals_struct = get_struct_type(g, buf_ptr(&frame_type->name),
|
||||||
|
field_names.items, field_types.items, field_names.length);
|
||||||
|
return ErrorNone;
|
||||||
|
}
|
||||||
|
|
||||||
static bool type_is_valid_extern_enum_tag(CodeGen *g, ZigType *ty) {
|
static bool type_is_valid_extern_enum_tag(CodeGen *g, ZigType *ty) {
|
||||||
// Only integer types are allowed by the C ABI
|
// Only integer types are allowed by the C ABI
|
||||||
if(ty->id != ZigTypeIdInt)
|
if(ty->id != ZigTypeIdInt)
|
||||||
|
@ -2997,6 +3069,7 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
|
||||||
case ZigTypeIdFn:
|
case ZigTypeIdFn:
|
||||||
case ZigTypeIdBoundFn:
|
case ZigTypeIdBoundFn:
|
||||||
case ZigTypeIdVector:
|
case ZigTypeIdVector:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
return type_entry;
|
return type_entry;
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
|
@ -3496,6 +3569,7 @@ bool is_container(ZigType *type_entry) {
|
||||||
case ZigTypeIdArgTuple:
|
case ZigTypeIdArgTuple:
|
||||||
case ZigTypeIdOpaque:
|
case ZigTypeIdOpaque:
|
||||||
case ZigTypeIdVector:
|
case ZigTypeIdVector:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
|
@ -3552,6 +3626,7 @@ Error resolve_container_type(CodeGen *g, ZigType *type_entry) {
|
||||||
case ZigTypeIdArgTuple:
|
case ZigTypeIdArgTuple:
|
||||||
case ZigTypeIdOpaque:
|
case ZigTypeIdOpaque:
|
||||||
case ZigTypeIdVector:
|
case ZigTypeIdVector:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
|
@ -4002,6 +4077,7 @@ bool handle_is_ptr(ZigType *type_entry) {
|
||||||
return false;
|
return false;
|
||||||
case ZigTypeIdArray:
|
case ZigTypeIdArray:
|
||||||
case ZigTypeIdStruct:
|
case ZigTypeIdStruct:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
return type_has_bits(type_entry);
|
return type_has_bits(type_entry);
|
||||||
case ZigTypeIdErrorUnion:
|
case ZigTypeIdErrorUnion:
|
||||||
return type_has_bits(type_entry->data.error_union.payload_type);
|
return type_has_bits(type_entry->data.error_union.payload_type);
|
||||||
|
@ -4246,6 +4322,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
|
||||||
case ZigTypeIdVector:
|
case ZigTypeIdVector:
|
||||||
// TODO better hashing algorithm
|
// TODO better hashing algorithm
|
||||||
return 3647867726;
|
return 3647867726;
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
|
// TODO better hashing algorithm
|
||||||
|
return 675741936;
|
||||||
case ZigTypeIdBoundFn:
|
case ZigTypeIdBoundFn:
|
||||||
case ZigTypeIdInvalid:
|
case ZigTypeIdInvalid:
|
||||||
case ZigTypeIdUnreachable:
|
case ZigTypeIdUnreachable:
|
||||||
|
@ -4310,6 +4389,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
|
||||||
case ZigTypeIdOpaque:
|
case ZigTypeIdOpaque:
|
||||||
case ZigTypeIdErrorSet:
|
case ZigTypeIdErrorSet:
|
||||||
case ZigTypeIdEnum:
|
case ZigTypeIdEnum:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case ZigTypeIdPointer:
|
case ZigTypeIdPointer:
|
||||||
|
@ -4381,6 +4461,7 @@ static bool return_type_is_cacheable(ZigType *return_type) {
|
||||||
case ZigTypeIdEnum:
|
case ZigTypeIdEnum:
|
||||||
case ZigTypeIdPointer:
|
case ZigTypeIdPointer:
|
||||||
case ZigTypeIdVector:
|
case ZigTypeIdVector:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case ZigTypeIdArray:
|
case ZigTypeIdArray:
|
||||||
|
@ -4512,6 +4593,7 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
|
||||||
case ZigTypeIdBool:
|
case ZigTypeIdBool:
|
||||||
case ZigTypeIdFloat:
|
case ZigTypeIdFloat:
|
||||||
case ZigTypeIdErrorUnion:
|
case ZigTypeIdErrorUnion:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
return OnePossibleValueNo;
|
return OnePossibleValueNo;
|
||||||
case ZigTypeIdUndefined:
|
case ZigTypeIdUndefined:
|
||||||
case ZigTypeIdNull:
|
case ZigTypeIdNull:
|
||||||
|
@ -4599,6 +4681,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
|
||||||
case ZigTypeIdFloat:
|
case ZigTypeIdFloat:
|
||||||
case ZigTypeIdVoid:
|
case ZigTypeIdVoid:
|
||||||
case ZigTypeIdUnreachable:
|
case ZigTypeIdUnreachable:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
return ReqCompTimeNo;
|
return ReqCompTimeNo;
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
|
@ -4941,6 +5024,8 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
|
||||||
return resolve_enum_zero_bits(g, ty);
|
return resolve_enum_zero_bits(g, ty);
|
||||||
} else if (ty->id == ZigTypeIdUnion) {
|
} else if (ty->id == ZigTypeIdUnion) {
|
||||||
return resolve_union_alignment(g, ty);
|
return resolve_union_alignment(g, ty);
|
||||||
|
} else if (ty->id == ZigTypeIdCoroFrame) {
|
||||||
|
return resolve_coro_frame(g, ty);
|
||||||
}
|
}
|
||||||
return ErrorNone;
|
return ErrorNone;
|
||||||
case ResolveStatusSizeKnown:
|
case ResolveStatusSizeKnown:
|
||||||
|
@ -4950,6 +5035,8 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
|
||||||
return resolve_enum_zero_bits(g, ty);
|
return resolve_enum_zero_bits(g, ty);
|
||||||
} else if (ty->id == ZigTypeIdUnion) {
|
} else if (ty->id == ZigTypeIdUnion) {
|
||||||
return resolve_union_type(g, ty);
|
return resolve_union_type(g, ty);
|
||||||
|
} else if (ty->id == ZigTypeIdCoroFrame) {
|
||||||
|
return resolve_coro_frame(g, ty);
|
||||||
}
|
}
|
||||||
return ErrorNone;
|
return ErrorNone;
|
||||||
case ResolveStatusLLVMFwdDecl:
|
case ResolveStatusLLVMFwdDecl:
|
||||||
|
@ -5144,6 +5231,8 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
|
zig_panic("TODO");
|
||||||
case ZigTypeIdUndefined:
|
case ZigTypeIdUndefined:
|
||||||
zig_panic("TODO");
|
zig_panic("TODO");
|
||||||
case ZigTypeIdNull:
|
case ZigTypeIdNull:
|
||||||
|
@ -5496,6 +5585,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
|
||||||
buf_appendf(buf, "(args value)");
|
buf_appendf(buf, "(args value)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
|
buf_appendf(buf, "(TODO: coroutine frame value)");
|
||||||
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
@ -5542,6 +5635,7 @@ uint32_t type_id_hash(TypeId x) {
|
||||||
case ZigTypeIdFn:
|
case ZigTypeIdFn:
|
||||||
case ZigTypeIdBoundFn:
|
case ZigTypeIdBoundFn:
|
||||||
case ZigTypeIdArgTuple:
|
case ZigTypeIdArgTuple:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
case ZigTypeIdErrorUnion:
|
case ZigTypeIdErrorUnion:
|
||||||
return hash_ptr(x.data.error_union.err_set_type) ^ hash_ptr(x.data.error_union.payload_type);
|
return hash_ptr(x.data.error_union.err_set_type) ^ hash_ptr(x.data.error_union.payload_type);
|
||||||
|
@ -5590,6 +5684,7 @@ bool type_id_eql(TypeId a, TypeId b) {
|
||||||
case ZigTypeIdBoundFn:
|
case ZigTypeIdBoundFn:
|
||||||
case ZigTypeIdArgTuple:
|
case ZigTypeIdArgTuple:
|
||||||
case ZigTypeIdOpaque:
|
case ZigTypeIdOpaque:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
case ZigTypeIdErrorUnion:
|
case ZigTypeIdErrorUnion:
|
||||||
return a.data.error_union.err_set_type == b.data.error_union.err_set_type &&
|
return a.data.error_union.err_set_type == b.data.error_union.err_set_type &&
|
||||||
|
@ -5818,10 +5913,12 @@ size_t type_id_index(ZigType *entry) {
|
||||||
return 20;
|
return 20;
|
||||||
case ZigTypeIdOpaque:
|
case ZigTypeIdOpaque:
|
||||||
return 21;
|
return 21;
|
||||||
case ZigTypeIdVector:
|
case ZigTypeIdCoroFrame:
|
||||||
return 22;
|
return 22;
|
||||||
case ZigTypeIdEnumLiteral:
|
case ZigTypeIdVector:
|
||||||
return 23;
|
return 23;
|
||||||
|
case ZigTypeIdEnumLiteral:
|
||||||
|
return 24;
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
@ -5878,6 +5975,8 @@ const char *type_id_name(ZigTypeId id) {
|
||||||
return "Opaque";
|
return "Opaque";
|
||||||
case ZigTypeIdVector:
|
case ZigTypeIdVector:
|
||||||
return "Vector";
|
return "Vector";
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
|
return "Frame";
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
@ -5947,7 +6046,7 @@ bool type_can_fail(ZigType *type_entry) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fn_type_can_fail(FnTypeId *fn_type_id) {
|
bool fn_type_can_fail(FnTypeId *fn_type_id) {
|
||||||
return type_can_fail(fn_type_id->return_type) || fn_type_id->cc == CallingConventionAsync;
|
return type_can_fail(fn_type_id->return_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrorNone - result pointer has the type
|
// ErrorNone - result pointer has the type
|
||||||
|
@ -6935,12 +7034,12 @@ static void resolve_llvm_types_array(CodeGen *g, ZigType *type) {
|
||||||
debug_align_in_bits, get_llvm_di_type(g, elem_type), (int)type->data.array.len);
|
debug_align_in_bits, get_llvm_di_type(g, elem_type), (int)type->data.array.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type) {
|
void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type, ZigFn *fn) {
|
||||||
if (fn_type->llvm_di_type != nullptr) return;
|
if (fn_type->llvm_di_type != nullptr) return;
|
||||||
|
|
||||||
FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
|
FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
|
||||||
bool first_arg_return = want_first_arg_sret(g, fn_type_id);
|
bool first_arg_return = want_first_arg_sret(g, fn_type_id);
|
||||||
bool is_async = fn_type_id->cc == CallingConventionAsync;
|
bool is_async = fn_type_id->cc == CallingConventionAsync || (fn != nullptr && fn->resume_blocks.length != 0);
|
||||||
bool is_c_abi = fn_type_id->cc == CallingConventionC;
|
bool is_c_abi = fn_type_id->cc == CallingConventionC;
|
||||||
bool prefix_arg_error_return_trace = g->have_err_ret_tracing && fn_type_can_fail(fn_type_id);
|
bool prefix_arg_error_return_trace = g->have_err_ret_tracing && fn_type_can_fail(fn_type_id);
|
||||||
// +1 for maybe making the first argument the return value
|
// +1 for maybe making the first argument the return value
|
||||||
|
@ -6955,7 +7054,7 @@ static void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type) {
|
||||||
param_di_types.append(get_llvm_di_type(g, fn_type_id->return_type));
|
param_di_types.append(get_llvm_di_type(g, fn_type_id->return_type));
|
||||||
ZigType *gen_return_type;
|
ZigType *gen_return_type;
|
||||||
if (is_async) {
|
if (is_async) {
|
||||||
gen_return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, false);
|
gen_return_type = g->builtin_types.entry_usize;
|
||||||
} else if (!type_has_bits(fn_type_id->return_type)) {
|
} else if (!type_has_bits(fn_type_id->return_type)) {
|
||||||
gen_return_type = g->builtin_types.entry_void;
|
gen_return_type = g->builtin_types.entry_void;
|
||||||
} else if (first_arg_return) {
|
} else if (first_arg_return) {
|
||||||
|
@ -6974,13 +7073,10 @@ static void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type) {
|
||||||
param_di_types.append(get_llvm_di_type(g, gen_type));
|
param_di_types.append(get_llvm_di_type(g, gen_type));
|
||||||
}
|
}
|
||||||
if (is_async) {
|
if (is_async) {
|
||||||
// coroutine frame pointer
|
ZigType *frame_type = (fn == nullptr) ? g->builtin_types.entry_frame_header : get_coro_frame_type(g, fn);
|
||||||
// TODO if we can make this typed a little more it will be better for
|
ZigType *ptr_type = get_pointer_to_type(g, frame_type, false);
|
||||||
// debug symbols.
|
gen_param_types.append(get_llvm_type(g, ptr_type));
|
||||||
// TODO do we need to make this aligned more?
|
param_di_types.append(get_llvm_di_type(g, ptr_type));
|
||||||
ZigType *void_star = get_pointer_to_type(g, g->builtin_types.entry_c_void, false);
|
|
||||||
gen_param_types.append(get_llvm_type(g, void_star));
|
|
||||||
param_di_types.append(get_llvm_di_type(g, void_star));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn_type->data.fn.gen_param_info = allocate<FnGenParamInfo>(fn_type_id->param_count);
|
fn_type->data.fn.gen_param_info = allocate<FnGenParamInfo>(fn_type_id->param_count);
|
||||||
|
@ -7055,6 +7151,17 @@ static void resolve_llvm_types_anyerror(CodeGen *g) {
|
||||||
get_llvm_di_type(g, g->err_tag_type), "");
|
get_llvm_di_type(g, g->err_tag_type), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void resolve_llvm_types_coro_frame(CodeGen *g, ZigType *frame_type, ResolveStatus wanted_resolve_status) {
|
||||||
|
if (frame_type->llvm_di_type != nullptr) return;
|
||||||
|
|
||||||
|
resolve_llvm_types_struct(g, frame_type->data.frame.locals_struct, wanted_resolve_status);
|
||||||
|
frame_type->llvm_type = frame_type->data.frame.locals_struct->llvm_type;
|
||||||
|
frame_type->llvm_di_type = frame_type->data.frame.locals_struct->llvm_di_type;
|
||||||
|
frame_type->abi_size = frame_type->data.frame.locals_struct->abi_size;
|
||||||
|
frame_type->abi_align = frame_type->data.frame.locals_struct->abi_align;
|
||||||
|
frame_type->size_in_bits = frame_type->data.frame.locals_struct->size_in_bits;
|
||||||
|
}
|
||||||
|
|
||||||
static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {
|
static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {
|
||||||
assert(type->id == ZigTypeIdOpaque || type_is_resolved(type, ResolveStatusSizeKnown));
|
assert(type->id == ZigTypeIdOpaque || type_is_resolved(type, ResolveStatusSizeKnown));
|
||||||
assert(wanted_resolve_status > ResolveStatusSizeKnown);
|
assert(wanted_resolve_status > ResolveStatusSizeKnown);
|
||||||
|
@ -7096,7 +7203,7 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r
|
||||||
case ZigTypeIdArray:
|
case ZigTypeIdArray:
|
||||||
return resolve_llvm_types_array(g, type);
|
return resolve_llvm_types_array(g, type);
|
||||||
case ZigTypeIdFn:
|
case ZigTypeIdFn:
|
||||||
return resolve_llvm_types_fn(g, type);
|
return resolve_llvm_types_fn(g, type, nullptr);
|
||||||
case ZigTypeIdErrorSet: {
|
case ZigTypeIdErrorSet: {
|
||||||
if (type->llvm_di_type != nullptr) return;
|
if (type->llvm_di_type != nullptr) return;
|
||||||
|
|
||||||
|
@ -7115,6 +7222,8 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r
|
||||||
type->abi_align, get_llvm_di_type(g, type->data.vector.elem_type), type->data.vector.len);
|
type->abi_align, get_llvm_di_type(g, type->data.vector.elem_type), type->data.vector.len);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
|
return resolve_llvm_types_coro_frame(g, type, wanted_resolve_status);
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg);
|
||||||
ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg);
|
ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg);
|
||||||
void emit_error_notes_for_ref_stack(CodeGen *g, ErrorMsg *msg);
|
void emit_error_notes_for_ref_stack(CodeGen *g, ErrorMsg *msg);
|
||||||
ZigType *new_type_table_entry(ZigTypeId id);
|
ZigType *new_type_table_entry(ZigTypeId id);
|
||||||
|
ZigType *get_coro_frame_type(CodeGen *g, ZigFn *fn);
|
||||||
ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const);
|
ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const);
|
||||||
ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
|
ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
|
||||||
bool is_volatile, PtrLen ptr_len,
|
bool is_volatile, PtrLen ptr_len,
|
||||||
|
@ -247,4 +248,6 @@ void src_assert(bool ok, AstNode *source_node);
|
||||||
bool is_container(ZigType *type_entry);
|
bool is_container(ZigType *type_entry);
|
||||||
ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name);
|
ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name);
|
||||||
|
|
||||||
|
void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type, ZigFn *fn);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
141
src/codegen.cpp
141
src/codegen.cpp
|
@ -498,7 +498,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
|
||||||
|
|
||||||
ZigType *fn_type = fn_table_entry->type_entry;
|
ZigType *fn_type = fn_table_entry->type_entry;
|
||||||
// Make the raw_type_ref populated
|
// Make the raw_type_ref populated
|
||||||
(void)get_llvm_type(g, fn_type);
|
resolve_llvm_types_fn(g, fn_type, fn_table_entry);
|
||||||
LLVMTypeRef fn_llvm_type = fn_type->data.fn.raw_type_ref;
|
LLVMTypeRef fn_llvm_type = fn_type->data.fn.raw_type_ref;
|
||||||
if (fn_table_entry->body_node == nullptr) {
|
if (fn_table_entry->body_node == nullptr) {
|
||||||
LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name));
|
LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name));
|
||||||
|
@ -921,9 +921,8 @@ static bool ir_want_fast_math(CodeGen *g, IrInstruction *instruction) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ir_want_runtime_safety(CodeGen *g, IrInstruction *instruction) {
|
static bool ir_want_runtime_safety_scope(CodeGen *g, Scope *scope) {
|
||||||
// TODO memoize
|
// TODO memoize
|
||||||
Scope *scope = instruction->scope;
|
|
||||||
while (scope) {
|
while (scope) {
|
||||||
if (scope->id == ScopeIdBlock) {
|
if (scope->id == ScopeIdBlock) {
|
||||||
ScopeBlock *block_scope = (ScopeBlock *)scope;
|
ScopeBlock *block_scope = (ScopeBlock *)scope;
|
||||||
|
@ -941,6 +940,10 @@ static bool ir_want_runtime_safety(CodeGen *g, IrInstruction *instruction) {
|
||||||
g->build_mode != BuildModeSmallRelease);
|
g->build_mode != BuildModeSmallRelease);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ir_want_runtime_safety(CodeGen *g, IrInstruction *instruction) {
|
||||||
|
return ir_want_runtime_safety_scope(g, instruction->scope);
|
||||||
|
}
|
||||||
|
|
||||||
static Buf *panic_msg_buf(PanicMsgId msg_id) {
|
static Buf *panic_msg_buf(PanicMsgId msg_id) {
|
||||||
switch (msg_id) {
|
switch (msg_id) {
|
||||||
case PanicMsgIdCount:
|
case PanicMsgIdCount:
|
||||||
|
@ -981,6 +984,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
|
||||||
return buf_create_from_str("integer part of floating point value out of bounds");
|
return buf_create_from_str("integer part of floating point value out of bounds");
|
||||||
case PanicMsgIdPtrCastNull:
|
case PanicMsgIdPtrCastNull:
|
||||||
return buf_create_from_str("cast causes pointer to be null");
|
return buf_create_from_str("cast causes pointer to be null");
|
||||||
|
case PanicMsgIdBadResume:
|
||||||
|
return buf_create_from_str("invalid resume of async function");
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
@ -1027,14 +1032,18 @@ static void gen_safety_crash(CodeGen *g, PanicMsgId msg_id) {
|
||||||
gen_panic(g, get_panic_msg_ptr_val(g, msg_id), nullptr);
|
gen_panic(g, get_panic_msg_ptr_val(g, msg_id), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_assertion(CodeGen *g, PanicMsgId msg_id, IrInstruction *source_instruction) {
|
static void gen_assertion_scope(CodeGen *g, PanicMsgId msg_id, Scope *source_scope) {
|
||||||
if (ir_want_runtime_safety(g, source_instruction)) {
|
if (ir_want_runtime_safety_scope(g, source_scope)) {
|
||||||
gen_safety_crash(g, msg_id);
|
gen_safety_crash(g, msg_id);
|
||||||
} else {
|
} else {
|
||||||
LLVMBuildUnreachable(g->builder);
|
LLVMBuildUnreachable(g->builder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gen_assertion(CodeGen *g, PanicMsgId msg_id, IrInstruction *source_instruction) {
|
||||||
|
return gen_assertion_scope(g, msg_id, source_instruction->scope);
|
||||||
|
}
|
||||||
|
|
||||||
static LLVMValueRef get_stacksave_fn_val(CodeGen *g) {
|
static LLVMValueRef get_stacksave_fn_val(CodeGen *g) {
|
||||||
if (g->stacksave_fn_val)
|
if (g->stacksave_fn_val)
|
||||||
return g->stacksave_fn_val;
|
return g->stacksave_fn_val;
|
||||||
|
@ -2092,6 +2101,10 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut
|
||||||
}
|
}
|
||||||
|
|
||||||
static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
|
static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
|
||||||
|
if (g->cur_fn->resume_blocks.length != 0) {
|
||||||
|
LLVMBuildRet(g->builder, LLVMGetUndef(g->builtin_types.entry_usize->llvm_type));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) {
|
if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) {
|
||||||
if (return_instruction->value == nullptr) {
|
if (return_instruction->value == nullptr) {
|
||||||
LLVMBuildRetVoid(g->builder);
|
LLVMBuildRetVoid(g->builder);
|
||||||
|
@ -3375,8 +3388,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
|
||||||
static bool get_prefix_arg_err_ret_stack(CodeGen *g, FnTypeId *fn_type_id) {
|
static bool get_prefix_arg_err_ret_stack(CodeGen *g, FnTypeId *fn_type_id) {
|
||||||
return g->have_err_ret_tracing &&
|
return g->have_err_ret_tracing &&
|
||||||
(fn_type_id->return_type->id == ZigTypeIdErrorUnion ||
|
(fn_type_id->return_type->id == ZigTypeIdErrorUnion ||
|
||||||
fn_type_id->return_type->id == ZigTypeIdErrorSet ||
|
fn_type_id->return_type->id == ZigTypeIdErrorSet);
|
||||||
fn_type_id->cc == CallingConventionAsync);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static LLVMValueRef get_new_stack_addr(CodeGen *g, LLVMValueRef new_stack) {
|
static LLVMValueRef get_new_stack_addr(CodeGen *g, LLVMValueRef new_stack) {
|
||||||
|
@ -3440,14 +3452,22 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
|
||||||
bool is_var_args = fn_type_id->is_var_args;
|
bool is_var_args = fn_type_id->is_var_args;
|
||||||
ZigList<LLVMValueRef> gen_param_values = {};
|
ZigList<LLVMValueRef> gen_param_values = {};
|
||||||
LLVMValueRef result_loc = instruction->result_loc ? ir_llvm_value(g, instruction->result_loc) : nullptr;
|
LLVMValueRef result_loc = instruction->result_loc ? ir_llvm_value(g, instruction->result_loc) : nullptr;
|
||||||
if (first_arg_ret) {
|
|
||||||
gen_param_values.append(result_loc);
|
|
||||||
}
|
|
||||||
if (prefix_arg_err_ret_stack) {
|
|
||||||
gen_param_values.append(get_cur_err_ret_trace_val(g, instruction->base.scope));
|
|
||||||
}
|
|
||||||
if (instruction->is_async) {
|
if (instruction->is_async) {
|
||||||
zig_panic("TODO codegen async call");
|
assert(result_loc != nullptr);
|
||||||
|
assert(instruction->fn_entry != nullptr);
|
||||||
|
LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, result_loc, coro_resume_index_index, "");
|
||||||
|
LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->llvm_type);
|
||||||
|
LLVMBuildStore(g->builder, zero, resume_index_ptr);
|
||||||
|
|
||||||
|
if (prefix_arg_err_ret_stack) {
|
||||||
|
zig_panic("TODO");
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_param_values.append(result_loc);
|
||||||
|
} else if (first_arg_ret) {
|
||||||
|
gen_param_values.append(result_loc);
|
||||||
|
} else if (prefix_arg_err_ret_stack) {
|
||||||
|
gen_param_values.append(get_cur_err_ret_trace_val(g, instruction->base.scope));
|
||||||
}
|
}
|
||||||
FnWalk fn_walk = {};
|
FnWalk fn_walk = {};
|
||||||
fn_walk.id = FnWalkIdCall;
|
fn_walk.id = FnWalkIdCall;
|
||||||
|
@ -3489,9 +3509,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
|
||||||
|
|
||||||
|
|
||||||
if (instruction->is_async) {
|
if (instruction->is_async) {
|
||||||
LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_payload_index, "");
|
return nullptr;
|
||||||
LLVMBuildStore(g->builder, result, payload_ptr);
|
|
||||||
return result_loc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src_return_type->id == ZigTypeIdUnreachable) {
|
if (src_return_type->id == ZigTypeIdUnreachable) {
|
||||||
|
@ -4921,6 +4939,24 @@ static LLVMValueRef ir_render_assert_non_null(CodeGen *g, IrExecutable *executab
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LLVMValueRef ir_render_suspend_begin(CodeGen *g, IrExecutable *executable,
|
||||||
|
IrInstructionSuspendBegin *instruction)
|
||||||
|
{
|
||||||
|
LLVMValueRef locals_ptr = g->cur_ret_ptr;
|
||||||
|
LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, locals_ptr, coro_resume_index_index, "");
|
||||||
|
LLVMValueRef new_resume_index = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,
|
||||||
|
instruction->resume_block->resume_index, false);
|
||||||
|
LLVMBuildStore(g->builder, new_resume_index, resume_index_ptr);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LLVMValueRef ir_render_suspend_br(CodeGen *g, IrExecutable *executable,
|
||||||
|
IrInstructionSuspendBr *instruction)
|
||||||
|
{
|
||||||
|
LLVMBuildRet(g->builder, LLVMGetUndef(g->builtin_types.entry_usize->llvm_type));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
|
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
|
||||||
AstNode *source_node = instruction->source_node;
|
AstNode *source_node = instruction->source_node;
|
||||||
Scope *scope = instruction->scope;
|
Scope *scope = instruction->scope;
|
||||||
|
@ -5161,6 +5197,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||||
return ir_render_resize_slice(g, executable, (IrInstructionResizeSlice *)instruction);
|
return ir_render_resize_slice(g, executable, (IrInstructionResizeSlice *)instruction);
|
||||||
case IrInstructionIdPtrOfArrayToSlice:
|
case IrInstructionIdPtrOfArrayToSlice:
|
||||||
return ir_render_ptr_of_array_to_slice(g, executable, (IrInstructionPtrOfArrayToSlice *)instruction);
|
return ir_render_ptr_of_array_to_slice(g, executable, (IrInstructionPtrOfArrayToSlice *)instruction);
|
||||||
|
case IrInstructionIdSuspendBegin:
|
||||||
|
return ir_render_suspend_begin(g, executable, (IrInstructionSuspendBegin *)instruction);
|
||||||
|
case IrInstructionIdSuspendBr:
|
||||||
|
return ir_render_suspend_br(g, executable, (IrInstructionSuspendBr *)instruction);
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
@ -5422,7 +5462,8 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
|
zig_panic("TODO bit pack a coroutine frame");
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
@ -5943,7 +5984,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||||
case ZigTypeIdArgTuple:
|
case ZigTypeIdArgTuple:
|
||||||
case ZigTypeIdOpaque:
|
case ZigTypeIdOpaque:
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
|
zig_panic("TODO");
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
@ -6027,12 +6069,20 @@ static void generate_error_name_table(CodeGen *g) {
|
||||||
static void build_all_basic_blocks(CodeGen *g, ZigFn *fn) {
|
static void build_all_basic_blocks(CodeGen *g, ZigFn *fn) {
|
||||||
IrExecutable *executable = &fn->analyzed_executable;
|
IrExecutable *executable = &fn->analyzed_executable;
|
||||||
assert(executable->basic_block_list.length > 0);
|
assert(executable->basic_block_list.length > 0);
|
||||||
|
LLVMValueRef fn_val = fn_llvm_value(g, fn);
|
||||||
|
LLVMBasicBlockRef first_bb = nullptr;
|
||||||
|
if (fn->resume_blocks.length != 0) {
|
||||||
|
first_bb = LLVMAppendBasicBlock(fn_val, "AsyncSwitch");
|
||||||
|
fn->preamble_llvm_block = first_bb;
|
||||||
|
}
|
||||||
for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {
|
for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {
|
||||||
IrBasicBlock *bb = executable->basic_block_list.at(block_i);
|
IrBasicBlock *bb = executable->basic_block_list.at(block_i);
|
||||||
bb->llvm_block = LLVMAppendBasicBlock(fn_llvm_value(g, fn), bb->name_hint);
|
bb->llvm_block = LLVMAppendBasicBlock(fn_val, bb->name_hint);
|
||||||
}
|
}
|
||||||
IrBasicBlock *entry_bb = executable->basic_block_list.at(0);
|
if (first_bb == nullptr) {
|
||||||
LLVMPositionBuilderAtEnd(g->builder, entry_bb->llvm_block);
|
first_bb = executable->basic_block_list.at(0)->llvm_block;
|
||||||
|
}
|
||||||
|
LLVMPositionBuilderAtEnd(g->builder, first_bb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_global_var(CodeGen *g, ZigVar *var, LLVMValueRef init_val,
|
static void gen_global_var(CodeGen *g, ZigVar *var, LLVMValueRef init_val,
|
||||||
|
@ -6209,7 +6259,7 @@ static void do_code_gen(CodeGen *g) {
|
||||||
build_all_basic_blocks(g, fn_table_entry);
|
build_all_basic_blocks(g, fn_table_entry);
|
||||||
clear_debug_source_node(g);
|
clear_debug_source_node(g);
|
||||||
|
|
||||||
if (want_sret) {
|
if (want_sret || fn_table_entry->resume_blocks.length != 0) {
|
||||||
g->cur_ret_ptr = LLVMGetParam(fn, 0);
|
g->cur_ret_ptr = LLVMGetParam(fn, 0);
|
||||||
} else if (handle_is_ptr(fn_type_id->return_type)) {
|
} else if (handle_is_ptr(fn_type_id->return_type)) {
|
||||||
g->cur_ret_ptr = build_alloca(g, fn_type_id->return_type, "result", 0);
|
g->cur_ret_ptr = build_alloca(g, fn_type_id->return_type, "result", 0);
|
||||||
|
@ -6357,6 +6407,41 @@ static void do_code_gen(CodeGen *g) {
|
||||||
fn_walk_init.data.inits.gen_i = gen_i_init;
|
fn_walk_init.data.inits.gen_i = gen_i_init;
|
||||||
walk_function_params(g, fn_table_entry->type_entry, &fn_walk_init);
|
walk_function_params(g, fn_table_entry->type_entry, &fn_walk_init);
|
||||||
|
|
||||||
|
if (fn_table_entry->resume_blocks.length != 0) {
|
||||||
|
if (!g->strip_debug_symbols) {
|
||||||
|
AstNode *source_node = fn_table_entry->proto_node;
|
||||||
|
ZigLLVMSetCurrentDebugLocation(g->builder, (int)source_node->line + 1,
|
||||||
|
(int)source_node->column + 1, get_di_scope(g, fn_table_entry->child_scope));
|
||||||
|
}
|
||||||
|
LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
|
||||||
|
LLVMBasicBlockRef bad_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadResume");
|
||||||
|
LLVMPositionBuilderAtEnd(g->builder, bad_resume_block);
|
||||||
|
gen_assertion_scope(g, PanicMsgIdBadResume, fn_table_entry->child_scope);
|
||||||
|
|
||||||
|
LLVMBasicBlockRef get_size_block = LLVMAppendBasicBlock(g->cur_fn_val, "GetSize");
|
||||||
|
LLVMPositionBuilderAtEnd(g->builder, get_size_block);
|
||||||
|
assert(fn_table_entry->frame_type->abi_size != 0);
|
||||||
|
assert(fn_table_entry->frame_type->abi_size != SIZE_MAX);
|
||||||
|
LLVMValueRef size_val = LLVMConstInt(usize_type_ref, fn_table_entry->frame_type->abi_size, false);
|
||||||
|
LLVMBuildRet(g->builder, size_val);
|
||||||
|
|
||||||
|
LLVMPositionBuilderAtEnd(g->builder, fn_table_entry->preamble_llvm_block);
|
||||||
|
LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr,
|
||||||
|
coro_resume_index_index, "");
|
||||||
|
LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, "");
|
||||||
|
// The +1 is because index 0 is reserved for getting the size.
|
||||||
|
LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, resume_index, bad_resume_block,
|
||||||
|
fn_table_entry->resume_blocks.length + 1);
|
||||||
|
|
||||||
|
LLVMValueRef zero = LLVMConstNull(usize_type_ref);
|
||||||
|
LLVMAddCase(switch_instr, zero, get_size_block);
|
||||||
|
|
||||||
|
for (size_t resume_i = 0; resume_i < fn_table_entry->resume_blocks.length; resume_i += 1) {
|
||||||
|
LLVMValueRef case_value = LLVMConstInt(usize_type_ref, resume_i + 1, false);
|
||||||
|
LLVMAddCase(switch_instr, case_value, fn_table_entry->resume_blocks.at(resume_i)->llvm_block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ir_render(g, fn_table_entry);
|
ir_render(g, fn_table_entry);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6644,9 +6729,13 @@ static void define_builtin_types(CodeGen *g) {
|
||||||
|
|
||||||
g->primitive_type_table.put(&entry->name, entry);
|
g->primitive_type_table.put(&entry->name, entry);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
const char *field_names[] = {"resume_index"};
|
||||||
|
ZigType *field_types[] = {g->builtin_types.entry_usize};
|
||||||
|
g->builtin_types.entry_frame_header = get_struct_type(g, "(frame header)", field_names, field_types, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static BuiltinFnEntry *create_builtin_fn(CodeGen *g, BuiltinFnId id, const char *name, size_t count) {
|
static BuiltinFnEntry *create_builtin_fn(CodeGen *g, BuiltinFnId id, const char *name, size_t count) {
|
||||||
BuiltinFnEntry *builtin_fn = allocate<BuiltinFnEntry>(1);
|
BuiltinFnEntry *builtin_fn = allocate<BuiltinFnEntry>(1);
|
||||||
buf_init_from_str(&builtin_fn->name, name);
|
buf_init_from_str(&builtin_fn->name, name);
|
||||||
|
@ -7072,6 +7161,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
|
||||||
" BoundFn: Fn,\n"
|
" BoundFn: Fn,\n"
|
||||||
" ArgTuple: void,\n"
|
" ArgTuple: void,\n"
|
||||||
" Opaque: void,\n"
|
" Opaque: void,\n"
|
||||||
|
" Frame: void,\n"
|
||||||
" Vector: Vector,\n"
|
" Vector: Vector,\n"
|
||||||
" EnumLiteral: void,\n"
|
" EnumLiteral: void,\n"
|
||||||
"\n\n"
|
"\n\n"
|
||||||
|
@ -8335,6 +8425,7 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e
|
||||||
case ZigTypeIdArgTuple:
|
case ZigTypeIdArgTuple:
|
||||||
case ZigTypeIdErrorUnion:
|
case ZigTypeIdErrorUnion:
|
||||||
case ZigTypeIdErrorSet:
|
case ZigTypeIdErrorSet:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
case ZigTypeIdVoid:
|
case ZigTypeIdVoid:
|
||||||
case ZigTypeIdUnreachable:
|
case ZigTypeIdUnreachable:
|
||||||
|
@ -8518,6 +8609,7 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu
|
||||||
case ZigTypeIdUndefined:
|
case ZigTypeIdUndefined:
|
||||||
case ZigTypeIdNull:
|
case ZigTypeIdNull:
|
||||||
case ZigTypeIdArgTuple:
|
case ZigTypeIdArgTuple:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8685,6 +8777,7 @@ static void gen_h_file(CodeGen *g) {
|
||||||
case ZigTypeIdOptional:
|
case ZigTypeIdOptional:
|
||||||
case ZigTypeIdFn:
|
case ZigTypeIdFn:
|
||||||
case ZigTypeIdVector:
|
case ZigTypeIdVector:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
case ZigTypeIdEnum:
|
case ZigTypeIdEnum:
|
||||||
if (type_entry->data.enumeration.layout == ContainerLayoutExtern) {
|
if (type_entry->data.enumeration.layout == ContainerLayoutExtern) {
|
||||||
|
|
187
src/ir.cpp
187
src/ir.cpp
|
@ -318,6 +318,7 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
|
||||||
case ZigTypeIdFn:
|
case ZigTypeIdFn:
|
||||||
case ZigTypeIdArgTuple:
|
case ZigTypeIdArgTuple:
|
||||||
case ZigTypeIdVector:
|
case ZigTypeIdVector:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
|
@ -1026,6 +1027,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionInitNamedFi
|
||||||
return IrInstructionIdUnionInitNamedField;
|
return IrInstructionIdUnionInitNamedField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr IrInstructionId ir_instruction_id(IrInstructionSuspendBegin *) {
|
||||||
|
return IrInstructionIdSuspendBegin;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr IrInstructionId ir_instruction_id(IrInstructionSuspendBr *) {
|
||||||
|
return IrInstructionIdSuspendBr;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
|
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
|
||||||
T *special_instruction = allocate<T>(1);
|
T *special_instruction = allocate<T>(1);
|
||||||
|
@ -3183,6 +3192,30 @@ static IrInstruction *ir_build_end_expr(IrBuilder *irb, Scope *scope, AstNode *s
|
||||||
return &instruction->base;
|
return &instruction->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static IrInstruction *ir_build_suspend_begin(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||||
|
IrBasicBlock *resume_block)
|
||||||
|
{
|
||||||
|
IrInstructionSuspendBegin *instruction = ir_build_instruction<IrInstructionSuspendBegin>(irb, scope, source_node);
|
||||||
|
instruction->base.value.type = irb->codegen->builtin_types.entry_void;
|
||||||
|
instruction->resume_block = resume_block;
|
||||||
|
|
||||||
|
ir_ref_bb(resume_block);
|
||||||
|
|
||||||
|
return &instruction->base;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IrInstruction *ir_build_suspend_br(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||||
|
IrBasicBlock *resume_block)
|
||||||
|
{
|
||||||
|
IrInstructionSuspendBr *instruction = ir_build_instruction<IrInstructionSuspendBr>(irb, scope, source_node);
|
||||||
|
instruction->base.value.type = irb->codegen->builtin_types.entry_unreachable;
|
||||||
|
instruction->resume_block = resume_block;
|
||||||
|
|
||||||
|
ir_ref_bb(resume_block);
|
||||||
|
|
||||||
|
return &instruction->base;
|
||||||
|
}
|
||||||
|
|
||||||
static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
|
static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
|
||||||
results[ReturnKindUnconditional] = 0;
|
results[ReturnKindUnconditional] = 0;
|
||||||
results[ReturnKindError] = 0;
|
results[ReturnKindError] = 0;
|
||||||
|
@ -3286,6 +3319,18 @@ static void ir_set_cursor_at_end_and_append_block(IrBuilder *irb, IrBasicBlock *
|
||||||
ir_set_cursor_at_end(irb, basic_block);
|
ir_set_cursor_at_end(irb, basic_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ScopeSuspend *get_scope_suspend(Scope *scope) {
|
||||||
|
while (scope) {
|
||||||
|
if (scope->id == ScopeIdSuspend)
|
||||||
|
return (ScopeSuspend *)scope;
|
||||||
|
if (scope->id == ScopeIdFnDef)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
scope = scope->parent;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) {
|
static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) {
|
||||||
while (scope) {
|
while (scope) {
|
||||||
if (scope->id == ScopeIdDeferExpr)
|
if (scope->id == ScopeIdDeferExpr)
|
||||||
|
@ -3308,14 +3353,9 @@ static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode
|
||||||
{
|
{
|
||||||
ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, return_value));
|
ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, return_value));
|
||||||
|
|
||||||
bool is_async = exec_is_async(irb->exec);
|
IrInstruction *return_inst = ir_build_return(irb, scope, node, return_value);
|
||||||
if (!is_async) {
|
return_inst->is_gen = is_generated_code;
|
||||||
IrInstruction *return_inst = ir_build_return(irb, scope, node, return_value);
|
return return_inst;
|
||||||
return_inst->is_gen = is_generated_code;
|
|
||||||
return return_inst;
|
|
||||||
}
|
|
||||||
|
|
||||||
zig_panic("TODO async return");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) {
|
static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) {
|
||||||
|
@ -5393,12 +5433,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_async = node->data.fn_call_expr.is_async;
|
bool is_async = node->data.fn_call_expr.is_async;
|
||||||
if (is_async) {
|
IrInstruction *fn_call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,
|
||||||
zig_panic("TODO async fn call");
|
FnInlineAuto, is_async, nullptr, result_loc);
|
||||||
}
|
|
||||||
|
|
||||||
IrInstruction *fn_call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto,
|
|
||||||
is_async, nullptr, result_loc);
|
|
||||||
return ir_lval_wrap(irb, scope, fn_call, lval, result_loc);
|
return ir_lval_wrap(irb, scope, fn_call, lval, result_loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7655,7 +7691,45 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
|
||||||
static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
|
static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
|
||||||
assert(node->type == NodeTypeSuspend);
|
assert(node->type == NodeTypeSuspend);
|
||||||
|
|
||||||
zig_panic("TODO ir_gen_suspend");
|
ZigFn *fn_entry = exec_fn_entry(irb->exec);
|
||||||
|
if (!fn_entry) {
|
||||||
|
add_node_error(irb->codegen, node, buf_sprintf("suspend outside function definition"));
|
||||||
|
return irb->codegen->invalid_instruction;
|
||||||
|
}
|
||||||
|
ScopeDeferExpr *scope_defer_expr = get_scope_defer_expr(parent_scope);
|
||||||
|
if (scope_defer_expr) {
|
||||||
|
if (!scope_defer_expr->reported_err) {
|
||||||
|
ErrorMsg *msg = add_node_error(irb->codegen, node, buf_sprintf("cannot suspend inside defer expression"));
|
||||||
|
add_error_note(irb->codegen, msg, scope_defer_expr->base.source_node, buf_sprintf("defer here"));
|
||||||
|
scope_defer_expr->reported_err = true;
|
||||||
|
}
|
||||||
|
return irb->codegen->invalid_instruction;
|
||||||
|
}
|
||||||
|
ScopeSuspend *existing_suspend_scope = get_scope_suspend(parent_scope);
|
||||||
|
if (existing_suspend_scope) {
|
||||||
|
if (!existing_suspend_scope->reported_err) {
|
||||||
|
ErrorMsg *msg = add_node_error(irb->codegen, node, buf_sprintf("cannot suspend inside suspend block"));
|
||||||
|
add_error_note(irb->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("other suspend block here"));
|
||||||
|
existing_suspend_scope->reported_err = true;
|
||||||
|
}
|
||||||
|
return irb->codegen->invalid_instruction;
|
||||||
|
}
|
||||||
|
|
||||||
|
IrBasicBlock *resume_block = ir_create_basic_block(irb, parent_scope, "Resume");
|
||||||
|
|
||||||
|
ir_build_suspend_begin(irb, parent_scope, node, resume_block);
|
||||||
|
if (node->data.suspend.block != nullptr) {
|
||||||
|
Scope *child_scope;
|
||||||
|
ScopeSuspend *suspend_scope = create_suspend_scope(irb->codegen, node, parent_scope);
|
||||||
|
suspend_scope->resume_block = resume_block;
|
||||||
|
child_scope = &suspend_scope->base;
|
||||||
|
IrInstruction *susp_res = ir_gen_node(irb, node->data.suspend.block, child_scope);
|
||||||
|
ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.suspend.block, susp_res));
|
||||||
|
}
|
||||||
|
|
||||||
|
IrInstruction *result = ir_build_suspend_br(irb, parent_scope, node, resume_block);
|
||||||
|
ir_set_cursor_at_end_and_append_block(irb, resume_block);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope,
|
static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope,
|
||||||
|
@ -7854,13 +7928,6 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
|
||||||
// Entry block gets a reference because we enter it to begin.
|
// Entry block gets a reference because we enter it to begin.
|
||||||
ir_ref_bb(irb->current_basic_block);
|
ir_ref_bb(irb->current_basic_block);
|
||||||
|
|
||||||
ZigFn *fn_entry = exec_fn_entry(irb->exec);
|
|
||||||
|
|
||||||
bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
|
|
||||||
if (is_async) {
|
|
||||||
zig_panic("ir_gen async fn");
|
|
||||||
}
|
|
||||||
|
|
||||||
IrInstruction *result = ir_gen_node_extra(irb, node, scope, LValNone, nullptr);
|
IrInstruction *result = ir_gen_node_extra(irb, node, scope, LValNone, nullptr);
|
||||||
assert(result);
|
assert(result);
|
||||||
if (irb->exec->invalid)
|
if (irb->exec->invalid)
|
||||||
|
@ -12659,6 +12726,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
|
||||||
case ZigTypeIdNull:
|
case ZigTypeIdNull:
|
||||||
case ZigTypeIdErrorUnion:
|
case ZigTypeIdErrorUnion:
|
||||||
case ZigTypeIdUnion:
|
case ZigTypeIdUnion:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
operator_allowed = false;
|
operator_allowed = false;
|
||||||
break;
|
break;
|
||||||
case ZigTypeIdOptional:
|
case ZigTypeIdOptional:
|
||||||
|
@ -14023,6 +14091,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
|
||||||
case ZigTypeIdBoundFn:
|
case ZigTypeIdBoundFn:
|
||||||
case ZigTypeIdArgTuple:
|
case ZigTypeIdArgTuple:
|
||||||
case ZigTypeIdOpaque:
|
case ZigTypeIdOpaque:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
ir_add_error(ira, target,
|
ir_add_error(ira, target,
|
||||||
buf_sprintf("invalid export target '%s'", buf_ptr(&type_value->name)));
|
buf_sprintf("invalid export target '%s'", buf_ptr(&type_value->name)));
|
||||||
break;
|
break;
|
||||||
|
@ -14047,6 +14116,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
|
||||||
case ZigTypeIdArgTuple:
|
case ZigTypeIdArgTuple:
|
||||||
case ZigTypeIdOpaque:
|
case ZigTypeIdOpaque:
|
||||||
case ZigTypeIdEnumLiteral:
|
case ZigTypeIdEnumLiteral:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
ir_add_error(ira, target,
|
ir_add_error(ira, target,
|
||||||
buf_sprintf("invalid export target type '%s'", buf_ptr(&target->value.type->name)));
|
buf_sprintf("invalid export target type '%s'", buf_ptr(&target->value.type->name)));
|
||||||
break;
|
break;
|
||||||
|
@ -14553,6 +14623,20 @@ static IrInstruction *ir_analyze_instruction_reset_result(IrAnalyze *ira, IrInst
|
||||||
return ir_const_void(ira, &instruction->base);
|
return ir_const_void(ira, &instruction->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, ZigFn *fn_entry,
|
||||||
|
ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count)
|
||||||
|
{
|
||||||
|
ir_assert(fn_entry != nullptr, &call_instruction->base);
|
||||||
|
|
||||||
|
ZigType *frame_type = get_coro_frame_type(ira->codegen, fn_entry);
|
||||||
|
IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
|
||||||
|
frame_type, nullptr, true, true);
|
||||||
|
if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) {
|
||||||
|
return result_loc;
|
||||||
|
}
|
||||||
|
return ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref, arg_count,
|
||||||
|
casted_args, FnInlineAuto, true, nullptr, result_loc, frame_type);
|
||||||
|
}
|
||||||
static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,
|
static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,
|
||||||
IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i)
|
IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i)
|
||||||
{
|
{
|
||||||
|
@ -15366,16 +15450,18 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
|
||||||
if (type_is_invalid(return_type))
|
if (type_is_invalid(return_type))
|
||||||
return ira->codegen->invalid_instruction;
|
return ira->codegen->invalid_instruction;
|
||||||
|
|
||||||
if (call_instruction->is_async) {
|
|
||||||
zig_panic("TODO async call");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fn_entry != nullptr && fn_entry->fn_inline == FnInlineAlways && fn_inline == FnInlineNever) {
|
if (fn_entry != nullptr && fn_entry->fn_inline == FnInlineAlways && fn_inline == FnInlineNever) {
|
||||||
ir_add_error(ira, &call_instruction->base,
|
ir_add_error(ira, &call_instruction->base,
|
||||||
buf_sprintf("no-inline call of inline function"));
|
buf_sprintf("no-inline call of inline function"));
|
||||||
return ira->codegen->invalid_instruction;
|
return ira->codegen->invalid_instruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (call_instruction->is_async) {
|
||||||
|
IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref,
|
||||||
|
casted_args, call_param_count);
|
||||||
|
return ir_finish_anal(ira, result);
|
||||||
|
}
|
||||||
|
|
||||||
IrInstruction *result_loc;
|
IrInstruction *result_loc;
|
||||||
if (handle_is_ptr(return_type)) {
|
if (handle_is_ptr(return_type)) {
|
||||||
result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
|
result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
|
||||||
|
@ -15535,7 +15621,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
|
static IrInstruction *ir_analyze_optional_type(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
|
||||||
Error err;
|
Error err;
|
||||||
IrInstruction *value = un_op_instruction->value->child;
|
IrInstruction *value = un_op_instruction->value->child;
|
||||||
ZigType *type_entry = ir_resolve_type(ira, value);
|
ZigType *type_entry = ir_resolve_type(ira, value);
|
||||||
|
@ -15569,6 +15655,7 @@ static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_
|
||||||
case ZigTypeIdFn:
|
case ZigTypeIdFn:
|
||||||
case ZigTypeIdBoundFn:
|
case ZigTypeIdBoundFn:
|
||||||
case ZigTypeIdArgTuple:
|
case ZigTypeIdArgTuple:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
return ir_const_type(ira, &un_op_instruction->base, get_optional_type(ira->codegen, type_entry));
|
return ir_const_type(ira, &un_op_instruction->base, get_optional_type(ira->codegen, type_entry));
|
||||||
case ZigTypeIdUnreachable:
|
case ZigTypeIdUnreachable:
|
||||||
case ZigTypeIdOpaque:
|
case ZigTypeIdOpaque:
|
||||||
|
@ -15733,7 +15820,7 @@ static IrInstruction *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstruction
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
case IrUnOpOptional:
|
case IrUnOpOptional:
|
||||||
return ir_analyze_maybe(ira, instruction);
|
return ir_analyze_optional_type(ira, instruction);
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
@ -17340,6 +17427,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
|
||||||
case ZigTypeIdFn:
|
case ZigTypeIdFn:
|
||||||
case ZigTypeIdBoundFn:
|
case ZigTypeIdBoundFn:
|
||||||
case ZigTypeIdVector:
|
case ZigTypeIdVector:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
{
|
{
|
||||||
ResolveStatus needed_status = (align_bytes == 0) ?
|
ResolveStatus needed_status = (align_bytes == 0) ?
|
||||||
ResolveStatusZeroBitsKnown : ResolveStatusAlignmentKnown;
|
ResolveStatusZeroBitsKnown : ResolveStatusAlignmentKnown;
|
||||||
|
@ -17454,6 +17542,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
|
||||||
case ZigTypeIdFn:
|
case ZigTypeIdFn:
|
||||||
case ZigTypeIdBoundFn:
|
case ZigTypeIdBoundFn:
|
||||||
case ZigTypeIdVector:
|
case ZigTypeIdVector:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
{
|
{
|
||||||
if ((err = ensure_complete_type(ira->codegen, child_type)))
|
if ((err = ensure_complete_type(ira->codegen, child_type)))
|
||||||
return ira->codegen->invalid_instruction;
|
return ira->codegen->invalid_instruction;
|
||||||
|
@ -17504,6 +17593,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
|
||||||
case ZigTypeIdUnion:
|
case ZigTypeIdUnion:
|
||||||
case ZigTypeIdFn:
|
case ZigTypeIdFn:
|
||||||
case ZigTypeIdVector:
|
case ZigTypeIdVector:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
{
|
{
|
||||||
uint64_t size_in_bytes = type_size(ira->codegen, type_entry);
|
uint64_t size_in_bytes = type_size(ira->codegen, type_entry);
|
||||||
return ir_const_unsigned(ira, &size_of_instruction->base, size_in_bytes);
|
return ir_const_unsigned(ira, &size_of_instruction->base, size_in_bytes);
|
||||||
|
@ -18067,6 +18157,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
|
||||||
case ZigTypeIdArgTuple:
|
case ZigTypeIdArgTuple:
|
||||||
case ZigTypeIdOpaque:
|
case ZigTypeIdOpaque:
|
||||||
case ZigTypeIdVector:
|
case ZigTypeIdVector:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
ir_add_error(ira, &switch_target_instruction->base,
|
ir_add_error(ira, &switch_target_instruction->base,
|
||||||
buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name)));
|
buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name)));
|
||||||
return ira->codegen->invalid_instruction;
|
return ira->codegen->invalid_instruction;
|
||||||
|
@ -19906,6 +19997,8 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
|
zig_panic("TODO @typeInfo for coro frames");
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(result != nullptr);
|
assert(result != nullptr);
|
||||||
|
@ -21660,6 +21753,7 @@ static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruct
|
||||||
case ZigTypeIdUnion:
|
case ZigTypeIdUnion:
|
||||||
case ZigTypeIdFn:
|
case ZigTypeIdFn:
|
||||||
case ZigTypeIdVector:
|
case ZigTypeIdVector:
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
{
|
{
|
||||||
uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry);
|
uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry);
|
||||||
return ir_const_unsigned(ira, &instruction->base, align_in_bytes);
|
return ir_const_unsigned(ira, &instruction->base, align_in_bytes);
|
||||||
|
@ -22815,6 +22909,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
|
||||||
zig_panic("TODO buf_write_value_bytes fn type");
|
zig_panic("TODO buf_write_value_bytes fn type");
|
||||||
case ZigTypeIdUnion:
|
case ZigTypeIdUnion:
|
||||||
zig_panic("TODO buf_write_value_bytes union type");
|
zig_panic("TODO buf_write_value_bytes union type");
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
|
zig_panic("TODO buf_write_value_bytes coro frame type");
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
@ -22994,6 +23090,8 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
|
||||||
zig_panic("TODO buf_read_value_bytes fn type");
|
zig_panic("TODO buf_read_value_bytes fn type");
|
||||||
case ZigTypeIdUnion:
|
case ZigTypeIdUnion:
|
||||||
zig_panic("TODO buf_read_value_bytes union type");
|
zig_panic("TODO buf_read_value_bytes union type");
|
||||||
|
case ZigTypeIdCoroFrame:
|
||||||
|
zig_panic("TODO buf_read_value_bytes coro frame type");
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
@ -24021,6 +24119,33 @@ static IrInstruction *ir_analyze_instruction_union_init_named_field(IrAnalyze *i
|
||||||
union_type, field_name, field_result_loc, result_loc);
|
union_type, field_name, field_result_loc, result_loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static IrInstruction *ir_analyze_instruction_suspend_begin(IrAnalyze *ira, IrInstructionSuspendBegin *instruction) {
|
||||||
|
IrBasicBlock *new_bb = ir_get_new_bb_runtime(ira, instruction->resume_block, &instruction->base);
|
||||||
|
if (new_bb == nullptr)
|
||||||
|
return ir_unreach_error(ira);
|
||||||
|
return ir_build_suspend_begin(&ira->new_irb, instruction->base.scope, instruction->base.source_node, new_bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static IrInstruction *ir_analyze_instruction_suspend_br(IrAnalyze *ira, IrInstructionSuspendBr *instruction) {
|
||||||
|
IrBasicBlock *old_dest_block = instruction->resume_block;
|
||||||
|
|
||||||
|
IrBasicBlock *new_bb = ir_get_new_bb_runtime(ira, old_dest_block, &instruction->base);
|
||||||
|
if (new_bb == nullptr)
|
||||||
|
return ir_unreach_error(ira);
|
||||||
|
|
||||||
|
ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
|
||||||
|
ir_assert(fn_entry != nullptr, &instruction->base);
|
||||||
|
fn_entry->resume_blocks.append(new_bb);
|
||||||
|
// This is done after appending the block because resume_index 0 is reserved for querying the size.
|
||||||
|
new_bb->resume_index = fn_entry->resume_blocks.length;
|
||||||
|
|
||||||
|
ir_push_resume_block(ira, old_dest_block);
|
||||||
|
|
||||||
|
IrInstruction *result = ir_build_suspend_br(&ira->new_irb,
|
||||||
|
instruction->base.scope, instruction->base.source_node, new_bb);
|
||||||
|
return ir_finish_anal(ira, result);
|
||||||
|
}
|
||||||
|
|
||||||
static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) {
|
static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) {
|
||||||
switch (instruction->id) {
|
switch (instruction->id) {
|
||||||
case IrInstructionIdInvalid:
|
case IrInstructionIdInvalid:
|
||||||
|
@ -24304,6 +24429,10 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
|
||||||
return ir_analyze_instruction_bit_cast_src(ira, (IrInstructionBitCastSrc *)instruction);
|
return ir_analyze_instruction_bit_cast_src(ira, (IrInstructionBitCastSrc *)instruction);
|
||||||
case IrInstructionIdUnionInitNamedField:
|
case IrInstructionIdUnionInitNamedField:
|
||||||
return ir_analyze_instruction_union_init_named_field(ira, (IrInstructionUnionInitNamedField *)instruction);
|
return ir_analyze_instruction_union_init_named_field(ira, (IrInstructionUnionInitNamedField *)instruction);
|
||||||
|
case IrInstructionIdSuspendBegin:
|
||||||
|
return ir_analyze_instruction_suspend_begin(ira, (IrInstructionSuspendBegin *)instruction);
|
||||||
|
case IrInstructionIdSuspendBr:
|
||||||
|
return ir_analyze_instruction_suspend_br(ira, (IrInstructionSuspendBr *)instruction);
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
@ -24436,6 +24565,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
||||||
case IrInstructionIdOptionalWrap:
|
case IrInstructionIdOptionalWrap:
|
||||||
case IrInstructionIdVectorToArray:
|
case IrInstructionIdVectorToArray:
|
||||||
case IrInstructionIdResetResult:
|
case IrInstructionIdResetResult:
|
||||||
|
case IrInstructionIdSuspendBegin:
|
||||||
|
case IrInstructionIdSuspendBr:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case IrInstructionIdPhi:
|
case IrInstructionIdPhi:
|
||||||
|
|
|
@ -1503,6 +1503,16 @@ static void ir_print_union_init_named_field(IrPrint *irp, IrInstructionUnionInit
|
||||||
fprintf(irp->f, ")");
|
fprintf(irp->f, ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ir_print_suspend_begin(IrPrint *irp, IrInstructionSuspendBegin *instruction) {
|
||||||
|
fprintf(irp->f, "@suspendBegin()");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ir_print_suspend_br(IrPrint *irp, IrInstructionSuspendBr *instruction) {
|
||||||
|
fprintf(irp->f, "@suspendBr(");
|
||||||
|
ir_print_other_block(irp, instruction->resume_block);
|
||||||
|
fprintf(irp->f, ")");
|
||||||
|
}
|
||||||
|
|
||||||
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||||
ir_print_prefix(irp, instruction);
|
ir_print_prefix(irp, instruction);
|
||||||
switch (instruction->id) {
|
switch (instruction->id) {
|
||||||
|
@ -1961,6 +1971,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||||
case IrInstructionIdUnionInitNamedField:
|
case IrInstructionIdUnionInitNamedField:
|
||||||
ir_print_union_init_named_field(irp, (IrInstructionUnionInitNamedField *)instruction);
|
ir_print_union_init_named_field(irp, (IrInstructionUnionInitNamedField *)instruction);
|
||||||
break;
|
break;
|
||||||
|
case IrInstructionIdSuspendBegin:
|
||||||
|
ir_print_suspend_begin(irp, (IrInstructionSuspendBegin *)instruction);
|
||||||
|
break;
|
||||||
|
case IrInstructionIdSuspendBr:
|
||||||
|
ir_print_suspend_br(irp, (IrInstructionSuspendBr *)instruction);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
fprintf(irp->f, "\n");
|
fprintf(irp->f, "\n");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue