Skip to content

Specialisation for XRef problems #89

@mbenke

Description

@mbenke

Ref.load for XRef does not get specialised in:

function add_(x:word, y:word) { // _add is not a legal identifier :(
    let res: word;
    assembly {
       res := add(x, y)
    };
    return res;
  }

function mload_(x:word) -> word {
    let res: word;
    assembly {
       res := mload(x)
    };
    return res;
  }

function mstore_(a:word, v:word) {
    assembly { mstore(a,v) };
}

class r:Ref(d) { function load(x:r) -> d; function store(x:r, v:d) -> ();}

class self:Typedef(underlyingType) {
    function rep(x:self) -> underlyingType;   // abbr: x.rep = Typedef.rep(x)
    function abs(x:underlyingType) -> self;   // abbr: x.abs
}
data Proxy(a) = Proxy;

data M(a) = M(word);

instance M(a) : Typedef(word) {
  function rep(m) { match m { | M(w) => return w; };}
  function abs(w) { return M(w); }
}

class Self:MemoryType {
    function memorySize(p:Proxy(Self)) -> word; 
    /* inline function sizeof(Self) -> word { // an abbreviation to avoid writing Proxy; wasteful unless inlined
      return memorySize(Proxy:Proxy(self)); 
    } */
    function memoryStep(word, self:Self) -> word;
    function mload(r:word) -> Self;
    function mstore(r:word, v:Self) -> ();
}

forall Self:MemoryType . function sizeof(self:Self) -> word {
      return MemoryType.memorySize(Proxy:Proxy(self)); 
}

class a:MemoryRef(d) { function addr(r:a) -> word; }
instance M(a):MemoryRef(a) { function addr(r:M(a)) -> word {return Typedef.rep(r);} }

function xaddr(r:M(a)) -> word { return MemoryRef.addr(r); }
function asMemRefTo(r:M(a), p:Proxy(b)) -> M(b) { return Typedef.abs(xaddr(r)); }

forall a:MemoryType. function stepStore(aa: word, va: a) -> word {
  MemoryType.mstore(aa, va);
  return add_(aa, MemoryType.memorySize(Proxy:Proxy(a)));
}

instance (Self:MemoryType, r:MemoryRef(Self)) => r : Ref(Self) {
  function load(r:M(Self)) { return MemoryType.mload(xaddr(r)); }
  function store(r:M(Self), v:Self) { MemoryType.mstore(xaddr(r), v); }
}

instance word:MemoryType {
  function memorySize(p:Proxy(word)) -> word { return 32; }
  function memoryStep(a:word, self:word) -> word { return add_(a,32); }
  function mload(a: word) -> word { return mload_(a); }
  function mstore(a: word, v:word) -> () { mstore_(a, v); }
}

instance (a:MemoryType, b:MemoryType) => (a,b) : MemoryType {
  function memorySize(p:Proxy((a,b))) -> word {
    return add_(MemoryType.memorySize(Proxy:Proxy(a)), MemoryType.memorySize(Proxy:Proxy(a)) );
  }
  
  function mload(aa:word) -> (a,b)  {
    let va = MemoryType.mload(aa);
    let ab = add_(aa, sizeof(va));
    let vb = MemoryType.mload(ab);
    return (va,vb);
  }

  function mstore(aa:word, v: (a,b)) {
    match v { | pair(va, vb) => mstore2(aa, va, vb); }; // match-compiler cannot compile mopre than 1 stmt in a branch :(
  }
}

forall a: MemoryType, b: MemoryType . function mstore2(aa:word, va:a, vb: b) { //needed because of bug in match-compiler
  let ab = stepStore(aa, va); 
  MemoryType.mstore(ab, vb);
}

pragma no-bounded-variable-condition MemoryRef;
pragma no-coverage-condition Ref;
pragma no-patterson-condition Ref;
data XRef(st, field, fieldType) = XRef(st, field);
data PairFst = PairFst;
data PairSnd = PairSnd;


instance ( r:MemoryRef ( (a,b)), a:MemoryType, b:MemoryType ) => XRef(r, PairFst, a) : MemoryRef(a) {
  function addr(xr) { match xr { | XRef(r, _) => return MemoryRef.addr(r); }; }
}

instance ( r:MemoryRef ( (a,b)), a:MemoryType, b:MemoryType ) => XRef(r, PairSnd, b) : MemoryRef(b) {
  function addr(xr) {
    match xr {
      | XRef(r, _) => return add_(MemoryRef.addr(r), MemoryType.memorySize(Proxy:Proxy(b)));
    };
  }
}

contract Ref219 {
  function main() {
    let mp:M((word, word, word)) = M(96); // no alloc yet
    let p = (1,16,25);
    Ref.store(mp, p);

    let ra = XRef(mp, PairFst);
    let a = Ref.load(ra);
    let r2 = XRef(mp, PairSnd);
    let rb = XRef(r2, PairFst);
    let a = Ref.load(ra);
    let b = Ref.load(rb);
    let rc = XRef(r2, PairSnd);
    let c = Ref.load(rc);
    return add_(a, add_(b, c));
  }
}

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions