From 41be002e89358649da46c33c8245aa786afdad6a Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Mon, 28 Sep 2026 16:25:01 -0700 Subject: Extend smaller-width C results to full width --- .../com/seaofnodes/simple/codegen/Machine.java | 11 ++++++++ .../seaofnodes/simple/node/cpus/arm/ExtendARM.java | 30 ++++++++++++++++++++ .../com/seaofnodes/simple/node/cpus/arm/arm.java | 7 ++++- .../simple/node/cpus/riscv/ExtendRISC.java | 31 ++++++++++++++++++++ .../seaofnodes/simple/node/cpus/riscv/riscv.java | 2 ++ .../simple/node/cpus/x86_64_v2/ExtendX86.java | 33 ++++++++++++++++++++++ .../simple/node/cpus/x86_64_v2/x86_64_v2.java | 2 ++ 7 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java create mode 100644 chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java create mode 100644 chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java (limited to 'chapter24/src/main/java') diff --git a/chapter24/src/main/java/com/seaofnodes/simple/codegen/Machine.java b/chapter24/src/main/java/com/seaofnodes/simple/codegen/Machine.java index 2766414f..a95faefc 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/codegen/Machine.java +++ b/chapter24/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/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java new file mode 100644 index 00000000..26a237d0 --- /dev/null +++ b/chapter24/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/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java index 74dc70d4..70034227 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java @@ -678,7 +678,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); @@ -822,4 +822,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/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java new file mode 100644 index 00000000..22ac2a69 --- /dev/null +++ b/chapter24/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/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java index 7a6361bc..48cb5d23 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java +++ b/chapter24/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/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java new file mode 100644 index 00000000..e905e2e3 --- /dev/null +++ b/chapter24/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/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java index 026e12aa..7ac7fc19 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java +++ b/chapter24/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); } -- cgit v1.2.3