Skip to content

Commit

Permalink
Give the ts compiler special handling for returns in then branches
Browse files Browse the repository at this point in the history
  • Loading branch information
Pat-Lafon committed Sep 9, 2023
1 parent db8ea47 commit 0596887
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 12 deletions.
28 changes: 27 additions & 1 deletion bril-ts/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export class Builder {
return this.buildEffect("call", args, [func], undefined);
}
}

/**
* Build a constant instruction. As above, the destination name is optional.
*/
Expand Down Expand Up @@ -124,6 +124,32 @@ export class Builder {
this.curFunction.instrs.push(instr);
}

/**
* Checks whether the last emitted instruction in the current function is the specified op code.
* Useful for checking for terminating instructions.
*/
isLastEmittedEffectOp(op: bril.EffectOpCode): boolean {
if (!this.curFunction) {
return false
}

if (!this.curFunction.instrs) {
return false
}

if (this.curFunction.instrs.length === 0) {
return false
}

const last_instr : bril.Instruction | bril.Label = this.curFunction.instrs[this.curFunction.instrs.length - 1];

if ('label' in last_instr) {
return false
}

return last_instr.op === op
}

/**
* Generate an unused variable name.
*/
Expand Down
2 changes: 0 additions & 2 deletions test/ts/factorial.out
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@
.then.0:
v4: int = const 1;
ret v4;
jmp .endif.0;
.else.0:
.endif.0:
v5: int = id x;
v6: int = id x;
v7: int = const 1;
Expand Down
13 changes: 13 additions & 0 deletions test/ts/simplified.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@main {
v0: int = const 1;
call @erronious v0;
v1: int = const 0;
}
@erronious(x: int): int {
v1: bool = const true;
br v1 .then.0 .else.0;
.then.0:
v2: int = id x;
ret v2;
.else.0:
}
8 changes: 8 additions & 0 deletions test/ts/simplified.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
erronious(1n);

// This snippet checks that the ts compiler doesn't try to create an unreachable else branch
function erronious(x: bigint): bigint {
if (true) {
return x;
}
}
24 changes: 15 additions & 9 deletions ts2bril.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,20 +145,20 @@ function emitBril(prog: ts.Node, checker: ts.TypeChecker): bril.Program {

// Check if effect statement, i.e., a call that is not a subexpression
if (call.parent.kind === ts.SyntaxKind.ExpressionStatement) {
builder.buildCall(callText,
builder.buildCall(callText,
values.map(v => v.dest));
return builder.buildInt(0); // Expressions must produce values
} else {
let decl = call.parent as ts.VariableDeclaration;
let type = brilType(decl, checker);
let name = (decl.name != undefined) ? decl.name.getText() : undefined;
return builder.buildCall(
callText,
values.map(v => v.dest),
type,
callText,
values.map(v => v.dest),
type,
name,
);
}
}
}
default:
throw `unsupported expression kind: ${expr.getText()}`;
Expand Down Expand Up @@ -215,12 +215,18 @@ function emitBril(prog: ts.Node, checker: ts.TypeChecker): bril.Program {
// Statement chunks.
builder.buildLabel(thenLab);
emit(if_.thenStatement);
builder.buildEffect("jmp", [], undefined, [endLab]);
const then_branch_terminated = builder.isLastEmittedEffectOp("ret");
if (!then_branch_terminated) {
builder.buildEffect("jmp", [], undefined, [endLab]);
}
builder.buildLabel(elseLab);
if (if_.elseStatement) {
emit(if_.elseStatement);
}
builder.buildLabel(endLab);
// The else branch otherwise just falls through without needing a target label
if (!then_branch_terminated) {
builder.buildLabel(endLab);
}

break;
}
Expand Down Expand Up @@ -258,7 +264,7 @@ function emitBril(prog: ts.Node, checker: ts.TypeChecker): bril.Program {
break;
}

case ts.SyntaxKind.FunctionDeclaration:
case ts.SyntaxKind.FunctionDeclaration:
let funcDef = node as ts.FunctionDeclaration;
if (funcDef.name === undefined) {
throw `no anonymous functions!`;
Expand Down Expand Up @@ -298,7 +304,7 @@ function emitBril(prog: ts.Node, checker: ts.TypeChecker): bril.Program {

case ts.SyntaxKind.ImportDeclaration:
break;

default:
throw `unhandled TypeScript AST node kind ${ts.SyntaxKind[node.kind]}`;
}
Expand Down

0 comments on commit 0596887

Please sign in to comment.