summaryrefslogtreecommitdiff
path: root/src/main/java/com/seaofnodes/simple/node/NewNode.java
blob: 5eedd0cd48128bfaea57007d4e3dd739bfc059e3 (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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package com.seaofnodes.simple.node;

import com.seaofnodes.print.ExprPrinter;

import com.seaofnodes.simple.codegen.*;
import com.seaofnodes.simple.type.*;
import com.seaofnodes.simple.util.BAOS;
import com.seaofnodes.simple.util.SB;

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

/**
 * Allocation!  Allocate a chunk of memory, no init.
 * Takes in ctrl and size, and TypeStruct.
 * Produces a ptr and private memory.
*/
public class NewNode extends Node implements MultiNode {
    public TypeStruct _ts;
    public NewNode( TypeStruct ts, Node ctrl, Node size ) { super(ctrl,size); _ts = ts; }

    public Node ctrl() { return in(0); }
    public Node size() { return in(1); }

    // --- Serialization
    public NewNode(NewNode nnn) { super(nnn); _ts = nnn._ts; }
    @Override public Tag serialTag() { return Tag.New; }
    @Override public void packed( BAOS baos, HashMap<String,Integer> strs, HashMap<Type,Integer> types, IdentityHashMap<Node, Integer> anodes ) {
        baos.packed2(types.get(_ts));
    }
    static Node make( BAOS bais, Type[] types)  {
        TypeStruct ts = (TypeStruct)types[bais.packed2()];
        return new NewNode(ts,null,null);
    }

    @Override public String label() { return "new_"+(_ts.isAry() ? "ary_"+_ts._fields[1]._t.str() : _ts.str()); }

    @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
        return p.p("new ").p(_ts.str());
    }

    @Override public TypeTuple compute() {
        if( ctrl()._type.isHigh() )
            return TypeTuple.DEAD_NEW;
        TypeStruct ts = _ts.isAry() ? _ts : _ts.makeInit();
        return TypeTuple.make(TypeMemPtr.make(_ts),
                              // Arrays get pre-zeroed by constructor.
                              // Objects start with default-zero memory for
                              // fields that can be zero-initialized.  This is
                              // still private memory, so no aliases escape yet.
                              TypeMem.make(1,ts,true,false,false,null,null));
    }

    @Override public Node idealize() { return null; }

    @Override boolean _upgradeType( HashMap<String,Type> TYPES) {
        Type old = _ts; _ts = (TypeStruct)_ts.upgradeType(TYPES);  return old != _ts;
    }

    // Two NewNodes are never equal; NewNodes always make independent pointers
    // so they are not functional - they internally bump-ptr allocate always a
    // new pointer.
    @Override public boolean eq(Node n) { return this==n; }

    @Override int hash() { return _ts.hashCode(); }

    // ------------
    // MachNode specifics, shared across all CPUs
    public int _arg2Reg, _xslot;
    private RegMask _arg3Mask;
    private RegMask _retMask;
    private RegMask _kills;
    public void cacheRegs(CodeGen code) {
        _arg2Reg  = code._mach.callArgMask(TypeFunPtr.CALLOC,2,0,code._cCallingConv).firstReg();
        _arg3Mask = code._mach.callArgMask(TypeFunPtr.CALLOC,3,0,code._cCallingConv);
        // Return mask depends on TFP (either GPR or FPR)
        _retMask = code._mach.retMask(TypeFunPtr.CALLOC);
        // Kill mask is all caller-saves, and any mirror stack slots for args
        // in registers.
        RegMaskRW kills = code._cCallerSave.copy();
        // Start of stack slots
        int maxReg = code._mach.regs().length;
        // Incoming function arg slots, all low numbered in the RA
        int fslot = cfg0().fun()._maxArgSlot;
        // Killed slots for this calls outgoing args
        int xslot = code._mach.maxArgSlot(TypeFunPtr.CALLOC,code._cCallingConv);
        _xslot = (maxReg+fslot)+xslot;
        for( int i=0; i<xslot; i++ )
            kills.set((maxReg+fslot)+i);
        _kills = kills;
    }
    public String op() { return "alloc"; }
    public RegMask regmap(int i) { return i==1 ? _arg3Mask : null; }
    public RegMask outregmap() { return null; }
    public RegMask outregmap(int idx) { return idx==0  ? _retMask : null; }
    public RegMask killmap() { return _kills; }
    public void asm(CodeGen code, SB sb) {
        sb.p("#malloc, ").p(code.reg(size()));
    }

}