summaryrefslogtreecommitdiff
path: root/chapter23/src/main
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-09-28 16:25:01 -0700
committerCliff Click <cliffc@acm.org>2026-09-28 16:25:01 -0700
commit41be002e89358649da46c33c8245aa786afdad6a (patch)
treefcd5fb874fe4c5596ba8fcaa45b82eede5ac558e /chapter23/src/main
parent75390f477ac7d4568ac02f97358d146ff9879d6e (diff)
downloadSimple-41be002e89358649da46c33c8245aa786afdad6a.tar.gz
Simple-41be002e89358649da46c33c8245aa786afdad6a.zip
Extend smaller-width C results to full width
Diffstat (limited to 'chapter23/src/main')
-rw-r--r--chapter23/src/main/java/com/seaofnodes/simple/codegen/Machine.java11
-rw-r--r--chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java30
-rw-r--r--chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java7
-rw-r--r--chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java31
-rw-r--r--chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java2
-rw-r--r--chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java33
-rw-r--r--chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java2
7 files changed, 115 insertions, 1 deletions
diff --git a/chapter23/src/main/java/com/seaofnodes/simple/codegen/Machine.java b/chapter23/src/main/java/com/seaofnodes/simple/codegen/Machine.java
index 2766414f..a95faefc 100644
--- a/chapter23/src/main/java/com/seaofnodes/simple/codegen/Machine.java
+++ b/chapter23/src/main/java/com/seaofnodes/simple/codegen/Machine.java
@@ -2,6 +2,7 @@ package com.seaofnodes.simple.codegen;
import com.seaofnodes.simple.node.*;
import com.seaofnodes.simple.type.TypeFunPtr;
+import com.seaofnodes.simple.type.TypeInteger;
abstract public class Machine {
// Human readable machine name. Something like "x86-64" or "arm" or "risc5"
@@ -94,4 +95,14 @@ Pre-alloc Post-Alloc SP+48 RPC
// registers.
public abstract short maxArgSlot(TypeFunPtr tfp);
+ // Only the declared C result width describes the physical return register.
+ // Simple functions already return canonical full-width integer values.
+ protected static TypeInteger cReturn(ProjNode prj) {
+ if( prj._idx==2 && prj.in(0) instanceof CallEndNode cend &&
+ cend.call().fptr() instanceof ExternNode ext &&
+ ((TypeFunPtr)ext._con).ret() instanceof TypeInteger ret && ret.log_size()<3 )
+ return ret;
+ return null;
+ }
+
}
diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java
new file mode 100644
index 00000000..26a237d0
--- /dev/null
+++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java
@@ -0,0 +1,30 @@
+package com.seaofnodes.simple.node.cpus.arm;
+
+import com.seaofnodes.simple.codegen.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.TypeInteger;
+import com.seaofnodes.simple.util.SB;
+
+// Convert a narrow C return register to Simple's full-width integer value.
+public class ExtendARM extends MachConcreteNode {
+ final int _bits;
+ final boolean _signed;
+ ExtendARM(ProjNode prj, TypeInteger ret) {
+ super(prj);
+ _inputs.set(0,null);
+ _inputs.add(new ProjARM(prj));
+ _bits = 8 << ret.log_size();
+ _signed = ret._min < 0;
+ }
+ @Override public String op() { return (_signed ? "sext" : "zext")+_bits; }
+ @Override public RegMask regmap(int i) { return arm.RMASK; }
+ @Override public RegMask outregmap() { return arm.WMASK; }
+ @Override public void encoding(Encoding enc) {
+ short dst = enc.reg(this), src = enc.reg(in(1));
+ // SBFM/UBFM aliases: sign/zero extend the low byte, short or int.
+ enc.add4(arm.imm_shift(_signed ? arm.OPI_ASR : arm.OPI_LSR,0,_bits-1,src,dst));
+ }
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1)));
+ }
+}
diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java
index db179754..bca3dfa4 100644
--- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java
+++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java
@@ -674,7 +674,7 @@ public class arm extends Machine {
case OrNode or -> or(or);
case ParmNode parm -> new ParmARM(parm);
case PhiNode phi -> new PhiNode(phi);
- case ProjNode prj -> new ProjARM(prj);
+ case ProjNode prj -> prj(prj);
case ReadOnlyNode read -> new ReadOnlyMach(read);
case ReturnNode ret -> new RetARM(ret,ret.fun());
case SarNode sar -> asr(sar);
@@ -818,4 +818,9 @@ public class arm extends Machine {
}
+ private Node prj(ProjNode prj) {
+ TypeInteger ret = cReturn(prj);
+ return ret==null ? new ProjARM(prj) : new ExtendARM(prj,ret);
+ }
+
}
diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java
new file mode 100644
index 00000000..22ac2a69
--- /dev/null
+++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java
@@ -0,0 +1,31 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.codegen.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.TypeInteger;
+import com.seaofnodes.simple.util.SB;
+
+// Convert a narrow C return register to Simple's full-width integer value.
+public class ExtendRISC extends MachConcreteNode {
+ final int _bits;
+ final boolean _signed;
+ ExtendRISC(ProjNode prj, TypeInteger ret) {
+ super(prj);
+ _inputs.set(0,null);
+ _inputs.add(new ProjRISC(prj));
+ _bits = 8 << ret.log_size();
+ _signed = ret._min < 0;
+ }
+ @Override public String op() { return (_signed ? "sext" : "zext")+_bits; }
+ @Override public RegMask regmap(int i) { return riscv.RMASK; }
+ @Override public RegMask outregmap() { return riscv.WMASK; }
+ @Override public void encoding(Encoding enc) {
+ short dst = enc.reg(this), src = enc.reg(in(1));
+ int shift = 64-_bits;
+ enc.add4(riscv.i_type(riscv.OP_IMM,dst,1,src,shift));
+ enc.add4(riscv.i_type(riscv.OP_IMM,dst,5,dst,shift | (_signed ? 0x400 : 0)));
+ }
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1)));
+ }
+}
diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java
index 7a6361bc..48cb5d23 100644
--- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java
+++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java
@@ -509,6 +509,8 @@ public class riscv extends Machine {
}
private Node prj(ProjNode prj) {
+ TypeInteger ret = cReturn(prj);
+ if( ret!=null ) return new ExtendRISC(prj,ret);
return new ProjRISC(prj);
}
diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java
new file mode 100644
index 00000000..e905e2e3
--- /dev/null
+++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java
@@ -0,0 +1,33 @@
+package com.seaofnodes.simple.node.cpus.x86_64_v2;
+
+import com.seaofnodes.simple.codegen.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.TypeInteger;
+import com.seaofnodes.simple.util.SB;
+
+// Convert a narrow C return register to Simple's full-width integer value.
+public class ExtendX86 extends MachConcreteNode {
+ final int _bits;
+ final boolean _signed;
+ ExtendX86(ProjNode prj, TypeInteger ret) {
+ super(prj);
+ _inputs.set(0,null);
+ _inputs.add(new ProjX86(prj));
+ _bits = 8 << ret.log_size();
+ _signed = ret._min < 0;
+ }
+ @Override public String op() { return (_signed ? "sext" : "zext")+_bits; }
+ @Override public RegMask regmap(int i) { return x86_64_v2.RMASK; }
+ @Override public RegMask outregmap() { return x86_64_v2.WMASK; }
+ @Override public void encoding(Encoding enc) {
+ short dst = enc.reg(this), src = enc.reg(in(1));
+ // MOVSX/MOVZX for bytes and shorts; MOVSXD/MOV r32 for ints.
+ enc.add1(x86_64_v2.rex(dst,src,0,_signed || _bits<32));
+ if( _bits==32 ) enc.add1(_signed ? 0x63 : 0x8b);
+ else enc.add1(0x0f).add1((_signed ? 0xbe : 0xb6) + (_bits==16 ? 1 : 0));
+ enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT,dst,src));
+ }
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1)));
+ }
+}
diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java
index 026e12aa..7ac7fc19 100644
--- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java
+++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java
@@ -549,6 +549,8 @@ public class x86_64_v2 extends Machine {
}
private Node prj( ProjNode prj ) {
+ TypeInteger ret = cReturn(prj);
+ if( ret!=null ) return new ExtendX86(prj,ret);
return new ProjX86(prj);
}