| ... | ... | @@ -97,17 +97,24 @@ static ZigList<AstNode *> *create_empty_directives(Context *c) { |
| 97 | 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 | 103 | AstNode *node = create_node(c, NodeTypeVariableDeclaration); |
| 102 | 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 | 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 | 108 | node->data.variable_declaration.directives = create_empty_directives(c); |
| 109 | node->data.variable_declaration.type = type_node; |
| 107 | 110 | normalize_parent_ptrs(node); |
| 108 | 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 | 118 | static AstNode *create_prefix_node(Context *c, PrefixOp op, AstNode *child_node) { |
| 112 | 119 | assert(child_node); |
| 113 | 120 | AstNode *node = create_node(c, NodeTypePrefixOpExpr); |
| ... | ... | @@ -150,10 +157,24 @@ static AstNode *create_num_lit_unsigned(Context *c, uint64_t x) { |
| 150 | 157 | AstNode *node = create_node(c, NodeTypeNumberLiteral); |
| 151 | 158 | node->data.number_literal.kind = NumLitUInt; |
| 152 | 159 | node->data.number_literal.data.x_uint = x; |
| 153 | | |
| 154 | 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 | 178 | static AstNode *create_array_type_node(Context *c, AstNode *child_type_node, uint64_t size, bool is_const) { |
| 158 | 179 | AstNode *node = create_node(c, NodeTypeArrayType); |
| 159 | 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 | 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 | 231 | static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl, |
| 206 | 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 | 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 | 816 | static bool decl_visitor(void *context, const Decl *decl) { |
| 693 | 817 | Context *c = (Context*)context; |
| 694 | 818 | |
| ... | ... | @@ -705,6 +829,9 @@ static bool decl_visitor(void *context, const Decl *decl) { |
| 705 | 829 | case Decl::Record: |
| 706 | 830 | visit_record_decl(c, static_cast<const RecordDecl *>(decl)); |
| 707 | 831 | break; |
| 832 | case Decl::Var: |
| 833 | visit_var_decl(c, static_cast<const VarDecl *>(decl)); |
| 834 | break; |
| 708 | 835 | default: |
| 709 | 836 | emit_warning(c, decl, "ignoring %s decl\n", decl->getDeclKindName()); |
| 710 | 837 | } |