package com.seaofnodes.simple.node; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.Parser; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.type.Type; import com.seaofnodes.simple.util.BAOS; import java.util.*; public class RegionNode extends CFGNode { // Source location for late discovered errors public Parser.Lexer _loc; public RegionNode(Parser.Lexer loc, Node... nodes) { super(nodes); _loc = loc; } public RegionNode(RegionNode r, Parser.Lexer loc) { super(r); _loc = loc; } public RegionNode(RegionNode r) { super(r); if( r!=null ) _loc = r._loc; } @Override public Tag serialTag() { return Tag.Region; } public void packed( BAOS baos, HashMap strs, HashMap types, IdentityHashMap anodes ) { baos.packed1(nIns()); } static Node make( BAOS bais ) { return new RegionNode(null,new Node[bais.packed1()]); } @Override protected ExprPrinter _print1(ExprPrinter p) { return p.p(label()); } @Override public boolean blockHead() { return true; } @Override public Type compute() { if( inProgress() ) return Type.CONTROL; Type t = Type.XCONTROL; for (int i = 1; i < nIns(); i++) t = t.meet(in(i)._type); return t; } @Override public Node idealize() { if( inProgress() ) return null; Node progress = deadPath(false); if( progress!=null ) return progress; // If down to a single input, become that input if( nIns()==2 && !hasPhi() ) return in(1); // Collapse if no Phis; 1-input Phis will collapse on their own // If a CFG diamond with no merging, delete: "if( pred ) {} else {};" if( !hasPhi() && nIns()>3 && // No Phi users, just a control user in(1) instanceof CProjNode p1 && in(2) instanceof CProjNode p2 && addDepForwards(p1).in(0)==addDepForwards(p2).in(0) && p1.in(0) instanceof IfNode iff ) { // Replace with the iff.ctrl directly if( nIns()==3 ) return iff.ctrl(); // Just delete the path for fat Regions setDef(1,iff.ctrl()); return delDef(2); } // Flatten stacked regions (no loops involved) if( getClass() == RegionNode.class && nIns()>2 ) { for( int i=1; i2 && !hasMidUser(region) ) { assert !region.inProgress(); // Fold Phis for( Node use : _outputs ) { if( use instanceof PhiNode phi ) { PhiNode phi2 = phi.in(i) instanceof PhiNode phi2x && phi2x.region()==region ? phi2x : null; for( int j=1; j1 && in(nIns()-1) == null; } // Never equal if inProgress @Override public boolean eq( Node n ) { return !inProgress(); } }