/* * Copyright (c) 2015 Andrew Kelley * * This file is part of zig, which is MIT licensed. * See http://opensource.org/licenses/MIT */ #ifndef ZIG_ALL_TYPES_HPP #define ZIG_ALL_TYPES_HPP #include "list.hpp" #include "buffer.hpp" #include "cache_hash.hpp" #include "zig_llvm.h" #include "hash_map.hpp" #include "errmsg.hpp" #include "bigint.hpp" #include "bigfloat.hpp" #include "target.hpp" #include "tokenizer.hpp" #ifndef NDEBUG #define DBG_MACRO_NO_WARNING #include #endif struct AstNode; struct ZigFn; struct Scope; struct ScopeBlock; struct ScopeFnDef; struct ScopeExpr; struct ZigType; struct ZigVar; struct ErrorTableEntry; struct BuiltinFnEntry; struct TypeStructField; struct CodeGen; struct ZigValue; struct IrInst; struct IrInstSrc; struct IrInstGen; struct IrInstGenCast; struct IrInstGenAlloca; struct IrInstGenCall; struct IrInstGenAwait; struct IrBasicBlockSrc; struct IrBasicBlockGen; struct ScopeDecls; struct ZigWindowsSDK; struct Tld; struct TldExport; struct IrAnalyze; struct ResultLoc; struct ResultLocPeer; struct ResultLocPeerParent; struct ResultLocBitCast; struct ResultLocCast; struct ResultLocReturn; struct IrExecutableGen; enum FileExt { FileExtUnknown, FileExtAsm, FileExtC, FileExtCpp, FileExtHeader, FileExtLLVMIr, FileExtLLVMBitCode, }; enum PtrLen { PtrLenUnknown, PtrLenSingle, PtrLenC, }; enum CallingConvention { CallingConventionUnspecified, CallingConventionC, CallingConventionCold, CallingConventionNaked, CallingConventionAsync, CallingConventionInterrupt, CallingConventionSignal, CallingConventionStdcall, CallingConventionFastcall, CallingConventionVectorcall, CallingConventionThiscall, CallingConventionAPCS, CallingConventionAAPCS, CallingConventionAAPCSVFP, }; // This one corresponds to the builtin.zig enum. enum BuiltinPtrSize { BuiltinPtrSizeOne, BuiltinPtrSizeMany, BuiltinPtrSizeSlice, BuiltinPtrSizeC, }; enum UndefAllowed { UndefOk, UndefBad, LazyOkNoUndef, LazyOk, }; enum X64CABIClass { X64CABIClass_Unknown, X64CABIClass_MEMORY, X64CABIClass_MEMORY_nobyval, X64CABIClass_INTEGER, X64CABIClass_SSE, }; struct IrExecutableSrc { ZigList basic_block_list; Buf *name; ZigFn *name_fn; size_t mem_slot_count; size_t next_debug_id; size_t *backward_branch_count; size_t *backward_branch_quota; ZigFn *fn_entry; Buf *c_import_buf; AstNode *source_node; IrExecutableGen *parent_exec; IrAnalyze *analysis; Scope *begin_scope; ErrorMsg *first_err_trace_msg; ZigList tld_list; bool is_inline; bool is_generic_instantiation; bool need_err_code_spill; // This is a function for use in the debugger to print // the source location. void src(); }; struct IrExecutableGen { ZigList basic_block_list; Buf *name; ZigFn *name_fn; size_t mem_slot_count; size_t next_debug_id; size_t *backward_branch_count; size_t *backward_branch_quota; ZigFn *fn_entry; Buf *c_import_buf; AstNode *source_node; IrExecutableGen *parent_exec; IrExecutableSrc *source_exec; Scope *begin_scope; ErrorMsg *first_err_trace_msg; ZigList tld_list; bool is_inline; bool is_generic_instantiation; bool need_err_code_spill; // This is a function for use in the debugger to print // the source location. void src(); }; enum OutType { OutTypeUnknown, OutTypeExe, OutTypeLib, OutTypeObj, }; enum ConstParentId { ConstParentIdNone, ConstParentIdStruct, ConstParentIdErrUnionCode, ConstParentIdErrUnionPayload, ConstParentIdOptionalPayload, ConstParentIdArray, ConstParentIdUnion, ConstParentIdScalar, }; struct ConstParent { ConstParentId id; union { struct { ZigValue *array_val; size_t elem_index; } p_array; struct { ZigValue *struct_val; size_t field_index; } p_struct; struct { ZigValue *err_union_val; } p_err_union_code; struct { ZigValue *err_union_val; } p_err_union_payload; struct { ZigValue *optional_val; } p_optional_payload; struct { ZigValue *union_val; } p_union; struct { ZigValue *scalar_val; } p_scalar; } data; }; struct ConstStructValue { ZigValue **fields; }; struct ConstUnionValue { BigInt tag; ZigValue *payload; }; enum ConstArraySpecial { ConstArraySpecialNone, ConstArraySpecialUndef, ConstArraySpecialBuf, }; struct ConstArrayValue { ConstArraySpecial special; union { struct { ZigValue *elements; } s_none; Buf *s_buf; } data; }; enum ConstPtrSpecial { // Enforce explicitly setting this ID by making the zero value invalid. ConstPtrSpecialInvalid, // The pointer is a reference to a single object. ConstPtrSpecialRef, // The pointer points to an element in an underlying array. // Not to be confused with ConstPtrSpecialSubArray. ConstPtrSpecialBaseArray, // The pointer points to a field in an underlying struct. ConstPtrSpecialBaseStruct, // The pointer points to the error set field of an error union ConstPtrSpecialBaseErrorUnionCode, // The pointer points to the payload field of an error union ConstPtrSpecialBaseErrorUnionPayload, // The pointer points to the payload field of an optional ConstPtrSpecialBaseOptionalPayload, // This means that we did a compile-time pointer reinterpret and we cannot // understand the value of pointee at compile time. However, we will still // emit a binary with a compile time known address. // In this case index is the numeric address value. ConstPtrSpecialHardCodedAddr, // This means that the pointer represents memory of assigning to _. // That is, storing discards the data, and loading is invalid. ConstPtrSpecialDiscard, // This is actually a function. ConstPtrSpecialFunction, // This means the pointer is null. This is only allowed when the type is ?*T. // We use this instead of ConstPtrSpecialHardCodedAddr because often we check // for that value to avoid doing comptime work. // We need the data layout for ConstCastOnly == true // types to be the same, so all optionals of pointer types use x_ptr // instead of x_optional. ConstPtrSpecialNull, // The pointer points to a sub-array (not an individual element). // Not to be confused with ConstPtrSpecialBaseArray. However, it uses the same // union payload struct (base_array). ConstPtrSpecialSubArray, }; enum ConstPtrMut { // The pointer points to memory that is known at compile time and immutable. ConstPtrMutComptimeConst, // This means that the pointer points to memory used by a comptime variable, // so attempting to write a non-compile-time known value is an error // But the underlying value is allowed to change at compile time. ConstPtrMutComptimeVar, // 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 { ConstPtrSpecial special; ConstPtrMut mut; union { struct { ZigValue *pointee; } ref; struct { ZigValue *array_val; size_t elem_index; } base_array; struct { ZigValue *struct_val; size_t field_index; } base_struct; struct { ZigValue *err_union_val; } base_err_union_code; struct { ZigValue *err_union_val; } base_err_union_payload; struct { ZigValue *optional_val; } base_optional_payload; struct { uint64_t addr; } hard_coded_addr; struct { ZigFn *fn_entry; } fn; } data; }; struct ConstErrValue { ZigValue *error_set; ZigValue *payload; }; struct ConstBoundFnValue { ZigFn *fn; IrInstGen *first_arg; IrInst *first_arg_src; }; struct ConstArgTuple { size_t start_index; size_t end_index; }; enum ConstValSpecial { ConstValSpecialRuntime, ConstValSpecialStatic, ConstValSpecialUndef, ConstValSpecialLazy, }; enum RuntimeHintErrorUnion { RuntimeHintErrorUnionUnknown, RuntimeHintErrorUnionError, RuntimeHintErrorUnionNonError, }; enum RuntimeHintOptional { RuntimeHintOptionalUnknown, RuntimeHintOptionalNull, // TODO is this value even possible? if this is the case it might mean the const value is compile time known. RuntimeHintOptionalNonNull, }; enum RuntimeHintPtr { RuntimeHintPtrUnknown, RuntimeHintPtrStack, RuntimeHintPtrNonStack, }; enum RuntimeHintSliceId { RuntimeHintSliceIdUnknown, RuntimeHintSliceIdLen, }; struct RuntimeHintSlice { enum RuntimeHintSliceId id; uint64_t len; }; enum LazyValueId { LazyValueIdInvalid, LazyValueIdAlignOf, LazyValueIdSizeOf, LazyValueIdPtrType, LazyValueIdOptType, LazyValueIdSliceType, LazyValueIdFnType, LazyValueIdErrUnionType, LazyValueIdArrayType, LazyValueIdTypeInfoDecls, }; struct LazyValue { LazyValueId id; }; struct LazyValueTypeInfoDecls { LazyValue base; IrAnalyze *ira; ScopeDecls *decls_scope; IrInst *source_instr; }; struct LazyValueAlignOf { LazyValue base; IrAnalyze *ira; IrInstGen *target_type; }; struct LazyValueSizeOf { LazyValue base; IrAnalyze *ira; IrInstGen *target_type; bool bit_size; }; struct LazyValueSliceType { LazyValue base; IrAnalyze *ira; IrInstGen *sentinel; // can be null IrInstGen *elem_type; IrInstGen *align_inst; // can be null bool is_const; bool is_volatile; bool is_allowzero; }; struct LazyValueArrayType { LazyValue base; IrAnalyze *ira; IrInstGen *sentinel; // can be null IrInstGen *elem_type; uint64_t length; }; struct LazyValuePtrType { LazyValue base; IrAnalyze *ira; IrInstGen *sentinel; // can be null IrInstGen *elem_type; IrInstGen *align_inst; // can be null PtrLen ptr_len; uint32_t bit_offset_in_host; uint32_t host_int_bytes; bool is_const; bool is_volatile; bool is_allowzero; }; struct LazyValueOptType { LazyValue base; IrAnalyze *ira; IrInstGen *payload_type; }; struct LazyValueFnType { LazyValue base; IrAnalyze *ira; AstNode *proto_node; IrInstGen **param_types; IrInstGen *align_inst; // can be null IrInstGen *return_type; CallingConvention cc; bool is_generic; }; struct LazyValueErrUnionType { LazyValue base; IrAnalyze *ira; IrInstGen *err_set_type; IrInstGen *payload_type; Buf *type_name; }; struct ZigValue { ZigType *type; ConstValSpecial special; uint32_t llvm_align; ConstParent parent; LLVMValueRef llvm_value; LLVMValueRef llvm_global; union { // populated if special == ConstValSpecialLazy LazyValue *x_lazy; // populated if special == ConstValSpecialStatic BigInt x_bigint; BigFloat x_bigfloat; float16_t x_f16; float x_f32; double x_f64; float128_t x_f128; bool x_bool; ConstBoundFnValue x_bound_fn; ZigType *x_type; ZigValue *x_optional; ConstErrValue x_err_union; ErrorTableEntry *x_err_set; BigInt x_enum_tag; ConstStructValue x_struct; ConstUnionValue x_union; ConstArrayValue x_array; ConstPtrValue x_ptr; ConstArgTuple x_arg_tuple; Buf *x_enum_literal; // populated if special == ConstValSpecialRuntime RuntimeHintErrorUnion rh_error_union; RuntimeHintOptional rh_maybe; RuntimeHintPtr rh_ptr; RuntimeHintSlice rh_slice; } data; // uncomment this to find bugs. can't leave it uncommented because of a gcc-9 warning //ZigValue& operator= (const ZigValue &other) = delete; // use copy_const_val ZigValue(const ZigValue &other) = delete; // plz zero initialize with ZigValue val = {}; // for use in debuggers void dump(); }; enum ReturnKnowledge { ReturnKnowledgeUnknown, ReturnKnowledgeKnownError, ReturnKnowledgeKnownNonError, ReturnKnowledgeKnownNull, ReturnKnowledgeKnownNonNull, ReturnKnowledgeSkipDefers, }; enum VisibMod { VisibModPrivate, VisibModPub, }; enum GlobalLinkageId { GlobalLinkageIdInternal, GlobalLinkageIdStrong, GlobalLinkageIdWeak, GlobalLinkageIdLinkOnce, }; enum TldId { TldIdVar, TldIdFn, TldIdContainer, TldIdCompTime, TldIdUsingNamespace, }; enum TldResolution { TldResolutionUnresolved, TldResolutionResolving, TldResolutionInvalid, TldResolutionOkLazy, TldResolutionOk, }; struct Tld { TldId id; Buf *name; VisibMod visib_mod; AstNode *source_node; ZigType *import; Scope *parent_scope; TldResolution resolution; }; struct TldVar { Tld base; ZigVar *var; Buf *extern_lib_name; bool analyzing_type; // flag to detect dependency loops }; struct TldFn { Tld base; ZigFn *fn_entry; Buf *extern_lib_name; }; struct TldContainer { Tld base; ScopeDecls *decls_scope; ZigType *type_entry; }; struct TldCompTime { Tld base; }; struct TldUsingNamespace { Tld base; ZigValue *using_namespace_value; }; struct TypeEnumField { Buf *name; BigInt value; uint32_t decl_index; AstNode *decl_node; }; struct TypeUnionField { Buf *name; ZigType *type_entry; // available after ResolveStatusSizeKnown ZigValue *type_val; // available after ResolveStatusZeroBitsKnown TypeEnumField *enum_field; AstNode *decl_node; uint32_t gen_index; uint32_t align; }; enum NodeType { NodeTypeFnProto, NodeTypeFnDef, NodeTypeParamDecl, NodeTypeBlock, NodeTypeGroupedExpr, NodeTypeReturnExpr, NodeTypeDefer, NodeTypeVariableDeclaration, NodeTypeTestDecl, NodeTypeBinOpExpr, NodeTypeCatchExpr, NodeTypeFloatLiteral, NodeTypeIntLiteral, NodeTypeStringLiteral, NodeTypeCharLiteral, NodeTypeSymbol, NodeTypePrefixOpExpr, NodeTypePointerType, NodeTypeFnCallExpr, NodeTypeArrayAccessExpr, NodeTypeSliceExpr, NodeTypeFieldAccessExpr, NodeTypePtrDeref, NodeTypeUnwrapOptional, NodeTypeUsingNamespace, NodeTypeBoolLiteral, NodeTypeNullLiteral, NodeTypeUndefinedLiteral, NodeTypeUnreachable, NodeTypeIfBoolExpr, NodeTypeWhileExpr, NodeTypeForExpr, NodeTypeSwitchExpr, NodeTypeSwitchProng, NodeTypeSwitchRange, NodeTypeCompTime, NodeTypeNoSuspend, NodeTypeBreak, NodeTypeContinue, NodeTypeAsmExpr, NodeTypeContainerDecl, NodeTypeStructField, NodeTypeContainerInitExpr, NodeTypeStructValueField, NodeTypeArrayType, NodeTypeInferredArrayType, NodeTypeErrorType, NodeTypeIfErrorExpr, NodeTypeIfOptional, NodeTypeErrorSetDecl, NodeTypeErrorSetField, NodeTypeResume, NodeTypeAwaitExpr, NodeTypeSuspend, NodeTypeAnyFrameType, NodeTypeEnumLiteral, NodeTypeAnyTypeField, }; enum FnInline { FnInlineAuto, FnInlineAlways, FnInlineNever, }; struct AstNodeFnProto { Buf *name; ZigList params; AstNode *return_type; Token *return_anytype_token; AstNode *fn_def_node; // populated if this is an extern declaration Buf *lib_name; // populated if the "align A" is present AstNode *align_expr; // populated if the "section(S)" is present AstNode *section_expr; // populated if the "callconv(S)" is present AstNode *callconv_expr; Buf doc_comments; FnInline fn_inline; VisibMod visib_mod; bool auto_err_set; bool is_var_args; bool is_extern; bool is_export; }; struct AstNodeFnDef { AstNode *fn_proto; AstNode *body; }; struct AstNodeParamDecl { Buf *name; AstNode *type; Token *anytype_token; Buf doc_comments; bool is_noalias; bool is_comptime; bool is_var_args; }; struct AstNodeBlock { Buf *name; ZigList statements; }; enum ReturnKind { ReturnKindUnconditional, ReturnKindError, }; struct AstNodeReturnExpr { ReturnKind kind; // might be null in case of return void; AstNode *expr; }; struct AstNodeDefer { ReturnKind kind; AstNode *err_payload; AstNode *expr; // temporary data used in IR generation Scope *child_scope; Scope *expr_scope; }; struct AstNodeVariableDeclaration { Buf *symbol; // one or both of type and expr will be non null AstNode *type; AstNode *expr; // populated if this is an extern declaration Buf *lib_name; // populated if the "align(A)" is present AstNode *align_expr; // populated if the "section(S)" is present AstNode *section_expr; Token *threadlocal_tok; Buf doc_comments; VisibMod visib_mod; bool is_const; bool is_comptime; bool is_export; bool is_extern; }; struct AstNodeTestDecl { Buf *name; AstNode *body; }; enum BinOpType { BinOpTypeInvalid, BinOpTypeAssign, BinOpTypeAssignTimes, BinOpTypeAssignTimesWrap, BinOpTypeAssignDiv, BinOpTypeAssignMod, BinOpTypeAssignPlus, BinOpTypeAssignPlusWrap, BinOpTypeAssignMinus, BinOpTypeAssignMinusWrap, BinOpTypeAssignBitShiftLeft, BinOpTypeAssignBitShiftRight, BinOpTypeAssignBitAnd, BinOpTypeAssignBitXor, BinOpTypeAssignBitOr, BinOpTypeAssignMergeErrorSets, BinOpTypeBoolOr, BinOpTypeBoolAnd, BinOpTypeCmpEq, BinOpTypeCmpNotEq, BinOpTypeCmpLessThan, BinOpTypeCmpGreaterThan, BinOpTypeCmpLessOrEq, BinOpTypeCmpGreaterOrEq, BinOpTypeBinOr, BinOpTypeBinXor, BinOpTypeBinAnd, BinOpTypeBitShiftLeft, BinOpTypeBitShiftRight, BinOpTypeAdd, BinOpTypeAddWrap, BinOpTypeSub, BinOpTypeSubWrap, BinOpTypeMult, BinOpTypeMultWrap, BinOpTypeDiv, BinOpTypeMod, BinOpTypeUnwrapOptional, BinOpTypeArrayCat, BinOpTypeArrayMult, BinOpTypeErrorUnion, BinOpTypeMergeErrorSets, }; struct AstNodeBinOpExpr { AstNode *op1; BinOpType bin_op; AstNode *op2; }; struct AstNodeCatchExpr { AstNode *op1; AstNode *symbol; // can be null AstNode *op2; }; struct AstNodeUnwrapOptional { AstNode *expr; }; // Must be synchronized with std.builtin.CallOptions.Modifier enum CallModifier { CallModifierNone, CallModifierAsync, CallModifierNeverTail, CallModifierNeverInline, CallModifierNoSuspend, CallModifierAlwaysTail, CallModifierAlwaysInline, CallModifierCompileTime, // These are additional tags in the compiler, but not exposed in the std lib. CallModifierBuiltin, }; struct AstNodeFnCallExpr { AstNode *fn_ref_expr; ZigList params; CallModifier modifier; bool seen; // used by @compileLog }; struct AstNodeArrayAccessExpr { AstNode *array_ref_expr; AstNode *subscript; }; struct AstNodeSliceExpr { AstNode *array_ref_expr; AstNode *start; AstNode *end; AstNode *sentinel; // can be null }; struct AstNodeFieldAccessExpr { AstNode *struct_expr; Buf *field_name; }; struct AstNodePtrDerefExpr { AstNode *target; }; enum PrefixOp { PrefixOpInvalid, PrefixOpBoolNot, PrefixOpBinNot, PrefixOpNegation, PrefixOpNegationWrap, PrefixOpOptional, PrefixOpAddrOf, }; struct AstNodePrefixOpExpr { PrefixOp prefix_op; AstNode *primary_expr; }; struct AstNodePointerType { Token *star_token; AstNode *sentinel; AstNode *align_expr; BigInt *bit_offset_start; BigInt *host_int_bytes; AstNode *op_expr; Token *allow_zero_token; bool is_const; bool is_volatile; }; struct AstNodeInferredArrayType { AstNode *sentinel; // can be null AstNode *child_type; }; struct AstNodeArrayType { AstNode *size; AstNode *sentinel; AstNode *child_type; AstNode *align_expr; Token *allow_zero_token; bool is_const; bool is_volatile; }; struct AstNodeUsingNamespace { VisibMod visib_mod; AstNode *expr; }; struct AstNodeIfBoolExpr { AstNode *condition; AstNode *then_block; AstNode *else_node; // null, block node, or other if expr node }; struct AstNodeTryExpr { Buf *var_symbol; bool var_is_ptr; AstNode *target_node; AstNode *then_node; AstNode *else_node; Buf *err_symbol; }; struct AstNodeTestExpr { Buf *var_symbol; bool var_is_ptr; AstNode *target_node; AstNode *then_node; AstNode *else_node; // null, block node, or other if expr node }; struct AstNodeWhileExpr { Buf *name; AstNode *condition; Buf *var_symbol; bool var_is_ptr; AstNode *continue_expr; AstNode *body; AstNode *else_node; Buf *err_symbol; bool is_inline; }; struct AstNodeForExpr { Buf *name; AstNode *array_expr; AstNode *elem_node; // always a symbol AstNode *index_node; // always a symbol, might be null AstNode *body; AstNode *else_node; // can be null bool elem_is_ptr; bool is_inline; }; struct AstNodeSwitchExpr { AstNode *expr; ZigList prongs; }; struct AstNodeSwitchProng { ZigList items; AstNode *var_symbol; AstNode *expr; bool var_is_ptr; bool any_items_are_range; }; struct AstNodeSwitchRange { AstNode *start; AstNode *end; }; struct AstNodeCompTime { AstNode *expr; }; struct AstNodeNoSuspend { AstNode *expr; }; struct AsmOutput { Buf *asm_symbolic_name; Buf *constraint; Buf *variable_name; AstNode *return_type; // null unless "=r" and return }; struct AsmInput { Buf *asm_symbolic_name; Buf *constraint; AstNode *expr; }; struct SrcPos { size_t line; size_t column; }; enum AsmTokenId { AsmTokenIdTemplate, AsmTokenIdPercent, AsmTokenIdVar, AsmTokenIdUniqueId, }; struct AsmToken { enum AsmTokenId id; size_t start; size_t end; }; struct AstNodeAsmExpr { Token *volatile_token; AstNode *asm_template; ZigList output_list; ZigList input_list; ZigList clobber_list; }; enum ContainerKind { ContainerKindStruct, ContainerKindEnum, ContainerKindUnion, }; enum ContainerLayout { ContainerLayoutAuto, ContainerLayoutExtern, ContainerLayoutPacked, }; struct AstNodeContainerDecl { AstNode *init_arg_expr; // enum(T), struct(endianness), or union(T), or union(enum(T)) ZigList fields; ZigList decls; Buf doc_comments; ContainerKind kind; ContainerLayout layout; bool auto_enum, is_root; // union(enum) }; struct AstNodeErrorSetField { Buf doc_comments; AstNode *field_name; }; struct AstNodeErrorSetDecl { // Each AstNode could be AstNodeErrorSetField or just AstNodeSymbolExpr to save memory ZigList decls; }; struct AstNodeStructField { Buf *name; AstNode *type; AstNode *value; // populated if the "align(A)" is present AstNode *align_expr; Buf doc_comments; Token *comptime_token; }; struct AstNodeStringLiteral { Buf *buf; }; struct AstNodeCharLiteral { uint32_t value; }; struct AstNodeFloatLiteral { BigFloat *bigfloat; // overflow is true if when parsing the number, we discovered it would not // fit without losing data in a double bool overflow; }; struct AstNodeIntLiteral { BigInt *bigint; }; struct AstNodeStructValueField { Buf *name; AstNode *expr; }; enum ContainerInitKind { ContainerInitKindStruct, ContainerInitKindArray, }; struct AstNodeContainerInitExpr { AstNode *type; ZigList entries; ContainerInitKind kind; }; struct AstNodeNullLiteral { }; struct AstNodeUndefinedLiteral { }; struct AstNodeThisLiteral { }; struct AstNodeSymbolExpr { Buf *symbol; }; struct AstNodeBoolLiteral { bool value; }; struct AstNodeBreakExpr { Buf *name; AstNode *expr; // may be null }; struct AstNodeResumeExpr { AstNode *expr; }; struct AstNodeContinueExpr { Buf *name; }; struct AstNodeUnreachableExpr { }; struct AstNodeErrorType { }; struct AstNodeAwaitExpr { AstNode *expr; }; struct AstNodeSuspend { AstNode *block; }; struct AstNodeAnyFrameType { AstNode *payload_type; // can be NULL }; struct AstNodeEnumLiteral { Token *period; Token *identifier; }; struct AstNode { enum NodeType type; bool already_traced_this_node; size_t line; size_t column; ZigType *owner; union { AstNodeFnDef fn_def; AstNodeFnProto fn_proto; AstNodeParamDecl param_decl; AstNodeBlock block; AstNode * grouped_expr; AstNodeReturnExpr return_expr; AstNodeDefer defer; AstNodeVariableDeclaration variable_declaration; AstNodeTestDecl test_decl; AstNodeBinOpExpr bin_op_expr; AstNodeCatchExpr unwrap_err_expr; AstNodeUnwrapOptional unwrap_optional; AstNodePrefixOpExpr prefix_op_expr; AstNodePointerType pointer_type; AstNodeFnCallExpr fn_call_expr; AstNodeArrayAccessExpr array_access_expr; AstNodeSliceExpr slice_expr; AstNodeUsingNamespace using_namespace; AstNodeIfBoolExpr if_bool_expr; AstNodeTryExpr if_err_expr; AstNodeTestExpr test_expr; AstNodeWhileExpr while_expr; AstNodeForExpr for_expr; AstNodeSwitchExpr switch_expr; AstNodeSwitchProng switch_prong; AstNodeSwitchRange switch_range; AstNodeCompTime comptime_expr; AstNodeNoSuspend nosuspend_expr; AstNodeAsmExpr asm_expr; AstNodeFieldAccessExpr field_access_expr; AstNodePtrDerefExpr ptr_deref_expr; AstNodeContainerDecl container_decl; AstNodeStructField struct_field; AstNodeStringLiteral string_literal; AstNodeCharLiteral char_literal; AstNodeFloatLiteral float_literal; AstNodeIntLiteral int_literal; AstNodeContainerInitExpr container_init_expr; AstNodeStructValueField struct_val_field; AstNodeNullLiteral null_literal; AstNodeUndefinedLiteral undefined_literal; AstNodeThisLiteral this_literal; AstNodeSymbolExpr symbol_expr; AstNodeBoolLiteral bool_literal; AstNodeBreakExpr break_expr; AstNodeContinueExpr continue_expr; AstNodeUnreachableExpr unreachable_expr; AstNodeArrayType array_type; AstNodeInferredArrayType inferred_array_type; AstNodeErrorType error_type; AstNodeErrorSetDecl err_set_decl; AstNodeErrorSetField err_set_field; AstNodeResumeExpr resume_expr; AstNodeAwaitExpr await_expr; AstNodeSuspend suspend; AstNodeAnyFrameType anyframe_type; AstNodeEnumLiteral enum_literal; } data; // This is a function for use in the debugger to print // the source location. void src(); }; // this struct is allocated with allocate_nonzero struct FnTypeParamInfo { bool is_noalias; ZigType *type; }; struct GenericFnTypeId { CodeGen *codegen; ZigFn *fn_entry; ZigValue *params; size_t param_count; }; uint32_t generic_fn_type_id_hash(GenericFnTypeId *id); bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b); struct FnTypeId { ZigType *return_type; FnTypeParamInfo *param_info; size_t param_count; size_t next_param_index; bool is_var_args; CallingConvention cc; uint32_t alignment; }; uint32_t fn_type_id_hash(FnTypeId*); bool fn_type_id_eql(FnTypeId *a, FnTypeId *b); static const uint32_t VECTOR_INDEX_NONE = UINT32_MAX; static const uint32_t VECTOR_INDEX_RUNTIME = UINT32_MAX - 1; struct InferredStructField { ZigType *inferred_struct_type; Buf *field_name; bool already_resolved; }; struct ZigTypePointer { ZigType *child_type; ZigType *slice_parent; // Anonymous struct literal syntax uses this when the result location has // no type in it. This field is null if this pointer does not refer to // a field of a currently-being-inferred struct type. // When this is non-null, the pointer is pointing to the base of the inferred // struct. InferredStructField *inferred_struct_field; // This can be null. If it is non-null, it means the pointer is terminated by this // sentinel value. This is most commonly used for C-style strings, with a 0 byte // to specify the length of the memory pointed to. ZigValue *sentinel; PtrLen ptr_len; uint32_t explicit_alignment; // 0 means use ABI alignment uint32_t bit_offset_in_host; // size of host integer. 0 means no host integer; this field is aligned // when vector_index != VECTOR_INDEX_NONE this is the len of the containing vector uint32_t host_int_bytes; uint32_t vector_index; // see the VECTOR_INDEX_* constants bool is_const; bool is_volatile; bool allow_zero; bool resolve_loop_flag_zero_bits; }; struct ZigTypeInt { uint32_t bit_count; bool is_signed; }; struct ZigTypeFloat { size_t bit_count; }; // Needs to have the same memory layout as ZigTypeVector struct ZigTypeArray { ZigType *child_type; uint64_t len; ZigValue *sentinel; }; struct TypeStructField { Buf *name; ZigType *type_entry; // available after ResolveStatusSizeKnown ZigValue *type_val; // available after ResolveStatusZeroBitsKnown size_t src_index; size_t gen_index; size_t offset; // byte offset from beginning of struct AstNode *decl_node; ZigValue *init_val; // null and then memoized uint32_t bit_offset_in_host; // offset from the memory at gen_index uint32_t host_int_bytes; // size of host integer uint32_t align; bool is_comptime; }; enum ResolveStatus { ResolveStatusUnstarted, ResolveStatusInvalid, ResolveStatusBeingInferred, ResolveStatusZeroBitsKnown, ResolveStatusAlignmentKnown, ResolveStatusSizeKnown, ResolveStatusLLVMFwdDecl, ResolveStatusLLVMFull, }; struct ZigPackage { Buf root_src_dir; Buf root_src_path; // relative to root_src_dir Buf pkg_path; // a.b.c.d which follows the package dependency chain from the root package // reminder: hash tables must be initialized before use HashMap package_table; bool added_to_cache; }; // Stuff that only applies to a struct which is the implicit root struct of a file struct RootStruct { ZigPackage *package; Buf *path; // relative to root_package->root_src_dir ZigList *line_offsets; Buf *source_code; ZigLLVMDIFile *di_file; }; enum StructSpecial { StructSpecialNone, StructSpecialSlice, StructSpecialInferredTuple, StructSpecialInferredStruct, }; struct ZigTypeStruct { AstNode *decl_node; TypeStructField **fields; ScopeDecls *decls_scope; HashMap fields_by_name; RootStruct *root_struct; uint32_t *host_int_bytes; // available for packed structs, indexed by gen_index size_t llvm_full_type_queue_index; uint32_t src_field_count; uint32_t gen_field_count; ContainerLayout layout; ResolveStatus resolve_status; StructSpecial special; // whether any of the fields require comptime // known after ResolveStatusZeroBitsKnown bool requires_comptime; bool resolve_loop_flag_zero_bits; bool resolve_loop_flag_other; }; struct ZigTypeOptional { ZigType *child_type; ResolveStatus resolve_status; }; struct ZigTypeErrorUnion { ZigType *err_set_type; ZigType *payload_type; size_t pad_bytes; LLVMTypeRef pad_llvm_type; }; struct ZigTypeErrorSet { ErrorTableEntry **errors; ZigFn *infer_fn; uint32_t err_count; bool incomplete; }; struct ZigTypeEnum { AstNode *decl_node; TypeEnumField *fields; ZigType *tag_int_type; ScopeDecls *decls_scope; LLVMValueRef name_function; HashMap fields_by_name; uint32_t src_field_count; ContainerLayout layout; ResolveStatus resolve_status; bool non_exhaustive; bool resolve_loop_flag; }; uint32_t type_ptr_hash(const ZigType *ptr); bool type_ptr_eql(const ZigType *a, const ZigType *b); uint32_t pkg_ptr_hash(const ZigPackage *ptr); bool pkg_ptr_eql(const ZigPackage *a, const ZigPackage *b); uint32_t tld_ptr_hash(const Tld *ptr); bool tld_ptr_eql(const Tld *a, const Tld *b); uint32_t node_ptr_hash(const AstNode *ptr); bool node_ptr_eql(const AstNode *a, const AstNode *b); uint32_t fn_ptr_hash(const ZigFn *ptr); bool fn_ptr_eql(const ZigFn *a, const ZigFn *b); uint32_t err_ptr_hash(const ErrorTableEntry *ptr); bool err_ptr_eql(const ErrorTableEntry *a, const ErrorTableEntry *b); struct ZigTypeUnion { AstNode *decl_node; TypeUnionField *fields; ScopeDecls *decls_scope; HashMap fields_by_name; ZigType *tag_type; // always an enum or null LLVMTypeRef union_llvm_type; TypeUnionField *most_aligned_union_member; size_t gen_union_index; size_t gen_tag_index; size_t union_abi_size; uint32_t src_field_count; uint32_t gen_field_count; ContainerLayout layout; ResolveStatus resolve_status; bool have_explicit_tag_type; // whether any of the fields require comptime // the value is not valid until zero_bits_known == true bool requires_comptime; bool resolve_loop_flag_zero_bits; bool resolve_loop_flag_other; }; struct FnGenParamInfo { size_t src_index; size_t gen_index; bool is_byval; ZigType *type; }; struct ZigTypeFn { FnTypeId fn_type_id; bool is_generic; ZigType *gen_return_type; size_t gen_param_count; FnGenParamInfo *gen_param_info; LLVMTypeRef raw_type_ref; ZigLLVMDIType *raw_di_type; ZigType *bound_fn_parent; }; struct ZigTypeBoundFn { ZigType *fn_type; }; // Needs to have the same memory layout as ZigTypeArray struct ZigTypeVector { // The type must be a pointer, integer, bool, or float ZigType *elem_type; uint64_t len; size_t padding; }; // A lot of code is relying on ZigTypeArray and ZigTypeVector having the same layout/size static_assert(sizeof(ZigTypeVector) == sizeof(ZigTypeArray), "Size of ZigTypeVector and ZigTypeArray do not match!"); enum ZigTypeId { ZigTypeIdInvalid, ZigTypeIdMetaType, ZigTypeIdVoid, ZigTypeIdBool, ZigTypeIdUnreachable, ZigTypeIdInt, ZigTypeIdFloat, ZigTypeIdPointer, ZigTypeIdArray, ZigTypeIdStruct, ZigTypeIdComptimeFloat, ZigTypeIdComptimeInt, ZigTypeIdUndefined, ZigTypeIdNull, ZigTypeIdOptional, ZigTypeIdErrorUnion, ZigTypeIdErrorSet, ZigTypeIdEnum, ZigTypeIdUnion, ZigTypeIdFn, ZigTypeIdBoundFn, ZigTypeIdOpaque, ZigTypeIdFnFrame, ZigTypeIdAnyFrame, ZigTypeIdVector, ZigTypeIdEnumLiteral, }; enum OnePossibleValue { OnePossibleValueInvalid, OnePossibleValueNo, OnePossibleValueYes, }; struct ZigTypeOpaque { Buf *bare_name; }; struct ZigTypeFnFrame { ZigFn *fn; ZigType *locals_struct; // This is set to the type that resolving the frame currently depends on, null if none. // It's for generating a helpful error message. ZigType *resolve_loop_type; AstNode *resolve_loop_src_node; bool reported_loop_err; }; struct ZigTypeAnyFrame { ZigType *result_type; // null if `anyframe` instead of `anyframe->T` }; struct ZigType { ZigTypeId id; Buf name; // These are not supposed to be accessed directly. They're // null during semantic analysis, memoized with get_llvm_type // and get_llvm_di_type LLVMTypeRef llvm_type; ZigLLVMDIType *llvm_di_type; union { ZigTypePointer pointer; ZigTypeInt integral; ZigTypeFloat floating; ZigTypeArray array; ZigTypeStruct structure; ZigTypeOptional maybe; ZigTypeErrorUnion error_union; ZigTypeErrorSet error_set; ZigTypeEnum enumeration; ZigTypeUnion unionation; ZigTypeFn fn; ZigTypeBoundFn bound_fn; ZigTypeVector vector; ZigTypeOpaque opaque; ZigTypeFnFrame frame; ZigTypeAnyFrame any_frame; } data; // use these fields to make sure we don't duplicate type table entries for the same type ZigType *pointer_parent[2]; // [0 - mut, 1 - const] ZigType *optional_parent; ZigType *any_frame_parent; // If we generate a constant name value for this type, we memoize it here. // The type of this is array ZigValue *cached_const_name_val; OnePossibleValue one_possible_value; // Known after ResolveStatusAlignmentKnown. uint32_t abi_align; // The offset in bytes between consecutive array elements of this type. Known // after ResolveStatusSizeKnown. size_t abi_size; // Number of bits of information in this type. Known after ResolveStatusSizeKnown. size_t size_in_bits; bool gen_h_loop_flag; }; enum FnAnalState { FnAnalStateReady, FnAnalStateProbing, FnAnalStateComplete, FnAnalStateInvalid, }; struct GlobalExport { Buf name; GlobalLinkageId linkage; }; struct ZigFn { LLVMValueRef llvm_value; const char *llvm_name; AstNode *proto_node; AstNode *body_node; ScopeFnDef *fndef_scope; // parent should be the top level decls or container decls Scope *child_scope; // parent is scope for last parameter ScopeBlock *def_scope; // parent is child_scope Buf symbol_name; // This is the function type assuming the function does not suspend. // Note that for an async function, this can be shared with non-async functions. So the value here // should only be read for things in common between non-async and async function types. ZigType *type_entry; // For normal functions one could use the type_entry->raw_type_ref and type_entry->raw_di_type. // However for functions that suspend, those values could possibly be their non-suspending equivalents. // So these values should be preferred. LLVMTypeRef raw_type_ref; ZigLLVMDIType *raw_di_type; ZigType *frame_type; // in the case of normal functions this is the implicit return type // in the case of async functions this is the implicit return type according to the // zig source code, not according to zig ir ZigType *src_implicit_return_type; IrExecutableSrc *ir_executable; IrExecutableGen analyzed_executable; size_t prealloc_bbc; size_t prealloc_backward_branch_quota; AstNode **param_source_nodes; Buf **param_names; IrInstGen *err_code_spill; AstNode *assumed_non_async; AstNode *fn_no_inline_set_node; AstNode *fn_static_eval_set_node; ZigList alloca_gen_list; ZigList variable_list; Buf *section_name; AstNode *set_alignstack_node; AstNode *set_cold_node; const AstNode *inferred_async_node; ZigFn *inferred_async_fn; AstNode *non_async_node; ZigList export_list; ZigList call_list; ZigList await_list; LLVMValueRef valgrind_client_request_array; FnInline fn_inline; FnAnalState anal_state; uint32_t align_bytes; uint32_t alignstack_value; bool calls_or_awaits_errorable_fn; bool is_cold; bool is_test; }; uint32_t fn_table_entry_hash(ZigFn*); bool fn_table_entry_eql(ZigFn *a, ZigFn *b); enum BuiltinFnId { BuiltinFnIdInvalid, BuiltinFnIdMemcpy, BuiltinFnIdMemset, BuiltinFnIdSizeof, BuiltinFnIdAlignOf, BuiltinFnIdField, BuiltinFnIdTypeInfo, BuiltinFnIdType, BuiltinFnIdHasField, BuiltinFnIdTypeof, BuiltinFnIdAddWithOverflow, BuiltinFnIdSubWithOverflow, BuiltinFnIdMulWithOverflow, BuiltinFnIdShlWithOverflow, BuiltinFnIdMulAdd, BuiltinFnIdCInclude, BuiltinFnIdCDefine, BuiltinFnIdCUndef, BuiltinFnIdCompileErr, BuiltinFnIdCompileLog, BuiltinFnIdCtz, BuiltinFnIdClz, BuiltinFnIdPopCount, BuiltinFnIdBswap, BuiltinFnIdBitReverse, BuiltinFnIdImport, BuiltinFnIdCImport, BuiltinFnIdErrName, BuiltinFnIdBreakpoint, BuiltinFnIdReturnAddress, BuiltinFnIdEmbedFile, BuiltinFnIdCmpxchgWeak, BuiltinFnIdCmpxchgStrong, BuiltinFnIdFence, BuiltinFnIdDivExact, BuiltinFnIdDivTrunc, BuiltinFnIdDivFloor, BuiltinFnIdRem, BuiltinFnIdMod, BuiltinFnIdSqrt, BuiltinFnIdSin, BuiltinFnIdCos, BuiltinFnIdExp, BuiltinFnIdExp2, BuiltinFnIdLog, BuiltinFnIdLog2, BuiltinFnIdLog10, BuiltinFnIdFabs, BuiltinFnIdFloor, BuiltinFnIdCeil, BuiltinFnIdTrunc, BuiltinFnIdNearbyInt, BuiltinFnIdRound, BuiltinFnIdTruncate, BuiltinFnIdIntCast, BuiltinFnIdFloatCast, BuiltinFnIdErrSetCast, BuiltinFnIdIntToFloat, BuiltinFnIdFloatToInt, BuiltinFnIdBoolToInt, BuiltinFnIdErrToInt, BuiltinFnIdIntToErr, BuiltinFnIdEnumToInt, BuiltinFnIdIntToEnum, BuiltinFnIdVectorType, BuiltinFnIdShuffle, BuiltinFnIdSplat, BuiltinFnIdSetCold, BuiltinFnIdSetRuntimeSafety, BuiltinFnIdSetFloatMode, BuiltinFnIdTypeName, BuiltinFnIdPanic, BuiltinFnIdPtrCast, BuiltinFnIdBitCast, BuiltinFnIdIntToPtr, BuiltinFnIdPtrToInt, BuiltinFnIdTagName, BuiltinFnIdTagType, BuiltinFnIdFieldParentPtr, BuiltinFnIdByteOffsetOf, BuiltinFnIdBitOffsetOf, BuiltinFnIdAsyncCall, BuiltinFnIdShlExact, BuiltinFnIdShrExact, BuiltinFnIdSetEvalBranchQuota, BuiltinFnIdAlignCast, BuiltinFnIdOpaqueType, BuiltinFnIdThis, BuiltinFnIdSetAlignStack, BuiltinFnIdExport, BuiltinFnIdErrorReturnTrace, BuiltinFnIdAtomicRmw, BuiltinFnIdAtomicLoad, BuiltinFnIdAtomicStore, BuiltinFnIdHasDecl, BuiltinFnIdUnionInit, BuiltinFnIdFrameAddress, BuiltinFnIdFrameType, BuiltinFnIdFrameHandle, BuiltinFnIdFrameSize, BuiltinFnIdAs, BuiltinFnIdCall, BuiltinFnIdBitSizeof, BuiltinFnIdWasmMemorySize, BuiltinFnIdWasmMemoryGrow, BuiltinFnIdSrc, }; struct BuiltinFnEntry { BuiltinFnId id; Buf name; size_t param_count; }; enum PanicMsgId { PanicMsgIdUnreachable, PanicMsgIdBoundsCheckFailure, PanicMsgIdCastNegativeToUnsigned, PanicMsgIdCastTruncatedData, PanicMsgIdIntegerOverflow, PanicMsgIdShlOverflowedBits, PanicMsgIdShrOverflowedBits, PanicMsgIdDivisionByZero, PanicMsgIdRemainderDivisionByZero, PanicMsgIdExactDivisionRemainder, PanicMsgIdUnwrapOptionalFail, PanicMsgIdInvalidErrorCode, PanicMsgIdIncorrectAlignment, PanicMsgIdBadUnionField, PanicMsgIdBadEnumValue, PanicMsgIdFloatToInt, PanicMsgIdPtrCastNull, PanicMsgIdBadResume, PanicMsgIdBadAwait, PanicMsgIdBadReturn, PanicMsgIdResumedAnAwaitingFn, PanicMsgIdFrameTooSmall, PanicMsgIdResumedFnPendingAwait, PanicMsgIdBadNoSuspendCall, PanicMsgIdResumeNotSuspendedFn, PanicMsgIdBadSentinel, PanicMsgIdShxTooBigRhs, PanicMsgIdCount, }; uint32_t fn_eval_hash(Scope*); bool fn_eval_eql(Scope *a, Scope *b); struct TypeId { ZigTypeId id; union { struct { CodeGen *codegen; ZigType *child_type; InferredStructField *inferred_struct_field; ZigValue *sentinel; PtrLen ptr_len; uint32_t alignment; uint32_t bit_offset_in_host; uint32_t host_int_bytes; uint32_t vector_index; bool is_const; bool is_volatile; bool allow_zero; } pointer; struct { CodeGen *codegen; ZigType *child_type; uint64_t size; ZigValue *sentinel; } array; struct { bool is_signed; uint32_t bit_count; } integer; struct { ZigType *err_set_type; ZigType *payload_type; } error_union; struct { ZigType *elem_type; uint32_t len; } vector; } data; }; uint32_t type_id_hash(TypeId); bool type_id_eql(TypeId a, TypeId b); enum ZigLLVMFnId { ZigLLVMFnIdCtz, ZigLLVMFnIdClz, ZigLLVMFnIdPopCount, ZigLLVMFnIdOverflowArithmetic, ZigLLVMFnIdFMA, ZigLLVMFnIdFloatOp, ZigLLVMFnIdBswap, ZigLLVMFnIdBitReverse, }; // There are a bunch of places in code that rely on these values being in // exactly this order. enum AddSubMul { AddSubMulAdd = 0, AddSubMulSub = 1, AddSubMulMul = 2, }; struct ZigLLVMFnKey { ZigLLVMFnId id; union { struct { uint32_t bit_count; } ctz; struct { uint32_t bit_count; } clz; struct { uint32_t bit_count; } pop_count; struct { BuiltinFnId op; uint32_t bit_count; uint32_t vector_len; // 0 means not a vector } floating; struct { AddSubMul add_sub_mul; uint32_t bit_count; uint32_t vector_len; // 0 means not a vector bool is_signed; } overflow_arithmetic; struct { uint32_t bit_count; uint32_t vector_len; // 0 means not a vector } bswap; struct { uint32_t bit_count; } bit_reverse; } data; }; uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey); bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b); struct TimeEvent { double time; const char *name; }; enum BuildMode { BuildModeDebug, BuildModeFastRelease, BuildModeSafeRelease, BuildModeSmallRelease, }; enum CodeModel { CodeModelDefault, CodeModelTiny, CodeModelSmall, CodeModelKernel, CodeModelMedium, CodeModelLarge, }; struct LinkLib { Buf *name; Buf *path; ZigList symbols; // the list of symbols that we depend on from this lib bool provided_explicitly; }; enum ValgrindSupport { ValgrindSupportAuto, ValgrindSupportDisabled, ValgrindSupportEnabled, }; enum WantPIC { WantPICAuto, WantPICDisabled, WantPICEnabled, }; enum WantStackCheck { WantStackCheckAuto, WantStackCheckDisabled, WantStackCheckEnabled, }; enum WantCSanitize { WantCSanitizeAuto, WantCSanitizeDisabled, WantCSanitizeEnabled, }; enum OptionalBool { OptionalBoolNull, OptionalBoolFalse, OptionalBoolTrue, }; struct CFile { ZigList args; const char *source_path; const char *preprocessor_only_basename; }; // When adding fields, check if they should be added to the hash computation in build_with_cache struct CodeGen { // arena allocator destroyed just prior to codegen emit heap::ArenaAllocator *pass1_arena; //////////////////////////// Runtime State LLVMModuleRef module; ZigList errors; ErrorMsg *trace_err; LLVMBuilderRef builder; ZigLLVMDIBuilder *dbuilder; ZigLLVMDICompileUnit *compile_unit; ZigLLVMDIFile *compile_unit_file; LinkLib *libc_link_lib; LinkLib *libcpp_link_lib; LLVMTargetDataRef target_data_ref; LLVMTargetMachineRef target_machine; ZigLLVMDIFile *dummy_di_file; LLVMValueRef cur_ret_ptr; LLVMValueRef cur_frame_ptr; LLVMValueRef cur_fn_val; LLVMValueRef cur_async_switch_instr; LLVMValueRef cur_async_resume_index_ptr; LLVMValueRef cur_async_awaiter_ptr; LLVMBasicBlockRef cur_preamble_llvm_block; size_t cur_resume_block_count; LLVMValueRef cur_err_ret_trace_val_arg; LLVMValueRef cur_err_ret_trace_val_stack; LLVMValueRef cur_bad_not_suspended_index; LLVMValueRef memcpy_fn_val; LLVMValueRef memset_fn_val; LLVMValueRef trap_fn_val; LLVMValueRef return_address_fn_val; LLVMValueRef frame_address_fn_val; LLVMValueRef add_error_return_trace_addr_fn_val; LLVMValueRef stacksave_fn_val; LLVMValueRef stackrestore_fn_val; LLVMValueRef write_register_fn_val; LLVMValueRef merge_err_ret_traces_fn_val; LLVMValueRef sp_md_node; LLVMValueRef err_name_table; LLVMValueRef safety_crash_err_fn; LLVMValueRef return_err_fn; LLVMValueRef wasm_memory_size; LLVMValueRef wasm_memory_grow; LLVMTypeRef anyframe_fn_type; // reminder: hash tables must be initialized before use HashMap import_table; HashMap builtin_fn_table; HashMap primitive_type_table; HashMap type_table; HashMap fn_type_table; HashMap error_table; HashMap generic_table; HashMap memoized_fn_eval_table; HashMap llvm_fn_table; HashMap exported_symbol_names; HashMap external_symbol_names; HashMap string_literals_table; HashMap type_info_cache; HashMap one_possible_values; ZigList resolve_queue; size_t resolve_queue_index; ZigList timing_events; ZigList inline_fns; ZigList test_fns; ZigList errors_by_index; ZigList caches_to_release; size_t largest_err_name_len; ZigList type_resolve_stack; ZigPackage *std_package; ZigPackage *test_runner_package; ZigPackage *compile_var_package; ZigPackage *root_pkg; // @import("root") ZigPackage *main_pkg; // usually same as root_pkg, except for `zig test` ZigType *compile_var_import; ZigType *root_import; ZigType *start_import; struct { ZigType *entry_bool; ZigType *entry_c_int[CIntTypeCount]; ZigType *entry_c_longdouble; ZigType *entry_c_void; ZigType *entry_u8; ZigType *entry_u16; ZigType *entry_u32; ZigType *entry_u29; ZigType *entry_u64; ZigType *entry_i8; ZigType *entry_i32; ZigType *entry_i64; ZigType *entry_isize; ZigType *entry_usize; ZigType *entry_f16; ZigType *entry_f32; ZigType *entry_f64; ZigType *entry_f128; ZigType *entry_void; ZigType *entry_unreachable; ZigType *entry_type; ZigType *entry_invalid; ZigType *entry_block; ZigType *entry_num_lit_int; ZigType *entry_num_lit_float; ZigType *entry_undef; ZigType *entry_null; ZigType *entry_anytype; ZigType *entry_global_error_set; ZigType *entry_enum_literal; ZigType *entry_any_frame; } builtin_types; struct Intern { ZigValue x_undefined; ZigValue x_void; ZigValue x_null; ZigValue x_unreachable; ZigValue zero_byte; ZigValue *for_undefined(); ZigValue *for_void(); ZigValue *for_null(); ZigValue *for_unreachable(); ZigValue *for_zero_byte(); } intern; ZigType *align_amt_type; ZigType *stack_trace_type; ZigType *err_tag_type; ZigType *test_fn_type; Buf llvm_triple_str; Buf global_asm; Buf o_file_output_path; Buf bin_file_output_path; Buf asm_file_output_path; Buf llvm_ir_file_output_path; Buf *cache_dir; // As an input parameter, mutually exclusive with enable_cache. But it gets // populated in codegen_build_and_link. Buf *output_dir; Buf *c_artifact_dir; const char **libc_include_dir_list; size_t libc_include_dir_len; Buf *zig_c_headers_dir; // Cannot be overridden; derived from zig_lib_dir. Buf *zig_std_special_dir; // Cannot be overridden; derived from zig_lib_dir. IrInstSrc *invalid_inst_src; IrInstGen *invalid_inst_gen; IrInstGen *unreach_instruction; ZigValue panic_msg_vals[PanicMsgIdCount]; // The function definitions this module includes. ZigList fn_defs; size_t fn_defs_index; ZigList global_vars; ZigFn *cur_fn; ZigFn *panic_fn; ZigFn *largest_frame_fn; Stage2ProgressNode *main_progress_node; Stage2ProgressNode *sub_progress_node; WantPIC want_pic; WantStackCheck want_stack_check; WantCSanitize want_sanitize_c; CacheHash cache_hash; ErrColor err_color; uint32_t next_unresolved_index; unsigned pointer_size_bytes; uint32_t target_os_index; uint32_t target_arch_index; uint32_t target_sub_arch_index; uint32_t target_abi_index; uint32_t target_oformat_index; bool is_big_endian; bool have_c_main; bool have_winmain; bool have_wwinmain; bool have_winmain_crt_startup; bool have_wwinmain_crt_startup; bool have_dllmain_crt_startup; bool have_err_ret_tracing; bool link_eh_frame_hdr; bool c_want_stdint; bool c_want_stdbool; bool verbose_tokenize; bool verbose_ast; bool verbose_link; bool verbose_ir; bool verbose_llvm_ir; bool verbose_cimport; bool verbose_cc; bool verbose_llvm_cpu_features; bool error_during_imports; bool generate_error_name_table; bool enable_cache; // mutually exclusive with output_dir bool enable_time_report; bool enable_stack_report; bool system_linker_hack; bool reported_bad_link_libc_error; bool is_dynamic; // shared library rather than static library. dynamic musl rather than static musl. bool need_frame_size_prefix_data; bool disable_c_depfile; //////////////////////////// Participates in Input Parameter Cache Hash /////// Note: there is a separate cache hash for builtin.zig, when adding fields, /////// consider if they need to go into both. ZigList link_libs_list; // add -framework [name] args to linker ZigList darwin_frameworks; // add -rpath [name] args to linker ZigList rpath_list; ZigList forbidden_libs; ZigList link_objects; ZigList assembly_files; ZigList c_source_files; ZigList lib_dirs; ZigList framework_dirs; Stage2LibCInstallation *libc; size_t version_major; size_t version_minor; size_t version_patch; const char *linker_script; size_t stack_size_override; BuildMode build_mode; OutType out_type; const ZigTarget *zig_target; TargetSubsystem subsystem; // careful using this directly; see detect_subsystem ValgrindSupport valgrind_support; CodeModel code_model; OptionalBool linker_gc_sections; OptionalBool linker_allow_shlib_undefined; OptionalBool linker_bind_global_refs_locally; bool strip_debug_symbols; bool is_test_build; bool is_single_threaded; bool want_single_threaded; bool linker_rdynamic; bool each_lib_rpath; bool is_dummy_so; bool disable_gen_h; bool bundle_compiler_rt; 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 have_sanitize_c; bool function_sections; bool enable_dump_analysis; bool enable_doc_generation; bool emit_bin; bool emit_asm; bool emit_llvm_ir; bool test_is_evented; bool linker_z_nodelete; bool linker_z_defs; Buf *root_out_name; Buf *test_filter; Buf *test_name_prefix; Buf *zig_lib_dir; Buf *zig_std_dir; Buf *version_script_path; Buf *override_soname; Buf *linker_optimization; const char **llvm_argv; size_t llvm_argv_len; const char **clang_argv; size_t clang_argv_len; }; struct ZigVar { const char *name; ZigValue *const_value; ZigType *var_type; LLVMValueRef value_ref; IrInstSrc *is_comptime; IrInstGen *ptr_instruction; // which node is the declaration of the variable AstNode *decl_node; ZigLLVMDILocalVariable *di_loc_var; size_t src_arg_index; Scope *parent_scope; Scope *child_scope; LLVMValueRef param_value_ref; Buf *section_name; // In an inline loop, multiple variables may be created, // In this case, a reference to a variable should follow // this pointer to the redefined variable. ZigVar *next_var; ZigList export_list; uint32_t align_bytes; uint32_t ref_count; bool shadowable; bool src_is_const; bool gen_is_const; bool is_thread_local; bool is_comptime_memoized; bool is_comptime_memoized_value; bool did_the_decl_codegen; }; struct ErrorTableEntry { Buf name; uint32_t value; AstNode *decl_node; ErrorTableEntry *other; // null, or another error decl that was merged into this ZigType *set_with_only_this_in_it; // If we generate a constant error name value for this error, we memoize it here. // The type of this is array ZigValue *cached_error_name_val; }; enum ScopeId { ScopeIdDecls, ScopeIdBlock, ScopeIdDefer, ScopeIdDeferExpr, ScopeIdVarDecl, ScopeIdCImport, ScopeIdLoop, ScopeIdSuspend, ScopeIdFnDef, ScopeIdCompTime, ScopeIdRuntime, ScopeIdTypeOf, ScopeIdExpr, ScopeIdNoSuspend, }; struct Scope { CodeGen *codegen; AstNode *source_node; // if the scope has a parent, this is it Scope *parent; ZigLLVMDIScope *di_scope; ScopeId id; }; // This scope comes from global declarations or from // declarations in a container declaration // NodeTypeContainerDecl struct ScopeDecls { Scope base; HashMap decl_table; ZigList use_decls; AstNode *safety_set_node; AstNode *fast_math_set_node; ZigType *import; // If this is a scope from a container, this is the type entry, otherwise null ZigType *container_type; Buf *bare_name; bool safety_off; bool fast_math_on; bool any_imports_failed; }; enum LVal { LValNone, LValPtr, LValAssign, }; // This scope comes from a block expression in user code. // NodeTypeBlock struct ScopeBlock { Scope base; Buf *name; IrBasicBlockSrc *end_block; IrInstSrc *is_comptime; ResultLocPeerParent *peer_parent; ZigList *incoming_values; ZigList *incoming_blocks; AstNode *safety_set_node; AstNode *fast_math_set_node; LVal lval; bool safety_off; bool fast_math_on; }; // This scope is created from every defer expression. // It's the code following the defer statement. // NodeTypeDefer struct ScopeDefer { Scope base; }; // This scope is created from every defer expression. // It's the parent of the defer expression itself. // NodeTypeDefer struct ScopeDeferExpr { Scope base; bool reported_err; }; // This scope is created for every variable declaration inside an IrExecutable // NodeTypeVariableDeclaration, NodeTypeParamDecl struct ScopeVarDecl { Scope base; // The variable that creates this scope ZigVar *var; }; // This scope is created for a @cImport // NodeTypeFnCallExpr struct ScopeCImport { Scope base; Buf buf; }; // This scope is created for a loop such as for or while in order to // make break and continue statements work. // NodeTypeForExpr or NodeTypeWhileExpr struct ScopeLoop { Scope base; LVal lval; Buf *name; IrBasicBlockSrc *break_block; IrBasicBlockSrc *continue_block; IrInstSrc *is_comptime; ZigList *incoming_values; ZigList *incoming_blocks; ResultLocPeerParent *peer_parent; ScopeExpr *spill_scope; }; // This scope blocks certain things from working such as comptime continue // inside a runtime if expression. // NodeTypeIfBoolExpr, NodeTypeWhileExpr, NodeTypeForExpr struct ScopeRuntime { Scope base; IrInstSrc *is_comptime; }; // This scope is created for a suspend block in order to have labeled // suspend for breaking out of a suspend and for detecting if a suspend // block is inside a suspend block. struct ScopeSuspend { Scope base; bool reported_err; }; // This scope is created for a comptime expression. // NodeTypeCompTime, NodeTypeSwitchExpr struct ScopeCompTime { Scope base; }; // This scope is created for a nosuspend expression. // NodeTypeNoSuspend struct ScopeNoSuspend { Scope base; }; // This scope is created for a function definition. // NodeTypeFnDef struct ScopeFnDef { Scope base; ZigFn *fn_entry; }; // This scope is created for a @TypeOf. // All runtime side-effects are elided within it. // NodeTypeFnCallExpr struct ScopeTypeOf { Scope base; }; enum MemoizedBool { MemoizedBoolUnknown, MemoizedBoolFalse, MemoizedBoolTrue, }; // This scope is created for each expression. // It's used to identify when an instruction needs to be spilled, // so that it can be accessed after a suspend point. struct ScopeExpr { Scope base; ScopeExpr **children_ptr; size_t children_len; MemoizedBool need_spill; // This is a hack. I apologize for this, I need this to work so that I // can make progress on other fronts. I'll pay off this tech debt eventually. bool spill_harder; }; // synchronized with code in define_builtin_compile_vars enum AtomicOrder { AtomicOrderUnordered, AtomicOrderMonotonic, AtomicOrderAcquire, AtomicOrderRelease, AtomicOrderAcqRel, AtomicOrderSeqCst, }; // synchronized with the code in define_builtin_compile_vars enum AtomicRmwOp { AtomicRmwOp_xchg, AtomicRmwOp_add, AtomicRmwOp_sub, AtomicRmwOp_and, AtomicRmwOp_nand, AtomicRmwOp_or, AtomicRmwOp_xor, AtomicRmwOp_max, AtomicRmwOp_min, }; // A basic block contains no branching. Branches send control flow // to another basic block. // Phi instructions must be first in a basic block. // The last instruction in a basic block must be of type unreachable. struct IrBasicBlockSrc { ZigList instruction_list; IrBasicBlockGen *child; Scope *scope; const char *name_hint; IrInst *suspend_instruction_ref; uint32_t ref_count; uint32_t index; // index into the basic block list uint32_t debug_id; bool suspended; bool in_resume_stack; }; struct IrBasicBlockGen { ZigList instruction_list; Scope *scope; const char *name_hint; LLVMBasicBlockRef llvm_block; LLVMBasicBlockRef llvm_exit_block; // The instruction that referenced this basic block and caused us to // analyze the basic block. If the same instruction wants us to emit // the same basic block, then we re-generate it instead of saving it. IrInst *ref_instruction; // When this is non-null, a branch to this basic block is only allowed // if the branch is comptime. The instruction points to the reason // the basic block must be comptime. IrInst *must_be_comptime_source_instr; uint32_t debug_id; bool already_appended; }; // Src instructions are generated by ir_gen_* functions in ir.cpp from AST. // ir_analyze_* functions consume Src instructions and produce Gen instructions. // Src instructions do not have type information; Gen instructions do. enum IrInstSrcId { IrInstSrcIdInvalid, IrInstSrcIdDeclVar, IrInstSrcIdBr, IrInstSrcIdCondBr, IrInstSrcIdSwitchBr, IrInstSrcIdSwitchVar, IrInstSrcIdSwitchElseVar, IrInstSrcIdSwitchTarget, IrInstSrcIdPhi, IrInstSrcIdUnOp, IrInstSrcIdBinOp, IrInstSrcIdMergeErrSets, IrInstSrcIdLoadPtr, IrInstSrcIdStorePtr, IrInstSrcIdFieldPtr, IrInstSrcIdElemPtr, IrInstSrcIdVarPtr, IrInstSrcIdCall, IrInstSrcIdCallArgs, IrInstSrcIdCallExtra, IrInstSrcIdAsyncCallExtra, IrInstSrcIdConst, IrInstSrcIdReturn, IrInstSrcIdContainerInitList, IrInstSrcIdContainerInitFields, IrInstSrcIdUnreachable, IrInstSrcIdTypeOf, IrInstSrcIdSetCold, IrInstSrcIdSetRuntimeSafety, IrInstSrcIdSetFloatMode, IrInstSrcIdArrayType, IrInstSrcIdAnyFrameType, IrInstSrcIdSliceType, IrInstSrcIdAsm, IrInstSrcIdSizeOf, IrInstSrcIdTestNonNull, IrInstSrcIdOptionalUnwrapPtr, IrInstSrcIdClz, IrInstSrcIdCtz, IrInstSrcIdPopCount, IrInstSrcIdBswap, IrInstSrcIdBitReverse, IrInstSrcIdImport, IrInstSrcIdCImport, IrInstSrcIdCInclude, IrInstSrcIdCDefine, IrInstSrcIdCUndef, IrInstSrcIdRef, IrInstSrcIdCompileErr, IrInstSrcIdCompileLog, IrInstSrcIdErrName, IrInstSrcIdEmbedFile, IrInstSrcIdCmpxchg, IrInstSrcIdFence, IrInstSrcIdTruncate, IrInstSrcIdIntCast, IrInstSrcIdFloatCast, IrInstSrcIdIntToFloat, IrInstSrcIdFloatToInt, IrInstSrcIdBoolToInt, IrInstSrcIdVectorType, IrInstSrcIdShuffleVector, IrInstSrcIdSplat, IrInstSrcIdBoolNot, IrInstSrcIdMemset, IrInstSrcIdMemcpy, IrInstSrcIdSlice, IrInstSrcIdBreakpoint, IrInstSrcIdReturnAddress, IrInstSrcIdFrameAddress, IrInstSrcIdFrameHandle, IrInstSrcIdFrameType, IrInstSrcIdFrameSize, IrInstSrcIdAlignOf, IrInstSrcIdOverflowOp, IrInstSrcIdTestErr, IrInstSrcIdMulAdd, IrInstSrcIdFloatOp, IrInstSrcIdUnwrapErrCode, IrInstSrcIdUnwrapErrPayload, IrInstSrcIdFnProto, IrInstSrcIdTestComptime, IrInstSrcIdPtrCast, IrInstSrcIdBitCast, IrInstSrcIdIntToPtr, IrInstSrcIdPtrToInt, IrInstSrcIdIntToEnum, IrInstSrcIdEnumToInt, IrInstSrcIdIntToErr, IrInstSrcIdErrToInt, IrInstSrcIdCheckSwitchProngs, IrInstSrcIdCheckStatementIsVoid, IrInstSrcIdTypeName, IrInstSrcIdDeclRef, IrInstSrcIdPanic, IrInstSrcIdTagName, IrInstSrcIdTagType, IrInstSrcIdFieldParentPtr, IrInstSrcIdByteOffsetOf, IrInstSrcIdBitOffsetOf, IrInstSrcIdTypeInfo, IrInstSrcIdType, IrInstSrcIdHasField, IrInstSrcIdSetEvalBranchQuota, IrInstSrcIdPtrType, IrInstSrcIdAlignCast, IrInstSrcIdImplicitCast, IrInstSrcIdResolveResult, IrInstSrcIdResetResult, IrInstSrcIdOpaqueType, IrInstSrcIdSetAlignStack, IrInstSrcIdArgType, IrInstSrcIdExport, IrInstSrcIdErrorReturnTrace, IrInstSrcIdErrorUnion, IrInstSrcIdAtomicRmw, IrInstSrcIdAtomicLoad, IrInstSrcIdAtomicStore, IrInstSrcIdSaveErrRetAddr, IrInstSrcIdAddImplicitReturnType, IrInstSrcIdErrSetCast, IrInstSrcIdCheckRuntimeScope, IrInstSrcIdHasDecl, IrInstSrcIdUndeclaredIdent, IrInstSrcIdAlloca, IrInstSrcIdEndExpr, IrInstSrcIdUnionInitNamedField, IrInstSrcIdSuspendBegin, IrInstSrcIdSuspendFinish, IrInstSrcIdAwait, IrInstSrcIdResume, IrInstSrcIdSpillBegin, IrInstSrcIdSpillEnd, IrInstSrcIdWasmMemorySize, IrInstSrcIdWasmMemoryGrow, IrInstSrcIdSrc, }; // ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR. // Src instructions do not have type information; Gen instructions do. enum IrInstGenId { IrInstGenIdInvalid, IrInstGenIdDeclVar, IrInstGenIdBr, IrInstGenIdCondBr, IrInstGenIdSwitchBr, IrInstGenIdPhi, IrInstGenIdBinaryNot, IrInstGenIdNegation, IrInstGenIdNegationWrapping, IrInstGenIdBinOp, IrInstGenIdLoadPtr, IrInstGenIdStorePtr, IrInstGenIdVectorStoreElem, IrInstGenIdStructFieldPtr, IrInstGenIdUnionFieldPtr, IrInstGenIdElemPtr, IrInstGenIdVarPtr, IrInstGenIdReturnPtr, IrInstGenIdCall, IrInstGenIdReturn, IrInstGenIdCast, IrInstGenIdUnreachable, IrInstGenIdAsm, IrInstGenIdTestNonNull, IrInstGenIdOptionalUnwrapPtr, IrInstGenIdOptionalWrap, IrInstGenIdUnionTag, IrInstGenIdClz, IrInstGenIdCtz, IrInstGenIdPopCount, IrInstGenIdBswap, IrInstGenIdBitReverse, IrInstGenIdRef, IrInstGenIdErrName, IrInstGenIdCmpxchg, IrInstGenIdFence, IrInstGenIdTruncate, IrInstGenIdShuffleVector, IrInstGenIdSplat, IrInstGenIdBoolNot, IrInstGenIdMemset, IrInstGenIdMemcpy, IrInstGenIdSlice, IrInstGenIdBreakpoint, IrInstGenIdReturnAddress, IrInstGenIdFrameAddress, IrInstGenIdFrameHandle, IrInstGenIdFrameSize, IrInstGenIdOverflowOp, IrInstGenIdTestErr, IrInstGenIdMulAdd, IrInstGenIdFloatOp, IrInstGenIdUnwrapErrCode, IrInstGenIdUnwrapErrPayload, IrInstGenIdErrWrapCode, IrInstGenIdErrWrapPayload, IrInstGenIdPtrCast, IrInstGenIdBitCast, IrInstGenIdWidenOrShorten, IrInstGenIdIntToPtr, IrInstGenIdPtrToInt, IrInstGenIdIntToEnum, IrInstGenIdIntToErr, IrInstGenIdErrToInt, IrInstGenIdPanic, IrInstGenIdTagName, IrInstGenIdFieldParentPtr, IrInstGenIdAlignCast, IrInstGenIdErrorReturnTrace, IrInstGenIdAtomicRmw, IrInstGenIdAtomicLoad, IrInstGenIdAtomicStore, IrInstGenIdSaveErrRetAddr, IrInstGenIdVectorToArray, IrInstGenIdArrayToVector, IrInstGenIdAssertZero, IrInstGenIdAssertNonNull, IrInstGenIdPtrOfArrayToSlice, IrInstGenIdSuspendBegin, IrInstGenIdSuspendFinish, IrInstGenIdAwait, IrInstGenIdResume, IrInstGenIdSpillBegin, IrInstGenIdSpillEnd, IrInstGenIdVectorExtractElem, IrInstGenIdAlloca, IrInstGenIdConst, IrInstGenIdWasmMemorySize, IrInstGenIdWasmMemoryGrow, }; // Common fields between IrInstSrc and IrInstGen. This allows future passes // after pass2 to be added to zig. struct IrInst { // if ref_count is zero and the instruction has no side effects, // the instruction can be omitted in codegen uint32_t ref_count; uint32_t debug_id; Scope *scope; AstNode *source_node; // for debugging purposes, these are useful to call to inspect the instruction void dump(); void src(); }; struct IrInstSrc { IrInst base; IrInstSrcId id; // true if this instruction was generated by zig and not from user code // this matters for the "unreachable code" compile error bool is_gen; bool is_noreturn; // When analyzing IR, instructions that point to this instruction in the "old ir" // can find the instruction that corresponds to this value in the "new ir" // with this child field. IrInstGen *child; IrBasicBlockSrc *owner_bb; // for debugging purposes, these are useful to call to inspect the instruction void dump(); void src(); }; struct IrInstGen { IrInst base; IrInstGenId id; LLVMValueRef llvm_value; ZigValue *value; IrBasicBlockGen *owner_bb; // Nearly any instruction can have to be stored as a local variable before suspending // and then loaded after resuming, in case there is an expression with a suspend point // in it, such as: x + await y IrInstGen *spill; // for debugging purposes, these are useful to call to inspect the instruction void dump(); void src(); }; struct IrInstSrcDeclVar { IrInstSrc base; ZigVar *var; IrInstSrc *var_type; IrInstSrc *align_value; IrInstSrc *ptr; }; struct IrInstGenDeclVar { IrInstGen base; ZigVar *var; IrInstGen *var_ptr; }; struct IrInstSrcCondBr { IrInstSrc base; IrInstSrc *condition; IrBasicBlockSrc *then_block; IrBasicBlockSrc *else_block; IrInstSrc *is_comptime; ResultLoc *result_loc; }; struct IrInstGenCondBr { IrInstGen base; IrInstGen *condition; IrBasicBlockGen *then_block; IrBasicBlockGen *else_block; }; struct IrInstSrcBr { IrInstSrc base; IrBasicBlockSrc *dest_block; IrInstSrc *is_comptime; }; struct IrInstGenBr { IrInstGen base; IrBasicBlockGen *dest_block; }; struct IrInstSrcSwitchBrCase { IrInstSrc *value; IrBasicBlockSrc *block; }; struct IrInstSrcSwitchBr { IrInstSrc base; IrInstSrc *target_value; IrBasicBlockSrc *else_block; size_t case_count; IrInstSrcSwitchBrCase *cases; IrInstSrc *is_comptime; IrInstSrc *switch_prongs_void; }; struct IrInstGenSwitchBrCase { IrInstGen *value; IrBasicBlockGen *block; }; struct IrInstGenSwitchBr { IrInstGen base; IrInstGen *target_value; IrBasicBlockGen *else_block; size_t case_count; IrInstGenSwitchBrCase *cases; }; struct IrInstSrcSwitchVar { IrInstSrc base; IrInstSrc *target_value_ptr; IrInstSrc **prongs_ptr; size_t prongs_len; }; struct IrInstSrcSwitchElseVar { IrInstSrc base; IrInstSrc *target_value_ptr; IrInstSrcSwitchBr *switch_br; }; struct IrInstSrcSwitchTarget { IrInstSrc base; IrInstSrc *target_value_ptr; }; struct IrInstSrcPhi { IrInstSrc base; size_t incoming_count; IrBasicBlockSrc **incoming_blocks; IrInstSrc **incoming_values; ResultLocPeerParent *peer_parent; }; struct IrInstGenPhi { IrInstGen base; size_t incoming_count; IrBasicBlockGen **incoming_blocks; IrInstGen **incoming_values; }; enum IrUnOp { IrUnOpInvalid, IrUnOpBinNot, IrUnOpNegation, IrUnOpNegationWrap, IrUnOpDereference, IrUnOpOptional, }; struct IrInstSrcUnOp { IrInstSrc base; IrUnOp op_id; LVal lval; IrInstSrc *value; ResultLoc *result_loc; }; struct IrInstGenBinaryNot { IrInstGen base; IrInstGen *operand; }; struct IrInstGenNegation { IrInstGen base; IrInstGen *operand; }; struct IrInstGenNegationWrapping { IrInstGen base; IrInstGen *operand; }; enum IrBinOp { IrBinOpInvalid, IrBinOpBoolOr, IrBinOpBoolAnd, IrBinOpCmpEq, IrBinOpCmpNotEq, IrBinOpCmpLessThan, IrBinOpCmpGreaterThan, IrBinOpCmpLessOrEq, IrBinOpCmpGreaterOrEq, IrBinOpBinOr, IrBinOpBinXor, IrBinOpBinAnd, IrBinOpBitShiftLeftLossy, IrBinOpBitShiftLeftExact, IrBinOpBitShiftRightLossy, IrBinOpBitShiftRightExact, IrBinOpAdd, IrBinOpAddWrap, IrBinOpSub, IrBinOpSubWrap, IrBinOpMult, IrBinOpMultWrap, IrBinOpDivUnspecified, IrBinOpDivExact, IrBinOpDivTrunc, IrBinOpDivFloor, IrBinOpRemUnspecified, IrBinOpRemRem, IrBinOpRemMod, IrBinOpArrayCat, IrBinOpArrayMult, }; struct IrInstSrcBinOp { IrInstSrc base; IrInstSrc *op1; IrInstSrc *op2; IrBinOp op_id; bool safety_check_on; }; struct IrInstGenBinOp { IrInstGen base; IrInstGen *op1; IrInstGen *op2; IrBinOp op_id; bool safety_check_on; }; struct IrInstSrcMergeErrSets { IrInstSrc base; IrInstSrc *op1; IrInstSrc *op2; Buf *type_name; }; struct IrInstSrcLoadPtr { IrInstSrc base; IrInstSrc *ptr; }; struct IrInstGenLoadPtr { IrInstGen base; IrInstGen *ptr; IrInstGen *result_loc; }; struct IrInstSrcStorePtr { IrInstSrc base; IrInstSrc *ptr; IrInstSrc *value; bool allow_write_through_const; }; struct IrInstGenStorePtr { IrInstGen base; IrInstGen *ptr; IrInstGen *value; }; struct IrInstGenVectorStoreElem { IrInstGen base; IrInstGen *vector_ptr; IrInstGen *index; IrInstGen *value; }; struct IrInstSrcFieldPtr { IrInstSrc base; IrInstSrc *container_ptr; Buf *field_name_buffer; IrInstSrc *field_name_expr; bool initializing; }; struct IrInstGenStructFieldPtr { IrInstGen base; IrInstGen *struct_ptr; TypeStructField *field; bool is_const; }; struct IrInstGenUnionFieldPtr { IrInstGen base; IrInstGen *union_ptr; TypeUnionField *field; bool safety_check_on; bool initializing; }; struct IrInstSrcElemPtr { IrInstSrc base; IrInstSrc *array_ptr; IrInstSrc *elem_index; AstNode *init_array_type_source_node; PtrLen ptr_len; bool safety_check_on; }; struct IrInstGenElemPtr { IrInstGen base; IrInstGen *array_ptr; IrInstGen *elem_index; bool safety_check_on; }; struct IrInstSrcVarPtr { IrInstSrc base; ZigVar *var; ScopeFnDef *crossed_fndef_scope; }; struct IrInstGenVarPtr { IrInstGen base; ZigVar *var; }; // 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 IrInstGenReturnPtr { IrInstGen base; }; struct IrInstSrcCall { IrInstSrc base; IrInstSrc *fn_ref; ZigFn *fn_entry; size_t arg_count; IrInstSrc **args; IrInstSrc *ret_ptr; ResultLoc *result_loc; IrInstSrc *new_stack; CallModifier modifier; bool is_async_call_builtin; }; // This is a pass1 instruction, used by @call when the args node is // a tuple or struct literal. struct IrInstSrcCallArgs { IrInstSrc base; IrInstSrc *options; IrInstSrc *fn_ref; IrInstSrc **args_ptr; size_t args_len; ResultLoc *result_loc; }; // This is a pass1 instruction, used by @call, when the args node // is not a literal. // `args` is expected to be either a struct or a tuple. struct IrInstSrcCallExtra { IrInstSrc base; IrInstSrc *options; IrInstSrc *fn_ref; IrInstSrc *args; ResultLoc *result_loc; }; // This is a pass1 instruction, used by @asyncCall, when the args node // is not a literal. // `args` is expected to be either a struct or a tuple. struct IrInstSrcAsyncCallExtra { IrInstSrc base; CallModifier modifier; IrInstSrc *fn_ref; IrInstSrc *ret_ptr; IrInstSrc *new_stack; IrInstSrc *args; ResultLoc *result_loc; }; struct IrInstGenCall { IrInstGen base; IrInstGen *fn_ref; ZigFn *fn_entry; size_t arg_count; IrInstGen **args; IrInstGen *result_loc; IrInstGen *frame_result_loc; IrInstGen *new_stack; CallModifier modifier; bool is_async_call_builtin; }; struct IrInstSrcConst { IrInstSrc base; ZigValue *value; }; struct IrInstGenConst { IrInstGen base; }; struct IrInstSrcReturn { IrInstSrc base; IrInstSrc *operand; }; // When an IrExecutable is not in a function, a return instruction means that // the expression returns with that value, even though a return statement from // an AST perspective is invalid. struct IrInstGenReturn { IrInstGen base; IrInstGen *operand; }; enum CastOp { CastOpNoCast, // signifies the function call expression is not a cast CastOpNoop, // fn call expr is a cast, but does nothing CastOpIntToFloat, CastOpFloatToInt, CastOpBoolToInt, CastOpNumLitToConcrete, CastOpErrSet, CastOpBitCast, }; // TODO get rid of this instruction, replace with instructions for each op code struct IrInstGenCast { IrInstGen base; IrInstGen *value; CastOp cast_op; }; struct IrInstSrcContainerInitList { IrInstSrc base; IrInstSrc *elem_type; size_t item_count; IrInstSrc **elem_result_loc_list; IrInstSrc *result_loc; AstNode *init_array_type_source_node; }; struct IrInstSrcContainerInitFieldsField { Buf *name; AstNode *source_node; IrInstSrc *result_loc; }; struct IrInstSrcContainerInitFields { IrInstSrc base; size_t field_count; IrInstSrcContainerInitFieldsField *fields; IrInstSrc *result_loc; }; struct IrInstSrcUnreachable { IrInstSrc base; }; struct IrInstGenUnreachable { IrInstGen base; }; struct IrInstSrcTypeOf { IrInstSrc base; union { IrInstSrc *scalar; // value_count == 1 IrInstSrc **list; // value_count > 1 } value; size_t value_count; }; struct IrInstSrcSetCold { IrInstSrc base; IrInstSrc *is_cold; }; struct IrInstSrcSetRuntimeSafety { IrInstSrc base; IrInstSrc *safety_on; }; struct IrInstSrcSetFloatMode { IrInstSrc base; IrInstSrc *scope_value; IrInstSrc *mode_value; }; struct IrInstSrcArrayType { IrInstSrc base; IrInstSrc *size; IrInstSrc *sentinel; IrInstSrc *child_type; }; struct IrInstSrcPtrType { IrInstSrc base; IrInstSrc *sentinel; IrInstSrc *align_value; IrInstSrc *child_type; uint32_t bit_offset_start; uint32_t host_int_bytes; PtrLen ptr_len; bool is_const; bool is_volatile; bool is_allow_zero; }; struct IrInstSrcAnyFrameType { IrInstSrc base; IrInstSrc *payload_type; }; struct IrInstSrcSliceType { IrInstSrc base; IrInstSrc *sentinel; IrInstSrc *align_value; IrInstSrc *child_type; bool is_const; bool is_volatile; bool is_allow_zero; }; struct IrInstSrcAsm { IrInstSrc base; IrInstSrc *asm_template; IrInstSrc **input_list; IrInstSrc **output_types; ZigVar **output_vars; size_t return_count; bool has_side_effects; bool is_global; }; struct IrInstGenAsm { IrInstGen base; Buf *asm_template; AsmToken *token_list; size_t token_list_len; IrInstGen **input_list; IrInstGen **output_types; ZigVar **output_vars; size_t return_count; bool has_side_effects; }; struct IrInstSrcSizeOf { IrInstSrc base; IrInstSrc *type_value; bool bit_size; }; // returns true if nonnull, returns false if null struct IrInstSrcTestNonNull { IrInstSrc base; IrInstSrc *value; }; struct IrInstGenTestNonNull { IrInstGen base; IrInstGen *value; }; // Takes a pointer to an optional value, returns a pointer // to the payload. struct IrInstSrcOptionalUnwrapPtr { IrInstSrc base; IrInstSrc *base_ptr; bool safety_check_on; }; struct IrInstGenOptionalUnwrapPtr { IrInstGen base; IrInstGen *base_ptr; bool safety_check_on; bool initializing; }; struct IrInstSrcCtz { IrInstSrc base; IrInstSrc *type; IrInstSrc *op; }; struct IrInstGenCtz { IrInstGen base; IrInstGen *op; }; struct IrInstSrcClz { IrInstSrc base; IrInstSrc *type; IrInstSrc *op; }; struct IrInstGenClz { IrInstGen base; IrInstGen *op; }; struct IrInstSrcPopCount { IrInstSrc base; IrInstSrc *type; IrInstSrc *op; }; struct IrInstGenPopCount { IrInstGen base; IrInstGen *op; }; struct IrInstGenUnionTag { IrInstGen base; IrInstGen *value; }; struct IrInstSrcImport { IrInstSrc base; IrInstSrc *name; }; struct IrInstSrcRef { IrInstSrc base; IrInstSrc *value; }; struct IrInstGenRef { IrInstGen base; IrInstGen *operand; IrInstGen *result_loc; }; struct IrInstSrcCompileErr { IrInstSrc base; IrInstSrc *msg; }; struct IrInstSrcCompileLog { IrInstSrc base; size_t msg_count; IrInstSrc **msg_list; }; struct IrInstSrcErrName { IrInstSrc base; IrInstSrc *value; }; struct IrInstGenErrName { IrInstGen base; IrInstGen *value; }; struct IrInstSrcCImport { IrInstSrc base; }; struct IrInstSrcCInclude { IrInstSrc base; IrInstSrc *name; }; struct IrInstSrcCDefine { IrInstSrc base; IrInstSrc *name; IrInstSrc *value; }; struct IrInstSrcCUndef { IrInstSrc base; IrInstSrc *name; }; struct IrInstSrcEmbedFile { IrInstSrc base; IrInstSrc *name; }; struct IrInstSrcCmpxchg { IrInstSrc base; bool is_weak; IrInstSrc *type_value; IrInstSrc *ptr; IrInstSrc *cmp_value; IrInstSrc *new_value; IrInstSrc *success_order_value; IrInstSrc *failure_order_value; ResultLoc *result_loc; }; struct IrInstGenCmpxchg { IrInstGen base; AtomicOrder success_order; AtomicOrder failure_order; IrInstGen *ptr; IrInstGen *cmp_value; IrInstGen *new_value; IrInstGen *result_loc; bool is_weak; }; struct IrInstSrcFence { IrInstSrc base; IrInstSrc *order; }; struct IrInstGenFence { IrInstGen base; AtomicOrder order; }; struct IrInstSrcTruncate { IrInstSrc base; IrInstSrc *dest_type; IrInstSrc *target; }; struct IrInstGenTruncate { IrInstGen base; IrInstGen *target; }; struct IrInstSrcIntCast { IrInstSrc base; IrInstSrc *dest_type; IrInstSrc *target; }; struct IrInstSrcFloatCast { IrInstSrc base; IrInstSrc *dest_type; IrInstSrc *target; }; struct IrInstSrcErrSetCast { IrInstSrc base; IrInstSrc *dest_type; IrInstSrc *target; }; struct IrInstSrcIntToFloat { IrInstSrc base; IrInstSrc *dest_type; IrInstSrc *target; }; struct IrInstSrcFloatToInt { IrInstSrc base; IrInstSrc *dest_type; IrInstSrc *target; }; struct IrInstSrcBoolToInt { IrInstSrc base; IrInstSrc *target; }; struct IrInstSrcVectorType { IrInstSrc base; IrInstSrc *len; IrInstSrc *elem_type; }; struct IrInstSrcBoolNot { IrInstSrc base; IrInstSrc *value; }; struct IrInstGenBoolNot { IrInstGen base; IrInstGen *value; }; struct IrInstSrcMemset { IrInstSrc base; IrInstSrc *dest_ptr; IrInstSrc *byte; IrInstSrc *count; }; struct IrInstGenMemset { IrInstGen base; IrInstGen *dest_ptr; IrInstGen *byte; IrInstGen *count; }; struct IrInstSrcMemcpy { IrInstSrc base; IrInstSrc *dest_ptr; IrInstSrc *src_ptr; IrInstSrc *count; }; struct IrInstGenMemcpy { IrInstGen base; IrInstGen *dest_ptr; IrInstGen *src_ptr; IrInstGen *count; }; struct IrInstSrcWasmMemorySize { IrInstSrc base; IrInstSrc *index; }; struct IrInstGenWasmMemorySize { IrInstGen base; IrInstGen *index; }; struct IrInstSrcWasmMemoryGrow { IrInstSrc base; IrInstSrc *index; IrInstSrc *delta; }; struct IrInstGenWasmMemoryGrow { IrInstGen base; IrInstGen *index; IrInstGen *delta; }; struct IrInstSrcSrc { IrInstSrc base; }; struct IrInstSrcSlice { IrInstSrc base; IrInstSrc *ptr; IrInstSrc *start; IrInstSrc *end; IrInstSrc *sentinel; ResultLoc *result_loc; bool safety_check_on; }; struct IrInstGenSlice { IrInstGen base; IrInstGen *ptr; IrInstGen *start; IrInstGen *end; IrInstGen *result_loc; ZigValue *sentinel; bool safety_check_on; }; struct IrInstSrcBreakpoint { IrInstSrc base; }; struct IrInstGenBreakpoint { IrInstGen base; }; struct IrInstSrcReturnAddress { IrInstSrc base; }; struct IrInstGenReturnAddress { IrInstGen base; }; struct IrInstSrcFrameAddress { IrInstSrc base; }; struct IrInstGenFrameAddress { IrInstGen base; }; struct IrInstSrcFrameHandle { IrInstSrc base; }; struct IrInstGenFrameHandle { IrInstGen base; }; struct IrInstSrcFrameType { IrInstSrc base; IrInstSrc *fn; }; struct IrInstSrcFrameSize { IrInstSrc base; IrInstSrc *fn; }; struct IrInstGenFrameSize { IrInstGen base; IrInstGen *fn; }; enum IrOverflowOp { IrOverflowOpAdd, IrOverflowOpSub, IrOverflowOpMul, IrOverflowOpShl, }; struct IrInstSrcOverflowOp { IrInstSrc base; IrOverflowOp op; IrInstSrc *type_value; IrInstSrc *op1; IrInstSrc *op2; IrInstSrc *result_ptr; }; struct IrInstGenOverflowOp { IrInstGen base; IrOverflowOp op; IrInstGen *op1; IrInstGen *op2; IrInstGen *result_ptr; // TODO can this field be removed? ZigType *result_ptr_type; }; struct IrInstSrcMulAdd { IrInstSrc base; IrInstSrc *type_value; IrInstSrc *op1; IrInstSrc *op2; IrInstSrc *op3; }; struct IrInstGenMulAdd { IrInstGen base; IrInstGen *op1; IrInstGen *op2; IrInstGen *op3; }; struct IrInstSrcAlignOf { IrInstSrc base; IrInstSrc *type_value; }; // returns true if error, returns false if not error struct IrInstSrcTestErr { IrInstSrc base; IrInstSrc *base_ptr; bool resolve_err_set; bool base_ptr_is_payload; }; struct IrInstGenTestErr { IrInstGen base; IrInstGen *err_union; }; // Takes an error union pointer, returns a pointer to the error code. struct IrInstSrcUnwrapErrCode { IrInstSrc base; IrInstSrc *err_union_ptr; bool initializing; }; struct IrInstGenUnwrapErrCode { IrInstGen base; IrInstGen *err_union_ptr; bool initializing; }; struct IrInstSrcUnwrapErrPayload { IrInstSrc base; IrInstSrc *value; bool safety_check_on; bool initializing; }; struct IrInstGenUnwrapErrPayload { IrInstGen base; IrInstGen *value; bool safety_check_on; bool initializing; }; struct IrInstGenOptionalWrap { IrInstGen base; IrInstGen *operand; IrInstGen *result_loc; }; struct IrInstGenErrWrapPayload { IrInstGen base; IrInstGen *operand; IrInstGen *result_loc; }; struct IrInstGenErrWrapCode { IrInstGen base; IrInstGen *operand; IrInstGen *result_loc; }; struct IrInstSrcFnProto { IrInstSrc base; IrInstSrc **param_types; IrInstSrc *align_value; IrInstSrc *callconv_value; IrInstSrc *return_type; bool is_var_args; }; // true if the target value is compile time known, false otherwise struct IrInstSrcTestComptime { IrInstSrc base; IrInstSrc *value; }; struct IrInstSrcPtrCast { IrInstSrc base; IrInstSrc *dest_type; IrInstSrc *ptr; bool safety_check_on; }; struct IrInstGenPtrCast { IrInstGen base; IrInstGen *ptr; bool safety_check_on; }; struct IrInstSrcImplicitCast { IrInstSrc base; IrInstSrc *operand; ResultLocCast *result_loc_cast; }; struct IrInstSrcBitCast { IrInstSrc base; IrInstSrc *operand; ResultLocBitCast *result_loc_bit_cast; }; struct IrInstGenBitCast { IrInstGen base; IrInstGen *operand; }; struct IrInstGenWidenOrShorten { IrInstGen base; IrInstGen *target; }; struct IrInstSrcPtrToInt { IrInstSrc base; IrInstSrc *target; }; struct IrInstGenPtrToInt { IrInstGen base; IrInstGen *target; }; struct IrInstSrcIntToPtr { IrInstSrc base; IrInstSrc *dest_type; IrInstSrc *target; }; struct IrInstGenIntToPtr { IrInstGen base; IrInstGen *target; }; struct IrInstSrcIntToEnum { IrInstSrc base; IrInstSrc *dest_type; IrInstSrc *target; }; struct IrInstGenIntToEnum { IrInstGen base; IrInstGen *target; }; struct IrInstSrcEnumToInt { IrInstSrc base; IrInstSrc *target; }; struct IrInstSrcIntToErr { IrInstSrc base; IrInstSrc *target; }; struct IrInstGenIntToErr { IrInstGen base; IrInstGen *target; }; struct IrInstSrcErrToInt { IrInstSrc base; IrInstSrc *target; }; struct IrInstGenErrToInt { IrInstGen base; IrInstGen *target; }; struct IrInstSrcCheckSwitchProngsRange { IrInstSrc *start; IrInstSrc *end; }; struct IrInstSrcCheckSwitchProngs { IrInstSrc base; IrInstSrc *target_value; IrInstSrcCheckSwitchProngsRange *ranges; size_t range_count; bool have_else_prong; bool have_underscore_prong; }; struct IrInstSrcCheckStatementIsVoid { IrInstSrc base; IrInstSrc *statement_value; }; struct IrInstSrcTypeName { IrInstSrc base; IrInstSrc *type_value; }; struct IrInstSrcDeclRef { IrInstSrc base; LVal lval; Tld *tld; }; struct IrInstSrcPanic { IrInstSrc base; IrInstSrc *msg; }; struct IrInstGenPanic { IrInstGen base; IrInstGen *msg; }; struct IrInstSrcTagName { IrInstSrc base; IrInstSrc *target; }; struct IrInstGenTagName { IrInstGen base; IrInstGen *target; }; struct IrInstSrcTagType { IrInstSrc base; IrInstSrc *target; }; struct IrInstSrcFieldParentPtr { IrInstSrc base; IrInstSrc *type_value; IrInstSrc *field_name; IrInstSrc *field_ptr; }; struct IrInstGenFieldParentPtr { IrInstGen base; IrInstGen *field_ptr; TypeStructField *field; }; struct IrInstSrcByteOffsetOf { IrInstSrc base; IrInstSrc *type_value; IrInstSrc *field_name; }; struct IrInstSrcBitOffsetOf { IrInstSrc base; IrInstSrc *type_value; IrInstSrc *field_name; }; struct IrInstSrcTypeInfo { IrInstSrc base; IrInstSrc *type_value; }; struct IrInstSrcType { IrInstSrc base; IrInstSrc *type_info; }; struct IrInstSrcHasField { IrInstSrc base; IrInstSrc *container_type; IrInstSrc *field_name; }; struct IrInstSrcSetEvalBranchQuota { IrInstSrc base; IrInstSrc *new_quota; }; struct IrInstSrcAlignCast { IrInstSrc base; IrInstSrc *align_bytes; IrInstSrc *target; }; struct IrInstGenAlignCast { IrInstGen base; IrInstGen *target; }; struct IrInstSrcOpaqueType { IrInstSrc base; }; struct IrInstSrcSetAlignStack { IrInstSrc base; IrInstSrc *align_bytes; }; struct IrInstSrcArgType { IrInstSrc base; IrInstSrc *fn_type; IrInstSrc *arg_index; bool allow_var; }; struct IrInstSrcExport { IrInstSrc base; IrInstSrc *target; IrInstSrc *options; }; enum IrInstErrorReturnTraceOptional { IrInstErrorReturnTraceNull, IrInstErrorReturnTraceNonNull, }; struct IrInstSrcErrorReturnTrace { IrInstSrc base; IrInstErrorReturnTraceOptional optional; }; struct IrInstGenErrorReturnTrace { IrInstGen base; IrInstErrorReturnTraceOptional optional; }; struct IrInstSrcErrorUnion { IrInstSrc base; IrInstSrc *err_set; IrInstSrc *payload; Buf *type_name; }; struct IrInstSrcAtomicRmw { IrInstSrc base; IrInstSrc *operand_type; IrInstSrc *ptr; IrInstSrc *op; IrInstSrc *operand; IrInstSrc *ordering; }; struct IrInstGenAtomicRmw { IrInstGen base; IrInstGen *ptr; IrInstGen *operand; AtomicRmwOp op; AtomicOrder ordering; }; struct IrInstSrcAtomicLoad { IrInstSrc base; IrInstSrc *operand_type; IrInstSrc *ptr; IrInstSrc *ordering; }; struct IrInstGenAtomicLoad { IrInstGen base; IrInstGen *ptr; AtomicOrder ordering; }; struct IrInstSrcAtomicStore { IrInstSrc base; IrInstSrc *operand_type; IrInstSrc *ptr; IrInstSrc *value; IrInstSrc *ordering; }; struct IrInstGenAtomicStore { IrInstGen base; IrInstGen *ptr; IrInstGen *value; AtomicOrder ordering; }; struct IrInstSrcSaveErrRetAddr { IrInstSrc base; }; struct IrInstGenSaveErrRetAddr { IrInstGen base; }; struct IrInstSrcAddImplicitReturnType { IrInstSrc base; IrInstSrc *value; ResultLocReturn *result_loc_ret; }; // For float ops that take a single argument struct IrInstSrcFloatOp { IrInstSrc base; IrInstSrc *operand; BuiltinFnId fn_id; }; struct IrInstGenFloatOp { IrInstGen base; IrInstGen *operand; BuiltinFnId fn_id; }; struct IrInstSrcCheckRuntimeScope { IrInstSrc base; IrInstSrc *scope_is_comptime; IrInstSrc *is_comptime; }; struct IrInstSrcBswap { IrInstSrc base; IrInstSrc *type; IrInstSrc *op; }; struct IrInstGenBswap { IrInstGen base; IrInstGen *op; }; struct IrInstSrcBitReverse { IrInstSrc base; IrInstSrc *type; IrInstSrc *op; }; struct IrInstGenBitReverse { IrInstGen base; IrInstGen *op; }; struct IrInstGenArrayToVector { IrInstGen base; IrInstGen *array; }; struct IrInstGenVectorToArray { IrInstGen base; IrInstGen *vector; IrInstGen *result_loc; }; struct IrInstSrcShuffleVector { IrInstSrc base; IrInstSrc *scalar_type; IrInstSrc *a; IrInstSrc *b; IrInstSrc *mask; // This is in zig-format, not llvm format }; struct IrInstGenShuffleVector { IrInstGen base; IrInstGen *a; IrInstGen *b; IrInstGen *mask; // This is in zig-format, not llvm format }; struct IrInstSrcSplat { IrInstSrc base; IrInstSrc *len; IrInstSrc *scalar; }; struct IrInstGenSplat { IrInstGen base; IrInstGen *scalar; }; struct IrInstGenAssertZero { IrInstGen base; IrInstGen *target; }; struct IrInstGenAssertNonNull { IrInstGen base; IrInstGen *target; }; struct IrInstSrcUnionInitNamedField { IrInstSrc base; IrInstSrc *union_type; IrInstSrc *field_name; IrInstSrc *field_result_loc; IrInstSrc *result_loc; }; struct IrInstSrcHasDecl { IrInstSrc base; IrInstSrc *container; IrInstSrc *name; }; struct IrInstSrcUndeclaredIdent { IrInstSrc base; Buf *name; }; struct IrInstSrcAlloca { IrInstSrc base; IrInstSrc *align; IrInstSrc *is_comptime; const char *name_hint; }; struct IrInstGenAlloca { IrInstGen base; uint32_t align; const char *name_hint; size_t field_index; }; struct IrInstSrcEndExpr { IrInstSrc base; IrInstSrc *value; ResultLoc *result_loc; }; // This one is for writing through the result pointer. struct IrInstSrcResolveResult { IrInstSrc base; ResultLoc *result_loc; IrInstSrc *ty; }; struct IrInstSrcResetResult { IrInstSrc base; ResultLoc *result_loc; }; struct IrInstGenPtrOfArrayToSlice { IrInstGen base; IrInstGen *operand; IrInstGen *result_loc; }; struct IrInstSrcSuspendBegin { IrInstSrc base; }; struct IrInstGenSuspendBegin { IrInstGen base; LLVMBasicBlockRef resume_bb; }; struct IrInstSrcSuspendFinish { IrInstSrc base; IrInstSrcSuspendBegin *begin; }; struct IrInstGenSuspendFinish { IrInstGen base; IrInstGenSuspendBegin *begin; }; struct IrInstSrcAwait { IrInstSrc base; IrInstSrc *frame; ResultLoc *result_loc; bool is_nosuspend; }; struct IrInstGenAwait { IrInstGen base; IrInstGen *frame; IrInstGen *result_loc; ZigFn *target_fn; bool is_nosuspend; }; struct IrInstSrcResume { IrInstSrc base; IrInstSrc *frame; }; struct IrInstGenResume { IrInstGen base; IrInstGen *frame; }; enum SpillId { SpillIdInvalid, SpillIdRetErrCode, }; struct IrInstSrcSpillBegin { IrInstSrc base; IrInstSrc *operand; SpillId spill_id; }; struct IrInstGenSpillBegin { IrInstGen base; SpillId spill_id; IrInstGen *operand; }; struct IrInstSrcSpillEnd { IrInstSrc base; IrInstSrcSpillBegin *begin; }; struct IrInstGenSpillEnd { IrInstGen base; IrInstGenSpillBegin *begin; }; struct IrInstGenVectorExtractElem { IrInstGen base; IrInstGen *vector; IrInstGen *index; }; enum ResultLocId { ResultLocIdInvalid, ResultLocIdNone, ResultLocIdVar, ResultLocIdReturn, ResultLocIdPeer, ResultLocIdPeerParent, ResultLocIdInstruction, ResultLocIdBitCast, ResultLocIdCast, }; // Additions to this struct may need to be handled in // ir_reset_result struct ResultLoc { ResultLocId id; bool written; bool allow_write_through_const; IrInstGen *resolved_loc; // result ptr IrInstSrc *source_instruction; IrInstGen *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; bool implicit_return_type_done; }; struct IrSuspendPosition { size_t basic_block_index; size_t instruction_index; }; struct ResultLocPeerParent { ResultLoc base; bool skipped; bool done_resuming; IrBasicBlockSrc *end_bb; ResultLoc *parent; ZigList peers; ZigType *resolved_type; IrInstSrc *is_comptime; }; struct ResultLocPeer { ResultLoc base; ResultLocPeerParent *parent; IrBasicBlockSrc *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; }; // The source_instruction is the destination type struct ResultLocCast { ResultLoc base; ResultLoc *parent; }; static const size_t slice_ptr_index = 0; static const size_t slice_len_index = 1; static const size_t maybe_child_index = 0; static const size_t maybe_null_index = 1; static const size_t err_union_payload_index = 0; static const size_t err_union_err_index = 1; // label (grep this): [fn_frame_struct_layout] static const size_t frame_fn_ptr_index = 0; static const size_t frame_resume_index = 1; static const size_t frame_awaiter_index = 2; static const size_t frame_ret_start = 3; // TODO https://github.com/ziglang/zig/issues/3056 // We require this to be a power of 2 so that we can use shifting rather than // remainder division. static const size_t stack_trace_ptr_count = 32; // Must be a power of 2. #define NAMESPACE_SEP_CHAR '.' #define NAMESPACE_SEP_STR "." #define CACHE_OUT_SUBDIR "o" #define CACHE_HASH_SUBDIR "h" enum FloatMode { FloatModeStrict, FloatModeOptimized, }; enum FnWalkId { FnWalkIdAttrs, FnWalkIdCall, FnWalkIdTypes, FnWalkIdVars, FnWalkIdInits, }; struct FnWalkAttrs { ZigFn *fn; LLVMValueRef llvm_fn; unsigned gen_i; }; struct FnWalkCall { ZigList *gen_param_values; ZigList *gen_param_types; IrInstGenCall *inst; bool is_var_args; }; struct FnWalkTypes { ZigList *param_di_types; ZigList *gen_param_types; }; struct FnWalkVars { ZigType *import; LLVMValueRef llvm_fn; ZigFn *fn; ZigVar *var; unsigned gen_i; }; struct FnWalkInits { LLVMValueRef llvm_fn; ZigFn *fn; unsigned gen_i; }; struct FnWalk { FnWalkId id; union { FnWalkAttrs attrs; FnWalkCall call; FnWalkTypes types; FnWalkVars vars; FnWalkInits inits; } data; }; #endif