Commit 2a256d5ea0

LemonBoy <thatlemon@gmail.com>
2020-10-17 10:06:14
stage1: Fix type-checking of unary neg for vector types
Validate the vector element type as done for the scalar case. Fixes #6708
1 parent e51bc19
src/stage1/all_types.hpp
@@ -2653,7 +2653,6 @@ enum IrInstGenId {
     IrInstGenIdPhi,
     IrInstGenIdBinaryNot,
     IrInstGenIdNegation,
-    IrInstGenIdNegationWrapping,
     IrInstGenIdBinOp,
     IrInstGenIdLoadPtr,
     IrInstGenIdStorePtr,
@@ -2932,11 +2931,7 @@ struct IrInstGenBinaryNot {
 struct IrInstGenNegation {
     IrInstGen base;
     IrInstGen *operand;
-};
-
-struct IrInstGenNegationWrapping {
-    IrInstGen base;
-    IrInstGen *operand;
+    bool wrapping;
 };
 
 enum IrBinOp {
src/stage1/codegen.cpp
@@ -3564,13 +3564,7 @@ static LLVMValueRef ir_gen_negation(CodeGen *g, IrInstGen *inst, IrInstGen *oper
 static LLVMValueRef ir_render_negation(CodeGen *g, IrExecutableGen *executable,
         IrInstGenNegation *inst)
 {
-    return ir_gen_negation(g, &inst->base, inst->operand, false);
-}
-
-static LLVMValueRef ir_render_negation_wrapping(CodeGen *g, IrExecutableGen *executable,
-        IrInstGenNegationWrapping *inst)
-{
-    return ir_gen_negation(g, &inst->base, inst->operand, true);
+    return ir_gen_negation(g, &inst->base, inst->operand, inst->wrapping);
 }
 
 static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutableGen *executable, IrInstGenBoolNot *instruction) {
@@ -6645,8 +6639,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutableGen *executabl
             return ir_render_binary_not(g, executable, (IrInstGenBinaryNot *)instruction);
         case IrInstGenIdNegation:
             return ir_render_negation(g, executable, (IrInstGenNegation *)instruction);
-        case IrInstGenIdNegationWrapping:
-            return ir_render_negation_wrapping(g, executable, (IrInstGenNegationWrapping *)instruction);
         case IrInstGenIdLoadPtr:
             return ir_render_load_ptr(g, executable, (IrInstGenLoadPtr *)instruction);
         case IrInstGenIdStorePtr:
src/stage1/ir.cpp
@@ -749,8 +749,6 @@ void destroy_instruction_gen(IrInstGen *inst) {
             return heap::c_allocator.destroy(reinterpret_cast<IrInstGenBinaryNot *>(inst));
         case IrInstGenIdNegation:
             return heap::c_allocator.destroy(reinterpret_cast<IrInstGenNegation *>(inst));
-        case IrInstGenIdNegationWrapping:
-            return heap::c_allocator.destroy(reinterpret_cast<IrInstGenNegationWrapping *>(inst));
         case IrInstGenIdWasmMemorySize:
             return heap::c_allocator.destroy(reinterpret_cast<IrInstGenWasmMemorySize *>(inst));
         case IrInstGenIdWasmMemoryGrow:
@@ -1672,10 +1670,6 @@ static constexpr IrInstGenId ir_inst_id(IrInstGenNegation *) {
     return IrInstGenIdNegation;
 }
 
-static constexpr IrInstGenId ir_inst_id(IrInstGenNegationWrapping *) {
-    return IrInstGenIdNegationWrapping;
-}
-
 static constexpr IrInstGenId ir_inst_id(IrInstGenBinOp *) {
     return IrInstGenIdBinOp;
 }
@@ -2652,24 +2646,12 @@ static IrInstSrc *ir_build_un_op(IrBuilderSrc *irb, Scope *scope, AstNode *sourc
     return ir_build_un_op_lval(irb, scope, source_node, op_id, value, LValNone, nullptr);
 }
 
-static IrInstGen *ir_build_negation(IrAnalyze *ira, IrInst *source_instr, IrInstGen *operand, ZigType *expr_type) {
+static IrInstGen *ir_build_negation(IrAnalyze *ira, IrInst *source_instr, IrInstGen *operand, ZigType *expr_type, bool wrapping) {
     IrInstGenNegation *instruction = ir_build_inst_gen<IrInstGenNegation>(&ira->new_irb,
             source_instr->scope, source_instr->source_node);
     instruction->base.value->type = expr_type;
     instruction->operand = operand;
-
-    ir_ref_inst_gen(operand);
-
-    return &instruction->base;
-}
-
-static IrInstGen *ir_build_negation_wrapping(IrAnalyze *ira, IrInst *source_instr, IrInstGen *operand,
-        ZigType *expr_type)
-{
-    IrInstGenNegationWrapping *instruction = ir_build_inst_gen<IrInstGenNegationWrapping>(&ira->new_irb,
-            source_instr->scope, source_instr->source_node);
-    instruction->base.value->type = expr_type;
-    instruction->operand = operand;
+    instruction->wrapping = wrapping;
 
     ir_ref_inst_gen(operand);
 
@@ -21273,24 +21255,24 @@ static IrInstGen *ir_analyze_negation(IrAnalyze *ira, IrInstSrcUnOp *instruction
 
     bool is_wrap_op = (instruction->op_id == IrUnOpNegationWrap);
 
-    switch (expr_type->id) {
+    ZigType *scalar_type = (expr_type->id == ZigTypeIdVector) ?
+            expr_type->data.vector.elem_type : expr_type;
+
+    switch (scalar_type->id) {
         case ZigTypeIdComptimeInt:
         case ZigTypeIdFloat:
         case ZigTypeIdComptimeFloat:
-        case ZigTypeIdVector:
             break;
         case ZigTypeIdInt:
-            if (is_wrap_op || expr_type->data.integral.is_signed)
+            if (is_wrap_op || scalar_type->data.integral.is_signed)
                 break;
             ZIG_FALLTHROUGH;
         default:
             ir_add_error(ira, &instruction->base.base,
-                buf_sprintf("negation of type '%s'", buf_ptr(&expr_type->name)));
+                buf_sprintf("negation of type '%s'", buf_ptr(&scalar_type->name)));
             return ira->codegen->invalid_inst_gen;
     }
 
-    ZigType *scalar_type = (expr_type->id == ZigTypeIdVector) ? expr_type->data.vector.elem_type : expr_type;
-
     if (instr_is_comptime(value)) {
         ZigValue *operand_val = ir_resolve_const(ira, value, UndefBad);
         if (!operand_val)
@@ -21328,11 +21310,7 @@ static IrInstGen *ir_analyze_negation(IrAnalyze *ira, IrInstSrcUnOp *instruction
         return result_instruction;
     }
 
-    if (is_wrap_op) {
-        return ir_build_negation_wrapping(ira, &instruction->base.base, value, expr_type);
-    } else {
-        return ir_build_negation(ira, &instruction->base.base, value, expr_type);
-    }
+    return ir_build_negation(ira, &instruction->base.base, value, expr_type, is_wrap_op);
 }
 
 static IrInstGen *ir_analyze_bin_not(IrAnalyze *ira, IrInstSrcUnOp *instruction) {
@@ -32214,7 +32192,6 @@ bool ir_inst_gen_has_side_effects(IrInstGen *instruction) {
         case IrInstGenIdVectorExtractElem:
         case IrInstGenIdBinaryNot:
         case IrInstGenIdNegation:
-        case IrInstGenIdNegationWrapping:
         case IrInstGenIdWasmMemorySize:
         case IrInstGenIdReduce:
             return false;
src/stage1/ir_print.cpp
@@ -540,8 +540,6 @@ const char* ir_inst_gen_type_str(IrInstGenId id) {
             return "GenBinaryNot";
         case IrInstGenIdNegation:
             return "GenNegation";
-        case IrInstGenIdNegationWrapping:
-            return "GenNegationWrapping";
         case IrInstGenIdWasmMemorySize:
             return "GenWasmMemorySize";
         case IrInstGenIdWasmMemoryGrow:
@@ -1144,16 +1142,10 @@ static void ir_print_binary_not(IrPrintGen *irp, IrInstGenBinaryNot *instruction
 }
 
 static void ir_print_negation(IrPrintGen *irp, IrInstGenNegation *instruction) {
-    fprintf(irp->f, "-");
+    fprintf(irp->f, instruction->wrapping ? "-%%" : "-");
     ir_print_other_inst_gen(irp, instruction->operand);
 }
 
-static void ir_print_negation_wrapping(IrPrintGen *irp, IrInstGenNegationWrapping *instruction) {
-    fprintf(irp->f, "-%%");
-    ir_print_other_inst_gen(irp, instruction->operand);
-}
-
-
 static void ir_print_field_ptr(IrPrintSrc *irp, IrInstSrcFieldPtr *instruction) {
     if (instruction->field_name_buffer) {
         fprintf(irp->f, "fieldptr ");
@@ -3294,9 +3286,6 @@ static void ir_print_inst_gen(IrPrintGen *irp, IrInstGen *instruction, bool trai
         case IrInstGenIdNegation:
             ir_print_negation(irp, (IrInstGenNegation *)instruction);
             break;
-        case IrInstGenIdNegationWrapping:
-            ir_print_negation_wrapping(irp, (IrInstGenNegationWrapping *)instruction);
-            break;
         case IrInstGenIdWasmMemorySize:
             ir_print_wasm_memory_size(irp, (IrInstGenWasmMemorySize *)instruction);
             break;
test/compile_errors.zig
@@ -8172,14 +8172,19 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
     , &[_][]const u8{
         "tmp.zig:2:9: error: @wasmMemoryGrow is a wasm32 feature only",
     });
-
     cases.add("Issue #5586: Make unary minus for unsigned types a compile error",
-        \\export fn f(x: u32) u32 {
+        \\export fn f1(x: u32) u32 {
+        \\    const y = -%x;
+        \\    return -y;
+        \\}
+        \\const V = @import("std").meta.Vector;
+        \\export fn f2(x: V(4, u32)) V(4, u32) {
         \\    const y = -%x;
         \\    return -y;
         \\}
     , &[_][]const u8{
         "tmp.zig:3:12: error: negation of type 'u32'",
+        "tmp.zig:8:12: error: negation of type 'u32'",
     });
 
     cases.add("Issue #5618: coercion of ?*c_void to *c_void must fail.",