Commit 3ef2f7058b
Changed files (7)
src/all_types.hpp
@@ -0,0 +1,928 @@
+/*
+ * 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.hpp"
+#include "hash_map.hpp"
+#include "errmsg.hpp"
+
+struct AstNode;
+struct ImportTableEntry;
+struct AsmToken;
+struct FnTableEntry;
+struct BlockContext;
+struct TypeTableEntry;
+struct VariableTableEntry;
+struct Cast;
+struct BuiltinFnEntry;
+struct LabelTableEntry;
+struct TypeStructField;
+struct CodeGen;
+
+enum OutType {
+ OutTypeUnknown,
+ OutTypeExe,
+ OutTypeLib,
+ OutTypeObj,
+};
+
+enum CodeGenBuildType {
+ CodeGenBuildTypeDebug,
+ CodeGenBuildTypeRelease,
+};
+
+enum CastOp {
+ CastOpNothing,
+ CastOpPtrToInt,
+ CastOpIntWidenOrShorten,
+ CastOpToUnknownSizeArray,
+ CastOpMaybeWrap,
+ CastOpPointerReinterpret,
+};
+
+struct Cast {
+ CastOp op;
+ // if op is CastOpArrayToString, this will be a pointer to
+ // the string struct on the stack
+ LLVMValueRef ptr;
+ TypeTableEntry *after_type;
+ AstNode *source_node;
+};
+
+struct Expr {
+ TypeTableEntry *type_entry;
+ // the context in which this expression is evaluated.
+ // for blocks, this points to the containing scope, not the block's own scope for its children.
+ BlockContext *block_context;
+
+ // may be null for no cast
+ Cast implicit_cast; // happens first
+ Cast implicit_maybe_cast; // happens second
+};
+
+struct NumLitCodeGen {
+ TypeTableEntry *resolved_type;
+};
+
+struct StructValExprCodeGen {
+ TypeTableEntry *type_entry;
+ LLVMValueRef ptr;
+ AstNode *source_node;
+};
+
+struct TopLevelDecl {
+ // reminder: hash tables must be initialized before use
+ HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> deps;
+ Buf *name;
+ ImportTableEntry *import;
+ // set this flag temporarily to detect infinite loops
+ bool in_current_deps;
+};
+
+enum NodeType {
+ NodeTypeRoot,
+ NodeTypeRootExportDecl,
+ NodeTypeFnProto,
+ NodeTypeFnDef,
+ NodeTypeFnDecl,
+ NodeTypeParamDecl,
+ NodeTypeType,
+ NodeTypeBlock,
+ NodeTypeExternBlock,
+ NodeTypeDirective,
+ NodeTypeReturnExpr,
+ NodeTypeVariableDeclaration,
+ NodeTypeBinOpExpr,
+ NodeTypeCastExpr,
+ NodeTypeNumberLiteral,
+ NodeTypeStringLiteral,
+ NodeTypeCharLiteral,
+ NodeTypeUnreachable,
+ NodeTypeSymbol,
+ NodeTypePrefixOpExpr,
+ NodeTypeFnCallExpr,
+ NodeTypeArrayAccessExpr,
+ NodeTypeSliceExpr,
+ NodeTypeFieldAccessExpr,
+ NodeTypeUse,
+ NodeTypeVoid,
+ NodeTypeBoolLiteral,
+ NodeTypeNullLiteral,
+ NodeTypeIfBoolExpr,
+ NodeTypeIfVarExpr,
+ NodeTypeWhileExpr,
+ NodeTypeLabel,
+ NodeTypeGoto,
+ NodeTypeBreak,
+ NodeTypeContinue,
+ NodeTypeAsmExpr,
+ NodeTypeStructDecl,
+ NodeTypeStructField,
+ NodeTypeStructValueExpr,
+ NodeTypeStructValueField,
+ NodeTypeEnumDecl,
+ NodeTypeEnumField,
+ NodeTypeCompilerFnExpr,
+ NodeTypeCompilerFnType,
+};
+
+struct AstNodeRoot {
+ ZigList<AstNode *> top_level_decls;
+};
+
+enum VisibMod {
+ VisibModPrivate,
+ VisibModPub,
+ VisibModExport,
+};
+
+struct AstNodeFnProto {
+ ZigList<AstNode *> *directives;
+ VisibMod visib_mod;
+ Buf name;
+ ZigList<AstNode *> params;
+ AstNode *return_type;
+ bool is_var_args;
+
+ // populated by semantic analyzer:
+
+ // the extern block this fn proto is inside. can be null.
+ AstNode *extern_node;
+ // the struct decl node this fn proto is inside. can be null.
+ AstNode *struct_node;
+ // the function definition this fn proto is inside. can be null.
+ AstNode *fn_def_node;
+ FnTableEntry *fn_table_entry;
+ bool skip;
+ TopLevelDecl top_level_decl;
+};
+
+struct AstNodeFnDef {
+ AstNode *fn_proto;
+ AstNode *body;
+
+ // populated by semantic analyzer
+ TypeTableEntry *implicit_return_type;
+ BlockContext *block_context;
+};
+
+struct AstNodeFnDecl {
+ AstNode *fn_proto;
+};
+
+struct AstNodeParamDecl {
+ Buf name;
+ AstNode *type;
+
+ // populated by semantic analyzer
+ VariableTableEntry *variable;
+};
+
+enum AstNodeTypeType {
+ AstNodeTypeTypePrimitive,
+ AstNodeTypeTypePointer,
+ AstNodeTypeTypeArray,
+ AstNodeTypeTypeMaybe,
+ AstNodeTypeTypeCompilerExpr,
+};
+
+struct AstNodeType {
+ AstNodeTypeType type;
+ Buf primitive_name;
+ AstNode *child_type;
+ AstNode *array_size; // can be null
+ bool is_const;
+ bool is_noalias;
+ AstNode *compiler_expr;
+
+ // populated by semantic analyzer
+ TypeTableEntry *entry;
+};
+
+struct AstNodeBlock {
+ ZigList<AstNode *> statements;
+
+ // populated by semantic analyzer
+ BlockContext *block_context;
+ Expr resolved_expr;
+};
+
+struct AstNodeReturnExpr {
+ // might be null in case of return void;
+ AstNode *expr;
+
+ // populated by semantic analyzer:
+ Expr resolved_expr;
+};
+
+struct AstNodeVariableDeclaration {
+ Buf symbol;
+ bool is_const;
+ VisibMod visib_mod;
+ // one or both of type and expr will be non null
+ AstNode *type;
+ AstNode *expr;
+
+ // populated by semantic analyzer
+ TopLevelDecl top_level_decl;
+ Expr resolved_expr;
+};
+
+enum BinOpType {
+ BinOpTypeInvalid,
+ BinOpTypeAssign,
+ BinOpTypeAssignTimes,
+ BinOpTypeAssignDiv,
+ BinOpTypeAssignMod,
+ BinOpTypeAssignPlus,
+ BinOpTypeAssignMinus,
+ BinOpTypeAssignBitShiftLeft,
+ BinOpTypeAssignBitShiftRight,
+ BinOpTypeAssignBitAnd,
+ BinOpTypeAssignBitXor,
+ BinOpTypeAssignBitOr,
+ BinOpTypeAssignBoolAnd,
+ BinOpTypeAssignBoolOr,
+ BinOpTypeBoolOr,
+ BinOpTypeBoolAnd,
+ BinOpTypeCmpEq,
+ BinOpTypeCmpNotEq,
+ BinOpTypeCmpLessThan,
+ BinOpTypeCmpGreaterThan,
+ BinOpTypeCmpLessOrEq,
+ BinOpTypeCmpGreaterOrEq,
+ BinOpTypeBinOr,
+ BinOpTypeBinXor,
+ BinOpTypeBinAnd,
+ BinOpTypeBitShiftLeft,
+ BinOpTypeBitShiftRight,
+ BinOpTypeAdd,
+ BinOpTypeSub,
+ BinOpTypeMult,
+ BinOpTypeDiv,
+ BinOpTypeMod,
+ BinOpTypeUnwrapMaybe,
+};
+
+struct AstNodeBinOpExpr {
+ AstNode *op1;
+ BinOpType bin_op;
+ AstNode *op2;
+
+ // populated by semantic analyzer:
+ // for when op is BinOpTypeAssign
+ VariableTableEntry *var_entry;
+ Expr resolved_expr;
+};
+
+struct AstNodeFnCallExpr {
+ AstNode *fn_ref_expr;
+ ZigList<AstNode *> params;
+ bool is_builtin;
+
+ // populated by semantic analyzer:
+ BuiltinFnEntry *builtin_fn;
+ Expr resolved_expr;
+};
+
+struct AstNodeArrayAccessExpr {
+ AstNode *array_ref_expr;
+ AstNode *subscript;
+
+ // populated by semantic analyzer:
+ Expr resolved_expr;
+};
+
+struct AstNodeSliceExpr {
+ AstNode *array_ref_expr;
+ AstNode *start;
+ AstNode *end;
+ bool is_const;
+
+ // populated by semantic analyzer:
+ Expr resolved_expr;
+ StructValExprCodeGen resolved_struct_val_expr;
+};
+
+struct AstNodeFieldAccessExpr {
+ AstNode *struct_expr;
+ Buf field_name;
+
+ // populated by semantic analyzer
+ int field_index;
+ TypeStructField *type_struct_field;
+ Expr resolved_expr;
+};
+
+struct AstNodeExternBlock {
+ ZigList<AstNode *> *directives;
+ ZigList<AstNode *> fn_decls;
+};
+
+struct AstNodeDirective {
+ Buf name;
+ Buf param;
+};
+
+struct AstNodeRootExportDecl {
+ Buf type;
+ Buf name;
+ ZigList<AstNode *> *directives;
+};
+
+struct AstNodeCastExpr {
+ AstNode *expr;
+ AstNode *type;
+
+ // populated by semantic analyzer
+ Cast cast;
+ Expr resolved_expr;
+};
+
+enum PrefixOp {
+ PrefixOpInvalid,
+ PrefixOpBoolNot,
+ PrefixOpBinNot,
+ PrefixOpNegation,
+ PrefixOpAddressOf,
+ PrefixOpConstAddressOf,
+ PrefixOpDereference,
+};
+
+struct AstNodePrefixOpExpr {
+ PrefixOp prefix_op;
+ AstNode *primary_expr;
+
+ // populated by semantic analyzer
+ Expr resolved_expr;
+};
+
+struct AstNodeUse {
+ Buf path;
+ ZigList<AstNode *> *directives;
+
+ // populated by semantic analyzer
+ ImportTableEntry *import;
+};
+
+struct AstNodeIfBoolExpr {
+ AstNode *condition;
+ AstNode *then_block;
+ AstNode *else_node; // null, block node, or other if expr node
+
+ // populated by semantic analyzer
+ Expr resolved_expr;
+};
+
+struct AstNodeIfVarExpr {
+ AstNodeVariableDeclaration var_decl;
+ AstNode *then_block;
+ AstNode *else_node; // null, block node, or other if expr node
+
+ // populated by semantic analyzer
+ TypeTableEntry *type;
+ BlockContext *block_context;
+ Expr resolved_expr;
+};
+
+struct AstNodeWhileExpr {
+ AstNode *condition;
+ AstNode *body;
+
+ // populated by semantic analyzer
+ bool condition_always_true;
+ bool contains_break;
+ Expr resolved_expr;
+};
+
+struct AstNodeLabel {
+ Buf name;
+
+ // populated by semantic analyzer
+ LabelTableEntry *label_entry;
+ Expr resolved_expr;
+};
+
+struct AstNodeGoto {
+ Buf name;
+
+ // populated by semantic analyzer
+ LabelTableEntry *label_entry;
+ Expr resolved_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 {
+ int line;
+ int column;
+};
+
+struct AstNodeAsmExpr {
+ bool is_volatile;
+ Buf asm_template;
+ ZigList<SrcPos> offset_map;
+ ZigList<AsmToken> token_list;
+ ZigList<AsmOutput*> output_list;
+ ZigList<AsmInput*> input_list;
+ ZigList<Buf*> clobber_list;
+
+ // populated by semantic analyzer
+ int return_count;
+ Expr resolved_expr;
+};
+
+struct AstNodeStructDecl {
+ Buf name;
+ ZigList<AstNode *> fields;
+ ZigList<AstNode *> fns;
+ ZigList<AstNode *> *directives;
+ VisibMod visib_mod;
+
+ // populated by semantic analyzer
+ TypeTableEntry *type_entry;
+ TopLevelDecl top_level_decl;
+};
+
+struct AstNodeStructField {
+ Buf name;
+ AstNode *type;
+ ZigList<AstNode *> *directives;
+};
+
+struct AstNodeEnumDecl {
+ Buf name;
+ ZigList<AstNode *> fields;
+ ZigList<AstNode *> *directives;
+ VisibMod visib_mod;
+};
+
+struct AstNodeEnumField {
+ Buf name;
+ ZigList<AstNode *> fields; // length 0 means simple enum
+ AstNode *val_expr;
+};
+
+struct AstNodeStringLiteral {
+ Buf buf;
+ bool c;
+
+ // populated by semantic analyzer:
+ Expr resolved_expr;
+};
+
+struct AstNodeCharLiteral {
+ uint8_t value;
+
+ // populated by semantic analyzer:
+ Expr resolved_expr;
+};
+
+enum NumLit {
+ NumLitF32,
+ NumLitF64,
+ NumLitF128,
+ NumLitU8,
+ NumLitU16,
+ NumLitU32,
+ NumLitU64,
+ NumLitI8,
+ NumLitI16,
+ NumLitI32,
+ NumLitI64,
+
+ NumLitCount
+};
+
+struct AstNodeNumberLiteral {
+ NumLit kind;
+
+ // overflow is true if when parsing the number, we discovered it would not
+ // fit without losing data in a uint64_t, int64_t, or double
+ bool overflow;
+
+ union {
+ uint64_t x_uint;
+ int64_t x_int;
+ double x_float;
+ } data;
+
+ // populated by semantic analyzer
+ NumLitCodeGen codegen;
+ Expr resolved_expr;
+};
+
+struct AstNodeStructValueField {
+ Buf name;
+ AstNode *expr;
+
+ // populated by semantic analyzer
+ int index;
+};
+
+struct AstNodeStructValueExpr {
+ AstNode *type;
+ ZigList<AstNode *> fields;
+
+ // populated by semantic analyzer
+ StructValExprCodeGen codegen;
+ Expr resolved_expr;
+};
+
+struct AstNodeCompilerFnExpr {
+ Buf name;
+ AstNode *expr;
+
+ // populated by semantic analyzer
+ Expr resolved_expr;
+};
+
+struct AstNodeCompilerFnType {
+ Buf name;
+ AstNode *type;
+
+ // populated by semantic analyzer
+ Expr resolved_expr;
+ NumLitCodeGen resolved_num_lit;
+};
+
+struct AstNodeNullLiteral {
+ // populated by semantic analyzer
+ StructValExprCodeGen resolved_struct_val_expr;
+ Expr resolved_expr;
+};
+
+struct AstNodeVoidExpr {
+ // populated by semantic analyzer
+ Expr resolved_expr;
+};
+
+struct AstNodeUnreachableExpr {
+ // populated by semantic analyzer
+ Expr resolved_expr;
+};
+
+struct AstNodeSymbolExpr {
+ Buf symbol;
+
+ // populated by semantic analyzer
+ Expr resolved_expr;
+};
+
+struct AstNodeBoolLiteral {
+ bool value;
+
+ // populated by semantic analyzer
+ Expr resolved_expr;
+};
+
+struct AstNodeBreakExpr {
+ // populated by semantic analyzer
+ Expr resolved_expr;
+};
+
+struct AstNodeContinueExpr {
+ // populated by semantic analyzer
+ Expr resolved_expr;
+};
+
+struct AstNode {
+ enum NodeType type;
+ int line;
+ int column;
+ uint32_t create_index; // for determinism purposes
+ ImportTableEntry *owner;
+ union {
+ AstNodeRoot root;
+ AstNodeRootExportDecl root_export_decl;
+ AstNodeFnDef fn_def;
+ AstNodeFnDecl fn_decl;
+ AstNodeFnProto fn_proto;
+ AstNodeType type;
+ AstNodeParamDecl param_decl;
+ AstNodeBlock block;
+ AstNodeReturnExpr return_expr;
+ AstNodeVariableDeclaration variable_declaration;
+ AstNodeBinOpExpr bin_op_expr;
+ AstNodeExternBlock extern_block;
+ AstNodeDirective directive;
+ AstNodeCastExpr cast_expr;
+ AstNodePrefixOpExpr prefix_op_expr;
+ AstNodeFnCallExpr fn_call_expr;
+ AstNodeArrayAccessExpr array_access_expr;
+ AstNodeSliceExpr slice_expr;
+ AstNodeUse use;
+ AstNodeIfBoolExpr if_bool_expr;
+ AstNodeIfVarExpr if_var_expr;
+ AstNodeWhileExpr while_expr;
+ AstNodeLabel label;
+ AstNodeGoto goto_expr;
+ AstNodeAsmExpr asm_expr;
+ AstNodeFieldAccessExpr field_access_expr;
+ AstNodeStructDecl struct_decl;
+ AstNodeStructField struct_field;
+ AstNodeEnumDecl enum_decl;
+ AstNodeEnumField enum_field;
+ AstNodeStringLiteral string_literal;
+ AstNodeCharLiteral char_literal;
+ AstNodeNumberLiteral number_literal;
+ AstNodeStructValueExpr struct_val_expr;
+ AstNodeStructValueField struct_val_field;
+ AstNodeCompilerFnExpr compiler_fn_expr;
+ AstNodeCompilerFnType compiler_fn_type;
+ AstNodeNullLiteral null_literal;
+ AstNodeVoidExpr void_expr;
+ AstNodeUnreachableExpr unreachable_expr;
+ AstNodeSymbolExpr symbol_expr;
+ AstNodeBoolLiteral bool_literal;
+ AstNodeBreakExpr break_expr;
+ AstNodeContinueExpr continue_expr;
+ } data;
+};
+
+enum AsmTokenId {
+ AsmTokenIdTemplate,
+ AsmTokenIdPercent,
+ AsmTokenIdVar,
+};
+
+struct AsmToken {
+ enum AsmTokenId id;
+ int start;
+ int end;
+};
+
+struct TypeTableEntryPointer {
+ TypeTableEntry *child_type;
+ bool is_const;
+ bool is_noalias;
+};
+
+struct TypeTableEntryInt {
+ bool is_signed;
+};
+
+struct TypeTableEntryArray {
+ TypeTableEntry *child_type;
+ uint64_t len;
+};
+
+struct TypeStructField {
+ Buf *name;
+ TypeTableEntry *type_entry;
+};
+
+struct TypeTableEntryStruct {
+ AstNode *decl_node;
+ bool is_packed;
+ int field_count;
+ TypeStructField *fields;
+ uint64_t size_bytes;
+ bool is_invalid; // true if any fields are invalid
+ bool is_unknown_size_array;
+ // reminder: hash tables must be initialized before use
+ HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
+
+ // set this flag temporarily to detect infinite loops
+ bool embedded_in_current;
+ bool reported_infinite_err;
+};
+
+struct TypeTableEntryNumLit {
+ NumLit kind;
+};
+
+struct TypeTableEntryMaybe {
+ TypeTableEntry *child_type;
+};
+
+enum TypeTableEntryId {
+ TypeTableEntryIdInvalid,
+ TypeTableEntryIdVoid,
+ TypeTableEntryIdBool,
+ TypeTableEntryIdUnreachable,
+ TypeTableEntryIdInt,
+ TypeTableEntryIdFloat,
+ TypeTableEntryIdPointer,
+ TypeTableEntryIdArray,
+ TypeTableEntryIdStruct,
+ TypeTableEntryIdNumberLiteral,
+ TypeTableEntryIdMaybe,
+};
+
+struct TypeTableEntry {
+ TypeTableEntryId id;
+
+ LLVMTypeRef type_ref;
+ LLVMZigDIType *di_type;
+ uint64_t size_in_bits;
+ uint64_t align_in_bits;
+
+ Buf name;
+
+ union {
+ TypeTableEntryPointer pointer;
+ TypeTableEntryInt integral;
+ TypeTableEntryArray array;
+ TypeTableEntryStruct structure;
+ TypeTableEntryNumLit num_lit;
+ TypeTableEntryMaybe maybe;
+ } data;
+
+ // use these fields to make sure we don't duplicate type table entries for the same type
+ TypeTableEntry *pointer_parent[2][2]; // 0 - const. 1 - noalias
+ TypeTableEntry *unknown_size_array_parent[2][2]; // 0 - const. 1 - noalias
+ HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size;
+ TypeTableEntry *maybe_parent;
+
+};
+
+struct ImporterInfo {
+ ImportTableEntry *import;
+ AstNode *source_node;
+};
+
+struct ImportTableEntry {
+ AstNode *root;
+ Buf *path; // relative to root_source_dir
+ LLVMZigDIFile *di_file;
+ Buf *source_code;
+ ZigList<int> *line_offsets;
+ BlockContext *block_context;
+ ZigList<ImporterInfo> importers;
+
+ // reminder: hash tables must be initialized before use
+ HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
+ HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> type_table;
+};
+
+struct LabelTableEntry {
+ AstNode *label_node;
+ LLVMBasicBlockRef basic_block;
+ bool used;
+ bool entered_from_fallthrough;
+};
+
+enum FnAttrId {
+ FnAttrIdNaked,
+ FnAttrIdAlwaysInline,
+};
+
+struct FnTableEntry {
+ LLVMValueRef fn_value;
+ AstNode *proto_node;
+ AstNode *fn_def_node;
+ bool is_extern;
+ bool internal_linkage;
+ unsigned calling_convention;
+ ImportTableEntry *import_entry;
+ ZigList<FnAttrId> fn_attr_list;
+ // Required to be a pre-order traversal of the AST. (parents must come before children)
+ ZigList<BlockContext *> all_block_contexts;
+ TypeTableEntry *member_of_struct;
+ Buf symbol_name;
+
+ // reminder: hash tables must be initialized before use
+ HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table;
+};
+
+enum BuiltinFnId {
+ BuiltinFnIdInvalid,
+ BuiltinFnIdArithmeticWithOverflow,
+ BuiltinFnIdMemcpy,
+ BuiltinFnIdMemset,
+};
+
+struct BuiltinFnEntry {
+ BuiltinFnId id;
+ Buf name;
+ int param_count;
+ TypeTableEntry *return_type;
+ TypeTableEntry **param_types;
+ LLVMValueRef fn_val;
+};
+
+struct CodeGen {
+ LLVMModuleRef module;
+ ZigList<ErrorMsg*> errors;
+ LLVMBuilderRef builder;
+ LLVMZigDIBuilder *dbuilder;
+ LLVMZigDICompileUnit *compile_unit;
+
+ ZigList<Buf *> lib_search_paths;
+
+ // reminder: hash tables must be initialized before use
+ HashMap<Buf *, LLVMValueRef, buf_hash, buf_eql_buf> str_table;
+ HashMap<Buf *, bool, buf_hash, buf_eql_buf> link_table;
+ HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;
+ HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;
+ HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table;
+ HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> unresolved_top_level_decls;
+
+ uint32_t next_unresolved_index;
+
+ struct {
+ TypeTableEntry *entry_bool;
+ TypeTableEntry *entry_u8;
+ TypeTableEntry *entry_u16;
+ TypeTableEntry *entry_u32;
+ TypeTableEntry *entry_u64;
+ TypeTableEntry *entry_i8;
+ TypeTableEntry *entry_i16;
+ TypeTableEntry *entry_i32;
+ TypeTableEntry *entry_i64;
+ TypeTableEntry *entry_isize;
+ TypeTableEntry *entry_usize;
+ TypeTableEntry *entry_f32;
+ TypeTableEntry *entry_f64;
+ TypeTableEntry *entry_c_string_literal;
+ TypeTableEntry *entry_void;
+ TypeTableEntry *entry_unreachable;
+ TypeTableEntry *entry_invalid;
+ } builtin_types;
+
+ TypeTableEntry *num_lit_types[NumLitCount];
+
+ LLVMTargetDataRef target_data_ref;
+ unsigned pointer_size_bytes;
+ bool is_static;
+ bool strip_debug_symbols;
+ bool have_exported_main;
+ bool link_libc;
+ Buf *libc_path;
+ CodeGenBuildType build_type;
+ LLVMTargetMachineRef target_machine;
+ LLVMZigDIFile *dummy_di_file;
+ bool is_native_target;
+ Buf *root_source_dir;
+ Buf *root_out_name;
+
+ // The function definitions this module includes. There must be a corresponding
+ // fn_protos entry.
+ ZigList<FnTableEntry *> fn_defs;
+ // The function prototypes this module includes. In the case of external declarations,
+ // there will not be a corresponding fn_defs entry.
+ ZigList<FnTableEntry *> fn_protos;
+ ZigList<VariableTableEntry *> global_vars;
+
+ OutType out_type;
+ FnTableEntry *cur_fn;
+ BlockContext *cur_block_context;
+ ZigList<LLVMBasicBlockRef> break_block_stack;
+ ZigList<LLVMBasicBlockRef> continue_block_stack;
+ bool c_stdint_used;
+ AstNode *root_export_decl;
+ int version_major;
+ int version_minor;
+ int version_patch;
+ bool verbose;
+ ErrColor err_color;
+ ImportTableEntry *root_import;
+ ImportTableEntry *bootstrap_import;
+ LLVMValueRef memcpy_fn_val;
+ bool error_during_imports;
+};
+
+struct VariableTableEntry {
+ Buf name;
+ TypeTableEntry *type;
+ LLVMValueRef value_ref;
+ bool is_const;
+ bool is_ptr; // if true, value_ref is a pointer
+ AstNode *decl_node;
+ LLVMZigDILocalVariable *di_loc_var;
+ int arg_index;
+};
+
+struct BlockContext {
+ AstNode *node; // either NodeTypeFnDef or NodeTypeBlock or NodeTypeRoot
+ FnTableEntry *fn_entry; // null at the module scope
+ BlockContext *parent; // null when this is the root
+ HashMap<Buf *, VariableTableEntry *, buf_hash, buf_eql_buf> variable_table;
+ ZigList<Cast *> cast_expr_alloca_list;
+ ZigList<StructValExprCodeGen *> struct_val_expr_alloca_list;
+ AstNode *parent_loop_node;
+ AstNode *next_child_parent_loop_node;
+ LLVMZigDIScope *di_scope;
+};
+
+#endif
src/analyze.cpp
@@ -6,6 +6,7 @@
*/
#include "analyze.hpp"
+#include "parser.hpp"
#include "error.hpp"
#include "zig_llvm.hpp"
#include "os.hpp"
@@ -14,7 +15,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
TypeTableEntry *expected_type, AstNode *node);
static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,
AstNode *node, AstNodeNumberLiteral *out_number_literal);
-static void collect_type_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *type_node, DeclNode *decl_node);
+static void collect_type_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *type_node, TopLevelDecl *decl_node);
static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import,
BlockContext *context, TypeTableEntry *expected_type, AstNode *node);
@@ -317,7 +318,7 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context,
out_number_literal->kind = NumLitU8;
out_number_literal->overflow = false;
out_number_literal->data.x_uint = (op1_lit.data.x_uint != op2_lit.data.x_uint);
- return node->codegen_node->expr_node.type_entry;
+ return get_resolved_expr(node)->type_entry;
} else {
return g->builtin_types.entry_invalid;
}
@@ -330,7 +331,7 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context,
out_number_literal->kind = NumLitU8;
out_number_literal->overflow = false;
out_number_literal->data.x_uint = (op1_lit.data.x_uint < op2_lit.data.x_uint);
- return node->codegen_node->expr_node.type_entry;
+ return get_resolved_expr(node)->type_entry;
} else {
return g->builtin_types.entry_invalid;
}
@@ -343,7 +344,7 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context,
out_number_literal->kind = NumLitU64;
out_number_literal->overflow = false;
out_number_literal->data.x_uint = (op1_lit.data.x_uint % op2_lit.data.x_uint);
- return node->codegen_node->expr_node.type_entry;
+ return get_resolved_expr(node)->type_entry;
} else {
return g->builtin_types.entry_invalid;
}
@@ -390,20 +391,20 @@ static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,
switch (node->type) {
case NodeTypeNumberLiteral:
*out_number_literal = node->data.number_literal;
- return node->codegen_node->expr_node.type_entry;
+ return get_resolved_expr(node)->type_entry;
case NodeTypeBoolLiteral:
- out_number_literal->data.x_uint = node->data.bool_literal ? 1 : 0;
- return node->codegen_node->expr_node.type_entry;
+ out_number_literal->data.x_uint = node->data.bool_literal.value ? 1 : 0;
+ return get_resolved_expr(node)->type_entry;
case NodeTypeNullLiteral:
- return node->codegen_node->expr_node.type_entry;
+ return get_resolved_expr(node)->type_entry;
case NodeTypeBinOpExpr:
return eval_const_expr_bin_op(g, context, node, out_number_literal);
case NodeTypeCompilerFnType:
{
Buf *name = &node->data.compiler_fn_type.name;
- TypeTableEntry *expr_type = node->codegen_node->expr_node.type_entry;
+ TypeTableEntry *expr_type = get_resolved_expr(node)->type_entry;
if (buf_eql_str(name, "sizeof")) {
- TypeTableEntry *target_type = node->data.compiler_fn_type.type->codegen_node->data.type_node.entry;
+ TypeTableEntry *target_type = node->data.compiler_fn_type.type->data.type.entry;
out_number_literal->overflow = false;
out_number_literal->data.x_uint = target_type->size_in_bits / 8;
out_number_literal->kind = get_number_literal_kind_unsigned(out_number_literal->data.x_uint);
@@ -420,11 +421,11 @@ static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,
}
case NodeTypeSymbol:
{
- VariableTableEntry *var = find_variable(context, &node->data.symbol);
+ VariableTableEntry *var = find_variable(context, &node->data.symbol_expr.symbol);
assert(var);
AstNode *decl_node = var->decl_node;
AstNode *expr_node = decl_node->data.variable_declaration.expr;
- BlockContext *next_context = expr_node->codegen_node->expr_node.block_context;
+ BlockContext *next_context = get_resolved_expr(expr_node)->block_context;
return eval_const_expr(g, next_context, expr_node, out_number_literal);
}
default:
@@ -436,8 +437,6 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry
BlockContext *context, bool noalias_allowed)
{
assert(node->type == NodeTypeType);
- alloc_codegen_node(node);
- TypeNode *type_node = &node->codegen_node->data.type_node;
switch (node->data.type.type) {
case AstNodeTypeTypePrimitive:
{
@@ -447,13 +446,13 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry
table_entry = g->primitive_type_table.maybe_get(name);
}
if (table_entry) {
- type_node->entry = table_entry->value;
+ node->data.type.entry = table_entry->value;
} else {
add_node_error(g, node,
buf_sprintf("invalid type name: '%s'", buf_ptr(name)));
- type_node->entry = g->builtin_types.entry_invalid;
+ node->data.type.entry = g->builtin_types.entry_invalid;
}
- return type_node->entry;
+ return node->data.type.entry;
}
case AstNodeTypeTypePointer:
{
@@ -468,19 +467,19 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry
}
resolve_type(g, node->data.type.child_type, import, context, false);
- TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry;
+ TypeTableEntry *child_type = node->data.type.child_type->data.type.entry;
assert(child_type);
if (child_type->id == TypeTableEntryIdUnreachable) {
add_node_error(g, node,
buf_create_from_str("pointer to unreachable not allowed"));
- type_node->entry = g->builtin_types.entry_invalid;
- return type_node->entry;
+ node->data.type.entry = g->builtin_types.entry_invalid;
+ return node->data.type.entry;
} else if (child_type->id == TypeTableEntryIdInvalid) {
- type_node->entry = child_type;
+ node->data.type.entry = child_type;
return child_type;
} else {
- type_node->entry = get_pointer_to_type(g, child_type, node->data.type.is_const, use_noalias);
- return type_node->entry;
+ node->data.type.entry = get_pointer_to_type(g, child_type, node->data.type.is_const, use_noalias);
+ return node->data.type.entry;
}
}
case AstNodeTypeTypeArray:
@@ -501,16 +500,16 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry
if (child_type->id == TypeTableEntryIdUnreachable) {
add_node_error(g, node,
buf_create_from_str("array of unreachable not allowed"));
- type_node->entry = g->builtin_types.entry_invalid;
- return type_node->entry;
+ node->data.type.entry = g->builtin_types.entry_invalid;
+ return node->data.type.entry;
}
if (size_node) {
TypeTableEntry *size_type = analyze_expression(g, import, context,
g->builtin_types.entry_usize, size_node);
if (size_type->id == TypeTableEntryIdInvalid) {
- type_node->entry = g->builtin_types.entry_invalid;
- return type_node->entry;
+ node->data.type.entry = g->builtin_types.entry_invalid;
+ return node->data.type.entry;
}
AstNodeNumberLiteral number_literal;
@@ -520,27 +519,27 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry
if (resolved_type->data.integral.is_signed) {
add_node_error(g, size_node,
buf_create_from_str("array size must be unsigned integer"));
- type_node->entry = g->builtin_types.entry_invalid;
+ node->data.type.entry = g->builtin_types.entry_invalid;
} else {
- type_node->entry = get_array_type(g, import, child_type, number_literal.data.x_uint);
+ node->data.type.entry = get_array_type(g, import, child_type, number_literal.data.x_uint);
}
} else {
add_node_error(g, size_node,
buf_create_from_str("unable to resolve constant expression"));
- type_node->entry = g->builtin_types.entry_invalid;
+ node->data.type.entry = g->builtin_types.entry_invalid;
}
- return type_node->entry;
+ return node->data.type.entry;
} else {
- type_node->entry = get_unknown_size_array_type(g, import, child_type,
+ node->data.type.entry = get_unknown_size_array_type(g, import, child_type,
node->data.type.is_const, use_noalias);
- return type_node->entry;
+ return node->data.type.entry;
}
}
case AstNodeTypeTypeMaybe:
{
resolve_type(g, node->data.type.child_type, import, context, false);
- TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry;
+ TypeTableEntry *child_type = node->data.type.child_type->data.type.entry;
assert(child_type);
if (child_type->id == TypeTableEntryIdUnreachable) {
add_node_error(g, node,
@@ -548,22 +547,22 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry
} else if (child_type->id == TypeTableEntryIdInvalid) {
return child_type;
}
- type_node->entry = get_maybe_type(g, import, child_type);
- return type_node->entry;
+ node->data.type.entry = get_maybe_type(g, import, child_type);
+ return node->data.type.entry;
}
case AstNodeTypeTypeCompilerExpr:
{
AstNode *compiler_expr_node = node->data.type.compiler_expr;
Buf *fn_name = &compiler_expr_node->data.compiler_fn_expr.name;
if (buf_eql_str(fn_name, "typeof")) {
- type_node->entry = analyze_expression(g, import, context, nullptr,
+ node->data.type.entry = analyze_expression(g, import, context, nullptr,
compiler_expr_node->data.compiler_fn_expr.expr);
} else {
add_node_error(g, node,
buf_sprintf("invalid compiler function: '%s'", buf_ptr(fn_name)));
- type_node->entry = g->builtin_types.entry_invalid;
+ node->data.type.entry = g->builtin_types.entry_invalid;
}
- return type_node->entry;
+ return node->data.type.entry;
}
}
zig_unreachable();
@@ -631,8 +630,7 @@ static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_
Buf *name = &label_node->data.label.name;
fn_table_entry->label_table.put(name, label_entry);
- alloc_codegen_node(label_node);
- label_node->codegen_node->data.label_entry = label_entry;
+ label_node->data.label.label_entry = label_entry;
}
}
@@ -732,7 +730,8 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
AstNode *struct_node = proto_node->data.fn_proto.struct_node;
TypeTableEntry *struct_type;
if (struct_node) {
- struct_type = struct_node->codegen_node->data.struct_decl_node.type_entry;
+ assert(struct_node->type == NodeTypeStructDecl);
+ struct_type = struct_node->data.struct_decl.type_entry;
} else {
struct_type = nullptr;
}
@@ -749,13 +748,14 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
if (entry) {
add_node_error(g, proto_node,
buf_sprintf("redefinition of '%s'", buf_ptr(proto_name)));
- proto_node->codegen_node->data.fn_proto_node.skip = true;
+ proto_node->data.fn_proto.skip = true;
skip = true;
} else if (is_pub) {
+ // TODO is this else if branch a mistake?
auto entry = fn_table->maybe_get(proto_name);
if (entry) {
add_node_error(g, proto_node, buf_sprintf("redefinition of '%s'", buf_ptr(proto_name)));
- proto_node->codegen_node->data.fn_proto_node.skip = true;
+ proto_node->data.fn_proto.skip = true;
skip = true;
}
}
@@ -804,7 +804,7 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
resolve_function_proto(g, proto_node, fn_table_entry, import);
- proto_node->codegen_node->data.fn_proto_node.fn_table_entry = fn_table_entry;
+ proto_node->data.fn_proto.fn_table_entry = fn_table_entry;
if (fn_def_node) {
preview_function_labels(g, fn_def_node->data.fn_def.body, fn_table_entry);
@@ -888,8 +888,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
break;
case NodeTypeStructDecl:
{
- StructDeclNode *struct_codegen = &node->codegen_node->data.struct_decl_node;
- TypeTableEntry *type_entry = struct_codegen->type_entry;
+ TypeTableEntry *type_entry = node->data.struct_decl.type_entry;
resolve_struct_type(g, import, type_entry);
@@ -962,8 +961,8 @@ static TypeTableEntry *get_return_type(BlockContext *context) {
AstNode *fn_proto_node = fn_entry->proto_node;
assert(fn_proto_node->type == NodeTypeFnProto);
AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
- assert(return_type_node->codegen_node);
- return return_type_node->codegen_node->data.type_node.entry;
+ assert(return_type_node->type == NodeTypeType);
+ return return_type_node->data.type.entry;
}
static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type, TypeTableEntry *other_type) {
@@ -1003,15 +1002,14 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type,
zig_unreachable();
}
-static TypeTableEntry * resolve_rhs_number_literal(CodeGen *g, AstNode *non_literal_node,
+static TypeTableEntry *resolve_rhs_number_literal(CodeGen *g, AstNode *non_literal_node,
TypeTableEntry *non_literal_type, AstNode *literal_node, TypeTableEntry *literal_type)
{
- assert(literal_node->codegen_node);
- NumberLiteralNode *codegen_num_lit = &literal_node->codegen_node->data.num_lit_node;
+ NumLitCodeGen *num_lit_codegen = get_resolved_num_lit(literal_node);
if (non_literal_type && num_lit_fits_in_other_type(g, literal_type, non_literal_type)) {
- assert(!codegen_num_lit->resolved_type);
- codegen_num_lit->resolved_type = non_literal_type;
+ assert(!num_lit_codegen->resolved_type);
+ num_lit_codegen->resolved_type = non_literal_type;
return non_literal_type;
} else {
return nullptr;
@@ -1024,11 +1022,8 @@ static TypeTableEntry * resolve_number_literals(CodeGen *g, AstNode *node1, AstN
if (type1->id == TypeTableEntryIdNumberLiteral &&
type2->id == TypeTableEntryIdNumberLiteral)
{
- assert(node1->codegen_node);
- assert(node2->codegen_node);
-
- NumberLiteralNode *codegen_num_lit_1 = &node1->codegen_node->data.num_lit_node;
- NumberLiteralNode *codegen_num_lit_2 = &node2->codegen_node->data.num_lit_node;
+ NumLitCodeGen *codegen_num_lit_1 = get_resolved_num_lit(node1);
+ NumLitCodeGen *codegen_num_lit_2 = get_resolved_num_lit(node2);
assert(!codegen_num_lit_1->resolved_type);
assert(!codegen_num_lit_2->resolved_type);
@@ -1113,9 +1108,10 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont
if (actual_type->id == TypeTableEntryIdNumberLiteral &&
num_lit_fits_in_other_type(g, actual_type, expected_type))
{
- assert(!node->codegen_node->data.num_lit_node.resolved_type ||
- node->codegen_node->data.num_lit_node.resolved_type == expected_type);
- node->codegen_node->data.num_lit_node.resolved_type = expected_type;
+ NumLitCodeGen *num_lit_code_gen = get_resolved_num_lit(node);
+ assert(!num_lit_code_gen->resolved_type ||
+ num_lit_code_gen->resolved_type == expected_type);
+ num_lit_code_gen->resolved_type = expected_type;
return expected_type;
}
@@ -1134,10 +1130,11 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont
if (resolved_type->id == TypeTableEntryIdInvalid) {
return resolved_type;
}
- node->codegen_node->expr_node.implicit_maybe_cast.op = CastOpMaybeWrap;
- node->codegen_node->expr_node.implicit_maybe_cast.after_type = expected_type;
- node->codegen_node->expr_node.implicit_maybe_cast.source_node = node;
- context->cast_expr_alloca_list.append(&node->codegen_node->expr_node.implicit_maybe_cast);
+ Expr *expr = get_resolved_expr(node);
+ expr->implicit_maybe_cast.op = CastOpMaybeWrap;
+ expr->implicit_maybe_cast.after_type = expected_type;
+ expr->implicit_maybe_cast.source_node = node;
+ context->cast_expr_alloca_list.append(&expr->implicit_maybe_cast);
return expected_type;
}
@@ -1147,9 +1144,10 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont
expected_type->data.integral.is_signed == actual_type->data.integral.is_signed &&
expected_type->size_in_bits > actual_type->size_in_bits)
{
- node->codegen_node->expr_node.implicit_cast.after_type = expected_type;
- node->codegen_node->expr_node.implicit_cast.op = CastOpIntWidenOrShorten;
- node->codegen_node->expr_node.implicit_cast.source_node = node;
+ Expr *expr = get_resolved_expr(node);
+ expr->implicit_cast.after_type = expected_type;
+ expr->implicit_cast.op = CastOpIntWidenOrShorten;
+ expr->implicit_cast.source_node = node;
return expected_type;
}
@@ -1159,10 +1157,11 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont
actual_type->id == TypeTableEntryIdArray &&
actual_type->data.array.child_type == expected_type->data.structure.fields[0].type_entry->data.pointer.child_type)
{
- node->codegen_node->expr_node.implicit_cast.after_type = expected_type;
- node->codegen_node->expr_node.implicit_cast.op = CastOpToUnknownSizeArray;
- node->codegen_node->expr_node.implicit_cast.source_node = node;
- context->cast_expr_alloca_list.append(&node->codegen_node->expr_node.implicit_cast);
+ Expr *expr = get_resolved_expr(node);
+ expr->implicit_cast.after_type = expected_type;
+ expr->implicit_cast.op = CastOpToUnknownSizeArray;
+ expr->implicit_cast.source_node = node;
+ context->cast_expr_alloca_list.append(&expr->implicit_cast);
return expected_type;
}
@@ -1225,7 +1224,7 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
if (node && node->type == NodeTypeFnDef) {
AstNode *fn_proto_node = node->data.fn_def.fn_proto;
- context->fn_entry = fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry;
+ context->fn_entry = fn_proto_node->data.fn_proto.fn_table_entry;
} else if (parent) {
context->fn_entry = parent->fn_entry;
}
@@ -1275,6 +1274,8 @@ static void get_struct_field(TypeTableEntry *struct_type, Buf *name, TypeStructF
static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
AstNode *node)
{
+ assert(node->type == NodeTypeFieldAccessExpr);
+
TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr,
node->data.field_access_expr.struct_expr);
@@ -1283,20 +1284,16 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer &&
struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))
{
- assert(node->codegen_node);
- FieldAccessNode *codegen_field_access = &node->codegen_node->data.field_access_node;
- assert(codegen_field_access);
-
Buf *field_name = &node->data.field_access_expr.field_name;
TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ?
struct_type : struct_type->data.pointer.child_type;
get_struct_field(bare_struct_type, field_name,
- &codegen_field_access->type_struct_field,
- &codegen_field_access->field_index);
- if (codegen_field_access->type_struct_field) {
- return_type = codegen_field_access->type_struct_field->type_entry;
+ &node->data.field_access_expr.type_struct_field,
+ &node->data.field_access_expr.field_index);
+ if (node->data.field_access_expr.type_struct_field) {
+ return_type = node->data.field_access_expr.type_struct_field->type_entry;
} else {
add_node_error(g, node,
buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&struct_type->name)));
@@ -1329,6 +1326,8 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
AstNode *node)
{
+ assert(node->type == NodeTypeSliceExpr);
+
TypeTableEntry *array_type = analyze_expression(g, import, context, nullptr,
node->data.slice_expr.array_ref_expr);
@@ -1355,10 +1354,9 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import,
}
if (return_type->id != TypeTableEntryIdInvalid) {
- assert(node->codegen_node);
- node->codegen_node->data.struct_val_expr_node.type_entry = return_type;
- node->codegen_node->data.struct_val_expr_node.source_node = node;
- context->struct_val_expr_alloca_list.append(&node->codegen_node->data.struct_val_expr_node);
+ node->data.slice_expr.resolved_struct_val_expr.type_entry = return_type;
+ node->data.slice_expr.resolved_struct_val_expr.source_node = node;
+ context->struct_val_expr_alloca_list.append(&node->data.slice_expr.resolved_struct_val_expr);
}
analyze_expression(g, import, context, g->builtin_types.entry_usize, node->data.slice_expr.start);
@@ -1463,6 +1461,8 @@ static bool is_op_allowed(TypeTableEntry *type, BinOpType op) {
static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
TypeTableEntry *expected_type, AstNode *node)
{
+ assert(node->type == NodeTypeCastExpr);
+
TypeTableEntry *wanted_type = resolve_type(g, node->data.cast_expr.type, import, context, false);
TypeTableEntry *actual_type = analyze_expression(g, import, context, nullptr, node->data.cast_expr.expr);
@@ -1472,43 +1472,41 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
return g->builtin_types.entry_invalid;
}
- CastNode *cast_node = &node->codegen_node->data.cast_node;
- cast_node->source_node = node;
- cast_node->after_type = wanted_type;
+ Cast *cast = &node->data.cast_expr.cast;
+ cast->source_node = node;
+ cast->after_type = wanted_type;
- // special casing this for now, TODO think about casting and do a general solution
if ((wanted_type == g->builtin_types.entry_isize || wanted_type == g->builtin_types.entry_usize) &&
actual_type->id == TypeTableEntryIdPointer)
{
- cast_node->op = CastOpPtrToInt;
+ cast->op = CastOpPtrToInt;
return wanted_type;
} else if (wanted_type->id == TypeTableEntryIdInt &&
actual_type->id == TypeTableEntryIdInt)
{
- cast_node->op = CastOpIntWidenOrShorten;
+ cast->op = CastOpIntWidenOrShorten;
return wanted_type;
} else if (wanted_type->id == TypeTableEntryIdStruct &&
wanted_type->data.structure.is_unknown_size_array &&
actual_type->id == TypeTableEntryIdArray &&
actual_type->data.array.child_type == wanted_type->data.structure.fields[0].type_entry)
{
- cast_node->op = CastOpToUnknownSizeArray;
- context->cast_expr_alloca_list.append(cast_node);
+ cast->op = CastOpToUnknownSizeArray;
+ context->cast_expr_alloca_list.append(cast);
return wanted_type;
} else if (actual_type->id == TypeTableEntryIdNumberLiteral &&
num_lit_fits_in_other_type(g, actual_type, wanted_type))
{
AstNode *literal_node = node->data.cast_expr.expr;
- assert(literal_node->codegen_node);
- NumberLiteralNode *codegen_num_lit = &literal_node->codegen_node->data.num_lit_node;
+ NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(literal_node);
assert(!codegen_num_lit->resolved_type);
codegen_num_lit->resolved_type = wanted_type;
- cast_node->op = CastOpNothing;
+ cast->op = CastOpNothing;
return wanted_type;
} else if (actual_type->id == TypeTableEntryIdPointer &&
wanted_type->id == TypeTableEntryIdPointer)
{
- cast_node->op = CastOpPointerReinterpret;
+ cast->op = CastOpPointerReinterpret;
return wanted_type;
} else {
add_node_error(g, node,
@@ -1529,7 +1527,7 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc
{
TypeTableEntry *expected_rhs_type = nullptr;
if (lhs_node->type == NodeTypeSymbol) {
- Buf *name = &lhs_node->data.symbol;
+ Buf *name = &lhs_node->data.symbol_expr.symbol;
VariableTableEntry *var = find_variable(block_context, name);
if (var) {
if (purpose == LValPurposeAssign && var->is_const) {
@@ -1551,7 +1549,6 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc
} else if (lhs_node->type == NodeTypeArrayAccessExpr) {
expected_rhs_type = analyze_array_access_expr(g, import, block_context, lhs_node);
} else if (lhs_node->type == NodeTypeFieldAccessExpr) {
- alloc_codegen_node(lhs_node);
expected_rhs_type = analyze_field_access_expr(g, import, block_context, lhs_node);
} else if (lhs_node->type == NodeTypePrefixOpExpr &&
lhs_node->data.prefix_op_expr.prefix_op == PrefixOpDereference)
@@ -1774,10 +1771,9 @@ static TypeTableEntry *analyze_null_literal_expr(CodeGen *g, ImportTableEntry *i
if (expected_type) {
assert(expected_type->id == TypeTableEntryIdMaybe);
- assert(node->codegen_node);
- node->codegen_node->data.struct_val_expr_node.type_entry = expected_type;
- node->codegen_node->data.struct_val_expr_node.source_node = node;
- block_context->struct_val_expr_alloca_list.append(&node->codegen_node->data.struct_val_expr_node);
+ node->data.null_literal.resolved_struct_val_expr.type_entry = expected_type;
+ node->data.null_literal.resolved_struct_val_expr.source_node = node;
+ block_context->struct_val_expr_alloca_list.append(&node->data.null_literal.resolved_struct_val_expr);
return expected_type;
} else {
@@ -1796,7 +1792,7 @@ static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry
buf_sprintf("number literal too large to be represented in any type"));
return g->builtin_types.entry_invalid;
} else if (expected_type) {
- NumberLiteralNode *codegen_num_lit = &node->codegen_node->data.num_lit_node;
+ NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node);
assert(!codegen_num_lit->resolved_type);
TypeTableEntry *after_implicit_cast_resolved_type =
resolve_type_compatibility(g, block_context, node, expected_type, num_lit_type);
@@ -1837,10 +1833,9 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp
return g->builtin_types.entry_invalid;
}
- assert(node->codegen_node);
- node->codegen_node->data.struct_val_expr_node.type_entry = type_entry;
- node->codegen_node->data.struct_val_expr_node.source_node = node;
- context->struct_val_expr_alloca_list.append(&node->codegen_node->data.struct_val_expr_node);
+ node->data.struct_val_expr.codegen.type_entry = type_entry;
+ node->data.struct_val_expr.codegen.source_node = node;
+ context->struct_val_expr_alloca_list.append(&node->data.struct_val_expr.codegen);
int expr_field_count = struct_val_expr->fields.length;
int actual_field_count = type_entry->data.structure.field_count;
@@ -1848,6 +1843,8 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp
int *field_use_counts = allocate<int>(actual_field_count);
for (int i = 0; i < expr_field_count; i += 1) {
AstNode *val_field_node = struct_val_expr->fields.at(i);
+ assert(val_field_node->type == NodeTypeStructValueField);
+
int field_index;
TypeStructField *type_field = find_struct_type_field(type_entry,
&val_field_node->data.struct_val_field.name, &field_index);
@@ -1865,8 +1862,7 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp
continue;
}
- alloc_codegen_node(val_field_node);
- val_field_node->codegen_node->data.struct_val_field_node.index = field_index;
+ val_field_node->data.struct_val_field.index = field_index;
analyze_expression(g, import, context, type_field->type_entry,
val_field_node->data.struct_val_field.expr);
@@ -1885,6 +1881,8 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp
static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
TypeTableEntry *expected_type, AstNode *node)
{
+ assert(node->type == NodeTypeWhileExpr);
+
AstNode *condition_node = node->data.while_expr.condition;
AstNode *while_body_node = node->data.while_expr.body;
TypeTableEntry *condition_type = analyze_expression(g, import, context,
@@ -1907,8 +1905,8 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import,
assert(resolved_type->id == TypeTableEntryIdBool);
bool constant_cond_value = number_literal.data.x_uint;
if (constant_cond_value) {
- node->codegen_node->data.while_node.condition_always_true = true;
- if (!node->codegen_node->data.while_node.contains_break) {
+ node->data.while_expr.condition_always_true = true;
+ if (!node->data.while_expr.contains_break) {
expr_return_type = g->builtin_types.entry_unreachable;
}
}
@@ -1921,12 +1919,14 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import,
static TypeTableEntry *analyze_break_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
TypeTableEntry *expected_type, AstNode *node)
{
+ assert(node->type == NodeTypeBreak);
+
AstNode *loop_node = context->parent_loop_node;
if (loop_node) {
- loop_node->codegen_node->data.while_node.contains_break = true;
+ assert(loop_node->type == NodeTypeWhileExpr);
+ loop_node->data.while_expr.contains_break = true;
} else {
- add_node_error(g, node,
- buf_sprintf("'break' expression outside loop"));
+ add_node_error(g, node, buf_sprintf("'break' expression outside loop"));
}
return g->builtin_types.entry_unreachable;
}
@@ -1935,8 +1935,7 @@ static TypeTableEntry *analyze_continue_expr(CodeGen *g, ImportTableEntry *impor
TypeTableEntry *expected_type, AstNode *node)
{
if (!context->parent_loop_node) {
- add_node_error(g, node,
- buf_sprintf("'continue' expression outside loop"));
+ add_node_error(g, node, buf_sprintf("'continue' expression outside loop"));
}
return g->builtin_types.entry_unreachable;
}
@@ -1981,7 +1980,7 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import,
assert(node->type == NodeTypeIfVarExpr);
BlockContext *child_context = new_block_context(node, context);
- node->codegen_node->data.if_var_node.block_context = child_context;
+ node->data.if_var_expr.block_context = child_context;
analyze_variable_declaration_raw(g, import, child_context, node, &node->data.if_var_expr.var_decl, true);
@@ -2032,8 +2031,10 @@ static TypeTableEntry *analyze_compiler_fn_type(CodeGen *g, ImportTableEntry *im
static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
TypeTableEntry *expected_type, AstNode *node)
{
+ assert(node->type == NodeTypeFnCallExpr);
+
AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
- Buf *name = &fn_ref_expr->data.symbol;
+ Buf *name = &fn_ref_expr->data.symbol_expr.symbol;
auto entry = g->builtin_fn_table.maybe_get(name);
@@ -2041,8 +2042,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
BuiltinFnEntry *builtin_fn = entry->value;
int actual_param_count = node->data.fn_call_expr.params.length;
- assert(node->codegen_node);
- node->codegen_node->data.fn_call_node.builtin_fn = builtin_fn;
+ node->data.fn_call_expr.builtin_fn = builtin_fn;
if (builtin_fn->param_count != actual_param_count) {
add_node_error(g, node,
@@ -2155,7 +2155,7 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
if (node->data.fn_call_expr.is_builtin) {
return analyze_builtin_fn_call_expr(g, import, context, expected_type, node);
}
- name = &fn_ref_expr->data.symbol;
+ name = &fn_ref_expr->data.symbol_expr.symbol;
} else {
add_node_error(g, node,
buf_sprintf("function pointers not yet supported"));
@@ -2210,13 +2210,15 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
AstNode *param_decl_node = fn_proto->params.at(fn_proto_i);
assert(param_decl_node->type == NodeTypeParamDecl);
AstNode *param_type_node = param_decl_node->data.param_decl.type;
- if (param_type_node->codegen_node)
- expected_param_type = param_type_node->codegen_node->data.type_node.entry;
+ assert(param_type_node->type == NodeTypeType);
+ if (param_type_node->data.type.entry) {
+ expected_param_type = param_type_node->data.type.entry;
+ }
}
analyze_expression(g, import, context, expected_param_type, child);
}
- return fn_proto->return_type->codegen_node->data.type_node.entry;
+ return fn_proto->return_type->data.type.entry;
}
}
@@ -2224,18 +2226,17 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
TypeTableEntry *expected_type, AstNode *node)
{
TypeTableEntry *return_type = nullptr;
- alloc_codegen_node(node);
switch (node->type) {
case NodeTypeBlock:
{
BlockContext *child_context = new_block_context(node, context);
- node->codegen_node->data.block_node.block_context = child_context;
+ node->data.block.block_context = child_context;
return_type = g->builtin_types.entry_void;
for (int i = 0; i < node->data.block.statements.length; i += 1) {
AstNode *child = node->data.block.statements.at(i);
if (child->type == NodeTypeLabel) {
- LabelTableEntry *label_entry = child->codegen_node->data.label_entry;
+ LabelTableEntry *label_entry = child->data.label.label_entry;
assert(label_entry);
label_entry->entered_from_fallthrough = (return_type->id != TypeTableEntryIdUnreachable);
return_type = g->builtin_types.entry_void;
@@ -2288,13 +2289,13 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
case NodeTypeGoto:
{
FnTableEntry *fn_table_entry = get_context_fn_entry(context);
- auto table_entry = fn_table_entry->label_table.maybe_get(&node->data.go_to.name);
+ auto table_entry = fn_table_entry->label_table.maybe_get(&node->data.goto_expr.name);
if (table_entry) {
- node->codegen_node->data.label_entry = table_entry->value;
+ node->data.goto_expr.label_entry = table_entry->value;
table_entry->value->used = true;
} else {
add_node_error(g, node,
- buf_sprintf("use of undeclared label '%s'", buf_ptr(&node->data.go_to.name)));
+ buf_sprintf("use of undeclared label '%s'", buf_ptr(&node->data.goto_expr.name)));
}
return_type = g->builtin_types.entry_unreachable;
break;
@@ -2380,7 +2381,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
case NodeTypeSymbol:
{
- return_type = analyze_variable_name(g, import, context, node, &node->data.symbol);
+ return_type = analyze_variable_name(g, import, context, node, &node->data.symbol_expr.symbol);
break;
}
case NodeTypeCastExpr:
@@ -2507,8 +2508,8 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
assert(return_type);
resolve_type_compatibility(g, context, node, expected_type, return_type);
- node->codegen_node->expr_node.type_entry = return_type;
- node->codegen_node->expr_node.block_context = context;
+ get_resolved_expr(node)->type_entry = return_type;
+ get_resolved_expr(node)->block_context = context;
return return_type;
}
@@ -2519,15 +2520,14 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
AstNode *fn_proto_node = node->data.fn_def.fn_proto;
assert(fn_proto_node->type == NodeTypeFnProto);
- if (fn_proto_node->codegen_node->data.fn_proto_node.skip) {
+ if (fn_proto_node->data.fn_proto.skip) {
// we detected an error with this function definition which prevents us
// from further analyzing it.
return;
}
- alloc_codegen_node(node);
BlockContext *context = new_block_context(node, import->block_context);
- node->codegen_node->data.fn_def_node.block_context = context;
+ node->data.fn_def.block_context = context;
AstNodeFnProto *fn_proto = &fn_proto_node->data.fn_proto;
bool is_exported = (fn_proto->visib_mod == VisibModExport);
@@ -2538,7 +2538,7 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
// define local variables for parameters
AstNodeParamDecl *param_decl = ¶m_decl_node->data.param_decl;
assert(param_decl->type->type == NodeTypeType);
- TypeTableEntry *type = param_decl->type->codegen_node->data.type_node.entry;
+ TypeTableEntry *type = param_decl->type->data.type.entry;
if (is_exported && type->id == TypeTableEntryIdStruct) {
add_node_error(g, param_decl_node,
@@ -2552,8 +2552,7 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
variable_entry->decl_node = param_decl_node;
variable_entry->arg_index = i;
- alloc_codegen_node(param_decl_node);
- param_decl_node->codegen_node->data.param_decl_node.variable = variable_entry;
+ param_decl_node->data.param_decl.variable = variable_entry;
VariableTableEntry *existing_entry = find_local_variable(context, &variable_entry->name);
if (!existing_entry) {
@@ -2571,13 +2570,13 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
}
}
- TypeTableEntry *expected_type = fn_proto->return_type->codegen_node->data.type_node.entry;
+ TypeTableEntry *expected_type = fn_proto->return_type->data.type.entry;
TypeTableEntry *block_return_type = analyze_expression(g, import, context, expected_type, node->data.fn_def.body);
- node->codegen_node->data.fn_def_node.implicit_return_type = block_return_type;
+ node->data.fn_def.implicit_return_type = block_return_type;
{
- FnTableEntry *fn_table_entry = fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry;
+ FnTableEntry *fn_table_entry = fn_proto_node->data.fn_proto.fn_table_entry;
auto it = fn_table_entry->label_table.entry_iterator();
for (;;) {
auto *entry = it.next();
@@ -2656,7 +2655,7 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
}
static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *expr_node,
- DeclNode *decl_node)
+ TopLevelDecl *decl_node)
{
switch (expr_node->type) {
case NodeTypeNumberLiteral:
@@ -2672,7 +2671,7 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
// no dependencies on other top level declarations
break;
case NodeTypeSymbol:
- decl_node->deps.put(&expr_node->data.symbol, expr_node);
+ decl_node->deps.put(&expr_node->data.symbol_expr.symbol, expr_node);
break;
case NodeTypeBinOpExpr:
collect_expr_decl_deps(g, import, expr_node->data.bin_op_expr.op1, decl_node);
@@ -2787,7 +2786,7 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
}
}
-static void collect_type_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *type_node, DeclNode *decl_node) {
+static void collect_type_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *type_node, TopLevelDecl *decl_node) {
assert(type_node->type == NodeTypeType);
switch (type_node->data.type.type) {
case AstNodeTypeTypePrimitive:
@@ -2824,16 +2823,13 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
switch (node->type) {
case NodeTypeStructDecl:
{
- alloc_codegen_node(node);
- StructDeclNode *struct_codegen = &node->codegen_node->data.struct_decl_node;
-
Buf *name = &node->data.struct_decl.name;
auto table_entry = g->primitive_type_table.maybe_get(name);
if (!table_entry) {
table_entry = import->type_table.maybe_get(name);
}
if (table_entry) {
- struct_codegen->type_entry = table_entry->value;
+ node->data.struct_decl.type_entry = table_entry->value;
add_node_error(g, node,
buf_sprintf("redefinition of '%s'", buf_ptr(name)));
} else {
@@ -2848,7 +2844,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
// put off adding the debug type until we do the full struct body
// this type is incomplete until we do another pass
import->type_table.put(&entry->name, entry);
- struct_codegen->type_entry = entry;
+ node->data.struct_decl.type_entry = entry;
bool is_pub = (node->data.struct_decl.visib_mod != VisibModPrivate);
if (is_pub) {
@@ -2867,14 +2863,15 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
}
// determine which other top level declarations this struct depends on.
- DeclNode *decl_node = &node->codegen_node->decl_node;
+ TopLevelDecl *decl_node = &node->data.struct_decl.top_level_decl;
+ decl_node->deps.init(1);
for (int i = 0; i < node->data.struct_decl.fields.length; i += 1) {
AstNode *field_node = node->data.struct_decl.fields.at(i);
AstNode *type_node = field_node->data.struct_field.type;
collect_type_decl_deps(g, import, type_node, decl_node);
}
- node->codegen_node->decl_node.name = name;
- node->codegen_node->decl_node.import = import;
+ decl_node->name = name;
+ decl_node->import = import;
if (decl_node->deps.size() > 0) {
g->unresolved_top_level_decls.put(name, node);
} else {
@@ -2913,8 +2910,8 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
case NodeTypeVariableDeclaration:
{
// determine which other top level declarations this variable declaration depends on.
- alloc_codegen_node(node);
- DeclNode *decl_node = &node->codegen_node->decl_node;
+ TopLevelDecl *decl_node = &node->data.variable_declaration.top_level_decl;
+ decl_node->deps.init(1);
if (node->data.variable_declaration.type) {
collect_type_decl_deps(g, import, node->data.variable_declaration.type, decl_node);
}
@@ -2922,8 +2919,8 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
collect_expr_decl_deps(g, import, node->data.variable_declaration.expr, decl_node);
}
Buf *name = &node->data.variable_declaration.symbol;
- node->codegen_node->decl_node.name = name;
- node->codegen_node->decl_node.import = import;
+ decl_node->name = name;
+ decl_node->import = import;
if (decl_node->deps.size() > 0) {
g->unresolved_top_level_decls.put(name, node);
} else {
@@ -2934,8 +2931,8 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
case NodeTypeFnProto:
{
// determine which other top level declarations this function prototype depends on.
- alloc_codegen_node(node);
- DeclNode *decl_node = &node->codegen_node->decl_node;
+ TopLevelDecl *decl_node = &node->data.fn_proto.top_level_decl;
+ decl_node->deps.init(1);
for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {
AstNode *param_node = node->data.fn_proto.params.at(i);
assert(param_node->type == NodeTypeParamDecl);
@@ -2943,8 +2940,8 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
}
Buf *name = &node->data.fn_proto.name;
- node->codegen_node->decl_node.name = name;
- node->codegen_node->decl_node.import = import;
+ decl_node->name = name;
+ decl_node->import = import;
if (decl_node->deps.size() > 0) {
g->unresolved_top_level_decls.put(name, node);
} else {
@@ -2999,7 +2996,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
}
static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
- auto it = node->codegen_node->decl_node.deps.entry_iterator();
+ auto it = get_resolved_top_level_decl(node)->deps.entry_iterator();
for (;;) {
auto *entry = it.next();
if (!entry)
@@ -3012,23 +3009,24 @@ static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode
AstNode *child_node = unresolved_entry->value;
- if (child_node->codegen_node->decl_node.in_current_deps) {
+ if (get_resolved_top_level_decl(child_node)->in_current_deps) {
// dependency loop. we'll let the fact that it's not in the respective
// table cause an error in resolve_top_level_decl.
continue;
}
// set temporary flag
- child_node->codegen_node->decl_node.in_current_deps = true;
+ TopLevelDecl *top_level_decl = get_resolved_top_level_decl(child_node);
+ top_level_decl->in_current_deps = true;
- recursive_resolve_decl(g, child_node->codegen_node->decl_node.import, child_node);
+ recursive_resolve_decl(g, top_level_decl->import, child_node);
// unset temporary flag
- child_node->codegen_node->decl_node.in_current_deps = false;
+ top_level_decl->in_current_deps = false;
}
resolve_top_level_decl(g, import, node);
- g->unresolved_top_level_decls.remove(node->codegen_node->decl_node.name);
+ g->unresolved_top_level_decls.remove(get_resolved_top_level_decl(node)->name);
}
static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {
@@ -3051,12 +3049,13 @@ static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *im
}
// set temporary flag
- decl_node->codegen_node->decl_node.in_current_deps = true;
+ TopLevelDecl *top_level_decl = get_resolved_top_level_decl(decl_node);
+ top_level_decl->in_current_deps = true;
- recursive_resolve_decl(g, decl_node->codegen_node->decl_node.import, decl_node);
+ recursive_resolve_decl(g, top_level_decl->import, decl_node);
// unset temporary flag
- decl_node->codegen_node->decl_node.in_current_deps = false;
+ top_level_decl->in_current_deps = false;
}
}
@@ -3089,7 +3088,7 @@ void semantic_analyze(CodeGen *g) {
buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
}
- ImportTableEntry *target_import = child->codegen_node->data.import_node.import;
+ ImportTableEntry *target_import = child->data.use.import;
assert(target_import);
target_import->importers.append({import, child});
@@ -3144,9 +3143,186 @@ void semantic_analyze(CodeGen *g) {
}
}
-void alloc_codegen_node(AstNode *node) {
- assert(!node->codegen_node);
- node->codegen_node = allocate<CodeGenNode>(1);
- node->codegen_node->decl_node.deps.init(1);
+Expr *get_resolved_expr(AstNode *node) {
+ switch (node->type) {
+ case NodeTypeReturnExpr:
+ return &node->data.return_expr.resolved_expr;
+ case NodeTypeBinOpExpr:
+ return &node->data.bin_op_expr.resolved_expr;
+ case NodeTypeCastExpr:
+ return &node->data.cast_expr.resolved_expr;
+ case NodeTypePrefixOpExpr:
+ return &node->data.prefix_op_expr.resolved_expr;
+ case NodeTypeFnCallExpr:
+ return &node->data.fn_call_expr.resolved_expr;
+ case NodeTypeArrayAccessExpr:
+ return &node->data.array_access_expr.resolved_expr;
+ case NodeTypeSliceExpr:
+ return &node->data.slice_expr.resolved_expr;
+ case NodeTypeFieldAccessExpr:
+ return &node->data.field_access_expr.resolved_expr;
+ case NodeTypeIfBoolExpr:
+ return &node->data.if_bool_expr.resolved_expr;
+ case NodeTypeIfVarExpr:
+ return &node->data.if_var_expr.resolved_expr;
+ case NodeTypeWhileExpr:
+ return &node->data.while_expr.resolved_expr;
+ case NodeTypeAsmExpr:
+ return &node->data.asm_expr.resolved_expr;
+ case NodeTypeStructValueExpr:
+ return &node->data.struct_val_expr.resolved_expr;
+ case NodeTypeNumberLiteral:
+ return &node->data.number_literal.resolved_expr;
+ case NodeTypeStringLiteral:
+ return &node->data.string_literal.resolved_expr;
+ case NodeTypeBlock:
+ return &node->data.block.resolved_expr;
+ case NodeTypeVoid:
+ return &node->data.void_expr.resolved_expr;
+ case NodeTypeUnreachable:
+ return &node->data.unreachable_expr.resolved_expr;
+ case NodeTypeSymbol:
+ return &node->data.symbol_expr.resolved_expr;
+ case NodeTypeVariableDeclaration:
+ return &node->data.variable_declaration.resolved_expr;
+ case NodeTypeCharLiteral:
+ return &node->data.char_literal.resolved_expr;
+ case NodeTypeBoolLiteral:
+ return &node->data.bool_literal.resolved_expr;
+ case NodeTypeNullLiteral:
+ return &node->data.null_literal.resolved_expr;
+ case NodeTypeGoto:
+ return &node->data.goto_expr.resolved_expr;
+ case NodeTypeBreak:
+ return &node->data.break_expr.resolved_expr;
+ case NodeTypeContinue:
+ return &node->data.continue_expr.resolved_expr;
+ case NodeTypeCompilerFnExpr:
+ return &node->data.compiler_fn_expr.resolved_expr;
+ case NodeTypeCompilerFnType:
+ return &node->data.compiler_fn_type.resolved_expr;
+ case NodeTypeLabel:
+ return &node->data.label.resolved_expr;
+ case NodeTypeRoot:
+ case NodeTypeRootExportDecl:
+ case NodeTypeFnProto:
+ case NodeTypeFnDef:
+ case NodeTypeFnDecl:
+ case NodeTypeParamDecl:
+ case NodeTypeType:
+ case NodeTypeExternBlock:
+ case NodeTypeDirective:
+ case NodeTypeUse:
+ case NodeTypeStructDecl:
+ case NodeTypeStructField:
+ case NodeTypeStructValueField:
+ case NodeTypeEnumDecl:
+ case NodeTypeEnumField:
+ zig_unreachable();
+ }
+}
+
+NumLitCodeGen *get_resolved_num_lit(AstNode *node) {
+ switch (node->type) {
+ case NodeTypeNumberLiteral:
+ return &node->data.number_literal.codegen;
+ case NodeTypeCompilerFnType:
+ return &node->data.compiler_fn_type.resolved_num_lit;
+ case NodeTypeReturnExpr:
+ case NodeTypeBinOpExpr:
+ case NodeTypeCastExpr:
+ case NodeTypePrefixOpExpr:
+ case NodeTypeFnCallExpr:
+ case NodeTypeArrayAccessExpr:
+ case NodeTypeSliceExpr:
+ case NodeTypeFieldAccessExpr:
+ case NodeTypeIfBoolExpr:
+ case NodeTypeIfVarExpr:
+ case NodeTypeWhileExpr:
+ case NodeTypeAsmExpr:
+ case NodeTypeStructValueExpr:
+ case NodeTypeRoot:
+ case NodeTypeRootExportDecl:
+ case NodeTypeFnProto:
+ case NodeTypeFnDef:
+ case NodeTypeFnDecl:
+ case NodeTypeParamDecl:
+ case NodeTypeType:
+ case NodeTypeBlock:
+ case NodeTypeExternBlock:
+ case NodeTypeDirective:
+ case NodeTypeVariableDeclaration:
+ case NodeTypeStringLiteral:
+ case NodeTypeCharLiteral:
+ case NodeTypeUnreachable:
+ case NodeTypeSymbol:
+ case NodeTypeUse:
+ case NodeTypeVoid:
+ case NodeTypeBoolLiteral:
+ case NodeTypeNullLiteral:
+ case NodeTypeLabel:
+ case NodeTypeGoto:
+ case NodeTypeBreak:
+ case NodeTypeContinue:
+ case NodeTypeStructDecl:
+ case NodeTypeStructField:
+ case NodeTypeStructValueField:
+ case NodeTypeEnumDecl:
+ case NodeTypeEnumField:
+ case NodeTypeCompilerFnExpr:
+ zig_unreachable();
+ }
}
+TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
+ switch (node->type) {
+ case NodeTypeVariableDeclaration:
+ return &node->data.variable_declaration.top_level_decl;
+ case NodeTypeFnProto:
+ return &node->data.fn_proto.top_level_decl;
+ case NodeTypeStructDecl:
+ return &node->data.struct_decl.top_level_decl;
+ case NodeTypeNumberLiteral:
+ case NodeTypeReturnExpr:
+ case NodeTypeBinOpExpr:
+ case NodeTypeCastExpr:
+ case NodeTypePrefixOpExpr:
+ case NodeTypeFnCallExpr:
+ case NodeTypeArrayAccessExpr:
+ case NodeTypeSliceExpr:
+ case NodeTypeFieldAccessExpr:
+ case NodeTypeIfBoolExpr:
+ case NodeTypeIfVarExpr:
+ case NodeTypeWhileExpr:
+ case NodeTypeAsmExpr:
+ case NodeTypeStructValueExpr:
+ case NodeTypeRoot:
+ case NodeTypeRootExportDecl:
+ case NodeTypeFnDef:
+ case NodeTypeFnDecl:
+ case NodeTypeParamDecl:
+ case NodeTypeType:
+ case NodeTypeBlock:
+ case NodeTypeExternBlock:
+ case NodeTypeDirective:
+ case NodeTypeStringLiteral:
+ case NodeTypeCharLiteral:
+ case NodeTypeUnreachable:
+ case NodeTypeSymbol:
+ case NodeTypeUse:
+ case NodeTypeVoid:
+ case NodeTypeBoolLiteral:
+ case NodeTypeNullLiteral:
+ case NodeTypeLabel:
+ case NodeTypeGoto:
+ case NodeTypeBreak:
+ case NodeTypeContinue:
+ case NodeTypeStructField:
+ case NodeTypeStructValueField:
+ case NodeTypeEnumDecl:
+ case NodeTypeEnumField:
+ case NodeTypeCompilerFnExpr:
+ case NodeTypeCompilerFnType:
+ zig_unreachable();
+ }
+}
src/analyze.hpp
@@ -8,414 +8,16 @@
#ifndef ZIG_ANALYZE_HPP
#define ZIG_ANALYZE_HPP
-#include "codegen.hpp"
-#include "hash_map.hpp"
-#include "zig_llvm.hpp"
-#include "errmsg.hpp"
-
-struct FnTableEntry;
-struct BlockContext;
-struct TypeTableEntry;
-struct VariableTableEntry;
-struct CastNode;
-struct StructValExprNode;
-
-struct TypeTableEntryPointer {
- TypeTableEntry *child_type;
- bool is_const;
- bool is_noalias;
-};
-
-struct TypeTableEntryInt {
- bool is_signed;
-};
-
-struct TypeTableEntryArray {
- TypeTableEntry *child_type;
- uint64_t len;
-};
-
-struct TypeStructField {
- Buf *name;
- TypeTableEntry *type_entry;
-};
-
-struct TypeTableEntryStruct {
- AstNode *decl_node;
- bool is_packed;
- int field_count;
- TypeStructField *fields;
- uint64_t size_bytes;
- bool is_invalid; // true if any fields are invalid
- bool is_unknown_size_array;
- // reminder: hash tables must be initialized before use
- HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
-
- // set this flag temporarily to detect infinite loops
- bool embedded_in_current;
- bool reported_infinite_err;
-};
-
-struct TypeTableEntryNumLit {
- NumLit kind;
-};
-
-struct TypeTableEntryMaybe {
- TypeTableEntry *child_type;
-};
-
-enum TypeTableEntryId {
- TypeTableEntryIdInvalid,
- TypeTableEntryIdVoid,
- TypeTableEntryIdBool,
- TypeTableEntryIdUnreachable,
- TypeTableEntryIdInt,
- TypeTableEntryIdFloat,
- TypeTableEntryIdPointer,
- TypeTableEntryIdArray,
- TypeTableEntryIdStruct,
- TypeTableEntryIdNumberLiteral,
- TypeTableEntryIdMaybe,
-};
-
-struct TypeTableEntry {
- TypeTableEntryId id;
-
- LLVMTypeRef type_ref;
- LLVMZigDIType *di_type;
- uint64_t size_in_bits;
- uint64_t align_in_bits;
-
- Buf name;
-
- union {
- TypeTableEntryPointer pointer;
- TypeTableEntryInt integral;
- TypeTableEntryArray array;
- TypeTableEntryStruct structure;
- TypeTableEntryNumLit num_lit;
- TypeTableEntryMaybe maybe;
- } data;
-
- // use these fields to make sure we don't duplicate type table entries for the same type
- TypeTableEntry *pointer_parent[2][2]; // 0 - const. 1 - noalias
- TypeTableEntry *unknown_size_array_parent[2][2]; // 0 - const. 1 - noalias
- HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size;
- TypeTableEntry *maybe_parent;
-
-};
-
-struct ImporterInfo {
- ImportTableEntry *import;
- AstNode *source_node;
-};
-
-struct ImportTableEntry {
- AstNode *root;
- Buf *path; // relative to root_source_dir
- LLVMZigDIFile *di_file;
- Buf *source_code;
- ZigList<int> *line_offsets;
- BlockContext *block_context;
- ZigList<ImporterInfo> importers;
-
- // reminder: hash tables must be initialized before use
- HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
- HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> type_table;
-};
-
-struct LabelTableEntry {
- AstNode *label_node;
- LLVMBasicBlockRef basic_block;
- bool used;
- bool entered_from_fallthrough;
-};
-
-enum FnAttrId {
- FnAttrIdNaked,
- FnAttrIdAlwaysInline,
-};
-
-struct FnTableEntry {
- LLVMValueRef fn_value;
- AstNode *proto_node;
- AstNode *fn_def_node;
- bool is_extern;
- bool internal_linkage;
- unsigned calling_convention;
- ImportTableEntry *import_entry;
- ZigList<FnAttrId> fn_attr_list;
- // Required to be a pre-order traversal of the AST. (parents must come before children)
- ZigList<BlockContext *> all_block_contexts;
- TypeTableEntry *member_of_struct;
- Buf symbol_name;
-
- // reminder: hash tables must be initialized before use
- HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table;
-};
-
-enum BuiltinFnId {
- BuiltinFnIdInvalid,
- BuiltinFnIdArithmeticWithOverflow,
- BuiltinFnIdMemcpy,
- BuiltinFnIdMemset,
-};
-
-struct BuiltinFnEntry {
- BuiltinFnId id;
- Buf name;
- int param_count;
- TypeTableEntry *return_type;
- TypeTableEntry **param_types;
- LLVMValueRef fn_val;
-};
-
-struct CodeGen {
- LLVMModuleRef module;
- ZigList<ErrorMsg*> errors;
- LLVMBuilderRef builder;
- LLVMZigDIBuilder *dbuilder;
- LLVMZigDICompileUnit *compile_unit;
-
- ZigList<Buf *> lib_search_paths;
-
- // reminder: hash tables must be initialized before use
- HashMap<Buf *, LLVMValueRef, buf_hash, buf_eql_buf> str_table;
- HashMap<Buf *, bool, buf_hash, buf_eql_buf> link_table;
- HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;
- HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;
- HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table;
- HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> unresolved_top_level_decls;
-
- uint32_t next_unresolved_index;
-
- struct {
- TypeTableEntry *entry_bool;
- TypeTableEntry *entry_u8;
- TypeTableEntry *entry_u16;
- TypeTableEntry *entry_u32;
- TypeTableEntry *entry_u64;
- TypeTableEntry *entry_i8;
- TypeTableEntry *entry_i16;
- TypeTableEntry *entry_i32;
- TypeTableEntry *entry_i64;
- TypeTableEntry *entry_isize;
- TypeTableEntry *entry_usize;
- TypeTableEntry *entry_f32;
- TypeTableEntry *entry_f64;
- TypeTableEntry *entry_c_string_literal;
- TypeTableEntry *entry_void;
- TypeTableEntry *entry_unreachable;
- TypeTableEntry *entry_invalid;
- } builtin_types;
-
- TypeTableEntry *num_lit_types[NumLitCount];
-
- LLVMTargetDataRef target_data_ref;
- unsigned pointer_size_bytes;
- bool is_static;
- bool strip_debug_symbols;
- bool have_exported_main;
- bool link_libc;
- Buf *libc_path;
- CodeGenBuildType build_type;
- LLVMTargetMachineRef target_machine;
- LLVMZigDIFile *dummy_di_file;
- bool is_native_target;
- Buf *root_source_dir;
- Buf *root_out_name;
-
- // The function definitions this module includes. There must be a corresponding
- // fn_protos entry.
- ZigList<FnTableEntry *> fn_defs;
- // The function prototypes this module includes. In the case of external declarations,
- // there will not be a corresponding fn_defs entry.
- ZigList<FnTableEntry *> fn_protos;
- ZigList<VariableTableEntry *> global_vars;
-
- OutType out_type;
- FnTableEntry *cur_fn;
- BlockContext *cur_block_context;
- ZigList<LLVMBasicBlockRef> break_block_stack;
- ZigList<LLVMBasicBlockRef> continue_block_stack;
- bool c_stdint_used;
- AstNode *root_export_decl;
- int version_major;
- int version_minor;
- int version_patch;
- bool verbose;
- ErrColor err_color;
- ImportTableEntry *root_import;
- ImportTableEntry *bootstrap_import;
- LLVMValueRef memcpy_fn_val;
- bool error_during_imports;
-};
-
-struct VariableTableEntry {
- Buf name;
- TypeTableEntry *type;
- LLVMValueRef value_ref;
- bool is_const;
- bool is_ptr; // if true, value_ref is a pointer
- AstNode *decl_node;
- LLVMZigDILocalVariable *di_loc_var;
- int arg_index;
-};
-
-struct BlockContext {
- AstNode *node; // either NodeTypeFnDef or NodeTypeBlock or NodeTypeRoot
- FnTableEntry *fn_entry; // null at the module scope
- BlockContext *parent; // null when this is the root
- HashMap<Buf *, VariableTableEntry *, buf_hash, buf_eql_buf> variable_table;
- ZigList<CastNode *> cast_expr_alloca_list;
- ZigList<StructValExprNode *> struct_val_expr_alloca_list;
- AstNode *parent_loop_node;
- AstNode *next_child_parent_loop_node;
- LLVMZigDIScope *di_scope;
-};
-
-struct TypeNode {
- TypeTableEntry *entry;
-};
-
-struct FnProtoNode {
- FnTableEntry *fn_table_entry;
- bool skip;
-};
-
-struct FnDefNode {
- TypeTableEntry *implicit_return_type;
- BlockContext *block_context;
-};
-
-
-struct AssignNode {
- VariableTableEntry *var_entry;
-};
-
-struct BlockNode {
- BlockContext *block_context;
-};
-
-struct StructDeclNode {
- TypeTableEntry *type_entry;
-};
-
-struct FieldAccessNode {
- int field_index;
- TypeStructField *type_struct_field;
-};
-
-enum CastOp {
- CastOpNothing,
- CastOpPtrToInt,
- CastOpIntWidenOrShorten,
- CastOpToUnknownSizeArray,
- CastOpMaybeWrap,
- CastOpPointerReinterpret,
-};
-
-struct CastNode {
- CastOp op;
- // if op is CastOpArrayToString, this will be a pointer to
- // the string struct on the stack
- LLVMValueRef ptr;
- TypeTableEntry *after_type;
- AstNode *source_node;
-};
-
-struct ExprNode {
- TypeTableEntry *type_entry;
- // the context in which this expression is evaluated.
- // for blocks, this points to the containing scope, not the block's own scope for its children.
- BlockContext *block_context;
-
- // may be null for no cast
- CastNode implicit_cast; // happens first
- CastNode implicit_maybe_cast; // happens second
-};
-
-struct NumberLiteralNode {
- TypeTableEntry *resolved_type;
-};
-
-struct VarDeclNode {
- TypeTableEntry *type;
-};
-
-struct StructValFieldNode {
- int index;
-};
-
-struct StructValExprNode {
- TypeTableEntry *type_entry;
- LLVMValueRef ptr;
- AstNode *source_node;
-};
-
-struct IfVarNode {
- BlockContext *block_context;
-};
-
-struct ParamDeclNode {
- VariableTableEntry *variable;
-};
-
-struct ImportNode {
- ImportTableEntry *import;
-};
-
-struct WhileNode {
- bool condition_always_true;
- bool contains_break;
-};
-
-struct FnCallNode {
- BuiltinFnEntry *builtin_fn;
-};
-
-struct DeclNode {
- HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> deps;
- Buf *name;
- ImportTableEntry *import;
- // set this flag temporarily to detect infinite loops
- bool in_current_deps;
-};
-
-// TODO get rid of this structure and put the data directly in the appropriate AST node
-struct CodeGenNode {
- union {
- TypeNode type_node; // for NodeTypeType
- FnDefNode fn_def_node; // for NodeTypeFnDef
- FnProtoNode fn_proto_node; // for NodeTypeFnProto
- LabelTableEntry *label_entry; // for NodeTypeGoto and NodeTypeLabel
- AssignNode assign_node; // for NodeTypeBinOpExpr where op is BinOpTypeAssign
- BlockNode block_node; // for NodeTypeBlock
- StructDeclNode struct_decl_node; // for NodeTypeStructDecl
- FieldAccessNode field_access_node; // for NodeTypeFieldAccessExpr
- CastNode cast_node; // for NodeTypeCastExpr
- // note: I've been using this field on some non-number literal nodes too.
- NumberLiteralNode num_lit_node; // for NodeTypeNumberLiteral
- VarDeclNode var_decl_node; // for NodeTypeVariableDeclaration
- StructValFieldNode struct_val_field_node; // for NodeTypeStructValueField
- // note: I've been using this field on some non-struct val expressions too.
- StructValExprNode struct_val_expr_node; // for NodeTypeStructValueExpr
- IfVarNode if_var_node; // for NodeTypeStructValueExpr
- ParamDeclNode param_decl_node; // for NodeTypeParamDecl
- ImportNode import_node; // for NodeTypeUse
- WhileNode while_node; // for NodeTypeWhileExpr
- FnCallNode fn_call_node; // for NodeTypeFnCallExpr
- } data;
- ExprNode expr_node; // for all the expression nodes
- DeclNode decl_node; // for all top level decls
-};
+#include "all_types.hpp"
void semantic_analyze(CodeGen *g);
void add_node_error(CodeGen *g, AstNode *node, Buf *msg);
-void alloc_codegen_node(AstNode *node);
TypeTableEntry *new_type_table_entry(TypeTableEntryId id);
TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const, bool is_noalias);
VariableTableEntry *find_variable(BlockContext *context, Buf *name);
BlockContext *new_block_context(AstNode *node, BlockContext *parent);
+Expr *get_resolved_expr(AstNode *node);
+NumLitCodeGen *get_resolved_num_lit(AstNode *node);
+TopLevelDecl *get_resolved_top_level_decl(AstNode *node);
#endif
src/codegen.cpp
@@ -75,9 +75,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b
static TypeTableEntry *get_type_for_type_node(CodeGen *g, AstNode *type_node) {
assert(type_node->type == NodeTypeType);
- assert(type_node->codegen_node);
- assert(type_node->codegen_node->data.type_node.entry);
- return type_node->codegen_node->data.type_node.entry;
+ return type_node->data.type.entry;
}
static TypeTableEntry *fn_proto_type_from_type_node(CodeGen *g, AstNode *type_node) {
@@ -138,15 +136,16 @@ static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str, bool c) {
}
static TypeTableEntry *get_expr_type(AstNode *node) {
- TypeTableEntry *cast_type = node->codegen_node->expr_node.implicit_cast.after_type;
- return cast_type ? cast_type : node->codegen_node->expr_node.type_entry;
+ Expr *expr = get_resolved_expr(node);
+ TypeTableEntry *cast_type = expr->implicit_cast.after_type;
+ return cast_type ? cast_type : expr->type_entry;
}
static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
assert(node->type == NodeTypeFnCallExpr);
AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
assert(fn_ref_expr->type == NodeTypeSymbol);
- BuiltinFnEntry *builtin_fn = node->codegen_node->data.fn_call_node.builtin_fn;
+ BuiltinFnEntry *builtin_fn = node->data.fn_call_expr.builtin_fn;
switch (builtin_fn->id) {
case BuiltinFnIdInvalid:
@@ -265,7 +264,7 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
// Assume that the expression evaluates to a simple name and return the buf
// TODO after we support function pointers we can make this generic
assert(fn_ref_expr->type == NodeTypeSymbol);
- Buf *name = &fn_ref_expr->data.symbol;
+ Buf *name = &fn_ref_expr->data.symbol_expr.symbol;
struct_type = nullptr;
first_param_expr = nullptr;
@@ -388,8 +387,8 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou
LLVMValueRef struct_ptr;
if (struct_expr_node->type == NodeTypeSymbol) {
- VariableTableEntry *var = find_variable(struct_expr_node->codegen_node->expr_node.block_context,
- &struct_expr_node->data.symbol);
+ VariableTableEntry *var = find_variable(get_resolved_expr(struct_expr_node)->block_context,
+ &struct_expr_node->data.symbol_expr.symbol);
assert(var);
if (var->is_ptr && var->type->id == TypeTableEntryIdPointer) {
@@ -413,14 +412,12 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou
assert(LLVMGetTypeKind(LLVMTypeOf(struct_ptr)) == LLVMPointerTypeKind);
assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(struct_ptr))) == LLVMStructTypeKind);
- FieldAccessNode *codegen_field_access = &node->codegen_node->data.field_access_node;
+ assert(node->data.field_access_expr.field_index >= 0);
- assert(codegen_field_access->field_index >= 0);
-
- *out_type_entry = codegen_field_access->type_struct_field->type_entry;
+ *out_type_entry = node->data.field_access_expr.type_struct_field->type_entry;
add_debug_source_node(g, node);
- return LLVMBuildStructGEP(g->builder, struct_ptr, codegen_field_access->field_index, "");
+ return LLVMBuildStructGEP(g->builder, struct_ptr, node->data.field_access_expr.field_index, "");
}
static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
@@ -429,7 +426,7 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
AstNode *array_ref_node = node->data.slice_expr.array_ref_expr;
TypeTableEntry *array_type = get_expr_type(array_ref_node);
- LLVMValueRef tmp_struct_ptr = node->codegen_node->data.struct_val_expr_node.ptr;
+ LLVMValueRef tmp_struct_ptr = node->data.slice_expr.resolved_struct_val_expr.ptr;
LLVMValueRef array_ptr = gen_array_base_ptr(g, array_ref_node);
if (array_type->id == TypeTableEntryIdArray) {
@@ -545,8 +542,8 @@ static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node,
LLVMValueRef target_ref;
if (node->type == NodeTypeSymbol) {
- VariableTableEntry *var = find_variable(expr_node->codegen_node->expr_node.block_context,
- &node->data.symbol);
+ VariableTableEntry *var = find_variable(get_resolved_expr(expr_node)->block_context,
+ &node->data.symbol_expr.symbol);
assert(var);
// semantic checking ensures no variables are constant
assert(!var->is_const);
@@ -630,7 +627,7 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
}
static LLVMValueRef gen_bare_cast(CodeGen *g, AstNode *node, LLVMValueRef expr_val,
- TypeTableEntry *actual_type, TypeTableEntry *wanted_type, CastNode *cast_node)
+ TypeTableEntry *actual_type, TypeTableEntry *wanted_type, Cast *cast_node)
{
switch (cast_node->op) {
case CastOpNothing:
@@ -705,7 +702,7 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
TypeTableEntry *actual_type = get_expr_type(node->data.cast_expr.expr);
TypeTableEntry *wanted_type = get_expr_type(node);
- CastNode *cast_node = &node->codegen_node->data.cast_node;
+ Cast *cast_node = &node->data.cast_expr.cast;
return gen_bare_cast(g, node, expr_val, actual_type, wanted_type, cast_node);
@@ -1218,7 +1215,7 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
assert(node->data.if_var_expr.var_decl.expr);
BlockContext *old_block_context = g->cur_block_context;
- BlockContext *new_block_context = node->codegen_node->data.if_var_node.block_context;
+ BlockContext *new_block_context = node->data.if_var_expr.block_context;
LLVMValueRef init_val;
gen_var_decl_raw(g, node, &node->data.if_var_expr.var_decl, new_block_context, true, &init_val);
@@ -1242,7 +1239,7 @@ static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *i
assert(block_node->type == NodeTypeBlock);
BlockContext *old_block_context = g->cur_block_context;
- g->cur_block_context = block_node->codegen_node->data.block_node.block_context;
+ g->cur_block_context = block_node->data.block.block_context;
LLVMValueRef return_value;
for (int i = 0; i < block_node->data.block.statements.length; i += 1) {
@@ -1347,7 +1344,7 @@ static LLVMValueRef gen_asm_expr(CodeGen *g, AstNode *node) {
if (!is_return) {
VariableTableEntry *variable = find_variable(
- node->codegen_node->expr_node.block_context,
+ get_resolved_expr(node)->block_context,
&asm_output->variable_name);
assert(variable);
param_types[param_index] = LLVMTypeOf(variable->value_ref);
@@ -1396,7 +1393,7 @@ static LLVMValueRef gen_null_literal(CodeGen *g, AstNode *node) {
TypeTableEntry *type_entry = get_expr_type(node);
assert(type_entry->id == TypeTableEntryIdMaybe);
- LLVMValueRef tmp_struct_ptr = node->codegen_node->data.struct_val_expr_node.ptr;
+ LLVMValueRef tmp_struct_ptr = node->data.null_literal.resolved_struct_val_expr.ptr;
add_debug_source_node(g, node);
LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");
@@ -1416,12 +1413,13 @@ static LLVMValueRef gen_struct_val_expr(CodeGen *g, AstNode *node) {
int field_count = type_entry->data.structure.field_count;
assert(field_count == node->data.struct_val_expr.fields.length);
- StructValExprNode *struct_val_expr_node = &node->codegen_node->data.struct_val_expr_node;
+ StructValExprCodeGen *struct_val_expr_node = &node->data.struct_val_expr.codegen;
LLVMValueRef tmp_struct_ptr = struct_val_expr_node->ptr;
for (int i = 0; i < field_count; i += 1) {
AstNode *field_node = node->data.struct_val_expr.fields.at(i);
- int index = field_node->codegen_node->data.struct_val_field_node.index;
+ assert(field_node->type == NodeTypeStructValueField);
+ int index = field_node->data.struct_val_field.index;
TypeStructField *type_struct_field = &type_entry->data.structure.fields[index];
assert(buf_eql_buf(type_struct_field->name, &field_node->data.struct_val_field.name));
@@ -1439,8 +1437,8 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
assert(node->data.while_expr.condition);
assert(node->data.while_expr.body);
- bool condition_always_true = node->codegen_node->data.while_node.condition_always_true;
- bool contains_break = node->codegen_node->data.while_node.contains_break;
+ bool condition_always_true = node->data.while_expr.condition_always_true;
+ bool contains_break = node->data.while_expr.contains_break;
if (condition_always_true) {
// generate a forever loop
@@ -1559,17 +1557,17 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa
static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) {
LLVMValueRef init_val;
return gen_var_decl_raw(g, node, &node->data.variable_declaration,
- node->codegen_node->expr_node.block_context, false, &init_val);
+ get_resolved_expr(node)->block_context, false, &init_val);
}
static LLVMValueRef gen_number_literal_raw(CodeGen *g, AstNode *source_node,
- NumberLiteralNode *codegen_num_lit, AstNodeNumberLiteral *num_lit_node)
+ NumLitCodeGen *codegen_num_lit, AstNodeNumberLiteral *num_lit_node)
{
TypeTableEntry *type_entry = codegen_num_lit->resolved_type;
assert(type_entry);
// override the expression type for number literals
- source_node->codegen_node->expr_node.type_entry = type_entry;
+ get_resolved_expr(source_node)->type_entry = type_entry;
if (type_entry->id == TypeTableEntryIdInt) {
// here the union has int64_t and uint64_t and we purposefully read
@@ -1594,7 +1592,7 @@ static LLVMValueRef gen_compiler_fn_type(CodeGen *g, AstNode *node) {
Buf *name = &node->data.compiler_fn_type.name;
TypeTableEntry *type_entry = get_type_for_type_node(g, node->data.compiler_fn_type.type);
if (buf_eql_str(name, "sizeof")) {
- NumberLiteralNode *codegen_num_lit = &node->codegen_node->data.num_lit_node;
+ NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node);
AstNodeNumberLiteral num_lit_node;
num_lit_node.kind = type_entry->data.num_lit.kind;
num_lit_node.overflow = false;
@@ -1632,7 +1630,7 @@ static LLVMValueRef gen_compiler_fn_type(CodeGen *g, AstNode *node) {
static LLVMValueRef gen_number_literal(CodeGen *g, AstNode *node) {
assert(node->type == NodeTypeNumberLiteral);
- NumberLiteralNode *codegen_num_lit = &node->codegen_node->data.num_lit_node;
+ NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node);
assert(codegen_num_lit);
return gen_number_literal_raw(g, node, codegen_num_lit, &node->data.number_literal);
@@ -1664,7 +1662,7 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
case NodeTypeVoid:
return nullptr;
case NodeTypeBoolLiteral:
- if (node->data.bool_literal)
+ if (node->data.bool_literal.value)
return LLVMConstAllOnes(LLVMInt1Type());
else
return LLVMConstNull(LLVMInt1Type());
@@ -1696,8 +1694,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
case NodeTypeSymbol:
{
VariableTableEntry *variable = find_variable(
- node->codegen_node->expr_node.block_context,
- &node->data.symbol);
+ get_resolved_expr(node)->block_context,
+ &node->data.symbol_expr.symbol);
assert(variable);
if (variable->type->id == TypeTableEntryIdVoid) {
return nullptr;
@@ -1721,14 +1719,14 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
return gen_block(g, node, nullptr);
case NodeTypeGoto:
add_debug_source_node(g, node);
- return LLVMBuildBr(g->builder, node->codegen_node->data.label_entry->basic_block);
+ return LLVMBuildBr(g->builder, node->data.goto_expr.label_entry->basic_block);
case NodeTypeBreak:
return gen_break(g, node);
case NodeTypeContinue:
return gen_continue(g, node);
case NodeTypeLabel:
{
- LabelTableEntry *label_entry = node->codegen_node->data.label_entry;
+ LabelTableEntry *label_entry = node->data.label.label_entry;
assert(label_entry);
LLVMBasicBlockRef basic_block = label_entry->basic_block;
if (label_entry->entered_from_fallthrough) {
@@ -1770,19 +1768,19 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
return val;
}
- assert(node->codegen_node);
+ Expr *expr = get_resolved_expr(node);
- TypeTableEntry *before_type = node->codegen_node->expr_node.type_entry;
+ TypeTableEntry *before_type = expr->type_entry;
if (before_type && before_type->id == TypeTableEntryIdUnreachable) {
return val;
}
- CastNode *cast_node = &node->codegen_node->expr_node.implicit_cast;
+ Cast *cast_node = &expr->implicit_cast;
if (cast_node->after_type) {
val = gen_bare_cast(g, node, val, before_type, cast_node->after_type, cast_node);
before_type = cast_node->after_type;
}
- cast_node = &node->codegen_node->expr_node.implicit_maybe_cast;
+ cast_node = &expr->implicit_maybe_cast;
if (cast_node->after_type) {
val = gen_bare_cast(g, node, val, before_type, cast_node->after_type, cast_node);
}
@@ -1798,7 +1796,7 @@ static void build_label_blocks(CodeGen *g, AstNode *block_node) {
continue;
Buf *name = &label_node->data.label.name;
- label_node->codegen_node->data.label_entry->basic_block = LLVMAppendBasicBlock(
+ label_node->data.label.label_entry->basic_block = LLVMAppendBasicBlock(
g->cur_fn->fn_value, buf_ptr(name));
}
@@ -1944,13 +1942,7 @@ static void do_code_gen(CodeGen *g) {
LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn, "entry");
LLVMPositionBuilderAtEnd(g->builder, entry_block);
- CodeGenNode *codegen_node = fn_def_node->codegen_node;
- assert(codegen_node);
-
- FnDefNode *codegen_fn_def = &codegen_node->data.fn_def_node;
- assert(codegen_fn_def);
-
- codegen_fn_def->block_context->di_scope = LLVMZigSubprogramToScope(subprogram);
+ fn_def_node->data.fn_def.block_context->di_scope = LLVMZigSubprogramToScope(subprogram);
int non_void_param_count = count_non_void_params(g, &fn_proto->params);
assert(non_void_param_count == (int)LLVMCountParams(fn));
@@ -1963,7 +1955,7 @@ static void do_code_gen(CodeGen *g) {
assert(param_decl->type == NodeTypeParamDecl);
if (is_param_decl_type_void(g, param_decl))
continue;
- VariableTableEntry *parameter_variable = fn_def_node->codegen_node->data.fn_def_node.block_context->variable_table.get(¶m_decl->data.param_decl.name);
+ VariableTableEntry *parameter_variable = fn_def_node->data.fn_def.block_context->variable_table.get(¶m_decl->data.param_decl.name);
parameter_variable->value_ref = params[non_void_index];
non_void_index += 1;
}
@@ -2019,14 +2011,14 @@ static void do_code_gen(CodeGen *g) {
// allocate structs which are the result of casts
for (int cea_i = 0; cea_i < block_context->cast_expr_alloca_list.length; cea_i += 1) {
- CastNode *cast_node = block_context->cast_expr_alloca_list.at(cea_i);
+ Cast *cast_node = block_context->cast_expr_alloca_list.at(cea_i);
add_debug_source_node(g, cast_node->source_node);
cast_node->ptr = LLVMBuildAlloca(g->builder, cast_node->after_type->type_ref, "");
}
// allocate structs which are struct value expressions
for (int alloca_i = 0; alloca_i < block_context->struct_val_expr_alloca_list.length; alloca_i += 1) {
- StructValExprNode *struct_val_expr_node = block_context->struct_val_expr_alloca_list.at(alloca_i);
+ StructValExprCodeGen *struct_val_expr_node = block_context->struct_val_expr_alloca_list.at(alloca_i);
add_debug_source_node(g, struct_val_expr_node->source_node);
struct_val_expr_node->ptr = LLVMBuildAlloca(g->builder,
struct_val_expr_node->type_entry->type_ref, "");
@@ -2041,15 +2033,15 @@ static void do_code_gen(CodeGen *g) {
if (is_param_decl_type_void(g, param_decl))
continue;
- VariableTableEntry *variable = param_decl->codegen_node->data.param_decl_node.variable;
+ VariableTableEntry *variable = param_decl->data.param_decl.variable;
LLVMZigDILocation *debug_loc = LLVMZigGetDebugLoc(param_decl->line + 1, param_decl->column + 1,
- codegen_fn_def->block_context->di_scope);
+ fn_def_node->data.fn_def.block_context->di_scope);
LLVMZigInsertDeclareAtEnd(g->dbuilder, variable->value_ref, variable->di_loc_var, debug_loc,
entry_block);
}
- TypeTableEntry *implicit_return_type = codegen_fn_def->implicit_return_type;
+ TypeTableEntry *implicit_return_type = fn_def_node->data.fn_def.implicit_return_type;
gen_block(g, fn_def_node->data.fn_def.body, implicit_return_type);
}
@@ -2549,8 +2541,6 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
Buf *import_code = buf_alloc();
bool found_it = false;
- alloc_codegen_node(top_level_decl);
-
for (int path_i = 0; path_i < g->lib_search_paths.length; path_i += 1) {
Buf *search_path = g->lib_search_paths.at(path_i);
os_path_join(search_path, import_target_path, &full_path);
@@ -2570,7 +2560,7 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
auto entry = g->import_table.maybe_get(abs_full_path);
if (entry) {
found_it = true;
- top_level_decl->codegen_node->data.import_node.import = entry->value;
+ top_level_decl->data.use.import = entry->value;
} else {
if ((err = os_fetch_file_path(abs_full_path, import_code))) {
if (err == ErrorFileNotFound) {
@@ -2582,7 +2572,7 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
goto done_looking_at_imports;
}
}
- top_level_decl->codegen_node->data.import_node.import = codegen_add_code(g,
+ top_level_decl->data.use.import = codegen_add_code(g,
abs_full_path, search_path, &top_level_decl->data.use.path, import_code);
found_it = true;
}
@@ -2682,9 +2672,8 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou
static void to_c_type(CodeGen *g, AstNode *type_node, Buf *out_buf) {
assert(type_node->type == NodeTypeType);
- assert(type_node->codegen_node);
- TypeTableEntry *type_entry = type_node->codegen_node->data.type_node.entry;
+ TypeTableEntry *type_entry = type_node->data.type.entry;
assert(type_entry);
if (type_entry == g->builtin_types.entry_u8) {
src/codegen.hpp
@@ -11,21 +11,8 @@
#include "parser.hpp"
#include "errmsg.hpp"
-struct CodeGen;
-
-enum OutType {
- OutTypeUnknown,
- OutTypeExe,
- OutTypeLib,
- OutTypeObj,
-};
-
CodeGen *codegen_create(Buf *root_source_dir);
-enum CodeGenBuildType {
- CodeGenBuildTypeDebug,
- CodeGenBuildTypeRelease,
-};
void codegen_set_build_type(CodeGen *codegen, CodeGenBuildType build_type);
void codegen_set_is_static(CodeGen *codegen, bool is_static);
void codegen_set_strip(CodeGen *codegen, bool strip);
src/parser.cpp
@@ -356,8 +356,7 @@ void ast_print(AstNode *node, int indent) {
fprintf(stderr, "Unreachable\n");
break;
case NodeTypeSymbol:
- fprintf(stderr, "Symbol %s\n",
- buf_ptr(&node->data.symbol));
+ fprintf(stderr, "Symbol %s\n", buf_ptr(&node->data.symbol_expr.symbol));
break;
case NodeTypeUse:
fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.use.path));
@@ -366,7 +365,8 @@ void ast_print(AstNode *node, int indent) {
fprintf(stderr, "%s\n", node_type_str(node->type));
break;
case NodeTypeBoolLiteral:
- fprintf(stderr, "%s '%s'\n", node_type_str(node->type), node->data.bool_literal ? "true" : "false");
+ fprintf(stderr, "%s '%s'\n", node_type_str(node->type),
+ node->data.bool_literal.value ? "true" : "false");
break;
case NodeTypeNullLiteral:
fprintf(stderr, "%s\n", node_type_str(node->type));
@@ -401,7 +401,7 @@ void ast_print(AstNode *node, int indent) {
fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.label.name));
break;
case NodeTypeGoto:
- fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.go_to.name));
+ fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.goto_expr.name));
break;
case NodeTypeBreak:
fprintf(stderr, "%s\n", node_type_str(node->type));
@@ -1369,12 +1369,12 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
return node;
} else if (token->id == TokenIdKeywordTrue) {
AstNode *node = ast_create_node(pc, NodeTypeBoolLiteral, token);
- node->data.bool_literal = true;
+ node->data.bool_literal.value = true;
*token_index += 1;
return node;
} else if (token->id == TokenIdKeywordFalse) {
AstNode *node = ast_create_node(pc, NodeTypeBoolLiteral, token);
- node->data.bool_literal = false;
+ node->data.bool_literal.value = false;
*token_index += 1;
return node;
} else if (token->id == TokenIdKeywordNull) {
@@ -1385,7 +1385,7 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
*token_index += 1;
Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
AstNode *name_node = ast_create_node(pc, NodeTypeSymbol, name_tok);
- ast_buf_from_token(pc, name_tok, &name_node->data.symbol);
+ ast_buf_from_token(pc, name_tok, &name_node->data.symbol_expr.symbol);
AstNode *node = ast_create_node(pc, NodeTypeFnCallExpr, token);
node->data.fn_call_expr.fn_ref_expr = name_node;
@@ -1401,7 +1401,7 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
} else {
*token_index += 1;
AstNode *node = ast_create_node(pc, NodeTypeSymbol, token);
- ast_buf_from_token(pc, token, &node->data.symbol);
+ ast_buf_from_token(pc, token, &node->data.symbol_expr.symbol);
return node;
}
} else if (token->id == TokenIdKeywordGoto) {
@@ -1412,7 +1412,7 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
*token_index += 1;
ast_expect_token(pc, dest_symbol, TokenIdSymbol);
- ast_buf_from_token(pc, dest_symbol, &node->data.go_to.name);
+ ast_buf_from_token(pc, dest_symbol, &node->data.goto_expr.name);
return node;
} else if (token->id == TokenIdKeywordBreak) {
AstNode *node = ast_create_node(pc, NodeTypeBreak, token);
src/parser.hpp
@@ -8,450 +8,10 @@
#ifndef ZIG_PARSER_HPP
#define ZIG_PARSER_HPP
-#include "list.hpp"
-#include "buffer.hpp"
+#include "all_types.hpp"
#include "tokenizer.hpp"
#include "errmsg.hpp"
-struct AstNode;
-struct CodeGenNode;
-struct ImportTableEntry;
-struct AsmToken;
-
-enum NodeType {
- NodeTypeRoot,
- NodeTypeRootExportDecl,
- NodeTypeFnProto,
- NodeTypeFnDef,
- NodeTypeFnDecl,
- NodeTypeParamDecl,
- NodeTypeType,
- NodeTypeBlock,
- NodeTypeExternBlock,
- NodeTypeDirective,
- NodeTypeReturnExpr,
- NodeTypeVariableDeclaration,
- NodeTypeBinOpExpr,
- NodeTypeCastExpr,
- NodeTypeNumberLiteral,
- NodeTypeStringLiteral,
- NodeTypeCharLiteral,
- NodeTypeUnreachable,
- NodeTypeSymbol,
- NodeTypePrefixOpExpr,
- NodeTypeFnCallExpr,
- NodeTypeArrayAccessExpr,
- NodeTypeSliceExpr,
- NodeTypeFieldAccessExpr,
- NodeTypeUse,
- NodeTypeVoid,
- NodeTypeBoolLiteral,
- NodeTypeNullLiteral,
- NodeTypeIfBoolExpr,
- NodeTypeIfVarExpr,
- NodeTypeWhileExpr,
- NodeTypeLabel,
- NodeTypeGoto,
- NodeTypeBreak,
- NodeTypeContinue,
- NodeTypeAsmExpr,
- NodeTypeStructDecl,
- NodeTypeStructField,
- NodeTypeStructValueExpr,
- NodeTypeStructValueField,
- NodeTypeEnumDecl,
- NodeTypeEnumField,
- NodeTypeCompilerFnExpr,
- NodeTypeCompilerFnType,
-};
-
-struct AstNodeRoot {
- ZigList<AstNode *> top_level_decls;
-};
-
-enum VisibMod {
- VisibModPrivate,
- VisibModPub,
- VisibModExport,
-};
-
-struct AstNodeFnProto {
- ZigList<AstNode *> *directives;
- VisibMod visib_mod;
- Buf name;
- ZigList<AstNode *> params;
- AstNode *return_type;
- bool is_var_args;
-
- // the extern block this fn proto is inside. can be null.
- // populated by semantic analyzer.
- AstNode *extern_node;
- // the struct decl node this fn proto is inside. can be null.
- // populated by semantic analyzer.
- AstNode *struct_node;
- // the function definition this fn proto is inside. can be null.
- // populated by semantic analyzer.
- AstNode *fn_def_node;
-};
-
-struct AstNodeFnDef {
- AstNode *fn_proto;
- AstNode *body;
-};
-
-struct AstNodeFnDecl {
- AstNode *fn_proto;
-};
-
-struct AstNodeParamDecl {
- Buf name;
- AstNode *type;
-};
-
-enum AstNodeTypeType {
- AstNodeTypeTypePrimitive,
- AstNodeTypeTypePointer,
- AstNodeTypeTypeArray,
- AstNodeTypeTypeMaybe,
- AstNodeTypeTypeCompilerExpr,
-};
-
-struct AstNodeType {
- AstNodeTypeType type;
- Buf primitive_name;
- AstNode *child_type;
- AstNode *array_size; // can be null
- bool is_const;
- bool is_noalias;
- AstNode *compiler_expr;
-};
-
-struct AstNodeBlock {
- ZigList<AstNode *> statements;
-};
-
-struct AstNodeReturnExpr {
- // might be null in case of return void;
- AstNode *expr;
-};
-
-struct AstNodeVariableDeclaration {
- Buf symbol;
- bool is_const;
- VisibMod visib_mod;
- // one or both of type and expr will be non null
- AstNode *type;
- AstNode *expr;
-};
-
-enum BinOpType {
- BinOpTypeInvalid,
- BinOpTypeAssign,
- BinOpTypeAssignTimes,
- BinOpTypeAssignDiv,
- BinOpTypeAssignMod,
- BinOpTypeAssignPlus,
- BinOpTypeAssignMinus,
- BinOpTypeAssignBitShiftLeft,
- BinOpTypeAssignBitShiftRight,
- BinOpTypeAssignBitAnd,
- BinOpTypeAssignBitXor,
- BinOpTypeAssignBitOr,
- BinOpTypeAssignBoolAnd,
- BinOpTypeAssignBoolOr,
- BinOpTypeBoolOr,
- BinOpTypeBoolAnd,
- BinOpTypeCmpEq,
- BinOpTypeCmpNotEq,
- BinOpTypeCmpLessThan,
- BinOpTypeCmpGreaterThan,
- BinOpTypeCmpLessOrEq,
- BinOpTypeCmpGreaterOrEq,
- BinOpTypeBinOr,
- BinOpTypeBinXor,
- BinOpTypeBinAnd,
- BinOpTypeBitShiftLeft,
- BinOpTypeBitShiftRight,
- BinOpTypeAdd,
- BinOpTypeSub,
- BinOpTypeMult,
- BinOpTypeDiv,
- BinOpTypeMod,
- BinOpTypeUnwrapMaybe,
-};
-
-struct AstNodeBinOpExpr {
- AstNode *op1;
- BinOpType bin_op;
- AstNode *op2;
-};
-
-struct AstNodeFnCallExpr {
- AstNode *fn_ref_expr;
- ZigList<AstNode *> params;
- bool is_builtin;
-};
-
-struct AstNodeArrayAccessExpr {
- AstNode *array_ref_expr;
- AstNode *subscript;
-};
-
-struct AstNodeSliceExpr {
- AstNode *array_ref_expr;
- AstNode *start;
- AstNode *end;
- bool is_const;
-};
-
-struct AstNodeFieldAccessExpr {
- AstNode *struct_expr;
- Buf field_name;
-};
-
-struct AstNodeExternBlock {
- ZigList<AstNode *> *directives;
- ZigList<AstNode *> fn_decls;
-};
-
-struct AstNodeDirective {
- Buf name;
- Buf param;
-};
-
-struct AstNodeRootExportDecl {
- Buf type;
- Buf name;
- ZigList<AstNode *> *directives;
-};
-
-struct AstNodeCastExpr {
- AstNode *expr;
- AstNode *type;
-};
-
-enum PrefixOp {
- PrefixOpInvalid,
- PrefixOpBoolNot,
- PrefixOpBinNot,
- PrefixOpNegation,
- PrefixOpAddressOf,
- PrefixOpConstAddressOf,
- PrefixOpDereference,
-};
-
-struct AstNodePrefixOpExpr {
- PrefixOp prefix_op;
- AstNode *primary_expr;
-};
-
-struct AstNodeUse {
- Buf path;
- ZigList<AstNode *> *directives;
-};
-
-struct AstNodeIfBoolExpr {
- AstNode *condition;
- AstNode *then_block;
- AstNode *else_node; // null, block node, or other if expr node
-};
-
-struct AstNodeIfVarExpr {
- AstNodeVariableDeclaration var_decl;
- AstNode *then_block;
- AstNode *else_node; // null, block node, or other if expr node
-};
-
-struct AstNodeWhileExpr {
- AstNode *condition;
- AstNode *body;
-};
-
-struct AstNodeLabel {
- Buf name;
-};
-
-struct AstNodeGoto {
- Buf name;
-};
-
-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 {
- int line;
- int column;
-};
-
-struct AstNodeAsmExpr {
- bool is_volatile;
- Buf asm_template;
- ZigList<SrcPos> offset_map;
- ZigList<AsmToken> token_list;
- ZigList<AsmOutput*> output_list;
- ZigList<AsmInput*> input_list;
- ZigList<Buf*> clobber_list;
- int return_count; // populated by analyze
-};
-
-struct AstNodeStructDecl {
- Buf name;
- ZigList<AstNode *> fields;
- ZigList<AstNode *> fns;
- ZigList<AstNode *> *directives;
- VisibMod visib_mod;
-};
-
-struct AstNodeStructField {
- Buf name;
- AstNode *type;
- ZigList<AstNode *> *directives;
-};
-
-struct AstNodeEnumDecl {
- Buf name;
- ZigList<AstNode *> fields;
- ZigList<AstNode *> *directives;
- VisibMod visib_mod;
-};
-
-struct AstNodeEnumField {
- Buf name;
- ZigList<AstNode *> fields; // length 0 means simple enum
- AstNode *val_expr;
-};
-
-struct AstNodeStringLiteral {
- Buf buf;
- bool c;
-};
-
-struct AstNodeCharLiteral {
- uint8_t value;
-};
-
-enum NumLit {
- NumLitF32,
- NumLitF64,
- NumLitF128,
- NumLitU8,
- NumLitU16,
- NumLitU32,
- NumLitU64,
- NumLitI8,
- NumLitI16,
- NumLitI32,
- NumLitI64,
-
- NumLitCount
-};
-
-struct AstNodeNumberLiteral {
- NumLit kind;
-
- // overflow is true if when parsing the number, we discovered it would not
- // fit without losing data in a uint64_t, int64_t, or double
- bool overflow;
-
- union {
- uint64_t x_uint;
- int64_t x_int;
- double x_float;
- } data;
-};
-
-struct AstNodeStructValueField {
- Buf name;
- AstNode *expr;
-};
-
-struct AstNodeStructValueExpr {
- AstNode *type;
- ZigList<AstNode *> fields;
-};
-
-struct AstNodeCompilerFnExpr {
- Buf name;
- AstNode *expr;
-};
-
-struct AstNodeCompilerFnType {
- Buf name;
- AstNode *type;
-};
-
-struct AstNode {
- enum NodeType type;
- int line;
- int column;
- uint32_t create_index; // for determinism purposes
- CodeGenNode *codegen_node;
- ImportTableEntry *owner;
- union {
- AstNodeRoot root;
- AstNodeRootExportDecl root_export_decl;
- AstNodeFnDef fn_def;
- AstNodeFnDecl fn_decl;
- AstNodeFnProto fn_proto;
- AstNodeType type;
- AstNodeParamDecl param_decl;
- AstNodeBlock block;
- AstNodeReturnExpr return_expr;
- AstNodeVariableDeclaration variable_declaration;
- AstNodeBinOpExpr bin_op_expr;
- AstNodeExternBlock extern_block;
- AstNodeDirective directive;
- AstNodeCastExpr cast_expr;
- AstNodePrefixOpExpr prefix_op_expr;
- AstNodeFnCallExpr fn_call_expr;
- AstNodeArrayAccessExpr array_access_expr;
- AstNodeSliceExpr slice_expr;
- AstNodeUse use;
- AstNodeIfBoolExpr if_bool_expr;
- AstNodeIfVarExpr if_var_expr;
- AstNodeWhileExpr while_expr;
- AstNodeLabel label;
- AstNodeGoto go_to;
- AstNodeAsmExpr asm_expr;
- AstNodeFieldAccessExpr field_access_expr;
- AstNodeStructDecl struct_decl;
- AstNodeStructField struct_field;
- AstNodeEnumDecl enum_decl;
- AstNodeEnumField enum_field;
- AstNodeStringLiteral string_literal;
- AstNodeCharLiteral char_literal;
- AstNodeNumberLiteral number_literal;
- AstNodeStructValueExpr struct_val_expr;
- AstNodeStructValueField struct_val_field;
- AstNodeCompilerFnExpr compiler_fn_expr;
- AstNodeCompilerFnType compiler_fn_type;
- Buf symbol;
- bool bool_literal;
- } data;
-};
-
-enum AsmTokenId {
- AsmTokenIdTemplate,
- AsmTokenIdPercent,
- AsmTokenIdVar,
-};
-
-struct AsmToken {
- enum AsmTokenId id;
- int start;
- int end;
-};
-
__attribute__ ((format (printf, 2, 3)))
void ast_token_error(Token *token, const char *format, ...);