blob: f94fa48478b6ddd10b291bed2eda5aa1bd1e8155 (
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
|
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<Node> _print1(ExprPrinter<Node> 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<String,Type> 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(); }
}
|