authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-27 14:18:20-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-27 14:18:20-07:00
log707154da36ee10c7893cacfafdd3034385d69103
tree6504a69798b28899d131de6def91e11ab7a2c18d
parent261517aa4443404e0ab7b7925937a5c1046f58f5

fix codegen for pointers to void


4 files changed, 206 insertions(+), 127 deletions(-)

src/all_types.hpp+4
...@@ -788,6 +788,8 @@ struct TypeTableEntryStruct {...@@ -788,6 +788,8 @@ struct TypeTableEntryStruct {
788 // set this flag temporarily to detect infinite loops788 // set this flag temporarily to detect infinite loops
789 bool embedded_in_current;789 bool embedded_in_current;
790 bool reported_infinite_err;790 bool reported_infinite_err;
791 // whether we've finished resolving it
792 bool complete;
791};793};
792794
793struct TypeTableEntryMaybe {795struct TypeTableEntryMaybe {
...@@ -812,6 +814,8 @@ struct TypeTableEntryEnum {...@@ -812,6 +814,8 @@ struct TypeTableEntryEnum {
812 // set this flag temporarily to detect infinite loops814 // set this flag temporarily to detect infinite loops
813 bool embedded_in_current;815 bool embedded_in_current;
814 bool reported_infinite_err;816 bool reported_infinite_err;
817 // whether we've finished resolving it
818 bool complete;
815};819};
816820
817struct TypeTableEntryFn {821struct TypeTableEntryFn {
src/analyze.cpp+39-9
...@@ -25,6 +25,7 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *...@@ -25,6 +25,7 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *
25 BlockContext *context, AstNode *node, Buf *err_name);25 BlockContext *context, AstNode *node, Buf *err_name);
26static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,26static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
27 TypeTableEntry *expected_type, AstNode *node);27 TypeTableEntry *expected_type, AstNode *node);
28static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node);
2829
29static AstNode *first_executing_node(AstNode *node) {30static AstNode *first_executing_node(AstNode *node) {
30 switch (node->type) {31 switch (node->type) {
...@@ -152,17 +153,34 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool...@@ -152,17 +153,34 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
152 return *parent_pointer;153 return *parent_pointer;
153 } else {154 } else {
154 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPointer);155 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPointer);
155 entry->type_ref = LLVMPointerType(child_type->type_ref, 0);
156156
157 const char *const_str = is_const ? "const " : "";157 const char *const_str = is_const ? "const " : "";
158 buf_resize(&entry->name, 0);158 buf_resize(&entry->name, 0);
159 buf_appendf(&entry->name, "&%s%s", const_str, buf_ptr(&child_type->name));159 buf_appendf(&entry->name, "&%s%s", const_str, buf_ptr(&child_type->name));
160160
161 entry->size_in_bits = g->pointer_size_bytes * 8;161 bool zero_bits;
162 entry->align_in_bits = g->pointer_size_bytes * 8;162 if (child_type->size_in_bits == 0) {
163 assert(child_type->di_type);163 if (child_type->id == TypeTableEntryIdStruct) {
164 entry->di_type = LLVMZigCreateDebugPointerType(g->dbuilder, child_type->di_type,164 zero_bits = child_type->data.structure.complete;
165 entry->size_in_bits, entry->align_in_bits, buf_ptr(&entry->name));165 } else if (child_type->id == TypeTableEntryIdEnum) {
166 zero_bits = child_type->data.enumeration.complete;
167 } else {
168 zero_bits = true;
169 }
170 } else {
171 zero_bits = false;
172 }
173
174 if (!zero_bits) {
175 entry->type_ref = LLVMPointerType(child_type->type_ref, 0);
176
177 entry->size_in_bits = g->pointer_size_bytes * 8;
178 entry->align_in_bits = g->pointer_size_bytes * 8;
179 assert(child_type->di_type);
180 entry->di_type = LLVMZigCreateDebugPointerType(g->dbuilder, child_type->di_type,
181 entry->size_in_bits, entry->align_in_bits, buf_ptr(&entry->name));
182 }
183
166 entry->data.pointer.child_type = child_type;184 entry->data.pointer.child_type = child_type;
167 entry->data.pointer.is_const = is_const;185 entry->data.pointer.is_const = is_const;
168186
...@@ -511,6 +529,8 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -511,6 +529,8 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
511 // after the gen_param_index += 1 because 0 is the return type529 // after the gen_param_index += 1 because 0 is the return type
512 param_di_types[gen_param_index] = gen_type->di_type;530 param_di_types[gen_param_index] = gen_type->di_type;
513 gen_return_type = g->builtin_types.entry_void;531 gen_return_type = g->builtin_types.entry_void;
532 } else if (return_type->size_in_bits == 0) {
533 gen_return_type = g->builtin_types.entry_void;
514 } else {534 } else {
515 gen_return_type = return_type;535 gen_return_type = return_type;
516 }536 }
...@@ -584,7 +604,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -584,7 +604,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
584 LLVMSetLinkage(fn_table_entry->fn_value, fn_table_entry->internal_linkage ?604 LLVMSetLinkage(fn_table_entry->fn_value, fn_table_entry->internal_linkage ?
585 LLVMInternalLinkage : LLVMExternalLinkage);605 LLVMInternalLinkage : LLVMExternalLinkage);
586606
587 if (gen_return_type->id == TypeTableEntryIdUnreachable) {607 if (return_type->id == TypeTableEntryIdUnreachable) {
588 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNoReturnAttribute);608 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNoReturnAttribute);
589 }609 }
590 LLVMSetFunctionCallConv(fn_table_entry->fn_value, fn_type->data.fn.calling_convention);610 LLVMSetFunctionCallConv(fn_table_entry->fn_value, fn_type->data.fn.calling_convention);
...@@ -707,6 +727,7 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt...@@ -707,6 +727,7 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt
707727
708 // unset temporary flag728 // unset temporary flag
709 enum_type->data.enumeration.embedded_in_current = false;729 enum_type->data.enumeration.embedded_in_current = false;
730 enum_type->data.enumeration.complete = true;
710731
711 if (!enum_type->data.enumeration.is_invalid) {732 if (!enum_type->data.enumeration.is_invalid) {
712 enum_type->data.enumeration.gen_field_count = gen_field_index;733 enum_type->data.enumeration.gen_field_count = gen_field_index;
...@@ -872,6 +893,7 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE...@@ -872,6 +893,7 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
872 struct_type->data.structure.embedded_in_current = false;893 struct_type->data.structure.embedded_in_current = false;
873894
874 struct_type->data.structure.gen_field_count = gen_field_index;895 struct_type->data.structure.gen_field_count = gen_field_index;
896 struct_type->data.structure.complete = true;
875897
876 if (!struct_type->data.structure.is_invalid) {898 if (!struct_type->data.structure.is_invalid) {
877899
...@@ -1186,7 +1208,9 @@ static bool type_has_codegen_value(TypeTableEntryId id) {...@@ -1186,7 +1208,9 @@ static bool type_has_codegen_value(TypeTableEntryId id) {
11861208
1187static void add_global_const_expr(CodeGen *g, Expr *expr) {1209static void add_global_const_expr(CodeGen *g, Expr *expr) {
1188 if (expr->const_val.ok &&1210 if (expr->const_val.ok &&
1189 type_has_codegen_value(expr->type_entry->id) && !expr->has_global_const)1211 type_has_codegen_value(expr->type_entry->id) &&
1212 !expr->has_global_const &&
1213 expr->type_entry->size_in_bits > 0)
1190 {1214 {
1191 g->global_const_list.append(expr);1215 g->global_const_list.append(expr);
1192 expr->has_global_const = true;1216 expr->has_global_const = true;
...@@ -1776,7 +1800,7 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry...@@ -1776,7 +1800,7 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry
1776 add_node_error(g, node, buf_sprintf("void expression expects no arguments"));1800 add_node_error(g, node, buf_sprintf("void expression expects no arguments"));
1777 return g->builtin_types.entry_invalid;1801 return g->builtin_types.entry_invalid;
1778 } else {1802 } else {
1779 return container_type;1803 return resolve_expr_const_val_as_void(g, node);
1780 }1804 }
1781 } else if (container_type->id == TypeTableEntryIdUnreachable) {1805 } else if (container_type->id == TypeTableEntryIdUnreachable) {
1782 if (container_init_expr->entries.length != 0) {1806 if (container_init_expr->entries.length != 0) {
...@@ -1925,6 +1949,12 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i...@@ -1925,6 +1949,12 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i
1925 return return_type;1949 return return_type;
1926}1950}
19271951
1952static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node) {
1953 Expr *expr = get_resolved_expr(node);
1954 expr->const_val.ok = true;
1955 return g->builtin_types.entry_void;
1956}
1957
1928static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type) {1958static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type) {
1929 Expr *expr = get_resolved_expr(node);1959 Expr *expr = get_resolved_expr(node);
1930 expr->const_val.ok = true;1960 expr->const_val.ok = true;
src/codegen.cpp+150-118
...@@ -510,7 +510,6 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -510,7 +510,6 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
510 }510 }
511511
512 TypeTableEntry *src_return_type = fn_type->data.fn.src_return_type;512 TypeTableEntry *src_return_type = fn_type->data.fn.src_return_type;
513 TypeTableEntry *gen_return_type = fn_type->data.fn.gen_return_type;
514513
515 int fn_call_param_count = node->data.fn_call_expr.params.length;514 int fn_call_param_count = node->data.fn_call_expr.params.length;
516 bool first_arg_ret = handle_is_ptr(src_return_type);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,7 +543,7 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
544 LLVMValueRef result = LLVMZigBuildCall(g->builder, fn_val,543 LLVMValueRef result = LLVMZigBuildCall(g->builder, fn_val,
545 gen_param_values, gen_param_index, fn_type->data.fn.calling_convention, "");544 gen_param_values, gen_param_index, fn_type->data.fn.calling_convention, "");
546545
547 if (gen_return_type->id == TypeTableEntryIdUnreachable) {546 if (src_return_type->id == TypeTableEntryIdUnreachable) {
548 return LLVMBuildUnreachable(g->builder);547 return LLVMBuildUnreachable(g->builder);
549 } else if (first_arg_ret) {548 } else if (first_arg_ret) {
550 return node->data.fn_call_expr.tmp_ptr;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,8 +820,6 @@ static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node,
821 VariableTableEntry *var = find_variable(expr_node->block_context,820 VariableTableEntry *var = find_variable(expr_node->block_context,
822 &node->data.symbol_expr.symbol);821 &node->data.symbol_expr.symbol);
823 assert(var);822 assert(var);
824 // semantic checking ensures no variables are constant
825 assert(!var->is_const);
826823
827 *out_type_entry = var->type;824 *out_type_entry = var->type;
828 target_ref = var->value_ref;825 target_ref = var->value_ref;
...@@ -895,8 +892,13 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {...@@ -895,8 +892,13 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
895 case PrefixOpDereference:892 case PrefixOpDereference:
896 {893 {
897 LLVMValueRef expr = gen_expr(g, expr_node);894 LLVMValueRef expr = gen_expr(g, expr_node);
898 add_debug_source_node(g, node);895 TypeTableEntry *type_entry = get_expr_type(expr_node);
899 return LLVMBuildLoad(g->builder, expr, "");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 case PrefixOpMaybe:903 case PrefixOpMaybe:
902 {904 {
...@@ -2182,8 +2184,12 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {...@@ -2182,8 +2184,12 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
2182static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {2184static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
2183 Expr *expr = get_resolved_expr(node);2185 Expr *expr = get_resolved_expr(node);
2184 if (expr->const_val.ok) {2186 if (expr->const_val.ok) {
2185 assert(expr->const_llvm_val);2187 if (expr->type_entry->size_in_bits == 0) {
2186 return expr->const_llvm_val;2188 return nullptr;
2189 } else {
2190 assert(expr->const_llvm_val);
2191 return expr->const_llvm_val;
2192 }
2187 }2193 }
2188 switch (node->type) {2194 switch (node->type) {
2189 case NodeTypeBinOpExpr:2195 case NodeTypeBinOpExpr:
...@@ -2291,119 +2297,144 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -2291,119 +2297,144 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
2291 return LLVMGetUndef(type_entry->type_ref);2297 return LLVMGetUndef(type_entry->type_ref);
2292 }2298 }
22932299
2294 if (type_entry->id == TypeTableEntryIdInt) {2300 switch (type_entry->id) {
2295 return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false);2301 case TypeTableEntryIdInt:
2296 } else if (type_entry->id == TypeTableEntryIdPureError) {2302 return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false);
2297 assert(const_val->data.x_err.err);2303 case TypeTableEntryIdPureError:
2298 return LLVMConstInt(g->builtin_types.entry_pure_error->type_ref, const_val->data.x_err.err->value, false);2304 assert(const_val->data.x_err.err);
2299 } else if (type_entry->id == TypeTableEntryIdFloat) {2305 return LLVMConstInt(g->builtin_types.entry_pure_error->type_ref,
2300 if (const_val->data.x_bignum.kind == BigNumKindFloat) {2306 const_val->data.x_err.err->value, false);
2301 return LLVMConstReal(type_entry->type_ref, const_val->data.x_bignum.data.x_float);2307 case TypeTableEntryIdFloat:
2302 } else {2308 if (const_val->data.x_bignum.kind == BigNumKindFloat) {
2303 int64_t x = const_val->data.x_bignum.data.x_uint;2309 return LLVMConstReal(type_entry->type_ref, const_val->data.x_bignum.data.x_float);
2304 if (const_val->data.x_bignum.is_negative) {2310 } else {
2305 x = -x;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);2317 case TypeTableEntryIdBool:
2308 }2318 if (const_val->data.x_bool) {
2309 } else if (type_entry->id == TypeTableEntryIdBool) {2319 return LLVMConstAllOnes(LLVMInt1Type());
2310 if (const_val->data.x_bool) {2320 } else {
2311 return LLVMConstAllOnes(LLVMInt1Type());2321 return LLVMConstNull(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]);
2368 }2322 }
2369 target_val = LLVMConstArray(child_type->type_ref, values, len);2323 case TypeTableEntryIdMaybe:
2370 } else {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 zig_unreachable();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);
23782437
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}
24092440
...@@ -2438,7 +2469,8 @@ static void do_code_gen(CodeGen *g) {...@@ -2438,7 +2469,8 @@ static void do_code_gen(CodeGen *g) {
2438 VariableTableEntry *var = g->global_vars.at(i);2469 VariableTableEntry *var = g->global_vars.at(i);
24392470
2440 if (var->type->id == TypeTableEntryIdNumLitFloat ||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 continue;2475 continue;
2444 }2476 }
test/run_tests.cpp+13
...@@ -1316,6 +1316,19 @@ pub fn main(args: [][]u8) -> %void {...@@ -1316,6 +1316,19 @@ pub fn main(args: [][]u8) -> %void {
1316 %%stdout.printf("BAD\n");1316 %%stdout.printf("BAD\n");
1317 }1317 }
1318 %%stdout.printf("OK\n");1318 %%stdout.printf("OK\n");
1319}
1320 )SOURCE", "OK\n");
1321
1322 add_simple_case("pointer to void return type", R"SOURCE(
1323import "std.zig";
1324const x = void{};
1325fn f() -> &void {
1326 %%stdout.printf("OK\n");
1327 return &x;
1328}
1329pub fn main(args: [][]u8) -> %void {
1330 const a = f();
1331 return *a;
1319}1332}
1320 )SOURCE", "OK\n");1333 )SOURCE", "OK\n");
1321}1334}