Skip to content

Commit

Permalink
fix: reg allocator crashes on SAL / SAR instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
Mati365 committed Jan 21, 2024
1 parent 97c4dac commit b358fcf
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ export function compileIntMathInstruction({
switch (operator) {
case TokenType.BIT_SHIFT_RIGHT:
case TokenType.BIT_SHIFT_LEFT: {
const rightAllocResult = regs.tryResolveIrArg({
size: biggestArgSize,
arg: rightVar,
allowedRegs: ['cl', 'cx'],
allow: IRArgDynamicResolverType.REG | IRArgDynamicResolverType.NUMBER,
});

const leftAllocResult = regs.tryResolveIRArgAsReg({
size: biggestArgSize,
arg: leftVar,
Expand All @@ -59,15 +66,8 @@ export function compileIntMathInstruction({
});
}

const rightAllocResult = regs.tryResolveIrArg({
size: biggestArgSize,
arg: rightVar,
allowedRegs: ['cl', 'cx'],
allow: IRArgDynamicResolverType.REG | IRArgDynamicResolverType.NUMBER,
});

const opcode = operator === TokenType.BIT_SHIFT_RIGHT ? 'sar' : 'sal';
const asm: string[] = [...leftAllocResult.asm, ...rightAllocResult.asm];
const asm: string[] = [...rightAllocResult.asm, ...leftAllocResult.asm];

if (rightAllocResult.value === 'cx') {
asm.push(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,10 @@ export class X86BasicRegAllocator {

if (!result) {
if (query.size) {
const [reg] = query.allowedRegs ?? ['ax'];
const [reg] = query.allowedRegs?.filter(
allowedReg => getX86RegByteSize(allowedReg) === query.size,
) ?? ['ax'];

const spillVar = stackFrame.allocSpillVariable(query.size);
const ownerships = ownership.getOwnershipByReg(reg);

Expand Down
39 changes: 38 additions & 1 deletion packages/compiler-pico-c/tests/codegen/statements/math.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ describe('Math', () => {
sub sp, 4
mov word [bp - 2], 14 ; *(a{0}: int*2B) = store %14: int2B
mov word [bp - 4], 4 ; *(c{0}: int*2B) = store %4: int2B
mov ax, [bp - 2]
mov cx, [bp - 4]
mov ax, [bp - 2]
sal ax, cl ; %t{2}: int2B = %t{1}: int2B bit_shift_left %t{0}: int2B
sar ax, 2 ; %t{4}: int2B = %t{2}: int2B bit_shift_right %2: char1B
mov word [bp - 2], ax ; *(a{0}: int*2B) = store %t{4}: int2B
Expand All @@ -30,6 +30,43 @@ describe('Math', () => {
`);
});

test('bit shift with exhausted regs', () => {
expect(/* cpp */ `
int main() {
const char *ptr = "Hello world!";
int bs = sizeof(int)*8;
int mi;
mi = (1 << (bs-1)) + 1;
asm("xchg bx, bx");
return 0;
}
`).toCompiledAsmBeEqual(`
cpu 386
; def main(): [ret: int2B]
@@_fn_main:
push bp
mov bp, sp
sub sp, 6
mov bx, @@_c_0_ ; %t{0}: const char*2B = lea c{0}: const char[13]*2B
mov word [bp - 2], bx ; *(ptr{0}: const char**2B) = store %t{0}: const char*2B
mov word [bp - 4], 16 ; *(bs{0}: int*2B) = store %16: int2B
mov ax, [bp - 4]
sub ax, 1 ; %t{2}: int2B = %t{1}: int2B minus %1: char1B
mov cx, ax
mov ax, word 1
sal ax, cl ; %t{3}: int2B = %1: char1B bit_shift_left %t{2}: int2B
add ax, 1 ; %t{4}: int2B = %t{3}: int2B plus %1: char1B
mov word [bp - 6], ax ; *(mi{0}: int*2B) = store %t{4}: int2B
xchg bx, bx
mov ax, word 0
mov sp, bp
pop bp
ret
@@_c_0_:
db "Hello world!", 0x0
`);
});

test('int b = 1 + ~a', () => {
expect(/* cpp */ `
void main() {
Expand Down

0 comments on commit b358fcf

Please sign in to comment.