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.type.TypeInteger; import com.seaofnodes.simple.type.TypeStruct; import com.seaofnodes.simple.util.SB; import com.seaofnodes.simple.util.Utils; import java.util.HashMap; /** * A field offset. This becomes a constant *after* other optimizations which * determine field sizes - some fields might be dead, or hold only zeros or * small values. */ public class ConFldOffNode extends ConstantNode { public TypeStruct _ts; // Struct holding field public final String _fname; // Field name public ConFldOffNode( TypeStruct ts, String fname ) { super(TypeInteger.BOT); _ts = ts; _fname = fname; } @Override public Tag serialTag() { throw Utils.TODO("should not reach here"); } @Override public String label() { return _fname == " len" ? "sizeof("+_ts._name+")" : "#"+_fname; } @Override protected ExprPrinter _print1(ExprPrinter p) { return p.p(label()); } @Override public Node idealize() { // Some array offsets are known early if( _ts.isAry() ) { // Length always at offset zero if( _fname==" len" ) return CodeGen.CODE.ZERO; // The shift depends on the element if( _fname=="<<" ) return Node.con(_ts.aryScale()); // The base depends on the layout (alignment for large elements may // involve padding) and MAY depend on the length if I go for // smaller array lengths. } return null; } // Convert field offset to an integer public Node asOffset() { int fldx = _fname==" len" ? _ts._fields.length : _ts.find(_fname); if( fldx == -1 ) return null; // " len" selects the terminal size slot, not a Field. if( fldx < _ts._fields.length && _ts._fields[fldx]._extern ) return new ExternOffsetNode(_fname).peephole(); return ConstantNode.make(TypeInteger.constant(_ts.offset(fldx))).peephole(); } // Upgrade the internal type @Override boolean _upgradeType( HashMap TYPES) { boolean progress = super._upgradeType(TYPES); TypeStruct ts = (TypeStruct)_ts.upgradeType(TYPES); if( ts == _ts ) return progress; _ts = ts; return true; } @Override public boolean eq(Node n) { ConFldOffNode off = (ConFldOffNode)n; // Invariant return _ts._name==off._ts._name && _fname.equals(off._fname) && super.eq(n); } @Override int hash() { return super.hash() * _ts._name.hashCode() * _fname.hashCode(); } }