throw e
L3:
* ****************************************************************/
public Operand buildEnsureNode(Node node, IRScope m) {
EnsureNode ensureNode = (EnsureNode)node;
Node bodyNode = ensureNode.getBodyNode();
// Push a new ensure block info node onto the stack of ensure block
EnsureBlockInfo ebi = new EnsureBlockInfo(m);
_ensureBlockStack.push(ebi);
Label rBeginLabel = m.getNewLabel();
Label rEndLabel = ebi.end;
List<Label> rescueLabels = new ArrayList<Label>() { };
// Start of region
m.addInstr(new LABEL_Instr(rBeginLabel));
m.addInstr(new ExceptionRegionStartMarkerInstr(rBeginLabel, rEndLabel, rescueLabels));
// Generate IR for Code being protected
Operand rv = (bodyNode instanceof RescueNode) ? buildRescueInternal(bodyNode, m, rBeginLabel) : build(bodyNode, m);
// End of protected region
m.addInstr(new ExceptionRegionEndMarkerInstr());
// Jump to start of ensure block -- dont bother if we had a return in the protected body
if (rv != U_NIL)
m.addInstr(new SET_RETADDR_Instr(ebi.returnAddr, rEndLabel));
// Pop the current ensure block info node *BEFORE* generating the ensure code for this block itself!
_ensureBlockStack.pop();
// Generate the ensure block now
m.addInstr(new LABEL_Instr(ebi.start));
// Two cases:
// 1. Ensure block has no explicit return => the result of the entire ensure expression is the result of the protected body.
// 2. Ensure block has an explicit return => the result of the protected body is ignored.
Operand ensureRetVal = (ensureNode.getEnsureNode() == null) ? Nil.NIL : build(ensureNode.getEnsureNode(), m);
if (ensureRetVal == null) // null => there was a return from within the ensure block!
rv = null;
m.addInstr(new JUMP_INDIRECT_Instr(ebi.returnAddr));