zig/src/stage1/all_types.hpp

4639 lines
97 KiB
C++

/*
* 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 "zig_llvm.h"
#include "hash_map.hpp"
#include "errmsg.hpp"
#include "bigint.hpp"
#include "bigfloat.hpp"
#include "target.hpp"
#include "tokenizer.hpp"
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<IrBasicBlockSrc *> 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 *> 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<IrBasicBlockGen *> 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 *> 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<AstNode *> 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<AstNode *> 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<AstNode *> 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<AstNode *> prongs;
};
struct AstNodeSwitchProng {
ZigList<AstNode *> 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<AsmOutput*> output_list;
ZigList<AsmInput*> input_list;
ZigList<Buf*> 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<AstNode *> fields;
ZigList<AstNode *> 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<AstNode *> 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<AstNode *> 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<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
struct RootStruct {
ZigPackage *package;
Buf *path; // relative to root_package->root_src_dir
ZigList<size_t> *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<Buf *, TypeStructField *, buf_hash, buf_eql_buf> 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;
bool created_by_at_type;
};
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<Buf *, TypeEnumField *, buf_hash, buf_eql_buf> fields_by_name;
uint32_t src_field_count;
ContainerLayout layout;
ResolveStatus resolve_status;
bool has_explicit_tag_type;
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<Buf *, TypeUnionField *, buf_hash, buf_eql_buf> 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;
};
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<IrInstGenAlloca *> alloca_gen_list;
ZigList<ZigVar *> 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<GlobalExport> export_list;
ZigList<IrInstGenCall *> call_list;
ZigList<IrInstGenAwait *> 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,
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;
};
struct CFile {
ZigList<const char *> args;
const char *source_path;
const char *preprocessor_only_basename;
};
struct CodeGen {
// Other code depends on this being first.
ZigStage1 stage1;
// arena allocator destroyed just prior to codegen emit
heap::ArenaAllocator *pass1_arena;
//////////////////////////// Runtime State
LLVMModuleRef module;
ZigList<ErrorMsg*> errors;
ErrorMsg *trace_err;
LLVMBuilderRef builder;
ZigLLVMDIBuilder *dbuilder;
ZigLLVMDICompileUnit *compile_unit;
ZigLLVMDIFile *compile_unit_file;
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<Buf *, ZigType *, buf_hash, buf_eql_buf> import_table;
HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;
HashMap<Buf *, ZigType *, buf_hash, buf_eql_buf> primitive_type_table;
HashMap<TypeId, ZigType *, type_id_hash, type_id_eql> type_table;
HashMap<FnTypeId *, ZigType *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;
HashMap<Scope *, ZigValue *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;
HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;
HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> exported_symbol_names;
HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_symbol_names;
HashMap<Buf *, ZigValue *, buf_hash, buf_eql_buf> string_literals_table;
HashMap<const ZigType *, ZigValue *, type_ptr_hash, type_ptr_eql> type_info_cache;
HashMap<const ZigType *, ZigValue *, type_ptr_hash, type_ptr_eql> one_possible_values;
ZigList<Tld *> resolve_queue;
size_t resolve_queue_index;
ZigList<TimeEvent> timing_events;
ZigList<ZigFn *> inline_fns;
ZigList<ZigFn *> test_fns;
ZigList<ErrorTableEntry *> errors_by_index;
size_t largest_err_name_len;
ZigList<ZigType *> 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 h_file_output_path;
Buf asm_file_output_path;
Buf llvm_ir_file_output_path;
Buf analysis_json_output_path;
Buf docs_output_path;
Buf *cache_dir;
Buf *c_artifact_dir;
const char **libc_include_dir_list;
size_t libc_include_dir_len;
Buf *builtin_zig_path;
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<ZigFn *> fn_defs;
size_t fn_defs_index;
ZigList<TldVar *> global_vars;
ZigFn *cur_fn;
ZigFn *panic_fn;
ZigFn *largest_frame_fn;
Stage2ProgressNode *main_progress_node;
Stage2ProgressNode *sub_progress_node;
ErrColor err_color;
uint32_t next_unresolved_index;
unsigned pointer_size_bytes;
bool is_big_endian;
bool have_err_ret_tracing;
bool verbose_tokenize;
bool verbose_ast;
bool verbose_ir;
bool verbose_llvm_ir;
bool verbose_cimport;
bool verbose_llvm_cpu_features;
bool error_during_imports;
bool generate_error_name_table;
bool enable_time_report;
bool enable_stack_report;
bool reported_bad_link_libc_error;
bool need_frame_size_prefix_data;
bool link_libc;
bool link_libcpp;
BuildMode build_mode;
const ZigTarget *zig_target;
TargetSubsystem subsystem; // careful using this directly; see detect_subsystem
CodeModel code_model;
bool strip_debug_symbols;
bool is_test_build;
bool is_single_threaded;
bool have_pic;
bool link_mode_dynamic;
bool dll_export_fns;
bool have_stack_probing;
bool function_sections;
bool test_is_evented;
bool valgrind_enabled;
Buf *root_out_name;
Buf *test_filter;
Buf *test_name_prefix;
Buf *zig_lib_dir;
Buf *zig_std_dir;
};
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<GlobalExport> 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<Buf *, Tld *, buf_hash, buf_eql_buf> decl_table;
ZigList<TldUsingNamespace *> 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<IrInstSrc *> *incoming_values;
ZigList<IrBasicBlockSrc *> *incoming_blocks;
AstNode *safety_set_node;
AstNode *fast_math_set_node;
LVal lval;
bool safety_off;
bool fast_math_on;
bool name_used;
};
// 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<IrInstSrc *> *incoming_values;
ZigList<IrBasicBlockSrc *> *incoming_blocks;
ResultLocPeerParent *peer_parent;
ScopeExpr *spill_scope;
bool name_used;
};
// 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<IrInstSrc *> 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<IrInstGen *> 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,
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;
AstNode* 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 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<ResultLocPeer *> 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<LLVMValueRef> *gen_param_values;
ZigList<ZigType *> *gen_param_types;
IrInstGenCall *inst;
bool is_var_args;
};
struct FnWalkTypes {
ZigList<ZigLLVMDIType *> *param_di_types;
ZigList<LLVMTypeRef> *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