← board

C unsigned int / Pascal Cardinal division+mod use signed div on 32-bit backends

Symptom

On i386/arm32/riscv32, unsigned int (C) and Cardinal/LongWord (Pascal) / and % (mod) emit signed divide for scalar (32-bit) ordinals, so operands with bit 31 set divide as negative. x86-64 is correct (keys on TypeDivideUnsigned).

unsigned int a = 3000000000u;   /* > 2^31 */
printf("%u\n", a / 7);          /* x86-64: 428571428   32-bit backends: wrong (signed idiv) */

Root cause

Scalar ordinal divide/mod is hardcoded signed:

The 64-bit pair paths already honor signedOp (EmitBinop64_386 / …Arm32 / …RISCV32). Only the scalar 32-bit path ignores signedness.

Fix

Mirror the x86-64 TypeDivideUnsigned(IntToTypeKind(IRTk[left])) decision per backend: i386 xor edx,edx; div ecx; arm32 udiv; riscv32 divu/remu. Same shape as the compare-signedness fix in the parent ticket. 32-bit-backend-only, so x86-64 self-host stays byte-identical; gate = cross green + a guard test (unsigned div/mod with a >2^31 operand, exit-code or oracle-diff) on each 32-bit target.

Acceptance