Skip to content

Commit cc9645d

Browse files
committed
Almost done with all codegen for Chapter 12, except not all unsigned int works...
1 parent 734f163 commit cc9645d

14 files changed

+208
-15
lines changed

examples/arithmetic_ops.c

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/* Test basic arithmetic operations on unsigned integers
2+
* None of these operations wrap around; that's tested separately in arithmetic_wraparound
3+
*/
4+
5+
unsigned int ui_a;
6+
unsigned int ui_b;
7+
8+
int division(void) {
9+
// ui_a = 100
10+
// ui_b = 4294967294
11+
12+
/* ui_a/ui_b is 0.
13+
* If you interpreted these as signed values, ui_b would be -2
14+
* and ui_a / ui_b would be -50
15+
*/
16+
return (ui_a / ui_b == 0);
17+
}
18+
19+
int main(void) {
20+
21+
ui_a = 100u;
22+
ui_b = 4294967294u;
23+
24+
if (!division()) {
25+
return 4;
26+
}
27+
28+
return 0;
29+
}

src/com/plasstech/lang/c/codegen/AsmNode.java

+4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ interface Visitor<R> {
3535
R visit(Call op);
3636

3737
R visit(Movsx op);
38+
39+
R visit(MovZeroExtend op);
40+
41+
R visit(Div op);
3842
}
3943

4044
<R> R accept(Visitor<R> visitor);

src/com/plasstech/lang/c/codegen/AssemblyType.java

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public enum AssemblyType {
1616
}
1717

1818
public static AssemblyType from(Type type) {
19+
// page 289
1920
if (type.equals(Type.LONG) || type.equals(Type.UNSIGNED_LONG)) {
2021
return Quadword;
2122
} else if (type.equals(Type.INT) || type.equals(Type.UNSIGNED_INT)) {

src/com/plasstech/lang/c/codegen/CodeEmission.java

+13
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ public Void visit(AsmStaticVariable n) {
7777
}
7878
emit(".align %d", n.alignment());
7979
emit0("%s:", n.name());
80+
81+
// These seem to be independent of signed-ness
82+
// Page 291
8083
if (n.init().valueAsLong() == 0) {
8184
emit(".zero %d", n.init().bytes());
8285
} else {
@@ -160,4 +163,14 @@ public Void visit(Call n) {
160163
public Void visit(Movsx n) {
161164
return emit(n);
162165
}
166+
167+
@Override
168+
public Void visit(MovZeroExtend op) {
169+
throw new UnsupportedOperationException("movzeroextend");
170+
}
171+
172+
@Override
173+
public Void visit(Div op) {
174+
return emit(op);
175+
}
163176
}

src/com/plasstech/lang/c/codegen/CondCode.java

+21-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@ public enum CondCode {
1212
G,
1313
GE,
1414
L,
15-
LE;
15+
LE,
16+
// Page 287
17+
A,
18+
AE,
19+
B,
20+
BE;
1621

1722
private static final Map<TokenType, CondCode> FROM_TOKEN_TYPE = ImmutableMap.of(
1823
TokenType.EQEQ, E,
@@ -22,7 +27,20 @@ public enum CondCode {
2227
TokenType.LT, L,
2328
TokenType.LEQ, LE);
2429

25-
public static CondCode from(TokenType operator) {
26-
return FROM_TOKEN_TYPE.get(operator);
30+
// Page 289
31+
private static final Map<TokenType, CondCode> FROM_TOKEN_TYPE_UNSIGNED = ImmutableMap.of(
32+
TokenType.EQEQ, E,
33+
TokenType.NEQ, NE,
34+
TokenType.GT, A,
35+
TokenType.GEQ, AE,
36+
TokenType.LT, B,
37+
TokenType.LEQ, BE);
38+
39+
public static CondCode from(TokenType operator, boolean signed) {
40+
if (signed) {
41+
return FROM_TOKEN_TYPE.get(operator);
42+
} else {
43+
return FROM_TOKEN_TYPE_UNSIGNED.get(operator);
44+
}
2745
}
2846
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.plasstech.lang.c.codegen;
2+
3+
/** eax=eax/operand for unsigned */
4+
public record Div(AssemblyType type, Operand operand) implements Instruction {
5+
@Override
6+
public <R> R accept(Visitor<R> visitor) {
7+
return visitor.visit(this);
8+
}
9+
10+
@Override
11+
public final String toString() {
12+
return String.format("div%s %s", type().suffix(), operand().toString(type()));
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.plasstech.lang.c.codegen;
2+
3+
/** Page 287 */
4+
public record MovZeroExtend(Operand src, Operand dst) implements Instruction {
5+
@Override
6+
public <R> R accept(Visitor<R> visitor) {
7+
return visitor.visit(this);
8+
}
9+
}

src/com/plasstech/lang/c/codegen/tacky/FixupVisitor.java

+28
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@
1616
import com.plasstech.lang.c.codegen.Call;
1717
import com.plasstech.lang.c.codegen.Cdq;
1818
import com.plasstech.lang.c.codegen.Cmp;
19+
import com.plasstech.lang.c.codegen.Div;
1920
import com.plasstech.lang.c.codegen.Idiv;
2021
import com.plasstech.lang.c.codegen.Imm;
2122
import com.plasstech.lang.c.codegen.Instruction;
2223
import com.plasstech.lang.c.codegen.Jmp;
2324
import com.plasstech.lang.c.codegen.JmpCC;
2425
import com.plasstech.lang.c.codegen.Label;
2526
import com.plasstech.lang.c.codegen.Mov;
27+
import com.plasstech.lang.c.codegen.MovZeroExtend;
2628
import com.plasstech.lang.c.codegen.Movsx;
2729
import com.plasstech.lang.c.codegen.Operand;
2830
import com.plasstech.lang.c.codegen.Push;
@@ -112,6 +114,17 @@ public List<Instruction> visit(Idiv n) {
112114
return ImmutableList.of(n);
113115
}
114116

117+
@Override
118+
public List<Instruction> visit(Div n) {
119+
// Can't divide by a constant; use r10 as an intermediary. See page 290
120+
if (n.operand() instanceof Imm) {
121+
return ImmutableList.of(
122+
new Mov(n.type(), n.operand(), R10),
123+
new Div(n.type(), R10));
124+
}
125+
return ImmutableList.of(n);
126+
}
127+
115128
@Override
116129
public List<Instruction> visit(AsmUnary n) {
117130
return ImmutableList.of(n);
@@ -232,4 +245,19 @@ public List<Instruction> visit(Movsx op) {
232245
}
233246
return ImmutableList.of(op);
234247
}
248+
249+
@Override
250+
public List<Instruction> visit(MovZeroExtend op) {
251+
// Page 290
252+
if (op.dst().inMemory()) {
253+
// if dest is memory, rewrite to two:
254+
// 1. mov(longword, src, reg 11)
255+
// 2. mov(quadword, r11, dest)
256+
return ImmutableList.of(
257+
new Mov(AssemblyType.Longword, op.src(), R11),
258+
new Mov(AssemblyType.Quadword, R11, op.dst()));
259+
}
260+
// dest is a register: rewrite to mov longword src, dst
261+
return ImmutableList.of(new Mov(AssemblyType.Longword, op.src(), op.dst()));
262+
}
235263
}

src/com/plasstech/lang/c/codegen/tacky/PseudoRegisterReplacer.java

+15
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@
1616
import com.plasstech.lang.c.codegen.Cdq;
1717
import com.plasstech.lang.c.codegen.Cmp;
1818
import com.plasstech.lang.c.codegen.Data;
19+
import com.plasstech.lang.c.codegen.Div;
1920
import com.plasstech.lang.c.codegen.Idiv;
2021
import com.plasstech.lang.c.codegen.Imm;
2122
import com.plasstech.lang.c.codegen.Instruction;
2223
import com.plasstech.lang.c.codegen.Jmp;
2324
import com.plasstech.lang.c.codegen.JmpCC;
2425
import com.plasstech.lang.c.codegen.Label;
2526
import com.plasstech.lang.c.codegen.Mov;
27+
import com.plasstech.lang.c.codegen.MovZeroExtend;
2628
import com.plasstech.lang.c.codegen.Movsx;
2729
import com.plasstech.lang.c.codegen.ObjEntry;
2830
import com.plasstech.lang.c.codegen.Operand;
@@ -191,4 +193,17 @@ public Instruction visit(Movsx op) {
191193
Operand newDest = remap(op.dst());
192194
return new Movsx(newSrc, newDest);
193195
}
196+
197+
@Override
198+
public Instruction visit(MovZeroExtend op) {
199+
Operand newSrc = remap(op.src());
200+
Operand newDest = remap(op.dst());
201+
return new MovZeroExtend(newSrc, newDest);
202+
}
203+
204+
@Override
205+
public Instruction visit(Div op) {
206+
Operand newOperand = remap(op.operand());
207+
return new Div(op.type(), newOperand);
208+
}
194209
}

src/com/plasstech/lang/c/codegen/tacky/TackyCodeGen.java

+1
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ public TackyVal visit(Compound n) {
136136

137137
@Override
138138
public <T extends Number> TackyVal visit(Constant<T> n) {
139+
// this may be the error - something about subtracting 2^32?
139140
return new TackyConstant(n.type(), n.asLong());
140141
}
141142

src/com/plasstech/lang/c/codegen/tacky/TackyInstructionToInstructionsVisitor.java

+35-10
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@
1111
import com.plasstech.lang.c.codegen.Cdq;
1212
import com.plasstech.lang.c.codegen.Cmp;
1313
import com.plasstech.lang.c.codegen.CondCode;
14+
import com.plasstech.lang.c.codegen.Div;
1415
import com.plasstech.lang.c.codegen.Idiv;
1516
import com.plasstech.lang.c.codegen.Imm;
1617
import com.plasstech.lang.c.codegen.Instruction;
1718
import com.plasstech.lang.c.codegen.Jmp;
1819
import com.plasstech.lang.c.codegen.JmpCC;
1920
import com.plasstech.lang.c.codegen.Label;
2021
import com.plasstech.lang.c.codegen.Mov;
22+
import com.plasstech.lang.c.codegen.MovZeroExtend;
2123
import com.plasstech.lang.c.codegen.Movsx;
2224
import com.plasstech.lang.c.codegen.Operand;
2325
import com.plasstech.lang.c.codegen.Pseudo;
@@ -94,6 +96,7 @@ public List<Instruction> visit(TackyUnary op) {
9496
@Override
9597
public List<Instruction> visit(TackyBinary op) {
9698
List<Instruction> instructions = new ArrayList<>();
99+
97100
Operand left = toOperand(op.left());
98101
Operand right = toOperand(op.right());
99102
Operand dst = toOperand(op.dst());
@@ -105,16 +108,30 @@ public List<Instruction> visit(TackyBinary op) {
105108
case PERCENT:
106109
// mov (left, register(ax))
107110
instructions.add(new Mov(leftType, left, RegisterOperand.RAX));
108-
// cdq
109-
instructions.add(new Cdq(leftType));
110-
// idiv(right)
111-
instructions.add(new Idiv(leftType, right));
112-
if (operator == TokenType.SLASH) {
113-
// mov(reg(ax), dst)
114-
instructions.add(new Mov(leftType, RegisterOperand.RAX, dst));
111+
if (op.left().type().signed()) {
112+
// cdq
113+
instructions.add(new Cdq(leftType));
114+
// idiv(right)
115+
instructions.add(new Idiv(leftType, right));
116+
if (operator == TokenType.SLASH) {
117+
// mov(reg(ax), dst)
118+
instructions.add(new Mov(leftType, RegisterOperand.RAX, dst));
119+
} else {
120+
// mov(reg(dx), dst) for modulo
121+
instructions.add(new Mov(leftType, RegisterOperand.RDX, dst));
122+
}
115123
} else {
116-
// mov(reg(dx), dst) for modulo
117-
instructions.add(new Mov(leftType, RegisterOperand.RDX, dst));
124+
// page 288
125+
// mov (left, register(ax))
126+
// div(right)
127+
instructions.add(new Div(leftType, right));
128+
if (operator == TokenType.SLASH) {
129+
// mov(reg(ax), dst)
130+
instructions.add(new Mov(leftType, RegisterOperand.RAX, dst));
131+
} else {
132+
// mov(reg(dx), dst) for modulo
133+
instructions.add(new Mov(leftType, RegisterOperand.RDX, dst));
134+
}
118135
}
119136
break;
120137

@@ -127,7 +144,9 @@ public List<Instruction> visit(TackyBinary op) {
127144
// Page 86
128145
instructions.add(new Cmp(leftType, right, left));
129146
instructions.add(new Mov(dstType, ZERO, dst));
130-
instructions.add(new SetCC(CondCode.from(operator), dst));
147+
// page 288 adds signed
148+
boolean signed = op.left().type().signed();
149+
instructions.add(new SetCC(CondCode.from(operator, signed), dst));
131150
break;
132151

133152
case PLUS:
@@ -273,4 +292,10 @@ public List<Instruction> visit(TackyTruncate op) {
273292
return ImmutableList
274293
.of(new Mov(AssemblyType.Longword, toOperand(op.src()), toOperand(op.dst())));
275294
}
295+
296+
@Override
297+
public List<Instruction> visit(TackyZeroExtend op) {
298+
// page 288ff
299+
return ImmutableList.of(new MovZeroExtend(toOperand(op.src()), toOperand(op.dst())));
300+
}
276301
}

src/com/plasstech/lang/c/codegen/tacky/TackyToAsmCodeGen.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ public AsmState generate(TackyProgram program) {
4545
case TackyFunction fn -> generateFn(fn);
4646
case TackyStaticVariable sv -> {
4747
int alignment;
48-
if (sv.type().equals(Type.LONG)) {
48+
if (sv.type().equals(Type.LONG) || sv.type().equals(Type.UNSIGNED_LONG)) {
4949
alignment = 8;
50-
} else if (sv.type().equals(Type.INT)) {
50+
} else if (sv.type().equals(Type.INT) || sv.type().equals(Type.UNSIGNED_INT)) {
5151
alignment = 4;
5252
} else {
5353
throw new IllegalStateException("Unknown static type " + sv.type());

src/com/plasstech/lang/c/codegen/tacky/TackyVal.java

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.plasstech.lang.c.codegen.tacky;
22

3+
import com.plasstech.lang.c.typecheck.Type;
4+
35
/**
46
* Represents a value: a constant or a variable.
57
*/
@@ -10,5 +12,7 @@ interface Visitor<R> {
1012
R visit(TackyConstant tackyInt);
1113
}
1214

15+
Type type();
16+
1317
<R> R accept(Visitor<R> visitor);
1418
}

test/com/plasstech/lang/c/codegen/CodeEmissionTest.java

+32
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,36 @@ int main(void) {
100100
System.err.println(Joiner.on('\n').join(asm));
101101
}
102102

103+
@Test
104+
public void divUnsigned() {
105+
String input = """
106+
unsigned int ui_a;
107+
unsigned int ui_b;
108+
109+
int division(void) {
110+
// ui_a = 100
111+
// ui_b = 4294967294
112+
113+
/* ui_a/ui_b is 0.
114+
* If you interpreted these as signed values, ui_b would be -2
115+
* and ui_a / ui_b would be -50
116+
*/
117+
return (ui_a / ui_b == 0);
118+
}
119+
120+
int main(void) {
121+
122+
ui_a = 100u;
123+
ui_b = 4294967294u;
124+
125+
if (!division()) {
126+
return 4;
127+
}
128+
129+
return 0;
130+
}
131+
""";
132+
List<String> asm = generate(input);
133+
System.err.println(Joiner.on('\n').join(asm));
134+
}
103135
}

0 commit comments

Comments
 (0)