Reduced memory usage
This commit is contained in:
parent
668971808b
commit
c8b25dd5b7
@ -1,22 +0,0 @@
|
||||
package build
|
||||
|
||||
import "git.akyoto.dev/cli/q/src/build/token"
|
||||
|
||||
type debug struct {
|
||||
pos int
|
||||
instruction token.List
|
||||
}
|
||||
|
||||
func (f *Function) debugLine(instructionIndex int) token.List {
|
||||
for _, record := range f.debug {
|
||||
if record.pos == instructionIndex {
|
||||
return record.instruction
|
||||
}
|
||||
|
||||
if record.pos > instructionIndex {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -64,7 +64,7 @@ func (f *Function) CompileTokens(body token.List) error {
|
||||
|
||||
if config.Verbose {
|
||||
f.debug = append(f.debug, debug{
|
||||
pos: len(f.Assembler.Instructions),
|
||||
position: len(f.Assembler.Instructions),
|
||||
instruction: instruction,
|
||||
})
|
||||
}
|
||||
@ -233,7 +233,7 @@ func (f *Function) PrintAsm() {
|
||||
ansi.Dim.Println("╭──────────────────────────────────────╮")
|
||||
|
||||
for i, x := range f.Assembler.Instructions {
|
||||
instruction := f.debugLine(i)
|
||||
instruction := f.instructionAt(i)
|
||||
|
||||
if instruction != nil {
|
||||
ansi.Dim.Println("├──────────────────────────────────────┤")
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
type Result struct {
|
||||
Used []*Function
|
||||
Unused map[string]*Function
|
||||
instructionCount int
|
||||
InstructionCount int
|
||||
}
|
||||
|
||||
// Finalize generates the final machine code.
|
||||
@ -20,7 +20,7 @@ func (r Result) Finalize() ([]byte, []byte) {
|
||||
// The reason we call `main` instead of using `main` itself is to place
|
||||
// a return address on the stack, which allows return statements in `main`.
|
||||
final := asm.Assembler{
|
||||
Instructions: make([]asm.Instruction, 0, r.instructionCount+4),
|
||||
Instructions: make([]asm.Instruction, 0, r.InstructionCount+4),
|
||||
}
|
||||
|
||||
final.Call("main")
|
||||
|
@ -39,8 +39,6 @@ func compile(functions <-chan *Function, errors <-chan error) (Result, error) {
|
||||
if function.Error != nil {
|
||||
return result, function.Error
|
||||
}
|
||||
|
||||
result.instructionCount += len(function.Assembler.Instructions)
|
||||
}
|
||||
|
||||
main, exists := result.Unused["main"]
|
||||
@ -49,8 +47,8 @@ func compile(functions <-chan *Function, errors <-chan error) (Result, error) {
|
||||
return result, fail.MissingMainFunction
|
||||
}
|
||||
|
||||
result.Used = append(result.Used, main)
|
||||
delete(result.Unused, "main")
|
||||
result.Used = make([]*Function, 0, len(result.Unused))
|
||||
result.markAlive(main)
|
||||
result.findAliveCode(main)
|
||||
|
||||
return result, nil
|
||||
@ -73,21 +71,27 @@ func compileFunctions(functions map[string]*Function) {
|
||||
}
|
||||
|
||||
// findAliveCode recursively finds all the calls to external functions and marks them as required.
|
||||
func (result *Result) findAliveCode(f *Function) {
|
||||
for _, x := range f.Assembler.Instructions {
|
||||
func (result *Result) findAliveCode(caller *Function) {
|
||||
for _, x := range caller.Assembler.Instructions {
|
||||
if x.Mnemonic != asm.CALL {
|
||||
continue
|
||||
}
|
||||
|
||||
name := x.Data.(*asm.Label).Name
|
||||
called, exists := result.Unused[name]
|
||||
callee, exists := result.Unused[name]
|
||||
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
|
||||
result.Used = append(result.Used, called)
|
||||
delete(result.Unused, name)
|
||||
result.findAliveCode(called)
|
||||
result.markAlive(callee)
|
||||
result.findAliveCode(callee)
|
||||
}
|
||||
}
|
||||
|
||||
// markAlive marks a function as being alive.
|
||||
func (result *Result) markAlive(f *Function) {
|
||||
result.Used = append(result.Used, f)
|
||||
result.InstructionCount += len(f.Assembler.Instructions)
|
||||
delete(result.Unused, f.Name)
|
||||
}
|
||||
|
24
src/build/debug.go
Normal file
24
src/build/debug.go
Normal file
@ -0,0 +1,24 @@
|
||||
package build
|
||||
|
||||
import "git.akyoto.dev/cli/q/src/build/token"
|
||||
|
||||
// debug is used to look up instructions at a certain index.
|
||||
type debug struct {
|
||||
position int
|
||||
instruction token.List
|
||||
}
|
||||
|
||||
// instructionAt retrieves the instruction at the given index.
|
||||
func (f *Function) instructionAt(index int) token.List {
|
||||
for _, record := range f.debug {
|
||||
if record.position == index {
|
||||
return record.instruction
|
||||
}
|
||||
|
||||
if record.position > index {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user