Skip to content

Commit

Permalink
boots: Fix inlining of functions with unreachable return
Browse files Browse the repository at this point in the history
  • Loading branch information
dinfuehr committed Jan 24, 2025
1 parent 6219ee7 commit 5030f6e
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 11 deletions.
22 changes: 22 additions & 0 deletions pkgs/boots/graph.dora
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,18 @@ impl Block {
inst
}

pub fn prependInst(inst: Inst): Inst {
assert(inst.block.isNone() && !inst.hasId());

inst.block = Some(self);
self.graph.getOrPanic().assignNextInstId(inst);

self.instructions.prependInst(inst);
inst.registerUses();

inst
}

pub fn splitAfter(inst: Inst): Block {
assert(inst.getBlock() === self);
assert(!inst.isTerminator());
Expand Down Expand Up @@ -3167,6 +3179,16 @@ impl InstLinkedList {
self.last.getOrPanic()
}

fn prependInst(inst: Inst) {
let first = self.first.getOrPanic();
first.previous = Some(inst);

inst.previous = None[Inst];
inst.next = Some[Inst](first);

self.first = Some(inst);
}

fn appendInst(inst: Inst) {
if self.first.isNone() {
inst.previous = None;
Expand Down
8 changes: 3 additions & 5 deletions pkgs/boots/graph_builder.dora
Original file line number Diff line number Diff line change
Expand Up @@ -1206,9 +1206,7 @@ impl SsaGen {
let value = self.readVariable(opnd, self.current());
let ty = self.graphTy(ty);

if self.returnValue.isSome() {
let returnValue = self.returnValue.getOrPanic();

if self.returnValue is Some(returnValue) {
let phi = if returnValue.getBlock() == exitBlock {
assert(returnValue.isPhi());
returnValue
Expand All @@ -1219,8 +1217,8 @@ impl SsaGen {
phi
};

// Here we add input to phi after the phi was already appended to
// the graph. Therefore we need to register the input manually.
// Here we add another input to the phi after the phi was already appended
// to the graph. Therefore we need to register the input manually.
let input = phi.addInput(value);
value.addUse(input);
self.returnValue = Some(phi);
Expand Down
19 changes: 13 additions & 6 deletions pkgs/boots/inlining.dora
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use package::bytecode::{BytecodeType, FunctionId};
use package::compilation::CompilationInfo;
use package::graph::{Graph, Inst, Op};
use package::graph::{createUndefInst, Graph, Inst, Op};
use package::graph_builder;
use package::interface as iface;

Expand Down Expand Up @@ -43,11 +43,18 @@ fn inline(ci: CompilationInfo, graph: Graph, inst: Inst, fctId: FunctionId, type
if returnValue.isSome() {
let returnValue = returnValue.getOrPanic();
inst.replaceAllUsesWith(returnValue);
}
if inst.hasUses() {
println("ouch: ${ci.getDisplayName()}");
// println(dumpGraph(Some[CompilationInfo](ci), graph, config.architecture));
// println("ouch");
} else if inst.hasUses() {
// This call has users but the inlined function has no return value
// because it e.g. crashes unconditionally. In this case newBlock is
// unreachable and will be removed by cfg_simplification.
// There is no value to replace all uses of the call return value, so
// replace it with Undef. Undef also needs to be in newBlock to not
// break SSA.
let undef = createUndefInst();
newBlock.prependInst(undef);
inst.replaceAllUsesWith(undef);
} else {
assert(inst.getValueType().isUnit());
}
inst.remove();
}
18 changes: 18 additions & 0 deletions tests/boots/opt/inline-unreachable.dora
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//= boots
//= error code 1

fn main() {
testme();
}

@Optimize
fn testme(): Int {
let x = myFatalError[Int]();
// Everything here is unreachable after inlining.
println("x = ${x}");
x + 1
}

fn myFatalError[T](): T {
std::fatalError[T]("not yet implemented")
}

0 comments on commit 5030f6e

Please sign in to comment.