| ... | @@ -97,17 +97,24 @@ static ZigList<AstNode *> *create_empty_directives(Context *c) { | ... | @@ -97,17 +97,24 @@ static ZigList<AstNode *> *create_empty_directives(Context *c) { |
| 97 | return allocate<ZigList<AstNode*>>(1); | 97 | return allocate<ZigList<AstNode*>>(1); |
| 98 | } | 98 | } |
| 99 | | 99 | |
| 100 | static AstNode *create_var_decl_node(Context *c, const char *var_name, AstNode *expr_node) { | 100 | static AstNode *create_typed_var_decl_node(Context *c, bool is_const, const char *var_name, |
| | 101 | AstNode *type_node, AstNode *init_node) |
| | 102 | { |
| 101 | AstNode *node = create_node(c, NodeTypeVariableDeclaration); | 103 | AstNode *node = create_node(c, NodeTypeVariableDeclaration); |
| 102 | buf_init_from_str(&node->data.variable_declaration.symbol, var_name); | 104 | buf_init_from_str(&node->data.variable_declaration.symbol, var_name); |
| 103 | node->data.variable_declaration.is_const = true; | 105 | node->data.variable_declaration.is_const = is_const; |
| 104 | node->data.variable_declaration.visib_mod = c->visib_mod; | 106 | node->data.variable_declaration.visib_mod = c->visib_mod; |
| 105 | node->data.variable_declaration.expr = expr_node; | 107 | node->data.variable_declaration.expr = init_node; |
| 106 | node->data.variable_declaration.directives = create_empty_directives(c); | 108 | node->data.variable_declaration.directives = create_empty_directives(c); |
| | 109 | node->data.variable_declaration.type = type_node; |
| 107 | normalize_parent_ptrs(node); | 110 | normalize_parent_ptrs(node); |
| 108 | return node; | 111 | return node; |
| 109 | } | 112 | } |
| 110 | | 113 | |
| | 114 | static AstNode *create_var_decl_node(Context *c, const char *var_name, AstNode *expr_node) { |
| | 115 | return create_typed_var_decl_node(c, true, var_name, nullptr, expr_node); |
| | 116 | } |
| | 117 | |
| 111 | static AstNode *create_prefix_node(Context *c, PrefixOp op, AstNode *child_node) { | 118 | static AstNode *create_prefix_node(Context *c, PrefixOp op, AstNode *child_node) { |
| 112 | assert(child_node); | 119 | assert(child_node); |
| 113 | AstNode *node = create_node(c, NodeTypePrefixOpExpr); | 120 | AstNode *node = create_node(c, NodeTypePrefixOpExpr); |
| ... | @@ -150,10 +157,24 @@ static AstNode *create_num_lit_unsigned(Context *c, uint64_t x) { | ... | @@ -150,10 +157,24 @@ static AstNode *create_num_lit_unsigned(Context *c, uint64_t x) { |
| 150 | AstNode *node = create_node(c, NodeTypeNumberLiteral); | 157 | AstNode *node = create_node(c, NodeTypeNumberLiteral); |
| 151 | node->data.number_literal.kind = NumLitUInt; | 158 | node->data.number_literal.kind = NumLitUInt; |
| 152 | node->data.number_literal.data.x_uint = x; | 159 | node->data.number_literal.data.x_uint = x; |
| 153 | | | |
| 154 | return node; | 160 | return node; |
| 155 | } | 161 | } |
| 156 | | 162 | |
| | 163 | static AstNode *create_num_lit_signed(Context *c, int64_t x) { |
| | 164 | if (x >= 0) { |
| | 165 | return create_num_lit_unsigned(c, x); |
| | 166 | } |
| | 167 | BigNum bn_orig; |
| | 168 | bignum_init_signed(&bn_orig, x); |
| | 169 | |
| | 170 | BigNum bn_negated; |
| | 171 | bignum_negate(&bn_negated, &bn_orig); |
| | 172 | |
| | 173 | uint64_t uint = bignum_to_twos_complement(&bn_negated); |
| | 174 | AstNode *num_lit_node = create_num_lit_unsigned(c, uint); |
| | 175 | return create_prefix_node(c, PrefixOpNegation, num_lit_node); |
| | 176 | } |
| | 177 | |
| 157 | static AstNode *create_array_type_node(Context *c, AstNode *child_type_node, uint64_t size, bool is_const) { | 178 | static AstNode *create_array_type_node(Context *c, AstNode *child_type_node, uint64_t size, bool is_const) { |
| 158 | AstNode *node = create_node(c, NodeTypeArrayType); | 179 | AstNode *node = create_node(c, NodeTypeArrayType); |
| 159 | node->data.array_type.size = create_num_lit_unsigned(c, size); | 180 | node->data.array_type.size = create_num_lit_unsigned(c, size); |
| ... | @@ -202,6 +223,11 @@ static AstNode *pointer_to_type(Context *c, AstNode *type_node, bool is_const) { | ... | @@ -202,6 +223,11 @@ static AstNode *pointer_to_type(Context *c, AstNode *type_node, bool is_const) { |
| 202 | return create_prefix_node(c, PrefixOpMaybe, child_node); | 223 | return create_prefix_node(c, PrefixOpMaybe, child_node); |
| 203 | } | 224 | } |
| 204 | | 225 | |
| | 226 | static bool type_is_int(AstNode *type_node) { |
| | 227 | // TODO recurse through the type table |
| | 228 | return true; |
| | 229 | } |
| | 230 | |
| 205 | static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl, | 231 | static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl, |
| 206 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> *type_table) | 232 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> *type_table) |
| 207 | { | 233 | { |
| ... | @@ -689,6 +715,104 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) { | ... | @@ -689,6 +715,104 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) { |
| 689 | add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name)); | 715 | add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name)); |
| 690 | } | 716 | } |
| 691 | | 717 | |
| | 718 | static void visit_var_decl(Context *c, const VarDecl *var_decl) { |
| | 719 | Buf *name = buf_create_from_str(decl_name(var_decl)); |
| | 720 | |
| | 721 | switch (var_decl->getTLSKind()) { |
| | 722 | case VarDecl::TLS_None: |
| | 723 | break; |
| | 724 | case VarDecl::TLS_Static: |
| | 725 | emit_warning(c, var_decl, "ignoring variable '%s' - static thread local storage\n", buf_ptr(name)); |
| | 726 | return; |
| | 727 | case VarDecl::TLS_Dynamic: |
| | 728 | emit_warning(c, var_decl, "ignoring variable '%s' - dynamic thread local storage\n", buf_ptr(name)); |
| | 729 | return; |
| | 730 | } |
| | 731 | |
| | 732 | QualType qt = var_decl->getType(); |
| | 733 | AstNode *type_node = make_qual_type_node(c, qt, var_decl); |
| | 734 | if (!type_node) { |
| | 735 | emit_warning(c, var_decl, "ignoring variable '%s' - unresolved type\n", buf_ptr(name)); |
| | 736 | return; |
| | 737 | } |
| | 738 | |
| | 739 | bool is_extern = var_decl->hasExternalStorage(); |
| | 740 | bool is_static = var_decl->isFileVarDecl(); |
| | 741 | bool is_const = qt.isConstQualified(); |
| | 742 | |
| | 743 | if (is_static && !is_extern) { |
| | 744 | if (!var_decl->hasInit()) { |
| | 745 | emit_warning(c, var_decl, "ignoring variable '%s' - no initializer\n", buf_ptr(name)); |
| | 746 | return; |
| | 747 | } |
| | 748 | APValue *ap_value = var_decl->evaluateValue(); |
| | 749 | if (!ap_value) { |
| | 750 | emit_warning(c, var_decl, "ignoring variable '%s' - unable to evaluate initializer\n", buf_ptr(name)); |
| | 751 | return; |
| | 752 | } |
| | 753 | AstNode *init_node; |
| | 754 | switch (ap_value->getKind()) { |
| | 755 | case APValue::Int: |
| | 756 | { |
| | 757 | if (!type_is_int(type_node)) { |
| | 758 | emit_warning(c, var_decl, |
| | 759 | "ignoring variable '%s' - int initializer for non int type\n", buf_ptr(name)); |
| | 760 | return; |
| | 761 | } |
| | 762 | llvm::APSInt aps_int = ap_value->getInt(); |
| | 763 | if (aps_int.isSigned()) { |
| | 764 | if (aps_int > INT64_MAX || aps_int < INT64_MIN) { |
| | 765 | emit_warning(c, var_decl, |
| | 766 | "ignoring variable '%s' - initializer overflow\n", buf_ptr(name)); |
| | 767 | return; |
| | 768 | } else { |
| | 769 | init_node = create_num_lit_signed(c, aps_int.getExtValue()); |
| | 770 | } |
| | 771 | } else { |
| | 772 | if (aps_int > UINT64_MAX) { |
| | 773 | emit_warning(c, var_decl, |
| | 774 | "ignoring variable '%s' - initializer overflow\n", buf_ptr(name)); |
| | 775 | return; |
| | 776 | } else { |
| | 777 | init_node = create_num_lit_unsigned(c, aps_int.getExtValue()); |
| | 778 | } |
| | 779 | } |
| | 780 | break; |
| | 781 | } |
| | 782 | case APValue::Uninitialized: |
| | 783 | case APValue::Float: |
| | 784 | case APValue::ComplexInt: |
| | 785 | case APValue::ComplexFloat: |
| | 786 | case APValue::LValue: |
| | 787 | case APValue::Vector: |
| | 788 | case APValue::Array: |
| | 789 | case APValue::Struct: |
| | 790 | case APValue::Union: |
| | 791 | case APValue::MemberPointer: |
| | 792 | case APValue::AddrLabelDiff: |
| | 793 | emit_warning(c, var_decl, |
| | 794 | "ignoring variable '%s' - unrecognized initializer value kind\n", buf_ptr(name)); |
| | 795 | return; |
| | 796 | } |
| | 797 | |
| | 798 | AstNode *var_node = create_typed_var_decl_node(c, true, buf_ptr(name), type_node, init_node); |
| | 799 | c->root->data.root.top_level_decls.append(var_node); |
| | 800 | c->root_name_table.put(name, true); |
| | 801 | return; |
| | 802 | } |
| | 803 | |
| | 804 | if (is_extern) { |
| | 805 | AstNode *var_node = create_typed_var_decl_node(c, is_const, buf_ptr(name), type_node, nullptr); |
| | 806 | var_node->data.variable_declaration.is_extern = true; |
| | 807 | c->root->data.root.top_level_decls.append(var_node); |
| | 808 | c->root_name_table.put(name, true); |
| | 809 | return; |
| | 810 | } |
| | 811 | |
| | 812 | emit_warning(c, var_decl, "ignoring variable '%s' - non-extern, non-static variable\n", buf_ptr(name)); |
| | 813 | return; |
| | 814 | } |
| | 815 | |
| 692 | static bool decl_visitor(void *context, const Decl *decl) { | 816 | static bool decl_visitor(void *context, const Decl *decl) { |
| 693 | Context *c = (Context*)context; | 817 | Context *c = (Context*)context; |
| 694 | | 818 | |
| ... | @@ -705,6 +829,9 @@ static bool decl_visitor(void *context, const Decl *decl) { | ... | @@ -705,6 +829,9 @@ static bool decl_visitor(void *context, const Decl *decl) { |
| 705 | case Decl::Record: | 829 | case Decl::Record: |
| 706 | visit_record_decl(c, static_cast<const RecordDecl *>(decl)); | 830 | visit_record_decl(c, static_cast<const RecordDecl *>(decl)); |
| 707 | break; | 831 | break; |
| | 832 | case Decl::Var: |
| | 833 | visit_var_decl(c, static_cast<const VarDecl *>(decl)); |
| | 834 | break; |
| 708 | default: | 835 | default: |
| 709 | emit_warning(c, decl, "ignoring %s decl\n", decl->getDeclKindName()); | 836 | emit_warning(c, decl, "ignoring %s decl\n", decl->getDeclKindName()); |
| 710 | } | 837 | } |