| ... | ... | @@ -510,7 +510,6 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) { |
| 510 | 510 | } |
| 511 | 511 | |
| 512 | 512 | TypeTableEntry *src_return_type = fn_type->data.fn.src_return_type; |
| 513 | | TypeTableEntry *gen_return_type = fn_type->data.fn.gen_return_type; |
| 514 | 513 | |
| 515 | 514 | int fn_call_param_count = node->data.fn_call_expr.params.length; |
| 516 | 515 | bool first_arg_ret = handle_is_ptr(src_return_type); |
| ... | ... | @@ -544,7 +543,7 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) { |
| 544 | 543 | LLVMValueRef result = LLVMZigBuildCall(g->builder, fn_val, |
| 545 | 544 | gen_param_values, gen_param_index, fn_type->data.fn.calling_convention, ""); |
| 546 | 545 | |
| 547 | | if (gen_return_type->id == TypeTableEntryIdUnreachable) { |
| 546 | if (src_return_type->id == TypeTableEntryIdUnreachable) { |
| 548 | 547 | return LLVMBuildUnreachable(g->builder); |
| 549 | 548 | } else if (first_arg_ret) { |
| 550 | 549 | return node->data.fn_call_expr.tmp_ptr; |
| ... | ... | @@ -821,8 +820,6 @@ static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node, |
| 821 | 820 | VariableTableEntry *var = find_variable(expr_node->block_context, |
| 822 | 821 | &node->data.symbol_expr.symbol); |
| 823 | 822 | assert(var); |
| 824 | | // semantic checking ensures no variables are constant |
| 825 | | assert(!var->is_const); |
| 826 | 823 | |
| 827 | 824 | *out_type_entry = var->type; |
| 828 | 825 | target_ref = var->value_ref; |
| ... | ... | @@ -895,8 +892,13 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) { |
| 895 | 892 | case PrefixOpDereference: |
| 896 | 893 | { |
| 897 | 894 | LLVMValueRef expr = gen_expr(g, expr_node); |
| 898 | | add_debug_source_node(g, node); |
| 899 | | return LLVMBuildLoad(g->builder, expr, ""); |
| 895 | TypeTableEntry *type_entry = get_expr_type(expr_node); |
| 896 | if (type_entry->size_in_bits == 0) { |
| 897 | return nullptr; |
| 898 | } else { |
| 899 | add_debug_source_node(g, node); |
| 900 | return LLVMBuildLoad(g->builder, expr, ""); |
| 901 | } |
| 900 | 902 | } |
| 901 | 903 | case PrefixOpMaybe: |
| 902 | 904 | { |
| ... | ... | @@ -2182,8 +2184,12 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) { |
| 2182 | 2184 | static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { |
| 2183 | 2185 | Expr *expr = get_resolved_expr(node); |
| 2184 | 2186 | if (expr->const_val.ok) { |
| 2185 | | assert(expr->const_llvm_val); |
| 2186 | | return expr->const_llvm_val; |
| 2187 | if (expr->type_entry->size_in_bits == 0) { |
| 2188 | return nullptr; |
| 2189 | } else { |
| 2190 | assert(expr->const_llvm_val); |
| 2191 | return expr->const_llvm_val; |
| 2192 | } |
| 2187 | 2193 | } |
| 2188 | 2194 | switch (node->type) { |
| 2189 | 2195 | case NodeTypeBinOpExpr: |
| ... | ... | @@ -2291,119 +2297,144 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE |
| 2291 | 2297 | return LLVMGetUndef(type_entry->type_ref); |
| 2292 | 2298 | } |
| 2293 | 2299 | |
| 2294 | | if (type_entry->id == TypeTableEntryIdInt) { |
| 2295 | | return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false); |
| 2296 | | } else if (type_entry->id == TypeTableEntryIdPureError) { |
| 2297 | | assert(const_val->data.x_err.err); |
| 2298 | | return LLVMConstInt(g->builtin_types.entry_pure_error->type_ref, const_val->data.x_err.err->value, false); |
| 2299 | | } else if (type_entry->id == TypeTableEntryIdFloat) { |
| 2300 | | if (const_val->data.x_bignum.kind == BigNumKindFloat) { |
| 2301 | | return LLVMConstReal(type_entry->type_ref, const_val->data.x_bignum.data.x_float); |
| 2302 | | } else { |
| 2303 | | int64_t x = const_val->data.x_bignum.data.x_uint; |
| 2304 | | if (const_val->data.x_bignum.is_negative) { |
| 2305 | | x = -x; |
| 2300 | switch (type_entry->id) { |
| 2301 | case TypeTableEntryIdInt: |
| 2302 | return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false); |
| 2303 | case TypeTableEntryIdPureError: |
| 2304 | assert(const_val->data.x_err.err); |
| 2305 | return LLVMConstInt(g->builtin_types.entry_pure_error->type_ref, |
| 2306 | const_val->data.x_err.err->value, false); |
| 2307 | case TypeTableEntryIdFloat: |
| 2308 | if (const_val->data.x_bignum.kind == BigNumKindFloat) { |
| 2309 | return LLVMConstReal(type_entry->type_ref, const_val->data.x_bignum.data.x_float); |
| 2310 | } else { |
| 2311 | int64_t x = const_val->data.x_bignum.data.x_uint; |
| 2312 | if (const_val->data.x_bignum.is_negative) { |
| 2313 | x = -x; |
| 2314 | } |
| 2315 | return LLVMConstReal(type_entry->type_ref, x); |
| 2306 | 2316 | } |
| 2307 | | return LLVMConstReal(type_entry->type_ref, x); |
| 2308 | | } |
| 2309 | | } else if (type_entry->id == TypeTableEntryIdBool) { |
| 2310 | | if (const_val->data.x_bool) { |
| 2311 | | return LLVMConstAllOnes(LLVMInt1Type()); |
| 2312 | | } else { |
| 2313 | | return LLVMConstNull(LLVMInt1Type()); |
| 2314 | | } |
| 2315 | | } else if (type_entry->id == TypeTableEntryIdMaybe) { |
| 2316 | | TypeTableEntry *child_type = type_entry->data.maybe.child_type; |
| 2317 | | LLVMValueRef child_val; |
| 2318 | | LLVMValueRef maybe_val; |
| 2319 | | if (const_val->data.x_maybe) { |
| 2320 | | child_val = gen_const_val(g, child_type, const_val->data.x_maybe); |
| 2321 | | maybe_val = LLVMConstAllOnes(LLVMInt1Type()); |
| 2322 | | } else { |
| 2323 | | child_val = LLVMConstNull(child_type->type_ref); |
| 2324 | | maybe_val = LLVMConstNull(LLVMInt1Type()); |
| 2325 | | } |
| 2326 | | LLVMValueRef fields[] = { |
| 2327 | | child_val, |
| 2328 | | maybe_val, |
| 2329 | | }; |
| 2330 | | return LLVMConstStruct(fields, 2, false); |
| 2331 | | } else if (type_entry->id == TypeTableEntryIdStruct) { |
| 2332 | | LLVMValueRef *fields = allocate<LLVMValueRef>(type_entry->data.structure.gen_field_count); |
| 2333 | | for (int i = 0; i < type_entry->data.structure.src_field_count; i += 1) { |
| 2334 | | TypeStructField *type_struct_field = &type_entry->data.structure.fields[i]; |
| 2335 | | fields[type_struct_field->gen_index] = gen_const_val(g, type_struct_field->type_entry, |
| 2336 | | const_val->data.x_struct.fields[i]); |
| 2337 | | } |
| 2338 | | return LLVMConstNamedStruct(type_entry->type_ref, fields, type_entry->data.structure.gen_field_count); |
| 2339 | | } else if (type_entry->id == TypeTableEntryIdArray) { |
| 2340 | | TypeTableEntry *child_type = type_entry->data.array.child_type; |
| 2341 | | uint64_t len = type_entry->data.array.len; |
| 2342 | | LLVMValueRef *values = allocate<LLVMValueRef>(len); |
| 2343 | | for (int i = 0; i < len; i += 1) { |
| 2344 | | ConstExprValue *field_value = const_val->data.x_array.fields[i]; |
| 2345 | | values[i] = gen_const_val(g, child_type, field_value); |
| 2346 | | } |
| 2347 | | return LLVMConstArray(child_type->type_ref, values, len); |
| 2348 | | } else if (type_entry->id == TypeTableEntryIdEnum) { |
| 2349 | | LLVMTypeRef tag_type_ref = type_entry->data.enumeration.tag_type->type_ref; |
| 2350 | | LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, const_val->data.x_enum.tag, false); |
| 2351 | | if (type_entry->data.enumeration.gen_field_count == 0) { |
| 2352 | | return tag_value; |
| 2353 | | } else { |
| 2354 | | zig_panic("TODO"); |
| 2355 | | } |
| 2356 | | } else if (type_entry->id == TypeTableEntryIdFn) { |
| 2357 | | return const_val->data.x_fn->fn_value; |
| 2358 | | } else if (type_entry->id == TypeTableEntryIdPointer) { |
| 2359 | | TypeTableEntry *child_type = type_entry->data.pointer.child_type; |
| 2360 | | int len = const_val->data.x_ptr.len; |
| 2361 | | LLVMValueRef target_val; |
| 2362 | | if (len == 1) { |
| 2363 | | target_val = gen_const_val(g, child_type, const_val->data.x_ptr.ptr[0]); |
| 2364 | | } else if (len > 1) { |
| 2365 | | LLVMValueRef *values = allocate<LLVMValueRef>(len); |
| 2366 | | for (int i = 0; i < len; i += 1) { |
| 2367 | | values[i] = gen_const_val(g, child_type, const_val->data.x_ptr.ptr[i]); |
| 2317 | case TypeTableEntryIdBool: |
| 2318 | if (const_val->data.x_bool) { |
| 2319 | return LLVMConstAllOnes(LLVMInt1Type()); |
| 2320 | } else { |
| 2321 | return LLVMConstNull(LLVMInt1Type()); |
| 2368 | 2322 | } |
| 2369 | | target_val = LLVMConstArray(child_type->type_ref, values, len); |
| 2370 | | } else { |
| 2323 | case TypeTableEntryIdMaybe: |
| 2324 | { |
| 2325 | TypeTableEntry *child_type = type_entry->data.maybe.child_type; |
| 2326 | LLVMValueRef child_val; |
| 2327 | LLVMValueRef maybe_val; |
| 2328 | if (const_val->data.x_maybe) { |
| 2329 | child_val = gen_const_val(g, child_type, const_val->data.x_maybe); |
| 2330 | maybe_val = LLVMConstAllOnes(LLVMInt1Type()); |
| 2331 | } else { |
| 2332 | child_val = LLVMConstNull(child_type->type_ref); |
| 2333 | maybe_val = LLVMConstNull(LLVMInt1Type()); |
| 2334 | } |
| 2335 | LLVMValueRef fields[] = { |
| 2336 | child_val, |
| 2337 | maybe_val, |
| 2338 | }; |
| 2339 | return LLVMConstStruct(fields, 2, false); |
| 2340 | } |
| 2341 | case TypeTableEntryIdStruct: |
| 2342 | { |
| 2343 | LLVMValueRef *fields = allocate<LLVMValueRef>(type_entry->data.structure.gen_field_count); |
| 2344 | for (int i = 0; i < type_entry->data.structure.src_field_count; i += 1) { |
| 2345 | TypeStructField *type_struct_field = &type_entry->data.structure.fields[i]; |
| 2346 | if (type_struct_field->gen_index == -1) { |
| 2347 | continue; |
| 2348 | } |
| 2349 | fields[type_struct_field->gen_index] = gen_const_val(g, type_struct_field->type_entry, |
| 2350 | const_val->data.x_struct.fields[i]); |
| 2351 | } |
| 2352 | return LLVMConstNamedStruct(type_entry->type_ref, fields, |
| 2353 | type_entry->data.structure.gen_field_count); |
| 2354 | } |
| 2355 | case TypeTableEntryIdArray: |
| 2356 | { |
| 2357 | TypeTableEntry *child_type = type_entry->data.array.child_type; |
| 2358 | uint64_t len = type_entry->data.array.len; |
| 2359 | LLVMValueRef *values = allocate<LLVMValueRef>(len); |
| 2360 | for (int i = 0; i < len; i += 1) { |
| 2361 | ConstExprValue *field_value = const_val->data.x_array.fields[i]; |
| 2362 | values[i] = gen_const_val(g, child_type, field_value); |
| 2363 | } |
| 2364 | return LLVMConstArray(child_type->type_ref, values, len); |
| 2365 | } |
| 2366 | case TypeTableEntryIdEnum: |
| 2367 | { |
| 2368 | LLVMTypeRef tag_type_ref = type_entry->data.enumeration.tag_type->type_ref; |
| 2369 | LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, const_val->data.x_enum.tag, false); |
| 2370 | if (type_entry->data.enumeration.gen_field_count == 0) { |
| 2371 | return tag_value; |
| 2372 | } else { |
| 2373 | zig_panic("TODO"); |
| 2374 | } |
| 2375 | } |
| 2376 | case TypeTableEntryIdFn: |
| 2377 | return const_val->data.x_fn->fn_value; |
| 2378 | case TypeTableEntryIdPointer: |
| 2379 | { |
| 2380 | TypeTableEntry *child_type = type_entry->data.pointer.child_type; |
| 2381 | int len = const_val->data.x_ptr.len; |
| 2382 | LLVMValueRef target_val; |
| 2383 | if (len == 1) { |
| 2384 | target_val = gen_const_val(g, child_type, const_val->data.x_ptr.ptr[0]); |
| 2385 | } else if (len > 1) { |
| 2386 | LLVMValueRef *values = allocate<LLVMValueRef>(len); |
| 2387 | for (int i = 0; i < len; i += 1) { |
| 2388 | values[i] = gen_const_val(g, child_type, const_val->data.x_ptr.ptr[i]); |
| 2389 | } |
| 2390 | target_val = LLVMConstArray(child_type->type_ref, values, len); |
| 2391 | } else { |
| 2392 | zig_unreachable(); |
| 2393 | } |
| 2394 | LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(target_val), ""); |
| 2395 | LLVMSetInitializer(global_value, target_val); |
| 2396 | LLVMSetLinkage(global_value, LLVMPrivateLinkage); |
| 2397 | LLVMSetGlobalConstant(global_value, type_entry->data.pointer.is_const); |
| 2398 | LLVMSetUnnamedAddr(global_value, true); |
| 2399 | |
| 2400 | if (len > 1) { |
| 2401 | return LLVMConstBitCast(global_value, type_entry->type_ref); |
| 2402 | } else { |
| 2403 | return global_value; |
| 2404 | } |
| 2405 | } |
| 2406 | case TypeTableEntryIdErrorUnion: |
| 2407 | { |
| 2408 | TypeTableEntry *child_type = type_entry->data.error.child_type; |
| 2409 | if (child_type->size_in_bits == 0) { |
| 2410 | uint64_t value = const_val->data.x_err.err ? const_val->data.x_err.err->value : 0; |
| 2411 | return LLVMConstInt(g->err_tag_type->type_ref, value, false); |
| 2412 | } else { |
| 2413 | LLVMValueRef err_tag_value; |
| 2414 | LLVMValueRef err_payload_value; |
| 2415 | if (const_val->data.x_err.err) { |
| 2416 | err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err.err->value, false); |
| 2417 | err_payload_value = LLVMConstNull(child_type->type_ref); |
| 2418 | } else { |
| 2419 | err_tag_value = LLVMConstNull(g->err_tag_type->type_ref); |
| 2420 | err_payload_value = gen_const_val(g, child_type, const_val->data.x_err.payload); |
| 2421 | } |
| 2422 | LLVMValueRef fields[] = { |
| 2423 | err_tag_value, |
| 2424 | err_payload_value, |
| 2425 | }; |
| 2426 | return LLVMConstStruct(fields, 2, false); |
| 2427 | } |
| 2428 | } |
| 2429 | case TypeTableEntryIdInvalid: |
| 2430 | case TypeTableEntryIdMetaType: |
| 2431 | case TypeTableEntryIdUnreachable: |
| 2432 | case TypeTableEntryIdNumLitFloat: |
| 2433 | case TypeTableEntryIdNumLitInt: |
| 2434 | case TypeTableEntryIdUndefLit: |
| 2435 | case TypeTableEntryIdVoid: |
| 2371 | 2436 | zig_unreachable(); |
| 2372 | | } |
| 2373 | | LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(target_val), ""); |
| 2374 | | LLVMSetInitializer(global_value, target_val); |
| 2375 | | LLVMSetLinkage(global_value, LLVMPrivateLinkage); |
| 2376 | | LLVMSetGlobalConstant(global_value, type_entry->data.pointer.is_const); |
| 2377 | | LLVMSetUnnamedAddr(global_value, true); |
| 2378 | 2437 | |
| 2379 | | if (len > 1) { |
| 2380 | | return LLVMConstBitCast(global_value, type_entry->type_ref); |
| 2381 | | } else { |
| 2382 | | return global_value; |
| 2383 | | } |
| 2384 | | } else if (type_entry->id == TypeTableEntryIdErrorUnion) { |
| 2385 | | TypeTableEntry *child_type = type_entry->data.error.child_type; |
| 2386 | | if (child_type->size_in_bits == 0) { |
| 2387 | | uint64_t value = const_val->data.x_err.err ? const_val->data.x_err.err->value : 0; |
| 2388 | | return LLVMConstInt(g->err_tag_type->type_ref, value, false); |
| 2389 | | } else { |
| 2390 | | LLVMValueRef err_tag_value; |
| 2391 | | LLVMValueRef err_payload_value; |
| 2392 | | if (const_val->data.x_err.err) { |
| 2393 | | err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err.err->value, false); |
| 2394 | | err_payload_value = LLVMConstNull(child_type->type_ref); |
| 2395 | | } else { |
| 2396 | | err_tag_value = LLVMConstNull(g->err_tag_type->type_ref); |
| 2397 | | err_payload_value = gen_const_val(g, child_type, const_val->data.x_err.payload); |
| 2398 | | } |
| 2399 | | LLVMValueRef fields[] = { |
| 2400 | | err_tag_value, |
| 2401 | | err_payload_value, |
| 2402 | | }; |
| 2403 | | return LLVMConstStruct(fields, 2, false); |
| 2404 | | } |
| 2405 | | } else { |
| 2406 | | zig_unreachable(); |
| 2407 | 2438 | } |
| 2408 | 2439 | } |
| 2409 | 2440 | |
| ... | ... | @@ -2438,7 +2469,8 @@ static void do_code_gen(CodeGen *g) { |
| 2438 | 2469 | VariableTableEntry *var = g->global_vars.at(i); |
| 2439 | 2470 | |
| 2440 | 2471 | if (var->type->id == TypeTableEntryIdNumLitFloat || |
| 2441 | | var->type->id == TypeTableEntryIdNumLitInt) |
| 2472 | var->type->id == TypeTableEntryIdNumLitInt || |
| 2473 | var->type->size_in_bits == 0) |
| 2442 | 2474 | { |
| 2443 | 2475 | continue; |
| 2444 | 2476 | } |