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 {
|
if config.Verbose {
|
||||||
f.debug = append(f.debug, debug{
|
f.debug = append(f.debug, debug{
|
||||||
pos: len(f.Assembler.Instructions),
|
position: len(f.Assembler.Instructions),
|
||||||
instruction: instruction,
|
instruction: instruction,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -233,7 +233,7 @@ func (f *Function) PrintAsm() {
|
|||||||
ansi.Dim.Println("╭──────────────────────────────────────╮")
|
ansi.Dim.Println("╭──────────────────────────────────────╮")
|
||||||
|
|
||||||
for i, x := range f.Assembler.Instructions {
|
for i, x := range f.Assembler.Instructions {
|
||||||
instruction := f.debugLine(i)
|
instruction := f.instructionAt(i)
|
||||||
|
|
||||||
if instruction != nil {
|
if instruction != nil {
|
||||||
ansi.Dim.Println("├──────────────────────────────────────┤")
|
ansi.Dim.Println("├──────────────────────────────────────┤")
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
type Result struct {
|
type Result struct {
|
||||||
Used []*Function
|
Used []*Function
|
||||||
Unused map[string]*Function
|
Unused map[string]*Function
|
||||||
instructionCount int
|
InstructionCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalize generates the final machine code.
|
// 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
|
// 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`.
|
// a return address on the stack, which allows return statements in `main`.
|
||||||
final := asm.Assembler{
|
final := asm.Assembler{
|
||||||
Instructions: make([]asm.Instruction, 0, r.instructionCount+4),
|
Instructions: make([]asm.Instruction, 0, r.InstructionCount+4),
|
||||||
}
|
}
|
||||||
|
|
||||||
final.Call("main")
|
final.Call("main")
|
||||||
|
@ -39,8 +39,6 @@ func compile(functions <-chan *Function, errors <-chan error) (Result, error) {
|
|||||||
if function.Error != nil {
|
if function.Error != nil {
|
||||||
return result, function.Error
|
return result, function.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
result.instructionCount += len(function.Assembler.Instructions)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main, exists := result.Unused["main"]
|
main, exists := result.Unused["main"]
|
||||||
@ -49,8 +47,8 @@ func compile(functions <-chan *Function, errors <-chan error) (Result, error) {
|
|||||||
return result, fail.MissingMainFunction
|
return result, fail.MissingMainFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Used = append(result.Used, main)
|
result.Used = make([]*Function, 0, len(result.Unused))
|
||||||
delete(result.Unused, "main")
|
result.markAlive(main)
|
||||||
result.findAliveCode(main)
|
result.findAliveCode(main)
|
||||||
|
|
||||||
return result, nil
|
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.
|
// findAliveCode recursively finds all the calls to external functions and marks them as required.
|
||||||
func (result *Result) findAliveCode(f *Function) {
|
func (result *Result) findAliveCode(caller *Function) {
|
||||||
for _, x := range f.Assembler.Instructions {
|
for _, x := range caller.Assembler.Instructions {
|
||||||
if x.Mnemonic != asm.CALL {
|
if x.Mnemonic != asm.CALL {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
name := x.Data.(*asm.Label).Name
|
name := x.Data.(*asm.Label).Name
|
||||||
called, exists := result.Unused[name]
|
callee, exists := result.Unused[name]
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Used = append(result.Used, called)
|
result.markAlive(callee)
|
||||||
delete(result.Unused, name)
|
result.findAliveCode(callee)
|
||||||
result.findAliveCode(called)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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