| ... | @@ -134,38 +134,6 @@ static TypeTableEntry *fn_proto_type_from_type_node(CodeGen *g, AstNode *type_no | ... | @@ -134,38 +134,6 @@ static TypeTableEntry *fn_proto_type_from_type_node(CodeGen *g, AstNode *type_no |
| 134 | } | 134 | } |
| 135 | } | 135 | } |
| 136 | | 136 | |
| 137 | static LLVMValueRef gen_number_literal(CodeGen *g, AstNode *expr_node) { | | |
| 138 | Expr *expr = get_resolved_expr(expr_node); | | |
| 139 | TypeTableEntry *type_entry = expr->resolved_type; | | |
| 140 | if (!type_entry) { | | |
| 141 | type_entry = expr->type_entry; | | |
| 142 | } | | |
| 143 | assert(type_entry); | | |
| 144 | | | |
| 145 | ConstExprValue *const_val = &expr->const_val; | | |
| 146 | | | |
| 147 | assert(const_val->ok); | | |
| 148 | | | |
| 149 | if (type_entry->id == TypeTableEntryIdInt) { | | |
| 150 | assert(const_val->data.x_bignum.kind == BigNumKindInt); | | |
| 151 | return LLVMConstInt(type_entry->type_ref, | | |
| 152 | bignum_to_twos_complement(&const_val->data.x_bignum), | | |
| 153 | type_entry->data.integral.is_signed); | | |
| 154 | } else if (type_entry->id == TypeTableEntryIdFloat) { | | |
| 155 | if (const_val->data.x_bignum.kind == BigNumKindFloat) { | | |
| 156 | return LLVMConstReal(type_entry->type_ref, const_val->data.x_bignum.data.x_float); | | |
| 157 | } else { | | |
| 158 | int64_t x = const_val->data.x_bignum.data.x_uint; | | |
| 159 | if (const_val->data.x_bignum.is_negative) { | | |
| 160 | x = -x; | | |
| 161 | } | | |
| 162 | return LLVMConstReal(type_entry->type_ref, x); | | |
| 163 | } | | |
| 164 | } else { | | |
| 165 | zig_unreachable(); | | |
| 166 | } | | |
| 167 | } | | |
| 168 | | | |
| 169 | static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { | 137 | static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { |
| 170 | assert(node->type == NodeTypeFnCallExpr); | 138 | assert(node->type == NodeTypeFnCallExpr); |
| 171 | AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; | 139 | AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; |
| ... | @@ -277,7 +245,8 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { | ... | @@ -277,7 +245,8 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { |
| 277 | case BuiltinFnIdMinValue: | 245 | case BuiltinFnIdMinValue: |
| 278 | case BuiltinFnIdMaxValue: | 246 | case BuiltinFnIdMaxValue: |
| 279 | case BuiltinFnIdMemberCount: | 247 | case BuiltinFnIdMemberCount: |
| 280 | return gen_number_literal(g, node); | 248 | // caught by constant expression eval codegen |
| | 249 | zig_unreachable(); |
| 281 | } | 250 | } |
| 282 | zig_unreachable(); | 251 | zig_unreachable(); |
| 283 | } | 252 | } |
| ... | @@ -1884,6 +1853,16 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa | ... | @@ -1884,6 +1853,16 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa |
| 1884 | } | 1853 | } |
| 1885 | | 1854 | |
| 1886 | static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) { | 1855 | static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) { |
| | 1856 | AstNode *init_expr = node->data.variable_declaration.expr; |
| | 1857 | if (node->data.variable_declaration.is_const && init_expr) { |
| | 1858 | TypeTableEntry *init_expr_type = get_expr_type(init_expr); |
| | 1859 | if (init_expr_type->id == TypeTableEntryIdNumLitFloat || |
| | 1860 | init_expr_type->id == TypeTableEntryIdNumLitInt) |
| | 1861 | { |
| | 1862 | return nullptr; |
| | 1863 | } |
| | 1864 | } |
| | 1865 | |
| 1887 | LLVMValueRef init_val; | 1866 | LLVMValueRef init_val; |
| 1888 | return gen_var_decl_raw(g, node, &node->data.variable_declaration, | 1867 | return gen_var_decl_raw(g, node, &node->data.variable_declaration, |
| 1889 | get_resolved_expr(node)->block_context, false, &init_val); | 1868 | get_resolved_expr(node)->block_context, false, &init_val); |
| ... | @@ -1992,6 +1971,11 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) { | ... | @@ -1992,6 +1971,11 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) { |
| 1992 | } | 1971 | } |
| 1993 | | 1972 | |
| 1994 | static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { | 1973 | static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| | 1974 | Expr *expr = get_resolved_expr(node); |
| | 1975 | if (expr->const_val.ok) { |
| | 1976 | assert(expr->const_llvm_val); |
| | 1977 | return expr->const_llvm_val; |
| | 1978 | } |
| 1995 | switch (node->type) { | 1979 | switch (node->type) { |
| 1996 | case NodeTypeBinOpExpr: | 1980 | case NodeTypeBinOpExpr: |
| 1997 | return gen_bin_op_expr(g, node); | 1981 | return gen_bin_op_expr(g, node); |
| ... | @@ -2009,11 +1993,6 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { | ... | @@ -2009,11 +1993,6 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 2009 | return gen_slice_expr(g, node); | 1993 | return gen_slice_expr(g, node); |
| 2010 | case NodeTypeFieldAccessExpr: | 1994 | case NodeTypeFieldAccessExpr: |
| 2011 | return gen_field_access_expr(g, node, false); | 1995 | return gen_field_access_expr(g, node, false); |
| 2012 | case NodeTypeBoolLiteral: | | |
| 2013 | if (node->data.bool_literal.value) | | |
| 2014 | return LLVMConstAllOnes(LLVMInt1Type()); | | |
| 2015 | else | | |
| 2016 | return LLVMConstNull(LLVMInt1Type()); | | |
| 2017 | case NodeTypeNullLiteral: | 1996 | case NodeTypeNullLiteral: |
| 2018 | return gen_null_literal(g, node); | 1997 | return gen_null_literal(g, node); |
| 2019 | case NodeTypeIfBoolExpr: | 1998 | case NodeTypeIfBoolExpr: |
| ... | @@ -2026,8 +2005,6 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { | ... | @@ -2026,8 +2005,6 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 2026 | return gen_for_expr(g, node); | 2005 | return gen_for_expr(g, node); |
| 2027 | case NodeTypeAsmExpr: | 2006 | case NodeTypeAsmExpr: |
| 2028 | return gen_asm_expr(g, node); | 2007 | return gen_asm_expr(g, node); |
| 2029 | case NodeTypeNumberLiteral: | | |
| 2030 | return gen_number_literal(g, node); | | |
| 2031 | case NodeTypeErrorLiteral: | 2008 | case NodeTypeErrorLiteral: |
| 2032 | return gen_error_literal(g, node); | 2009 | return gen_error_literal(g, node); |
| 2033 | case NodeTypeStringLiteral: | 2010 | case NodeTypeStringLiteral: |
| ... | @@ -2070,6 +2047,10 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { | ... | @@ -2070,6 +2047,10 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 2070 | return gen_container_init_expr(g, node); | 2047 | return gen_container_init_expr(g, node); |
| 2071 | case NodeTypeSwitchExpr: | 2048 | case NodeTypeSwitchExpr: |
| 2072 | return gen_switch_expr(g, node); | 2049 | return gen_switch_expr(g, node); |
| | 2050 | case NodeTypeNumberLiteral: |
| | 2051 | case NodeTypeBoolLiteral: |
| | 2052 | // caught by constant expression eval codegen |
| | 2053 | zig_unreachable(); |
| 2073 | case NodeTypeRoot: | 2054 | case NodeTypeRoot: |
| 2074 | case NodeTypeRootExportDecl: | 2055 | case NodeTypeRootExportDecl: |
| 2075 | case NodeTypeFnProto: | 2056 | case NodeTypeFnProto: |
| ... | @@ -2129,16 +2110,114 @@ static void build_label_blocks(CodeGen *g, AstNode *block_node) { | ... | @@ -2129,16 +2110,114 @@ static void build_label_blocks(CodeGen *g, AstNode *block_node) { |
| 2129 | label_node->data.label.label_entry->basic_block = LLVMAppendBasicBlock( | 2110 | label_node->data.label.label_entry->basic_block = LLVMAppendBasicBlock( |
| 2130 | g->cur_fn->fn_value, buf_ptr(name)); | 2111 | g->cur_fn->fn_value, buf_ptr(name)); |
| 2131 | } | 2112 | } |
| | 2113 | } |
| 2132 | | 2114 | |
| | 2115 | static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) { |
| | 2116 | assert(const_val->ok); |
| | 2117 | |
| | 2118 | if (type_entry->id == TypeTableEntryIdInt) { |
| | 2119 | return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false); |
| | 2120 | } else if (type_entry->id == TypeTableEntryIdFloat) { |
| | 2121 | if (const_val->data.x_bignum.kind == BigNumKindFloat) { |
| | 2122 | return LLVMConstReal(type_entry->type_ref, const_val->data.x_bignum.data.x_float); |
| | 2123 | } else { |
| | 2124 | int64_t x = const_val->data.x_bignum.data.x_uint; |
| | 2125 | if (const_val->data.x_bignum.is_negative) { |
| | 2126 | x = -x; |
| | 2127 | } |
| | 2128 | return LLVMConstReal(type_entry->type_ref, x); |
| | 2129 | } |
| | 2130 | } else if (type_entry->id == TypeTableEntryIdBool) { |
| | 2131 | if (const_val->data.x_bool) { |
| | 2132 | return LLVMConstAllOnes(LLVMInt1Type()); |
| | 2133 | } else { |
| | 2134 | return LLVMConstNull(LLVMInt1Type()); |
| | 2135 | } |
| | 2136 | } else if (type_entry->id == TypeTableEntryIdMaybe) { |
| | 2137 | TypeTableEntry *child_type = type_entry->data.maybe.child_type; |
| | 2138 | LLVMValueRef child_val; |
| | 2139 | LLVMValueRef maybe_val; |
| | 2140 | if (const_val->data.x_maybe) { |
| | 2141 | child_val = gen_const_val(g, child_type, const_val->data.x_maybe); |
| | 2142 | maybe_val = LLVMConstAllOnes(LLVMInt1Type()); |
| | 2143 | } else { |
| | 2144 | child_val = LLVMConstNull(child_type->type_ref); |
| | 2145 | maybe_val = LLVMConstNull(LLVMInt1Type()); |
| | 2146 | } |
| | 2147 | LLVMValueRef fields[] = { |
| | 2148 | child_val, |
| | 2149 | maybe_val, |
| | 2150 | }; |
| | 2151 | return LLVMConstStruct(fields, 2, false); |
| | 2152 | } else if (type_entry->id == TypeTableEntryIdStruct) { |
| | 2153 | zig_panic("TODO"); |
| | 2154 | } else if (type_entry->id == TypeTableEntryIdArray) { |
| | 2155 | zig_panic("TODO"); |
| | 2156 | } else if (type_entry->id == TypeTableEntryIdEnum) { |
| | 2157 | LLVMTypeRef tag_type_ref = type_entry->data.enumeration.tag_type->type_ref; |
| | 2158 | LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, const_val->data.x_enum.tag, false); |
| | 2159 | if (type_entry->data.enumeration.gen_field_count == 0) { |
| | 2160 | return tag_value; |
| | 2161 | } else { |
| | 2162 | zig_panic("TODO"); |
| | 2163 | /* |
| | 2164 | LLVMValueRef fields[] = { |
| | 2165 | tag_value, |
| | 2166 | union_value, |
| | 2167 | }; |
| | 2168 | return LLVMConstStruct(fields, 2, false); |
| | 2169 | */ |
| | 2170 | } |
| | 2171 | } else if (type_entry->id == TypeTableEntryIdFn) { |
| | 2172 | return const_val->data.x_fn->fn_value; |
| | 2173 | } else { |
| | 2174 | zig_unreachable(); |
| | 2175 | } |
| | 2176 | } |
| | 2177 | |
| | 2178 | static void gen_const_globals(CodeGen *g) { |
| | 2179 | for (int i = 0; i < g->global_const_list.length; i += 1) { |
| | 2180 | Expr *expr = g->global_const_list.at(i); |
| | 2181 | ConstExprValue *const_val = &expr->const_val; |
| | 2182 | assert(const_val->ok); |
| | 2183 | TypeTableEntry *type_entry = expr->resolved_type; |
| | 2184 | |
| | 2185 | // TODO delete this if when we make implicit casts insert ast nodes |
| | 2186 | if (type_entry->id == TypeTableEntryIdNumLitFloat || |
| | 2187 | type_entry->id == TypeTableEntryIdNumLitInt) |
| | 2188 | { |
| | 2189 | continue; |
| | 2190 | } |
| | 2191 | |
| | 2192 | if (handle_is_ptr(type_entry)) { |
| | 2193 | LLVMValueRef global_value = LLVMAddGlobal(g->module, type_entry->type_ref, ""); |
| | 2194 | LLVMSetLinkage(global_value, LLVMPrivateLinkage); |
| | 2195 | LLVMValueRef init_val = gen_const_val(g, type_entry, const_val); |
| | 2196 | LLVMSetInitializer(global_value, init_val); |
| | 2197 | LLVMSetGlobalConstant(global_value, true); |
| | 2198 | LLVMSetUnnamedAddr(global_value, true); |
| | 2199 | expr->const_llvm_val = global_value; |
| | 2200 | } else { |
| | 2201 | expr->const_llvm_val = gen_const_val(g, type_entry, const_val); |
| | 2202 | } |
| | 2203 | } |
| 2133 | } | 2204 | } |
| 2134 | | 2205 | |
| 2135 | static void do_code_gen(CodeGen *g) { | 2206 | static void do_code_gen(CodeGen *g) { |
| 2136 | assert(!g->errors.length); | 2207 | assert(!g->errors.length); |
| 2137 | | 2208 | |
| | 2209 | gen_const_globals(g); |
| | 2210 | |
| 2138 | // Generate module level variables | 2211 | // Generate module level variables |
| 2139 | for (int i = 0; i < g->global_vars.length; i += 1) { | 2212 | for (int i = 0; i < g->global_vars.length; i += 1) { |
| 2140 | VariableTableEntry *var = g->global_vars.at(i); | 2213 | VariableTableEntry *var = g->global_vars.at(i); |
| 2141 | | 2214 | |
| | 2215 | if (var->type->id == TypeTableEntryIdNumLitFloat || |
| | 2216 | var->type->id == TypeTableEntryIdNumLitInt) |
| | 2217 | { |
| | 2218 | continue; |
| | 2219 | } |
| | 2220 | |
| 2142 | // TODO if the global is exported, set external linkage | 2221 | // TODO if the global is exported, set external linkage |
| 2143 | LLVMValueRef global_value = LLVMAddGlobal(g->module, var->type->type_ref, ""); | 2222 | LLVMValueRef global_value = LLVMAddGlobal(g->module, var->type->type_ref, ""); |
| 2144 | LLVMSetLinkage(global_value, LLVMPrivateLinkage); | 2223 | LLVMSetLinkage(global_value, LLVMPrivateLinkage); |