zig/src/all_types.hpp
2018-05-13 13:38:03 -04:00

3136 lines
69 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 ImportTableEntry;
struct FnTableEntry;
struct Scope;
struct ScopeBlock;
struct ScopeFnDef;
struct TypeTableEntry;
struct VariableTableEntry;
struct ErrorTableEntry;
struct BuiltinFnEntry;
struct TypeStructField;
struct CodeGen;
struct ConstExprValue;
struct IrInstruction;
struct IrInstructionCast;
struct IrBasicBlock;
struct ScopeDecls;
struct ZigWindowsSDK;
struct Tld;
struct TldExport;
struct IrAnalyze;
struct IrExecutable {
ZigList<IrBasicBlock *> basic_block_list;
Buf *name;
size_t mem_slot_count;
size_t next_debug_id;
size_t *backward_branch_count;
size_t backward_branch_quota;
bool invalid;
bool is_inline;
bool is_generic_instantiation;
FnTableEntry *fn_entry;
Buf *c_import_buf;
AstNode *source_node;
IrExecutable *parent_exec;
IrExecutable *source_exec;
IrAnalyze *analysis;
Scope *begin_scope;
ZigList<Tld *> tld_list;
IrInstruction *coro_handle;
IrInstruction *coro_awaiter_field_ptr; // this one is shared and in the promise
IrInstruction *coro_result_ptr_field_ptr;
IrInstruction *coro_result_field_ptr;
IrInstruction *await_handle_var_ptr; // this one is where we put the one we extracted from the promise
IrBasicBlock *coro_early_final;
IrBasicBlock *coro_normal_final;
IrBasicBlock *coro_suspend_block;
IrBasicBlock *coro_final_cleanup_block;
VariableTableEntry *coro_allocator_var;
};
enum OutType {
OutTypeUnknown,
OutTypeExe,
OutTypeLib,
OutTypeObj,
};
enum ConstParentId {
ConstParentIdNone,
ConstParentIdStruct,
ConstParentIdArray,
ConstParentIdUnion,
};
struct ConstParent {
ConstParentId id;
union {
struct {
ConstExprValue *array_val;
size_t elem_index;
} p_array;
struct {
ConstExprValue *struct_val;
size_t field_index;
} p_struct;
struct {
ConstExprValue *union_val;
} p_union;
} data;
};
struct ConstStructValue {
ConstExprValue *fields;
ConstParent parent;
};
struct ConstUnionValue {
BigInt tag;
ConstExprValue *payload;
ConstParent parent;
};
enum ConstArraySpecial {
ConstArraySpecialNone,
ConstArraySpecialUndef,
};
struct ConstArrayValue {
ConstArraySpecial special;
struct {
ConstExprValue *elements;
ConstParent parent;
} s_none;
};
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.
ConstPtrSpecialBaseArray,
// The pointer points to a field in an underlying struct.
ConstPtrSpecialBaseStruct,
// 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,
};
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,
};
struct ConstPtrValue {
ConstPtrSpecial special;
ConstPtrMut mut;
union {
struct {
ConstExprValue *pointee;
} ref;
struct {
ConstExprValue *array_val;
size_t elem_index;
// This helps us preserve the null byte when performing compile-time
// concatenation on C strings.
bool is_cstr;
} base_array;
struct {
ConstExprValue *struct_val;
size_t field_index;
} base_struct;
struct {
uint64_t addr;
} hard_coded_addr;
struct {
FnTableEntry *fn_entry;
} fn;
} data;
};
struct ConstErrValue {
ErrorTableEntry *err;
ConstExprValue *payload;
};
struct ConstBoundFnValue {
FnTableEntry *fn;
IrInstruction *first_arg;
};
struct ConstArgTuple {
size_t start_index;
size_t end_index;
};
enum ConstValSpecial {
ConstValSpecialRuntime,
ConstValSpecialStatic,
ConstValSpecialUndef,
};
enum RuntimeHintErrorUnion {
RuntimeHintErrorUnionUnknown,
RuntimeHintErrorUnionError,
RuntimeHintErrorUnionNonError,
};
enum RuntimeHintMaybe {
RuntimeHintMaybeUnknown,
RuntimeHintMaybeNull, // TODO is this value even possible? if this is the case it might mean the const value is compile time known.
RuntimeHintMaybeNonNull,
};
enum RuntimeHintPtr {
RuntimeHintPtrUnknown,
RuntimeHintPtrStack,
RuntimeHintPtrNonStack,
};
struct ConstGlobalRefs {
LLVMValueRef llvm_value;
LLVMValueRef llvm_global;
};
struct ConstExprValue {
TypeTableEntry *type;
ConstValSpecial special;
ConstGlobalRefs *global_refs;
union {
// populated if special == ConstValSpecialStatic
BigInt x_bigint;
BigFloat x_bigfloat;
float x_f32;
double x_f64;
float128_t x_f128;
bool x_bool;
ConstBoundFnValue x_bound_fn;
TypeTableEntry *x_type;
ConstExprValue *x_maybe;
ConstErrValue x_err_union;
ErrorTableEntry *x_err_set;
BigInt x_enum_tag;
ConstStructValue x_struct;
ConstUnionValue x_union;
ConstArrayValue x_array;
ConstPtrValue x_ptr;
ImportTableEntry *x_import;
Scope *x_block;
ConstArgTuple x_arg_tuple;
// populated if special == ConstValSpecialRuntime
RuntimeHintErrorUnion rh_error_union;
RuntimeHintMaybe rh_maybe;
RuntimeHintPtr rh_ptr;
} data;
};
enum ReturnKnowledge {
ReturnKnowledgeUnknown,
ReturnKnowledgeKnownError,
ReturnKnowledgeKnownNonError,
ReturnKnowledgeKnownNull,
ReturnKnowledgeKnownNonNull,
ReturnKnowledgeSkipDefers,
};
enum VisibMod {
VisibModPrivate,
VisibModPub,
};
enum GlobalLinkageId {
GlobalLinkageIdInternal,
GlobalLinkageIdStrong,
GlobalLinkageIdWeak,
GlobalLinkageIdLinkOnce,
};
enum TldId {
TldIdVar,
TldIdFn,
TldIdContainer,
TldIdCompTime,
};
enum TldResolution {
TldResolutionUnresolved,
TldResolutionResolving,
TldResolutionInvalid,
TldResolutionOk,
};
struct Tld {
TldId id;
Buf *name;
VisibMod visib_mod;
AstNode *source_node;
ImportTableEntry *import;
Scope *parent_scope;
// set this flag temporarily to detect infinite loops
bool dep_loop_flag;
TldResolution resolution;
};
struct TldVar {
Tld base;
VariableTableEntry *var;
Buf *extern_lib_name;
Buf *section_name;
};
struct TldFn {
Tld base;
FnTableEntry *fn_entry;
Buf *extern_lib_name;
};
struct TldContainer {
Tld base;
ScopeDecls *decls_scope;
TypeTableEntry *type_entry;
};
struct TldCompTime {
Tld base;
};
struct TypeEnumField {
Buf *name;
BigInt value;
uint32_t decl_index;
AstNode *decl_node;
};
struct TypeUnionField {
Buf *name;
TypeEnumField *enum_field;
TypeTableEntry *type_entry;
AstNode *decl_node;
uint32_t gen_index;
};
enum NodeType {
NodeTypeRoot,
NodeTypeFnProto,
NodeTypeFnDef,
NodeTypeParamDecl,
NodeTypeBlock,
NodeTypeGroupedExpr,
NodeTypeReturnExpr,
NodeTypeDefer,
NodeTypeVariableDeclaration,
NodeTypeTestDecl,
NodeTypeBinOpExpr,
NodeTypeUnwrapErrorExpr,
NodeTypeFloatLiteral,
NodeTypeIntLiteral,
NodeTypeStringLiteral,
NodeTypeCharLiteral,
NodeTypeSymbol,
NodeTypePrefixOpExpr,
NodeTypeAddrOfExpr,
NodeTypeFnCallExpr,
NodeTypeArrayAccessExpr,
NodeTypeSliceExpr,
NodeTypeFieldAccessExpr,
NodeTypePtrDeref,
NodeTypeUse,
NodeTypeBoolLiteral,
NodeTypeNullLiteral,
NodeTypeUndefinedLiteral,
NodeTypeThisLiteral,
NodeTypeUnreachable,
NodeTypeIfBoolExpr,
NodeTypeWhileExpr,
NodeTypeForExpr,
NodeTypeSwitchExpr,
NodeTypeSwitchProng,
NodeTypeSwitchRange,
NodeTypeCompTime,
NodeTypeBreak,
NodeTypeContinue,
NodeTypeAsmExpr,
NodeTypeContainerDecl,
NodeTypeStructField,
NodeTypeContainerInitExpr,
NodeTypeStructValueField,
NodeTypeArrayType,
NodeTypeErrorType,
NodeTypeIfErrorExpr,
NodeTypeTestExpr,
NodeTypeErrorSetDecl,
NodeTypeCancel,
NodeTypeResume,
NodeTypeAwaitExpr,
NodeTypeSuspend,
NodeTypePromiseType,
};
struct AstNodeRoot {
ZigList<AstNode *> top_level_decls;
};
enum CallingConvention {
CallingConventionUnspecified,
CallingConventionC,
CallingConventionCold,
CallingConventionNaked,
CallingConventionStdcall,
CallingConventionAsync,
};
struct AstNodeFnProto {
VisibMod visib_mod;
Buf *name;
ZigList<AstNode *> params;
AstNode *return_type;
Token *return_var_token;
bool is_var_args;
bool is_extern;
bool is_export;
bool is_inline;
CallingConvention cc;
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;
bool auto_err_set;
AstNode *async_allocator_type;
};
struct AstNodeFnDef {
AstNode *fn_proto;
AstNode *body;
};
struct AstNodeParamDecl {
Buf *name;
AstNode *type;
Token *var_token;
bool is_noalias;
bool is_inline;
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 *expr;
// temporary data used in IR generation
Scope *child_scope;
Scope *expr_scope;
};
struct AstNodeVariableDeclaration {
VisibMod visib_mod;
Buf *symbol;
bool is_const;
bool is_comptime;
bool is_export;
bool is_extern;
// 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;
};
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,
BinOpTypeUnwrapMaybe,
BinOpTypeArrayCat,
BinOpTypeArrayMult,
BinOpTypeErrorUnion,
BinOpTypeMergeErrorSets,
};
struct AstNodeBinOpExpr {
AstNode *op1;
BinOpType bin_op;
AstNode *op2;
};
struct AstNodeCatchExpr {
AstNode *op1;
AstNode *symbol; // can be null
AstNode *op2;
};
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,
CastOpResizeSlice,
CastOpBytesToSlice,
CastOpNumLitToConcrete,
CastOpErrSet,
};
struct AstNodeFnCallExpr {
AstNode *fn_ref_expr;
ZigList<AstNode *> params;
bool is_builtin;
bool is_async;
AstNode *async_allocator;
};
struct AstNodeArrayAccessExpr {
AstNode *array_ref_expr;
AstNode *subscript;
};
struct AstNodeSliceExpr {
AstNode *array_ref_expr;
AstNode *start;
AstNode *end;
};
struct AstNodeFieldAccessExpr {
AstNode *struct_expr;
Buf *field_name;
};
struct AstNodePtrDerefExpr {
AstNode *target;
};
enum PrefixOp {
PrefixOpInvalid,
PrefixOpBoolNot,
PrefixOpBinNot,
PrefixOpNegation,
PrefixOpNegationWrap,
PrefixOpMaybe,
PrefixOpUnwrapMaybe,
};
struct AstNodePrefixOpExpr {
PrefixOp prefix_op;
AstNode *primary_expr;
};
struct AstNodeAddrOfExpr {
AstNode *align_expr;
BigInt *bit_offset_start;
BigInt *bit_offset_end;
bool is_const;
bool is_volatile;
AstNode *op_expr;
};
struct AstNodeArrayType {
AstNode *size;
AstNode *child_type;
AstNode *align_expr;
bool is_const;
bool is_volatile;
};
struct AstNodeUse {
VisibMod visib_mod;
AstNode *expr;
TldResolution resolution;
IrInstruction *value;
};
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 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 {
bool is_volatile;
Buf *asm_template;
ZigList<AsmToken> token_list;
ZigList<AsmOutput*> output_list;
ZigList<AsmInput*> input_list;
ZigList<Buf*> clobber_list;
};
enum ContainerKind {
ContainerKindStruct,
ContainerKindEnum,
ContainerKindUnion,
};
enum ContainerLayout {
ContainerLayoutAuto,
ContainerLayoutExtern,
ContainerLayoutPacked,
};
struct AstNodeContainerDecl {
ContainerKind kind;
ZigList<AstNode *> fields;
ZigList<AstNode *> decls;
ContainerLayout layout;
AstNode *init_arg_expr; // enum(T), struct(endianness), or union(T), or union(enum(T))
bool auto_enum; // union(enum)
};
struct AstNodeErrorSetDecl {
ZigList<AstNode *> decls;
};
struct AstNodeStructField {
VisibMod visib_mod;
Buf *name;
AstNode *type;
AstNode *value;
};
struct AstNodeStringLiteral {
Buf *buf;
bool c;
};
struct AstNodeCharLiteral {
uint8_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 AstNodeCancelExpr {
AstNode *expr;
};
struct AstNodeResumeExpr {
AstNode *expr;
};
struct AstNodeContinueExpr {
Buf *name;
};
struct AstNodeUnreachableExpr {
};
struct AstNodeErrorType {
};
struct AstNodeAwaitExpr {
AstNode *expr;
};
struct AstNodeSuspend {
Buf *name;
AstNode *block;
AstNode *promise_symbol;
};
struct AstNodePromiseType {
AstNode *payload_type; // can be NULL
};
struct AstNode {
enum NodeType type;
size_t line;
size_t column;
ImportTableEntry *owner;
union {
AstNodeRoot root;
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;
AstNodePrefixOpExpr prefix_op_expr;
AstNodeAddrOfExpr addr_of_expr;
AstNodeFnCallExpr fn_call_expr;
AstNodeArrayAccessExpr array_access_expr;
AstNodeSliceExpr slice_expr;
AstNodeUse use;
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;
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;
AstNodeErrorType error_type;
AstNodeErrorSetDecl err_set_decl;
AstNodeCancelExpr cancel_expr;
AstNodeResumeExpr resume_expr;
AstNodeAwaitExpr await_expr;
AstNodeSuspend suspend;
AstNodePromiseType promise_type;
} data;
};
// this struct is allocated with allocate_nonzero
struct FnTypeParamInfo {
bool is_noalias;
TypeTableEntry *type;
};
struct GenericFnTypeId {
FnTableEntry *fn_entry;
ConstExprValue *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 {
TypeTableEntry *return_type;
FnTypeParamInfo *param_info;
size_t param_count;
size_t next_param_index;
bool is_var_args;
CallingConvention cc;
uint32_t alignment;
TypeTableEntry *async_allocator_type;
};
uint32_t fn_type_id_hash(FnTypeId*);
bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
struct TypeTableEntryPointer {
TypeTableEntry *child_type;
bool is_const;
bool is_volatile;
uint32_t alignment;
uint32_t bit_offset;
uint32_t unaligned_bit_count;
TypeTableEntry *slice_parent;
};
struct TypeTableEntryInt {
uint32_t bit_count;
bool is_signed;
};
struct TypeTableEntryFloat {
size_t bit_count;
};
struct TypeTableEntryArray {
TypeTableEntry *child_type;
uint64_t len;
};
struct TypeStructField {
Buf *name;
TypeTableEntry *type_entry;
size_t src_index;
size_t gen_index;
// offset from the memory at gen_index
size_t packed_bits_offset;
size_t packed_bits_size;
size_t unaligned_bit_count;
AstNode *decl_node;
};
struct TypeTableEntryStruct {
AstNode *decl_node;
ContainerLayout layout;
uint32_t src_field_count;
uint32_t gen_field_count;
TypeStructField *fields;
uint64_t size_bytes;
bool is_invalid; // true if any fields are invalid
bool is_slice;
ScopeDecls *decls_scope;
// set this flag temporarily to detect infinite loops
bool embedded_in_current;
bool reported_infinite_err;
// whether we've finished resolving it
bool complete;
bool zero_bits_loop_flag;
bool zero_bits_known;
uint32_t abi_alignment; // also figured out with zero_bits pass
HashMap<Buf *, TypeStructField *, buf_hash, buf_eql_buf> fields_by_name;
};
struct TypeTableEntryMaybe {
TypeTableEntry *child_type;
};
struct TypeTableEntryErrorUnion {
TypeTableEntry *err_set_type;
TypeTableEntry *payload_type;
};
struct TypeTableEntryErrorSet {
uint32_t err_count;
ErrorTableEntry **errors;
FnTableEntry *infer_fn;
};
struct TypeTableEntryEnum {
AstNode *decl_node;
ContainerLayout layout;
uint32_t src_field_count;
TypeEnumField *fields;
bool is_invalid; // true if any fields are invalid
TypeTableEntry *tag_int_type;
ScopeDecls *decls_scope;
// set this flag temporarily to detect infinite loops
bool embedded_in_current;
bool reported_infinite_err;
// whether we've finished resolving it
bool complete;
bool zero_bits_loop_flag;
bool zero_bits_known;
bool generate_name_table;
LLVMValueRef name_table;
HashMap<Buf *, TypeEnumField *, buf_hash, buf_eql_buf> fields_by_name;
};
uint32_t type_ptr_hash(const TypeTableEntry *ptr);
bool type_ptr_eql(const TypeTableEntry *a, const TypeTableEntry *b);
struct TypeTableEntryUnion {
AstNode *decl_node;
ContainerLayout layout;
uint32_t src_field_count;
uint32_t gen_field_count;
TypeUnionField *fields;
bool is_invalid; // true if any fields are invalid
TypeTableEntry *tag_type; // always an enum or null
LLVMTypeRef union_type_ref;
ScopeDecls *decls_scope;
// set this flag temporarily to detect infinite loops
bool embedded_in_current;
bool reported_infinite_err;
// whether we've finished resolving it
bool complete;
bool zero_bits_loop_flag;
bool zero_bits_known;
uint32_t abi_alignment; // also figured out with zero_bits pass
size_t gen_union_index;
size_t gen_tag_index;
bool have_explicit_tag_type;
uint32_t union_size_bytes;
TypeTableEntry *most_aligned_union_member;
HashMap<Buf *, TypeUnionField *, buf_hash, buf_eql_buf> fields_by_name;
};
struct FnGenParamInfo {
size_t src_index;
size_t gen_index;
bool is_byval;
TypeTableEntry *type;
};
struct TypeTableEntryFn {
FnTypeId fn_type_id;
bool is_generic;
TypeTableEntry *gen_return_type;
size_t gen_param_count;
FnGenParamInfo *gen_param_info;
LLVMTypeRef raw_type_ref;
TypeTableEntry *bound_fn_parent;
};
struct TypeTableEntryBoundFn {
TypeTableEntry *fn_type;
};
struct TypeTableEntryPromise {
// null if `promise` instead of `promise->T`
TypeTableEntry *result_type;
};
enum TypeTableEntryId {
TypeTableEntryIdInvalid,
TypeTableEntryIdMetaType,
TypeTableEntryIdVoid,
TypeTableEntryIdBool,
TypeTableEntryIdUnreachable,
TypeTableEntryIdInt,
TypeTableEntryIdFloat,
TypeTableEntryIdPointer,
TypeTableEntryIdArray,
TypeTableEntryIdStruct,
TypeTableEntryIdNumLitFloat,
TypeTableEntryIdNumLitInt,
TypeTableEntryIdUndefLit,
TypeTableEntryIdNullLit,
TypeTableEntryIdMaybe,
TypeTableEntryIdErrorUnion,
TypeTableEntryIdErrorSet,
TypeTableEntryIdEnum,
TypeTableEntryIdUnion,
TypeTableEntryIdFn,
TypeTableEntryIdNamespace,
TypeTableEntryIdBlock,
TypeTableEntryIdBoundFn,
TypeTableEntryIdArgTuple,
TypeTableEntryIdOpaque,
TypeTableEntryIdPromise,
};
struct TypeTableEntry {
TypeTableEntryId id;
Buf name;
LLVMTypeRef type_ref;
ZigLLVMDIType *di_type;
bool zero_bits; // this is denormalized data
bool is_copyable;
bool gen_h_loop_flag;
union {
TypeTableEntryPointer pointer;
TypeTableEntryInt integral;
TypeTableEntryFloat floating;
TypeTableEntryArray array;
TypeTableEntryStruct structure;
TypeTableEntryMaybe maybe;
TypeTableEntryErrorUnion error_union;
TypeTableEntryErrorSet error_set;
TypeTableEntryEnum enumeration;
TypeTableEntryUnion unionation;
TypeTableEntryFn fn;
TypeTableEntryBoundFn bound_fn;
TypeTableEntryPromise promise;
} data;
// use these fields to make sure we don't duplicate type table entries for the same type
TypeTableEntry *pointer_parent[2]; // [0 - mut, 1 - const]
TypeTableEntry *maybe_parent;
TypeTableEntry *promise_parent;
TypeTableEntry *promise_frame_parent;
// If we generate a constant name value for this type, we memoize it here.
// The type of this is array
ConstExprValue *cached_const_name_val;
};
struct PackageTableEntry {
Buf root_src_dir;
Buf root_src_path; // relative to root_src_dir
// reminder: hash tables must be initialized before use
HashMap<Buf *, PackageTableEntry *, buf_hash, buf_eql_buf> package_table;
};
struct ImportTableEntry {
AstNode *root;
Buf *path; // relative to root_package->root_src_dir
PackageTableEntry *package;
ZigLLVMDIFile *di_file;
Buf *source_code;
ZigList<size_t> *line_offsets;
ScopeDecls *decls_scope;
AstNode *c_import_node;
bool any_imports_failed;
bool scanned;
ZigList<AstNode *> use_decls;
};
enum FnAnalState {
FnAnalStateReady,
FnAnalStateProbing,
FnAnalStateComplete,
FnAnalStateInvalid,
};
enum FnInline {
FnInlineAuto,
FnInlineAlways,
FnInlineNever,
};
struct FnExport {
Buf name;
GlobalLinkageId linkage;
};
struct FnTableEntry {
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;
TypeTableEntry *type_entry; // function 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
TypeTableEntry *src_implicit_return_type;
bool is_test;
FnInline fn_inline;
FnAnalState anal_state;
IrExecutable ir_executable;
IrExecutable analyzed_executable;
size_t prealloc_bbc;
AstNode **param_source_nodes;
Buf **param_names;
uint32_t align_bytes;
AstNode *fn_no_inline_set_node;
AstNode *fn_static_eval_set_node;
ZigList<IrInstruction *> alloca_list;
ZigList<VariableTableEntry *> variable_list;
Buf *section_name;
AstNode *set_alignstack_node;
uint32_t alignstack_value;
AstNode *set_cold_node;
bool is_cold;
ZigList<FnExport> export_list;
bool calls_or_awaits_errorable_fn;
};
uint32_t fn_table_entry_hash(FnTableEntry*);
bool fn_table_entry_eql(FnTableEntry *a, FnTableEntry *b);
enum BuiltinFnId {
BuiltinFnIdInvalid,
BuiltinFnIdMemcpy,
BuiltinFnIdMemset,
BuiltinFnIdSizeof,
BuiltinFnIdAlignOf,
BuiltinFnIdMaxValue,
BuiltinFnIdMinValue,
BuiltinFnIdMemberCount,
BuiltinFnIdMemberType,
BuiltinFnIdMemberName,
BuiltinFnIdField,
BuiltinFnIdTypeInfo,
BuiltinFnIdTypeof,
BuiltinFnIdAddWithOverflow,
BuiltinFnIdSubWithOverflow,
BuiltinFnIdMulWithOverflow,
BuiltinFnIdShlWithOverflow,
BuiltinFnIdCInclude,
BuiltinFnIdCDefine,
BuiltinFnIdCUndef,
BuiltinFnIdCompileErr,
BuiltinFnIdCompileLog,
BuiltinFnIdCtz,
BuiltinFnIdClz,
BuiltinFnIdImport,
BuiltinFnIdCImport,
BuiltinFnIdErrName,
BuiltinFnIdBreakpoint,
BuiltinFnIdReturnAddress,
BuiltinFnIdFrameAddress,
BuiltinFnIdEmbedFile,
BuiltinFnIdCmpxchgWeak,
BuiltinFnIdCmpxchgStrong,
BuiltinFnIdFence,
BuiltinFnIdDivExact,
BuiltinFnIdDivTrunc,
BuiltinFnIdDivFloor,
BuiltinFnIdRem,
BuiltinFnIdMod,
BuiltinFnIdSqrt,
BuiltinFnIdTruncate,
BuiltinFnIdIntType,
BuiltinFnIdSetCold,
BuiltinFnIdSetRuntimeSafety,
BuiltinFnIdSetFloatMode,
BuiltinFnIdTypeName,
BuiltinFnIdCanImplicitCast,
BuiltinFnIdPanic,
BuiltinFnIdPtrCast,
BuiltinFnIdBitCast,
BuiltinFnIdIntToPtr,
BuiltinFnIdPtrToInt,
BuiltinFnIdTagName,
BuiltinFnIdTagType,
BuiltinFnIdFieldParentPtr,
BuiltinFnIdOffsetOf,
BuiltinFnIdInlineCall,
BuiltinFnIdNoInlineCall,
BuiltinFnIdNewStackCall,
BuiltinFnIdTypeId,
BuiltinFnIdShlExact,
BuiltinFnIdShrExact,
BuiltinFnIdSetEvalBranchQuota,
BuiltinFnIdAlignCast,
BuiltinFnIdOpaqueType,
BuiltinFnIdSetAlignStack,
BuiltinFnIdArgType,
BuiltinFnIdExport,
BuiltinFnIdErrorReturnTrace,
BuiltinFnIdAtomicRmw,
BuiltinFnIdAtomicLoad,
};
struct BuiltinFnEntry {
BuiltinFnId id;
Buf name;
size_t param_count;
};
enum PanicMsgId {
PanicMsgIdUnreachable,
PanicMsgIdBoundsCheckFailure,
PanicMsgIdCastNegativeToUnsigned,
PanicMsgIdCastTruncatedData,
PanicMsgIdIntegerOverflow,
PanicMsgIdShlOverflowedBits,
PanicMsgIdShrOverflowedBits,
PanicMsgIdDivisionByZero,
PanicMsgIdRemainderDivisionByZero,
PanicMsgIdExactDivisionRemainder,
PanicMsgIdSliceWidenRemainder,
PanicMsgIdUnwrapMaybeFail,
PanicMsgIdInvalidErrorCode,
PanicMsgIdIncorrectAlignment,
PanicMsgIdBadUnionField,
PanicMsgIdCount,
};
uint32_t fn_eval_hash(Scope*);
bool fn_eval_eql(Scope *a, Scope *b);
struct TypeId {
TypeTableEntryId id;
union {
struct {
TypeTableEntry *child_type;
bool is_const;
bool is_volatile;
uint32_t alignment;
uint32_t bit_offset;
uint32_t unaligned_bit_count;
} pointer;
struct {
TypeTableEntry *child_type;
uint64_t size;
} array;
struct {
bool is_signed;
uint32_t bit_count;
} integer;
struct {
TypeTableEntry *err_set_type;
TypeTableEntry *payload_type;
} error_union;
} data;
};
uint32_t type_id_hash(TypeId);
bool type_id_eql(TypeId a, TypeId b);
enum ZigLLVMFnId {
ZigLLVMFnIdCtz,
ZigLLVMFnIdClz,
ZigLLVMFnIdOverflowArithmetic,
ZigLLVMFnIdFloor,
ZigLLVMFnIdCeil,
ZigLLVMFnIdSqrt,
};
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;
} floating;
struct {
AddSubMul add_sub_mul;
uint32_t bit_count;
bool is_signed;
} overflow_arithmetic;
} 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 EmitFileType {
EmitFileTypeBinary,
EmitFileTypeAssembly,
EmitFileTypeLLVMIr,
};
struct LinkLib {
Buf *name;
Buf *path;
ZigList<Buf *> symbols; // the list of symbols that we depend on from this lib
bool provided_explicitly;
};
struct CodeGen {
LLVMModuleRef module;
ZigList<ErrorMsg*> errors;
LLVMBuilderRef builder;
ZigLLVMDIBuilder *dbuilder;
ZigLLVMDICompileUnit *compile_unit;
ZigLLVMDIFile *compile_unit_file;
ZigList<LinkLib *> link_libs_list;
LinkLib *libc_link_lib;
// add -framework [name] args to linker
ZigList<Buf *> darwin_frameworks;
// add -rpath [name] args to linker
ZigList<Buf *> rpath_list;
// reminder: hash tables must be initialized before use
HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;
HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;
HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table;
HashMap<TypeId, TypeTableEntry *, type_id_hash, type_id_eql> type_table;
HashMap<FnTypeId *, TypeTableEntry *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
HashMap<GenericFnTypeId *, FnTableEntry *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;
HashMap<Scope *, IrInstruction *, 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 *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names;
HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table;
HashMap<const TypeTableEntry *, ConstExprValue *, type_ptr_hash, type_ptr_eql> type_info_cache;
ZigList<ImportTableEntry *> import_queue;
size_t import_queue_index;
ZigList<Tld *> resolve_queue;
size_t resolve_queue_index;
ZigList<AstNode *> use_queue;
size_t use_queue_index;
uint32_t next_unresolved_index;
struct {
TypeTableEntry *entry_bool;
TypeTableEntry *entry_int[2][12]; // [signed,unsigned][2,3,4,5,6,7,8,16,29,32,64,128]
TypeTableEntry *entry_c_int[CIntTypeCount];
TypeTableEntry *entry_c_longdouble;
TypeTableEntry *entry_c_void;
TypeTableEntry *entry_u8;
TypeTableEntry *entry_u16;
TypeTableEntry *entry_u32;
TypeTableEntry *entry_u29;
TypeTableEntry *entry_u64;
TypeTableEntry *entry_u128;
TypeTableEntry *entry_i8;
TypeTableEntry *entry_i16;
TypeTableEntry *entry_i32;
TypeTableEntry *entry_i64;
TypeTableEntry *entry_i128;
TypeTableEntry *entry_isize;
TypeTableEntry *entry_usize;
TypeTableEntry *entry_f32;
TypeTableEntry *entry_f64;
TypeTableEntry *entry_f128;
TypeTableEntry *entry_void;
TypeTableEntry *entry_unreachable;
TypeTableEntry *entry_type;
TypeTableEntry *entry_invalid;
TypeTableEntry *entry_namespace;
TypeTableEntry *entry_block;
TypeTableEntry *entry_num_lit_int;
TypeTableEntry *entry_num_lit_float;
TypeTableEntry *entry_undef;
TypeTableEntry *entry_null;
TypeTableEntry *entry_var;
TypeTableEntry *entry_global_error_set;
TypeTableEntry *entry_arg_tuple;
TypeTableEntry *entry_promise;
} builtin_types;
EmitFileType emit_file_type;
ZigTarget zig_target;
LLVMTargetDataRef target_data_ref;
unsigned pointer_size_bytes;
bool is_big_endian;
bool is_static;
bool strip_debug_symbols;
bool want_h_file;
bool have_pub_main;
bool have_c_main;
bool have_winmain;
bool have_winmain_crt_startup;
bool have_dllmain_crt_startup;
bool have_pub_panic;
Buf *libc_lib_dir;
Buf *libc_static_lib_dir;
Buf *libc_include_dir;
Buf *msvc_lib_dir;
Buf *kernel32_lib_dir;
Buf *zig_lib_dir;
Buf *zig_std_dir;
Buf *zig_c_headers_dir;
Buf *zig_std_special_dir;
Buf *dynamic_linker;
Buf *ar_path;
ZigWindowsSDK *win_sdk;
Buf triple_str;
BuildMode build_mode;
bool is_test_build;
bool have_err_ret_tracing;
uint32_t target_os_index;
uint32_t target_arch_index;
uint32_t target_environ_index;
uint32_t target_oformat_index;
LLVMTargetMachineRef target_machine;
ZigLLVMDIFile *dummy_di_file;
bool is_native_target;
PackageTableEntry *root_package;
PackageTableEntry *std_package;
PackageTableEntry *panic_package;
PackageTableEntry *test_runner_package;
PackageTableEntry *compile_var_package;
ImportTableEntry *compile_var_import;
Buf *root_out_name;
bool windows_subsystem_windows;
bool windows_subsystem_console;
Buf *mmacosx_version_min;
Buf *mios_version_min;
bool linker_rdynamic;
const char *linker_script;
// The function definitions this module includes.
ZigList<FnTableEntry *> fn_defs;
size_t fn_defs_index;
ZigList<TldVar *> global_vars;
OutType out_type;
FnTableEntry *cur_fn;
FnTableEntry *main_fn;
FnTableEntry *panic_fn;
LLVMValueRef cur_ret_ptr;
LLVMValueRef cur_fn_val;
LLVMValueRef cur_err_ret_trace_val_arg;
LLVMValueRef cur_err_ret_trace_val_stack;
bool c_want_stdint;
bool c_want_stdbool;
AstNode *root_export_decl;
size_t version_major;
size_t version_minor;
size_t version_patch;
bool verbose_tokenize;
bool verbose_ast;
bool verbose_link;
bool verbose_ir;
bool verbose_llvm_ir;
bool verbose_cimport;
ErrColor err_color;
ImportTableEntry *root_import;
ImportTableEntry *bootstrap_import;
ImportTableEntry *test_runner_import;
LLVMValueRef memcpy_fn_val;
LLVMValueRef memset_fn_val;
LLVMValueRef trap_fn_val;
LLVMValueRef return_address_fn_val;
LLVMValueRef frame_address_fn_val;
LLVMValueRef coro_destroy_fn_val;
LLVMValueRef coro_id_fn_val;
LLVMValueRef coro_alloc_fn_val;
LLVMValueRef coro_size_fn_val;
LLVMValueRef coro_begin_fn_val;
LLVMValueRef coro_suspend_fn_val;
LLVMValueRef coro_end_fn_val;
LLVMValueRef coro_free_fn_val;
LLVMValueRef coro_resume_fn_val;
LLVMValueRef coro_save_fn_val;
LLVMValueRef coro_promise_fn_val;
LLVMValueRef coro_alloc_helper_fn_val;
LLVMValueRef merge_err_ret_traces_fn_val;
LLVMValueRef add_error_return_trace_addr_fn_val;
LLVMValueRef stacksave_fn_val;
LLVMValueRef stackrestore_fn_val;
LLVMValueRef write_register_fn_val;
bool error_during_imports;
LLVMValueRef sp_md_node;
const char **clang_argv;
size_t clang_argv_len;
ZigList<const char *> lib_dirs;
const char **llvm_argv;
size_t llvm_argv_len;
ZigList<FnTableEntry *> test_fns;
TypeTableEntry *test_fn_type;
bool each_lib_rpath;
TypeTableEntry *err_tag_type;
ZigList<ZigLLVMDIEnumerator *> err_enumerators;
ZigList<ErrorTableEntry *> errors_by_index;
bool generate_error_name_table;
LLVMValueRef err_name_table;
size_t largest_err_name_len;
LLVMValueRef safety_crash_err_fn;
LLVMValueRef return_err_fn;
IrInstruction *invalid_instruction;
ConstExprValue const_void_val;
ConstExprValue panic_msg_vals[PanicMsgIdCount];
Buf global_asm;
ZigList<Buf *> link_objects;
ZigList<Buf *> assembly_files;
ZigList<TypeTableEntry *> name_table_enums;
Buf *test_filter;
Buf *test_name_prefix;
ZigList<TimeEvent> timing_events;
Buf *cache_dir;
Buf *out_h_path;
ZigList<FnTableEntry *> inline_fns;
ZigList<AstNode *> tld_ref_source_node_stack;
TypeTableEntry *align_amt_type;
TypeTableEntry *stack_trace_type;
TypeTableEntry *ptr_to_stack_trace_type;
ZigList<ZigLLVMDIType **> error_di_types;
ZigList<Buf *> forbidden_libs;
bool no_rosegment_workaround;
};
enum VarLinkage {
VarLinkageInternal,
VarLinkageExport,
VarLinkageExternal,
};
struct VariableTableEntry {
Buf name;
ConstExprValue *value;
LLVMValueRef value_ref;
bool src_is_const;
bool gen_is_const;
IrInstruction *is_comptime;
// which node is the declaration of the variable
AstNode *decl_node;
ZigLLVMDILocalVariable *di_loc_var;
size_t src_arg_index;
size_t gen_arg_index;
Scope *parent_scope;
Scope *child_scope;
LLVMValueRef param_value_ref;
bool shadowable;
size_t mem_slot_index;
IrExecutable *owner_exec;
size_t ref_count;
VarLinkage linkage;
IrInstruction *decl_instruction;
uint32_t align_bytes;
};
struct ErrorTableEntry {
Buf name;
uint32_t value;
AstNode *decl_node;
TypeTableEntry *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
ConstExprValue *cached_error_name_val;
};
enum ScopeId {
ScopeIdDecls,
ScopeIdBlock,
ScopeIdDefer,
ScopeIdDeferExpr,
ScopeIdVarDecl,
ScopeIdCImport,
ScopeIdLoop,
ScopeIdSuspend,
ScopeIdFnDef,
ScopeIdCompTime,
ScopeIdCoroPrelude,
};
struct Scope {
ScopeId id;
AstNode *source_node;
// if the scope has a parent, this is it
Scope *parent;
ZigLLVMDIScope *di_scope;
};
// This scope comes from global declarations or from
// declarations in a container declaration
// NodeTypeRoot, NodeTypeContainerDecl
struct ScopeDecls {
Scope base;
HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> decl_table;
bool safety_off;
AstNode *safety_set_node;
bool fast_math_off;
AstNode *fast_math_set_node;
ImportTableEntry *import;
// If this is a scope from a container, this is the type entry, otherwise null
TypeTableEntry *container_type;
};
// This scope comes from a block expression in user code.
// NodeTypeBlock
struct ScopeBlock {
Scope base;
Buf *name;
IrBasicBlock *end_block;
IrInstruction *is_comptime;
ZigList<IrInstruction *> *incoming_values;
ZigList<IrBasicBlock *> *incoming_blocks;
bool safety_off;
AstNode *safety_set_node;
bool fast_math_off;
AstNode *fast_math_set_node;
};
// 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
VariableTableEntry *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;
Buf *name;
IrBasicBlock *break_block;
IrBasicBlock *continue_block;
IrInstruction *is_comptime;
ZigList<IrInstruction *> *incoming_values;
ZigList<IrBasicBlock *> *incoming_blocks;
};
// 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;
Buf *name;
IrBasicBlock *resume_block;
bool reported_err;
};
// This scope is created for a comptime expression.
// NodeTypeCompTime, NodeTypeSwitchExpr
struct ScopeCompTime {
Scope base;
};
// This scope is created for a function definition.
// NodeTypeFnDef
struct ScopeFnDef {
Scope base;
FnTableEntry *fn_entry;
};
// This scope is created to indicate that the code in the scope
// is auto-generated coroutine prelude stuff.
struct ScopeCoroPrelude {
Scope base;
};
// 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 IrBasicBlock {
ZigList<IrInstruction *> instruction_list;
IrBasicBlock *other;
Scope *scope;
const char *name_hint;
size_t debug_id;
size_t ref_count;
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.
IrInstruction *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.
IrInstruction *must_be_comptime_source_instr;
};
struct LVal {
bool is_ptr;
bool is_const;
bool is_volatile;
};
enum IrInstructionId {
IrInstructionIdInvalid,
IrInstructionIdBr,
IrInstructionIdCondBr,
IrInstructionIdSwitchBr,
IrInstructionIdSwitchVar,
IrInstructionIdSwitchTarget,
IrInstructionIdPhi,
IrInstructionIdUnOp,
IrInstructionIdBinOp,
IrInstructionIdDeclVar,
IrInstructionIdLoadPtr,
IrInstructionIdStorePtr,
IrInstructionIdFieldPtr,
IrInstructionIdStructFieldPtr,
IrInstructionIdUnionFieldPtr,
IrInstructionIdElemPtr,
IrInstructionIdVarPtr,
IrInstructionIdCall,
IrInstructionIdConst,
IrInstructionIdReturn,
IrInstructionIdCast,
IrInstructionIdContainerInitList,
IrInstructionIdContainerInitFields,
IrInstructionIdStructInit,
IrInstructionIdUnionInit,
IrInstructionIdUnreachable,
IrInstructionIdTypeOf,
IrInstructionIdToPtrType,
IrInstructionIdPtrTypeChild,
IrInstructionIdSetCold,
IrInstructionIdSetRuntimeSafety,
IrInstructionIdSetFloatMode,
IrInstructionIdArrayType,
IrInstructionIdPromiseType,
IrInstructionIdSliceType,
IrInstructionIdAsm,
IrInstructionIdSizeOf,
IrInstructionIdTestNonNull,
IrInstructionIdUnwrapMaybe,
IrInstructionIdMaybeWrap,
IrInstructionIdUnionTag,
IrInstructionIdClz,
IrInstructionIdCtz,
IrInstructionIdImport,
IrInstructionIdCImport,
IrInstructionIdCInclude,
IrInstructionIdCDefine,
IrInstructionIdCUndef,
IrInstructionIdArrayLen,
IrInstructionIdRef,
IrInstructionIdMinValue,
IrInstructionIdMaxValue,
IrInstructionIdCompileErr,
IrInstructionIdCompileLog,
IrInstructionIdErrName,
IrInstructionIdEmbedFile,
IrInstructionIdCmpxchg,
IrInstructionIdFence,
IrInstructionIdTruncate,
IrInstructionIdIntType,
IrInstructionIdBoolNot,
IrInstructionIdMemset,
IrInstructionIdMemcpy,
IrInstructionIdSlice,
IrInstructionIdMemberCount,
IrInstructionIdMemberType,
IrInstructionIdMemberName,
IrInstructionIdBreakpoint,
IrInstructionIdReturnAddress,
IrInstructionIdFrameAddress,
IrInstructionIdAlignOf,
IrInstructionIdOverflowOp,
IrInstructionIdTestErr,
IrInstructionIdUnwrapErrCode,
IrInstructionIdUnwrapErrPayload,
IrInstructionIdErrWrapCode,
IrInstructionIdErrWrapPayload,
IrInstructionIdFnProto,
IrInstructionIdTestComptime,
IrInstructionIdPtrCast,
IrInstructionIdBitCast,
IrInstructionIdWidenOrShorten,
IrInstructionIdIntToPtr,
IrInstructionIdPtrToInt,
IrInstructionIdIntToEnum,
IrInstructionIdIntToErr,
IrInstructionIdErrToInt,
IrInstructionIdCheckSwitchProngs,
IrInstructionIdCheckStatementIsVoid,
IrInstructionIdTypeName,
IrInstructionIdCanImplicitCast,
IrInstructionIdDeclRef,
IrInstructionIdPanic,
IrInstructionIdTagName,
IrInstructionIdTagType,
IrInstructionIdFieldParentPtr,
IrInstructionIdOffsetOf,
IrInstructionIdTypeInfo,
IrInstructionIdTypeId,
IrInstructionIdSetEvalBranchQuota,
IrInstructionIdPtrTypeOf,
IrInstructionIdAlignCast,
IrInstructionIdOpaqueType,
IrInstructionIdSetAlignStack,
IrInstructionIdArgType,
IrInstructionIdExport,
IrInstructionIdErrorReturnTrace,
IrInstructionIdErrorUnion,
IrInstructionIdCancel,
IrInstructionIdGetImplicitAllocator,
IrInstructionIdCoroId,
IrInstructionIdCoroAlloc,
IrInstructionIdCoroSize,
IrInstructionIdCoroBegin,
IrInstructionIdCoroAllocFail,
IrInstructionIdCoroSuspend,
IrInstructionIdCoroEnd,
IrInstructionIdCoroFree,
IrInstructionIdCoroResume,
IrInstructionIdCoroSave,
IrInstructionIdCoroPromise,
IrInstructionIdCoroAllocHelper,
IrInstructionIdAtomicRmw,
IrInstructionIdAtomicLoad,
IrInstructionIdPromiseResultType,
IrInstructionIdAwaitBookkeeping,
IrInstructionIdSaveErrRetAddr,
IrInstructionIdAddImplicitReturnType,
IrInstructionIdMergeErrRetTraces,
IrInstructionIdMarkErrRetTracePtr,
IrInstructionIdSqrt,
};
struct IrInstruction {
IrInstructionId id;
Scope *scope;
AstNode *source_node;
ConstExprValue value;
size_t debug_id;
LLVMValueRef llvm_value;
// if ref_count is zero and the instruction has no side effects,
// the instruction can be omitted in codegen
size_t ref_count;
IrInstruction *other;
IrBasicBlock *owner_bb;
// true if this instruction was generated by zig and not from user code
bool is_gen;
};
struct IrInstructionCondBr {
IrInstruction base;
IrInstruction *condition;
IrBasicBlock *then_block;
IrBasicBlock *else_block;
IrInstruction *is_comptime;
};
struct IrInstructionBr {
IrInstruction base;
IrBasicBlock *dest_block;
IrInstruction *is_comptime;
};
struct IrInstructionSwitchBrCase {
IrInstruction *value;
IrBasicBlock *block;
};
struct IrInstructionSwitchBr {
IrInstruction base;
IrInstruction *target_value;
IrBasicBlock *else_block;
size_t case_count;
IrInstructionSwitchBrCase *cases;
IrInstruction *is_comptime;
};
struct IrInstructionSwitchVar {
IrInstruction base;
IrInstruction *target_value_ptr;
IrInstruction *prong_value;
};
struct IrInstructionSwitchTarget {
IrInstruction base;
IrInstruction *target_value_ptr;
};
struct IrInstructionPhi {
IrInstruction base;
size_t incoming_count;
IrBasicBlock **incoming_blocks;
IrInstruction **incoming_values;
};
enum IrUnOp {
IrUnOpInvalid,
IrUnOpBinNot,
IrUnOpNegation,
IrUnOpNegationWrap,
IrUnOpDereference,
IrUnOpMaybe,
};
struct IrInstructionUnOp {
IrInstruction base;
IrUnOp op_id;
IrInstruction *value;
};
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,
IrBinOpMergeErrorSets,
};
struct IrInstructionBinOp {
IrInstruction base;
IrInstruction *op1;
IrBinOp op_id;
IrInstruction *op2;
bool safety_check_on;
};
struct IrInstructionDeclVar {
IrInstruction base;
VariableTableEntry *var;
IrInstruction *var_type;
IrInstruction *align_value;
IrInstruction *init_value;
};
struct IrInstructionLoadPtr {
IrInstruction base;
IrInstruction *ptr;
};
struct IrInstructionStorePtr {
IrInstruction base;
IrInstruction *ptr;
IrInstruction *value;
};
struct IrInstructionFieldPtr {
IrInstruction base;
IrInstruction *container_ptr;
Buf *field_name_buffer;
IrInstruction *field_name_expr;
bool is_const;
};
struct IrInstructionStructFieldPtr {
IrInstruction base;
IrInstruction *struct_ptr;
TypeStructField *field;
bool is_const;
};
struct IrInstructionUnionFieldPtr {
IrInstruction base;
IrInstruction *union_ptr;
TypeUnionField *field;
bool is_const;
};
struct IrInstructionElemPtr {
IrInstruction base;
IrInstruction *array_ptr;
IrInstruction *elem_index;
bool is_const;
bool safety_check_on;
};
struct IrInstructionVarPtr {
IrInstruction base;
VariableTableEntry *var;
bool is_const;
bool is_volatile;
};
struct IrInstructionCall {
IrInstruction base;
IrInstruction *fn_ref;
FnTableEntry *fn_entry;
size_t arg_count;
IrInstruction **args;
bool is_comptime;
LLVMValueRef tmp_ptr;
FnInline fn_inline;
bool is_async;
IrInstruction *async_allocator;
IrInstruction *new_stack;
};
struct IrInstructionConst {
IrInstruction base;
};
// 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 IrInstructionReturn {
IrInstruction base;
IrInstruction *value;
};
// TODO get rid of this instruction, replace with instructions for each op code
struct IrInstructionCast {
IrInstruction base;
IrInstruction *value;
TypeTableEntry *dest_type;
CastOp cast_op;
LLVMValueRef tmp_ptr;
};
struct IrInstructionContainerInitList {
IrInstruction base;
IrInstruction *container_type;
size_t item_count;
IrInstruction **items;
LLVMValueRef tmp_ptr;
};
struct IrInstructionContainerInitFieldsField {
Buf *name;
IrInstruction *value;
AstNode *source_node;
TypeStructField *type_struct_field;
};
struct IrInstructionContainerInitFields {
IrInstruction base;
IrInstruction *container_type;
size_t field_count;
IrInstructionContainerInitFieldsField *fields;
};
struct IrInstructionStructInitField {
IrInstruction *value;
TypeStructField *type_struct_field;
};
struct IrInstructionStructInit {
IrInstruction base;
TypeTableEntry *struct_type;
size_t field_count;
IrInstructionStructInitField *fields;
LLVMValueRef tmp_ptr;
};
struct IrInstructionUnionInit {
IrInstruction base;
TypeTableEntry *union_type;
TypeUnionField *field;
IrInstruction *init_value;
LLVMValueRef tmp_ptr;
};
struct IrInstructionUnreachable {
IrInstruction base;
};
struct IrInstructionTypeOf {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionToPtrType {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionPtrTypeChild {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionSetCold {
IrInstruction base;
IrInstruction *is_cold;
};
struct IrInstructionSetRuntimeSafety {
IrInstruction base;
IrInstruction *safety_on;
};
struct IrInstructionSetFloatMode {
IrInstruction base;
IrInstruction *scope_value;
IrInstruction *mode_value;
};
struct IrInstructionArrayType {
IrInstruction base;
IrInstruction *size;
IrInstruction *child_type;
};
struct IrInstructionPromiseType {
IrInstruction base;
IrInstruction *payload_type;
};
struct IrInstructionSliceType {
IrInstruction base;
IrInstruction *align_value;
bool is_const;
bool is_volatile;
IrInstruction *child_type;
};
struct IrInstructionAsm {
IrInstruction base;
// Most information on inline assembly comes from the source node.
IrInstruction **input_list;
IrInstruction **output_types;
VariableTableEntry **output_vars;
size_t return_count;
bool has_side_effects;
};
struct IrInstructionSizeOf {
IrInstruction base;
IrInstruction *type_value;
};
// returns true if nonnull, returns false if null
// this is so that `zeroes` sets maybe values to null
struct IrInstructionTestNonNull {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionUnwrapMaybe {
IrInstruction base;
IrInstruction *value;
bool safety_check_on;
};
struct IrInstructionCtz {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionClz {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionUnionTag {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionImport {
IrInstruction base;
IrInstruction *name;
};
struct IrInstructionArrayLen {
IrInstruction base;
IrInstruction *array_value;
};
struct IrInstructionRef {
IrInstruction base;
IrInstruction *value;
LLVMValueRef tmp_ptr;
bool is_const;
bool is_volatile;
};
struct IrInstructionMinValue {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionMaxValue {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionCompileErr {
IrInstruction base;
IrInstruction *msg;
};
struct IrInstructionCompileLog {
IrInstruction base;
size_t msg_count;
IrInstruction **msg_list;
};
struct IrInstructionErrName {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionCImport {
IrInstruction base;
};
struct IrInstructionCInclude {
IrInstruction base;
IrInstruction *name;
};
struct IrInstructionCDefine {
IrInstruction base;
IrInstruction *name;
IrInstruction *value;
};
struct IrInstructionCUndef {
IrInstruction base;
IrInstruction *name;
};
struct IrInstructionEmbedFile {
IrInstruction base;
IrInstruction *name;
};
struct IrInstructionCmpxchg {
IrInstruction base;
IrInstruction *type_value;
IrInstruction *ptr;
IrInstruction *cmp_value;
IrInstruction *new_value;
IrInstruction *success_order_value;
IrInstruction *failure_order_value;
// if this instruction gets to runtime then we know these values:
TypeTableEntry *type;
AtomicOrder success_order;
AtomicOrder failure_order;
bool is_weak;
LLVMValueRef tmp_ptr;
};
struct IrInstructionFence {
IrInstruction base;
IrInstruction *order_value;
// if this instruction gets to runtime then we know these values:
AtomicOrder order;
};
struct IrInstructionTruncate {
IrInstruction base;
IrInstruction *dest_type;
IrInstruction *target;
};
struct IrInstructionIntType {
IrInstruction base;
IrInstruction *is_signed;
IrInstruction *bit_count;
};
struct IrInstructionBoolNot {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionMemset {
IrInstruction base;
IrInstruction *dest_ptr;
IrInstruction *byte;
IrInstruction *count;
};
struct IrInstructionMemcpy {
IrInstruction base;
IrInstruction *dest_ptr;
IrInstruction *src_ptr;
IrInstruction *count;
};
struct IrInstructionSlice {
IrInstruction base;
IrInstruction *ptr;
IrInstruction *start;
IrInstruction *end;
bool safety_check_on;
LLVMValueRef tmp_ptr;
};
struct IrInstructionMemberCount {
IrInstruction base;
IrInstruction *container;
};
struct IrInstructionMemberType {
IrInstruction base;
IrInstruction *container_type;
IrInstruction *member_index;
};
struct IrInstructionMemberName {
IrInstruction base;
IrInstruction *container_type;
IrInstruction *member_index;
};
struct IrInstructionBreakpoint {
IrInstruction base;
};
struct IrInstructionReturnAddress {
IrInstruction base;
};
struct IrInstructionFrameAddress {
IrInstruction base;
};
enum IrOverflowOp {
IrOverflowOpAdd,
IrOverflowOpSub,
IrOverflowOpMul,
IrOverflowOpShl,
};
struct IrInstructionOverflowOp {
IrInstruction base;
IrOverflowOp op;
IrInstruction *type_value;
IrInstruction *op1;
IrInstruction *op2;
IrInstruction *result_ptr;
TypeTableEntry *result_ptr_type;
};
struct IrInstructionAlignOf {
IrInstruction base;
IrInstruction *type_value;
};
// returns true if error, returns false if not error
struct IrInstructionTestErr {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionUnwrapErrCode {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionUnwrapErrPayload {
IrInstruction base;
IrInstruction *value;
bool safety_check_on;
};
struct IrInstructionMaybeWrap {
IrInstruction base;
IrInstruction *value;
LLVMValueRef tmp_ptr;
};
struct IrInstructionErrWrapPayload {
IrInstruction base;
IrInstruction *value;
LLVMValueRef tmp_ptr;
};
struct IrInstructionErrWrapCode {
IrInstruction base;
IrInstruction *value;
LLVMValueRef tmp_ptr;
};
struct IrInstructionFnProto {
IrInstruction base;
IrInstruction **param_types;
IrInstruction *align_value;
IrInstruction *return_type;
IrInstruction *async_allocator_type_value;
bool is_var_args;
};
// true if the target value is compile time known, false otherwise
struct IrInstructionTestComptime {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionPtrCast {
IrInstruction base;
IrInstruction *dest_type;
IrInstruction *ptr;
};
struct IrInstructionBitCast {
IrInstruction base;
IrInstruction *dest_type;
IrInstruction *value;
};
struct IrInstructionWidenOrShorten {
IrInstruction base;
IrInstruction *target;
};
struct IrInstructionPtrToInt {
IrInstruction base;
IrInstruction *target;
};
struct IrInstructionIntToPtr {
IrInstruction base;
IrInstruction *dest_type;
IrInstruction *target;
};
struct IrInstructionIntToEnum {
IrInstruction base;
IrInstruction *target;
};
struct IrInstructionIntToErr {
IrInstruction base;
IrInstruction *target;
};
struct IrInstructionErrToInt {
IrInstruction base;
IrInstruction *target;
};
struct IrInstructionCheckSwitchProngsRange {
IrInstruction *start;
IrInstruction *end;
};
struct IrInstructionCheckSwitchProngs {
IrInstruction base;
IrInstruction *target_value;
IrInstructionCheckSwitchProngsRange *ranges;
size_t range_count;
bool have_else_prong;
};
struct IrInstructionCheckStatementIsVoid {
IrInstruction base;
IrInstruction *statement_value;
};
struct IrInstructionTypeName {
IrInstruction base;
IrInstruction *type_value;
};
struct IrInstructionCanImplicitCast {
IrInstruction base;
IrInstruction *type_value;
IrInstruction *target_value;
};
struct IrInstructionDeclRef {
IrInstruction base;
Tld *tld;
LVal lval;
};
struct IrInstructionPanic {
IrInstruction base;
IrInstruction *msg;
};
struct IrInstructionTagName {
IrInstruction base;
IrInstruction *target;
};
struct IrInstructionTagType {
IrInstruction base;
IrInstruction *target;
};
struct IrInstructionFieldParentPtr {
IrInstruction base;
IrInstruction *type_value;
IrInstruction *field_name;
IrInstruction *field_ptr;
TypeStructField *field;
};
struct IrInstructionOffsetOf {
IrInstruction base;
IrInstruction *type_value;
IrInstruction *field_name;
};
struct IrInstructionTypeInfo {
IrInstruction base;
IrInstruction *type_value;
};
struct IrInstructionTypeId {
IrInstruction base;
IrInstruction *type_value;
};
struct IrInstructionSetEvalBranchQuota {
IrInstruction base;
IrInstruction *new_quota;
};
struct IrInstructionPtrTypeOf {
IrInstruction base;
IrInstruction *align_value;
IrInstruction *child_type;
uint32_t bit_offset_start;
uint32_t bit_offset_end;
bool is_const;
bool is_volatile;
};
struct IrInstructionAlignCast {
IrInstruction base;
IrInstruction *align_bytes;
IrInstruction *target;
};
struct IrInstructionOpaqueType {
IrInstruction base;
};
struct IrInstructionSetAlignStack {
IrInstruction base;
IrInstruction *align_bytes;
};
struct IrInstructionArgType {
IrInstruction base;
IrInstruction *fn_type;
IrInstruction *arg_index;
};
struct IrInstructionExport {
IrInstruction base;
IrInstruction *name;
IrInstruction *linkage;
IrInstruction *target;
};
struct IrInstructionErrorReturnTrace {
IrInstruction base;
enum Nullable {
Null,
NonNull,
} nullable;
};
struct IrInstructionErrorUnion {
IrInstruction base;
IrInstruction *err_set;
IrInstruction *payload;
};
struct IrInstructionCancel {
IrInstruction base;
IrInstruction *target;
};
enum ImplicitAllocatorId {
ImplicitAllocatorIdArg,
ImplicitAllocatorIdLocalVar,
};
struct IrInstructionGetImplicitAllocator {
IrInstruction base;
ImplicitAllocatorId id;
};
struct IrInstructionCoroId {
IrInstruction base;
IrInstruction *promise_ptr;
};
struct IrInstructionCoroAlloc {
IrInstruction base;
IrInstruction *coro_id;
};
struct IrInstructionCoroSize {
IrInstruction base;
};
struct IrInstructionCoroBegin {
IrInstruction base;
IrInstruction *coro_id;
IrInstruction *coro_mem_ptr;
};
struct IrInstructionCoroAllocFail {
IrInstruction base;
IrInstruction *err_val;
};
struct IrInstructionCoroSuspend {
IrInstruction base;
IrInstruction *save_point;
IrInstruction *is_final;
};
struct IrInstructionCoroEnd {
IrInstruction base;
};
struct IrInstructionCoroFree {
IrInstruction base;
IrInstruction *coro_id;
IrInstruction *coro_handle;
};
struct IrInstructionCoroResume {
IrInstruction base;
IrInstruction *awaiter_handle;
};
struct IrInstructionCoroSave {
IrInstruction base;
IrInstruction *coro_handle;
};
struct IrInstructionCoroPromise {
IrInstruction base;
IrInstruction *coro_handle;
};
struct IrInstructionCoroAllocHelper {
IrInstruction base;
IrInstruction *alloc_fn;
IrInstruction *coro_size;
};
struct IrInstructionAtomicRmw {
IrInstruction base;
IrInstruction *operand_type;
IrInstruction *ptr;
IrInstruction *op;
AtomicRmwOp resolved_op;
IrInstruction *operand;
IrInstruction *ordering;
AtomicOrder resolved_ordering;
};
struct IrInstructionAtomicLoad {
IrInstruction base;
IrInstruction *operand_type;
IrInstruction *ptr;
IrInstruction *ordering;
AtomicOrder resolved_ordering;
};
struct IrInstructionPromiseResultType {
IrInstruction base;
IrInstruction *promise_type;
};
struct IrInstructionAwaitBookkeeping {
IrInstruction base;
IrInstruction *promise_result_type;
};
struct IrInstructionSaveErrRetAddr {
IrInstruction base;
};
struct IrInstructionAddImplicitReturnType {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionMergeErrRetTraces {
IrInstruction base;
IrInstruction *coro_promise_ptr;
IrInstruction *src_err_ret_trace_ptr;
IrInstruction *dest_err_ret_trace_ptr;
};
struct IrInstructionMarkErrRetTracePtr {
IrInstruction base;
IrInstruction *err_ret_trace_ptr;
};
struct IrInstructionSqrt {
IrInstruction base;
IrInstruction *type;
IrInstruction *op;
};
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_err_index = 0;
static const size_t err_union_payload_index = 1;
// TODO call graph analysis to find out what this number needs to be for every function
static const size_t stack_trace_ptr_count = 30;
// these belong to the async function
#define RETURN_ADDRESSES_FIELD_NAME "return_addresses"
#define ERR_RET_TRACE_FIELD_NAME "err_ret_trace"
#define RESULT_FIELD_NAME "result"
#define ASYNC_ALLOC_FIELD_NAME "allocFn"
#define ASYNC_FREE_FIELD_NAME "freeFn"
#define AWAITER_HANDLE_FIELD_NAME "awaiter_handle"
// these point to data belonging to the awaiter
#define ERR_RET_TRACE_PTR_FIELD_NAME "err_ret_trace_ptr"
#define RESULT_PTR_FIELD_NAME "result_ptr"
enum FloatMode {
FloatModeOptimized,
FloatModeStrict,
};
#endif