4639 lines
97 KiB
C++
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
|