summaryrefslogtreecommitdiff
path: root/chapter22/src
diff options
context:
space:
mode:
Diffstat (limited to 'chapter22/src')
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/Parser.java7
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java9
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/codegen/Encoding.java70
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/CastNode.java5
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java10
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java79
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/sys/sys.smp2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/type/Type.java1
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/type/TypeConAry.java5
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/type/TypeConAryB.java4
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/type/TypeStruct.java45
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/Chapter15Test.java4
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java4
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/progs/helloWorld.smp4
14 files changed, 168 insertions, 81 deletions
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/Parser.java b/chapter22/src/main/java/com/seaofnodes/simple/Parser.java
index 9d313046..ab2c775c 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/Parser.java
@@ -656,6 +656,9 @@ public class Parser {
t = tmp.makeRO();
expr = peep(new ReadOnlyNode(expr));
}
+ // Auto-widen array to i64
+ if( t == TypeInteger.BOT && expr._type instanceof TypeMemPtr tmp && tmp._obj.isAry() )
+ expr = peep(new AddNode(peep(new CastNode(t,ctrl(),expr)),con(tmp._obj.aryBase())));
// Auto-widen int to float
expr = widenInt( expr, t );
// Auto-narrow wide ints to narrow ints
@@ -678,7 +681,10 @@ public class Parser {
* exprAsgn = var '=' exprAsgn | expr
*/
private Node parseDeclarationStatement() {
+ int old = pos();
Type t = type();
+ if( peek('.') ) // Ambiguity static vars: "type.var", parse as expression
+ { pos(old); t=null; }
if( t == null )
return require(parseAsgn(),";");
@@ -1123,7 +1129,6 @@ public class Parser {
return init.in(idx);
}
-
// Expect an identifier now
Var n = requireLookupId();
Node rvalue = _scope.in(n);
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java b/chapter22/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java
index 746ecfed..0eaaae7b 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java
@@ -273,8 +273,6 @@ public class ElfFile {
int start_global = num+1; // Add one to skip the final .rela.text local symbol
for( Symbol a: symbols._symbols )
a._index = start_global++;
- int bigConIdx = start_global;
- start_global += enc._bigCons.size();
// create .text relocations
DataSection text_rela = new DataSection(".rela.text", 4 /* SHT_RELA */);
@@ -298,10 +296,10 @@ public class ElfFile {
// Write relocations for the constant pool
for( Encoding.Relo relo : enc._bigCons.values() ) {
- Symbol glob = new Symbol("GLOB$"+bigConIdx, rdata._index, SYM_BIND_GLOBAL, SYM_TYPE_FUNC);
+ Symbol glob = new Symbol("CPOOL$"+start_global, rdata._index, SYM_BIND_GLOBAL, SYM_TYPE_FUNC);
glob._value = relo._target;
- glob._size = 1 << relo._t.log_size();
- glob._index = bigConIdx++;
+ glob._size = relo._t.size();
+ glob._index = start_global++;
symbols.push(glob);
write8(text_rela._contents, relo._opStart+relo._off);
write8(text_rela._contents, ((long)glob._index << 32L) | relo._elf );
@@ -313,6 +311,7 @@ public class ElfFile {
text_rela._info = text._index;
pushSection(text_rela);
+ // Final .rela.text symbol
Symbol sym = new Symbol(text_rela._name, num++, SYM_BIND_LOCAL, SYM_TYPE_SECTION);
sym._name_pos = text_rela._name_pos;
sym._size = text_rela.size();
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/codegen/Encoding.java b/chapter22/src/main/java/com/seaofnodes/simple/codegen/Encoding.java
index 693c4077..722320e8 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/codegen/Encoding.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/codegen/Encoding.java
@@ -51,7 +51,7 @@ public class Encoding {
public final Type _t; // Constant type
public final byte _off; // Offset from start of opcode
public final byte _elf; // ELF relocation type, e.g. 2/PC32
- public int _target; // Where constant is finally placede
+ public int _target; // Where constant is finally placed
public int _opStart; // Opcode start
Relo( Node op, Type t, byte off, byte elf ) {
_op=op; _t=t; _off=off; _elf=elf;
@@ -440,28 +440,56 @@ public class Encoding {
// By alignment
for( int align = 4; align >= 0; align-- ) {
Ary<Relo> relos = raligns[align];
- if( relos != null )
- for( Relo relo : relos ) {
- // Map from relo to constant start and patch
- Integer target = targets.get(relo._t);
- if( target==null ) {
- targets.put(relo._t,target = bits.size());
- // Put constant into code space.
- if( relo._t instanceof TypeTuple tt ) // Constant tuples put all entries at same alignment
- for( Type tx : tt._types )
- addN(align,tx,bits);
- else if( relo._t instanceof TypeStruct ts ) {
- int alignX = ts.alignment();
- throw Utils.TODO();
- } else // Simple primitive (e.g. larger int, float)
- addN(align,relo._t,bits);
+ if( relos == null ) continue;
+ for( Relo relo : relos ) {
+ // Map from relo to constant start and patch
+ Integer target = targets.get(relo._t);
+ if( target==null ) {
+ targets.put(relo._t,target = bits.size());
+ // Write constant into constant pool
+ switch( relo._t ) {
+ case TypeTuple tt -> cpool(align,bits,tt);
+ case TypeStruct ts -> cpool(bits,ts);
+ // Simple primitive (e.g. larger int, float)
+ default -> addN(align,relo._t,bits);
}
- relo._target = target;
- relo._opStart= _opStart[relo._op._nid];
- // Go ahead and locally patch in-memory
- if( patch )
- ((RIPRelSize)relo._op).patch(this, relo._opStart, _opLen[relo._op._nid], relo._target - relo._opStart);
}
+ // Record target address and opcode start
+ relo._target = target;
+ relo._opStart= _opStart[relo._op._nid];
+ // Go ahead and locally patch in-memory
+ if( patch )
+ ((RIPRelSize)relo._op).patch(this, relo._opStart, _opLen[relo._op._nid], relo._target - relo._opStart);
+ }
+ }
+ }
+
+ // Constant tuples put all entries at same alignment
+ private void cpool(int align, BAOS bits, TypeTuple tt) {
+ for( Type tx : tt._types )
+ addN(align,tx,bits);
+ }
+
+ // Structs use internal field layout
+ private void cpool( BAOS bits, TypeStruct ts ) {
+ // Field order by offset
+ int[] layout = ts.layout();
+ int off=0; // offset in the struct
+ for( int fn=0; fn<ts._fields.length; fn++ ) {
+ Field f = ts._fields[layout[fn]];
+ int foff = ts. offset(layout[fn]);
+ // Pad up to field
+ while( off < foff ) { bits.write(0); off++; };
+ // Constant array fields are special
+ if( f._fname=="[]" ) { // Must be a constant array
+ ts._con.write(bits); // Write the constant array bits
+ off += ts._con.len();
+ } else {
+ int log = f._type.log_size();
+ if( f._fname=="#" ) addN(log,ts._con.len(),bits); // Must be a constant array
+ else addN(log,f._type ,bits);
+ off += 1<<log;
+ }
}
}
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/CastNode.java b/chapter22/src/main/java/com/seaofnodes/simple/node/CastNode.java
index 0947bcf0..8d8f0257 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/CastNode.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/CastNode.java
@@ -4,6 +4,8 @@ import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeInteger;
+import com.seaofnodes.simple.type.TypeMemPtr;
+
import java.util.BitSet;
// Upcast (join) the input to a t. Used after guard test to lift an input.
@@ -37,6 +39,9 @@ public class CastNode extends Node {
@Override
public Type compute() {
+ // Cast array to int
+ if( _t == TypeInteger.BOT && in(1)._type instanceof TypeMemPtr tmp && tmp._obj.isAry() )
+ return _t;
return in(1)._type.join(_t);
}
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java
index 00219576..70b9dbb0 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java
@@ -6,7 +6,6 @@ import com.seaofnodes.simple.node.*;
import com.seaofnodes.simple.type.TypeMemPtr;
public class TMPX86 extends ConstantNode implements MachNode, RIPRelSize{
- private byte _encSize;
TMPX86(ConstantNode con ) { super(con); }
@Override public String op() { return "ldp"; }
@Override public RegMask regmap(int i) { return null; }
@@ -16,16 +15,13 @@ public class TMPX86 extends ConstantNode implements MachNode, RIPRelSize{
@Override public void encoding( Encoding enc ) {
short dst = enc.reg(this);
- _encSize = (byte)(x86_64_v2.rexF(dst, 0, 0, false, enc) + 1/*Op*/ + 1/*MODRM*/ + 4/*offset*/);
+ x86_64_v2.rexF(dst, 0, 0, true, enc);
enc.add1(0x8D).add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0b101)).add4(0);
- enc.largeConstant(this,((TypeMemPtr)_con)._obj,_encSize-4,2/*ELF encoding PC32*/);
+ enc.largeConstant(this,((TypeMemPtr)_con)._obj,7-4,2/*ELF encoding PC32*/);
}
// Delta is from opcode start
- @Override public byte encSize(int delta) {
- // TODO: 1-byte RIP offset?
- return (byte)_encSize;
- }
+ @Override public byte encSize(int delta) { return (byte)7; }
// Delta is from opcode start
@Override public void patch( Encoding enc, int opStart, int opLen, int delta ) {
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java b/chapter22/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java
index da269d31..3b946cb5 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java
@@ -1,9 +1,11 @@
package com.seaofnodes.simple.print;
+import com.seaofnodes.simple.Ary;
import com.seaofnodes.simple.SB;
import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.codegen.Encoding;
+import com.seaofnodes.simple.codegen.Encoding.Relo;
import com.seaofnodes.simple.node.*;
import com.seaofnodes.simple.type.*;
import java.util.HashSet;
@@ -25,49 +27,70 @@ public abstract class ASMPrinter {
iadr++;
// constant pool
+ iadr = (iadr+15)&-16; // pad to 16
Encoding enc = code._encoding;
- if( enc!=null && !enc._bigCons.isEmpty() ) {
- iadr = (iadr+15)&-16; // pad to 16
+ if( enc!=null && !enc._bigCons.isEmpty() && iadr < enc._bits.size() ) {
+ // radix sort the big constants by alignment
+ Ary<Relo>[] raligns = new Ary[5];
+ for( Node op : enc._bigCons.keySet() ) {
+ Relo relo = enc._bigCons.get(op);
+ int align = relo._t.alignment();
+ Ary<Relo> relos = raligns[align]==null ? (raligns[align]=new Ary<>( Relo.class)) : raligns[align];
+ relos.add(relo);
+ }
+
HashSet<Type> targets = new HashSet<>();
sb.p("--- Constant Pool ------").nl();
- // By log size
- for( int log = 3; log >= 0; log-- ) {
- for( Node op : enc._bigCons.keySet() ) {
- Encoding.Relo relo = enc._bigCons.get(op);
+
+ // By alignment
+ for( int align = 4; align >= 0; align-- ) {
+ Ary<Relo> relos = raligns[align];
+ if( relos == null ) continue;
+ for( Relo relo : relos ) {
if( targets.contains(relo._t) ) continue;
targets.add(relo._t);
- if( relo._t.log_size()==log ) {
- sb.hex2(iadr).p(" ");
- if( relo._t instanceof TypeTuple tt ) {
- for( Type tx : tt._types ) {
- switch( log ) {
- case 0: sb.hex1(enc.read1(iadr)); break;
- case 1: sb.hex2(enc.read2(iadr)); break;
- case 2: sb.hex4(enc.read4(iadr)); break;
- case 3: sb.hex8(enc.read8(iadr)); break;
- }
- iadr += (1<<log);
- sb.p(" ");
- }
- } else {
- switch( log ) {
- case 0: sb.hex1(enc.read1(iadr)).fix(9-1,""); break;
- case 1: sb.hex2(enc.read2(iadr)).fix(9-2,""); break;
- case 2: sb.hex4(enc.read4(iadr)).fix(9-4,""); break;
- case 3: sb.hex8(enc.read8(iadr)).p(" "); break;
- }
- iadr += (1<<log);
+ sb.hex2(iadr).p(" ");
+ switch( relo._t ) {
+ case TypeTuple tt -> {
+ for( Type tx : tt._types ) {
+ pN(enc,sb,iadr,align).p(" ");
+ iadr += (1<<align);
}
- relo._t.print(sb).nl();
}
+
+ case TypeStruct ts -> {
+ int sz = ts.size();
+ int log = 1<<align;
+ sz = (sz + (log -1)) & -log; // Round up final padding
+ for( int i=0; i<sz; i++ )
+ sb.hex1(enc.read1(iadr++));
+ }
+
+ // Simple primitive (e.g. larger int, float)
+ default -> {
+ pN(enc,sb,iadr,align).fix(9-(1<<align),"");
+ iadr += (1<<align);
+ }
+ }
+ relo._t.print(sb).nl();
}
}
}
+ return sb;
+ }
+ private static SB pN( Encoding enc, SB sb, int iadr, int log ) {
+ switch( log ) {
+ case 0: sb.hex1(enc.read1(iadr)); break;
+ case 1: sb.hex2(enc.read2(iadr)); break;
+ case 2: sb.hex4(enc.read4(iadr)); break;
+ case 3: sb.hex8(enc.read8(iadr)); break;
+ }
return sb;
}
+
private static int print(int iadr, SB sb, CodeGen code, FunNode fun, int cfgidx) {
FunNode old=null;
if( code._encoding!=null ) {
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/sys/sys.smp b/chapter22/src/main/java/com/seaofnodes/simple/sys/sys.smp
index 6b12ba20..67de77ef 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/sys/sys.smp
+++ b/chapter22/src/main/java/com/seaofnodes/simple/sys/sys.smp
@@ -6,7 +6,7 @@ struct sys {
/** https://www.man7.org/linux/man-pages/man2/<libc call>.2.html */
struct libc {
// fd buf len -> len
- { i32 u8[~] i32 -> i32 } write = "C";
+ { i32 i64 i32 -> i32 } write = "C";
// addr len prot flags fd off -> void*
{ i64 i64 i32 i32 i32 i32 -> i64 } mmap = "C";
// mmap flags
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/type/Type.java b/chapter22/src/main/java/com/seaofnodes/simple/type/Type.java
index bc98f358..a44cdd61 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/type/Type.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/type/Type.java
@@ -223,6 +223,7 @@ public class Type {
// Size 0 means this either takes no space (such as a known-zero field)
// or isn't a scalar to be stored in memory.
public int log_size () { return 3; } // log-size of a type; log_size for a struct is usually undefined
+ public int size() { return 1<<log_size(); }
public int alignment() { return log_size(); } // alignment; for structs, max align of Fields
// ----------------------------------------------------------
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeConAry.java b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeConAry.java
index b57926bb..8a19c9d7 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeConAry.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeConAry.java
@@ -3,6 +3,7 @@ package com.seaofnodes.simple.type;
import com.seaofnodes.simple.SB;
import com.seaofnodes.simple.Utils;
import java.util.ArrayList;
+import java.io.ByteArrayOutputStream;
/**
* Represents a constant array of primitives
@@ -37,6 +38,7 @@ public class TypeConAry<A> extends Type {
return BOT;
}
+ // Meet-over-elements type
public Type elem() {
if( _ary==null )
return _any ? TOP : BOTTOM;
@@ -50,8 +52,9 @@ public class TypeConAry<A> extends Type {
return TypeInteger.make(min,max);
}
long at(int idx) { throw Utils.TODO(); }
- int len() { throw Utils.TODO(); }
+ public int len() { throw Utils.TODO(); }
@Override public int alignment() { return 0; }
+ public void write( ByteArrayOutputStream baos ) { throw Utils.TODO(); }
@Override boolean eq(Type t) {
TypeConAry ary = (TypeConAry)t; // Invariant
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeConAryB.java b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeConAryB.java
index 8a212867..34475ac1 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeConAryB.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeConAryB.java
@@ -2,6 +2,7 @@ package com.seaofnodes.simple.type;
import java.util.ArrayList;
import java.util.Arrays;
+import java.io.ByteArrayOutputStream;
public class TypeConAryB extends TypeConAry<byte[]> {
private TypeConAryB(byte[] bs) { super(false,bs); }
@@ -11,9 +12,10 @@ public class TypeConAryB extends TypeConAry<byte[]> {
static final TypeConAryB ABCD = make("abcd");
public static void gather(ArrayList<Type> ts) { ts.add(ABC); ts.add(ABCD); }
@Override long at(int idx) { return _ary[idx]; }
- @Override int len() { return _ary.length; }
+ @Override public int len() { return _ary.length; }
@Override public int alignment() { return 0; }
@Override public String str() { return "[\""+new String(_ary)+"\"]"; }
@Override boolean eq(Type t) { return Arrays.equals(_ary,((TypeConAryB)t)._ary); }
@Override int hash() { return Arrays.hashCode(_ary); }
+ @Override public void write( ByteArrayOutputStream baos ) { baos.write(_ary,0,_ary.length); }
}
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeStruct.java b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeStruct.java
index e0426e0c..827e85f0 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeStruct.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeStruct.java
@@ -205,6 +205,7 @@ public class TypeStruct extends Type {
// log_size for a struct is not defined, unless its exactly some power of
// 2. *Total size* is well-defined, and is available in the offsets.
@Override public int log_size() { throw Utils.TODO(); }
+ @Override public int size() { return offset(_fields.length); }
@Override public int alignment() {
int align = 0;
for( Field f : _fields )
@@ -251,7 +252,7 @@ public class TypeStruct extends Type {
@Override public String str() { return _con==TypeConAry.BOT ? _name : _con.str(); }
- public boolean isAry() { return _fields.length==2 && _fields[1]._fname.equals("[]"); }
+ public boolean isAry() { return _fields.length>=2 && _fields[_fields.length-1]._fname=="[]"; }
public int aryBase() {
assert isAry();
@@ -274,14 +275,12 @@ public class TypeStruct extends Type {
// Compute a layout for a collection of fields
assert _fields != null; // No forward refs
- // Array layout is different: len,[pad],body...
- if( isAry() )
- return _offs = new int[]{ 0, _fields[1]._type.log_size() < 3 ? 4 : 8 };
-
// Compute a layout
- int[] cnts = new int[4]; // Count of fields at log field size
- for( Field f : _fields )
- cnts[f._type.log_size()]++; // Log size is 0(byte), 1(i16/u16), 2(i32/f32), 3(i64/dbl)
+ int[] cnts = new int[5]; // Count of fields at log field size
+ int flen = _fields.length;
+ if( isAry() ) flen--; // Array field is aligned differently
+ for( int i=0; i<flen; i++ )
+ cnts[_fields[i]._type.log_size()]++; // Log size is 0(byte), 1(i16/u16), 2(i32/f32), 3(i64/dbl)
int off = 0, idx = 0; // Base common struct fields go here, e.g. Mark/Klass
// Compute offsets to the start of each power-of-2 aligned fields.
int[] offs = new int[4];
@@ -292,14 +291,38 @@ public class TypeStruct extends Type {
// Assign offsets to all fields.
// Really a hidden radix sort.
_offs = new int[_fields.length+1];
- for( Field f : _fields ) {
- int log = f._type.log_size();
+ for( int i=0; i<flen; i++ ) {
+ int log = _fields[i]._type.log_size();
_offs[idx++] = offs[log]; // Field offset
offs[log] += 1<<log; // Next field offset at same alignment
cnts[log]--; // Count down, should be all zero at end
}
- _offs[_fields.length] = (off+7)& ~7; // Round out to max alignment
+
+ // Array bits
+ if( isAry() ) {
+ // Pad out to the element alignment
+ int align = (_fields[flen]._fname!="[]" || _con==TypeConAry.BOT ? _fields[flen]._type : _con).alignment();
+ off = (off + ((1<<align)-1)) & -(1<<align);
+ _offs[flen] = off;
+ if( _con!=TypeConAry.BOT )
+ _offs[flen+1] = off+_con.len();
+ } else
+ _offs[flen] = off; // Max struct size, no trailing padding
return _offs;
}
+ // Field order with increasing offset
+ public int[] layout() {
+ offset(0);
+ int len = _offs.length;
+ int[] is = new int[len];
+ for( int i=0; i<len; i++ ) is[i] = i;
+ // Stoopid hand rolled bubble sort
+ for( int i=0; i<len; i++ )
+ for( int j=i+1; j<len; j++ )
+ if( _offs[is[j]] < _offs[is[i]] )
+ { int tmp = is[i]; is[i] = is[j]; is[j] = tmp; }
+ return is;
+ }
+
}
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter15Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter15Test.java
index cebbf4a0..a98e62d8 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter15Test.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter15Test.java
@@ -253,10 +253,10 @@ return new flt;
public void testBad1() {
CodeGen code = new CodeGen(
"""
-int is = new int[2];
+flt is = new int[2];
""");
try { code.parse().opto(); fail(); }
- catch( Exception e ) { assertEquals("Type *[int] is not of declared type int",e.getMessage()); }
+ catch( Exception e ) { assertEquals("Type *[int] is not of declared type flt",e.getMessage()); }
}
@Test
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java
index b99a01a6..de9c35c7 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java
@@ -33,7 +33,7 @@ public class Chapter22Test {
@Test public void testJig1() throws IOException {
- EvalRisc5 R5 = TestRisc5.build("riscv_load", 0, 0, true);
+ EvalRisc5 R5 = TestRisc5.build("riscv_load", 0, 0, false);
int trap = R5.step(100);
assertEquals(0,trap);
// do assertEquals here
@@ -108,7 +108,7 @@ return cc.cz;
@Test @Ignore
public void testHelloWorld() throws IOException {
String src = Files.readString(Path.of("src/test/java/com/seaofnodes/simple/progs/helloWorld.smp"));
- TestC.run(src,TestC.CALL_CONVENTION,null,null,"build/objs/helloWorld","","Hello, World!",13);
+ TestC.run(src,TestC.CALL_CONVENTION,null,null,"build/objs/helloWorld","","Hello, World!",0);
}
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/progs/helloWorld.smp b/chapter22/src/test/java/com/seaofnodes/simple/progs/helloWorld.smp
index 16ef4bc6..b83a055c 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/progs/helloWorld.smp
+++ b/chapter22/src/test/java/com/seaofnodes/simple/progs/helloWorld.smp
@@ -1,2 +1,4 @@
// -*- mode: java; -*-
-return sys.libc.write(1,"Hello, World!",13);
+i64 buf = "Hello, World!";
+sys.libc.write(1,buf,13);
+return 0;