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 | 12 ++++++++ .../seaofnodes/simple/node/cpus/arm/ExtendARM.java | 30 ++++++++++++++++++++ .../com/seaofnodes/simple/node/cpus/arm/arm.java | 2 ++ .../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, 112 insertions(+) create mode 100644 chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java create mode 100644 chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java create mode 100644 chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java (limited to 'chapter25/src/main/java') diff --git a/chapter25/src/main/java/com/seaofnodes/simple/codegen/Machine.java b/chapter25/src/main/java/com/seaofnodes/simple/codegen/Machine.java index 91d07d57..3eee8fc3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/codegen/Machine.java +++ b/chapter25/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" @@ -112,4 +113,15 @@ Pre-alloc Post-Alloc SP+48 RPC // Calling convention used for external C symbols. public String cCallingConv(String callingConv) { return callingConv; } + // 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()._type instanceof TypeFunPtr tfp && tfp.isConstant() && + CodeGen.CODE.externFunc(tfp.fidx())!=null && + tfp.ret() instanceof TypeInteger ret && ret.log_size()<3 ) + return ret; + return null; + } + } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java new file mode 100644 index 00000000..26a237d0 --- /dev/null +++ b/chapter25/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/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java index d4e10404..044d0352 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java @@ -846,6 +846,8 @@ public class arm extends Machine { } private Node prj(ProjNode prj) { + TypeInteger ret = cReturn(prj); + if( ret!=null ) return new ExtendARM(prj,ret); return prj.in(0) instanceof StartNode ? new ProjNode(prj) : new ProjARM(prj); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java new file mode 100644 index 00000000..22ac2a69 --- /dev/null +++ b/chapter25/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/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java index 27141d21..03f7371b 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java @@ -531,6 +531,8 @@ public class riscv extends Machine { } private Node prj(ProjNode prj) { + TypeInteger ret = cReturn(prj); + if( ret!=null ) return new ExtendRISC(prj,ret); return prj.in(0) instanceof StartNode ? new ProjNode(prj) : new ProjRISC(prj); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java new file mode 100644 index 00000000..e905e2e3 --- /dev/null +++ b/chapter25/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/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java index 5b70834c..99010ffd 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java @@ -580,6 +580,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 prj.in(0) instanceof StartNode ? new ProjNode(prj) : new ProjX86(prj); } -- cgit v1.2.3