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()));
}
}
|