aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVexu <15308111+Vexu@users.noreply.github.com>2019-07-17 01:20:59 +0300
committerGitHub <noreply@github.com>2019-07-17 01:20:59 +0300
commitf8e753e19c013cc605a951e5038b4a26099aa135 (patch)
tree3cbb2ce1b8815bc565344e23a39e3d39505cfd31 /src
parent0063953d1634ce770ce88519c66e3956832ceb7e (diff)
parent158e2312ea5f680b7c8598ef578aefb6cbdd3372 (diff)
downloadzig-f8e753e19c013cc605a951e5038b4a26099aa135.tar.gz
zig-f8e753e19c013cc605a951e5038b4a26099aa135.zip
Merge branch 'master' into comment-in-array
Diffstat (limited to 'src')
-rw-r--r--src/all_types.hpp399
-rw-r--r--src/analyze.cpp38
-rw-r--r--src/analyze.hpp1
-rw-r--r--src/ast_render.cpp9
-rw-r--r--src/buffer.hpp10
-rw-r--r--src/codegen.cpp786
-rw-r--r--src/codegen.hpp5
-rw-r--r--src/compiler.cpp26
-rw-r--r--src/compiler.hpp1
-rw-r--r--src/config.h.in2
-rw-r--r--src/glibc.cpp406
-rw-r--r--src/glibc.hpp53
-rw-r--r--src/install_files.h1802
-rw-r--r--src/ir.cpp4803
-rw-r--r--src/ir_print.cpp369
-rw-r--r--src/link.cpp1168
-rw-r--r--src/main.cpp180
-rw-r--r--src/parser.cpp11
-rw-r--r--src/target.cpp92
-rw-r--r--src/target.hpp12
-rw-r--r--src/tokenizer.cpp117
-rw-r--r--src/tokenizer.hpp1
-rw-r--r--src/translate_c.cpp44
-rw-r--r--src/userland.cpp2
-rw-r--r--src/userland.h3
-rw-r--r--src/util.cpp26
-rw-r--r--src/util.hpp11
-rw-r--r--src/zig_clang.cpp161
-rw-r--r--src/zig_clang.h79
-rw-r--r--src/zig_llvm.cpp57
-rw-r--r--src/zig_llvm.h4
31 files changed, 8313 insertions, 2365 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 6595218bcf..3cdaf36cd9 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -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,
@@ -1097,6 +1110,8 @@ struct ZigPackage {
// reminder: hash tables must be initialized before use
HashMap<Buf *, ZigPackage *, buf_hash, buf_eql_buf> package_table;
+
+ bool added_to_cache;
};
// Stuff that only applies to a struct which is the implicit root struct of a file
@@ -1364,7 +1379,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;
@@ -1401,6 +1416,7 @@ enum BuiltinFnId {
BuiltinFnIdMemberName,
BuiltinFnIdField,
BuiltinFnIdTypeInfo,
+ BuiltinFnIdHasField,
BuiltinFnIdTypeof,
BuiltinFnIdAddWithOverflow,
BuiltinFnIdSubWithOverflow,
@@ -1493,6 +1509,7 @@ enum BuiltinFnId {
BuiltinFnIdAtomicRmw,
BuiltinFnIdAtomicLoad,
BuiltinFnIdHasDecl,
+ BuiltinFnIdUnionInit,
};
struct BuiltinFnEntry {
@@ -1744,7 +1761,7 @@ struct CodeGen {
ZigPackage *compile_var_package;
ZigType *compile_var_import;
ZigType *root_import;
- ZigType *bootstrap_import;
+ ZigType *start_import;
ZigType *test_runner_import;
struct {
@@ -1787,7 +1804,7 @@ struct CodeGen {
ZigType *err_tag_type;
ZigType *test_fn_type;
- Buf triple_str;
+ Buf llvm_triple_str;
Buf global_asm;
Buf output_file_path;
Buf o_file_output_path;
@@ -1893,6 +1910,7 @@ struct CodeGen {
bool have_pic;
bool have_dynamic_link; // this is whether the final thing will be dynamically linked. see also is_dynamic
bool have_stack_probing;
+ bool function_sections;
Buf *mmacosx_version_min;
Buf *mios_version_min;
@@ -1903,6 +1921,7 @@ struct CodeGen {
Buf *zig_lib_dir;
Buf *zig_std_dir;
Buf *dynamic_linker_path;
+ Buf *version_script_path;
const char **llvm_argv;
size_t llvm_argv_len;
@@ -1999,6 +2018,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 +2031,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 +2082,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 +2166,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 +2178,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 +2214,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 +2249,7 @@ enum IrInstructionId {
IrInstructionIdCDefine,
IrInstructionIdCUndef,
IrInstructionIdRef,
+ IrInstructionIdRefGen,
IrInstructionIdCompileErr,
IrInstructionIdCompileLog,
IrInstructionIdErrName,
@@ -2240,7 +2268,8 @@ enum IrInstructionId {
IrInstructionIdBoolNot,
IrInstructionIdMemset,
IrInstructionIdMemcpy,
- IrInstructionIdSlice,
+ IrInstructionIdSliceSrc,
+ IrInstructionIdSliceGen,
IrInstructionIdMemberCount,
IrInstructionIdMemberType,
IrInstructionIdMemberName,
@@ -2250,9 +2279,10 @@ enum IrInstructionId {
IrInstructionIdHandle,
IrInstructionIdAlignOf,
IrInstructionIdOverflowOp,
+ IrInstructionIdTestErrSrc,
+ IrInstructionIdTestErrGen,
IrInstructionIdMulAdd,
IrInstructionIdFloatOp,
- IrInstructionIdTestErr,
IrInstructionIdUnwrapErrCode,
IrInstructionIdUnwrapErrPayload,
IrInstructionIdErrWrapCode,
@@ -2261,7 +2291,7 @@ enum IrInstructionId {
IrInstructionIdTestComptime,
IrInstructionIdPtrCastSrc,
IrInstructionIdPtrCastGen,
- IrInstructionIdBitCast,
+ IrInstructionIdBitCastSrc,
IrInstructionIdBitCastGen,
IrInstructionIdWidenOrShorten,
IrInstructionIdIntToPtr,
@@ -2281,10 +2311,15 @@ enum IrInstructionId {
IrInstructionIdByteOffsetOf,
IrInstructionIdBitOffsetOf,
IrInstructionIdTypeInfo,
+ IrInstructionIdHasField,
IrInstructionIdTypeId,
IrInstructionIdSetEvalBranchQuota,
IrInstructionIdPtrType,
IrInstructionIdAlignCast,
+ IrInstructionIdImplicitCast,
+ IrInstructionIdResolveResult,
+ IrInstructionIdResetResult,
+ IrInstructionIdResultPtr,
IrInstructionIdOpaqueType,
IrInstructionIdSetAlignStack,
IrInstructionIdArgType,
@@ -2323,10 +2358,14 @@ enum IrInstructionId {
IrInstructionIdAssertNonNull,
IrInstructionIdHasDecl,
IrInstructionIdUndeclaredIdent,
+ IrInstructionIdAllocaSrc,
+ IrInstructionIdAllocaGen,
+ IrInstructionIdEndExpr,
+ IrInstructionIdPtrOfArrayToSlice,
+ IrInstructionIdUnionInitNamedField,
};
struct IrInstruction {
- IrInstructionId id;
Scope *scope;
AstNode *source_node;
ConstExprValue value;
@@ -2340,6 +2379,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 +2390,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 +2407,7 @@ struct IrInstructionCondBr {
IrBasicBlock *then_block;
IrBasicBlock *else_block;
IrInstruction *is_comptime;
+ ResultLoc *result_loc;
};
struct IrInstructionBr {
@@ -2419,6 +2460,7 @@ struct IrInstructionPhi {
size_t incoming_count;
IrBasicBlock **incoming_blocks;
IrInstruction **incoming_values;
+ ResultLocPeerParent *peer_parent;
};
enum IrUnOp {
@@ -2434,8 +2476,9 @@ struct IrInstructionUnOp {
IrInstruction base;
IrUnOp op_id;
- IrInstruction *value;
LVal lval;
+ IrInstruction *value;
+ ResultLoc *result_loc;
};
enum IrBinOp {
@@ -2492,7 +2535,7 @@ struct IrInstructionLoadPtrGen {
IrInstruction base;
IrInstruction *ptr;
- LLVMValueRef tmp_ptr;
+ IrInstruction *result_loc;
};
struct IrInstructionStorePtr {
@@ -2505,6 +2548,7 @@ struct IrInstructionStorePtr {
struct IrInstructionFieldPtr {
IrInstruction base;
+ bool initializing;
IrInstruction *container_ptr;
Buf *field_name_buffer;
IrInstruction *field_name_expr;
@@ -2521,9 +2565,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 +2576,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 +2588,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 +2611,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 +2648,6 @@ enum CastOp {
CastOpNumLitToConcrete,
CastOpErrSet,
CastOpBitCast,
- CastOpPtrOfArrayToSlice,
};
// TODO get rid of this instruction, replace with instructions for each op code
@@ -2591,14 +2657,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 +2672,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 +2689,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 +2702,6 @@ struct IrInstructionTypeOf {
IrInstruction *value;
};
-struct IrInstructionToPtrType {
- IrInstruction base;
-
- IrInstruction *ptr;
-};
-
-struct IrInstructionPtrTypeChild {
- IrInstruction base;
-
- IrInstruction *value;
-};
-
struct IrInstructionSetCold {
IrInstruction base;
@@ -2764,8 +2795,9 @@ struct IrInstructionTestNonNull {
struct IrInstructionOptionalUnwrapPtr {
IrInstruction base;
- IrInstruction *base_ptr;
bool safety_check_on;
+ bool initializing;
+ IrInstruction *base_ptr;
};
struct IrInstructionCtz {
@@ -2805,11 +2837,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 +2899,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 +2962,7 @@ struct IrInstructionToBytes {
IrInstruction base;
IrInstruction *target;
+ ResultLoc *result_loc;
};
struct IrInstructionFromBytes {
@@ -2931,6 +2970,7 @@ struct IrInstructionFromBytes {
IrInstruction *dest_child_type;
IrInstruction *target;
+ ResultLoc *result_loc;
};
struct IrInstructionIntToFloat {
@@ -2989,14 +3029,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 +3120,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 +3202,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 +3288,8 @@ struct IrInstructionTypeName {
struct IrInstructionDeclRef {
IrInstruction base;
- Tld *tld;
LVal lval;
+ Tld *tld;
};
struct IrInstructionPanic {
@@ -3280,6 +3339,13 @@ struct IrInstructionTypeInfo {
IrInstruction *type_value;
};
+struct IrInstructionHasField {
+ IrInstruction base;
+
+ IrInstruction *container_type;
+ IrInstruction *field_name;
+};
+
struct IrInstructionTypeId {
IrInstruction base;
@@ -3526,7 +3592,7 @@ struct IrInstructionVectorToArray {
IrInstruction base;
IrInstruction *vector;
- LLVMValueRef tmp_ptr;
+ IrInstruction *result_loc;
};
struct IrInstructionAssertZero {
@@ -3541,6 +3607,15 @@ struct IrInstructionAssertNonNull {
IrInstruction *target;
};
+struct IrInstructionUnionInitNamedField {
+ IrInstruction base;
+
+ IrInstruction *union_type;
+ IrInstruction *field_name;
+ IrInstruction *field_result_loc;
+ IrInstruction *result_loc;
+};
+
struct IrInstructionHasDecl {
IrInstruction base;
@@ -3554,6 +3629,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;
@@ -3581,6 +3789,9 @@ static const size_t stack_trace_ptr_count = 32;
#define NAMESPACE_SEP_CHAR '.'
#define NAMESPACE_SEP_STR "."
+#define CACHE_OUT_SUBDIR "o"
+#define CACHE_HASH_SUBDIR "h"
+
enum FloatMode {
FloatModeStrict,
FloatModeOptimized,
@@ -3601,7 +3812,7 @@ struct FnWalkAttrs {
struct FnWalkCall {
ZigList<LLVMValueRef> *gen_param_values;
- IrInstructionCall *inst;
+ IrInstructionCallGen *inst;
bool is_var_args;
};
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 13b35e0aff..3ec839464e 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -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:
@@ -3896,22 +3896,21 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu
Buf *pkg_root_src_dir = &package->root_src_dir;
Buf resolved_root_src_dir = os_path_resolve(&pkg_root_src_dir, 1);
- Buf namespace_name = BUF_INIT;
- buf_init_from_buf(&namespace_name, &package->pkg_path);
+ Buf *namespace_name = buf_create_from_buf(&package->pkg_path);
if (source_kind == SourceKindNonRoot) {
assert(buf_starts_with_buf(resolved_path, &resolved_root_src_dir));
- if (buf_len(&namespace_name) != 0) {
- buf_append_char(&namespace_name, NAMESPACE_SEP_CHAR);
+ if (buf_len(namespace_name) != 0) {
+ buf_append_char(namespace_name, NAMESPACE_SEP_CHAR);
}
// The namespace components are obtained from the relative path to the
// source directory
if (buf_len(&noextname) > buf_len(&resolved_root_src_dir)) {
// Skip the trailing separator
- buf_append_mem(&namespace_name,
+ buf_append_mem(namespace_name,
buf_ptr(&noextname) + buf_len(&resolved_root_src_dir) + 1,
buf_len(&noextname) - buf_len(&resolved_root_src_dir) - 1);
}
- buf_replace(&namespace_name, ZIG_OS_SEP_CHAR, NAMESPACE_SEP_CHAR);
+ buf_replace(namespace_name, ZIG_OS_SEP_CHAR, NAMESPACE_SEP_CHAR);
}
Buf *bare_name = buf_alloc();
os_path_extname(src_basename, bare_name, nullptr);
@@ -3922,7 +3921,7 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu
root_struct->line_offsets = tokenization.line_offsets;
root_struct->path = resolved_path;
root_struct->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
- ZigType *import_entry = get_root_container_type(g, buf_ptr(&namespace_name), bare_name, root_struct);
+ ZigType *import_entry = get_root_container_type(g, buf_ptr(namespace_name), bare_name, root_struct);
if (source_kind == SourceKindRoot) {
assert(g->root_import == nullptr);
g->root_import = import_entry;
@@ -3966,7 +3965,7 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu
}
TldContainer *tld_container = allocate<TldContainer>(1);
- init_tld(&tld_container->base, TldIdContainer, &namespace_name, VisibModPub, root_node, nullptr);
+ init_tld(&tld_container->base, TldIdContainer, namespace_name, VisibModPub, root_node, nullptr);
tld_container->type_entry = import_entry;
tld_container->decls_scope = import_entry->data.structure.decls_scope;
g->resolve_queue.append(&tld_container->base);
@@ -4181,6 +4180,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 +4511,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 +4712,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 +5000,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 +5842,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 +7275,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));
}
diff --git a/src/analyze.hpp b/src/analyze.hpp
index 8d78ef86e2..a6ad92110e 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -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);
diff --git a/src/ast_render.cpp b/src/ast_render.cpp
index d93efe2193..154803f884 100644
--- a/src/ast_render.cpp
+++ b/src/ast_render.cpp
@@ -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:
@@ -444,9 +444,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
const char *extern_str = extern_string(node->data.fn_proto.is_extern);
const char *export_str = export_string(node->data.fn_proto.is_export);
const char *inline_str = inline_string(node->data.fn_proto.is_inline);
- fprintf(ar->f, "%s%s%s%sfn", pub_str, inline_str, export_str, extern_str);
+ fprintf(ar->f, "%s%s%s%sfn ", pub_str, inline_str, export_str, extern_str);
if (node->data.fn_proto.name != nullptr) {
- fprintf(ar->f, " ");
print_symbol(ar, node->data.fn_proto.name);
}
fprintf(ar->f, "(");
@@ -1108,7 +1107,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 ");
diff --git a/src/buffer.hpp b/src/buffer.hpp
index d4a911fc21..d7254c18a7 100644
--- a/src/buffer.hpp
+++ b/src/buffer.hpp
@@ -136,11 +136,21 @@ static inline bool buf_eql_mem(Buf *buf, const char *mem, size_t mem_len) {
return mem_eql_mem(buf_ptr(buf), buf_len(buf), mem, mem_len);
}
+static inline bool buf_eql_mem_ignore_case(Buf *buf, const char *mem, size_t mem_len) {
+ assert(buf->list.length);
+ return mem_eql_mem_ignore_case(buf_ptr(buf), buf_len(buf), mem, mem_len);
+}
+
static inline bool buf_eql_str(Buf *buf, const char *str) {
assert(buf->list.length);
return buf_eql_mem(buf, str, strlen(str));
}
+static inline bool buf_eql_str_ignore_case(Buf *buf, const char *str) {
+ assert(buf->list.length);
+ return buf_eql_mem_ignore_case(buf, str, strlen(str));
+}
+
static inline bool buf_starts_with_mem(Buf *buf, const char *mem, size_t mem_len) {
if (buf_len(buf) < mem_len) {
return false;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 41caa29dbd..234b28219b 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -24,9 +24,6 @@
#include <stdio.h>
#include <errno.h>
-#define CACHE_OUT_SUBDIR "o"
-#define CACHE_HASH_SUBDIR "h"
-
static void init_darwin_native(CodeGen *g) {
char *osx_target = getenv("MACOSX_DEPLOYMENT_TARGET");
char *ios_target = getenv("IPHONEOS_DEPLOYMENT_TARGET");
@@ -180,6 +177,8 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
g->root_package = new_package(".", "", "");
}
+ g->root_package->package_table.put(buf_create_from_str("root"), g->root_package);
+
g->zig_std_special_dir = buf_alloc();
os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir);
@@ -200,7 +199,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
g->link_libs_list.append(g->libc_link_lib);
}
- get_target_triple(&g->triple_str, g->zig_target);
+ target_triple_llvm(&g->llvm_triple_str, g->zig_target);
g->pointer_size_bytes = target_arch_pointer_bit_width(g->zig_target->arch) / 8;
if (!target_has_debug_info(g->zig_target)) {
@@ -691,7 +690,9 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
is_definition, scope_line, flags, is_optimized, nullptr);
scope->di_scope = ZigLLVMSubprogramToScope(subprogram);
- ZigLLVMFnSetSubprogram(fn_llvm_value(g, fn_table_entry), subprogram);
+ if (!g->strip_debug_symbols) {
+ ZigLLVMFnSetSubprogram(fn_llvm_value(g, fn_table_entry), subprogram);
+ }
return scope->di_scope;
}
case ScopeIdDecls:
@@ -859,9 +860,7 @@ static LLVMValueRef gen_store_untyped(CodeGen *g, LLVMValueRef value, LLVMValueR
{
LLVMValueRef instruction = LLVMBuildStore(g->builder, value, ptr);
if (is_volatile) LLVMSetVolatile(instruction, true);
- if (alignment == 0) {
- LLVMSetAlignment(instruction, LLVMABIAlignmentOfType(g->target_data_ref, LLVMTypeOf(value)));
- } else {
+ if (alignment != 0) {
LLVMSetAlignment(instruction, alignment);
}
return instruction;
@@ -1339,7 +1338,9 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {
LLVMBuildRetVoid(g->builder);
LLVMPositionBuilderAtEnd(g->builder, prev_block);
- LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ if (!g->strip_debug_symbols) {
+ LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ }
g->add_error_return_trace_addr_fn_val = fn_val;
return fn_val;
@@ -1470,7 +1471,9 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
LLVMBuildBr(g->builder, loop_block);
LLVMPositionBuilderAtEnd(g->builder, prev_block);
- LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ if (!g->strip_debug_symbols) {
+ LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ }
g->merge_err_ret_traces_fn_val = fn_val;
return fn_val;
@@ -1526,7 +1529,9 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
LLVMBuildRetVoid(g->builder);
LLVMPositionBuilderAtEnd(g->builder, prev_block);
- LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ if (!g->strip_debug_symbols) {
+ LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ }
g->return_err_fn = fn_val;
return fn_val;
@@ -1654,7 +1659,9 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
gen_panic(g, msg_slice, err_ret_trace_arg);
LLVMPositionBuilderAtEnd(g->builder, prev_block);
- LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ if (!g->strip_debug_symbols) {
+ LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ }
g->safety_crash_err_fn = fn_val;
return fn_val;
@@ -2004,6 +2011,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty
}
static void gen_var_debug_decl(CodeGen *g, ZigVar *var) {
+ if (g->strip_debug_symbols) return;
assert(var->di_loc_var != nullptr);
AstNode *source_node = var->decl_node;
ZigLLVMDILocation *debug_loc = ZigLLVMGetDebugLoc((unsigned)source_node->line + 1,
@@ -2016,7 +2024,7 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
if (!type_has_bits(instruction->value.type))
return nullptr;
if (!instruction->llvm_value) {
- assert(instruction->value.special != ConstValSpecialRuntime);
+ src_assert(instruction->value.special != ConstValSpecialRuntime, instruction->source_node);
assert(instruction->value.type);
render_const_val(g, &instruction->value, "");
// we might have to do some pointer casting here due to the way union
@@ -2025,11 +2033,9 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
render_const_val_global(g, &instruction->value, "");
ZigType *ptr_type = get_pointer_to_type(g, instruction->value.type, true);
instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.global_refs->llvm_global, get_llvm_type(g, ptr_type), "");
- } else if (get_codegen_ptr_type(instruction->value.type) != nullptr) {
+ } else {
instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.global_refs->llvm_value,
get_llvm_type(g, instruction->value.type), "");
- } else {
- instruction->llvm_value = instruction->value.global_refs->llvm_value;
}
assert(instruction->llvm_value);
}
@@ -2310,7 +2316,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
return;
}
if (fn_walk->id == FnWalkIdCall) {
- IrInstructionCall *instruction = fn_walk->data.call.inst;
+ IrInstructionCallGen *instruction = fn_walk->data.call.inst;
bool is_var_args = fn_walk->data.call.is_var_args;
for (size_t call_i = 0; call_i < instruction->arg_count; call_i += 1) {
IrInstruction *param_instruction = instruction->args[call_i];
@@ -2404,17 +2410,33 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut
}
static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
- LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
- ZigType *return_type = return_instruction->value->value.type;
-
if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) {
+ if (return_instruction->value == nullptr) {
+ LLVMBuildRetVoid(g->builder);
+ return nullptr;
+ }
assert(g->cur_ret_ptr);
+ src_assert(return_instruction->value->value.special != ConstValSpecialRuntime,
+ return_instruction->base.source_node);
+ LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
+ ZigType *return_type = return_instruction->value->value.type;
gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
LLVMBuildRetVoid(g->builder);
- } else if (handle_is_ptr(return_type)) {
- LLVMValueRef by_val_value = gen_load_untyped(g, value, 0, false, "");
- LLVMBuildRet(g->builder, by_val_value);
+ } else if (g->cur_fn->type_entry->data.fn.fn_type_id.cc != CallingConventionAsync &&
+ handle_is_ptr(g->cur_fn->type_entry->data.fn.fn_type_id.return_type))
+ {
+ if (return_instruction->value == nullptr) {
+ LLVMValueRef by_val_value = gen_load_untyped(g, g->cur_ret_ptr, 0, false, "");
+ LLVMBuildRet(g->builder, by_val_value);
+ } else {
+ LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
+ LLVMValueRef by_val_value = gen_load_untyped(g, value, 0, false, "");
+ LLVMBuildRet(g->builder, by_val_value);
+ }
+ } else if (return_instruction->value == nullptr) {
+ LLVMBuildRetVoid(g->builder);
} else {
+ LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
LLVMBuildRet(g->builder, value);
}
return nullptr;
@@ -2952,7 +2974,7 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable,
LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand);
assert(expr_val);
- assert(instruction->tmp_ptr);
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
assert(wanted_type->id == ZigTypeIdStruct);
assert(wanted_type->data.structure.is_slice);
assert(actual_type->id == ZigTypeIdStruct);
@@ -2973,7 +2995,7 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable,
LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, "");
LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr,
get_llvm_type(g, wanted_type->data.structure.fields[0].type_entry), "");
- LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
+ LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, result_loc,
(unsigned)wanted_ptr_index, "");
gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false);
@@ -3006,12 +3028,10 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable,
zig_unreachable();
}
- LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
- (unsigned)wanted_len_index, "");
+ LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, result_loc, (unsigned)wanted_len_index, "");
gen_store_untyped(g, new_len, dest_len_ptr, 0, false);
-
- return instruction->tmp_ptr;
+ return result_loc;
}
static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
@@ -3081,33 +3101,39 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
return expr_val;
case CastOpBitCast:
return LLVMBuildBitCast(g->builder, expr_val, get_llvm_type(g, wanted_type), "");
- case CastOpPtrOfArrayToSlice: {
- assert(cast_instruction->tmp_ptr);
- assert(actual_type->id == ZigTypeIdPointer);
- ZigType *array_type = actual_type->data.pointer.child_type;
- assert(array_type->id == ZigTypeIdArray);
-
- LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
- slice_ptr_index, "");
- LLVMValueRef indices[] = {
- LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
- LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 0, false),
- };
- LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, expr_val, indices, 2, "");
- gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
-
- LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
- slice_len_index, "");
- LLVMValueRef len_value = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,
- array_type->data.array.len, false);
- gen_store_untyped(g, len_value, len_field_ptr, 0, false);
-
- return cast_instruction->tmp_ptr;
- }
}
zig_unreachable();
}
+static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutable *executable,
+ IrInstructionPtrOfArrayToSlice *instruction)
+{
+ ZigType *actual_type = instruction->operand->value.type;
+ LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand);
+ assert(expr_val);
+
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
+
+ assert(actual_type->id == ZigTypeIdPointer);
+ ZigType *array_type = actual_type->data.pointer.child_type;
+ assert(array_type->id == ZigTypeIdArray);
+
+ LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, slice_ptr_index, "");
+ LLVMValueRef indices[] = {
+ LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
+ LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 0, false),
+ };
+ LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, expr_val, indices, 2, "");
+ gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
+
+ LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, slice_len_index, "");
+ LLVMValueRef len_value = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,
+ array_type->data.array.len, false);
+ gen_store_untyped(g, len_value, len_field_ptr, 0, false);
+
+ return result_loc;
+}
+
static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
IrInstructionPtrCastGen *instruction)
{
@@ -3154,12 +3180,7 @@ static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,
uint32_t alignment = get_abi_alignment(g, actual_type);
return gen_load_untyped(g, bitcasted_ptr, alignment, false, "");
} else {
- assert(instruction->tmp_ptr != nullptr);
- LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(get_llvm_type(g, actual_type), 0);
- LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr, wanted_ptr_type_ref, "");
- uint32_t alignment = get_abi_alignment(g, wanted_type);
- gen_store_untyped(g, value, bitcasted_ptr, alignment, false);
- return instruction->tmp_ptr;
+ zig_unreachable();
}
}
@@ -3345,31 +3366,13 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI
return LLVMBuildICmp(g->builder, LLVMIntEQ, value, zero, "");
}
-static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
- IrInstructionDeclVarGen *decl_var_instruction)
-{
- ZigVar *var = decl_var_instruction->var;
+static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, IrInstructionDeclVarGen *instruction) {
+ ZigVar *var = instruction->var;
if (!type_has_bits(var->var_type))
return nullptr;
- if (var->ref_count == 0 && g->build_mode != BuildModeDebug)
- return nullptr;
-
- IrInstruction *init_value = decl_var_instruction->init_value;
-
- bool have_init_expr = !value_is_all_undef(&init_value->value);
-
- if (have_init_expr) {
- ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->var_type, false, false,
- PtrLenSingle, var->align_bytes, 0, 0, false);
- LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);
- gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);
- } else if (ir_want_runtime_safety(g, &decl_var_instruction->base)) {
- uint32_t align_bytes = (var->align_bytes == 0) ? get_abi_alignment(g, var->var_type) : var->align_bytes;
- gen_undef_init(g, align_bytes, var->var_type, var->value_ref);
- }
-
+ var->value_ref = ir_llvm_value(g, instruction->var_ptr);
gen_var_debug_decl(g, var);
return nullptr;
}
@@ -3401,13 +3404,13 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, "");
if (handle_is_ptr(child_type)) {
- assert(instruction->tmp_ptr != nullptr);
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
LLVMTypeRef same_size_int = LLVMIntType(size_in_bits);
LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, shifted_value, same_size_int, "");
- LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr,
+ LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, result_loc,
LLVMPointerType(same_size_int, 0), "");
LLVMBuildStore(g->builder, truncated_int, bitcasted_ptr);
- return instruction->tmp_ptr;
+ return result_loc;
}
if (child_type->id == ZigTypeIdFloat) {
@@ -3585,6 +3588,14 @@ static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrIn
}
}
+static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutable *executable,
+ IrInstructionReturnPtr *instruction)
+{
+ src_assert(g->cur_ret_ptr != nullptr || !type_has_bits(instruction->base.value.type),
+ instruction->base.source_node);
+ return g->cur_ret_ptr;
+}
+
static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrInstructionElemPtr *instruction) {
LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->array_ptr);
ZigType *array_ptr_type = instruction->array_ptr->value.type;
@@ -3736,7 +3747,7 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) {
LLVMAddCallSiteAttribute(call_instr, 1, sret_attr);
}
-static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) {
+static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCallGen *instruction) {
LLVMValueRef fn_val;
ZigType *fn_type;
if (instruction->fn_entry) {
@@ -3759,8 +3770,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack(g, fn_type_id);
bool is_var_args = fn_type_id->is_var_args;
ZigList<LLVMValueRef> gen_param_values = {};
+ LLVMValueRef result_loc = instruction->result_loc ? ir_llvm_value(g, instruction->result_loc) : nullptr;
if (first_arg_ret) {
- gen_param_values.append(instruction->tmp_ptr);
+ 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));
@@ -3768,7 +3780,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
if (instruction->is_async) {
gen_param_values.append(ir_llvm_value(g, instruction->async_allocator));
- LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, "");
+ LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_err_index, "");
gen_param_values.append(err_val_ptr);
}
FnWalk fn_walk = {};
@@ -3811,9 +3823,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
if (instruction->is_async) {
- LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_payload_index, "");
+ LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_payload_index, "");
LLVMBuildStore(g->builder, result, payload_ptr);
- return instruction->tmp_ptr;
+ return result_loc;
}
if (src_return_type->id == ZigTypeIdUnreachable) {
@@ -3822,11 +3834,11 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
return nullptr;
} else if (first_arg_ret) {
set_call_instr_sret(g, result);
- return instruction->tmp_ptr;
+ return result_loc;
} else if (handle_is_ptr(src_return_type)) {
- auto store_instr = LLVMBuildStore(g->builder, result, instruction->tmp_ptr);
- LLVMSetAlignment(store_instr, LLVMGetAlignment(instruction->tmp_ptr));
- return instruction->tmp_ptr;
+ LLVMValueRef store_instr = LLVMBuildStore(g->builder, result, result_loc);
+ LLVMSetAlignment(store_instr, get_ptr_align(g, instruction->result_loc->value.type));
+ return result_loc;
} else {
return result;
}
@@ -3835,6 +3847,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executable,
IrInstructionStructFieldPtr *instruction)
{
+ if (instruction->base.value.special != ConstValSpecialRuntime)
+ return nullptr;
+
LLVMValueRef struct_ptr = ir_llvm_value(g, instruction->struct_ptr);
// not necessarily a pointer. could be ZigTypeIdStruct
ZigType *struct_ptr_type = instruction->struct_ptr->value.type;
@@ -3856,6 +3871,9 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable,
IrInstructionUnionFieldPtr *instruction)
{
+ if (instruction->base.value.special != ConstValSpecialRuntime)
+ return nullptr;
+
ZigType *union_ptr_type = instruction->union_ptr->value.type;
assert(union_ptr_type->id == ZigTypeIdPointer);
ZigType *union_type = union_ptr_type->data.pointer.child_type;
@@ -3863,8 +3881,20 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
TypeUnionField *field = instruction->field;
- if (!type_has_bits(field->type_entry))
+ if (!type_has_bits(field->type_entry)) {
+ if (union_type->data.unionation.gen_tag_index == SIZE_MAX) {
+ return nullptr;
+ }
+ if (instruction->initializing) {
+ LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr);
+ LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr,
+ union_type->data.unionation.gen_tag_index, "");
+ LLVMValueRef tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type),
+ &field->enum_field->value);
+ gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
+ }
return nullptr;
+ }
LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr);
LLVMTypeRef field_type_ref = LLVMPointerType(get_llvm_type(g, field->type_entry), 0);
@@ -3875,7 +3905,12 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
return bitcasted_union_field_ptr;
}
- if (ir_want_runtime_safety(g, &instruction->base)) {
+ if (instruction->initializing) {
+ LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, "");
+ LLVMValueRef tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type),
+ &field->enum_field->value);
+ gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
+ } else if (instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base)) {
LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, "");
LLVMValueRef tag_value = gen_load_untyped(g, tag_field_ptr, 0, false, "");
@@ -4075,14 +4110,17 @@ static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable
static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *executable,
IrInstructionOptionalUnwrapPtr *instruction)
{
+ if (instruction->base.value.special != ConstValSpecialRuntime)
+ return nullptr;
+
ZigType *ptr_type = instruction->base_ptr->value.type;
assert(ptr_type->id == ZigTypeIdPointer);
ZigType *maybe_type = ptr_type->data.pointer.child_type;
assert(maybe_type->id == ZigTypeIdOptional);
ZigType *child_type = maybe_type->data.maybe.child_type;
- LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->base_ptr);
- if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) {
- LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
+ LLVMValueRef base_ptr = ir_llvm_value(g, instruction->base_ptr);
+ if (instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base)) {
+ LLVMValueRef maybe_handle = get_handle_value(g, base_ptr, maybe_type, ptr_type);
LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);
LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");
LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");
@@ -4098,10 +4136,16 @@ static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *exec
} else {
bool is_scalar = !handle_is_ptr(maybe_type);
if (is_scalar) {
- return maybe_ptr;
+ return base_ptr;
} else {
- LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
- return LLVMBuildStructGEP(g->builder, maybe_struct_ref, maybe_child_index, "");
+ LLVMValueRef optional_struct_ref = get_handle_value(g, base_ptr, maybe_type, ptr_type);
+ if (instruction->initializing) {
+ LLVMValueRef non_null_bit_ptr = LLVMBuildStructGEP(g->builder, optional_struct_ref,
+ maybe_null_index, "");
+ LLVMValueRef non_null_bit = LLVMConstInt(LLVMInt1Type(), 1, false);
+ gen_store_untyped(g, non_null_bit, non_null_bit_ptr, 0, false);
+ }
+ return LLVMBuildStructGEP(g->builder, optional_struct_ref, maybe_child_index, "");
}
}
}
@@ -4224,17 +4268,17 @@ static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutable *executable, IrInstru
return phi;
}
-static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutable *executable, IrInstructionRef *instruction) {
+static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutable *executable, IrInstructionRefGen *instruction) {
if (!type_has_bits(instruction->base.value.type)) {
return nullptr;
}
- LLVMValueRef value = ir_llvm_value(g, instruction->value);
- if (handle_is_ptr(instruction->value->value.type)) {
+ LLVMValueRef value = ir_llvm_value(g, instruction->operand);
+ if (handle_is_ptr(instruction->operand->value.type)) {
return value;
} else {
- assert(instruction->tmp_ptr);
- gen_store_untyped(g, value, instruction->tmp_ptr, 0, false);
- return instruction->tmp_ptr;
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
+ gen_store_untyped(g, value, result_loc, 0, false);
+ return result_loc;
}
}
@@ -4350,7 +4394,9 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) {
g->cur_fn = prev_cur_fn;
g->cur_fn_val = prev_cur_fn_val;
LLVMPositionBuilderAtEnd(g->builder, prev_block);
- LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ if (!g->strip_debug_symbols) {
+ LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ }
enum_type->data.enumeration.name_function = fn_val;
return fn_val;
@@ -4526,28 +4572,28 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn
LLVMValueRef result_val = ZigLLVMBuildCmpXchg(g->builder, ptr_val, cmp_val, new_val,
success_order, failure_order, instruction->is_weak);
- ZigType *maybe_type = instruction->base.value.type;
- assert(maybe_type->id == ZigTypeIdOptional);
- ZigType *child_type = maybe_type->data.maybe.child_type;
+ ZigType *optional_type = instruction->base.value.type;
+ assert(optional_type->id == ZigTypeIdOptional);
+ ZigType *child_type = optional_type->data.maybe.child_type;
- if (!handle_is_ptr(maybe_type)) {
+ if (!handle_is_ptr(optional_type)) {
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, "");
}
- assert(instruction->tmp_ptr != nullptr);
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
assert(type_has_bits(child_type));
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
- LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");
+ LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, "");
gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, "");
- LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_null_index, "");
+ LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_null_index, "");
gen_store_untyped(g, nonnull_bit, maybe_ptr, 0, false);
- return instruction->tmp_ptr;
+ return result_loc;
}
static LLVMValueRef ir_render_fence(CodeGen *g, IrExecutable *executable, IrInstructionFence *instruction) {
@@ -4619,16 +4665,14 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns
return nullptr;
}
-static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInstructionSlice *instruction) {
- assert(instruction->tmp_ptr);
-
+static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInstructionSliceGen *instruction) {
LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->ptr);
ZigType *array_ptr_type = instruction->ptr->value.type;
assert(array_ptr_type->id == ZigTypeIdPointer);
ZigType *array_type = array_ptr_type->data.pointer.child_type;
LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
- LLVMValueRef tmp_struct_ptr = instruction->tmp_ptr;
+ LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
bool want_runtime_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base);
@@ -4646,7 +4690,9 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
end_val = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, array_type->data.array.len, false);
}
if (want_runtime_safety) {
- add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
+ if (instruction->start->value.special == ConstValSpecialRuntime || instruction->end) {
+ add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
+ }
if (instruction->end) {
LLVMValueRef array_end = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,
array_type->data.array.len, false);
@@ -4877,10 +4923,10 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutable *executable,
return overflow_bit;
}
-static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrInstructionTestErr *instruction) {
- ZigType *err_union_type = instruction->value->value.type;
+static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrInstructionTestErrGen *instruction) {
+ ZigType *err_union_type = instruction->err_union->value.type;
ZigType *payload_type = err_union_type->data.error_union.payload_type;
- LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->value);
+ LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->err_union);
LLVMValueRef err_val;
if (type_has_bits(payload_type)) {
@@ -4897,25 +4943,30 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI
static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable,
IrInstructionUnwrapErrCode *instruction)
{
- ZigType *ptr_type = instruction->err_union->value.type;
+ if (instruction->base.value.special != ConstValSpecialRuntime)
+ return nullptr;
+
+ ZigType *ptr_type = instruction->err_union_ptr->value.type;
assert(ptr_type->id == ZigTypeIdPointer);
ZigType *err_union_type = ptr_type->data.pointer.child_type;
ZigType *payload_type = err_union_type->data.error_union.payload_type;
- LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->err_union);
- LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
-
- if (type_has_bits(payload_type)) {
- LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
- return gen_load_untyped(g, err_val_ptr, 0, false, "");
+ LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->err_union_ptr);
+ if (!type_has_bits(payload_type)) {
+ return err_union_ptr;
} else {
- return err_union_handle;
+ // TODO assign undef to the payload
+ LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
+ return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
}
}
static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable,
IrInstructionUnwrapErrPayload *instruction)
{
- bool want_safety = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on &&
+ if (instruction->base.value.special != ConstValSpecialRuntime)
+ return nullptr;
+
+ bool want_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base) &&
g->errors_by_index.length > 1;
if (!want_safety && !type_has_bits(instruction->base.value.type))
return nullptr;
@@ -4951,13 +5002,18 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu
}
if (type_has_bits(payload_type)) {
+ if (instruction->initializing) {
+ LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
+ LLVMValueRef ok_err_val = LLVMConstNull(get_llvm_type(g, g->err_tag_type));
+ gen_store_untyped(g, ok_err_val, err_tag_ptr, 0, false);
+ }
return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_payload_index, "");
} else {
return nullptr;
}
}
-static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, IrInstructionOptionalWrap *instruction) {
+static LLVMValueRef ir_render_optional_wrap(CodeGen *g, IrExecutable *executable, IrInstructionOptionalWrap *instruction) {
ZigType *wanted_type = instruction->base.value.type;
assert(wanted_type->id == ZigTypeIdOptional);
@@ -4965,23 +5021,32 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I
ZigType *child_type = wanted_type->data.maybe.child_type;
if (!type_has_bits(child_type)) {
- return LLVMConstInt(LLVMInt1Type(), 1, false);
+ LLVMValueRef result = LLVMConstAllOnes(LLVMInt1Type());
+ if (instruction->result_loc != nullptr) {
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
+ gen_store_untyped(g, result, result_loc, 0, false);
+ }
+ return result;
}
- LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
+ LLVMValueRef payload_val = ir_llvm_value(g, instruction->operand);
if (!handle_is_ptr(wanted_type)) {
+ if (instruction->result_loc != nullptr) {
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
+ gen_store_untyped(g, payload_val, result_loc, 0, false);
+ }
return payload_val;
}
- assert(instruction->tmp_ptr);
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
- LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");
+ LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, "");
// child_type and instruction->value->value.type may differ by constness
gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
- LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_null_index, "");
+ LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_null_index, "");
gen_store_untyped(g, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr, 0, false);
- return instruction->tmp_ptr;
+ return result_loc;
}
static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutable *executable, IrInstructionErrWrapCode *instruction) {
@@ -4989,20 +5054,19 @@ static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutable *executable
assert(wanted_type->id == ZigTypeIdErrorUnion);
- ZigType *payload_type = wanted_type->data.error_union.payload_type;
- ZigType *err_set_type = wanted_type->data.error_union.err_set_type;
+ LLVMValueRef err_val = ir_llvm_value(g, instruction->operand);
- LLVMValueRef err_val = ir_llvm_value(g, instruction->value);
-
- if (!type_has_bits(payload_type) || !type_has_bits(err_set_type))
+ if (!handle_is_ptr(wanted_type))
return err_val;
- assert(instruction->tmp_ptr);
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
- LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, "");
+ LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_err_index, "");
gen_store_untyped(g, err_val, err_tag_ptr, 0, false);
- return instruction->tmp_ptr;
+ // TODO store undef to the payload
+
+ return result_loc;
}
static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executable, IrInstructionErrWrapPayload *instruction) {
@@ -5014,7 +5078,7 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa
ZigType *err_set_type = wanted_type->data.error_union.err_set_type;
if (!type_has_bits(err_set_type)) {
- return ir_llvm_value(g, instruction->value);
+ return ir_llvm_value(g, instruction->operand);
}
LLVMValueRef ok_err_val = LLVMConstNull(get_llvm_type(g, g->err_tag_type));
@@ -5022,17 +5086,18 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa
if (!type_has_bits(payload_type))
return ok_err_val;
- assert(instruction->tmp_ptr);
- LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
- LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, "");
+ LLVMValueRef payload_val = ir_llvm_value(g, instruction->operand);
+
+ LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_err_index, "");
gen_store_untyped(g, ok_err_val, err_tag_ptr, 0, false);
- LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_payload_index, "");
+ LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_payload_index, "");
gen_assign_raw(g, payload_ptr, get_pointer_to_type(g, payload_type, false), payload_val);
- return instruction->tmp_ptr;
+ return result_loc;
}
static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, IrInstructionUnionTag *instruction) {
@@ -5053,90 +5118,6 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, Ir
return get_handle_value(g, tag_field_ptr, tag_type, ptr_type);
}
-static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, IrInstructionStructInit *instruction) {
- for (size_t i = 0; i < instruction->field_count; i += 1) {
- IrInstructionStructInitField *field = &instruction->fields[i];
- TypeStructField *type_struct_field = field->type_struct_field;
- if (!type_has_bits(type_struct_field->type_entry))
- continue;
-
- LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
- (unsigned)type_struct_field->gen_index, "");
- LLVMValueRef value = ir_llvm_value(g, field->value);
-
- uint32_t field_align_bytes = get_abi_alignment(g, type_struct_field->type_entry);
- uint32_t host_int_bytes = get_host_int_bytes(g, instruction->struct_type, type_struct_field);
-
- ZigType *ptr_type = get_pointer_to_type_extra(g, type_struct_field->type_entry,
- false, false, PtrLenSingle, field_align_bytes,
- (uint32_t)type_struct_field->bit_offset_in_host, host_int_bytes, false);
-
- gen_assign_raw(g, field_ptr, ptr_type, value);
- }
- return instruction->tmp_ptr;
-}
-
-static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, IrInstructionUnionInit *instruction) {
- TypeUnionField *type_union_field = instruction->field;
-
- if (!type_has_bits(type_union_field->type_entry))
- return nullptr;
-
- uint32_t field_align_bytes = get_abi_alignment(g, type_union_field->type_entry);
- ZigType *ptr_type = get_pointer_to_type_extra(g, type_union_field->type_entry,
- false, false, PtrLenSingle, field_align_bytes,
- 0, 0, false);
-
- LLVMValueRef uncasted_union_ptr;
- // Even if safety is off in this block, if the union type has the safety field, we have to populate it
- // correctly. Otherwise safety code somewhere other than here could fail.
- ZigType *union_type = instruction->union_type;
- if (union_type->data.unionation.gen_tag_index != SIZE_MAX) {
- LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
- union_type->data.unionation.gen_tag_index, "");
-
- LLVMValueRef tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type),
- &type_union_field->enum_field->value);
- gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
-
- uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
- (unsigned)union_type->data.unionation.gen_union_index, "");
- } else {
- uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, (unsigned)0, "");
- }
-
- LLVMValueRef field_ptr = LLVMBuildBitCast(g->builder, uncasted_union_ptr, get_llvm_type(g, ptr_type), "");
- LLVMValueRef value = ir_llvm_value(g, instruction->init_value);
-
- gen_assign_raw(g, field_ptr, ptr_type, value);
-
- return instruction->tmp_ptr;
-}
-
-static LLVMValueRef ir_render_container_init_list(CodeGen *g, IrExecutable *executable,
- IrInstructionContainerInitList *instruction)
-{
- ZigType *array_type = instruction->base.value.type;
- assert(array_type->id == ZigTypeIdArray);
- LLVMValueRef tmp_array_ptr = instruction->tmp_ptr;
- assert(tmp_array_ptr);
-
- size_t field_count = instruction->item_count;
-
- ZigType *child_type = array_type->data.array.child_type;
- for (size_t i = 0; i < field_count; i += 1) {
- LLVMValueRef elem_val = ir_llvm_value(g, instruction->items[i]);
- LLVMValueRef indices[] = {
- LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
- LLVMConstInt(g->builtin_types.entry_usize->llvm_type, i, false),
- };
- LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, tmp_array_ptr, indices, 2, "");
- gen_assign_raw(g, elem_ptr, get_pointer_to_type(g, child_type, false), elem_val);
- }
-
- return tmp_array_ptr;
-}
-
static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutable *executable, IrInstructionPanic *instruction) {
gen_panic(g, ir_llvm_value(g, instruction->msg), get_cur_err_ret_trace_val(g, instruction->base.scope));
return nullptr;
@@ -5353,7 +5334,9 @@ static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_f
g->cur_fn = prev_cur_fn;
g->cur_fn_val = prev_cur_fn_val;
LLVMPositionBuilderAtEnd(g->builder, prev_block);
- LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ if (!g->strip_debug_symbols) {
+ LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ }
g->coro_alloc_helper_fn_val = fn_val;
return fn_val;
@@ -5499,12 +5482,12 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab
ZigType *array_type = instruction->base.value.type;
assert(array_type->id == ZigTypeIdArray);
assert(handle_is_ptr(array_type));
- assert(instruction->tmp_ptr);
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
- LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr,
+ LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc,
LLVMPointerType(get_llvm_type(g, instruction->vector->value.type), 0), "");
- gen_store_untyped(g, vector, casted_ptr, 0, false);
- return instruction->tmp_ptr;
+ gen_store_untyped(g, vector, casted_ptr, get_ptr_align(g, instruction->result_loc->value.type), false);
+ return result_loc;
}
static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executable,
@@ -5567,14 +5550,10 @@ static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
}
static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
- set_debug_location(g, instruction);
-
switch (instruction->id) {
case IrInstructionIdInvalid:
case IrInstructionIdConst:
case IrInstructionIdTypeOf:
- case IrInstructionIdToPtrType:
- case IrInstructionIdPtrTypeChild:
case IrInstructionIdFieldPtr:
case IrInstructionIdSetCold:
case IrInstructionIdSetRuntimeSafety:
@@ -5610,6 +5589,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdByteOffsetOf:
case IrInstructionIdBitOffsetOf:
case IrInstructionIdTypeInfo:
+ case IrInstructionIdHasField:
case IrInstructionIdTypeId:
case IrInstructionIdSetEvalBranchQuota:
case IrInstructionIdPtrType:
@@ -5636,10 +5616,23 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdPtrCastSrc:
case IrInstructionIdCmpxchgSrc:
case IrInstructionIdLoadPtr:
- case IrInstructionIdBitCast:
case IrInstructionIdGlobalAsm:
case IrInstructionIdHasDecl:
case IrInstructionIdUndeclaredIdent:
+ case IrInstructionIdCallSrc:
+ case IrInstructionIdAllocaSrc:
+ case IrInstructionIdEndExpr:
+ case IrInstructionIdAllocaGen:
+ case IrInstructionIdImplicitCast:
+ case IrInstructionIdResolveResult:
+ case IrInstructionIdResetResult:
+ case IrInstructionIdResultPtr:
+ case IrInstructionIdContainerInitList:
+ case IrInstructionIdSliceSrc:
+ case IrInstructionIdRef:
+ case IrInstructionIdBitCastSrc:
+ case IrInstructionIdTestErrSrc:
+ case IrInstructionIdUnionInitNamedField:
zig_unreachable();
case IrInstructionIdDeclVarGen:
@@ -5664,10 +5657,12 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction);
case IrInstructionIdVarPtr:
return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction);
+ case IrInstructionIdReturnPtr:
+ return ir_render_return_ptr(g, executable, (IrInstructionReturnPtr *)instruction);
case IrInstructionIdElemPtr:
return ir_render_elem_ptr(g, executable, (IrInstructionElemPtr *)instruction);
- case IrInstructionIdCall:
- return ir_render_call(g, executable, (IrInstructionCall *)instruction);
+ case IrInstructionIdCallGen:
+ return ir_render_call(g, executable, (IrInstructionCallGen *)instruction);
case IrInstructionIdStructFieldPtr:
return ir_render_struct_field_ptr(g, executable, (IrInstructionStructFieldPtr *)instruction);
case IrInstructionIdUnionFieldPtr:
@@ -5692,8 +5687,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_bit_reverse(g, executable, (IrInstructionBitReverse *)instruction);
case IrInstructionIdPhi:
return ir_render_phi(g, executable, (IrInstructionPhi *)instruction);
- case IrInstructionIdRef:
- return ir_render_ref(g, executable, (IrInstructionRef *)instruction);
+ case IrInstructionIdRefGen:
+ return ir_render_ref(g, executable, (IrInstructionRefGen *)instruction);
case IrInstructionIdErrName:
return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction);
case IrInstructionIdCmpxchgGen:
@@ -5708,8 +5703,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_memset(g, executable, (IrInstructionMemset *)instruction);
case IrInstructionIdMemcpy:
return ir_render_memcpy(g, executable, (IrInstructionMemcpy *)instruction);
- case IrInstructionIdSlice:
- return ir_render_slice(g, executable, (IrInstructionSlice *)instruction);
+ case IrInstructionIdSliceGen:
+ return ir_render_slice(g, executable, (IrInstructionSliceGen *)instruction);
case IrInstructionIdBreakpoint:
return ir_render_breakpoint(g, executable, (IrInstructionBreakpoint *)instruction);
case IrInstructionIdReturnAddress:
@@ -5720,24 +5715,20 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_handle(g, executable, (IrInstructionHandle *)instruction);
case IrInstructionIdOverflowOp:
return ir_render_overflow_op(g, executable, (IrInstructionOverflowOp *)instruction);
- case IrInstructionIdTestErr:
- return ir_render_test_err(g, executable, (IrInstructionTestErr *)instruction);
+ case IrInstructionIdTestErrGen:
+ return ir_render_test_err(g, executable, (IrInstructionTestErrGen *)instruction);
case IrInstructionIdUnwrapErrCode:
return ir_render_unwrap_err_code(g, executable, (IrInstructionUnwrapErrCode *)instruction);
case IrInstructionIdUnwrapErrPayload:
return ir_render_unwrap_err_payload(g, executable, (IrInstructionUnwrapErrPayload *)instruction);
case IrInstructionIdOptionalWrap:
- return ir_render_maybe_wrap(g, executable, (IrInstructionOptionalWrap *)instruction);
+ return ir_render_optional_wrap(g, executable, (IrInstructionOptionalWrap *)instruction);
case IrInstructionIdErrWrapCode:
return ir_render_err_wrap_code(g, executable, (IrInstructionErrWrapCode *)instruction);
case IrInstructionIdErrWrapPayload:
return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction);
case IrInstructionIdUnionTag:
return ir_render_union_tag(g, executable, (IrInstructionUnionTag *)instruction);
- case IrInstructionIdStructInit:
- return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
- case IrInstructionIdUnionInit:
- return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
case IrInstructionIdPtrCastGen:
return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction);
case IrInstructionIdBitCastGen:
@@ -5754,8 +5745,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_int_to_err(g, executable, (IrInstructionIntToErr *)instruction);
case IrInstructionIdErrToInt:
return ir_render_err_to_int(g, executable, (IrInstructionErrToInt *)instruction);
- case IrInstructionIdContainerInitList:
- return ir_render_container_init_list(g, executable, (IrInstructionContainerInitList *)instruction);
case IrInstructionIdPanic:
return ir_render_panic(g, executable, (IrInstructionPanic *)instruction);
case IrInstructionIdTagName:
@@ -5818,6 +5807,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_assert_non_null(g, executable, (IrInstructionAssertNonNull *)instruction);
case IrInstructionIdResizeSlice:
return ir_render_resize_slice(g, executable, (IrInstructionResizeSlice *)instruction);
+ case IrInstructionIdPtrOfArrayToSlice:
+ return ir_render_ptr_of_array_to_slice(g, executable, (IrInstructionPtrOfArrayToSlice *)instruction);
}
zig_unreachable();
}
@@ -5829,7 +5820,6 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
assert(executable->basic_block_list.length > 0);
for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {
IrBasicBlock *current_block = executable->basic_block_list.at(block_i);
- //assert(current_block->ref_count > 0);
assert(current_block->llvm_block);
LLVMPositionBuilderAtEnd(g->builder, current_block->llvm_block);
for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {
@@ -5837,6 +5827,9 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
if (instruction->ref_count == 0 && !ir_has_side_effects(instruction))
continue;
+ if (!g->strip_debug_symbols) {
+ set_debug_location(g, instruction);
+ }
instruction->llvm_value = ir_render_instruction(g, executable, instruction);
}
current_block->llvm_exit_block = LLVMGetInsertBlock(g->builder);
@@ -6626,7 +6619,8 @@ static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const
LLVMSetLinkage(global_value, LLVMInternalLinkage);
LLVMSetGlobalConstant(global_value, true);
LLVMSetUnnamedAddr(global_value, true);
- LLVMSetAlignment(global_value, get_abi_alignment(g, const_val->type));
+ LLVMSetAlignment(global_value, (const_val->global_refs->align == 0) ?
+ get_abi_alignment(g, const_val->type) : const_val->global_refs->align);
const_val->global_refs->llvm_global = global_value;
}
@@ -6751,7 +6745,7 @@ static void do_code_gen(CodeGen *g) {
zig_panic("TODO debug info for var with ptr casted value");
}
ZigType *var_type = g->builtin_types.entry_f128;
- ConstExprValue coerced_value;
+ ConstExprValue coerced_value = {};
coerced_value.special = ConstValSpecialStatic;
coerced_value.type = var_type;
coerced_value.data.x_f128 = bigfloat_to_f128(&const_val->data.x_bigfloat);
@@ -6856,20 +6850,24 @@ static void do_code_gen(CodeGen *g) {
FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id;
CallingConvention cc = fn_type_id->cc;
bool is_c_abi = cc == CallingConventionC;
+ bool want_sret = want_first_arg_sret(g, fn_type_id);
LLVMValueRef fn = fn_llvm_value(g, fn_table_entry);
g->cur_fn = fn_table_entry;
g->cur_fn_val = fn;
- ZigType *return_type = fn_type_id->return_type;
- if (handle_is_ptr(return_type)) {
+
+ build_all_basic_blocks(g, fn_table_entry);
+ clear_debug_source_node(g);
+
+ if (want_sret) {
g->cur_ret_ptr = LLVMGetParam(fn, 0);
+ } else if (handle_is_ptr(fn_type_id->return_type)) {
+ g->cur_ret_ptr = build_alloca(g, fn_type_id->return_type, "result", 0);
+ // TODO add debug info variable for this
} else {
g->cur_ret_ptr = nullptr;
}
- build_all_basic_blocks(g, fn_table_entry);
- clear_debug_source_node(g);
-
uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
bool have_err_ret_trace_arg = err_ret_trace_arg_index != UINT32_MAX;
if (have_err_ret_trace_arg) {
@@ -6894,68 +6892,28 @@ static void do_code_gen(CodeGen *g) {
}
// allocate temporary stack data
- for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_list.length; alloca_i += 1) {
- IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i);
- LLVMValueRef *slot;
- ZigType *slot_type = instruction->value.type;
- uint32_t alignment_bytes = 0;
- if (instruction->id == IrInstructionIdCast) {
- IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction;
- slot = &cast_instruction->tmp_ptr;
- } else if (instruction->id == IrInstructionIdRef) {
- IrInstructionRef *ref_instruction = (IrInstructionRef *)instruction;
- slot = &ref_instruction->tmp_ptr;
- assert(instruction->value.type->id == ZigTypeIdPointer);
- slot_type = instruction->value.type->data.pointer.child_type;
- } else if (instruction->id == IrInstructionIdContainerInitList) {
- IrInstructionContainerInitList *container_init_list_instruction = (IrInstructionContainerInitList *)instruction;
- slot = &container_init_list_instruction->tmp_ptr;
- } else if (instruction->id == IrInstructionIdStructInit) {
- IrInstructionStructInit *struct_init_instruction = (IrInstructionStructInit *)instruction;
- slot = &struct_init_instruction->tmp_ptr;
- } else if (instruction->id == IrInstructionIdUnionInit) {
- IrInstructionUnionInit *union_init_instruction = (IrInstructionUnionInit *)instruction;
- slot = &union_init_instruction->tmp_ptr;
- } else if (instruction->id == IrInstructionIdCall) {
- IrInstructionCall *call_instruction = (IrInstructionCall *)instruction;
- slot = &call_instruction->tmp_ptr;
- } else if (instruction->id == IrInstructionIdSlice) {
- IrInstructionSlice *slice_instruction = (IrInstructionSlice *)instruction;
- slot = &slice_instruction->tmp_ptr;
- } else if (instruction->id == IrInstructionIdOptionalWrap) {
- IrInstructionOptionalWrap *maybe_wrap_instruction = (IrInstructionOptionalWrap *)instruction;
- slot = &maybe_wrap_instruction->tmp_ptr;
- } else if (instruction->id == IrInstructionIdErrWrapPayload) {
- IrInstructionErrWrapPayload *err_wrap_payload_instruction = (IrInstructionErrWrapPayload *)instruction;
- slot = &err_wrap_payload_instruction->tmp_ptr;
- } else if (instruction->id == IrInstructionIdErrWrapCode) {
- IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;
- slot = &err_wrap_code_instruction->tmp_ptr;
- } else if (instruction->id == IrInstructionIdCmpxchgGen) {
- IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction;
- slot = &cmpxchg_instruction->tmp_ptr;
- } else if (instruction->id == IrInstructionIdResizeSlice) {
- IrInstructionResizeSlice *resize_slice_instruction = (IrInstructionResizeSlice *)instruction;
- slot = &resize_slice_instruction->tmp_ptr;
- } else if (instruction->id == IrInstructionIdLoadPtrGen) {
- IrInstructionLoadPtrGen *load_ptr_inst = (IrInstructionLoadPtrGen *)instruction;
- slot = &load_ptr_inst->tmp_ptr;
- } else if (instruction->id == IrInstructionIdBitCastGen) {
- IrInstructionBitCastGen *bit_cast_inst = (IrInstructionBitCastGen *)instruction;
- slot = &bit_cast_inst->tmp_ptr;
- } else if (instruction->id == IrInstructionIdVectorToArray) {
- IrInstructionVectorToArray *vector_to_array_instruction = (IrInstructionVectorToArray *)instruction;
- alignment_bytes = get_abi_alignment(g, vector_to_array_instruction->vector->value.type);
- slot = &vector_to_array_instruction->tmp_ptr;
- } else {
- zig_unreachable();
+ for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_gen_list.length; alloca_i += 1) {
+ IrInstructionAllocaGen *instruction = fn_table_entry->alloca_gen_list.at(alloca_i);
+ ZigType *ptr_type = instruction->base.value.type;
+ assert(ptr_type->id == ZigTypeIdPointer);
+ ZigType *child_type = ptr_type->data.pointer.child_type;
+ if (!type_has_bits(child_type))
+ continue;
+ if (instruction->base.ref_count == 0)
+ continue;
+ if (instruction->base.value.special != ConstValSpecialRuntime) {
+ if (const_ptr_pointee(nullptr, g, &instruction->base.value, nullptr)->special !=
+ ConstValSpecialRuntime)
+ {
+ continue;
+ }
}
- *slot = build_alloca(g, slot_type, "", alignment_bytes);
+ instruction->base.llvm_value = build_alloca(g, child_type, instruction->name_hint,
+ get_ptr_align(g, ptr_type));
}
ZigType *import = get_scope_import(&fn_table_entry->fndef_scope->base);
-
- unsigned gen_i_init = want_first_arg_sret(g, fn_type_id) ? 1 : 0;
+ unsigned gen_i_init = want_sret ? 1 : 0;
// create debug variable declarations for variables and allocate all local variables
FnWalk fn_walk_var = {};
@@ -6982,8 +6940,6 @@ static void do_code_gen(CodeGen *g) {
}
if (var->src_arg_index == SIZE_MAX) {
- var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
-
var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
buf_ptr(&var->name), import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1),
get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0);
@@ -7371,6 +7327,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdMemberName, "memberName", 2);
create_builtin_fn(g, BuiltinFnIdField, "field", 2);
create_builtin_fn(g, BuiltinFnIdTypeInfo, "typeInfo", 1);
+ create_builtin_fn(g, BuiltinFnIdHasField, "hasField", 2);
create_builtin_fn(g, BuiltinFnIdTypeof, "typeOf", 1); // TODO rename to TypeOf
create_builtin_fn(g, BuiltinFnIdAddWithOverflow, "addWithOverflow", 4);
create_builtin_fn(g, BuiltinFnIdSubWithOverflow, "subWithOverflow", 4);
@@ -7460,6 +7417,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
create_builtin_fn(g, BuiltinFnIdThis, "This", 0);
create_builtin_fn(g, BuiltinFnIdHasDecl, "hasDecl", 2);
+ create_builtin_fn(g, BuiltinFnIdUnionInit, "unionInit", 3);
}
static const char *bool_to_str(bool b) {
@@ -7962,6 +7920,14 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
}
{
buf_appendf(contents,
+ "pub const Version = struct {\n"
+ " major: u32,\n"
+ " minor: u32,\n"
+ " patch: u32,\n"
+ "};\n\n");
+ }
+ {
+ buf_appendf(contents,
"pub const SubSystem = enum {\n"
" Console,\n"
" Windows,\n"
@@ -7991,6 +7957,15 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);
buf_appendf(contents, "pub const arch = %s;\n", cur_arch);
buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi);
+ if (g->libc_link_lib != nullptr && g->zig_target->glibc_version != nullptr) {
+ buf_appendf(contents,
+ "pub const glibc_version: ?Version = Version{.major = %d, .minor = %d, .patch = %d};\n",
+ g->zig_target->glibc_version->major,
+ g->zig_target->glibc_version->minor,
+ g->zig_target->glibc_version->patch);
+ } else {
+ buf_appendf(contents, "pub const glibc_version: ?Version = null;\n");
+ }
buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt);
buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode));
buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->libc_link_lib != nullptr));
@@ -8047,6 +8022,11 @@ static Error define_builtin_compile_vars(CodeGen *g) {
cache_int(&cache_hash, g->zig_target->vendor);
cache_int(&cache_hash, g->zig_target->os);
cache_int(&cache_hash, g->zig_target->abi);
+ if (g->zig_target->glibc_version != nullptr) {
+ cache_int(&cache_hash, g->zig_target->glibc_version->major);
+ cache_int(&cache_hash, g->zig_target->glibc_version->minor);
+ cache_int(&cache_hash, g->zig_target->glibc_version->patch);
+ }
cache_bool(&cache_hash, g->have_err_ret_tracing);
cache_bool(&cache_hash, g->libc_link_lib != nullptr);
cache_bool(&cache_hash, g->valgrind_support);
@@ -8098,6 +8078,8 @@ static Error define_builtin_compile_vars(CodeGen *g) {
g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
g->std_package->package_table.put(buf_create_from_str("std"), g->std_package);
+ g->std_package->package_table.put(buf_create_from_str("root"),
+ g->is_test_build ? g->test_runner_package : g->root_package);
g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents,
SourceKindPkgMain);
@@ -8121,7 +8103,7 @@ static void init(CodeGen *g) {
assert(g->root_out_name);
g->module = LLVMModuleCreateWithName(buf_ptr(g->root_out_name));
- LLVMSetTarget(g->module, buf_ptr(&g->triple_str));
+ LLVMSetTarget(g->module, buf_ptr(&g->llvm_triple_str));
if (target_object_format(g->zig_target) == ZigLLVM_COFF) {
ZigLLVMAddModuleCodeViewFlag(g->module);
@@ -8131,13 +8113,13 @@ static void init(CodeGen *g) {
LLVMTargetRef target_ref;
char *err_msg = nullptr;
- if (LLVMGetTargetFromTriple(buf_ptr(&g->triple_str), &target_ref, &err_msg)) {
+ if (LLVMGetTargetFromTriple(buf_ptr(&g->llvm_triple_str), &target_ref, &err_msg)) {
fprintf(stderr,
"Zig is expecting LLVM to understand this target: '%s'\n"
"However LLVM responded with: \"%s\"\n"
"Zig is unable to continue. This is a bug in Zig:\n"
"https://github.com/ziglang/zig/issues/438\n"
- , buf_ptr(&g->triple_str), err_msg);
+ , buf_ptr(&g->llvm_triple_str), err_msg);
exit(1);
}
@@ -8171,8 +8153,9 @@ static void init(CodeGen *g) {
target_specific_features = "";
}
- g->target_machine = LLVMCreateTargetMachine(target_ref, buf_ptr(&g->triple_str),
- target_specific_cpu_args, target_specific_features, opt_level, reloc_mode, LLVMCodeModelDefault);
+ g->target_machine = ZigLLVMCreateTargetMachine(target_ref, buf_ptr(&g->llvm_triple_str),
+ target_specific_cpu_args, target_specific_features, opt_level, reloc_mode,
+ LLVMCodeModelDefault, g->function_sections);
g->target_data_ref = LLVMCreateTargetDataLayout(g->target_machine);
@@ -8350,12 +8333,12 @@ static void detect_libc(CodeGen *g) {
!target_os_is_darwin(g->zig_target->os))
{
Buf triple_buf = BUF_INIT;
- get_target_triple(&triple_buf, g->zig_target);
+ target_triple_zig(&triple_buf, g->zig_target);
fprintf(stderr,
"Zig is unable to provide a libc for the chosen target '%s'.\n"
"The target is non-native, so Zig also cannot use the native libc installation.\n"
- "Choose a target which has a libc available, or provide a libc installation text file.\n"
- "See `zig libc --help` for more details.\n", buf_ptr(&triple_buf));
+ "Choose a target which has a libc available (see `zig targets`), or\n"
+ "provide a libc installation text file (see `zig libc --help`).\n", buf_ptr(&triple_buf));
exit(1);
}
}
@@ -8377,6 +8360,10 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
args.append("-nostdinc");
args.append("-fno-spell-checking");
+ if (g->function_sections) {
+ args.append("-ffunction-sections");
+ }
+
if (translate_c) {
// this gives us access to preprocessing entities, presumably at
// the cost of performance
@@ -8410,12 +8397,18 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
args.append("-march=native");
} else {
args.append("-target");
- args.append(buf_ptr(&g->triple_str));
+ args.append(buf_ptr(&g->llvm_triple_str));
}
if (g->zig_target->os == OsFreestanding) {
args.append("-ffreestanding");
}
+ // windows.h has files such as pshpack1.h which do #pragma packing, triggering a clang warning.
+ // So for this target, we disable this warning.
+ if (g->zig_target->os == OsWindows && target_abi_is_gnu(g->zig_target->abi)) {
+ args.append("-Wno-pragma-pack");
+ }
+
if (!g->strip_debug_symbols) {
args.append("-g");
}
@@ -8565,9 +8558,9 @@ static ZigType *add_special_code(CodeGen *g, ZigPackage *package, const char *ba
return add_source_file(g, package, resolved_path, import_code, SourceKindPkgMain);
}
-static ZigPackage *create_bootstrap_pkg(CodeGen *g, ZigPackage *pkg_with_main) {
- ZigPackage *package = codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "bootstrap.zig", "std.special");
- package->package_table.put(buf_create_from_str("@root"), pkg_with_main);
+static ZigPackage *create_start_pkg(CodeGen *g, ZigPackage *pkg_with_main) {
+ ZigPackage *package = codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "start.zig", "std.special");
+ package->package_table.put(buf_create_from_str("root"), pkg_with_main);
return package;
}
@@ -8647,6 +8640,38 @@ static Buf *get_resolved_root_src_path(CodeGen *g) {
return resolved_path;
}
+static bool want_startup_code(CodeGen *g) {
+ // Test builds get handled separately.
+ if (g->is_test_build)
+ return false;
+
+ // start code does not handle UEFI target
+ if (g->zig_target->os == OsUefi)
+ return false;
+
+ // WASM freestanding can still have an entry point but other freestanding targets do not.
+ if (g->zig_target->os == OsFreestanding && !target_is_wasm(g->zig_target))
+ return false;
+
+ // Declaring certain export functions means skipping the start code
+ if (g->have_c_main || g->have_winmain || g->have_winmain_crt_startup)
+ return false;
+
+ // If there is a pub main in the root source file, that means we need start code.
+ if (g->have_pub_main)
+ return true;
+
+ if (g->out_type == OutTypeExe) {
+ // For build-exe, we might add start code even though there is no pub main, so that the
+ // programmer gets the "no pub main" compile error. However if linking libc and there is
+ // a C source file, that might have main().
+ return g->c_source_files.length == 0 || g->libc_link_lib == nullptr;
+ }
+
+ // For objects and libraries, and we don't have pub main, no start code.
+ return false;
+}
+
static void gen_root_source(CodeGen *g) {
Buf *resolved_path = get_resolved_root_src_path(g);
if (resolved_path == nullptr)
@@ -8687,17 +8712,13 @@ static void gen_root_source(CodeGen *g) {
}
report_errors_and_maybe_exit(g);
- if (!g->is_test_build && (g->zig_target->os != OsFreestanding || target_is_wasm(g->zig_target)) &&
- g->zig_target->os != OsUefi &&
- !g->have_c_main && !g->have_winmain && !g->have_winmain_crt_startup &&
- ((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe))
- {
- g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap.zig");
+ if (want_startup_code(g)) {
+ g->start_import = add_special_code(g, create_start_pkg(g, g->root_package), "start.zig");
}
if (g->zig_target->os == OsWindows && !g->have_dllmain_crt_startup &&
g->out_type == OutTypeLib && g->is_dynamic)
{
- g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap_lib.zig");
+ g->start_import = add_special_code(g, create_start_pkg(g, g->root_package), "start_lib.zig");
}
if (!g->error_during_imports) {
@@ -8705,7 +8726,7 @@ static void gen_root_source(CodeGen *g) {
}
if (g->is_test_build) {
create_test_compile_var_and_add_test_runner(g);
- g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->test_runner_package), "bootstrap.zig");
+ g->start_import = add_special_code(g, create_start_pkg(g, g->test_runner_package), "start.zig");
if (!g->error_during_imports) {
semantic_analyze(g);
@@ -8720,10 +8741,10 @@ static void gen_root_source(CodeGen *g) {
}
-static void print_zig_cc_cmd(const char *zig_exe, ZigList<const char *> *args) {
- fprintf(stderr, "%s", zig_exe);
+static void print_zig_cc_cmd(ZigList<const char *> *args) {
for (size_t arg_i = 0; arg_i < args->length; arg_i += 1) {
- fprintf(stderr, " %s", args->at(arg_i));
+ const char *space_str = (arg_i == 0) ? "" : " ";
+ fprintf(stderr, "%s%s", space_str, args->at(arg_i));
}
fprintf(stderr, "\n");
}
@@ -8773,6 +8794,7 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose
cache_int(cache_hash, g->build_mode);
cache_bool(cache_hash, g->have_pic);
cache_bool(cache_hash, want_valgrind_support(g));
+ cache_bool(cache_hash, g->function_sections);
for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) {
cache_str(cache_hash, g->clang_argv[arg_i]);
}
@@ -8860,12 +8882,12 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
}
if (g->verbose_cc) {
- print_zig_cc_cmd("zig", &args);
+ print_zig_cc_cmd(&args);
}
os_spawn_process(args, &term);
if (term.how != TerminationIdClean || term.code != 0) {
fprintf(stderr, "\nThe following command failed:\n");
- print_zig_cc_cmd(buf_ptr(self_exe_path), &args);
+ print_zig_cc_cmd(&args);
exit(1);
}
@@ -9420,6 +9442,7 @@ void codegen_add_time_event(CodeGen *g, const char *name) {
static void add_cache_pkg(CodeGen *g, CacheHash *ch, ZigPackage *pkg) {
if (buf_len(&pkg->root_src_path) == 0)
return;
+ pkg->added_to_cache = true;
Buf *rel_full_path = buf_alloc();
os_path_join(&pkg->root_src_dir, &pkg->root_src_path, rel_full_path);
@@ -9431,9 +9454,7 @@ static void add_cache_pkg(CodeGen *g, CacheHash *ch, ZigPackage *pkg) {
if (!entry)
break;
- // TODO: I think we need a more sophisticated detection of
- // packages we have already seen
- if (entry->value != pkg) {
+ if (!pkg->added_to_cache) {
cache_buf(ch, entry->key);
add_cache_pkg(g, ch, entry->value);
}
@@ -9472,6 +9493,11 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_int(ch, g->zig_target->vendor);
cache_int(ch, g->zig_target->os);
cache_int(ch, g->zig_target->abi);
+ if (g->zig_target->glibc_version != nullptr) {
+ cache_int(ch, g->zig_target->glibc_version->major);
+ cache_int(ch, g->zig_target->glibc_version->minor);
+ cache_int(ch, g->zig_target->glibc_version->patch);
+ }
cache_int(ch, detect_subsystem(g));
cache_bool(ch, g->strip_debug_symbols);
cache_bool(ch, g->is_test_build);
@@ -9489,6 +9515,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_bool(ch, g->have_dynamic_link);
cache_bool(ch, g->have_stack_probing);
cache_bool(ch, g->is_dummy_so);
+ cache_bool(ch, g->function_sections);
cache_buf_opt(ch, g->mmacosx_version_min);
cache_buf_opt(ch, g->mios_version_min);
cache_usize(ch, g->version_major);
@@ -9505,6 +9532,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_buf(ch, &g->libc->kernel32_lib_dir);
}
cache_buf_opt(ch, g->dynamic_linker_path);
+ cache_buf_opt(ch, g->version_script_path);
// gen_c_objects appends objects to g->link_objects which we want to include in the hash
gen_c_objects(g);
@@ -9612,7 +9640,7 @@ void codegen_build_and_link(CodeGen *g) {
fprintf(stderr, "Unable to check cache: %s is not a directory\n",
buf_ptr(manifest_dir));
} else {
- fprintf(stderr, "Unable to check cache: %s\n", err_str(err));
+ fprintf(stderr, "Unable to check cache: %s: %s\n", buf_ptr(manifest_dir), err_str(err));
}
exit(1);
}
@@ -9676,10 +9704,14 @@ void codegen_build_and_link(CodeGen *g) {
}
}
+ codegen_release_caches(g);
+ codegen_add_time_event(g, "Done");
+}
+
+void codegen_release_caches(CodeGen *g) {
while (g->caches_to_release.length != 0) {
cache_release(g->caches_to_release.pop());
}
- codegen_add_time_event(g, "Done");
}
ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path,
@@ -9690,7 +9722,43 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c
if (g->std_package != nullptr) {
assert(g->compile_var_package != nullptr);
pkg->package_table.put(buf_create_from_str("std"), g->std_package);
+
+ ZigPackage *main_pkg = g->is_test_build ? g->test_runner_package : g->root_package;
+ pkg->package_table.put(buf_create_from_str("root"), main_pkg);
+
pkg->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
}
return pkg;
}
+
+CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType out_type,
+ ZigLibCInstallation *libc)
+{
+ CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type,
+ parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir, libc, get_stage1_cache_path());
+ child_gen->disable_gen_h = true;
+ child_gen->want_stack_check = WantStackCheckDisabled;
+ child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
+ child_gen->verbose_ast = parent_gen->verbose_ast;
+ child_gen->verbose_link = parent_gen->verbose_link;
+ child_gen->verbose_ir = parent_gen->verbose_ir;
+ child_gen->verbose_llvm_ir = parent_gen->verbose_llvm_ir;
+ child_gen->verbose_cimport = parent_gen->verbose_cimport;
+ child_gen->verbose_cc = parent_gen->verbose_cc;
+ child_gen->llvm_argv = parent_gen->llvm_argv;
+ child_gen->dynamic_linker_path = parent_gen->dynamic_linker_path;
+
+ codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);
+ child_gen->want_pic = parent_gen->have_pic ? WantPICEnabled : WantPICDisabled;
+ child_gen->valgrind_support = ValgrindSupportDisabled;
+
+ codegen_set_errmsg_color(child_gen, parent_gen->err_color);
+
+ codegen_set_mmacosx_version_min(child_gen, parent_gen->mmacosx_version_min);
+ codegen_set_mios_version_min(child_gen, parent_gen->mios_version_min);
+
+ child_gen->enable_cache = true;
+
+ return child_gen;
+}
+
diff --git a/src/codegen.hpp b/src/codegen.hpp
index 9a340d7205..5de36c1aab 100644
--- a/src/codegen.hpp
+++ b/src/codegen.hpp
@@ -20,6 +20,9 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
OutType out_type, BuildMode build_mode, Buf *zig_lib_dir, Buf *override_std_dir,
ZigLibCInstallation *libc, Buf *cache_dir);
+CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType out_type,
+ ZigLibCInstallation *libc);
+
void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);
void codegen_set_is_test(CodeGen *codegen, bool is_test);
@@ -58,4 +61,6 @@ Buf *codegen_generate_builtin_source(CodeGen *g);
TargetSubsystem detect_subsystem(CodeGen *g);
+void codegen_release_caches(CodeGen *codegen);
+
#endif
diff --git a/src/compiler.cpp b/src/compiler.cpp
index 8bfe87bfcd..5d401f1851 100644
--- a/src/compiler.cpp
+++ b/src/compiler.cpp
@@ -9,9 +9,13 @@ static Buf saved_stage1_path = BUF_INIT;
static Buf saved_lib_dir = BUF_INIT;
static Buf saved_special_dir = BUF_INIT;
static Buf saved_std_dir = BUF_INIT;
+
static Buf saved_dynamic_linker_path = BUF_INIT;
static bool searched_for_dyn_linker = false;
+static Buf saved_libc_path = BUF_INIT;
+static bool searched_for_libc = false;
+
Buf *get_stage1_cache_path(void) {
if (saved_stage1_path.list.length != 0) {
return &saved_stage1_path;
@@ -36,6 +40,28 @@ static void detect_dynamic_linker(Buf *lib_path) {
#endif
}
+const Buf *get_self_libc_path(void) {
+ for (;;) {
+ if (saved_libc_path.list.length != 0) {
+ return &saved_libc_path;
+ }
+ if (searched_for_libc)
+ return nullptr;
+ ZigList<Buf *> lib_paths = {};
+ Error err;
+ if ((err = os_self_exe_shared_libs(lib_paths)))
+ return nullptr;
+ for (size_t i = 0; i < lib_paths.length; i += 1) {
+ Buf *lib_path = lib_paths.at(i);
+ if (buf_ends_with_str(lib_path, "libc.so.6")) {
+ buf_init_from_buf(&saved_libc_path, lib_path);
+ return &saved_libc_path;
+ }
+ }
+ searched_for_libc = true;
+ }
+}
+
Buf *get_self_dynamic_linker_path(void) {
for (;;) {
if (saved_dynamic_linker_path.list.length != 0) {
diff --git a/src/compiler.hpp b/src/compiler.hpp
index 4d682ba2fa..62991570f0 100644
--- a/src/compiler.hpp
+++ b/src/compiler.hpp
@@ -14,6 +14,7 @@
Buf *get_stage1_cache_path(void);
Error get_compiler_id(Buf **result);
Buf *get_self_dynamic_linker_path(void);
+Buf *get_self_libc_path(void);
Buf *get_zig_lib_dir(void);
Buf *get_zig_special_dir(Buf *zig_lib_dir);
diff --git a/src/config.h.in b/src/config.h.in
index 93e31ad9b7..a99aab0d72 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -23,7 +23,5 @@
#define ZIG_LLD_LIBRARIES "@LLD_LIBRARIES@"
#define ZIG_LLVM_CONFIG_EXE "@LLVM_CONFIG_EXE@"
#define ZIG_DIA_GUIDS_LIB "@ZIG_DIA_GUIDS_LIB_ESCAPED@"
-#define ZIG_STD_FILES "@ZIG_STD_FILES@"
-#define ZIG_C_HEADER_FILES "@ZIG_C_HEADER_FILES@"
#endif
diff --git a/src/glibc.cpp b/src/glibc.cpp
new file mode 100644
index 0000000000..d7ae47ed71
--- /dev/null
+++ b/src/glibc.cpp
@@ -0,0 +1,406 @@
+/*
+ * Copyright (c) 2019 Andrew Kelley
+ *
+ * This file is part of zig, which is MIT licensed.
+ * See http://opensource.org/licenses/MIT
+ */
+
+#include "glibc.hpp"
+#include "compiler.hpp"
+#include "cache_hash.hpp"
+#include "codegen.hpp"
+
+static const ZigGLibCLib glibc_libs[] = {
+ {"c", 6},
+ {"m", 6},
+ {"pthread", 0},
+ {"dl", 2},
+ {"rt", 1},
+};
+
+Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbose) {
+ Error err;
+
+ ZigGLibCAbi *glibc_abi = allocate<ZigGLibCAbi>(1);
+ glibc_abi->vers_txt_path = buf_sprintf("%s" OS_SEP "libc" OS_SEP "glibc" OS_SEP "vers.txt", buf_ptr(zig_lib_dir));
+ glibc_abi->fns_txt_path = buf_sprintf("%s" OS_SEP "libc" OS_SEP "glibc" OS_SEP "fns.txt", buf_ptr(zig_lib_dir));
+ glibc_abi->abi_txt_path = buf_sprintf("%s" OS_SEP "libc" OS_SEP "glibc" OS_SEP "abi.txt", buf_ptr(zig_lib_dir));
+ glibc_abi->version_table.init(16);
+
+ Buf *vers_txt_contents = buf_alloc();
+ if ((err = os_fetch_file_path(glibc_abi->vers_txt_path, vers_txt_contents))) {
+ if (verbose) {
+ fprintf(stderr, "Unable to read %s: %s\n", buf_ptr(glibc_abi->vers_txt_path), err_str(err));
+ }
+ return err;
+ }
+ Buf *fns_txt_contents = buf_alloc();
+ if ((err = os_fetch_file_path(glibc_abi->fns_txt_path, fns_txt_contents))) {
+ if (verbose) {
+ fprintf(stderr, "Unable to read %s: %s\n", buf_ptr(glibc_abi->fns_txt_path), err_str(err));
+ }
+ return err;
+ }
+ Buf *abi_txt_contents = buf_alloc();
+ if ((err = os_fetch_file_path(glibc_abi->abi_txt_path, abi_txt_contents))) {
+ if (verbose) {
+ fprintf(stderr, "Unable to read %s: %s\n", buf_ptr(glibc_abi->abi_txt_path), err_str(err));
+ }
+ return err;
+ }
+
+ {
+ SplitIterator it = memSplit(buf_to_slice(vers_txt_contents), str("\n"));
+ for (;;) {
+ Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
+ if (!opt_component.is_some) break;
+ Buf *ver_buf = buf_create_from_slice(opt_component.value);
+ ZigGLibCVersion *this_ver = glibc_abi->all_versions.add_one();
+ if ((err = target_parse_glibc_version(this_ver, buf_ptr(ver_buf)))) {
+ if (verbose) {
+ fprintf(stderr, "Unable to parse glibc version '%s': %s\n", buf_ptr(ver_buf), err_str(err));
+ }
+ return err;
+ }
+ }
+ }
+ {
+ SplitIterator it = memSplit(buf_to_slice(fns_txt_contents), str("\n"));
+ for (;;) {
+ Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
+ if (!opt_component.is_some) break;
+ SplitIterator line_it = memSplit(opt_component.value, str(" "));
+ Optional<Slice<uint8_t>> opt_fn_name = SplitIterator_next(&line_it);
+ if (!opt_fn_name.is_some) {
+ if (verbose) {
+ fprintf(stderr, "%s: Expected function name\n", buf_ptr(glibc_abi->fns_txt_path));
+ }
+ return ErrorInvalidFormat;
+ }
+ Optional<Slice<uint8_t>> opt_lib_name = SplitIterator_next(&line_it);
+ if (!opt_lib_name.is_some) {
+ if (verbose) {
+ fprintf(stderr, "%s: Expected lib name\n", buf_ptr(glibc_abi->fns_txt_path));
+ }
+ return ErrorInvalidFormat;
+ }
+
+ Buf *this_fn_name = buf_create_from_slice(opt_fn_name.value);
+ Buf *this_lib_name = buf_create_from_slice(opt_lib_name.value);
+ glibc_abi->all_functions.append({ this_fn_name, glibc_lib_find(buf_ptr(this_lib_name)) });
+ }
+ }
+ {
+ SplitIterator it = memSplit(buf_to_slice(abi_txt_contents), str("\n"));
+ ZigGLibCVerList *ver_list_base = nullptr;
+ for (;;) {
+ if (ver_list_base == nullptr) {
+ Optional<Slice<uint8_t>> opt_line = SplitIterator_next_separate(&it);
+ if (!opt_line.is_some) break;
+
+ ver_list_base = allocate<ZigGLibCVerList>(glibc_abi->all_functions.length);
+ ZigTarget *target = allocate<ZigTarget>(1);
+ SplitIterator line_it = memSplit(opt_line.value, str(" "));
+ for (;;) {
+ Optional<Slice<uint8_t>> opt_target = SplitIterator_next(&line_it);
+ if (!opt_target.is_some) break;
+
+ SplitIterator component_it = memSplit(opt_target.value, str("-"));
+ Optional<Slice<uint8_t>> opt_arch = SplitIterator_next(&component_it);
+ assert(opt_arch.is_some);
+ Optional<Slice<uint8_t>> opt_os = SplitIterator_next(&component_it);
+ assert(opt_os.is_some); // it's always "linux" so we ignore it
+ Optional<Slice<uint8_t>> opt_abi = SplitIterator_next(&component_it);
+ assert(opt_abi.is_some);
+
+
+ err = target_parse_archsub(&target->arch, &target->sub_arch,
+ (char*)opt_arch.value.ptr, opt_arch.value.len);
+ // there's no sub arch so we might get an error, but the arch is still populated
+ assert(err == ErrorNone || err == ErrorUnknownArchitecture);
+
+ target->os = OsLinux;
+
+ err = target_parse_abi(&target->abi, (char*)opt_abi.value.ptr, opt_abi.value.len);
+ assert(err == ErrorNone);
+
+ glibc_abi->version_table.put(target, ver_list_base);
+ }
+ continue;
+ }
+ for (size_t fn_i = 0; fn_i < glibc_abi->all_functions.length; fn_i += 1) {
+ ZigGLibCVerList *ver_list = &ver_list_base[fn_i];
+ Optional<Slice<uint8_t>> opt_line = SplitIterator_next_separate(&it);
+ assert(opt_line.is_some);
+
+ SplitIterator line_it = memSplit(opt_line.value, str(" "));
+ for (;;) {
+ Optional<Slice<uint8_t>> opt_ver = SplitIterator_next(&line_it);
+ if (!opt_ver.is_some) break;
+ assert(ver_list->len < 8); // increase the array len in the type
+
+ unsigned long ver_index = strtoul(buf_ptr(buf_create_from_slice(opt_ver.value)), nullptr, 10);
+ assert(ver_index < 255); // use a bigger integer in the type
+ ver_list->versions[ver_list->len] = ver_index;
+ ver_list->len += 1;
+ }
+ }
+ ver_list_base = nullptr;
+ }
+ }
+
+ *out_result = glibc_abi;
+ return ErrorNone;
+}
+
+Error glibc_build_dummies_and_maps(CodeGen *g, const ZigGLibCAbi *glibc_abi, const ZigTarget *target,
+ Buf **out_dir, bool verbose)
+{
+ Error err;
+
+ Buf *cache_dir = get_stage1_cache_path();
+ CacheHash *cache_hash = allocate<CacheHash>(1);
+ Buf *manifest_dir = buf_sprintf("%s" OS_SEP CACHE_HASH_SUBDIR, buf_ptr(cache_dir));
+ cache_init(cache_hash, manifest_dir);
+
+ Buf *compiler_id;
+ if ((err = get_compiler_id(&compiler_id))) {
+ if (verbose) {
+ fprintf(stderr, "unable to get compiler id: %s\n", err_str(err));
+ }
+ return err;
+ }
+ cache_buf(cache_hash, compiler_id);
+ cache_int(cache_hash, target->arch);
+ cache_int(cache_hash, target->abi);
+ cache_int(cache_hash, target->glibc_version->major);
+ cache_int(cache_hash, target->glibc_version->minor);
+ cache_int(cache_hash, target->glibc_version->patch);
+
+ Buf digest = BUF_INIT;
+ buf_resize(&digest, 0);
+ if ((err = cache_hit(cache_hash, &digest))) {
+ // Treat an invalid format error as a cache miss.
+ if (err != ErrorInvalidFormat)
+ return err;
+ }
+ // We should always get a cache hit because there are no
+ // files in the input hash.
+ assert(buf_len(&digest) != 0);
+
+ Buf *dummy_dir = buf_alloc();
+ os_path_join(manifest_dir, &digest, dummy_dir);
+
+ if ((err = os_make_path(dummy_dir)))
+ return err;
+
+ Buf *test_if_exists_path = buf_alloc();
+ os_path_join(dummy_dir, buf_create_from_str("ok"), test_if_exists_path);
+
+ bool hit;
+ if ((err = os_file_exists(test_if_exists_path, &hit)))
+ return err;
+
+ if (hit) {
+ *out_dir = dummy_dir;
+ return ErrorNone;
+ }
+
+
+ ZigGLibCVerList *ver_list_base = glibc_abi->version_table.get(target);
+
+ uint8_t target_ver_index = 0;
+ for (;target_ver_index < glibc_abi->all_versions.length; target_ver_index += 1) {
+ const ZigGLibCVersion *this_ver = &glibc_abi->all_versions.at(target_ver_index);
+ if (this_ver->major == target->glibc_version->major &&
+ this_ver->minor == target->glibc_version->minor &&
+ this_ver->patch == target->glibc_version->patch)
+ {
+ break;
+ }
+ }
+ if (target_ver_index == glibc_abi->all_versions.length) {
+ if (verbose) {
+ fprintf(stderr, "Unrecognized glibc version: %d.%d.%d\n",
+ target->glibc_version->major,
+ target->glibc_version->minor,
+ target->glibc_version->patch);
+ }
+ return ErrorUnknownABI;
+ }
+
+ Buf *map_file_path = buf_sprintf("%s" OS_SEP "all.map", buf_ptr(dummy_dir));
+ Buf *map_contents = buf_alloc();
+
+ for (uint8_t ver_i = 0; ver_i < glibc_abi->all_versions.length; ver_i += 1) {
+ const ZigGLibCVersion *ver = &glibc_abi->all_versions.at(ver_i);
+ if (ver->patch == 0) {
+ buf_appendf(map_contents, "GLIBC_%d.%d { };\n", ver->major, ver->minor);
+ } else {
+ buf_appendf(map_contents, "GLIBC_%d.%d.%d { };\n", ver->major, ver->minor, ver->patch);
+ }
+ }
+
+ if ((err = os_write_file(map_file_path, map_contents))) {
+ if (verbose) {
+ fprintf(stderr, "unable to write %s: %s", buf_ptr(map_file_path), err_str(err));
+ }
+ return err;
+ }
+
+
+ for (size_t lib_i = 0; lib_i < array_length(glibc_libs); lib_i += 1) {
+ const ZigGLibCLib *lib = &glibc_libs[lib_i];
+ Buf *zig_file_path = buf_sprintf("%s" OS_SEP "%s.zig", buf_ptr(dummy_dir), lib->name);
+ Buf *zig_body = buf_alloc();
+ Buf *zig_footer = buf_alloc();
+
+ buf_appendf(zig_body, "comptime {\n");
+ buf_appendf(zig_body, " asm (\n");
+
+ for (size_t fn_i = 0; fn_i < glibc_abi->all_functions.length; fn_i += 1) {
+ const ZigGLibCFn *libc_fn = &glibc_abi->all_functions.at(fn_i);
+ if (libc_fn->lib != lib) continue;
+ ZigGLibCVerList *ver_list = &ver_list_base[fn_i];
+ // Pick the default symbol version:
+ // - If there are no versions, don't emit it
+ // - Take the greatest one <= than the target one
+ // - If none of them is <= than the
+ // specified one don't pick any default version
+ if (ver_list->len == 0) continue;
+ uint8_t chosen_def_ver_index = 255;
+ for (uint8_t ver_i = 0; ver_i < ver_list->len; ver_i += 1) {
+ uint8_t ver_index = ver_list->versions[ver_i];
+ if ((chosen_def_ver_index == 255 || ver_index > chosen_def_ver_index) &&
+ target_ver_index >= ver_index)
+ {
+ chosen_def_ver_index = ver_index;
+ }
+ }
+ for (uint8_t ver_i = 0; ver_i < ver_list->len; ver_i += 1) {
+ uint8_t ver_index = ver_list->versions[ver_i];
+
+ Buf *stub_name;
+ const ZigGLibCVersion *ver = &glibc_abi->all_versions.at(ver_index);
+ const char *sym_name = buf_ptr(libc_fn->name);
+ if (ver->patch == 0) {
+ stub_name = buf_sprintf("%s_%d_%d", sym_name, ver->major, ver->minor);
+ } else {
+ stub_name = buf_sprintf("%s_%d_%d_%d", sym_name, ver->major, ver->minor, ver->patch);
+ }
+
+ buf_appendf(zig_footer, "export fn %s() void {}\n", buf_ptr(stub_name));
+
+ // Default symbol version definition vs normal symbol version definition
+ const char *at_sign_str = (chosen_def_ver_index != 255 &&
+ ver_index == chosen_def_ver_index) ? "@@" : "@";
+ if (ver->patch == 0) {
+ buf_appendf(zig_body, " \\\\ .symver %s, %s%sGLIBC_%d.%d\n",
+ buf_ptr(stub_name), sym_name, at_sign_str, ver->major, ver->minor);
+ } else {
+ buf_appendf(zig_body, " \\\\ .symver %s, %s%sGLIBC_%d.%d.%d\n",
+ buf_ptr(stub_name), sym_name, at_sign_str, ver->major, ver->minor, ver->patch);
+ }
+ // Hide the stub to keep the symbol table clean
+ buf_appendf(zig_body, " \\\\ .hidden %s\n", buf_ptr(stub_name));
+ }
+ }
+
+ buf_appendf(zig_body, " );\n");
+ buf_appendf(zig_body, "}\n");
+ buf_append_buf(zig_body, zig_footer);
+
+ if ((err = os_write_file(zig_file_path, zig_body))) {
+ if (verbose) {
+ fprintf(stderr, "unable to write %s: %s", buf_ptr(zig_file_path), err_str(err));
+ }
+ return err;
+ }
+
+ CodeGen *child_gen = create_child_codegen(g, zig_file_path, OutTypeLib, nullptr);
+ codegen_set_out_name(child_gen, buf_create_from_str(lib->name));
+ codegen_set_lib_version(child_gen, lib->sover, 0, 0);
+ child_gen->is_dynamic = true;
+ child_gen->is_dummy_so = true;
+ child_gen->version_script_path = map_file_path;
+ child_gen->enable_cache = false;
+ child_gen->output_dir = dummy_dir;
+ codegen_build_and_link(child_gen);
+ }
+
+ if ((err = os_write_file(test_if_exists_path, buf_alloc()))) {
+ if (verbose) {
+ fprintf(stderr, "unable to write %s: %s", buf_ptr(test_if_exists_path), err_str(err));
+ }
+ return err;
+ }
+ *out_dir = dummy_dir;
+ return ErrorNone;
+}
+
+uint32_t hash_glibc_target(const ZigTarget *x) {
+ return x->arch * 3250106448 +
+ x->os * 542534372 +
+ x->abi * 59162639;
+}
+
+bool eql_glibc_target(const ZigTarget *a, const ZigTarget *b) {
+ return a->arch == b->arch &&
+ a->os == b->os &&
+ a->abi == b->abi;
+}
+
+#ifdef ZIG_OS_LINUX
+#include <unistd.h>
+Error glibc_detect_native_version(ZigGLibCVersion *glibc_ver) {
+ Buf *self_libc_path = get_self_libc_path();
+ if (self_libc_path == nullptr) {
+ // TODO There is still more we could do to detect the native glibc version. For example,
+ // we could look at the ELF file of `/usr/bin/env`, find `libc.so.6`, and then `readlink`
+ // to find out the glibc version. This is relevant for the static zig builds distributed
+ // on the download page, since the above detection based on zig's own dynamic linking
+ // will not work.
+
+ return ErrorUnknownABI;
+ }
+ Buf *link_name = buf_alloc();
+ buf_resize(link_name, 4096);
+ ssize_t amt = readlink(buf_ptr(self_libc_path), buf_ptr(link_name), buf_len(link_name));
+ if (amt == -1) {
+ return ErrorUnknownABI;
+ }
+ buf_resize(link_name, amt);
+ if (!buf_starts_with_str(link_name, "libc-") || !buf_ends_with_str(link_name, ".so")) {
+ return ErrorUnknownABI;
+ }
+ // example: "libc-2.3.4.so"
+ // example: "libc-2.27.so"
+ buf_resize(link_name, buf_len(link_name) - 3); // chop off ".so"
+ glibc_ver->major = 2;
+ glibc_ver->minor = 0;
+ glibc_ver->patch = 0;
+ return target_parse_glibc_version(glibc_ver, buf_ptr(link_name) + 5);
+}
+#else
+Error glibc_detect_native_version(ZigGLibCVersion *glibc_ver) {
+ return ErrorUnknownABI;
+}
+#endif
+
+size_t glibc_lib_count(void) {
+ return array_length(glibc_libs);
+}
+
+const ZigGLibCLib *glibc_lib_enum(size_t index) {
+ assert(index < array_length(glibc_libs));
+ return &glibc_libs[index];
+}
+
+const ZigGLibCLib *glibc_lib_find(const char *name) {
+ for (size_t i = 0; i < array_length(glibc_libs); i += 1) {
+ if (strcmp(glibc_libs[i].name, name) == 0) {
+ return &glibc_libs[i];
+ }
+ }
+ return nullptr;
+}
diff --git a/src/glibc.hpp b/src/glibc.hpp
new file mode 100644
index 0000000000..50796197d4
--- /dev/null
+++ b/src/glibc.hpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019 Andrew Kelley
+ *
+ * This file is part of zig, which is MIT licensed.
+ * See http://opensource.org/licenses/MIT
+ */
+
+#ifndef ZIG_GLIBC_HPP
+#define ZIG_GLIBC_HPP
+
+#include "all_types.hpp"
+
+struct ZigGLibCLib {
+ const char *name;
+ uint8_t sover;
+};
+
+struct ZigGLibCFn {
+ Buf *name;
+ const ZigGLibCLib *lib;
+};
+
+struct ZigGLibCVerList {
+ uint8_t versions[8]; // 8 is just the max number, we know statically it's big enough
+ uint8_t len;
+};
+
+uint32_t hash_glibc_target(const ZigTarget *x);
+bool eql_glibc_target(const ZigTarget *a, const ZigTarget *b);
+
+struct ZigGLibCAbi {
+ Buf *abi_txt_path;
+ Buf *vers_txt_path;
+ Buf *fns_txt_path;
+ ZigList<ZigGLibCVersion> all_versions;
+ ZigList<ZigGLibCFn> all_functions;
+ // The value is a pointer to all_functions.length items and each item is an index
+ // into all_functions.
+ HashMap<const ZigTarget *, ZigGLibCVerList *, hash_glibc_target, eql_glibc_target> version_table;
+};
+
+Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbose);
+Error glibc_build_dummies_and_maps(CodeGen *codegen, const ZigGLibCAbi *glibc_abi, const ZigTarget *target,
+ Buf **out_dir, bool verbose);
+
+// returns ErrorUnknownABI when glibc is not the native libc
+Error glibc_detect_native_version(ZigGLibCVersion *glibc_ver);
+
+size_t glibc_lib_count(void);
+const ZigGLibCLib *glibc_lib_enum(size_t index);
+const ZigGLibCLib *glibc_lib_find(const char *name);
+
+#endif
diff --git a/src/install_files.h b/src/install_files.h
new file mode 100644
index 0000000000..8b6a4dc059
--- /dev/null
+++ b/src/install_files.h
@@ -0,0 +1,1802 @@
+#ifndef ZIG_INSTALL_FILES_H
+#define ZIG_INSTALL_FILES_H
+static const char *ZIG_MUSL_SRC_FILES[] = {
+"musl/src/aio/aio.c",
+"musl/src/aio/aio_suspend.c",
+"musl/src/aio/lio_listio.c",
+"musl/src/complex/__cexp.c",
+"musl/src/complex/__cexpf.c",
+"musl/src/complex/cabs.c",
+"musl/src/complex/cabsf.c",
+"musl/src/complex/cabsl.c",
+"musl/src/complex/cacos.c",
+"musl/src/complex/cacosf.c",
+"musl/src/complex/cacosh.c",
+"musl/src/complex/cacoshf.c",
+"musl/src/complex/cacoshl.c",
+"musl/src/complex/cacosl.c",
+"musl/src/complex/carg.c",
+"musl/src/complex/cargf.c",
+"musl/src/complex/cargl.c",
+"musl/src/complex/casin.c",
+"musl/src/complex/casinf.c",
+"musl/src/complex/casinh.c",
+"musl/src/complex/casinhf.c",
+"musl/src/complex/casinhl.c",
+"musl/src/complex/casinl.c",
+"musl/src/complex/catan.c",
+"musl/src/complex/catanf.c",
+"musl/src/complex/catanh.c",
+"musl/src/complex/catanhf.c",
+"musl/src/complex/catanhl.c",
+"musl/src/complex/catanl.c",
+"musl/src/complex/ccos.c",
+"musl/src/complex/ccosf.c",
+"musl/src/complex/ccosh.c",
+"musl/src/complex/ccoshf.c",
+"musl/src/complex/ccoshl.c",
+"musl/src/complex/ccosl.c",
+"musl/src/complex/cexp.c",
+"musl/src/complex/cexpf.c",
+"musl/src/complex/cexpl.c",
+"musl/src/complex/cimag.c",
+"musl/src/complex/cimagf.c",
+"musl/src/complex/cimagl.c",
+"musl/src/complex/clog.c",
+"musl/src/complex/clogf.c",
+"musl/src/complex/clogl.c",
+"musl/src/complex/conj.c",
+"musl/src/complex/conjf.c",
+"musl/src/complex/conjl.c",
+"musl/src/complex/cpow.c",
+"musl/src/complex/cpowf.c",
+"musl/src/complex/cpowl.c",
+"musl/src/complex/cproj.c",
+"musl/src/complex/cprojf.c",
+"musl/src/complex/cprojl.c",
+"musl/src/complex/creal.c",
+"musl/src/complex/crealf.c",
+"musl/src/complex/creall.c",
+"musl/src/complex/csin.c",
+"musl/src/complex/csinf.c",
+"musl/src/complex/csinh.c",
+"musl/src/complex/csinhf.c",
+"musl/src/complex/csinhl.c",
+"musl/src/complex/csinl.c",
+"musl/src/complex/csqrt.c",
+"musl/src/complex/csqrtf.c",
+"musl/src/complex/csqrtl.c",
+"musl/src/complex/ctan.c",
+"musl/src/complex/ctanf.c",
+"musl/src/complex/ctanh.c",
+"musl/src/complex/ctanhf.c",
+"musl/src/complex/ctanhl.c",
+"musl/src/complex/ctanl.c",
+"musl/src/conf/confstr.c",
+"musl/src/conf/fpathconf.c",
+"musl/src/conf/legacy.c",
+"musl/src/conf/pathconf.c",
+"musl/src/conf/sysconf.c",
+"musl/src/crypt/crypt.c",
+"musl/src/crypt/crypt_blowfish.c",
+"musl/src/crypt/crypt_des.c",
+"musl/src/crypt/crypt_des.h",
+"musl/src/crypt/crypt_md5.c",
+"musl/src/crypt/crypt_r.c",
+"musl/src/crypt/crypt_sha256.c",
+"musl/src/crypt/crypt_sha512.c",
+"musl/src/crypt/encrypt.c",
+"musl/src/ctype/__ctype_b_loc.c",
+"musl/src/ctype/__ctype_get_mb_cur_max.c",
+"musl/src/ctype/__ctype_tolower_loc.c",
+"musl/src/ctype/__ctype_toupper_loc.c",
+"musl/src/ctype/alpha.h",
+"musl/src/ctype/isalnum.c",
+"musl/src/ctype/isalpha.c",
+"musl/src/ctype/isascii.c",
+"musl/src/ctype/isblank.c",
+"musl/src/ctype/iscntrl.c",
+"musl/src/ctype/isdigit.c",
+"musl/src/ctype/isgraph.c",
+"musl/src/ctype/islower.c",
+"musl/src/ctype/isprint.c",
+"musl/src/ctype/ispunct.c",
+"musl/src/ctype/isspace.c",
+"musl/src/ctype/isupper.c",
+"musl/src/ctype/iswalnum.c",
+"musl/src/ctype/iswalpha.c",
+"musl/src/ctype/iswblank.c",
+"musl/src/ctype/iswcntrl.c",
+"musl/src/ctype/iswctype.c",
+"musl/src/ctype/iswdigit.c",
+"musl/src/ctype/iswgraph.c",
+"musl/src/ctype/iswlower.c",
+"musl/src/ctype/iswprint.c",
+"musl/src/ctype/iswpunct.c",
+"musl/src/ctype/iswspace.c",
+"musl/src/ctype/iswupper.c",
+"musl/src/ctype/iswxdigit.c",
+"musl/src/ctype/isxdigit.c",
+"musl/src/ctype/nonspacing.h",
+"musl/src/ctype/punct.h",
+"musl/src/ctype/toascii.c",
+"musl/src/ctype/tolower.c",
+"musl/src/ctype/toupper.c",
+"musl/src/ctype/towctrans.c",
+"musl/src/ctype/wcswidth.c",
+"musl/src/ctype/wctrans.c",
+"musl/src/ctype/wcwidth.c",
+"musl/src/ctype/wide.h",
+"musl/src/dirent/__dirent.h",
+"musl/src/dirent/alphasort.c",
+"musl/src/dirent/closedir.c",
+"musl/src/dirent/dirfd.c",
+"musl/src/dirent/fdopendir.c",
+"musl/src/dirent/opendir.c",
+"musl/src/dirent/readdir.c",
+"musl/src/dirent/readdir_r.c",
+"musl/src/dirent/rewinddir.c",
+"musl/src/dirent/scandir.c",
+"musl/src/dirent/seekdir.c",
+"musl/src/dirent/telldir.c",
+"musl/src/dirent/versionsort.c",
+"musl/src/env/__environ.c",
+"musl/src/env/__init_tls.c",
+"musl/src/env/__libc_start_main.c",
+"musl/src/env/__reset_tls.c",
+"musl/src/env/__stack_chk_fail.c",
+"musl/src/env/clearenv.c",
+"musl/src/env/getenv.c",
+"musl/src/env/putenv.c",
+"musl/src/env/setenv.c",
+"musl/src/env/unsetenv.c",
+"musl/src/errno/__errno_location.c",
+"musl/src/errno/__strerror.h",
+"musl/src/errno/strerror.c",
+"musl/src/exit/_Exit.c",
+"musl/src/exit/abort.c",
+"musl/src/exit/arm/__aeabi_atexit.c",
+"musl/src/exit/assert.c",
+"musl/src/exit/at_quick_exit.c",
+"musl/src/exit/atexit.c",
+"musl/src/exit/exit.c",
+"musl/src/exit/quick_exit.c",
+"musl/src/fcntl/creat.c",
+"musl/src/fcntl/fcntl.c",
+"musl/src/fcntl/open.c",
+"musl/src/fcntl/openat.c",
+"musl/src/fcntl/posix_fadvise.c",
+"musl/src/fcntl/posix_fallocate.c",
+"musl/src/fenv/__flt_rounds.c",
+"musl/src/fenv/aarch64/fenv.s",
+"musl/src/fenv/arm/fenv-hf.S",
+"musl/src/fenv/arm/fenv.c",
+"musl/src/fenv/fegetexceptflag.c",
+"musl/src/fenv/feholdexcept.c",
+"musl/src/fenv/fenv.c",
+"musl/src/fenv/fesetexceptflag.c",
+"musl/src/fenv/fesetround.c",
+"musl/src/fenv/feupdateenv.c",
+"musl/src/fenv/i386/fenv.s",
+"musl/src/fenv/m68k/fenv.c",
+"musl/src/fenv/mips/fenv-sf.c",
+"musl/src/fenv/mips/fenv.S",
+"musl/src/fenv/mips64/fenv-sf.c",
+"musl/src/fenv/mips64/fenv.S",
+"musl/src/fenv/mipsn32/fenv-sf.c",
+"musl/src/fenv/mipsn32/fenv.S",
+"musl/src/fenv/powerpc/fenv-sf.c",
+"musl/src/fenv/powerpc/fenv.S",
+"musl/src/fenv/powerpc64/fenv.c",
+"musl/src/fenv/s390x/fenv.c",
+"musl/src/fenv/sh/fenv-nofpu.c",
+"musl/src/fenv/sh/fenv.S",
+"musl/src/fenv/x32/fenv.s",
+"musl/src/fenv/x86_64/fenv.s",
+"musl/src/include/arpa/inet.h",
+"musl/src/include/crypt.h",
+"musl/src/include/errno.h",
+"musl/src/include/features.h",
+"musl/src/include/langinfo.h",
+"musl/src/include/pthread.h",
+"musl/src/include/resolv.h",
+"musl/src/include/signal.h",
+"musl/src/include/stdio.h",
+"musl/src/include/stdlib.h",
+"musl/src/include/string.h",
+"musl/src/include/sys/auxv.h",
+"musl/src/include/sys/mman.h",
+"musl/src/include/sys/sysinfo.h",
+"musl/src/include/sys/time.h",
+"musl/src/include/time.h",
+"musl/src/include/unistd.h",
+"musl/src/internal/aarch64/syscall.s",
+"musl/src/internal/arm/syscall.s",
+"musl/src/internal/atomic.h",
+"musl/src/internal/dynlink.h",
+"musl/src/internal/fdpic_crt.h",
+"musl/src/internal/floatscan.c",
+"musl/src/internal/floatscan.h",
+"musl/src/internal/futex.h",
+"musl/src/internal/i386/syscall.s",
+"musl/src/internal/intscan.c",
+"musl/src/internal/intscan.h",
+"musl/src/internal/ksigaction.h",
+"musl/src/internal/libc.c",
+"musl/src/internal/libc.h",
+"musl/src/internal/libm.h",
+"musl/src/internal/locale_impl.h",
+"musl/src/internal/lock.h",
+"musl/src/internal/m68k/syscall.s",
+"musl/src/internal/malloc_impl.h",
+"musl/src/internal/microblaze/syscall.s",
+"musl/src/internal/mips/syscall.s",
+"musl/src/internal/mips64/syscall.s",
+"musl/src/internal/mipsn32/syscall.s",
+"musl/src/internal/or1k/syscall.s",
+"musl/src/internal/powerpc/syscall.s",
+"musl/src/internal/powerpc64/syscall.s",
+"musl/src/internal/procfdname.c",
+"musl/src/internal/pthread_impl.h",
+"musl/src/internal/s390x/syscall.s",
+"musl/src/internal/sh/__shcall.c",
+"musl/src/internal/sh/syscall.s",
+"musl/src/internal/shgetc.c",
+"musl/src/internal/shgetc.h",
+"musl/src/internal/stdio_impl.h",
+"musl/src/internal/syscall.c",
+"musl/src/internal/syscall.h",
+"musl/src/internal/syscall_ret.c",
+"musl/src/internal/vdso.c",
+"musl/src/internal/version.c",
+"musl/src/internal/version.h",
+"musl/src/internal/x32/syscall.s",
+"musl/src/internal/x86_64/syscall.s",
+"musl/src/ipc/ftok.c",
+"musl/src/ipc/ipc.h",
+"musl/src/ipc/msgctl.c",
+"musl/src/ipc/msgget.c",
+"musl/src/ipc/msgrcv.c",
+"musl/src/ipc/msgsnd.c",
+"musl/src/ipc/semctl.c",
+"musl/src/ipc/semget.c",
+"musl/src/ipc/semop.c",
+"musl/src/ipc/semtimedop.c",
+"musl/src/ipc/shmat.c",
+"musl/src/ipc/shmctl.c",
+"musl/src/ipc/shmdt.c",
+"musl/src/ipc/shmget.c",
+"musl/src/ldso/__dlsym.c",
+"musl/src/ldso/aarch64/dlsym.s",
+"musl/src/ldso/aarch64/tlsdesc.s",
+"musl/src/ldso/arm/dlsym.s",
+"musl/src/ldso/arm/find_exidx.c",
+"musl/src/ldso/arm/tlsdesc.S",
+"musl/src/ldso/dl_iterate_phdr.c",
+"musl/src/ldso/dladdr.c",
+"musl/src/ldso/dlclose.c",
+"musl/src/ldso/dlerror.c",
+"musl/src/ldso/dlinfo.c",
+"musl/src/ldso/dlopen.c",
+"musl/src/ldso/dlsym.c",
+"musl/src/ldso/i386/dlsym.s",
+"musl/src/ldso/i386/tlsdesc.s",
+"musl/src/ldso/m68k/dlsym.s",
+"musl/src/ldso/microblaze/dlsym.s",
+"musl/src/ldso/mips/dlsym.s",
+"musl/src/ldso/mips64/dlsym.s",
+"musl/src/ldso/mipsn32/dlsym.s",
+"musl/src/ldso/or1k/dlsym.s",
+"musl/src/ldso/powerpc/dlsym.s",
+"musl/src/ldso/powerpc64/dlsym.s",
+"musl/src/ldso/s390x/dlsym.s",
+"musl/src/ldso/sh/dlsym.s",
+"musl/src/ldso/tlsdesc.c",
+"musl/src/ldso/x32/dlsym.s",
+"musl/src/ldso/x86_64/dlsym.s",
+"musl/src/ldso/x86_64/tlsdesc.s",
+"musl/src/legacy/cuserid.c",
+"musl/src/legacy/daemon.c",
+"musl/src/legacy/err.c",
+"musl/src/legacy/euidaccess.c",
+"musl/src/legacy/ftw.c",
+"musl/src/legacy/futimes.c",
+"musl/src/legacy/getdtablesize.c",
+"musl/src/legacy/getloadavg.c",
+"musl/src/legacy/getpagesize.c",
+"musl/src/legacy/getpass.c",
+"musl/src/legacy/getusershell.c",
+"musl/src/legacy/isastream.c",
+"musl/src/legacy/lutimes.c",
+"musl/src/legacy/ulimit.c",
+"musl/src/legacy/utmpx.c",
+"musl/src/legacy/valloc.c",
+"musl/src/linux/adjtime.c",
+"musl/src/linux/adjtimex.c",
+"musl/src/linux/arch_prctl.c",
+"musl/src/linux/brk.c",
+"musl/src/linux/cache.c",
+"musl/src/linux/cap.c",
+"musl/src/linux/chroot.c",
+"musl/src/linux/clock_adjtime.c",
+"musl/src/linux/clone.c",
+"musl/src/linux/epoll.c",
+"musl/src/linux/eventfd.c",
+"musl/src/linux/fallocate.c",
+"musl/src/linux/fanotify.c",
+"musl/src/linux/flock.c",
+"musl/src/linux/getdents.c",
+"musl/src/linux/getrandom.c",
+"musl/src/linux/inotify.c",
+"musl/src/linux/ioperm.c",
+"musl/src/linux/iopl.c",
+"musl/src/linux/klogctl.c",
+"musl/src/linux/memfd_create.c",
+"musl/src/linux/mlock2.c",
+"musl/src/linux/module.c",
+"musl/src/linux/mount.c",
+"musl/src/linux/name_to_handle_at.c",
+"musl/src/linux/open_by_handle_at.c",
+"musl/src/linux/personality.c",
+"musl/src/linux/pivot_root.c",
+"musl/src/linux/ppoll.c",
+"musl/src/linux/prctl.c",
+"musl/src/linux/prlimit.c",
+"musl/src/linux/process_vm.c",
+"musl/src/linux/ptrace.c",
+"musl/src/linux/quotactl.c",
+"musl/src/linux/readahead.c",
+"musl/src/linux/reboot.c",
+"musl/src/linux/remap_file_pages.c",
+"musl/src/linux/sbrk.c",
+"musl/src/linux/sendfile.c",
+"musl/src/linux/setfsgid.c",
+"musl/src/linux/setfsuid.c",
+"musl/src/linux/setgroups.c",
+"musl/src/linux/sethostname.c",
+"musl/src/linux/setns.c",
+"musl/src/linux/settimeofday.c",
+"musl/src/linux/signalfd.c",
+"musl/src/linux/splice.c",
+"musl/src/linux/stime.c",
+"musl/src/linux/swap.c",
+"musl/src/linux/sync_file_range.c",
+"musl/src/linux/syncfs.c",
+"musl/src/linux/sysinfo.c",
+"musl/src/linux/tee.c",
+"musl/src/linux/timerfd.c",
+"musl/src/linux/unshare.c",
+"musl/src/linux/utimes.c",
+"musl/src/linux/vhangup.c",
+"musl/src/linux/vmsplice.c",
+"musl/src/linux/wait3.c",
+"musl/src/linux/wait4.c",
+"musl/src/linux/x32/sysinfo.c",
+"musl/src/linux/xattr.c",
+"musl/src/locale/__lctrans.c",
+"musl/src/locale/__mo_lookup.c",
+"musl/src/locale/big5.h",
+"musl/src/locale/bind_textdomain_codeset.c",
+"musl/src/locale/c_locale.c",
+"musl/src/locale/catclose.c",
+"musl/src/locale/catgets.c",
+"musl/src/locale/catopen.c",
+"musl/src/locale/codepages.h",
+"musl/src/locale/dcngettext.c",
+"musl/src/locale/duplocale.c",
+"musl/src/locale/freelocale.c",
+"musl/src/locale/gb18030.h",
+"musl/src/locale/hkscs.h",
+"musl/src/locale/iconv.c",
+"musl/src/locale/iconv_close.c",
+"musl/src/locale/jis0208.h",
+"musl/src/locale/ksc.h",
+"musl/src/locale/langinfo.c",
+"musl/src/locale/legacychars.h",
+"musl/src/locale/locale_map.c",
+"musl/src/locale/localeconv.c",
+"musl/src/locale/newlocale.c",
+"musl/src/locale/pleval.c",
+"musl/src/locale/pleval.h",
+"musl/src/locale/revjis.h",
+"musl/src/locale/setlocale.c",
+"musl/src/locale/strcoll.c",
+"musl/src/locale/strfmon.c",
+"musl/src/locale/strxfrm.c",
+"musl/src/locale/textdomain.c",
+"musl/src/locale/uselocale.c",
+"musl/src/locale/wcscoll.c",
+"musl/src/locale/wcsxfrm.c",
+"musl/src/malloc/DESIGN",
+"musl/src/malloc/aligned_alloc.c",
+"musl/src/malloc/expand_heap.c",
+"musl/src/malloc/lite_malloc.c",
+"musl/src/malloc/malloc.c",
+"musl/src/malloc/malloc_usable_size.c",
+"musl/src/malloc/memalign.c",
+"musl/src/malloc/posix_memalign.c",
+"musl/src/math/__cos.c",
+"musl/src/math/__cosdf.c",
+"musl/src/math/__cosl.c",
+"musl/src/math/__expo2.c",
+"musl/src/math/__expo2f.c",
+"musl/src/math/__fpclassify.c",
+"musl/src/math/__fpclassifyf.c",
+"musl/src/math/__fpclassifyl.c",
+"musl/src/math/__invtrigl.c",
+"musl/src/math/__invtrigl.h",
+"musl/src/math/__polevll.c",
+"musl/src/math/__rem_pio2.c",
+"musl/src/math/__rem_pio2_large.c",
+"musl/src/math/__rem_pio2f.c",
+"musl/src/math/__rem_pio2l.c",
+"musl/src/math/__signbit.c",
+"musl/src/math/__signbitf.c",
+"musl/src/math/__signbitl.c",
+"musl/src/math/__sin.c",
+"musl/src/math/__sindf.c",
+"musl/src/math/__sinl.c",
+"musl/src/math/__tan.c",
+"musl/src/math/__tandf.c",
+"musl/src/math/__tanl.c",
+"musl/src/math/aarch64/ceil.c",
+"musl/src/math/aarch64/ceilf.c",
+"musl/src/math/aarch64/fabs.c",
+"musl/src/math/aarch64/fabsf.c",
+"musl/src/math/aarch64/floor.c",
+"musl/src/math/aarch64/floorf.c",
+"musl/src/math/aarch64/fma.c",
+"musl/src/math/aarch64/fmaf.c",
+"musl/src/math/aarch64/fmax.c",
+"musl/src/math/aarch64/fmaxf.c",
+"musl/src/math/aarch64/fmin.c",
+"musl/src/math/aarch64/fminf.c",
+"musl/src/math/aarch64/llrint.c",
+"musl/src/math/aarch64/llrintf.c",
+"musl/src/math/aarch64/llround.c",
+"musl/src/math/aarch64/llroundf.c",
+"musl/src/math/aarch64/lrint.c",
+"musl/src/math/aarch64/lrintf.c",
+"musl/src/math/aarch64/lround.c",
+"musl/src/math/aarch64/lroundf.c",
+"musl/src/math/aarch64/nearbyint.c",
+"musl/src/math/aarch64/nearbyintf.c",
+"musl/src/math/aarch64/rint.c",
+"musl/src/math/aarch64/rintf.c",
+"musl/src/math/aarch64/round.c",
+"musl/src/math/aarch64/roundf.c",
+"musl/src/math/aarch64/sqrt.c",
+"musl/src/math/aarch64/sqrtf.c",
+"musl/src/math/aarch64/trunc.c",
+"musl/src/math/aarch64/truncf.c",
+"musl/src/math/acos.c",
+"musl/src/math/acosf.c",
+"musl/src/math/acosh.c",
+"musl/src/math/acoshf.c",
+"musl/src/math/acoshl.c",
+"musl/src/math/acosl.c",
+"musl/src/math/arm/fabs.c",
+"musl/src/math/arm/fabsf.c",
+"musl/src/math/arm/fma.c",
+"musl/src/math/arm/fmaf.c",
+"musl/src/math/arm/sqrt.c",
+"musl/src/math/arm/sqrtf.c",
+"musl/src/math/asin.c",
+"musl/src/math/asinf.c",
+"musl/src/math/asinh.c",
+"musl/src/math/asinhf.c",
+"musl/src/math/asinhl.c",
+"musl/src/math/asinl.c",
+"musl/src/math/atan.c",
+"musl/src/math/atan2.c",
+"musl/src/math/atan2f.c",
+"musl/src/math/atan2l.c",
+"musl/src/math/atanf.c",
+"musl/src/math/atanh.c",
+"musl/src/math/atanhf.c",
+"musl/src/math/atanhl.c",
+"musl/src/math/atanl.c",
+"musl/src/math/cbrt.c",
+"musl/src/math/cbrtf.c",
+"musl/src/math/cbrtl.c",
+"musl/src/math/ceil.c",
+"musl/src/math/ceilf.c",
+"musl/src/math/ceill.c",
+"musl/src/math/copysign.c",
+"musl/src/math/copysignf.c",
+"musl/src/math/copysignl.c",
+"musl/src/math/cos.c",
+"musl/src/math/cosf.c",
+"musl/src/math/cosh.c",
+"musl/src/math/coshf.c",
+"musl/src/math/coshl.c",
+"musl/src/math/cosl.c",
+"musl/src/math/erf.c",
+"musl/src/math/erff.c",
+"musl/src/math/erfl.c",
+"musl/src/math/exp.c",
+"musl/src/math/exp10.c",
+"musl/src/math/exp10f.c",
+"musl/src/math/exp10l.c",
+"musl/src/math/exp2.c",
+"musl/src/math/exp2f.c",
+"musl/src/math/exp2l.c",
+"musl/src/math/expf.c",
+"musl/src/math/expl.c",
+"musl/src/math/expm1.c",
+"musl/src/math/expm1f.c",
+"musl/src/math/expm1l.c",
+"musl/src/math/fabs.c",
+"musl/src/math/fabsf.c",
+"musl/src/math/fabsl.c",
+"musl/src/math/fdim.c",
+"musl/src/math/fdimf.c",
+"musl/src/math/fdiml.c",
+"musl/src/math/finite.c",
+"musl/src/math/finitef.c",
+"musl/src/math/floor.c",
+"musl/src/math/floorf.c",
+"musl/src/math/floorl.c",
+"musl/src/math/fma.c",
+"musl/src/math/fmaf.c",
+"musl/src/math/fmal.c",
+"musl/src/math/fmax.c",
+"musl/src/math/fmaxf.c",
+"musl/src/math/fmaxl.c",
+"musl/src/math/fmin.c",
+"musl/src/math/fminf.c",
+"musl/src/math/fminl.c",
+"musl/src/math/fmod.c",
+"musl/src/math/fmodf.c",
+"musl/src/math/fmodl.c",
+"musl/src/math/frexp.c",
+"musl/src/math/frexpf.c",
+"musl/src/math/frexpl.c",
+"musl/src/math/hypot.c",
+"musl/src/math/hypotf.c",
+"musl/src/math/hypotl.c",
+"musl/src/math/i386/__invtrigl.s",
+"musl/src/math/i386/acos.s",
+"musl/src/math/i386/acosf.s",
+"musl/src/math/i386/acosl.s",
+"musl/src/math/i386/asin.s",
+"musl/src/math/i386/asinf.s",
+"musl/src/math/i386/asinl.s",
+"musl/src/math/i386/atan.s",
+"musl/src/math/i386/atan2.s",
+"musl/src/math/i386/atan2f.s",
+"musl/src/math/i386/atan2l.s",
+"musl/src/math/i386/atanf.s",
+"musl/src/math/i386/atanl.s",
+"musl/src/math/i386/ceil.s",
+"musl/src/math/i386/ceilf.s",
+"musl/src/math/i386/ceill.s",
+"musl/src/math/i386/exp.s",
+"musl/src/math/i386/exp2.s",
+"musl/src/math/i386/exp2f.s",
+"musl/src/math/i386/exp2l.s",
+"musl/src/math/i386/expf.s",
+"musl/src/math/i386/expl.s",
+"musl/src/math/i386/expm1.s",
+"musl/src/math/i386/expm1f.s",
+"musl/src/math/i386/expm1l.s",
+"musl/src/math/i386/fabs.s",
+"musl/src/math/i386/fabsf.s",
+"musl/src/math/i386/fabsl.s",
+"musl/src/math/i386/floor.s",
+"musl/src/math/i386/floorf.s",
+"musl/src/math/i386/floorl.s",
+"musl/src/math/i386/fmod.s",
+"musl/src/math/i386/fmodf.s",
+"musl/src/math/i386/fmodl.s",
+"musl/src/math/i386/hypot.s",
+"musl/src/math/i386/hypotf.s",
+"musl/src/math/i386/ldexp.s",
+"musl/src/math/i386/ldexpf.s",
+"musl/src/math/i386/ldexpl.s",
+"musl/src/math/i386/llrint.s",
+"musl/src/math/i386/llrintf.s",
+"musl/src/math/i386/llrintl.s",
+"musl/src/math/i386/log.s",
+"musl/src/math/i386/log10.s",
+"musl/src/math/i386/log10f.s",
+"musl/src/math/i386/log10l.s",
+"musl/src/math/i386/log1p.s",
+"musl/src/math/i386/log1pf.s",
+"musl/src/math/i386/log1pl.s",
+"musl/src/math/i386/log2.s",
+"musl/src/math/i386/log2f.s",
+"musl/src/math/i386/log2l.s",
+"musl/src/math/i386/logf.s",
+"musl/src/math/i386/logl.s",
+"musl/src/math/i386/lrint.s",
+"musl/src/math/i386/lrintf.s",
+"musl/src/math/i386/lrintl.s",
+"musl/src/math/i386/remainder.s",
+"musl/src/math/i386/remainderf.s",
+"musl/src/math/i386/remainderl.s",
+"musl/src/math/i386/remquo.s",
+"musl/src/math/i386/remquof.s",
+"musl/src/math/i386/remquol.s",
+"musl/src/math/i386/rint.s",
+"musl/src/math/i386/rintf.s",
+"musl/src/math/i386/rintl.s",
+"musl/src/math/i386/scalbln.s",
+"musl/src/math/i386/scalblnf.s",
+"musl/src/math/i386/scalblnl.s",
+"musl/src/math/i386/scalbn.s",
+"musl/src/math/i386/scalbnf.s",
+"musl/src/math/i386/scalbnl.s",
+"musl/src/math/i386/sqrt.s",
+"musl/src/math/i386/sqrtf.s",
+"musl/src/math/i386/sqrtl.s",
+"musl/src/math/i386/trunc.s",
+"musl/src/math/i386/truncf.s",
+"musl/src/math/i386/truncl.s",
+"musl/src/math/ilogb.c",
+"musl/src/math/ilogbf.c",
+"musl/src/math/ilogbl.c",
+"musl/src/math/j0.c",
+"musl/src/math/j0f.c",
+"musl/src/math/j1.c",
+"musl/src/math/j1f.c",
+"musl/src/math/jn.c",
+"musl/src/math/jnf.c",
+"musl/src/math/ldexp.c",
+"musl/src/math/ldexpf.c",
+"musl/src/math/ldexpl.c",
+"musl/src/math/lgamma.c",
+"musl/src/math/lgamma_r.c",
+"musl/src/math/lgammaf.c",
+"musl/src/math/lgammaf_r.c",
+"musl/src/math/lgammal.c",
+"musl/src/math/llrint.c",
+"musl/src/math/llrintf.c",
+"musl/src/math/llrintl.c",
+"musl/src/math/llround.c",
+"musl/src/math/llroundf.c",
+"musl/src/math/llroundl.c",
+"musl/src/math/log.c",
+"musl/src/math/log10.c",
+"musl/src/math/log10f.c",
+"musl/src/math/log10l.c",
+"musl/src/math/log1p.c",
+"musl/src/math/log1pf.c",
+"musl/src/math/log1pl.c",
+"musl/src/math/log2.c",
+"musl/src/math/log2f.c",
+"musl/src/math/log2l.c",
+"musl/src/math/logb.c",
+"musl/src/math/logbf.c",
+"musl/src/math/logbl.c",
+"musl/src/math/logf.c",
+"musl/src/math/logl.c",
+"musl/src/math/lrint.c",
+"musl/src/math/lrintf.c",
+"musl/src/math/lrintl.c",
+"musl/src/math/lround.c",
+"musl/src/math/lroundf.c",
+"musl/src/math/lroundl.c",
+"musl/src/math/modf.c",
+"musl/src/math/modff.c",
+"musl/src/math/modfl.c",
+"musl/src/math/nan.c",
+"musl/src/math/nanf.c",
+"musl/src/math/nanl.c",
+"musl/src/math/nearbyint.c",
+"musl/src/math/nearbyintf.c",
+"musl/src/math/nearbyintl.c",
+"musl/src/math/nextafter.c",
+"musl/src/math/nextafterf.c",
+"musl/src/math/nextafterl.c",
+"musl/src/math/nexttoward.c",
+"musl/src/math/nexttowardf.c",
+"musl/src/math/nexttowardl.c",
+"musl/src/math/pow.c",
+"musl/src/math/powerpc/fabs.c",
+"musl/src/math/powerpc/fabsf.c",
+"musl/src/math/powerpc/fma.c",
+"musl/src/math/powerpc/fmaf.c",
+"musl/src/math/powerpc/sqrt.c",
+"musl/src/math/powerpc/sqrtf.c",
+"musl/src/math/powerpc64/ceil.c",
+"musl/src/math/powerpc64/ceilf.c",
+"musl/src/math/powerpc64/fabs.c",
+"musl/src/math/powerpc64/fabsf.c",
+"musl/src/math/powerpc64/floor.c",
+"musl/src/math/powerpc64/floorf.c",
+"musl/src/math/powerpc64/fma.c",
+"musl/src/math/powerpc64/fmaf.c",
+"musl/src/math/powerpc64/fmax.c",
+"musl/src/math/powerpc64/fmaxf.c",
+"musl/src/math/powerpc64/fmin.c",
+"musl/src/math/powerpc64/fminf.c",
+"musl/src/math/powerpc64/lrint.c",
+"musl/src/math/powerpc64/lrintf.c",
+"musl/src/math/powerpc64/lround.c",
+"musl/src/math/powerpc64/lroundf.c",
+"musl/src/math/powerpc64/round.c",
+"musl/src/math/powerpc64/roundf.c",
+"musl/src/math/powerpc64/sqrt.c",
+"musl/src/math/powerpc64/sqrtf.c",
+"musl/src/math/powerpc64/trunc.c",
+"musl/src/math/powerpc64/truncf.c",
+"musl/src/math/powf.c",
+"musl/src/math/powl.c",
+"musl/src/math/remainder.c",
+"musl/src/math/remainderf.c",
+"musl/src/math/remainderl.c",
+"musl/src/math/remquo.c",
+"musl/src/math/remquof.c",
+"musl/src/math/remquol.c",
+"musl/src/math/rint.c",
+"musl/src/math/rintf.c",
+"musl/src/math/rintl.c",
+"musl/src/math/round.c",
+"musl/src/math/roundf.c",
+"musl/src/math/roundl.c",
+"musl/src/math/s390x/ceil.c",
+"musl/src/math/s390x/ceilf.c",
+"musl/src/math/s390x/ceill.c",
+"musl/src/math/s390x/fabs.c",
+"musl/src/math/s390x/fabsf.c",
+"musl/src/math/s390x/fabsl.c",
+"musl/src/math/s390x/floor.c",
+"musl/src/math/s390x/floorf.c",
+"musl/src/math/s390x/floorl.c",
+"musl/src/math/s390x/fma.c",
+"musl/src/math/s390x/fmaf.c",
+"musl/src/math/s390x/nearbyint.c",
+"musl/src/math/s390x/nearbyintf.c",
+"musl/src/math/s390x/nearbyintl.c",
+"musl/src/math/s390x/rint.c",
+"musl/src/math/s390x/rintf.c",
+"musl/src/math/s390x/rintl.c",
+"musl/src/math/s390x/round.c",
+"musl/src/math/s390x/roundf.c",
+"musl/src/math/s390x/roundl.c",
+"musl/src/math/s390x/sqrt.c",
+"musl/src/math/s390x/sqrtf.c",
+"musl/src/math/s390x/sqrtl.c",
+"musl/src/math/s390x/trunc.c",
+"musl/src/math/s390x/truncf.c",
+"musl/src/math/s390x/truncl.c",
+"musl/src/math/scalb.c",
+"musl/src/math/scalbf.c",
+"musl/src/math/scalbln.c",
+"musl/src/math/scalblnf.c",
+"musl/src/math/scalblnl.c",
+"musl/src/math/scalbn.c",
+"musl/src/math/scalbnf.c",
+"musl/src/math/scalbnl.c",
+"musl/src/math/signgam.c",
+"musl/src/math/significand.c",
+"musl/src/math/significandf.c",
+"musl/src/math/sin.c",
+"musl/src/math/sincos.c",
+"musl/src/math/sincosf.c",
+"musl/src/math/sincosl.c",
+"musl/src/math/sinf.c",
+"musl/src/math/sinh.c",
+"musl/src/math/sinhf.c",
+"musl/src/math/sinhl.c",
+"musl/src/math/sinl.c",
+"musl/src/math/sqrt.c",
+"musl/src/math/sqrtf.c",
+"musl/src/math/sqrtl.c",
+"musl/src/math/tan.c",
+"musl/src/math/tanf.c",
+"musl/src/math/tanh.c",
+"musl/src/math/tanhf.c",
+"musl/src/math/tanhl.c",
+"musl/src/math/tanl.c",
+"musl/src/math/tgamma.c",
+"musl/src/math/tgammaf.c",
+"musl/src/math/tgammal.c",
+"musl/src/math/trunc.c",
+"musl/src/math/truncf.c",
+"musl/src/math/truncl.c",
+"musl/src/math/x32/__invtrigl.s",
+"musl/src/math/x32/acosl.s",
+"musl/src/math/x32/asinl.s",
+"musl/src/math/x32/atan2l.s",
+"musl/src/math/x32/atanl.s",
+"musl/src/math/x32/ceill.s",
+"musl/src/math/x32/exp2l.s",
+"musl/src/math/x32/expl.s",
+"musl/src/math/x32/expm1l.s",
+"musl/src/math/x32/fabs.s",
+"musl/src/math/x32/fabsf.s",
+"musl/src/math/x32/fabsl.s",
+"musl/src/math/x32/floorl.s",
+"musl/src/math/x32/fma.c",
+"musl/src/math/x32/fmaf.c",
+"musl/src/math/x32/fmodl.s",
+"musl/src/math/x32/llrint.s",
+"musl/src/math/x32/llrintf.s",
+"musl/src/math/x32/llrintl.s",
+"musl/src/math/x32/log10l.s",
+"musl/src/math/x32/log1pl.s",
+"musl/src/math/x32/log2l.s",
+"musl/src/math/x32/logl.s",
+"musl/src/math/x32/lrint.s",
+"musl/src/math/x32/lrintf.s",
+"musl/src/math/x32/lrintl.s",
+"musl/src/math/x32/remainderl.s",
+"musl/src/math/x32/rintl.s",
+"musl/src/math/x32/sqrt.s",
+"musl/src/math/x32/sqrtf.s",
+"musl/src/math/x32/sqrtl.s",
+"musl/src/math/x32/truncl.s",
+"musl/src/math/x86_64/__invtrigl.s",
+"musl/src/math/x86_64/acosl.s",
+"musl/src/math/x86_64/asinl.s",
+"musl/src/math/x86_64/atan2l.s",
+"musl/src/math/x86_64/atanl.s",
+"musl/src/math/x86_64/ceill.s",
+"musl/src/math/x86_64/exp2l.s",
+"musl/src/math/x86_64/expl.s",
+"musl/src/math/x86_64/expm1l.s",
+"musl/src/math/x86_64/fabs.s",
+"musl/src/math/x86_64/fabsf.s",
+"musl/src/math/x86_64/fabsl.s",
+"musl/src/math/x86_64/floorl.s",
+"musl/src/math/x86_64/fma.c",
+"musl/src/math/x86_64/fmaf.c",
+"musl/src/math/x86_64/fmodl.s",
+"musl/src/math/x86_64/llrint.s",
+"musl/src/math/x86_64/llrintf.s",
+"musl/src/math/x86_64/llrintl.s",
+"musl/src/math/x86_64/log10l.s",
+"musl/src/math/x86_64/log1pl.s",
+"musl/src/math/x86_64/log2l.s",
+"musl/src/math/x86_64/logl.s",
+"musl/src/math/x86_64/lrint.s",
+"musl/src/math/x86_64/lrintf.s",
+"musl/src/math/x86_64/lrintl.s",
+"musl/src/math/x86_64/remainderl.s",
+"musl/src/math/x86_64/rintl.s",
+"musl/src/math/x86_64/sqrt.s",
+"musl/src/math/x86_64/sqrtf.s",
+"musl/src/math/x86_64/sqrtl.s",
+"musl/src/math/x86_64/truncl.s",
+"musl/src/misc/a64l.c",
+"musl/src/misc/basename.c",
+"musl/src/misc/dirname.c",
+"musl/src/misc/ffs.c",
+"musl/src/misc/ffsl.c",
+"musl/src/misc/ffsll.c",
+"musl/src/misc/fmtmsg.c",
+"musl/src/misc/forkpty.c",
+"musl/src/misc/get_current_dir_name.c",
+"musl/src/misc/getauxval.c",
+"musl/src/misc/getdomainname.c",
+"musl/src/misc/getentropy.c",
+"musl/src/misc/gethostid.c",
+"musl/src/misc/getopt.c",
+"musl/src/misc/getopt_long.c",
+"musl/src/misc/getpriority.c",
+"musl/src/misc/getresgid.c",
+"musl/src/misc/getresuid.c",
+"musl/src/misc/getrlimit.c",
+"musl/src/misc/getrusage.c",
+"musl/src/misc/getsubopt.c",
+"musl/src/misc/initgroups.c",
+"musl/src/misc/ioctl.c",
+"musl/src/misc/issetugid.c",
+"musl/src/misc/lockf.c",
+"musl/src/misc/login_tty.c",
+"musl/src/misc/mntent.c",
+"musl/src/misc/nftw.c",
+"musl/src/misc/openpty.c",
+"musl/src/misc/ptsname.c",
+"musl/src/misc/pty.c",
+"musl/src/misc/realpath.c",
+"musl/src/misc/setdomainname.c",
+"musl/src/misc/setpriority.c",
+"musl/src/misc/setrlimit.c",
+"musl/src/misc/syscall.c",
+"musl/src/misc/syslog.c",
+"musl/src/misc/uname.c",
+"musl/src/misc/wordexp.c",
+"musl/src/mman/madvise.c",
+"musl/src/mman/mincore.c",
+"musl/src/mman/mlock.c",
+"musl/src/mman/mlockall.c",
+"musl/src/mman/mmap.c",
+"musl/src/mman/mprotect.c",
+"musl/src/mman/mremap.c",
+"musl/src/mman/msync.c",
+"musl/src/mman/munlock.c",
+"musl/src/mman/munlockall.c",
+"musl/src/mman/munmap.c",
+"musl/src/mman/posix_madvise.c",
+"musl/src/mman/shm_open.c",
+"musl/src/mq/mq_close.c",
+"musl/src/mq/mq_getattr.c",
+"musl/src/mq/mq_notify.c",
+"musl/src/mq/mq_open.c",
+"musl/src/mq/mq_receive.c",
+"musl/src/mq/mq_send.c",
+"musl/src/mq/mq_setattr.c",
+"musl/src/mq/mq_timedreceive.c",
+"musl/src/mq/mq_timedsend.c",
+"musl/src/mq/mq_unlink.c",
+"musl/src/multibyte/btowc.c",
+"musl/src/multibyte/c16rtomb.c",
+"musl/src/multibyte/c32rtomb.c",
+"musl/src/multibyte/internal.c",
+"musl/src/multibyte/internal.h",
+"musl/src/multibyte/mblen.c",
+"musl/src/multibyte/mbrlen.c",
+"musl/src/multibyte/mbrtoc16.c",
+"musl/src/multibyte/mbrtoc32.c",
+"musl/src/multibyte/mbrtowc.c",
+"musl/src/multibyte/mbsinit.c",
+"musl/src/multibyte/mbsnrtowcs.c",
+"musl/src/multibyte/mbsrtowcs.c",
+"musl/src/multibyte/mbstowcs.c",
+"musl/src/multibyte/mbtowc.c",
+"musl/src/multibyte/wcrtomb.c",
+"musl/src/multibyte/wcsnrtombs.c",
+"musl/src/multibyte/wcsrtombs.c",
+"musl/src/multibyte/wcstombs.c",
+"musl/src/multibyte/wctob.c",
+"musl/src/multibyte/wctomb.c",
+"musl/src/network/accept.c",
+"musl/src/network/accept4.c",
+"musl/src/network/bind.c",
+"musl/src/network/connect.c",
+"musl/src/network/dn_comp.c",
+"musl/src/network/dn_expand.c",
+"musl/src/network/dn_skipname.c",
+"musl/src/network/dns_parse.c",
+"musl/src/network/ent.c",
+"musl/src/network/ether.c",
+"musl/src/network/freeaddrinfo.c",
+"musl/src/network/gai_strerror.c",
+"musl/src/network/getaddrinfo.c",
+"musl/src/network/gethostbyaddr.c",
+"musl/src/network/gethostbyaddr_r.c",
+"musl/src/network/gethostbyname.c",
+"musl/src/network/gethostbyname2.c",
+"musl/src/network/gethostbyname2_r.c",
+"musl/src/network/gethostbyname_r.c",
+"musl/src/network/getifaddrs.c",
+"musl/src/network/getnameinfo.c",
+"musl/src/network/getpeername.c",
+"musl/src/network/getservbyname.c",
+"musl/src/network/getservbyname_r.c",
+"musl/src/network/getservbyport.c",
+"musl/src/network/getservbyport_r.c",
+"musl/src/network/getsockname.c",
+"musl/src/network/getsockopt.c",
+"musl/src/network/h_errno.c",
+"musl/src/network/herror.c",
+"musl/src/network/hstrerror.c",
+"musl/src/network/htonl.c",
+"musl/src/network/htons.c",
+"musl/src/network/if_freenameindex.c",
+"musl/src/network/if_indextoname.c",
+"musl/src/network/if_nameindex.c",
+"musl/src/network/if_nametoindex.c",
+"musl/src/network/in6addr_any.c",
+"musl/src/network/in6addr_loopback.c",
+"musl/src/network/inet_addr.c",
+"musl/src/network/inet_aton.c",
+"musl/src/network/inet_legacy.c",
+"musl/src/network/inet_ntoa.c",
+"musl/src/network/inet_ntop.c",
+"musl/src/network/inet_pton.c",
+"musl/src/network/listen.c",
+"musl/src/network/lookup.h",
+"musl/src/network/lookup_ipliteral.c",
+"musl/src/network/lookup_name.c",
+"musl/src/network/lookup_serv.c",
+"musl/src/network/netlink.c",
+"musl/src/network/netlink.h",
+"musl/src/network/netname.c",
+"musl/src/network/ns_parse.c",
+"musl/src/network/ntohl.c",
+"musl/src/network/ntohs.c",
+"musl/src/network/proto.c",
+"musl/src/network/recv.c",
+"musl/src/network/recvfrom.c",
+"musl/src/network/recvmmsg.c",
+"musl/src/network/recvmsg.c",
+"musl/src/network/res_init.c",
+"musl/src/network/res_mkquery.c",
+"musl/src/network/res_msend.c",
+"musl/src/network/res_query.c",
+"musl/src/network/res_querydomain.c",
+"musl/src/network/res_send.c",
+"musl/src/network/res_state.c",
+"musl/src/network/resolvconf.c",
+"musl/src/network/send.c",
+"musl/src/network/sendmmsg.c",
+"musl/src/network/sendmsg.c",
+"musl/src/network/sendto.c",
+"musl/src/network/serv.c",
+"musl/src/network/setsockopt.c",
+"musl/src/network/shutdown.c",
+"musl/src/network/sockatmark.c",
+"musl/src/network/socket.c",
+"musl/src/network/socketpair.c",
+"musl/src/passwd/fgetgrent.c",
+"musl/src/passwd/fgetpwent.c",
+"musl/src/passwd/fgetspent.c",
+"musl/src/passwd/getgr_a.c",
+"musl/src/passwd/getgr_r.c",
+"musl/src/passwd/getgrent.c",
+"musl/src/passwd/getgrent_a.c",
+"musl/src/passwd/getgrouplist.c",
+"musl/src/passwd/getpw_a.c",
+"musl/src/passwd/getpw_r.c",
+"musl/src/passwd/getpwent.c",
+"musl/src/passwd/getpwent_a.c",
+"musl/src/passwd/getspent.c",
+"musl/src/passwd/getspnam.c",
+"musl/src/passwd/getspnam_r.c",
+"musl/src/passwd/lckpwdf.c",
+"musl/src/passwd/nscd.h",
+"musl/src/passwd/nscd_query.c",
+"musl/src/passwd/putgrent.c",
+"musl/src/passwd/putpwent.c",
+"musl/src/passwd/putspent.c",
+"musl/src/passwd/pwf.h",
+"musl/src/prng/__rand48_step.c",
+"musl/src/prng/__seed48.c",
+"musl/src/prng/drand48.c",
+"musl/src/prng/lcong48.c",
+"musl/src/prng/lrand48.c",
+"musl/src/prng/mrand48.c",
+"musl/src/prng/rand.c",
+"musl/src/prng/rand48.h",
+"musl/src/prng/rand_r.c",
+"musl/src/prng/random.c",
+"musl/src/prng/seed48.c",
+"musl/src/prng/srand48.c",
+"musl/src/process/arm/vfork.s",
+"musl/src/process/execl.c",
+"musl/src/process/execle.c",
+"musl/src/process/execlp.c",
+"musl/src/process/execv.c",
+"musl/src/process/execve.c",
+"musl/src/process/execvp.c",
+"musl/src/process/fdop.h",
+"musl/src/process/fexecve.c",
+"musl/src/process/fork.c",
+"musl/src/process/i386/vfork.s",
+"musl/src/process/posix_spawn.c",
+"musl/src/process/posix_spawn_file_actions_addclose.c",
+"musl/src/process/posix_spawn_file_actions_adddup2.c",
+"musl/src/process/posix_spawn_file_actions_addopen.c",
+"musl/src/process/posix_spawn_file_actions_destroy.c",
+"musl/src/process/posix_spawn_file_actions_init.c",
+"musl/src/process/posix_spawnattr_destroy.c",
+"musl/src/process/posix_spawnattr_getflags.c",
+"musl/src/process/posix_spawnattr_getpgroup.c",
+"musl/src/process/posix_spawnattr_getsigdefault.c",
+"musl/src/process/posix_spawnattr_getsigmask.c",
+"musl/src/process/posix_spawnattr_init.c",
+"musl/src/process/posix_spawnattr_sched.c",
+"musl/src/process/posix_spawnattr_setflags.c",
+"musl/src/process/posix_spawnattr_setpgroup.c",
+"musl/src/process/posix_spawnattr_setsigdefault.c",
+"musl/src/process/posix_spawnattr_setsigmask.c",
+"musl/src/process/posix_spawnp.c",
+"musl/src/process/s390x/vfork.s",
+"musl/src/process/sh/vfork.s",
+"musl/src/process/system.c",
+"musl/src/process/vfork.c",
+"musl/src/process/wait.c",
+"musl/src/process/waitid.c",
+"musl/src/process/waitpid.c",
+"musl/src/process/x32/vfork.s",
+"musl/src/process/x86_64/vfork.s",
+"musl/src/regex/fnmatch.c",
+"musl/src/regex/glob.c",
+"musl/src/regex/regcomp.c",
+"musl/src/regex/regerror.c",
+"musl/src/regex/regexec.c",
+"musl/src/regex/tre-mem.c",
+"musl/src/regex/tre.h",
+"musl/src/sched/affinity.c",
+"musl/src/sched/sched_cpucount.c",
+"musl/src/sched/sched_get_priority_max.c",
+"musl/src/sched/sched_getcpu.c",
+"musl/src/sched/sched_getparam.c",
+"musl/src/sched/sched_getscheduler.c",
+"musl/src/sched/sched_rr_get_interval.c",
+"musl/src/sched/sched_setparam.c",
+"musl/src/sched/sched_setscheduler.c",
+"musl/src/sched/sched_yield.c",
+"musl/src/search/hsearch.c",
+"musl/src/search/insque.c",
+"musl/src/search/lsearch.c",
+"musl/src/search/tdelete.c",
+"musl/src/search/tdestroy.c",
+"musl/src/search/tfind.c",
+"musl/src/search/tsearch.c",
+"musl/src/search/tsearch.h",
+"musl/src/search/twalk.c",
+"musl/src/select/poll.c",
+"musl/src/select/pselect.c",
+"musl/src/select/select.c",
+"musl/src/setjmp/aarch64/longjmp.s",
+"musl/src/setjmp/aarch64/setjmp.s",
+"musl/src/setjmp/arm/longjmp.s",
+"musl/src/setjmp/arm/setjmp.s",
+"musl/src/setjmp/i386/longjmp.s",
+"musl/src/setjmp/i386/setjmp.s",
+"musl/src/setjmp/longjmp.c",
+"musl/src/setjmp/m68k/longjmp.s",
+"musl/src/setjmp/m68k/setjmp.s",
+"musl/src/setjmp/microblaze/longjmp.s",
+"musl/src/setjmp/microblaze/setjmp.s",
+"musl/src/setjmp/mips/longjmp.S",
+"musl/src/setjmp/mips/setjmp.S",
+"musl/src/setjmp/mips64/longjmp.S",
+"musl/src/setjmp/mips64/setjmp.S",
+"musl/src/setjmp/mipsn32/longjmp.S",
+"musl/src/setjmp/mipsn32/setjmp.S",
+"musl/src/setjmp/or1k/longjmp.s",
+"musl/src/setjmp/or1k/setjmp.s",
+"musl/src/setjmp/powerpc/longjmp.S",
+"musl/src/setjmp/powerpc/setjmp.S",
+"musl/src/setjmp/powerpc64/longjmp.s",
+"musl/src/setjmp/powerpc64/setjmp.s",
+"musl/src/setjmp/s390x/longjmp.s",
+"musl/src/setjmp/s390x/setjmp.s",
+"musl/src/setjmp/setjmp.c",
+"musl/src/setjmp/sh/longjmp.S",
+"musl/src/setjmp/sh/setjmp.S",
+"musl/src/setjmp/x32/longjmp.s",
+"musl/src/setjmp/x32/setjmp.s",
+"musl/src/setjmp/x86_64/longjmp.s",
+"musl/src/setjmp/x86_64/setjmp.s",
+"musl/src/signal/aarch64/restore.s",
+"musl/src/signal/aarch64/sigsetjmp.s",
+"musl/src/signal/arm/restore.s",
+"musl/src/signal/arm/sigsetjmp.s",
+"musl/src/signal/block.c",
+"musl/src/signal/getitimer.c",
+"musl/src/signal/i386/restore.s",
+"musl/src/signal/i386/sigsetjmp.s",
+"musl/src/signal/kill.c",
+"musl/src/signal/killpg.c",
+"musl/src/signal/m68k/sigsetjmp.s",
+"musl/src/signal/microblaze/restore.s",
+"musl/src/signal/microblaze/sigsetjmp.s",
+"musl/src/signal/mips/restore.s",
+"musl/src/signal/mips/sigsetjmp.s",
+"musl/src/signal/mips64/restore.s",
+"musl/src/signal/mips64/sigsetjmp.s",
+"musl/src/signal/mipsn32/restore.s",
+"musl/src/signal/mipsn32/sigsetjmp.s",
+"musl/src/signal/or1k/sigsetjmp.s",
+"musl/src/signal/powerpc/restore.s",
+"musl/src/signal/powerpc/sigsetjmp.s",
+"musl/src/signal/powerpc64/restore.s",
+"musl/src/signal/powerpc64/sigsetjmp.s",
+"musl/src/signal/psiginfo.c",
+"musl/src/signal/psignal.c",
+"musl/src/signal/raise.c",
+"musl/src/signal/restore.c",
+"musl/src/signal/s390x/restore.s",
+"musl/src/signal/s390x/sigsetjmp.s",
+"musl/src/signal/setitimer.c",
+"musl/src/signal/sh/restore.s",
+"musl/src/signal/sh/sigsetjmp.s",
+"musl/src/signal/sigaction.c",
+"musl/src/signal/sigaddset.c",
+"musl/src/signal/sigaltstack.c",
+"musl/src/signal/sigandset.c",
+"musl/src/signal/sigdelset.c",
+"musl/src/signal/sigemptyset.c",
+"musl/src/signal/sigfillset.c",
+"musl/src/signal/sighold.c",
+"musl/src/signal/sigignore.c",
+"musl/src/signal/siginterrupt.c",
+"musl/src/signal/sigisemptyset.c",
+"musl/src/signal/sigismember.c",
+"musl/src/signal/siglongjmp.c",
+"musl/src/signal/signal.c",
+"musl/src/signal/sigorset.c",
+"musl/src/signal/sigpause.c",
+"musl/src/signal/sigpending.c",
+"musl/src/signal/sigprocmask.c",
+"musl/src/signal/sigqueue.c",
+"musl/src/signal/sigrelse.c",
+"musl/src/signal/sigrtmax.c",
+"musl/src/signal/sigrtmin.c",
+"musl/src/signal/sigset.c",
+"musl/src/signal/sigsetjmp.c",
+"musl/src/signal/sigsetjmp_tail.c",
+"musl/src/signal/sigsuspend.c",
+"musl/src/signal/sigtimedwait.c",
+"musl/src/signal/sigwait.c",
+"musl/src/signal/sigwaitinfo.c",
+"musl/src/signal/x32/restore.s",
+"musl/src/signal/x32/sigsetjmp.s",
+"musl/src/signal/x86_64/restore.s",
+"musl/src/signal/x86_64/sigsetjmp.s",
+"musl/src/stat/__xstat.c",
+"musl/src/stat/chmod.c",
+"musl/src/stat/fchmod.c",
+"musl/src/stat/fchmodat.c",
+"musl/src/stat/fstat.c",
+"musl/src/stat/fstatat.c",
+"musl/src/stat/futimens.c",
+"musl/src/stat/futimesat.c",
+"musl/src/stat/lchmod.c",
+"musl/src/stat/lstat.c",
+"musl/src/stat/mkdir.c",
+"musl/src/stat/mkdirat.c",
+"musl/src/stat/mkfifo.c",
+"musl/src/stat/mkfifoat.c",
+"musl/src/stat/mknod.c",
+"musl/src/stat/mknodat.c",
+"musl/src/stat/stat.c",
+"musl/src/stat/statvfs.c",
+"musl/src/stat/umask.c",
+"musl/src/stat/utimensat.c",
+"musl/src/stdio/__fclose_ca.c",
+"musl/src/stdio/__fdopen.c",
+"musl/src/stdio/__fmodeflags.c",
+"musl/src/stdio/__fopen_rb_ca.c",
+"musl/src/stdio/__lockfile.c",
+"musl/src/stdio/__overflow.c",
+"musl/src/stdio/__stdio_close.c",
+"musl/src/stdio/__stdio_exit.c",
+"musl/src/stdio/__stdio_read.c",
+"musl/src/stdio/__stdio_seek.c",
+"musl/src/stdio/__stdio_write.c",
+"musl/src/stdio/__stdout_write.c",
+"musl/src/stdio/__string_read.c",
+"musl/src/stdio/__toread.c",
+"musl/src/stdio/__towrite.c",
+"musl/src/stdio/__uflow.c",
+"musl/src/stdio/asprintf.c",
+"musl/src/stdio/clearerr.c",
+"musl/src/stdio/dprintf.c",
+"musl/src/stdio/ext.c",
+"musl/src/stdio/ext2.c",
+"musl/src/stdio/fclose.c",
+"musl/src/stdio/feof.c",
+"musl/src/stdio/ferror.c",
+"musl/src/stdio/fflush.c",
+"musl/src/stdio/fgetc.c",
+"musl/src/stdio/fgetln.c",
+"musl/src/stdio/fgetpos.c",
+"musl/src/stdio/fgets.c",
+"musl/src/stdio/fgetwc.c",
+"musl/src/stdio/fgetws.c",
+"musl/src/stdio/fileno.c",
+"musl/src/stdio/flockfile.c",
+"musl/src/stdio/fmemopen.c",
+"musl/src/stdio/fopen.c",
+"musl/src/stdio/fopencookie.c",
+"musl/src/stdio/fprintf.c",
+"musl/src/stdio/fputc.c",
+"musl/src/stdio/fputs.c",
+"musl/src/stdio/fputwc.c",
+"musl/src/stdio/fputws.c",
+"musl/src/stdio/fread.c",
+"musl/src/stdio/freopen.c",
+"musl/src/stdio/fscanf.c",
+"musl/src/stdio/fseek.c",
+"musl/src/stdio/fsetpos.c",
+"musl/src/stdio/ftell.c",
+"musl/src/stdio/ftrylockfile.c",
+"musl/src/stdio/funlockfile.c",
+"musl/src/stdio/fwide.c",
+"musl/src/stdio/fwprintf.c",
+"musl/src/stdio/fwrite.c",
+"musl/src/stdio/fwscanf.c",
+"musl/src/stdio/getc.c",
+"musl/src/stdio/getc.h",
+"musl/src/stdio/getc_unlocked.c",
+"musl/src/stdio/getchar.c",
+"musl/src/stdio/getchar_unlocked.c",
+"musl/src/stdio/getdelim.c",
+"musl/src/stdio/getline.c",
+"musl/src/stdio/gets.c",
+"musl/src/stdio/getw.c",
+"musl/src/stdio/getwc.c",
+"musl/src/stdio/getwchar.c",
+"musl/src/stdio/ofl.c",
+"musl/src/stdio/ofl_add.c",
+"musl/src/stdio/open_memstream.c",
+"musl/src/stdio/open_wmemstream.c",
+"musl/src/stdio/pclose.c",
+"musl/src/stdio/perror.c",
+"musl/src/stdio/popen.c",
+"musl/src/stdio/printf.c",
+"musl/src/stdio/putc.c",
+"musl/src/stdio/putc.h",
+"musl/src/stdio/putc_unlocked.c",
+"musl/src/stdio/putchar.c",
+"musl/src/stdio/putchar_unlocked.c",
+"musl/src/stdio/puts.c",
+"musl/src/stdio/putw.c",
+"musl/src/stdio/putwc.c",
+"musl/src/stdio/putwchar.c",
+"musl/src/stdio/remove.c",
+"musl/src/stdio/rename.c",
+"musl/src/stdio/rewind.c",
+"musl/src/stdio/scanf.c",
+"musl/src/stdio/setbuf.c",
+"musl/src/stdio/setbuffer.c",
+"musl/src/stdio/setlinebuf.c",
+"musl/src/stdio/setvbuf.c",
+"musl/src/stdio/snprintf.c",
+"musl/src/stdio/sprintf.c",
+"musl/src/stdio/sscanf.c",
+"musl/src/stdio/stderr.c",
+"musl/src/stdio/stdin.c",
+"musl/src/stdio/stdout.c",
+"musl/src/stdio/swprintf.c",
+"musl/src/stdio/swscanf.c",
+"musl/src/stdio/tempnam.c",
+"musl/src/stdio/tmpfile.c",
+"musl/src/stdio/tmpnam.c",
+"musl/src/stdio/ungetc.c",
+"musl/src/stdio/ungetwc.c",
+"musl/src/stdio/vasprintf.c",
+"musl/src/stdio/vdprintf.c",
+"musl/src/stdio/vfprintf.c",
+"musl/src/stdio/vfscanf.c",
+"musl/src/stdio/vfwprintf.c",
+"musl/src/stdio/vfwscanf.c",
+"musl/src/stdio/vprintf.c",
+"musl/src/stdio/vscanf.c",
+"musl/src/stdio/vsnprintf.c",
+"musl/src/stdio/vsprintf.c",
+"musl/src/stdio/vsscanf.c",
+"musl/src/stdio/vswprintf.c",
+"musl/src/stdio/vswscanf.c",
+"musl/src/stdio/vwprintf.c",
+"musl/src/stdio/vwscanf.c",
+"musl/src/stdio/wprintf.c",
+"musl/src/stdio/wscanf.c",
+"musl/src/stdlib/abs.c",
+"musl/src/stdlib/atof.c",
+"musl/src/stdlib/atoi.c",
+"musl/src/stdlib/atol.c",
+"musl/src/stdlib/atoll.c",
+"musl/src/stdlib/bsearch.c",
+"musl/src/stdlib/div.c",
+"musl/src/stdlib/ecvt.c",
+"musl/src/stdlib/fcvt.c",
+"musl/src/stdlib/gcvt.c",
+"musl/src/stdlib/imaxabs.c",
+"musl/src/stdlib/imaxdiv.c",
+"musl/src/stdlib/labs.c",
+"musl/src/stdlib/ldiv.c",
+"musl/src/stdlib/llabs.c",
+"musl/src/stdlib/lldiv.c",
+"musl/src/stdlib/qsort.c",
+"musl/src/stdlib/strtod.c",
+"musl/src/stdlib/strtol.c",
+"musl/src/stdlib/wcstod.c",
+"musl/src/stdlib/wcstol.c",
+"musl/src/string/arm/__aeabi_memcpy.s",
+"musl/src/string/arm/__aeabi_memset.s",
+"musl/src/string/arm/memcpy.c",
+"musl/src/string/arm/memcpy_le.S",
+"musl/src/string/bcmp.c",
+"musl/src/string/bcopy.c",
+"musl/src/string/bzero.c",
+"musl/src/string/explicit_bzero.c",
+"musl/src/string/i386/memcpy.s",
+"musl/src/string/i386/memmove.s",
+"musl/src/string/i386/memset.s",
+"musl/src/string/index.c",
+"musl/src/string/memccpy.c",
+"musl/src/string/memchr.c",
+"musl/src/string/memcmp.c",
+"musl/src/string/memcpy.c",
+"musl/src/string/memmem.c",
+"musl/src/string/memmove.c",
+"musl/src/string/mempcpy.c",
+"musl/src/string/memrchr.c",
+"musl/src/string/memset.c",
+"musl/src/string/rindex.c",
+"musl/src/string/stpcpy.c",
+"musl/src/string/stpncpy.c",
+"musl/src/string/strcasecmp.c",
+"musl/src/string/strcasestr.c",
+"musl/src/string/strcat.c",
+"musl/src/string/strchr.c",
+"musl/src/string/strchrnul.c",
+"musl/src/string/strcmp.c",
+"musl/src/string/strcpy.c",
+"musl/src/string/strcspn.c",
+"musl/src/string/strdup.c",
+"musl/src/string/strerror_r.c",
+"musl/src/string/strlcat.c",
+"musl/src/string/strlcpy.c",
+"musl/src/string/strlen.c",
+"musl/src/string/strncasecmp.c",
+"musl/src/string/strncat.c",
+"musl/src/string/strncmp.c",
+"musl/src/string/strncpy.c",
+"musl/src/string/strndup.c",
+"musl/src/string/strnlen.c",
+"musl/src/string/strpbrk.c",
+"musl/src/string/strrchr.c",
+"musl/src/string/strsep.c",
+"musl/src/string/strsignal.c",
+"musl/src/string/strspn.c",
+"musl/src/string/strstr.c",
+"musl/src/string/strtok.c",
+"musl/src/string/strtok_r.c",
+"musl/src/string/strverscmp.c",
+"musl/src/string/swab.c",
+"musl/src/string/wcpcpy.c",
+"musl/src/string/wcpncpy.c",
+"musl/src/string/wcscasecmp.c",
+"musl/src/string/wcscasecmp_l.c",
+"musl/src/string/wcscat.c",
+"musl/src/string/wcschr.c",
+"musl/src/string/wcscmp.c",
+"musl/src/string/wcscpy.c",
+"musl/src/string/wcscspn.c",
+"musl/src/string/wcsdup.c",
+"musl/src/string/wcslen.c",
+"musl/src/string/wcsncasecmp.c",
+"musl/src/string/wcsncasecmp_l.c",
+"musl/src/string/wcsncat.c",
+"musl/src/string/wcsncmp.c",
+"musl/src/string/wcsncpy.c",
+"musl/src/string/wcsnlen.c",
+"musl/src/string/wcspbrk.c",
+"musl/src/string/wcsrchr.c",
+"musl/src/string/wcsspn.c",
+"musl/src/string/wcsstr.c",
+"musl/src/string/wcstok.c",
+"musl/src/string/wcswcs.c",
+"musl/src/string/wmemchr.c",
+"musl/src/string/wmemcmp.c",
+"musl/src/string/wmemcpy.c",
+"musl/src/string/wmemmove.c",
+"musl/src/string/wmemset.c",
+"musl/src/string/x86_64/memcpy.s",
+"musl/src/string/x86_64/memmove.s",
+"musl/src/string/x86_64/memset.s",
+"musl/src/temp/__randname.c",
+"musl/src/temp/mkdtemp.c",
+"musl/src/temp/mkostemp.c",
+"musl/src/temp/mkostemps.c",
+"musl/src/temp/mkstemp.c",
+"musl/src/temp/mkstemps.c",
+"musl/src/temp/mktemp.c",
+"musl/src/termios/cfgetospeed.c",
+"musl/src/termios/cfmakeraw.c",
+"musl/src/termios/cfsetospeed.c",
+"musl/src/termios/tcdrain.c",
+"musl/src/termios/tcflow.c",
+"musl/src/termios/tcflush.c",
+"musl/src/termios/tcgetattr.c",
+"musl/src/termios/tcgetsid.c",
+"musl/src/termios/tcsendbreak.c",
+"musl/src/termios/tcsetattr.c",
+"musl/src/thread/__lock.c",
+"musl/src/thread/__set_thread_area.c",
+"musl/src/thread/__syscall_cp.c",
+"musl/src/thread/__timedwait.c",
+"musl/src/thread/__tls_get_addr.c",
+"musl/src/thread/__unmapself.c",
+"musl/src/thread/__wait.c",
+"musl/src/thread/aarch64/__set_thread_area.s",
+"musl/src/thread/aarch64/__unmapself.s",
+"musl/src/thread/aarch64/clone.s",
+"musl/src/thread/aarch64/syscall_cp.s",
+"musl/src/thread/arm/__aeabi_read_tp.s",
+"musl/src/thread/arm/__set_thread_area.c",
+"musl/src/thread/arm/__unmapself.s",
+"musl/src/thread/arm/atomics.s",
+"musl/src/thread/arm/clone.s",
+"musl/src/thread/arm/syscall_cp.s",
+"musl/src/thread/call_once.c",
+"musl/src/thread/clone.c",
+"musl/src/thread/cnd_broadcast.c",
+"musl/src/thread/cnd_destroy.c",
+"musl/src/thread/cnd_init.c",
+"musl/src/thread/cnd_signal.c",
+"musl/src/thread/cnd_timedwait.c",
+"musl/src/thread/cnd_wait.c",
+"musl/src/thread/default_attr.c",
+"musl/src/thread/i386/__set_thread_area.s",
+"musl/src/thread/i386/__unmapself.s",
+"musl/src/thread/i386/clone.s",
+"musl/src/thread/i386/syscall_cp.s",
+"musl/src/thread/i386/tls.s",
+"musl/src/thread/lock_ptc.c",
+"musl/src/thread/m68k/__m68k_read_tp.s",
+"musl/src/thread/m68k/clone.s",
+"musl/src/thread/m68k/syscall_cp.s",
+"musl/src/thread/microblaze/__set_thread_area.s",
+"musl/src/thread/microblaze/__unmapself.s",
+"musl/src/thread/microblaze/clone.s",
+"musl/src/thread/microblaze/syscall_cp.s",
+"musl/src/thread/mips/__unmapself.s",
+"musl/src/thread/mips/clone.s",
+"musl/src/thread/mips/syscall_cp.s",
+"musl/src/thread/mips64/__unmapself.s",
+"musl/src/thread/mips64/clone.s",
+"musl/src/thread/mips64/syscall_cp.s",
+"musl/src/thread/mipsn32/__unmapself.s",
+"musl/src/thread/mipsn32/clone.s",
+"musl/src/thread/mipsn32/syscall_cp.s",
+"musl/src/thread/mtx_destroy.c",
+"musl/src/thread/mtx_init.c",
+"musl/src/thread/mtx_lock.c",
+"musl/src/thread/mtx_timedlock.c",
+"musl/src/thread/mtx_trylock.c",
+"musl/src/thread/mtx_unlock.c",
+"musl/src/thread/or1k/__set_thread_area.s",
+"musl/src/thread/or1k/__unmapself.s",
+"musl/src/thread/or1k/clone.s",
+"musl/src/thread/or1k/syscall_cp.s",
+"musl/src/thread/powerpc/__set_thread_area.s",
+"musl/src/thread/powerpc/__unmapself.s",
+"musl/src/thread/powerpc/clone.s",
+"musl/src/thread/powerpc/syscall_cp.s",
+"musl/src/thread/powerpc64/__set_thread_area.s",
+"musl/src/thread/powerpc64/__unmapself.s",
+"musl/src/thread/powerpc64/clone.s",
+"musl/src/thread/powerpc64/syscall_cp.s",
+"musl/src/thread/pthread_atfork.c",
+"musl/src/thread/pthread_attr_destroy.c",
+"musl/src/thread/pthread_attr_get.c",
+"musl/src/thread/pthread_attr_init.c",
+"musl/src/thread/pthread_attr_setdetachstate.c",
+"musl/src/thread/pthread_attr_setguardsize.c",
+"musl/src/thread/pthread_attr_setinheritsched.c",
+"musl/src/thread/pthread_attr_setschedparam.c",
+"musl/src/thread/pthread_attr_setschedpolicy.c",
+"musl/src/thread/pthread_attr_setscope.c",
+"musl/src/thread/pthread_attr_setstack.c",
+"musl/src/thread/pthread_attr_setstacksize.c",
+"musl/src/thread/pthread_barrier_destroy.c",
+"musl/src/thread/pthread_barrier_init.c",
+"musl/src/thread/pthread_barrier_wait.c",
+"musl/src/thread/pthread_barrierattr_destroy.c",
+"musl/src/thread/pthread_barrierattr_init.c",
+"musl/src/thread/pthread_barrierattr_setpshared.c",
+"musl/src/thread/pthread_cancel.c",
+"musl/src/thread/pthread_cleanup_push.c",
+"musl/src/thread/pthread_cond_broadcast.c",
+"musl/src/thread/pthread_cond_destroy.c",
+"musl/src/thread/pthread_cond_init.c",
+"musl/src/thread/pthread_cond_signal.c",
+"musl/src/thread/pthread_cond_timedwait.c",
+"musl/src/thread/pthread_cond_wait.c",
+"musl/src/thread/pthread_condattr_destroy.c",
+"musl/src/thread/pthread_condattr_init.c",
+"musl/src/thread/pthread_condattr_setclock.c",
+"musl/src/thread/pthread_condattr_setpshared.c",
+"musl/src/thread/pthread_create.c",
+"musl/src/thread/pthread_detach.c",
+"musl/src/thread/pthread_equal.c",
+"musl/src/thread/pthread_getattr_np.c",
+"musl/src/thread/pthread_getconcurrency.c",
+"musl/src/thread/pthread_getcpuclockid.c",
+"musl/src/thread/pthread_getschedparam.c",
+"musl/src/thread/pthread_getspecific.c",
+"musl/src/thread/pthread_join.c",
+"musl/src/thread/pthread_key_create.c",
+"musl/src/thread/pthread_key_delete.c",
+"musl/src/thread/pthread_kill.c",
+"musl/src/thread/pthread_mutex_consistent.c",
+"musl/src/thread/pthread_mutex_destroy.c",
+"musl/src/thread/pthread_mutex_getprioceiling.c",
+"musl/src/thread/pthread_mutex_init.c",
+"musl/src/thread/pthread_mutex_lock.c",
+"musl/src/thread/pthread_mutex_setprioceiling.c",
+"musl/src/thread/pthread_mutex_timedlock.c",
+"musl/src/thread/pthread_mutex_trylock.c",
+"musl/src/thread/pthread_mutex_unlock.c",
+"musl/src/thread/pthread_mutexattr_destroy.c",
+"musl/src/thread/pthread_mutexattr_init.c",
+"musl/src/thread/pthread_mutexattr_setprotocol.c",
+"musl/src/thread/pthread_mutexattr_setpshared.c",
+"musl/src/thread/pthread_mutexattr_setrobust.c",
+"musl/src/thread/pthread_mutexattr_settype.c",
+"musl/src/thread/pthread_once.c",
+"musl/src/thread/pthread_rwlock_destroy.c",
+"musl/src/thread/pthread_rwlock_init.c",
+"musl/src/thread/pthread_rwlock_rdlock.c",
+"musl/src/thread/pthread_rwlock_timedrdlock.c",
+"musl/src/thread/pthread_rwlock_timedwrlock.c",
+"musl/src/thread/pthread_rwlock_tryrdlock.c",
+"musl/src/thread/pthread_rwlock_trywrlock.c",
+"musl/src/thread/pthread_rwlock_unlock.c",
+"musl/src/thread/pthread_rwlock_wrlock.c",
+"musl/src/thread/pthread_rwlockattr_destroy.c",
+"musl/src/thread/pthread_rwlockattr_init.c",
+"musl/src/thread/pthread_rwlockattr_setpshared.c",
+"musl/src/thread/pthread_self.c",
+"musl/src/thread/pthread_setattr_default_np.c",
+"musl/src/thread/pthread_setcancelstate.c",
+"musl/src/thread/pthread_setcanceltype.c",
+"musl/src/thread/pthread_setconcurrency.c",
+"musl/src/thread/pthread_setname_np.c",
+"musl/src/thread/pthread_setschedparam.c",
+"musl/src/thread/pthread_setschedprio.c",
+"musl/src/thread/pthread_setspecific.c",
+"musl/src/thread/pthread_sigmask.c",
+"musl/src/thread/pthread_spin_destroy.c",
+"musl/src/thread/pthread_spin_init.c",
+"musl/src/thread/pthread_spin_lock.c",
+"musl/src/thread/pthread_spin_trylock.c",
+"musl/src/thread/pthread_spin_unlock.c",
+"musl/src/thread/pthread_testcancel.c",
+"musl/src/thread/s390x/__set_thread_area.s",
+"musl/src/thread/s390x/__tls_get_offset.s",
+"musl/src/thread/s390x/__unmapself.s",
+"musl/src/thread/s390x/clone.s",
+"musl/src/thread/s390x/syscall_cp.s",
+"musl/src/thread/sem_destroy.c",
+"musl/src/thread/sem_getvalue.c",
+"musl/src/thread/sem_init.c",
+"musl/src/thread/sem_open.c",
+"musl/src/thread/sem_post.c",
+"musl/src/thread/sem_timedwait.c",
+"musl/src/thread/sem_trywait.c",
+"musl/src/thread/sem_unlink.c",
+"musl/src/thread/sem_wait.c",
+"musl/src/thread/sh/__set_thread_area.c",
+"musl/src/thread/sh/__unmapself.c",
+"musl/src/thread/sh/__unmapself_mmu.s",
+"musl/src/thread/sh/atomics.s",
+"musl/src/thread/sh/clone.s",
+"musl/src/thread/sh/syscall_cp.s",
+"musl/src/thread/synccall.c",
+"musl/src/thread/syscall_cp.c",
+"musl/src/thread/thrd_create.c",
+"musl/src/thread/thrd_exit.c",
+"musl/src/thread/thrd_join.c",
+"musl/src/thread/thrd_sleep.c",
+"musl/src/thread/thrd_yield.c",
+"musl/src/thread/tls.c",
+"musl/src/thread/tss_create.c",
+"musl/src/thread/tss_delete.c",
+"musl/src/thread/tss_set.c",
+"musl/src/thread/vmlock.c",
+"musl/src/thread/x32/__set_thread_area.s",
+"musl/src/thread/x32/__unmapself.s",
+"musl/src/thread/x32/clone.s",
+"musl/src/thread/x32/syscall_cp.s",
+"musl/src/thread/x32/syscall_cp_fixup.c",
+"musl/src/thread/x86_64/__set_thread_area.s",
+"musl/src/thread/x86_64/__unmapself.s",
+"musl/src/thread/x86_64/clone.s",
+"musl/src/thread/x86_64/syscall_cp.s",
+"musl/src/time/__map_file.c",
+"musl/src/time/__month_to_secs.c",
+"musl/src/time/__secs_to_tm.c",
+"musl/src/time/__tm_to_secs.c",
+"musl/src/time/__tz.c",
+"musl/src/time/__year_to_secs.c",
+"musl/src/time/asctime.c",
+"musl/src/time/asctime_r.c",
+"musl/src/time/clock.c",
+"musl/src/time/clock_getcpuclockid.c",
+"musl/src/time/clock_getres.c",
+"musl/src/time/clock_gettime.c",
+"musl/src/time/clock_nanosleep.c",
+"musl/src/time/clock_settime.c",
+"musl/src/time/ctime.c",
+"musl/src/time/ctime_r.c",
+"musl/src/time/difftime.c",
+"musl/src/time/ftime.c",
+"musl/src/time/getdate.c",
+"musl/src/time/gettimeofday.c",
+"musl/src/time/gmtime.c",
+"musl/src/time/gmtime_r.c",
+"musl/src/time/localtime.c",
+"musl/src/time/localtime_r.c",
+"musl/src/time/mktime.c",
+"musl/src/time/nanosleep.c",
+"musl/src/time/strftime.c",
+"musl/src/time/strptime.c",
+"musl/src/time/time.c",
+"musl/src/time/time_impl.h",
+"musl/src/time/timegm.c",
+"musl/src/time/timer_create.c",
+"musl/src/time/timer_delete.c",
+"musl/src/time/timer_getoverrun.c",
+"musl/src/time/timer_gettime.c",
+"musl/src/time/timer_settime.c",
+"musl/src/time/times.c",
+"musl/src/time/timespec_get.c",
+"musl/src/time/utime.c",
+"musl/src/time/wcsftime.c",
+"musl/src/unistd/_exit.c",
+"musl/src/unistd/access.c",
+"musl/src/unistd/acct.c",
+"musl/src/unistd/alarm.c",
+"musl/src/unistd/chdir.c",
+"musl/src/unistd/chown.c",
+"musl/src/unistd/close.c",
+"musl/src/unistd/ctermid.c",
+"musl/src/unistd/dup.c",
+"musl/src/unistd/dup2.c",
+"musl/src/unistd/dup3.c",
+"musl/src/unistd/faccessat.c",
+"musl/src/unistd/fchdir.c",
+"musl/src/unistd/fchown.c",
+"musl/src/unistd/fchownat.c",
+"musl/src/unistd/fdatasync.c",
+"musl/src/unistd/fsync.c",
+"musl/src/unistd/ftruncate.c",
+"musl/src/unistd/getcwd.c",
+"musl/src/unistd/getegid.c",
+"musl/src/unistd/geteuid.c",
+"musl/src/unistd/getgid.c",
+"musl/src/unistd/getgroups.c",
+"musl/src/unistd/gethostname.c",
+"musl/src/unistd/getlogin.c",
+"musl/src/unistd/getlogin_r.c",
+"musl/src/unistd/getpgid.c",
+"musl/src/unistd/getpgrp.c",
+"musl/src/unistd/getpid.c",
+"musl/src/unistd/getppid.c",
+"musl/src/unistd/getsid.c",
+"musl/src/unistd/getuid.c",
+"musl/src/unistd/isatty.c",
+"musl/src/unistd/lchown.c",
+"musl/src/unistd/link.c",
+"musl/src/unistd/linkat.c",
+"musl/src/unistd/lseek.c",
+"musl/src/unistd/mips/pipe.s",
+"musl/src/unistd/mips64/pipe.s",
+"musl/src/unistd/mipsn32/pipe.s",
+"musl/src/unistd/nice.c",
+"musl/src/unistd/pause.c",
+"musl/src/unistd/pipe.c",
+"musl/src/unistd/pipe2.c",
+"musl/src/unistd/posix_close.c",
+"musl/src/unistd/pread.c",
+"musl/src/unistd/preadv.c",
+"musl/src/unistd/pwrite.c",
+"musl/src/unistd/pwritev.c",
+"musl/src/unistd/read.c",
+"musl/src/unistd/readlink.c",
+"musl/src/unistd/readlinkat.c",
+"musl/src/unistd/readv.c",
+"musl/src/unistd/renameat.c",
+"musl/src/unistd/rmdir.c",
+"musl/src/unistd/setegid.c",
+"musl/src/unistd/seteuid.c",
+"musl/src/unistd/setgid.c",
+"musl/src/unistd/setpgid.c",
+"musl/src/unistd/setpgrp.c",
+"musl/src/unistd/setregid.c",
+"musl/src/unistd/setresgid.c",
+"musl/src/unistd/setresuid.c",
+"musl/src/unistd/setreuid.c",
+"musl/src/unistd/setsid.c",
+"musl/src/unistd/setuid.c",
+"musl/src/unistd/setxid.c",
+"musl/src/unistd/sh/pipe.s",
+"musl/src/unistd/sleep.c",
+"musl/src/unistd/symlink.c",
+"musl/src/unistd/symlinkat.c",
+"musl/src/unistd/sync.c",
+"musl/src/unistd/tcgetpgrp.c",
+"musl/src/unistd/tcsetpgrp.c",
+"musl/src/unistd/truncate.c",
+"musl/src/unistd/ttyname.c",
+"musl/src/unistd/ttyname_r.c",
+"musl/src/unistd/ualarm.c",
+"musl/src/unistd/unlink.c",
+"musl/src/unistd/unlinkat.c",
+"musl/src/unistd/usleep.c",
+"musl/src/unistd/write.c",
+"musl/src/unistd/writev.c",
+};
+#endif
diff --git a/src/ir.cpp b/src/ir.cpp
index 0c79316652..5193a63ec4 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -38,6 +38,7 @@ struct IrAnalyze {
ZigType *explicit_return_type;
AstNode *explicit_return_type_source_node;
ZigList<IrInstruction *> src_implicit_return_type_list;
+ ZigList<IrSuspendPosition> resume_stack;
IrBasicBlock *const_predecessor_bb;
};
@@ -157,16 +158,19 @@ enum UndefAllowed {
};
static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);
-static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval);
-static IrInstruction *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);
+static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval,
+ ResultLoc *result_loc);
static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type);
-static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr);
+static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr,
+ ResultLoc *result_loc);
static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg);
static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
- IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type);
+ IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing);
+static void ir_assert(bool ok, IrInstruction *source_instruction);
static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var);
static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op);
-static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval);
+static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval, ResultLoc *result_loc);
+static IrInstruction *ir_expr_wrap(IrBuilder *irb, Scope *scope, IrInstruction *inst, ResultLoc *result_loc);
static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);
static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);
static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val);
@@ -178,17 +182,31 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);
static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
-static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry);
static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
ZigType *ptr_type);
static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
ZigType *dest_type);
+static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr,
+ ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime);
+static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr,
+ ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime);
+static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *base_ptr, bool safety_check_on, bool initializing);
+static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *base_ptr, bool safety_check_on, bool initializing);
+static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *base_ptr, bool initializing);
+static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *ptr, IrInstruction *uncasted_value);
+static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *union_type, IrInstruction *field_name, AstNode *expr_node,
+ LVal lval, ResultLoc *parent_result_loc);
static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
assert(get_src_ptr_type(const_val->type) != nullptr);
assert(const_val->special == ConstValSpecialStatic);
ConstExprValue *result;
-
+
switch (type_has_one_possible_value(g, const_val->type->data.pointer.child_type)) {
case OnePossibleValueInvalid:
zig_unreachable();
@@ -200,7 +218,7 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
case OnePossibleValueNo:
break;
}
-
+
switch (const_val->data.x_ptr.special) {
case ConstPtrSpecialInvalid:
zig_unreachable();
@@ -246,6 +264,15 @@ static bool is_opt_err_set(ZigType *ty) {
(ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet);
}
+static bool is_slice(ZigType *type) {
+ return type->id == ZigTypeIdStruct && type->data.structure.is_slice;
+}
+
+static bool slice_is_const(ZigType *type) {
+ assert(is_slice(type));
+ return type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;
+}
+
// This function returns true when you can change the type of a ConstExprValue and the
// value remains meaningful.
static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
@@ -282,8 +309,9 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
return a->data.floating.bit_count == b->data.floating.bit_count;
case ZigTypeIdInt:
return a->data.integral.is_signed == b->data.integral.is_signed;
- case ZigTypeIdArray:
case ZigTypeIdStruct:
+ return is_slice(a) && is_slice(b);
+ case ZigTypeIdArray:
case ZigTypeIdOptional:
case ZigTypeIdErrorUnion:
case ZigTypeIdEnum:
@@ -386,6 +414,7 @@ static IrBasicBlock *ir_create_basic_block(IrBuilder *irb, Scope *scope, const c
result->scope = scope;
result->name_hint = name_hint;
result->debug_id = exec_next_debug_id(irb->exec);
+ result->index = SIZE_MAX; // set later
return result;
}
@@ -475,8 +504,16 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionVarPtr *) {
return IrInstructionIdVarPtr;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionCall *) {
- return IrInstructionIdCall;
+static constexpr IrInstructionId ir_instruction_id(IrInstructionReturnPtr *) {
+ return IrInstructionIdReturnPtr;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionCallSrc *) {
+ return IrInstructionIdCallSrc;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionCallGen *) {
+ return IrInstructionIdCallGen;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionConst *) {
@@ -511,14 +548,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeOf *) {
return IrInstructionIdTypeOf;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionToPtrType *) {
- return IrInstructionIdToPtrType;
-}
-
-static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrTypeChild *) {
- return IrInstructionIdPtrTypeChild;
-}
-
static constexpr IrInstructionId ir_instruction_id(IrInstructionSetCold *) {
return IrInstructionIdSetCold;
}
@@ -611,12 +640,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionRef *) {
return IrInstructionIdRef;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionStructInit *) {
- return IrInstructionIdStructInit;
-}
-
-static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionInit *) {
- return IrInstructionIdUnionInit;
+static constexpr IrInstructionId ir_instruction_id(IrInstructionRefGen *) {
+ return IrInstructionIdRefGen;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionCompileErr *) {
@@ -703,8 +728,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionMemcpy *) {
return IrInstructionIdMemcpy;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionSlice *) {
- return IrInstructionIdSlice;
+static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceSrc *) {
+ return IrInstructionIdSliceSrc;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceGen *) {
+ return IrInstructionIdSliceGen;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberCount *) {
@@ -743,8 +772,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionOverflowOp *) {
return IrInstructionIdOverflowOp;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionTestErr *) {
- return IrInstructionIdTestErr;
+static constexpr IrInstructionId ir_instruction_id(IrInstructionTestErrSrc *) {
+ return IrInstructionIdTestErrSrc;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionTestErrGen *) {
+ return IrInstructionIdTestErrGen;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionMulAdd *) {
@@ -787,8 +820,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastGen *) {
return IrInstructionIdPtrCastGen;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {
- return IrInstructionIdBitCast;
+static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCastSrc *) {
+ return IrInstructionIdBitCastSrc;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCastGen *) {
@@ -867,6 +900,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeInfo *) {
return IrInstructionIdTypeInfo;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionHasField *) {
+ return IrInstructionIdHasField;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeId *) {
return IrInstructionIdTypeId;
}
@@ -883,6 +920,26 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignCast *) {
return IrInstructionIdAlignCast;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionImplicitCast *) {
+ return IrInstructionIdImplicitCast;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionResolveResult *) {
+ return IrInstructionIdResolveResult;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionResetResult *) {
+ return IrInstructionIdResetResult;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionResultPtr *) {
+ return IrInstructionIdResultPtr;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrOfArrayToSlice *) {
+ return IrInstructionIdPtrOfArrayToSlice;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionOpaqueType *) {
return IrInstructionIdOpaqueType;
}
@@ -1023,6 +1080,22 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionUndeclaredIdent
return IrInstructionIdUndeclaredIdent;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionAllocaSrc *) {
+ return IrInstructionIdAllocaSrc;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionAllocaGen *) {
+ return IrInstructionIdAllocaGen;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionEndExpr *) {
+ return IrInstructionIdEndExpr;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionInitNamedField *) {
+ return IrInstructionIdUnionInitNamedField;
+}
+
template<typename T>
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
T *special_instruction = allocate<T>(1);
@@ -1074,13 +1147,15 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so
return &cond_br_instruction->base;
}
-static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *return_value) {
+static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *return_value)
+{
IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irb, scope, source_node);
return_instruction->base.value.type = irb->codegen->builtin_types.entry_unreachable;
return_instruction->base.value.special = ConstValSpecialStatic;
return_instruction->value = return_value;
- ir_ref_instruction(return_value, irb->current_basic_block);
+ if (return_value != nullptr) ir_ref_instruction(return_value, irb->current_basic_block);
return &return_instruction->base;
}
@@ -1258,28 +1333,39 @@ static IrInstruction *ir_build_var_ptr(IrBuilder *irb, Scope *scope, AstNode *so
return ir_build_var_ptr_x(irb, scope, source_node, var, nullptr);
}
-static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *array_ptr,
- IrInstruction *elem_index, bool safety_check_on, PtrLen ptr_len)
+static IrInstruction *ir_build_return_ptr(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) {
+ IrInstructionReturnPtr *instruction = ir_build_instruction<IrInstructionReturnPtr>(&ira->new_irb,
+ source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = ty;
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *array_ptr, IrInstruction *elem_index, bool safety_check_on, PtrLen ptr_len,
+ IrInstruction *init_array_type)
{
IrInstructionElemPtr *instruction = ir_build_instruction<IrInstructionElemPtr>(irb, scope, source_node);
instruction->array_ptr = array_ptr;
instruction->elem_index = elem_index;
instruction->safety_check_on = safety_check_on;
instruction->ptr_len = ptr_len;
+ instruction->init_array_type = init_array_type;
ir_ref_instruction(array_ptr, irb->current_basic_block);
ir_ref_instruction(elem_index, irb->current_basic_block);
+ if (init_array_type != nullptr) ir_ref_instruction(init_array_type, irb->current_basic_block);
return &instruction->base;
}
static IrInstruction *ir_build_field_ptr_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *container_ptr, IrInstruction *field_name_expr)
+ IrInstruction *container_ptr, IrInstruction *field_name_expr, bool initializing)
{
IrInstructionFieldPtr *instruction = ir_build_instruction<IrInstructionFieldPtr>(irb, scope, source_node);
instruction->container_ptr = container_ptr;
instruction->field_name_buffer = nullptr;
instruction->field_name_expr = field_name_expr;
+ instruction->initializing = initializing;
ir_ref_instruction(container_ptr, irb->current_basic_block);
ir_ref_instruction(field_name_expr, irb->current_basic_block);
@@ -1288,18 +1374,32 @@ static IrInstruction *ir_build_field_ptr_instruction(IrBuilder *irb, Scope *scop
}
static IrInstruction *ir_build_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *container_ptr, Buf *field_name)
+ IrInstruction *container_ptr, Buf *field_name, bool initializing)
{
IrInstructionFieldPtr *instruction = ir_build_instruction<IrInstructionFieldPtr>(irb, scope, source_node);
instruction->container_ptr = container_ptr;
instruction->field_name_buffer = field_name;
instruction->field_name_expr = nullptr;
+ instruction->initializing = initializing;
ir_ref_instruction(container_ptr, irb->current_basic_block);
return &instruction->base;
}
+static IrInstruction *ir_build_has_field(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *container_type, IrInstruction *field_name)
+{
+ IrInstructionHasField *instruction = ir_build_instruction<IrInstructionHasField>(irb, scope, source_node);
+ instruction->container_type = container_type;
+ instruction->field_name = field_name;
+
+ ir_ref_instruction(container_type, irb->current_basic_block);
+ ir_ref_instruction(field_name, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_struct_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *struct_ptr, TypeStructField *field)
{
@@ -1313,9 +1413,11 @@ static IrInstruction *ir_build_struct_field_ptr(IrBuilder *irb, Scope *scope, As
}
static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *union_ptr, TypeUnionField *field)
+ IrInstruction *union_ptr, TypeUnionField *field, bool safety_check_on, bool initializing)
{
IrInstructionUnionFieldPtr *instruction = ir_build_instruction<IrInstructionUnionFieldPtr>(irb, scope, source_node);
+ instruction->initializing = initializing;
+ instruction->safety_check_on = safety_check_on;
instruction->union_ptr = union_ptr;
instruction->field = field;
@@ -1324,12 +1426,12 @@ static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, Ast
return &instruction->base;
}
-static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *source_node,
+static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator,
- IrInstruction *new_stack)
+ IrInstruction *new_stack, ResultLoc *result_loc)
{
- IrInstructionCall *call_instruction = ir_build_instruction<IrInstructionCall>(irb, scope, source_node);
+ IrInstructionCallSrc *call_instruction = ir_build_instruction<IrInstructionCallSrc>(irb, scope, source_node);
call_instruction->fn_entry = fn_entry;
call_instruction->fn_ref = fn_ref;
call_instruction->is_comptime = is_comptime;
@@ -1339,6 +1441,7 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc
call_instruction->is_async = is_async;
call_instruction->async_allocator = async_allocator;
call_instruction->new_stack = new_stack;
+ call_instruction->result_loc = result_loc;
if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block);
for (size_t i = 0; i < arg_count; i += 1)
@@ -1349,8 +1452,37 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc
return &call_instruction->base;
}
+static IrInstruction *ir_build_call_gen(IrAnalyze *ira, IrInstruction *source_instruction,
+ ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
+ FnInline fn_inline, bool is_async, IrInstruction *async_allocator, IrInstruction *new_stack,
+ IrInstruction *result_loc, ZigType *return_type)
+{
+ IrInstructionCallGen *call_instruction = ir_build_instruction<IrInstructionCallGen>(&ira->new_irb,
+ source_instruction->scope, source_instruction->source_node);
+ call_instruction->base.value.type = return_type;
+ call_instruction->fn_entry = fn_entry;
+ call_instruction->fn_ref = fn_ref;
+ call_instruction->fn_inline = fn_inline;
+ call_instruction->args = args;
+ call_instruction->arg_count = arg_count;
+ call_instruction->is_async = is_async;
+ call_instruction->async_allocator = async_allocator;
+ call_instruction->new_stack = new_stack;
+ call_instruction->result_loc = result_loc;
+
+ if (fn_ref != nullptr) ir_ref_instruction(fn_ref, ira->new_irb.current_basic_block);
+ for (size_t i = 0; i < arg_count; i += 1)
+ ir_ref_instruction(args[i], ira->new_irb.current_basic_block);
+ if (async_allocator != nullptr) ir_ref_instruction(async_allocator, ira->new_irb.current_basic_block);
+ if (new_stack != nullptr) ir_ref_instruction(new_stack, ira->new_irb.current_basic_block);
+ if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
+
+ return &call_instruction->base;
+}
+
static IrInstruction *ir_build_phi(IrBuilder *irb, Scope *scope, AstNode *source_node,
- size_t incoming_count, IrBasicBlock **incoming_blocks, IrInstruction **incoming_values)
+ size_t incoming_count, IrBasicBlock **incoming_blocks, IrInstruction **incoming_values,
+ ResultLocPeerParent *peer_parent)
{
assert(incoming_count != 0);
assert(incoming_count != SIZE_MAX);
@@ -1359,6 +1491,7 @@ static IrInstruction *ir_build_phi(IrBuilder *irb, Scope *scope, AstNode *source
phi_instruction->incoming_count = incoming_count;
phi_instruction->incoming_blocks = incoming_blocks;
phi_instruction->incoming_values = incoming_values;
+ phi_instruction->peer_parent = peer_parent;
for (size_t i = 0; i < incoming_count; i += 1) {
ir_ref_bb(incoming_blocks[i]);
@@ -1412,12 +1545,13 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s
}
static IrInstruction *ir_build_un_op_lval(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id,
- IrInstruction *value, LVal lval)
+ IrInstruction *value, LVal lval, ResultLoc *result_loc)
{
IrInstructionUnOp *instruction = ir_build_instruction<IrInstructionUnOp>(irb, scope, source_node);
instruction->op_id = op_id;
instruction->value = value;
instruction->lval = lval;
+ instruction->result_loc = result_loc;
ir_ref_instruction(value, irb->current_basic_block);
@@ -1427,72 +1561,49 @@ static IrInstruction *ir_build_un_op_lval(IrBuilder *irb, Scope *scope, AstNode
static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id,
IrInstruction *value)
{
- return ir_build_un_op_lval(irb, scope, source_node, op_id, value, LValNone);
+ return ir_build_un_op_lval(irb, scope, source_node, op_id, value, LValNone, nullptr);
}
static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *container_type, IrInstruction *elem_type, size_t item_count, IrInstruction **items)
+ IrInstruction *container_type, size_t item_count, IrInstruction **elem_result_loc_list,
+ IrInstruction *result_loc)
{
IrInstructionContainerInitList *container_init_list_instruction =
ir_build_instruction<IrInstructionContainerInitList>(irb, scope, source_node);
container_init_list_instruction->container_type = container_type;
- container_init_list_instruction->elem_type = elem_type;
container_init_list_instruction->item_count = item_count;
- container_init_list_instruction->items = items;
+ container_init_list_instruction->elem_result_loc_list = elem_result_loc_list;
+ container_init_list_instruction->result_loc = result_loc;
- if (container_type != nullptr) ir_ref_instruction(container_type, irb->current_basic_block);
- if (elem_type != nullptr) ir_ref_instruction(elem_type, irb->current_basic_block);
+ ir_ref_instruction(container_type, irb->current_basic_block);
for (size_t i = 0; i < item_count; i += 1) {
- ir_ref_instruction(items[i], irb->current_basic_block);
+ ir_ref_instruction(elem_result_loc_list[i], irb->current_basic_block);
}
+ if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block);
return &container_init_list_instruction->base;
}
static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *container_type, size_t field_count, IrInstructionContainerInitFieldsField *fields)
+ IrInstruction *container_type, size_t field_count, IrInstructionContainerInitFieldsField *fields,
+ IrInstruction *result_loc)
{
IrInstructionContainerInitFields *container_init_fields_instruction =
ir_build_instruction<IrInstructionContainerInitFields>(irb, scope, source_node);
container_init_fields_instruction->container_type = container_type;
container_init_fields_instruction->field_count = field_count;
container_init_fields_instruction->fields = fields;
+ container_init_fields_instruction->result_loc = result_loc;
ir_ref_instruction(container_type, irb->current_basic_block);
for (size_t i = 0; i < field_count; i += 1) {
- ir_ref_instruction(fields[i].value, irb->current_basic_block);
+ ir_ref_instruction(fields[i].result_loc, irb->current_basic_block);
}
+ if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block);
return &container_init_fields_instruction->base;
}
-static IrInstruction *ir_build_struct_init(IrBuilder *irb, Scope *scope, AstNode *source_node,
- ZigType *struct_type, size_t field_count, IrInstructionStructInitField *fields)
-{
- IrInstructionStructInit *struct_init_instruction = ir_build_instruction<IrInstructionStructInit>(irb, scope, source_node);
- struct_init_instruction->struct_type = struct_type;
- struct_init_instruction->field_count = field_count;
- struct_init_instruction->fields = fields;
-
- for (size_t i = 0; i < field_count; i += 1)
- ir_ref_instruction(fields[i].value, irb->current_basic_block);
-
- return &struct_init_instruction->base;
-}
-
-static IrInstruction *ir_build_union_init(IrBuilder *irb, Scope *scope, AstNode *source_node,
- ZigType *union_type, TypeUnionField *field, IrInstruction *init_value)
-{
- IrInstructionUnionInit *union_init_instruction = ir_build_instruction<IrInstructionUnionInit>(irb, scope, source_node);
- union_init_instruction->union_type = union_type;
- union_init_instruction->field = field;
- union_init_instruction->init_value = init_value;
-
- ir_ref_instruction(init_value, irb->current_basic_block);
-
- return &union_init_instruction->base;
-}
-
static IrInstruction *ir_build_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node) {
IrInstructionUnreachable *unreachable_instruction =
ir_build_instruction<IrInstructionUnreachable>(irb, scope, source_node);
@@ -1517,47 +1628,47 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *
}
static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
- ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value)
+ ZigVar *var, IrInstruction *align_value, IrInstruction *ptr)
{
IrInstructionDeclVarSrc *decl_var_instruction = ir_build_instruction<IrInstructionDeclVarSrc>(irb, scope, source_node);
decl_var_instruction->base.value.special = ConstValSpecialStatic;
decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void;
decl_var_instruction->var = var;
- decl_var_instruction->var_type = var_type;
decl_var_instruction->align_value = align_value;
- decl_var_instruction->init_value = init_value;
+ decl_var_instruction->ptr = ptr;
- if (var_type != nullptr) ir_ref_instruction(var_type, irb->current_basic_block);
if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block);
- ir_ref_instruction(init_value, irb->current_basic_block);
+ ir_ref_instruction(ptr, irb->current_basic_block);
return &decl_var_instruction->base;
}
static IrInstruction *ir_build_var_decl_gen(IrAnalyze *ira, IrInstruction *source_instruction,
- ZigVar *var, IrInstruction *init_value)
+ ZigVar *var, IrInstruction *var_ptr)
{
IrInstructionDeclVarGen *decl_var_instruction = ir_build_instruction<IrInstructionDeclVarGen>(&ira->new_irb,
source_instruction->scope, source_instruction->source_node);
decl_var_instruction->base.value.special = ConstValSpecialStatic;
decl_var_instruction->base.value.type = ira->codegen->builtin_types.entry_void;
decl_var_instruction->var = var;
- decl_var_instruction->init_value = init_value;
+ decl_var_instruction->var_ptr = var_ptr;
- ir_ref_instruction(init_value, ira->new_irb.current_basic_block);
+ ir_ref_instruction(var_ptr, ira->new_irb.current_basic_block);
return &decl_var_instruction->base;
}
static IrInstruction *ir_build_resize_slice(IrAnalyze *ira, IrInstruction *source_instruction,
- IrInstruction *operand, ZigType *ty)
+ IrInstruction *operand, ZigType *ty, IrInstruction *result_loc)
{
IrInstructionResizeSlice *instruction = ir_build_instruction<IrInstructionResizeSlice>(&ira->new_irb,
source_instruction->scope, source_instruction->source_node);
instruction->base.value.type = ty;
instruction->operand = operand;
+ instruction->result_loc = result_loc;
ir_ref_instruction(operand, ira->new_irb.current_basic_block);
+ ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
return &instruction->base;
}
@@ -1598,27 +1709,6 @@ static IrInstruction *ir_build_typeof(IrBuilder *irb, Scope *scope, AstNode *sou
return &instruction->base;
}
-static IrInstruction *ir_build_to_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *ptr) {
- IrInstructionToPtrType *instruction = ir_build_instruction<IrInstructionToPtrType>(irb, scope, source_node);
- instruction->ptr = ptr;
-
- ir_ref_instruction(ptr, irb->current_basic_block);
-
- return &instruction->base;
-}
-
-static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *value)
-{
- IrInstructionPtrTypeChild *instruction = ir_build_instruction<IrInstructionPtrTypeChild>(
- irb, scope, source_node);
- instruction->value = value;
-
- ir_ref_instruction(value, irb->current_basic_block);
-
- return &instruction->base;
-}
-
static IrInstruction *ir_build_set_cold(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *is_cold) {
IrInstructionSetCold *instruction = ir_build_instruction<IrInstructionSetCold>(irb, scope, source_node);
instruction->is_cold = is_cold;
@@ -1744,40 +1834,59 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod
}
static IrInstruction *ir_build_optional_unwrap_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *base_ptr, bool safety_check_on)
+ IrInstruction *base_ptr, bool safety_check_on, bool initializing)
{
IrInstructionOptionalUnwrapPtr *instruction = ir_build_instruction<IrInstructionOptionalUnwrapPtr>(irb, scope, source_node);
instruction->base_ptr = base_ptr;
instruction->safety_check_on = safety_check_on;
+ instruction->initializing = initializing;
ir_ref_instruction(base_ptr, irb->current_basic_block);
return &instruction->base;
}
-static IrInstruction *ir_build_maybe_wrap(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
- IrInstructionOptionalWrap *instruction = ir_build_instruction<IrInstructionOptionalWrap>(irb, scope, source_node);
- instruction->value = value;
+static IrInstruction *ir_build_optional_wrap(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *result_ty,
+ IrInstruction *operand, IrInstruction *result_loc)
+{
+ IrInstructionOptionalWrap *instruction = ir_build_instruction<IrInstructionOptionalWrap>(
+ &ira->new_irb, source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = result_ty;
+ instruction->operand = operand;
+ instruction->result_loc = result_loc;
- ir_ref_instruction(value, irb->current_basic_block);
+ ir_ref_instruction(operand, ira->new_irb.current_basic_block);
+ if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
return &instruction->base;
}
-static IrInstruction *ir_build_err_wrap_payload(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
- IrInstructionErrWrapPayload *instruction = ir_build_instruction<IrInstructionErrWrapPayload>(irb, scope, source_node);
- instruction->value = value;
+static IrInstruction *ir_build_err_wrap_payload(IrAnalyze *ira, IrInstruction *source_instruction,
+ ZigType *result_type, IrInstruction *operand, IrInstruction *result_loc)
+{
+ IrInstructionErrWrapPayload *instruction = ir_build_instruction<IrInstructionErrWrapPayload>(
+ &ira->new_irb, source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = result_type;
+ instruction->operand = operand;
+ instruction->result_loc = result_loc;
- ir_ref_instruction(value, irb->current_basic_block);
+ ir_ref_instruction(operand, ira->new_irb.current_basic_block);
+ if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
return &instruction->base;
}
-static IrInstruction *ir_build_err_wrap_code(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
- IrInstructionErrWrapCode *instruction = ir_build_instruction<IrInstructionErrWrapCode>(irb, scope, source_node);
- instruction->value = value;
+static IrInstruction *ir_build_err_wrap_code(IrAnalyze *ira, IrInstruction *source_instruction,
+ ZigType *result_type, IrInstruction *operand, IrInstruction *result_loc)
+{
+ IrInstructionErrWrapCode *instruction = ir_build_instruction<IrInstructionErrWrapCode>(
+ &ira->new_irb, source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = result_type;
+ instruction->operand = operand;
+ instruction->result_loc = result_loc;
- ir_ref_instruction(value, irb->current_basic_block);
+ ir_ref_instruction(operand, ira->new_irb.current_basic_block);
+ if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
return &instruction->base;
}
@@ -1934,6 +2043,21 @@ static IrInstruction *ir_build_ref(IrBuilder *irb, Scope *scope, AstNode *source
return &instruction->base;
}
+static IrInstruction *ir_build_ref_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *result_type,
+ IrInstruction *operand, IrInstruction *result_loc)
+{
+ IrInstructionRefGen *instruction = ir_build_instruction<IrInstructionRefGen>(&ira->new_irb,
+ source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = result_type;
+ instruction->operand = operand;
+ instruction->result_loc = result_loc;
+
+ ir_ref_instruction(operand, ira->new_irb.current_basic_block);
+ if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_compile_err(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *msg) {
IrInstructionCompileErr *instruction = ir_build_instruction<IrInstructionCompileErr>(irb, scope, source_node);
instruction->msg = msg;
@@ -2011,8 +2135,7 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode
static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *type_value, IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
- IrInstruction *success_order_value, IrInstruction *failure_order_value,
- bool is_weak)
+ IrInstruction *success_order_value, IrInstruction *failure_order_value, bool is_weak, ResultLoc *result_loc)
{
IrInstructionCmpxchgSrc *instruction = ir_build_instruction<IrInstructionCmpxchgSrc>(irb, scope, source_node);
instruction->type_value = type_value;
@@ -2022,6 +2145,7 @@ static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode
instruction->success_order_value = success_order_value;
instruction->failure_order_value = failure_order_value;
instruction->is_weak = is_weak;
+ instruction->result_loc = result_loc;
ir_ref_instruction(type_value, irb->current_basic_block);
ir_ref_instruction(ptr, irb->current_basic_block);
@@ -2033,22 +2157,25 @@ static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode
return &instruction->base;
}
-static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source_instruction,
+static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *result_type,
IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
- AtomicOrder success_order, AtomicOrder failure_order, bool is_weak)
+ AtomicOrder success_order, AtomicOrder failure_order, bool is_weak, IrInstruction *result_loc)
{
IrInstructionCmpxchgGen *instruction = ir_build_instruction<IrInstructionCmpxchgGen>(&ira->new_irb,
source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = result_type;
instruction->ptr = ptr;
instruction->cmp_value = cmp_value;
instruction->new_value = new_value;
instruction->success_order = success_order;
instruction->failure_order = failure_order;
instruction->is_weak = is_weak;
+ instruction->result_loc = result_loc;
ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
ir_ref_instruction(cmp_value, ira->new_irb.current_basic_block);
ir_ref_instruction(new_value, ira->new_irb.current_basic_block);
+ if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
return &instruction->base;
}
@@ -2107,19 +2234,25 @@ static IrInstruction *ir_build_err_set_cast(IrBuilder *irb, Scope *scope, AstNod
return &instruction->base;
}
-static IrInstruction *ir_build_to_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target) {
+static IrInstruction *ir_build_to_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target,
+ ResultLoc *result_loc)
+{
IrInstructionToBytes *instruction = ir_build_instruction<IrInstructionToBytes>(irb, scope, source_node);
instruction->target = target;
+ instruction->result_loc = result_loc;
ir_ref_instruction(target, irb->current_basic_block);
return &instruction->base;
}
-static IrInstruction *ir_build_from_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_child_type, IrInstruction *target) {
+static IrInstruction *ir_build_from_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *dest_child_type, IrInstruction *target, ResultLoc *result_loc)
+{
IrInstructionFromBytes *instruction = ir_build_instruction<IrInstructionFromBytes>(irb, scope, source_node);
instruction->dest_child_type = dest_child_type;
instruction->target = target;
+ instruction->result_loc = result_loc;
ir_ref_instruction(dest_child_type, irb->current_basic_block);
ir_ref_instruction(target, irb->current_basic_block);
@@ -2221,14 +2354,15 @@ static IrInstruction *ir_build_memcpy(IrBuilder *irb, Scope *scope, AstNode *sou
return &instruction->base;
}
-static IrInstruction *ir_build_slice(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on)
+static IrInstruction *ir_build_slice_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on, ResultLoc *result_loc)
{
- IrInstructionSlice *instruction = ir_build_instruction<IrInstructionSlice>(irb, scope, source_node);
+ IrInstructionSliceSrc *instruction = ir_build_instruction<IrInstructionSliceSrc>(irb, scope, source_node);
instruction->ptr = ptr;
instruction->start = start;
instruction->end = end;
instruction->safety_check_on = safety_check_on;
+ instruction->result_loc = result_loc;
ir_ref_instruction(ptr, irb->current_basic_block);
ir_ref_instruction(start, irb->current_basic_block);
@@ -2237,6 +2371,26 @@ static IrInstruction *ir_build_slice(IrBuilder *irb, Scope *scope, AstNode *sour
return &instruction->base;
}
+static IrInstruction *ir_build_slice_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *slice_type,
+ IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on, IrInstruction *result_loc)
+{
+ IrInstructionSliceGen *instruction = ir_build_instruction<IrInstructionSliceGen>(
+ &ira->new_irb, source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = slice_type;
+ instruction->ptr = ptr;
+ instruction->start = start;
+ instruction->end = end;
+ instruction->safety_check_on = safety_check_on;
+ instruction->result_loc = result_loc;
+
+ ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
+ ir_ref_instruction(start, ira->new_irb.current_basic_block);
+ if (end) ir_ref_instruction(end, ira->new_irb.current_basic_block);
+ ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_member_count(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *container) {
IrInstructionMemberCount *instruction = ir_build_instruction<IrInstructionMemberCount>(irb, scope, source_node);
instruction->container = container;
@@ -2390,34 +2544,49 @@ static IrInstruction *ir_build_align_of(IrBuilder *irb, Scope *scope, AstNode *s
return &instruction->base;
}
-static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *value)
+static IrInstruction *ir_build_test_err_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *base_ptr, bool resolve_err_set)
{
- IrInstructionTestErr *instruction = ir_build_instruction<IrInstructionTestErr>(irb, scope, source_node);
- instruction->value = value;
+ IrInstructionTestErrSrc *instruction = ir_build_instruction<IrInstructionTestErrSrc>(irb, scope, source_node);
+ instruction->base_ptr = base_ptr;
+ instruction->resolve_err_set = resolve_err_set;
- ir_ref_instruction(value, irb->current_basic_block);
+ ir_ref_instruction(base_ptr, irb->current_basic_block);
return &instruction->base;
}
-static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node,
+static IrInstruction *ir_build_test_err_gen(IrAnalyze *ira, IrInstruction *source_instruction,
IrInstruction *err_union)
{
- IrInstructionUnwrapErrCode *instruction = ir_build_instruction<IrInstructionUnwrapErrCode>(irb, scope, source_node);
+ IrInstructionTestErrGen *instruction = ir_build_instruction<IrInstructionTestErrGen>(
+ &ira->new_irb, source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = ira->codegen->builtin_types.entry_bool;
instruction->err_union = err_union;
- ir_ref_instruction(err_union, irb->current_basic_block);
+ ir_ref_instruction(err_union, ira->new_irb.current_basic_block);
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *err_union_ptr)
+{
+ IrInstructionUnwrapErrCode *instruction = ir_build_instruction<IrInstructionUnwrapErrCode>(irb, scope, source_node);
+ instruction->err_union_ptr = err_union_ptr;
+
+ ir_ref_instruction(err_union_ptr, irb->current_basic_block);
return &instruction->base;
}
static IrInstruction *ir_build_unwrap_err_payload(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *value, bool safety_check_on)
+ IrInstruction *value, bool safety_check_on, bool initializing)
{
IrInstructionUnwrapErrPayload *instruction = ir_build_instruction<IrInstructionUnwrapErrPayload>(irb, scope, source_node);
instruction->value = value;
instruction->safety_check_on = safety_check_on;
+ instruction->initializing = initializing;
ir_ref_instruction(value, irb->current_basic_block);
@@ -2487,28 +2656,28 @@ static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *sourc
}
static IrInstruction *ir_build_load_ptr_gen(IrAnalyze *ira, IrInstruction *source_instruction,
- IrInstruction *ptr, ZigType *ty)
+ IrInstruction *ptr, ZigType *ty, IrInstruction *result_loc)
{
IrInstructionLoadPtrGen *instruction = ir_build_instruction<IrInstructionLoadPtrGen>(
&ira->new_irb, source_instruction->scope, source_instruction->source_node);
instruction->base.value.type = ty;
instruction->ptr = ptr;
+ instruction->result_loc = result_loc;
ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
+ if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
return &instruction->base;
}
-static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *dest_type, IrInstruction *value)
+static IrInstruction *ir_build_bit_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *operand, ResultLocBitCast *result_loc_bit_cast)
{
- IrInstructionBitCast *instruction = ir_build_instruction<IrInstructionBitCast>(
- irb, scope, source_node);
- instruction->dest_type = dest_type;
- instruction->value = value;
+ IrInstructionBitCastSrc *instruction = ir_build_instruction<IrInstructionBitCastSrc>(irb, scope, source_node);
+ instruction->operand = operand;
+ instruction->result_loc_bit_cast = result_loc_bit_cast;
- ir_ref_instruction(dest_type, irb->current_basic_block);
- ir_ref_instruction(value, irb->current_basic_block);
+ ir_ref_instruction(operand, irb->current_basic_block);
return &instruction->base;
}
@@ -2660,11 +2829,8 @@ static IrInstruction *ir_build_type_name(IrBuilder *irb, Scope *scope, AstNode *
return &instruction->base;
}
-static IrInstruction *ir_build_decl_ref(IrBuilder *irb, Scope *scope, AstNode *source_node,
- Tld *tld, LVal lval)
-{
- IrInstructionDeclRef *instruction = ir_build_instruction<IrInstructionDeclRef>(
- irb, scope, source_node);
+static IrInstruction *ir_build_decl_ref(IrBuilder *irb, Scope *scope, AstNode *source_node, Tld *tld, LVal lval) {
+ IrInstructionDeclRef *instruction = ir_build_instruction<IrInstructionDeclRef>(irb, scope, source_node);
instruction->tld = tld;
instruction->lval = lval;
@@ -2792,6 +2958,53 @@ static IrInstruction *ir_build_align_cast(IrBuilder *irb, Scope *scope, AstNode
return &instruction->base;
}
+static IrInstruction *ir_build_implicit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *dest_type, IrInstruction *target, ResultLoc *result_loc)
+{
+ IrInstructionImplicitCast *instruction = ir_build_instruction<IrInstructionImplicitCast>(irb, scope, source_node);
+ instruction->dest_type = dest_type;
+ instruction->target = target;
+ instruction->result_loc = result_loc;
+
+ ir_ref_instruction(dest_type, irb->current_basic_block);
+ ir_ref_instruction(target, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_resolve_result(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ ResultLoc *result_loc, IrInstruction *ty)
+{
+ IrInstructionResolveResult *instruction = ir_build_instruction<IrInstructionResolveResult>(irb, scope, source_node);
+ instruction->result_loc = result_loc;
+ instruction->ty = ty;
+
+ ir_ref_instruction(ty, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_reset_result(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ ResultLoc *result_loc)
+{
+ IrInstructionResetResult *instruction = ir_build_instruction<IrInstructionResetResult>(irb, scope, source_node);
+ instruction->result_loc = result_loc;
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_result_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ ResultLoc *result_loc, IrInstruction *result)
+{
+ IrInstructionResultPtr *instruction = ir_build_instruction<IrInstructionResultPtr>(irb, scope, source_node);
+ instruction->result_loc = result_loc;
+ instruction->result = result;
+
+ ir_ref_instruction(result, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_opaque_type(IrBuilder *irb, Scope *scope, AstNode *source_node) {
IrInstructionOpaqueType *instruction = ir_build_instruction<IrInstructionOpaqueType>(irb, scope, source_node);
@@ -3119,17 +3332,50 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope,
return &instruction->base;
}
+static IrInstruction *ir_build_union_init_named_field(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *union_type, IrInstruction *field_name, IrInstruction *field_result_loc, IrInstruction *result_loc)
+{
+ IrInstructionUnionInitNamedField *instruction = ir_build_instruction<IrInstructionUnionInitNamedField>(irb, scope, source_node);
+ instruction->union_type = union_type;
+ instruction->field_name = field_name;
+ instruction->field_result_loc = field_result_loc;
+ instruction->result_loc = result_loc;
+
+ ir_ref_instruction(union_type, irb->current_basic_block);
+ ir_ref_instruction(field_name, irb->current_basic_block);
+ ir_ref_instruction(field_result_loc, irb->current_basic_block);
+ if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
+
static IrInstruction *ir_build_vector_to_array(IrAnalyze *ira, IrInstruction *source_instruction,
- IrInstruction *vector, ZigType *result_type)
+ ZigType *result_type, IrInstruction *vector, IrInstruction *result_loc)
{
IrInstructionVectorToArray *instruction = ir_build_instruction<IrInstructionVectorToArray>(&ira->new_irb,
source_instruction->scope, source_instruction->source_node);
instruction->base.value.type = result_type;
instruction->vector = vector;
+ instruction->result_loc = result_loc;
ir_ref_instruction(vector, ira->new_irb.current_basic_block);
+ ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruction *source_instruction,
+ ZigType *result_type, IrInstruction *operand, IrInstruction *result_loc)
+{
+ IrInstructionPtrOfArrayToSlice *instruction = ir_build_instruction<IrInstructionPtrOfArrayToSlice>(&ira->new_irb,
+ source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = result_type;
+ instruction->operand = operand;
+ instruction->result_loc = result_loc;
- ir_add_alloca(ira, &instruction->base, result_type);
+ ir_ref_instruction(operand, ira->new_irb.current_basic_block);
+ ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
return &instruction->base;
}
@@ -3173,6 +3419,45 @@ static IrInstruction *ir_build_assert_non_null(IrAnalyze *ira, IrInstruction *so
return &instruction->base;
}
+static IrInstruction *ir_build_alloca_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *align, const char *name_hint, IrInstruction *is_comptime)
+{
+ IrInstructionAllocaSrc *instruction = ir_build_instruction<IrInstructionAllocaSrc>(irb, scope, source_node);
+ instruction->base.is_gen = true;
+ instruction->align = align;
+ instruction->name_hint = name_hint;
+ instruction->is_comptime = is_comptime;
+
+ if (align != nullptr) ir_ref_instruction(align, irb->current_basic_block);
+ if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
+static IrInstructionAllocaGen *ir_create_alloca_gen(IrAnalyze *ira, IrInstruction *source_instruction,
+ uint32_t align, const char *name_hint)
+{
+ IrInstructionAllocaGen *instruction = ir_create_instruction<IrInstructionAllocaGen>(&ira->new_irb,
+ source_instruction->scope, source_instruction->source_node);
+ instruction->align = align;
+ instruction->name_hint = name_hint;
+
+ return instruction;
+}
+
+static IrInstruction *ir_build_end_expr(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *value, ResultLoc *result_loc)
+{
+ IrInstructionEndExpr *instruction = ir_build_instruction<IrInstructionEndExpr>(irb, scope, source_node);
+ instruction->base.is_gen = true;
+ instruction->value = value;
+ instruction->result_loc = result_loc;
+
+ ir_ref_instruction(value, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
results[ReturnKindUnconditional] = 0;
results[ReturnKindError] = 0;
@@ -3273,6 +3558,7 @@ static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) {
}
static void ir_set_cursor_at_end_and_append_block(IrBuilder *irb, IrBasicBlock *basic_block) {
+ basic_block->index = irb->exec->basic_block_list.length;
irb->exec->basic_block_list.append(basic_block);
ir_set_cursor_at_end(irb, basic_block);
}
@@ -3361,7 +3647,7 @@ static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode
return ir_build_cond_br(irb, scope, node, is_canceled_bool, irb->exec->coro_final_cleanup_block, irb->exec->coro_early_final, is_comptime);
}
-static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
+static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) {
assert(node->type == NodeTypeReturnExpr);
ZigFn *fn_entry = exec_fn_entry(irb->exec);
@@ -3385,12 +3671,16 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
switch (node->data.return_expr.kind) {
case ReturnKindUnconditional:
{
+ ResultLocReturn *result_loc_ret = allocate<ResultLocReturn>(1);
+ result_loc_ret->base.id = ResultLocIdReturn;
+ ir_build_reset_result(irb, scope, node, &result_loc_ret->base);
+
IrInstruction *return_value;
if (expr_node) {
// Temporarily set this so that if we return a type it gets the name of the function
ZigFn *prev_name_fn = irb->exec->name_fn;
irb->exec->name_fn = exec_fn_entry(irb->exec);
- return_value = ir_gen_node(irb, expr_node, scope);
+ return_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, &result_loc_ret->base);
irb->exec->name_fn = prev_name_fn;
if (return_value == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
@@ -3408,7 +3698,9 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
ir_gen_defers_for_block(irb, scope, outer_scope, false);
}
- IrInstruction *is_err = ir_build_test_err(irb, scope, node, return_value);
+ IrInstruction *ret_ptr = ir_build_result_ptr(irb, scope, node, &result_loc_ret->base,
+ return_value);
+ IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, ret_ptr, false);
bool should_inline = ir_should_inline(irb->exec, scope);
IrInstruction *is_comptime;
@@ -3437,21 +3729,24 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block);
- return ir_gen_async_return(irb, scope, node, return_value, false);
+ IrInstruction *result = ir_gen_async_return(irb, scope, node, return_value, false);
+ result_loc_ret->base.source_instruction = result;
+ return result;
} else {
// generate unconditional defers
ir_gen_defers_for_block(irb, scope, outer_scope, false);
- return ir_gen_async_return(irb, scope, node, return_value, false);
+ IrInstruction *result = ir_gen_async_return(irb, scope, node, return_value, false);
+ result_loc_ret->base.source_instruction = result;
+ return result;
}
}
case ReturnKindError:
{
assert(expr_node);
- IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);
+ IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr);
if (err_union_ptr == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
- IrInstruction *err_union_val = ir_build_load_ptr(irb, scope, node, err_union_ptr);
- IrInstruction *is_err_val = ir_build_test_err(irb, scope, node, err_union_val);
+ IrInstruction *is_err_val = ir_build_test_err_src(irb, scope, node, err_union_ptr, true);
IrBasicBlock *return_block = ir_create_basic_block(irb, scope, "ErrRetReturn");
IrBasicBlock *continue_block = ir_create_basic_block(irb, scope, "ErrRetContinue");
@@ -3466,19 +3761,27 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
ir_set_cursor_at_end_and_append_block(irb, return_block);
if (!ir_gen_defers_for_block(irb, scope, outer_scope, true)) {
- IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);
+ IrInstruction *err_val_ptr = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);
+ IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr);
+
+ ResultLocReturn *result_loc_ret = allocate<ResultLocReturn>(1);
+ result_loc_ret->base.id = ResultLocIdReturn;
+ ir_build_reset_result(irb, scope, node, &result_loc_ret->base);
+ ir_build_end_expr(irb, scope, node, err_val, &result_loc_ret->base);
+
if (irb->codegen->have_err_ret_tracing && !should_inline) {
ir_build_save_err_ret_addr(irb, scope, node);
}
- ir_gen_async_return(irb, scope, node, err_val, false);
+ IrInstruction *ret_inst = ir_gen_async_return(irb, scope, node, err_val, false);
+ result_loc_ret->base.source_instruction = ret_inst;
}
ir_set_cursor_at_end_and_append_block(irb, continue_block);
- IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, false);
+ IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, false, false);
if (lval == LValPtr)
return unwrapped_ptr;
else
- return ir_build_load_ptr(irb, scope, node, unwrapped_ptr);
+ return ir_expr_wrap(irb, scope, ir_build_load_ptr(irb, scope, node, unwrapped_ptr), result_loc);
}
}
zig_unreachable();
@@ -3562,7 +3865,17 @@ static ZigVar *ir_create_var(IrBuilder *irb, AstNode *node, Scope *scope, Buf *n
return var;
}
-static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode *block_node) {
+static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) {
+ ResultLocPeer *result = allocate<ResultLocPeer>(1);
+ result->base.id = ResultLocIdPeer;
+ result->base.source_instruction = peer_parent->base.source_instruction;
+ result->parent = peer_parent;
+ return result;
+}
+
+static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode *block_node, LVal lval,
+ ResultLoc *result_loc)
+{
assert(block_node->type == NodeTypeBlock);
ZigList<IrInstruction *> incoming_values = {0};
@@ -3580,15 +3893,24 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
if (block_node->data.block.statements.length == 0) {
// {}
- return ir_build_const_void(irb, child_scope, block_node);
+ return ir_lval_wrap(irb, parent_scope, ir_build_const_void(irb, child_scope, block_node), lval, result_loc);
}
if (block_node->data.block.name != nullptr) {
+ scope_block->lval = lval;
scope_block->incoming_blocks = &incoming_blocks;
scope_block->incoming_values = &incoming_values;
scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd");
scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node,
ir_should_inline(irb->exec, parent_scope));
+
+ scope_block->peer_parent = allocate<ResultLocPeerParent>(1);
+ scope_block->peer_parent->base.id = ResultLocIdPeerParent;
+ scope_block->peer_parent->base.source_instruction = scope_block->is_comptime;
+ scope_block->peer_parent->end_bb = scope_block->end_block;
+ scope_block->peer_parent->is_comptime = scope_block->is_comptime;
+ scope_block->peer_parent->parent = result_loc;
+ ir_build_reset_result(irb, parent_scope, block_node, &scope_block->peer_parent->base);
}
bool is_continuation_unreachable = false;
@@ -3602,6 +3924,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
// keep the last noreturn statement value around in case we need to return it
noreturn_return_value = statement_value;
}
+ // This logic must be kept in sync with
+ // [STMT_EXPR_TEST_THING] <--- (search this token)
if (statement_node->type == NodeTypeDefer && statement_value != irb->codegen->invalid_instruction) {
// defer starts a new scope
child_scope = statement_node->data.defer.child_scope;
@@ -3622,21 +3946,41 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
return noreturn_return_value;
}
+ if (scope_block->peer_parent != nullptr && scope_block->peer_parent->peers.length != 0) {
+ scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block;
+ }
ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block);
- return ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);
+ IrInstruction *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length,
+ incoming_blocks.items, incoming_values.items, scope_block->peer_parent);
+ return ir_expr_wrap(irb, parent_scope, phi, result_loc);
} else {
incoming_blocks.append(irb->current_basic_block);
- incoming_values.append(ir_mark_gen(ir_build_const_void(irb, parent_scope, block_node)));
+ IrInstruction *else_expr_result = ir_mark_gen(ir_build_const_void(irb, parent_scope, block_node));
+
+ if (scope_block->peer_parent != nullptr) {
+ ResultLocPeer *peer_result = create_peer_result(scope_block->peer_parent);
+ scope_block->peer_parent->peers.append(peer_result);
+ ir_build_end_expr(irb, parent_scope, block_node, else_expr_result, &peer_result->base);
+
+ if (scope_block->peer_parent->peers.length != 0) {
+ scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block;
+ }
+ }
+
+ incoming_values.append(else_expr_result);
}
if (block_node->data.block.name != nullptr) {
ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);
ir_mark_gen(ir_build_br(irb, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime));
ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block);
- return ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);
+ IrInstruction *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length,
+ incoming_blocks.items, incoming_values.items, scope_block->peer_parent);
+ return ir_expr_wrap(irb, parent_scope, phi, result_loc);
} else {
ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);
- return ir_mark_gen(ir_mark_gen(ir_build_const_void(irb, child_scope, block_node)));
+ IrInstruction *void_inst = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node));
+ return ir_lval_wrap(irb, parent_scope, void_inst, lval, result_loc);
}
}
@@ -3656,7 +4000,7 @@ static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, Scope *scope, AstNode *no
}
static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node) {
- IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr);
+ IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr);
IrInstruction *rvalue = ir_gen_node(irb, node->data.bin_op_expr.op2, scope);
if (lvalue == irb->codegen->invalid_instruction || rvalue == irb->codegen->invalid_instruction)
@@ -3667,7 +4011,7 @@ static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node)
}
static IrInstruction *ir_gen_assign_op(IrBuilder *irb, Scope *scope, AstNode *node, IrBinOp op_id) {
- IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr);
+ IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr);
if (lvalue == irb->codegen->invalid_instruction)
return lvalue;
IrInstruction *op1 = ir_build_load_ptr(irb, scope, node->data.bin_op_expr.op1, lvalue);
@@ -3718,7 +4062,7 @@ static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node
incoming_blocks[0] = post_val1_block;
incoming_blocks[1] = post_val2_block;
- return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
+ return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr);
}
static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *node) {
@@ -3760,16 +4104,51 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod
incoming_blocks[0] = post_val1_block;
incoming_blocks[1] = post_val2_block;
- return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
+ return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr);
}
-static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
+static ResultLocPeerParent *ir_build_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst,
+ IrBasicBlock *end_block, ResultLoc *parent, IrInstruction *is_comptime)
+{
+ ResultLocPeerParent *peer_parent = allocate<ResultLocPeerParent>(1);
+ peer_parent->base.id = ResultLocIdPeerParent;
+ peer_parent->base.source_instruction = cond_br_inst;
+ peer_parent->end_bb = end_block;
+ peer_parent->is_comptime = is_comptime;
+ peer_parent->parent = parent;
+
+ IrInstruction *popped_inst = irb->current_basic_block->instruction_list.pop();
+ ir_assert(popped_inst == cond_br_inst, cond_br_inst);
+
+ ir_build_reset_result(irb, cond_br_inst->scope, cond_br_inst->source_node, &peer_parent->base);
+ irb->current_basic_block->instruction_list.append(popped_inst);
+
+ return peer_parent;
+}
+
+static ResultLocPeerParent *ir_build_binary_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst,
+ IrBasicBlock *else_block, IrBasicBlock *end_block, ResultLoc *parent, IrInstruction *is_comptime)
+{
+ ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, parent, is_comptime);
+
+ peer_parent->peers.append(create_peer_result(peer_parent));
+ peer_parent->peers.last()->next_bb = else_block;
+
+ peer_parent->peers.append(create_peer_result(peer_parent));
+ peer_parent->peers.last()->next_bb = end_block;
+
+ return peer_parent;
+}
+
+static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval,
+ ResultLoc *result_loc)
+{
assert(node->type == NodeTypeBinOpExpr);
AstNode *op1_node = node->data.bin_op_expr.op1;
AstNode *op2_node = node->data.bin_op_expr.op2;
- IrInstruction *maybe_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr);
+ IrInstruction *maybe_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr, nullptr);
if (maybe_ptr == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
@@ -3786,10 +4165,14 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode
IrBasicBlock *ok_block = ir_create_basic_block(irb, parent_scope, "OptionalNonNull");
IrBasicBlock *null_block = ir_create_basic_block(irb, parent_scope, "OptionalNull");
IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "OptionalEnd");
- ir_build_cond_br(irb, parent_scope, node, is_non_null, ok_block, null_block, is_comptime);
+ IrInstruction *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_non_null, ok_block, null_block, is_comptime);
+
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, ok_block, end_block,
+ result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, null_block);
- IrInstruction *null_result = ir_gen_node(irb, op2_node, parent_scope);
+ IrInstruction *null_result = ir_gen_node_extra(irb, op2_node, parent_scope, LValNone,
+ &peer_parent->peers.at(0)->base);
if (null_result == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
IrBasicBlock *after_null_block = irb->current_basic_block;
@@ -3797,8 +4180,9 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode
ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));
ir_set_cursor_at_end_and_append_block(irb, ok_block);
- IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false);
+ IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false, false);
IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
+ ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base);
IrBasicBlock *after_ok_block = irb->current_basic_block;
ir_build_br(irb, parent_scope, node, end_block, is_comptime);
@@ -3809,7 +4193,8 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode
IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);
incoming_blocks[0] = after_null_block;
incoming_blocks[1] = after_ok_block;
- return ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values);
+ IrInstruction *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent);
+ return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc);
}
static IrInstruction *ir_gen_error_union(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
@@ -3829,7 +4214,7 @@ static IrInstruction *ir_gen_error_union(IrBuilder *irb, Scope *parent_scope, As
return ir_build_error_union(irb, parent_scope, node, err_set, payload);
}
-static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) {
+static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) {
assert(node->type == NodeTypeBinOpExpr);
BinOpType bin_op_type = node->data.bin_op_expr.bin_op;
@@ -3837,87 +4222,87 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node)
case BinOpTypeInvalid:
zig_unreachable();
case BinOpTypeAssign:
- return ir_gen_assign(irb, scope, node);
+ return ir_lval_wrap(irb, scope, ir_gen_assign(irb, scope, node), lval, result_loc);
case BinOpTypeAssignTimes:
- return ir_gen_assign_op(irb, scope, node, IrBinOpMult);
+ return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpMult), lval, result_loc);
case BinOpTypeAssignTimesWrap:
- return ir_gen_assign_op(irb, scope, node, IrBinOpMultWrap);
+ return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpMultWrap), lval, result_loc);
case BinOpTypeAssignDiv:
- return ir_gen_assign_op(irb, scope, node, IrBinOpDivUnspecified);
+ return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpDivUnspecified), lval, result_loc);
case BinOpTypeAssignMod:
- return ir_gen_assign_op(irb, scope, node, IrBinOpRemUnspecified);
+ return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpRemUnspecified), lval, result_loc);
case BinOpTypeAssignPlus:
- return ir_gen_assign_op(irb, scope, node, IrBinOpAdd);
+ return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpAdd), lval, result_loc);
case BinOpTypeAssignPlusWrap:
- return ir_gen_assign_op(irb, scope, node, IrBinOpAddWrap);
+ return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpAddWrap), lval, result_loc);
case BinOpTypeAssignMinus:
- return ir_gen_assign_op(irb, scope, node, IrBinOpSub);
+ return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpSub), lval, result_loc);
case BinOpTypeAssignMinusWrap:
- return ir_gen_assign_op(irb, scope, node, IrBinOpSubWrap);
+ return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpSubWrap), lval, result_loc);
case BinOpTypeAssignBitShiftLeft:
- return ir_gen_assign_op(irb, scope, node, IrBinOpBitShiftLeftLossy);
+ return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc);
case BinOpTypeAssignBitShiftRight:
- return ir_gen_assign_op(irb, scope, node, IrBinOpBitShiftRightLossy);
+ return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc);
case BinOpTypeAssignBitAnd:
- return ir_gen_assign_op(irb, scope, node, IrBinOpBinAnd);
+ return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBinAnd), lval, result_loc);
case BinOpTypeAssignBitXor:
- return ir_gen_assign_op(irb, scope, node, IrBinOpBinXor);
+ return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBinXor), lval, result_loc);
case BinOpTypeAssignBitOr:
- return ir_gen_assign_op(irb, scope, node, IrBinOpBinOr);
+ return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBinOr), lval, result_loc);
case BinOpTypeAssignMergeErrorSets:
- return ir_gen_assign_op(irb, scope, node, IrBinOpMergeErrorSets);
+ return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpMergeErrorSets), lval, result_loc);
case BinOpTypeBoolOr:
- return ir_gen_bool_or(irb, scope, node);
+ return ir_lval_wrap(irb, scope, ir_gen_bool_or(irb, scope, node), lval, result_loc);
case BinOpTypeBoolAnd:
- return ir_gen_bool_and(irb, scope, node);
+ return ir_lval_wrap(irb, scope, ir_gen_bool_and(irb, scope, node), lval, result_loc);
case BinOpTypeCmpEq:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpEq);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpEq), lval, result_loc);
case BinOpTypeCmpNotEq:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpNotEq);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpNotEq), lval, result_loc);
case BinOpTypeCmpLessThan:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpLessThan);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpLessThan), lval, result_loc);
case BinOpTypeCmpGreaterThan:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpGreaterThan);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpGreaterThan), lval, result_loc);
case BinOpTypeCmpLessOrEq:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpLessOrEq);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpLessOrEq), lval, result_loc);
case BinOpTypeCmpGreaterOrEq:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpGreaterOrEq);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpGreaterOrEq), lval, result_loc);
case BinOpTypeBinOr:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpBinOr);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBinOr), lval, result_loc);
case BinOpTypeBinXor:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpBinXor);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBinXor), lval, result_loc);
case BinOpTypeBinAnd:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpBinAnd);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBinAnd), lval, result_loc);
case BinOpTypeBitShiftLeft:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpBitShiftLeftLossy);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc);
case BinOpTypeBitShiftRight:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpBitShiftRightLossy);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc);
case BinOpTypeAdd:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpAdd);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpAdd), lval, result_loc);
case BinOpTypeAddWrap:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpAddWrap);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpAddWrap), lval, result_loc);
case BinOpTypeSub:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpSub);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpSub), lval, result_loc);
case BinOpTypeSubWrap:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpSubWrap);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpSubWrap), lval, result_loc);
case BinOpTypeMult:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpMult);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpMult), lval, result_loc);
case BinOpTypeMultWrap:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpMultWrap);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpMultWrap), lval, result_loc);
case BinOpTypeDiv:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpDivUnspecified);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpDivUnspecified), lval, result_loc);
case BinOpTypeMod:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpRemUnspecified);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpRemUnspecified), lval, result_loc);
case BinOpTypeArrayCat:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayCat);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayCat), lval, result_loc);
case BinOpTypeArrayMult:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayMult);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayMult), lval, result_loc);
case BinOpTypeMergeErrorSets:
- return ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets), lval, result_loc);
case BinOpTypeUnwrapOptional:
- return ir_gen_orelse(irb, scope, node);
+ return ir_gen_orelse(irb, scope, node, lval, result_loc);
case BinOpTypeErrorUnion:
- return ir_gen_error_union(irb, scope, node);
+ return ir_lval_wrap(irb, scope, ir_gen_error_union(irb, scope, node), lval, result_loc);
}
zig_unreachable();
}
@@ -3962,12 +4347,12 @@ static void populate_invalid_variable_in_scope(CodeGen *g, Scope *scope, AstNode
TldVar *tld_var = allocate<TldVar>(1);
init_tld(&tld_var->base, TldIdVar, var_name, VisibModPub, node, &scope_decls->base);
tld_var->base.resolution = TldResolutionInvalid;
- tld_var->var = add_variable(g, node, &scope_decls->base, var_name, false,
+ tld_var->var = add_variable(g, node, &scope_decls->base, var_name, false,
&g->invalid_instruction->value, &tld_var->base, g->builtin_types.entry_invalid);
scope_decls->decl_table.put(var_name, &tld_var->base);
}
-static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
+static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) {
Error err;
assert(node->type == NodeTypeSymbol);
@@ -4001,7 +4386,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
if (lval == LValPtr) {
return ir_build_ref(irb, scope, node, value, false, false);
} else {
- return value;
+ return ir_expr_wrap(irb, scope, value, result_loc);
}
}
@@ -4009,15 +4394,22 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
ZigVar *var = find_variable(irb->codegen, scope, variable_name, &crossed_fndef_scope);
if (var) {
IrInstruction *var_ptr = ir_build_var_ptr_x(irb, scope, node, var, crossed_fndef_scope);
- if (lval == LValPtr)
+ if (lval == LValPtr) {
return var_ptr;
- else
- return ir_build_load_ptr(irb, scope, node, var_ptr);
+ } else {
+ return ir_expr_wrap(irb, scope, ir_build_load_ptr(irb, scope, node, var_ptr), result_loc);
+ }
}
Tld *tld = find_decl(irb->codegen, scope, variable_name);
- if (tld)
- return ir_build_decl_ref(irb, scope, node, tld, lval);
+ if (tld) {
+ IrInstruction *decl_ref = ir_build_decl_ref(irb, scope, node, tld, lval);
+ if (lval == LValPtr) {
+ return decl_ref;
+ } else {
+ return ir_expr_wrap(irb, scope, decl_ref, result_loc);
+ }
+ }
if (get_container_scope(node->owner)->any_imports_failed) {
// skip the error message since we had a failing import in this file
@@ -4028,11 +4420,13 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
return ir_build_undeclared_identifier(irb, scope, node, variable_name);
}
-static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
+static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
+ ResultLoc *result_loc)
+{
assert(node->type == NodeTypeArrayAccessExpr);
AstNode *array_ref_node = node->data.array_access_expr.array_ref_expr;
- IrInstruction *array_ref_instruction = ir_gen_node_extra(irb, array_ref_node, scope, LValPtr);
+ IrInstruction *array_ref_instruction = ir_gen_node_extra(irb, array_ref_node, scope, LValPtr, nullptr);
if (array_ref_instruction == irb->codegen->invalid_instruction)
return array_ref_instruction;
@@ -4042,11 +4436,12 @@ static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode
return subscript_instruction;
IrInstruction *ptr_instruction = ir_build_elem_ptr(irb, scope, node, array_ref_instruction,
- subscript_instruction, true, PtrLenSingle);
+ subscript_instruction, true, PtrLenSingle, nullptr);
if (lval == LValPtr)
return ptr_instruction;
- return ir_build_load_ptr(irb, scope, node, ptr_instruction);
+ IrInstruction *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction);
+ return ir_expr_wrap(irb, scope, load_ptr, result_loc);
}
static IrInstruction *ir_gen_field_access(IrBuilder *irb, Scope *scope, AstNode *node) {
@@ -4055,11 +4450,11 @@ static IrInstruction *ir_gen_field_access(IrBuilder *irb, Scope *scope, AstNode
AstNode *container_ref_node = node->data.field_access_expr.struct_expr;
Buf *field_name = node->data.field_access_expr.field_name;
- IrInstruction *container_ref_instruction = ir_gen_node_extra(irb, container_ref_node, scope, LValPtr);
+ IrInstruction *container_ref_instruction = ir_gen_node_extra(irb, container_ref_node, scope, LValPtr, nullptr);
if (container_ref_instruction == irb->codegen->invalid_instruction)
return container_ref_instruction;
- return ir_build_field_ptr(irb, scope, node, container_ref_instruction, field_name);
+ return ir_build_field_ptr(irb, scope, node, container_ref_instruction, field_name, false);
}
static IrInstruction *ir_gen_overflow_op(IrBuilder *irb, Scope *scope, AstNode *node, IrOverflowOp op) {
@@ -4132,7 +4527,9 @@ static IrInstruction *ir_gen_this(IrBuilder *irb, Scope *orig_scope, AstNode *no
zig_unreachable();
}
-static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
+static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
+ ResultLoc *result_loc)
+{
assert(node->type == NodeTypeFnCallExpr);
AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
@@ -4168,7 +4565,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg;
IrInstruction *type_of = ir_build_typeof(irb, scope, node, arg);
- return ir_lval_wrap(irb, scope, type_of, lval);
+ return ir_lval_wrap(irb, scope, type_of, lval, result_loc);
}
case BuiltinFnIdSetCold:
{
@@ -4178,7 +4575,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *set_cold = ir_build_set_cold(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, set_cold, lval);
+ return ir_lval_wrap(irb, scope, set_cold, lval, result_loc);
}
case BuiltinFnIdSetRuntimeSafety:
{
@@ -4188,7 +4585,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *set_safety = ir_build_set_runtime_safety(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, set_safety, lval);
+ return ir_lval_wrap(irb, scope, set_safety, lval, result_loc);
}
case BuiltinFnIdSetFloatMode:
{
@@ -4198,7 +4595,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *set_float_mode = ir_build_set_float_mode(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, set_float_mode, lval);
+ return ir_lval_wrap(irb, scope, set_float_mode, lval, result_loc);
}
case BuiltinFnIdSizeof:
{
@@ -4208,7 +4605,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *size_of = ir_build_size_of(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, size_of, lval);
+ return ir_lval_wrap(irb, scope, size_of, lval, result_loc);
}
case BuiltinFnIdImport:
{
@@ -4218,12 +4615,12 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *import = ir_build_import(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, import, lval);
+ return ir_lval_wrap(irb, scope, import, lval, result_loc);
}
case BuiltinFnIdCImport:
{
IrInstruction *c_import = ir_build_c_import(irb, scope, node);
- return ir_lval_wrap(irb, scope, c_import, lval);
+ return ir_lval_wrap(irb, scope, c_import, lval, result_loc);
}
case BuiltinFnIdCInclude:
{
@@ -4238,7 +4635,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
}
IrInstruction *c_include = ir_build_c_include(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, c_include, lval);
+ return ir_lval_wrap(irb, scope, c_include, lval, result_loc);
}
case BuiltinFnIdCDefine:
{
@@ -4258,7 +4655,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
}
IrInstruction *c_define = ir_build_c_define(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, c_define, lval);
+ return ir_lval_wrap(irb, scope, c_define, lval, result_loc);
}
case BuiltinFnIdCUndef:
{
@@ -4273,7 +4670,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
}
IrInstruction *c_undef = ir_build_c_undef(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, c_undef, lval);
+ return ir_lval_wrap(irb, scope, c_undef, lval, result_loc);
}
case BuiltinFnIdCompileErr:
{
@@ -4283,7 +4680,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *compile_err = ir_build_compile_err(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, compile_err, lval);
+ return ir_lval_wrap(irb, scope, compile_err, lval, result_loc);
}
case BuiltinFnIdCompileLog:
{
@@ -4297,7 +4694,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
}
IrInstruction *compile_log = ir_build_compile_log(irb, scope, node, actual_param_count, args);
- return ir_lval_wrap(irb, scope, compile_log, lval);
+ return ir_lval_wrap(irb, scope, compile_log, lval, result_loc);
}
case BuiltinFnIdErrName:
{
@@ -4307,7 +4704,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *err_name = ir_build_err_name(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, err_name, lval);
+ return ir_lval_wrap(irb, scope, err_name, lval, result_loc);
}
case BuiltinFnIdEmbedFile:
{
@@ -4317,7 +4714,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *embed_file = ir_build_embed_file(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, embed_file, lval);
+ return ir_lval_wrap(irb, scope, embed_file, lval, result_loc);
}
case BuiltinFnIdCmpxchgWeak:
case BuiltinFnIdCmpxchgStrong:
@@ -4353,8 +4750,9 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg5_value;
IrInstruction *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value,
- arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak));
- return ir_lval_wrap(irb, scope, cmpxchg, lval);
+ arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak),
+ result_loc);
+ return ir_lval_wrap(irb, scope, cmpxchg, lval, result_loc);
}
case BuiltinFnIdFence:
{
@@ -4364,7 +4762,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *fence = ir_build_fence(irb, scope, node, arg0_value, AtomicOrderUnordered);
- return ir_lval_wrap(irb, scope, fence, lval);
+ return ir_lval_wrap(irb, scope, fence, lval, result_loc);
}
case BuiltinFnIdDivExact:
{
@@ -4379,7 +4777,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivExact, arg0_value, arg1_value, true);
- return ir_lval_wrap(irb, scope, bin_op, lval);
+ return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
}
case BuiltinFnIdDivTrunc:
{
@@ -4394,7 +4792,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivTrunc, arg0_value, arg1_value, true);
- return ir_lval_wrap(irb, scope, bin_op, lval);
+ return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
}
case BuiltinFnIdDivFloor:
{
@@ -4409,7 +4807,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivFloor, arg0_value, arg1_value, true);
- return ir_lval_wrap(irb, scope, bin_op, lval);
+ return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
}
case BuiltinFnIdRem:
{
@@ -4424,7 +4822,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemRem, arg0_value, arg1_value, true);
- return ir_lval_wrap(irb, scope, bin_op, lval);
+ return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
}
case BuiltinFnIdMod:
{
@@ -4439,7 +4837,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemMod, arg0_value, arg1_value, true);
- return ir_lval_wrap(irb, scope, bin_op, lval);
+ return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
}
case BuiltinFnIdSqrt:
case BuiltinFnIdSin:
@@ -4467,7 +4865,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *ir_sqrt = ir_build_float_op(irb, scope, node, arg0_value, arg1_value, builtin_fn->id);
- return ir_lval_wrap(irb, scope, ir_sqrt, lval);
+ return ir_lval_wrap(irb, scope, ir_sqrt, lval, result_loc);
}
case BuiltinFnIdTruncate:
{
@@ -4482,7 +4880,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *truncate = ir_build_truncate(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, truncate, lval);
+ return ir_lval_wrap(irb, scope, truncate, lval, result_loc);
}
case BuiltinFnIdIntCast:
{
@@ -4497,7 +4895,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *result = ir_build_int_cast(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdFloatCast:
{
@@ -4512,7 +4910,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *result = ir_build_float_cast(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdErrSetCast:
{
@@ -4527,7 +4925,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *result = ir_build_err_set_cast(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdFromBytes:
{
@@ -4541,8 +4939,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
if (arg1_value == irb->codegen->invalid_instruction)
return arg1_value;
- IrInstruction *result = ir_build_from_bytes(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ IrInstruction *result = ir_build_from_bytes(irb, scope, node, arg0_value, arg1_value, result_loc);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdToBytes:
{
@@ -4551,8 +4949,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
if (arg0_value == irb->codegen->invalid_instruction)
return arg0_value;
- IrInstruction *result = ir_build_to_bytes(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ IrInstruction *result = ir_build_to_bytes(irb, scope, node, arg0_value, result_loc);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdIntToFloat:
{
@@ -4567,7 +4965,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *result = ir_build_int_to_float(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdFloatToInt:
{
@@ -4582,7 +4980,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *result = ir_build_float_to_int(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdErrToInt:
{
@@ -4592,7 +4990,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *result = ir_build_err_to_int(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdIntToErr:
{
@@ -4602,7 +5000,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *result = ir_build_int_to_err(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdBoolToInt:
{
@@ -4612,7 +5010,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *result = ir_build_bool_to_int(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdIntType:
{
@@ -4627,7 +5025,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *int_type = ir_build_int_type(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, int_type, lval);
+ return ir_lval_wrap(irb, scope, int_type, lval, result_loc);
}
case BuiltinFnIdVectorType:
{
@@ -4642,7 +5040,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *vector_type = ir_build_vector_type(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, vector_type, lval);
+ return ir_lval_wrap(irb, scope, vector_type, lval, result_loc);
}
case BuiltinFnIdMemcpy:
{
@@ -4662,7 +5060,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg2_value;
IrInstruction *ir_memcpy = ir_build_memcpy(irb, scope, node, arg0_value, arg1_value, arg2_value);
- return ir_lval_wrap(irb, scope, ir_memcpy, lval);
+ return ir_lval_wrap(irb, scope, ir_memcpy, lval, result_loc);
}
case BuiltinFnIdMemset:
{
@@ -4682,7 +5080,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg2_value;
IrInstruction *ir_memset = ir_build_memset(irb, scope, node, arg0_value, arg1_value, arg2_value);
- return ir_lval_wrap(irb, scope, ir_memset, lval);
+ return ir_lval_wrap(irb, scope, ir_memset, lval, result_loc);
}
case BuiltinFnIdMemberCount:
{
@@ -4692,7 +5090,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *member_count = ir_build_member_count(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, member_count, lval);
+ return ir_lval_wrap(irb, scope, member_count, lval, result_loc);
}
case BuiltinFnIdMemberType:
{
@@ -4708,7 +5106,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
IrInstruction *member_type = ir_build_member_type(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, member_type, lval);
+ return ir_lval_wrap(irb, scope, member_type, lval, result_loc);
}
case BuiltinFnIdMemberName:
{
@@ -4724,12 +5122,12 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
IrInstruction *member_name = ir_build_member_name(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, member_name, lval);
+ return ir_lval_wrap(irb, scope, member_name, lval, result_loc);
}
case BuiltinFnIdField:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
- IrInstruction *arg0_value = ir_gen_node_extra(irb, arg0_node, scope, LValPtr);
+ IrInstruction *arg0_value = ir_gen_node_extra(irb, arg0_node, scope, LValPtr, nullptr);
if (arg0_value == irb->codegen->invalid_instruction)
return arg0_value;
@@ -4738,12 +5136,29 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
if (arg1_value == irb->codegen->invalid_instruction)
return arg1_value;
- IrInstruction *ptr_instruction = ir_build_field_ptr_instruction(irb, scope, node, arg0_value, arg1_value);
+ IrInstruction *ptr_instruction = ir_build_field_ptr_instruction(irb, scope, node,
+ arg0_value, arg1_value, false);
if (lval == LValPtr)
return ptr_instruction;
- return ir_build_load_ptr(irb, scope, node, ptr_instruction);
+ IrInstruction *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction);
+ return ir_expr_wrap(irb, scope, load_ptr, result_loc);
+ }
+ case BuiltinFnIdHasField:
+ {
+ AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
+ IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
+ if (arg0_value == irb->codegen->invalid_instruction)
+ return arg0_value;
+
+ AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
+ IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
+ if (arg1_value == irb->codegen->invalid_instruction)
+ return arg1_value;
+
+ IrInstruction *type_info = ir_build_has_field(irb, scope, node, arg0_value, arg1_value);
+ return ir_lval_wrap(irb, scope, type_info, lval, result_loc);
}
case BuiltinFnIdTypeInfo:
{
@@ -4753,14 +5168,14 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *type_info = ir_build_type_info(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, type_info, lval);
+ return ir_lval_wrap(irb, scope, type_info, lval, result_loc);
}
case BuiltinFnIdBreakpoint:
- return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval, result_loc);
case BuiltinFnIdReturnAddress:
- return ir_lval_wrap(irb, scope, ir_build_return_address(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_build_return_address(irb, scope, node), lval, result_loc);
case BuiltinFnIdFrameAddress:
- return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval, result_loc);
case BuiltinFnIdHandle:
if (!irb->exec->fn_entry) {
add_node_error(irb->codegen, node, buf_sprintf("@handle() called outside of function definition"));
@@ -4770,7 +5185,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
add_node_error(irb->codegen, node, buf_sprintf("@handle() in non-async function"));
return irb->codegen->invalid_instruction;
}
- return ir_lval_wrap(irb, scope, ir_build_handle(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_build_handle(irb, scope, node), lval, result_loc);
case BuiltinFnIdAlignOf:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -4779,18 +5194,18 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *align_of = ir_build_align_of(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, align_of, lval);
+ return ir_lval_wrap(irb, scope, align_of, lval, result_loc);
}
case BuiltinFnIdAddWithOverflow:
- return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpAdd), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpAdd), lval, result_loc);
case BuiltinFnIdSubWithOverflow:
- return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpSub), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpSub), lval, result_loc);
case BuiltinFnIdMulWithOverflow:
- return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpMul), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpMul), lval, result_loc);
case BuiltinFnIdShlWithOverflow:
- return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpShl), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpShl), lval, result_loc);
case BuiltinFnIdMulAdd:
- return ir_lval_wrap(irb, scope, ir_gen_mul_add(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_mul_add(irb, scope, node), lval, result_loc);
case BuiltinFnIdTypeName:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -4799,7 +5214,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *type_name = ir_build_type_name(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, type_name, lval);
+ return ir_lval_wrap(irb, scope, type_name, lval, result_loc);
}
case BuiltinFnIdPanic:
{
@@ -4809,7 +5224,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *panic = ir_build_panic(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, panic, lval);
+ return ir_lval_wrap(irb, scope, panic, lval, result_loc);
}
case BuiltinFnIdPtrCast:
{
@@ -4824,22 +5239,31 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value, true);
- return ir_lval_wrap(irb, scope, ptr_cast, lval);
+ return ir_lval_wrap(irb, scope, ptr_cast, lval, result_loc);
}
case BuiltinFnIdBitCast:
{
- AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
- IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
- if (arg0_value == irb->codegen->invalid_instruction)
- return arg0_value;
+ AstNode *dest_type_node = node->data.fn_call_expr.params.at(0);
+ IrInstruction *dest_type = ir_gen_node(irb, dest_type_node, scope);
+ if (dest_type == irb->codegen->invalid_instruction)
+ return dest_type;
+
+ ResultLocBitCast *result_loc_bit_cast = allocate<ResultLocBitCast>(1);
+ result_loc_bit_cast->base.id = ResultLocIdBitCast;
+ result_loc_bit_cast->base.source_instruction = dest_type;
+ ir_ref_instruction(dest_type, irb->current_basic_block);
+ result_loc_bit_cast->parent = result_loc;
+
+ ir_build_reset_result(irb, scope, node, &result_loc_bit_cast->base);
AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
- IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
+ IrInstruction *arg1_value = ir_gen_node_extra(irb, arg1_node, scope, LValNone,
+ &result_loc_bit_cast->base);
if (arg1_value == irb->codegen->invalid_instruction)
return arg1_value;
- IrInstruction *bit_cast = ir_build_bit_cast(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, bit_cast, lval);
+ IrInstruction *bitcast = ir_build_bit_cast_src(irb, scope, arg1_node, arg1_value, result_loc_bit_cast);
+ return ir_lval_wrap(irb, scope, bitcast, lval, result_loc);
}
case BuiltinFnIdIntToPtr:
{
@@ -4854,7 +5278,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *int_to_ptr = ir_build_int_to_ptr(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, int_to_ptr, lval);
+ return ir_lval_wrap(irb, scope, int_to_ptr, lval, result_loc);
}
case BuiltinFnIdPtrToInt:
{
@@ -4864,7 +5288,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *ptr_to_int = ir_build_ptr_to_int(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, ptr_to_int, lval);
+ return ir_lval_wrap(irb, scope, ptr_to_int, lval, result_loc);
}
case BuiltinFnIdTagName:
{
@@ -4875,7 +5299,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
IrInstruction *actual_tag = ir_build_union_tag(irb, scope, node, arg0_value);
IrInstruction *tag_name = ir_build_tag_name(irb, scope, node, actual_tag);
- return ir_lval_wrap(irb, scope, tag_name, lval);
+ return ir_lval_wrap(irb, scope, tag_name, lval, result_loc);
}
case BuiltinFnIdTagType:
{
@@ -4885,7 +5309,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *tag_type = ir_build_tag_type(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, tag_type, lval);
+ return ir_lval_wrap(irb, scope, tag_type, lval, result_loc);
}
case BuiltinFnIdFieldParentPtr:
{
@@ -4905,7 +5329,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg2_value;
IrInstruction *field_parent_ptr = ir_build_field_parent_ptr(irb, scope, node, arg0_value, arg1_value, arg2_value, nullptr);
- return ir_lval_wrap(irb, scope, field_parent_ptr, lval);
+ return ir_lval_wrap(irb, scope, field_parent_ptr, lval, result_loc);
}
case BuiltinFnIdByteOffsetOf:
{
@@ -4920,7 +5344,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *offset_of = ir_build_byte_offset_of(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, offset_of, lval);
+ return ir_lval_wrap(irb, scope, offset_of, lval, result_loc);
}
case BuiltinFnIdBitOffsetOf:
{
@@ -4935,7 +5359,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *offset_of = ir_build_bit_offset_of(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, offset_of, lval);
+ return ir_lval_wrap(irb, scope, offset_of, lval, result_loc);
}
case BuiltinFnIdInlineCall:
case BuiltinFnIdNoInlineCall:
@@ -4961,8 +5385,9 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
}
FnInline fn_inline = (builtin_fn->id == BuiltinFnIdInlineCall) ? FnInlineAlways : FnInlineNever;
- IrInstruction *call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, fn_inline, false, nullptr, nullptr);
- return ir_lval_wrap(irb, scope, call, lval);
+ IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,
+ fn_inline, false, nullptr, nullptr, result_loc);
+ return ir_lval_wrap(irb, scope, call, lval, result_loc);
}
case BuiltinFnIdNewStackCall:
{
@@ -4991,8 +5416,9 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return args[i];
}
- IrInstruction *call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, false, nullptr, new_stack);
- return ir_lval_wrap(irb, scope, call, lval);
+ IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,
+ FnInlineAuto, false, nullptr, new_stack, result_loc);
+ return ir_lval_wrap(irb, scope, call, lval, result_loc);
}
case BuiltinFnIdTypeId:
{
@@ -5002,7 +5428,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *type_id = ir_build_type_id(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, type_id, lval);
+ return ir_lval_wrap(irb, scope, type_id, lval, result_loc);
}
case BuiltinFnIdShlExact:
{
@@ -5017,7 +5443,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftLeftExact, arg0_value, arg1_value, true);
- return ir_lval_wrap(irb, scope, bin_op, lval);
+ return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
}
case BuiltinFnIdShrExact:
{
@@ -5032,7 +5458,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftRightExact, arg0_value, arg1_value, true);
- return ir_lval_wrap(irb, scope, bin_op, lval);
+ return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
}
case BuiltinFnIdSetEvalBranchQuota:
{
@@ -5042,7 +5468,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *set_eval_branch_quota = ir_build_set_eval_branch_quota(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, set_eval_branch_quota, lval);
+ return ir_lval_wrap(irb, scope, set_eval_branch_quota, lval, result_loc);
}
case BuiltinFnIdAlignCast:
{
@@ -5057,17 +5483,17 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *align_cast = ir_build_align_cast(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, align_cast, lval);
+ return ir_lval_wrap(irb, scope, align_cast, lval, result_loc);
}
case BuiltinFnIdOpaqueType:
{
IrInstruction *opaque_type = ir_build_opaque_type(irb, scope, node);
- return ir_lval_wrap(irb, scope, opaque_type, lval);
+ return ir_lval_wrap(irb, scope, opaque_type, lval, result_loc);
}
case BuiltinFnIdThis:
{
IrInstruction *this_inst = ir_gen_this(irb, scope, node);
- return ir_lval_wrap(irb, scope, this_inst, lval);
+ return ir_lval_wrap(irb, scope, this_inst, lval, result_loc);
}
case BuiltinFnIdSetAlignStack:
{
@@ -5077,7 +5503,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *set_align_stack = ir_build_set_align_stack(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, set_align_stack, lval);
+ return ir_lval_wrap(irb, scope, set_align_stack, lval, result_loc);
}
case BuiltinFnIdArgType:
{
@@ -5092,7 +5518,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *arg_type = ir_build_arg_type(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, arg_type, lval);
+ return ir_lval_wrap(irb, scope, arg_type, lval, result_loc);
}
case BuiltinFnIdExport:
{
@@ -5112,12 +5538,12 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg2_value;
IrInstruction *ir_export = ir_build_export(irb, scope, node, arg0_value, arg1_value, arg2_value);
- return ir_lval_wrap(irb, scope, ir_export, lval);
+ return ir_lval_wrap(irb, scope, ir_export, lval, result_loc);
}
case BuiltinFnIdErrorReturnTrace:
{
IrInstruction *error_return_trace = ir_build_error_return_trace(irb, scope, node, IrInstructionErrorReturnTrace::Null);
- return ir_lval_wrap(irb, scope, error_return_trace, lval);
+ return ir_lval_wrap(irb, scope, error_return_trace, lval, result_loc);
}
case BuiltinFnIdAtomicRmw:
{
@@ -5146,10 +5572,11 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
if (arg4_value == irb->codegen->invalid_instruction)
return arg4_value;
- return ir_build_atomic_rmw(irb, scope, node, arg0_value, arg1_value, arg2_value, arg3_value,
+ IrInstruction *inst = ir_build_atomic_rmw(irb, scope, node, arg0_value, arg1_value, arg2_value, arg3_value,
arg4_value,
// these 2 values don't mean anything since we passed non-null values for other args
AtomicRmwOp_xchg, AtomicOrderMonotonic);
+ return ir_lval_wrap(irb, scope, inst, lval, result_loc);
}
case BuiltinFnIdAtomicLoad:
{
@@ -5168,9 +5595,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
if (arg2_value == irb->codegen->invalid_instruction)
return arg2_value;
- return ir_build_atomic_load(irb, scope, node, arg0_value, arg1_value, arg2_value,
+ IrInstruction *inst = ir_build_atomic_load(irb, scope, node, arg0_value, arg1_value, arg2_value,
// this value does not mean anything since we passed non-null values for other arg
AtomicOrderMonotonic);
+ return ir_lval_wrap(irb, scope, inst, lval, result_loc);
}
case BuiltinFnIdIntToEnum:
{
@@ -5185,7 +5613,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *result = ir_build_int_to_enum(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdEnumToInt:
{
@@ -5195,7 +5623,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdCtz:
case BuiltinFnIdPopCount:
@@ -5233,7 +5661,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
default:
zig_unreachable();
}
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdHasDecl:
{
@@ -5248,17 +5676,36 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *has_decl = ir_build_has_decl(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, has_decl, lval);
+ return ir_lval_wrap(irb, scope, has_decl, lval, result_loc);
+ }
+ case BuiltinFnIdUnionInit:
+ {
+ AstNode *union_type_node = node->data.fn_call_expr.params.at(0);
+ IrInstruction *union_type_inst = ir_gen_node(irb, union_type_node, scope);
+ if (union_type_inst == irb->codegen->invalid_instruction)
+ return union_type_inst;
+
+ AstNode *name_node = node->data.fn_call_expr.params.at(1);
+ IrInstruction *name_inst = ir_gen_node(irb, name_node, scope);
+ if (name_inst == irb->codegen->invalid_instruction)
+ return name_inst;
+
+ AstNode *init_node = node->data.fn_call_expr.params.at(2);
+
+ return ir_gen_union_init_expr(irb, scope, node, union_type_inst, name_inst, init_node,
+ lval, result_loc);
}
}
zig_unreachable();
}
-static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
+static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
+ ResultLoc *result_loc)
+{
assert(node->type == NodeTypeFnCallExpr);
if (node->data.fn_call_expr.is_builtin)
- return ir_gen_builtin_fn_call(irb, scope, node, lval);
+ return ir_gen_builtin_fn_call(irb, scope, node, lval, result_loc);
AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;
IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope);
@@ -5284,12 +5731,14 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
}
}
- IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto,
- is_async, async_allocator, nullptr);
- return ir_lval_wrap(irb, scope, fn_call, lval);
+ IrInstruction *fn_call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto,
+ is_async, async_allocator, nullptr, result_loc);
+ return ir_lval_wrap(irb, scope, fn_call, lval, result_loc);
}
-static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
+static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
+ ResultLoc *result_loc)
+{
assert(node->type == NodeTypeIfBoolExpr);
IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope);
@@ -5310,12 +5759,16 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "Else");
IrBasicBlock *endif_block = ir_create_basic_block(irb, scope, "EndIf");
- ir_build_cond_br(irb, scope, condition->source_node, condition, then_block, else_block, is_comptime);
+ IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, condition,
+ then_block, else_block, is_comptime);
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block,
+ result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, then_block);
Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
- IrInstruction *then_expr_result = ir_gen_node(irb, then_node, subexpr_scope);
+ IrInstruction *then_expr_result = ir_gen_node_extra(irb, then_node, subexpr_scope, lval,
+ &peer_parent->peers.at(0)->base);
if (then_expr_result == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
IrBasicBlock *after_then_block = irb->current_basic_block;
@@ -5325,11 +5778,12 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
ir_set_cursor_at_end_and_append_block(irb, else_block);
IrInstruction *else_expr_result;
if (else_node) {
- else_expr_result = ir_gen_node(irb, else_node, subexpr_scope);
+ else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base);
if (else_expr_result == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
} else {
else_expr_result = ir_build_const_void(irb, scope, node);
+ ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base);
}
IrBasicBlock *after_else_block = irb->current_basic_block;
if (!instr_is_unreachable(else_expr_result))
@@ -5343,14 +5797,15 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
incoming_blocks[0] = after_then_block;
incoming_blocks[1] = after_else_block;
- return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
+ IrInstruction *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent);
+ return ir_expr_wrap(irb, scope, phi, result_loc);
}
static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) {
assert(node->type == NodeTypePrefixOpExpr);
AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
- IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval);
+ IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval, nullptr);
if (value == irb->codegen->invalid_instruction)
return value;
@@ -5361,15 +5816,34 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode
return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValNone);
}
-static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval) {
- if (lval != LValPtr)
+static IrInstruction *ir_expr_wrap(IrBuilder *irb, Scope *scope, IrInstruction *inst, ResultLoc *result_loc) {
+ ir_build_end_expr(irb, scope, inst->source_node, inst, result_loc);
+ return inst;
+}
+
+static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval,
+ ResultLoc *result_loc)
+{
+ // This logic must be kept in sync with
+ // [STMT_EXPR_TEST_THING] <--- (search this token)
+ if (value == irb->codegen->invalid_instruction ||
+ instr_is_unreachable(value) ||
+ value->source_node->type == NodeTypeDefer ||
+ value->id == IrInstructionIdDeclVarSrc)
+ {
return value;
- if (value == irb->codegen->invalid_instruction)
+ }
+
+ if (lval == LValPtr) {
+ // We needed a pointer to a value, but we got a value. So we create
+ // an instruction which just makes a pointer of it.
+ return ir_build_ref(irb, scope, value->source_node, value, false, false);
+ } else if (result_loc != nullptr) {
+ return ir_expr_wrap(irb, scope, value, result_loc);
+ } else {
return value;
+ }
- // We needed a pointer to a value, but we got a value. So we create
- // an instruction which just makes a const pointer of it.
- return ir_build_ref(irb, scope, value->source_node, value, false, false);
}
static PtrLen star_token_to_ptr_len(TokenId token_id) {
@@ -5442,21 +5916,22 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
ptr_len, align_value, bit_offset_start, host_int_bytes, is_allow_zero);
}
-static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node,
- LVal lval)
+static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ AstNode *expr_node, LVal lval, ResultLoc *result_loc)
{
- IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);
+ IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr);
if (err_union_ptr == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
- IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, scope, source_node, err_union_ptr, true);
+ IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, scope, source_node, err_union_ptr, true, false);
if (payload_ptr == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
if (lval == LValPtr)
return payload_ptr;
- return ir_build_load_ptr(irb, scope, source_node, payload_ptr);
+ IrInstruction *load_ptr = ir_build_load_ptr(irb, scope, source_node, payload_ptr);
+ return ir_expr_wrap(irb, scope, load_ptr, result_loc);
}
static IrInstruction *ir_gen_bool_not(IrBuilder *irb, Scope *scope, AstNode *node) {
@@ -5470,7 +5945,9 @@ static IrInstruction *ir_gen_bool_not(IrBuilder *irb, Scope *scope, AstNode *nod
return ir_build_bool_not(irb, scope, node, value);
}
-static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
+static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
+ ResultLoc *result_loc)
+{
assert(node->type == NodeTypePrefixOpExpr);
PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op;
@@ -5479,24 +5956,51 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
case PrefixOpInvalid:
zig_unreachable();
case PrefixOpBoolNot:
- return ir_lval_wrap(irb, scope, ir_gen_bool_not(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_bool_not(irb, scope, node), lval, result_loc);
case PrefixOpBinNot:
- return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpBinNot), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpBinNot), lval, result_loc);
case PrefixOpNegation:
- return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval, result_loc);
case PrefixOpNegationWrap:
- return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval, result_loc);
case PrefixOpOptional:
- return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpOptional), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpOptional), lval, result_loc);
case PrefixOpAddrOf: {
AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
- return ir_lval_wrap(irb, scope, ir_gen_node_extra(irb, expr_node, scope, LValPtr), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr), lval, result_loc);
}
}
zig_unreachable();
}
-static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
+static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *union_type, IrInstruction *field_name, AstNode *expr_node,
+ LVal lval, ResultLoc *parent_result_loc)
+{
+ IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, source_node, parent_result_loc, union_type);
+ IrInstruction *field_ptr = ir_build_field_ptr_instruction(irb, scope, source_node, container_ptr,
+ field_name, true);
+
+ ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
+ result_loc_inst->base.id = ResultLocIdInstruction;
+ result_loc_inst->base.source_instruction = field_ptr;
+ ir_ref_instruction(field_ptr, irb->current_basic_block);
+ ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base);
+
+ IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone,
+ &result_loc_inst->base);
+ if (expr_value == irb->codegen->invalid_instruction)
+ return expr_value;
+
+ IrInstruction *init_union = ir_build_union_init_named_field(irb, scope, source_node, union_type,
+ field_name, field_ptr, container_ptr);
+
+ return ir_lval_wrap(irb, scope, init_union, lval, parent_result_loc);
+}
+
+static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
+ ResultLoc *parent_result_loc)
+{
assert(node->type == NodeTypeContainerInitExpr);
AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
@@ -5514,45 +6018,104 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
return container_type;
}
- if (kind == ContainerInitKindStruct) {
- if (elem_type != nullptr) {
- add_node_error(irb->codegen, container_init_expr->type,
- buf_sprintf("initializing array with struct syntax"));
- return irb->codegen->invalid_instruction;
- }
+ switch (kind) {
+ case ContainerInitKindStruct: {
+ if (elem_type != nullptr) {
+ add_node_error(irb->codegen, container_init_expr->type,
+ buf_sprintf("initializing array with struct syntax"));
+ return irb->codegen->invalid_instruction;
+ }
+
+ IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc,
+ container_type);
- size_t field_count = container_init_expr->entries.length;
- IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count);
- for (size_t i = 0; i < field_count; i += 1) {
- AstNode *entry_node = container_init_expr->entries.at(i);
- assert(entry_node->type == NodeTypeStructValueField);
+ size_t field_count = container_init_expr->entries.length;
+ IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count);
+ for (size_t i = 0; i < field_count; i += 1) {
+ AstNode *entry_node = container_init_expr->entries.at(i);
+ assert(entry_node->type == NodeTypeStructValueField);
- Buf *name = entry_node->data.struct_val_field.name;
- AstNode *expr_node = entry_node->data.struct_val_field.expr;
- IrInstruction *expr_value = ir_gen_node(irb, expr_node, scope);
- if (expr_value == irb->codegen->invalid_instruction)
- return expr_value;
+ Buf *name = entry_node->data.struct_val_field.name;
+ AstNode *expr_node = entry_node->data.struct_val_field.expr;
- fields[i].name = name;
- fields[i].value = expr_value;
- fields[i].source_node = entry_node;
+ IrInstruction *field_ptr = ir_build_field_ptr(irb, scope, entry_node, container_ptr, name, true);
+ ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
+ result_loc_inst->base.id = ResultLocIdInstruction;
+ result_loc_inst->base.source_instruction = field_ptr;
+ ir_ref_instruction(field_ptr, irb->current_basic_block);
+ ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base);
+
+ IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone,
+ &result_loc_inst->base);
+ if (expr_value == irb->codegen->invalid_instruction)
+ return expr_value;
+
+ fields[i].name = name;
+ fields[i].source_node = entry_node;
+ fields[i].result_loc = field_ptr;
+ }
+ IrInstruction *init_fields = ir_build_container_init_fields(irb, scope, node, container_type,
+ field_count, fields, container_ptr);
+
+ return ir_lval_wrap(irb, scope, init_fields, lval, parent_result_loc);
}
- return ir_build_container_init_fields(irb, scope, node, container_type, field_count, fields);
- } else if (kind == ContainerInitKindArray) {
- size_t item_count = container_init_expr->entries.length;
- IrInstruction **values = allocate<IrInstruction *>(item_count);
- for (size_t i = 0; i < item_count; i += 1) {
- AstNode *expr_node = container_init_expr->entries.at(i);
- IrInstruction *expr_value = ir_gen_node(irb, expr_node, scope);
- if (expr_value == irb->codegen->invalid_instruction)
- return expr_value;
+ case ContainerInitKindArray: {
+ size_t item_count = container_init_expr->entries.length;
- values[i] = expr_value;
+ if (container_type == nullptr) {
+ IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count);
+ container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type);
+ }
+
+ IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc,
+ container_type);
+
+ IrInstruction **result_locs = allocate<IrInstruction *>(item_count);
+ for (size_t i = 0; i < item_count; i += 1) {
+ AstNode *expr_node = container_init_expr->entries.at(i);
+
+ IrInstruction *elem_index = ir_build_const_usize(irb, scope, expr_node, i);
+ IrInstruction *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr, elem_index,
+ false, PtrLenSingle, container_type);
+ ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
+ result_loc_inst->base.id = ResultLocIdInstruction;
+ result_loc_inst->base.source_instruction = elem_ptr;
+ ir_ref_instruction(elem_ptr, irb->current_basic_block);
+ ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base);
+
+ IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone,
+ &result_loc_inst->base);
+ if (expr_value == irb->codegen->invalid_instruction)
+ return expr_value;
+
+ result_locs[i] = elem_ptr;
+ }
+ IrInstruction *init_list = ir_build_container_init_list(irb, scope, node, container_type,
+ item_count, result_locs, container_ptr);
+ return ir_lval_wrap(irb, scope, init_list, lval, parent_result_loc);
}
- return ir_build_container_init_list(irb, scope, node, container_type, elem_type, item_count, values);
- } else {
- zig_unreachable();
}
+ zig_unreachable();
+}
+
+static ResultLocVar *ir_build_var_result_loc(IrBuilder *irb, IrInstruction *alloca, ZigVar *var) {
+ ResultLocVar *result_loc_var = allocate<ResultLocVar>(1);
+ result_loc_var->base.id = ResultLocIdVar;
+ result_loc_var->base.source_instruction = alloca;
+ result_loc_var->var = var;
+
+ ir_build_reset_result(irb, alloca->scope, alloca->source_node, &result_loc_var->base);
+
+ return result_loc_var;
+}
+
+static void build_decl_var_and_init(IrBuilder *irb, Scope *scope, AstNode *source_node, ZigVar *var,
+ IrInstruction *init, const char *name_hint, IrInstruction *is_comptime)
+{
+ IrInstruction *alloca = ir_build_alloca_src(irb, scope, source_node, nullptr, name_hint, is_comptime);
+ ResultLocVar *var_result_loc = ir_build_var_result_loc(irb, alloca, var);
+ ir_build_end_expr(irb, scope, source_node, init, &var_result_loc->base);
+ ir_build_var_decl_src(irb, scope, source_node, var, nullptr, alloca);
}
static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *node) {
@@ -5565,9 +6128,12 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
return irb->codegen->invalid_instruction;
}
+ // Used for the type expr and the align expr
+ Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope);
+
IrInstruction *type_instruction;
if (variable_declaration->type != nullptr) {
- type_instruction = ir_gen_node(irb, variable_declaration->type, scope);
+ type_instruction = ir_gen_node(irb, variable_declaration->type, comptime_scope);
if (type_instruction == irb->codegen->invalid_instruction)
return type_instruction;
} else {
@@ -5578,8 +6144,8 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
bool is_const = variable_declaration->is_const;
bool is_extern = variable_declaration->is_extern;
- IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node,
- ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime);
+ bool is_comptime_scalar = ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime;
+ IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, is_comptime_scalar);
ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol,
is_const, is_const, is_shadowable, is_comptime);
// we detect IrInstructionIdDeclVarSrc in gen_block to make sure the next node
@@ -5593,7 +6159,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
IrInstruction *align_value = nullptr;
if (variable_declaration->align_expr != nullptr) {
- align_value = ir_gen_node(irb, variable_declaration->align_expr, scope);
+ align_value = ir_gen_node(irb, variable_declaration->align_expr, comptime_scope);
if (align_value == irb->codegen->invalid_instruction)
return align_value;
}
@@ -5606,20 +6172,39 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
// Parser should ensure that this never happens
assert(variable_declaration->threadlocal_tok == nullptr);
+ IrInstruction *alloca = ir_build_alloca_src(irb, scope, node, align_value,
+ buf_ptr(variable_declaration->symbol), is_comptime);
+
+ // Create a result location for the initialization expression.
+ ResultLocVar *result_loc_var = ir_build_var_result_loc(irb, alloca, var);
+ ResultLoc *init_result_loc = (type_instruction == nullptr) ? &result_loc_var->base : nullptr;
+
+ Scope *init_scope = is_comptime_scalar ?
+ create_comptime_scope(irb->codegen, variable_declaration->expr, scope) : scope;
+
// Temporarily set the name of the IrExecutable to the VariableDeclaration
// so that the struct or enum from the init expression inherits the name.
Buf *old_exec_name = irb->exec->name;
irb->exec->name = variable_declaration->symbol;
- IrInstruction *init_value = ir_gen_node(irb, variable_declaration->expr, scope);
+ IrInstruction *init_value = ir_gen_node_extra(irb, variable_declaration->expr, init_scope,
+ LValNone, init_result_loc);
irb->exec->name = old_exec_name;
if (init_value == irb->codegen->invalid_instruction)
- return init_value;
+ return irb->codegen->invalid_instruction;
+
+ if (type_instruction != nullptr) {
+ IrInstruction *implicit_cast = ir_build_implicit_cast(irb, scope, node, type_instruction, init_value,
+ &result_loc_var->base);
+ ir_build_end_expr(irb, scope, node, implicit_cast, &result_loc_var->base);
+ }
- return ir_build_var_decl_src(irb, scope, node, var, type_instruction, align_value, init_value);
+ return ir_build_var_decl_src(irb, scope, node, var, align_value, alloca);
}
-static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
+static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
+ ResultLoc *result_loc)
+{
assert(node->type == NodeTypeWhileExpr);
AstNode *continue_expr_node = node->data.while_expr.continue_expr;
@@ -5654,25 +6239,33 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
} else {
payload_scope = subexpr_scope;
}
- IrInstruction *err_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, LValPtr);
+ IrInstruction *err_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope,
+ LValPtr, nullptr);
if (err_val_ptr == irb->codegen->invalid_instruction)
return err_val_ptr;
- IrInstruction *err_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, err_val_ptr);
- IrInstruction *is_err = ir_build_test_err(irb, scope, node->data.while_expr.condition, err_val);
+ IrInstruction *is_err = ir_build_test_err_src(irb, scope, node->data.while_expr.condition, err_val_ptr, true);
IrBasicBlock *after_cond_block = irb->current_basic_block;
IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));
+ IrInstruction *cond_br_inst;
if (!instr_is_unreachable(is_err)) {
- ir_mark_gen(ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_err,
- else_block, body_block, is_comptime));
+ cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_err,
+ else_block, body_block, is_comptime);
+ cond_br_inst->is_gen = true;
+ } else {
+ // for the purposes of the source instruction to ir_build_result_peers
+ cond_br_inst = irb->current_basic_block->instruction_list.last();
}
+ ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc,
+ is_comptime);
+
ir_set_cursor_at_end_and_append_block(irb, body_block);
if (var_symbol) {
- IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, payload_scope, symbol_node,
- err_val_ptr, false);
- IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
- var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value);
- ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value);
+ IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, payload_scope, symbol_node,
+ err_val_ptr, false, false);
+ IrInstruction *var_ptr = node->data.while_expr.var_is_ptr ?
+ ir_build_ref(irb, payload_scope, symbol_node, payload_ptr, true, false) : payload_ptr;
+ ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, var_ptr);
}
ZigList<IrInstruction *> incoming_values = {0};
@@ -5684,7 +6277,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
loop_scope->is_comptime = is_comptime;
loop_scope->incoming_blocks = &incoming_blocks;
loop_scope->incoming_values = &incoming_values;
+ loop_scope->lval = lval;
+ loop_scope->peer_parent = peer_parent;
+ // Note the body block of the loop is not the place that lval and result_loc are used -
+ // it's actually in break statements, handled similarly to return statements.
+ // That is why we set those values in loop_scope above and not in this ir_gen_node call.
IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base);
if (body_result == irb->codegen->invalid_instruction)
return body_result;
@@ -5713,10 +6311,15 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
ZigVar *err_var = ir_create_var(irb, err_symbol_node, scope, err_symbol,
true, false, false, is_comptime);
Scope *err_scope = err_var->child_scope;
- IrInstruction *err_var_value = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);
- ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value);
+ IrInstruction *err_ptr = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);
+ ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, err_ptr);
- IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope);
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = else_block;
+ }
+ ResultLocPeer *peer_result = create_peer_result(peer_parent);
+ peer_parent->peers.append(peer_result);
+ IrInstruction *else_result = ir_gen_node_extra(irb, else_node, err_scope, lval, &peer_result->base);
if (else_result == irb->codegen->invalid_instruction)
return else_result;
if (!instr_is_unreachable(else_result))
@@ -5730,8 +6333,13 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
incoming_blocks.append(after_cond_block);
incoming_values.append(void_else_result);
}
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = end_block;
+ }
- return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);
+ IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length,
+ incoming_blocks.items, incoming_values.items, peer_parent);
+ return ir_expr_wrap(irb, scope, phi, result_loc);
} else if (var_symbol != nullptr) {
ir_set_cursor_at_end_and_append_block(irb, cond_block);
Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
@@ -5741,23 +6349,32 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
ZigVar *payload_var = ir_create_var(irb, symbol_node, subexpr_scope, var_symbol,
true, false, false, is_comptime);
Scope *child_scope = payload_var->child_scope;
- IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, LValPtr);
+ IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope,
+ LValPtr, nullptr);
if (maybe_val_ptr == irb->codegen->invalid_instruction)
return maybe_val_ptr;
IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, maybe_val_ptr);
IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node->data.while_expr.condition, maybe_val);
IrBasicBlock *after_cond_block = irb->current_basic_block;
IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));
+ IrInstruction *cond_br_inst;
if (!instr_is_unreachable(is_non_null)) {
- ir_mark_gen(ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_non_null,
- body_block, else_block, is_comptime));
+ cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_non_null,
+ body_block, else_block, is_comptime);
+ cond_br_inst->is_gen = true;
+ } else {
+ // for the purposes of the source instruction to ir_build_result_peers
+ cond_br_inst = irb->current_basic_block->instruction_list.last();
}
+ ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc,
+ is_comptime);
+
ir_set_cursor_at_end_and_append_block(irb, body_block);
- IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false);
- IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
- var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value);
- ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value);
+ IrInstruction *payload_ptr = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false, false);
+ IrInstruction *var_ptr = node->data.while_expr.var_is_ptr ?
+ ir_build_ref(irb, child_scope, symbol_node, payload_ptr, true, false) : payload_ptr;
+ ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, var_ptr);
ZigList<IrInstruction *> incoming_values = {0};
ZigList<IrBasicBlock *> incoming_blocks = {0};
@@ -5768,7 +6385,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
loop_scope->is_comptime = is_comptime;
loop_scope->incoming_blocks = &incoming_blocks;
loop_scope->incoming_values = &incoming_values;
+ loop_scope->lval = lval;
+ loop_scope->peer_parent = peer_parent;
+ // Note the body block of the loop is not the place that lval and result_loc are used -
+ // it's actually in break statements, handled similarly to return statements.
+ // That is why we set those values in loop_scope above and not in this ir_gen_node call.
IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base);
if (body_result == irb->codegen->invalid_instruction)
return body_result;
@@ -5793,7 +6415,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
if (else_node) {
ir_set_cursor_at_end_and_append_block(irb, else_block);
- else_result = ir_gen_node(irb, else_node, scope);
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = else_block;
+ }
+ ResultLocPeer *peer_result = create_peer_result(peer_parent);
+ peer_parent->peers.append(peer_result);
+ else_result = ir_gen_node_extra(irb, else_node, scope, lval, &peer_result->base);
if (else_result == irb->codegen->invalid_instruction)
return else_result;
if (!instr_is_unreachable(else_result))
@@ -5808,8 +6435,13 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
incoming_blocks.append(after_cond_block);
incoming_values.append(void_else_result);
}
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = end_block;
+ }
- return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);
+ IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length,
+ incoming_blocks.items, incoming_values.items, peer_parent);
+ return ir_expr_wrap(irb, scope, phi, result_loc);
} else {
ir_set_cursor_at_end_and_append_block(irb, cond_block);
IrInstruction *cond_val = ir_gen_node(irb, node->data.while_expr.condition, scope);
@@ -5817,11 +6449,18 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
return cond_val;
IrBasicBlock *after_cond_block = irb->current_basic_block;
IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));
+ IrInstruction *cond_br_inst;
if (!instr_is_unreachable(cond_val)) {
- ir_mark_gen(ir_build_cond_br(irb, scope, node->data.while_expr.condition, cond_val,
- body_block, else_block, is_comptime));
+ cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, cond_val,
+ body_block, else_block, is_comptime);
+ cond_br_inst->is_gen = true;
+ } else {
+ // for the purposes of the source instruction to ir_build_result_peers
+ cond_br_inst = irb->current_basic_block->instruction_list.last();
}
+ ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc,
+ is_comptime);
ir_set_cursor_at_end_and_append_block(irb, body_block);
ZigList<IrInstruction *> incoming_values = {0};
@@ -5835,7 +6474,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
loop_scope->is_comptime = is_comptime;
loop_scope->incoming_blocks = &incoming_blocks;
loop_scope->incoming_values = &incoming_values;
+ loop_scope->lval = lval;
+ loop_scope->peer_parent = peer_parent;
+ // Note the body block of the loop is not the place that lval and result_loc are used -
+ // it's actually in break statements, handled similarly to return statements.
+ // That is why we set those values in loop_scope above and not in this ir_gen_node call.
IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base);
if (body_result == irb->codegen->invalid_instruction)
return body_result;
@@ -5860,7 +6504,13 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
if (else_node) {
ir_set_cursor_at_end_and_append_block(irb, else_block);
- else_result = ir_gen_node(irb, else_node, subexpr_scope);
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = else_block;
+ }
+ ResultLocPeer *peer_result = create_peer_result(peer_parent);
+ peer_parent->peers.append(peer_result);
+
+ else_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_result->base);
if (else_result == irb->codegen->invalid_instruction)
return else_result;
if (!instr_is_unreachable(else_result))
@@ -5875,12 +6525,19 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
incoming_blocks.append(after_cond_block);
incoming_values.append(void_else_result);
}
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = end_block;
+ }
- return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);
+ IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length,
+ incoming_blocks.items, incoming_values.items, peer_parent);
+ return ir_expr_wrap(irb, scope, phi, result_loc);
}
}
-static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
+static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval,
+ ResultLoc *result_loc)
+{
assert(node->type == NodeTypeForExpr);
AstNode *array_node = node->data.for_expr.array_expr;
@@ -5895,76 +6552,67 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
}
assert(elem_node->type == NodeTypeSymbol);
- IrInstruction *array_val_ptr = ir_gen_node_extra(irb, array_node, parent_scope, LValPtr);
+ IrInstruction *array_val_ptr = ir_gen_node_extra(irb, array_node, parent_scope, LValPtr, nullptr);
if (array_val_ptr == irb->codegen->invalid_instruction)
return array_val_ptr;
- IrInstruction *pointer_type = ir_build_to_ptr_type(irb, parent_scope, array_node, array_val_ptr);
- IrInstruction *elem_var_type;
- if (node->data.for_expr.elem_is_ptr) {
- elem_var_type = pointer_type;
- } else {
- elem_var_type = ir_build_ptr_type_child(irb, parent_scope, elem_node, pointer_type);
- }
-
IrInstruction *is_comptime = ir_build_const_bool(irb, parent_scope, node,
ir_should_inline(irb->exec, parent_scope) || node->data.for_expr.is_inline);
- // TODO make it an error to write to element variable or i variable.
- Buf *elem_var_name = elem_node->data.symbol_expr.symbol;
- ZigVar *elem_var = ir_create_var(irb, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime);
- Scope *child_scope = elem_var->child_scope;
-
- IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node);
- ir_build_var_decl_src(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value);
- IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var);
-
AstNode *index_var_source_node;
ZigVar *index_var;
+ const char *index_var_name;
if (index_node) {
index_var_source_node = index_node;
- Buf *index_var_name = index_node->data.symbol_expr.symbol;
- index_var = ir_create_var(irb, index_node, child_scope, index_var_name, true, false, false, is_comptime);
+ Buf *index_var_name_buf = index_node->data.symbol_expr.symbol;
+ index_var = ir_create_var(irb, index_node, parent_scope, index_var_name_buf, true, false, false, is_comptime);
+ index_var_name = buf_ptr(index_var_name_buf);
} else {
index_var_source_node = node;
- index_var = ir_create_var(irb, node, child_scope, nullptr, true, false, true, is_comptime);
+ index_var = ir_create_var(irb, node, parent_scope, nullptr, true, false, true, is_comptime);
+ index_var_name = "i";
}
- child_scope = index_var->child_scope;
- IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize);
- IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0);
- IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1);
- ir_build_var_decl_src(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero);
- IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var);
+ IrInstruction *zero = ir_build_const_usize(irb, parent_scope, node, 0);
+ build_decl_var_and_init(irb, parent_scope, index_var_source_node, index_var, zero, index_var_name, is_comptime);
+ parent_scope = index_var->child_scope;
+ IrInstruction *one = ir_build_const_usize(irb, parent_scope, node, 1);
+ IrInstruction *index_ptr = ir_build_var_ptr(irb, parent_scope, node, index_var);
- IrBasicBlock *cond_block = ir_create_basic_block(irb, child_scope, "ForCond");
- IrBasicBlock *body_block = ir_create_basic_block(irb, child_scope, "ForBody");
- IrBasicBlock *end_block = ir_create_basic_block(irb, child_scope, "ForEnd");
- IrBasicBlock *else_block = else_node ? ir_create_basic_block(irb, child_scope, "ForElse") : end_block;
- IrBasicBlock *continue_block = ir_create_basic_block(irb, child_scope, "ForContinue");
+
+ IrBasicBlock *cond_block = ir_create_basic_block(irb, parent_scope, "ForCond");
+ IrBasicBlock *body_block = ir_create_basic_block(irb, parent_scope, "ForBody");
+ IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "ForEnd");
+ IrBasicBlock *else_block = else_node ? ir_create_basic_block(irb, parent_scope, "ForElse") : end_block;
+ IrBasicBlock *continue_block = ir_create_basic_block(irb, parent_scope, "ForContinue");
Buf *len_field_name = buf_create_from_str("len");
- IrInstruction *len_ref = ir_build_field_ptr(irb, child_scope, node, array_val_ptr, len_field_name);
- IrInstruction *len_val = ir_build_load_ptr(irb, child_scope, node, len_ref);
- ir_build_br(irb, child_scope, node, cond_block, is_comptime);
+ IrInstruction *len_ref = ir_build_field_ptr(irb, parent_scope, node, array_val_ptr, len_field_name, false);
+ IrInstruction *len_val = ir_build_load_ptr(irb, parent_scope, node, len_ref);
+ ir_build_br(irb, parent_scope, node, cond_block, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, cond_block);
- IrInstruction *index_val = ir_build_load_ptr(irb, child_scope, node, index_ptr);
- IrInstruction *cond = ir_build_bin_op(irb, child_scope, node, IrBinOpCmpLessThan, index_val, len_val, false);
+ IrInstruction *index_val = ir_build_load_ptr(irb, parent_scope, node, index_ptr);
+ IrInstruction *cond = ir_build_bin_op(irb, parent_scope, node, IrBinOpCmpLessThan, index_val, len_val, false);
IrBasicBlock *after_cond_block = irb->current_basic_block;
IrInstruction *void_else_value = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, parent_scope, node));
- ir_mark_gen(ir_build_cond_br(irb, child_scope, node, cond, body_block, else_block, is_comptime));
+ IrInstruction *cond_br_inst = ir_mark_gen(ir_build_cond_br(irb, parent_scope, node, cond,
+ body_block, else_block, is_comptime));
+
+ ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, body_block);
- IrInstruction *elem_ptr = ir_build_elem_ptr(irb, child_scope, node, array_val_ptr, index_val, false, PtrLenSingle);
- IrInstruction *elem_val;
- if (node->data.for_expr.elem_is_ptr) {
- elem_val = elem_ptr;
- } else {
- elem_val = ir_build_load_ptr(irb, child_scope, node, elem_ptr);
- }
- ir_mark_gen(ir_build_store_ptr(irb, child_scope, node, elem_var_ptr, elem_val));
+ IrInstruction *elem_ptr = ir_build_elem_ptr(irb, parent_scope, node, array_val_ptr, index_val, false,
+ PtrLenSingle, nullptr);
+ // TODO make it an error to write to element variable or i variable.
+ Buf *elem_var_name = elem_node->data.symbol_expr.symbol;
+ ZigVar *elem_var = ir_create_var(irb, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime);
+ Scope *child_scope = elem_var->child_scope;
+
+ IrInstruction *var_ptr = node->data.for_expr.elem_is_ptr ?
+ ir_build_ref(irb, parent_scope, elem_node, elem_ptr, true, false) : elem_ptr;
+ ir_build_var_decl_src(irb, parent_scope, elem_node, elem_var, nullptr, var_ptr);
ZigList<IrInstruction *> incoming_values = {0};
ZigList<IrBasicBlock *> incoming_blocks = {0};
@@ -5974,7 +6622,12 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
loop_scope->is_comptime = is_comptime;
loop_scope->incoming_blocks = &incoming_blocks;
loop_scope->incoming_values = &incoming_values;
+ loop_scope->lval = LValNone;
+ loop_scope->peer_parent = peer_parent;
+ // Note the body block of the loop is not the place that lval and result_loc are used -
+ // it's actually in break statements, handled similarly to return statements.
+ // That is why we set those values in loop_scope above and not in this ir_gen_node call.
IrInstruction *body_result = ir_gen_node(irb, body_node, &loop_scope->base);
if (!instr_is_unreachable(body_result)) {
@@ -5991,7 +6644,12 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
if (else_node) {
ir_set_cursor_at_end_and_append_block(irb, else_block);
- else_result = ir_gen_node(irb, else_node, parent_scope);
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = else_block;
+ }
+ ResultLocPeer *peer_result = create_peer_result(peer_parent);
+ peer_parent->peers.append(peer_result);
+ else_result = ir_gen_node_extra(irb, else_node, parent_scope, LValNone, &peer_result->base);
if (else_result == irb->codegen->invalid_instruction)
return else_result;
if (!instr_is_unreachable(else_result))
@@ -6007,8 +6665,13 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
incoming_blocks.append(after_cond_block);
incoming_values.append(void_else_value);
}
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = end_block;
+ }
- return ir_build_phi(irb, parent_scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);
+ IrInstruction *phi = ir_build_phi(irb, parent_scope, node, incoming_blocks.length,
+ incoming_blocks.items, incoming_values.items, peer_parent);
+ return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc);
}
static IrInstruction *ir_gen_bool_literal(IrBuilder *irb, Scope *scope, AstNode *node) {
@@ -6293,7 +6956,9 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod
input_list, output_types, output_vars, return_count, is_volatile);
}
-static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
+static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
+ ResultLoc *result_loc)
+{
assert(node->type == NodeTypeIfOptional);
Buf *var_symbol = node->data.test_expr.var_symbol;
@@ -6302,7 +6967,7 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN
AstNode *else_node = node->data.test_expr.else_node;
bool var_is_ptr = node->data.test_expr.var_is_ptr;
- IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);
+ IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr);
if (maybe_val_ptr == irb->codegen->invalid_instruction)
return maybe_val_ptr;
@@ -6319,27 +6984,31 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN
} else {
is_comptime = ir_build_test_comptime(irb, scope, node, is_non_null);
}
- ir_build_cond_br(irb, scope, node, is_non_null, then_block, else_block, is_comptime);
+ IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, is_non_null,
+ then_block, else_block, is_comptime);
+
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block,
+ result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, then_block);
Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
Scope *var_scope;
if (var_symbol) {
- IrInstruction *var_type = nullptr;
bool is_shadowable = false;
bool is_const = true;
ZigVar *var = ir_create_var(irb, node, subexpr_scope,
var_symbol, is_const, is_const, is_shadowable, is_comptime);
- IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false);
- IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);
- ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
+ IrInstruction *payload_ptr = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false, false);
+ IrInstruction *var_ptr = var_is_ptr ? ir_build_ref(irb, subexpr_scope, node, payload_ptr, true, false) : payload_ptr;
+ ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, var_ptr);
var_scope = var->child_scope;
} else {
var_scope = subexpr_scope;
}
- IrInstruction *then_expr_result = ir_gen_node(irb, then_node, var_scope);
+ IrInstruction *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval,
+ &peer_parent->peers.at(0)->base);
if (then_expr_result == irb->codegen->invalid_instruction)
return then_expr_result;
IrBasicBlock *after_then_block = irb->current_basic_block;
@@ -6349,11 +7018,12 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN
ir_set_cursor_at_end_and_append_block(irb, else_block);
IrInstruction *else_expr_result;
if (else_node) {
- else_expr_result = ir_gen_node(irb, else_node, subexpr_scope);
+ else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base);
if (else_expr_result == irb->codegen->invalid_instruction)
return else_expr_result;
} else {
else_expr_result = ir_build_const_void(irb, scope, node);
+ ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base);
}
IrBasicBlock *after_else_block = irb->current_basic_block;
if (!instr_is_unreachable(else_expr_result))
@@ -6367,10 +7037,13 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN
incoming_blocks[0] = after_then_block;
incoming_blocks[1] = after_else_block;
- return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
+ IrInstruction *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent);
+ return ir_expr_wrap(irb, scope, phi, result_loc);
}
-static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
+static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
+ ResultLoc *result_loc)
+{
assert(node->type == NodeTypeIfErrorExpr);
AstNode *target_node = node->data.if_err_expr.target_node;
@@ -6381,12 +7054,12 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
Buf *var_symbol = node->data.if_err_expr.var_symbol;
Buf *err_symbol = node->data.if_err_expr.err_symbol;
- IrInstruction *err_val_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr);
+ IrInstruction *err_val_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr, nullptr);
if (err_val_ptr == irb->codegen->invalid_instruction)
return err_val_ptr;
IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr);
- IrInstruction *is_err = ir_build_test_err(irb, scope, node, err_val);
+ IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, err_val_ptr, true);
IrBasicBlock *ok_block = ir_create_basic_block(irb, scope, "TryOk");
IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "TryElse");
@@ -6394,27 +7067,31 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
bool force_comptime = ir_should_inline(irb->exec, scope);
IrInstruction *is_comptime = force_comptime ? ir_build_const_bool(irb, scope, node, true) : ir_build_test_comptime(irb, scope, node, is_err);
- ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime);
+ IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime);
+
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block,
+ result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, ok_block);
Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
Scope *var_scope;
if (var_symbol) {
- IrInstruction *var_type = nullptr;
bool is_shadowable = false;
IrInstruction *var_is_comptime = force_comptime ? ir_build_const_bool(irb, subexpr_scope, node, true) : ir_build_test_comptime(irb, subexpr_scope, node, err_val);
ZigVar *var = ir_create_var(irb, node, subexpr_scope,
var_symbol, var_is_const, var_is_const, is_shadowable, var_is_comptime);
- IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false);
- IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);
- ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
+ IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false, false);
+ IrInstruction *var_ptr = var_is_ptr ?
+ ir_build_ref(irb, subexpr_scope, node, payload_ptr, true, false) : payload_ptr;
+ ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, var_ptr);
var_scope = var->child_scope;
} else {
var_scope = subexpr_scope;
}
- IrInstruction *then_expr_result = ir_gen_node(irb, then_node, var_scope);
+ IrInstruction *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval,
+ &peer_parent->peers.at(0)->base);
if (then_expr_result == irb->codegen->invalid_instruction)
return then_expr_result;
IrBasicBlock *after_then_block = irb->current_basic_block;
@@ -6427,23 +7104,23 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
if (else_node) {
Scope *err_var_scope;
if (err_symbol) {
- IrInstruction *var_type = nullptr;
bool is_shadowable = false;
bool is_const = true;
ZigVar *var = ir_create_var(irb, node, subexpr_scope,
err_symbol, is_const, is_const, is_shadowable, is_comptime);
- IrInstruction *var_value = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr);
- ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
+ IrInstruction *err_ptr = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr);
+ ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, err_ptr);
err_var_scope = var->child_scope;
} else {
err_var_scope = subexpr_scope;
}
- else_expr_result = ir_gen_node(irb, else_node, err_var_scope);
+ else_expr_result = ir_gen_node_extra(irb, else_node, err_var_scope, lval, &peer_parent->peers.at(1)->base);
if (else_expr_result == irb->codegen->invalid_instruction)
return else_expr_result;
} else {
else_expr_result = ir_build_const_void(irb, scope, node);
+ ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base);
}
IrBasicBlock *after_else_block = irb->current_basic_block;
if (!instr_is_unreachable(else_expr_result))
@@ -6457,14 +7134,15 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
incoming_blocks[0] = after_then_block;
incoming_blocks[1] = after_else_block;
- return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
+ IrInstruction *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent);
+ return ir_expr_wrap(irb, scope, phi, result_loc);
}
static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node,
IrBasicBlock *end_block, IrInstruction *is_comptime, IrInstruction *var_is_comptime,
IrInstruction *target_value_ptr, IrInstruction **prong_values, size_t prong_values_len,
ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values,
- IrInstructionSwitchElseVar **out_switch_else_var)
+ IrInstructionSwitchElseVar **out_switch_else_var, LVal lval, ResultLoc *result_loc)
{
assert(switch_node->type == NodeTypeSwitchExpr);
assert(prong_node->type == NodeTypeSwitchProng);
@@ -6482,28 +7160,27 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
ZigVar *var = ir_create_var(irb, var_symbol_node, scope,
var_name, is_const, is_const, is_shadowable, var_is_comptime);
child_scope = var->child_scope;
- IrInstruction *var_value;
+ IrInstruction *var_ptr;
if (out_switch_else_var != nullptr) {
IrInstructionSwitchElseVar *switch_else_var = ir_build_switch_else_var(irb, scope, var_symbol_node,
target_value_ptr);
*out_switch_else_var = switch_else_var;
- IrInstruction *var_ptr_value = &switch_else_var->base;
- var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, var_symbol_node, var_ptr_value);
+ IrInstruction *payload_ptr = &switch_else_var->base;
+ var_ptr = var_is_ptr ? ir_build_ref(irb, scope, var_symbol_node, payload_ptr, true, false) : payload_ptr;
} else if (prong_values != nullptr) {
- IrInstruction *var_ptr_value = ir_build_switch_var(irb, scope, var_symbol_node, target_value_ptr,
+ IrInstruction *payload_ptr = ir_build_switch_var(irb, scope, var_symbol_node, target_value_ptr,
prong_values, prong_values_len);
- var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, var_symbol_node, var_ptr_value);
+ var_ptr = var_is_ptr ? ir_build_ref(irb, scope, var_symbol_node, payload_ptr, true, false) : payload_ptr;
} else {
- var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node,
-target_value_ptr);
+ var_ptr = var_is_ptr ?
+ ir_build_ref(irb, scope, var_symbol_node, target_value_ptr, true, false) : target_value_ptr;
}
- IrInstruction *var_type = nullptr; // infer the type
- ir_build_var_decl_src(irb, scope, var_symbol_node, var, var_type, nullptr, var_value);
+ ir_build_var_decl_src(irb, scope, var_symbol_node, var, nullptr, var_ptr);
} else {
child_scope = scope;
}
- IrInstruction *expr_result = ir_gen_node(irb, expr_node, child_scope);
+ IrInstruction *expr_result = ir_gen_node_extra(irb, expr_node, child_scope, lval, result_loc);
if (expr_result == irb->codegen->invalid_instruction)
return false;
if (!instr_is_unreachable(expr_result))
@@ -6513,11 +7190,13 @@ target_value_ptr);
return true;
}
-static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
+static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
+ ResultLoc *result_loc)
+{
assert(node->type == NodeTypeSwitchExpr);
AstNode *target_node = node->data.switch_expr.expr;
- IrInstruction *target_value_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr);
+ IrInstruction *target_value_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr, nullptr);
if (target_value_ptr == irb->codegen->invalid_instruction)
return target_value_ptr;
IrInstruction *target_value = ir_build_switch_target(irb, scope, node, target_value_ptr);
@@ -6544,6 +7223,14 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
IrInstructionSwitchElseVar *switch_else_var = nullptr;
+ ResultLocPeerParent *peer_parent = allocate<ResultLocPeerParent>(1);
+ peer_parent->base.id = ResultLocIdPeerParent;
+ peer_parent->end_bb = end_block;
+ peer_parent->is_comptime = is_comptime;
+ peer_parent->parent = result_loc;
+
+ ir_build_reset_result(irb, scope, node, &peer_parent->base);
+
// First do the else and the ranges
Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope);
@@ -6552,6 +7239,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
size_t prong_item_count = prong_node->data.switch_prong.items.length;
if (prong_item_count == 0) {
+ ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
if (else_prong) {
ErrorMsg *msg = add_node_error(irb->codegen, prong_node,
buf_sprintf("multiple else prongs in switch expression"));
@@ -6562,15 +7250,21 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
else_prong = prong_node;
IrBasicBlock *prev_block = irb->current_basic_block;
+ if (peer_parent->peers.length > 0) {
+ peer_parent->peers.last()->next_bb = else_block;
+ }
+ peer_parent->peers.append(this_peer_result_loc);
ir_set_cursor_at_end_and_append_block(irb, else_block);
if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values,
- &switch_else_var))
+ &switch_else_var, LValNone, &this_peer_result_loc->base))
{
return irb->codegen->invalid_instruction;
}
ir_set_cursor_at_end(irb, prev_block);
} else if (prong_node->data.switch_prong.any_items_are_range) {
+ ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
+
IrInstruction *ok_bit = nullptr;
AstNode *last_item_node = nullptr;
for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) {
@@ -6627,13 +7321,20 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
assert(ok_bit);
assert(last_item_node);
- ir_mark_gen(ir_build_cond_br(irb, scope, last_item_node, ok_bit, range_block_yes,
- range_block_no, is_comptime));
+ IrInstruction *br_inst = ir_mark_gen(ir_build_cond_br(irb, scope, last_item_node, ok_bit,
+ range_block_yes, range_block_no, is_comptime));
+ if (peer_parent->base.source_instruction == nullptr) {
+ peer_parent->base.source_instruction = br_inst;
+ }
+ if (peer_parent->peers.length > 0) {
+ peer_parent->peers.last()->next_bb = range_block_yes;
+ }
+ peer_parent->peers.append(this_peer_result_loc);
ir_set_cursor_at_end_and_append_block(irb, range_block_yes);
if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
is_comptime, var_is_comptime, target_value_ptr, nullptr, 0,
- &incoming_blocks, &incoming_values, nullptr))
+ &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base))
{
return irb->codegen->invalid_instruction;
}
@@ -6651,6 +7352,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
if (prong_node->data.switch_prong.any_items_are_range)
continue;
+ ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
+
IrBasicBlock *prong_block = ir_create_basic_block(irb, scope, "SwitchProng");
IrInstruction **items = allocate<IrInstruction *>(prong_item_count);
@@ -6674,10 +7377,14 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
}
IrBasicBlock *prev_block = irb->current_basic_block;
+ if (peer_parent->peers.length > 0) {
+ peer_parent->peers.last()->next_bb = prong_block;
+ }
+ peer_parent->peers.append(this_peer_result_loc);
ir_set_cursor_at_end_and_append_block(irb, prong_block);
if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
is_comptime, var_is_comptime, target_value_ptr, items, prong_item_count,
- &incoming_blocks, &incoming_values, nullptr))
+ &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base))
{
return irb->codegen->invalid_instruction;
}
@@ -6686,38 +7393,57 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
}
- IrInstruction *switch_prongs_void = ir_build_check_switch_prongs(irb, scope, node, target_value, check_ranges.items, check_ranges.length,
- else_prong != nullptr);
+ IrInstruction *switch_prongs_void = ir_build_check_switch_prongs(irb, scope, node, target_value,
+ check_ranges.items, check_ranges.length, else_prong != nullptr);
+ IrInstruction *br_instruction;
if (cases.length == 0) {
- ir_build_br(irb, scope, node, else_block, is_comptime);
+ br_instruction = ir_build_br(irb, scope, node, else_block, is_comptime);
} else {
IrInstructionSwitchBr *switch_br = ir_build_switch_br(irb, scope, node, target_value, else_block,
cases.length, cases.items, is_comptime, switch_prongs_void);
if (switch_else_var != nullptr) {
switch_else_var->switch_br = switch_br;
}
+ br_instruction = &switch_br->base;
+ }
+ if (peer_parent->base.source_instruction == nullptr) {
+ peer_parent->base.source_instruction = br_instruction;
+ }
+ for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
+ peer_parent->peers.at(i)->base.source_instruction = peer_parent->base.source_instruction;
}
if (!else_prong) {
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = else_block;
+ }
ir_set_cursor_at_end_and_append_block(irb, else_block);
ir_build_unreachable(irb, scope, node);
+ } else {
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = end_block;
+ }
}
ir_set_cursor_at_end_and_append_block(irb, end_block);
assert(incoming_blocks.length == incoming_values.length);
+ IrInstruction *result_instruction;
if (incoming_blocks.length == 0) {
- return ir_build_const_void(irb, scope, node);
+ result_instruction = ir_build_const_void(irb, scope, node);
} else {
- return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);
+ result_instruction = ir_build_phi(irb, scope, node, incoming_blocks.length,
+ incoming_blocks.items, incoming_values.items, peer_parent);
}
+ return ir_lval_wrap(irb, scope, result_instruction, lval, result_loc);
}
static IrInstruction *ir_gen_comptime(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval) {
assert(node->type == NodeTypeCompTime);
Scope *child_scope = create_comptime_scope(irb->codegen, node, parent_scope);
- return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval);
+ // purposefully pass null for result_loc and let EndExpr handle it
+ return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr);
}
static IrInstruction *ir_gen_return_from_block(IrBuilder *irb, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) {
@@ -6730,7 +7456,11 @@ static IrInstruction *ir_gen_return_from_block(IrBuilder *irb, Scope *break_scop
IrInstruction *result_value;
if (node->data.break_expr.expr) {
- result_value = ir_gen_node(irb, node->data.break_expr.expr, break_scope);
+ ResultLocPeer *peer_result = create_peer_result(block_scope->peer_parent);
+ block_scope->peer_parent->peers.append(peer_result);
+
+ result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope, block_scope->lval,
+ &peer_result->base);
if (result_value == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
} else {
@@ -6800,7 +7530,11 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode *
IrInstruction *result_value;
if (node->data.break_expr.expr) {
- result_value = ir_gen_node(irb, node->data.break_expr.expr, break_scope);
+ ResultLocPeer *peer_result = create_peer_result(loop_scope->peer_parent);
+ loop_scope->peer_parent->peers.append(peer_result);
+
+ result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope,
+ loop_scope->lval, &peer_result->base);
if (result_value == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
} else {
@@ -6888,7 +7622,7 @@ static IrInstruction *ir_gen_defer(IrBuilder *irb, Scope *parent_scope, AstNode
return ir_build_const_void(irb, parent_scope, node);
}
-static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node) {
+static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) {
assert(node->type == NodeTypeSliceExpr);
AstNodeSliceExpr *slice_expr = &node->data.slice_expr;
@@ -6896,7 +7630,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)
AstNode *start_node = slice_expr->start;
AstNode *end_node = slice_expr->end;
- IrInstruction *ptr_value = ir_gen_node_extra(irb, array_node, scope, LValPtr);
+ IrInstruction *ptr_value = ir_gen_node_extra(irb, array_node, scope, LValPtr, nullptr);
if (ptr_value == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
@@ -6913,11 +7647,14 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)
end_value = nullptr;
}
- return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, true);
+ IrInstruction *slice = ir_build_slice_src(irb, scope, node, ptr_value, start_value, end_value, true, result_loc);
+ return ir_lval_wrap(irb, scope, slice, lval, result_loc);
}
-static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
- assert(node->type == NodeTypeUnwrapErrorExpr);
+static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval,
+ ResultLoc *result_loc)
+{
+ assert(node->type == NodeTypeCatchExpr);
AstNode *op1_node = node->data.unwrap_err_expr.op1;
AstNode *op2_node = node->data.unwrap_err_expr.op2;
@@ -6930,16 +7667,15 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name)));
return irb->codegen->invalid_instruction;
}
- return ir_gen_catch_unreachable(irb, parent_scope, node, op1_node, LValNone);
+ return ir_gen_catch_unreachable(irb, parent_scope, node, op1_node, lval, result_loc);
}
- IrInstruction *err_union_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr);
+ IrInstruction *err_union_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr, nullptr);
if (err_union_ptr == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
- IrInstruction *err_union_val = ir_build_load_ptr(irb, parent_scope, node, err_union_ptr);
- IrInstruction *is_err = ir_build_test_err(irb, parent_scope, node, err_union_val);
+ IrInstruction *is_err = ir_build_test_err_src(irb, parent_scope, node, err_union_ptr, true);
IrInstruction *is_comptime;
if (ir_should_inline(irb->exec, parent_scope)) {
@@ -6951,33 +7687,38 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
IrBasicBlock *ok_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrOk");
IrBasicBlock *err_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrError");
IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrEnd");
- ir_build_cond_br(irb, parent_scope, node, is_err, err_block, ok_block, is_comptime);
+ IrInstruction *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_err, err_block, ok_block, is_comptime);
+
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, ok_block, end_block, result_loc,
+ is_comptime);
ir_set_cursor_at_end_and_append_block(irb, err_block);
+ Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, parent_scope, is_comptime);
Scope *err_scope;
if (var_node) {
assert(var_node->type == NodeTypeSymbol);
Buf *var_name = var_node->data.symbol_expr.symbol;
bool is_const = true;
bool is_shadowable = false;
- ZigVar *var = ir_create_var(irb, node, parent_scope, var_name,
+ ZigVar *var = ir_create_var(irb, node, subexpr_scope, var_name,
is_const, is_const, is_shadowable, is_comptime);
err_scope = var->child_scope;
- IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);
- ir_build_var_decl_src(irb, err_scope, var_node, var, nullptr, nullptr, err_val);
+ IrInstruction *err_ptr = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);
+ ir_build_var_decl_src(irb, err_scope, var_node, var, nullptr, err_ptr);
} else {
- err_scope = parent_scope;
+ err_scope = subexpr_scope;
}
- IrInstruction *err_result = ir_gen_node(irb, op2_node, err_scope);
+ IrInstruction *err_result = ir_gen_node_extra(irb, op2_node, err_scope, LValNone, &peer_parent->peers.at(0)->base);
if (err_result == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
IrBasicBlock *after_err_block = irb->current_basic_block;
if (!instr_is_unreachable(err_result))
- ir_mark_gen(ir_build_br(irb, err_scope, node, end_block, is_comptime));
+ ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));
ir_set_cursor_at_end_and_append_block(irb, ok_block);
- IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, parent_scope, node, err_union_ptr, false);
+ IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, parent_scope, node, err_union_ptr, false, false);
IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
+ ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base);
IrBasicBlock *after_ok_block = irb->current_basic_block;
ir_build_br(irb, parent_scope, node, end_block, is_comptime);
@@ -6988,7 +7729,8 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);
incoming_blocks[0] = after_err_block;
incoming_blocks[1] = after_ok_block;
- return ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values);
+ IrInstruction *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent);
+ return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc);
}
static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *outer_scope, Scope *inner_scope) {
@@ -7264,7 +8006,7 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode
IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
- atomic_state_field_name);
+ atomic_state_field_name, false);
// set the is_canceled bit
IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
@@ -7343,7 +8085,7 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode
IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
- atomic_state_field_name);
+ atomic_state_field_name, false);
// clear the is_suspended bit
IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
@@ -7410,12 +8152,12 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, target_inst);
Buf *result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);
- IrInstruction *result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_ptr_field_name);
+ IrInstruction *result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_ptr_field_name, false);
if (irb->codegen->have_err_ret_tracing) {
IrInstruction *err_ret_trace_ptr = ir_build_error_return_trace(irb, scope, node, IrInstructionErrorReturnTrace::NonNull);
Buf *err_ret_trace_ptr_field_name = buf_create_from_str(ERR_RET_TRACE_PTR_FIELD_NAME);
- IrInstruction *err_ret_trace_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr_field_name);
+ IrInstruction *err_ret_trace_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr_field_name, false);
ir_build_store_ptr(irb, scope, node, err_ret_trace_ptr_field_ptr, err_ret_trace_ptr);
}
@@ -7437,11 +8179,11 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
- atomic_state_field_name);
+ atomic_state_field_name, false);
IrInstruction *promise_type_val = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_promise);
IrInstruction *const_bool_false = ir_build_const_bool(irb, scope, node, false);
- IrInstruction *undefined_value = ir_build_const_undefined(irb, scope, node);
+ IrInstruction *undef = ir_build_const_undefined(irb, scope, node);
IrInstruction *usize_type_val = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_usize);
IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
IrInstruction *inverted_ptr_mask = ir_build_const_usize(irb, scope, node, 0x7); // 0b111
@@ -7455,7 +8197,8 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst);
IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type);
ir_build_await_bookkeeping(irb, scope, node, promise_result_type);
- ir_build_var_decl_src(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value);
+ IrInstruction *undef_promise_result = ir_build_implicit_cast(irb, scope, node, promise_result_type, undef, nullptr);
+ build_decl_var_and_init(irb, scope, node, result_var, undef_promise_result, "result", const_bool_false);
IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var);
ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr);
IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle);
@@ -7490,12 +8233,12 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
ir_set_cursor_at_end_and_append_block(irb, no_suspend_block);
if (irb->codegen->have_err_ret_tracing) {
Buf *err_ret_trace_field_name = buf_create_from_str(ERR_RET_TRACE_FIELD_NAME);
- IrInstruction *src_err_ret_trace_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_field_name);
+ IrInstruction *src_err_ret_trace_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_field_name, false);
IrInstruction *dest_err_ret_trace_ptr = ir_build_error_return_trace(irb, scope, node, IrInstructionErrorReturnTrace::NonNull);
ir_build_merge_err_ret_traces(irb, scope, node, coro_promise_ptr, src_err_ret_trace_ptr, dest_err_ret_trace_ptr);
}
Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);
- IrInstruction *promise_result_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name);
+ IrInstruction *promise_result_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name, false);
// If the type of the result handle_is_ptr then this does not actually perform a load. But we need it to,
// because we're about to destroy the memory. So we store it into our result variable.
IrInstruction *no_suspend_result = ir_build_load_ptr(irb, scope, node, promise_result_ptr);
@@ -7671,7 +8414,8 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod
incoming_values[0] = const_bool_true;
incoming_blocks[1] = post_cancel_awaiter_block;
incoming_values[1] = const_bool_false;
- IrInstruction *destroy_ourselves = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values);
+ IrInstruction *destroy_ourselves = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values,
+ nullptr);
ir_gen_defers_for_block(irb, parent_scope, outer_scope, true);
ir_mark_gen(ir_build_cond_br(irb, parent_scope, node, destroy_ourselves, irb->exec->coro_final_cleanup_block, irb->exec->coro_early_final, const_bool_false));
@@ -7680,7 +8424,7 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod
}
static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope,
- LVal lval)
+ LVal lval, ResultLoc *result_loc)
{
assert(scope);
switch (node->type) {
@@ -7694,37 +8438,37 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
case NodeTypeTestDecl:
zig_unreachable();
case NodeTypeBlock:
- return ir_lval_wrap(irb, scope, ir_gen_block(irb, scope, node), lval);
+ return ir_gen_block(irb, scope, node, lval, result_loc);
case NodeTypeGroupedExpr:
- return ir_gen_node_raw(irb, node->data.grouped_expr, scope, lval);
+ return ir_gen_node_raw(irb, node->data.grouped_expr, scope, lval, result_loc);
case NodeTypeBinOpExpr:
- return ir_lval_wrap(irb, scope, ir_gen_bin_op(irb, scope, node), lval);
+ return ir_gen_bin_op(irb, scope, node, lval, result_loc);
case NodeTypeIntLiteral:
- return ir_lval_wrap(irb, scope, ir_gen_int_lit(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_int_lit(irb, scope, node), lval, result_loc);
case NodeTypeFloatLiteral:
- return ir_lval_wrap(irb, scope, ir_gen_float_lit(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_float_lit(irb, scope, node), lval, result_loc);
case NodeTypeCharLiteral:
- return ir_lval_wrap(irb, scope, ir_gen_char_lit(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_char_lit(irb, scope, node), lval, result_loc);
case NodeTypeSymbol:
- return ir_gen_symbol(irb, scope, node, lval);
+ return ir_gen_symbol(irb, scope, node, lval, result_loc);
case NodeTypeFnCallExpr:
- return ir_gen_fn_call(irb, scope, node, lval);
+ return ir_gen_fn_call(irb, scope, node, lval, result_loc);
case NodeTypeIfBoolExpr:
- return ir_lval_wrap(irb, scope, ir_gen_if_bool_expr(irb, scope, node), lval);
+ return ir_gen_if_bool_expr(irb, scope, node, lval, result_loc);
case NodeTypePrefixOpExpr:
- return ir_gen_prefix_op_expr(irb, scope, node, lval);
+ return ir_gen_prefix_op_expr(irb, scope, node, lval, result_loc);
case NodeTypeContainerInitExpr:
- return ir_lval_wrap(irb, scope, ir_gen_container_init_expr(irb, scope, node), lval);
+ return ir_gen_container_init_expr(irb, scope, node, lval, result_loc);
case NodeTypeVariableDeclaration:
- return ir_lval_wrap(irb, scope, ir_gen_var_decl(irb, scope, node), lval);
+ return ir_gen_var_decl(irb, scope, node);
case NodeTypeWhileExpr:
- return ir_lval_wrap(irb, scope, ir_gen_while_expr(irb, scope, node), lval);
+ return ir_gen_while_expr(irb, scope, node, lval, result_loc);
case NodeTypeForExpr:
- return ir_lval_wrap(irb, scope, ir_gen_for_expr(irb, scope, node), lval);
+ return ir_gen_for_expr(irb, scope, node, lval, result_loc);
case NodeTypeArrayAccessExpr:
- return ir_gen_array_access(irb, scope, node, lval);
+ return ir_gen_array_access(irb, scope, node, lval, result_loc);
case NodeTypeReturnExpr:
- return ir_gen_return(irb, scope, node, lval);
+ return ir_gen_return(irb, scope, node, lval, result_loc);
case NodeTypeFieldAccessExpr:
{
IrInstruction *ptr_instruction = ir_gen_field_access(irb, scope, node);
@@ -7733,86 +8477,89 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
if (lval == LValPtr)
return ptr_instruction;
- return ir_build_load_ptr(irb, scope, node, ptr_instruction);
+ IrInstruction *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction);
+ return ir_expr_wrap(irb, scope, load_ptr, result_loc);
}
case NodeTypePtrDeref: {
AstNode *expr_node = node->data.ptr_deref_expr.target;
- IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval);
+ IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval, nullptr);
if (value == irb->codegen->invalid_instruction)
return value;
// We essentially just converted any lvalue from &(x.*) to (&x).*;
// this inhibits checking that x is a pointer later, so we directly
// record whether the pointer check is needed
- return ir_build_un_op_lval(irb, scope, node, IrUnOpDereference, value, lval);
+ IrInstruction *un_op = ir_build_un_op_lval(irb, scope, node, IrUnOpDereference, value, lval, result_loc);
+ return ir_expr_wrap(irb, scope, un_op, result_loc);
}
case NodeTypeUnwrapOptional: {
AstNode *expr_node = node->data.unwrap_optional.expr;
- IrInstruction *maybe_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);
+ IrInstruction *maybe_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr);
if (maybe_ptr == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
- IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true);
+ IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true, false);
if (lval == LValPtr)
return unwrapped_ptr;
- return ir_build_load_ptr(irb, scope, node, unwrapped_ptr);
+ IrInstruction *load_ptr = ir_build_load_ptr(irb, scope, node, unwrapped_ptr);
+ return ir_expr_wrap(irb, scope, load_ptr, result_loc);
}
case NodeTypeBoolLiteral:
- return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval, result_loc);
case NodeTypeArrayType:
- return ir_lval_wrap(irb, scope, ir_gen_array_type(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_array_type(irb, scope, node), lval, result_loc);
case NodeTypePointerType:
- return ir_lval_wrap(irb, scope, ir_gen_pointer_type(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_pointer_type(irb, scope, node), lval, result_loc);
case NodeTypePromiseType:
- return ir_lval_wrap(irb, scope, ir_gen_promise_type(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_promise_type(irb, scope, node), lval, result_loc);
case NodeTypeStringLiteral:
- return ir_lval_wrap(irb, scope, ir_gen_string_literal(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_string_literal(irb, scope, node), lval, result_loc);
case NodeTypeUndefinedLiteral:
- return ir_lval_wrap(irb, scope, ir_gen_undefined_literal(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_undefined_literal(irb, scope, node), lval, result_loc);
case NodeTypeAsmExpr:
- return ir_lval_wrap(irb, scope, ir_gen_asm_expr(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_asm_expr(irb, scope, node), lval, result_loc);
case NodeTypeNullLiteral:
- return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval, result_loc);
case NodeTypeIfErrorExpr:
- return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval);
+ return ir_gen_if_err_expr(irb, scope, node, lval, result_loc);
case NodeTypeIfOptional:
- return ir_lval_wrap(irb, scope, ir_gen_if_optional_expr(irb, scope, node), lval);
+ return ir_gen_if_optional_expr(irb, scope, node, lval, result_loc);
case NodeTypeSwitchExpr:
- return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);
+ return ir_gen_switch_expr(irb, scope, node, lval, result_loc);
case NodeTypeCompTime:
- return ir_gen_comptime(irb, scope, node, lval);
+ return ir_expr_wrap(irb, scope, ir_gen_comptime(irb, scope, node, lval), result_loc);
case NodeTypeErrorType:
- return ir_lval_wrap(irb, scope, ir_gen_error_type(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_error_type(irb, scope, node), lval, result_loc);
case NodeTypeBreak:
- return ir_lval_wrap(irb, scope, ir_gen_break(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_break(irb, scope, node), lval, result_loc);
case NodeTypeContinue:
- return ir_lval_wrap(irb, scope, ir_gen_continue(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_continue(irb, scope, node), lval, result_loc);
case NodeTypeUnreachable:
- return ir_lval_wrap(irb, scope, ir_build_unreachable(irb, scope, node), lval);
+ return ir_build_unreachable(irb, scope, node);
case NodeTypeDefer:
- return ir_lval_wrap(irb, scope, ir_gen_defer(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_defer(irb, scope, node), lval, result_loc);
case NodeTypeSliceExpr:
- return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval);
- case NodeTypeUnwrapErrorExpr:
- return ir_lval_wrap(irb, scope, ir_gen_catch(irb, scope, node), lval);
+ return ir_gen_slice(irb, scope, node, lval, result_loc);
+ case NodeTypeCatchExpr:
+ return ir_gen_catch(irb, scope, node, lval, result_loc);
case NodeTypeContainerDecl:
- return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval, result_loc);
case NodeTypeFnProto:
- return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval, result_loc);
case NodeTypeErrorSetDecl:
- return ir_lval_wrap(irb, scope, ir_gen_err_set_decl(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_err_set_decl(irb, scope, node), lval, result_loc);
case NodeTypeCancel:
- return ir_lval_wrap(irb, scope, ir_gen_cancel(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_cancel(irb, scope, node), lval, result_loc);
case NodeTypeResume:
- return ir_lval_wrap(irb, scope, ir_gen_resume(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_resume(irb, scope, node), lval, result_loc);
case NodeTypeAwaitExpr:
- return ir_lval_wrap(irb, scope, ir_gen_await_expr(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_await_expr(irb, scope, node), lval, result_loc);
case NodeTypeSuspend:
- return ir_lval_wrap(irb, scope, ir_gen_suspend(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_suspend(irb, scope, node), lval, result_loc);
case NodeTypeEnumLiteral:
- return ir_lval_wrap(irb, scope, ir_gen_enum_literal(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_enum_literal(irb, scope, node), lval, result_loc);
case NodeTypeInferredArrayType:
add_node_error(irb->codegen, node,
buf_sprintf("inferred array size invalid here"));
@@ -7821,14 +8568,28 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
zig_unreachable();
}
-static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval) {
- IrInstruction *result = ir_gen_node_raw(irb, node, scope, lval);
+static ResultLoc *no_result_loc(void) {
+ ResultLocNone *result_loc_none = allocate<ResultLocNone>(1);
+ result_loc_none->base.id = ResultLocIdNone;
+ return &result_loc_none->base;
+}
+
+static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval,
+ ResultLoc *result_loc)
+{
+ if (result_loc == nullptr) {
+ // Create a result location indicating there is none - but if one gets created
+ // it will be properly distributed.
+ result_loc = no_result_loc();
+ ir_build_reset_result(irb, scope, node, result_loc);
+ }
+ IrInstruction *result = ir_gen_node_raw(irb, node, scope, lval, result_loc);
irb->exec->invalid = irb->exec->invalid || (result == irb->codegen->invalid_instruction);
return result;
}
static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope) {
- return ir_gen_node_extra(irb, node, scope, LValNone);
+ return ir_gen_node_extra(irb, node, scope, LValNone, nullptr);
}
static void invalidate_exec(IrExecutable *exec) {
@@ -7879,17 +8640,19 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
return_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
IrInstruction *undef = ir_build_const_undefined(irb, coro_scope, node);
+ // TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa
ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type);
IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);
- // TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa
- ir_build_var_decl_src(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef);
+ IrInstruction *undef_coro_frame = ir_build_implicit_cast(irb, coro_scope, node, coro_frame_type_value, undef, nullptr);
+ build_decl_var_and_init(irb, coro_scope, node, promise_var, undef_coro_frame, "promise", const_bool_false);
coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var);
ZigVar *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);
IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,
get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
- ir_build_var_decl_src(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value);
+ IrInstruction *null_await_handle = ir_build_implicit_cast(irb, coro_scope, node, await_handle_type_val, null_value, nullptr);
+ build_decl_var_and_init(irb, coro_scope, node, await_handle_var, null_await_handle, "await_handle", const_bool_false);
irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var);
u8_ptr_type = ir_build_const_type(irb, coro_scope, node,
@@ -7899,13 +8662,14 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);
coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);
- ir_build_var_decl_src(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size);
+ build_decl_var_and_init(irb, coro_scope, node, coro_size_var, coro_size, "coro_size", const_bool_false);
IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node,
ImplicitAllocatorIdArg);
irb->exec->coro_allocator_var = ir_create_var(irb, node, coro_scope, nullptr, true, true, true, const_bool_false);
- ir_build_var_decl_src(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);
+ build_decl_var_and_init(irb, coro_scope, node, irb->exec->coro_allocator_var, implicit_allocator_ptr,
+ "allocator", const_bool_false);
Buf *realloc_field_name = buf_create_from_str(ASYNC_REALLOC_FIELD_NAME);
- IrInstruction *realloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, realloc_field_name);
+ IrInstruction *realloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, realloc_field_name, false);
IrInstruction *realloc_fn = ir_build_load_ptr(irb, coro_scope, node, realloc_fn_ptr);
IrInstruction *maybe_coro_mem_ptr = ir_build_coro_alloc_helper(irb, coro_scope, node, realloc_fn, coro_size);
IrInstruction *alloc_result_is_ok = ir_build_test_nonnull(irb, coro_scope, node, maybe_coro_mem_ptr);
@@ -7925,32 +8689,32 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
irb->exec->atomic_state_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
- atomic_state_field_name);
+ atomic_state_field_name, false);
IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
ir_build_store_ptr(irb, scope, node, irb->exec->atomic_state_field_ptr, zero);
Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);
- irb->exec->coro_result_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name);
+ irb->exec->coro_result_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name, false);
result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);
- irb->exec->coro_result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_ptr_field_name);
+ irb->exec->coro_result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_ptr_field_name, false);
ir_build_store_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr, irb->exec->coro_result_field_ptr);
if (irb->codegen->have_err_ret_tracing) {
// initialize the error return trace
Buf *return_addresses_field_name = buf_create_from_str(RETURN_ADDRESSES_FIELD_NAME);
- IrInstruction *return_addresses_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, return_addresses_field_name);
+ IrInstruction *return_addresses_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, return_addresses_field_name, false);
Buf *err_ret_trace_field_name = buf_create_from_str(ERR_RET_TRACE_FIELD_NAME);
- err_ret_trace_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_field_name);
+ err_ret_trace_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_field_name, false);
ir_build_mark_err_ret_trace_ptr(irb, scope, node, err_ret_trace_ptr);
// coordinate with builtin.zig
Buf *index_name = buf_create_from_str("index");
- IrInstruction *index_ptr = ir_build_field_ptr(irb, scope, node, err_ret_trace_ptr, index_name);
+ IrInstruction *index_ptr = ir_build_field_ptr(irb, scope, node, err_ret_trace_ptr, index_name, false);
ir_build_store_ptr(irb, scope, node, index_ptr, zero);
Buf *instruction_addresses_name = buf_create_from_str("instruction_addresses");
- IrInstruction *addrs_slice_ptr = ir_build_field_ptr(irb, scope, node, err_ret_trace_ptr, instruction_addresses_name);
+ IrInstruction *addrs_slice_ptr = ir_build_field_ptr(irb, scope, node, err_ret_trace_ptr, instruction_addresses_name, false);
- IrInstruction *slice_value = ir_build_slice(irb, scope, node, return_addresses_ptr, zero, nullptr, false);
+ IrInstruction *slice_value = ir_build_slice_src(irb, scope, node, return_addresses_ptr, zero, nullptr, false, no_result_loc());
ir_build_store_ptr(irb, scope, node, addrs_slice_ptr, slice_value);
}
@@ -7961,7 +8725,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
irb->exec->coro_final_cleanup_block = ir_create_basic_block(irb, scope, "FinalCleanup");
}
- IrInstruction *result = ir_gen_node_extra(irb, node, scope, LValNone);
+ IrInstruction *result = ir_gen_node_extra(irb, node, scope, LValNone, nullptr);
assert(result);
if (irb->exec->invalid)
return false;
@@ -8009,7 +8773,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
}
if (irb->codegen->have_err_ret_tracing) {
Buf *err_ret_trace_ptr_field_name = buf_create_from_str(ERR_RET_TRACE_PTR_FIELD_NAME);
- IrInstruction *err_ret_trace_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr_field_name);
+ IrInstruction *err_ret_trace_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr_field_name, false);
IrInstruction *dest_err_ret_trace_ptr = ir_build_load_ptr(irb, scope, node, err_ret_trace_ptr_field_ptr);
ir_build_merge_err_ret_traces(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr, dest_err_ret_trace_ptr);
}
@@ -8017,7 +8781,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
// a register or local variable which does not get spilled into the frame,
// otherwise llvm tries to access memory inside the destroyed frame.
IrInstruction *unwrapped_await_handle_ptr = ir_build_optional_unwrap_ptr(irb, scope, node,
- irb->exec->await_handle_var_ptr, false);
+ irb->exec->await_handle_var_ptr, false, false);
IrInstruction *await_handle_in_block = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);
ir_build_br(irb, scope, node, check_free_block, const_bool_false);
@@ -8031,7 +8795,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
incoming_values[0] = const_bool_false;
incoming_blocks[1] = irb->exec->coro_normal_final;
incoming_values[1] = const_bool_true;
- IrInstruction *resume_awaiter = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
+ IrInstruction *resume_awaiter = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr);
IrBasicBlock **merge_incoming_blocks = allocate<IrBasicBlock *>(2);
IrInstruction **merge_incoming_values = allocate<IrInstruction *>(2);
@@ -8039,12 +8803,12 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
merge_incoming_values[0] = ir_build_const_undefined(irb, scope, node);
merge_incoming_blocks[1] = irb->exec->coro_normal_final;
merge_incoming_values[1] = await_handle_in_block;
- IrInstruction *awaiter_handle = ir_build_phi(irb, scope, node, 2, merge_incoming_blocks, merge_incoming_values);
+ IrInstruction *awaiter_handle = ir_build_phi(irb, scope, node, 2, merge_incoming_blocks, merge_incoming_values, nullptr);
Buf *shrink_field_name = buf_create_from_str(ASYNC_SHRINK_FIELD_NAME);
IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node,
ImplicitAllocatorIdLocalVar);
- IrInstruction *shrink_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, shrink_field_name);
+ IrInstruction *shrink_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, shrink_field_name, false);
IrInstruction *shrink_fn = ir_build_load_ptr(irb, scope, node, shrink_fn_ptr);
IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
IrInstruction *coro_mem_ptr_maybe = ir_build_coro_free(irb, scope, node, coro_id, irb->exec->coro_handle);
@@ -8056,7 +8820,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);
- IrInstruction *mem_slice = ir_build_slice(irb, scope, node, coro_mem_ptr_ref, zero, coro_size, false);
+ IrInstruction *mem_slice = ir_build_slice_src(irb, scope, node, coro_mem_ptr_ref, zero, coro_size, false,
+ no_result_loc());
size_t arg_count = 5;
IrInstruction **args = allocate<IrInstruction *>(arg_count);
args[0] = implicit_allocator_ptr; // self
@@ -8070,7 +8835,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
// non-allocating. Basically coroutines are not supported right now until they are reworked.
args[3] = ir_build_const_usize(irb, scope, node, 1); // new_size
args[4] = ir_build_const_usize(irb, scope, node, 1); // new_align
- ir_build_call(irb, scope, node, nullptr, shrink_fn, arg_count, args, false, FnInlineAuto, false, nullptr, nullptr);
+ ir_build_call_src(irb, scope, node, nullptr, shrink_fn, arg_count, args, false, FnInlineAuto, false, nullptr,
+ nullptr, no_result_loc());
IrBasicBlock *resume_block = ir_create_basic_block(irb, scope, "Resume");
ir_build_cond_br(irb, scope, node, resume_awaiter, resume_block, irb->exec->coro_suspend_block, const_bool_false);
@@ -8177,6 +8943,15 @@ static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec
}
return &value->value;
} else if (ir_has_side_effects(instruction)) {
+ if (instr_is_comptime(instruction)) {
+ switch (instruction->id) {
+ case IrInstructionIdUnwrapErrPayload:
+ case IrInstructionIdUnionFieldPtr:
+ continue;
+ default:
+ break;
+ }
+ }
exec_add_error_node(codegen, exec, instruction->source_node,
buf_sprintf("unable to evaluate constant expression"));
return &codegen->invalid_instruction->value;
@@ -9154,15 +9929,6 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
return false;
}
-static bool is_slice(ZigType *type) {
- return type->id == ZigTypeIdStruct && type->data.structure.is_slice;
-}
-
-static bool slice_is_const(ZigType *type) {
- assert(is_slice(type));
- return type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;
-}
-
static bool is_tagged_union(ZigType *type) {
if (type->id != ZigTypeIdUnion)
return false;
@@ -9533,9 +10299,21 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
{
Error err;
assert(instruction_count >= 1);
- IrInstruction *prev_inst = instructions[0];
- if (type_is_invalid(prev_inst->value.type)) {
- return ira->codegen->builtin_types.entry_invalid;
+ IrInstruction *prev_inst;
+ size_t i = 0;
+ for (;;) {
+ prev_inst = instructions[i];
+ if (type_is_invalid(prev_inst->value.type)) {
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+ if (prev_inst->value.type->id == ZigTypeIdUnreachable) {
+ i += 1;
+ if (i == instruction_count) {
+ return prev_inst->value.type;
+ }
+ continue;
+ }
+ break;
}
ErrorTableEntry **errors = nullptr;
size_t errors_count = 0;
@@ -9560,7 +10338,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
bool any_are_null = (prev_inst->value.type->id == ZigTypeIdNull);
bool convert_to_const_slice = false;
- for (size_t i = 1; i < instruction_count; i += 1) {
+ for (; i < instruction_count; i += 1) {
IrInstruction *cur_inst = instructions[i];
ZigType *cur_type = cur_inst->value.type;
ZigType *prev_type = prev_inst->value.type;
@@ -9579,7 +10357,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
}
if (prev_type->id == ZigTypeIdErrorSet) {
- assert(err_set_type != nullptr);
+ ir_assert(err_set_type != nullptr, prev_inst);
if (cur_type->id == ZigTypeIdErrorSet) {
if (type_is_global_error_set(err_set_type)) {
continue;
@@ -9839,6 +10617,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
if (prev_type->id == ZigTypeIdNull) {
prev_inst = cur_inst;
+ any_are_null = true;
continue;
}
@@ -10153,6 +10932,8 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
} else if (prev_inst->value.type->id == ZigTypeIdOptional) {
return prev_inst->value.type;
} else {
+ if ((err = type_resolve(ira->codegen, prev_inst->value.type, ResolveStatusSizeKnown)))
+ return ira->codegen->builtin_types.entry_invalid;
return get_optional_type(ira->codegen, prev_inst->value.type);
}
} else {
@@ -10160,24 +10941,18 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
}
}
-static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry) {
- if (type_has_bits(type_entry) && handle_is_ptr(type_entry)) {
- ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
- if (fn_entry != nullptr) {
- fn_entry->alloca_list.append(instruction);
- }
- }
-}
-
static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs) {
ConstGlobalRefs *global_refs = dest->global_refs;
- assert(!same_global_refs || src->global_refs != nullptr);
- *dest = *src;
+ memcpy(dest, src, sizeof(ConstExprValue));
if (!same_global_refs) {
dest->global_refs = global_refs;
+ if (src->special == ConstValSpecialUndef)
+ return;
if (dest->type->id == ZigTypeIdStruct) {
- dest->data.x_struct.fields = allocate_nonzero<ConstExprValue>(dest->type->data.structure.src_field_count);
- memcpy(dest->data.x_struct.fields, src->data.x_struct.fields, sizeof(ConstExprValue) * dest->type->data.structure.src_field_count);
+ dest->data.x_struct.fields = create_const_vals(dest->type->data.structure.src_field_count);
+ for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) {
+ copy_const_val(&dest->data.x_struct.fields[i], &src->data.x_struct.fields[i], false);
+ }
}
}
}
@@ -10195,7 +10970,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
zig_unreachable();
case CastOpErrSet:
case CastOpBitCast:
- case CastOpPtrOfArrayToSlice:
zig_panic("TODO");
case CastOpNoop:
{
@@ -10295,7 +11069,7 @@ static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, Z
}
static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
- ZigType *wanted_type, CastOp cast_op, bool need_alloca)
+ ZigType *wanted_type, CastOp cast_op)
{
if (instr_is_comptime(value) || !type_has_bits(wanted_type)) {
IrInstruction *result = ir_const(ira, source_instr, wanted_type);
@@ -10308,9 +11082,6 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst
} else {
IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node, wanted_type, value, cast_op);
result->value.type = wanted_type;
- if (need_alloca) {
- ir_add_alloca(ira, result, wanted_type);
- }
return result;
}
}
@@ -10352,7 +11123,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
}
static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr,
- IrInstruction *value, ZigType *wanted_type)
+ IrInstruction *value, ZigType *wanted_type, ResultLoc *result_loc)
{
Error err;
@@ -10383,11 +11154,12 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
}
}
- IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node,
- wanted_type, value, CastOpPtrOfArrayToSlice);
- result->value.type = wanted_type;
- ir_add_alloca(ira, result, wanted_type);
- return result;
+ if (result_loc == nullptr) result_loc = no_result_loc();
+ IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);
+ if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
+ return result_loc_inst;
+ }
+ return ir_build_ptr_of_array_to_slice(ira, source_instr, wanted_type, value, result_loc_inst);
}
static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) {
@@ -10419,51 +11191,136 @@ static IrBasicBlock *ir_get_new_bb_runtime(IrAnalyze *ira, IrBasicBlock *old_bb,
}
static void ir_start_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrBasicBlock *const_predecessor_bb) {
+ ir_assert(!old_bb->suspended, old_bb->instruction_list.at(0));
ira->instruction_index = 0;
ira->old_irb.current_basic_block = old_bb;
ira->const_predecessor_bb = const_predecessor_bb;
+ ira->old_bb_index = old_bb->index;
}
-static void ir_finish_bb(IrAnalyze *ira) {
- ira->new_irb.exec->basic_block_list.append(ira->new_irb.current_basic_block);
- ira->instruction_index += 1;
- while (ira->instruction_index < ira->old_irb.current_basic_block->instruction_list.length) {
- IrInstruction *next_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);
- if (!next_instruction->is_gen) {
- ir_add_error(ira, next_instruction, buf_sprintf("unreachable code"));
- break;
- }
- ira->instruction_index += 1;
+static IrInstruction *ira_suspend(IrAnalyze *ira, IrInstruction *old_instruction, IrBasicBlock *next_bb,
+ IrSuspendPosition *suspend_pos)
+{
+ if (ira->codegen->verbose_ir) {
+ fprintf(stderr, "suspend %s_%zu %s_%zu #%zu (%zu,%zu)\n", ira->old_irb.current_basic_block->name_hint,
+ ira->old_irb.current_basic_block->debug_id,
+ ira->old_irb.exec->basic_block_list.at(ira->old_bb_index)->name_hint,
+ ira->old_irb.exec->basic_block_list.at(ira->old_bb_index)->debug_id,
+ ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index)->debug_id,
+ ira->old_bb_index, ira->instruction_index);
+ }
+ suspend_pos->basic_block_index = ira->old_bb_index;
+ suspend_pos->instruction_index = ira->instruction_index;
+
+ ira->old_irb.current_basic_block->suspended = true;
+
+ // null next_bb means that the caller plans to call ira_resume before returning
+ if (next_bb != nullptr) {
+ ira->old_bb_index = next_bb->index;
+ ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(ira->old_bb_index);
+ assert(ira->old_irb.current_basic_block == next_bb);
+ ira->instruction_index = 0;
+ ira->const_predecessor_bb = nullptr;
+ next_bb->other = ir_get_new_bb_runtime(ira, next_bb, old_instruction);
+ ira->new_irb.current_basic_block = next_bb->other;
}
+ return ira->codegen->unreach_instruction;
+}
+
+static IrInstruction *ira_resume(IrAnalyze *ira) {
+ IrSuspendPosition pos = ira->resume_stack.pop();
+ if (ira->codegen->verbose_ir) {
+ fprintf(stderr, "resume (%zu,%zu) ", pos.basic_block_index, pos.instruction_index);
+ }
+ ira->old_bb_index = pos.basic_block_index;
+ ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(ira->old_bb_index);
+ assert(ira->old_irb.current_basic_block->in_resume_stack);
+ ira->old_irb.current_basic_block->in_resume_stack = false;
+ ira->old_irb.current_basic_block->suspended = false;
+ ira->instruction_index = pos.instruction_index;
+ assert(pos.instruction_index < ira->old_irb.current_basic_block->instruction_list.length);
+ if (ira->codegen->verbose_ir) {
+ fprintf(stderr, "%s_%zu #%zu\n", ira->old_irb.current_basic_block->name_hint,
+ ira->old_irb.current_basic_block->debug_id,
+ ira->old_irb.current_basic_block->instruction_list.at(pos.instruction_index)->debug_id);
+ }
+ ira->const_predecessor_bb = nullptr;
+ ira->new_irb.current_basic_block = ira->old_irb.current_basic_block->other;
+ assert(ira->new_irb.current_basic_block != nullptr);
+ return ira->codegen->unreach_instruction;
+}
- size_t my_old_bb_index = ira->old_bb_index;
+static void ir_start_next_bb(IrAnalyze *ira) {
ira->old_bb_index += 1;
bool need_repeat = true;
for (;;) {
while (ira->old_bb_index < ira->old_irb.exec->basic_block_list.length) {
IrBasicBlock *old_bb = ira->old_irb.exec->basic_block_list.at(ira->old_bb_index);
- if (old_bb->other == nullptr) {
+ if (old_bb->other == nullptr && old_bb->suspend_instruction_ref == nullptr) {
ira->old_bb_index += 1;
continue;
}
- if (old_bb->other->instruction_list.length != 0 || ira->old_bb_index == my_old_bb_index) {
+ // if it's already started, or
+ // if it's a suspended block,
+ // then skip it
+ if (old_bb->suspended ||
+ (old_bb->other != nullptr && old_bb->other->instruction_list.length != 0) ||
+ (old_bb->other != nullptr && old_bb->other->already_appended))
+ {
ira->old_bb_index += 1;
continue;
}
- ira->new_irb.current_basic_block = old_bb->other;
+ // if there is a resume_stack, pop one from there rather than moving on.
+ // the last item of the resume stack will be a basic block that will
+ // move on to the next one below
+ if (ira->resume_stack.length != 0) {
+ ira_resume(ira);
+ return;
+ }
+
+ if (old_bb->other == nullptr) {
+ old_bb->other = ir_get_new_bb_runtime(ira, old_bb, old_bb->suspend_instruction_ref);
+ }
+ ira->new_irb.current_basic_block = old_bb->other;
ir_start_bb(ira, old_bb, nullptr);
return;
}
- if (!need_repeat)
+ if (!need_repeat) {
+ if (ira->resume_stack.length != 0) {
+ ira_resume(ira);
+ }
return;
+ }
need_repeat = false;
ira->old_bb_index = 0;
continue;
}
}
+static void ir_finish_bb(IrAnalyze *ira) {
+ if (!ira->new_irb.current_basic_block->already_appended) {
+ ira->new_irb.current_basic_block->already_appended = true;
+ if (ira->codegen->verbose_ir) {
+ fprintf(stderr, "append new bb %s_%zu\n", ira->new_irb.current_basic_block->name_hint,
+ ira->new_irb.current_basic_block->debug_id);
+ }
+ ira->new_irb.exec->basic_block_list.append(ira->new_irb.current_basic_block);
+ }
+ ira->instruction_index += 1;
+ while (ira->instruction_index < ira->old_irb.current_basic_block->instruction_list.length) {
+ IrInstruction *next_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);
+ if (!next_instruction->is_gen) {
+ ir_add_error(ira, next_instruction, buf_sprintf("unreachable code"));
+ break;
+ }
+ ira->instruction_index += 1;
+ }
+
+ ir_start_next_bb(ira);
+}
+
static IrInstruction *ir_unreach_error(IrAnalyze *ira) {
ira->old_bb_index = SIZE_MAX;
ira->new_irb.exec->invalid = true;
@@ -10524,6 +11381,12 @@ static IrInstruction *ir_const_undef(IrAnalyze *ira, IrInstruction *source_instr
return result;
}
+static IrInstruction *ir_const_unreachable(IrAnalyze *ira, IrInstruction *source_instruction) {
+ IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_unreachable);
+ result->value.special = ConstValSpecialStatic;
+ return result;
+}
+
static IrInstruction *ir_const_void(IrAnalyze *ira, IrInstruction *source_instruction) {
return ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_void);
}
@@ -10721,7 +11584,7 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
}
static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
- ZigType *wanted_type)
+ ZigType *wanted_type, ResultLoc *result_loc)
{
assert(wanted_type->id == ZigTypeIdOptional);
@@ -10747,20 +11610,29 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so
return &const_instruction->base;
}
- IrInstruction *result = ir_build_maybe_wrap(&ira->new_irb, source_instr->scope, source_instr->source_node, value);
- result->value.type = wanted_type;
+ if (result_loc == nullptr && handle_is_ptr(wanted_type)) {
+ result_loc = no_result_loc();
+ }
+ IrInstruction *result_loc_inst = nullptr;
+ if (result_loc != nullptr) {
+ result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);
+ if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
+ return result_loc_inst;
+ }
+ }
+ IrInstruction *result = ir_build_optional_wrap(ira, source_instr, wanted_type, value, result_loc_inst);
result->value.data.rh_maybe = RuntimeHintOptionalNonNull;
- ir_add_alloca(ira, result, wanted_type);
return result;
}
static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction *source_instr,
- IrInstruction *value, ZigType *wanted_type)
+ IrInstruction *value, ZigType *wanted_type, ResultLoc *result_loc)
{
assert(wanted_type->id == ZigTypeIdErrorUnion);
+ ZigType *payload_type = wanted_type->data.error_union.payload_type;
+ ZigType *err_set_type = wanted_type->data.error_union.err_set_type;
if (instr_is_comptime(value)) {
- ZigType *payload_type = wanted_type->data.error_union.payload_type;
IrInstruction *casted_payload = ir_implicit_cast(ira, value, payload_type);
if (type_is_invalid(casted_payload->value.type))
return ira->codegen->invalid_instruction;
@@ -10770,7 +11642,7 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
return ira->codegen->invalid_instruction;
ConstExprValue *err_set_val = create_const_vals(1);
- err_set_val->type = wanted_type->data.error_union.err_set_type;
+ err_set_val->type = err_set_type;
err_set_val->special = ConstValSpecialStatic;
err_set_val->data.x_err_set = nullptr;
@@ -10783,10 +11655,19 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
return &const_instruction->base;
}
- IrInstruction *result = ir_build_err_wrap_payload(&ira->new_irb, source_instr->scope, source_instr->source_node, value);
- result->value.type = wanted_type;
+ IrInstruction *result_loc_inst;
+ if (handle_is_ptr(wanted_type)) {
+ if (result_loc == nullptr) result_loc = no_result_loc();
+ result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);
+ if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
+ return result_loc_inst;
+ }
+ } else {
+ result_loc_inst = nullptr;
+ }
+
+ IrInstruction *result = ir_build_err_wrap_payload(ira, source_instr, wanted_type, value, result_loc_inst);
result->value.data.rh_error_union = RuntimeHintErrorUnionNonError;
- ir_add_alloca(ira, result, wanted_type);
return result;
}
@@ -10833,7 +11714,9 @@ static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *sou
return result;
}
-static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, ZigType *wanted_type) {
+static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
+ ZigType *wanted_type, ResultLoc *result_loc)
+{
assert(wanted_type->id == ZigTypeIdErrorUnion);
IrInstruction *casted_value = ir_implicit_cast(ira, value, wanted_type->data.error_union.err_set_type);
@@ -10857,10 +11740,20 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so
return &const_instruction->base;
}
- IrInstruction *result = ir_build_err_wrap_code(&ira->new_irb, source_instr->scope, source_instr->source_node, value);
- result->value.type = wanted_type;
+ IrInstruction *result_loc_inst;
+ if (handle_is_ptr(wanted_type)) {
+ if (result_loc == nullptr) result_loc = no_result_loc();
+ result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);
+ if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
+ return result_loc_inst;
+ }
+ } else {
+ result_loc_inst = nullptr;
+ }
+
+
+ IrInstruction *result = ir_build_err_wrap_code(ira, source_instr, wanted_type, value, result_loc_inst);
result->value.data.rh_error_union = RuntimeHintErrorUnionError;
- ir_add_alloca(ira, result, wanted_type);
return result;
}
@@ -10920,20 +11813,21 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type,
is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
- IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope,
- source_instruction->source_node, value, is_const, is_volatile);
- new_instruction->value.type = ptr_type;
- new_instruction->value.data.rh_ptr = RuntimeHintPtrStack;
+
+ IrInstruction *result_loc;
if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) {
- ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
- assert(fn_entry);
- fn_entry->alloca_list.append(new_instruction);
+ result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), value->value.type, nullptr, true, false);
+ } else {
+ result_loc = nullptr;
}
+
+ IrInstruction *new_instruction = ir_build_ref_gen(ira, source_instruction, ptr_type, value, result_loc);
+ new_instruction->value.data.rh_ptr = RuntimeHintPtrStack;
return new_instruction;
}
static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr,
- IrInstruction *array_arg, ZigType *wanted_type)
+ IrInstruction *array_arg, ZigType *wanted_type, ResultLoc *result_loc)
{
assert(is_slice(wanted_type));
// In this function we honor the const-ness of wanted_type, because
@@ -10942,7 +11836,7 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
IrInstruction *array_ptr = nullptr;
IrInstruction *array;
if (array_arg->value.type->id == ZigTypeIdPointer) {
- array = ir_get_deref(ira, source_instr, array_arg);
+ array = ir_get_deref(ira, source_instr, array_arg, nullptr);
array_ptr = array_arg;
} else {
array = array_arg;
@@ -10965,12 +11859,14 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false);
- IrInstruction *result = ir_build_slice(&ira->new_irb, source_instr->scope,
- source_instr->source_node, array_ptr, start, end, false);
- result->value.type = wanted_type;
+ if (result_loc == nullptr) result_loc = no_result_loc();
+ IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);
+ if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
+ return result_loc_inst;
+ }
+ IrInstruction *result = ir_build_slice_gen(ira, source_instr, wanted_type, array_ptr, start, end, false, result_loc_inst);
result->value.data.rh_slice.id = RuntimeHintSliceIdLen;
result->value.data.rh_slice.len = array_type->data.array.len;
- ir_add_alloca(ira, result, result->value.type);
return result;
}
@@ -11608,7 +12504,7 @@ static IrInstruction *ir_analyze_array_to_vector(IrAnalyze *ira, IrInstruction *
}
static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *source_instr,
- IrInstruction *vector, ZigType *array_type)
+ IrInstruction *vector, ZigType *array_type, ResultLoc *result_loc)
{
if (instr_is_comptime(vector)) {
// arrays and vectors have the same ConstExprValue representation
@@ -11617,7 +12513,14 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *
result->value.type = array_type;
return result;
}
- return ir_build_vector_to_array(ira, source_instr, vector, array_type);
+ if (result_loc == nullptr) {
+ result_loc = no_result_loc();
+ }
+ IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, array_type, nullptr, true, false);
+ if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
+ return result_loc_inst;
+ }
+ return ir_build_vector_to_array(ira, source_instr, array_type, vector, result_loc_inst);
}
static IrInstruction *ir_analyze_int_to_c_ptr(IrAnalyze *ira, IrInstruction *source_instr,
@@ -11667,7 +12570,7 @@ static bool is_pointery_and_elem_is_not_pointery(ZigType *ty) {
}
static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
- ZigType *wanted_type, IrInstruction *value)
+ ZigType *wanted_type, IrInstruction *value, ResultLoc *result_loc)
{
Error err;
ZigType *actual_type = value->value.type;
@@ -11683,7 +12586,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
if (const_cast_result.id == ConstCastResultIdInvalid)
return ira->codegen->invalid_instruction;
if (const_cast_result.id == ConstCastResultIdOk) {
- return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);
+ return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop);
}
// cast from T to ?T
@@ -11693,12 +12596,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,
false).id == ConstCastResultIdOk)
{
- return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type);
+ return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type, result_loc);
} else if (actual_type->id == ZigTypeIdComptimeInt ||
actual_type->id == ZigTypeIdComptimeFloat)
{
if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {
- return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type);
+ return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type, result_loc);
} else {
return ira->codegen->invalid_instruction;
}
@@ -11722,7 +12625,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
wanted_child_type);
if (type_is_invalid(cast1->value.type))
return ira->codegen->invalid_instruction;
- return ir_analyze_optional_wrap(ira, source_instr, cast1, wanted_type);
+ return ir_analyze_optional_wrap(ira, source_instr, cast1, wanted_type, result_loc);
}
}
}
@@ -11732,12 +12635,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type,
source_node, false).id == ConstCastResultIdOk)
{
- return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
+ return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type, result_loc);
} else if (actual_type->id == ZigTypeIdComptimeInt ||
actual_type->id == ZigTypeIdComptimeFloat)
{
if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) {
- return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
+ return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type, result_loc);
} else {
return ira->codegen->invalid_instruction;
}
@@ -11755,11 +12658,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
actual_type->id == ZigTypeIdComptimeInt ||
actual_type->id == ZigTypeIdComptimeFloat)
{
- IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value);
+ IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value, nullptr);
if (type_is_invalid(cast1->value.type))
return ira->codegen->invalid_instruction;
- IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
+ IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1, result_loc);
if (type_is_invalid(cast2->value.type))
return ira->codegen->invalid_instruction;
@@ -11841,7 +12744,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
source_node, false).id == ConstCastResultIdOk)
{
- return ir_analyze_array_to_slice(ira, source_instr, value, wanted_type);
+ return ir_analyze_array_to_slice(ira, source_instr, value, wanted_type, result_loc);
}
}
@@ -11858,11 +12761,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
source_node, false).id == ConstCastResultIdOk)
{
- IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.maybe.child_type, value);
+ IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.maybe.child_type, value, nullptr);
if (type_is_invalid(cast1->value.type))
return ira->codegen->invalid_instruction;
- IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
+ IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1, result_loc);
if (type_is_invalid(cast2->value.type))
return ira->codegen->invalid_instruction;
@@ -11870,9 +12773,9 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
}
}
- // *[N]T to [*]T
+ // *[N]T to [*]T and [*c]T
if (wanted_type->id == ZigTypeIdPointer &&
- wanted_type->data.pointer.ptr_len == PtrLenUnknown &&
+ (wanted_type->data.pointer.ptr_len == PtrLenUnknown || wanted_type->data.pointer.ptr_len == PtrLenC) &&
actual_type->id == ZigTypeIdPointer &&
actual_type->data.pointer.ptr_len == PtrLenSingle &&
actual_type->data.pointer.child_type->id == ZigTypeIdArray)
@@ -11905,7 +12808,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
array_type->data.array.child_type, source_node,
!slice_ptr_type->data.pointer.is_const).id == ConstCastResultIdOk)
{
- return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, wanted_type);
+ return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, wanted_type, result_loc);
}
}
@@ -11936,11 +12839,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
source_node, false).id == ConstCastResultIdOk)
{
- IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value);
+ IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value, nullptr);
if (type_is_invalid(cast1->value.type))
return ira->codegen->invalid_instruction;
- IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
+ IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1, result_loc);
if (type_is_invalid(cast2->value.type))
return ira->codegen->invalid_instruction;
@@ -11952,7 +12855,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
if (wanted_type->id == ZigTypeIdErrorUnion &&
actual_type->id == ZigTypeIdErrorSet)
{
- return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type);
+ return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type, result_loc);
}
// cast from typed number to integer or float literal.
@@ -12076,7 +12979,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
types_match_const_cast_only(ira, wanted_type->data.array.child_type,
actual_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk)
{
- return ir_analyze_vector_to_array(ira, source_instr, value, wanted_type);
+ return ir_analyze_vector_to_array(ira, source_instr, value, wanted_type, result_loc);
}
// cast from [N]T to @Vector(N, T)
@@ -12118,7 +13021,9 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
return ira->codegen->invalid_instruction;
}
-static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type) {
+static IrInstruction *ir_implicit_cast_with_result(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type,
+ ResultLoc *result_loc)
+{
assert(value);
assert(value != ira->codegen->invalid_instruction);
assert(!expected_type || !type_is_invalid(expected_type));
@@ -12131,63 +13036,76 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Zig
if (value->value.type->id == ZigTypeIdUnreachable)
return value;
- return ir_analyze_cast(ira, value, expected_type, value);
+ return ir_analyze_cast(ira, value, expected_type, value, result_loc);
}
-static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr) {
+static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type) {
+ return ir_implicit_cast_with_result(ira, value, expected_type, nullptr);
+}
+
+static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr,
+ ResultLoc *result_loc)
+{
Error err;
ZigType *type_entry = ptr->value.type;
- if (type_is_invalid(type_entry)) {
+ if (type_is_invalid(type_entry))
return ira->codegen->invalid_instruction;
- } else if (type_entry->id == ZigTypeIdPointer) {
- ZigType *child_type = type_entry->data.pointer.child_type;
- // if the child type has one possible value, the deref is comptime
- switch (type_has_one_possible_value(ira->codegen, child_type)) {
- case OnePossibleValueInvalid:
- return ira->codegen->invalid_instruction;
- case OnePossibleValueYes:
- return ir_const(ira, source_instruction, child_type);
- case OnePossibleValueNo:
- break;
+
+ if (type_entry->id != ZigTypeIdPointer) {
+ ir_add_error_node(ira, source_instruction->source_node,
+ buf_sprintf("attempt to dereference non-pointer type '%s'",
+ buf_ptr(&type_entry->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ ZigType *child_type = type_entry->data.pointer.child_type;
+ // if the child type has one possible value, the deref is comptime
+ switch (type_has_one_possible_value(ira->codegen, child_type)) {
+ case OnePossibleValueInvalid:
+ return ira->codegen->invalid_instruction;
+ case OnePossibleValueYes:
+ return ir_const(ira, source_instruction, child_type);
+ case OnePossibleValueNo:
+ break;
+ }
+ if (instr_is_comptime(ptr)) {
+ if (ptr->value.special == ConstValSpecialUndef) {
+ ir_add_error(ira, ptr, buf_sprintf("attempt to dereference undefined value"));
+ return ira->codegen->invalid_instruction;
}
- if (instr_is_comptime(ptr)) {
- if (ptr->value.special == ConstValSpecialUndef) {
- ir_add_error(ira, ptr, buf_sprintf("attempt to dereference undefined value"));
- return ira->codegen->invalid_instruction;
- }
- if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst ||
- ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar)
- {
- ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
- if (pointee->special != ConstValSpecialRuntime) {
- IrInstruction *result = ir_const(ira, source_instruction, child_type);
+ if (ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {
+ ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
+ if (pointee->special != ConstValSpecialRuntime) {
+ IrInstruction *result = ir_const(ira, source_instruction, child_type);
- if ((err = ir_read_const_ptr(ira, ira->codegen, source_instruction->source_node, &result->value,
- &ptr->value)))
- {
- return ira->codegen->invalid_instruction;
- }
- result->value.type = child_type;
- return result;
+ if ((err = ir_read_const_ptr(ira, ira->codegen, source_instruction->source_node, &result->value,
+ &ptr->value)))
+ {
+ return ira->codegen->invalid_instruction;
}
+ result->value.type = child_type;
+ return result;
}
}
- // if the instruction is a const ref instruction we can skip it
- if (ptr->id == IrInstructionIdRef) {
- IrInstructionRef *ref_inst = reinterpret_cast<IrInstructionRef *>(ptr);
- return ref_inst->value;
- }
- IrInstruction *result = ir_build_load_ptr_gen(ira, source_instruction, ptr, child_type);
- if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) {
- ir_add_alloca(ira, result, child_type);
+ }
+ // if the instruction is a const ref instruction we can skip it
+ if (ptr->id == IrInstructionIdRef) {
+ IrInstructionRef *ref_inst = reinterpret_cast<IrInstructionRef *>(ptr);
+ return ref_inst->value;
+ }
+
+ IrInstruction *result_loc_inst;
+ if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) {
+ if (result_loc == nullptr) result_loc = no_result_loc();
+ result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr, true, false);
+ if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
+ return result_loc_inst;
}
- return result;
} else {
- ir_add_error_node(ira, source_instruction->source_node,
- buf_sprintf("attempt to dereference non-pointer type '%s'",
- buf_ptr(&type_entry->name)));
- return ira->codegen->invalid_instruction;
+ result_loc_inst = nullptr;
}
+
+ return ir_build_load_ptr_gen(ira, source_instruction, ptr, child_type, result_loc_inst);
}
static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out) {
@@ -12401,6 +13319,14 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio
if (type_is_invalid(value->value.type))
return ir_unreach_error(ira);
+ if (!instr_is_comptime(value) && handle_is_ptr(ira->explicit_return_type)) {
+ // result location mechanism took care of it.
+ IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope,
+ instruction->base.source_node, nullptr);
+ result->value.type = ira->codegen->builtin_types.entry_unreachable;
+ return ir_finish_anal(ira, result);
+ }
+
IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->explicit_return_type);
if (type_is_invalid(casted_value->value.type)) {
AstNode *source_node = ira->explicit_return_type_source_node;
@@ -12563,7 +13489,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
} else {
return is_non_null;
}
- } else if (is_equality_cmp &&
+ } else if (is_equality_cmp &&
((op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdPointer &&
op2->value.type->data.pointer.ptr_len == PtrLenC) ||
(op2->value.type->id == ZigTypeIdNull && op1->value.type->id == ZigTypeIdPointer &&
@@ -13005,7 +13931,7 @@ static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, IrInstruction *source_in
}
} else {
float_div_trunc(out_val, op1_val, op2_val);
- ConstExprValue remainder;
+ ConstExprValue remainder = {};
float_rem(&remainder, op1_val, op2_val);
if (float_cmp_zero(&remainder) != CmpEQ) {
return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder"));
@@ -13380,8 +14306,8 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
// have a remainder function ambiguity problem
ok = true;
} else {
- ConstExprValue rem_result;
- ConstExprValue mod_result;
+ ConstExprValue rem_result = {};
+ ConstExprValue mod_result = {};
float_rem(&rem_result, op1_val, op2_val);
float_mod(&mod_result, op1_val, op2_val);
ok = float_cmp(&rem_result, &mod_result) == CmpEQ;
@@ -13604,10 +14530,12 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
size_t next_index = 0;
for (size_t i = op1_array_index; i < op1_array_end; i += 1, next_index += 1) {
- out_array_val->data.x_array.data.s_none.elements[next_index] = op1_array_val->data.x_array.data.s_none.elements[i];
+ copy_const_val(&out_array_val->data.x_array.data.s_none.elements[next_index],
+ &op1_array_val->data.x_array.data.s_none.elements[i], true);
}
for (size_t i = op2_array_index; i < op2_array_end; i += 1, next_index += 1) {
- out_array_val->data.x_array.data.s_none.elements[next_index] = op2_array_val->data.x_array.data.s_none.elements[i];
+ copy_const_val(&out_array_val->data.x_array.data.s_none.elements[next_index],
+ &op2_array_val->data.x_array.data.s_none.elements[i], true);
}
if (next_index < new_len) {
ConstExprValue *null_byte = &out_array_val->data.x_array.data.s_none.elements[next_index];
@@ -13668,7 +14596,8 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
uint64_t i = 0;
for (uint64_t x = 0; x < mult_amt; x += 1) {
for (uint64_t y = 0; y < old_array_len; y += 1) {
- out_val->data.x_array.data.s_none.elements[i] = array_val->data.x_array.data.s_none.elements[y];
+ copy_const_val(&out_val->data.x_array.data.s_none.elements[i],
+ &array_val->data.x_array.data.s_none.elements[y], true);
i += 1;
}
}
@@ -13765,12 +14694,6 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
Error err;
ZigVar *var = decl_var_instruction->var;
- IrInstruction *init_value = decl_var_instruction->init_value->child;
- if (type_is_invalid(init_value->value.type)) {
- var->var_type = ira->codegen->builtin_types.entry_invalid;
- return ira->codegen->invalid_instruction;
- }
-
ZigType *explicit_type = nullptr;
IrInstruction *var_type = nullptr;
if (decl_var_instruction->var_type != nullptr) {
@@ -13785,18 +14708,40 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
AstNode *source_node = decl_var_instruction->base.source_node;
- IrInstruction *casted_init_value = ir_implicit_cast(ira, init_value, explicit_type);
bool is_comptime_var = ir_get_var_is_comptime(var);
bool var_class_requires_const = false;
- ZigType *result_type = casted_init_value->value.type;
+ IrInstruction *var_ptr = decl_var_instruction->ptr->child;
+ // if this is null, a compiler error happened and did not initialize the variable.
+ // if there are no compile errors there may be a missing ir_expr_wrap in pass1 IR generation.
+ if (var_ptr == nullptr || type_is_invalid(var_ptr->value.type)) {
+ ir_assert(var_ptr != nullptr || ira->codegen->errors.length != 0, &decl_var_instruction->base);
+ var->var_type = ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
+ }
+
+ // The ir_build_var_decl_src call is supposed to pass a pointer to the allocation, not an initialization value.
+ ir_assert(var_ptr->value.type->id == ZigTypeIdPointer, &decl_var_instruction->base);
+
+ ZigType *result_type = var_ptr->value.type->data.pointer.child_type;
if (type_is_invalid(result_type)) {
result_type = ira->codegen->builtin_types.entry_invalid;
} else if (result_type->id == ZigTypeIdUnreachable || result_type->id == ZigTypeIdOpaque) {
- ir_add_error_node(ira, source_node,
- buf_sprintf("variable of type '%s' not allowed", buf_ptr(&result_type->name)));
- result_type = ira->codegen->builtin_types.entry_invalid;
+ zig_unreachable();
+ }
+
+ ConstExprValue *init_val = nullptr;
+ if (instr_is_comptime(var_ptr) && var_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {
+ init_val = const_ptr_pointee(ira, ira->codegen, &var_ptr->value, decl_var_instruction->base.source_node);
+ if (is_comptime_var) {
+ if (var->gen_is_const) {
+ var->const_value = init_val;
+ } else {
+ var->const_value = create_const_vals(1);
+ copy_const_val(var->const_value, init_val, false);
+ }
+ }
}
switch (type_requires_comptime(ira->codegen, result_type)) {
@@ -13813,18 +14758,20 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
}
break;
case ReqCompTimeNo:
- if (casted_init_value->value.special == ConstValSpecialStatic &&
- casted_init_value->value.type->id == ZigTypeIdFn &&
- casted_init_value->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
- casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways)
- {
- var_class_requires_const = true;
- if (!var->src_is_const && !is_comptime_var) {
- ErrorMsg *msg = ir_add_error_node(ira, source_node,
- buf_sprintf("functions marked inline must be stored in const or comptime var"));
- AstNode *proto_node = casted_init_value->value.data.x_ptr.data.fn.fn_entry->proto_node;
- add_error_note(ira->codegen, msg, proto_node, buf_sprintf("declared here"));
- result_type = ira->codegen->builtin_types.entry_invalid;
+ if (init_val != nullptr) {
+ if (init_val->special == ConstValSpecialStatic &&
+ init_val->type->id == ZigTypeIdFn &&
+ init_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
+ init_val->data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways)
+ {
+ var_class_requires_const = true;
+ if (!var->src_is_const && !is_comptime_var) {
+ ErrorMsg *msg = ir_add_error_node(ira, source_node,
+ buf_sprintf("functions marked inline must be stored in const or comptime var"));
+ AstNode *proto_node = init_val->data.x_ptr.data.fn.fn_entry->proto_node;
+ add_error_note(ira->codegen, msg, proto_node, buf_sprintf("declared here"));
+ result_type = ira->codegen->builtin_types.entry_invalid;
+ }
}
}
break;
@@ -13871,11 +14818,29 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
}
}
- if (casted_init_value->value.special != ConstValSpecialRuntime) {
- if (var->mem_slot_index != SIZE_MAX) {
+ if (init_val != nullptr && init_val->special != ConstValSpecialRuntime) {
+ // Resolve ConstPtrMutInfer
+ if (var->gen_is_const) {
+ var_ptr->value.data.x_ptr.mut = ConstPtrMutComptimeConst;
+ } else if (is_comptime_var) {
+ var_ptr->value.data.x_ptr.mut = ConstPtrMutComptimeVar;
+ } else {
+ // we need a runtime ptr but we have a comptime val.
+ // since it's a comptime val there are no instructions for it.
+ // we memcpy the init value here
+ IrInstruction *deref = ir_get_deref(ira, var_ptr, var_ptr, nullptr);
+ // If this assertion trips, something is wrong with the IR instructions, because
+ // we expected the above deref to return a constant value, but it created a runtime
+ // instruction.
+ assert(deref->value.special != ConstValSpecialRuntime);
+ var_ptr->value.special = ConstValSpecialRuntime;
+ ir_analyze_store_ptr(ira, var_ptr, var_ptr, deref);
+ }
+
+ if (var_ptr->value.special == ConstValSpecialStatic && var->mem_slot_index != SIZE_MAX) {
assert(var->mem_slot_index < ira->exec_context.mem_slot_list.length);
ConstExprValue *mem_slot = ira->exec_context.mem_slot_list.at(var->mem_slot_index);
- copy_const_val(mem_slot, &casted_init_value->value, !is_comptime_var || var->gen_is_const);
+ copy_const_val(mem_slot, init_val, !is_comptime_var || var->gen_is_const);
if (is_comptime_var || (var_class_requires_const && var->gen_is_const)) {
return ir_const_void(ira, &decl_var_instruction->base);
@@ -13892,7 +14857,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
if (fn_entry)
fn_entry->variable_list.append(var);
- return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value);
+ return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, var_ptr);
}
static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {
@@ -14062,9 +15027,10 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
break;
}
} break;
+ case ZigTypeIdInt:
+ break;
case ZigTypeIdVoid:
case ZigTypeIdBool:
- case ZigTypeIdInt:
case ZigTypeIdFloat:
case ZigTypeIdPointer:
case ZigTypeIdComptimeFloat:
@@ -14186,7 +15152,7 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i
ZigVar *coro_allocator_var = ira->old_irb.exec->coro_allocator_var;
assert(coro_allocator_var != nullptr);
IrInstruction *var_ptr_inst = ir_get_var_ptr(ira, source_instr, coro_allocator_var);
- IrInstruction *result = ir_get_deref(ira, source_instr, var_ptr_inst);
+ IrInstruction *result = ir_get_deref(ira, source_instr, var_ptr_inst, nullptr);
assert(result->value.type != nullptr);
return result;
}
@@ -14194,7 +15160,436 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i
zig_unreachable();
}
-static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, ZigFn *fn_entry,
+static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_inst, ZigType *var_type,
+ uint32_t align, const char *name_hint, bool force_comptime)
+{
+ Error err;
+
+ ConstExprValue *pointee = create_const_vals(1);
+ pointee->special = ConstValSpecialUndef;
+
+ IrInstructionAllocaGen *result = ir_create_alloca_gen(ira, source_inst, align, name_hint);
+ result->base.value.special = ConstValSpecialStatic;
+ result->base.value.data.x_ptr.special = ConstPtrSpecialRef;
+ result->base.value.data.x_ptr.mut = force_comptime ? ConstPtrMutComptimeVar : ConstPtrMutInfer;
+ result->base.value.data.x_ptr.data.ref.pointee = pointee;
+
+ if ((err = type_resolve(ira->codegen, var_type, ResolveStatusZeroBitsKnown)))
+ return ira->codegen->invalid_instruction;
+ assert(result->base.value.data.x_ptr.special != ConstPtrSpecialInvalid);
+
+ pointee->type = var_type;
+ result->base.value.type = get_pointer_to_type_extra(ira->codegen, var_type, false, false,
+ PtrLenSingle, align, 0, 0, false);
+
+ ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
+ if (fn_entry != nullptr) {
+ fn_entry->alloca_gen_list.append(result);
+ }
+ result->base.is_gen = true;
+ return &result->base;
+}
+
+static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, IrInstruction *suspend_source_instr,
+ ResultLoc *result_loc)
+{
+ switch (result_loc->id) {
+ case ResultLocIdInvalid:
+ case ResultLocIdPeerParent:
+ zig_unreachable();
+ case ResultLocIdNone:
+ case ResultLocIdVar:
+ case ResultLocIdBitCast:
+ return nullptr;
+ case ResultLocIdInstruction:
+ return result_loc->source_instruction->child->value.type;
+ case ResultLocIdReturn:
+ return ira->explicit_return_type;
+ case ResultLocIdPeer:
+ return reinterpret_cast<ResultLocPeer*>(result_loc)->parent->resolved_type;
+ }
+ zig_unreachable();
+}
+
+static bool type_can_bit_cast(ZigType *t) {
+ switch (t->id) {
+ case ZigTypeIdInvalid:
+ zig_unreachable();
+ case ZigTypeIdMetaType:
+ case ZigTypeIdOpaque:
+ case ZigTypeIdBoundFn:
+ case ZigTypeIdArgTuple:
+ case ZigTypeIdUnreachable:
+ case ZigTypeIdComptimeFloat:
+ case ZigTypeIdComptimeInt:
+ case ZigTypeIdEnumLiteral:
+ case ZigTypeIdUndefined:
+ case ZigTypeIdNull:
+ case ZigTypeIdPointer:
+ return false;
+ default:
+ // TODO list these types out explicitly, there are probably some other invalid ones here
+ return true;
+ }
+}
+
+static void set_up_result_loc_for_inferred_comptime(IrInstruction *ptr) {
+ ConstExprValue *undef_child = create_const_vals(1);
+ undef_child->type = ptr->value.type->data.pointer.child_type;
+ undef_child->special = ConstValSpecialUndef;
+ ptr->value.special = ConstValSpecialStatic;
+ ptr->value.data.x_ptr.mut = ConstPtrMutInfer;
+ ptr->value.data.x_ptr.special = ConstPtrSpecialRef;
+ ptr->value.data.x_ptr.data.ref.pointee = undef_child;
+}
+
+// when calling this function, at the callsite must check for result type noreturn and propagate it up
+static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr,
+ ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime)
+{
+ Error err;
+ if (result_loc->resolved_loc != nullptr) {
+ // allow to redo the result location if the value is known and comptime and the previous one isn't
+ if (value == nullptr || !instr_is_comptime(value) || instr_is_comptime(result_loc->resolved_loc)) {
+ return result_loc->resolved_loc;
+ }
+ }
+ result_loc->gen_instruction = value;
+ result_loc->implicit_elem_type = value_type;
+ switch (result_loc->id) {
+ case ResultLocIdInvalid:
+ case ResultLocIdPeerParent:
+ zig_unreachable();
+ case ResultLocIdNone: {
+ if (value != nullptr) {
+ return nullptr;
+ }
+ // need to return a result location and don't have one. use a stack allocation
+ IrInstructionAllocaGen *alloca_gen = ir_create_alloca_gen(ira, suspend_source_instr, 0, "");
+ if ((err = type_resolve(ira->codegen, value_type, ResolveStatusZeroBitsKnown)))
+ return ira->codegen->invalid_instruction;
+ alloca_gen->base.value.type = get_pointer_to_type_extra(ira->codegen, value_type, false, false,
+ PtrLenSingle, 0, 0, 0, false);
+ set_up_result_loc_for_inferred_comptime(&alloca_gen->base);
+ ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
+ if (fn_entry != nullptr) {
+ fn_entry->alloca_gen_list.append(alloca_gen);
+ }
+ result_loc->written = true;
+ result_loc->resolved_loc = &alloca_gen->base;
+ return result_loc->resolved_loc;
+ }
+ case ResultLocIdVar: {
+ ResultLocVar *result_loc_var = reinterpret_cast<ResultLocVar *>(result_loc);
+ assert(result_loc->source_instruction->id == IrInstructionIdAllocaSrc);
+
+ if (value_type->id == ZigTypeIdUnreachable || value_type->id == ZigTypeIdOpaque) {
+ ir_add_error(ira, result_loc->source_instruction,
+ buf_sprintf("variable of type '%s' not allowed", buf_ptr(&value_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ IrInstructionAllocaSrc *alloca_src =
+ reinterpret_cast<IrInstructionAllocaSrc *>(result_loc->source_instruction);
+ bool force_comptime;
+ if (!ir_resolve_comptime(ira, alloca_src->is_comptime->child, &force_comptime))
+ return ira->codegen->invalid_instruction;
+ bool is_comptime = force_comptime || (value != nullptr &&
+ value->value.special != ConstValSpecialRuntime && result_loc_var->var->gen_is_const);
+
+ if (alloca_src->base.child == nullptr || is_comptime) {
+ uint32_t align = 0;
+ if (alloca_src->align != nullptr && !ir_resolve_align(ira, alloca_src->align->child, &align)) {
+ return ira->codegen->invalid_instruction;
+ }
+ IrInstruction *alloca_gen;
+ if (is_comptime && value != nullptr) {
+ if (align > value->value.global_refs->align) {
+ value->value.global_refs->align = align;
+ }
+ alloca_gen = ir_get_ref(ira, result_loc->source_instruction, value, true, false);
+ } else {
+ alloca_gen = ir_analyze_alloca(ira, result_loc->source_instruction, value_type, align,
+ alloca_src->name_hint, force_comptime);
+ }
+ if (alloca_src->base.child != nullptr) {
+ alloca_src->base.child->ref_count = 0;
+ }
+ alloca_src->base.child = alloca_gen;
+ }
+ result_loc->written = true;
+ result_loc->resolved_loc = is_comptime ? nullptr : alloca_src->base.child;
+ return result_loc->resolved_loc;
+ }
+ case ResultLocIdInstruction: {
+ result_loc->written = true;
+ result_loc->resolved_loc = result_loc->source_instruction->child;
+ return result_loc->resolved_loc;
+ }
+ case ResultLocIdReturn: {
+ if (!non_null_comptime) {
+ bool is_comptime = value != nullptr && value->value.special != ConstValSpecialRuntime;
+ if (is_comptime)
+ return nullptr;
+ }
+ if ((err = type_resolve(ira->codegen, ira->explicit_return_type, ResolveStatusZeroBitsKnown))) {
+ return ira->codegen->invalid_instruction;
+ }
+ if (!type_has_bits(ira->explicit_return_type) || !handle_is_ptr(ira->explicit_return_type))
+ return nullptr;
+
+ ZigType *ptr_return_type = get_pointer_to_type(ira->codegen, ira->explicit_return_type, false);
+ result_loc->written = true;
+ result_loc->resolved_loc = ir_build_return_ptr(ira, result_loc->source_instruction, ptr_return_type);
+ if (ir_should_inline(ira->old_irb.exec, result_loc->source_instruction->scope)) {
+ set_up_result_loc_for_inferred_comptime(result_loc->resolved_loc);
+ }
+ return result_loc->resolved_loc;
+ }
+ case ResultLocIdPeer: {
+ ResultLocPeer *result_peer = reinterpret_cast<ResultLocPeer *>(result_loc);
+ ResultLocPeerParent *peer_parent = result_peer->parent;
+
+ if (peer_parent->peers.length == 1) {
+ IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
+ value_type, value, force_runtime, non_null_comptime);
+ result_peer->suspend_pos.basic_block_index = SIZE_MAX;
+ result_peer->suspend_pos.instruction_index = SIZE_MAX;
+ if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
+ parent_result_loc->value.type->id == ZigTypeIdUnreachable)
+ {
+ return parent_result_loc;
+ }
+ result_loc->written = true;
+ result_loc->resolved_loc = parent_result_loc;
+ return result_loc->resolved_loc;
+ }
+
+ bool is_comptime;
+ if (!ir_resolve_comptime(ira, peer_parent->is_comptime->child, &is_comptime))
+ return ira->codegen->invalid_instruction;
+ peer_parent->skipped = is_comptime;
+ if (peer_parent->skipped) {
+ if (non_null_comptime) {
+ return ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
+ value_type, value, force_runtime, non_null_comptime);
+ }
+ return nullptr;
+ }
+
+ if (peer_parent->resolved_type == nullptr) {
+ if (peer_parent->end_bb->suspend_instruction_ref == nullptr) {
+ peer_parent->end_bb->suspend_instruction_ref = suspend_source_instr;
+ }
+ IrInstruction *unreach_inst = ira_suspend(ira, suspend_source_instr, result_peer->next_bb,
+ &result_peer->suspend_pos);
+ if (result_peer->next_bb == nullptr) {
+ ir_start_next_bb(ira);
+ }
+ return unreach_inst;
+ }
+
+ IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
+ peer_parent->resolved_type, nullptr, force_runtime, non_null_comptime);
+ if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
+ parent_result_loc->value.type->id == ZigTypeIdUnreachable)
+ {
+ return parent_result_loc;
+ }
+ // because is_comptime is false, we mark this a runtime pointer
+ parent_result_loc->value.special = ConstValSpecialRuntime;
+ result_loc->written = true;
+ result_loc->resolved_loc = parent_result_loc;
+ return result_loc->resolved_loc;
+ }
+ case ResultLocIdBitCast: {
+ ResultLocBitCast *result_bit_cast = reinterpret_cast<ResultLocBitCast *>(result_loc);
+ ZigType *dest_type = ir_resolve_type(ira, result_bit_cast->base.source_instruction->child);
+ if (type_is_invalid(dest_type))
+ return ira->codegen->invalid_instruction;
+
+ if (get_codegen_ptr_type(dest_type) != nullptr) {
+ ir_add_error(ira, result_loc->source_instruction,
+ buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ if (!type_can_bit_cast(dest_type)) {
+ ir_add_error(ira, result_loc->source_instruction,
+ buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ if (get_codegen_ptr_type(value_type) != nullptr) {
+ ir_add_error(ira, suspend_source_instr,
+ buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&value_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ if (!type_can_bit_cast(value_type)) {
+ ir_add_error(ira, suspend_source_instr,
+ buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&value_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ IrInstruction *bitcasted_value;
+ if (value != nullptr) {
+ bitcasted_value = ir_analyze_bit_cast(ira, result_loc->source_instruction, value, dest_type);
+ } else {
+ bitcasted_value = nullptr;
+ }
+
+ IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_bit_cast->parent,
+ dest_type, bitcasted_value, force_runtime, non_null_comptime);
+ if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
+ parent_result_loc->value.type->id == ZigTypeIdUnreachable)
+ {
+ return parent_result_loc;
+ }
+ ZigType *parent_ptr_type = parent_result_loc->value.type;
+ assert(parent_ptr_type->id == ZigTypeIdPointer);
+ if ((err = type_resolve(ira->codegen, parent_ptr_type->data.pointer.child_type,
+ ResolveStatusAlignmentKnown)))
+ {
+ return ira->codegen->invalid_instruction;
+ }
+ uint64_t parent_ptr_align = get_ptr_align(ira->codegen, parent_ptr_type);
+ ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value_type,
+ parent_ptr_type->data.pointer.is_const, parent_ptr_type->data.pointer.is_volatile, PtrLenSingle,
+ parent_ptr_align, 0, 0, parent_ptr_type->data.pointer.allow_zero);
+
+ result_loc->written = true;
+ result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr, parent_result_loc,
+ ptr_type, result_bit_cast->base.source_instruction, false);
+ return result_loc->resolved_loc;
+ }
+ }
+ zig_unreachable();
+}
+
+static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr,
+ ResultLoc *result_loc_pass1, ZigType *value_type, IrInstruction *value, bool force_runtime,
+ bool non_null_comptime)
+{
+ IrInstruction *result_loc = ir_resolve_result_raw(ira, suspend_source_instr, result_loc_pass1, value_type,
+ value, force_runtime, non_null_comptime);
+ if (result_loc == nullptr || (instr_is_unreachable(result_loc) || type_is_invalid(result_loc->value.type)))
+ return result_loc;
+
+ if ((force_runtime || (value != nullptr && !instr_is_comptime(value))) &&
+ result_loc_pass1->written && result_loc->value.data.x_ptr.mut == ConstPtrMutInfer)
+ {
+ result_loc->value.special = ConstValSpecialRuntime;
+ }
+
+ ir_assert(result_loc->value.type->id == ZigTypeIdPointer, suspend_source_instr);
+ ZigType *actual_elem_type = result_loc->value.type->data.pointer.child_type;
+ if (actual_elem_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional &&
+ value_type->id != ZigTypeIdNull)
+ {
+ return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true);
+ } else if (actual_elem_type->id == ZigTypeIdErrorUnion && value_type->id != ZigTypeIdErrorUnion) {
+ if (value_type->id == ZigTypeIdErrorSet) {
+ return ir_analyze_unwrap_err_code(ira, suspend_source_instr, result_loc, true);
+ } else {
+ IrInstruction *unwrapped_err_ptr = ir_analyze_unwrap_error_payload(ira, suspend_source_instr,
+ result_loc, false, true);
+ ZigType *actual_payload_type = actual_elem_type->data.error_union.payload_type;
+ if (actual_payload_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional) {
+ return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, unwrapped_err_ptr, false, true);
+ } else {
+ return unwrapped_err_ptr;
+ }
+ }
+ } else if (is_slice(actual_elem_type) && value_type->id == ZigTypeIdArray) {
+ // need to allow EndExpr to do the implicit cast from array to slice
+ result_loc_pass1->written = false;
+ }
+ return result_loc;
+}
+
+static IrInstruction *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, IrInstructionImplicitCast *instruction) {
+ ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
+ if (type_is_invalid(dest_type))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *target = instruction->target->child;
+ if (type_is_invalid(target->value.type))
+ return ira->codegen->invalid_instruction;
+
+ return ir_implicit_cast_with_result(ira, target, dest_type, instruction->result_loc);
+}
+
+static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrInstructionResolveResult *instruction) {
+ ZigType *implicit_elem_type = ir_resolve_type(ira, instruction->ty->child);
+ if (type_is_invalid(implicit_elem_type))
+ return ira->codegen->invalid_instruction;
+ IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
+ implicit_elem_type, nullptr, false, true);
+ if (result_loc != nullptr)
+ return result_loc;
+
+ ZigFn *fn = exec_fn_entry(ira->new_irb.exec);
+ if (fn != nullptr && fn->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync &&
+ instruction->result_loc->id == ResultLocIdReturn)
+ {
+ result_loc = ir_resolve_result(ira, &instruction->base, no_result_loc(),
+ implicit_elem_type, nullptr, false, true);
+ if (result_loc != nullptr &&
+ (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)))
+ {
+ return result_loc;
+ }
+ result_loc->value.special = ConstValSpecialRuntime;
+ return result_loc;
+ }
+
+ IrInstruction *result = ir_const(ira, &instruction->base, implicit_elem_type);
+ result->value.special = ConstValSpecialUndef;
+ IrInstruction *ptr = ir_get_ref(ira, &instruction->base, result, false, false);
+ ptr->value.data.x_ptr.mut = ConstPtrMutComptimeVar;
+ return ptr;
+}
+
+static void ir_reset_result(ResultLoc *result_loc) {
+ result_loc->written = false;
+ result_loc->resolved_loc = nullptr;
+ result_loc->gen_instruction = nullptr;
+ result_loc->implicit_elem_type = nullptr;
+ switch (result_loc->id) {
+ case ResultLocIdInvalid:
+ zig_unreachable();
+ case ResultLocIdPeerParent: {
+ ResultLocPeerParent *peer_parent = reinterpret_cast<ResultLocPeerParent *>(result_loc);
+ peer_parent->skipped = false;
+ peer_parent->done_resuming = false;
+ peer_parent->resolved_type = nullptr;
+ for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
+ ir_reset_result(&peer_parent->peers.at(i)->base);
+ }
+ break;
+ }
+ case ResultLocIdVar: {
+ IrInstructionAllocaSrc *alloca_src =
+ reinterpret_cast<IrInstructionAllocaSrc *>(result_loc->source_instruction);
+ alloca_src->base.child = nullptr;
+ break;
+ }
+ case ResultLocIdPeer:
+ case ResultLocIdNone:
+ case ResultLocIdReturn:
+ case ResultLocIdInstruction:
+ case ResultLocIdBitCast:
+ break;
+ }
+}
+
+static IrInstruction *ir_analyze_instruction_reset_result(IrAnalyze *ira, IrInstructionResetResult *instruction) {
+ ir_reset_result(instruction->result_loc);
+ 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,
IrInstruction *async_allocator_inst)
{
@@ -14202,7 +15597,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *c
ir_assert(async_allocator_inst->value.type->id == ZigTypeIdPointer, &call_instruction->base);
ZigType *container_type = async_allocator_inst->value.type->data.pointer.child_type;
IrInstruction *field_ptr_inst = ir_analyze_container_field_ptr(ira, realloc_field_name, &call_instruction->base,
- async_allocator_inst, container_type);
+ async_allocator_inst, container_type, false);
if (type_is_invalid(field_ptr_inst->value.type)) {
return ira->codegen->invalid_instruction;
}
@@ -14227,10 +15622,15 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *c
ZigType *promise_type = get_promise_type(ira->codegen, return_type);
ZigType *async_return_type = get_error_union_type(ira->codegen, alloc_fn_error_set_type, promise_type);
- IrInstruction *result = ir_build_call(&ira->new_irb, call_instruction->base.scope, call_instruction->base.source_node,
- fn_entry, fn_ref, arg_count, casted_args, false, FnInlineAuto, true, async_allocator_inst, nullptr);
- result->value.type = async_return_type;
- return result;
+ IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, no_result_loc(),
+ async_return_type, nullptr, true, true);
+ if (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, async_allocator_inst, nullptr, result_loc,
+ async_return_type);
}
static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,
@@ -14253,7 +15653,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node
casted_arg = arg;
}
- ConstExprValue *arg_val = ir_resolve_const(ira, casted_arg, UndefBad);
+ ConstExprValue *arg_val = ir_resolve_const(ira, casted_arg, UndefOk);
if (!arg_val)
return false;
@@ -14309,7 +15709,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
arg_val = create_const_runtime(casted_arg->value.type);
}
if (arg_part_of_generic_id) {
- generic_id->params[generic_id->param_count] = *arg_val;
+ copy_const_val(&generic_id->params[generic_id->param_count], arg_val, true);
generic_id->param_count += 1;
}
@@ -14480,7 +15880,9 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
return ira->codegen->invalid_instruction;
}
- if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) {
+ if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar ||
+ ptr->value.data.x_ptr.mut == ConstPtrMutInfer)
+ {
if (instr_is_comptime(value)) {
ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, source_instr->source_node);
if (dest_val == nullptr)
@@ -14494,18 +15896,24 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
// ConstPtrMutComptimeVar, thus defeating the logic below.
bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar;
copy_const_val(dest_val, &value->value, same_global_refs);
- if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
+ if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar &&
+ !ira->new_irb.current_basic_block->must_be_comptime_source_instr)
+ {
ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;
}
return ir_const_void(ira, source_instr);
}
}
- ir_add_error(ira, source_instr,
- buf_sprintf("cannot store runtime value in compile time variable"));
- ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
- dest_val->type = ira->codegen->builtin_types.entry_invalid;
+ if (ptr->value.data.x_ptr.mut == ConstPtrMutInfer) {
+ ptr->value.special = ConstValSpecialRuntime;
+ } else {
+ ir_add_error(ira, source_instr,
+ buf_sprintf("cannot store runtime value in compile time variable"));
+ ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
+ dest_val->type = ira->codegen->builtin_types.entry_invalid;
- return ira->codegen->invalid_instruction;
+ return ira->codegen->invalid_instruction;
+ }
}
}
@@ -14534,7 +15942,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
return result;
}
-static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction,
+static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,
ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)
{
@@ -14637,7 +16045,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
if (!first_arg_known_bare && handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) {
first_arg = first_arg_ptr;
} else {
- first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr);
+ first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr, nullptr);
if (type_is_invalid(first_arg->value.type))
return ira->codegen->invalid_instruction;
}
@@ -14796,7 +16204,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
if (!first_arg_known_bare && handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) {
first_arg = first_arg_ptr;
} else {
- first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr);
+ first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr, nullptr);
if (type_is_invalid(first_arg->value.type))
return ira->codegen->invalid_instruction;
}
@@ -14840,7 +16248,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
if (type_is_invalid(arg_var_ptr_inst->value.type))
return ira->codegen->invalid_instruction;
- IrInstruction *arg_tuple_arg = ir_get_deref(ira, arg, arg_var_ptr_inst);
+ IrInstruction *arg_tuple_arg = ir_get_deref(ira, arg, arg_var_ptr_inst, nullptr);
if (type_is_invalid(arg_tuple_arg->value.type))
return ira->codegen->invalid_instruction;
@@ -14889,7 +16297,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr);
IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);
- const_instruction->base.value = *align_result;
+ copy_const_val(&const_instruction->base.value, align_result, true);
uint32_t align_bytes = 0;
ir_resolve_align(ira, &const_instruction->base, &align_bytes);
@@ -14971,6 +16379,19 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
}
FnTypeId *impl_fn_type_id = &impl_fn->type_entry->data.fn.fn_type_id;
+ IrInstruction *result_loc;
+ if (handle_is_ptr(impl_fn_type_id->return_type)) {
+ result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
+ impl_fn_type_id->return_type, nullptr, true, true);
+ if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) ||
+ instr_is_unreachable(result_loc)))
+ {
+ return result_loc;
+ }
+ } else {
+ result_loc = nullptr;
+ }
+
if (fn_type_can_fail(impl_fn_type_id)) {
parent_fn_entry->calls_or_awaits_errorable_fn = true;
}
@@ -14979,18 +16400,14 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
if (call_instruction->is_async) {
IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,
fn_ref, casted_args, impl_param_count, async_allocator_inst);
- ir_add_alloca(ira, result, result->value.type);
return ir_finish_anal(ira, result);
}
assert(async_allocator_inst == nullptr);
- IrInstruction *new_call_instruction = ir_build_call(&ira->new_irb,
- call_instruction->base.scope, call_instruction->base.source_node,
- impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline,
- call_instruction->is_async, nullptr, casted_new_stack);
- new_call_instruction->value.type = impl_fn_type_id->return_type;
-
- ir_add_alloca(ira, new_call_instruction, impl_fn_type_id->return_type);
+ IrInstruction *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base,
+ impl_fn, nullptr, impl_param_count, casted_args, fn_inline,
+ call_instruction->is_async, nullptr, casted_new_stack, result_loc,
+ impl_fn_type_id->return_type);
return ir_finish_anal(ira, new_call_instruction);
}
@@ -15018,7 +16435,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
{
first_arg = first_arg_ptr;
} else {
- first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr);
+ first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr, nullptr);
if (type_is_invalid(first_arg->value.type))
return ira->codegen->invalid_instruction;
}
@@ -15075,7 +16492,6 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref,
casted_args, call_param_count, async_allocator_inst);
- ir_add_alloca(ira, result, result->value.type);
return ir_finish_anal(ira, result);
}
@@ -15085,15 +16501,24 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
return ira->codegen->invalid_instruction;
}
- IrInstruction *new_call_instruction = ir_build_call(&ira->new_irb,
- call_instruction->base.scope, call_instruction->base.source_node,
- fn_entry, fn_ref, call_param_count, casted_args, false, fn_inline, false, nullptr, casted_new_stack);
- new_call_instruction->value.type = return_type;
- ir_add_alloca(ira, new_call_instruction, return_type);
+ IrInstruction *result_loc;
+ if (handle_is_ptr(return_type)) {
+ result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
+ return_type, nullptr, true, true);
+ if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) {
+ return result_loc;
+ }
+ } else {
+ result_loc = nullptr;
+ }
+
+ IrInstruction *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref,
+ call_param_count, casted_args, fn_inline, false, nullptr, casted_new_stack,
+ result_loc, return_type);
return ir_finish_anal(ira, new_call_instruction);
}
-static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCall *call_instruction) {
+static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction) {
IrInstruction *fn_ref = call_instruction->fn_ref->child;
if (type_is_invalid(fn_ref->value.type))
return ira->codegen->invalid_instruction;
@@ -15117,7 +16542,8 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC
IrInstruction *arg = call_instruction->args[0]->child;
- IrInstruction *cast_instruction = ir_analyze_cast(ira, &call_instruction->base, dest_type, arg);
+ IrInstruction *cast_instruction = ir_analyze_cast(ira, &call_instruction->base, dest_type, arg,
+ call_instruction->result_loc);
if (type_is_invalid(cast_instruction->value.type))
return ira->codegen->invalid_instruction;
return ir_finish_anal(ira, cast_instruction);
@@ -15170,7 +16596,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
if (dst_size <= src_size) {
if (src_size == dst_size && types_have_same_zig_comptime_repr(pointee->type, out_val->type)) {
- copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut == ConstPtrMutComptimeConst);
+ copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut != ConstPtrMutComptimeVar);
return ErrorNone;
}
Buf buf = BUF_INIT;
@@ -15419,7 +16845,7 @@ static IrInstruction *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstruction
return ira->codegen->invalid_instruction;
}
- IrInstruction *result = ir_get_deref(ira, &instruction->base, ptr);
+ IrInstruction *result = ir_get_deref(ira, &instruction->base, ptr, instruction->result_loc);
if (result == ira->codegen->invalid_instruction)
return ira->codegen->invalid_instruction;
@@ -15438,6 +16864,19 @@ static IrInstruction *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstruction
zig_unreachable();
}
+static void ir_push_resume(IrAnalyze *ira, IrSuspendPosition pos) {
+ IrBasicBlock *old_bb = ira->old_irb.exec->basic_block_list.at(pos.basic_block_index);
+ if (old_bb->in_resume_stack) return;
+ ira->resume_stack.append(pos);
+ old_bb->in_resume_stack = true;
+}
+
+static void ir_push_resume_block(IrAnalyze *ira, IrBasicBlock *old_bb) {
+ if (ira->resume_stack.length != 0) {
+ ir_push_resume(ira, {old_bb->index, 0});
+ }
+}
+
static IrInstruction *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) {
IrBasicBlock *old_dest_block = br_instruction->dest_block;
@@ -15445,13 +16884,15 @@ static IrInstruction *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr
if (!ir_resolve_comptime(ira, br_instruction->is_comptime->child, &is_comptime))
return ir_unreach_error(ira);
- if (is_comptime || old_dest_block->ref_count == 1)
+ if (is_comptime || (old_dest_block->ref_count == 1 && old_dest_block->suspend_instruction_ref == nullptr))
return ir_inline_bb(ira, &br_instruction->base, old_dest_block);
IrBasicBlock *new_bb = ir_get_new_bb_runtime(ira, old_dest_block, &br_instruction->base);
if (new_bb == nullptr)
return ir_unreach_error(ira);
+ ir_push_resume_block(ira, old_dest_block);
+
IrInstruction *result = ir_build_br(&ira->new_irb,
br_instruction->base.scope, br_instruction->base.source_node, new_bb, nullptr);
result->value.type = ira->codegen->builtin_types.entry_unreachable;
@@ -15480,13 +16921,15 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi
IrBasicBlock *old_dest_block = cond_is_true ?
cond_br_instruction->then_block : cond_br_instruction->else_block;
- if (is_comptime || old_dest_block->ref_count == 1)
+ if (is_comptime || (old_dest_block->ref_count == 1 && old_dest_block->suspend_instruction_ref == nullptr))
return ir_inline_bb(ira, &cond_br_instruction->base, old_dest_block);
IrBasicBlock *new_dest_block = ir_get_new_bb_runtime(ira, old_dest_block, &cond_br_instruction->base);
if (new_dest_block == nullptr)
return ir_unreach_error(ira);
+ ir_push_resume_block(ira, old_dest_block);
+
IrInstruction *result = ir_build_br(&ira->new_irb,
cond_br_instruction->base.scope, cond_br_instruction->base.source_node, new_dest_block, nullptr);
result->value.type = ira->codegen->builtin_types.entry_unreachable;
@@ -15502,6 +16945,9 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi
if (new_else_block == nullptr)
return ir_unreach_error(ira);
+ ir_push_resume_block(ira, cond_br_instruction->else_block);
+ ir_push_resume_block(ira, cond_br_instruction->then_block);
+
IrInstruction *result = ir_build_cond_br(&ira->new_irb,
cond_br_instruction->base.scope, cond_br_instruction->base.source_node,
casted_condition, new_then_block, new_else_block, nullptr);
@@ -15540,6 +16986,80 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
zig_unreachable();
}
+ ResultLocPeerParent *peer_parent = phi_instruction->peer_parent;
+ if (peer_parent != nullptr && !peer_parent->skipped && !peer_parent->done_resuming &&
+ peer_parent->peers.length >= 2)
+ {
+ if (peer_parent->resolved_type == nullptr) {
+ IrInstruction **instructions = allocate<IrInstruction *>(peer_parent->peers.length);
+ for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
+ ResultLocPeer *this_peer = peer_parent->peers.at(i);
+
+ IrInstruction *gen_instruction = this_peer->base.gen_instruction;
+ if (gen_instruction == nullptr) {
+ // unreachable instructions will cause implicit_elem_type to be null
+ if (this_peer->base.implicit_elem_type == nullptr) {
+ instructions[i] = ir_const_unreachable(ira, this_peer->base.source_instruction);
+ } else {
+ instructions[i] = ir_const(ira, this_peer->base.source_instruction,
+ this_peer->base.implicit_elem_type);
+ instructions[i]->value.special = ConstValSpecialRuntime;
+ }
+ } else {
+ instructions[i] = gen_instruction;
+ }
+
+ }
+ ZigType *expected_type = ir_result_loc_expected_type(ira, &phi_instruction->base, peer_parent->parent);
+ peer_parent->resolved_type = ir_resolve_peer_types(ira,
+ peer_parent->base.source_instruction->source_node, expected_type, instructions,
+ peer_parent->peers.length);
+
+ // the logic below assumes there are no instructions in the new current basic block yet
+ ir_assert(ira->new_irb.current_basic_block->instruction_list.length == 0, &phi_instruction->base);
+
+ // In case resolving the parent activates a suspend, do it now
+ IrInstruction *parent_result_loc = ir_resolve_result(ira, &phi_instruction->base, peer_parent->parent,
+ peer_parent->resolved_type, nullptr, false, false);
+ if (parent_result_loc != nullptr &&
+ (type_is_invalid(parent_result_loc->value.type) || instr_is_unreachable(parent_result_loc)))
+ {
+ return parent_result_loc;
+ }
+ // If the above code generated any instructions in the current basic block, we need
+ // to move them to the peer parent predecessor.
+ ZigList<IrInstruction *> instrs_to_move = {};
+ while (ira->new_irb.current_basic_block->instruction_list.length != 0) {
+ instrs_to_move.append(ira->new_irb.current_basic_block->instruction_list.pop());
+ }
+ if (instrs_to_move.length != 0) {
+ IrBasicBlock *predecessor = peer_parent->base.source_instruction->child->owner_bb;
+ IrInstruction *branch_instruction = predecessor->instruction_list.pop();
+ ir_assert(branch_instruction->value.type->id == ZigTypeIdUnreachable, &phi_instruction->base);
+ while (instrs_to_move.length != 0) {
+ predecessor->instruction_list.append(instrs_to_move.pop());
+ }
+ predecessor->instruction_list.append(branch_instruction);
+ }
+ }
+
+ IrSuspendPosition suspend_pos;
+ ira_suspend(ira, &phi_instruction->base, nullptr, &suspend_pos);
+ ir_push_resume(ira, suspend_pos);
+
+ for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
+ ResultLocPeer *opposite_peer = peer_parent->peers.at(peer_parent->peers.length - i - 1);
+ if (opposite_peer->base.implicit_elem_type != nullptr &&
+ opposite_peer->base.implicit_elem_type->id != ZigTypeIdUnreachable)
+ {
+ ir_push_resume(ira, opposite_peer->suspend_pos);
+ }
+ }
+
+ peer_parent->done_resuming = true;
+ return ira_resume(ira);
+ }
+
ZigList<IrBasicBlock*> new_incoming_blocks = {0};
ZigList<IrInstruction*> new_incoming_values = {0};
@@ -15609,10 +17129,11 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
for (size_t i = 0; i < new_incoming_values.length; i += 1) {
IrInstruction *new_value = new_incoming_values.at(i);
IrBasicBlock *predecessor = new_incoming_blocks.at(i);
+ ir_assert(predecessor->instruction_list.length != 0, &phi_instruction->base);
IrInstruction *branch_instruction = predecessor->instruction_list.pop();
ir_set_cursor_at_end(&ira->new_irb, predecessor);
IrInstruction *casted_value = ir_implicit_cast(ira, new_value, resolved_type);
- if (casted_value == ira->codegen->invalid_instruction) {
+ if (type_is_invalid(casted_value->value.type)) {
return ira->codegen->invalid_instruction;
}
new_incoming_values.items[i] = casted_value;
@@ -15628,7 +17149,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
IrInstruction *result = ir_build_phi(&ira->new_irb,
phi_instruction->base.scope, phi_instruction->base.source_node,
- new_incoming_blocks.length, new_incoming_blocks.items, new_incoming_values.items);
+ new_incoming_blocks.length, new_incoming_blocks.items, new_incoming_values.items, nullptr);
result->value.type = resolved_type;
if (all_stack_ptrs) {
@@ -15846,6 +17367,52 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
if (array_ptr_val == nullptr)
return ira->codegen->invalid_instruction;
+ if (array_ptr_val->special == ConstValSpecialUndef && elem_ptr_instruction->init_array_type != nullptr) {
+ if (array_type->id == ZigTypeIdArray) {
+ array_ptr_val->data.x_array.special = ConstArraySpecialNone;
+ array_ptr_val->data.x_array.data.s_none.elements = create_const_vals(array_type->data.array.len);
+ array_ptr_val->special = ConstValSpecialStatic;
+ for (size_t i = 0; i < array_type->data.array.len; i += 1) {
+ ConstExprValue *elem_val = &array_ptr_val->data.x_array.data.s_none.elements[i];
+ elem_val->special = ConstValSpecialUndef;
+ elem_val->type = array_type->data.array.child_type;
+ elem_val->parent.id = ConstParentIdArray;
+ elem_val->parent.data.p_array.array_val = array_ptr_val;
+ elem_val->parent.data.p_array.elem_index = i;
+ }
+ } else if (is_slice(array_type)) {
+ ZigType *actual_array_type = ir_resolve_type(ira, elem_ptr_instruction->init_array_type->child);
+ if (type_is_invalid(actual_array_type))
+ return ira->codegen->invalid_instruction;
+ if (actual_array_type->id != ZigTypeIdArray) {
+ ir_add_error(ira, elem_ptr_instruction->init_array_type,
+ buf_sprintf("expected array type or [_], found slice"));
+ return ira->codegen->invalid_instruction;
+ }
+
+ ConstExprValue *array_init_val = create_const_vals(1);
+ array_init_val->special = ConstValSpecialStatic;
+ array_init_val->type = actual_array_type;
+ array_init_val->data.x_array.special = ConstArraySpecialNone;
+ array_init_val->data.x_array.data.s_none.elements = create_const_vals(actual_array_type->data.array.len);
+ array_init_val->special = ConstValSpecialStatic;
+ for (size_t i = 0; i < actual_array_type->data.array.len; i += 1) {
+ ConstExprValue *elem_val = &array_init_val->data.x_array.data.s_none.elements[i];
+ elem_val->special = ConstValSpecialUndef;
+ elem_val->type = actual_array_type->data.array.child_type;
+ elem_val->parent.id = ConstParentIdArray;
+ elem_val->parent.data.p_array.array_val = array_init_val;
+ elem_val->parent.data.p_array.elem_index = i;
+ }
+
+ init_const_slice(ira->codegen, array_ptr_val, array_init_val, 0, actual_array_type->data.array.len,
+ false);
+ array_ptr_val->data.x_struct.fields[slice_ptr_index].data.x_ptr.mut = ConstPtrMutInfer;
+ } else {
+ zig_unreachable();
+ }
+ }
+
if (array_ptr_val->special != ConstValSpecialRuntime &&
(array_type->id != ZigTypeIdPointer ||
array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr))
@@ -15911,8 +17478,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
} else if (is_slice(array_type)) {
ConstExprValue *ptr_field = &array_ptr_val->data.x_struct.fields[slice_ptr_index];
if (ptr_field->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
- IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, elem_ptr_instruction->base.source_node,
- array_ptr, casted_elem_index, false, elem_ptr_instruction->ptr_len);
+ IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,
+ elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, false,
+ elem_ptr_instruction->ptr_len, nullptr);
result->value.type = return_type;
return result;
}
@@ -15965,7 +17533,16 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
}
return result;
} else if (array_type->id == ZigTypeIdArray) {
- IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type);
+ IrInstruction *result;
+ if (orig_array_ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
+ result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,
+ elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index,
+ false, elem_ptr_instruction->ptr_len, elem_ptr_instruction->init_array_type);
+ result->value.type = return_type;
+ result->value.special = ConstValSpecialStatic;
+ } else {
+ result = ir_const(ira, &elem_ptr_instruction->base, return_type);
+ }
ConstExprValue *out_val = &result->value;
out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
out_val->data.x_ptr.mut = orig_array_ptr_val->data.x_ptr.mut;
@@ -15977,7 +17554,6 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
}
}
}
-
} else {
// runtime known element index
switch (type_requires_comptime(ira->codegen, return_type)) {
@@ -16003,8 +17579,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
}
}
- IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, elem_ptr_instruction->base.source_node,
- array_ptr, casted_elem_index, safety_check_on, elem_ptr_instruction->ptr_len);
+ IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,
+ elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, safety_check_on,
+ elem_ptr_instruction->ptr_len, elem_ptr_instruction->init_array_type);
result->value.type = return_type;
return result;
}
@@ -16049,8 +17626,80 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
return ira->codegen->invalid_instruction;
}
+static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction *source_instr,
+ TypeStructField *field, IrInstruction *struct_ptr, ZigType *struct_type, bool initializing)
+{
+ switch (type_has_one_possible_value(ira->codegen, field->type_entry)) {
+ case OnePossibleValueInvalid:
+ return ira->codegen->invalid_instruction;
+ case OnePossibleValueYes: {
+ IrInstruction *elem = ir_const(ira, source_instr, field->type_entry);
+ return ir_get_ref(ira, source_instr, elem, false, false);
+ }
+ case OnePossibleValueNo:
+ break;
+ }
+ assert(struct_ptr->value.type->id == ZigTypeIdPointer);
+ bool is_packed = (struct_type->data.structure.layout == ContainerLayoutPacked);
+ uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry);
+ uint32_t ptr_bit_offset = struct_ptr->value.type->data.pointer.bit_offset_in_host;
+ uint32_t ptr_host_int_bytes = struct_ptr->value.type->data.pointer.host_int_bytes;
+ uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ?
+ get_host_int_bytes(ira->codegen, struct_type, field) : ptr_host_int_bytes;
+ bool is_const = struct_ptr->value.type->data.pointer.is_const;
+ bool is_volatile = struct_ptr->value.type->data.pointer.is_volatile;
+ ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
+ is_const, is_volatile, PtrLenSingle, align_bytes,
+ (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
+ (uint32_t)host_int_bytes_for_result_type, false);
+ if (instr_is_comptime(struct_ptr)) {
+ ConstExprValue *ptr_val = ir_resolve_const(ira, struct_ptr, UndefBad);
+ if (!ptr_val)
+ return ira->codegen->invalid_instruction;
+
+ if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
+ ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
+ if (struct_val == nullptr)
+ return ira->codegen->invalid_instruction;
+ if (type_is_invalid(struct_val->type))
+ return ira->codegen->invalid_instruction;
+ if (struct_val->special == ConstValSpecialUndef && initializing) {
+ struct_val->data.x_struct.fields = create_const_vals(struct_type->data.structure.src_field_count);
+ struct_val->special = ConstValSpecialStatic;
+ for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) {
+ ConstExprValue *field_val = &struct_val->data.x_struct.fields[i];
+ field_val->special = ConstValSpecialUndef;
+ field_val->type = struct_type->data.structure.fields[i].type_entry;
+ field_val->parent.id = ConstParentIdStruct;
+ field_val->parent.data.p_struct.struct_val = struct_val;
+ field_val->parent.data.p_struct.field_index = i;
+ }
+ }
+ IrInstruction *result;
+ if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
+ result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, struct_ptr, field);
+ result->value.type = ptr_type;
+ result->value.special = ConstValSpecialStatic;
+ } else {
+ result = ir_const(ira, source_instr, ptr_type);
+ }
+ ConstExprValue *const_val = &result->value;
+ const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct;
+ const_val->data.x_ptr.mut = ptr_val->data.x_ptr.mut;
+ const_val->data.x_ptr.data.base_struct.struct_val = struct_val;
+ const_val->data.x_ptr.data.base_struct.field_index = field->src_index;
+ return result;
+ }
+ }
+ IrInstruction *result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node,
+ struct_ptr, field);
+ result->value.type = ptr_type;
+ return result;
+}
+
static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
- IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type)
+ IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing)
{
Error err;
@@ -16059,81 +17708,55 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
return ira->codegen->invalid_instruction;
assert(container_ptr->value.type->id == ZigTypeIdPointer);
- bool is_const = container_ptr->value.type->data.pointer.is_const;
- bool is_volatile = container_ptr->value.type->data.pointer.is_volatile;
if (bare_type->id == ZigTypeIdStruct) {
TypeStructField *field = find_struct_type_field(bare_type, field_name);
- if (field) {
- switch (type_has_one_possible_value(ira->codegen, field->type_entry)) {
- case OnePossibleValueInvalid:
- return ira->codegen->invalid_instruction;
- case OnePossibleValueYes: {
- IrInstruction *elem = ir_const(ira, source_instr, field->type_entry);
- return ir_get_ref(ira, source_instr, elem, false, false);
- }
- case OnePossibleValueNo:
- break;
- }
- bool is_packed = (bare_type->data.structure.layout == ContainerLayoutPacked);
- uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry);
- uint32_t ptr_bit_offset = container_ptr->value.type->data.pointer.bit_offset_in_host;
- uint32_t ptr_host_int_bytes = container_ptr->value.type->data.pointer.host_int_bytes;
- uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ?
- get_host_int_bytes(ira->codegen, bare_type, field) : ptr_host_int_bytes;
- if (instr_is_comptime(container_ptr)) {
- ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
- if (!ptr_val)
- return ira->codegen->invalid_instruction;
-
- if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
- ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
- if (struct_val == nullptr)
- return ira->codegen->invalid_instruction;
- if (type_is_invalid(struct_val->type))
- return ira->codegen->invalid_instruction;
- ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
- is_const, is_volatile, PtrLenSingle, align_bytes,
- (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
- (uint32_t)host_int_bytes_for_result_type, false);
- IrInstruction *result = ir_const(ira, source_instr, ptr_type);
- ConstExprValue *const_val = &result->value;
- const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct;
- const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut;
- const_val->data.x_ptr.data.base_struct.struct_val = struct_val;
- const_val->data.x_ptr.data.base_struct.field_index = field->src_index;
- return result;
- }
- }
- IrInstruction *result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node,
- container_ptr, field);
- result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
- PtrLenSingle,
- align_bytes,
- (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
- host_int_bytes_for_result_type, false);
- return result;
+ if (field != nullptr) {
+ return ir_analyze_struct_field_ptr(ira, source_instr, field, container_ptr, bare_type, initializing);
} else {
return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
source_instr, container_ptr, container_type);
}
- } else if (bare_type->id == ZigTypeIdEnum) {
+ }
+
+ if (bare_type->id == ZigTypeIdEnum) {
return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
source_instr, container_ptr, container_type);
- } else if (bare_type->id == ZigTypeIdUnion) {
+ }
+
+ if (bare_type->id == ZigTypeIdUnion) {
+ bool is_const = container_ptr->value.type->data.pointer.is_const;
+ bool is_volatile = container_ptr->value.type->data.pointer.is_volatile;
+
TypeUnionField *field = find_union_type_field(bare_type, field_name);
- if (field) {
- if (instr_is_comptime(container_ptr)) {
- ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
- if (!ptr_val)
+ if (field == nullptr) {
+ return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
+ source_instr, container_ptr, container_type);
+ }
+ ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
+ is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
+ if (instr_is_comptime(container_ptr)) {
+ ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
+ if (!ptr_val)
+ return ira->codegen->invalid_instruction;
+
+ if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
+ ConstExprValue *union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
+ if (union_val == nullptr)
+ return ira->codegen->invalid_instruction;
+ if (type_is_invalid(union_val->type))
return ira->codegen->invalid_instruction;
- if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
- ConstExprValue *union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
- if (union_val == nullptr)
- return ira->codegen->invalid_instruction;
- if (type_is_invalid(union_val->type))
- return ira->codegen->invalid_instruction;
+ if (initializing) {
+ ConstExprValue *payload_val = create_const_vals(1);
+ payload_val->special = ConstValSpecialUndef;
+ payload_val->type = field->type_entry;
+ payload_val->parent.id = ConstParentIdUnion;
+ payload_val->parent.data.p_union.union_val = union_val;
+ union_val->special = ConstValSpecialStatic;
+ bigint_init_bigint(&union_val->data.x_union.tag, &field->enum_field->value);
+ union_val->data.x_union.payload = payload_val;
+ } else {
TypeUnionField *actual_field = find_union_field_by_tag(bare_type, &union_val->data.x_union.tag);
if (actual_field == nullptr)
zig_unreachable();
@@ -16144,33 +17767,35 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
buf_ptr(actual_field->name)));
return ira->codegen->invalid_instruction;
}
+ }
- ConstExprValue *payload_val = union_val->data.x_union.payload;
+ ConstExprValue *payload_val = union_val->data.x_union.payload;
- ZigType *field_type = field->type_entry;
- ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
- is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
- IrInstruction *result = ir_const(ira, source_instr, ptr_type);
- ConstExprValue *const_val = &result->value;
- const_val->data.x_ptr.special = ConstPtrSpecialRef;
- const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut;
- const_val->data.x_ptr.data.ref.pointee = payload_val;
- return result;
+ IrInstruction *result;
+ if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
+ result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, container_ptr, field, true, initializing);
+ result->value.type = ptr_type;
+ result->value.special = ConstValSpecialStatic;
+ } else {
+ result = ir_const(ira, source_instr, ptr_type);
}
+ ConstExprValue *const_val = &result->value;
+ const_val->data.x_ptr.special = ConstPtrSpecialRef;
+ const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut;
+ const_val->data.x_ptr.data.ref.pointee = payload_val;
+ return result;
}
-
- IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, container_ptr, field);
- result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
- PtrLenSingle, 0, 0, 0, false);
- return result;
- } else {
- return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
- source_instr, container_ptr, container_type);
}
- } else {
- zig_unreachable();
+
+ IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, container_ptr, field, true, initializing);
+ result->value.type = ptr_type;
+ return result;
}
+
+ zig_unreachable();
}
static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, AstNode *source_node) {
@@ -16208,6 +17833,11 @@ static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name,
link_lib->symbols.append(symbol_name);
}
+static IrInstruction *ir_error_dependency_loop(IrAnalyze *ira, IrInstruction *source_instr) {
+ ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("dependency loop detected"));
+ emit_error_notes_for_ref_stack(ira->codegen, msg);
+ return ira->codegen->invalid_instruction;
+}
static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instruction, Tld *tld) {
resolve_top_level_decl(ira->codegen, tld, source_instruction->source_node);
@@ -16222,6 +17852,9 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_
{
TldVar *tld_var = (TldVar *)tld;
ZigVar *var = tld_var->var;
+ if (var == nullptr) {
+ return ir_error_dependency_loop(ira, source_instruction);
+ }
if (tld_var->extern_lib_name != nullptr) {
add_link_lib_symbol(ira, tld_var->extern_lib_name, &var->name, source_instruction->source_node);
}
@@ -16237,23 +17870,13 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_
if (type_is_invalid(fn_entry->type_entry))
return ira->codegen->invalid_instruction;
- // TODO instead of allocating this every time, put it in the tld value and we can reference
- // the same one every time
- ConstExprValue *const_val = create_const_vals(1);
- const_val->special = ConstValSpecialStatic;
- const_val->type = fn_entry->type_entry;
- const_val->data.x_ptr.data.fn.fn_entry = fn_entry;
- const_val->data.x_ptr.special = ConstPtrSpecialFunction;
- const_val->data.x_ptr.mut = ConstPtrMutComptimeConst;
-
if (tld_fn->extern_lib_name != nullptr) {
add_link_lib_symbol(ira, tld_fn->extern_lib_name, &fn_entry->symbol_name, source_instruction->source_node);
}
- bool ptr_is_const = true;
- bool ptr_is_volatile = false;
- return ir_get_const_ptr(ira, source_instruction, const_val, fn_entry->type_entry,
- ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
+ IrInstruction *fn_inst = ir_create_const_fn(&ira->new_irb, source_instruction->scope,
+ source_instruction->source_node, fn_entry);
+ return ir_get_ref(ira, source_instruction, fn_inst, true, false);
}
}
zig_unreachable();
@@ -16295,14 +17918,14 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
assert(container_ptr->value.type->id == ZigTypeIdPointer);
if (container_type->id == ZigTypeIdPointer) {
ZigType *bare_type = container_ref_type(container_type);
- IrInstruction *container_child = ir_get_deref(ira, &field_ptr_instruction->base, container_ptr);
- IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_child, bare_type);
+ IrInstruction *container_child = ir_get_deref(ira, &field_ptr_instruction->base, container_ptr, nullptr);
+ IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_child, bare_type, field_ptr_instruction->initializing);
return result;
} else {
- IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_ptr, container_type);
+ IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_ptr, container_type, field_ptr_instruction->initializing);
return result;
}
- } else if (is_array_ref(container_type)) {
+ } else if (is_array_ref(container_type) && !field_ptr_instruction->initializing) {
if (buf_eql_str(field_name, "len")) {
ConstExprValue *len_val = create_const_vals(1);
if (container_type->id == ZigTypeIdPointer) {
@@ -16617,6 +18240,10 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
buf_sprintf("type '%s' does not support field access", buf_ptr(&child_type->name)));
return ira->codegen->invalid_instruction;
}
+ } else if (field_ptr_instruction->initializing) {
+ ir_add_error(ira, &field_ptr_instruction->base,
+ buf_sprintf("type '%s' does not support struct initialization syntax", buf_ptr(&container_type->name)));
+ return ira->codegen->invalid_instruction;
} else {
ir_add_error_node(ira, field_ptr_instruction->base.source_node,
buf_sprintf("type '%s' does not support field access", buf_ptr(&container_type->name)));
@@ -16640,7 +18267,7 @@ static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruct
IrInstruction *ptr = instruction->ptr->child;
if (type_is_invalid(ptr->value.type))
return ira->codegen->invalid_instruction;
- return ir_get_deref(ira, &instruction->base, ptr);
+ return ir_get_deref(ira, &instruction->base, ptr, nullptr);
}
static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) {
@@ -16651,64 +18278,6 @@ static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructio
return ir_const_type(ira, &typeof_instruction->base, type_entry);
}
-static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
- IrInstructionToPtrType *to_ptr_type_instruction)
-{
- Error err;
- IrInstruction *ptr_ptr = to_ptr_type_instruction->ptr->child;
- if (type_is_invalid(ptr_ptr->value.type))
- return ira->codegen->invalid_instruction;
-
- ZigType *ptr_ptr_type = ptr_ptr->value.type;
- assert(ptr_ptr_type->id == ZigTypeIdPointer);
- ZigType *type_entry = ptr_ptr_type->data.pointer.child_type;
-
- ZigType *ptr_type;
- if (type_entry->id == ZigTypeIdArray) {
- ptr_type = get_pointer_to_type(ira->codegen, type_entry->data.array.child_type, ptr_ptr_type->data.pointer.is_const);
- } else if (is_array_ref(type_entry)) {
- ptr_type = get_pointer_to_type(ira->codegen,
- type_entry->data.pointer.child_type->data.array.child_type, type_entry->data.pointer.is_const);
- } else if (is_slice(type_entry)) {
- ZigType *slice_ptr_type = type_entry->data.structure.fields[0].type_entry;
- ptr_type = adjust_ptr_len(ira->codegen, slice_ptr_type, PtrLenSingle);
- // If the pointer is over-aligned, we may have to reduce it based on the alignment of the element type.
- if (slice_ptr_type->data.pointer.explicit_alignment != 0) {
- ZigType *elem_type = slice_ptr_type->data.pointer.child_type;
- if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusAlignmentKnown)))
- return ira->codegen->invalid_instruction;
- uint32_t elem_align = get_abi_alignment(ira->codegen, elem_type);
- uint32_t reduced_align = min(elem_align, slice_ptr_type->data.pointer.explicit_alignment);
- ptr_type = adjust_ptr_align(ira->codegen, ptr_type, reduced_align);
- }
- } else if (type_entry->id == ZigTypeIdArgTuple) {
- zig_panic("TODO for loop on var args");
- } else {
- ir_add_error_node(ira, to_ptr_type_instruction->base.source_node,
- buf_sprintf("expected array type, found '%s'", buf_ptr(&type_entry->name)));
- return ira->codegen->invalid_instruction;
- }
-
- return ir_const_type(ira, &to_ptr_type_instruction->base, ptr_type);
-}
-
-static IrInstruction *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira,
- IrInstructionPtrTypeChild *ptr_type_child_instruction)
-{
- IrInstruction *type_value = ptr_type_child_instruction->value->child;
- ZigType *type_entry = ir_resolve_type(ira, type_value);
- if (type_is_invalid(type_entry))
- return ira->codegen->invalid_instruction;
-
- if (type_entry->id != ZigTypeIdPointer) {
- ir_add_error_node(ira, ptr_type_child_instruction->base.source_node,
- buf_sprintf("expected pointer type, found '%s'", buf_ptr(&type_entry->name)));
- return ira->codegen->invalid_instruction;
- }
-
- return ir_const_type(ira, &ptr_type_child_instruction->base, type_entry->data.pointer.child_type);
-}
-
static IrInstruction *ir_analyze_instruction_set_cold(IrAnalyze *ira, IrInstructionSetCold *instruction) {
if (ira->new_irb.exec->is_inline) {
// ignore setCold when running functions at compile time
@@ -17138,7 +18707,7 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns
}
static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
- IrInstruction *base_ptr, bool safety_check_on)
+ IrInstruction *base_ptr, bool safety_check_on, bool initializing)
{
ZigType *ptr_type = base_ptr->value.type;
assert(ptr_type->id == ZigTypeIdPointer);
@@ -17168,7 +18737,7 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
}
if (!safety_check_on)
return base_ptr;
- IrInstruction *c_ptr_val = ir_get_deref(ira, source_instr, base_ptr);
+ IrInstruction *c_ptr_val = ir_get_deref(ira, source_instr, base_ptr, nullptr);
ir_build_assert_non_null(ira, source_instr, c_ptr_val);
return base_ptr;
}
@@ -17183,34 +18752,84 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0, false);
+ bool same_comptime_repr = types_have_same_zig_comptime_repr(type_entry, child_type);
+
if (instr_is_comptime(base_ptr)) {
- ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad);
- if (!val)
+ ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
+ if (!ptr_val)
return ira->codegen->invalid_instruction;
- if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
- ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node);
- if (maybe_val == nullptr)
+ if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
+ ConstExprValue *optional_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
+ if (optional_val == nullptr)
return ira->codegen->invalid_instruction;
- if (optional_value_is_null(maybe_val)) {
+ if (initializing && optional_val->special == ConstValSpecialUndef) {
+ switch (type_has_one_possible_value(ira->codegen, child_type)) {
+ case OnePossibleValueInvalid:
+ return ira->codegen->invalid_instruction;
+ case OnePossibleValueNo:
+ if (!same_comptime_repr) {
+ ConstExprValue *payload_val = create_const_vals(1);
+ payload_val->type = child_type;
+ payload_val->special = ConstValSpecialUndef;
+ payload_val->parent.id = ConstParentIdOptionalPayload;
+ payload_val->parent.data.p_optional_payload.optional_val = optional_val;
+
+ optional_val->data.x_optional = payload_val;
+ optional_val->special = ConstValSpecialStatic;
+ }
+ break;
+ case OnePossibleValueYes: {
+ ConstExprValue *pointee = create_const_vals(1);
+ pointee->special = ConstValSpecialStatic;
+ pointee->type = child_type;
+ pointee->parent.id = ConstParentIdOptionalPayload;
+ pointee->parent.data.p_optional_payload.optional_val = optional_val;
+
+ optional_val->special = ConstValSpecialStatic;
+ optional_val->data.x_optional = pointee;
+ break;
+ }
+ }
+ } else if (optional_value_is_null(optional_val)) {
ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null"));
return ira->codegen->invalid_instruction;
}
- IrInstruction *result = ir_const(ira, source_instr, result_type);
- ConstExprValue *out_val = &result->value;
- out_val->data.x_ptr.special = ConstPtrSpecialRef;
- out_val->data.x_ptr.mut = val->data.x_ptr.mut;
- if (types_have_same_zig_comptime_repr(type_entry, child_type)) {
- out_val->data.x_ptr.data.ref.pointee = maybe_val;
+
+ IrInstruction *result;
+ if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
+ result = ir_build_optional_unwrap_ptr(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, base_ptr, false, initializing);
+ result->value.type = result_type;
+ result->value.special = ConstValSpecialStatic;
} else {
- out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_optional;
+ result = ir_const(ira, source_instr, result_type);
+ }
+ ConstExprValue *result_val = &result->value;
+ result_val->data.x_ptr.special = ConstPtrSpecialRef;
+ result_val->data.x_ptr.mut = ptr_val->data.x_ptr.mut;
+ switch (type_has_one_possible_value(ira->codegen, child_type)) {
+ case OnePossibleValueInvalid:
+ return ira->codegen->invalid_instruction;
+ case OnePossibleValueNo:
+ if (same_comptime_repr) {
+ result_val->data.x_ptr.data.ref.pointee = optional_val;
+ } else {
+ assert(optional_val->data.x_optional != nullptr);
+ result_val->data.x_ptr.data.ref.pointee = optional_val->data.x_optional;
+ }
+ break;
+ case OnePossibleValueYes:
+ assert(optional_val->data.x_optional != nullptr);
+ result_val->data.x_ptr.data.ref.pointee = optional_val->data.x_optional;
+ break;
}
return result;
}
}
IrInstruction *result = ir_build_optional_unwrap_ptr(&ira->new_irb, source_instr->scope,
- source_instr->source_node, base_ptr, safety_check_on);
+ source_instr->source_node, base_ptr, safety_check_on, initializing);
result->value.type = result_type;
return result;
}
@@ -17222,7 +18841,8 @@ static IrInstruction *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira,
if (type_is_invalid(base_ptr->value.type))
return ira->codegen->invalid_instruction;
- return ir_analyze_unwrap_optional_payload(ira, &instruction->base, base_ptr, instruction->safety_check_on);
+ return ir_analyze_unwrap_optional_payload(ira, &instruction->base, base_ptr,
+ instruction->safety_check_on, false);
}
static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *instruction) {
@@ -17523,7 +19143,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
return result;
}
- IrInstruction *result = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
+ IrInstruction *result = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr, nullptr);
result->value.type = target_type;
return result;
}
@@ -17553,7 +19173,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
return result;
}
- IrInstruction *union_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
+ IrInstruction *union_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr, nullptr);
union_value->value.type = target_type;
IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope,
@@ -17577,7 +19197,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
return result;
}
- IrInstruction *enum_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
+ IrInstruction *enum_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr, nullptr);
enum_value->value.type = target_type;
return enum_value;
}
@@ -17611,24 +19231,53 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru
ZigType *enum_type = target_type->data.unionation.tag_type;
assert(enum_type != nullptr);
assert(enum_type->id == ZigTypeIdEnum);
+ assert(instruction->prongs_len > 0);
- if (instruction->prongs_len != 1) {
- return target_value_ptr;
- }
-
- IrInstruction *prong_value = instruction->prongs_ptr[0]->child;
- if (type_is_invalid(prong_value->value.type))
+ IrInstruction *first_prong_value = instruction->prongs_ptr[0]->child;
+ if (type_is_invalid(first_prong_value->value.type))
return ira->codegen->invalid_instruction;
- IrInstruction *casted_prong_value = ir_implicit_cast(ira, prong_value, enum_type);
- if (type_is_invalid(casted_prong_value->value.type))
+ IrInstruction *first_casted_prong_value = ir_implicit_cast(ira, first_prong_value, enum_type);
+ if (type_is_invalid(first_casted_prong_value->value.type))
return ira->codegen->invalid_instruction;
- ConstExprValue *prong_val = ir_resolve_const(ira, casted_prong_value, UndefBad);
- if (!prong_val)
+ ConstExprValue *first_prong_val = ir_resolve_const(ira, first_casted_prong_value, UndefBad);
+ if (first_prong_val == nullptr)
return ira->codegen->invalid_instruction;
- TypeUnionField *field = find_union_field_by_tag(target_type, &prong_val->data.x_enum_tag);
+ TypeUnionField *first_field = find_union_field_by_tag(target_type, &first_prong_val->data.x_enum_tag);
+
+ ErrorMsg *invalid_payload_msg = nullptr;
+ for (size_t prong_i = 1; prong_i < instruction->prongs_len; prong_i += 1) {
+ IrInstruction *this_prong_inst = instruction->prongs_ptr[prong_i]->child;
+ if (type_is_invalid(this_prong_inst->value.type))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *this_casted_prong_value = ir_implicit_cast(ira, this_prong_inst, enum_type);
+ if (type_is_invalid(this_casted_prong_value->value.type))
+ return ira->codegen->invalid_instruction;
+
+ ConstExprValue *this_prong = ir_resolve_const(ira, this_casted_prong_value, UndefBad);
+ if (this_prong == nullptr)
+ return ira->codegen->invalid_instruction;
+
+ TypeUnionField *payload_field = find_union_field_by_tag(target_type, &this_prong->data.x_enum_tag);
+ ZigType *payload_type = payload_field->type_entry;
+ if (first_field->type_entry != payload_type) {
+ if (invalid_payload_msg == nullptr) {
+ invalid_payload_msg = ir_add_error(ira, &instruction->base,
+ buf_sprintf("capture group with incompatible types"));
+ add_error_note(ira->codegen, invalid_payload_msg, first_prong_value->source_node,
+ buf_sprintf("type '%s' here", buf_ptr(&first_field->type_entry->name)));
+ }
+ add_error_note(ira->codegen, invalid_payload_msg, this_prong_inst->source_node,
+ buf_sprintf("type '%s' here", buf_ptr(&payload_field->type_entry->name)));
+ }
+ }
+
+ if (invalid_payload_msg != nullptr) {
+ return ira->codegen->invalid_instruction;
+ }
if (instr_is_comptime(target_value_ptr)) {
ConstExprValue *target_val_ptr = ir_resolve_const(ira, target_value_ptr, UndefBad);
@@ -17640,7 +19289,7 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru
return ira->codegen->invalid_instruction;
IrInstruction *result = ir_const(ira, &instruction->base,
- get_pointer_to_type(ira->codegen, field->type_entry,
+ get_pointer_to_type(ira->codegen, first_field->type_entry,
target_val_ptr->type->data.pointer.is_const));
ConstExprValue *out_val = &result->value;
out_val->data.x_ptr.special = ConstPtrSpecialRef;
@@ -17650,8 +19299,8 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru
}
IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb,
- instruction->base.scope, instruction->base.source_node, target_value_ptr, field);
- result->value.type = get_pointer_to_type(ira->codegen, field->type_entry,
+ instruction->base.scope, instruction->base.source_node, target_value_ptr, first_field, false, false);
+ result->value.type = get_pointer_to_type(ira->codegen, first_field->type_entry,
target_value_ptr->value.type->data.pointer.is_const);
return result;
} else if (target_type->id == ZigTypeIdErrorSet) {
@@ -17859,77 +19508,67 @@ static IrInstruction *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRe
return ir_get_ref(ira, &ref_instruction->base, value, ref_instruction->is_const, ref_instruction->is_volatile);
}
-static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruction *instruction,
- ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields)
+static IrInstruction *ir_analyze_union_init(IrAnalyze *ira, IrInstruction *source_instruction,
+ AstNode *field_source_node, ZigType *union_type, Buf *field_name, IrInstruction *field_result_loc,
+ IrInstruction *result_loc)
{
Error err;
- assert(container_type->id == ZigTypeIdUnion);
-
- if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
- return ira->codegen->invalid_instruction;
-
- if (instr_field_count != 1) {
- ir_add_error(ira, instruction,
- buf_sprintf("union initialization expects exactly one field"));
- return ira->codegen->invalid_instruction;
- }
+ assert(union_type->id == ZigTypeIdUnion);
- IrInstructionContainerInitFieldsField *field = &fields[0];
- IrInstruction *field_value = field->value->child;
- if (type_is_invalid(field_value->value.type))
+ if ((err = type_resolve(ira->codegen, union_type, ResolveStatusSizeKnown)))
return ira->codegen->invalid_instruction;
- TypeUnionField *type_field = find_union_type_field(container_type, field->name);
- if (!type_field) {
- ir_add_error_node(ira, field->source_node,
+ TypeUnionField *type_field = find_union_type_field(union_type, field_name);
+ if (type_field == nullptr) {
+ ir_add_error_node(ira, field_source_node,
buf_sprintf("no member named '%s' in union '%s'",
- buf_ptr(field->name), buf_ptr(&container_type->name)));
+ buf_ptr(field_name), buf_ptr(&union_type->name)));
return ira->codegen->invalid_instruction;
}
if (type_is_invalid(type_field->type_entry))
return ira->codegen->invalid_instruction;
- IrInstruction *casted_field_value = ir_implicit_cast(ira, field_value, type_field->type_entry);
- if (casted_field_value == ira->codegen->invalid_instruction)
- return ira->codegen->invalid_instruction;
-
- if ((err = type_resolve(ira->codegen, casted_field_value->value.type, ResolveStatusZeroBitsKnown)))
- return ira->codegen->invalid_instruction;
-
- bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)
- || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;
- if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime ||
- !type_has_bits(casted_field_value->value.type))
- {
- ConstExprValue *field_val = ir_resolve_const(ira, casted_field_value, UndefOk);
- if (!field_val)
- return ira->codegen->invalid_instruction;
+ if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) {
+ if (instr_is_comptime(field_result_loc) &&
+ field_result_loc->value.data.x_ptr.mut != ConstPtrMutRuntimeVar)
+ {
+ // nothing
+ } else {
+ result_loc->value.special = ConstValSpecialRuntime;
+ }
+ }
- IrInstruction *result = ir_const(ira, instruction, container_type);
- ConstExprValue *out_val = &result->value;
- out_val->data.x_union.payload = field_val;
- out_val->data.x_union.tag = type_field->enum_field->value;
- out_val->parent.id = ConstParentIdUnion;
- out_val->parent.data.p_union.union_val = out_val;
+ bool is_comptime = ir_should_inline(ira->new_irb.exec, source_instruction->scope)
+ || type_requires_comptime(ira->codegen, union_type) == ReqCompTimeYes;
- return result;
+ IrInstruction *result = ir_get_deref(ira, source_instruction, result_loc, nullptr);
+ if (is_comptime && !instr_is_comptime(result)) {
+ ir_add_error(ira, field_result_loc,
+ buf_sprintf("unable to evaluate constant expression"));
+ return ira->codegen->invalid_instruction;
}
-
- IrInstruction *new_instruction = ir_build_union_init(&ira->new_irb,
- instruction->scope, instruction->source_node,
- container_type, type_field, casted_field_value);
- new_instruction->value.type = container_type;
- ir_add_alloca(ira, new_instruction, container_type);
- return new_instruction;
+ return result;
}
static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction,
- ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields)
+ ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields,
+ IrInstruction *result_loc)
{
Error err;
if (container_type->id == ZigTypeIdUnion) {
- return ir_analyze_container_init_fields_union(ira, instruction, container_type, instr_field_count, fields);
+ if (instr_field_count != 1) {
+ ir_add_error(ira, instruction,
+ buf_sprintf("union initialization expects exactly one field"));
+ return ira->codegen->invalid_instruction;
+ }
+ IrInstructionContainerInitFieldsField *field = &fields[0];
+ IrInstruction *field_result_loc = field->result_loc->child;
+ if (type_is_invalid(field_result_loc->value.type))
+ return ira->codegen->invalid_instruction;
+
+ return ir_analyze_union_init(ira, instruction, field->source_node, container_type, field->name,
+ field_result_loc, result_loc);
}
if (container_type->id != ZigTypeIdStruct || is_slice(container_type)) {
ir_add_error(ira, instruction,
@@ -17946,22 +19585,28 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
IrInstruction *first_non_const_instruction = nullptr;
AstNode **field_assign_nodes = allocate<AstNode *>(actual_field_count);
-
- IrInstructionStructInitField *new_fields = allocate<IrInstructionStructInitField>(actual_field_count);
+ ZigList<IrInstruction *> const_ptrs = {};
bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)
|| type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;
- ConstExprValue const_val = {};
- const_val.special = ConstValSpecialStatic;
- const_val.type = container_type;
- // const_val.global_refs = allocate<ConstGlobalRefs>(1);
- const_val.data.x_struct.fields = create_const_vals(actual_field_count);
+
+ // Here we iterate over the fields that have been initialized, and emit
+ // compile errors for missing fields and duplicate fields.
+ // It is only now that we find out whether the struct initialization can be a comptime
+ // value, but we have already emitted runtime instructions for the fields that
+ // were initialized with runtime values, and have omitted instructions that would have
+ // initialized fields with comptime values.
+ // So now we must clean up this situation. If it turns out the struct initialization can
+ // be a comptime value, overwrite ConstPtrMutInfer with ConstPtrMutComptimeConst.
+ // Otherwise, we must emit instructions to runtime-initialize the fields that have
+ // comptime-known values.
+
for (size_t i = 0; i < instr_field_count; i += 1) {
IrInstructionContainerInitFieldsField *field = &fields[i];
- IrInstruction *field_value = field->value->child;
- if (type_is_invalid(field_value->value.type))
+ IrInstruction *field_result_loc = field->result_loc->child;
+ if (type_is_invalid(field_result_loc->value.type))
return ira->codegen->invalid_instruction;
TypeStructField *type_field = find_struct_type_field(container_type, field->name);
@@ -17975,10 +19620,6 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
if (type_is_invalid(type_field->type_entry))
return ira->codegen->invalid_instruction;
- IrInstruction *casted_field_value = ir_implicit_cast(ira, field_value, type_field->type_entry);
- if (casted_field_value == ira->codegen->invalid_instruction)
- return ira->codegen->invalid_instruction;
-
size_t field_index = type_field->src_index;
AstNode *existing_assign_node = field_assign_nodes[field_index];
if (existing_assign_node) {
@@ -17988,26 +19629,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
}
field_assign_nodes[field_index] = field->source_node;
- new_fields[field_index].value = casted_field_value;
- new_fields[field_index].type_struct_field = type_field;
-
- if (const_val.special == ConstValSpecialStatic) {
- if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime) {
- ConstExprValue *field_val = ir_resolve_const(ira, casted_field_value, UndefOk);
- if (!field_val)
- return ira->codegen->invalid_instruction;
-
- copy_const_val(&const_val.data.x_struct.fields[field_index], field_val, true);
- } else {
- first_non_const_instruction = casted_field_value;
- const_val.special = ConstValSpecialRuntime;
- }
+ if (instr_is_comptime(field_result_loc) &&
+ field_result_loc->value.data.x_ptr.mut != ConstPtrMutRuntimeVar)
+ {
+ const_ptrs.append(field_result_loc);
+ } else {
+ first_non_const_instruction = field_result_loc;
}
}
bool any_missing = false;
for (size_t i = 0; i < actual_field_count; i += 1) {
- if (field_assign_nodes[i]) continue;
+ if (field_assign_nodes[i] != nullptr) continue;
// look for a default field value
TypeStructField *field = &container_type->data.structure.fields[i];
@@ -18033,182 +19666,177 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
IrInstruction *runtime_inst = ir_const(ira, instruction, field->init_val->type);
copy_const_val(&runtime_inst->value, field->init_val, true);
- new_fields[i].value = runtime_inst;
- new_fields[i].type_struct_field = field;
-
- if (const_val.special == ConstValSpecialStatic) {
- copy_const_val(&const_val.data.x_struct.fields[i], field->init_val, true);
+ IrInstruction *field_ptr = ir_analyze_struct_field_ptr(ira, instruction, field, result_loc,
+ container_type, true);
+ ir_analyze_store_ptr(ira, instruction, field_ptr, runtime_inst);
+ if (instr_is_comptime(field_ptr) && field_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {
+ const_ptrs.append(field_ptr);
+ } else {
+ first_non_const_instruction = result_loc;
}
}
if (any_missing)
return ira->codegen->invalid_instruction;
- if (const_val.special == ConstValSpecialStatic) {
- IrInstruction *result = ir_const(ira, instruction, nullptr);
- ConstExprValue *out_val = &result->value;
- copy_const_val(out_val, &const_val, false);
- out_val->type = container_type;
-
- for (size_t i = 0; i < instr_field_count; i += 1) {
- ConstExprValue *field_val = &out_val->data.x_struct.fields[i];
- ConstParent *parent = get_const_val_parent(ira->codegen, field_val);
- if (parent != nullptr) {
- parent->id = ConstParentIdStruct;
- parent->data.p_struct.field_index = i;
- parent->data.p_struct.struct_val = out_val;
+ if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) {
+ if (const_ptrs.length != actual_field_count) {
+ result_loc->value.special = ConstValSpecialRuntime;
+ for (size_t i = 0; i < const_ptrs.length; i += 1) {
+ IrInstruction *field_result_loc = const_ptrs.at(i);
+ IrInstruction *deref = ir_get_deref(ira, field_result_loc, field_result_loc, nullptr);
+ field_result_loc->value.special = ConstValSpecialRuntime;
+ ir_analyze_store_ptr(ira, field_result_loc, field_result_loc, deref);
}
}
-
- return result;
}
- if (is_comptime) {
+ IrInstruction *result = ir_get_deref(ira, instruction, result_loc, nullptr);
+
+ if (is_comptime && !instr_is_comptime(result)) {
ir_add_error_node(ira, first_non_const_instruction->source_node,
buf_sprintf("unable to evaluate constant expression"));
return ira->codegen->invalid_instruction;
}
- IrInstruction *new_instruction = ir_build_struct_init(&ira->new_irb,
- instruction->scope, instruction->source_node,
- container_type, actual_field_count, new_fields);
- new_instruction->value.type = container_type;
- ir_add_alloca(ira, new_instruction, container_type);
- return new_instruction;
+ return result;
}
static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
IrInstructionContainerInitList *instruction)
{
- Error err;
+ ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
+ if (type_is_invalid(container_type))
+ return ira->codegen->invalid_instruction;
size_t elem_count = instruction->item_count;
- ZigType *container_type;
- if (instruction->container_type != nullptr) {
- container_type = ir_resolve_type(ira, instruction->container_type->child);
- if (type_is_invalid(container_type))
- return ira->codegen->invalid_instruction;
- } else {
- ZigType *elem_type = ir_resolve_type(ira, instruction->elem_type->child);
- if (type_is_invalid(elem_type))
- return ira->codegen->invalid_instruction;
- if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown))) {
- return ira->codegen->invalid_instruction;
- }
- container_type = get_array_type(ira->codegen, elem_type, elem_count);
- }
-
if (is_slice(container_type)) {
- ir_add_error(ira, &instruction->base,
+ ir_add_error(ira, instruction->container_type,
buf_sprintf("expected array type or [_], found slice"));
return ira->codegen->invalid_instruction;
- } else if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {
- return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
- 0, nullptr);
- } else if (container_type->id == ZigTypeIdArray) {
- // array is same as slice init but we make a compile error if the length is wrong
- ZigType *child_type;
- if (container_type->id == ZigTypeIdArray) {
- child_type = container_type->data.array.child_type;
- if (container_type->data.array.len != elem_count) {
- ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
-
- ir_add_error(ira, &instruction->base,
- buf_sprintf("expected %s literal, found %s literal",
- buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
- return ira->codegen->invalid_instruction;
- }
- } else {
- ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry;
- assert(pointer_type->id == ZigTypeIdPointer);
- child_type = pointer_type->data.pointer.child_type;
- }
+ }
- if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown))) {
+ if (container_type->id == ZigTypeIdVoid) {
+ if (elem_count != 0) {
+ ir_add_error_node(ira, instruction->base.source_node,
+ buf_sprintf("void expression expects no arguments"));
return ira->codegen->invalid_instruction;
}
+ return ir_const_void(ira, &instruction->base);
+ }
- ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count);
+ if (container_type->id == ZigTypeIdStruct && elem_count == 0) {
+ ir_assert(instruction->result_loc != nullptr, &instruction->base);
+ IrInstruction *result_loc = instruction->result_loc->child;
+ if (type_is_invalid(result_loc->value.type))
+ return result_loc;
+ return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, result_loc);
+ }
- ConstExprValue const_val = {};
- const_val.special = ConstValSpecialStatic;
- const_val.type = fixed_size_array_type;
- // const_val.global_refs = allocate<ConstGlobalRefs>(1);
- const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);
+ if (container_type->id != ZigTypeIdArray) {
+ ir_add_error_node(ira, instruction->base.source_node,
+ buf_sprintf("type '%s' does not support array initialization",
+ buf_ptr(&container_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
- bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);
+ ir_assert(instruction->result_loc != nullptr, &instruction->base);
+ IrInstruction *result_loc = instruction->result_loc->child;
+ if (type_is_invalid(result_loc->value.type))
+ return result_loc;
+ ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base);
- IrInstruction **new_items = allocate<IrInstruction *>(elem_count);
+ ZigType *child_type = container_type->data.array.child_type;
+ if (container_type->data.array.len != elem_count) {
+ ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
- IrInstruction *first_non_const_instruction = nullptr;
+ ir_add_error(ira, &instruction->base,
+ buf_sprintf("expected %s literal, found %s literal",
+ buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
- for (size_t i = 0; i < elem_count; i += 1) {
- IrInstruction *arg_value = instruction->items[i]->child;
- if (type_is_invalid(arg_value->value.type))
- return ira->codegen->invalid_instruction;
+ switch (type_has_one_possible_value(ira->codegen, container_type)) {
+ case OnePossibleValueInvalid:
+ return ira->codegen->invalid_instruction;
+ case OnePossibleValueYes:
+ return ir_const(ira, &instruction->base, container_type);
+ case OnePossibleValueNo:
+ break;
+ }
- IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);
- if (casted_arg == ira->codegen->invalid_instruction)
- return ira->codegen->invalid_instruction;
+ bool is_comptime;
+ switch (type_requires_comptime(ira->codegen, container_type)) {
+ case ReqCompTimeInvalid:
+ return ira->codegen->invalid_instruction;
+ case ReqCompTimeNo:
+ is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);
+ break;
+ case ReqCompTimeYes:
+ is_comptime = true;
+ break;
+ }
- new_items[i] = casted_arg;
+ IrInstruction *first_non_const_instruction = nullptr;
- if (const_val.special == ConstValSpecialStatic) {
- if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) {
- ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);
- if (!elem_val)
- return ira->codegen->invalid_instruction;
+ // The Result Location Mechanism has already emitted runtime instructions to
+ // initialize runtime elements and has omitted instructions for the comptime
+ // elements. However it is only now that we find out whether the array initialization
+ // can be a comptime value. So we must clean up the situation. If it turns out
+ // array initialization can be a comptime value, overwrite ConstPtrMutInfer with
+ // ConstPtrMutComptimeConst. Otherwise, emit instructions to runtime-initialize the
+ // elements that have comptime-known values.
+ ZigList<IrInstruction *> const_ptrs = {};
+
+ for (size_t i = 0; i < elem_count; i += 1) {
+ IrInstruction *elem_result_loc = instruction->elem_result_loc_list[i]->child;
+ if (type_is_invalid(elem_result_loc->value.type))
+ return ira->codegen->invalid_instruction;
- copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);
- } else {
- first_non_const_instruction = casted_arg;
- const_val.special = ConstValSpecialRuntime;
- }
- }
+ assert(elem_result_loc->value.type->id == ZigTypeIdPointer);
+
+ if (instr_is_comptime(elem_result_loc) &&
+ elem_result_loc->value.data.x_ptr.mut != ConstPtrMutRuntimeVar)
+ {
+ const_ptrs.append(elem_result_loc);
+ } else {
+ first_non_const_instruction = elem_result_loc;
}
+ }
- if (const_val.special == ConstValSpecialStatic) {
- IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
- ConstExprValue *out_val = &result->value;
- copy_const_val(out_val, &const_val, false);
- result->value.type = fixed_size_array_type;
- for (size_t i = 0; i < elem_count; i += 1) {
- ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i];
- ConstParent *parent = get_const_val_parent(ira->codegen, elem_val);
- if (parent != nullptr) {
- parent->id = ConstParentIdArray;
- parent->data.p_array.array_val = out_val;
- parent->data.p_array.elem_index = i;
- }
+ if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) {
+ if (const_ptrs.length != elem_count) {
+ result_loc->value.special = ConstValSpecialRuntime;
+ for (size_t i = 0; i < const_ptrs.length; i += 1) {
+ IrInstruction *elem_result_loc = const_ptrs.at(i);
+ assert(elem_result_loc->value.special == ConstValSpecialStatic);
+ IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr);
+ elem_result_loc->value.special = ConstValSpecialRuntime;
+ ir_analyze_store_ptr(ira, elem_result_loc, elem_result_loc, deref);
}
- return result;
}
+ }
- if (is_comptime) {
- ir_add_error_node(ira, first_non_const_instruction->source_node,
- buf_sprintf("unable to evaluate constant expression"));
- return ira->codegen->invalid_instruction;
- }
+ IrInstruction *result = ir_get_deref(ira, &instruction->base, result_loc, nullptr);
+ if (instr_is_comptime(result))
+ return result;
- IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb,
- instruction->base.scope, instruction->base.source_node,
- nullptr, nullptr, elem_count, new_items);
- new_instruction->value.type = fixed_size_array_type;
- ir_add_alloca(ira, new_instruction, fixed_size_array_type);
- return new_instruction;
- } else if (container_type->id == ZigTypeIdVoid) {
- if (elem_count != 0) {
- ir_add_error_node(ira, instruction->base.source_node,
- buf_sprintf("void expression expects no arguments"));
- return ira->codegen->invalid_instruction;
- }
- return ir_const_void(ira, &instruction->base);
- } else {
- ir_add_error_node(ira, instruction->base.source_node,
- buf_sprintf("type '%s' does not support array initialization",
- buf_ptr(&container_type->name)));
+ if (is_comptime) {
+ ir_add_error_node(ira, first_non_const_instruction->source_node,
+ buf_sprintf("unable to evaluate constant expression"));
return ira->codegen->invalid_instruction;
}
+
+ ZigType *result_elem_type = result_loc->value.type->data.pointer.child_type;
+ if (is_slice(result_elem_type)) {
+ ErrorMsg *msg = ir_add_error(ira, &instruction->base,
+ buf_sprintf("runtime-initialized array cannot be casted to slice type '%s'",
+ buf_ptr(&result_elem_type->name)));
+ add_error_note(ira->codegen, msg, first_non_const_instruction->source_node,
+ buf_sprintf("this value is not comptime-known"));
+ return ira->codegen->invalid_instruction;
+ }
+ return result;
}
static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira,
@@ -18219,8 +19847,13 @@ static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ir
if (type_is_invalid(container_type))
return ira->codegen->invalid_instruction;
+ ir_assert(instruction->result_loc != nullptr, &instruction->base);
+ IrInstruction *result_loc = instruction->result_loc->child;
+ if (type_is_invalid(result_loc->value.type))
+ return result_loc;
+
return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
- instruction->field_count, instruction->fields);
+ instruction->field_count, instruction->fields, result_loc);
}
static IrInstruction *ir_analyze_instruction_compile_err(IrAnalyze *ira,
@@ -18489,12 +20122,6 @@ static IrInstruction *ir_analyze_instruction_bit_offset_of(IrAnalyze *ira,
return ir_const_unsigned(ira, &instruction->base, bit_offset);
}
-static IrInstruction *ir_error_dependency_loop(IrAnalyze *ira, IrInstruction *source_instr) {
- ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("dependency loop detected"));
- emit_error_notes_for_ref_stack(ira->codegen, msg);
- return ira->codegen->invalid_instruction;
-}
-
static void ensure_field_index(ZigType *type, const char *field_name, size_t index) {
Buf *field_name_buf;
@@ -19613,7 +21240,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to make dir: %s", err_str(err)));
return ira->codegen->invalid_instruction;
}
-
+
if ((err = os_write_file(&tmp_c_file_path, &cimport_scope->buf))) {
ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to write .h file: %s", err_str(err)));
return ira->codegen->invalid_instruction;
@@ -19900,12 +21527,21 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi
zig_panic("TODO compile-time execution of cmpxchg");
}
- IrInstruction *result = ir_build_cmpxchg_gen(ira, &instruction->base,
+ ZigType *result_type = get_optional_type(ira->codegen, operand_type);
+ IrInstruction *result_loc;
+ if (handle_is_ptr(result_type)) {
+ result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
+ result_type, nullptr, true, false);
+ if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
+ return result_loc;
+ }
+ } else {
+ result_loc = nullptr;
+ }
+
+ return ir_build_cmpxchg_gen(ira, &instruction->base, result_type,
casted_ptr, casted_cmp_value, casted_new_value,
- success_order, failure_order, instruction->is_weak);
- result->value.type = get_optional_type(ira->codegen, operand_type);
- ir_add_alloca(ira, result, result->value.type);
- return result;
+ success_order, failure_order, instruction->is_weak, result_loc);
}
static IrInstruction *ir_analyze_instruction_fence(IrAnalyze *ira, IrInstructionFence *instruction) {
@@ -20043,7 +21679,7 @@ static IrInstruction *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstru
} else {
op = CastOpNumLitToConcrete;
}
- return ir_resolve_cast(ira, &instruction->base, target, dest_type, op, false);
+ return ir_resolve_cast(ira, &instruction->base, target, dest_type, op);
} else {
return ira->codegen->invalid_instruction;
}
@@ -20151,6 +21787,12 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru
}
}
+ IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
+ dest_slice_type, nullptr, true, false);
+ if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) {
+ return result_loc;
+ }
+
if (casted_value->value.data.rh_slice.id == RuntimeHintSliceIdLen) {
known_len = casted_value->value.data.rh_slice.len;
have_known_len = true;
@@ -20170,9 +21812,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru
}
}
- IrInstruction *result = ir_build_resize_slice(ira, &instruction->base, casted_value, dest_slice_type);
- ir_add_alloca(ira, result, dest_slice_type);
- return result;
+ return ir_build_resize_slice(ira, &instruction->base, casted_value, dest_slice_type, result_loc);
}
static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) {
@@ -20224,9 +21864,13 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct
return result;
}
- IrInstruction *result = ir_build_resize_slice(ira, &instruction->base, target, dest_slice_type);
- ir_add_alloca(ira, result, dest_slice_type);
- return result;
+ IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
+ dest_slice_type, nullptr, true, false);
+ if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
+ return result_loc;
+ }
+
+ return ir_build_resize_slice(ira, &instruction->base, target, dest_slice_type, result_loc);
}
static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
@@ -20258,7 +21902,7 @@ static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInst
return ira->codegen->invalid_instruction;
}
- return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpIntToFloat, false);
+ return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpIntToFloat);
}
static IrInstruction *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrInstructionFloatToInt *instruction) {
@@ -20280,7 +21924,7 @@ static IrInstruction *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrInst
return ira->codegen->invalid_instruction;
}
- return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpFloatToInt, false);
+ return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpFloatToInt);
}
static IrInstruction *ir_analyze_instruction_err_to_int(IrAnalyze *ira, IrInstructionErrToInt *instruction) {
@@ -20332,7 +21976,7 @@ static IrInstruction *ir_analyze_instruction_bool_to_int(IrAnalyze *ira, IrInstr
}
ZigType *u1_type = get_int_type(ira->codegen, false, 1);
- return ir_resolve_cast(ira, &instruction->base, target, u1_type, CastOpBoolToInt, false);
+ return ir_resolve_cast(ira, &instruction->base, target, u1_type, CastOpBoolToInt);
}
static IrInstruction *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstructionIntType *instruction) {
@@ -20493,7 +22137,7 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio
ConstExprValue *byte_val = &casted_byte->value;
for (size_t i = start; i < end; i += 1) {
- dest_elements[i] = *byte_val;
+ copy_const_val(&dest_elements[i], byte_val, true);
}
return ir_const_void(ira, &instruction->base);
@@ -20563,7 +22207,7 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
return ira->codegen->invalid_instruction;
// TODO test this at comptime with u8 and non-u8 types
- // TODO test with dest ptr being a global runtime variable
+ // TODO test with dest ptr being a global runtime variable
if (casted_dest_ptr->value.special == ConstValSpecialStatic &&
casted_src_ptr->value.special == ConstValSpecialStatic &&
casted_count->value.special == ConstValSpecialStatic &&
@@ -20661,7 +22305,7 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
// TODO check for noalias violations - this should be generalized to work for any function
for (size_t i = 0; i < count; i += 1) {
- dest_elements[dest_start + i] = src_elements[src_start + i];
+ copy_const_val(&dest_elements[dest_start + i], &src_elements[src_start + i], true);
}
return ir_const_void(ira, &instruction->base);
@@ -20673,7 +22317,7 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
return result;
}
-static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice *instruction) {
+static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSliceSrc *instruction) {
IrInstruction *ptr_ptr = instruction->ptr->child;
if (type_is_invalid(ptr_ptr->value.type))
return ira->codegen->invalid_instruction;
@@ -20962,12 +22606,13 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
return result;
}
- IrInstruction *new_instruction = ir_build_slice(&ira->new_irb,
- instruction->base.scope, instruction->base.source_node,
- ptr_ptr, casted_start, end, instruction->safety_check_on);
- new_instruction->value.type = return_type;
- ir_add_alloca(ira, new_instruction, return_type);
- return new_instruction;
+ IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
+ return_type, nullptr, true, false);
+ if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
+ return result_loc;
+ }
+ return ir_build_slice_gen(ira, &instruction->base, return_type,
+ ptr_ptr, casted_start, end, instruction->safety_check_on, result_loc);
}
static IrInstruction *ir_analyze_instruction_member_count(IrAnalyze *ira, IrInstructionMemberCount *instruction) {
@@ -21107,6 +22752,34 @@ static IrInstruction *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInstr
}
}
+static IrInstruction *ir_analyze_instruction_has_field(IrAnalyze *ira, IrInstructionHasField *instruction) {
+ Error err;
+ ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
+ if (type_is_invalid(container_type))
+ return ira->codegen->invalid_instruction;
+
+ if ((err = type_resolve(ira->codegen, container_type, ResolveStatusZeroBitsKnown)))
+ return ira->codegen->invalid_instruction;
+
+ Buf *field_name = ir_resolve_str(ira, instruction->field_name->child);
+ if (field_name == nullptr)
+ return ira->codegen->invalid_instruction;
+
+ bool result;
+ if (container_type->id == ZigTypeIdStruct) {
+ result = find_struct_type_field(container_type, field_name) != nullptr;
+ } else if (container_type->id == ZigTypeIdEnum) {
+ result = find_enum_type_field(container_type, field_name) != nullptr;
+ } else if (container_type->id == ZigTypeIdUnion) {
+ result = find_union_type_field(container_type, field_name) != nullptr;
+ } else {
+ ir_add_error(ira, instruction->container_type,
+ buf_sprintf("type '%s' does not support @hasField", buf_ptr(&container_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+ return ir_const_bool(ira, &instruction->base, result);
+}
+
static IrInstruction *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstructionBreakpoint *instruction) {
IrInstruction *result = ir_build_breakpoint(&ira->new_irb,
instruction->base.scope, instruction->base.source_node);
@@ -21291,6 +22964,19 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr
return result;
}
+static IrInstruction *ir_analyze_instruction_result_ptr(IrAnalyze *ira, IrInstructionResultPtr *instruction) {
+ IrInstruction *result = instruction->result->child;
+ if (type_is_invalid(result->value.type))
+ return result;
+
+ if (instruction->result_loc->written && instruction->result_loc->resolved_loc != nullptr &&
+ !instr_is_comptime(result))
+ {
+ return instruction->result_loc->resolved_loc;
+ }
+ return ir_get_ref(ira, &instruction->base, result, true, false);
+}
+
static void ir_eval_mul_add(IrAnalyze *ira, IrInstructionMulAdd *source_instr, ZigType *float_type,
ConstExprValue *op1, ConstExprValue *op2, ConstExprValue *op3, ConstExprValue *out_val) {
if (float_type->id == ZigTypeIdComptimeFloat) {
@@ -21322,11 +23008,11 @@ static IrInstruction *ir_analyze_instruction_mul_add(IrAnalyze *ira, IrInstructi
IrInstruction *type_value = instruction->type_value->child;
if (type_is_invalid(type_value->value.type))
return ira->codegen->invalid_instruction;
-
+
ZigType *expr_type = ir_resolve_type(ira, type_value);
if (type_is_invalid(expr_type))
return ira->codegen->invalid_instruction;
-
+
// Only allow float types, and vectors of floats.
ZigType *float_type = (expr_type->id == ZigTypeIdVector) ? expr_type->data.vector.elem_type : expr_type;
if (float_type->id != ZigTypeIdFloat) {
@@ -21410,15 +23096,17 @@ static IrInstruction *ir_analyze_instruction_mul_add(IrAnalyze *ira, IrInstructi
return result;
}
-static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstructionTestErr *instruction) {
- IrInstruction *value = instruction->value->child;
- if (type_is_invalid(value->value.type))
+static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstructionTestErrSrc *instruction) {
+ IrInstruction *base_ptr = instruction->base_ptr->child;
+ if (type_is_invalid(base_ptr->value.type))
return ira->codegen->invalid_instruction;
+ IrInstruction *value = ir_get_deref(ira, &instruction->base, base_ptr, nullptr);
ZigType *type_entry = value->value.type;
- if (type_is_invalid(type_entry)) {
+ if (type_is_invalid(type_entry))
return ira->codegen->invalid_instruction;
- } else if (type_entry->id == ZigTypeIdErrorUnion) {
+
+ if (type_entry->id == ZigTypeIdErrorUnion) {
if (instr_is_comptime(value)) {
ConstExprValue *err_union_val = ir_resolve_const(ira, value, UndefBad);
if (!err_union_val)
@@ -21430,21 +23118,20 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
}
}
- ZigType *err_set_type = type_entry->data.error_union.err_set_type;
- if (!resolve_inferred_error_set(ira->codegen, err_set_type, instruction->base.source_node)) {
- return ira->codegen->invalid_instruction;
- }
- if (!type_is_global_error_set(err_set_type) &&
- err_set_type->data.error_set.err_count == 0)
- {
- assert(err_set_type->data.error_set.infer_fn == nullptr);
- return ir_const_bool(ira, &instruction->base, false);
+ if (instruction->resolve_err_set) {
+ ZigType *err_set_type = type_entry->data.error_union.err_set_type;
+ if (!resolve_inferred_error_set(ira->codegen, err_set_type, instruction->base.source_node)) {
+ return ira->codegen->invalid_instruction;
+ }
+ if (!type_is_global_error_set(err_set_type) &&
+ err_set_type->data.error_set.err_count == 0)
+ {
+ assert(err_set_type->data.error_set.infer_fn == nullptr);
+ return ir_const_bool(ira, &instruction->base, false);
+ }
}
- IrInstruction *result = ir_build_test_err(&ira->new_irb,
- instruction->base.scope, instruction->base.source_node, value);
- result->value.type = ira->codegen->builtin_types.entry_bool;
- return result;
+ return ir_build_test_err_gen(ira, &instruction->base, value);
} else if (type_entry->id == ZigTypeIdErrorSet) {
return ir_const_bool(ira, &instruction->base, true);
} else {
@@ -21452,10 +23139,9 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
}
}
-static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrInstructionUnwrapErrCode *instruction) {
- IrInstruction *base_ptr = instruction->err_union->child;
- if (type_is_invalid(base_ptr->value.type))
- return ira->codegen->invalid_instruction;
+static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *base_ptr, bool initializing)
+{
ZigType *ptr_type = base_ptr->value.type;
// This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
@@ -21471,40 +23157,79 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrI
return ira->codegen->invalid_instruction;
}
+ ZigType *err_set_type = type_entry->data.error_union.err_set_type;
+ ZigType *result_type = get_pointer_to_type_extra(ira->codegen, err_set_type,
+ ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle,
+ ptr_type->data.pointer.explicit_alignment, 0, 0, false);
+
if (instr_is_comptime(base_ptr)) {
ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
if (!ptr_val)
return ira->codegen->invalid_instruction;
- if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
- ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
+ if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar &&
+ ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr)
+ {
+ ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
if (err_union_val == nullptr)
return ira->codegen->invalid_instruction;
- if (err_union_val->special != ConstValSpecialRuntime) {
- ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
- assert(err);
- IrInstruction *result = ir_const(ira, &instruction->base,
- type_entry->data.error_union.err_set_type);
- result->value.data.x_err_set = err;
- return result;
+ if (initializing && err_union_val->special == ConstValSpecialUndef) {
+ ConstExprValue *vals = create_const_vals(2);
+ ConstExprValue *err_set_val = &vals[0];
+ ConstExprValue *payload_val = &vals[1];
+
+ err_set_val->special = ConstValSpecialUndef;
+ err_set_val->type = err_set_type;
+ err_set_val->parent.id = ConstParentIdErrUnionCode;
+ err_set_val->parent.data.p_err_union_code.err_union_val = err_union_val;
+
+ payload_val->special = ConstValSpecialUndef;
+ payload_val->type = type_entry->data.error_union.payload_type;
+ payload_val->parent.id = ConstParentIdErrUnionPayload;
+ payload_val->parent.data.p_err_union_payload.err_union_val = err_union_val;
+
+ err_union_val->special = ConstValSpecialStatic;
+ err_union_val->data.x_err_union.error_set = err_set_val;
+ err_union_val->data.x_err_union.payload = payload_val;
+ }
+ ir_assert(err_union_val->special != ConstValSpecialRuntime, source_instr);
+
+ IrInstruction *result;
+ if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
+ result = ir_build_unwrap_err_code(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, base_ptr);
+ result->value.type = result_type;
+ result->value.special = ConstValSpecialStatic;
+ } else {
+ result = ir_const(ira, source_instr, result_type);
}
+ ConstExprValue *const_val = &result->value;
+ const_val->data.x_ptr.special = ConstPtrSpecialBaseErrorUnionCode;
+ const_val->data.x_ptr.data.base_err_union_code.err_union_val = err_union_val;
+ const_val->data.x_ptr.mut = ptr_val->data.x_ptr.mut;
+ return result;
}
}
IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb,
- instruction->base.scope, instruction->base.source_node, base_ptr);
- result->value.type = type_entry->data.error_union.err_set_type;
+ source_instr->scope, source_instr->source_node, base_ptr);
+ result->value.type = result_type;
return result;
}
-static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
- IrInstructionUnwrapErrPayload *instruction)
+static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,
+ IrInstructionUnwrapErrCode *instruction)
{
- assert(instruction->value->child);
- IrInstruction *value = instruction->value->child;
- if (type_is_invalid(value->value.type))
+ IrInstruction *base_ptr = instruction->err_union_ptr->child;
+ if (type_is_invalid(base_ptr->value.type))
return ira->codegen->invalid_instruction;
- ZigType *ptr_type = value->value.type;
+ return ir_analyze_unwrap_err_code(ira, &instruction->base, base_ptr, false);
+}
+
+static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *base_ptr, bool safety_check_on, bool initializing)
+{
+ ZigType *ptr_type = base_ptr->value.type;
// This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
assert(ptr_type->id == ZigTypeIdPointer);
@@ -21514,7 +23239,7 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
return ira->codegen->invalid_instruction;
if (type_entry->id != ZigTypeIdErrorUnion) {
- ir_add_error(ira, value,
+ ir_add_error(ira, base_ptr,
buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
return ira->codegen->invalid_instruction;
}
@@ -21526,36 +23251,73 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
PtrLenSingle, 0, 0, 0, false);
- if (instr_is_comptime(value)) {
- ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
+ if (instr_is_comptime(base_ptr)) {
+ ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
if (!ptr_val)
return ira->codegen->invalid_instruction;
if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
- ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
+ ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
if (err_union_val == nullptr)
return ira->codegen->invalid_instruction;
+ if (err_union_val->special == ConstValSpecialUndef && initializing) {
+ ConstExprValue *vals = create_const_vals(2);
+ ConstExprValue *err_set_val = &vals[0];
+ ConstExprValue *payload_val = &vals[1];
+
+ err_set_val->special = ConstValSpecialStatic;
+ err_set_val->type = type_entry->data.error_union.err_set_type;
+ err_set_val->data.x_err_set = nullptr;
+
+ payload_val->special = ConstValSpecialUndef;
+ payload_val->type = payload_type;
+
+ err_union_val->special = ConstValSpecialStatic;
+ err_union_val->data.x_err_union.error_set = err_set_val;
+ err_union_val->data.x_err_union.payload = payload_val;
+ }
+
if (err_union_val->special != ConstValSpecialRuntime) {
ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
if (err != nullptr) {
- ir_add_error(ira, &instruction->base,
+ ir_add_error(ira, source_instr,
buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name)));
return ira->codegen->invalid_instruction;
}
- IrInstruction *result = ir_const(ira, &instruction->base, result_type);
+ IrInstruction *result;
+ if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
+ result = ir_build_unwrap_err_payload(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, base_ptr, safety_check_on, initializing);
+ result->value.type = result_type;
+ result->value.special = ConstValSpecialStatic;
+ } else {
+ result = ir_const(ira, source_instr, result_type);
+ }
result->value.data.x_ptr.special = ConstPtrSpecialRef;
result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload;
+ result->value.data.x_ptr.mut = ptr_val->data.x_ptr.mut;
return result;
}
}
}
- IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb,
- instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on);
+ IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, base_ptr, safety_check_on, initializing);
result->value.type = result_type;
return result;
}
+static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
+ IrInstructionUnwrapErrPayload *instruction)
+{
+ assert(instruction->value->child);
+ IrInstruction *value = instruction->value->child;
+ if (type_is_invalid(value->value.type))
+ return ira->codegen->invalid_instruction;
+
+ return ir_analyze_unwrap_error_payload(ira, &instruction->base, value, instruction->safety_check_on, false);
+}
+
static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) {
AstNode *proto_node = instruction->base.source_node;
assert(proto_node->type == NodeTypeFnProto);
@@ -22047,14 +23809,19 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
}
}
- IrInstruction *result = ir_const(ira, source_instr, dest_type);
+ IrInstruction *result;
+ if (ptr->value.data.x_ptr.mut == ConstPtrMutInfer) {
+ result = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on);
+ } else {
+ result = ir_const(ira, source_instr, dest_type);
+ }
copy_const_val(&result->value, val, true);
result->value.type = dest_type;
// Keep the bigger alignment, it can only help-
// unless the target is zero bits.
if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) {
- result = ir_align_cast(ira, result, src_align_bytes, false);
+ result = ir_align_cast(ira, result, src_align_bytes, false);
}
return result;
@@ -22138,6 +23905,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
case ZigTypeIdUndefined:
case ZigTypeIdNull:
case ZigTypeIdPromise:
+ case ZigTypeIdErrorUnion:
+ case ZigTypeIdErrorSet:
zig_unreachable();
case ZigTypeIdVoid:
return;
@@ -22241,10 +24010,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
}
case ZigTypeIdOptional:
zig_panic("TODO buf_write_value_bytes maybe type");
- case ZigTypeIdErrorUnion:
- zig_panic("TODO buf_write_value_bytes error union");
- case ZigTypeIdErrorSet:
- zig_panic("TODO buf_write_value_bytes pure error type");
case ZigTypeIdFn:
zig_panic("TODO buf_write_value_bytes fn type");
case ZigTypeIdUnion:
@@ -22433,28 +24198,6 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
zig_unreachable();
}
-static bool type_can_bit_cast(ZigType *t) {
- switch (t->id) {
- case ZigTypeIdInvalid:
- zig_unreachable();
- case ZigTypeIdMetaType:
- case ZigTypeIdOpaque:
- case ZigTypeIdBoundFn:
- case ZigTypeIdArgTuple:
- case ZigTypeIdUnreachable:
- case ZigTypeIdComptimeFloat:
- case ZigTypeIdComptimeInt:
- case ZigTypeIdEnumLiteral:
- case ZigTypeIdUndefined:
- case ZigTypeIdNull:
- case ZigTypeIdPointer:
- return false;
- default:
- // TODO list these types out explicitly, there are probably some other invalid ones here
- return true;
- }
-}
-
static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
ZigType *dest_type)
{
@@ -22506,49 +24249,7 @@ static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_
return result;
}
- IrInstruction *result = ir_build_bit_cast_gen(ira, source_instr, value, dest_type);
- if (handle_is_ptr(dest_type) && !handle_is_ptr(src_type)) {
- ir_add_alloca(ira, result, dest_type);
- }
- return result;
-}
-
-static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
- IrInstruction *dest_type_value = instruction->dest_type->child;
- ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
- if (type_is_invalid(dest_type))
- return ira->codegen->invalid_instruction;
-
- IrInstruction *value = instruction->value->child;
- ZigType *src_type = value->value.type;
- if (type_is_invalid(src_type))
- return ira->codegen->invalid_instruction;
-
- if (get_codegen_ptr_type(src_type) != nullptr) {
- ir_add_error(ira, value,
- buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name)));
- return ira->codegen->invalid_instruction;
- }
-
- if (!type_can_bit_cast(src_type)) {
- ir_add_error(ira, dest_type_value,
- buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
- return ira->codegen->invalid_instruction;
- }
-
- if (get_codegen_ptr_type(dest_type) != nullptr) {
- ir_add_error(ira, dest_type_value,
- buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));
- return ira->codegen->invalid_instruction;
- }
-
- if (!type_can_bit_cast(dest_type)) {
- ir_add_error(ira, dest_type_value,
- buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
- return ira->codegen->invalid_instruction;
- }
-
- return ir_analyze_bit_cast(ira, &instruction->base, value, dest_type);
+ return ir_build_bit_cast_gen(ira, source_instr, value, dest_type);
}
static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
@@ -22618,58 +24319,15 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru
static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
IrInstructionDeclRef *instruction)
{
- Tld *tld = instruction->tld;
- LVal lval = instruction->lval;
-
- resolve_top_level_decl(ira->codegen, tld, instruction->base.source_node);
- if (tld->resolution == TldResolutionInvalid)
+ IrInstruction *ref_instruction = ir_analyze_decl_ref(ira, &instruction->base, instruction->tld);
+ if (type_is_invalid(ref_instruction->value.type))
return ira->codegen->invalid_instruction;
- switch (tld->id) {
- case TldIdContainer:
- case TldIdCompTime:
- zig_unreachable();
- case TldIdVar: {
- TldVar *tld_var = (TldVar *)tld;
- ZigVar *var = tld_var->var;
-
- if (var == nullptr) {
- return ir_error_dependency_loop(ira, &instruction->base);
- }
-
- IrInstruction *var_ptr = ir_get_var_ptr(ira, &instruction->base, var);
- if (type_is_invalid(var_ptr->value.type))
- return ira->codegen->invalid_instruction;
-
- if (tld_var->extern_lib_name != nullptr) {
- add_link_lib_symbol(ira, tld_var->extern_lib_name, &var->name, instruction->base.source_node);
- }
-
- if (lval == LValPtr) {
- return var_ptr;
- } else {
- return ir_get_deref(ira, &instruction->base, var_ptr);
- }
- }
- case TldIdFn: {
- TldFn *tld_fn = (TldFn *)tld;
- ZigFn *fn_entry = tld_fn->fn_entry;
- ir_assert(fn_entry->type_entry, &instruction->base);
-
- if (tld_fn->extern_lib_name != nullptr) {
- add_link_lib_symbol(ira, tld_fn->extern_lib_name, &fn_entry->symbol_name, instruction->base.source_node);
- }
-
- IrInstruction *ref_instruction = ir_create_const_fn(&ira->new_irb, instruction->base.scope,
- instruction->base.source_node, fn_entry);
- if (lval == LValPtr) {
- return ir_get_ref(ira, &instruction->base, ref_instruction, true, false);
- } else {
- return ref_instruction;
- }
- }
+ if (instruction->lval == LValPtr) {
+ return ref_instruction;
+ } else {
+ return ir_get_deref(ira, &instruction->base, ref_instruction, nullptr);
}
- zig_unreachable();
}
static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstructionPtrToInt *instruction) {
@@ -23183,7 +24841,7 @@ static IrInstruction *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstr
}
if (instr_is_comptime(casted_ptr)) {
- IrInstruction *result = ir_get_deref(ira, &instruction->base, casted_ptr);
+ IrInstruction *result = ir_get_deref(ira, &instruction->base, casted_ptr, nullptr);
ir_assert(result->value.type != nullptr, &instruction->base);
return result;
}
@@ -23455,7 +25113,7 @@ static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstruct
IrInstruction *type = instruction->type->child;
if (type_is_invalid(type->value.type))
return ira->codegen->invalid_instruction;
-
+
ZigType *expr_type = ir_resolve_type(ira, type);
if (type_is_invalid(expr_type))
return ira->codegen->invalid_instruction;
@@ -23721,12 +25379,85 @@ static IrInstruction *ir_analyze_instruction_undeclared_ident(IrAnalyze *ira, Ir
return ira->codegen->invalid_instruction;
}
-static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
+static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstructionEndExpr *instruction) {
+ IrInstruction *value = instruction->value->child;
+ if (type_is_invalid(value->value.type))
+ return ira->codegen->invalid_instruction;
+
+ bool was_written = instruction->result_loc->written;
+ IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
+ value->value.type, value, false, false);
+ if (result_loc != nullptr) {
+ if (type_is_invalid(result_loc->value.type))
+ return ira->codegen->invalid_instruction;
+ if (result_loc->value.type->id == ZigTypeIdUnreachable)
+ return result_loc;
+
+ if (!was_written) {
+ IrInstruction *store_ptr = ir_analyze_store_ptr(ira, &instruction->base, result_loc, value);
+ if (type_is_invalid(store_ptr->value.type)) {
+ return ira->codegen->invalid_instruction;
+ }
+ }
+
+ if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) {
+ if (instr_is_comptime(value)) {
+ result_loc->value.data.x_ptr.mut = ConstPtrMutComptimeConst;
+ } else {
+ result_loc->value.special = ConstValSpecialRuntime;
+ }
+ }
+ }
+
+ return ir_const_void(ira, &instruction->base);
+}
+
+static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInstructionBitCastSrc *instruction) {
+ IrInstruction *operand = instruction->operand->child;
+ if (type_is_invalid(operand->value.type))
+ return operand;
+
+ IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base,
+ &instruction->result_loc_bit_cast->base, operand->value.type, operand, false, false);
+ if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)))
+ return result_loc;
+
+ return instruction->result_loc_bit_cast->parent->gen_instruction;
+}
+
+static IrInstruction *ir_analyze_instruction_union_init_named_field(IrAnalyze *ira,
+ IrInstructionUnionInitNamedField *instruction)
+{
+ ZigType *union_type = ir_resolve_type(ira, instruction->union_type->child);
+ if (type_is_invalid(union_type))
+ return ira->codegen->invalid_instruction;
+
+ if (union_type->id != ZigTypeIdUnion) {
+ ir_add_error(ira, instruction->union_type,
+ buf_sprintf("non-union type '%s' passed to @unionInit", buf_ptr(&union_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ Buf *field_name = ir_resolve_str(ira, instruction->field_name->child);
+ if (field_name == nullptr)
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *field_result_loc = instruction->field_result_loc->child;
+ if (type_is_invalid(field_result_loc->value.type))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *result_loc = instruction->result_loc->child;
+ if (type_is_invalid(result_loc->value.type))
+ return ira->codegen->invalid_instruction;
+
+ return ir_analyze_union_init(ira, &instruction->base, instruction->base.source_node,
+ union_type, field_name, field_result_loc, result_loc);
+}
+
+static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) {
switch (instruction->id) {
case IrInstructionIdInvalid:
case IrInstructionIdWidenOrShorten:
- case IrInstructionIdStructInit:
- case IrInstructionIdUnionInit:
case IrInstructionIdStructFieldPtr:
case IrInstructionIdUnionFieldPtr:
case IrInstructionIdOptionalWrap:
@@ -23738,11 +25469,18 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
case IrInstructionIdCmpxchgGen:
case IrInstructionIdArrayToVector:
case IrInstructionIdVectorToArray:
+ case IrInstructionIdPtrOfArrayToSlice:
case IrInstructionIdAssertZero:
case IrInstructionIdAssertNonNull:
case IrInstructionIdResizeSlice:
case IrInstructionIdLoadPtrGen:
case IrInstructionIdBitCastGen:
+ case IrInstructionIdCallGen:
+ case IrInstructionIdReturnPtr:
+ case IrInstructionIdAllocaGen:
+ case IrInstructionIdSliceGen:
+ case IrInstructionIdRefGen:
+ case IrInstructionIdTestErrGen:
zig_unreachable();
case IrInstructionIdReturn:
@@ -23765,8 +25503,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_var_ptr(ira, (IrInstructionVarPtr *)instruction);
case IrInstructionIdFieldPtr:
return ir_analyze_instruction_field_ptr(ira, (IrInstructionFieldPtr *)instruction);
- case IrInstructionIdCall:
- return ir_analyze_instruction_call(ira, (IrInstructionCall *)instruction);
+ case IrInstructionIdCallSrc:
+ return ir_analyze_instruction_call(ira, (IrInstructionCallSrc *)instruction);
case IrInstructionIdBr:
return ir_analyze_instruction_br(ira, (IrInstructionBr *)instruction);
case IrInstructionIdCondBr:
@@ -23777,10 +25515,6 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_phi(ira, (IrInstructionPhi *)instruction);
case IrInstructionIdTypeOf:
return ir_analyze_instruction_typeof(ira, (IrInstructionTypeOf *)instruction);
- case IrInstructionIdToPtrType:
- return ir_analyze_instruction_to_ptr_type(ira, (IrInstructionToPtrType *)instruction);
- case IrInstructionIdPtrTypeChild:
- return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction);
case IrInstructionIdSetCold:
return ir_analyze_instruction_set_cold(ira, (IrInstructionSetCold *)instruction);
case IrInstructionIdSetRuntimeSafety:
@@ -23881,8 +25615,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_memset(ira, (IrInstructionMemset *)instruction);
case IrInstructionIdMemcpy:
return ir_analyze_instruction_memcpy(ira, (IrInstructionMemcpy *)instruction);
- case IrInstructionIdSlice:
- return ir_analyze_instruction_slice(ira, (IrInstructionSlice *)instruction);
+ case IrInstructionIdSliceSrc:
+ return ir_analyze_instruction_slice(ira, (IrInstructionSliceSrc *)instruction);
case IrInstructionIdMemberCount:
return ir_analyze_instruction_member_count(ira, (IrInstructionMemberCount *)instruction);
case IrInstructionIdMemberType:
@@ -23901,8 +25635,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_align_of(ira, (IrInstructionAlignOf *)instruction);
case IrInstructionIdOverflowOp:
return ir_analyze_instruction_overflow_op(ira, (IrInstructionOverflowOp *)instruction);
- case IrInstructionIdTestErr:
- return ir_analyze_instruction_test_err(ira, (IrInstructionTestErr *)instruction);
+ case IrInstructionIdTestErrSrc:
+ return ir_analyze_instruction_test_err(ira, (IrInstructionTestErrSrc *)instruction);
case IrInstructionIdUnwrapErrCode:
return ir_analyze_instruction_unwrap_err_code(ira, (IrInstructionUnwrapErrCode *)instruction);
case IrInstructionIdUnwrapErrPayload:
@@ -23921,8 +25655,6 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);
case IrInstructionIdPtrCastSrc:
return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCastSrc *)instruction);
- case IrInstructionIdBitCast:
- return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction);
case IrInstructionIdIntToPtr:
return ir_analyze_instruction_int_to_ptr(ira, (IrInstructionIntToPtr *)instruction);
case IrInstructionIdPtrToInt:
@@ -23937,6 +25669,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_bit_offset_of(ira, (IrInstructionBitOffsetOf *)instruction);
case IrInstructionIdTypeInfo:
return ir_analyze_instruction_type_info(ira, (IrInstructionTypeInfo *) instruction);
+ case IrInstructionIdHasField:
+ return ir_analyze_instruction_has_field(ira, (IrInstructionHasField *) instruction);
case IrInstructionIdTypeId:
return ir_analyze_instruction_type_id(ira, (IrInstructionTypeId *)instruction);
case IrInstructionIdSetEvalBranchQuota:
@@ -23945,6 +25679,14 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_ptr_type(ira, (IrInstructionPtrType *)instruction);
case IrInstructionIdAlignCast:
return ir_analyze_instruction_align_cast(ira, (IrInstructionAlignCast *)instruction);
+ case IrInstructionIdImplicitCast:
+ return ir_analyze_instruction_implicit_cast(ira, (IrInstructionImplicitCast *)instruction);
+ case IrInstructionIdResolveResult:
+ return ir_analyze_instruction_resolve_result(ira, (IrInstructionResolveResult *)instruction);
+ case IrInstructionIdResetResult:
+ return ir_analyze_instruction_reset_result(ira, (IrInstructionResetResult *)instruction);
+ case IrInstructionIdResultPtr:
+ return ir_analyze_instruction_result_ptr(ira, (IrInstructionResultPtr *)instruction);
case IrInstructionIdOpaqueType:
return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction);
case IrInstructionIdSetAlignStack:
@@ -24021,17 +25763,18 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_has_decl(ira, (IrInstructionHasDecl *)instruction);
case IrInstructionIdUndeclaredIdent:
return ir_analyze_instruction_undeclared_ident(ira, (IrInstructionUndeclaredIdent *)instruction);
+ case IrInstructionIdAllocaSrc:
+ return nullptr;
+ case IrInstructionIdEndExpr:
+ return ir_analyze_instruction_end_expr(ira, (IrInstructionEndExpr *)instruction);
+ case IrInstructionIdBitCastSrc:
+ return ir_analyze_instruction_bit_cast_src(ira, (IrInstructionBitCastSrc *)instruction);
+ case IrInstructionIdUnionInitNamedField:
+ return ir_analyze_instruction_union_init_named_field(ira, (IrInstructionUnionInitNamedField *)instruction);
}
zig_unreachable();
}
-static IrInstruction *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *old_instruction) {
- IrInstruction *new_instruction = ir_analyze_instruction_nocast(ira, old_instruction);
- ir_assert(new_instruction->value.type != nullptr, old_instruction);
- old_instruction->child = new_instruction;
- return new_instruction;
-}
-
// This function attempts to evaluate IR code while doing type checking and other analysis.
// It emits a new IrExecutable which is partially evaluated IR code.
ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_exec,
@@ -24077,14 +25820,22 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_
continue;
}
- IrInstruction *new_instruction = ir_analyze_instruction(ira, old_instruction);
- if (type_is_invalid(new_instruction->value.type) && ir_should_inline(new_exec, old_instruction->scope)) {
- return ira->codegen->builtin_types.entry_invalid;
+ if (ira->codegen->verbose_ir) {
+ fprintf(stderr, "analyze #%zu\n", old_instruction->debug_id);
}
+ IrInstruction *new_instruction = ir_analyze_instruction_base(ira, old_instruction);
+ if (new_instruction != nullptr) {
+ ir_assert(new_instruction->value.type != nullptr || new_instruction->value.type != nullptr, old_instruction);
+ old_instruction->child = new_instruction;
- // unreachable instructions do their own control flow.
- if (new_instruction->value.type->id == ZigTypeIdUnreachable)
- continue;
+ if (type_is_invalid(new_instruction->value.type)) {
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+
+ // unreachable instructions do their own control flow.
+ if (new_instruction->value.type->id == ZigTypeIdUnreachable)
+ continue;
+ }
ira->instruction_index += 1;
}
@@ -24109,7 +25860,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdDeclVarSrc:
case IrInstructionIdDeclVarGen:
case IrInstructionIdStorePtr:
- case IrInstructionIdCall:
+ case IrInstructionIdCallSrc:
+ case IrInstructionIdCallGen:
case IrInstructionIdReturn:
case IrInstructionIdUnreachable:
case IrInstructionIdSetCold:
@@ -24156,27 +25908,29 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdResizeSlice:
case IrInstructionIdGlobalAsm:
case IrInstructionIdUndeclaredIdent:
+ case IrInstructionIdEndExpr:
+ case IrInstructionIdPtrOfArrayToSlice:
+ case IrInstructionIdSliceGen:
+ case IrInstructionIdOptionalWrap:
+ case IrInstructionIdVectorToArray:
+ case IrInstructionIdResetResult:
return true;
case IrInstructionIdPhi:
case IrInstructionIdUnOp:
case IrInstructionIdBinOp:
case IrInstructionIdLoadPtr:
- case IrInstructionIdLoadPtrGen:
case IrInstructionIdConst:
case IrInstructionIdCast:
case IrInstructionIdContainerInitList:
case IrInstructionIdContainerInitFields:
- case IrInstructionIdStructInit:
- case IrInstructionIdUnionInit:
+ case IrInstructionIdUnionInitNamedField:
case IrInstructionIdFieldPtr:
case IrInstructionIdElemPtr:
case IrInstructionIdVarPtr:
+ case IrInstructionIdReturnPtr:
case IrInstructionIdTypeOf:
- case IrInstructionIdToPtrType:
- case IrInstructionIdPtrTypeChild:
case IrInstructionIdStructFieldPtr:
- case IrInstructionIdUnionFieldPtr:
case IrInstructionIdArrayType:
case IrInstructionIdPromiseType:
case IrInstructionIdSliceType:
@@ -24198,7 +25952,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdIntType:
case IrInstructionIdVectorType:
case IrInstructionIdBoolNot:
- case IrInstructionIdSlice:
+ case IrInstructionIdSliceSrc:
case IrInstructionIdMemberCount:
case IrInstructionIdMemberType:
case IrInstructionIdMemberName:
@@ -24206,16 +25960,13 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdReturnAddress:
case IrInstructionIdFrameAddress:
case IrInstructionIdHandle:
- case IrInstructionIdTestErr:
- case IrInstructionIdUnwrapErrCode:
- case IrInstructionIdOptionalWrap:
- case IrInstructionIdErrWrapCode:
- case IrInstructionIdErrWrapPayload:
+ case IrInstructionIdTestErrSrc:
+ case IrInstructionIdTestErrGen:
case IrInstructionIdFnProto:
case IrInstructionIdTestComptime:
case IrInstructionIdPtrCastSrc:
case IrInstructionIdPtrCastGen:
- case IrInstructionIdBitCast:
+ case IrInstructionIdBitCastSrc:
case IrInstructionIdBitCastGen:
case IrInstructionIdWidenOrShorten:
case IrInstructionIdPtrToInt:
@@ -24231,8 +25982,11 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdByteOffsetOf:
case IrInstructionIdBitOffsetOf:
case IrInstructionIdTypeInfo:
+ case IrInstructionIdHasField:
case IrInstructionIdTypeId:
case IrInstructionIdAlignCast:
+ case IrInstructionIdImplicitCast:
+ case IrInstructionIdResolveResult:
case IrInstructionIdOpaqueType:
case IrInstructionIdArgType:
case IrInstructionIdTagType:
@@ -24257,9 +26011,11 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdFromBytes:
case IrInstructionIdToBytes:
case IrInstructionIdEnumToInt:
- case IrInstructionIdVectorToArray:
case IrInstructionIdArrayToVector:
case IrInstructionIdHasDecl:
+ case IrInstructionIdAllocaSrc:
+ case IrInstructionIdAllocaGen:
+ case IrInstructionIdResultPtr:
return false;
case IrInstructionIdAsm:
@@ -24271,8 +26027,21 @@ bool ir_has_side_effects(IrInstruction *instruction) {
{
IrInstructionUnwrapErrPayload *unwrap_err_payload_instruction =
(IrInstructionUnwrapErrPayload *)instruction;
- return unwrap_err_payload_instruction->safety_check_on;
+ return unwrap_err_payload_instruction->safety_check_on ||
+ unwrap_err_payload_instruction->initializing;
}
+ case IrInstructionIdUnwrapErrCode:
+ return reinterpret_cast<IrInstructionUnwrapErrCode *>(instruction)->initializing;
+ case IrInstructionIdUnionFieldPtr:
+ return reinterpret_cast<IrInstructionUnionFieldPtr *>(instruction)->initializing;
+ case IrInstructionIdErrWrapPayload:
+ return reinterpret_cast<IrInstructionErrWrapPayload *>(instruction)->result_loc != nullptr;
+ case IrInstructionIdErrWrapCode:
+ return reinterpret_cast<IrInstructionErrWrapCode *>(instruction)->result_loc != nullptr;
+ case IrInstructionIdLoadPtrGen:
+ return reinterpret_cast<IrInstructionLoadPtrGen *>(instruction)->result_loc != nullptr;
+ case IrInstructionIdRefGen:
+ return reinterpret_cast<IrInstructionRefGen *>(instruction)->result_loc != nullptr;
}
zig_unreachable();
}
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 165d9b4739..588a9b2882 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -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, ")");
}
@@ -1162,6 +1270,14 @@ static void ir_print_type_info(IrPrint *irp, IrInstructionTypeInfo *instruction)
fprintf(irp->f, ")");
}
+static void ir_print_has_field(IrPrint *irp, IrInstructionHasField *instruction) {
+ fprintf(irp->f, "@hasField(");
+ ir_print_other_instruction(irp, instruction->container_type);
+ fprintf(irp->f, ",");
+ ir_print_other_instruction(irp, instruction->field_name);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_type_id(IrPrint *irp, IrInstructionTypeId *instruction) {
fprintf(irp->f, "@typeId(");
ir_print_other_instruction(irp, instruction->type_value);
@@ -1186,6 +1302,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 +1607,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);
@@ -1482,6 +1626,18 @@ static void ir_print_undeclared_ident(IrPrint *irp, IrInstructionUndeclaredIdent
fprintf(irp->f, "@undeclaredIdent(%s)", buf_ptr(instruction->name));
}
+static void ir_print_union_init_named_field(IrPrint *irp, IrInstructionUnionInitNamedField *instruction) {
+ fprintf(irp->f, "@unionInit(");
+ ir_print_other_instruction(irp, instruction->union_type);
+ fprintf(irp->f, ", ");
+ ir_print_other_instruction(irp, instruction->field_name);
+ fprintf(irp->f, ", ");
+ ir_print_other_instruction(irp, instruction->field_result_loc);
+ fprintf(irp->f, ", ");
+ ir_print_other_instruction(irp, instruction->result_loc);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
ir_print_prefix(irp, instruction);
switch (instruction->id) {
@@ -1502,8 +1658,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 +1682,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 +1691,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 +1706,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 +1784,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 +1862,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 +1895,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 +1908,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 +1928,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);
@@ -1826,6 +1985,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdTypeInfo:
ir_print_type_info(irp, (IrInstructionTypeInfo *)instruction);
break;
+ case IrInstructionIdHasField:
+ ir_print_has_field(irp, (IrInstructionHasField *)instruction);
+ break;
case IrInstructionIdTypeId:
ir_print_type_id(irp, (IrInstructionTypeId *)instruction);
break;
@@ -1835,6 +1997,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 +2117,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 +2135,18 @@ 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;
+ case IrInstructionIdUnionInitNamedField:
+ ir_print_union_init_named_field(irp, (IrInstructionUnionInitNamedField *)instruction);
+ break;
}
fprintf(irp->f, "\n");
}
diff --git a/src/link.cpp b/src/link.cpp
index 277dcbc5c6..4a17ec892c 100644
--- a/src/link.cpp
+++ b/src/link.cpp
@@ -11,44 +11,577 @@
#include "analyze.hpp"
#include "compiler.hpp"
#include "install_files.h"
+#include "glibc.hpp"
+
+static const char *msvcrt_common_src[] = {
+ "misc" OS_SEP "onexit_table.c",
+ "misc" OS_SEP "register_tls_atexit.c",
+ "stdio" OS_SEP "acrt_iob_func.c",
+ "misc" OS_SEP "_configthreadlocale.c",
+ "misc" OS_SEP "_get_current_locale.c",
+ "misc" OS_SEP "invalid_parameter_handler.c",
+ "misc" OS_SEP "output_format.c",
+ "misc" OS_SEP "purecall.c",
+ "secapi" OS_SEP "_access_s.c",
+ "secapi" OS_SEP "_cgets_s.c",
+ "secapi" OS_SEP "_cgetws_s.c",
+ "secapi" OS_SEP "_chsize_s.c",
+ "secapi" OS_SEP "_controlfp_s.c",
+ "secapi" OS_SEP "_cprintf_s.c",
+ "secapi" OS_SEP "_cprintf_s_l.c",
+ "secapi" OS_SEP "_ctime32_s.c",
+ "secapi" OS_SEP "_ctime64_s.c",
+ "secapi" OS_SEP "_cwprintf_s.c",
+ "secapi" OS_SEP "_cwprintf_s_l.c",
+ "secapi" OS_SEP "_gmtime32_s.c",
+ "secapi" OS_SEP "_gmtime64_s.c",
+ "secapi" OS_SEP "_localtime32_s.c",
+ "secapi" OS_SEP "_localtime64_s.c",
+ "secapi" OS_SEP "_mktemp_s.c",
+ "secapi" OS_SEP "_sopen_s.c",
+ "secapi" OS_SEP "_strdate_s.c",
+ "secapi" OS_SEP "_strtime_s.c",
+ "secapi" OS_SEP "_umask_s.c",
+ "secapi" OS_SEP "_vcprintf_s.c",
+ "secapi" OS_SEP "_vcprintf_s_l.c",
+ "secapi" OS_SEP "_vcwprintf_s.c",
+ "secapi" OS_SEP "_vcwprintf_s_l.c",
+ "secapi" OS_SEP "_vscprintf_p.c",
+ "secapi" OS_SEP "_vscwprintf_p.c",
+ "secapi" OS_SEP "_vswprintf_p.c",
+ "secapi" OS_SEP "_waccess_s.c",
+ "secapi" OS_SEP "_wasctime_s.c",
+ "secapi" OS_SEP "_wctime32_s.c",
+ "secapi" OS_SEP "_wctime64_s.c",
+ "secapi" OS_SEP "_wstrtime_s.c",
+ "secapi" OS_SEP "_wmktemp_s.c",
+ "secapi" OS_SEP "_wstrdate_s.c",
+ "secapi" OS_SEP "asctime_s.c",
+ "secapi" OS_SEP "memcpy_s.c",
+ "secapi" OS_SEP "memmove_s.c",
+ "secapi" OS_SEP "rand_s.c",
+ "secapi" OS_SEP "sprintf_s.c",
+ "secapi" OS_SEP "strerror_s.c",
+ "secapi" OS_SEP "vsprintf_s.c",
+ "secapi" OS_SEP "wmemcpy_s.c",
+ "secapi" OS_SEP "wmemmove_s.c",
+ "stdio" OS_SEP "mingw_lock.c",
+};
+
+static const char *msvcrt_i386_src[] = {
+ "misc" OS_SEP "lc_locale_func.c",
-struct LinkJob {
- CodeGen *codegen;
- ZigList<const char *> args;
- bool link_in_crt;
- HashMap<Buf *, bool, buf_hash, buf_eql_buf> rpath_table;
};
-static CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType out_type,
- ZigLibCInstallation *libc)
-{
- CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type,
- parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir, libc, get_stage1_cache_path());
- child_gen->disable_gen_h = true;
- child_gen->want_stack_check = WantStackCheckDisabled;
- child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
- child_gen->verbose_ast = parent_gen->verbose_ast;
- child_gen->verbose_link = parent_gen->verbose_link;
- child_gen->verbose_ir = parent_gen->verbose_ir;
- child_gen->verbose_llvm_ir = parent_gen->verbose_llvm_ir;
- child_gen->verbose_cimport = parent_gen->verbose_cimport;
- child_gen->verbose_cc = parent_gen->verbose_cc;
- child_gen->llvm_argv = parent_gen->llvm_argv;
- child_gen->dynamic_linker_path = parent_gen->dynamic_linker_path;
+static const char *msvcrt_other_src[] = {
+ "misc" OS_SEP "__p___argv.c",
+ "misc" OS_SEP "__p__acmdln.c",
+ "misc" OS_SEP "__p__fmode.c",
+ "misc" OS_SEP "__p__wcmdln.c",
+};
- codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);
- child_gen->want_pic = parent_gen->have_pic ? WantPICEnabled : WantPICDisabled;
- child_gen->valgrind_support = ValgrindSupportDisabled;
+static const char *mingwex_generic_src[] = {
+ "complex" OS_SEP "_cabs.c",
+ "complex" OS_SEP "cabs.c",
+ "complex" OS_SEP "cabsf.c",
+ "complex" OS_SEP "cabsl.c",
+ "complex" OS_SEP "cacos.c",
+ "complex" OS_SEP "cacosf.c",
+ "complex" OS_SEP "cacosl.c",
+ "complex" OS_SEP "carg.c",
+ "complex" OS_SEP "cargf.c",
+ "complex" OS_SEP "cargl.c",
+ "complex" OS_SEP "casin.c",
+ "complex" OS_SEP "casinf.c",
+ "complex" OS_SEP "casinl.c",
+ "complex" OS_SEP "catan.c",
+ "complex" OS_SEP "catanf.c",
+ "complex" OS_SEP "catanl.c",
+ "complex" OS_SEP "ccos.c",
+ "complex" OS_SEP "ccosf.c",
+ "complex" OS_SEP "ccosl.c",
+ "complex" OS_SEP "cexp.c",
+ "complex" OS_SEP "cexpf.c",
+ "complex" OS_SEP "cexpl.c",
+ "complex" OS_SEP "cimag.c",
+ "complex" OS_SEP "cimagf.c",
+ "complex" OS_SEP "cimagl.c",
+ "complex" OS_SEP "clog.c",
+ "complex" OS_SEP "clog10.c",
+ "complex" OS_SEP "clog10f.c",
+ "complex" OS_SEP "clog10l.c",
+ "complex" OS_SEP "clogf.c",
+ "complex" OS_SEP "clogl.c",
+ "complex" OS_SEP "conj.c",
+ "complex" OS_SEP "conjf.c",
+ "complex" OS_SEP "conjl.c",
+ "complex" OS_SEP "cpow.c",
+ "complex" OS_SEP "cpowf.c",
+ "complex" OS_SEP "cpowl.c",
+ "complex" OS_SEP "cproj.c",
+ "complex" OS_SEP "cprojf.c",
+ "complex" OS_SEP "cprojl.c",
+ "complex" OS_SEP "creal.c",
+ "complex" OS_SEP "crealf.c",
+ "complex" OS_SEP "creall.c",
+ "complex" OS_SEP "csin.c",
+ "complex" OS_SEP "csinf.c",
+ "complex" OS_SEP "csinl.c",
+ "complex" OS_SEP "csqrt.c",
+ "complex" OS_SEP "csqrtf.c",
+ "complex" OS_SEP "csqrtl.c",
+ "complex" OS_SEP "ctan.c",
+ "complex" OS_SEP "ctanf.c",
+ "complex" OS_SEP "ctanl.c",
+ "crt" OS_SEP "dllentry.c",
+ "crt" OS_SEP "dllmain.c",
+ "gdtoa" OS_SEP "arithchk.c",
+ "gdtoa" OS_SEP "dmisc.c",
+ "gdtoa" OS_SEP "dtoa.c",
+ "gdtoa" OS_SEP "g__fmt.c",
+ "gdtoa" OS_SEP "g_dfmt.c",
+ "gdtoa" OS_SEP "g_ffmt.c",
+ "gdtoa" OS_SEP "g_xfmt.c",
+ "gdtoa" OS_SEP "gdtoa.c",
+ "gdtoa" OS_SEP "gethex.c",
+ "gdtoa" OS_SEP "gmisc.c",
+ "gdtoa" OS_SEP "hd_init.c",
+ "gdtoa" OS_SEP "hexnan.c",
+ "gdtoa" OS_SEP "misc.c",
+ "gdtoa" OS_SEP "qnan.c",
+ "gdtoa" OS_SEP "smisc.c",
+ "gdtoa" OS_SEP "strtodg.c",
+ "gdtoa" OS_SEP "strtodnrp.c",
+ "gdtoa" OS_SEP "strtof.c",
+ "gdtoa" OS_SEP "strtopx.c",
+ "gdtoa" OS_SEP "sum.c",
+ "gdtoa" OS_SEP "ulp.c",
+ "math" OS_SEP "abs64.c",
+ "math" OS_SEP "cbrt.c",
+ "math" OS_SEP "cbrtf.c",
+ "math" OS_SEP "cbrtl.c",
+ "math" OS_SEP "cephes_emath.c",
+ "math" OS_SEP "copysign.c",
+ "math" OS_SEP "copysignf.c",
+ "math" OS_SEP "coshf.c",
+ "math" OS_SEP "coshl.c",
+ "math" OS_SEP "erfl.c",
+ "math" OS_SEP "expf.c",
+ "math" OS_SEP "fabs.c",
+ "math" OS_SEP "fabsf.c",
+ "math" OS_SEP "fabsl.c",
+ "math" OS_SEP "fdim.c",
+ "math" OS_SEP "fdimf.c",
+ "math" OS_SEP "fdiml.c",
+ "math" OS_SEP "fma.c",
+ "math" OS_SEP "fmaf.c",
+ "math" OS_SEP "fmal.c",
+ "math" OS_SEP "fmax.c",
+ "math" OS_SEP "fmaxf.c",
+ "math" OS_SEP "fmaxl.c",
+ "math" OS_SEP "fmin.c",
+ "math" OS_SEP "fminf.c",
+ "math" OS_SEP "fminl.c",
+ "math" OS_SEP "fp_consts.c",
+ "math" OS_SEP "fp_constsf.c",
+ "math" OS_SEP "fp_constsl.c",
+ "math" OS_SEP "fpclassify.c",
+ "math" OS_SEP "fpclassifyf.c",
+ "math" OS_SEP "fpclassifyl.c",
+ "math" OS_SEP "frexpf.c",
+ "math" OS_SEP "hypot.c",
+ "math" OS_SEP "hypotf.c",
+ "math" OS_SEP "hypotl.c",
+ "math" OS_SEP "isnan.c",
+ "math" OS_SEP "isnanf.c",
+ "math" OS_SEP "isnanl.c",
+ "math" OS_SEP "ldexpf.c",
+ "math" OS_SEP "lgamma.c",
+ "math" OS_SEP "lgammaf.c",
+ "math" OS_SEP "lgammal.c",
+ "math" OS_SEP "llrint.c",
+ "math" OS_SEP "llrintf.c",
+ "math" OS_SEP "llrintl.c",
+ "math" OS_SEP "llround.c",
+ "math" OS_SEP "llroundf.c",
+ "math" OS_SEP "llroundl.c",
+ "math" OS_SEP "log10f.c",
+ "math" OS_SEP "logf.c",
+ "math" OS_SEP "lrint.c",
+ "math" OS_SEP "lrintf.c",
+ "math" OS_SEP "lrintl.c",
+ "math" OS_SEP "lround.c",
+ "math" OS_SEP "lroundf.c",
+ "math" OS_SEP "lroundl.c",
+ "math" OS_SEP "modf.c",
+ "math" OS_SEP "modff.c",
+ "math" OS_SEP "modfl.c",
+ "math" OS_SEP "nextafterf.c",
+ "math" OS_SEP "nextafterl.c",
+ "math" OS_SEP "nexttoward.c",
+ "math" OS_SEP "nexttowardf.c",
+ "math" OS_SEP "powf.c",
+ "math" OS_SEP "powi.c",
+ "math" OS_SEP "powif.c",
+ "math" OS_SEP "powil.c",
+ "math" OS_SEP "rint.c",
+ "math" OS_SEP "rintf.c",
+ "math" OS_SEP "rintl.c",
+ "math" OS_SEP "round.c",
+ "math" OS_SEP "roundf.c",
+ "math" OS_SEP "roundl.c",
+ "math" OS_SEP "s_erf.c",
+ "math" OS_SEP "sf_erf.c",
+ "math" OS_SEP "signbit.c",
+ "math" OS_SEP "signbitf.c",
+ "math" OS_SEP "signbitl.c",
+ "math" OS_SEP "signgam.c",
+ "math" OS_SEP "sinhf.c",
+ "math" OS_SEP "sinhl.c",
+ "math" OS_SEP "sqrt.c",
+ "math" OS_SEP "sqrtf.c",
+ "math" OS_SEP "sqrtl.c",
+ "math" OS_SEP "tanhf.c",
+ "math" OS_SEP "tanhl.c",
+ "math" OS_SEP "tgamma.c",
+ "math" OS_SEP "tgammaf.c",
+ "math" OS_SEP "tgammal.c",
+ "math" OS_SEP "truncl.c",
+ "misc" OS_SEP "alarm.c",
+ "misc" OS_SEP "assert.c",
+ "misc" OS_SEP "basename.c",
+ "misc" OS_SEP "btowc.c",
+ "misc" OS_SEP "delay-f.c",
+ "misc" OS_SEP "delay-n.c",
+ "misc" OS_SEP "delayimp.c",
+ "misc" OS_SEP "difftime.c",
+ "misc" OS_SEP "difftime32.c",
+ "misc" OS_SEP "difftime64.c",
+ "misc" OS_SEP "dirent.c",
+ "misc" OS_SEP "dirname.c",
+ "misc" OS_SEP "execv.c",
+ "misc" OS_SEP "execve.c",
+ "misc" OS_SEP "execvp.c",
+ "misc" OS_SEP "execvpe.c",
+ "misc" OS_SEP "feclearexcept.c",
+ "misc" OS_SEP "fegetenv.c",
+ "misc" OS_SEP "fegetexceptflag.c",
+ "misc" OS_SEP "fegetround.c",
+ "misc" OS_SEP "feholdexcept.c",
+ "misc" OS_SEP "feraiseexcept.c",
+ "misc" OS_SEP "fesetenv.c",
+ "misc" OS_SEP "fesetexceptflag.c",
+ "misc" OS_SEP "fesetround.c",
+ "misc" OS_SEP "fetestexcept.c",
+ "misc" OS_SEP "feupdateenv.c",
+ "misc" OS_SEP "ftruncate.c",
+ "misc" OS_SEP "ftw.c",
+ "misc" OS_SEP "ftw64.c",
+ "misc" OS_SEP "fwide.c",
+ "misc" OS_SEP "getlogin.c",
+ "misc" OS_SEP "getopt.c",
+ "misc" OS_SEP "gettimeofday.c",
+ "misc" OS_SEP "imaxabs.c",
+ "misc" OS_SEP "imaxdiv.c",
+ "misc" OS_SEP "isblank.c",
+ "misc" OS_SEP "iswblank.c",
+ "misc" OS_SEP "mbrtowc.c",
+ "misc" OS_SEP "mbsinit.c",
+ "misc" OS_SEP "mempcpy.c",
+ "misc" OS_SEP "mingw-aligned-malloc.c",
+ "misc" OS_SEP "mingw-fseek.c",
+ "misc" OS_SEP "mingw_getsp.S",
+ "misc" OS_SEP "mingw_matherr.c",
+ "misc" OS_SEP "mingw_mbwc_convert.c",
+ "misc" OS_SEP "mingw_usleep.c",
+ "misc" OS_SEP "mingw_wcstod.c",
+ "misc" OS_SEP "mingw_wcstof.c",
+ "misc" OS_SEP "mingw_wcstold.c",
+ "misc" OS_SEP "mkstemp.c",
+ "misc" OS_SEP "seterrno.c",
+ "misc" OS_SEP "sleep.c",
+ "misc" OS_SEP "spawnv.c",
+ "misc" OS_SEP "spawnve.c",
+ "misc" OS_SEP "spawnvp.c",
+ "misc" OS_SEP "spawnvpe.c",
+ "misc" OS_SEP "strnlen.c",
+ "misc" OS_SEP "strsafe.c",
+ "misc" OS_SEP "strtoimax.c",
+ "misc" OS_SEP "strtold.c",
+ "misc" OS_SEP "strtoumax.c",
+ "misc" OS_SEP "tdelete.c",
+ "misc" OS_SEP "tfind.c",
+ "misc" OS_SEP "tsearch.c",
+ "misc" OS_SEP "twalk.c",
+ "misc" OS_SEP "uchar_c16rtomb.c",
+ "misc" OS_SEP "uchar_c32rtomb.c",
+ "misc" OS_SEP "uchar_mbrtoc16.c",
+ "misc" OS_SEP "uchar_mbrtoc32.c",
+ "misc" OS_SEP "wassert.c",
+ "misc" OS_SEP "wcrtomb.c",
+ "misc" OS_SEP "wcsnlen.c",
+ "misc" OS_SEP "wcstof.c",
+ "misc" OS_SEP "wcstoimax.c",
+ "misc" OS_SEP "wcstold.c",
+ "misc" OS_SEP "wcstoumax.c",
+ "misc" OS_SEP "wctob.c",
+ "misc" OS_SEP "wctrans.c",
+ "misc" OS_SEP "wctype.c",
+ "misc" OS_SEP "wdirent.c",
+ "misc" OS_SEP "winbs_uint64.c",
+ "misc" OS_SEP "winbs_ulong.c",
+ "misc" OS_SEP "winbs_ushort.c",
+ "misc" OS_SEP "wmemchr.c",
+ "misc" OS_SEP "wmemcmp.c",
+ "misc" OS_SEP "wmemcpy.c",
+ "misc" OS_SEP "wmemmove.c",
+ "misc" OS_SEP "wmempcpy.c",
+ "misc" OS_SEP "wmemset.c",
+ "stdio" OS_SEP "_Exit.c",
+ "stdio" OS_SEP "_findfirst64i32.c",
+ "stdio" OS_SEP "_findnext64i32.c",
+ "stdio" OS_SEP "_fstat.c",
+ "stdio" OS_SEP "_fstat64i32.c",
+ "stdio" OS_SEP "_ftime.c",
+ "stdio" OS_SEP "_getc_nolock.c",
+ "stdio" OS_SEP "_getwc_nolock.c",
+ "stdio" OS_SEP "_putc_nolock.c",
+ "stdio" OS_SEP "_putwc_nolock.c",
+ "stdio" OS_SEP "_stat.c",
+ "stdio" OS_SEP "_stat64i32.c",
+ "stdio" OS_SEP "_wfindfirst64i32.c",
+ "stdio" OS_SEP "_wfindnext64i32.c",
+ "stdio" OS_SEP "_wstat.c",
+ "stdio" OS_SEP "_wstat64i32.c",
+ "stdio" OS_SEP "asprintf.c",
+ "stdio" OS_SEP "atoll.c",
+ "stdio" OS_SEP "fgetpos64.c",
+ "stdio" OS_SEP "fopen64.c",
+ "stdio" OS_SEP "fseeko32.c",
+ "stdio" OS_SEP "fseeko64.c",
+ "stdio" OS_SEP "fsetpos64.c",
+ "stdio" OS_SEP "ftello.c",
+ "stdio" OS_SEP "ftello64.c",
+ "stdio" OS_SEP "ftruncate64.c",
+ "stdio" OS_SEP "lltoa.c",
+ "stdio" OS_SEP "lltow.c",
+ "stdio" OS_SEP "lseek64.c",
+ "stdio" OS_SEP "mingw_asprintf.c",
+ "stdio" OS_SEP "mingw_fprintf.c",
+ "stdio" OS_SEP "mingw_fprintfw.c",
+ "stdio" OS_SEP "mingw_fscanf.c",
+ "stdio" OS_SEP "mingw_fwscanf.c",
+ "stdio" OS_SEP "mingw_pformat.c",
+ "stdio" OS_SEP "mingw_pformatw.c",
+ "stdio" OS_SEP "mingw_printf.c",
+ "stdio" OS_SEP "mingw_printfw.c",
+ "stdio" OS_SEP "mingw_scanf.c",
+ "stdio" OS_SEP "mingw_snprintf.c",
+ "stdio" OS_SEP "mingw_snprintfw.c",
+ "stdio" OS_SEP "mingw_sprintf.c",
+ "stdio" OS_SEP "mingw_sprintfw.c",
+ "stdio" OS_SEP "mingw_sscanf.c",
+ "stdio" OS_SEP "mingw_swscanf.c",
+ "stdio" OS_SEP "mingw_vasprintf.c",
+ "stdio" OS_SEP "mingw_vfprintf.c",
+ "stdio" OS_SEP "mingw_vfprintfw.c",
+ "stdio" OS_SEP "mingw_vfscanf.c",
+ "stdio" OS_SEP "mingw_vprintf.c",
+ "stdio" OS_SEP "mingw_vprintfw.c",
+ "stdio" OS_SEP "mingw_vsnprintf.c",
+ "stdio" OS_SEP "mingw_vsnprintfw.c",
+ "stdio" OS_SEP "mingw_vsprintf.c",
+ "stdio" OS_SEP "mingw_vsprintfw.c",
+ "stdio" OS_SEP "mingw_wscanf.c",
+ "stdio" OS_SEP "mingw_wvfscanf.c",
+ "stdio" OS_SEP "scanf.S",
+ "stdio" OS_SEP "snprintf.c",
+ "stdio" OS_SEP "snwprintf.c",
+ "stdio" OS_SEP "strtof.c",
+ "stdio" OS_SEP "strtok_r.c",
+ "stdio" OS_SEP "truncate.c",
+ "stdio" OS_SEP "ulltoa.c",
+ "stdio" OS_SEP "ulltow.c",
+ "stdio" OS_SEP "vasprintf.c",
+ "stdio" OS_SEP "vfscanf.c",
+ "stdio" OS_SEP "vfscanf2.S",
+ "stdio" OS_SEP "vfwscanf.c",
+ "stdio" OS_SEP "vfwscanf2.S",
+ "stdio" OS_SEP "vscanf.c",
+ "stdio" OS_SEP "vscanf2.S",
+ "stdio" OS_SEP "vsnprintf.c",
+ "stdio" OS_SEP "vsnwprintf.c",
+ "stdio" OS_SEP "vsscanf.c",
+ "stdio" OS_SEP "vsscanf2.S",
+ "stdio" OS_SEP "vswscanf.c",
+ "stdio" OS_SEP "vswscanf2.S",
+ "stdio" OS_SEP "vwscanf.c",
+ "stdio" OS_SEP "vwscanf2.S",
+ "stdio" OS_SEP "wtoll.c",
+};
- codegen_set_errmsg_color(child_gen, parent_gen->err_color);
+static const char *mingwex_x86_src[] = {
+ "math" OS_SEP "x86" OS_SEP "acosf.c",
+ "math" OS_SEP "x86" OS_SEP "acosh.c",
+ "math" OS_SEP "x86" OS_SEP "acoshf.c",
+ "math" OS_SEP "x86" OS_SEP "acoshl.c",
+ "math" OS_SEP "x86" OS_SEP "acosl.c",
+ "math" OS_SEP "x86" OS_SEP "asinf.c",
+ "math" OS_SEP "x86" OS_SEP "asinh.c",
+ "math" OS_SEP "x86" OS_SEP "asinhf.c",
+ "math" OS_SEP "x86" OS_SEP "asinhl.c",
+ "math" OS_SEP "x86" OS_SEP "asinl.c",
+ "math" OS_SEP "x86" OS_SEP "atan2.c",
+ "math" OS_SEP "x86" OS_SEP "atan2f.c",
+ "math" OS_SEP "x86" OS_SEP "atan2l.c",
+ "math" OS_SEP "x86" OS_SEP "atanf.c",
+ "math" OS_SEP "x86" OS_SEP "atanh.c",
+ "math" OS_SEP "x86" OS_SEP "atanhf.c",
+ "math" OS_SEP "x86" OS_SEP "atanhl.c",
+ "math" OS_SEP "x86" OS_SEP "atanl.c",
+ "math" OS_SEP "x86" OS_SEP "ceilf.S",
+ "math" OS_SEP "x86" OS_SEP "ceill.S",
+ "math" OS_SEP "x86" OS_SEP "ceil.S",
+ "math" OS_SEP "x86" OS_SEP "_chgsignl.S",
+ "math" OS_SEP "x86" OS_SEP "copysignl.S",
+ "math" OS_SEP "x86" OS_SEP "cos.c",
+ "math" OS_SEP "x86" OS_SEP "cosf.c",
+ "math" OS_SEP "x86" OS_SEP "cosl.c",
+ "math" OS_SEP "x86" OS_SEP "cosl_internal.S",
+ "math" OS_SEP "x86" OS_SEP "cossin.c",
+ "math" OS_SEP "x86" OS_SEP "exp2f.S",
+ "math" OS_SEP "x86" OS_SEP "exp2l.S",
+ "math" OS_SEP "x86" OS_SEP "exp2.S",
+ "math" OS_SEP "x86" OS_SEP "exp.c",
+ "math" OS_SEP "x86" OS_SEP "expl.c",
+ "math" OS_SEP "x86" OS_SEP "expm1.c",
+ "math" OS_SEP "x86" OS_SEP "expm1f.c",
+ "math" OS_SEP "x86" OS_SEP "expm1l.c",
+ "math" OS_SEP "x86" OS_SEP "floorf.S",
+ "math" OS_SEP "x86" OS_SEP "floorl.S",
+ "math" OS_SEP "x86" OS_SEP "floor.S",
+ "math" OS_SEP "x86" OS_SEP "fmod.c",
+ "math" OS_SEP "x86" OS_SEP "fmodf.c",
+ "math" OS_SEP "x86" OS_SEP "fmodl.c",
+ "math" OS_SEP "x86" OS_SEP "frexpl.S",
+ "math" OS_SEP "x86" OS_SEP "fucom.c",
+ "math" OS_SEP "x86" OS_SEP "ilogbf.S",
+ "math" OS_SEP "x86" OS_SEP "ilogbl.S",
+ "math" OS_SEP "x86" OS_SEP "ilogb.S",
+ "math" OS_SEP "x86" OS_SEP "internal_logl.S",
+ "math" OS_SEP "x86" OS_SEP "ldexp.c",
+ "math" OS_SEP "x86" OS_SEP "ldexpl.c",
+ "math" OS_SEP "x86" OS_SEP "log10l.S",
+ "math" OS_SEP "x86" OS_SEP "log1pf.S",
+ "math" OS_SEP "x86" OS_SEP "log1pl.S",
+ "math" OS_SEP "x86" OS_SEP "log1p.S",
+ "math" OS_SEP "x86" OS_SEP "log2f.S",
+ "math" OS_SEP "x86" OS_SEP "log2l.S",
+ "math" OS_SEP "x86" OS_SEP "log2.S",
+ "math" OS_SEP "x86" OS_SEP "logb.c",
+ "math" OS_SEP "x86" OS_SEP "logbf.c",
+ "math" OS_SEP "x86" OS_SEP "logbl.c",
+ "math" OS_SEP "x86" OS_SEP "log.c",
+ "math" OS_SEP "x86" OS_SEP "logl.c",
+ "math" OS_SEP "x86" OS_SEP "nearbyintf.S",
+ "math" OS_SEP "x86" OS_SEP "nearbyintl.S",
+ "math" OS_SEP "x86" OS_SEP "nearbyint.S",
+ "math" OS_SEP "x86" OS_SEP "pow.c",
+ "math" OS_SEP "x86" OS_SEP "powl.c",
+ "math" OS_SEP "x86" OS_SEP "remainderf.S",
+ "math" OS_SEP "x86" OS_SEP "remainderl.S",
+ "math" OS_SEP "x86" OS_SEP "remainder.S",
+ "math" OS_SEP "x86" OS_SEP "remquof.S",
+ "math" OS_SEP "x86" OS_SEP "remquol.S",
+ "math" OS_SEP "x86" OS_SEP "remquo.S",
+ "math" OS_SEP "x86" OS_SEP "scalbnf.S",
+ "math" OS_SEP "x86" OS_SEP "scalbnl.S",
+ "math" OS_SEP "x86" OS_SEP "scalbn.S",
+ "math" OS_SEP "x86" OS_SEP "sin.c",
+ "math" OS_SEP "x86" OS_SEP "sinf.c",
+ "math" OS_SEP "x86" OS_SEP "sinl.c",
+ "math" OS_SEP "x86" OS_SEP "sinl_internal.S",
+ "math" OS_SEP "x86" OS_SEP "tanf.c",
+ "math" OS_SEP "x86" OS_SEP "tanl.S",
+ "math" OS_SEP "x86" OS_SEP "truncf.S",
+ "math" OS_SEP "x86" OS_SEP "trunc.S",
+};
- codegen_set_mmacosx_version_min(child_gen, parent_gen->mmacosx_version_min);
- codegen_set_mios_version_min(child_gen, parent_gen->mios_version_min);
+static const char *mingwex_arm32_src[] = {
+ "math" OS_SEP "arm" OS_SEP "_chgsignl.S",
+ "math" OS_SEP "arm" OS_SEP "ceil.S",
+ "math" OS_SEP "arm" OS_SEP "ceilf.S",
+ "math" OS_SEP "arm" OS_SEP "ceill.S",
+ "math" OS_SEP "arm" OS_SEP "copysignl.c",
+ "math" OS_SEP "arm" OS_SEP "exp2.c",
+ "math" OS_SEP "arm" OS_SEP "floor.S",
+ "math" OS_SEP "arm" OS_SEP "floorf.S",
+ "math" OS_SEP "arm" OS_SEP "floorl.S",
+ "math" OS_SEP "arm" OS_SEP "ldexpl.c",
+ "math" OS_SEP "arm" OS_SEP "log2.c",
+ "math" OS_SEP "arm" OS_SEP "nearbyint.S",
+ "math" OS_SEP "arm" OS_SEP "nearbyintf.S",
+ "math" OS_SEP "arm" OS_SEP "nearbyintl.S",
+ "math" OS_SEP "arm" OS_SEP "scalbn.c",
+ "math" OS_SEP "arm" OS_SEP "sincos.c",
+ "math" OS_SEP "arm" OS_SEP "trunc.S",
+ "math" OS_SEP "arm" OS_SEP "truncf.S",
+};
- child_gen->enable_cache = true;
+static const char *mingwex_arm64_src[] = {
+ "math" OS_SEP "arm64" OS_SEP "ceilf.S",
+ "math" OS_SEP "arm64" OS_SEP "ceill.S",
+ "math" OS_SEP "arm64" OS_SEP "ceil.S",
+ "math" OS_SEP "arm64" OS_SEP "_chgsignl.S",
+ "math" OS_SEP "arm64" OS_SEP "copysignl.c",
+ "math" OS_SEP "arm64" OS_SEP "exp2f.S",
+ "math" OS_SEP "arm64" OS_SEP "exp2.S",
+ "math" OS_SEP "arm64" OS_SEP "floorf.S",
+ "math" OS_SEP "arm64" OS_SEP "floorl.S",
+ "math" OS_SEP "arm64" OS_SEP "floor.S",
+ "math" OS_SEP "arm64" OS_SEP "ldexpl.c",
+ "math" OS_SEP "arm64" OS_SEP "log2.c",
+ "math" OS_SEP "arm64" OS_SEP "nearbyintf.S",
+ "math" OS_SEP "arm64" OS_SEP "nearbyintl.S",
+ "math" OS_SEP "arm64" OS_SEP "nearbyint.S",
+ "math" OS_SEP "arm64" OS_SEP "scalbn.c",
+ "math" OS_SEP "arm64" OS_SEP "sincos.c",
+ "math" OS_SEP "arm64" OS_SEP "truncf.S",
+ "math" OS_SEP "arm64" OS_SEP "trunc.S",
+};
- return child_gen;
-}
+struct MinGWDef {
+ const char *name;
+ const char *path;
+ bool always_link;
+};
+static const MinGWDef mingw_def_list[] = {
+ {"msvcrt", "lib-common" OS_SEP "msvcrt.def.in", true},
+ {"setupapi", "libarm32" OS_SEP "setupapi.def", false},
+ {"setupapi", "libarm64" OS_SEP "setupapi.def", false},
+ {"setupapi", "lib32" OS_SEP "setupapi.def", false},
+ {"setupapi", "lib64" OS_SEP "setupapi.def", false},
+ {"winmm", "lib-common" OS_SEP "winmm.def", false},
+ {"gdi32", "lib-common" OS_SEP "gdi32.def", false},
+ {"imm32", "lib-common" OS_SEP "imm32.def", false},
+ {"version", "lib-common" OS_SEP "version.def", false},
+ {"advapi32", "lib-common" OS_SEP "advapi32.def.in", true},
+ {"oleaut32", "lib-common" OS_SEP "oleaut32.def.in", false},
+ {"ole32", "lib-common" OS_SEP "ole32.def.in", false},
+ {"shell32", "lib-common" OS_SEP "shell32.def", true},
+ {"user32", "lib-common" OS_SEP "user32.def.in", true},
+ {"kernel32", "lib-common" OS_SEP "kernel32.def.in", true},
+ {"ntdll", "libarm32" OS_SEP "ntdll.def", true},
+ {"ntdll", "lib32" OS_SEP "ntdll.def", true},
+ {"ntdll", "lib64" OS_SEP "ntdll.def", true},
+};
+
+struct LinkJob {
+ CodeGen *codegen;
+ ZigList<const char *> args;
+ bool link_in_crt;
+ HashMap<Buf *, bool, buf_hash, buf_eql_buf> rpath_table;
+};
static const char *build_libc_object(CodeGen *parent_gen, const char *name, CFile *c_file) {
CodeGen *child_gen = create_child_codegen(parent_gen, nullptr, OutTypeObj, nullptr);
@@ -76,18 +609,6 @@ static const char *path_from_libunwind(CodeGen *g, const char *subpath) {
return path_from_zig_lib(g, "libunwind", subpath);
}
-static const char *build_dummy_so(CodeGen *parent, const char *name, size_t major_version) {
- Buf *glibc_dummy_root_src = buf_sprintf("%s" OS_SEP "libc" OS_SEP "dummy" OS_SEP "%s.zig",
- buf_ptr(parent->zig_lib_dir), name);
- CodeGen *child_gen = create_child_codegen(parent, glibc_dummy_root_src, OutTypeLib, nullptr);
- codegen_set_out_name(child_gen, buf_create_from_str(name));
- codegen_set_lib_version(child_gen, major_version, 0, 0);
- child_gen->is_dynamic = true;
- child_gen->is_dummy_so = true;
- codegen_build_and_link(child_gen);
- return buf_ptr(&child_gen->output_file_path);
-}
-
static const char *build_libunwind(CodeGen *parent) {
CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr);
codegen_set_out_name(child_gen, buf_create_from_str("unwind"));
@@ -150,6 +671,29 @@ static const char *build_libunwind(CodeGen *parent) {
return buf_ptr(&child_gen->output_file_path);
}
+static void mingw_add_cc_args(CodeGen *parent, CFile *c_file) {
+ c_file->args.append("-DHAVE_CONFIG_H");
+
+ c_file->args.append("-I");
+ c_file->args.append(buf_ptr(buf_sprintf("%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "include",
+ buf_ptr(parent->zig_lib_dir))));
+
+ c_file->args.append("-isystem");
+ c_file->args.append(buf_ptr(buf_sprintf("%s" OS_SEP "libc" OS_SEP "include" OS_SEP "any-windows-any",
+ buf_ptr(parent->zig_lib_dir))));
+
+ if (target_is_arm(parent->zig_target) &&
+ target_arch_pointer_bit_width(parent->zig_target->arch) == 32)
+ {
+ c_file->args.append("-mfpu=vfp");
+ }
+
+ c_file->args.append("-std=gnu11");
+ c_file->args.append("-D_CRTBLD");
+ c_file->args.append("-D_WIN32_WINNT=0x0f00");
+ c_file->args.append("-D__MSVCRT_VERSION__=0x700");
+}
+
static void glibc_add_include_dirs_arch(CFile *c_file, ZigLLVM_ArchType arch, const char *nptl, const char *dir) {
bool is_x86 = arch == ZigLLVM_x86 || arch == ZigLLVM_x86_64;
bool is_aarch64 = arch == ZigLLVM_aarch64 || arch == ZigLLVM_aarch64_be;
@@ -591,9 +1135,183 @@ static const char *build_musl(CodeGen *parent) {
return buf_ptr(&child_gen->output_file_path);
}
+static void add_msvcrt_os_dep(CodeGen *parent, CodeGen *child_gen, const char *src_path) {
+ CFile *c_file = allocate<CFile>(1);
+ c_file->source_path = buf_ptr(buf_sprintf("%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "%s",
+ buf_ptr(parent->zig_lib_dir), src_path));
+ c_file->args.append("-DHAVE_CONFIG_H");
+ c_file->args.append("-D__LIBMSVCRT__");
+
+ c_file->args.append("-I");
+ c_file->args.append(path_from_libc(parent, "mingw" OS_SEP "include"));
+
+ c_file->args.append("-std=gnu99");
+ c_file->args.append("-D_CRTBLD");
+ c_file->args.append("-D_WIN32_WINNT=0x0f00");
+ c_file->args.append("-D__MSVCRT_VERSION__=0x700");
+
+ c_file->args.append("-isystem");
+ c_file->args.append(path_from_libc(parent, "include" OS_SEP "any-windows-any"));
+
+ c_file->args.append("-g");
+ c_file->args.append("-O2");
+
+ child_gen->c_source_files.append(c_file);
+}
+
+static void add_mingwex_os_dep(CodeGen *parent, CodeGen *child_gen, const char *src_path) {
+ CFile *c_file = allocate<CFile>(1);
+ c_file->source_path = buf_ptr(buf_sprintf("%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "%s",
+ buf_ptr(parent->zig_lib_dir), src_path));
+ c_file->args.append("-DHAVE_CONFIG_H");
+
+ c_file->args.append("-I");
+ c_file->args.append(path_from_libc(parent, "mingw"));
+
+ c_file->args.append("-I");
+ c_file->args.append(path_from_libc(parent, "mingw" OS_SEP "include"));
+
+ c_file->args.append("-std=gnu99");
+ c_file->args.append("-D_CRTBLD");
+ c_file->args.append("-D_WIN32_WINNT=0x0f00");
+ c_file->args.append("-D__MSVCRT_VERSION__=0x700");
+ c_file->args.append("-g");
+ c_file->args.append("-O2");
+
+ c_file->args.append("-isystem");
+ c_file->args.append(path_from_libc(parent, "include" OS_SEP "any-windows-any"));
+
+ child_gen->c_source_files.append(c_file);
+}
static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
- if (parent->libc == nullptr && target_is_glibc(parent->zig_target)) {
+ if (parent->libc == nullptr && parent->zig_target->os == OsWindows) {
+ if (strcmp(file, "crt2.o") == 0) {
+ CFile *c_file = allocate<CFile>(1);
+ c_file->source_path = buf_ptr(buf_sprintf(
+ "%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "crt" OS_SEP "crtexe.c", buf_ptr(parent->zig_lib_dir)));
+ mingw_add_cc_args(parent, c_file);
+ c_file->args.append("-U__CRTDLL__");
+ c_file->args.append("-D__MSVCRT__");
+ // Uncomment these 3 things for crtu
+ //c_file->args.append("-DUNICODE");
+ //c_file->args.append("-D_UNICODE");
+ //c_file->args.append("-DWPRFLAG=1");
+ return build_libc_object(parent, "crt2", c_file);
+ } else if (strcmp(file, "dllcrt2.o") == 0) {
+ CFile *c_file = allocate<CFile>(1);
+ c_file->source_path = buf_ptr(buf_sprintf(
+ "%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "crt" OS_SEP "crtdll.c", buf_ptr(parent->zig_lib_dir)));
+ mingw_add_cc_args(parent, c_file);
+ c_file->args.append("-U__CRTDLL__");
+ c_file->args.append("-D__MSVCRT__");
+ return build_libc_object(parent, "dllcrt2", c_file);
+ } else if (strcmp(file, "mingw32.lib") == 0) {
+ CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr);
+ codegen_set_out_name(child_gen, buf_create_from_str("mingw32"));
+
+ static const char *deps[] = {
+ "mingw" OS_SEP "crt" OS_SEP "crt0_c.c",
+ "mingw" OS_SEP "crt" OS_SEP "dll_argv.c",
+ "mingw" OS_SEP "crt" OS_SEP "gccmain.c",
+ "mingw" OS_SEP "crt" OS_SEP "natstart.c",
+ "mingw" OS_SEP "crt" OS_SEP "pseudo-reloc-list.c",
+ "mingw" OS_SEP "crt" OS_SEP "wildcard.c",
+ "mingw" OS_SEP "crt" OS_SEP "charmax.c",
+ "mingw" OS_SEP "crt" OS_SEP "crt0_w.c",
+ "mingw" OS_SEP "crt" OS_SEP "dllargv.c",
+ "mingw" OS_SEP "crt" OS_SEP "gs_support.c",
+ "mingw" OS_SEP "crt" OS_SEP "_newmode.c",
+ "mingw" OS_SEP "crt" OS_SEP "tlssup.c",
+ "mingw" OS_SEP "crt" OS_SEP "xncommod.c",
+ "mingw" OS_SEP "crt" OS_SEP "cinitexe.c",
+ "mingw" OS_SEP "crt" OS_SEP "merr.c",
+ "mingw" OS_SEP "crt" OS_SEP "pesect.c",
+ "mingw" OS_SEP "crt" OS_SEP "udllargc.c",
+ "mingw" OS_SEP "crt" OS_SEP "xthdloc.c",
+ "mingw" OS_SEP "crt" OS_SEP "CRT_fp10.c",
+ "mingw" OS_SEP "crt" OS_SEP "mingw_helpers.c",
+ "mingw" OS_SEP "crt" OS_SEP "pseudo-reloc.c",
+ "mingw" OS_SEP "crt" OS_SEP "udll_argv.c",
+ "mingw" OS_SEP "crt" OS_SEP "xtxtmode.c",
+ "mingw" OS_SEP "crt" OS_SEP "crt_handler.c",
+ "mingw" OS_SEP "crt" OS_SEP "tlsthrd.c",
+ "mingw" OS_SEP "crt" OS_SEP "tlsmthread.c",
+ "mingw" OS_SEP "crt" OS_SEP "tlsmcrt.c",
+ "mingw" OS_SEP "crt" OS_SEP "cxa_atexit.c",
+ };
+ for (size_t i = 0; i < array_length(deps); i += 1) {
+ CFile *c_file = allocate<CFile>(1);
+ c_file->source_path = path_from_libc(parent, deps[i]);
+ c_file->args.append("-DHAVE_CONFIG_H");
+ c_file->args.append("-D_SYSCRT=1");
+ c_file->args.append("-DCRTDLL=1");
+
+ c_file->args.append("-isystem");
+ c_file->args.append(path_from_libc(parent, "include" OS_SEP "any-windows-any"));
+
+ c_file->args.append("-isystem");
+ c_file->args.append(path_from_libc(parent, "mingw" OS_SEP "include"));
+
+ c_file->args.append("-std=gnu99");
+ c_file->args.append("-D_CRTBLD");
+ c_file->args.append("-D_WIN32_WINNT=0x0f00");
+ c_file->args.append("-D__MSVCRT_VERSION__=0x700");
+ c_file->args.append("-g");
+ c_file->args.append("-O2");
+
+ child_gen->c_source_files.append(c_file);
+ }
+ codegen_build_and_link(child_gen);
+ return buf_ptr(&child_gen->output_file_path);
+ } else if (strcmp(file, "msvcrt-os.lib") == 0) {
+ CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr);
+ codegen_set_out_name(child_gen, buf_create_from_str("msvcrt-os"));
+
+ for (size_t i = 0; i < array_length(msvcrt_common_src); i += 1) {
+ add_msvcrt_os_dep(parent, child_gen, msvcrt_common_src[i]);
+ }
+ if (parent->zig_target->arch == ZigLLVM_x86) {
+ for (size_t i = 0; i < array_length(msvcrt_i386_src); i += 1) {
+ add_msvcrt_os_dep(parent, child_gen, msvcrt_i386_src[i]);
+ }
+ } else {
+ for (size_t i = 0; i < array_length(msvcrt_other_src); i += 1) {
+ add_msvcrt_os_dep(parent, child_gen, msvcrt_other_src[i]);
+ }
+ }
+ codegen_build_and_link(child_gen);
+ return buf_ptr(&child_gen->output_file_path);
+ } else if (strcmp(file, "mingwex.lib") == 0) {
+ CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr);
+ codegen_set_out_name(child_gen, buf_create_from_str("mingwex"));
+
+ for (size_t i = 0; i < array_length(mingwex_generic_src); i += 1) {
+ add_mingwex_os_dep(parent, child_gen, mingwex_generic_src[i]);
+ }
+ if (parent->zig_target->arch == ZigLLVM_x86 || parent->zig_target->arch == ZigLLVM_x86_64) {
+ for (size_t i = 0; i < array_length(mingwex_x86_src); i += 1) {
+ add_mingwex_os_dep(parent, child_gen, mingwex_x86_src[i]);
+ }
+ } else if (target_is_arm(parent->zig_target)) {
+ if (target_arch_pointer_bit_width(parent->zig_target->arch) == 32) {
+ for (size_t i = 0; i < array_length(mingwex_arm32_src); i += 1) {
+ add_mingwex_os_dep(parent, child_gen, mingwex_arm32_src[i]);
+ }
+ } else {
+ for (size_t i = 0; i < array_length(mingwex_arm64_src); i += 1) {
+ add_mingwex_os_dep(parent, child_gen, mingwex_arm64_src[i]);
+ }
+ }
+ } else {
+ zig_unreachable();
+ }
+ codegen_build_and_link(child_gen);
+ return buf_ptr(&child_gen->output_file_path);
+ } else {
+ zig_unreachable();
+ }
+ } else if (parent->libc == nullptr && target_is_glibc(parent->zig_target)) {
if (strcmp(file, "crti.o") == 0) {
CFile *c_file = allocate<CFile>(1);
c_file->source_path = glibc_start_asm_path(parent, "crti.S");
@@ -791,6 +1509,9 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path,
new_link_lib->provided_explicitly = parent_gen->libc_link_lib->provided_explicitly;
}
+ child_gen->function_sections = true;
+ child_gen->want_stack_check = WantStackCheckDisabled;
+
codegen_build_and_link(child_gen);
return &child_gen->output_file_path;
}
@@ -890,6 +1611,30 @@ static void add_rpath(LinkJob *lj, Buf *rpath) {
lj->rpath_table.put(rpath, true);
}
+static void add_glibc_libs(LinkJob *lj) {
+ Error err;
+ ZigGLibCAbi *glibc_abi;
+ if ((err = glibc_load_metadata(&glibc_abi, lj->codegen->zig_lib_dir, true))) {
+ fprintf(stderr, "%s\n", err_str(err));
+ exit(1);
+ }
+
+ Buf *artifact_dir;
+ if ((err = glibc_build_dummies_and_maps(lj->codegen, glibc_abi, lj->codegen->zig_target,
+ &artifact_dir, true)))
+ {
+ fprintf(stderr, "%s\n", err_str(err));
+ exit(1);
+ }
+
+ size_t lib_count = glibc_lib_count();
+ for (size_t i = 0; i < lib_count; i += 1) {
+ const ZigGLibCLib *lib = glibc_lib_enum(i);
+ Buf *so_path = buf_sprintf("%s" OS_SEP "lib%s.so.%d.0.0", buf_ptr(artifact_dir), lib->name, lib->sover);
+ lj->args.append(buf_ptr(so_path));
+ }
+}
+
static void construct_linker_job_elf(LinkJob *lj) {
CodeGen *g = lj->codegen;
@@ -988,6 +1733,11 @@ static void construct_linker_job_elf(LinkJob *lj) {
if (is_dyn_lib) {
lj->args.append("-soname");
lj->args.append(buf_ptr(soname));
+
+ if (g->version_script_path != nullptr) {
+ lj->args.append("-version-script");
+ lj->args.append(buf_ptr(g->version_script_path));
+ }
}
// .o files
@@ -1051,11 +1801,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
}
} else if (target_is_glibc(g->zig_target)) {
lj->args.append(build_libunwind(g));
- lj->args.append(build_dummy_so(g, "c", 6));
- lj->args.append(build_dummy_so(g, "m", 6));
- lj->args.append(build_dummy_so(g, "pthread", 0));
- lj->args.append(build_dummy_so(g, "dl", 2));
- lj->args.append(build_dummy_so(g, "rt", 1));
+ add_glibc_libs(lj);
lj->args.append(get_libc_crt_file(g, "libc_nonshared.a"));
} else if (target_is_musl(g->zig_target)) {
lj->args.append(build_libunwind(g));
@@ -1088,7 +1834,7 @@ static void construct_linker_job_wasm(LinkJob *lj) {
lj->args.append("-error-limit=0");
if (g->out_type != OutTypeExe) {
- lj->args.append("--no-entry"); // So lld doesn't look for _start.
+ lj->args.append("--no-entry"); // So lld doesn't look for _start.
// If there are any C source files we cannot rely on individual exports.
if (g->c_source_files.length != 0) {
@@ -1125,8 +1871,12 @@ static void coff_append_machine_arg(CodeGen *g, ZigList<const char *> *list) {
list->append("-MACHINE:X86");
} else if (g->zig_target->arch == ZigLLVM_x86_64) {
list->append("-MACHINE:X64");
- } else if (g->zig_target->arch == ZigLLVM_arm) {
- list->append("-MACHINE:ARM");
+ } else if (target_is_arm(g->zig_target)) {
+ if (target_arch_pointer_bit_width(g->zig_target->arch) == 32) {
+ list->append("-MACHINE:ARM");
+ } else {
+ list->append("-MACHINE:ARM64");
+ }
}
}
@@ -1154,8 +1904,7 @@ static void add_uefi_link_args(LinkJob *lj) {
static void add_msvc_link_args(LinkJob *lj, bool is_library) {
CodeGen *g = lj->codegen;
- // TODO: https://github.com/ziglang/zig/issues/2064
- bool is_dynamic = true; // g->is_dynamic;
+ bool is_dynamic = g->is_dynamic;
const char *lib_str = is_dynamic ? "" : "lib";
const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : "";
@@ -1182,21 +1931,161 @@ static void add_msvc_link_args(LinkJob *lj, bool is_library) {
lj->args.append("ntdll.lib");
}
-static const char *get_libc_file(ZigLibCInstallation *lib, const char *file) {
- Buf *out_buf = buf_alloc();
- os_path_join(&lib->crt_dir, buf_create_from_str(file), out_buf);
- return buf_ptr(out_buf);
+static void print_zig_cc_cmd(ZigList<const char *> *args) {
+ for (size_t arg_i = 0; arg_i < args->length; arg_i += 1) {
+ const char *space_str = (arg_i == 0) ? "" : " ";
+ fprintf(stderr, "%s%s", space_str, args->at(arg_i));
+ }
+ fprintf(stderr, "\n");
}
-static const char *get_libc_static_file(ZigLibCInstallation *lib, const char *file) {
- Buf *out_buf = buf_alloc();
- os_path_join(&lib->static_crt_dir, buf_create_from_str(file), out_buf);
- return buf_ptr(out_buf);
+static const char *get_def_lib(CodeGen *parent, const char *name, Buf *def_in_rel_path) {
+ Error err;
+
+ Buf *self_exe_path = buf_alloc();
+ if ((err = os_self_exe_path(self_exe_path))) {
+ fprintf(stderr, "Unable to get self exe path: %s\n", err_str(err));
+ exit(1);
+ }
+ Buf *compiler_id;
+ if ((err = get_compiler_id(&compiler_id))) {
+ fprintf(stderr, "Unable to get compiler id: %s\n", err_str(err));
+ exit(1);
+ }
+
+ Buf *cache_dir = get_stage1_cache_path();
+ Buf *o_dir = buf_sprintf("%s" OS_SEP CACHE_OUT_SUBDIR, buf_ptr(cache_dir));
+ Buf *manifest_dir = buf_sprintf("%s" OS_SEP CACHE_HASH_SUBDIR, buf_ptr(cache_dir));
+
+ Buf *def_in_file = buf_sprintf("%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "%s",
+ buf_ptr(parent->zig_lib_dir), buf_ptr(def_in_rel_path));
+ Buf *def_include_dir = buf_sprintf("%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "def-include",
+ buf_ptr(parent->zig_lib_dir));
+
+ CacheHash *cache_hash = allocate<CacheHash>(1);
+ cache_init(cache_hash, manifest_dir);
+
+ cache_buf(cache_hash, compiler_id);
+ cache_file(cache_hash, def_in_file);
+ cache_buf(cache_hash, def_include_dir);
+ cache_int(cache_hash, parent->zig_target->arch);
+
+ Buf digest = BUF_INIT;
+ buf_resize(&digest, 0);
+ if ((err = cache_hit(cache_hash, &digest))) {
+ if (err != ErrorInvalidFormat) {
+ if (err == ErrorCacheUnavailable) {
+ // already printed error
+ } else {
+ fprintf(stderr, "unable to check cache when processing .def.in file: %s\n", err_str(err));
+ }
+ exit(1);
+ }
+ }
+
+ Buf *artifact_dir;
+ Buf *lib_final_path;
+ Buf *final_lib_basename = buf_sprintf("%s.lib", name);
+
+ bool is_cache_miss = (buf_len(&digest) == 0);
+ if (is_cache_miss) {
+ if ((err = cache_final(cache_hash, &digest))) {
+ fprintf(stderr, "Unable to finalize cache hash: %s\n", err_str(err));
+ exit(1);
+ }
+ artifact_dir = buf_alloc();
+ os_path_join(o_dir, &digest, artifact_dir);
+ if ((err = os_make_path(artifact_dir))) {
+ fprintf(stderr, "Unable to create output directory '%s': %s",
+ buf_ptr(artifact_dir), err_str(err));
+ exit(1);
+ }
+ Buf *final_def_basename = buf_sprintf("%s.def", name);
+ Buf *def_final_path = buf_alloc();
+ os_path_join(artifact_dir, final_def_basename, def_final_path);
+
+ ZigList<const char *> args = {};
+ args.append(buf_ptr(self_exe_path));
+ args.append("cc");
+ args.append("-x");
+ args.append("c");
+ args.append(buf_ptr(def_in_file));
+ args.append("-Wp,-w");
+ args.append("-undef");
+ args.append("-P");
+ args.append("-I");
+ args.append(buf_ptr(def_include_dir));
+ if (target_is_arm(parent->zig_target)) {
+ if (target_arch_pointer_bit_width(parent->zig_target->arch) == 32) {
+ args.append("-DDEF_ARM32");
+ } else {
+ args.append("-DDEF_ARM64");
+ }
+ } else if (parent->zig_target->arch == ZigLLVM_x86) {
+ args.append("-DDEF_I386");
+ } else if (parent->zig_target->arch == ZigLLVM_x86_64) {
+ args.append("-DDEF_X64");
+ } else {
+ zig_unreachable();
+ }
+ args.append("-E");
+ args.append("-o");
+ args.append(buf_ptr(def_final_path));
+
+ if (parent->verbose_cc) {
+ print_zig_cc_cmd(&args);
+ }
+ Termination term;
+ os_spawn_process(args, &term);
+ if (term.how != TerminationIdClean || term.code != 0) {
+ fprintf(stderr, "\nThe following command failed:\n");
+ print_zig_cc_cmd(&args);
+ exit(1);
+ }
+
+ lib_final_path = buf_alloc();
+ os_path_join(artifact_dir, final_lib_basename, lib_final_path);
+
+ args.resize(0);
+ args.append("link");
+ coff_append_machine_arg(parent, &args);
+
+ args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_final_path))));
+ args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(lib_final_path))));
+
+ Buf diag = BUF_INIT;
+ ZigLLVM_ObjectFormatType target_ofmt = target_object_format(parent->zig_target);
+ if (!zig_lld_link(target_ofmt, args.items, args.length, &diag)) {
+ fprintf(stderr, "%s\n", buf_ptr(&diag));
+ exit(1);
+ }
+ } else {
+ // cache hit
+ artifact_dir = buf_alloc();
+ os_path_join(o_dir, &digest, artifact_dir);
+ lib_final_path = buf_alloc();
+ os_path_join(artifact_dir, final_lib_basename, lib_final_path);
+ }
+ parent->caches_to_release.append(cache_hash);
+
+ return buf_ptr(lib_final_path);
+}
+
+static bool is_linking_system_lib(CodeGen *g, const char *name) {
+ for (size_t lib_i = 0; lib_i < g->link_libs_list.length; lib_i += 1) {
+ LinkLib *link_lib = g->link_libs_list.at(lib_i);
+ if (buf_eql_str(link_lib->name, name)) {
+ return true;
+ }
+ }
+ return false;
}
static void add_mingw_link_args(LinkJob *lj, bool is_library) {
CodeGen *g = lj->codegen;
+ lj->args.append("-lldmingw");
+
bool is_dll = g->out_type == OutTypeLib && g->is_dynamic;
if (g->zig_target->arch == ZigLLVM_x86) {
@@ -1206,45 +2095,43 @@ static void add_mingw_link_args(LinkJob *lj, bool is_library) {
}
if (is_dll) {
- lj->args.append(get_libc_file(g->libc, "dllcrt2.o"));
+ lj->args.append(get_libc_crt_file(g, "dllcrt2.o"));
} else {
- lj->args.append(get_libc_file(g->libc, "crt2.o"));
- }
-
- lj->args.append(get_libc_static_file(g->libc, "crtbegin.o"));
-
- lj->args.append(get_libc_file(g->libc, "libmingw32.a"));
-
- if (is_dll) {
- lj->args.append(get_libc_static_file(g->libc, "libgcc_s.a"));
- lj->args.append(get_libc_static_file(g->libc, "libgcc.a"));
- } else {
- lj->args.append(get_libc_static_file(g->libc, "libgcc.a"));
- lj->args.append(get_libc_static_file(g->libc, "libgcc_eh.a"));
- }
-
- lj->args.append(get_libc_static_file(g->libc, "libssp.a"));
- lj->args.append(get_libc_file(g->libc, "libmoldname.a"));
- lj->args.append(get_libc_file(g->libc, "libmingwex.a"));
- lj->args.append(get_libc_file(g->libc, "libmsvcrt.a"));
-
- if (detect_subsystem(g) == TargetSubsystemWindows) {
- lj->args.append(get_libc_file(g->libc, "libgdi32.a"));
- lj->args.append(get_libc_file(g->libc, "libcomdlg32.a"));
+ lj->args.append(get_libc_crt_file(g, "crt2.o"));
+ }
+
+ lj->args.append(get_libc_crt_file(g, "mingw32.lib"));
+ lj->args.append(get_libc_crt_file(g, "mingwex.lib"));
+ lj->args.append(get_libc_crt_file(g, "msvcrt-os.lib"));
+
+ for (size_t def_i = 0; def_i < array_length(mingw_def_list); def_i += 1) {
+ const char *name = mingw_def_list[def_i].name;
+ Buf *path = buf_create_from_str(mingw_def_list[def_i].path);
+ bool always_link = mingw_def_list[def_i].always_link;
+ bool is_this_arch = false;
+ if (buf_starts_with_str(path, "lib-common" OS_SEP)) {
+ is_this_arch = true;
+ } else if (target_is_arm(g->zig_target)) {
+ if (target_arch_pointer_bit_width(g->zig_target->arch) == 32) {
+ is_this_arch = buf_starts_with_str(path, "libarm32" OS_SEP);
+ } else {
+ is_this_arch = buf_starts_with_str(path, "libarm64" OS_SEP);
+ }
+ } else if (g->zig_target->arch == ZigLLVM_x86) {
+ is_this_arch = buf_starts_with_str(path, "lib32" OS_SEP);
+ } else if (g->zig_target->arch == ZigLLVM_x86_64) {
+ is_this_arch = buf_starts_with_str(path, "lib64" OS_SEP);
+ }
+ if (is_this_arch && (always_link || is_linking_system_lib(g, name))) {
+ lj->args.append(get_def_lib(g, name, path));
+ }
}
-
- lj->args.append(get_libc_file(g->libc, "libadvapi32.a"));
- lj->args.append(get_libc_file(g->libc, "libadvapi32.a"));
- lj->args.append(get_libc_file(g->libc, "libshell32.a"));
- lj->args.append(get_libc_file(g->libc, "libuser32.a"));
- lj->args.append(get_libc_file(g->libc, "libkernel32.a"));
-
- lj->args.append(get_libc_static_file(g->libc, "crtend.o"));
}
-static void add_win_link_args(LinkJob *lj, bool is_library) {
+static void add_win_link_args(LinkJob *lj, bool is_library, bool *have_windows_dll_import_libs) {
if (lj->link_in_crt) {
if (target_abi_is_gnu(lj->codegen->zig_target->abi)) {
+ *have_windows_dll_import_libs = true;
add_mingw_link_args(lj, is_library);
} else {
add_msvc_link_args(lj, is_library);
@@ -1261,6 +2148,14 @@ static void add_win_link_args(LinkJob *lj, bool is_library) {
}
}
+static bool is_mingw_link_lib(Buf *name) {
+ for (size_t def_i = 0; def_i < array_length(mingw_def_list); def_i += 1) {
+ if (buf_eql_str_ignore_case(name, mingw_def_list[def_i].name)) {
+ return true;
+ }
+ }
+ return false;
+}
static void construct_linker_job_coff(LinkJob *lj) {
Error err;
CodeGen *g = lj->codegen;
@@ -1287,9 +2182,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
- if (g->libc_link_lib != nullptr) {
- assert(g->libc != nullptr);
-
+ if (g->libc_link_lib != nullptr && g->libc != nullptr) {
lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->crt_dir))));
if (target_abi_is_gnu(g->zig_target->abi)) {
@@ -1310,17 +2203,18 @@ static void construct_linker_job_coff(LinkJob *lj) {
lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
}
+ bool have_windows_dll_import_libs = false;
switch (detect_subsystem(g)) {
case TargetSubsystemAuto:
if (g->zig_target->os == OsUefi) {
add_uefi_link_args(lj);
} else {
- add_win_link_args(lj, is_library);
+ add_win_link_args(lj, is_library, &have_windows_dll_import_libs);
}
break;
case TargetSubsystemConsole:
lj->args.append("-SUBSYSTEM:console");
- add_win_link_args(lj, is_library);
+ add_win_link_args(lj, is_library, &have_windows_dll_import_libs);
break;
case TargetSubsystemEfiApplication:
lj->args.append("-SUBSYSTEM:efi_application");
@@ -1340,15 +2234,15 @@ static void construct_linker_job_coff(LinkJob *lj) {
break;
case TargetSubsystemNative:
lj->args.append("-SUBSYSTEM:native");
- add_win_link_args(lj, is_library);
+ add_win_link_args(lj, is_library, &have_windows_dll_import_libs);
break;
case TargetSubsystemPosix:
lj->args.append("-SUBSYSTEM:posix");
- add_win_link_args(lj, is_library);
+ add_win_link_args(lj, is_library, &have_windows_dll_import_libs);
break;
case TargetSubsystemWindows:
lj->args.append("-SUBSYSTEM:windows");
- add_win_link_args(lj, is_library);
+ add_win_link_args(lj, is_library, &have_windows_dll_import_libs);
break;
}
@@ -1370,47 +2264,54 @@ static void construct_linker_job_coff(LinkJob *lj) {
if (buf_eql_str(link_lib->name, "c")) {
continue;
}
- if (link_lib->provided_explicitly) {
+ bool is_sys_lib = is_mingw_link_lib(link_lib->name);
+ if (have_windows_dll_import_libs && is_sys_lib) {
+ continue;
+ }
+ // If we're linking in the CRT or the libs are provided explictly we don't want to generate def/libs
+ if ((lj->link_in_crt && is_sys_lib) || link_lib->provided_explicitly) {
if (target_abi_is_gnu(lj->codegen->zig_target->abi)) {
- Buf *lib_name = buf_sprintf("lib%s.a", buf_ptr(link_lib->name));
+ Buf* lib_name = buf_sprintf("lib%s.a", buf_ptr(link_lib->name));
lj->args.append(buf_ptr(lib_name));
- } else {
- lj->args.append(buf_ptr(link_lib->name));
}
- } else {
- buf_resize(def_contents, 0);
- buf_appendf(def_contents, "LIBRARY %s\nEXPORTS\n", buf_ptr(link_lib->name));
- for (size_t exp_i = 0; exp_i < link_lib->symbols.length; exp_i += 1) {
- Buf *symbol_name = link_lib->symbols.at(exp_i);
- buf_appendf(def_contents, "%s\n", buf_ptr(symbol_name));
+ else {
+ Buf* lib_name = buf_sprintf("%s.lib", buf_ptr(link_lib->name));
+ lj->args.append(buf_ptr(lib_name));
}
- buf_appendf(def_contents, "\n");
+ continue;
+ }
- Buf *def_path = buf_alloc();
- os_path_join(g->output_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path);
- if ((err = os_write_file(def_path, def_contents))) {
- zig_panic("error writing def file: %s", err_str(err));
- }
+ buf_resize(def_contents, 0);
+ buf_appendf(def_contents, "LIBRARY %s\nEXPORTS\n", buf_ptr(link_lib->name));
+ for (size_t exp_i = 0; exp_i < link_lib->symbols.length; exp_i += 1) {
+ Buf *symbol_name = link_lib->symbols.at(exp_i);
+ buf_appendf(def_contents, "%s\n", buf_ptr(symbol_name));
+ }
+ buf_appendf(def_contents, "\n");
- Buf *generated_lib_path = buf_alloc();
- os_path_join(g->output_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path);
+ Buf *def_path = buf_alloc();
+ os_path_join(g->output_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path);
+ if ((err = os_write_file(def_path, def_contents))) {
+ zig_panic("error writing def file: %s", err_str(err));
+ }
- gen_lib_args.resize(0);
- gen_lib_args.append("link");
+ Buf *generated_lib_path = buf_alloc();
+ os_path_join(g->output_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path);
- coff_append_machine_arg(g, &gen_lib_args);
- gen_lib_args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_path))));
- gen_lib_args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(generated_lib_path))));
- Buf diag = BUF_INIT;
- ZigLLVM_ObjectFormatType target_ofmt = target_object_format(g->zig_target);
- if (!zig_lld_link(target_ofmt, gen_lib_args.items, gen_lib_args.length, &diag)) {
- fprintf(stderr, "%s\n", buf_ptr(&diag));
- exit(1);
- }
- lj->args.append(buf_ptr(generated_lib_path));
+ gen_lib_args.resize(0);
+ gen_lib_args.append("link");
+
+ coff_append_machine_arg(g, &gen_lib_args);
+ gen_lib_args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_path))));
+ gen_lib_args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(generated_lib_path))));
+ Buf diag = BUF_INIT;
+ ZigLLVM_ObjectFormatType target_ofmt = target_object_format(g->zig_target);
+ if (!zig_lld_link(target_ofmt, gen_lib_args.items, gen_lib_args.length, &diag)) {
+ fprintf(stderr, "%s\n", buf_ptr(&diag));
+ exit(1);
}
+ lj->args.append(buf_ptr(generated_lib_path));
}
-
}
@@ -1734,3 +2635,4 @@ void codegen_link(CodeGen *g) {
exit(1);
}
}
+
diff --git a/src/main.cpp b/src/main.cpp
index 9b1892061b..ce68e53d85 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -15,6 +15,7 @@
#include "target.hpp"
#include "libc_installation.hpp"
#include "userland.h"
+#include "glibc.hpp"
#include <stdio.h>
@@ -74,6 +75,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
" -dynamic create a shared library (.so; .dll; .dylib)\n"
" --strip exclude debug symbols\n"
" -target [name] <arch><sub>-<os>-<abi> see the targets command\n"
+ " -target-glibc [version] target a specific glibc version (default: 2.17)\n"
" --verbose-tokenize enable compiler debug output for tokenization\n"
" --verbose-ast enable compiler debug output for AST parsing\n"
" --verbose-link enable compiler debug output for linking\n"
@@ -84,16 +86,19 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
" -dirafter [dir] same as -isystem but do it last\n"
" -isystem [dir] add additional search path for other .h files\n"
" -mllvm [arg] forward an arg to LLVM's option processing\n"
- " --override-std-dir [arg] use an alternate Zig standard library\n"
+ " --override-std-dir [arg] override path to Zig standard library\n"
+ " --override-lib-dir [arg] override path to Zig lib library\n"
+ " -ffunction-sections places each function in a seperate section\n"
"\n"
"Link Options:\n"
- " --bundle-compiler-rt [path] for static libraries, include compiler-rt symbols\n"
+ " --bundle-compiler-rt for static libraries, include compiler-rt symbols\n"
" --dynamic-linker [path] set the path to ld.so\n"
" --each-lib-rpath add rpath for each used dynamic library\n"
" --library [lib] link against lib\n"
" --forbid-library [lib] make it an error to link against lib\n"
" --library-path [dir] add a directory to the library search path\n"
" --linker-script [path] use a custom linker script\n"
+ " --version-script [path] provide a version .map file\n"
" --object [obj] add object file to build\n"
" -L[dir] alias for --library-path\n"
" -rdynamic add all symbols to the dynamic symbol table\n"
@@ -187,10 +192,33 @@ static int print_target_list(FILE *f) {
for (size_t i = 0; i < libc_count; i += 1) {
ZigTarget libc_target;
target_libc_enum(i, &libc_target);
- fprintf(f, " %s-%s-%s\n", target_arch_name(libc_target.arch),
- target_os_name(libc_target.os), target_abi_name(libc_target.abi));
+ bool is_native = native.arch == libc_target.arch &&
+ native.os == libc_target.os &&
+ native.abi == libc_target.abi;
+ const char *native_str = is_native ? " (native)" : "";
+ fprintf(f, " %s-%s-%s%s\n", target_arch_name(libc_target.arch),
+ target_os_name(libc_target.os), target_abi_name(libc_target.abi), native_str);
}
+ fprintf(f, "\nAvailable glibc versions:\n");
+ ZigGLibCAbi *glibc_abi;
+ Error err;
+ if ((err = glibc_load_metadata(&glibc_abi, get_zig_lib_dir(), true))) {
+ return EXIT_FAILURE;
+ }
+ for (size_t i = 0; i < glibc_abi->all_versions.length; i += 1) {
+ ZigGLibCVersion *this_ver = &glibc_abi->all_versions.at(i);
+ bool is_native = native.glibc_version != nullptr &&
+ native.glibc_version->major == this_ver->major &&
+ native.glibc_version->minor == this_ver->minor &&
+ native.glibc_version->patch == this_ver->patch;
+ const char *native_str = is_native ? " (native)" : "";
+ if (this_ver->patch == 0) {
+ fprintf(f, " %d.%d%s\n", this_ver->major, this_ver->minor, native_str);
+ } else {
+ fprintf(f, " %d.%d.%d%s\n", this_ver->major, this_ver->minor, this_ver->patch, native_str);
+ }
+ }
return EXIT_SUCCESS;
}
@@ -259,21 +287,30 @@ static bool get_cache_opt(CacheOpt opt, bool default_value) {
zig_unreachable();
}
+static int zig_error_no_build_file(void) {
+ fprintf(stderr,
+ "No 'build.zig' file found, in the current directory or any parent directories.\n"
+ "Initialize a 'build.zig' template file with `zig init-lib` or `zig init-exe`,\n"
+ "or see `zig --help` for more options.\n"
+ );
+ return EXIT_FAILURE;
+}
+
extern "C" int ZigClang_main(int argc, char **argv);
int main(int argc, char **argv) {
+ stage2_attach_segfault_handler();
+
char *arg0 = argv[0];
Error err;
if (argc == 2 && strcmp(argv[1], "BUILD_INFO") == 0) {
- printf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
+ printf("%s\n%s\n%s\n%s\n%s\n%s\n",
ZIG_CMAKE_BINARY_DIR,
ZIG_CXX_COMPILER,
ZIG_LLVM_CONFIG_EXE,
ZIG_LLD_INCLUDE_PATH,
ZIG_LLD_LIBRARIES,
- ZIG_STD_FILES,
- ZIG_C_HEADER_FILES,
ZIG_DIA_GUIDS_LIB);
return 0;
}
@@ -424,6 +461,8 @@ int main(int argc, char **argv) {
const char *mmacosx_version_min = nullptr;
const char *mios_version_min = nullptr;
const char *linker_script = nullptr;
+ Buf *version_script = nullptr;
+ const char *target_glibc = nullptr;
ZigList<const char *> rpath_list = {0};
bool each_lib_rpath = false;
ZigList<const char *> objects = {0};
@@ -450,6 +489,7 @@ int main(int argc, char **argv) {
ValgrindSupport valgrind_support = ValgrindSupportAuto;
WantPIC want_pic = WantPICAuto;
WantStackCheck want_stack_check = WantStackCheckAuto;
+ bool function_sections = false;
ZigList<const char *> llvm_argv = {0};
llvm_argv.append("zig (LLVM option parsing)");
@@ -461,8 +501,7 @@ int main(int argc, char **argv) {
return EXIT_FAILURE;
}
const char *zig_exe_path = buf_ptr(&zig_exe_path_buf);
- const char *build_file = "build.zig";
- bool asked_for_help = false;
+ const char *build_file = nullptr;
init_all_targets();
@@ -473,7 +512,6 @@ int main(int argc, char **argv) {
args.append(NULL); // placeholder
for (int i = 2; i < argc; i += 1) {
if (strcmp(argv[i], "--help") == 0) {
- asked_for_help = true;
args.append(argv[i]);
} else if (i + 1 < argc && strcmp(argv[i], "--build-file") == 0) {
build_file = argv[i + 1];
@@ -506,12 +544,36 @@ int main(int argc, char **argv) {
ZigTarget target;
get_native_target(&target);
- Buf *build_file_buf = buf_create_from_str(build_file);
+ Buf *build_file_buf = buf_create_from_str((build_file != nullptr) ? build_file : "build.zig");
Buf build_file_abs = os_path_resolve(&build_file_buf, 1);
Buf build_file_basename = BUF_INIT;
Buf build_file_dirname = BUF_INIT;
os_path_split(&build_file_abs, &build_file_dirname, &build_file_basename);
+ for (;;) {
+ bool build_file_exists;
+ if ((err = os_file_exists(&build_file_abs, &build_file_exists))) {
+ fprintf(stderr, "unable to check existence of '%s': %s\n", buf_ptr(&build_file_abs), err_str(err));
+ return 1;
+ }
+ if (build_file_exists)
+ break;
+
+ if (build_file != nullptr) {
+ // they asked for a specific build file path. only look for that one
+ return zig_error_no_build_file();
+ }
+
+ Buf *next_dir = buf_alloc();
+ os_path_dirname(&build_file_dirname, next_dir);
+ if (buf_eql_buf(&build_file_dirname, next_dir)) {
+ // no more parent directories to search, give up
+ return zig_error_no_build_file();
+ }
+ os_path_join(next_dir, &build_file_basename, &build_file_abs);
+ buf_init_from_buf(&build_file_dirname, next_dir);
+ }
+
Buf full_cache_dir = BUF_INIT;
if (cache_dir == nullptr) {
os_path_join(&build_file_dirname, buf_create_from_str(default_zig_cache_name), &full_cache_dir);
@@ -529,51 +591,6 @@ int main(int argc, char **argv) {
args.items[2] = buf_ptr(&build_file_dirname);
args.items[3] = buf_ptr(&full_cache_dir);
- bool build_file_exists;
- if ((err = os_file_exists(&build_file_abs, &build_file_exists))) {
- fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(&build_file_abs), err_str(err));
- return 1;
- }
- if (!build_file_exists) {
- if (asked_for_help) {
- // This usage text has to be synchronized with std/special/build_runner.zig
- fprintf(stdout,
- "Usage: %s build [options]\n"
- "\n"
- "General Options:\n"
- " --help Print this help and exit\n"
- " --verbose Print commands before executing them\n"
- " --prefix [path] Override default install prefix\n"
- " --search-prefix [path] Add a path to look for binaries, libraries, headers\n"
- "\n"
- "Project-specific options become available when the build file is found.\n"
- "\n"
- "Advanced Options:\n"
- " --build-file [file] Override path to build.zig\n"
- " --cache-dir [path] Override path to cache directory\n"
- " --override-std-dir [arg] Override path to Zig standard library\n"
- " --override-lib-dir [arg] Override path to Zig lib library\n"
- " --verbose-tokenize Enable compiler debug output for tokenization\n"
- " --verbose-ast Enable compiler debug output for parsing into an AST\n"
- " --verbose-link Enable compiler debug output for linking\n"
- " --verbose-ir Enable compiler debug output for Zig IR\n"
- " --verbose-llvm-ir Enable compiler debug output for LLVM IR\n"
- " --verbose-cimport Enable compiler debug output for C imports\n"
- " --verbose-cc Enable compiler debug output for C compilation\n"
- "\n"
- , zig_exe_path);
- return EXIT_SUCCESS;
- }
-
- fprintf(stderr,
- "No 'build.zig' file found.\n"
- "Initialize a 'build.zig' template file with `zig init-lib` or `zig init-exe`,\n"
- "or build an executable directly with `zig build-exe $FILENAME.zig`.\n"
- "See: `zig build --help` or `zig --help` for more options.\n"
- );
- return EXIT_FAILURE;
- }
-
ZigPackage *build_pkg = codegen_create_package(g, buf_ptr(&build_file_dirname),
buf_ptr(&build_file_basename), "std.special");
g->root_package->package_table.put(buf_create_from_str("@build"), build_pkg);
@@ -688,6 +705,8 @@ int main(int argc, char **argv) {
return EXIT_FAILURE;
}
cur_pkg = cur_pkg->parent;
+ } else if (strcmp(arg, "-ffunction-sections") == 0) {
+ function_sections = true;
} else if (i + 1 >= argc) {
fprintf(stderr, "Expected another argument after %s\n", arg);
return print_error_usage(arg0);
@@ -790,6 +809,10 @@ int main(int argc, char **argv) {
frameworks.append(argv[i]);
} else if (strcmp(arg, "--linker-script") == 0) {
linker_script = argv[i];
+ } else if (strcmp(arg, "--version-script") == 0) {
+ version_script = buf_create_from_str(argv[i]);
+ } else if (strcmp(arg, "-target-glibc") == 0) {
+ target_glibc = argv[i];
} else if (strcmp(arg, "-rpath") == 0) {
rpath_list.append(argv[i]);
} else if (strcmp(arg, "--test-filter") == 0) {
@@ -911,9 +934,41 @@ int main(int argc, char **argv) {
ZigTarget target;
if (target_string == nullptr) {
get_native_target(&target);
+ if (target_glibc != nullptr) {
+ fprintf(stderr, "-target-glibc provided but no -target parameter\n");
+ return print_error_usage(arg0);
+ }
} else {
if ((err = target_parse_triple(&target, target_string))) {
- fprintf(stderr, "invalid target: %s\n", err_str(err));
+ if (err == ErrorUnknownArchitecture && target.arch != ZigLLVM_UnknownArch) {
+ fprintf(stderr, "'%s' requires a sub-architecture. Try one of these:\n",
+ target_arch_name(target.arch));
+ SubArchList sub_arch_list = target_subarch_list(target.arch);
+ size_t subarch_count = target_subarch_count(sub_arch_list);
+ for (size_t sub_i = 0; sub_i < subarch_count; sub_i += 1) {
+ ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i);
+ fprintf(stderr, " %s%s\n", target_arch_name(target.arch), target_subarch_name(sub));
+ }
+ return print_error_usage(arg0);
+ } else {
+ fprintf(stderr, "invalid target: %s\n", err_str(err));
+ return print_error_usage(arg0);
+ }
+ }
+ if (target_is_glibc(&target)) {
+ target.glibc_version = allocate<ZigGLibCVersion>(1);
+
+ if (target_glibc != nullptr) {
+ if ((err = target_parse_glibc_version(target.glibc_version, target_glibc))) {
+ fprintf(stderr, "invalid glibc version '%s': %s\n", target_glibc, err_str(err));
+ return print_error_usage(arg0);
+ }
+ } else {
+ // Default cross-compiling glibc version
+ *target.glibc_version = {2, 17, 0};
+ }
+ } else if (target_glibc != nullptr) {
+ fprintf(stderr, "'%s' is not a glibc-compatible target", target_string);
return print_error_usage(arg0);
}
}
@@ -925,7 +980,7 @@ int main(int argc, char **argv) {
if (target_requires_pic(&target, have_libc) && want_pic == WantPICDisabled) {
Buf triple_buf = BUF_INIT;
- get_target_triple(&triple_buf, &target);
+ target_triple_zig(&triple_buf, &target);
fprintf(stderr, "`--disable-pic` is incompatible with target '%s'\n", buf_ptr(&triple_buf));
return print_error_usage(arg0);
}
@@ -958,6 +1013,10 @@ int main(int argc, char **argv) {
CodeGen *g = codegen_create(main_pkg_path, nullptr, &target,
out_type, build_mode, override_lib_dir, override_std_dir, nullptr, nullptr);
codegen_set_strip(g, strip);
+ for (size_t i = 0; i < link_libs.length; i += 1) {
+ LinkLib *link_lib = codegen_add_link_lib(g, buf_create_from_str(link_libs.at(i)));
+ link_lib->provided_explicitly = true;
+ }
g->subsystem = subsystem;
g->valgrind_support = valgrind_support;
g->want_pic = want_pic;
@@ -1069,6 +1128,7 @@ int main(int argc, char **argv) {
codegen_set_is_test(g, cmd == CmdTest);
g->want_single_threaded = want_single_threaded;
codegen_set_linker_script(g, linker_script);
+ g->version_script_path = version_script;
if (each_lib_rpath)
codegen_set_each_lib_rpath(g, each_lib_rpath);
@@ -1089,6 +1149,7 @@ int main(int argc, char **argv) {
g->bundle_compiler_rt = bundle_compiler_rt;
codegen_set_errmsg_color(g, color);
g->system_linker_hack = system_linker_hack;
+ g->function_sections = function_sections;
for (size_t i = 0; i < lib_dirs.length; i += 1) {
codegen_add_lib_dir(g, lib_dirs.at(i));
@@ -1168,6 +1229,9 @@ int main(int argc, char **argv) {
return term.code;
} else if (cmd == CmdBuild) {
if (g->enable_cache) {
+#if defined(ZIG_OS_WINDOWS)
+ buf_replace(&g->output_file_path, '/', '\\');
+#endif
if (printf("%s\n", buf_ptr(&g->output_file_path)) < 0)
return EXIT_FAILURE;
}
diff --git a/src/parser.cpp b/src/parser.cpp
index 33f8836ef3..25541d5351 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -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;
@@ -1519,7 +1519,6 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
// / IDENTIFIER
// / IfTypeExpr
// / INTEGER
-// / KEYWORD_anyerror
// / KEYWORD_comptime TypeExpr
// / KEYWORD_error DOT IDENTIFIER
// / KEYWORD_false
@@ -1614,10 +1613,6 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {
return res;
}
- Token *error_type = eat_token_if(pc, TokenIdKeywordAnyerror);
- if (error_type != nullptr)
- return ast_create_node(pc, NodeTypeErrorType, error_type);
-
Token *comptime = eat_token_if(pc, TokenIdKeywordCompTime);
if (comptime != nullptr) {
AstNode *expr = ast_expect(pc, ast_parse_type_expr);
@@ -2404,7 +2399,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 +2892,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);
diff --git a/src/target.cpp b/src/target.cpp
index 1d74304584..56c9a72c8f 100644
--- a/src/target.cpp
+++ b/src/target.cpp
@@ -10,6 +10,8 @@
#include "target.hpp"
#include "util.hpp"
#include "os.hpp"
+#include "compiler.hpp"
+#include "glibc.hpp"
#include <stdio.h>
@@ -466,7 +468,33 @@ const char *target_abi_name(ZigLLVM_EnvironmentType abi) {
return ZigLLVMGetEnvironmentTypeName(abi);
}
+Error target_parse_glibc_version(ZigGLibCVersion *glibc_ver, const char *text) {
+ glibc_ver->major = 2;
+ glibc_ver->minor = 0;
+ glibc_ver->patch = 0;
+ SplitIterator it = memSplit(str(text), str("GLIBC_."));
+ {
+ Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
+ if (!opt_component.is_some) return ErrorUnknownABI;
+ glibc_ver->major = strtoul(buf_ptr(buf_create_from_slice(opt_component.value)), nullptr, 10);
+ }
+ {
+ Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
+ if (!opt_component.is_some) return ErrorNone;
+ glibc_ver->minor = strtoul(buf_ptr(buf_create_from_slice(opt_component.value)), nullptr, 10);
+ }
+ {
+ Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
+ if (!opt_component.is_some) return ErrorNone;
+ glibc_ver->patch = strtoul(buf_ptr(buf_create_from_slice(opt_component.value)), nullptr, 10);
+ }
+ return ErrorNone;
+}
+
void get_native_target(ZigTarget *target) {
+ // first zero initialize
+ *target = {};
+
ZigLLVM_OSType os_type;
ZigLLVM_ObjectFormatType oformat; // ignored; based on arch/os
ZigLLVMGetNativeTarget(
@@ -481,22 +509,32 @@ void get_native_target(ZigTarget *target) {
if (target->abi == ZigLLVM_UnknownEnvironment) {
target->abi = target_default_abi(target->arch, target->os);
}
+ if (target_is_glibc(target)) {
+ target->glibc_version = allocate<ZigGLibCVersion>(1);
+ *target->glibc_version = {2, 17, 0};
+#ifdef ZIG_OS_LINUX
+ Error err;
+ if ((err = glibc_detect_native_version(target->glibc_version))) {
+ // Fall back to the default version.
+ }
+#endif
+ }
}
Error target_parse_archsub(ZigLLVM_ArchType *out_arch, ZigLLVM_SubArchType *out_sub,
const char *archsub_ptr, size_t archsub_len)
{
+ *out_arch = ZigLLVM_UnknownArch;
+ *out_sub = ZigLLVM_NoSubArch;
for (size_t arch_i = 0; arch_i < array_length(arch_list); arch_i += 1) {
ZigLLVM_ArchType arch = arch_list[arch_i];
SubArchList sub_arch_list = target_subarch_list(arch);
size_t subarch_count = target_subarch_count(sub_arch_list);
- if (subarch_count == 0) {
- if (mem_eql_str(archsub_ptr, archsub_len, target_arch_name(arch))) {
- *out_arch = arch;
- *out_sub = ZigLLVM_NoSubArch;
+ if (mem_eql_str(archsub_ptr, archsub_len, target_arch_name(arch))) {
+ *out_arch = arch;
+ if (subarch_count == 0) {
return ErrorNone;
}
- continue;
}
for (size_t sub_i = 0; sub_i < subarch_count; sub_i += 1) {
ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i);
@@ -667,6 +705,10 @@ Error target_parse_abi(ZigLLVM_EnvironmentType *out_abi, const char *abi_ptr, si
Error target_parse_triple(ZigTarget *target, const char *triple) {
Error err;
+
+ // first initialize all to zero
+ *target = {};
+
SplitIterator it = memSplit(str(triple), str("-"));
Optional<Slice<uint8_t>> opt_archsub = SplitIterator_next(&it);
@@ -696,9 +738,6 @@ Error target_parse_triple(ZigTarget *target, const char *triple) {
} else {
target->abi = target_default_abi(target->arch, target->os);
}
-
- target->vendor = ZigLLVM_UnknownVendor;
- target->is_native = false;
return ErrorNone;
}
@@ -714,7 +753,16 @@ void init_all_targets(void) {
LLVMInitializeAllAsmParsers();
}
-void get_target_triple(Buf *triple, const ZigTarget *target) {
+void target_triple_zig(Buf *triple, const ZigTarget *target) {
+ buf_resize(triple, 0);
+ buf_appendf(triple, "%s%s-%s-%s",
+ ZigLLVMGetArchTypeName(target->arch),
+ ZigLLVMGetSubArchTypeName(target->sub_arch),
+ ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)),
+ ZigLLVMGetEnvironmentTypeName(target->abi));
+}
+
+void target_triple_llvm(Buf *triple, const ZigTarget *target) {
buf_resize(triple, 0);
buf_appendf(triple, "%s%s-%s-%s-%s",
ZigLLVMGetArchTypeName(target->arch),
@@ -945,7 +993,9 @@ bool target_allows_addr_zero(const ZigTarget *target) {
}
const char *target_o_file_ext(const ZigTarget *target) {
- if (target->abi == ZigLLVM_MSVC || target->os == OsWindows || target->os == OsUefi) {
+ if (target->abi == ZigLLVM_MSVC ||
+ (target->os == OsWindows && !target_abi_is_gnu(target->abi)) ||
+ target->os == OsUefi) {
return ".obj";
} else {
return ".o";
@@ -973,7 +1023,10 @@ const char *target_exe_file_ext(const ZigTarget *target) {
}
const char *target_lib_file_prefix(const ZigTarget *target) {
- if (target->os == OsWindows || target->os == OsUefi || target_is_wasm(target)) {
+ if ((target->os == OsWindows && !target_abi_is_gnu(target->abi)) ||
+ target->os == OsUefi ||
+ target_is_wasm(target))
+ {
return "";
} else {
return "lib";
@@ -988,7 +1041,11 @@ const char *target_lib_file_ext(const ZigTarget *target, bool is_static,
}
if (target->os == OsWindows || target->os == OsUefi) {
if (is_static) {
- return ".lib";
+ if (target->os == OsWindows && target_abi_is_gnu(target->abi)) {
+ return ".a";
+ } else {
+ return ".lib";
+ }
} else {
return ".dll";
}
@@ -1420,8 +1477,8 @@ ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) {
case OsKFreeBSD:
case OsNetBSD:
case OsHurd:
- return ZigLLVM_GNU;
case OsWindows:
+ return ZigLLVM_GNU;
case OsUefi:
return ZigLLVM_MSVC;
case OsLinux:
@@ -1465,18 +1522,23 @@ struct AvailableLibC {
static const AvailableLibC libcs_available[] = {
{ZigLLVM_aarch64_be, OsLinux, ZigLLVM_GNU},
{ZigLLVM_aarch64_be, OsLinux, ZigLLVM_Musl},
+ {ZigLLVM_aarch64_be, OsWindows, ZigLLVM_GNU},
{ZigLLVM_aarch64, OsLinux, ZigLLVM_GNU},
{ZigLLVM_aarch64, OsLinux, ZigLLVM_MuslEABI},
+ {ZigLLVM_aarch64, OsWindows, ZigLLVM_GNU},
{ZigLLVM_armeb, OsLinux, ZigLLVM_GNUEABI},
{ZigLLVM_armeb, OsLinux, ZigLLVM_GNUEABIHF},
{ZigLLVM_armeb, OsLinux, ZigLLVM_MuslEABI},
{ZigLLVM_armeb, OsLinux, ZigLLVM_MuslEABIHF},
+ {ZigLLVM_armeb, OsWindows, ZigLLVM_GNU},
{ZigLLVM_arm, OsLinux, ZigLLVM_GNUEABI},
{ZigLLVM_arm, OsLinux, ZigLLVM_GNUEABIHF},
{ZigLLVM_arm, OsLinux, ZigLLVM_MuslEABI},
{ZigLLVM_arm, OsLinux, ZigLLVM_MuslEABIHF},
+ {ZigLLVM_arm, OsWindows, ZigLLVM_GNU},
{ZigLLVM_x86, OsLinux, ZigLLVM_GNU},
{ZigLLVM_x86, OsLinux, ZigLLVM_Musl},
+ {ZigLLVM_x86, OsWindows, ZigLLVM_GNU},
{ZigLLVM_mips64el, OsLinux, ZigLLVM_GNUABI64},
{ZigLLVM_mips64el, OsLinux, ZigLLVM_GNUABIN32},
{ZigLLVM_mips64el, OsLinux, ZigLLVM_Musl},
@@ -1504,6 +1566,7 @@ static const AvailableLibC libcs_available[] = {
{ZigLLVM_x86_64, OsLinux, ZigLLVM_GNU},
{ZigLLVM_x86_64, OsLinux, ZigLLVM_GNUX32},
{ZigLLVM_x86_64, OsLinux, ZigLLVM_Musl},
+ {ZigLLVM_x86_64, OsWindows, ZigLLVM_GNU},
};
bool target_can_build_libc(const ZigTarget *target) {
@@ -1519,6 +1582,9 @@ bool target_can_build_libc(const ZigTarget *target) {
}
const char *target_libc_generic_name(const ZigTarget *target) {
+ if (target->os == OsWindows) {
+ return "mingw";
+ }
switch (target->abi) {
case ZigLLVM_GNU:
case ZigLLVM_GNUABIN32:
diff --git a/src/target.hpp b/src/target.hpp
index 7fca430df6..e7e102a8ce 100644
--- a/src/target.hpp
+++ b/src/target.hpp
@@ -77,12 +77,19 @@ enum TargetSubsystem {
TargetSubsystemAuto
};
+struct ZigGLibCVersion {
+ uint32_t major; // always 2
+ uint32_t minor;
+ uint32_t patch;
+};
+
struct ZigTarget {
ZigLLVM_ArchType arch;
ZigLLVM_SubArchType sub_arch;
ZigLLVM_VendorType vendor;
Os os;
ZigLLVM_EnvironmentType abi;
+ ZigGLibCVersion *glibc_version; // null means default
bool is_native;
};
@@ -105,6 +112,8 @@ Error target_parse_archsub(ZigLLVM_ArchType *arch, ZigLLVM_SubArchType *sub,
Error target_parse_os(Os *os, const char *os_ptr, size_t os_len);
Error target_parse_abi(ZigLLVM_EnvironmentType *abi, const char *abi_ptr, size_t abi_len);
+Error target_parse_glibc_version(ZigGLibCVersion *out, const char *text);
+
size_t target_arch_count(void);
ZigLLVM_ArchType target_arch_enum(size_t index);
const char *target_arch_name(ZigLLVM_ArchType arch);
@@ -139,7 +148,8 @@ const char *target_oformat_name(ZigLLVM_ObjectFormatType oformat);
ZigLLVM_ObjectFormatType target_object_format(const ZigTarget *target);
void get_native_target(ZigTarget *target);
-void get_target_triple(Buf *triple, const ZigTarget *target);
+void target_triple_llvm(Buf *triple, const ZigTarget *target);
+void target_triple_zig(Buf *triple, const ZigTarget *target);
void init_all_targets(void);
diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp
index a0acde52e9..783b6e0e20 100644
--- a/src/tokenizer.cpp
+++ b/src/tokenizer.cpp
@@ -109,7 +109,6 @@ static const struct ZigKeyword zig_keywords[] = {
{"align", TokenIdKeywordAlign},
{"allowzero", TokenIdKeywordAllowZero},
{"and", TokenIdKeywordAnd},
- {"anyerror", TokenIdKeywordAnyerror},
{"asm", TokenIdKeywordAsm},
{"async", TokenIdKeywordAsync},
{"await", TokenIdKeywordAwait},
@@ -190,6 +189,7 @@ enum TokenizeState {
TokenizeStateFloatExponentNumber, // "123.456e-", "123.456e5", "123.456e5e-5"
TokenizeStateString,
TokenizeStateStringEscape,
+ TokenizeStateStringEscapeUnicodeStart,
TokenizeStateCharLiteral,
TokenizeStateCharLiteralEnd,
TokenizeStateSawStar,
@@ -241,7 +241,6 @@ struct Tokenize {
int32_t exp_add_amt;
bool is_exp_negative;
size_t char_code_index;
- size_t char_code_end;
bool unicode;
uint32_t char_code;
int exponent_in_bin_or_dec;
@@ -1071,24 +1070,10 @@ void tokenize(Buf *buf, Tokenization *out) {
t.radix = 16;
t.char_code = 0;
t.char_code_index = 0;
- t.char_code_end = 2;
t.unicode = false;
break;
case 'u':
- t.state = TokenizeStateCharCode;
- t.radix = 16;
- t.char_code = 0;
- t.char_code_index = 0;
- t.char_code_end = 4;
- t.unicode = true;
- break;
- case 'U':
- t.state = TokenizeStateCharCode;
- t.radix = 16;
- t.char_code = 0;
- t.char_code_index = 0;
- t.char_code_end = 6;
- t.unicode = true;
+ t.state = TokenizeStateStringEscapeUnicodeStart;
break;
case 'n':
handle_string_escape(&t, '\n');
@@ -1112,8 +1097,63 @@ void tokenize(Buf *buf, Tokenization *out) {
invalid_char_error(&t, c);
}
break;
+ case TokenizeStateStringEscapeUnicodeStart:
+ switch (c) {
+ case '{':
+ t.state = TokenizeStateCharCode;
+ t.radix = 16;
+ t.char_code = 0;
+ t.char_code_index = 0;
+ t.unicode = true;
+ break;
+ default:
+ invalid_char_error(&t, c);
+ }
+ break;
case TokenizeStateCharCode:
{
+ if (t.unicode && c == '}') {
+ if (t.char_code_index == 0) {
+ tokenize_error(&t, "empty unicode escape sequence");
+ break;
+ }
+ if (t.char_code > 0x10ffff) {
+ tokenize_error(&t, "unicode value out of range: %x", t.char_code);
+ break;
+ }
+ if (t.cur_tok->id == TokenIdCharLiteral) {
+ t.cur_tok->data.char_lit.c = t.char_code;
+ t.state = TokenizeStateCharLiteralEnd;
+ } else if (t.char_code <= 0x7f) {
+ // 00000000 00000000 00000000 0xxxxxxx
+ handle_string_escape(&t, (uint8_t)t.char_code);
+ } else if (t.char_code <= 0x7ff) {
+ // 00000000 00000000 00000xxx xx000000
+ handle_string_escape(&t, (uint8_t)(0xc0 | (t.char_code >> 6)));
+ // 00000000 00000000 00000000 00xxxxxx
+ handle_string_escape(&t, (uint8_t)(0x80 | (t.char_code & 0x3f)));
+ } else if (t.char_code <= 0xffff) {
+ // 00000000 00000000 xxxx0000 00000000
+ handle_string_escape(&t, (uint8_t)(0xe0 | (t.char_code >> 12)));
+ // 00000000 00000000 0000xxxx xx000000
+ handle_string_escape(&t, (uint8_t)(0x80 | ((t.char_code >> 6) & 0x3f)));
+ // 00000000 00000000 00000000 00xxxxxx
+ handle_string_escape(&t, (uint8_t)(0x80 | (t.char_code & 0x3f)));
+ } else if (t.char_code <= 0x10ffff) {
+ // 00000000 000xxx00 00000000 00000000
+ handle_string_escape(&t, (uint8_t)(0xf0 | (t.char_code >> 18)));
+ // 00000000 000000xx xxxx0000 00000000
+ handle_string_escape(&t, (uint8_t)(0x80 | ((t.char_code >> 12) & 0x3f)));
+ // 00000000 00000000 0000xxxx xx000000
+ handle_string_escape(&t, (uint8_t)(0x80 | ((t.char_code >> 6) & 0x3f)));
+ // 00000000 00000000 00000000 00xxxxxx
+ handle_string_escape(&t, (uint8_t)(0x80 | (t.char_code & 0x3f)));
+ } else {
+ zig_unreachable();
+ }
+ break;
+ }
+
uint32_t digit_value = get_digit_value(c);
if (digit_value >= t.radix) {
tokenize_error(&t, "invalid digit: '%c'", c);
@@ -1123,44 +1163,9 @@ void tokenize(Buf *buf, Tokenization *out) {
t.char_code += digit_value;
t.char_code_index += 1;
- if (t.char_code_index >= t.char_code_end) {
- if (t.unicode) {
- if (t.char_code > 0x10ffff) {
- tokenize_error(&t, "unicode value out of range: %x", t.char_code);
- break;
- }
- if (t.cur_tok->id == TokenIdCharLiteral) {
- t.cur_tok->data.char_lit.c = t.char_code;
- t.state = TokenizeStateCharLiteralEnd;
- } else if (t.char_code <= 0x7f) {
- // 00000000 00000000 00000000 0xxxxxxx
- handle_string_escape(&t, (uint8_t)t.char_code);
- } else if (t.char_code <= 0x7ff) {
- // 00000000 00000000 00000xxx xx000000
- handle_string_escape(&t, (uint8_t)(0xc0 | (t.char_code >> 6)));
- // 00000000 00000000 00000000 00xxxxxx
- handle_string_escape(&t, (uint8_t)(0x80 | (t.char_code & 0x3f)));
- } else if (t.char_code <= 0xffff) {
- // 00000000 00000000 xxxx0000 00000000
- handle_string_escape(&t, (uint8_t)(0xe0 | (t.char_code >> 12)));
- // 00000000 00000000 0000xxxx xx000000
- handle_string_escape(&t, (uint8_t)(0x80 | ((t.char_code >> 6) & 0x3f)));
- // 00000000 00000000 00000000 00xxxxxx
- handle_string_escape(&t, (uint8_t)(0x80 | (t.char_code & 0x3f)));
- } else if (t.char_code <= 0x10ffff) {
- // 00000000 000xxx00 00000000 00000000
- handle_string_escape(&t, (uint8_t)(0xf0 | (t.char_code >> 18)));
- // 00000000 000000xx xxxx0000 00000000
- handle_string_escape(&t, (uint8_t)(0x80 | ((t.char_code >> 12) & 0x3f)));
- // 00000000 00000000 0000xxxx xx000000
- handle_string_escape(&t, (uint8_t)(0x80 | ((t.char_code >> 6) & 0x3f)));
- // 00000000 00000000 00000000 00xxxxxx
- handle_string_escape(&t, (uint8_t)(0x80 | (t.char_code & 0x3f)));
- }
- } else {
- assert(t.char_code <= 255);
- handle_string_escape(&t, (uint8_t)t.char_code);
- }
+ if (!t.unicode && t.char_code_index >= 2) {
+ assert(t.char_code <= 255);
+ handle_string_escape(&t, (uint8_t)t.char_code);
}
}
break;
@@ -1409,6 +1414,7 @@ void tokenize(Buf *buf, Tokenization *out) {
tokenize_error(&t, "unterminated string");
break;
case TokenizeStateStringEscape:
+ case TokenizeStateStringEscapeUnicodeStart:
case TokenizeStateCharCode:
if (t.cur_tok->id == TokenIdStringLiteral) {
tokenize_error(&t, "unterminated string");
@@ -1521,7 +1527,6 @@ const char * token_name(TokenId id) {
case TokenIdFloatLiteral: return "FloatLiteral";
case TokenIdIntLiteral: return "IntLiteral";
case TokenIdKeywordAsync: return "async";
- case TokenIdKeywordAnyerror: return "anyerror";
case TokenIdKeywordAllowZero: return "allowzero";
case TokenIdKeywordAwait: return "await";
case TokenIdKeywordResume: return "resume";
diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp
index d5174c24de..83dbe99471 100644
--- a/src/tokenizer.hpp
+++ b/src/tokenizer.hpp
@@ -53,7 +53,6 @@ enum TokenId {
TokenIdKeywordAlign,
TokenIdKeywordAllowZero,
TokenIdKeywordAnd,
- TokenIdKeywordAnyerror,
TokenIdKeywordAsm,
TokenIdKeywordAsync,
TokenIdKeywordAwait,
diff --git a/src/translate_c.cpp b/src/translate_c.cpp
index 28e4a7daa4..69c70958e5 100644
--- a/src/translate_c.cpp
+++ b/src/translate_c.cpp
@@ -833,6 +833,27 @@ static bool qual_type_has_wrapping_overflow(Context *c, ZigClangQualType qt) {
}
}
+static bool type_is_function(Context *c, const ZigClangType *ty, ZigClangSourceLocation source_loc) {
+ switch (ZigClangType_getTypeClass(ty)) {
+ case ZigClangType_FunctionProto:
+ case ZigClangType_FunctionNoProto:
+ return true;
+ case ZigClangType_Elaborated: {
+ const clang::ElaboratedType *elaborated_ty = reinterpret_cast<const clang::ElaboratedType*>(ty);
+ ZigClangQualType qt = bitcast(elaborated_ty->getNamedType());
+ return type_is_function(c, ZigClangQualType_getTypePtr(qt), source_loc);
+ }
+ case ZigClangType_Typedef: {
+ const ZigClangTypedefType *typedef_ty = reinterpret_cast<const ZigClangTypedefType*>(ty);
+ const ZigClangTypedefNameDecl *typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
+ ZigClangQualType underlying_type = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
+ return type_is_function(c, ZigClangQualType_getTypePtr(underlying_type), source_loc);
+ }
+ default:
+ return false;
+ }
+}
+
static bool type_is_opaque(Context *c, const ZigClangType *ty, ZigClangSourceLocation source_loc) {
switch (ZigClangType_getTypeClass(ty)) {
case ZigClangType_Builtin: {
@@ -840,8 +861,23 @@ static bool type_is_opaque(Context *c, const ZigClangType *ty, ZigClangSourceLoc
return ZigClangBuiltinType_getKind(builtin_ty) == ZigClangBuiltinTypeVoid;
}
case ZigClangType_Record: {
- const clang::RecordType *record_ty = reinterpret_cast<const clang::RecordType*>(ty);
- return record_ty->getDecl()->getDefinition() == nullptr;
+ const ZigClangRecordType *record_ty = reinterpret_cast<const ZigClangRecordType*>(ty);
+ const ZigClangRecordDecl *record_decl = ZigClangRecordType_getDecl(record_ty);
+ const ZigClangRecordDecl *record_def = ZigClangRecordDecl_getDefinition(record_decl);
+ if (record_def == nullptr) {
+ return true;
+ }
+ for (auto it = reinterpret_cast<const clang::RecordDecl *>(record_def)->field_begin(),
+ it_end = reinterpret_cast<const clang::RecordDecl *>(record_def)->field_end();
+ it != it_end; ++it)
+ {
+ const clang::FieldDecl *field_decl = *it;
+
+ if (field_decl->isBitField()) {
+ return true;
+ }
+ }
+ return false;
}
case ZigClangType_Elaborated: {
const clang::ElaboratedType *elaborated_ty = reinterpret_cast<const clang::ElaboratedType*>(ty);
@@ -1019,7 +1055,9 @@ static AstNode *trans_type(Context *c, const ZigClangType *ty, ZigClangSourceLoc
return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
}
- if (type_is_opaque(c, ZigClangQualType_getTypePtr(child_qt), source_loc)) {
+ if (type_is_function(c, ZigClangQualType_getTypePtr(child_qt), source_loc)) {
+ return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
+ } else if (type_is_opaque(c, ZigClangQualType_getTypePtr(child_qt), source_loc)) {
AstNode *pointer_node = trans_create_node_ptr_type(c,
ZigClangQualType_isConstQualified(child_qt),
ZigClangQualType_isVolatileQualified(child_qt),
diff --git a/src/userland.cpp b/src/userland.cpp
index d0330669dd..d82f776cd6 100644
--- a/src/userland.cpp
+++ b/src/userland.cpp
@@ -26,6 +26,8 @@ void stage2_zen(const char **ptr, size_t *len) {
stage2_panic(msg, strlen(msg));
}
+void stage2_attach_segfault_handler(void) { }
+
void stage2_panic(const char *ptr, size_t len) {
fwrite(ptr, 1, len, stderr);
fprintf(stderr, "\n");
diff --git a/src/userland.h b/src/userland.h
index eac28053e6..43bdbd18b1 100644
--- a/src/userland.h
+++ b/src/userland.h
@@ -114,6 +114,9 @@ ZIG_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file);
ZIG_EXTERN_C void stage2_zen(const char **ptr, size_t *len);
// ABI warning
+ZIG_EXTERN_C void stage2_attach_segfault_handler(void);
+
+// ABI warning
ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len);
// ABI warning
diff --git a/src/util.cpp b/src/util.cpp
index 9a6a382993..65b1fe3082 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -86,6 +86,32 @@ Optional<Slice<uint8_t>> SplitIterator_next(SplitIterator *self) {
return Optional<Slice<uint8_t>>::some(self->buffer.slice(start, end));
}
+// Ported from std/mem.zig.
+// This one won't collapse multiple separators into one, so you could use it, for example,
+// to parse Comma Separated Value format.
+Optional<Slice<uint8_t>> SplitIterator_next_separate(SplitIterator *self) {
+ // move to beginning of token
+ if (self->index < self->buffer.len &&
+ SplitIterator_isSplitByte(self, self->buffer.ptr[self->index]))
+ {
+ self->index += 1;
+ }
+ size_t start = self->index;
+ if (start == self->buffer.len) {
+ return {};
+ }
+
+ // move to end of token
+ while (self->index < self->buffer.len &&
+ !SplitIterator_isSplitByte(self, self->buffer.ptr[self->index]))
+ {
+ self->index += 1;
+ }
+ size_t end = self->index;
+
+ return Optional<Slice<uint8_t>>::some(self->buffer.slice(start, end));
+}
+
// Ported from std/mem.zig
Slice<uint8_t> SplitIterator_rest(SplitIterator *self) {
// move to beginning of token
diff --git a/src/util.hpp b/src/util.hpp
index f1942dd480..1fa33b30f9 100644
--- a/src/util.hpp
+++ b/src/util.hpp
@@ -12,6 +12,7 @@
#include <stdint.h>
#include <string.h>
#include <assert.h>
+#include <ctype.h>
#if defined(_MSC_VER)
@@ -161,6 +162,15 @@ static inline bool mem_eql_mem(const char *a_ptr, size_t a_len, const char *b_pt
return false;
return memcmp(a_ptr, b_ptr, a_len) == 0;
}
+static inline bool mem_eql_mem_ignore_case(const char *a_ptr, size_t a_len, const char *b_ptr, size_t b_len) {
+ if (a_len != b_len)
+ return false;
+ for (size_t i = 0; i < a_len; i += 1) {
+ if (tolower(a_ptr[i]) != tolower(b_ptr[i]))
+ return false;
+ }
+ return true;
+}
static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str) {
return mem_eql_mem(mem, mem_len, str, strlen(str));
@@ -314,6 +324,7 @@ struct SplitIterator {
bool SplitIterator_isSplitByte(SplitIterator *self, uint8_t byte);
Optional< Slice<uint8_t> > SplitIterator_next(SplitIterator *self);
+Optional< Slice<uint8_t> > SplitIterator_next_separate(SplitIterator *self);
Slice<uint8_t> SplitIterator_rest(SplitIterator *self);
SplitIterator memSplit(Slice<uint8_t> buffer, Slice<uint8_t> split_bytes);
diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp
index 28062ea69f..7c87f31125 100644
--- a/src/zig_clang.cpp
+++ b/src/zig_clang.cpp
@@ -21,6 +21,7 @@
#include <clang/Frontend/ASTUnit.h>
#include <clang/Frontend/CompilerInstance.h>
+#include <clang/AST/APValue.h>
#include <clang/AST/Expr.h>
#if __GNUC__ >= 8
@@ -1287,6 +1288,20 @@ static_assert((clang::StringLiteral::StringKind)ZigClangStringLiteral_StringKind
static_assert((clang::StringLiteral::StringKind)ZigClangStringLiteral_StringKind_UTF16 == clang::StringLiteral::UTF16, "");
static_assert((clang::StringLiteral::StringKind)ZigClangStringLiteral_StringKind_UTF32 == clang::StringLiteral::UTF32, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Uninitialized == clang::APValue::ValueKind::Uninitialized, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Int == clang::APValue::ValueKind::Int, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Float == clang::APValue::ValueKind::Float, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_ComplexInt == clang::APValue::ValueKind::ComplexInt, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_ComplexFloat == clang::APValue::ValueKind::ComplexFloat, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_LValue == clang::APValue::ValueKind::LValue, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Vector == clang::APValue::ValueKind::Vector, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Array == clang::APValue::ValueKind::Array, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Struct == clang::APValue::ValueKind::Struct, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Union == clang::APValue::ValueKind::Union, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_MemberPointer == clang::APValue::ValueKind::MemberPointer, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_AddrLabelDiff == clang::APValue::ValueKind::AddrLabelDiff, "");
+
+static_assert(sizeof(ZigClangAPValue) == sizeof(clang::APValue), "");
static_assert(sizeof(ZigClangSourceLocation) == sizeof(clang::SourceLocation), "");
static ZigClangSourceLocation bitcast(clang::SourceLocation src) {
@@ -1312,6 +1327,13 @@ static clang::QualType bitcast(ZigClangQualType src) {
return dest;
}
+static_assert(sizeof(ZigClangExprEvalResult) == sizeof(clang::Expr::EvalResult), "");
+static ZigClangExprEvalResult bitcast(clang::Expr::EvalResult src) {
+ ZigClangExprEvalResult dest;
+ memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangExprEvalResult));
+ return dest;
+}
+
static_assert(sizeof(ZigClangAPValueLValueBase) == sizeof(clang::APValue::LValueBase), "");
static ZigClangAPValueLValueBase bitcast(clang::APValue::LValueBase src) {
ZigClangAPValueLValueBase dest;
@@ -1331,6 +1353,12 @@ static ZigClangCompoundStmt_const_body_iterator bitcast(clang::CompoundStmt::con
return dest;
}
+static_assert(sizeof(ZigClangDeclStmt_const_decl_iterator) == sizeof(clang::DeclStmt::const_decl_iterator), "");
+static ZigClangDeclStmt_const_decl_iterator bitcast(clang::DeclStmt::const_decl_iterator src) {
+ ZigClangDeclStmt_const_decl_iterator dest;
+ memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangDeclStmt_const_decl_iterator));
+ return dest;
+}
ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *self,
ZigClangSourceLocation Loc)
@@ -1381,7 +1409,7 @@ ZigClangSourceManager *ZigClangASTUnit_getSourceManager(ZigClangASTUnit *self) {
return reinterpret_cast<ZigClangSourceManager *>(result);
}
-bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *self, void *context,
+bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *self, void *context,
bool (*Fn)(void *context, const ZigClangDecl *decl))
{
return reinterpret_cast<clang::ASTUnit *>(self)->visitLocalTopLevelDecls(context,
@@ -1540,6 +1568,11 @@ const ZigClangType *ZigClangQualType_getTypePtr(ZigClangQualType self) {
return reinterpret_cast<const ZigClangType *>(ty);
}
+ZigClangTypeClass ZigClangQualType_getTypeClass(ZigClangQualType self) {
+ clang::QualType ty = bitcast(self);
+ return (ZigClangTypeClass)(ty->getTypeClass());
+}
+
void ZigClangQualType_addConst(ZigClangQualType *self) {
reinterpret_cast<clang::QualType *>(self)->addConst();
}
@@ -1815,6 +1848,21 @@ void ZigClangASTUnit_delete(struct ZigClangASTUnit *self) {
delete reinterpret_cast<clang::ASTUnit *>(self);
}
+struct ZigClangQualType ZigClangVarDecl_getType(const struct ZigClangVarDecl *self) {
+ auto casted = reinterpret_cast<const clang::VarDecl *>(self);
+ return bitcast(casted->getType());
+}
+
+const struct ZigClangExpr *ZigClangVarDecl_getInit(const struct ZigClangVarDecl *self) {
+ auto casted = reinterpret_cast<const clang::VarDecl *>(self);
+ return reinterpret_cast<const ZigClangExpr *>(casted->getInit());
+}
+
+enum ZigClangVarDecl_TLSKind ZigClangVarDecl_getTLSKind(const ZigClangVarDecl *self) {
+ auto casted = reinterpret_cast<const clang::VarDecl *>(self);
+ return (ZigClangVarDecl_TLSKind)casted->getTLSKind();
+}
+
enum ZigClangBuiltinTypeKind ZigClangBuiltinType_getKind(const struct ZigClangBuiltinType *self) {
auto casted = reinterpret_cast<const clang::BuiltinType *>(self);
return (ZigClangBuiltinTypeKind)casted->getKind();
@@ -1862,6 +1910,16 @@ ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_end(const str
return bitcast(casted->body_end());
}
+ZigClangDeclStmt_const_decl_iterator ZigClangDeclStmt_decl_begin(const struct ZigClangDeclStmt *self) {
+ auto casted = reinterpret_cast<const clang::DeclStmt *>(self);
+ return bitcast(casted->decl_begin());
+}
+
+ZigClangDeclStmt_const_decl_iterator ZigClangDeclStmt_decl_end(const struct ZigClangDeclStmt *self) {
+ auto casted = reinterpret_cast<const clang::DeclStmt *>(self);
+ return bitcast(casted->decl_end());
+}
+
unsigned ZigClangAPFloat_convertToHexString(const ZigClangAPFloat *self, char *DST,
unsigned HexDigits, bool UpperCase, enum ZigClangAPFloat_roundingMode RM)
{
@@ -1888,3 +1946,104 @@ const struct ZigClangStringLiteral *ZigClangPredefinedExpr_getFunctionName(
const clang::StringLiteral *result = casted->getFunctionName();
return reinterpret_cast<const struct ZigClangStringLiteral *>(result);
}
+
+ZigClangSourceLocation ZigClangImplicitCastExpr_getBeginLoc(const struct ZigClangImplicitCastExpr *self) {
+ auto casted = reinterpret_cast<const clang::ImplicitCastExpr *>(self);
+ return bitcast(casted->getBeginLoc());
+}
+
+enum ZigClangCK ZigClangImplicitCastExpr_getCastKind(const struct ZigClangImplicitCastExpr *self) {
+ auto casted = reinterpret_cast<const clang::ImplicitCastExpr *>(self);
+ return (ZigClangCK)casted->getCastKind();
+}
+
+const struct ZigClangExpr *ZigClangImplicitCastExpr_getSubExpr(const struct ZigClangImplicitCastExpr *self) {
+ auto casted = reinterpret_cast<const clang::ImplicitCastExpr *>(self);
+ return reinterpret_cast<const struct ZigClangExpr *>(casted->getSubExpr());
+}
+
+struct ZigClangQualType ZigClangArrayType_getElementType(const struct ZigClangArrayType *self) {
+ auto casted = reinterpret_cast<const clang::ArrayType *>(self);
+ return bitcast(casted->getElementType());
+}
+
+const struct ZigClangValueDecl *ZigClangDeclRefExpr_getDecl(const struct ZigClangDeclRefExpr *self) {
+ auto casted = reinterpret_cast<const clang::DeclRefExpr *>(self);
+ return reinterpret_cast<const struct ZigClangValueDecl *>(casted->getDecl());
+}
+
+struct ZigClangQualType ZigClangParenType_getInnerType(const struct ZigClangParenType *self) {
+ auto casted = reinterpret_cast<const clang::ParenType *>(self);
+ return bitcast(casted->getInnerType());
+}
+
+struct ZigClangQualType ZigClangAttributedType_getEquivalentType(const struct ZigClangAttributedType *self) {
+ auto casted = reinterpret_cast<const clang::AttributedType *>(self);
+ return bitcast(casted->getEquivalentType());
+}
+
+struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *self) {
+ auto casted = reinterpret_cast<const clang::ElaboratedType *>(self);
+ return bitcast(casted->getNamedType());
+}
+
+struct ZigClangSourceLocation ZigClangCStyleCastExpr_getBeginLoc(const struct ZigClangCStyleCastExpr *self) {
+ auto casted = reinterpret_cast<const clang::CStyleCastExpr *>(self);
+ return bitcast(casted->getBeginLoc());
+}
+
+const struct ZigClangExpr *ZigClangCStyleCastExpr_getSubExpr(const struct ZigClangCStyleCastExpr *self) {
+ auto casted = reinterpret_cast<const clang::CStyleCastExpr *>(self);
+ return reinterpret_cast<const struct ZigClangExpr *>(casted->getSubExpr());
+}
+
+struct ZigClangQualType ZigClangCStyleCastExpr_getType(const struct ZigClangCStyleCastExpr *self) {
+ auto casted = reinterpret_cast<const clang::CStyleCastExpr *>(self);
+ return bitcast(casted->getType());
+}
+
+bool ZigClangIntegerLiteral_EvaluateAsInt(const struct ZigClangIntegerLiteral *self, struct ZigClangExprEvalResult *result, const struct ZigClangASTContext *ctx) {
+ auto casted_self = reinterpret_cast<const clang::IntegerLiteral *>(self);
+ auto casted_ctx = reinterpret_cast<const clang::ASTContext *>(ctx);
+ clang::Expr::EvalResult eval_result;
+ if (!casted_self->EvaluateAsInt(eval_result, *casted_ctx)) {
+ return false;
+ }
+ *result = bitcast(eval_result);
+ return true;
+}
+
+struct ZigClangSourceLocation ZigClangIntegerLiteral_getBeginLoc(const struct ZigClangIntegerLiteral *self) {
+ auto casted = reinterpret_cast<const clang::IntegerLiteral *>(self);
+ return bitcast(casted->getBeginLoc());
+}
+
+const struct ZigClangExpr *ZigClangReturnStmt_getRetValue(const struct ZigClangReturnStmt *self) {
+ auto casted = reinterpret_cast<const clang::ReturnStmt *>(self);
+ return reinterpret_cast<const struct ZigClangExpr *>(casted->getRetValue());
+}
+
+enum ZigClangBO ZigClangBinaryOperator_getOpcode(const struct ZigClangBinaryOperator *self) {
+ auto casted = reinterpret_cast<const clang::BinaryOperator *>(self);
+ return (ZigClangBO)casted->getOpcode();
+}
+
+struct ZigClangSourceLocation ZigClangBinaryOperator_getBeginLoc(const struct ZigClangBinaryOperator *self) {
+ auto casted = reinterpret_cast<const clang::BinaryOperator *>(self);
+ return bitcast(casted->getBeginLoc());
+}
+
+const struct ZigClangExpr *ZigClangBinaryOperator_getLHS(const struct ZigClangBinaryOperator *self) {
+ auto casted = reinterpret_cast<const clang::BinaryOperator *>(self);
+ return reinterpret_cast<const struct ZigClangExpr *>(casted->getLHS());
+}
+
+const struct ZigClangExpr *ZigClangBinaryOperator_getRHS(const struct ZigClangBinaryOperator *self) {
+ auto casted = reinterpret_cast<const clang::BinaryOperator *>(self);
+ return reinterpret_cast<const struct ZigClangExpr *>(casted->getRHS());
+}
+
+struct ZigClangQualType ZigClangBinaryOperator_getType(const struct ZigClangBinaryOperator *self) {
+ auto casted = reinterpret_cast<const clang::BinaryOperator *>(self);
+ return bitcast(casted->getType());
+}
diff --git a/src/zig_clang.h b/src/zig_clang.h
index 1bdf34fc2f..9d03b592fd 100644
--- a/src/zig_clang.h
+++ b/src/zig_clang.h
@@ -30,6 +30,38 @@ struct ZigClangAPValueLValueBase {
unsigned Version;
};
+enum ZigClangAPValue_ValueKind {
+ ZigClangAPValue_ValueKind_Uninitialized,
+ ZigClangAPValue_ValueKind_Int,
+ ZigClangAPValue_ValueKind_Float,
+ ZigClangAPValue_ValueKind_ComplexInt,
+ ZigClangAPValue_ValueKind_ComplexFloat,
+ ZigClangAPValue_ValueKind_LValue,
+ ZigClangAPValue_ValueKind_Vector,
+ ZigClangAPValue_ValueKind_Array,
+ ZigClangAPValue_ValueKind_Struct,
+ ZigClangAPValue_ValueKind_Union,
+ ZigClangAPValue_ValueKind_MemberPointer,
+ ZigClangAPValue_ValueKind_AddrLabelDiff
+};
+
+struct ZigClangAPValue {
+ enum ZigClangAPValue_ValueKind Kind;
+ // experimentally-derived size of clang::APValue::DataType
+#if defined(WIN32) && defined(_MSC_VER)
+ char Data[52];
+#else
+ char Data[68];
+#endif
+};
+
+struct ZigClangExprEvalResult {
+ bool HasSideEffects;
+ bool HasUndefinedBehavior;
+ void *SmallVectorImpl;
+ ZigClangAPValue Val;
+};
+
struct ZigClangAPValue;
struct ZigClangAPSInt;
struct ZigClangAPFloat;
@@ -105,6 +137,7 @@ struct ZigClangFunctionType;
struct ZigClangPredefinedExpr;
typedef struct ZigClangStmt *const * ZigClangCompoundStmt_const_body_iterator;
+typedef struct ZigClangDecl *const * ZigClangDeclStmt_const_decl_iterator;
enum ZigClangBO {
ZigClangBO_PtrMemD,
@@ -732,6 +765,12 @@ enum ZigClangStringLiteral_StringKind {
ZigClangStringLiteral_StringKind_UTF32,
};
+enum ZigClangVarDecl_TLSKind {
+ ZigClangVarDecl_TLSKind_None,
+ ZigClangVarDecl_TLSKind_Static,
+ ZigClangVarDecl_TLSKind_Dynamic,
+};
+
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const struct ZigClangSourceManager *,
struct ZigClangSourceLocation Loc);
ZIG_EXTERN_C const char *ZigClangSourceManager_getFilename(const struct ZigClangSourceManager *,
@@ -754,7 +793,7 @@ ZIG_EXTERN_C void ZigClangErrorMsg_delete(struct Stage2ErrorMsg *ptr, size_t len
ZIG_EXTERN_C struct ZigClangASTContext *ZigClangASTUnit_getASTContext(struct ZigClangASTUnit *);
ZIG_EXTERN_C struct ZigClangSourceManager *ZigClangASTUnit_getSourceManager(struct ZigClangASTUnit *);
-ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(struct ZigClangASTUnit *, void *context,
+ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(struct ZigClangASTUnit *, void *context,
bool (*Fn)(void *context, const struct ZigClangDecl *decl));
ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangRecordType_getDecl(const struct ZigClangRecordType *record_ty);
@@ -789,6 +828,10 @@ ZIG_EXTERN_C const char *ZigClangDecl_getName_bytes_begin(const struct ZigClangD
ZIG_EXTERN_C enum ZigClangDeclKind ZigClangDecl_getKind(const struct ZigClangDecl *decl);
ZIG_EXTERN_C const char *ZigClangDecl_getDeclKindName(const struct ZigClangDecl *decl);
+ZIG_EXTERN_C struct ZigClangQualType ZigClangVarDecl_getType(const struct ZigClangVarDecl *);
+ZIG_EXTERN_C const struct ZigClangExpr *ZigClangVarDecl_getInit(const struct ZigClangVarDecl *var_decl);
+ZIG_EXTERN_C enum ZigClangVarDecl_TLSKind ZigClangVarDecl_getTLSKind(const struct ZigClangVarDecl *var_decl);
+
ZIG_EXTERN_C bool ZigClangSourceLocation_eq(struct ZigClangSourceLocation a, struct ZigClangSourceLocation b);
ZIG_EXTERN_C const struct ZigClangTypedefNameDecl *ZigClangTypedefType_getDecl(const struct ZigClangTypedefType *);
@@ -796,6 +839,7 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangTypedefNameDecl_getUnderlyingType(c
ZIG_EXTERN_C struct ZigClangQualType ZigClangQualType_getCanonicalType(struct ZigClangQualType);
ZIG_EXTERN_C const struct ZigClangType *ZigClangQualType_getTypePtr(struct ZigClangQualType);
+ZIG_EXTERN_C enum ZigClangTypeClass ZigClangQualType_getTypeClass(struct ZigClangQualType);
ZIG_EXTERN_C void ZigClangQualType_addConst(struct ZigClangQualType *);
ZIG_EXTERN_C bool ZigClangQualType_eq(struct ZigClangQualType, struct ZigClangQualType);
ZIG_EXTERN_C bool ZigClangQualType_isConstQualified(struct ZigClangQualType);
@@ -846,6 +890,9 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionProtoType_getParamType(cons
ZIG_EXTERN_C ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_begin(const struct ZigClangCompoundStmt *self);
ZIG_EXTERN_C ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_end(const struct ZigClangCompoundStmt *self);
+ZIG_EXTERN_C ZigClangDeclStmt_const_decl_iterator ZigClangDeclStmt_decl_begin(const struct ZigClangDeclStmt *self);
+ZIG_EXTERN_C ZigClangDeclStmt_const_decl_iterator ZigClangDeclStmt_decl_end(const struct ZigClangDeclStmt *self);
+
ZIG_EXTERN_C unsigned ZigClangAPFloat_convertToHexString(const struct ZigClangAPFloat *self, char *DST,
unsigned HexDigits, bool UpperCase, enum ZigClangAPFloat_roundingMode RM);
@@ -855,4 +902,34 @@ ZIG_EXTERN_C const char *ZigClangStringLiteral_getString_bytes_begin_size(const
ZIG_EXTERN_C const struct ZigClangStringLiteral *ZigClangPredefinedExpr_getFunctionName(
const struct ZigClangPredefinedExpr *self);
+
+ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangImplicitCastExpr_getBeginLoc(const struct ZigClangImplicitCastExpr *);
+ZIG_EXTERN_C enum ZigClangCK ZigClangImplicitCastExpr_getCastKind(const struct ZigClangImplicitCastExpr *);
+ZIG_EXTERN_C const struct ZigClangExpr *ZigClangImplicitCastExpr_getSubExpr(const struct ZigClangImplicitCastExpr *);
+
+ZIG_EXTERN_C struct ZigClangQualType ZigClangArrayType_getElementType(const struct ZigClangArrayType *);
+
+ZIG_EXTERN_C const struct ZigClangValueDecl *ZigClangDeclRefExpr_getDecl(const struct ZigClangDeclRefExpr *);
+
+ZIG_EXTERN_C struct ZigClangQualType ZigClangParenType_getInnerType(const struct ZigClangParenType *);
+
+ZIG_EXTERN_C struct ZigClangQualType ZigClangAttributedType_getEquivalentType(const struct ZigClangAttributedType *);
+
+ZIG_EXTERN_C struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *);
+
+ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangCStyleCastExpr_getBeginLoc(const struct ZigClangCStyleCastExpr *);
+ZIG_EXTERN_C const struct ZigClangExpr *ZigClangCStyleCastExpr_getSubExpr(const struct ZigClangCStyleCastExpr *);
+ZIG_EXTERN_C struct ZigClangQualType ZigClangCStyleCastExpr_getType(const struct ZigClangCStyleCastExpr *);
+
+ZIG_EXTERN_C bool ZigClangIntegerLiteral_EvaluateAsInt(const struct ZigClangIntegerLiteral *, struct ZigClangExprEvalResult *, const struct ZigClangASTContext *);
+ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangIntegerLiteral_getBeginLoc(const struct ZigClangIntegerLiteral *);
+
+ZIG_EXTERN_C const struct ZigClangExpr *ZigClangReturnStmt_getRetValue(const struct ZigClangReturnStmt *);
+
+ZIG_EXTERN_C enum ZigClangBO ZigClangBinaryOperator_getOpcode(const struct ZigClangBinaryOperator *);
+ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangBinaryOperator_getBeginLoc(const struct ZigClangBinaryOperator *);
+ZIG_EXTERN_C const struct ZigClangExpr *ZigClangBinaryOperator_getLHS(const struct ZigClangBinaryOperator *);
+ZIG_EXTERN_C const struct ZigClangExpr *ZigClangBinaryOperator_getRHS(const struct ZigClangBinaryOperator *);
+ZIG_EXTERN_C struct ZigClangQualType ZigClangBinaryOperator_getType(const struct ZigClangBinaryOperator *);
+
#endif
diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp
index fe1b279cf0..c51c9e1a50 100644
--- a/src/zig_llvm.cpp
+++ b/src/zig_llvm.cpp
@@ -39,7 +39,9 @@
#include <llvm/Support/TargetParser.h>
#include <llvm/Support/Timer.h>
#include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/TargetRegistry.h>
#include <llvm/Target/TargetMachine.h>
+#include <llvm/Target/CodeGenCWrappers.h>
#include <llvm/Transforms/Coroutines.h>
#include <llvm/Transforms/IPO.h>
#include <llvm/Transforms/IPO/AlwaysInliner.h>
@@ -93,6 +95,61 @@ static const bool assertions_on = true;
static const bool assertions_on = false;
#endif
+LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple,
+ const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc,
+ LLVMCodeModel CodeModel, bool function_sections)
+{
+ Optional<Reloc::Model> RM;
+ switch (Reloc){
+ case LLVMRelocStatic:
+ RM = Reloc::Static;
+ break;
+ case LLVMRelocPIC:
+ RM = Reloc::PIC_;
+ break;
+ case LLVMRelocDynamicNoPic:
+ RM = Reloc::DynamicNoPIC;
+ break;
+ case LLVMRelocROPI:
+ RM = Reloc::ROPI;
+ break;
+ case LLVMRelocRWPI:
+ RM = Reloc::RWPI;
+ break;
+ case LLVMRelocROPI_RWPI:
+ RM = Reloc::ROPI_RWPI;
+ break;
+ default:
+ break;
+ }
+
+ bool JIT;
+ Optional<CodeModel::Model> CM = unwrap(CodeModel, JIT);
+
+ CodeGenOpt::Level OL;
+ switch (Level) {
+ case LLVMCodeGenLevelNone:
+ OL = CodeGenOpt::None;
+ break;
+ case LLVMCodeGenLevelLess:
+ OL = CodeGenOpt::Less;
+ break;
+ case LLVMCodeGenLevelAggressive:
+ OL = CodeGenOpt::Aggressive;
+ break;
+ default:
+ OL = CodeGenOpt::Default;
+ break;
+ }
+
+ TargetOptions opt;
+ opt.FunctionSections = function_sections;
+
+ TargetMachine *TM = reinterpret_cast<Target*>(T)->createTargetMachine(Triple, CPU, Features, opt, RM, CM,
+ OL, JIT);
+ return reinterpret_cast<LLVMTargetMachineRef>(TM);
+}
+
bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug,
bool is_small, bool time_report)
diff --git a/src/zig_llvm.h b/src/zig_llvm.h
index d667e0423d..8b7b0775f7 100644
--- a/src/zig_llvm.h
+++ b/src/zig_llvm.h
@@ -58,6 +58,10 @@ ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machi
const char *filename, enum ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug,
bool is_small, bool time_report);
+ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple,
+ const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc,
+ LLVMCodeModel CodeModel, bool function_sections);
+
ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref);
enum ZigLLVM_FnInline {