aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2016-04-25 21:51:04 -0700
committerAndrew Kelley <superjoe30@gmail.com>2016-04-25 21:51:04 -0700
commitd0378057d1276d0bbbf0f0cac05e252bcc131692 (patch)
tree945fed7b6d4914c629cd201c41bd52ca57765401 /src/codegen.cpp
parentd1b65c6f46ab0891db3c80db2eedbb434168aabe (diff)
downloadzig-d0378057d1276d0bbbf0f0cac05e252bcc131692.tar.gz
zig-d0378057d1276d0bbbf0f0cac05e252bcc131692.zip
support switching on error union type
closes #23
Diffstat (limited to 'src/codegen.cpp')
-rw-r--r--src/codegen.cpp51
1 files changed, 40 insertions, 11 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index e15553e2dc..aa3b4d1529 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -2627,12 +2627,6 @@ static LLVMValueRef gen_symbol(CodeGen *g, AstNode *node) {
}
zig_unreachable();
-
- /* TODO delete
- FnTableEntry *fn_entry = node->data.symbol_expr.fn_entry;
- assert(fn_entry);
- return fn_entry->fn_value;
- */
}
static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
@@ -2653,6 +2647,10 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
add_debug_source_node(g, node);
LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, target_value_handle, 0, "");
target_value = LLVMBuildLoad(g->builder, tag_field_ptr, "");
+ } else if (target_type->id == TypeTableEntryIdErrorUnion) {
+ add_debug_source_node(g, node);
+ LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, target_value_handle, 0, "");
+ target_value = LLVMBuildLoad(g->builder, tag_field_ptr, "");
} else {
zig_unreachable();
}
@@ -2696,12 +2694,23 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
assert(item_node->type != NodeTypeSwitchRange);
LLVMValueRef val;
- if (target_type->id == TypeTableEntryIdEnum) {
+ if (target_type->id == TypeTableEntryIdEnum ||
+ target_type->id == TypeTableEntryIdErrorUnion)
+ {
assert(item_node->type == NodeTypeSymbol);
- TypeEnumField *enum_field = item_node->data.symbol_expr.enum_field;
- assert(enum_field);
- val = LLVMConstInt(target_type->data.enumeration.tag_type->type_ref,
- enum_field->value, false);
+ TypeEnumField *enum_field = nullptr;
+ uint32_t err_value = 0;
+ if (target_type->id == TypeTableEntryIdEnum) {
+ enum_field = item_node->data.symbol_expr.enum_field;
+ assert(enum_field);
+ val = LLVMConstInt(target_type->data.enumeration.tag_type->type_ref,
+ enum_field->value, false);
+ } else if (target_type->id == TypeTableEntryIdErrorUnion) {
+ err_value = item_node->data.symbol_expr.err_value;
+ val = LLVMConstInt(g->err_tag_type->type_ref, err_value, false);
+ } else {
+ zig_unreachable();
+ }
if (prong_var && type_has_bits(prong_var->type)) {
LLVMBasicBlockRef item_block;
@@ -2721,6 +2730,7 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
gen_assign_raw(g, var_node, BinOpTypeAssign,
prong_var->value_ref, target_value, prong_var->type, target_type);
} else if (target_type->id == TypeTableEntryIdEnum) {
+ assert(enum_field);
assert(type_has_bits(enum_field->type_entry));
LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, target_value_handle,
1, "");
@@ -2731,6 +2741,25 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
gen_assign_raw(g, var_node, BinOpTypeAssign,
prong_var->value_ref, handle_val, prong_var->type, enum_field->type_entry);
+ } else if (target_type->id == TypeTableEntryIdErrorUnion) {
+ if (err_value == 0) {
+ // variable is the payload
+ LLVMValueRef err_payload_ptr = LLVMBuildStructGEP(g->builder,
+ target_value_handle, 1, "");
+ LLVMValueRef handle_val = get_handle_value(g, var_node,
+ err_payload_ptr, prong_var->type);
+ gen_assign_raw(g, var_node, BinOpTypeAssign,
+ prong_var->value_ref, handle_val, prong_var->type, prong_var->type);
+ } else {
+ // variable is the pure error value
+ LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder,
+ target_value_handle, 0, "");
+ LLVMValueRef handle_val = LLVMBuildLoad(g->builder, err_tag_ptr, "");
+ gen_assign_raw(g, var_node, BinOpTypeAssign,
+ prong_var->value_ref, handle_val, prong_var->type, g->err_tag_type);
+ }
+ } else {
+ zig_unreachable();
}
if (make_item_blocks) {
LLVMBuildBr(g->builder, prong_block);