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 strs, HashMap types, IdentityHashMap 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 _print1(ExprPrinter 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 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