Merge pull request #2602 from ziglang/copy-elision-3

result location mechanism (part of no-copy semantics)
This commit is contained in:
Andrew Kelley 2019-06-26 18:29:19 -04:00 committed by GitHub
commit 01ff0d4d62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 4377 additions and 2170 deletions

View File

@ -6734,6 +6734,7 @@ add_custom_command(
"-Doutput-dir=${CMAKE_BINARY_DIR}"
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
DEPENDS
zig0
"${CMAKE_SOURCE_DIR}/src-self-hosted/dep_tokenizer.zig"
"${CMAKE_SOURCE_DIR}/src-self-hosted/stage1.zig"
"${CMAKE_SOURCE_DIR}/src-self-hosted/translate_c.zig"

View File

@ -74,7 +74,8 @@ pub fn build(b: *Builder) !void {
const skip_non_native = b.option(bool, "skip-non-native", "Main test suite skips non-native builds") orelse false;
const skip_self_hosted = b.option(bool, "skip-self-hosted", "Main test suite skips building self hosted compiler") orelse false;
if (!skip_self_hosted) {
test_step.dependOn(&exe.step);
// TODO re-enable this after https://github.com/ziglang/zig/issues/2377
//test_step.dependOn(&exe.step);
}
const verbose_link_exe = b.option(bool, "verbose-link", "Print link command for self hosted compiler") orelse false;
exe.setVerboseLink(verbose_link_exe);

View File

@ -5096,7 +5096,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {
<p>
For example, if we were to introduce another function to the above snippet:
</p>
{#code_begin|test_err|values of type 'type' must be comptime known#}
{#code_begin|test_err|cannot store runtime value in type 'type'#}
fn max(comptime T: type, a: T, b: T) T {
return if (a > b) a else b;
}

View File

@ -34,12 +34,17 @@ struct CodeGen;
struct ConstExprValue;
struct IrInstruction;
struct IrInstructionCast;
struct IrInstructionAllocaGen;
struct IrBasicBlock;
struct ScopeDecls;
struct ZigWindowsSDK;
struct Tld;
struct TldExport;
struct IrAnalyze;
struct ResultLoc;
struct ResultLocPeer;
struct ResultLocPeerParent;
struct ResultLocBitCast;
enum X64CABIClass {
X64CABIClass_Unknown,
@ -198,6 +203,9 @@ enum ConstPtrMut {
// The pointer points to memory that is known only at runtime.
// For example it may point to the initializer value of a variable.
ConstPtrMutRuntimeVar,
// The pointer points to memory for which it must be inferred whether the
// value is comptime known or not.
ConstPtrMutInfer,
};
struct ConstPtrValue {
@ -289,6 +297,7 @@ struct RuntimeHintSlice {
struct ConstGlobalRefs {
LLVMValueRef llvm_value;
LLVMValueRef llvm_global;
uint32_t align;
};
struct ConstExprValue {
@ -325,6 +334,10 @@ struct ConstExprValue {
RuntimeHintPtr rh_ptr;
RuntimeHintSlice rh_slice;
} data;
// uncomment these to find bugs. can't leave them uncommented because of a gcc-9 warning
//ConstExprValue(const ConstExprValue &other) = delete; // plz zero initialize with {}
//ConstExprValue& operator= (const ConstExprValue &other) = delete; // use copy_const_val
};
enum ReturnKnowledge {
@ -426,7 +439,7 @@ enum NodeType {
NodeTypeVariableDeclaration,
NodeTypeTestDecl,
NodeTypeBinOpExpr,
NodeTypeUnwrapErrorExpr,
NodeTypeCatchExpr,
NodeTypeFloatLiteral,
NodeTypeIntLiteral,
NodeTypeStringLiteral,
@ -1364,7 +1377,7 @@ struct ZigFn {
AstNode *fn_no_inline_set_node;
AstNode *fn_static_eval_set_node;
ZigList<IrInstruction *> alloca_list;
ZigList<IrInstructionAllocaGen *> alloca_gen_list;
ZigList<ZigVar *> variable_list;
Buf *section_name;
@ -1999,6 +2012,11 @@ struct ScopeDecls {
bool any_imports_failed;
};
enum LVal {
LValNone,
LValPtr,
};
// This scope comes from a block expression in user code.
// NodeTypeBlock
struct ScopeBlock {
@ -2007,12 +2025,14 @@ struct ScopeBlock {
Buf *name;
IrBasicBlock *end_block;
IrInstruction *is_comptime;
ResultLocPeerParent *peer_parent;
ZigList<IrInstruction *> *incoming_values;
ZigList<IrBasicBlock *> *incoming_blocks;
AstNode *safety_set_node;
AstNode *fast_math_set_node;
LVal lval;
bool safety_off;
bool fast_math_on;
};
@ -2056,12 +2076,14 @@ struct ScopeCImport {
struct ScopeLoop {
Scope base;
LVal lval;
Buf *name;
IrBasicBlock *break_block;
IrBasicBlock *continue_block;
IrInstruction *is_comptime;
ZigList<IrInstruction *> *incoming_values;
ZigList<IrBasicBlock *> *incoming_blocks;
ResultLocPeerParent *peer_parent;
};
// This scope blocks certain things from working such as comptime continue
@ -2138,6 +2160,8 @@ struct IrBasicBlock {
const char *name_hint;
size_t debug_id;
size_t ref_count;
// index into the basic block list
size_t index;
LLVMBasicBlockRef llvm_block;
LLVMBasicBlockRef llvm_exit_block;
// The instruction that referenced this basic block and caused us to
@ -2148,11 +2172,10 @@ struct IrBasicBlock {
// if the branch is comptime. The instruction points to the reason
// the basic block must be comptime.
IrInstruction *must_be_comptime_source_instr;
};
enum LVal {
LValNone,
LValPtr,
IrInstruction *suspend_instruction_ref;
bool already_appended;
bool suspended;
bool in_resume_stack;
};
// These instructions are in transition to having "pass 1" instructions
@ -2185,19 +2208,17 @@ enum IrInstructionId {
IrInstructionIdUnionFieldPtr,
IrInstructionIdElemPtr,
IrInstructionIdVarPtr,
IrInstructionIdCall,
IrInstructionIdReturnPtr,
IrInstructionIdCallSrc,
IrInstructionIdCallGen,
IrInstructionIdConst,
IrInstructionIdReturn,
IrInstructionIdCast,
IrInstructionIdResizeSlice,
IrInstructionIdContainerInitList,
IrInstructionIdContainerInitFields,
IrInstructionIdStructInit,
IrInstructionIdUnionInit,
IrInstructionIdUnreachable,
IrInstructionIdTypeOf,
IrInstructionIdToPtrType,
IrInstructionIdPtrTypeChild,
IrInstructionIdSetCold,
IrInstructionIdSetRuntimeSafety,
IrInstructionIdSetFloatMode,
@ -2222,6 +2243,7 @@ enum IrInstructionId {
IrInstructionIdCDefine,
IrInstructionIdCUndef,
IrInstructionIdRef,
IrInstructionIdRefGen,
IrInstructionIdCompileErr,
IrInstructionIdCompileLog,
IrInstructionIdErrName,
@ -2240,7 +2262,8 @@ enum IrInstructionId {
IrInstructionIdBoolNot,
IrInstructionIdMemset,
IrInstructionIdMemcpy,
IrInstructionIdSlice,
IrInstructionIdSliceSrc,
IrInstructionIdSliceGen,
IrInstructionIdMemberCount,
IrInstructionIdMemberType,
IrInstructionIdMemberName,
@ -2250,9 +2273,10 @@ enum IrInstructionId {
IrInstructionIdHandle,
IrInstructionIdAlignOf,
IrInstructionIdOverflowOp,
IrInstructionIdTestErrSrc,
IrInstructionIdTestErrGen,
IrInstructionIdMulAdd,
IrInstructionIdFloatOp,
IrInstructionIdTestErr,
IrInstructionIdUnwrapErrCode,
IrInstructionIdUnwrapErrPayload,
IrInstructionIdErrWrapCode,
@ -2261,7 +2285,7 @@ enum IrInstructionId {
IrInstructionIdTestComptime,
IrInstructionIdPtrCastSrc,
IrInstructionIdPtrCastGen,
IrInstructionIdBitCast,
IrInstructionIdBitCastSrc,
IrInstructionIdBitCastGen,
IrInstructionIdWidenOrShorten,
IrInstructionIdIntToPtr,
@ -2285,6 +2309,10 @@ enum IrInstructionId {
IrInstructionIdSetEvalBranchQuota,
IrInstructionIdPtrType,
IrInstructionIdAlignCast,
IrInstructionIdImplicitCast,
IrInstructionIdResolveResult,
IrInstructionIdResetResult,
IrInstructionIdResultPtr,
IrInstructionIdOpaqueType,
IrInstructionIdSetAlignStack,
IrInstructionIdArgType,
@ -2323,10 +2351,13 @@ enum IrInstructionId {
IrInstructionIdAssertNonNull,
IrInstructionIdHasDecl,
IrInstructionIdUndeclaredIdent,
IrInstructionIdAllocaSrc,
IrInstructionIdAllocaGen,
IrInstructionIdEndExpr,
IrInstructionIdPtrOfArrayToSlice,
};
struct IrInstruction {
IrInstructionId id;
Scope *scope;
AstNode *source_node;
ConstExprValue value;
@ -2340,6 +2371,7 @@ struct IrInstruction {
// with this child field.
IrInstruction *child;
IrBasicBlock *owner_bb;
IrInstructionId id;
// true if this instruction was generated by zig and not from user code
bool is_gen;
};
@ -2350,14 +2382,14 @@ struct IrInstructionDeclVarSrc {
ZigVar *var;
IrInstruction *var_type;
IrInstruction *align_value;
IrInstruction *init_value;
IrInstruction *ptr;
};
struct IrInstructionDeclVarGen {
IrInstruction base;
ZigVar *var;
IrInstruction *init_value;
IrInstruction *var_ptr;
};
struct IrInstructionCondBr {
@ -2367,6 +2399,7 @@ struct IrInstructionCondBr {
IrBasicBlock *then_block;
IrBasicBlock *else_block;
IrInstruction *is_comptime;
ResultLoc *result_loc;
};
struct IrInstructionBr {
@ -2419,6 +2452,7 @@ struct IrInstructionPhi {
size_t incoming_count;
IrBasicBlock **incoming_blocks;
IrInstruction **incoming_values;
ResultLocPeerParent *peer_parent;
};
enum IrUnOp {
@ -2434,8 +2468,9 @@ struct IrInstructionUnOp {
IrInstruction base;
IrUnOp op_id;
IrInstruction *value;
LVal lval;
IrInstruction *value;
ResultLoc *result_loc;
};
enum IrBinOp {
@ -2492,7 +2527,7 @@ struct IrInstructionLoadPtrGen {
IrInstruction base;
IrInstruction *ptr;
LLVMValueRef tmp_ptr;
IrInstruction *result_loc;
};
struct IrInstructionStorePtr {
@ -2505,6 +2540,7 @@ struct IrInstructionStorePtr {
struct IrInstructionFieldPtr {
IrInstruction base;
bool initializing;
IrInstruction *container_ptr;
Buf *field_name_buffer;
IrInstruction *field_name_expr;
@ -2521,9 +2557,10 @@ struct IrInstructionStructFieldPtr {
struct IrInstructionUnionFieldPtr {
IrInstruction base;
bool safety_check_on;
bool initializing;
IrInstruction *union_ptr;
TypeUnionField *field;
bool is_const;
};
struct IrInstructionElemPtr {
@ -2531,8 +2568,8 @@ struct IrInstructionElemPtr {
IrInstruction *array_ptr;
IrInstruction *elem_index;
IrInstruction *init_array_type;
PtrLen ptr_len;
bool is_const;
bool safety_check_on;
};
@ -2543,14 +2580,21 @@ struct IrInstructionVarPtr {
ScopeFnDef *crossed_fndef_scope;
};
struct IrInstructionCall {
// For functions that have a return type for which handle_is_ptr is true, a
// result location pointer is the secret first parameter ("sret"). This
// instruction returns that pointer.
struct IrInstructionReturnPtr {
IrInstruction base;
};
struct IrInstructionCallSrc {
IrInstruction base;
IrInstruction *fn_ref;
ZigFn *fn_entry;
size_t arg_count;
IrInstruction **args;
LLVMValueRef tmp_ptr;
ResultLoc *result_loc;
IrInstruction *async_allocator;
IrInstruction *new_stack;
@ -2559,6 +2603,21 @@ struct IrInstructionCall {
bool is_comptime;
};
struct IrInstructionCallGen {
IrInstruction base;
IrInstruction *fn_ref;
ZigFn *fn_entry;
size_t arg_count;
IrInstruction **args;
IrInstruction *result_loc;
IrInstruction *async_allocator;
IrInstruction *new_stack;
FnInline fn_inline;
bool is_async;
};
struct IrInstructionConst {
IrInstruction base;
};
@ -2581,7 +2640,6 @@ enum CastOp {
CastOpNumLitToConcrete,
CastOpErrSet,
CastOpBitCast,
CastOpPtrOfArrayToSlice,
};
// TODO get rid of this instruction, replace with instructions for each op code
@ -2591,14 +2649,13 @@ struct IrInstructionCast {
IrInstruction *value;
ZigType *dest_type;
CastOp cast_op;
LLVMValueRef tmp_ptr;
};
struct IrInstructionResizeSlice {
IrInstruction base;
IrInstruction *operand;
LLVMValueRef tmp_ptr;
IrInstruction *result_loc;
};
struct IrInstructionContainerInitList {
@ -2607,15 +2664,15 @@ struct IrInstructionContainerInitList {
IrInstruction *container_type;
IrInstruction *elem_type;
size_t item_count;
IrInstruction **items;
LLVMValueRef tmp_ptr;
IrInstruction **elem_result_loc_list;
IrInstruction *result_loc;
};
struct IrInstructionContainerInitFieldsField {
Buf *name;
IrInstruction *value;
AstNode *source_node;
TypeStructField *type_struct_field;
IrInstruction *result_loc;
};
struct IrInstructionContainerInitFields {
@ -2624,29 +2681,7 @@ struct IrInstructionContainerInitFields {
IrInstruction *container_type;
size_t field_count;
IrInstructionContainerInitFieldsField *fields;
};
struct IrInstructionStructInitField {
IrInstruction *value;
TypeStructField *type_struct_field;
};
struct IrInstructionStructInit {
IrInstruction base;
ZigType *struct_type;
size_t field_count;
IrInstructionStructInitField *fields;
LLVMValueRef tmp_ptr;
};
struct IrInstructionUnionInit {
IrInstruction base;
ZigType *union_type;
TypeUnionField *field;
IrInstruction *init_value;
LLVMValueRef tmp_ptr;
IrInstruction *result_loc;
};
struct IrInstructionUnreachable {
@ -2659,18 +2694,6 @@ struct IrInstructionTypeOf {
IrInstruction *value;
};
struct IrInstructionToPtrType {
IrInstruction base;
IrInstruction *ptr;
};
struct IrInstructionPtrTypeChild {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionSetCold {
IrInstruction base;
@ -2764,8 +2787,9 @@ struct IrInstructionTestNonNull {
struct IrInstructionOptionalUnwrapPtr {
IrInstruction base;
IrInstruction *base_ptr;
bool safety_check_on;
bool initializing;
IrInstruction *base_ptr;
};
struct IrInstructionCtz {
@ -2805,11 +2829,17 @@ struct IrInstructionRef {
IrInstruction base;
IrInstruction *value;
LLVMValueRef tmp_ptr;
bool is_const;
bool is_volatile;
};
struct IrInstructionRefGen {
IrInstruction base;
IrInstruction *operand;
IrInstruction *result_loc;
};
struct IrInstructionCompileErr {
IrInstruction base;
@ -2861,26 +2891,26 @@ struct IrInstructionEmbedFile {
struct IrInstructionCmpxchgSrc {
IrInstruction base;
bool is_weak;
IrInstruction *type_value;
IrInstruction *ptr;
IrInstruction *cmp_value;
IrInstruction *new_value;
IrInstruction *success_order_value;
IrInstruction *failure_order_value;
bool is_weak;
ResultLoc *result_loc;
};
struct IrInstructionCmpxchgGen {
IrInstruction base;
bool is_weak;
AtomicOrder success_order;
AtomicOrder failure_order;
IrInstruction *ptr;
IrInstruction *cmp_value;
IrInstruction *new_value;
LLVMValueRef tmp_ptr;
AtomicOrder success_order;
AtomicOrder failure_order;
bool is_weak;
IrInstruction *result_loc;
};
struct IrInstructionFence {
@ -2924,6 +2954,7 @@ struct IrInstructionToBytes {
IrInstruction base;
IrInstruction *target;
ResultLoc *result_loc;
};
struct IrInstructionFromBytes {
@ -2931,6 +2962,7 @@ struct IrInstructionFromBytes {
IrInstruction *dest_child_type;
IrInstruction *target;
ResultLoc *result_loc;
};
struct IrInstructionIntToFloat {
@ -2989,14 +3021,24 @@ struct IrInstructionMemcpy {
IrInstruction *count;
};
struct IrInstructionSlice {
struct IrInstructionSliceSrc {
IrInstruction base;
bool safety_check_on;
IrInstruction *ptr;
IrInstruction *start;
IrInstruction *end;
ResultLoc *result_loc;
};
struct IrInstructionSliceGen {
IrInstruction base;
bool safety_check_on;
LLVMValueRef tmp_ptr;
IrInstruction *ptr;
IrInstruction *start;
IrInstruction *end;
IrInstruction *result_loc;
};
struct IrInstructionMemberCount {
@ -3070,44 +3112,54 @@ struct IrInstructionAlignOf {
};
// returns true if error, returns false if not error
struct IrInstructionTestErr {
struct IrInstructionTestErrSrc {
IrInstruction base;
IrInstruction *value;
bool resolve_err_set;
IrInstruction *base_ptr;
};
struct IrInstructionUnwrapErrCode {
struct IrInstructionTestErrGen {
IrInstruction base;
IrInstruction *err_union;
};
// Takes an error union pointer, returns a pointer to the error code.
struct IrInstructionUnwrapErrCode {
IrInstruction base;
bool initializing;
IrInstruction *err_union_ptr;
};
struct IrInstructionUnwrapErrPayload {
IrInstruction base;
IrInstruction *value;
bool safety_check_on;
bool initializing;
IrInstruction *value;
};
struct IrInstructionOptionalWrap {
IrInstruction base;
IrInstruction *value;
LLVMValueRef tmp_ptr;
IrInstruction *operand;
IrInstruction *result_loc;
};
struct IrInstructionErrWrapPayload {
IrInstruction base;
IrInstruction *value;
LLVMValueRef tmp_ptr;
IrInstruction *operand;
IrInstruction *result_loc;
};
struct IrInstructionErrWrapCode {
IrInstruction base;
IrInstruction *value;
LLVMValueRef tmp_ptr;
IrInstruction *operand;
IrInstruction *result_loc;
};
struct IrInstructionFnProto {
@ -3142,18 +3194,17 @@ struct IrInstructionPtrCastGen {
bool safety_check_on;
};
struct IrInstructionBitCast {
struct IrInstructionBitCastSrc {
IrInstruction base;
IrInstruction *dest_type;
IrInstruction *value;
IrInstruction *operand;
ResultLocBitCast *result_loc_bit_cast;
};
struct IrInstructionBitCastGen {
IrInstruction base;
IrInstruction *operand;
LLVMValueRef tmp_ptr;
};
struct IrInstructionWidenOrShorten {
@ -3229,8 +3280,8 @@ struct IrInstructionTypeName {
struct IrInstructionDeclRef {
IrInstruction base;
Tld *tld;
LVal lval;
Tld *tld;
};
struct IrInstructionPanic {
@ -3526,7 +3577,7 @@ struct IrInstructionVectorToArray {
IrInstruction base;
IrInstruction *vector;
LLVMValueRef tmp_ptr;
IrInstruction *result_loc;
};
struct IrInstructionAssertZero {
@ -3554,6 +3605,139 @@ struct IrInstructionUndeclaredIdent {
Buf *name;
};
struct IrInstructionAllocaSrc {
IrInstruction base;
IrInstruction *align;
IrInstruction *is_comptime;
const char *name_hint;
};
struct IrInstructionAllocaGen {
IrInstruction base;
uint32_t align;
const char *name_hint;
};
struct IrInstructionEndExpr {
IrInstruction base;
IrInstruction *value;
ResultLoc *result_loc;
};
struct IrInstructionImplicitCast {
IrInstruction base;
IrInstruction *dest_type;
IrInstruction *target;
ResultLoc *result_loc;
};
// This one is for writing through the result pointer.
struct IrInstructionResolveResult {
IrInstruction base;
ResultLoc *result_loc;
IrInstruction *ty;
};
// This one is when you want to read the value of the result.
// You have to give the value in case it is comptime.
struct IrInstructionResultPtr {
IrInstruction base;
ResultLoc *result_loc;
IrInstruction *result;
};
struct IrInstructionResetResult {
IrInstruction base;
ResultLoc *result_loc;
};
struct IrInstructionPtrOfArrayToSlice {
IrInstruction base;
IrInstruction *operand;
IrInstruction *result_loc;
};
enum ResultLocId {
ResultLocIdInvalid,
ResultLocIdNone,
ResultLocIdVar,
ResultLocIdReturn,
ResultLocIdPeer,
ResultLocIdPeerParent,
ResultLocIdInstruction,
ResultLocIdBitCast,
};
// Additions to this struct may need to be handled in
// ir_reset_result
struct ResultLoc {
ResultLocId id;
bool written;
IrInstruction *resolved_loc; // result ptr
IrInstruction *source_instruction;
IrInstruction *gen_instruction; // value to store to the result loc
ZigType *implicit_elem_type;
};
struct ResultLocNone {
ResultLoc base;
};
struct ResultLocVar {
ResultLoc base;
ZigVar *var;
};
struct ResultLocReturn {
ResultLoc base;
};
struct IrSuspendPosition {
size_t basic_block_index;
size_t instruction_index;
};
struct ResultLocPeerParent {
ResultLoc base;
bool skipped;
bool done_resuming;
IrBasicBlock *end_bb;
ResultLoc *parent;
ZigList<ResultLocPeer *> peers;
ZigType *resolved_type;
IrInstruction *is_comptime;
};
struct ResultLocPeer {
ResultLoc base;
ResultLocPeerParent *parent;
IrBasicBlock *next_bb;
IrSuspendPosition suspend_pos;
};
// The result location is the source instruction
struct ResultLocInstruction {
ResultLoc base;
};
// The source_instruction is the destination type
struct ResultLocBitCast {
ResultLoc base;
ResultLoc *parent;
};
static const size_t slice_ptr_index = 0;
static const size_t slice_len_index = 1;
@ -3601,7 +3785,7 @@ struct FnWalkAttrs {
struct FnWalkCall {
ZigList<LLVMValueRef> *gen_param_values;
IrInstructionCall *inst;
IrInstructionCallGen *inst;
bool is_var_args;
};

View File

@ -2995,7 +2995,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
case NodeTypeBlock:
case NodeTypeGroupedExpr:
case NodeTypeBinOpExpr:
case NodeTypeUnwrapErrorExpr:
case NodeTypeCatchExpr:
case NodeTypeFnCallExpr:
case NodeTypeArrayAccessExpr:
case NodeTypeSliceExpr:
@ -4181,6 +4181,7 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
case ConstPtrMutComptimeConst:
hash_val += (uint32_t)4214318515;
break;
case ConstPtrMutInfer:
case ConstPtrMutComptimeVar:
hash_val += (uint32_t)1103195694;
break;
@ -4511,6 +4512,8 @@ bool fn_eval_cacheable(Scope *scope, ZigType *return_type) {
ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
if (type_is_invalid(var_scope->var->var_type))
return false;
if (var_scope->var->const_value->special == ConstValSpecialUndef)
return false;
if (can_mutate_comptime_var_state(var_scope->var->const_value))
return false;
} else if (scope->id == ScopeIdFnDef) {
@ -4710,7 +4713,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
auto entry = g->string_literals_table.maybe_get(str);
if (entry != nullptr) {
*const_val = *entry->value;
memcpy(const_val, entry->value, sizeof(ConstExprValue));
return;
}
@ -4998,12 +5001,9 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val) {
field_val->type = wanted_type->data.structure.fields[i].type_entry;
assert(field_val->type);
init_const_undefined(g, field_val);
ConstParent *parent = get_const_val_parent(g, field_val);
if (parent != nullptr) {
parent->id = ConstParentIdStruct;
parent->data.p_struct.struct_val = const_val;
parent->data.p_struct.field_index = i;
}
field_val->parent.id = ConstParentIdStruct;
field_val->parent.data.p_struct.struct_val = const_val;
field_val->parent.data.p_struct.field_index = i;
}
} else {
const_val->special = ConstValSpecialUndef;
@ -5843,11 +5843,6 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
zig_unreachable();
}
// Deprecated. Reference the parent field directly.
ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {
return &value->parent;
}
static const ZigTypeId all_type_ids[] = {
ZigTypeIdMetaType,
ZigTypeIdVoid,
@ -7281,6 +7276,6 @@ void src_assert(bool ok, AstNode *source_node) {
buf_ptr(source_node->owner->data.structure.root_struct->path),
(unsigned)source_node->line + 1, (unsigned)source_node->column + 1);
}
const char *msg = "assertion failed";
const char *msg = "assertion failed. This is a bug in the Zig compiler.";
stage2_panic(msg, strlen(msg));
}

View File

@ -180,7 +180,6 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val);
ConstExprValue *create_const_vals(size_t count);
ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value);
void expand_undef_array(CodeGen *g, ConstExprValue *const_val);
void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value);

View File

@ -165,8 +165,8 @@ static const char *node_type_str(NodeType node_type) {
return "Parens";
case NodeTypeBinOpExpr:
return "BinOpExpr";
case NodeTypeUnwrapErrorExpr:
return "UnwrapErrorExpr";
case NodeTypeCatchExpr:
return "CatchExpr";
case NodeTypeFnCallExpr:
return "FnCallExpr";
case NodeTypeArrayAccessExpr:
@ -1108,7 +1108,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
fprintf(ar->f, "]");
break;
}
case NodeTypeUnwrapErrorExpr:
case NodeTypeCatchExpr:
{
render_node_ungrouped(ar, node->data.unwrap_err_expr.op1);
fprintf(ar->f, " catch ");

File diff suppressed because it is too large Load Diff

4646
src/ir.cpp

File diff suppressed because it is too large Load Diff

View File

@ -57,13 +57,18 @@ static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction)
}
static void ir_print_other_block(IrPrint *irp, IrBasicBlock *bb) {
fprintf(irp->f, "$%s_%" ZIG_PRI_usize "", bb->name_hint, bb->debug_id);
if (bb == nullptr) {
fprintf(irp->f, "(null block)");
} else {
fprintf(irp->f, "$%s_%" ZIG_PRI_usize "", bb->name_hint, bb->debug_id);
}
}
static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instruction) {
assert(return_instruction->value);
fprintf(irp->f, "return ");
ir_print_other_instruction(irp, return_instruction->value);
if (return_instruction->value != nullptr) {
ir_print_other_instruction(irp, return_instruction->value);
}
}
static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) {
@ -188,7 +193,7 @@ static void ir_print_decl_var_src(IrPrint *irp, IrInstructionDeclVarSrc *decl_va
fprintf(irp->f, " ");
}
fprintf(irp->f, "= ");
ir_print_other_instruction(irp, decl_var_instruction->init_value);
ir_print_other_instruction(irp, decl_var_instruction->ptr);
if (decl_var_instruction->var->is_comptime != nullptr) {
fprintf(irp->f, " // comptime = ");
ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime);
@ -201,7 +206,56 @@ static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) {
fprintf(irp->f, " to %s", buf_ptr(&cast_instruction->dest_type->name));
}
static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {
static void ir_print_result_loc_var(IrPrint *irp, ResultLocVar *result_loc_var) {
fprintf(irp->f, "var(");
ir_print_other_instruction(irp, result_loc_var->base.source_instruction);
fprintf(irp->f, ")");
}
static void ir_print_result_loc_instruction(IrPrint *irp, ResultLocInstruction *result_loc_inst) {
fprintf(irp->f, "inst(");
ir_print_other_instruction(irp, result_loc_inst->base.source_instruction);
fprintf(irp->f, ")");
}
static void ir_print_result_loc_peer(IrPrint *irp, ResultLocPeer *result_loc_peer) {
fprintf(irp->f, "peer(next=");
ir_print_other_block(irp, result_loc_peer->next_bb);
fprintf(irp->f, ")");
}
static void ir_print_result_loc_bit_cast(IrPrint *irp, ResultLocBitCast *result_loc_bit_cast) {
fprintf(irp->f, "bitcast(ty=");
ir_print_other_instruction(irp, result_loc_bit_cast->base.source_instruction);
fprintf(irp->f, ")");
}
static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) {
switch (result_loc->id) {
case ResultLocIdInvalid:
zig_unreachable();
case ResultLocIdNone:
fprintf(irp->f, "none");
return;
case ResultLocIdReturn:
fprintf(irp->f, "return");
return;
case ResultLocIdVar:
return ir_print_result_loc_var(irp, (ResultLocVar *)result_loc);
case ResultLocIdInstruction:
return ir_print_result_loc_instruction(irp, (ResultLocInstruction *)result_loc);
case ResultLocIdPeer:
return ir_print_result_loc_peer(irp, (ResultLocPeer *)result_loc);
case ResultLocIdBitCast:
return ir_print_result_loc_bit_cast(irp, (ResultLocBitCast *)result_loc);
case ResultLocIdPeerParent:
fprintf(irp->f, "peer_parent");
return;
}
zig_unreachable();
}
static void ir_print_call_src(IrPrint *irp, IrInstructionCallSrc *call_instruction) {
if (call_instruction->is_async) {
fprintf(irp->f, "async");
if (call_instruction->async_allocator != nullptr) {
@ -224,7 +278,35 @@ static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {
fprintf(irp->f, ", ");
ir_print_other_instruction(irp, arg);
}
fprintf(irp->f, ")");
fprintf(irp->f, ")result=");
ir_print_result_loc(irp, call_instruction->result_loc);
}
static void ir_print_call_gen(IrPrint *irp, IrInstructionCallGen *call_instruction) {
if (call_instruction->is_async) {
fprintf(irp->f, "async");
if (call_instruction->async_allocator != nullptr) {
fprintf(irp->f, "<");
ir_print_other_instruction(irp, call_instruction->async_allocator);
fprintf(irp->f, ">");
}
fprintf(irp->f, " ");
}
if (call_instruction->fn_entry) {
fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name));
} else {
assert(call_instruction->fn_ref);
ir_print_other_instruction(irp, call_instruction->fn_ref);
}
fprintf(irp->f, "(");
for (size_t i = 0; i < call_instruction->arg_count; i += 1) {
IrInstruction *arg = call_instruction->args[i];
if (i != 0)
fprintf(irp->f, ", ");
ir_print_other_instruction(irp, arg);
}
fprintf(irp->f, ")result=");
ir_print_other_instruction(irp, call_instruction->result_loc);
}
static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) {
@ -270,10 +352,10 @@ static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerIni
fprintf(irp->f, "...(%" ZIG_PRI_usize " items)...", instruction->item_count);
} else {
for (size_t i = 0; i < instruction->item_count; i += 1) {
IrInstruction *item = instruction->items[i];
IrInstruction *result_loc = instruction->elem_result_loc_list[i];
if (i != 0)
fprintf(irp->f, ", ");
ir_print_other_instruction(irp, item);
ir_print_other_instruction(irp, result_loc);
}
}
fprintf(irp->f, "}");
@ -286,32 +368,11 @@ static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerI
IrInstructionContainerInitFieldsField *field = &instruction->fields[i];
const char *comma = (i == 0) ? "" : ", ";
fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field->name));
ir_print_other_instruction(irp, field->value);
ir_print_other_instruction(irp, field->result_loc);
}
fprintf(irp->f, "} // container init");
}
static void ir_print_struct_init(IrPrint *irp, IrInstructionStructInit *instruction) {
fprintf(irp->f, "%s {", buf_ptr(&instruction->struct_type->name));
for (size_t i = 0; i < instruction->field_count; i += 1) {
IrInstructionStructInitField *field = &instruction->fields[i];
Buf *field_name = field->type_struct_field->name;
const char *comma = (i == 0) ? "" : ", ";
fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field_name));
ir_print_other_instruction(irp, field->value);
}
fprintf(irp->f, "} // struct init");
}
static void ir_print_union_init(IrPrint *irp, IrInstructionUnionInit *instruction) {
Buf *field_name = instruction->field->enum_field->name;
fprintf(irp->f, "%s {", buf_ptr(&instruction->union_type->name));
fprintf(irp->f, ".%s = ", buf_ptr(field_name));
ir_print_other_instruction(irp, instruction->init_value);
fprintf(irp->f, "} // union init");
}
static void ir_print_unreachable(IrPrint *irp, IrInstructionUnreachable *instruction) {
fprintf(irp->f, "unreachable");
}
@ -331,14 +392,20 @@ static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) {
fprintf(irp->f, "&%s", buf_ptr(&instruction->var->name));
}
static void ir_print_return_ptr(IrPrint *irp, IrInstructionReturnPtr *instruction) {
fprintf(irp->f, "@ReturnPtr");
}
static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {
ir_print_other_instruction(irp, instruction->ptr);
fprintf(irp->f, ".*");
}
static void ir_print_load_ptr_gen(IrPrint *irp, IrInstructionLoadPtrGen *instruction) {
fprintf(irp->f, "loadptr(");
ir_print_other_instruction(irp, instruction->ptr);
fprintf(irp->f, ".*");
fprintf(irp->f, ")result=");
ir_print_other_instruction(irp, instruction->result_loc);
}
static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {
@ -354,18 +421,6 @@ static void ir_print_typeof(IrPrint *irp, IrInstructionTypeOf *instruction) {
fprintf(irp->f, ")");
}
static void ir_print_to_ptr_type(IrPrint *irp, IrInstructionToPtrType *instruction) {
fprintf(irp->f, "@toPtrType(");
ir_print_other_instruction(irp, instruction->ptr);
fprintf(irp->f, ")");
}
static void ir_print_ptr_type_child(IrPrint *irp, IrInstructionPtrTypeChild *instruction) {
fprintf(irp->f, "@ptrTypeChild(");
ir_print_other_instruction(irp, instruction->value);
fprintf(irp->f, ")");
}
static void ir_print_field_ptr(IrPrint *irp, IrInstructionFieldPtr *instruction) {
if (instruction->field_name_buffer) {
fprintf(irp->f, "fieldptr ");
@ -618,6 +673,13 @@ static void ir_print_ref(IrPrint *irp, IrInstructionRef *instruction) {
ir_print_other_instruction(irp, instruction->value);
}
static void ir_print_ref_gen(IrPrint *irp, IrInstructionRefGen *instruction) {
fprintf(irp->f, "@ref(");
ir_print_other_instruction(irp, instruction->operand);
fprintf(irp->f, ")result=");
ir_print_other_instruction(irp, instruction->result_loc);
}
static void ir_print_compile_err(IrPrint *irp, IrInstructionCompileErr *instruction) {
fprintf(irp->f, "@compileError(");
ir_print_other_instruction(irp, instruction->msg);
@ -682,7 +744,8 @@ static void ir_print_cmpxchg_src(IrPrint *irp, IrInstructionCmpxchgSrc *instruct
ir_print_other_instruction(irp, instruction->success_order_value);
fprintf(irp->f, ", ");
ir_print_other_instruction(irp, instruction->failure_order_value);
fprintf(irp->f, ")");
fprintf(irp->f, ")result=");
ir_print_result_loc(irp, instruction->result_loc);
}
static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruction) {
@ -692,7 +755,8 @@ static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruct
ir_print_other_instruction(irp, instruction->cmp_value);
fprintf(irp->f, ", ");
ir_print_other_instruction(irp, instruction->new_value);
fprintf(irp->f, ", TODO print atomic orders)");
fprintf(irp->f, ", TODO print atomic orders)result=");
ir_print_other_instruction(irp, instruction->result_loc);
}
static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) {
@ -810,14 +874,26 @@ static void ir_print_memcpy(IrPrint *irp, IrInstructionMemcpy *instruction) {
fprintf(irp->f, ")");
}
static void ir_print_slice(IrPrint *irp, IrInstructionSlice *instruction) {
static void ir_print_slice_src(IrPrint *irp, IrInstructionSliceSrc *instruction) {
ir_print_other_instruction(irp, instruction->ptr);
fprintf(irp->f, "[");
ir_print_other_instruction(irp, instruction->start);
fprintf(irp->f, "..");
if (instruction->end)
ir_print_other_instruction(irp, instruction->end);
fprintf(irp->f, "]");
fprintf(irp->f, "]result=");
ir_print_result_loc(irp, instruction->result_loc);
}
static void ir_print_slice_gen(IrPrint *irp, IrInstructionSliceGen *instruction) {
ir_print_other_instruction(irp, instruction->ptr);
fprintf(irp->f, "[");
ir_print_other_instruction(irp, instruction->start);
fprintf(irp->f, "..");
if (instruction->end)
ir_print_other_instruction(irp, instruction->end);
fprintf(irp->f, "]result=");
ir_print_other_instruction(irp, instruction->result_loc);
}
static void ir_print_member_count(IrPrint *irp, IrInstructionMemberCount *instruction) {
@ -889,43 +965,49 @@ static void ir_print_overflow_op(IrPrint *irp, IrInstructionOverflowOp *instruct
fprintf(irp->f, ")");
}
static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) {
static void ir_print_test_err_src(IrPrint *irp, IrInstructionTestErrSrc *instruction) {
fprintf(irp->f, "@testError(");
ir_print_other_instruction(irp, instruction->value);
ir_print_other_instruction(irp, instruction->base_ptr);
fprintf(irp->f, ")");
}
static void ir_print_test_err_gen(IrPrint *irp, IrInstructionTestErrGen *instruction) {
fprintf(irp->f, "@testError(");
ir_print_other_instruction(irp, instruction->err_union);
fprintf(irp->f, ")");
}
static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) {
fprintf(irp->f, "UnwrapErrorCode(");
ir_print_other_instruction(irp, instruction->err_union);
ir_print_other_instruction(irp, instruction->err_union_ptr);
fprintf(irp->f, ")");
}
static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) {
fprintf(irp->f, "ErrorUnionFieldPayload(");
ir_print_other_instruction(irp, instruction->value);
fprintf(irp->f, ")");
if (!instruction->safety_check_on) {
fprintf(irp->f, " // no safety");
}
fprintf(irp->f, ")safety=%d,init=%d",instruction->safety_check_on, instruction->initializing);
}
static void ir_print_maybe_wrap(IrPrint *irp, IrInstructionOptionalWrap *instruction) {
fprintf(irp->f, "@maybeWrap(");
ir_print_other_instruction(irp, instruction->value);
fprintf(irp->f, ")");
static void ir_print_optional_wrap(IrPrint *irp, IrInstructionOptionalWrap *instruction) {
fprintf(irp->f, "@optionalWrap(");
ir_print_other_instruction(irp, instruction->operand);
fprintf(irp->f, ")result=");
ir_print_other_instruction(irp, instruction->result_loc);
}
static void ir_print_err_wrap_code(IrPrint *irp, IrInstructionErrWrapCode *instruction) {
fprintf(irp->f, "@errWrapCode(");
ir_print_other_instruction(irp, instruction->value);
fprintf(irp->f, ")");
ir_print_other_instruction(irp, instruction->operand);
fprintf(irp->f, ")result=");
ir_print_other_instruction(irp, instruction->result_loc);
}
static void ir_print_err_wrap_payload(IrPrint *irp, IrInstructionErrWrapPayload *instruction) {
fprintf(irp->f, "@errWrapPayload(");
ir_print_other_instruction(irp, instruction->value);
fprintf(irp->f, ")");
ir_print_other_instruction(irp, instruction->operand);
fprintf(irp->f, ")result=");
ir_print_other_instruction(irp, instruction->result_loc);
}
static void ir_print_fn_proto(IrPrint *irp, IrInstructionFnProto *instruction) {
@ -971,12 +1053,11 @@ static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruc
fprintf(irp->f, ")");
}
static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
static void ir_print_bit_cast_src(IrPrint *irp, IrInstructionBitCastSrc *instruction) {
fprintf(irp->f, "@bitCast(");
ir_print_other_instruction(irp, instruction->dest_type);
fprintf(irp->f, ",");
ir_print_other_instruction(irp, instruction->value);
fprintf(irp->f, ")");
ir_print_other_instruction(irp, instruction->operand);
fprintf(irp->f, ")result=");
ir_print_result_loc(irp, &instruction->result_loc_bit_cast->base);
}
static void ir_print_bit_cast_gen(IrPrint *irp, IrInstructionBitCastGen *instruction) {
@ -1043,7 +1124,15 @@ static void ir_print_array_to_vector(IrPrint *irp, IrInstructionArrayToVector *i
static void ir_print_vector_to_array(IrPrint *irp, IrInstructionVectorToArray *instruction) {
fprintf(irp->f, "VectorToArray(");
ir_print_other_instruction(irp, instruction->vector);
fprintf(irp->f, ")");
fprintf(irp->f, ")result=");
ir_print_other_instruction(irp, instruction->result_loc);
}
static void ir_print_ptr_of_array_to_slice(IrPrint *irp, IrInstructionPtrOfArrayToSlice *instruction) {
fprintf(irp->f, "PtrOfArrayToSlice(");
ir_print_other_instruction(irp, instruction->operand);
fprintf(irp->f, ")result=");
ir_print_other_instruction(irp, instruction->result_loc);
}
static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruction) {
@ -1061,6 +1150,25 @@ static void ir_print_assert_non_null(IrPrint *irp, IrInstructionAssertNonNull *i
static void ir_print_resize_slice(IrPrint *irp, IrInstructionResizeSlice *instruction) {
fprintf(irp->f, "@resizeSlice(");
ir_print_other_instruction(irp, instruction->operand);
fprintf(irp->f, ")result=");
ir_print_other_instruction(irp, instruction->result_loc);
}
static void ir_print_alloca_src(IrPrint *irp, IrInstructionAllocaSrc *instruction) {
fprintf(irp->f, "Alloca(align=");
ir_print_other_instruction(irp, instruction->align);
fprintf(irp->f, ",name=%s)", instruction->name_hint);
}
static void ir_print_alloca_gen(IrPrint *irp, IrInstructionAllocaGen *instruction) {
fprintf(irp->f, "Alloca(align=%" PRIu32 ",name=%s)", instruction->align, instruction->name_hint);
}
static void ir_print_end_expr(IrPrint *irp, IrInstructionEndExpr *instruction) {
fprintf(irp->f, "EndExpr(result=");
ir_print_result_loc(irp, instruction->result_loc);
fprintf(irp->f, ",value=");
ir_print_other_instruction(irp, instruction->value);
fprintf(irp->f, ")");
}
@ -1186,6 +1294,34 @@ static void ir_print_align_cast(IrPrint *irp, IrInstructionAlignCast *instructio
fprintf(irp->f, ")");
}
static void ir_print_implicit_cast(IrPrint *irp, IrInstructionImplicitCast *instruction) {
fprintf(irp->f, "@implicitCast(");
ir_print_other_instruction(irp, instruction->dest_type);
fprintf(irp->f, ",");
ir_print_other_instruction(irp, instruction->target);
fprintf(irp->f, ")");
}
static void ir_print_resolve_result(IrPrint *irp, IrInstructionResolveResult *instruction) {
fprintf(irp->f, "ResolveResult(");
ir_print_result_loc(irp, instruction->result_loc);
fprintf(irp->f, ")");
}
static void ir_print_reset_result(IrPrint *irp, IrInstructionResetResult *instruction) {
fprintf(irp->f, "ResetResult(");
ir_print_result_loc(irp, instruction->result_loc);
fprintf(irp->f, ")");
}
static void ir_print_result_ptr(IrPrint *irp, IrInstructionResultPtr *instruction) {
fprintf(irp->f, "ResultPtr(");
ir_print_result_loc(irp, instruction->result_loc);
fprintf(irp->f, ",");
ir_print_other_instruction(irp, instruction->result);
fprintf(irp->f, ")");
}
static void ir_print_opaque_type(IrPrint *irp, IrInstructionOpaqueType *instruction) {
fprintf(irp->f, "@OpaqueType()");
}
@ -1463,7 +1599,7 @@ static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_va
fprintf(irp->f, "%s %s: %s align(%u) = ", var_or_const, name, buf_ptr(&var->var_type->name),
var->align_bytes);
ir_print_other_instruction(irp, decl_var_instruction->init_value);
ir_print_other_instruction(irp, decl_var_instruction->var_ptr);
if (decl_var_instruction->var->is_comptime != nullptr) {
fprintf(irp->f, " // comptime = ");
ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime);
@ -1502,8 +1638,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdCast:
ir_print_cast(irp, (IrInstructionCast *)instruction);
break;
case IrInstructionIdCall:
ir_print_call(irp, (IrInstructionCall *)instruction);
case IrInstructionIdCallSrc:
ir_print_call_src(irp, (IrInstructionCallSrc *)instruction);
break;
case IrInstructionIdCallGen:
ir_print_call_gen(irp, (IrInstructionCallGen *)instruction);
break;
case IrInstructionIdUnOp:
ir_print_un_op(irp, (IrInstructionUnOp *)instruction);
@ -1523,12 +1662,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdContainerInitFields:
ir_print_container_init_fields(irp, (IrInstructionContainerInitFields *)instruction);
break;
case IrInstructionIdStructInit:
ir_print_struct_init(irp, (IrInstructionStructInit *)instruction);
break;
case IrInstructionIdUnionInit:
ir_print_union_init(irp, (IrInstructionUnionInit *)instruction);
break;
case IrInstructionIdUnreachable:
ir_print_unreachable(irp, (IrInstructionUnreachable *)instruction);
break;
@ -1538,6 +1671,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdVarPtr:
ir_print_var_ptr(irp, (IrInstructionVarPtr *)instruction);
break;
case IrInstructionIdReturnPtr:
ir_print_return_ptr(irp, (IrInstructionReturnPtr *)instruction);
break;
case IrInstructionIdLoadPtr:
ir_print_load_ptr(irp, (IrInstructionLoadPtr *)instruction);
break;
@ -1550,12 +1686,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdTypeOf:
ir_print_typeof(irp, (IrInstructionTypeOf *)instruction);
break;
case IrInstructionIdToPtrType:
ir_print_to_ptr_type(irp, (IrInstructionToPtrType *)instruction);
break;
case IrInstructionIdPtrTypeChild:
ir_print_ptr_type_child(irp, (IrInstructionPtrTypeChild *)instruction);
break;
case IrInstructionIdFieldPtr:
ir_print_field_ptr(irp, (IrInstructionFieldPtr *)instruction);
break;
@ -1634,6 +1764,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdRef:
ir_print_ref(irp, (IrInstructionRef *)instruction);
break;
case IrInstructionIdRefGen:
ir_print_ref_gen(irp, (IrInstructionRefGen *)instruction);
break;
case IrInstructionIdCompileErr:
ir_print_compile_err(irp, (IrInstructionCompileErr *)instruction);
break;
@ -1709,8 +1842,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdMemcpy:
ir_print_memcpy(irp, (IrInstructionMemcpy *)instruction);
break;
case IrInstructionIdSlice:
ir_print_slice(irp, (IrInstructionSlice *)instruction);
case IrInstructionIdSliceSrc:
ir_print_slice_src(irp, (IrInstructionSliceSrc *)instruction);
break;
case IrInstructionIdSliceGen:
ir_print_slice_gen(irp, (IrInstructionSliceGen *)instruction);
break;
case IrInstructionIdMemberCount:
ir_print_member_count(irp, (IrInstructionMemberCount *)instruction);
@ -1739,8 +1875,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdOverflowOp:
ir_print_overflow_op(irp, (IrInstructionOverflowOp *)instruction);
break;
case IrInstructionIdTestErr:
ir_print_test_err(irp, (IrInstructionTestErr *)instruction);
case IrInstructionIdTestErrSrc:
ir_print_test_err_src(irp, (IrInstructionTestErrSrc *)instruction);
break;
case IrInstructionIdTestErrGen:
ir_print_test_err_gen(irp, (IrInstructionTestErrGen *)instruction);
break;
case IrInstructionIdUnwrapErrCode:
ir_print_unwrap_err_code(irp, (IrInstructionUnwrapErrCode *)instruction);
@ -1749,7 +1888,7 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
ir_print_unwrap_err_payload(irp, (IrInstructionUnwrapErrPayload *)instruction);
break;
case IrInstructionIdOptionalWrap:
ir_print_maybe_wrap(irp, (IrInstructionOptionalWrap *)instruction);
ir_print_optional_wrap(irp, (IrInstructionOptionalWrap *)instruction);
break;
case IrInstructionIdErrWrapCode:
ir_print_err_wrap_code(irp, (IrInstructionErrWrapCode *)instruction);
@ -1769,8 +1908,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdPtrCastGen:
ir_print_ptr_cast_gen(irp, (IrInstructionPtrCastGen *)instruction);
break;
case IrInstructionIdBitCast:
ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);
case IrInstructionIdBitCastSrc:
ir_print_bit_cast_src(irp, (IrInstructionBitCastSrc *)instruction);
break;
case IrInstructionIdBitCastGen:
ir_print_bit_cast_gen(irp, (IrInstructionBitCastGen *)instruction);
@ -1835,6 +1974,18 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdAlignCast:
ir_print_align_cast(irp, (IrInstructionAlignCast *)instruction);
break;
case IrInstructionIdImplicitCast:
ir_print_implicit_cast(irp, (IrInstructionImplicitCast *)instruction);
break;
case IrInstructionIdResolveResult:
ir_print_resolve_result(irp, (IrInstructionResolveResult *)instruction);
break;
case IrInstructionIdResetResult:
ir_print_reset_result(irp, (IrInstructionResetResult *)instruction);
break;
case IrInstructionIdResultPtr:
ir_print_result_ptr(irp, (IrInstructionResultPtr *)instruction);
break;
case IrInstructionIdOpaqueType:
ir_print_opaque_type(irp, (IrInstructionOpaqueType *)instruction);
break;
@ -1943,6 +2094,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdVectorToArray:
ir_print_vector_to_array(irp, (IrInstructionVectorToArray *)instruction);
break;
case IrInstructionIdPtrOfArrayToSlice:
ir_print_ptr_of_array_to_slice(irp, (IrInstructionPtrOfArrayToSlice *)instruction);
break;
case IrInstructionIdAssertZero:
ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction);
break;
@ -1958,6 +2112,15 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdUndeclaredIdent:
ir_print_undeclared_ident(irp, (IrInstructionUndeclaredIdent *)instruction);
break;
case IrInstructionIdAllocaSrc:
ir_print_alloca_src(irp, (IrInstructionAllocaSrc *)instruction);
break;
case IrInstructionIdAllocaGen:
ir_print_alloca_gen(irp, (IrInstructionAllocaGen *)instruction);
break;
case IrInstructionIdEndExpr:
ir_print_end_expr(irp, (IrInstructionEndExpr *)instruction);
break;
}
fprintf(irp->f, "\n");
}

View File

@ -344,7 +344,7 @@ static AstNode *ast_parse_bin_op_expr(
op->data.bin_op_expr.op1 = left;
op->data.bin_op_expr.op2 = right;
break;
case NodeTypeUnwrapErrorExpr:
case NodeTypeCatchExpr:
op->data.unwrap_err_expr.op1 = left;
op->data.unwrap_err_expr.op2 = right;
break;
@ -2404,7 +2404,7 @@ static AstNode *ast_parse_bitwise_op(ParseContext *pc) {
Token *catch_token = eat_token_if(pc, TokenIdKeywordCatch);
if (catch_token != nullptr) {
Token *payload = ast_parse_payload(pc);
AstNode *res = ast_create_node(pc, NodeTypeUnwrapErrorExpr, catch_token);
AstNode *res = ast_create_node(pc, NodeTypeCatchExpr, catch_token);
if (payload != nullptr)
res->data.unwrap_err_expr.symbol = token_symbol(pc, payload);
@ -2897,7 +2897,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
visit_field(&node->data.bin_op_expr.op1, visit, context);
visit_field(&node->data.bin_op_expr.op2, visit, context);
break;
case NodeTypeUnwrapErrorExpr:
case NodeTypeCatchExpr:
visit_field(&node->data.unwrap_err_expr.op1, visit, context);
visit_field(&node->data.unwrap_err_expr.symbol, visit, context);
visit_field(&node->data.unwrap_err_expr.op2, visit, context);

View File

@ -1290,10 +1290,9 @@ pub fn Watch(comptime V: type) type {
error.FileDescriptorAlreadyPresentInSet => unreachable,
error.OperationCausesCircularLoop => unreachable,
error.FileDescriptorNotRegistered => unreachable,
error.SystemResources => error.SystemResources,
error.UserResourceLimitReached => error.UserResourceLimitReached,
error.FileDescriptorIncompatibleWithEpoll => unreachable,
error.Unexpected => unreachable,
else => |e| e,
};
await (async channel.put(transformed_err) catch unreachable);
};

View File

@ -123,7 +123,6 @@ pub const Lock = struct {
};
test "std.event.Lock" {
// https://github.com/ziglang/zig/issues/1908
if (builtin.single_threaded) return error.SkipZigTest;
const allocator = std.heap.direct_allocator;

View File

@ -263,8 +263,8 @@ pub async fn connect(loop: *Loop, _address: *const std.net.Address) !File {
}
test "listen on a port, send bytes, receive bytes" {
// https://github.com/ziglang/zig/issues/1908
if (builtin.single_threaded) return error.SkipZigTest;
// https://github.com/ziglang/zig/issues/2377
if (true) return error.SkipZigTest;
if (builtin.os != builtin.Os.linux) {
// TODO build abstractions for other operating systems

View File

@ -212,8 +212,8 @@ pub const RwLock = struct {
};
test "std.event.RwLock" {
// https://github.com/ziglang/zig/issues/1908
if (builtin.single_threaded or builtin.os != builtin.Os.linux) return error.SkipZigTest;
// https://github.com/ziglang/zig/issues/2377
if (true) return error.SkipZigTest;
const allocator = std.heap.direct_allocator;

View File

@ -360,9 +360,9 @@ pub const ArenaAllocator = struct {
var it = self.buffer_list.first;
while (it) |node| {
// this has to occur before the free because the free frees node
it = node.next;
const next_it = node.next;
self.child_allocator.free(node.data);
it = next_it;
}
}

View File

@ -164,32 +164,32 @@ pub fn InStream(comptime ReadError: type) type {
/// Reads a native-endian integer
pub fn readIntNative(self: *Self, comptime T: type) !T {
var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
try self.readNoEof(bytes[0..]);
return mem.readIntNative(T, &bytes);
}
/// Reads a foreign-endian integer
pub fn readIntForeign(self: *Self, comptime T: type) !T {
var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
try self.readNoEof(bytes[0..]);
return mem.readIntForeign(T, &bytes);
}
pub fn readIntLittle(self: *Self, comptime T: type) !T {
var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
try self.readNoEof(bytes[0..]);
return mem.readIntLittle(T, &bytes);
}
pub fn readIntBig(self: *Self, comptime T: type) !T {
var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
try self.readNoEof(bytes[0..]);
return mem.readIntBig(T, &bytes);
}
pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {
var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
try self.readNoEof(bytes[0..]);
return mem.readInt(T, &bytes, endian);
}
@ -249,32 +249,32 @@ pub fn OutStream(comptime WriteError: type) type {
/// Write a native-endian integer.
pub fn writeIntNative(self: *Self, comptime T: type, value: T) Error!void {
var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
mem.writeIntNative(T, &bytes, value);
return self.writeFn(self, bytes);
}
/// Write a foreign-endian integer.
pub fn writeIntForeign(self: *Self, comptime T: type, value: T) Error!void {
var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
mem.writeIntForeign(T, &bytes, value);
return self.writeFn(self, bytes);
}
pub fn writeIntLittle(self: *Self, comptime T: type, value: T) Error!void {
var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
mem.writeIntLittle(T, &bytes, value);
return self.writeFn(self, bytes);
}
pub fn writeIntBig(self: *Self, comptime T: type, value: T) Error!void {
var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
mem.writeIntBig(T, &bytes, value);
return self.writeFn(self, bytes);
}
pub fn writeInt(self: *Self, comptime T: type, value: T, endian: builtin.Endian) Error!void {
var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
mem.writeInt(T, &bytes, value, endian);
return self.writeFn(self, bytes);
}

View File

@ -597,7 +597,10 @@ test "c out stream" {
const filename = c"tmp_io_test_file.txt";
const out_file = std.c.fopen(filename, c"w") orelse return error.UnableToOpenTestFile;
defer fs.deleteFileC(filename) catch {};
defer {
_ = std.c.fclose(out_file);
fs.deleteFileC(filename) catch {};
}
const out_stream = &io.COutStream.init(out_file).stream;
try out_stream.print("hi: {}\n", i32(123));

View File

@ -876,8 +876,9 @@ pub const TokenStream = struct {
pub fn next(self: *TokenStream) !?Token {
if (self.token) |token| {
const copy = token;
self.token = null;
return token;
return copy;
}
var t1: ?Token = undefined;

View File

@ -348,6 +348,7 @@ pub const DeleteFileError = error{
FileNotFound,
AccessDenied,
NameTooLong,
FileBusy,
Unexpected,
};
@ -363,6 +364,7 @@ pub fn DeleteFileW(filename: [*]const u16) DeleteFileError!void {
ERROR.ACCESS_DENIED => return error.AccessDenied,
ERROR.FILENAME_EXCED_RANGE => return error.NameTooLong,
ERROR.INVALID_PARAMETER => return error.NameTooLong,
ERROR.SHARING_VIOLATION => return error.FileBusy,
else => |err| return unexpectedError(err),
}
}

View File

@ -114,20 +114,20 @@ extern fn main(c_argc: i32, c_argv: [*][*]u8, c_envp: [*]?[*]u8) i32 {
// and we want fewer call frames in stack traces.
inline fn callMain() u8 {
switch (@typeId(@typeOf(root.main).ReturnType)) {
builtin.TypeId.NoReturn => {
.NoReturn => {
root.main();
},
builtin.TypeId.Void => {
.Void => {
root.main();
return 0;
},
builtin.TypeId.Int => {
.Int => {
if (@typeOf(root.main).ReturnType.bit_count != 8) {
@compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'");
}
return root.main();
},
builtin.TypeId.ErrorUnion => {
.ErrorUnion => {
root.main() catch |err| {
std.debug.warn("error: {}\n", @errorName(err));
if (builtin.os != builtin.Os.zen) {

View File

@ -73,12 +73,15 @@ pub extern fn __getf2(a: f128, b: f128) c_int {
if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED;
if ((aAbs | bAbs) == 0) return GE_EQUAL;
return if ((aInt & bInt) >= 0) if (aInt < bInt)
GE_LESS
else if (aInt == bInt)
GE_EQUAL
else
GE_GREATER else if (aInt > bInt)
// zig fmt issue here, see https://github.com/ziglang/zig/issues/2661
return if ((aInt & bInt) >= 0)
if (aInt < bInt)
GE_LESS
else if (aInt == bInt)
GE_EQUAL
else
GE_GREATER
else if (aInt > bInt)
GE_LESS
else if (aInt == bInt)
GE_EQUAL

View File

@ -9,16 +9,15 @@ const std = @import("std");
pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {
@setCold(true);
switch (builtin.os) {
// TODO: fix panic in zen
builtin.Os.freestanding, builtin.Os.zen => {
.freestanding => {
while (true) {}
},
builtin.Os.wasi => {
.wasi => {
std.debug.warn("{}", msg);
_ = std.os.wasi.proc_raise(std.os.wasi.SIGABRT);
unreachable;
},
builtin.Os.uefi => {
.uefi => {
// TODO look into using the debug info and logging helpful messages
std.os.abort();
},

View File

@ -1,4 +1,4 @@
// TODO remove `use` keyword eventually
// TODO remove `use` keyword eventually: https://github.com/ziglang/zig/issues/2591
test "zig fmt: change use to usingnamespace" {
try testTransform(
\\use @import("std");
@ -1105,7 +1105,7 @@ test "zig fmt: first line comment in struct initializer" {
try testCanonical(
\\pub async fn acquire(self: *Self) HeldLock {
\\ return HeldLock{
\\ // TODO guaranteed allocation elision
\\ // guaranteed allocation elision
\\ .held = await (async self.lock.acquire() catch unreachable),
\\ .value = &self.private_data,
\\ };

View File

@ -939,10 +939,10 @@ fn renderExpression(
}
switch (container_decl.init_arg_expr) {
ast.Node.ContainerDecl.InitArg.None => {
.None => {
try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.Space); // union
},
ast.Node.ContainerDecl.InitArg.Enum => |enum_tag_type| {
.Enum => |enum_tag_type| {
try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.None); // union
const lparen = tree.nextToken(container_decl.kind_token);
@ -962,7 +962,7 @@ fn renderExpression(
try renderToken(tree, stream, tree.nextToken(enum_token), indent, start_col, Space.Space); // )
}
},
ast.Node.ContainerDecl.InitArg.Type => |type_expr| {
.Type => |type_expr| {
try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.None); // union
const lparen = tree.nextToken(container_decl.kind_token);

View File

@ -49,16 +49,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\const Foo = struct {
\\ a: undefined,
\\};
\\const Bar = union {
\\ a: undefined,
\\};
\\pub fn main() void {
\\export fn entry1() void {
\\ const foo: Foo = undefined;
\\ const bar: Bar = undefined;
\\}
,
"tmp.zig:2:8: error: expected type 'type', found '(undefined)'",
"tmp.zig:5:8: error: expected type 'type', found '(undefined)'",
);
cases.add(
@ -461,13 +456,25 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\const G = packed struct {
\\ x: Enum,
\\};
\\export fn entry() void {
\\export fn entry1() void {
\\ var a: A = undefined;
\\}
\\export fn entry2() void {
\\ var b: B = undefined;
\\}
\\export fn entry3() void {
\\ var r: C = undefined;
\\}
\\export fn entry4() void {
\\ var d: D = undefined;
\\}
\\export fn entry5() void {
\\ var e: E = undefined;
\\}
\\export fn entry6() void {
\\ var f: F = undefined;
\\}
\\export fn entry7() void {
\\ var g: G = undefined;
\\}
\\const S = struct {
@ -489,7 +496,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:14:5: error: non-packed, non-extern struct 'U' not allowed in packed struct; no guaranteed in-memory representation",
"tmp.zig:17:5: error: type '?anyerror' not allowed in packed struct; no guaranteed in-memory representation",
"tmp.zig:20:5: error: type 'Enum' not allowed in packed struct; no guaranteed in-memory representation",
"tmp.zig:38:14: note: enum declaration does not specify an integer tag type",
"tmp.zig:50:14: note: enum declaration does not specify an integer tag type",
);
cases.addCase(x: {
@ -721,7 +728,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ var oops = @bitCast(u7, byte);
\\}
,
"tmp.zig:2:16: error: destination type 'u7' has 7 bits but source type 'u8' has 8 bits",
"tmp.zig:2:25: error: destination type 'u7' has 7 bits but source type 'u8' has 8 bits",
);
cases.add(
@ -1381,7 +1388,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ for (xx) |f| {}
\\}
,
"tmp.zig:7:15: error: variable of type 'Foo' must be const or comptime",
"tmp.zig:7:5: error: values of type 'Foo' must be comptime known, but index value is runtime known",
);
cases.add(
@ -2250,6 +2257,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\}
\\
\\extern fn bar(x: *void) void { }
\\export fn entry2() void {
\\ bar(&{});
\\}
,
"tmp.zig:1:30: error: parameter of type '*void' has 0 bits; not allowed in function with calling convention 'ccc'",
"tmp.zig:7:18: error: parameter of type '*void' has 0 bits; not allowed in function with calling convention 'ccc'",
@ -2576,7 +2586,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\
\\fn b() void {}
,
"tmp.zig:3:5: error: unreachable code",
"tmp.zig:3:6: error: unreachable code",
);
cases.add(
@ -2596,7 +2606,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\}
,
"tmp.zig:3:5: error: use of undeclared identifier 'b'",
"tmp.zig:4:5: error: use of undeclared identifier 'c'",
);
cases.add(
@ -2662,7 +2671,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ const a: noreturn = {};
\\}
,
"tmp.zig:2:14: error: variable of type 'noreturn' not allowed",
"tmp.zig:2:25: error: expected type 'noreturn', found 'void'",
);
cases.add(
@ -2725,9 +2734,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ var bad : bool = undefined;
\\ bad[bad] = bad[bad];
\\}
\\export fn g() void {
\\ var bad : bool = undefined;
\\ _ = bad[bad];
\\}
,
"tmp.zig:3:8: error: array access of non-array type 'bool'",
"tmp.zig:3:19: error: array access of non-array type 'bool'",
"tmp.zig:7:12: error: array access of non-array type 'bool'",
);
cases.add(
@ -2737,9 +2750,14 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ var bad = false;
\\ array[bad] = array[bad];
\\}
\\export fn g() void {
\\ var array = "aoeu";
\\ var bad = false;
\\ _ = array[bad];
\\}
,
"tmp.zig:4:11: error: expected type 'usize', found 'bool'",
"tmp.zig:4:24: error: expected type 'usize', found 'bool'",
"tmp.zig:9:15: error: expected type 'usize', found 'bool'",
);
cases.add(
@ -2757,12 +2775,14 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"missing else clause",
\\fn f(b: bool) void {
\\ const x : i32 = if (b) h: { break :h 1; };
\\}
\\fn g(b: bool) void {
\\ const y = if (b) h: { break :h i32(1); };
\\}
\\export fn entry() void { f(true); }
\\export fn entry() void { f(true); g(true); }
,
"tmp.zig:2:42: error: integer value 1 cannot be implicitly casted to type 'void'",
"tmp.zig:3:15: error: incompatible types: 'i32' and 'void'",
"tmp.zig:5:15: error: incompatible types: 'i32' and 'void'",
);
cases.add(
@ -2773,9 +2793,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ a.foo = 1;
\\ const y = a.bar;
\\}
\\export fn g() void {
\\ var a : A = undefined;
\\ const y = a.bar;
\\}
,
"tmp.zig:4:6: error: no member named 'foo' in struct 'A'",
"tmp.zig:5:16: error: no member named 'bar' in struct 'A'",
"tmp.zig:9:16: error: no member named 'bar' in struct 'A'",
);
cases.add(
@ -2920,7 +2944,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = foo;
\\}
,
"tmp.zig:1:19: error: type '[3]u16' does not support struct initialization syntax",
"tmp.zig:1:21: error: type '[3]u16' does not support struct initialization syntax",
);
cases.add(
@ -3239,7 +3263,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\
\\export fn entry() usize { return @sizeOf(@typeOf(Foo)); }
,
"tmp.zig:5:25: error: unable to evaluate constant expression",
"tmp.zig:5:18: error: unable to evaluate constant expression",
"tmp.zig:2:12: note: called from here",
"tmp.zig:2:8: note: called from here",
);
@ -3856,7 +3880,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ return 2;
\\}
,
"tmp.zig:2:15: error: values of type 'comptime_int' must be comptime known",
"tmp.zig:5:17: error: cannot store runtime value in type 'comptime_int'",
);
cases.add(
@ -5108,7 +5132,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ const array = [2]u8{1, 2, 3};
\\}
,
"tmp.zig:2:24: error: expected [2]u8 literal, found [3]u8 literal",
"tmp.zig:2:31: error: index 2 outside array of size 2",
);
cases.add(
@ -5125,36 +5149,47 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.add(
"non-const variables of things that require const variables",
\\const Opaque = @OpaqueType();
\\
\\export fn entry(opaque: *Opaque) void {
\\export fn entry1() void {
\\ var m2 = &2;
\\ const y: u32 = m2.*;
\\
\\}
\\export fn entry2() void {
\\ var a = undefined;
\\}
\\export fn entry3() void {
\\ var b = 1;
\\}
\\export fn entry4() void {
\\ var c = 1.0;
\\}
\\export fn entry5() void {
\\ var d = null;
\\}
\\export fn entry6(opaque: *Opaque) void {
\\ var e = opaque.*;
\\}
\\export fn entry7() void {
\\ var f = i32;
\\}
\\export fn entry8() void {
\\ var h = (Foo {}).bar;
\\
\\}
\\export fn entry9() void {
\\ var z: noreturn = return;
\\}
\\
\\const Opaque = @OpaqueType();
\\const Foo = struct {
\\ fn bar(self: *const Foo) void {}
\\};
,
"tmp.zig:4:4: error: variable of type '*comptime_int' must be const or comptime",
"tmp.zig:7:4: error: variable of type '(undefined)' must be const or comptime",
"tmp.zig:2:4: error: variable of type '*comptime_int' must be const or comptime",
"tmp.zig:5:4: error: variable of type '(undefined)' must be const or comptime",
"tmp.zig:8:4: error: variable of type 'comptime_int' must be const or comptime",
"tmp.zig:9:4: error: variable of type 'comptime_float' must be const or comptime",
"tmp.zig:10:4: error: variable of type '(null)' must be const or comptime",
"tmp.zig:11:4: error: variable of type 'Opaque' not allowed",
"tmp.zig:12:4: error: variable of type 'type' must be const or comptime",
"tmp.zig:13:4: error: variable of type '(bound fn(*const Foo) void)' must be const or comptime",
"tmp.zig:15:4: error: unreachable code",
"tmp.zig:11:4: error: variable of type 'comptime_float' must be const or comptime",
"tmp.zig:14:4: error: variable of type '(null)' must be const or comptime",
"tmp.zig:17:4: error: variable of type 'Opaque' not allowed",
"tmp.zig:20:4: error: variable of type 'type' must be const or comptime",
"tmp.zig:23:4: error: variable of type '(bound fn(*const Foo) void)' must be const or comptime",
"tmp.zig:26:4: error: unreachable code",
);
cases.add(
@ -5300,7 +5335,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ }
\\}
,
"tmp.zig:37:16: error: cannot store runtime value in compile time variable",
"tmp.zig:37:29: error: cannot store runtime value in compile time variable",
);
cases.add(
@ -5924,7 +5959,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ const foo = Foo { .Bar = x, .Baz = u8 };
\\}
,
"tmp.zig:7:30: error: unable to evaluate constant expression",
"tmp.zig:7:23: error: unable to evaluate constant expression",
);
cases.add(
@ -5938,7 +5973,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ const foo = Foo { .Bar = x };
\\}
,
"tmp.zig:7:30: error: unable to evaluate constant expression",
"tmp.zig:7:23: error: unable to evaluate constant expression",
);
cases.addTest(

View File

@ -172,6 +172,12 @@ fn plusOne(x: u32) u32 {
return x + 1;
}
test "runtime initialize array elem and then implicit cast to slice" {
var two: i32 = 2;
const x: []const i32 = [_]i32{two};
expect(x[0] == 2);
}
test "array literal as argument to function" {
const S = struct {
fn entry(two: i32) void {
@ -227,7 +233,7 @@ test "double nested array to const slice cast in array literal" {
const cases2 = [_][]const i32{
[_]i32{1},
[_]i32{ two, 3 },
&[_]i32{ two, 3 },
};
expect(cases2.len == 2);
expect(cases2[0].len == 1);
@ -238,7 +244,7 @@ test "double nested array to const slice cast in array literal" {
const cases3 = [_][]const []const i32{
[_][]const i32{[_]i32{1}},
[_][]const i32{[_]i32{ two, 3 }},
&[_][]const i32{&[_]i32{ two, 3 }},
[_][]const i32{
[_]i32{4},
[_]i32{ 5, 6, 7 },

View File

@ -112,3 +112,16 @@ test "bitcast packed struct to integer and back" {
S.doTheTest();
comptime S.doTheTest();
}
test "implicit cast to error union by returning" {
const S = struct {
fn entry() void {
expect((func(-1) catch unreachable) == maxInt(u64));
}
pub fn func(sz: i64) anyerror!u64 {
return @bitCast(u64, sz);
}
};
S.entry();
comptime S.entry();
}

View File

@ -482,3 +482,40 @@ test "@intCast to u0 and use the result" {
S.doTheTest(0, 1, 0);
comptime S.doTheTest(0, 1, 0);
}
test "peer type resolution: unreachable, null, slice" {
const S = struct {
fn doTheTest(num: usize, word: []const u8) void {
const result = switch (num) {
0 => null,
1 => word,
else => unreachable,
};
expect(mem.eql(u8, result.?, "hi"));
}
};
S.doTheTest(1, "hi");
}
test "peer type resolution: unreachable, error set, unreachable" {
const Error = error {
FileDescriptorAlreadyPresentInSet,
OperationCausesCircularLoop,
FileDescriptorNotRegistered,
SystemResources,
UserResourceLimitReached,
FileDescriptorIncompatibleWithEpoll,
Unexpected,
};
var err = Error.SystemResources;
const transformed_err = switch (err) {
error.FileDescriptorAlreadyPresentInSet => unreachable,
error.OperationCausesCircularLoop => unreachable,
error.FileDescriptorNotRegistered => unreachable,
error.SystemResources => error.SystemResources,
error.UserResourceLimitReached => error.UserResourceLimitReached,
error.FileDescriptorIncompatibleWithEpoll => unreachable,
error.Unexpected => unreachable,
};
expect(transformed_err == error.SystemResources);
}

View File

@ -335,3 +335,43 @@ test "debug info for optional error set" {
const SomeError = error{Hello};
var a_local_variable: ?SomeError = null;
}
test "nested catch" {
const S = struct {
fn entry() void {
expectError(error.Bad, func());
}
fn fail() anyerror!Foo {
return error.Wrong;
}
fn func() anyerror!Foo {
const x = fail() catch
fail() catch
return error.Bad;
unreachable;
}
const Foo = struct {
field: i32,
};
};
S.entry();
comptime S.entry();
}
test "implicit cast to optional to error union to return result loc" {
const S = struct {
fn entry() void {
if (func(undefined)) |opt| {
expect(opt != null);
} else |_| @panic("expected non error");
}
fn func(f: *Foo) anyerror!?*Foo {
return f;
}
const Foo = struct {
field: i32,
};
};
S.entry();
//comptime S.entry(); TODO
}

View File

@ -190,6 +190,17 @@ fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
}
}
test "inlined loop has array literal with elided runtime scope on first iteration but not second iteration" {
var runtime = [1]i32{3};
comptime var i: usize = 0;
inline while (i < 2) : (i += 1) {
const result = if (i == 0) [1]i32{2} else runtime;
}
comptime {
expect(i == 2);
}
}
fn max(comptime T: type, a: T, b: T) T {
if (T == bool) {
return a or b;
@ -756,8 +767,7 @@ test "comptime bitwise operators" {
test "*align(1) u16 is the same as *align(1:0:2) u16" {
comptime {
expect(*align(1:0:2) u16 == *align(1) u16);
// TODO add parsing support for this syntax
//expect(*align(:0:2) u16 == *u16);
expect(*align(:0:2) u16 == *u16);
}
}

View File

@ -205,3 +205,26 @@ test "extern struct with stdcallcc fn pointer" {
s.ptr = S.foo;
expect(s.ptr() == 1234);
}
test "implicit cast fn call result to optional in field result" {
const S = struct {
fn entry() void {
var x = Foo{
.field = optionalPtr(),
};
expect(x.field.?.* == 999);
}
const glob: i32 = 999;
fn optionalPtr() *const i32 {
return &glob;
}
const Foo = struct {
field: ?*const i32,
};
};
S.entry();
comptime S.entry();
}

View File

@ -110,3 +110,19 @@ fn testContinueOuter() void {
}
expect(counter == array.len);
}
test "2 break statements and an else" {
const S = struct {
fn entry(t: bool, f: bool) void {
var buf: [10]u8 = undefined;
var ok = false;
ok = for (buf) |item| {
if (f) break false;
if (t) break true;
} else false;
expect(ok);
}
};
S.entry(true, false);
comptime S.entry(true, false);
}

View File

@ -52,3 +52,14 @@ test "unwrap mutable global var" {
expect(e == error.SomeError);
}
}
test "labeled break inside comptime if inside runtime if" {
var answer: i32 = 0;
var c = true;
if (c) {
answer = if (true) blk: {
break :blk i32(42);
};
}
expect(answer == 42);
}

View File

@ -698,3 +698,11 @@ test "unicode escape in character literal" {
var a: u24 = '\U01f4a9';
expect(a == 128169);
}
test "result location zero sized array inside struct field implicit cast to slice" {
const E = struct {
entries: []u32,
};
var foo = E{ .entries = [_]u32{} };
expect(foo.entries.len == 0);
}

View File

@ -76,6 +76,27 @@ test "unwrap function call with optional pointer return value" {
}
};
S.entry();
// TODO https://github.com/ziglang/zig/issues/1901
//comptime S.entry();
comptime S.entry();
}
test "nested orelse" {
const S = struct {
fn entry() void {
expect(func() == null);
}
fn maybe() ?Foo {
return null;
}
fn func() ?Foo {
const x = maybe() orelse
maybe() orelse
return null;
unreachable;
}
const Foo = struct {
field: i32,
};
};
S.entry();
comptime S.entry();
}

View File

@ -578,3 +578,24 @@ test "default struct initialization fields" {
};
expectEqual(1239, x.a + x.b);
}
test "extern fn returns struct by value" {
const S = struct {
fn entry() void {
var x = makeBar(10);
expectEqual(i32(10), x.handle);
}
const ExternBar = extern struct {
handle: i32,
};
extern fn makeBar(t: i32) ExternBar {
return ExternBar{
.handle = t,
};
}
};
S.entry();
comptime S.entry();
}

View File

@ -360,3 +360,19 @@ test "switch prongs with error set cases make a new error set type for capture v
S.doTheTest();
comptime S.doTheTest();
}
test "return result loc and then switch with range implicit casted to error union" {
const S = struct {
fn doTheTest() void {
expect((func(0xb) catch unreachable) == 0xb);
}
fn func(d: u8) anyerror!u8 {
return switch (d) {
0xa...0xf => d,
else => unreachable,
};
}
};
S.doTheTest();
comptime S.doTheTest();
}

View File

@ -402,3 +402,23 @@ test "comptime union field value equality" {
expect(a0 != a1);
expect(b0 != b1);
}
test "return union init with void payload" {
const S = struct {
fn entry() void {
expect(func().state == State.one);
}
const Outer = union(enum) {
state: State,
};
const State = union(enum) {
one: void,
two: u32,
};
fn func() Outer {
return Outer{ .state = State{ .one = {} }};
}
};
S.entry();
comptime S.entry();
}

View File

@ -61,3 +61,16 @@ test "vector bit operators" {
S.doTheTest();
comptime S.doTheTest();
}
test "implicit cast vector to array" {
const S = struct {
fn doTheTest() void {
var a: @Vector(4, i32) = [_]i32{ 1, 2, 3, 4 };
var result_array: [4]i32 = a;
result_array = a;
expect(mem.eql(i32, result_array, [4]i32{ 1, 2, 3, 4 }));
}
};
S.doTheTest();
comptime S.doTheTest();
}

View File

@ -226,3 +226,48 @@ fn returnFalse() bool {
fn returnTrue() bool {
return true;
}
test "while bool 2 break statements and an else" {
const S = struct {
fn entry(t: bool, f: bool) void {
var ok = false;
ok = while (t) {
if (f) break false;
if (t) break true;
} else false;
expect(ok);
}
};
S.entry(true, false);
comptime S.entry(true, false);
}
test "while optional 2 break statements and an else" {
const S = struct {
fn entry(opt_t: ?bool, f: bool) void {
var ok = false;
ok = while (opt_t) |t| {
if (f) break false;
if (t) break true;
} else false;
expect(ok);
}
};
S.entry(true, false);
comptime S.entry(true, false);
}
test "while error 2 break statements and an else" {
const S = struct {
fn entry(opt_t: anyerror!bool, f: bool) void {
var ok = false;
ok = while (opt_t) |t| {
if (f) break false;
if (t) break true;
} else |_| false;
expect(ok);
}
};
S.entry(true, false);
comptime S.entry(true, false);
}

View File

@ -811,23 +811,21 @@ pub const CompileErrorContext = struct {
pub fn addCase(self: *CompileErrorContext, case: *const TestCase) void {
const b = self.b;
for (self.modes) |mode| {
const annotated_case_name = fmt.allocPrint(self.b.allocator, "compile-error {} ({})", case.name, @tagName(mode)) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) continue;
}
const annotated_case_name = fmt.allocPrint(self.b.allocator, "compile-error {}", case.name) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
}
const compile_and_cmp_errors = CompileCmpOutputStep.create(self, annotated_case_name, case, mode);
self.step.dependOn(&compile_and_cmp_errors.step);
const compile_and_cmp_errors = CompileCmpOutputStep.create(self, annotated_case_name, case, .Debug);
self.step.dependOn(&compile_and_cmp_errors.step);
for (case.sources.toSliceConst()) |src_file| {
const expanded_src_path = fs.path.join(
b.allocator,
[_][]const u8{ b.cache_root, src_file.filename },
) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source);
compile_and_cmp_errors.step.dependOn(&write_src.step);
}
for (case.sources.toSliceConst()) |src_file| {
const expanded_src_path = fs.path.join(
b.allocator,
[_][]const u8{ b.cache_root, src_file.filename },
) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source);
compile_and_cmp_errors.step.dependOn(&write_src.step);
}
}
};