From b5ebb2032aa04cf4506d533127d373d4cf5a25c6 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Fri, 13 Jun 2025 15:42:08 -0700 Subject: Chapter 24: Chaining Relationals and Sparse Conditional Constant Propagation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tamás Hadházy <85063808+Hels15@users.noreply.github.com> Co-authored-by: Hsiang-Ying Fu <66062782+fuhsnn@users.noreply.github.com> Co-authored-by: fuhsnn <66062782+fuhsnn@users.noreply.github.com> Co-authored-by: Symious <14933944+symious@users.noreply.github.com> Co-authored-by: Jun Kawasaki Co-authored-by: Hadházy Tamás Co-authored-by: Claude Opus 5 --- src/main/java/com/seaofnodes/simple/IterPeeps.java | 36 +- src/main/java/com/seaofnodes/simple/Parser.java | 115 +- .../com/seaofnodes/simple/codegen/CodeGen.java | 78 +- .../com/seaofnodes/simple/codegen/Encoding.java | 6 +- .../java/com/seaofnodes/simple/codegen/Opto.java | 267 + .../com/seaofnodes/simple/codegen/RegAlloc.java | 37 +- .../java/com/seaofnodes/simple/node/AddFNode.java | 28 +- .../java/com/seaofnodes/simple/node/AddNode.java | 2 +- .../com/seaofnodes/simple/node/ArithFNode.java | 30 + .../java/com/seaofnodes/simple/node/ArithNode.java | 8 +- .../java/com/seaofnodes/simple/node/CProjNode.java | 2 +- .../com/seaofnodes/simple/node/CallEndNode.java | 33 +- .../java/com/seaofnodes/simple/node/CallNode.java | 7 +- .../com/seaofnodes/simple/node/ConFldOffNode.java | 6 +- .../com/seaofnodes/simple/node/ConstantNode.java | 2 +- .../java/com/seaofnodes/simple/node/DivFNode.java | 18 +- .../java/com/seaofnodes/simple/node/FunNode.java | 35 +- .../java/com/seaofnodes/simple/node/IfNode.java | 7 +- .../java/com/seaofnodes/simple/node/LoadNode.java | 29 +- .../com/seaofnodes/simple/node/MemMergeNode.java | 10 +- .../com/seaofnodes/simple/node/MemPhiNode.java | 6 +- .../com/seaofnodes/simple/node/MinusFNode.java | 3 +- .../java/com/seaofnodes/simple/node/MinusNode.java | 2 +- .../java/com/seaofnodes/simple/node/MulFNode.java | 18 +- .../java/com/seaofnodes/simple/node/NewNode.java | 5 +- src/main/java/com/seaofnodes/simple/node/Node.java | 27 +- .../java/com/seaofnodes/simple/node/ParmNode.java | 21 + .../java/com/seaofnodes/simple/node/PhiNode.java | 41 +- .../java/com/seaofnodes/simple/node/ProjNode.java | 2 +- .../com/seaofnodes/simple/node/RegionNode.java | 27 +- .../com/seaofnodes/simple/node/ReturnNode.java | 7 +- .../java/com/seaofnodes/simple/node/StoreNode.java | 2 +- .../java/com/seaofnodes/simple/node/SubFNode.java | 24 +- .../com/seaofnodes/simple/node/ToFloatNode.java | 8 +- .../seaofnodes/simple/node/cpus/arm/SetARM.java | 1 + .../com/seaofnodes/simple/node/cpus/arm/arm.java | 4 +- .../simple/node/cpus/riscv/MemOpRISC.java | 3 + .../simple/node/cpus/x86_64_v2/SetX86.java | 1 + .../simple/print/SimpleGraphAdapter.java | 2 +- .../simple/print/SimpleGraphObserver.java | 2 +- src/main/java/com/seaofnodes/simple/type/Type.java | 10 +- .../com/seaofnodes/simple/type/TypeConAry.java | 77 +- .../com/seaofnodes/simple/type/TypeConAryB.java | 9 +- .../com/seaofnodes/simple/type/TypeConAryI.java | 9 +- .../com/seaofnodes/simple/type/TypeFunPtr.java | 7 +- .../com/seaofnodes/simple/type/TypeInteger.java | 80 +- .../com/seaofnodes/simple/type/TypeMemPtr.java | 1 + .../java/com/seaofnodes/simple/type/TypeRPC.java | 30 +- .../com/seaofnodes/simple/type/TypeStruct.java | 6 + .../java/com/seaofnodes/simple/BrainFuckTest.java | 61 +- .../java/com/seaofnodes/simple/Chapter13Test.java | 287 -- .../java/com/seaofnodes/simple/Chapter18Test.java | 12 +- .../java/com/seaofnodes/simple/Chapter19Test.java | 85 +- .../java/com/seaofnodes/simple/Chapter20Test.java | 4 +- .../java/com/seaofnodes/simple/Chapter21Test.java | 185 +- .../java/com/seaofnodes/simple/Chapter22Test.java | 52 +- .../java/com/seaofnodes/simple/Chapter23Test.java | 157 +- .../com/seaofnodes/simple/Chapter24AllocTest.java | 170 + .../java/com/seaofnodes/simple/Chapter24Test.java | 721 +++ src/test/java/com/seaofnodes/simple/Eval2.java | 21 +- .../com/seaofnodes/simple/MemoryEncodingTest.java | 3 +- .../java/com/seaofnodes/simple/MergeSortTest.java | 46 +- src/test/java/com/seaofnodes/simple/Simple.java | 2 +- .../java/com/seaofnodes/simple/SpillStats.java | 5 +- src/test/java/com/seaofnodes/simple/TestArm64.java | 12 +- src/test/java/com/seaofnodes/simple/TestC.java | 17 + src/test/java/com/seaofnodes/simple/TestRisc5.java | 12 +- src/test/java/com/seaofnodes/simple/TypeTest.java | 16 + .../simple/codegen/RegAllocTestSupport.java | 27 + .../com/seaofnodes/simple/evaluator/Scheduler.java | 2 +- .../java/com/seaofnodes/simple/fuzzer/Reducer.java | 2 +- .../seaofnodes/simple/fuzzer/ScriptGenerator.java | 4 +- src/test/java/com/seaofnodes/simple/progs/and1.smp | 10 - src/test/java/com/seaofnodes/simple/progs/and2.smp | 16 - src/test/java/com/seaofnodes/simple/progs/and3.smp | 14 - .../java/com/seaofnodes/simple/progs/antiDep1.smp | 11 - .../com/seaofnodes/simple/progs/brain_fuck.smp | 46 - src/test/java/com/seaofnodes/simple/progs/echo.smp | 3 - src/test/java/com/seaofnodes/simple/progs/fib.smp | 11 - .../com/seaofnodes/simple/progs/helloWorld.smp | 3 - .../java/com/seaofnodes/simple/progs/large.smp | 5344 -------------------- .../java/com/seaofnodes/simple/progs/loop2.smp | 10 - src/test/java/com/seaofnodes/simple/progs/or1.smp | 12 - src/test/java/com/seaofnodes/simple/progs/or2.smp | 23 - .../java/com/seaofnodes/simple/progs/person.smp | 9 - .../java/com/seaofnodes/simple/progs/print.smp | 8 - .../java/com/seaofnodes/simple/progs/ptrand.smp | 10 - .../com/seaofnodes/simple/progs/riscv_load.smp | 4 - .../com/seaofnodes/simple/progs/sext_str_1.smp | 4 - .../seaofnodes/simple/progs/sext_str_fold_away.smp | 5 - .../simple/progs/sext_str_not_fold_away.smp | 4 - .../simple/progs/sext_str_not_fold_away_2.smp | 4 - .../java/com/seaofnodes/simple/progs/sieve.smp | 31 - src/test/java/com/seaofnodes/simple/progs/sort.smp | 38 - .../com/seaofnodes/simple/progs/stacked_r_10x.c | 13 + .../com/seaofnodes/simple/progs/stacked_r_11x.c | 13 + .../com/seaofnodes/simple/progs/stacked_r_12x.c | 13 + .../com/seaofnodes/simple/progs/stacked_r_13x.c | 13 + .../com/seaofnodes/simple/progs/stacked_r_9x.c | 13 + .../com/seaofnodes/simple/progs/store_peep.smp | 3 - 100 files changed, 2433 insertions(+), 6349 deletions(-) create mode 100644 src/main/java/com/seaofnodes/simple/codegen/Opto.java create mode 100644 src/main/java/com/seaofnodes/simple/node/ArithFNode.java create mode 100644 src/test/java/com/seaofnodes/simple/Chapter24AllocTest.java create mode 100644 src/test/java/com/seaofnodes/simple/Chapter24Test.java delete mode 100644 src/test/java/com/seaofnodes/simple/progs/and1.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/and2.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/and3.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/antiDep1.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/brain_fuck.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/echo.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/fib.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/helloWorld.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/large.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/loop2.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/or1.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/or2.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/person.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/print.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/ptrand.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/riscv_load.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/sext_str_1.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/sext_str_fold_away.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/sext_str_not_fold_away.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/sext_str_not_fold_away_2.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/sieve.smp delete mode 100644 src/test/java/com/seaofnodes/simple/progs/sort.smp create mode 100644 src/test/java/com/seaofnodes/simple/progs/stacked_r_10x.c create mode 100644 src/test/java/com/seaofnodes/simple/progs/stacked_r_11x.c create mode 100644 src/test/java/com/seaofnodes/simple/progs/stacked_r_12x.c create mode 100644 src/test/java/com/seaofnodes/simple/progs/stacked_r_13x.c create mode 100644 src/test/java/com/seaofnodes/simple/progs/stacked_r_9x.c delete mode 100644 src/test/java/com/seaofnodes/simple/progs/store_peep.smp (limited to 'src') diff --git a/src/main/java/com/seaofnodes/simple/IterPeeps.java b/src/main/java/com/seaofnodes/simple/IterPeeps.java index c4b96c5c..a3b66e09 100644 --- a/src/main/java/com/seaofnodes/simple/IterPeeps.java +++ b/src/main/java/com/seaofnodes/simple/IterPeeps.java @@ -1,6 +1,8 @@ package com.seaofnodes.simple; import com.seaofnodes.simple.codegen.CodeGen; +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeInteger; import com.seaofnodes.simple.util.Ary; import com.seaofnodes.simple.node.*; import java.util.Arrays; @@ -45,7 +47,7 @@ import java.util.Random; */ public class IterPeeps { - private final WorkList _work; + public final WorkList _work; private final WorkList _workInline; @@ -74,7 +76,7 @@ public class IterPeeps { // Only try growing inlines once the shrinking peepholes reach a fixed point. private void iteratePeeps( CodeGen code ) { - assert progressOnList(code); + assert progressOnList(code, _work, true); int cnt=0; Node n; @@ -109,7 +111,7 @@ public class IterPeeps { } // If there are distant neighbors, move to worklist n.moveDepsToWorklist(); - assert progressOnList(code); // Very expensive assert + assert progressOnList(code, _work, true); // Very expensive assert } if( n.isUnused() && !(n instanceof StopNode) ) n.kill(); // Just plain dead @@ -130,18 +132,24 @@ public class IterPeeps { // neighbors and these should fail, but will then try to add dependencies // {@link #Node.addDep} which is a side effect in an assert. The {@link // #midAssert} is used to stop this side effect. - private boolean progressOnList(CodeGen code) { + // Pessimistic solver assert + public static boolean progressOnList(CodeGen code, WorkList list, boolean dir ) { code._midAssert = true; Node changed = code._stop.walk( n -> { - Node m = n; - if( n.compute().isa(n._type) && (!n.iskeep() || n._nid<=6) ) { // Types must be forwards, even if on worklist - if( _work.on(n) ) return null; - m = n.peepholeOpt(); - if( m==null ) return null; - } - System.err.println("BREAK HERE FOR BUG"); - return m; - }); + Node m = n; + Type nval = n.compute(); + if( (!n.iskeep() || n._nid<=8) && // Types must be forwards, even if on worklist + ( dir + ? nval.isa(n._type) // Pesi: new value lifts over old + : n._type.isa(nval) // Opto: new value falls over old + ) ) { + if( list.on(n) ) return null; + m = n.peepholeOpt(); + if( m==null ) return null; + } + System.err.println("BREAK HERE FOR BUG"); + return m; + }); code._midAssert = false; return changed==null; } @@ -197,7 +205,7 @@ public class IterPeeps { /** * True if Node is on the WorkList */ - boolean on( E x ) { return _on.get(x._nid); } + public boolean on( E x ) { return _on.get(x._nid); } boolean isEmpty() { return _len==0; } /** diff --git a/src/main/java/com/seaofnodes/simple/Parser.java b/src/main/java/com/seaofnodes/simple/Parser.java index 6084eaa5..9cf565ac 100644 --- a/src/main/java/com/seaofnodes/simple/Parser.java +++ b/src/main/java/com/seaofnodes/simple/Parser.java @@ -133,7 +133,7 @@ public class Parser { public void parse() { // Graph callbacks during scope setup need a source position. - _lexer = new Lexer(com.seaofnodes.simple.sys.SYS); + _lexer = new Lexer(sys.SYS); _scope.define(ScopeNode.CTRL, Type.CONTROL , false, null, _lexer); _scope.define(ScopeNode.MEM0, TypeMem.BOT , false, null, _lexer); @@ -160,18 +160,26 @@ public class Parser { // default main). FunNode main = _code.link(_code._main); StopNode stop = _code._stop; + // Gather an explicit main + FunNode xmain = null; + for( Node n : stop._inputs ) + if( n instanceof ReturnNode ret && "main".equals(ret.fun()._name) ) + if( xmain != null ) throw Utils.TODO(); + else xmain = ret.fun(); + if( main.ret().expr()._type==Type.TOP && main.uctrl()==null ) { // Kill an empty default main; so it does not attempt to put a // "main" in any final ELF file main.setDef(1,XCTRL); // Delete default start input stop.delDef(stop._inputs.find(main.ret())); + if( xmain != null ) + _code.setMain(xmain); + } else { // We have a non-empty default main. - // Check for an explicit main - for( Node n : stop._inputs ) - if( n instanceof FunNode fun && fun._name.equals("main") ) - // Found an explicit "main" AND we have a default "main" - throw error("Cannot define both an explicit main and a default main"); + if( xmain != null ) + // Found an explicit "main" AND we have a default "main" + throw error("Cannot define both an explicit main and a default main"); main._name = "main"; } @@ -540,9 +548,8 @@ public class Parser { // Parse a conditional expression, merging results. private Node parseTrinary( Node pred, String fside ) { - pred.keep(); - // IfNode takes current control and predicate + pred.keep(); Node ifNode = new IfNode(ctrl(), pred).peephole(); // Setup projection nodes Node ifT = new CProjNode(ifNode. keep(), 0, "True" ).peephole().keep(); @@ -708,7 +715,7 @@ public class Parser { // Type is sane if( et!=Type.BOTTOM && (!et.shallowISA(t) || !et.accessISA(t)) ) - expr = peep(new CastNode(t,null,expr)); + expr = peep(new CastNode(t.isConstant() ? t : t.widen(),null,expr)); return expr; } @@ -822,7 +829,7 @@ public class Parser { // Lift type to the declaration. This will report as an error later if // we cannot lift the type. if( !lift._type.isa(t) ) - lift = peep(new CastNode(t,null,lift)); + lift = peep(new CastNode(t.widen(),null,lift)); // Define a new name if( !_scope.define(name,t,xfinal || fld_final,lift, loc) ) throw error("Redefining name '" + name + "'", loc); @@ -1050,49 +1057,100 @@ public class Parser { } private Node parseBitwise() { - Node lhs = parseComparison(); + Node lhs = parseEquality(); while( true ) { if( false ) ; else if( matchOp('&') ) lhs = new AndNode(loc(),lhs,null); else if( matchOp('|') ) lhs = new OrNode(loc(),lhs,null); else if( match ("^") ) lhs = new XorNode(loc(),lhs,null); else break; - lhs.setDef(2,parseComparison()); + lhs.setDef(2,parseEquality()); lhs = peep(lhs); } return lhs; } + + + /** + * Parse an eq/ne expression + */ + private Node parseEquality() { + Node lhs = parseComparison(); + while( true ) { + boolean eq = false; + if( match("==") ) eq = true; + else if( !match("!=") ) break; + lhs.keep(); + Node rhs = parseComparison(); + lhs = peep(new BoolNode.EQ(lhs.unkeep(),rhs).widen()); + if( !eq ) lhs = peep(new NotNode(lhs)); + } + return lhs; + } + /** * Parse an expression of the form: * *
-     *     expr : additiveExpr op additiveExpr
+     *     expr : shiftExpr < shiftExpr <= shiftExpr...
+     *     expr : shiftExpr > shiftExpr >= shiftExpr...
      * 
* @return an comparator expression {@link Node}, never {@code null} */ private Node parseComparison() { - var lhs = parseShift(); + Node lhs = parseShift(); + int dir = 0; + while( true ) { - int idx=0; boolean negate=false; - // Test for any local nodes made, and "keep" lhs during peepholes + int dir0; if( false ) ; - else if( match("==") ) { idx=2; lhs = new BoolNode.EQ(lhs, null); } - else if( match("!=") ) { idx=2; lhs = new BoolNode.EQ(lhs, null); negate=true; } - else if( match("<=") ) { idx=2; lhs = new BoolNode.LE(lhs, null); } - else if( match("<" ) ) { idx=2; lhs = new BoolNode.LT(lhs, null); } - else if( match(">=") ) { idx=1; lhs = new BoolNode.LE(null, lhs); } - else if( match(">" ) ) { idx=1; lhs = new BoolNode.LT(null, lhs); } + else if( match("<=" ) ) dir0 = -1; + else if( match(">=" ) ) dir0 = -2; + else if( match("<" ) ) dir0 = 1; + else if( match(">" ) ) dir0 = 2; else break; - // Peepholes can fire, but lhs is already "hooked", kept alive - lhs.setDef(idx,parseShift()); - lhs = peep(lhs.widen()); - if( negate ) // Extra negate for != - lhs = peep(new NotNode(lhs)); + lhs.keep(); + // Check and record direction + if( dir==0 ) { + dir = Math.abs(dir0); + Node rhs = parseShift(); + lhs = makeCompBool(dir0,lhs.unkeep(),rhs); // Convert to a bool + } else if( dir == Math.abs(dir0) ) { + // e0 < lhs < ??? + Node ifNode = new IfNode(ctrl(), lhs).peephole(); + Node ifT = new CProjNode(ifNode. keep(), 0, "True" ).peephole(); + Node ifF = new CProjNode(ifNode.unkeep(), 1, "False").peephole(); + // False side does nothing + ScopeNode fScope = _scope.dup(); + fScope.ctrl(ifF); + // True side executes next part of range + ctrl(ifT); + _scope.addGuards(ifT,lhs,false); + Node rhs = parseShift(); + _scope.removeGuards(ifT); // TODO: I think should remain true as long as possible + Node next = makeCompBool(dir0, lhs, rhs).keep(); + // Merge result + RegionNode r = ctrl(_scope.mergeScopes(fScope, loc())); + assert next._type.meet(lhs._type).isa( TypeInteger.BOOL ); + lhs = peep(new PhiNode("",TypeInteger.BOOL,r,next.unkeep(),lhs.unkeep())); + r.peephole(); + } else { + throw error("Mixing relational directions in a chained relational test"); + } } return lhs; } + private Node makeCompBool( int dir0, Node lhs, Node rhs ) { + // Convert to a bool + if( Math.abs(dir0)==2 ) // Swap direction + { Node tmp = lhs; lhs = rhs; rhs = tmp; } + lhs = peep(dir0 < 0 ? new BoolNode.LE(lhs,rhs) : new BoolNode.LT(lhs,rhs)); + return peep(lhs.widen()); + } + + /** * Parse an additive expression * @@ -1523,6 +1581,8 @@ public class Parser { Type tf = f._t; if( tf instanceof TypeMemPtr ftmp && ftmp.isFRef() ) tf = ftmp.makeFrom(((TypeMemPtr)(TYPES.get(ftmp._obj._name)))._obj); + if( base.isAry() && tf instanceof TypeConAry con ) + tf = con.elem(); expr.keep(); // Field offset; fixed for structs, computed for arrays @@ -1685,7 +1745,6 @@ public class Parser { // Into the call CallNode call = (CallNode)new CallNode(loc(), args.asAry()).peephole(); - // Post-call setup CallEndNode cend = (CallEndNode)new CallEndNode(call).peephole(); call.peephole(); // Rerun peeps after CallEnd, allows early inlining diff --git a/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java b/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java index 9bf1aa61..f3d3dee3 100644 --- a/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java +++ b/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java @@ -9,6 +9,7 @@ import com.seaofnodes.simple.print.*; import com.seaofnodes.simple.type.*; import com.seaofnodes.simple.util.Ary; import com.seaofnodes.simple.util.SB; +import com.seaofnodes.simple.util.Utils; import java.io.IOException; import java.util.*; @@ -33,7 +34,6 @@ public class CodeGen { Export, // Export } public Phase _phase; - // --------------------------- // Compilation source code public final String _src; @@ -117,7 +117,7 @@ public class CodeGen { // are structurally equal. public final HashMap _gvn = new HashMap<>(); - // + // Source of unique function indices private int _fidx =0; public TypeFunPtr makeFun( TypeFunPtr fun ) { int fidx = _fidx++; @@ -125,23 +125,36 @@ public class CodeGen { return fun.makeFrom(fidx); } // Signature for MAIN - public final TypeFunPtr _main; - // Reverse from a constant function pointer to the IR function being called - public FunNode link( TypeFunPtr tfp ) { - assert tfp.isConstant(); - return _linker.get(tfp.makeFrom(Type.BOTTOM)); + public TypeFunPtr _main; + public void setMain(FunNode main) { + _main = main.sig(); + link(main); + } + // Reverse from a constant function pointer to the IR function being called. + // Error to call with a non-constant TFP + public FunNode link( TypeFunPtr tfp ) { return link(tfp.fidx()); } + // Read-only diagnostic lookup; preserve stale entries. + public FunNode _link(TypeFunPtr tfp) { return _link(tfp.fidx()); } + public FunNode _link(int fidx) { return _linker.atX(fidx); } + // Return the FunNode from a fidx, cleaning up dead entries. + public FunNode link( int fidx ) { + FunNode fun =_linker.atX(fidx); + if( fun!=null && fun.isDead() ) { + _linker.setX(fidx,null); fun = null; } + return fun; } // Insert linker mapping from constant function signature to the function // being called. public void link(FunNode fun) { - _linker.put(fun.sig().makeFrom(Type.BOTTOM),fun); + int fidx = fun.sig().fidx(); + _linker.setX(fidx,fun); } // "Linker" mapping from constant TypeFunPtrs to heads of function. These // TFPs all have exact single fidxs and their return is wiped to BOTTOM (so // the return is not part of the match). - private final HashMap _linker = new HashMap<>(); + final Ary _linker = new Ary<>(FunNode.class); // Parser object public final Parser P; @@ -178,60 +191,15 @@ public class CodeGen { _phase = Phase.Opto; long t0 = System.currentTimeMillis(); - // Pessimistic peephole optimization on a worklist - _iter.iterate(this); - - // OPTIMISTIC PASS GOES HERE - - // Not really a true optimistic pass, but look for unlinked functions. - // This can be removed, which may trigger another round of pessimistic. - // This is the point where we flip from a virtual Call Graph (any call - // can call any function) to having a correct (but conservative) CG. - int progress = 0; - while( progress != _start.nOuts() ) { - progress = _start.nOuts(); - FunNode main = link(_main); - for( int i=0; i<_start.nOuts(); i++ ) { - Node use = _start.out(i); - if( use instanceof FunNode fun && - fun.nIns()==2 && fun.in(1)==_start && fun != main && !fun.hasPtr() && - (fun._name==null || fun._name.startsWith("sys.")) ) { - add(fun).setDef(1,Parser.XCTRL); - addAll(fun._outputs); - i--; - } - } - _iter.iterate(this); - } - - // Freeze field sizes; do struct layouts; convert field offsets into - // constants. - for( int i=0; i<_start.nOuts(); i++ ) { - Node use = _start.out(i); - if( use instanceof ConFldOffNode off ) { - TypeMemPtr tmp = (TypeMemPtr) Parser.TYPES.get(off._name); - off.subsume( off.asOffset(tmp._obj) ); - i--; - } - } - _iter.iterate(this); - - // To help with testing, sort StopNode returns by NID - Arrays.sort(_stop._inputs._es,0,_stop.nIns(),(x,y) -> x._nid - y._nid ); + Opto.opto(this); _tOpto = (int)(System.currentTimeMillis() - t0); - - // TODO: - // Optimistic - // TODO: - // loop unroll, peel, RCE, etc if( _obs != null ) _obs.phase("Opto"); return this; } public N add( N n ) { return _iter.add(n); } public void addAll( Ary ary ) { _iter.addAll(ary); } - // --------------------------- // Last check for bad programs public int _tTypeCheck; diff --git a/src/main/java/com/seaofnodes/simple/codegen/Encoding.java b/src/main/java/com/seaofnodes/simple/codegen/Encoding.java index 5099c02a..b5a8e148 100644 --- a/src/main/java/com/seaofnodes/simple/codegen/Encoding.java +++ b/src/main/java/com/seaofnodes/simple/codegen/Encoding.java @@ -193,12 +193,16 @@ public class Encoding implements com.seaofnodes.isa.CodeSink { rpos.put(_code._start.loop(),rpo); BitSet visit = _code.visit(); rpo.add(_code._stop); + FunNode main = _code.link(_code._main); for( Node n : _code._start._outputs ) - if( n instanceof FunNode fun ) { + if( n instanceof FunNode fun && fun != main ) { int x = rpo._len; _rpo_cfg(fun, visit, rpos ); assert rpo.at(x) instanceof ReturnNode; } + // Do any main function last... so it lands at offset 0 in the RPO + if( main!=null ) + _rpo_cfg(main, visit, rpos ); rpo.add(_code._start); // Reverse in-place diff --git a/src/main/java/com/seaofnodes/simple/codegen/Opto.java b/src/main/java/com/seaofnodes/simple/codegen/Opto.java new file mode 100644 index 00000000..cd52aadd --- /dev/null +++ b/src/main/java/com/seaofnodes/simple/codegen/Opto.java @@ -0,0 +1,267 @@ +package com.seaofnodes.simple.codegen; + +import com.seaofnodes.simple.Parser; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.*; +import com.seaofnodes.simple.util.Ary; +import java.util.Arrays; + +// Optimistic Algorithm +abstract public class Opto { + + // Optimistic analysis - extended SCCP + + // Start all Types at TOP, and propagate changes until stable. Unlike a + // normal Sparse Conditional Constant Propagation, this version is + // interprocedural, computing effectively CFA0 in linear time using the + // normal SCCP algorithm. + + // This algo also builds a Call Graph; as Calls become reachable (CONTROL + // not TOP nor XCONTROL), they "link" against the reaching function + // pointers - adding edges from the Call to the Fun, and from the Return to + // the CallEnd. This allows the normal algorithm to use the normal edge + // propagation rules as function argument types stabilize. In the end, we + // get a fairly precise set of Call Graph edges between CallNodes and + // FunNodes. + public static void opto(CodeGen code) { + + // Pessimistic peephole optimization on a worklist - this completes + // whatever peepholes can run after parsing. + code._iter.iterate(code); + + // Reset Types before running the worklist algorithm + Ary oldTypes = new Ary<>(Type.class); // Used for asserts only + resetToTop(code,oldTypes); + + // The whole-world assumption: we use it if compiling `main`, and not otherwise. + // The assumption is no unknown callers into functions: + // - during or past an Opto phase (but not before, since parse through + // pessimistic must assume somebody calls an unknown function which + // calls everybody). + // - Have a `main` to start tracing the Call Graph from + // - - True for most test cases + // - - False for lacking a main; we assume the linker will call all public functions + + // True if we can make the "whole world" assumption, which means we are + // compiling the program entry: `main`. + boolean wholeWorld = code.link(code._main) != null; + + + // If wholeWorld, remove the Start inputs to functions - they are not + // called unless they get linked (hence go dead and can be removed). + // If not wholeWorld, keep only public methods (and not the std lib). + unlinkStart(wholeWorld,code); + + + // OPTIMISTIC INTERPROCEDURAL SCCP + sccp(code, oldTypes); + + // After SCCP add everything changed to the worklist and see if + // peepholes can make more progress. + moveChangesToWorklist(code, oldTypes); + + // Progress with improved types. E.g. since we have a full Call Graph + // here, we might do better inlining. + code._iter.iterate(code); + + // TODO: + // loop unroll, peel, RCE, etc + + // Freeze field sizes; do struct layouts; convert field offsets into + // constants. + fieldSizes(code); + // Propagate field size constants + code._iter.iterate(code); + + // Throw away the Call Graph + + // The remaining passes assume all calls are unlinked; i.e. we are + // throwing away the Call Graph here. Functions only reachable from + // internal calls need to be re-hooked to stop/start less they go dead. + removeCallGraph(code); + + // To help with testing, sort StopNode Returns by NID + Arrays.sort(code._stop._inputs._es,0,code._stop.nIns(),(x,y) -> x._nid - y._nid ); + } + + // Reset Types before running the worklist algorithm + private static void resetToTop(CodeGen code, Ary oldTypes ) { + code._start.walk( x -> { + oldTypes.setX(x._nid,x._type); // Record original types for asserts + x._type = Type.TOP; // Reset all Nodes to TOP + code._iter.add(x); // Visit everybody at least once; most Nodes produce better than TOP + // Unlink all existing (conservative) linkages. + if( x instanceof CallNode call ) + call.unlink_all(); + return null; + } ); + } + + + // If wholeWorld, remove the Start inputs to functions - they are not + // called unless they get linked (hence go dead and can be removed). If + // not wholeWorld, keep only public methods (and not the std lib). + private static void unlinkStart(boolean wholeWorld, CodeGen code) { + for( FunNode fun : code._linker ) { + if( fun != null && !fun.isDead() && !funIsPublic(code,wholeWorld,fun) ) { + assert fun.in(1)==code._start; // Start always in slot 1 + fun.removeDeadPath(1); + // By same logic, remove stop->return linkage, without + // remove the (now dead) ReturnNode; it awaits in limbo + // for the opto phase to link to some valid call + code._stop._inputs.del(code._stop._inputs.find(fun.ret())); + fun.ret().delUse(code._stop); + } + } + } + + // Function is public (callable from Start directly). + // - Always true for main + // - True for function addresses used as values + // - Otherwise false for stdlib or anonymous functions + // - Named functions use `!wholeWorld` + private static boolean funIsPublic( CodeGen code, boolean wholeWorld, FunNode fun ) { + // Always true for main + if( fun.sig().fidx() == code._main.fidx() ) return true; + // No escape analysis yet: a surviving address may be called from outside. + if( fun.hasPtr() ) return true; + // Never true for stdlib or anonymous functions + if( fun._name == null || fun._name.startsWith("sys.") ) + return false; + // Named functions (and not stdlib) are callable if not whole-world. + return !wholeWorld; + } + + // As part of building a CallGraph, when opto finds a function ptr flowing + // into a Call, link the Call and Fun. + private static void linkCG(CodeGen code, TypeFunPtr tfp, CallNode call) { + if( tfp.nargs() != call.nargs() ) return; // Error calls hit this + for( long fidxs=tfp.fidxs(); fidxs!=0; fidxs=TypeFunPtr.nextFIDX(fidxs) ) { + int fidx = Long.numberOfTrailingZeros(fidxs); + FunNode fun = code.link(fidx); + // null here means an external function; i.e. this Call + // calls to an outside library and all its arguments escape. + if( fun != null && !call.linked(fun) ) { + call.link( fun ); + code._iter.add(fun); + code._iter.addAll(fun._outputs); + } + } + } + + // The core SCCP algorithm + private static void sccp( CodeGen code, Ary oldTypes ) { + // Iter workList is empty at this point + // OPTIMISTIC PASS + Node n; + int count = 0; // Debug counter + while( (n = code._iter._work.pop()) != null ) { + if( n.isDead() ) continue; + count++; + Type oval = n._type, nval = n.compute(); + if( oval == nval ) continue; + assert oval.isa(nval); // Types start high and always fall + Type pesiVal = oldTypes.at(n._nid); + assert nval.isa(pesiVal); // Never fall worse than the pessimistic pass + n._type = nval; + + // If a TFP adds a new function input to a call, link to the new Fun + if( nval instanceof TypeFunPtr tfp ) { + for( Node use : n._outputs ) + if( !use._type.isHigh() && use instanceof CallNode call && call.fptr() == n ) + linkCG(code,tfp,call); + } + + // Link a Call which becomes alive + if( n instanceof CallNode call && oval.isHigh() && !nval.isHigh() && call.fptr()._type instanceof TypeFunPtr ) + linkCG(code,call.tfp(),call); + + // Since n._type changed, visit all output neighbors + code._iter.addAll(n._outputs); + n.moveDepsToWorklist(code._iter); + // Quadratic (expensive) small-step assert + assert check(code); + } + } + + // Quadratic (expensive) small-step assert + private static boolean check(CodeGen code) { + code._start.walk( x -> { + Type xval = x.compute(); + assert xval == x._type || (x._type.isa( xval ) && code._iter._work.on( x )); + return null; + }); + return true; + } + + // After SCCP add everything changed to the worklist and see if peepholes + // can make more progress. + private static void moveChangesToWorklist(CodeGen code, Ary oldTypes) { + code._start.walk( x -> { + assert x.compute() == x._type; // Hit the fixed point + assert x._nid >= oldTypes._len || x._type.isa(oldTypes.at(x._nid)); // Hit at least the bottom-up type + code._iter.add(x); + return null; + }); + } + + // Freeze field sizes; do struct layouts; convert field offsets into + // constants. + private static void fieldSizes( CodeGen code ) { + for( int i=0; i { + // Unlink all existing (conservative) linkages. + if( x instanceof CallNode call ) { + for( Node y : call._outputs ) { + // Keep function alive and hooked to Start so it gets + // codegen'd. Function is callable by this call via + // TFP, although perhaps not by any other means. + if( y instanceof FunNode fun && !(fun.in(1) instanceof StartNode) ) { + ParmNode rpc = fun.rpc(); + if( rpc==null ) // Ensure valid RPC + rpc = makeRPC(fun); + // Insert a hook to Start and Stop + fun.insertDef(1,code._start); + for( Node use : fun._outputs ) + if( use instanceof ParmNode parm ) + parm.insertDef(1,ConstantNode.make(parm._type).peephole()); + code._stop.addDef(fun.ret()); + } + } + call.unlink_all(); + } + return null; + } ); + + } + + // Make a valid Parm RPC. + // First make sure a valid RPC; single-call into multi-fun will have each + // function having a single call site, so the RPC becomes a constant and + // folds - but since multiple targets, the Call never inlines. Recreate a + // valid RPC so codegen (and Eval2) understands the calling convention. + private static ParmNode makeRPC( FunNode fun ) { + ParmNode rpc = new ParmNode("$rpc",0,fun.ret().rpc()._type,fun); + for( int i=1; i _failed = new IdentityHashMap<>(); + // Loop Phis get one chance to color after only cold self-conflict splits. + // If the same Phi self-conflicts again, split its hot def/backedge also. + private final IdentityHashMap _deferredLoopSelf = new IdentityHashMap<>(); void fail( LRG lrg ) { assert lrg.leader(); _failed.put(lrg,""); @@ -341,6 +344,7 @@ public class RegAlloc { rclass.push(rmask); } + // Self conflicts require Phis (or two-address). // Insert a split after every def. boolean splitSelfConflict( byte round, LRG lrg ) { @@ -348,6 +352,19 @@ public class RegAlloc { Node[] conflicts = lrg._selfConflicts.keySet().toArray(new Node[0]); Arrays.sort(conflicts, (x,y) -> x._nid - y._nid ); + // First encounter with a loop Phi: try only cold splits this round. + // Remember the Phi across rounds so a persistent self-conflict forces + // the hot def/backedge splits on the next encounter. + IdentityHashMap deferred = new IdentityHashMap<>(); + for( Node def : conflicts ) { + if( def instanceof PhiNode phi && phi.region() instanceof LoopNode ) + deferLoopSelf(phi,deferred); + for( Node use : def._outputs ) + if( use instanceof PhiNode phi && phi.region() instanceof LoopNode && + phi._inputs.find(def)==2 ) + deferLoopSelf(phi,deferred); + } + // For all conflicts for( Node def : conflicts ) { assert lrg(def)==lrg; // Might be conflict use-side @@ -356,6 +373,7 @@ public class RegAlloc { for( int i=0; i loop.idepth() ) ) || (use instanceof MachNode mach && mach.twoAddress()!=0 && use.in(mach.twoAddress())==def) ) insertBefore( use, use._inputs.find(def), "use/self/use",round,lrg ); @@ -364,11 +382,13 @@ public class RegAlloc { // shared with another Phi: otherwise the shared input keeps the // conflicting live ranges joined, even after splitting the entry. if( def instanceof PhiNode phi && !(def instanceof ParmNode) ) { - SplitNode split = makeSplit("def/self",round,lrg); - insertAfterAndReplace(split,def,false); - if( split.nOuts()==0 ) - split.killOrdered(); - for( int i=1; i deferred) { + if( !_deferredLoopSelf.containsKey(phi) ) { + _deferredLoopSelf.put(phi,""); + deferred.put(phi,""); + } + } + private static boolean sharedPhiInput(PhiNode phi, int i) { for( Node use : phi.in(i)._outputs ) diff --git a/src/main/java/com/seaofnodes/simple/node/AddFNode.java b/src/main/java/com/seaofnodes/simple/node/AddFNode.java index fd713156..4ad02dbb 100644 --- a/src/main/java/com/seaofnodes/simple/node/AddFNode.java +++ b/src/main/java/com/seaofnodes/simple/node/AddFNode.java @@ -1,35 +1,29 @@ package com.seaofnodes.simple.node; - import com.seaofnodes.simple.type.Type; import com.seaofnodes.simple.type.TypeFloat; +import java.util.BitSet; -public class AddFNode extends Node { - public AddFNode(Node lhs, Node rhs) { super(null, lhs, rhs); } +public class AddFNode extends ArithFNode { + public AddFNode(Node lhs, Node rhs) { super(lhs, rhs); } @Override public String label() { return "AddF"; } - @Override protected String format() { return "(%1+%2)"; } + @Override public String glabel() { return "+"; } - @Override - public Type compute() { - if (in(1)._type instanceof TypeFloat i0 && - in(2)._type instanceof TypeFloat i1) { - if (i0.isConstant() && i1.isConstant()) - return TypeFloat.constant(i0.value()+i1.value()); - } - return in(1)._type.meet(in(2)._type); - } + @Override double doOp( double x, double y ) { return x+y; } @Override public Node idealize() { - Node lhs = in(1); - Type t2 = in(2)._type; - // Add of 0. + Type t2 = in(2)._type; if ( t2.isConstant() && t2 instanceof TypeFloat i && i.value()==0 ) - return lhs; + return in(1); + + // Move constants to RHS: con+arg becomes arg+con + if ( in(1)._type.isConstant() && !t2.isConstant() ) + return swap12(); return null; } diff --git a/src/main/java/com/seaofnodes/simple/node/AddNode.java b/src/main/java/com/seaofnodes/simple/node/AddNode.java index dfc7d7b3..2bbe1053 100644 --- a/src/main/java/com/seaofnodes/simple/node/AddNode.java +++ b/src/main/java/com/seaofnodes/simple/node/AddNode.java @@ -139,7 +139,7 @@ public class AddNode extends ArithNode { * dep can make progress. */ static PhiNode pcon(Node op, Node dep) { - return op instanceof PhiNode phi && phi.allCons(dep) ? phi : null; + return op instanceof PhiNode phi && !(phi instanceof ParmNode) && phi.allCons(dep) ? phi : null; } // Compare two off-spine nodes and decide what order they should be in. diff --git a/src/main/java/com/seaofnodes/simple/node/ArithFNode.java b/src/main/java/com/seaofnodes/simple/node/ArithFNode.java new file mode 100644 index 00000000..dafba626 --- /dev/null +++ b/src/main/java/com/seaofnodes/simple/node/ArithFNode.java @@ -0,0 +1,30 @@ +package com.seaofnodes.simple.node; + +import com.seaofnodes.print.ExprPrinter; + +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeFloat; + +public abstract class ArithFNode extends Node { + public ArithFNode(Node lhs, Node rhs) { super(null, lhs, rhs); } + + @Override protected ExprPrinter _print1(ExprPrinter p) { + return p.open().n(in(1)).p(glabel()).n(in(2)).close(); + } + + abstract double doOp(double x, double y); + + @Override + public Type compute() { + Type t1 = in(1)._type, t2 = in(2)._type; + if( t1.isHigh() || t2.isHigh() ) + return Type.TOP; + if( t1 instanceof TypeFloat f1 && + t2 instanceof TypeFloat f2 ) { + if( f1.isConstant() && f2.isConstant() ) + return TypeFloat.constant(doOp(f1.value(),f2.value())); + } + return t1.meet(t2); + } + +} diff --git a/src/main/java/com/seaofnodes/simple/node/ArithNode.java b/src/main/java/com/seaofnodes/simple/node/ArithNode.java index 124acbd7..54290330 100644 --- a/src/main/java/com/seaofnodes/simple/node/ArithNode.java +++ b/src/main/java/com/seaofnodes/simple/node/ArithNode.java @@ -24,15 +24,15 @@ public abstract class ArithNode extends Node { // Generic airthmetic op math: high returns high; low returns low; 2 // constants fold; only 2 non-constants call specialized math. @Override - public final TypeInteger compute() { + public final Type compute() { Type t1 = in(1)._type, t2 = in(2)._type; if( t1.isHigh() || t2.isHigh() ) - return TypeInteger.TOP; + return Type.TOP; if( t1 instanceof TypeInteger x && t2 instanceof TypeInteger y ) return x.isConstant() && y.isConstant() ? con(x,y) - : doOp(x,y); + : doOp(x,y).makeWide( (byte)Math.max(x._widen,y._widen) ); return TypeInteger.BOT; } @@ -53,7 +53,7 @@ public abstract class ArithNode extends Node { if( in(1) instanceof PhiNode lhs && in(2) instanceof PhiNode rhs && lhs.nIns() >= 2 && !lhs.inProgress() && - lhs.region()==rhs.region() && + lhs.region()==rhs.region() && !(lhs.region() instanceof FunNode) && lhs.nIns()>2 && // A 1-input Phi will collapse already // Disallow with self-looping phi; these will collapse (lhs.in(2)!=lhs && rhs.in(2)!=rhs) ) { diff --git a/src/main/java/com/seaofnodes/simple/node/CProjNode.java b/src/main/java/com/seaofnodes/simple/node/CProjNode.java index 1225de31..c62de840 100644 --- a/src/main/java/com/seaofnodes/simple/node/CProjNode.java +++ b/src/main/java/com/seaofnodes/simple/node/CProjNode.java @@ -34,7 +34,7 @@ public class CProjNode extends CFGNode { @Override public Type compute() { Type t = ctrl()._type; - return t instanceof TypeTuple tt ? tt._types[_idx] : Type.BOTTOM; + return t instanceof TypeTuple tt ? tt._types[_idx] : (t.isHigh() ? Type.TOP : Type.BOTTOM); } @Override diff --git a/src/main/java/com/seaofnodes/simple/node/CallEndNode.java b/src/main/java/com/seaofnodes/simple/node/CallEndNode.java index e83e5cba..115f70c6 100644 --- a/src/main/java/com/seaofnodes/simple/node/CallEndNode.java +++ b/src/main/java/com/seaofnodes/simple/node/CallEndNode.java @@ -40,16 +40,23 @@ public class CallEndNode extends CFGNode implements MultiNode { @Override public Type compute() { - if( !(in(0) instanceof CallNode call) ) + if( !(in(0) instanceof CallNode call) || call._type != Type.CONTROL ) return TypeTuple.RET.dual(); - Type ret = Type.BOTTOM; - if( addDep(call.fptr())._type instanceof TypeFunPtr tfp ) { + // Mid-fold, just take the one single callers' return type + if( _folding ) return in(1)._type; + // Grab the TFP and use the functions declared return type. + Type ftype = addDep(call.fptr())._type; + Type ret = ftype.isHigh() ? Type.TOP : Type.BOTTOM; + if( ftype instanceof TypeFunPtr tfp ) { ret = tfp.ret(); // Here, if I can figure out I've found *all* callers, then I can meet // across the linked returns and join with the function return type. - if( tfp.isConstant() && nIns()>1 ) { - assert nIns()==2; // Linked exactly once for a constant - ret = ((TypeTuple)in(1)._type).ret(); // Return type + if( 1+tfp.nfcns() == nIns() ) { // A linked function for every concrete function + ret = Type.TOP; + for( int i=1; i _print1(ExprPrinter p) { if( _con instanceof TypeFunPtr tfp && tfp._isConstant() && tfp.notNull() ) { - FunNode fun = CodeGen.CODE.link(tfp); + FunNode fun = CodeGen.CODE._link(tfp); if( fun!=null && fun._name != null ) return p.p("{ ").p(fun._name).p("}"); } diff --git a/src/main/java/com/seaofnodes/simple/node/DivFNode.java b/src/main/java/com/seaofnodes/simple/node/DivFNode.java index 149499f9..0d037a30 100644 --- a/src/main/java/com/seaofnodes/simple/node/DivFNode.java +++ b/src/main/java/com/seaofnodes/simple/node/DivFNode.java @@ -1,26 +1,18 @@ package com.seaofnodes.simple.node; - import com.seaofnodes.simple.type.Type; import com.seaofnodes.simple.type.TypeFloat; +import java.util.BitSet; -public class DivFNode extends Node { - public DivFNode(Node lhs, Node rhs) { super(null, lhs, rhs); } +public class DivFNode extends ArithFNode { + public DivFNode(Node lhs, Node rhs) { super(lhs, rhs); } @Override public String label() { return "DivF"; } - @Override protected String format() { return "(%1/%2)"; } + @Override public String glabel() { return "/"; } - @Override - public Type compute() { - if (in(1)._type instanceof TypeFloat i0 && - in(2)._type instanceof TypeFloat i1) { - if (i0.isConstant() && i1.isConstant()) - return TypeFloat.constant(i0.value()/i1.value()); - } - return in(1)._type.meet(in(2)._type); - } + @Override double doOp( double x, double y ) { return x/y; } @Override public Node idealize() { diff --git a/src/main/java/com/seaofnodes/simple/node/FunNode.java b/src/main/java/com/seaofnodes/simple/node/FunNode.java index e7d6c3a6..70e1c200 100644 --- a/src/main/java/com/seaofnodes/simple/node/FunNode.java +++ b/src/main/java/com/seaofnodes/simple/node/FunNode.java @@ -91,14 +91,22 @@ public class FunNode extends RegionNode { // Only dead if no callers after SCCP if( unknownCallers() ) return Type.CONTROL; - return super.compute(); + Type t = Type.XCONTROL; + for (int i = 1; i < nIns(); i++) { + // Since no unknown callers, we are not main and the Start input + // will be a Tuple with XControl, so ignore it. Need to be called + // from someplace other than Start + if( !(in(i) instanceof StartNode) ) + t = t.meet(in(i)._type); + } + return t; } @Override public Node idealize() { - // Some linked path dies - Node progress = deadPath(); + // Some linked path dies, except main never kills Start + Node progress = deadPath(unknownCallers()); if( progress!=null ) { if( nIns()==3 && in(2) instanceof CallNode call ) CODE.add(call.cend()); // If Start and one call, check for inline @@ -106,8 +114,11 @@ public class FunNode extends RegionNode { } // Upgrade inferred or user-written return type to actual - if( _ret!=null && _ret._type instanceof TypeTuple tt && tt.ret() != _sig.ret() ) - throw Utils.TODO(); + if( _ret!=null && _ret._type instanceof TypeTuple tt && tt.ret() != _sig.ret() ) { + setSig(_sig.makeFrom(tt.ret())); + return this; + } + // When can we assume no callers? Or no other callers (except main)? // In a partial compilation, we assume Start gets access to any/all @@ -121,8 +132,10 @@ public class FunNode extends RegionNode { // to collapse if( unknownCallers() ) return null; - // If down to a single input, become that input - if( nIns()==2 && !hasPhi() ) { + // If folding (already inlined) down to a single input, become that input. + // Cannot collapse if not-inlining, and might not inline if call site + // calls multiple targets. + if( _folding && nIns()==2 && !hasPhi() ) { CODE.add( CODE._stop ); // Stop will remove dead path CODE.add( _ret ); // Return will compute to TOP control return in(1); // Collapse if no Phis; 1-input Phis will collapse on their own @@ -185,6 +198,14 @@ public class FunNode extends RegionNode { return in; } + // FunNodes must match signature (equivalent: no 2 FunNodes are ever GVN'able) + @Override public boolean eq( Node n ) { + return _sig == ((FunNode)n)._sig; + } + + @Override public int hash() { + return _sig.hashCode(); + } // ------------ // MachNode specifics, shared across all CPUs diff --git a/src/main/java/com/seaofnodes/simple/node/IfNode.java b/src/main/java/com/seaofnodes/simple/node/IfNode.java index da6a0cde..c96993e5 100644 --- a/src/main/java/com/seaofnodes/simple/node/IfNode.java +++ b/src/main/java/com/seaofnodes/simple/node/IfNode.java @@ -34,6 +34,7 @@ public class IfNode extends CFGNode implements MultiNode { @Override public Type compute() { // If the If node is not reachable then neither is any following Proj + assert !_inputs.isEmpty(); if (ctrl()._type != Type.CONTROL && ctrl()._type != Type.BOTTOM ) return TypeTuple.IF_NEITHER; Node pred = pred(); @@ -58,11 +59,15 @@ public class IfNode extends CFGNode implements MultiNode { // Hunt up the immediate dominator tree. If we find an identical if // test on either the true or false branch, that side wins. if( !pred()._type.isHighOrConst() ) - for( CFGNode dom = idom(), prior=this; dom!=null; prior = dom, dom = dom.idom() ) + for( CFGNode dom = idom(), prior=this; dom!=null; prior = dom, dom = dom.idom() ) { if( addDep(dom) instanceof IfNode iff && addDep(iff.pred())==pred() && prior instanceof CProjNode prj ) { setDef(1,con( prj._idx==0 ? 1 : 0 )); return this; } + if( dom instanceof RegionNode r ) + for( Node c : r._inputs ) + if( c!= null ) addDep(c); // If region loses input, idom changes + } return null; } diff --git a/src/main/java/com/seaofnodes/simple/node/LoadNode.java b/src/main/java/com/seaofnodes/simple/node/LoadNode.java index 06226df0..b3204cff 100644 --- a/src/main/java/com/seaofnodes/simple/node/LoadNode.java +++ b/src/main/java/com/seaofnodes/simple/node/LoadNode.java @@ -52,21 +52,32 @@ public class LoadNode extends MemOpNode { @Override public Type compute() { - if( ptr()._type==Type.TOP ) return Type.TOP; // Dead pointer, not a type error. - if( !(mem()._type instanceof TypeMem mem) ) - return _declaredType; // No memory yet? Declared type + Type tmem = mem()._type; + if( !(tmem instanceof TypeMem mem) ) + return tmem; // No memory yet? Assume TOP/BOT assert !_declaredType.isFRef(); // No lifting if ptr might null-check - if( err()!=null || !(ptr()._type instanceof TypeMemPtr tmp) ) - return _declaredType; // No pointer yet? Declared type - Type t = tmp._obj.field(_name)._t; - if( t instanceof TypeConAry ary ) { + Type tptr = ptr()._type; + if( err() != null ) + return _declaredType; + if( !(tptr instanceof TypeMemPtr tmp) ) + return tptr; // No pointer yet? Assume TOP/BOT + // Load field from object + Field f = tmp._obj.field(_name); + // No field? Open objects might yet get the field when falling; + // closed objects with missing field are an error. + if( f == null ) + return tmp.isHigh() ? Type.TOP : _declaredType; + Type t = f._t; + // Load member of constant array + if( t instanceof TypeConAry ary ) t = ary.elem(); // TODO: if offset is known, can peek the constant - } // Lift from declared type and memory input - t = t.join(_declaredType).join(MemMergeNode.contents(mem(),_alias,this)); + t = t.join(MemMergeNode.contents(mem(),_alias,this)); if( ptr()._type.isFinal() || _declaredType.isFinal() ) t = t.makeRO(); // Deep final applied + // Pinch between declared type + t = t.join(_declaredType); return t; } diff --git a/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java b/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java index 8d924b96..7a329117 100644 --- a/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java +++ b/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java @@ -45,6 +45,7 @@ public class MemMergeNode extends Node { if( mem instanceof ProjNode proj && proj.in(0) instanceof NewNode nnn ) { assert proj._idx==1 && nnn.field(alias)!=null; dep.addDep(nnn); + if( dep.addDep(nnn.in(0))._type.isHigh() ) return Type.TOP; return contents(nnn.mem(),alias,dep).meet(nnn.field(alias)._t.makeZero()); } // Function parameters and call results may contain arbitrary heap values. @@ -56,7 +57,6 @@ public class MemMergeNode extends Node { @Override public String label() { return "MemMerge"; } @Override public boolean isMem() { return true; } - @Override public Type compute() { return TypeMem.BOT; } @Override protected ExprPrinter _print1(ExprPrinter p) { p.p("MEM["); for( int i=1; i implements Cloneable { } // Insert the numbered input, sliding other inputs to the right - Node insertDef(int idx, Node new_def) { - _inputs.add(idx,null); - return setDef(idx,new_def); + public void insertDef(int idx, Node new_def) { + _inputs.insert(null,idx); + setDef(idx,new_def); } /** @@ -182,7 +183,7 @@ public abstract class Node extends BaseNode implements Cloneable { // Remove node 'use' from 'def's (i.e. our) output list, by compressing the list in-place. // Return true if the output list is empty afterward. // Error is 'use' does not exist; ok for 'use' to be null. - protected boolean delUse( Node use ) { + public boolean delUse( Node use ) { _outputs.del(_outputs.find(use)); moveDepsToWorklist(); // User-count and anti-dependence queries can now change. return _outputs.isEmpty(); @@ -213,8 +214,11 @@ public abstract class Node extends BaseNode implements Cloneable { while( nIns()>0 ) { // Set all inputs to null, recursively killing unused Nodes Node old_def = _inputs.removeLast(); // Revisit neighbor because removed use - if( old_def != null && CODE.add(old_def).delUse(this) ) - old_def.kill(); // If we removed the last use, the old def is now dead + if( old_def != null ) { + if( CODE.add(old_def).delUse(this) ) + old_def.kill(); // If we removed the last use, the old def is now dead + old_def.moveDepsToWorklist(); // Use-count changes can enable distant rewrites. + } } assert isDead(); // Really dead now } @@ -431,7 +435,7 @@ public abstract class Node extends BaseNode implements Cloneable { // If changing, add users to worklist. public Type setType(Type type) { Type old = _type; - assert old==null || type.isa(old); // Since _type not set, can just re-run this in assert in the debugger + assert old == null || type.isa(old) : "Monotonicity test failed"; if( old == type ) return old; _type = type; // Set _type late for easier assert debugging CODE.addAll(_outputs); @@ -499,7 +503,7 @@ public abstract class Node extends BaseNode implements Cloneable { public Node dep(int idx) { return _deps.get(idx); } /** - * Add a node to the list of dependencies. Only add it if its not an input + * Add a node to the list of dependencies. Only add it if it's not an input * or output of this node, that is, it is at least one step away. The node * being added must benefit from this node being peepholed. */ @@ -523,9 +527,10 @@ public abstract class Node extends BaseNode implements Cloneable { } // Move the dependents onto a worklist, and clear for future dependents. - public void moveDepsToWorklist( ) { - if( _deps==null ) return; - CODE.addAll(_deps); + public void moveDepsToWorklist( ) { moveDepsToWorklist(CODE._iter); } + public void moveDepsToWorklist( IterPeeps iter ) { + if( _deps == null ) return; + iter.addAll(_deps); _deps.clear(); } diff --git a/src/main/java/com/seaofnodes/simple/node/ParmNode.java b/src/main/java/com/seaofnodes/simple/node/ParmNode.java index 8b614624..95934e4b 100644 --- a/src/main/java/com/seaofnodes/simple/node/ParmNode.java +++ b/src/main/java/com/seaofnodes/simple/node/ParmNode.java @@ -2,7 +2,9 @@ package com.seaofnodes.simple.node; import com.seaofnodes.print.ExprPrinter; +import com.seaofnodes.simple.Parser; import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeMemPtr; public class ParmNode extends PhiNode { @@ -32,6 +34,25 @@ public class ParmNode extends PhiNode { // Always in-progress until we run out of unknown callers @Override public boolean inProgress() { return in(0) instanceof FunNode fun && fun.inProgress(); } + @Override + public Node idealize() { + if( !(region() instanceof FunNode) ) + return in(1); // Input has collapse to e.g. starting control. + // If function is folding, do all possible peeps + if( fun()._folding ) return super.idealize(); + + // Can upgrade minType even while in-progress + if( _minType instanceof TypeMemPtr tmp && _minType.isFRef() ) { + TypeMemPtr tmp2 = (TypeMemPtr) Parser.TYPES.get(tmp._obj._name); + if( tmp2!=null && tmp2 != _minType ) { + _minType = tmp2; + return this; + } + } + // Skip most phi optimizations on parms + return null; + } + @Override public boolean eq( Node n ) { return ((ParmNode)n)._idx==_idx && super.eq(n); } diff --git a/src/main/java/com/seaofnodes/simple/node/PhiNode.java b/src/main/java/com/seaofnodes/simple/node/PhiNode.java index af5d900b..6cfeecfe 100644 --- a/src/main/java/com/seaofnodes/simple/node/PhiNode.java +++ b/src/main/java/com/seaofnodes/simple/node/PhiNode.java @@ -15,6 +15,8 @@ public class PhiNode extends Node { // Int stays Int, Ptr stays Ptr, Control stays Control, Mem stays Mem. Type _minType; + int lattice_drop; + public PhiNode(String label, Type minType, Node... inputs) { super(inputs); _label = label; @@ -51,26 +53,44 @@ public class PhiNode extends Node { public CFGNode region() { return (CFGNode)in(0); } @Override public boolean isMem() { return _minType instanceof TypeMem; } + boolean isRPC() { return false; } @Override public Type compute() { if( !(region() instanceof RegionNode r) ) - return region()._type==Type.XCONTROL ? (_type instanceof TypeMem ? TypeMem.TOP : Type.TOP) : _type; + return region()._type==Type.XCONTROL || region()._type==Type.TOP ? (_type instanceof TypeMem ? TypeMem.TOP : Type.TOP) : _type; // During parsing Phis have to be computed type pessimistically. - if( r.inProgress() ) return _minType; + if( r.inProgress() || in(nIns()-1)==null ) + // Loop-Phis must lift to the declared type, because that is how + // the Parser keeps precise types until the loop finishes parsing. + // Similar, ParmNodes use precise minType until all calls are + // linked (post opto). + return r instanceof LoopNode || (this instanceof ParmNode) ? _minType : Type.BOTTOM; // Set type to local top of the starting type - //Type t = _minType.dual(); Type t = Type.TOP; - for (int i = 1; i < nIns(); i++) + for (int i = 1; i < nIns(); i++) { // If the region's control input is live, add this as a dependency // to the control because we can be peeped should it become dead. - if( addDep(r.in(i))._type != Type.XCONTROL ) { + Type ctrl = addDep(r.in(i))._type; + if( ctrl != Type.XCONTROL && ctrl != Type.TOP ) { if( in(i)._type==Type.BOTTOM ) return Type.BOTTOM; t = t.meet(in(i)._type); } - t = t.join( _minType ); - return t; + } + Type newt = t.join( _minType ); + + // Above-center ranges may still fall to unwidened constants. + // Widen only below-center ranges to preserve monotonicity. + if( region() instanceof LoopNode && // Only around loops + newt instanceof TypeInteger newi && + // Types changed and are falling (the optimistic case, expected to fall forever) + newi != _type ) { + if( !newi.isHigh() && !newi.isConstant() && (!(_type instanceof TypeInteger oldi) || newi._widen <= oldi._widen) ) + return newi.same_but_slightly_wider_than(_minType); + } + + return newt; } @Override @@ -79,7 +99,7 @@ public class PhiNode extends Node { return in(1); // Input has collapse to e.g. starting control. // Can upgrade minType even while in-progress if( _minType instanceof TypeMemPtr tmp && _minType.isFRef() ) { - TypeMemPtr tmp2 = (TypeMemPtr)CodeGen.CODE.P.TYPES.get(tmp._obj._name); + TypeMemPtr tmp2 = (TypeMemPtr) Parser.TYPES.get(tmp._obj._name); if( tmp2!=null && tmp2._obj != tmp._obj ) { _minType = tmp.makeFrom(tmp2._obj); return this; @@ -124,13 +144,14 @@ public class PhiNode extends Node { Node val = in(3-nullx); if( val instanceof CastNode cast ) val = cast.in(1); - if( addDep(r.idom(this)) instanceof IfNode iff && addDep(iff.pred())==val ) { + Node ridom = r.idom(this); + if( ridom instanceof IfNode iff && addDep(iff.pred())==val ) { // Must walk the idom on the null side to make sure we hit False. CFGNode idom = (CFGNode)r.in(nullx); while( idom != null && idom.nIns() > 0 && idom.in(0) != iff ) idom = idom.idom(); if( idom instanceof CProjNode proj && proj._idx==1 ) return val; - } + } else if( ridom != null ) addDep(ridom); } } diff --git a/src/main/java/com/seaofnodes/simple/node/ProjNode.java b/src/main/java/com/seaofnodes/simple/node/ProjNode.java index 26b3a522..92c6c2be 100644 --- a/src/main/java/com/seaofnodes/simple/node/ProjNode.java +++ b/src/main/java/com/seaofnodes/simple/node/ProjNode.java @@ -41,7 +41,7 @@ public class ProjNode extends Node { @Override public Type compute() { Type t = in(0)._type; - return t instanceof TypeTuple tt ? tt._types[_idx] : Type.BOTTOM; + return t instanceof TypeTuple tt ? tt._types[_idx] : t.oob(); } @Override public Node idealize() { return ((MultiNode)in(0)).pcopy(_idx); } diff --git a/src/main/java/com/seaofnodes/simple/node/RegionNode.java b/src/main/java/com/seaofnodes/simple/node/RegionNode.java index 72f0df7e..59030dee 100644 --- a/src/main/java/com/seaofnodes/simple/node/RegionNode.java +++ b/src/main/java/com/seaofnodes/simple/node/RegionNode.java @@ -38,7 +38,7 @@ public class RegionNode extends CFGNode { public Node idealize() { if( inProgress() ) return null; - Node progress = deadPath(); + Node progress = deadPath(false); if( progress!=null ) return progress; // If down to a single input, become that input @@ -84,16 +84,21 @@ public class RegionNode extends CFGNode { return null; } - Node deadPath() { + Node deadPath(boolean skipStart) { // Delete dead paths into a Region - int path = findDeadInput(); + int path = findDeadInput(skipStart ? 2 :1); if( path==0 ) return null; + // Do not delete the entry path of a loop (ok to remove the back edge // and make the loop a single-entry Region which folds away the Loop). // Folding the entry path confused the loop structure, moving the // backedge to the entry point. if( this instanceof LoopNode loop && loop.entry()==in(path) ) return null; + return removeDeadPath(path); + } + + public Node removeDeadPath(int path) { // Cannot use the obvious output iterator here, because a Phi deleting // an input might recursively delete *itself*. This shuffles the // output array, and we might miss iterating an unrelated Phi. So on @@ -102,15 +107,16 @@ public class RegionNode extends CFGNode { while( nouts != nOuts() ) { nouts = nOuts(); for( int i=0; i return f() };` return Parser.error("No defined return type", loc); + // Rather ugly way to print conflicting return types + int cnt = (ti?1:0) + (tf?1:0) + (tp||tn?1:0); + if( cnt==1 ) return null; // Uniform return type, something else errored and will report SB sb = new SB().p("No common type amongst "); if( ti ) sb.p("int and "); if( tf ) sb.p("f64 and "); diff --git a/src/main/java/com/seaofnodes/simple/node/StoreNode.java b/src/main/java/com/seaofnodes/simple/node/StoreNode.java index 603a0607..4e1d7ce3 100644 --- a/src/main/java/com/seaofnodes/simple/node/StoreNode.java +++ b/src/main/java/com/seaofnodes/simple/node/StoreNode.java @@ -165,7 +165,7 @@ public class StoreNode extends MemOpNode { Parser.ParseException err = super.err(); if( err != null ) return err; if( ptr()._type == Type.TOP ) - return null; // Dead store + return null; // This means we have an error input, report elsewhere TypeMemPtr tmp = (TypeMemPtr)ptr()._type; if( (tmp._ro || tmp._obj.field(_name)._final) && !_init ) return Parser.error("Cannot modify final field '"+_name+"'",_loc); diff --git a/src/main/java/com/seaofnodes/simple/node/SubFNode.java b/src/main/java/com/seaofnodes/simple/node/SubFNode.java index 2d218a03..3fc4f7ca 100644 --- a/src/main/java/com/seaofnodes/simple/node/SubFNode.java +++ b/src/main/java/com/seaofnodes/simple/node/SubFNode.java @@ -1,35 +1,25 @@ package com.seaofnodes.simple.node; - import com.seaofnodes.simple.type.Type; import com.seaofnodes.simple.type.TypeFloat; +import java.util.BitSet; -public class SubFNode extends Node { - public SubFNode(Node lhs, Node rhs) { super(null, lhs, rhs); } +public class SubFNode extends ArithFNode { + public SubFNode(Node lhs, Node rhs) { super(lhs, rhs); } @Override public String label() { return "SubF"; } - @Override protected String format() { return "(%1-%2)"; } + @Override public String glabel() { return "-"; } - @Override - public Type compute() { - if (in(1)._type instanceof TypeFloat i0 && - in(2)._type instanceof TypeFloat i1) { - if (i0.isConstant() && i1.isConstant()) - return TypeFloat.constant(i0.value()-i1.value()); - } - return in(1)._type.meet(in(2)._type); - } + @Override double doOp( double x, double y ) { return x-y; } @Override public Node idealize() { - Node lhs = in(1); - Type t2 = in(2)._type; - // Sub of 0. + Type t2 = in(2)._type; if ( t2.isConstant() && t2 instanceof TypeFloat i && i.value()==0 ) - return lhs; + return in(1); return null; } diff --git a/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java b/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java index 7b0122ce..840a95ec 100644 --- a/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java +++ b/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java @@ -15,12 +15,10 @@ public class ToFloatNode extends Node { @Override public Type compute() { + if( in(1)._type.isHigh() ) return TypeFloat.F64.dual(); if( in(1)._type == Type.NIL ) return TypeFloat.FZERO; - if (in(1)._type instanceof TypeInteger i0 ) { - if( i0.isHigh() ) return TypeFloat.F64.dual(); - if( i0.isConstant() ) - return TypeFloat.constant(i0.value()); - } + if( in(1)._type instanceof TypeInteger i0 && i0.isConstant() ) + return TypeFloat.constant(i0.value()); return TypeFloat.F64; } diff --git a/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java b/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java index 1cda4787..afbbd3bf 100644 --- a/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java +++ b/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java @@ -21,6 +21,7 @@ public class SetARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { + // Using RM==RN==31 implies a *zero* value, not R31. int body = Arm64.cset(Arm64.OP_CSET,0b11111, Arm64.make_condition(_bop), 0b011111, enc.reg(this)); enc.add4(body); } diff --git a/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java b/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java index 9faf1d40..32c1e2fc 100644 --- a/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java +++ b/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java @@ -239,7 +239,9 @@ public class arm extends Machine { if( idx-2-fcnt < cargs.length ) return cargs[idx-2-fcnt]; } - throw Utils.TODO(); // Pass on stack slot + // Pass on stack slot (8 and higher) + if( maxArgSlot>0 ) throw Utils.TODO(); + return new RegMask(MAX_REG + 1 + (idx - 2)); } // Return the max stack slot used by this signature, or 0 diff --git a/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java b/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java index 22dba099..adf21848 100644 --- a/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java +++ b/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java @@ -50,6 +50,9 @@ public abstract class MemOpRISC extends MemOpNode implements MachNode { if( _declaredType == TypeInteger.BOOL) func3=4; // LBU if( _declaredType == TypeInteger.U16 ) func3=5; // LHU if( _declaredType == TypeInteger.U32 ) func3=6; // LWU + if( _declaredType instanceof TypeInteger ti ) { + if( -128 <= ti._min && ti._max < 128 ) func3 = 0; // LB + } // float if( _declaredType == TypeFloat.F32) func3 = 2; // fLW fSW diff --git a/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java b/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java index 533d5652..864c1b55 100644 --- a/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java +++ b/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java @@ -30,6 +30,7 @@ public class SetX86 extends MachConcreteNode implements MachNode { case "<" -> _unsigned ? 0x92 : 0x9C; // SETB /SETL case "<=" -> _unsigned ? 0x96 : 0x9E; // SETBE/SETLE case ">=" -> _unsigned ? 0x93 : 0x9D; // SETAE/SETGE + case ">" -> _unsigned ? 0x97 : 0x9F; // SETA /SETG default -> throw Utils.TODO(); }; X86.set(enc,op&15,enc.reg(this)); diff --git a/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java b/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java index 785049dc..8dc6ea47 100644 --- a/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java +++ b/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java @@ -6,7 +6,7 @@ import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.type.TypeMem; -/** Chapter 23's view of the IR; browser, transport and layout are shared. */ +/** Chapter 24's view of the IR; browser, transport and layout are shared. */ public class SimpleGraphAdapter extends GraphAdapter { @Override protected String edgeName(Node n, int i) { diff --git a/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java b/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java index 8877b310..3df1e0ea 100644 --- a/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java +++ b/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java @@ -7,7 +7,7 @@ import com.seaofnodes.simple.node.Node; import java.util.ArrayList; import java.io.IOException; -/** Chapter 23's compilation context; capture and event bookkeeping are shared. */ +/** Chapter 24's compilation context; capture and event bookkeeping are shared. */ public class SimpleGraphObserver extends GraphCapture { private CodeGen _code; public SimpleGraphObserver() { super(new SimpleGraphAdapter()); } diff --git a/src/main/java/com/seaofnodes/simple/type/Type.java b/src/main/java/com/seaofnodes/simple/type/Type.java index 3f115c3f..b9a6a1f3 100644 --- a/src/main/java/com/seaofnodes/simple/type/Type.java +++ b/src/main/java/com/seaofnodes/simple/type/Type.java @@ -264,6 +264,9 @@ public class Type /*implements Cloneable*/ { // Reverse; xmeet 2nd arg is never "is_simple" and never equal to "this". if( is_simple() ) return this.xmeet(t ); if( t.is_simple() ) return t .xmeet(this); + // Constant arrays meet their integer element types. + if( this instanceof TypeConAry tcon && t instanceof TypeInteger ti ) return tcon.ymeet(ti); + if( t instanceof TypeConAry tcon && this instanceof TypeInteger ti ) return tcon.ymeet(ti); return Type.BOTTOM; // Mixing 2 unrelated types } @@ -316,7 +319,8 @@ public class Type /*implements Cloneable*/ { } // True if this "isa" t; e.g. 17 isa TypeInteger.BOT - public boolean isa( Type t ) { return meet(t)==t; } + // Applies for pessimistic case + public boolean isa( Type t ) { return meet(t)==t; } // True if this "isa" t up to named structures public boolean shallowISA( Type t ) { return isa(t); } @@ -333,6 +337,9 @@ public class Type /*implements Cloneable*/ { // Is forward-reference public boolean isFRef() { return false; } + // Cap at limits + public Type oob() { return isHigh() ? TOP : BOTTOM; } + // ---------------------------------------------------------- // Cyclic types! Flag the start of a cyclic type by putting a sentinel in @@ -481,6 +488,7 @@ public class Type /*implements Cloneable*/ { Type _glb(boolean mem) { assert is_simple(); return Type.BOTTOM; } Type _close() { return this; } + public Type widen() { return this; } // ---------------------------------------------------------- diff --git a/src/main/java/com/seaofnodes/simple/type/TypeConAry.java b/src/main/java/com/seaofnodes/simple/type/TypeConAry.java index 84cccd12..0bc264fc 100644 --- a/src/main/java/com/seaofnodes/simple/type/TypeConAry.java +++ b/src/main/java/com/seaofnodes/simple/type/TypeConAry.java @@ -1,56 +1,62 @@ package com.seaofnodes.simple.type; -import com.seaofnodes.simple.util.Utils; import java.io.ByteArrayOutputStream; +import com.seaofnodes.simple.util.Utils; import java.util.ArrayList; /** * Represents a constant array of primitives */ -public class TypeConAry extends Type { +public abstract class TypeConAry extends Type { boolean _any; - // One of byte,short,int,long,float,double array + byte _widen; + // One of byte or int array public final A _ary; - TypeConAry( boolean any, A ary ) { super(TINT); _any = any; _ary = ary; } - public static final TypeConAry BOT = new TypeConAry(false,null).intern(); + TypeConAry( boolean any, byte widen, A ary ) { super(TCONARY); _any = any; _widen = widen; _ary = ary; } public static void gather(ArrayList ts) { - ts.add(BOT); ts.add(TypeConAryB.ABC); ts.add(TypeConAryB.ABCD); ts.add(TypeConAryI.I123); } + // Fresh, uninterned type sharing this array; xdual must not intern. + abstract TypeConAry _make(boolean any, byte widen); - @Override public String str() { return (_any?"~":"") + "[]"; } - @Override TypeConAry xdual() { - if( _ary==null ) - return new TypeConAry(!_any,null); - return this; - } + @Override TypeConAry xdual() { return _make( !_any, (byte)(3-_widen) ); } @Override Type xmeet(Type t) { - if( t instanceof TypeInteger ti ) return imeet(ti); TypeConAry ary = (TypeConAry)t; // Invariant - if( this==BOT ) return BOT; - if( ary ==BOT ) return BOT; - if( this==BOT.dual() ) return ary ; - if( ary ==BOT.dual() ) return this; - assert _ary!=ary._ary; // Already interned and this!=t + // Same base array but different? + if( _equals(ary) ) + // Return array with larger widen + return _widen >= ary._widen ? this : ary; + // Unrelated constant arrays, falls to some int range return elem().meet(ary.elem()); } - Type imeet( TypeInteger ti ) { - if( this==BOT.dual() ) return ti; - if( this==BOT ) return BOT; - Type elem = elem(); - if( !(elem instanceof TypeInteger) ) return BOTTOM; - if( ti.isHigh() && elem.isa(ti.dual()) ) - return this; - return elem.meet(ti); + + Type ymeet( TypeInteger ti ) { + // if i can isa *each* element, then maybe can keep. + // no good to i.isa(elem()) because fails the dual + for( int j=0; j extends Type { min = Math.min(min,at8(i)); max = Math.max(max,at8(i)); } - return TypeInteger.make(min,max); - } - public long at8(int idx) { throw Utils.TODO(); } - public int len() { throw Utils.TODO(); } - @Override public int log_size() { throw Utils.TODO(); } - public void write( ByteArrayOutputStream baos ) { throw Utils.TODO(); } - - @Override boolean eq(Type t) { - return t instanceof TypeConAry ary && _any==ary._any && ary._ary==null; - } - - @Override int hash() { - assert _ary==null; - return _any ? 1024 : 0; + return TypeInteger.make(min,max,_widen); } + public abstract long at8(int idx); + public abstract int len(); + @Override public abstract int log_size(); + public void write( ByteArrayOutputStream baos ) { throw Utils.TODO("Should not reach here: abstract constant array cannot be written"); } } diff --git a/src/main/java/com/seaofnodes/simple/type/TypeConAryB.java b/src/main/java/com/seaofnodes/simple/type/TypeConAryB.java index 75f08bef..095cdeca 100644 --- a/src/main/java/com/seaofnodes/simple/type/TypeConAryB.java +++ b/src/main/java/com/seaofnodes/simple/type/TypeConAryB.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.type; -import java.util.Arrays; import java.io.ByteArrayOutputStream; +import java.util.Arrays; public class TypeConAryB extends TypeConAry { - private TypeConAryB(byte[] bs) { super(false,bs); } - public static TypeConAryB make( byte[] bs ) { return new TypeConAryB(bs).intern(); } + private TypeConAryB(boolean any, byte widen, byte[] bs) { super(any,widen,bs); } + @Override TypeConAryB _make( boolean any, byte widen ) { return new TypeConAryB(any,widen,_ary); } + public static TypeConAryB make( byte[] bs ) { return new TypeConAryB(false,(byte)0,bs).intern(); } public static TypeConAryB make( String s ) { return make(s.getBytes()); } static final TypeConAryB ABC = make("abc"); static final TypeConAryB ABCD = make("abcd"); @@ -13,7 +14,7 @@ public class TypeConAryB extends TypeConAry { @Override public int len() { return _ary.length; } @Override public int log_size() { return 0; } @Override public String str() { return "[\""+new String(_ary)+"\"]"; } - @Override boolean eq(Type t) { return t instanceof TypeConAryB ary && Arrays.equals(_ary,ary._ary); } + @Override boolean eq(Type t) { return t instanceof TypeConAryB ary && _widen==ary._widen && Arrays.equals(_ary,ary._ary); } @Override int hash() { return Arrays.hashCode(_ary); } @Override public void write( ByteArrayOutputStream baos ) { baos.write(_ary,0,_ary.length); } } diff --git a/src/main/java/com/seaofnodes/simple/type/TypeConAryI.java b/src/main/java/com/seaofnodes/simple/type/TypeConAryI.java index 577de82c..b1b061de 100644 --- a/src/main/java/com/seaofnodes/simple/type/TypeConAryI.java +++ b/src/main/java/com/seaofnodes/simple/type/TypeConAryI.java @@ -3,13 +3,14 @@ package com.seaofnodes.simple.type; import java.util.Arrays; public class TypeConAryI extends TypeConAry { - private TypeConAryI(int[] bs) { super(false,bs); } - public static TypeConAryI make( int[] bs ) { return new TypeConAryI(bs).intern(); } - static final TypeConAryI I123 = make(new int[]{1,2,3}); + private TypeConAryI(boolean any, byte widen, int[] bs) { super(any,widen,bs); } + public static TypeConAryI make( int[] bs ) { return new TypeConAryI(false,(byte)0,bs).intern(); } + @Override TypeConAryI _make( boolean any, byte widen ) { return new TypeConAryI(any,widen,_ary); } + static final TypeConAryI I123 = make(new int[]{1,2,3}); @Override public long at8(int idx) { return _ary[idx]; } @Override public int len() { return _ary.length; } @Override public int log_size() { return 2; } @Override public String str() { return "[i32]"; } - @Override boolean eq(Type t) { return Arrays.equals(_ary,((TypeConAryI)t)._ary); } + @Override boolean eq(Type t) { return t instanceof TypeConAryI ary && _widen==ary._widen && Arrays.equals(_ary,ary._ary); } @Override int hash() { return Arrays.hashCode(_ary); } } diff --git a/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java b/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java index cbf06e0c..50743f69 100644 --- a/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java +++ b/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java @@ -175,8 +175,13 @@ public class TypeFunPtr extends TypeNil { public Type ret() { return _ret; } public int nargs() { return _sig.length; } public int fidx() { assert Long.bitCount(_fidxs)==1; return Long.numberOfTrailingZeros(_fidxs); } + public int nfcns() { + if( _fidxs < 0 ) return Integer.MAX_VALUE; // Infinite choices + return Long.bitCount(_fidxs); + } + // Used to walk over type structures @Override int nkids() { return _sig.length+1; } @Override Type at( int idx ) { return idx == _sig.length ? _ret : _sig[idx]; @@ -258,7 +263,7 @@ public class TypeFunPtr extends TypeNil { return tilde+fidx; } - // Usage: for( long fidxs=fidxs(); fidxs!=0; fidxs=nextFIDX(fidxs) { int fidxs = Long.numberOfTrailingZeros(fidxs); ... } + // Usage: for( long fidxs=fidxs(); fidxs!=0; fidxs=nextFIDX(fidxs) ) { int fidx = Long.numberOfTrailingZeros(fidxs); ... } public static long nextFIDX(long fidxs) { return fidxs & (fidxs-1); } } diff --git a/src/main/java/com/seaofnodes/simple/type/TypeInteger.java b/src/main/java/com/seaofnodes/simple/type/TypeInteger.java index 1d398e3b..74fbfb9f 100644 --- a/src/main/java/com/seaofnodes/simple/type/TypeInteger.java +++ b/src/main/java/com/seaofnodes/simple/type/TypeInteger.java @@ -18,24 +18,45 @@ public class TypeInteger extends Type { */ public long _min, _max; + public byte _widen; + private static final Ary FREE = new Ary<>(TypeInteger.class); - private TypeInteger(long min, long max) { super(TINT); init(min,max); } - private TypeInteger init(long min, long max) { _min = min; _max = max; return this; } - public static TypeInteger malloc(long lo, long hi) { return FREE.isEmpty() ? new TypeInteger(lo,hi) : FREE.pop().init(lo,hi); } - public static TypeInteger make(long lo, long hi) { - TypeInteger i = malloc(lo,hi); + private TypeInteger(long min, long max, byte widen) { super(TINT); init(min,max,widen); } + private TypeInteger init(long min, long max, byte widen) { + _min = min; _max = max; _widen=widen; + return this; + } + public static TypeInteger malloc(long lo, long hi, byte widen) { return FREE.isEmpty() ? new TypeInteger(lo,hi,widen) : FREE.pop().init(lo,hi,widen); } + public static TypeInteger make(long lo, long hi) { return make(lo,hi,(byte)0); } + public static TypeInteger make(long lo, long hi, byte widen) { + TypeInteger i = malloc(lo,hi,widen); TypeInteger t2 = i.intern(); return t2==i ? i : t2.free(i); } + public TypeInteger makeWide(byte widen) { + if( widen == _widen ) return this; + if( _min == Long.MIN_VALUE && _max == Long.MAX_VALUE ) + return TypeInteger.BOT; + if( _min==_max ) return this; // Leave constants always narrow + return make(_min,_max,widen); + } @Override TypeInteger free(Type t) { TypeInteger i = (TypeInteger)t; i._min = i._max = 0; + i._widen = 0; i._hash = 0; i._dual = null; FREE.push(i); return this; } + public Type same_but_slightly_wider_than( Type minType ) { + return _widen < 3 ? make(_min,_max, (byte)(_widen+1)) : minType; + } + // Force max widen + @Override public Type widen() { + return _widen==3 ? this : make(_min,_max,(byte)3); + } public static TypeInteger constant(long con) { return make(con, con); } public final static TypeInteger ZERO= make(0,0); @@ -43,20 +64,31 @@ public class TypeInteger extends Type { public final static TypeInteger TRUE= make(1,1); public final static TypeInteger TWO = make(2,2); // Shows up in some Simple tests as the starting argument - public final static TypeInteger I1 = make(-1,0); - public final static TypeInteger I8 = make(-128,127); - public final static TypeInteger I16 = make(-32768,32767); - public final static TypeInteger I32 = make(-1L<<31,(1L<<31)-1); - public final static TypeInteger BOT = make(Long.MIN_VALUE,Long.MAX_VALUE); + public final static TypeInteger I1 = make(-1,0,(byte)3); + public final static TypeInteger I8 = make(-128,127,(byte)3); + public final static TypeInteger I16 = make(-32768,32767,(byte)3); + public final static TypeInteger I32 = make(-1L<<31,(1L<<31)-1,(byte)3); + public final static TypeInteger BOT = make(Long.MIN_VALUE,Long.MAX_VALUE,(byte)3); public final static TypeInteger TOP = (TypeInteger)BOT.dual(); - public final static TypeInteger U1 = make(0,1); + public final static TypeInteger U1 = make(0,1,(byte)3); public final static TypeInteger BOOL= U1; - public final static TypeInteger U8 = make(0,255); - public final static TypeInteger U16 = make(0,65535); - public final static TypeInteger U32 = make(0,(1L<<32)-1); - - public static void gather(ArrayList ts) { ts.add(I32); ts.add(BOT); ts.add(U1); ts.add(I1); ts.add(U8); } + public final static TypeInteger U8 = make(0,255,(byte)3); + public final static TypeInteger U16 = make(0,65535,(byte)3); + public final static TypeInteger U32 = make(0,(1L<<32)-1,(byte)3); + + public final static TypeInteger FATBOOL = make(0,1,(byte)2); + + public static void gather(ArrayList ts) { + ts.add(I32); ts.add(BOT); ts.add(U1); ts.add(I1); ts.add(U8); ts.add(ZERO); ts.add(FATBOOL); + // Ranges before and after excluding zero, at each widening level. + for( byte widen=0; widen<=3; widen++ ) { + ts.add(make(0,255,widen)); + ts.add(make(1,255,widen)); + ts.add(make(-255,0,widen)); + ts.add(make(-255,-1,widen)); + } + } @Override public String str() { if( _isConstant() ) return ""+_min; @@ -95,6 +127,7 @@ public class TypeInteger extends Type { else if (-0xFFFFFFFFL <= _min && _min <= 0xFFFFFFFFL) return 2; else return 3; } + if( -128 <= _min && _max < 128 ) return 0; // 1 byte throw Utils.TODO(); } @@ -119,21 +152,18 @@ public class TypeInteger extends Type { @Override public Type xmeet(Type other) { - if( other instanceof TypeConAry ary ) return ary.imeet(this); // Invariant from caller: 'this' != 'other' and same class (TypeInteger) TypeInteger i = (TypeInteger)other; // Contract - return make(Math.min(_min,i._min), Math.max(_max,i._max)); + return make(Math.min(_min,i._min), Math.max(_max,i._max), (byte)Math.max(_widen,i._widen)); } - @Override TypeInteger xdual() { - return _min==_max ? this : malloc(_max,_min); - } + @Override TypeInteger xdual() { return malloc(_max,_min,(byte)(3-_widen)); } @Override public TypeInteger nonZero() { if( isHigh() ) return this; if( this==ZERO ) return null; // No sane answer - if( _min==0 ) return make(1,Math.max(_max,1)); // specifically good on BOOL - if( _max==0 ) return make(_min,-1); + if( _min==0 ) return make(1,Math.max(_max,1),_widen); // specifically good on BOOL + if( _max==0 ) return make(_min,-1,_widen); return this; } @Override public Type makeZero() { return ZERO; } @@ -146,8 +176,8 @@ public class TypeInteger extends Type { return isHigh() ? dual() : this; } - @Override int hash() { return Utils.fold(_min) * Utils.fold(_max); } + @Override int hash() { return Utils.fold(_min) * Utils.fold(_max) + _widen; } @Override public boolean eq( Type t ) { - return t instanceof TypeInteger i && _min==i._min && _max==i._max; + return t instanceof TypeInteger i && _min==i._min && _max==i._max && _widen==i._widen; } } diff --git a/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java b/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java index ad744c8f..9fc90544 100644 --- a/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java +++ b/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java @@ -67,6 +67,7 @@ public class TypeMemPtr extends TypeNil { public TypeMemPtr makeFrom(TypeStruct obj) { return obj==_obj ? this : make(_nil, obj, _one,_ro); } public TypeMemPtr makeNullable() { return makeFrom((byte)3); } @Override TypeMemPtr makeFrom(byte nil) { return nil==_nil ? this : make(nil, _obj, _one,_ro); } + public TypeMemPtr makeHigh() { return make((byte)0,_obj.makeHigh(),false); } private TypeMemPtr access(boolean ro) { _ro=ro; return this; } diff --git a/src/main/java/com/seaofnodes/simple/type/TypeRPC.java b/src/main/java/com/seaofnodes/simple/type/TypeRPC.java index bd5e2923..a1389540 100644 --- a/src/main/java/com/seaofnodes/simple/type/TypeRPC.java +++ b/src/main/java/com/seaofnodes/simple/type/TypeRPC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.type; +import com.seaofnodes.simple.util.Ary; import com.seaofnodes.simple.util.SB; import com.seaofnodes.simple.util.Utils; import java.util.ArrayList; @@ -13,19 +14,31 @@ public class TypeRPC extends Type { // A set of CallEndNode IDs (or StopNode); commonly just one. // Basically a sparse bit set - final HashSet _rpcs; + HashSet _rpcs; // If true, invert the meaning of the bits - final boolean _any; + boolean _any; - private TypeRPC(boolean any, HashSet rpcs) { - super(TRPC); - _any = any; - _rpcs = rpcs; + private static final Ary FREE = new Ary<>(TypeRPC.class); + private TypeRPC init(boolean any, HashSet rpcs) { _any=any; _rpcs=rpcs; return this; } + private TypeRPC() { super(TRPC); } + private static TypeRPC malloc(boolean any, HashSet rpcs) { + return (FREE.isEmpty() ? new TypeRPC() : FREE.pop()).init(any,rpcs); } private static TypeRPC make(boolean any, HashSet rpcs) { - return new TypeRPC(any,rpcs).intern(); + TypeRPC rpc = (FREE.isEmpty() ? new TypeRPC() : FREE.pop()).init(any,rpcs); + TypeRPC t2 = rpc.intern(); + return t2==rpc ? rpc : t2.free(rpc); } + @Override TypeRPC free(Type t) { + TypeRPC rpc = (TypeRPC)t; + rpc._rpcs = null; + rpc._dual = null; + rpc._hash = 0; + FREE.push(rpc); + return this; + } + @Override boolean isFree() { return _rpcs==null; } public static TypeRPC constant(int cend) { HashSet rpcs = new HashSet<>(); @@ -82,8 +95,7 @@ public class TypeRPC extends Type { return make(any,rpcs); } - @Override - Type xdual() { return new TypeRPC(!_any,_rpcs); } + @Override Type xdual() { return malloc(!_any,_rpcs); } @Override boolean _isConstant() { return !_any && _rpcs.size()==1; } @Override boolean _isGLB(boolean mem) { return true; } diff --git a/src/main/java/com/seaofnodes/simple/type/TypeStruct.java b/src/main/java/com/seaofnodes/simple/type/TypeStruct.java index f065126a..bb6ce4cb 100644 --- a/src/main/java/com/seaofnodes/simple/type/TypeStruct.java +++ b/src/main/java/com/seaofnodes/simple/type/TypeStruct.java @@ -68,6 +68,12 @@ public class TypeStruct extends Type { Field.make("#" ,len , lenAlias,true ,false), Field.make("[]",body,bodyAlias,efinal,false)); } + public TypeStruct makeHigh() { + Field[] fs = new Field[_fields.length]; + for( int i=0; i<_fields.length; i++ ) + fs[i] = _fields[i].makeFrom(Type.TOP); + return make(_name,false,fs); + } public TypeStruct add( Field f ) { assert _open && find(f._fname)==-1; // No double field names diff --git a/src/test/java/com/seaofnodes/simple/BrainFuckTest.java b/src/test/java/com/seaofnodes/simple/BrainFuckTest.java index 9f626805..a3b98fe0 100644 --- a/src/test/java/com/seaofnodes/simple/BrainFuckTest.java +++ b/src/test/java/com/seaofnodes/simple/BrainFuckTest.java @@ -5,8 +5,6 @@ import com.seaofnodes.isa.eval.EvalRisc5; import com.seaofnodes.isa.eval.EvalArm64; import com.seaofnodes.simple.codegen.CodeGen; -import com.seaofnodes.simple.node.cpus.arm.arm; -import com.seaofnodes.simple.node.cpus.riscv.riscv; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -18,21 +16,70 @@ public class BrainFuckTest { @Test public void testBrainFuck() throws IOException { String brain_fuck = "Hello World!\n"; - TestC.run("brain_fuck", brain_fuck, 40); + String src = +""" +// -*- mode: java; -*- +val brain_fuck = { -> + var !program = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."; + int d = 0; + u8[] !output = new u8[0]; + u8[] !data = new u8[100]; - EvalRisc5 R5 = TestRisc5.build("brain_fuck", 0, 28, false); + for( int pc = 0; pc < program#; pc++ ) { + var command = program[pc]; + if (command == 62) { + d++; + } else if (command == 60) { + d--; + } else if (command == 43) { + data[d]++; + } else if (command == 45) { + data[d]--; + } else if (command == 46) { + // Output a byte; increase the output array size + var old = output; + output = new u8[output# + 1]; + for( int i = 0; i < old#; i++ ) + output[i] = old[i]; + output[old#] = data[d]; // Add the extra byte on the end + } else if (command == 44) { + data[d] = 42; + } else if (command == 91) { + if (data[d] == 0) { + for( int d = 1; d > 0; ) { + command = program[++pc]; + if (command == 91) d++; + if (command == 93) d--; + } + } + } else if (command == 93) { + if (data[d]) { + for( int d = 1; d > 0; ) { + command = program[--pc]; + if (command == 93) d++; + if (command == 91) d--; + } + } + } + } + return output; +}; +"""; + TestC.run(src,"brain_fuck", null, brain_fuck, 40); + + EvalRisc5 R5 = TestRisc5.build("brain_fuck", src, 0, 28, false); int trap = R5.step(100000); assertEquals(0,trap); - int ptr = (int)R5.regs[riscv.A0]; + int ptr = (int)R5.regs[com.seaofnodes.simple.node.cpus.riscv.riscv.A0]; assertEquals(brain_fuck.length(),R5.ld4s(ptr)); for( int i=0; i=24; - if(7) continue; - kzEl_r7EYz=false; - if(-kzEl_r7EYz+arg<-3) continue; - else { - while(kzEl_r7EYz) continue; - arg=----3; - kzEl_r7EYz=-(-----arg*1>-kzEl_r7EYz); - int v2uF_4ba=9; - } - } - } - int pjcp7rv=arg; - { - int m2ya3=--arg-pjcp7rv; - while(m2ya3<-----pjcp7rv>=pjcp7rv+--pjcp7rv!=---pjcp7rv!=-arg<---(-m2ya3)>m2ya3<=-----true>14!=--m2ya3) { - m2ya3=m2ya3+-(--0<=false=-pjcp7rv>=arg<=arg); - while(arg<-arg) { - arg=arg+--arg; - { - while((--93)--pjcp7rv*-pjcp7rv+arg) arg=0-(6>=(--(---41/(0))!=--pjcp7rv)>=---2*33); - pjcp7rv=11; - int c=pjcp7rv; - if(--107) break; - else break; - } - } - } - pjcp7rv=pjcp7rv; - int aR0Wkua=-pjcp7rv==pjcp7rv; - { - if(-0!=-0) while(-true) break; - else { - while(aR0Wkua) pjcp7rv=-0/pjcp7rv; - pjcp7rv=pjcp7rv; - } - } - } - if(-arg) { - { - int Isdlt0fr91=0!=arg; - while(Isdlt0fr91<-Isdlt0fr91==-Isdlt0fr91+true) { - Isdlt0fr91=Isdlt0fr91+-1!=true; - if(-arg) if(--arg<=Isdlt0fr91) Isdlt0fr91=-Isdlt0fr91; - int i=---arg<---arg!=--40; - { - int jVX43Ln4Dm=-(6)==-Isdlt0fr91/----0; - while(jVX43Ln4Dm<--(3-3)) { - jVX43Ln4Dm=jVX43Ln4Dm+-0<25; - i=24<--(jVX43Ln4Dm); - } - } - i=(arg!=----false>=7); - int Te=5>-arg; - break; - } - } - arg=arg!=--true/arg; - { - int UX=arg; - while(UX<-3*arg) { - UX=UX+arg/-1; - arg=-3--(-UX- -47=-arg; - if(---12) while(-UX) break; - break; - } - } - continue; - } - if(arg) arg=--0; - else if(1) continue; - int DtTlhjYq=19==arg; - { - arg=--DtTlhjYq<=(DtTlhjYq/---DtTlhjYq<=-DtTlhjYq); - if(---arg) continue; - else { - int Zsl=40; - while(Zsl<--Zsl--false>((Zsl))==Zsl!=--DtTlhjYq-DtTlhjYq-DtTlhjYq) { - Zsl=Zsl+arg; - } - } - if((arg)) if(-DtTlhjYq) { - } - else while(((2)==3*arg/DtTlhjYq)<=0==---arg) return false; - else { - int lwbF=arg>=0; - while(lwbF<57) { - lwbF=lwbF+--(-arg+lwbF)>=-2>=arg!=arg; - arg=----0+0; - while(49) break; - if(true) DtTlhjYq=-----arg; - DtTlhjYq=0!=-----(0); - } - } - arg=---arg!=DtTlhjYq/--0; - DtTlhjYq=-DtTlhjYq/(--argDtTlhjYq; - else { - } - DtTlhjYq=-0; - { - while((0)<-arg) DtTlhjYq=-DtTlhjYq; - } - if(30/--(arg)>=0) DtTlhjYq=-0>=arg; - else { - int Y2wcIQJ=--DtTlhjYq*---11; - if(arg==arg) { - Y2wcIQJ=-----Y2wcIQJ; - Y2wcIQJ=Y2wcIQJ<7; - if(DtTlhjYq) arg=arg; - else break; - while(-arg!=-31==(false<=-15>=-DtTlhjYq+--6*-----Y2wcIQJ<=---arg!=-Y2wcIQJ<=---0<-arg*--Y2wcIQJ)) DtTlhjYq=arg!=3; - } - continue; - } - arg=DtTlhjYq; - arg=--3/(---arg)>=80>=-DtTlhjYq<=DtTlhjYq; - arg=51+---(-true)!=arg!=----1==-DtTlhjYq; - if(11<=arg) if((arg)+79<32+(-arg)) continue; - else if(true==DtTlhjYq) break; - break; - } -} -if(arg!=62==arg) { - while(---arg) { - { - int bhmDacPM=arg/arg; - while(bhmDacPM1)=-arg+-arg; - break; - } - } - int arg=true; - arg=arg<=arg; - { - int KlC=30; - while(KlC<-2) { - KlC=KlC+-1!=25<=-KlC>KlC>----0; - int Ij=arg>=-arg<=---10; - { - int LAbgurVa2R=-arg!=Ij; - while(LAbgurVa2R<-true) { - LAbgurVa2R=LAbgurVa2R+Ij; - KlC=-LAbgurVa2R; - Ij=42*(-Ij>true); - while(Ij) arg=KlC; - KlC=-----7>-(--KlC<--7)==-LAbgurVa2R; - } - } - int a=Ij<=-KlC; - if(Ij) { - int r1W=a!=-false; - } - else { - arg=56>=Ij; - while(54) break; - arg=8>=-(a<--Ij)/a>=-a-KlC; - } - int Yt_T=KlC; - arg=KlC; - } - } - if(----false/--arg/12+-----0) if(-9+-arg) while(arg!=(arg)) arg=--1>=-71-arg!=---(--arg*11+102)/--arg; - else if(----arg) continue; - if(-arg-arg) { - arg=-(-arg)*--(-3)<(-7==-arg----arg); - { - int arg=arg; - while(arg<-0>arg==-arg-(-arg>1+11)) { - arg=arg+6-arg!=--0>---30>=---arg<=arg/(3)+---arg; - } - } - arg=-arg+arg; - arg=--47+-arg<1>arg*(-arg==-arg- -0>3); - arg=(----arg)!=arg+--59; - arg=- -4+arg==-(arg)-arg; - } - else { - while(--true-----true*-25+-18>arg>=-----(-arg)---13) { - arg=-0+--true=--0))<=-0/-arg; - int L=-arg; - int B4mHcrf=---vzXB; - int oZWGdzZl=-o3ypEsewxM; - int K6tQqa1=11; - while(0!=--L) { - int sdZfTM=vzXB*true+K6tQqa1; - while(sdZfTMfalse); - sdZfTM=vzXB; - } - } - L=false; - while(31) B4mHcrf=arg; - oZWGdzZl=-0<--oZWGdzZl<=--2; - if(K6tQqa1>=20<=46) { - if(-1+-L) if(oZWGdzZl) { - int wmhv=-----0; - } - int arg=0; - o3ypEsewxM=---(oZWGdzZl); - return -oZWGdzZl/0; - } - else if(arg) { - int yKk5=B4mHcrf>=4>K6tQqa1<-B4mHcrf/o3ypEsewxM; - return -K6tQqa1; - } - else { - if(---0) { - {} - {} - } - return o3ypEsewxM; - } -} -"""); - code.parse().opto().typeCheck().GCM(); - assertEquals("return 9;", code.print()); - } - - @Test public void testPrimes() { CodeGen code = new CodeGen( diff --git a/src/test/java/com/seaofnodes/simple/Chapter18Test.java b/src/test/java/com/seaofnodes/simple/Chapter18Test.java index 902344ed..44c365dd 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter18Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter18Test.java @@ -223,7 +223,7 @@ var fcn = arg ? { int x -> x*x; } : { int x -> x+x; }; return fcn(3); """); code.parse().opto(); - assertEquals("Stop[ return #2; return (Parm_x($fun21,i64,3)*x); return (Parm_x($fun22,i64,3)<<1); ]", code._stop.toString()); + assertEquals("Stop[ return #2; return (Parm_x($fun21,i64)*x); return (Parm_x($fun22,i64)<<1); ]", code._stop.toString()); assertEquals("6", Eval2.eval(code, 0)); assertEquals("9", Eval2.eval(code, 1)); } @@ -233,7 +233,7 @@ return fcn(3); public void testFcn5() { CodeGen code = new CodeGen("val fact = { int x -> x <= 1 ? 1 : x*fact(x-1); }; return fact(arg);"); code.parse().opto().typeCheck(); - assertEquals("Stop[ return #2; return Phi(Region,1,(Parm_x(fact,i64,arg,(x-1))*#2)); ]", code._stop.toString()); + assertEquals("Stop[ return #2; return Phi(Region,1,(Parm_x(fact,i64)*#2)); ]", code._stop.toString()); assertEquals( "1", Eval2.eval(code, 0)); assertEquals( "1", Eval2.eval(code, 1)); assertEquals( "2", Eval2.eval(code, 2)); @@ -249,7 +249,7 @@ struct S { int i; }; val newS = { int x -> return new S { i=x; }; }; return newS(1).i; """); - code.parse().opto().typeCheck().GCM(); + code.parse().opto().typeCheck(); assertEquals("return 1;", code._stop.toString()); assertEquals("1", Eval2.eval(code, 0)); } @@ -264,8 +264,8 @@ val f = {->1;}; val g = {->2;}; return 2; """); - code.parse().opto().typeCheck().GCM(); - assertEquals("Stop[ return 1; return 1; return 2; ]", code._stop.toString()); + code.parse().opto().typeCheck(); + assertEquals("return 1;", code._stop.toString()); assertEquals("1", Eval2.eval(code, 0)); } @@ -399,7 +399,7 @@ for(;;) { val g = { -> g(); }; -return 0; +return g(); """); try { code.parse().opto().typeCheck(); fail(); } catch( Exception e ) { assertEquals("No defined return type",e.getMessage()); } diff --git a/src/test/java/com/seaofnodes/simple/Chapter19Test.java b/src/test/java/com/seaofnodes/simple/Chapter19Test.java index 23b45e46..8a840787 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter19Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter19Test.java @@ -27,7 +27,7 @@ public class Chapter19Test { fun.addDef(code._start); code.link(fun); var otherReturn = tfp.makeFrom(TypeInteger.constant(654321)); - org.junit.Assert.assertSame(fun,code.link(otherReturn)); + org.junit.Assert.assertSame(fun,code._link(otherReturn)); org.junit.Assert.assertTrue(con.toString().contains("printerTarget")); assertEquals("printerTarget",call.name()); } @@ -47,7 +47,38 @@ return 0; @Test public void testString() throws IOException { - String src = Files.readString(Path.of("src/test/java/com/seaofnodes/simple/progs/stringHash.smp")); + String src = +""" +struct String { + u8[] !cs; + int _hashCode; +}; + +// Compare two Strings +val equals = { !String !self, !String s -> + if( self == s ) return true; + if( self.cs# != s.cs# ) return false; + for( int i=0; i< self.cs#; i++ ) + if( self.cs[i] != s.cs[i] ) + return false; + return true; +}; + +// Return the String hashCode (cached, and never 0) +val hashCode = { !String self -> + self._hashCode + ? self._hashCode + : (self._hashCode = _hashCodeString(self)); +}; + +val _hashCodeString = { !String self -> + int hash=0; + for( int i=0; i< self.cs#; i++ ) + hash = hash*31 + self.cs[i]; + if( !hash ) hash = 123456789; + return hash; +}; +"""; CodeGen code = new CodeGen(src).parse().opto().typeCheck().GCM().localSched(); assertEquals("Stop[ return Phi(Region,1,0,0,1); return Phi(Region,._hashCode,Phi(Region,123456789,Phi(Loop,0,(.[]+((Phi_hash<<5)-Phi_hash))))); ]", code._stop.toString()); //assertEquals("-4898613127354160978", Eval2.eval(code, 2)); @@ -316,8 +347,20 @@ return A[1]; @Test public void testNewton() throws IOException { - String src = Files.readString(Path.of("src/test/java/com/seaofnodes/simple/progs/newtonFloat.smp")) - + "flt farg = arg; return test_sqrt(farg);"; + String src = +""" +val test_sqrt = { flt x -> + flt epsilon = 1e-15; + flt guess = x; + while( 1 ) { + flt next = (x/guess + guess)/2; + if( guess-epsilon <= next & next <= guess+epsilon ) return guess; + //if( guess==next ) return guess; + guess = next; + } +}; +flt farg = arg; return test_sqrt(farg); +"""; CodeGen code = new CodeGen(src).driver(Phase.LocalSched,"x86_64_v2", "SystemV"); assertEquals("return Phi(Loop,(cvtf,arg),(mulf,(addf,(divf,cvtf,Phi_guess),Phi_guess),0.5f));", code.print()); }; @@ -325,7 +368,39 @@ return A[1]; @Test public void sieveOfEratosthenes() throws IOException { - String src = Files.readString(Path.of("src/test/java/com/seaofnodes/simple/progs/sieve.smp")); + String src = +""" +val sieve = { int N -> + // The main Sieve array + bool[] !ary = new bool[N]; + // The primes less than N + u32[] !primes = new u32[N>>1]; + // Number of primes so far, searching at index p + int nprimes = 0, p=2; + // Find primes while p^2 < N + while( p*p < N ) { + // skip marked non-primes + while( ary[p] ) p++; + // p is now a prime + primes[nprimes++] = p; + // Mark out the rest non-primes + for( int i = p + p; i < ary#; i+= p ) + ary[i] = true; + p++; + } + + // Now just collect the remaining primes, no more marking + for( ; p < N; p++ ) + if( !ary[p] ) + primes[nprimes++] = p; + + // Copy/shrink the result array + u32[] !rez = new u32[nprimes]; + for( int j=0; j < nprimes; j++ ) + rez[j] = primes[j]; + return rez; +}; +"""; CodeGen code = new CodeGen(src).driver(Phase.LocalSched,"x86_64_v2", "SystemV"); assertEquals("return []u32;", code.print()); //assertEquals("u32[ 2,3,5,7,11,13,17,19]",Eval2.eval(code, 20)); diff --git a/src/test/java/com/seaofnodes/simple/Chapter20Test.java b/src/test/java/com/seaofnodes/simple/Chapter20Test.java index 08a23ef0..4ca1dbda 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter20Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter20Test.java @@ -239,8 +239,8 @@ s.cs[1] = 108; // l hashCode(s); """; testTarget(src,"x86_64_v2", "SystemV",9,null); - testTarget(src,"riscv" , "SystemV",4,null); - testTarget(src,"arm" , "SystemV",1,null); + testTarget(src,"riscv" , "SystemV",3,null); + testTarget(src,"arm" , "SystemV",0,null); } @Test diff --git a/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/src/test/java/com/seaofnodes/simple/Chapter21Test.java index 30d22fc9..5b2c3a54 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter21Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter21Test.java @@ -309,7 +309,7 @@ public class Chapter21Test { } - // Enabled in Chapter 23; measured there by Chapter23AllocTest. + // Frozen Jig runs in Chapter23AllocTest; the revised input is in Chapter24AllocTest. @Test @Ignore public void testJig() throws IOException { String src = Files.readString(Path.of("src/test/java/com/seaofnodes/simple/progs/jig.smp")); @@ -343,7 +343,17 @@ public class Chapter21Test { @Test public void testArray1() throws IOException { - String src = Files.readString(Path.of("src/test/java/com/seaofnodes/simple/progs/array1.smp")); + String src = +""" +int[] !ary = new int[arg]; +// Fill [0,1,2,3,4,...] +for( int i=0; i + if( self == s ) return true; + if( self.cs# != s.cs# ) return false; + for( int i=0; i< self.cs#; i++ ) + if( self.cs[i] != s.cs[i] ) + return false; + return true; +}; + +// Return the String hashCode (cached, and never 0) +val hashCode = { !String self -> + self._hashCode + ? self._hashCode + : (self._hashCode = _hashCodeString(self)); +}; + +val _hashCodeString = { !String self -> + int hash=0; + for( int i=0; i< self.cs#; i++ ) + hash = hash*31 + self.cs[i]; + if( !hash ) hash = 123456789; + return hash; +}; +"""; testCPU(src,"x86_64_v2", "SystemV", 9,null); testCPU(src,"riscv" , "SystemV", 3,null); testCPU(src,"arm" , "SystemV", 1,null); } @Test public void testStringExport() throws IOException { - TestC.run("stringHash", 9); + String src = +""" +struct String { + u8[] !cs; + int _hashCode; +}; + +// Compare two Strings +val equals = { !String !self, !String s -> + if( self == s ) return true; + if( self.cs# != s.cs# ) return false; + for( int i=0; i< self.cs#; i++ ) + if( self.cs[i] != s.cs[i] ) + return false; + return true; +}; + +// Return the String hashCode (cached, and never 0) +val hashCode = { !String self -> + self._hashCode + ? self._hashCode + : (self._hashCode = _hashCodeString(self)); +}; + +val _hashCodeString = { !String self -> + int hash=0; + for( int i=0; i< self.cs#; i++ ) + hash = hash*31 + self.cs[i]; + if( !hash ) hash = 123456789; + return hash; +}; +"""; + TestC.run(src, "stringHash",null, "", 9); } @Test public void testLoop2() throws IOException { - String src = Files.readString(Path.of("src/test/java/com/seaofnodes/simple/progs/loop2.smp")); + String src = +""" +int i = 0; +while(true) { + i += 1; + if( i==0 ) continue; + if( i==1 ) continue; + if( i==2 ) break; + continue; +} +return i; +"""; testCPU(src,"x86_64_v2", "Win64" ,0,"return (inc,Phi(Loop,0,inc));"); testCPU(src,"riscv" , "SystemV",0,"return ( Phi(Loop,0,addi) + #1 );"); testCPU(src,"arm" , "SystemV",0,"return (inc,Phi(Loop,0,inc));"); @@ -389,9 +485,22 @@ public class Chapter21Test { 8 2.828427 (4.44089e-16) 9 3.000000 (0) """; - TestC.run("newtonFloat",result,34); + String src = +""" +val test_sqrt = { flt x -> + flt epsilon = 1e-15; + flt guess = x; + while( 1 ) { + flt next = (x/guess + guess)/2; + if( guess-epsilon <= next & next <= guess+epsilon ) return guess; + //if( guess==next ) return guess; + guess = next; + } +}; +"""; + TestC.run(src, "newtonFloat", null, result, 34); - EvalRisc5 R5 = TestRisc5.build("newtonFloat", 0, 10, false); + EvalRisc5 R5 = TestRisc5.build("newtonFloat",src, 0, 10, false); R5.fregs[riscv.FA0 - riscv.F_OFFSET] = 3.0; int trap_r5 = R5.step(1000); assertEquals(0,trap_r5); @@ -399,7 +508,7 @@ public class Chapter21Test { assertEquals(1.732051,R5.fregs[riscv.FA0 - riscv.F_OFFSET], 0.00001); // arm - EvalArm64 A5 = TestArm64.build("newtonFloat", 0, 10, false); + EvalArm64 A5 = TestArm64.build("newtonFloat", src,0, 10, false); A5.fregs[arm.D0 - arm.D_OFFSET] = 3.0; int trap_arm = A5.step(1000); assertEquals(0,trap_arm); @@ -408,6 +517,39 @@ public class Chapter21Test { @Test public void testSieve() throws IOException { + String src = +""" +val sieve = { int N -> + // The main Sieve array + bool[] !ary = new bool[N]; + // The primes less than N + u32[] !primes = new u32[N>>1]; + // Number of primes so far, searching at index p + int nprimes = 0, p=2; + // Find primes while p^2 < N + while( p*p < N ) { + // skip marked non-primes + while( ary[p] ) p++; + // p is now a prime + primes[nprimes++] = p; + // Mark out the rest non-primes + for( int i = p + p; i < ary#; i+= p ) + ary[i] = true; + p++; + } + + // Now just collect the remaining primes, no more marking + for( ; p < N; p++ ) + if( !ary[p] ) + primes[nprimes++] = p; + + // Copy/shrink the result array + u32[] !rez = new u32[nprimes]; + for( int j=0; j < nprimes; j++ ) + rez[j] = primes[j]; + return rez; +}; +"""; // The primes int[] primes = new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, }; SB sb = new SB().p(primes.length).p("["); @@ -416,11 +558,11 @@ public class Chapter21Test { String sprimes = sb.p("]").toString(); // Compile, link against native C; expect the above string of primes to be printed out by C - TestC.run("sieve",sprimes, 186); + TestC.run(src, "sieve", null, sprimes, 186); // Evaluate on RISC5 emulator; expect return of an array of primes in // the simulated heap. - EvalRisc5 R5 = TestRisc5.build("sieve", 100, 92, false); + EvalRisc5 R5 = TestRisc5.build("sieve", src, 100, 92, false); int trap = R5.step(10000); assertEquals(0,trap); // Return register A0 holds sieve(100) @@ -432,7 +574,7 @@ public class Chapter21Test { // Evaluate on ARM5 emulator; expect return of an array of primes in // the simulated heap. - EvalArm64 A5 = TestArm64.build("sieve", 100, 94, false); + EvalArm64 A5 = TestArm64.build("sieve", src, 100, 94, false); int trap_arm = A5.step(10000); assertEquals(0, trap_arm); int ary_arm = (int)A5.regs[arm.X0]; @@ -443,17 +585,30 @@ public class Chapter21Test { } @Test public void testFibExport() throws IOException { + String src = +""" +val fib = {int n -> + int f1=1; + int f2=1; + while( n-- > 1 ){ + int temp = f1+f2; + f1=f2; + f2=temp; + } + return f2; +}; +"""; String fib = "[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]"; - TestC.run("fib", fib, 24); + TestC.run(src, "fib", null, fib, 24); - EvalRisc5 R5 = TestRisc5.build("fib", 9, 17, false); + EvalRisc5 R5 = TestRisc5.build("fib", src, 9, 17, false); int trap = R5.step(100); assertEquals(0,trap); // Return register A0 holds fib(8)==55 assertEquals(55,R5.regs[riscv.A0]); // arm - EvalArm64 A5 = TestArm64.build("fib", 9, 17, false); + EvalArm64 A5 = TestArm64.build("fib", src, 9, 17, false); int trap_arm = A5.step(100); assertEquals(0,trap_arm); // Return register X0 holds fib(8)==55 diff --git a/src/test/java/com/seaofnodes/simple/Chapter22Test.java b/src/test/java/com/seaofnodes/simple/Chapter22Test.java index ea210e3f..c77221bf 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter22Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter22Test.java @@ -186,7 +186,8 @@ public class Chapter22Test { testCPU(src,"arm","SystemV",0,"return Top;"); } - // Enabled in Chapter 23; measured there by Chapter23AllocTest. + + // Frozen Jig runs in Chapter23AllocTest; the revised input is in Chapter24AllocTest. @Test @Ignore public void testJig() throws IOException { String src = Files.readString(Path.of("src/test/java/com/seaofnodes/simple/progs/jig.smp")); @@ -223,11 +224,11 @@ return 0; assertEquals(56, testCPUSize(src, "arm","SystemV",4,"return 0;")); // do assertEquals here - EvalRisc5 R5 = TestRisc5.build("sext_str_not_fold_away", 0, 4, false); + EvalRisc5 R5 = TestRisc5.build("sext_str_not_fold_away", src,0, 4, false); int trap = R5.step(100); assertEquals(0,trap); - EvalArm64 A5 = TestArm64.build("sext_str_not_fold_away", 0, 4, false); + EvalArm64 A5 = TestArm64.build("sext_str_not_fold_away", src, 0, 4, false); trap = A5.step(100); assertEquals(0,trap); @@ -243,11 +244,11 @@ return 0; return 0; """; - EvalRisc5 R5 = TestRisc5.build("sext_str_not_fold_away_2", 0, 4, false); + EvalRisc5 R5 = TestRisc5.build("sext_str_not_fold_away_2", src, 0, 4, false); int trap = R5.step(100); assertEquals(0,trap); - EvalArm64 A5 = TestArm64.build("sext_str_not_fold_away_2", 0, 4, false); + EvalArm64 A5 = TestArm64.build("sext_str_not_fold_away_2", src, 0, 4, false); int trap_arm = A5.step(100); assertEquals(0,trap_arm); @@ -267,11 +268,11 @@ p.age = (arg<<48)>>48; return 0; """; - EvalRisc5 R5 = TestRisc5.build("sext_str_fold_away", 0, 5, false); + EvalRisc5 R5 = TestRisc5.build("sext_str_fold_away", src, 0, 5, false); int trap = R5.step(100); assertEquals(0,trap); - EvalArm64 A5 = TestArm64.build("sext_str_fold_away", 0, 5, false); + EvalArm64 A5 = TestArm64.build("sext_str_fold_away", src, 0, 5, false); int trap_arm = A5.step(100); assertEquals(0,trap_arm); @@ -284,8 +285,19 @@ return 0; // Int now is changed to 4 bytes. @Test public void testPerson() throws IOException { + String src = +""" +struct Person { + i32 age; +}; + +val fcn = { !Person?[] !ps, int x -> + if( ps[x] ) + ps[x].age++; +}; +"""; String person = "6\n"; - TestC.run("person", person, 0); + TestC.run(src, "person", null, person, 0); // Memory layout starting at PS: int ps = 1<<16; // Person array pointer starts at heap start @@ -296,7 +308,7 @@ return 0; int p1 = ps+4*8+1*8; // P2 = { age } // sizeof=8 int p2 = ps+4*8+2*8; - EvalRisc5 R5 = TestRisc5.build("person", ps, 0, false); + EvalRisc5 R5 = TestRisc5.build("person", src, ps, 0, false); R5.regs[riscv.A1] = 1; // Index 1 R5.st8(ps,3); // Length R5.st8(ps+1*8,p0); @@ -312,7 +324,7 @@ return 0; assertEquals(17+1,R5.ld8(p1)); assertEquals(60+0,R5.ld8(p2)); - EvalArm64 A5 = TestArm64.build("person", ps, 0, false); + EvalArm64 A5 = TestArm64.build("person", src, ps, 0, false); A5.regs[arm.X1] = 1; // Index 1 A5.st8(ps, 3); A5.st8(ps+1*8,p0); @@ -351,18 +363,22 @@ return cc.cz; @Test public void testHelloWorld() throws IOException { - String src = Files.readString(Path.of("src/test/java/com/seaofnodes/simple/progs/helloWorld.smp")); + String src = +""" +sys.io.p("Hello, World!"); +return 0; +"""; TestC.run(src,TestC.CALL_CONVENTION,null, null,null,"build/objs/helloWorld","","Hello, World!",0); // Evaluate on RISC5 emulator - EvalRisc5 R5 = TestRisc5.build("helloWorld", 0, 2, false); + EvalRisc5 R5 = TestRisc5.build("helloWorld", src, 0, 2, false); int trap = R5.step(100); assertEquals(0,trap); assertEquals(0,R5.regs[riscv.A0]); assertEquals("Hello, World!",R5._stdout.toString()); // Evaluate on ARM emulator - EvalArm64 arm = TestArm64.build("helloWorld", 0, 2, false); + EvalArm64 arm = TestArm64.build("helloWorld", src,0, 2, false); trap = arm.step(100); assertEquals(0,trap); assertEquals(0,arm.regs[0]); @@ -392,17 +408,21 @@ return sum(is); @Test @Ignore public void testEcho() throws IOException { - String src = Files.readString(Path.of("src/test/java/com/seaofnodes/simple/progs/echo.smp")); + String src = +""" +// Echo stdin to stdout. +return sys.io.p( sys.io.stdin() ); +"""; TestC.run(src,TestC.CALL_CONVENTION,null, null,null,"build/objs/echo","","",0); // Evaluate on RISC5 emulator - EvalRisc5 R5 = TestRisc5.build("echo", 0, 2, false); + EvalRisc5 R5 = TestRisc5.build("echo", src, 0, 2, false); int trap = R5.step(100); assertEquals(0,trap); assertEquals(0,R5.regs[riscv.A0]); // Evaluate on ARM emulator - EvalArm64 arm = TestArm64.build("echo", 0, 2, false); + EvalArm64 arm = TestArm64.build("echo", src, 0, 2, false); trap = arm.step(100); assertEquals(0,trap); assertEquals(0,arm.regs[0]); diff --git a/src/test/java/com/seaofnodes/simple/Chapter23Test.java b/src/test/java/com/seaofnodes/simple/Chapter23Test.java index 0feaa5de..884e77e5 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter23Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter23Test.java @@ -25,6 +25,8 @@ public class Chapter23Test { @Test public void testDiagnosticTypeAccessors() throws Exception { new CodeGen("return 0;").parse(); var tfp = TypeFunPtr.TEST; + var con = new ConstantNode(tfp); + var call = new CallNode(null,con,con,con); var field = Type.class.getDeclaredField("VISIT"); field.setAccessible(true); var visit = (java.util.Map)field.get(null); @@ -34,6 +36,9 @@ public class Chapter23Test { assertEquals(0,TypeInteger.ZERO.alignment()); assertEquals(0,TypeInteger.ZERO.value()); org.junit.Assert.assertTrue(tfp._isConstant()); + con.toString(); + call.name(); + con.p(1); org.junit.Assert.assertSame(Type.BOTTOM,visit.get(marker)); assertEquals(1,visit.size()); } finally { visit.clear(); } @@ -94,10 +99,6 @@ var apply = { i64 x, { i64 -> u32 } fcn -> """; } - @Test @Ignore - public void myOwnSake2() throws IOException { - TestC.runS("print","Or",0); - } static CodeGen testCPU( String src, String cpu, String os, int spills, String stop ) { CodeGen code = new CheckedCodeGen(src).driver(CodeGen.Phase.Encoding,cpu,os); @@ -110,17 +111,32 @@ var apply = { i64 x, { i64 -> u32 } fcn -> @Test public void testOr() throws IOException { - TestC.runS("or1","Or",0); + String src = + """ + int a = 1; + int b = 0; + + if(a++ || b++ ) { + if(b == 0 && a == 2) { + sys.io.p("Or"); + } + } else{ + sys.io.p("And"); + } + return 0; + """; + + TestC.runSF("or1", src, null, "Or", 0); // Evaluate on RISC5 emulator - EvalRisc5 R5 = TestRisc5.build("or1", 0, 2, false); + EvalRisc5 R5 = TestRisc5.build("or1", src, 0, 2, false); int trap = R5.step(100); assertEquals(0,trap); assertEquals(0,R5.regs[riscv.A0]); assertEquals("Or",R5._stdout.toString()); // Evaluate on ARM emulator - EvalArm64 arm = TestArm64.build("or1", 0, 2, false); + EvalArm64 arm = TestArm64.build("or1", src,0, 2, false); trap = arm.step(100); assertEquals(0,trap); assertEquals(0,arm.regs[0]); @@ -129,17 +145,29 @@ var apply = { i64 x, { i64 -> u32 } fcn -> @Test public void testAnd() throws IOException { - TestC.runS("and1","And",0); + String src = + """ + int a = 1; + int b = 1; + + if(a && b) { + sys.io.p("And"); + } else { + sys.io.p("Or"); + } + return 0; + """; + TestC.runSF("and1", src, null, "And", 0); // Evaluate on RISC5 emulator - EvalRisc5 R5 = TestRisc5.build("and1", 0, 2, false); + EvalRisc5 R5 = TestRisc5.build("and1", src, 0, 2, false); int trap = R5.step(100); assertEquals(0,trap); assertEquals(0,R5.regs[riscv.A0]); assertEquals("And",R5._stdout.toString()); // Evaluate on ARM emulator - EvalArm64 arm = TestArm64.build("and1", 0, 2, false); + EvalArm64 arm = TestArm64.build("and1", src, 0, 2, false); trap = arm.step(100); assertEquals(0,trap); assertEquals(0,arm.regs[0]); @@ -148,24 +176,38 @@ var apply = { i64 x, { i64 -> u32 } fcn -> @Test public void testAndPtr() throws IOException { + // Todo: have one src here String src = -""" -struct S { !S? !fld; }; -val ptr = arg == 1 ? null : new S{fld = arg==1 ? null : new S{fld = null;};}; -return ptr && ptr.fld ? "true" : "false"; - """; + """ + struct S { !S? !fld; }; + val ptr = arg == 1 ? null : new S{fld = arg==1 ? null : new S{fld = null;};}; + return ptr && ptr.fld ? "true" : "false"; + """; + String src2 = + """ + struct S { !S? !fld; }; + + val ptr = arg == 1 ? null : new S{fld = arg==1 ? null : new S{fld = null;};}; + if( ptr && ptr.fld ) { + sys.io.p("true"); + } else { + sys.io.p("false"); + } + + return 0; + """; CodeGen code = new CodeGen(src).parse().opto().typeCheck(); assertEquals("[97-117][ 116,114,117,101]", Eval2.eval(code, 0)); // Evaluate on RISC5 emulator - EvalRisc5 R5 = TestRisc5.build("ptrand", 1, 8, false); + EvalRisc5 R5 = TestRisc5.build("ptrand",src2, 1, 8, false); int trap = R5.step(100); assertEquals(0,trap); assertEquals(0,R5.regs[riscv.A0]); assertEquals("false",R5._stdout.toString()); // Evaluate on ARM emulator - EvalArm64 arm = TestArm64.build("ptrand", 1, 8, false); + EvalArm64 arm = TestArm64.build("ptrand", src2, 1, 8, false); trap = arm.step(100); assertEquals(0,trap); assertEquals(0,arm.regs[0]); @@ -175,37 +217,80 @@ return ptr && ptr.fld ? "true" : "false"; // conditional side effect @Test public void testCondSideEffAnd() throws IOException { - TestC.runS("and2","Effected",0); + String src = + """ + int a = 1; + int b = 1; + + int x=1; + int y=1; + int z=0; + + int g = x++ && y++ && z++; + + if(x == 2 && y == 2 && z == 1 && g == 0) { + sys.io.p("Effected"); + } else { + sys.io.p("Not effected"); + } + return 0; + """; + + TestC.runSF("and2", src, null, "Effected", 0); // Evaluate on RISC5 emulator - EvalRisc5 R5 = TestRisc5.build("and2", 0, 2, false); + EvalRisc5 R5 = TestRisc5.build("and2", src, 0, 2, false); int trap = R5.step(100); assertEquals(0,trap); assertEquals(0,R5.regs[riscv.A0]); assertEquals("Effected",R5._stdout.toString()); // Evaluate on ARM emulator - EvalArm64 arm = TestArm64.build("and2", 0, 2, false); + EvalArm64 arm = TestArm64.build("and2", src, 0, 2, false); trap = arm.step(100); assertEquals(0,trap); assertEquals(0,arm.regs[0]); assertEquals("Effected",arm._stdout.toString()); } - @Test public void testCondSideEffOr() throws IOException { - TestC.runS("or2","Effected",0); + String src = + """ + int a = 1; + int b = 1; + + int x = -1; + int y=1; + int z= -1; + + int g = x++ || y++ || z++; + + int switch = 0; + if(x == 4 || y == 4 || z == 4) { + switch = -1; + } else { + switch = 1; + } + int cd = 1; + if((x == 0 && y == 1 && z==-1) && switch && g) { + sys.io.p("Effected"); + } else { + sys.io.p("Not effected"); + } + return 0; + """; + TestC.runSF("or2", src, null, "Effected", 0); // Evaluate on RISC5 emulator - EvalRisc5 R5 = TestRisc5.build("or2", 0, 2, false); + EvalRisc5 R5 = TestRisc5.build("or2", src, 0, 2, false); int trap = R5.step(100); assertEquals(0,trap); assertEquals(0,R5.regs[riscv.A0]); assertEquals("Effected",R5._stdout.toString()); // Evaluate on ARM emulator - EvalArm64 arm = TestArm64.build("or2", 0, 2, false); + EvalArm64 arm = TestArm64.build("or2", src, 0, 2, false); trap = arm.step(100); assertEquals(0,trap); assertEquals(0,arm.regs[0]); @@ -215,23 +300,41 @@ return ptr && ptr.fld ? "true" : "false"; // test it with function calls @Test public void testFuncCall() throws IOException { - TestC.runS("and3","Or",0); + String src = + """ + // -*- mode: java; -*- + int a = 1; + int b = 1; + + var sq = { int x -> + x*x; + }; + + if(a && sq(0)) { + sys.io.p("And"); + } else { + sys.io.p("Or"); + } + return 0; + """; + TestC.runSF("and3", src, null, "Or", 0); // Evaluate on RISC5 emulator - EvalRisc5 R5 = TestRisc5.build("and3", 0, 2, false); + EvalRisc5 R5 = TestRisc5.build("and3", src, 0, 2, false); int trap = R5.step(100); assertEquals(0,trap); assertEquals(0,R5.regs[riscv.A0]); assertEquals("Or",R5._stdout.toString()); // Evaluate on ARM emulator - EvalArm64 arm = TestArm64.build("and3", 0, 2, false); + EvalArm64 arm = TestArm64.build("and3", src, 0, 2, false); trap = arm.step(100); assertEquals(0,trap); assertEquals(0,arm.regs[0]); assertEquals("Or",arm._stdout.toString()); } + @Test public void testFRefFields() { String src = diff --git a/src/test/java/com/seaofnodes/simple/Chapter24AllocTest.java b/src/test/java/com/seaofnodes/simple/Chapter24AllocTest.java new file mode 100644 index 00000000..7fae2c27 --- /dev/null +++ b/src/test/java/com/seaofnodes/simple/Chapter24AllocTest.java @@ -0,0 +1,170 @@ +package com.seaofnodes.simple; + +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + +import java.io.IOException; +import java.nio.file.*; +import com.seaofnodes.simple.node.cpus.arm.arm; +import com.seaofnodes.simple.node.cpus.riscv.riscv; +import org.junit.Ignore; +import org.junit.Test; +import static org.junit.Assert.*; + +// Revised inherited programs belong to the chapter which changed their inputs. +public class Chapter24AllocTest { + @Test + public void testNewtonInteger() { + String src = +""" +// Newtons approximation to the square root +val sqrt = { int x -> + int guess = x; + while( 1 ) { + int next = (x/guess + guess)/2; + if( next == guess ) return guess; + guess = next; + } +}; +int cast_int = arg+2; +return sqrt(arg) + sqrt(cast_int); +"""; + Chapter24Test.testCPU(src,"x86_64_v2", "Win64" ,40,null); + Chapter24Test.testCPU(src,"riscv" , "SystemV",19,null); + Chapter24Test.testCPU(src,"arm" , "SystemV",19,null); + } + + @Ignore + @Test + public void testJig21() throws IOException { + String src = +""" +struct s0 { + bool v1; + i16 v2; + int v3; + i8 v4; + byte v5; +}; +while(new s0.v3) + while(new s0.v5< + return + i0 + f1+ i2+ f3+ i4+ f5+ i6+ f7+ x8 +f9 + + i10+f11+i12+f13+i14+f15+x16+f17+x18+f19 ; +}; +"""; + String arg_count = "191.000000\n"; + + TestC.run(src, "arg_count", null, arg_count, TestC.CALL_CONVENTION.equals("Win64") ? 32 : 9); + + EvalRisc5 R5 = TestRisc5.build("no_stack_arg_count", src, 0, 4, false); + + // Todo: handle stack(imaginary stack in emulator) + // pass in float arguments + R5.fregs[riscv.FA0 - riscv.F_OFFSET] = 1.1; + R5.fregs[riscv.FA1 - riscv.F_OFFSET] = 1.1; + R5.fregs[riscv.FA2 - riscv.F_OFFSET] = 1.1; + R5.fregs[riscv.FA3 - riscv.F_OFFSET] = 1.1; + R5.fregs[riscv.FA4 - riscv.F_OFFSET] = 1.1; + R5.fregs[riscv.FA5 - riscv.F_OFFSET] = 1.1; + R5.fregs[riscv.FA6 - riscv.F_OFFSET] = 1.1; + R5.fregs[riscv.FA7 - riscv.F_OFFSET] = 1.1; + + // a0 is passed in arg + R5.regs[riscv.A1] = 2; + R5.regs[riscv.A2] = 2; + R5.regs[riscv.A3] = 2; + R5.regs[riscv.A4] = 2; + R5.regs[riscv.A5] = 2; + R5.regs[riscv.A6] = 2; + R5.regs[riscv.A7] = 2; + + int trap = R5.step(100); + assertEquals(0,trap); + + double result = R5.fregs[riscv.FA0 - riscv.F_OFFSET]; + + assertEquals(22.8, result, 0.00001); + + // arm + EvalArm64 A5 = TestArm64.build("no_stack_arg_count", src, 0, 4, false); + + A5.fregs[arm.D0 - arm.D_OFFSET] = 1.1; + A5.fregs[arm.D1 - arm.D_OFFSET] = 1.1; + A5.fregs[arm.D2 - arm.D_OFFSET] = 1.1; + A5.fregs[arm.D3 - arm.D_OFFSET] = 1.1; + A5.fregs[arm.D4 - arm.D_OFFSET] = 1.1; + A5.fregs[arm.D5 - arm.D_OFFSET] = 1.1; + A5.fregs[arm.D6 - arm.D_OFFSET] = 1.1; + A5.fregs[arm.D7 - arm.D_OFFSET] = 1.1; + + A5.regs[arm.X1] = 2; + A5.regs[arm.X2] = 2; + A5.regs[arm.X3] = 2; + A5.regs[arm.X4] = 2; + A5.regs[arm.X5] = 2; + A5.regs[arm.X6] = 2; + A5.regs[arm.X7] = 2; + + int trap_arm = A5.step(100); + assertEquals(0,trap_arm); + + double result1 = A5.fregs[arm.D0 - arm.D_OFFSET]; + assertEquals(22.8, result1, 0.00001); + } + + @Ignore + @Test + public void testJig22() throws IOException { + String src = +""" +val fib = {int n -> + int temp=0; + int f1=1; + int f2=1; + int i=n; + while( i>1 ){ + temp = f1+f2; + f1=f2; + f2=temp; + i=i-1; + } + return f2; +}; + +fib(10); +"""; + Chapter24Test.testCPU(src,"x86_64_v2", "Win64" ,-1,null); + Chapter24Test.testCPU(src,"riscv" , "SystemV",-1,null); + Chapter24Test.testCPU(src,"arm" , "SystemV",-1,null); + } + + @Test + public void testBubbleSort() throws IOException { + //String src = Files.readString(Path.of("src/test/java/com/seaofnodes/simple/progs/jig.smp")); + String src = Files.readString(Path.of("docs/examples/BubbleSort.smp")); + Chapter24Test.testCPU(src,"x86_64_v2", "Win64" ,-1,null); + Chapter24Test.testCPU(src,"riscv" , "SystemV",-1,null); + Chapter24Test.testCPU(src,"arm" , "SystemV",-1,null); + } +} diff --git a/src/test/java/com/seaofnodes/simple/Chapter24Test.java b/src/test/java/com/seaofnodes/simple/Chapter24Test.java new file mode 100644 index 00000000..9a657855 --- /dev/null +++ b/src/test/java/com/seaofnodes/simple/Chapter24Test.java @@ -0,0 +1,721 @@ +package com.seaofnodes.simple; + +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + +import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.*; + + +import com.seaofnodes.simple.codegen.CodeGen; +import com.seaofnodes.simple.node.cpus.riscv.riscv; +import java.io.IOException; +import org.junit.Ignore; +import org.junit.Test; +import static org.junit.Assert.*; + +public class Chapter24Test { + @Test public void testColdLoopSelfConflict() { com.seaofnodes.simple.codegen.RegAllocTestSupport.coldLoopSelfConflict(); } + + @Test public void testPrintingDeadFunction() throws Exception { + var code = new CodeGen("return 0;").parse(); + var tfp = TypeFunPtr.TEST; + var fun = new FunNode(null,tfp,"deadPrinterTarget"); + org.junit.Assert.assertTrue(fun.isDead()); + code.link(fun); + var con = new ConstantNode(tfp); + var call = new CallNode(null,con,con,con); + con.toString(); + call.name(); + + org.junit.Assert.assertSame(fun,code._link(tfp)); + // Optimizer lookup still performs its usual lazy cleanup. + org.junit.Assert.assertNull(code.link(tfp)); + org.junit.Assert.assertNull(code._link(tfp)); + } + + + @Ignore + @Test + public void testJig() throws IOException { + String src = "int v0=0; v0 = arg && 0== 0 !=0;"; + testCPU(src,"x86_64_v2", "Win64" ,-1,null); + testCPU(src,"riscv" , "SystemV",-1,null); + testCPU(src,"arm" , "SystemV",-1,null); + } + + static CodeGen testCPU( String src, String cpu, String os, int spills, String stop ) { + CodeGen code = new CheckedCodeGen(src).driver(CodeGen.Phase.Encoding,cpu,os); + SpillStats.record(code,"Chapter24",cpu,os); + SpillStats.checkSpills(spills,code._regAlloc._spillScaled); + if( stop != null ) + assertEquals(stop, code._stop.toString()); + return code; + } + + @Test + public void testOr() throws IOException { + String src = +""" +int a = 1; +int b = 0; + +if(a++ || b++ ) { + if(b == 0 && a == 2) { + sys.io.p("Or"); + } +} else{ + sys.io.p("And"); +} +return 0; +"""; + + TestC.runSF("or1", src, null, "Or", 0); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build("or1", src, 0, 2, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(0,R5.regs[riscv.A0]); + assertEquals("Or",R5._stdout.toString()); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("or1", src,0, 2, false); + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(0,arm.regs[0]); + assertEquals("Or",arm._stdout.toString()); + } + + @Test + public void testAnd() throws IOException { + String src = +""" +int a = 1; +int b = 1; + +if(a && b) { + sys.io.p("And"); +} else { + sys.io.p("Or"); +} +return 0; +"""; + TestC.runSF("and1", src, null, "And", 0); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build("and1", src, 0, 2, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(0,R5.regs[riscv.A0]); + assertEquals("And",R5._stdout.toString()); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("and1", src, 0, 2, false); + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(0,arm.regs[0]); + assertEquals("And",arm._stdout.toString()); + } + + @Test + public void testAndPtr() throws IOException { + // Todo: have one src here + String src = +""" +struct S { !S? !fld; }; +val ptr = arg == 1 ? null : new S{fld = arg==1 ? null : new S{fld = null;};}; +return ptr && ptr.fld ? "true" : "false"; +"""; + String src2 = +""" +struct S { !S? !fld; }; + +val ptr = arg == 1 ? null : new S{fld = arg==1 ? null : new S{fld = null;};}; +if( ptr && ptr.fld ) { + sys.io.p("true"); +} else { + sys.io.p("false"); +} + +return 0; +"""; + CodeGen code = new CodeGen(src).parse().opto().typeCheck(); + assertEquals("[97-117][ 116,114,117,101]", Eval2.eval(code, 0)); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build("ptrand",src2, 1, 8, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(0,R5.regs[riscv.A0]); + assertEquals("false",R5._stdout.toString()); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("ptrand", src2, 1, 8, false); + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(0,arm.regs[0]); + assertEquals("false",arm._stdout.toString()); + } + + // conditional side effect + @Test + public void testCondSideEffAnd() throws IOException { + String src = +""" +int a = 1; +int b = 1; + +int x=1; +int y=1; +int z=0; + +int g = x++ && y++ && z++; + +if(x == 2 && y == 2 && z == 1 && g == 0) { + sys.io.p("Effected"); +} else { + sys.io.p("Not effected"); +} +return 0; +"""; + + TestC.runSF("and2", src, null, "Effected", 0); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build("and2", src, 0, 2, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(0,R5.regs[riscv.A0]); + assertEquals("Effected",R5._stdout.toString()); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("and2", src, 0, 2, false); + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(0,arm.regs[0]); + assertEquals("Effected",arm._stdout.toString()); + } + + + @Test + public void testCondSideEffOr() throws IOException { + String src = +""" +int a = 1; +int b = 1; + +int x = -1; +int y=1; +int z= -1; + +int g = x++ || y++ || z++; + +int switch = 0; +if(x == 4 || y == 4 || z == 4) { + switch = -1; +} else { + switch = 1; +} +int cd = 1; +if((x == 0 && y == 1 && z==-1) && switch && g) { + sys.io.p("Effected"); +} else { + sys.io.p("Not effected"); +} +return 0; +"""; + TestC.runSF("or2", src, null, "Effected", 0); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build("or2", src, 0, 2, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(0,R5.regs[riscv.A0]); + assertEquals("Effected",R5._stdout.toString()); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("or2", src, 0, 2, false); + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(0,arm.regs[0]); + assertEquals("Effected",arm._stdout.toString()); + } + + // test it with function calls + @Test + public void testFuncCall() throws IOException { + String src = +""" +// -*- mode: java; -*- +int a = 1; +int b = 1; + +var sq = { int x -> + x*x; +}; + +if(a && sq(0)) { + sys.io.p("And"); +} else { + sys.io.p("Or"); +} +return 0; +"""; + TestC.runSF("and3", src, null, "Or", 0); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build("and3", src, 0, 2, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(0,R5.regs[riscv.A0]); + assertEquals("Or",R5._stdout.toString()); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("and3", src, 0, 2, false); + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(0,arm.regs[0]); + assertEquals("Or",arm._stdout.toString()); + } + + // test it with function calls + @Test + public void testStack1() throws IOException { + String src = +""" +int something_specific = 11; + +if (10 < something_specific < 20) { + sys.io.p("In Range"); +} else { + sys.io.p("Out of Range"); +} +return 0; +"""; + + TestC.runSF("stacked_r_1", src, null, "In Range", 0); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build("stacked_r_1", src, 0, 2, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(0,R5.regs[riscv.A0]); + assertEquals("In Range",R5._stdout.toString()); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("stacked_r_1", src, 0, 2, false); + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(0,arm.regs[0]); + assertEquals("In Range",arm._stdout.toString()); + } + + @Test + public void testStack2() throws IOException { + String src = +""" +int score = 75; + +if (60 <= score < 90) { + sys.io.p("In Range"); +} else { +sys.io.p("Out of range"); +} +return 0; +"""; + + TestC.runSF("stacked_r_2", src, null, "In Range", 0); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build("stacked_r_2", src, 0, 2, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(0,R5.regs[riscv.A0]); + assertEquals("In Range",R5._stdout.toString()); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("stacked_r_2", src, 0, 2, false); + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(0,arm.regs[0]); + assertEquals("In Range",arm._stdout.toString()); + } + + @Test + public void testStack3() throws IOException { + String src = +""" +var sq = { int x -> + x*x; +}; + +int score = 5; + +val str = (sq(2) <= score < sq(3)) ? "In Range" : "Out of range"; +sys.io.p(str); +return 0; +"""; + + TestC.runSF("stacked_r_3", src, null, "In Range", 5); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build("stacked_r_3", src, 0, 5, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(0,R5.regs[riscv.A0]); + assertEquals("In Range",R5._stdout.toString()); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("stacked_r_3", src, 0, 5, false); + int trap_1 = arm.step(100); + assertEquals(0,trap_1); + assertEquals(0,arm.regs[0]); + assertEquals("In Range",arm._stdout.toString()); + } + + @Test + public void testStack4() throws IOException { + String src = +""" +int something_specific = 9; + +if (10 < something_specific < 20) { + sys.io.p("In Range"); +} else { + sys.io.p("Out of Range"); +} +return 0; +"""; + + TestC.runSF("stacked_r_4", src, null, "Out of Range", 0); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build("stacked_r_4", src,0, 2, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(0,R5.regs[riscv.A0]); + assertEquals("Out of Range",R5._stdout.toString()); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("stacked_r_4", src, 0, 2, false); + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(0,arm.regs[0]); + assertEquals("Out of Range",arm._stdout.toString()); + } + + @Test + public void testStack5() throws IOException { + String src = +""" +var sq = { int x -> + x*x; +}; + +int score = 5; + +if (sq(2) <= score < sq(3)) { +sys.io.p("In Range"); +} else { +sys.io.p("Out of range"); +} + +return 0; +"""; + TestC.runSF("stacked_r_5", src, null, "In Range", 5); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build("stacked_r_5", src, 0, 7, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(0,R5.regs[riscv.A0]); + assertEquals("In Range",R5._stdout.toString()); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("stacked_r_5", src, 0, 7, false); + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(0,arm.regs[0]); + assertEquals("In Range",arm._stdout.toString()); + } + + + @Test + public void testStack6() { + try { new CodeGen( + """ + return 0 < arg > 1; + """ + ).parse(); fail(); } + catch( RuntimeException e ) { assertEquals("Mixing relational directions in a chained relational test",e.getMessage()); } + } + + @Test + public void testStack9() throws IOException { + String stack9 = "1"; + String src = +""" +var stack9 = { int x -> + (x < 1) == 1; +}; +"""; + String src2 = +""" +return (0 < 1) == 1; +"""; + TestC.run(src, "stacked_r_9x", null, stack9,0); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build("stacked_r_9", src2, 0, 0, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(1,R5.regs[riscv.A0]); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("stacked_r_9", src2, 0, 0, false); + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(1,arm.regs[0]); + } + + @Test + public void testStack10() throws IOException { + String stack10 = "1"; + String src = +""" +var stack10 = { int x -> + (x < 1) == (1>x); +}; +"""; + String src2 = +""" +return (0 < 1) == (1>0); +"""; + TestC.run(src, "stacked_r_10x", null, stack10,0); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build("stacked_r_10", src2, 0, 0, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(1,R5.regs[riscv.A0]); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("stacked_r_10", src2,0, 0, false); + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(1,arm.regs[0]); + } + + @Test + public void testStack11() throws IOException { + String stack11 = "1"; + String src = +""" +var stack11 = { int x -> + 0 < x < x+1 < 4; +}; +"""; + String src2 = +""" +return 0 < arg < arg+1 < 4; +"""; + TestC.run(src, "stacked_r_11x", null, stack11,2); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build("stacked_r_11", src2, 1, 2, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(1,R5.regs[riscv.A0]); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("stacked_r_11", src2, 1, 0, false); + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(1,arm.regs[0]); + } + + // shows that it is parsed as + // ((0 != x) != 2) + @Test + public void testStack12() throws IOException { + String stack11 = "1"; + String src = + """ + var stack12 = { int x -> + 0 != x != 2; + }; + """; + String src2 = + """ + return 0 != arg != 2; + """; + TestC.run(src, "stacked_r_12x", null, stack11,0); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build("stacked_r_12", src2, 1, 0, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(1,R5.regs[riscv.A0]); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("stacked_r_12", src2, 1, 0, false); + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(1,arm.regs[0]); + } + + + // shows that it is parsed as + // ((0 == x) == 1) + @Test + public void testStack13() throws IOException { + String stack12 = "1"; + String src = + """ + var stack13 = { int x -> + 0 == x == 1; + }; + """; + String src2 = + """ + return 0 == arg == 1; + """; + TestC.run(src, "stacked_r_13x", null, stack12,0); + + // Compile once per target, then check false, true and negative inputs. + EvalRisc5 R5 = TestRisc5.build("stacked_r_13", src2, 1, 0, false); + for( int arg : new int[]{-1,0,1} ) { + R5._pc = 0; + R5.regs[riscv.A0] = arg; + assertEquals(0,R5.step(100)); + assertEquals(arg==0 ? 1 : 0,R5.regs[riscv.A0]); + } + EvalArm64 arm = TestArm64.build("stacked_r_13", src2, 1, 0, false); + for( int arg : new int[]{-1,0,1} ) { + arm._pc = 0; + arm.regs[0] = arg; + assertEquals(0,arm.step(100)); + assertEquals(arg==0 ? 1 : 0,arm.regs[0]); + } + } + + @Test + public void testFRefFields() { + String src = +""" +// A hypothetical scanner class +struct Scan { + int !x; + u8[~] !buf; + // Skip whitespace + val skip = { !Scan s -> + while( s.buf[s.x] <= ' ' ) + s.x++; + }; + // Peek a character; if matched consume it, else false. + val peek = { !Scan !s, u8 c -> + skip(s); + if( s.buf[s.x] != c ) return false; + s.x++; + return true; + }; +}; +!Scan !s = new Scan{ buf = " q"; }; +return Scan.peek(s,'q'); +"""; + + CodeGen code = new CodeGen(src).parse().opto().typeCheck(); + assertEquals("return Phi(Region,0,1);", code._stop.toString()); + assertEquals("1", Eval2.eval(code, 0)); + testCPU(src,"x86_64_v2", "Win64" ,23,null); + }; + + @Test + public void testFRefFields2() { + String src = +""" +// A hypothetical scanner class +struct Scan { + int !x; + u8[~] !buf; + // Skip whitespace + val skip = { -> + while( buf[x] <= ' ' ) + x++; + return self; + }; +}; +~Scan s = new Scan{ buf = " q"; }; +return s.skip().x; +"""; + + try { new CodeGen(src).parse().opto().typeCheck(); fail(); } + catch( Exception e ) { org.junit.Assert.assertTrue(e.getMessage().startsWith("Argument #0 isa")); } + }; + + + @Test + public void testMethod() { + String src = +""" +// A hypothetical scanner class +struct Scan { + int !x; + u8[~] !buf; + // Skip whitespace + val skip = { -> + while( buf[x] <= ' ' ) + x++; + }; + val require = { u8 ch -> + skip(); + buf[x++]==ch; + }; +}; +!Scan !s = new Scan{ buf = " [1,2]"; }; +return s.require('['); +"""; + + CodeGen code = new CodeGen(src).parse().opto().typeCheck(); + assertEquals("return (.[]==91);", code._stop.toString()); + assertEquals("1", Eval2.eval(code, 0)); + testCPU(src,"x86_64_v2", "Win64" ,4,null); + }; + + @Test + public void testSCCP0() { + String src = +""" +int x = 1; +int cnt = 5; +while (cnt) { + cnt -= 1; + if (x == 0) { + x += 1; + } +} +return x; +"""; + CodeGen code = new CodeGen(src).parse().opto().typeCheck(); + assertEquals("return 1;", code._stop.toString()); + } + + @Test + public void testSCCP1() { + String src = +""" +int x = 1; +int cnt = 5; +while( cnt-- ) + if( x == 1 ) + x = 2-x; +return x; +"""; + CodeGen code = new CodeGen(src).parse().opto().typeCheck(); + assertEquals("return 1;", code._stop.toString()); + } + +} diff --git a/src/test/java/com/seaofnodes/simple/Eval2.java b/src/test/java/com/seaofnodes/simple/Eval2.java index 908cc2e0..98e0f18a 100644 --- a/src/test/java/com/seaofnodes/simple/Eval2.java +++ b/src/test/java/com/seaofnodes/simple/Eval2.java @@ -319,14 +319,23 @@ public abstract class Eval2 { // Unknown-caller inputs are type placeholders, not heap constants. if( !tmp.isConstant() ) yield tmp; if( tmp._obj.isAry() ) { // Constant array ptr - TypeConAry con = (TypeConAry)tmp._obj.field("[]")._t; - Object[] xs = new Object[con.len()]; - for( int i=0; i null; diff --git a/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java b/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java index 52c0a573..e97194af 100644 --- a/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java +++ b/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java @@ -112,8 +112,7 @@ public class MemoryEncodingTest { @Test public void testEmulatedMemory() throws IOException { for( String target : new String[]{"riscv","arm"} ) for( int p=0; p + int[] !b = new int[a#]; + copy_array (a, 0, a#, b); + split_merge(a, 0, a#, b); + }; + + val split_merge = { int[] !b, int begin, int end, int[] a -> + if (end - begin <= 1) + return 0; + int middle = (end + begin) / 2; + split_merge(a, begin, middle, b); + split_merge(a, middle, end, b); + merge(b, begin, middle, end, a); + return 0; + }; + + val merge = { int[] !b, int begin, int middle, int end, int[] a -> + int i = begin, j = middle; + + for (int k = begin; k < end; k++) { + // && and || + bool cond = false; + if (i < middle) { + if (j >= end) cond = true; + else if (a[i] <= a[j]) cond = true; + } + if (cond) b[k] = a[i++]; + else b[k] = a[j++]; + } + }; + + val copy_array = { int[] !a, int begin, int end, int[] b -> + for (int k = begin; k < end; k++) + b[k] = a[k]; + }; +"""; int[] primes = new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, }; SB sb = new SB().p(primes.length).p("["); for( int prime : primes ) sb.p(prime).p(", "); String sprimes = sb.p("]").toString(); - TestC.run("sort", sprimes, 34); + TestC.run(src, "sort", null, sprimes, 34); - EvalRisc5 R5 = TestRisc5.build("src/test/java/com/seaofnodes/simple/progs", "sort", "merge_sort", 0, 36, false); + EvalRisc5 R5 = TestRisc5.build("src/test/java/com/seaofnodes/simple/progs",src, "sort", "merge_sort", 0, 36, false); // Allocate an array of primes, filled in reverse order int ps = R5._heap; R5._heap += (primes.length+1)*8; // 25 primes, and length @@ -41,7 +80,6 @@ public class MergeSortTest { assertEquals(primes[i], R5.ld8(ps+(i+1)*8)); // TODO: replace with ARM Eval - String src = Files.readString(Path.of("src/test/java/com/seaofnodes/simple/progs/sort.smp")); Chapter21Test.testCPU(src,"arm", "SystemV",36,null); } } diff --git a/src/test/java/com/seaofnodes/simple/Simple.java b/src/test/java/com/seaofnodes/simple/Simple.java index aef810d1..18804ebd 100644 --- a/src/test/java/com/seaofnodes/simple/Simple.java +++ b/src/test/java/com/seaofnodes/simple/Simple.java @@ -259,7 +259,7 @@ Options: if ( !TestC.CPU_PORT.equals( cpu ) || !TestC.CALL_CONVENTION.equals( abi ) ) throw bad("cannot run code on not native target"); String exe = TestC.OS.startsWith("Windows") ? base+".exe" : base; - String result = com.seaofnodes.simple.TestC.gcc(base+".o", null, null, true, exe); + String result = TestC.gcc(base+".o", null, null, true, exe); System.out.print(result); } } diff --git a/src/test/java/com/seaofnodes/simple/SpillStats.java b/src/test/java/com/seaofnodes/simple/SpillStats.java index 6af51b33..ad044a52 100644 --- a/src/test/java/com/seaofnodes/simple/SpillStats.java +++ b/src/test/java/com/seaofnodes/simple/SpillStats.java @@ -28,7 +28,8 @@ public class SpillStats extends RunListener { // The same native helpers serve old and new program cohorts. public static void recordNative(CodeGen code, String cpu, String abi) { - String cohort = ACTIVE!=null && ACTIVE._test.getTestClass()==Chapter23Test.class + String cohort = ACTIVE!=null && (ACTIVE._test.getTestClass()==Chapter24Test.class || ACTIVE._test.getTestClass()==Chapter24AllocTest.class) + ? "Chapter24" : ACTIVE!=null && ACTIVE._test.getTestClass()==Chapter23Test.class ? "Chapter23" : ACTIVE!=null && ACTIVE._test.getTestClass()==Chapter22Test.class ? "Chapter22" : "Chapter21"; record(code,cohort,cpu,abi); @@ -47,7 +48,7 @@ public class SpillStats extends RunListener { } public static void main(String[] args) throws ClassNotFoundException { - if( args.length==0 ) args = new String[]{"Chapter20Test","Chapter21Test","Chapter21AllocTest","Chapter22Test","Chapter23Test","Chapter23AllocTest","BrainFuckTest","MergeSortTest"}; + if( args.length==0 ) args = new String[]{"Chapter20Test","Chapter21Test","Chapter21AllocTest","Chapter22Test","Chapter23Test","Chapter23AllocTest","Chapter24Test","Chapter24AllocTest","BrainFuckTest","MergeSortTest"}; Class[] tests = new Class[args.length]; for( int i=0; i - x*x; -}; - -if(a && sq(0)) { - sys.io.p("And"); -} else { - sys.io.p("Or"); -} -return 0; diff --git a/src/test/java/com/seaofnodes/simple/progs/antiDep1.smp b/src/test/java/com/seaofnodes/simple/progs/antiDep1.smp deleted file mode 100644 index 52bfe29b..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/antiDep1.smp +++ /dev/null @@ -1,11 +0,0 @@ -// -*- mode: java; -*- -struct S { int f; }; -var v0 = new S; -!S? !v1; -if (arg) v1 = new S; -if (v1) { - v0.f = v1.f; -} else { - v0.f = 2; -} -return v0; diff --git a/src/test/java/com/seaofnodes/simple/progs/brain_fuck.smp b/src/test/java/com/seaofnodes/simple/progs/brain_fuck.smp deleted file mode 100644 index ed90cb84..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/brain_fuck.smp +++ /dev/null @@ -1,46 +0,0 @@ -// -*- mode: java; -*- -val brain_fuck = { -> - u8[] !program = new u8[106];program[0] = 43;program[1] = 43;program[2] = 43;program[3] = 43;program[4] = 43;program[5] = 43;program[6] = 43;program[7] = 43;program[8] = 91;program[9] = 62;program[10] = 43;program[11] = 43;program[12] = 43;program[13] = 43;program[14] = 91;program[15] = 62;program[16] = 43;program[17] = 43;program[18] = 62;program[19] = 43;program[20] = 43;program[21] = 43;program[22] = 62;program[23] = 43;program[24] = 43;program[25] = 43;program[26] = 62;program[27] = 43;program[28] = 60;program[29] = 60;program[30] = 60;program[31] = 60;program[32] = 45;program[33] = 93;program[34] = 62;program[35] = 43;program[36] = 62;program[37] = 43;program[38] = 62;program[39] = 45;program[40] = 62;program[41] = 62;program[42] = 43;program[43] = 91;program[44] = 60;program[45] = 93;program[46] = 60;program[47] = 45;program[48] = 93;program[49] = 62;program[50] = 62;program[51] = 46;program[52] = 62;program[53] = 45;program[54] = 45;program[55] = 45;program[56] = 46;program[57] = 43;program[58] = 43;program[59] = 43;program[60] = 43;program[61] = 43;program[62] = 43;program[63] = 43;program[64] = 46;program[65] = 46;program[66] = 43;program[67] = 43;program[68] = 43;program[69] = 46;program[70] = 62;program[71] = 62;program[72] = 46;program[73] = 60;program[74] = 45;program[75] = 46;program[76] = 60;program[77] = 46;program[78] = 43;program[79] = 43;program[80] = 43;program[81] = 46;program[82] = 45;program[83] = 45;program[84] = 45;program[85] = 45;program[86] = 45;program[87] = 45;program[88] = 46;program[89] = 45;program[90] = 45;program[91] = 45;program[92] = 45;program[93] = 45;program[94] = 45;program[95] = 45;program[96] = 45;program[97] = 46;program[98] = 62;program[99] = 62;program[100] = 43;program[101] = 46;program[102] = 62;program[103] = 43;program[104] = 43;program[105] = 46; - int d = 0; - u8[] !output = new u8[0]; - u8[] !data = new u8[100]; - - for( int pc = 0; pc < program#; pc++ ) { - var command = program[pc]; - if (command == 62) { - d++; - } else if (command == 60) { - d--; - } else if (command == 43) { - data[d]++; - } else if (command == 45) { - data[d]--; - } else if (command == 46) { - // Output a byte; increase the output array size - var old = output; - output = new u8[output# + 1]; - for( int i = 0; i < old#; i++ ) - output[i] = old[i]; - output[old#] = data[d]; // Add the extra byte on the end - } else if (command == 44) { - data[d] = 42; - } else if (command == 91) { - if (data[d] == 0) { - for( int d = 1; d > 0; ) { - command = program[++pc]; - if (command == 91) d++; - if (command == 93) d--; - } - } - } else if (command == 93) { - if (data[d]) { - for( int d = 1; d > 0; ) { - command = program[--pc]; - if (command == 93) d++; - if (command == 91) d--; - } - } - } - } - return output; -}; diff --git a/src/test/java/com/seaofnodes/simple/progs/echo.smp b/src/test/java/com/seaofnodes/simple/progs/echo.smp deleted file mode 100644 index 8eafd73b..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/echo.smp +++ /dev/null @@ -1,3 +0,0 @@ -// -*- mode: java; -*- -// Echo stdin to stdout. -return sys.io.p( sys.io.stdin() ); diff --git a/src/test/java/com/seaofnodes/simple/progs/fib.smp b/src/test/java/com/seaofnodes/simple/progs/fib.smp deleted file mode 100644 index 1512541b..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/fib.smp +++ /dev/null @@ -1,11 +0,0 @@ -// -*- mode: java; -*- -val fib = {int n -> - int f1=1; - int f2=1; - while( n-- > 1 ){ - int temp = f1+f2; - f1=f2; - f2=temp; - } - return f2; -}; \ No newline at end of file diff --git a/src/test/java/com/seaofnodes/simple/progs/helloWorld.smp b/src/test/java/com/seaofnodes/simple/progs/helloWorld.smp deleted file mode 100644 index 07ff935f..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/helloWorld.smp +++ /dev/null @@ -1,3 +0,0 @@ -// -*- mode: java; -*- -sys.io.p("Hello, World!"); -return 0; diff --git a/src/test/java/com/seaofnodes/simple/progs/large.smp b/src/test/java/com/seaofnodes/simple/progs/large.smp deleted file mode 100644 index 73271e66..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/large.smp +++ /dev/null @@ -1,5344 +0,0 @@ - -struct stbi_io_callbacks { - { i64 u8[] int -> int } read = "C"; // fill 'data' with 'size' bytes. return number of bytes actually read - { i64 int -> int } skip = "C"; // skip the next 'n' bytes, or 'unget' the last -n bytes if negative - { i64 -> int } eof = "C"; // returns nonzero if we are at end of file/data -}; - -struct stbi__context { - u32 img_x, img_y; - int img_n, img_out_n; - - !stbi_io_callbacks !io; - u8[]io_user_data; - - int read_from_callbacks; - int buflen; - u8[] buffer_start; - int callback_already_read; - - u8[] img_buffer; - int img_buffer_end; - u8[] img_buffer_original; - int img_buffer_original_end; -}; - -{ stbi__context -> u8 } stbi__get8 = "C"; - -val sample = { !stbi__context !s, int pal_len -> - var palette = new u8[1024]; - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - for (int i=0; i < pal_len; ++i) { - palette[i*4+3] = 0; - - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - for (int j=0; j < pal_len; ++j) { - palette[j*4+3] = 0; - - palette[j*4+0] = stbi__get8(s); - palette[j*4+1] = stbi__get8(s); - palette[j*4+2] = stbi__get8(s); - palette[j*4+3] = 255; - } - } - - return palette; -}; diff --git a/src/test/java/com/seaofnodes/simple/progs/loop2.smp b/src/test/java/com/seaofnodes/simple/progs/loop2.smp deleted file mode 100644 index 01ec827e..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/loop2.smp +++ /dev/null @@ -1,10 +0,0 @@ -// -*- mode: java; -*- -int i = 0; -while(true) { - i += 1; - if( i==0 ) continue; - if( i==1 ) continue; - if( i==2 ) break; - continue; -} -return i; diff --git a/src/test/java/com/seaofnodes/simple/progs/or1.smp b/src/test/java/com/seaofnodes/simple/progs/or1.smp deleted file mode 100644 index f5f526c3..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/or1.smp +++ /dev/null @@ -1,12 +0,0 @@ -// -*- mode: java; -*- -int a = 1; -int b = 0; - -if(a++ || b++ ) { - if(b == 0 && a == 2) { - sys.io.p("Or"); - } -} else{ - sys.io.p("And"); -} -return 0; diff --git a/src/test/java/com/seaofnodes/simple/progs/or2.smp b/src/test/java/com/seaofnodes/simple/progs/or2.smp deleted file mode 100644 index ac688b5a..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/or2.smp +++ /dev/null @@ -1,23 +0,0 @@ -// -*- mode: java; -*- -int a = 1; -int b = 1; - -int x = -1; -int y=1; -int z= -1; - -int g = x++ || y++ || z++; - -int switch = 0; -if(x == 4 || y == 4 || z == 4) { - switch = -1; -} else { - switch = 1; -} -int cd = 1; -if((x == 0 && y == 1 && z==-1) && switch && g) { - sys.io.p("Effected"); -} else { - sys.io.p("Not effected"); -} -return 0; diff --git a/src/test/java/com/seaofnodes/simple/progs/person.smp b/src/test/java/com/seaofnodes/simple/progs/person.smp deleted file mode 100644 index 94e2cdde..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/person.smp +++ /dev/null @@ -1,9 +0,0 @@ -// -*-java-*- -struct Person { - i32 age; -}; - -val fcn = { !Person?[] ps, int x -> - if( ps[x] ) - ps[x].age++; -}; \ No newline at end of file diff --git a/src/test/java/com/seaofnodes/simple/progs/print.smp b/src/test/java/com/seaofnodes/simple/progs/print.smp deleted file mode 100644 index 3bb86268..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/print.smp +++ /dev/null @@ -1,8 +0,0 @@ -int x = 1; - -int y = 2; -if(x == 1) { -y = 1; -} - -return y; \ No newline at end of file diff --git a/src/test/java/com/seaofnodes/simple/progs/ptrand.smp b/src/test/java/com/seaofnodes/simple/progs/ptrand.smp deleted file mode 100644 index 8b8af571..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/ptrand.smp +++ /dev/null @@ -1,10 +0,0 @@ -struct S { !S? !fld; }; - -val ptr = arg == 1 ? null : new S{fld = arg==1 ? null : new S{fld = null;};}; -if( ptr && ptr.fld ) { - sys.io.p("true"); -} else { - sys.io.p("false"); -} - -return 0; diff --git a/src/test/java/com/seaofnodes/simple/progs/riscv_load.smp b/src/test/java/com/seaofnodes/simple/progs/riscv_load.smp deleted file mode 100644 index 1a36fb99..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/riscv_load.smp +++ /dev/null @@ -1,4 +0,0 @@ -struct Person { i32 age;}; -!Person !p = new Person; -p.age += arg; -return p.age; diff --git a/src/test/java/com/seaofnodes/simple/progs/sext_str_1.smp b/src/test/java/com/seaofnodes/simple/progs/sext_str_1.smp deleted file mode 100644 index 57b37477..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/sext_str_1.smp +++ /dev/null @@ -1,4 +0,0 @@ -struct Person {i64 age;} -!Person !p = new Person; -p.age += arg; -return p.age; diff --git a/src/test/java/com/seaofnodes/simple/progs/sext_str_fold_away.smp b/src/test/java/com/seaofnodes/simple/progs/sext_str_fold_away.smp deleted file mode 100644 index 7d7fdce7..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/sext_str_fold_away.smp +++ /dev/null @@ -1,5 +0,0 @@ -// Should fold away sign extend -struct Person { i8 age;}; -!Person !p = new Person; -p.age = (arg<<48)>>48; -return 0; \ No newline at end of file diff --git a/src/test/java/com/seaofnodes/simple/progs/sext_str_not_fold_away.smp b/src/test/java/com/seaofnodes/simple/progs/sext_str_not_fold_away.smp deleted file mode 100644 index 4d6ca3a3..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/sext_str_not_fold_away.smp +++ /dev/null @@ -1,4 +0,0 @@ -struct Person { i32 age;}; -!Person !p = new Person; -p.age = (arg<<17)>>17; -return 0; \ No newline at end of file diff --git a/src/test/java/com/seaofnodes/simple/progs/sext_str_not_fold_away_2.smp b/src/test/java/com/seaofnodes/simple/progs/sext_str_not_fold_away_2.smp deleted file mode 100644 index 5c96c060..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/sext_str_not_fold_away_2.smp +++ /dev/null @@ -1,4 +0,0 @@ -struct Person { i32 age;}; -!Person !p = new Person; -p.age = (arg<<48)>>48; -return 0; \ No newline at end of file diff --git a/src/test/java/com/seaofnodes/simple/progs/sieve.smp b/src/test/java/com/seaofnodes/simple/progs/sieve.smp deleted file mode 100644 index 569dbb96..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/sieve.smp +++ /dev/null @@ -1,31 +0,0 @@ -// -*- mode: java; -*- -val sieve = { int N -> - // The main Sieve array - bool[] !ary = new bool[N]; - // The primes less than N - u32[] !primes = new u32[N>>1]; - // Number of primes so far, searching at index p - int nprimes = 0, p=2; - // Find primes while p^2 < N - while( p*p < N ) { - // skip marked non-primes - while( ary[p] ) p++; - // p is now a prime - primes[nprimes++] = p; - // Mark out the rest non-primes - for( int i = p + p; i < ary#; i+= p ) - ary[i] = true; - p++; - } - - // Now just collect the remaining primes, no more marking - for( ; p < N; p++ ) - if( !ary[p] ) - primes[nprimes++] = p; - - // Copy/shrink the result array - u32[] !rez = new u32[nprimes]; - for( int j=0; j < nprimes; j++ ) - rez[j] = primes[j]; - return rez; -}; diff --git a/src/test/java/com/seaofnodes/simple/progs/sort.smp b/src/test/java/com/seaofnodes/simple/progs/sort.smp deleted file mode 100644 index ae3f4f23..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/sort.smp +++ /dev/null @@ -1,38 +0,0 @@ -// -*- mode: java; -*- -// based on the top-down version from https://en.wikipedia.org/wiki/Merge_sort - -val merge_sort = { int[] a -> - int[] !b = new int[a#]; - copy_array (a, 0, a#, b); - split_merge(a, 0, a#, b); -}; - -val split_merge = { int[] b, int begin, int end, int[] a -> - if (end - begin <= 1) - return 0; - int middle = (end + begin) / 2; - split_merge(a, begin, middle, b); - split_merge(a, middle, end, b); - merge(b, begin, middle, end, a); - return 0; -}; - -val merge = { int[] b, int begin, int middle, int end, int[] a -> - int i = begin, j = middle; - - for (int k = begin; k < end; k++) { - // && and || - bool cond = false; - if (i < middle) { - if (j >= end) cond = true; - else if (a[i] <= a[j]) cond = true; - } - if (cond) b[k] = a[i++]; - else b[k] = a[j++]; - } -}; - -val copy_array = { int[] a, int begin, int end, int[] b -> - for (int k = begin; k < end; k++) - b[k] = a[k]; -}; diff --git a/src/test/java/com/seaofnodes/simple/progs/stacked_r_10x.c b/src/test/java/com/seaofnodes/simple/progs/stacked_r_10x.c new file mode 100644 index 00000000..d44d5387 --- /dev/null +++ b/src/test/java/com/seaofnodes/simple/progs/stacked_r_10x.c @@ -0,0 +1,13 @@ +#include +#include +#include + +__attribute__ ((CALL_CONV)) +extern int stack10(int x); + +int main() { +int result = stack10(0); + +printf("%d", result); +return 0; +} \ No newline at end of file diff --git a/src/test/java/com/seaofnodes/simple/progs/stacked_r_11x.c b/src/test/java/com/seaofnodes/simple/progs/stacked_r_11x.c new file mode 100644 index 00000000..d71979d1 --- /dev/null +++ b/src/test/java/com/seaofnodes/simple/progs/stacked_r_11x.c @@ -0,0 +1,13 @@ +#include +#include +#include + +__attribute__ ((CALL_CONV)) +extern int stack11(int x); + +int main() { +int result = stack11(1); + +printf("%d", result); +return 0; +} \ No newline at end of file diff --git a/src/test/java/com/seaofnodes/simple/progs/stacked_r_12x.c b/src/test/java/com/seaofnodes/simple/progs/stacked_r_12x.c new file mode 100644 index 00000000..a4e425cb --- /dev/null +++ b/src/test/java/com/seaofnodes/simple/progs/stacked_r_12x.c @@ -0,0 +1,13 @@ +#include +#include +#include + +__attribute__ ((CALL_CONV)) +extern int stack12(int x); + +int main() { +int result = stack12(0); + +printf("%d", result); +return 0; +} \ No newline at end of file diff --git a/src/test/java/com/seaofnodes/simple/progs/stacked_r_13x.c b/src/test/java/com/seaofnodes/simple/progs/stacked_r_13x.c new file mode 100644 index 00000000..a3a51d0e --- /dev/null +++ b/src/test/java/com/seaofnodes/simple/progs/stacked_r_13x.c @@ -0,0 +1,13 @@ +#include +#include +#include + +__attribute__ ((CALL_CONV)) +extern int stack13(int x); + +int main() { +int result = stack13(0); + +printf("%d", result); +return 0; +} \ No newline at end of file diff --git a/src/test/java/com/seaofnodes/simple/progs/stacked_r_9x.c b/src/test/java/com/seaofnodes/simple/progs/stacked_r_9x.c new file mode 100644 index 00000000..4f93ba24 --- /dev/null +++ b/src/test/java/com/seaofnodes/simple/progs/stacked_r_9x.c @@ -0,0 +1,13 @@ +#include +#include +#include + +__attribute__ ((CALL_CONV)) +extern int stack9(int x); + +int main() { +int result = stack9(0); + +printf("%d", result); +return 0; +} \ No newline at end of file diff --git a/src/test/java/com/seaofnodes/simple/progs/store_peep.smp b/src/test/java/com/seaofnodes/simple/progs/store_peep.smp deleted file mode 100644 index c3feddd5..00000000 --- a/src/test/java/com/seaofnodes/simple/progs/store_peep.smp +++ /dev/null @@ -1,3 +0,0 @@ -i64 a = 123456789012345; -i32 b = a; // truncate high order bits -return b; \ No newline at end of file -- cgit v1.2.3