Skip to content

Commit 77177e1

Browse files
authored
Merge #52
Instruction types refactor
2 parents 5be2b9c + 89dfd2d commit 77177e1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+1590
-1623
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727

2828
# build files
2929
build
30-
usm
3130

3231
# coverage
3332
coverage.txt

aarch64/codegen/file.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,17 @@ func NewFileCodegenContext(file *gen.FileInfo) *FileCodegenContext {
3131
functionIndices := make(map[*gen.FunctionInfo]uint32, len(file.Functions))
3232

3333
offset := uint64(0)
34-
for idx, function := range file.Functions {
34+
idx := uint32(0)
35+
for _, function := range file.Functions {
3536
if function.IsDefined() {
3637
functionOffsets[function] = offset
37-
functionIndices[function] = uint32(idx)
38+
functionIndices[function] = idx
3839

3940
functionSize := uint64(function.Size()) * 4 // TODO: handle overflow?
4041
offset += functionSize
4142
}
43+
44+
idx++
4245
}
4346

4447
return &FileCodegenContext{

aarch64/codegen/instruction.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ import (
1111
)
1212

1313
type Instruction interface {
14-
gen.BaseInstruction
14+
gen.InstructionDefinition
1515

1616
// Converts the abstract instruction representation into a concrete binary
1717
// instruction.
18-
Generate(
19-
*InstructionCodegenContext,
18+
Codegen(
19+
ctx *InstructionCodegenContext,
2020
) (instructions.Instruction, core.ResultList)
2121
}
2222

@@ -34,7 +34,7 @@ func (ctx *InstructionCodegenContext) InstructionOffsetInFile() uint64 {
3434
func (ctx *InstructionCodegenContext) Codegen(
3535
buffer *bytes.Buffer,
3636
) core.ResultList {
37-
instruction, ok := ctx.Instruction.(Instruction)
37+
instruction, ok := ctx.InstructionInfo.Definition.(Instruction)
3838
if !ok {
3939
return list.FromSingle(core.Result{
4040
{
@@ -45,7 +45,7 @@ func (ctx *InstructionCodegenContext) Codegen(
4545
})
4646
}
4747

48-
binaryInst, results := instruction.Generate(ctx)
48+
binaryInst, results := instruction.Codegen(ctx)
4949
if !results.IsEmpty() {
5050
return results
5151
}

aarch64/isa/add.go

Lines changed: 32 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -9,79 +9,59 @@ import (
99
"alon.kr/x/usm/gen"
1010
)
1111

12-
type BaseAdd struct {
13-
NonBranchingInstruction
12+
type Add struct {
13+
gen.NonBranchingInstruction
1414
}
1515

16-
func (BaseAdd) Operator() string {
17-
return "add"
18-
}
19-
20-
type AddReg struct {
21-
BaseAdd
22-
instructions.AddShiftedRegister
23-
}
24-
25-
func (i AddReg) Generate(
26-
*aarch64codegen.InstructionCodegenContext,
27-
) (instructions.Instruction, core.ResultList) {
28-
return i, core.ResultList{}
29-
}
30-
31-
type AddImm struct {
32-
BaseAdd
33-
instructions.AddImmediate
16+
func NewAdd() gen.InstructionDefinition {
17+
return Add{}
3418
}
3519

36-
func (i AddImm) Generate(
37-
*aarch64codegen.InstructionCodegenContext,
38-
) (instructions.Instruction, core.ResultList) {
39-
return i, core.ResultList{}
20+
func (Add) Operator(*gen.InstructionInfo) string {
21+
return "add"
4022
}
4123

42-
type AddDefinition struct{}
43-
44-
func (d AddDefinition) buildRegisterVariant(
24+
func (add Add) codegenRegisterVariant(
4525
info *gen.InstructionInfo,
46-
) (gen.BaseInstruction, core.ResultList) {
26+
) (instructions.Instruction, core.ResultList) {
4727
Xd, Xn, Xm, results := aarch64translation.BinaryInstructionToAarch64(info)
4828
if !results.IsEmpty() {
4929
return nil, results
5030
}
5131

52-
return AddReg{
53-
AddShiftedRegister: instructions.NewAddShiftedRegister(Xd, Xn, Xm),
54-
}, core.ResultList{}
32+
inst := instructions.NewAddShiftedRegister(Xd, Xn, Xm)
33+
return inst, core.ResultList{}
5534
}
5635

57-
func (AddDefinition) buildImmediateVariant(
36+
func (add Add) codegenImmediateVariant(
5837
info *gen.InstructionInfo,
59-
) (gen.BaseInstruction, core.ResultList) {
38+
) (instructions.Instruction, core.ResultList) {
6039
Xd, Xn, imm, results := aarch64translation.Immediate12InstructionToAarch64(info)
6140
if !results.IsEmpty() {
6241
return nil, results
6342
}
6443

65-
return AddImm{
66-
AddImmediate: instructions.NewAddImmediate(Xd, Xn, imm),
67-
}, core.ResultList{}
44+
inst := instructions.NewAddImmediate(Xd, Xn, imm)
45+
return inst, core.ResultList{}
6846
}
6947

70-
func (d AddDefinition) BuildInstruction(
71-
info *gen.InstructionInfo,
72-
) (gen.BaseInstruction, core.ResultList) {
48+
func (add Add) Codegen(
49+
ctx *aarch64codegen.InstructionCodegenContext,
50+
) (instructions.Instruction, core.ResultList) {
51+
// TODO: this implementation is very similar to the one in adds.go, and possibly
52+
// other binary arithmetic instructions. Consider refactoring this.
53+
54+
info := ctx.InstructionInfo
7355
results := aarch64translation.ValidateBinaryInstruction(info)
7456
if !results.IsEmpty() {
7557
return nil, results
7658
}
7759

7860
switch info.Arguments[1].(type) {
7961
case *gen.RegisterArgumentInfo:
80-
return d.buildRegisterVariant(info)
81-
62+
return add.codegenRegisterVariant(info)
8263
case *gen.ImmediateInfo:
83-
return d.buildImmediateVariant(info)
84-
64+
return add.codegenImmediateVariant(info)
8565
default:
8666
return nil, list.FromSingle(core.Result{
8767
{
@@ -93,6 +73,13 @@ func (d AddDefinition) BuildInstruction(
9373
}
9474
}
9575

96-
func NewAddInstructionDefinition() gen.InstructionDefinition {
97-
return AddDefinition{}
76+
func (add Add) Validate(
77+
info *gen.InstructionInfo,
78+
) core.ResultList {
79+
// TODO: this is a pretty hacky way to validate the instruction: we create
80+
// a "mock" generation context, and then try to generate the binary
81+
// representation of the instruction.
82+
ctx := aarch64codegen.InstructionCodegenContext{InstructionInfo: info}
83+
_, results := add.Codegen(&ctx)
84+
return results
9885
}

aarch64/isa/add_test.go

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func buildInstructionFromSource(
2222
t *testing.T,
2323
def gen.InstructionDefinition,
2424
src string,
25-
) aarch64codegen.Instruction {
25+
) (*gen.InstructionInfo, aarch64codegen.Instruction) {
2626
srcView := core.NewSourceView(src)
2727

2828
tokenizer := lex.NewTokenizer()
@@ -39,18 +39,14 @@ func buildInstructionFromSource(
3939
NewFunctionGenerationContext()
4040

4141
generator := gen.NewInstructionGenerator()
42-
baseInfo, results := generator.Generate(ctx, node)
42+
info, results := generator.Generate(ctx, node)
4343
assert.True(t, results.IsEmpty())
44-
assert.NotNil(t, baseInfo)
44+
assert.NotNil(t, info)
4545

46-
baseInst, results := def.BuildInstruction(baseInfo)
47-
assert.True(t, results.IsEmpty())
48-
assert.NotNil(t, baseInst)
49-
50-
inst, ok := baseInst.(aarch64codegen.Instruction)
46+
inst, ok := info.Definition.(aarch64codegen.Instruction)
5147
assert.True(t, ok)
5248

53-
return inst
49+
return info, inst
5450
}
5551

5652
func assertExpectedCodegen(
@@ -59,17 +55,20 @@ func assertExpectedCodegen(
5955
expected instructions.Instruction,
6056
src string,
6157
) {
62-
inst := buildInstructionFromSource(t, def, src)
58+
info, inst := buildInstructionFromSource(t, def, src)
59+
60+
generationContext := &aarch64codegen.InstructionCodegenContext{
61+
InstructionInfo: info,
62+
}
6363

64-
generationContext := &aarch64codegen.InstructionCodegenContext{}
65-
code, results := inst.Generate(generationContext)
64+
code, results := inst.Codegen(generationContext)
6665
assert.True(t, results.IsEmpty())
6766

6867
assert.Equal(t, expected.Binary(), code.Binary())
6968
}
7069

7170
func TestAddExpectedCodegen(t *testing.T) {
72-
def := aarch64isa.NewAddInstructionDefinition()
71+
def := aarch64isa.NewAdd()
7372

7473
testCases := []struct {
7574
src string

aarch64/isa/adds.go

Lines changed: 30 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,78 +9,58 @@ import (
99
"alon.kr/x/usm/gen"
1010
)
1111

12-
type BaseAdds struct {
13-
NonBranchingInstruction
12+
type Adds struct {
13+
gen.NonBranchingInstruction
1414
}
1515

16-
func (BaseAdds) Operator() string {
17-
return "adds"
18-
}
19-
20-
type AddsReg struct {
21-
BaseAdd
22-
instructions.AddShiftedRegister
16+
func NewAdds() gen.InstructionDefinition {
17+
return Adds{}
2318
}
2419

25-
func (i AddsReg) Generate(
26-
*aarch64codegen.InstructionCodegenContext,
27-
) (instructions.Instruction, core.ResultList) {
28-
return i, core.ResultList{}
29-
}
30-
31-
type AddsImm struct {
32-
BaseAdd
33-
instructions.AddsImmediate
34-
}
35-
36-
func (i AddsImm) Generate(
37-
*aarch64codegen.InstructionCodegenContext,
38-
) (instructions.Instruction, core.ResultList) {
39-
return i, core.ResultList{}
20+
func (Adds) Operator(*gen.InstructionInfo) string {
21+
return "adds"
4022
}
4123

42-
type AddsDefinition struct{}
43-
44-
func (d AddsDefinition) buildRegisterVariant(
24+
func (adds Adds) codegenRegisterVariant(
4525
info *gen.InstructionInfo,
46-
) (gen.BaseInstruction, core.ResultList) {
26+
) (instructions.Instruction, core.ResultList) {
4727
Xd, Xn, Xm, results := aarch64translation.BinaryInstructionToAarch64(info)
4828
if !results.IsEmpty() {
4929
return nil, results
5030
}
5131

52-
return AddReg{
53-
AddShiftedRegister: instructions.NewAddsShiftedRegister(Xd, Xn, Xm),
54-
}, core.ResultList{}
32+
inst := instructions.NewAddsShiftedRegister(Xd, Xn, Xm)
33+
return inst, core.ResultList{}
5534
}
5635

57-
func (AddsDefinition) buildImmediateVariant(
36+
func (adds Adds) codegenImmediateVariant(
5837
info *gen.InstructionInfo,
59-
) (gen.BaseInstruction, core.ResultList) {
38+
) (instructions.Instruction, core.ResultList) {
6039
Xd, Xn, imm, results := aarch64translation.Immediate12GPRegisterTargetInstructionToAarch64(info)
6140
if !results.IsEmpty() {
6241
return nil, results
6342
}
6443

65-
return AddsImm{
66-
AddsImmediate: instructions.NewAddsImmediate(Xd, Xn, imm),
67-
}, core.ResultList{}
44+
inst := instructions.NewAddsImmediate(Xd, Xn, imm)
45+
return inst, core.ResultList{}
6846
}
6947

70-
func (d AddsDefinition) BuildInstruction(
71-
info *gen.InstructionInfo,
72-
) (gen.BaseInstruction, core.ResultList) {
48+
func (adds Adds) Codegen(
49+
ctx *aarch64codegen.InstructionCodegenContext,
50+
) (instructions.Instruction, core.ResultList) {
51+
info := ctx.InstructionInfo
52+
7353
results := aarch64translation.ValidateBinaryInstruction(info)
7454
if !results.IsEmpty() {
7555
return nil, results
7656
}
7757

7858
switch info.Arguments[1].(type) {
7959
case *gen.RegisterArgumentInfo:
80-
return d.buildRegisterVariant(info)
60+
return adds.codegenRegisterVariant(info)
8161

8262
case *gen.ImmediateInfo:
83-
return d.buildImmediateVariant(info)
63+
return adds.codegenImmediateVariant(info)
8464

8565
default:
8666
return nil, list.FromSingle(core.Result{
@@ -93,6 +73,13 @@ func (d AddsDefinition) BuildInstruction(
9373
}
9474
}
9575

96-
func NewAddsInstructionDefinition() gen.InstructionDefinition {
97-
return AddsDefinition{}
76+
func (adds Adds) Validate(
77+
info *gen.InstructionInfo,
78+
) core.ResultList {
79+
// TODO: this is a pretty hacky way to validate the instruction: we create
80+
// a "mock" generation context, and then try to generate the binary
81+
// representation of the instruction.
82+
ctx := aarch64codegen.InstructionCodegenContext{InstructionInfo: info}
83+
_, results := adds.Codegen(&ctx)
84+
return results
9885
}

0 commit comments

Comments
 (0)