compiler: Check branch instruction printing

3b4ce6f2f680fc5ea207eaa03a60fc3a199c297e5b48db079f378044f470e928
Alexis Sellier committed ago 1 parent b1a85855
lib/std/lang/il/printer.rad +34 -22
177 177
//////////////////////////
178 178
// Instruction printing //
179 179
//////////////////////////
180 180
181 181
/// Write an instruction.
182 -
unsafe fn writeInstr(out: &mut opaque sexpr::Output, blocks: *unsafe [super::Block], inst: super::Instr) {
182 +
unsafe fn writeInstr(out: &mut opaque sexpr::Output, blocks: &[super::Block], inst: super::Instr) {
183 183
    match inst {
184 184
        case super::Instr::Call { args, .. } => writeOperandInstr(out, inst, args),
185 185
186 186
        case super::Instr::Jmp { target, args } => {
187 187
            write(out, "jmp ");
188 188
            writeTarget(out, blocks, target, args);
189 189
        }
190 -
        case super::Instr::Br { op, typ, a: va, b: vb, thenTarget, thenArgs, elseTarget, elseArgs } => {
191 -
            write(out, "br.");
192 -
            match op {
193 -
                case super::CmpOp::Eq  => write(out, "eq"),
194 -
                case super::CmpOp::Ne  => write(out, "ne"),
195 -
                case super::CmpOp::Slt => write(out, "slt"),
196 -
                case super::CmpOp::Ult => write(out, "ult"),
197 -
            }
198 -
            write(out, " ");
199 -
            writeType(out, typ);
200 -
            write(out, " ");
201 -
            writeVal(out, va);
202 -
            write(out, " ");
203 -
            writeVal(out, vb);
204 -
            write(out, " ");
205 -
            writeTarget(out, blocks, thenTarget, thenArgs);
206 -
            write(out, " ");
207 -
            writeTarget(out, blocks, elseTarget, elseArgs);
208 -
        }
190 +
        case super::Instr::Br { thenArgs, elseArgs, .. } =>
191 +
            writeBranch(out, blocks, inst, thenArgs, elseArgs),
209 192
        case super::Instr::Switch { val, defaultTarget, defaultArgs, cases } => {
210 193
            write(out, "switch ");
211 194
            writeVal(out, val);
212 195
            for c in cases {
213 196
                write(out, " (");
221 204
        }
222 205
        else => writeOperandInstr(out, inst, &[]),
223 206
    }
224 207
}
225 208
209 +
/// Write a comparison and both of its control-flow edges.
210 +
fn writeBranch(
211 +
    out: &mut opaque sexpr::Output,
212 +
    blocks: &[super::Block],
213 +
    inst: super::Instr,
214 +
    thenArgs: &[super::Val],
215 +
    elseArgs: &[super::Val],
216 +
) {
217 +
    let case super::Instr::Br { op, typ, a: va, b: vb, thenTarget, elseTarget, .. } = inst
218 +
        else panic "writeBranch: expected branch";
219 +
    write(out, "br.");
220 +
    match op {
221 +
        case super::CmpOp::Eq  => write(out, "eq"),
222 +
        case super::CmpOp::Ne  => write(out, "ne"),
223 +
        case super::CmpOp::Slt => write(out, "slt"),
224 +
        case super::CmpOp::Ult => write(out, "ult"),
225 +
    }
226 +
    write(out, " ");
227 +
    writeType(out, typ);
228 +
    write(out, " ");
229 +
    writeVal(out, va);
230 +
    write(out, " ");
231 +
    writeVal(out, vb);
232 +
    write(out, " ");
233 +
    writeTarget(out, blocks, thenTarget, thenArgs);
234 +
    write(out, " ");
235 +
    writeTarget(out, blocks, elseTarget, elseArgs);
236 +
}
237 +
226 238
/// Write a target label and its optional block arguments.
227 239
fn writeTarget(out: &mut opaque sexpr::Output, blocks: &[super::Block], target: u32, args: &[super::Val]) {
228 240
    write(out, "@");
229 241
    write(out, blocks[target].label);
230 242
    if args.len > 0 {
401 413
////////////////////
402 414
// Block printing //
403 415
////////////////////
404 416
405 417
/// Write a basic block.
406 -
unsafe fn writeBlock(out: &mut opaque sexpr::Output, blocks: *unsafe [super::Block], block: *unsafe super::Block) {
418 +
unsafe fn writeBlock(out: &mut opaque sexpr::Output, blocks: &[super::Block], block: &super::Block) {
407 419
    // Block label.
408 420
    write(out, "  @");
409 421
    write(out, block.label);
410 422
411 423
    // Block parameters.
427 439
///////////////////////
428 440
// Function printing //
429 441
///////////////////////
430 442
431 443
/// Write a function.
432 -
unsafe fn writeFn(out: &mut opaque sexpr::Output, f: *unsafe super::Fn) {
444 +
unsafe fn writeFn(out: &mut opaque sexpr::Output, f: &super::Fn) {
433 445
    // Function signature.
434 446
    if f.isExtern {
435 447
        write(out, "extern ");
436 448
    }
437 449
    write(out, "fn ");
lib/std/lang/il/tests.rad +9 -6
8 8
unsafe fn checkPrintedInstruction(instr: super::Instr, expected: &[u8]) throws (testing::TestError) {
9 9
    let mut instructions = [instr];
10 10
    let blocks = [super::Block {
11 11
        label: "entry", params: &[], instrs: &mut instructions[..],
12 12
        locs: &[], preds: &[], loopDepth: 0,
13 +
    }, super::Block {
14 +
        label: "exit", params: &[], instrs: &mut [],
15 +
        locs: &[], preds: &[], loopDepth: 0,
13 16
    }];
14 17
    let function = super::Fn {
15 18
        name: "sample", params: &[], returnType: super::Type::W64,
16 19
        isExtern: false, isLeaf: true, blocks: &blocks[..],
17 20
    };
86 89
    let mut args = [value, other];
87 90
    try checkPrintedInstruction(super::Instr::Jmp { target: 0, args: &mut [] }, "jmp @entry");
88 91
    try checkPrintedInstruction(super::Instr::Jmp { target: 0, args: &mut args[..] }, "jmp @entry(%3, -7)");
89 92
    try checkPrintedInstruction(super::Instr::Br {
90 93
        op: super::CmpOp::Eq, typ: super::Type::W8, a: value, b: other,
91 -
        thenTarget: 0, thenArgs: &mut [], elseTarget: 0, elseArgs: &mut [],
92 -
    }, "br.eq w8 %3 -7 @entry @entry");
94 +
        thenTarget: 0, thenArgs: &mut [], elseTarget: 1, elseArgs: &mut [],
95 +
    }, "br.eq w8 %3 -7 @entry @exit");
93 96
    try checkPrintedInstruction(super::Instr::Br {
94 97
        op: super::CmpOp::Ne, typ: super::Type::W16, a: value, b: other,
95 -
        thenTarget: 0, thenArgs: &mut args[..], elseTarget: 0, elseArgs: &mut [],
96 -
    }, "br.ne w16 %3 -7 @entry(%3, -7) @entry");
98 +
        thenTarget: 1, thenArgs: &mut args[..], elseTarget: 0, elseArgs: &mut [],
99 +
    }, "br.ne w16 %3 -7 @exit(%3, -7) @entry");
97 100
    try checkPrintedInstruction(super::Instr::Br {
98 101
        op: super::CmpOp::Slt, typ: super::Type::W32, a: value, b: other,
99 -
        thenTarget: 0, thenArgs: &mut [], elseTarget: 0, elseArgs: &mut args[..],
100 -
    }, "br.slt w32 %3 -7 @entry @entry(%3, -7)");
102 +
        thenTarget: 0, thenArgs: &mut [], elseTarget: 1, elseArgs: &mut args[..],
103 +
    }, "br.slt w32 %3 -7 @entry @exit(%3, -7)");
101 104
    try checkPrintedInstruction(super::Instr::Br {
102 105
        op: super::CmpOp::Ult, typ: super::Type::W64, a: value, b: other,
103 106
        thenTarget: 0, thenArgs: &mut args[..], elseTarget: 0, elseArgs: &mut args[..],
104 107
    }, "br.ult w64 %3 -7 @entry(%3, -7) @entry(%3, -7)");
105 108
    let mut cases = [