Implemented dead code elimination
This commit is contained in:
parent
d86d411959
commit
526b92aa09
@ -27,6 +27,7 @@ func TestErrors(t *testing.T) {
|
||||
{"MissingBlockStart.q", errors.MissingBlockStart},
|
||||
{"MissingGroupEnd.q", errors.MissingGroupEnd},
|
||||
{"MissingGroupStart.q", errors.MissingGroupStart},
|
||||
{"MissingMainFunction.q", errors.MissingMainFunction},
|
||||
{"VariableAlreadyExists.q", &errors.VariableAlreadyExists{Name: "x"}},
|
||||
{"UnknownIdentifier.q", &errors.UnknownIdentifier{Name: "x"}},
|
||||
{"UnknownIdentifier2.q", &errors.UnknownIdentifier{Name: "x"}},
|
||||
|
@ -14,3 +14,7 @@ print(address, length) {
|
||||
write(fd, address, length) {
|
||||
syscall(1, fd, address, length)
|
||||
}
|
||||
|
||||
empty() {
|
||||
|
||||
}
|
@ -8,7 +8,8 @@ import (
|
||||
|
||||
// Result contains all the compiled functions in a build.
|
||||
type Result struct {
|
||||
Functions map[string]*Function
|
||||
Used []*Function
|
||||
Unused map[string]*Function
|
||||
instructionCount int
|
||||
}
|
||||
|
||||
@ -27,13 +28,8 @@ func (r Result) Finalize() ([]byte, []byte) {
|
||||
final.RegisterNumber(asm.MOVE, x64.SyscallRegisters[1], 0)
|
||||
final.Syscall()
|
||||
|
||||
// Place the `main` function immediately after the entry point.
|
||||
main := r.Functions["main"]
|
||||
delete(r.Functions, "main")
|
||||
final.Merge(&main.Assembler)
|
||||
|
||||
// Merge all the remaining functions.
|
||||
for _, f := range r.Functions {
|
||||
// Merge all the called functions.
|
||||
for _, f := range r.Used {
|
||||
final.Merge(&f.Assembler)
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,15 @@ package build
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"git.akyoto.dev/cli/q/src/build/asm"
|
||||
fail "git.akyoto.dev/cli/q/src/errors"
|
||||
)
|
||||
|
||||
// compile waits for the scan to finish and compiles all functions.
|
||||
func compile(functions <-chan *Function, errors <-chan error) (Result, error) {
|
||||
result := Result{
|
||||
Functions: map[string]*Function{},
|
||||
Unused: map[string]*Function{},
|
||||
}
|
||||
|
||||
for functions != nil || errors != nil {
|
||||
@ -26,13 +29,13 @@ func compile(functions <-chan *Function, errors <-chan error) (Result, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
result.Functions[function.Name] = function
|
||||
result.Unused[function.Name] = function
|
||||
}
|
||||
}
|
||||
|
||||
compileFunctions(result.Functions)
|
||||
compileFunctions(result.Unused)
|
||||
|
||||
for _, function := range result.Functions {
|
||||
for _, function := range result.Unused {
|
||||
if function.Error != nil {
|
||||
return result, function.Error
|
||||
}
|
||||
@ -40,9 +43,38 @@ func compile(functions <-chan *Function, errors <-chan error) (Result, error) {
|
||||
result.instructionCount += len(function.Assembler.Instructions)
|
||||
}
|
||||
|
||||
main, exists := result.Unused["main"]
|
||||
|
||||
if !exists {
|
||||
return result, fail.MissingMainFunction
|
||||
}
|
||||
|
||||
result.Used = append(result.Used, main)
|
||||
delete(result.Unused, "main")
|
||||
result.findCalls(main)
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (result *Result) findCalls(f *Function) {
|
||||
for _, x := range f.Assembler.Instructions {
|
||||
if x.Mnemonic != asm.CALL {
|
||||
continue
|
||||
}
|
||||
|
||||
name := x.Data.(*asm.Label).Name
|
||||
called, exists := result.Unused[name]
|
||||
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
|
||||
result.Used = append(result.Used, called)
|
||||
delete(result.Unused, name)
|
||||
result.findCalls(called)
|
||||
}
|
||||
}
|
||||
|
||||
// compileFunctions starts a goroutine for each function compilation and waits for completion.
|
||||
func compileFunctions(functions map[string]*Function) {
|
||||
wg := sync.WaitGroup{}
|
||||
|
@ -43,7 +43,7 @@ func Build(args []string) int {
|
||||
}
|
||||
|
||||
if config.Verbose {
|
||||
for _, function := range result.Functions {
|
||||
for _, function := range result.Used {
|
||||
function.PrintAsm()
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
package errors
|
||||
|
||||
var (
|
||||
InvalidStatement = &Base{"Invalid statement"}
|
||||
InvalidExpression = &Base{"Invalid expression"}
|
||||
MissingAssignValue = &Base{"Missing assignment value"}
|
||||
NotImplemented = &Base{"Not implemented"}
|
||||
InvalidStatement = &Base{"Invalid statement"}
|
||||
InvalidExpression = &Base{"Invalid expression"}
|
||||
MissingAssignValue = &Base{"Missing assignment value"}
|
||||
MissingMainFunction = &Base{"Missing main function"}
|
||||
NotImplemented = &Base{"Not implemented"}
|
||||
)
|
||||
|
0
tests/errors/MissingMainFunction.q
Normal file
0
tests/errors/MissingMainFunction.q
Normal file
Loading…
Reference in New Issue
Block a user