summaryrefslogtreecommitdiff
path: root/src/main/java/com/seaofnodes/simple/node/CProjNode.java
blob: 12fde6c0606d5004d489050d9131b495d7616f4a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package com.seaofnodes.simple.node;

import com.seaofnodes.print.ExprPrinter;

import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.codegen.Serialize;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeTuple;
import com.seaofnodes.simple.util.BAOS;

import java.util.HashMap;
import java.util.IdentityHashMap;

public class CProjNode extends CFGNode implements Proj {

    // Which slice of the incoming multipart value
    public int _idx;

    // Debugging label
    public String _label;

    public CProjNode(Node ctrl, int idx, String label) {
        super(ctrl);
        _idx = idx;
        _label = label;
    }
    public CProjNode(CProjNode c) { super(c); _idx = c._idx; _label = c._label; }
    @Override public Tag serialTag() { return Tag.CProj; }
    @Override public void packed( BAOS baos, HashMap<String,Integer> strs, HashMap<Type,Integer> types, IdentityHashMap<Node, Integer> anodes ) {
        baos.packed1(_idx);
        baos.packed2(_label==null ? 0 : strs.get(_label));
    }
    static Node make( BAOS bais, String[] strs ) {
        return new CProjNode(null, bais.packed1(), strs[bais.packed2()] );
    }

    @Override public String label() { return _label; }

    @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) { return p.p(_label); }

    @Override public boolean blockHead() { return true; }

    public CFGNode ctrl() { return cfg(0); }

    @Override
    public Type compute() {
        Type t = ctrl()._type;
        return t instanceof TypeTuple tt ? tt._types[_idx] : (t.isHigh() ? Type.TOP : Type.BOTTOM);
    }

    @Override
    public Node idealize() {
        if( ctrl()._type instanceof TypeTuple tt ) {
            if( tt._types[_idx]==Type.XCONTROL )
                return CodeGen.CODE.XCTRL; // We are dead
            if( ctrl() instanceof IfNode && tt._types[1-_idx]==Type.XCONTROL ) // Only true for IfNodes
                return ctrl().in(0);               // We become our input control
        }

        // Flip a negating if-test, to remove the not
        if( ctrl() instanceof IfNode iff && iff.pred() != null && addDep(iff.pred()) instanceof NotNode not )
            return new CProjNode(new IfNode(iff.ctrl(),not.in(1)).peephole(),1-_idx,_idx==0 ? "False" : "True");

        // Copy of some other input
        return ((MultiNode)ctrl()).pcopy(_idx);
    }

    // Only called during basic-block layout, inverts a T/F CProj
    public void invert() {
        _label = _idx == 0 ? "False" : "True";
        _idx = 1-_idx;
    }

    @Override
    public boolean eq( Node n ) { return _idx == ((CProjNode)n)._idx; }

    @Override
    int hash() { return _idx; }

    @Override public int idx() { return _idx; }

    @Override public void gather( HashMap<String,Integer> strs ) {
        Serialize.gather(strs,_label);
    }
}