diff --git a/index.js b/index.js index d25511e..d4b3794 100644 --- a/index.js +++ b/index.js @@ -679,22 +679,46 @@ function lower(ast) { assert(!Number.isNaN(ctx.offset)); const { ib, variables } = ctx; switch (expr.kind) { - case "call": { - if (expr.lhs.kind !== "ident") { - throw new Error("bad"); - } - if (expr.args.length !== 1) { - throw new Error("bad"); - } + case "call": { + // Handle function calls with arguments + if (expr.lhs.kind !== "ident") { + throw new Error("unsupported call target"); + } + if (expr.args.length > 4) { + throw new Error("too many arguments"); + } - // TODO: save - codegenExpr(ctx, expr.args[0]); - // mov edi, eax - ib.movRegReg32(REG_DI, REG_A); - ib.call(expr.lhs.string); + // Generate code for arguments in reverse order (right-to-left) + for (let i = expr.args.length - 1; i >= 0; i--) { + const arg = expr.args[i]; + // If argument is a comma expression, use just the right side + if (arg.kind === ",") { + codegenExpr(ctx, arg.rhs); + } else { + codegenExpr(ctx, arg); + } + + // Move result to correct parameter register + switch (i) { + case 0: + ib.movRegReg32(REG_DI, REG_A); + break; + case 1: + ib.movRegReg32(REG_SI, REG_A); + break; + case 2: + ib.movRegReg32(REG_D, REG_A); + break; + case 3: + ib.movRegReg32(REG_C, REG_A); + break; + } + } - break; - } + ib.call(expr.lhs.string); + + break; + } case "integer": { ib.movEaxImm32(expr.integer); break; @@ -707,6 +731,22 @@ function lower(ast) { ib.movStackOffsetToReg(offset.stackOffset + ctx.offset, REG_A); break; } + case "=": { + // For assignment operations, generate code for RHS + codegenExpr(ctx, expr.rhs); + + // Find the variable to assign to + const varOffset = [...variables] + .reverse() + .find((v) => v.name === expr.lhs.string); + if (!varOffset) { + throw new Error(`undefined variable: ${expr.lhs.string}`); + } + + // Store the result (in eax) to the variable's stack location + ib.movRegToStackOffset(varOffset.stackOffset + ctx.offset, REG_A); + break; + } case "+": { // For binary expressions, we first evaluate the LHS, save it on the stack, // evaluate the RHS, then restore the LHS and perform the operation. @@ -741,7 +781,7 @@ function lower(ast) { func.params.forEach((param, i) => { assert(param.type.kind === "int"); - const offset = ib.reserveStack(4); + const offset = ib.reserveStack(8); // Use 8 bytes for 64-bit values ib.movRegToStackOffset(offset, PARAM_CALLCONV_REGISTERS[i]); variables.push({ name: param.name, @@ -769,7 +809,7 @@ function lower(ast) { if (stmt.init) { codegenExpr(ctx, stmt.init); } - const slot = ib.reserveStack(4); + const slot = ib.reserveStack(8); // Use 8 bytes for 64-bit values variables.push({ name: stmt.name, stackOffset: slot,