aboutsummaryrefslogtreecommitdiff
path: root/pkg/lang/vm
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2022-07-05 22:15:29 +0200
committerMel <einebeere@gmail.com>2022-07-05 22:15:29 +0200
commitb09fce67753e199d4ae0fe6138f909b5e3413208 (patch)
treee2010cc61b2614b43556a738eae38053ef8be345 /pkg/lang/vm
parente29ee3e310044ddb2356513808554a46de957659 (diff)
downloadjinx-b09fce67753e199d4ae0fe6138f909b5e3413208.tar.zst
jinx-b09fce67753e199d4ae0fe6138f909b5e3413208.zip
Fix nested if block compiling
Diffstat (limited to 'pkg/lang/vm')
-rw-r--r--pkg/lang/vm/code/builder.go77
1 files changed, 67 insertions, 10 deletions
diff --git a/pkg/lang/vm/code/builder.go b/pkg/lang/vm/code/builder.go
index 4a5ef70..f027c49 100644
--- a/pkg/lang/vm/code/builder.go
+++ b/pkg/lang/vm/code/builder.go
@@ -2,12 +2,14 @@ package code
import (
"encoding/binary"
+ "fmt"
"math"
)
type Builder struct {
- code []byte
- debugInfo DebugInfo
+ code []byte
+ debugInfo DebugInfo
+ relativePcRefs map[int][]int
currentLine int
lineStart int
@@ -15,10 +17,11 @@ type Builder struct {
func NewBuilder() Builder {
return Builder{
- code: make([]byte, 0, 64),
- debugInfo: NewDebugInfo("unknown file"),
- lineStart: -1,
- currentLine: -1,
+ code: make([]byte, 0, 64),
+ debugInfo: NewDebugInfo("unknown file"),
+ relativePcRefs: make(map[int][]int),
+ lineStart: -1,
+ currentLine: -1,
}
}
@@ -40,17 +43,59 @@ func (b *Builder) AppendString(s string) {
b.code = append(b.code, 0)
}
+func (b *Builder) AppendReferenceToPc(pc int64) {
+ b.addPcRef(int(pc), b.Len())
+ b.AppendInt(pc)
+}
+
func (b *Builder) AppendRaw(raw Raw) {
b.code = append(b.code, raw...)
}
+func (b *Builder) AppendBuilder(other Builder) {
+ code := other.code
+ for pc, refsToPc := range other.relativePcRefs {
+ newPc := b.Len() + pc
+ for _, ref := range refsToPc {
+ valueAtRef := binary.LittleEndian.Uint64(code[ref : ref+8])
+ if int(valueAtRef) != pc {
+ panic(fmt.Errorf("reference to pc in builder does not actually reference pc. (pc: %d, value at reference: %d)", pc, valueAtRef))
+ }
+
+ binary.LittleEndian.PutUint64(code[ref:], uint64(newPc))
+ b.addPcRef(newPc, ref+b.Len())
+ }
+ }
+
+ b.code = append(b.code, code...)
+
+ if other.debugInfo.pcToLine.Len() != 0 || other.currentLine != -1 || other.lineStart != -1 {
+ panic("appending debug infos not implemented yet")
+ }
+}
+
+func (b *Builder) AppendBuilderWithoutAdjustingReferences(other Builder) {
+ code := other.code
+ for pc, refsToPc := range other.relativePcRefs {
+ for _, ref := range refsToPc {
+ b.addPcRef(pc, ref+b.Len())
+ }
+ }
+
+ b.code = append(b.code, code...)
+
+ if other.debugInfo.pcToLine.Len() != 0 || other.currentLine != -1 || other.lineStart != -1 {
+ panic("appending debug infos not implemented yet")
+ }
+}
+
func (b *Builder) StartLine(line int) {
if b.lineStart != -1 {
panic("line already started")
}
b.currentLine = line
- b.lineStart = len(b.code)
+ b.lineStart = b.Len()
}
func (b *Builder) EndLine() {
@@ -63,11 +108,11 @@ func (b *Builder) EndLine() {
panic("line not started")
}
- if b.lineStart == len(b.code) {
+ if b.lineStart == b.Len() {
return
}
-
- b.debugInfo.AppendLine(len(b.code)-1, b.currentLine)
+
+ b.debugInfo.AppendLine(b.Len()-1, b.currentLine)
}
func (b *Builder) SetInt(at int, x int64) {
@@ -85,3 +130,15 @@ func (b *Builder) Len() int {
func (b *Builder) Build() Code {
return New(b.code, b.debugInfo)
}
+
+func (b *Builder) addPcRef(pc int, at int) {
+ refs, ok := b.relativePcRefs[pc]
+ if ok {
+ refs = append(refs, at)
+ } else {
+ refs = make([]int, 1)
+ refs[0] = at
+ }
+
+ b.relativePcRefs[pc] = refs
+}