aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2016-12-26 02:36:04 -0500
committerAndrew Kelley <superjoe30@gmail.com>2016-12-26 02:36:04 -0500
commit4664f793dc3fed2254863a5b6efc302c095890cb (patch)
tree1c52e0597e181d09ebf199797894945de1eb25f4 /src
parent1b5d1877aea6c0db7fbe6f56ffe4412ce2cffff7 (diff)
downloadzig-4664f793dc3fed2254863a5b6efc302c095890cb.tar.gz
zig-4664f793dc3fed2254863a5b6efc302c095890cb.zip
IR: pass enumToInt test
Diffstat (limited to 'src')
-rw-r--r--src/all_types.hpp9
-rw-r--r--src/codegen.cpp26
-rw-r--r--src/ir.cpp71
-rw-r--r--src/ir_print.cpp11
4 files changed, 101 insertions, 16 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 510905a2a3..6f4947d436 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -429,14 +429,12 @@ enum CastOp {
CastOpNoop, // fn call expr is a cast, but does nothing
CastOpPtrToInt,
CastOpIntToPtr,
- CastOpWidenOrShorten,
CastOpErrToInt,
CastOpIntToFloat,
CastOpFloatToInt,
CastOpBoolToInt,
CastOpResizeSlice,
CastOpIntToEnum,
- CastOpEnumToInt,
CastOpBytesToSlice,
};
@@ -1454,6 +1452,7 @@ enum IrInstructionId {
IrInstructionIdTestComptime,
IrInstructionIdInitEnum,
IrInstructionIdPointerReinterpret,
+ IrInstructionIdWidenOrShorten,
};
struct IrInstruction {
@@ -2096,6 +2095,12 @@ struct IrInstructionPointerReinterpret {
IrInstruction *ptr;
};
+struct IrInstructionWidenOrShorten {
+ IrInstruction base;
+
+ IrInstruction *target;
+};
+
enum LValPurpose {
LValPurposeNone,
LValPurposeAssign,
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 123caea75c..39cd6c8fd9 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -973,9 +973,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, "");
case CastOpIntToPtr:
return LLVMBuildIntToPtr(g->builder, expr_val, wanted_type->type_ref, "");
- case CastOpWidenOrShorten:
- return gen_widen_or_shorten(g, ir_want_debug_safety(g, &cast_instruction->base),
- actual_type, wanted_type, expr_val);
case CastOpResizeSlice:
{
assert(cast_instruction->tmp_ptr);
@@ -1086,9 +1083,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
case CastOpIntToEnum:
return gen_widen_or_shorten(g, ir_want_debug_safety(g, &cast_instruction->base),
actual_type, wanted_type->data.enumeration.tag_type, expr_val);
- case CastOpEnumToInt:
- return gen_widen_or_shorten(g, ir_want_debug_safety(g, &cast_instruction->base),
- actual_type->data.enumeration.tag_type, wanted_type, expr_val);
}
zig_unreachable();
}
@@ -1101,6 +1095,24 @@ static LLVMValueRef ir_render_pointer_reinterpret(CodeGen *g, IrExecutable *exec
return LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, "");
}
+static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executable,
+ IrInstructionWidenOrShorten *instruction)
+{
+ TypeTableEntry *actual_type = instruction->target->value.type;
+ // TODO instead of this logic, use the Noop instruction to change the type from
+ // enum_tag to the underlying int type
+ TypeTableEntry *int_type;
+ if (actual_type->id == TypeTableEntryIdEnum) {
+ TypeTableEntry *tag_type = actual_type->data.enumeration.tag_type;
+ assert(tag_type->id == TypeTableEntryIdEnumTag);
+ int_type = tag_type->data.enum_tag.int_type;
+ } else {
+ int_type = actual_type;
+ }
+ LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
+ return gen_widen_or_shorten(g, ir_want_debug_safety(g, &instruction->base), int_type,
+ instruction->base.value.type, target_val);
+}
static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutable *executable,
IrInstructionUnreachable *unreachable_instruction)
@@ -2309,6 +2321,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
case IrInstructionIdPointerReinterpret:
return ir_render_pointer_reinterpret(g, executable, (IrInstructionPointerReinterpret *)instruction);
+ case IrInstructionIdWidenOrShorten:
+ return ir_render_widen_or_shorten(g, executable, (IrInstructionWidenOrShorten *)instruction);
case IrInstructionIdSwitchVar:
zig_panic("TODO render switch var instruction to LLVM");
case IrInstructionIdContainerInitList:
diff --git a/src/ir.cpp b/src/ir.cpp
index 0da0e1f4ce..fe603dc2d9 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -455,6 +455,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPointerReinterpr
return IrInstructionIdPointerReinterpret;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionWidenOrShorten *) {
+ return IrInstructionIdWidenOrShorten;
+}
+
template<typename T>
static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
T *special_instruction = allocate<T>(1);
@@ -1883,6 +1887,18 @@ static IrInstruction *ir_build_pointer_reinterpret(IrBuilder *irb, Scope *scope,
return &instruction->base;
}
+static IrInstruction *ir_build_widen_or_shorten(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *target)
+{
+ IrInstructionWidenOrShorten *instruction = ir_build_instruction<IrInstructionWidenOrShorten>(
+ irb, scope, source_node);
+ instruction->target = target;
+
+ ir_ref_instruction(target);
+
+ return &instruction->base;
+}
+
static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
results[ReturnKindUnconditional] = 0;
results[ReturnKindError] = 0;
@@ -4638,7 +4654,6 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
case CastOpNoCast:
zig_unreachable();
case CastOpNoop:
- case CastOpWidenOrShorten:
*const_val = *other_val;
const_val->type = new_type;
break;
@@ -4684,10 +4699,6 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
const_val->special = ConstValSpecialStatic;
break;
}
- case CastOpEnumToInt:
- bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_enum.tag);
- const_val->special = ConstValSpecialStatic;
- break;
}
}
static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
@@ -5181,6 +5192,50 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
return result;
}
+static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *target, TypeTableEntry *wanted_type)
+{
+ assert(wanted_type->id == TypeTableEntryIdInt);
+
+ if (instr_is_comptime(target)) {
+ ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
+ if (!val)
+ return ira->codegen->invalid_instruction;
+ IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, wanted_type, val->depends_on_compile_var);
+ init_const_unsigned_negative(&result->value, wanted_type, val->data.x_enum.tag, false);
+ return result;
+ }
+
+ IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, target);
+ result->value.type = wanted_type;
+ return result;
+}
+
+static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *target, TypeTableEntry *wanted_type)
+{
+ assert(wanted_type->id == TypeTableEntryIdInt || wanted_type->id == TypeTableEntryIdFloat);
+
+ if (instr_is_comptime(target)) {
+ ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
+ if (!val)
+ return ira->codegen->invalid_instruction;
+ IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, wanted_type, val->depends_on_compile_var);
+ result->value = *val;
+ result->value.type = wanted_type;
+ return result;
+ }
+
+ IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, target);
+ result->value.type = wanted_type;
+ return result;
+}
+
+
static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
TypeTableEntry *wanted_type, IrInstruction *value)
{
@@ -5233,7 +5288,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
(wanted_type_canon->id == TypeTableEntryIdFloat &&
actual_type_canon->id == TypeTableEntryIdFloat))
{
- return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpWidenOrShorten, false);
+ return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type);
}
// explicit cast from int to float
@@ -5411,7 +5466,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
actual_type->id == TypeTableEntryIdEnum &&
actual_type->data.enumeration.gen_field_count == 0)
{
- return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpEnumToInt, false);
+ return ir_analyze_enum_to_int(ira, source_instr, value, wanted_type);
}
// explicit cast from undefined to anything
@@ -9882,6 +9937,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
switch (instruction->id) {
case IrInstructionIdInvalid:
case IrInstructionIdPointerReinterpret:
+ case IrInstructionIdWidenOrShorten:
case IrInstructionIdStructInit:
case IrInstructionIdStructFieldPtr:
case IrInstructionIdEnumFieldPtr:
@@ -10188,6 +10244,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdTestComptime:
case IrInstructionIdInitEnum:
case IrInstructionIdPointerReinterpret:
+ case IrInstructionIdWidenOrShorten:
return false;
case IrInstructionIdAsm:
{
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index be1089f895..f0dda04c6d 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -923,11 +923,17 @@ static void ir_print_init_enum(IrPrint *irp, IrInstructionInitEnum *instruction)
}
static void ir_print_pointer_reinterpret(IrPrint *irp, IrInstructionPointerReinterpret *instruction) {
- fprintf(irp->f, "(%s)(", buf_ptr(&instruction->base.value.type->name));
+ fprintf(irp->f, "@pointerReinterpret(");
ir_print_other_instruction(irp, instruction->ptr);
fprintf(irp->f, ")");
}
+static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) {
+ fprintf(irp->f, "@widenOrShorten(");
+ ir_print_other_instruction(irp, instruction->target);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
ir_print_prefix(irp, instruction);
switch (instruction->id) {
@@ -1170,6 +1176,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdPointerReinterpret:
ir_print_pointer_reinterpret(irp, (IrInstructionPointerReinterpret *)instruction);
break;
+ case IrInstructionIdWidenOrShorten:
+ ir_print_widen_or_shorten(irp, (IrInstructionWidenOrShorten *)instruction);
+ break;
}
fprintf(irp->f, "\n");
}