fspl/generator/generator.go

144 lines
3.4 KiB
Go
Raw Normal View History

2023-11-14 07:49:55 +00:00
package generator
2023-11-17 03:04:56 +00:00
import "sort"
import "errors"
2024-02-23 00:22:53 +00:00
import "git.tebibyte.media/fspl/fspl/llvm"
import "git.tebibyte.media/fspl/fspl/entity"
import "git.tebibyte.media/fspl/fspl/analyzer"
2023-11-14 07:49:55 +00:00
2023-12-15 17:40:27 +00:00
var errNotFound = errors.New("entity not found")
2023-11-17 03:04:56 +00:00
// Target contains information about the machine the code is being written for.
type Target struct {
// WordSize is the size of the machine word. This determines the width
// of the Word type.
WordSize uint64
// Arch specifies the machine architecture
Arch string
}
2023-11-14 07:49:55 +00:00
type generator struct {
2023-11-21 20:04:22 +00:00
target Target
tree analyzer.Tree
2023-11-23 06:26:14 +00:00
module *llvm.Module
2023-11-21 20:04:22 +00:00
2024-02-20 02:00:20 +00:00
types map[entity.Key] llvm.Type
functions map[entity.Key] *llvm.Function
2023-12-20 08:05:27 +00:00
2023-11-21 20:04:22 +00:00
managerStack []*blockManager
blockManager *blockManager
2023-11-14 07:49:55 +00:00
}
// Generate takes in a semantic tree and writes corresponding LLVM IR to the
// given io.Writer. It returns an error in case there is something wrong with
// the semantic tree that prevents the code generation process from occurring.
2023-11-23 06:26:14 +00:00
func (this Target) Generate (tree analyzer.Tree) (*llvm.Module, error) {
2023-11-14 07:49:55 +00:00
return (&generator {
2023-12-20 08:05:27 +00:00
module: new(llvm.Module),
target: this,
tree: tree,
2024-02-20 02:00:20 +00:00
types: make(map[entity.Key] llvm.Type),
functions: make(map[entity.Key] *llvm.Function),
2023-11-14 07:49:55 +00:00
}).generate()
}
2023-11-23 06:26:14 +00:00
func (this *generator) generate () (*llvm.Module, error) {
// generate functions
2024-02-20 02:00:20 +00:00
functions := sortKeyedMapKeys(this.tree.Functions)
for _, key := range functions {
_, err := this.function(key)
2023-11-23 06:26:14 +00:00
if err != nil { return nil, err }
2023-11-17 03:41:20 +00:00
}
2023-11-17 03:04:56 +00:00
2023-12-03 04:41:35 +00:00
// generate methods
2024-02-20 02:00:20 +00:00
types := sortKeyedMapKeys(this.tree.Types)
for _, key := range types {
ty := this.tree.Types[key]
2023-12-03 04:41:35 +00:00
methods := sortMapKeys(ty.Methods)
for _, methodName := range methods {
2024-02-20 02:00:20 +00:00
methodKey := key
methodKey.Method = methodName
_, err := this.method(methodKey)
2023-12-03 04:41:35 +00:00
if err != nil { return nil, err }
}
}
2023-11-23 06:26:14 +00:00
return this.module, nil
2023-11-14 07:49:55 +00:00
}
2023-11-16 20:52:28 +00:00
2024-02-20 02:00:20 +00:00
func (this *generator) typedef (key entity.Key) (llvm.Type, error) {
ty, exists := this.types[key]
if exists { return ty, nil }
def, exists := this.tree.Types[key]
2023-11-17 03:04:56 +00:00
if !exists {
2023-12-15 17:40:27 +00:00
return nil, errNotFound
2023-11-17 03:04:56 +00:00
}
return this.generateTypedef(def)
2023-11-16 20:52:28 +00:00
}
2024-02-20 02:00:20 +00:00
func (this *generator) method (key entity.Key) (*llvm.Function, error) {
method, exists := this.functions[key]
2023-12-20 08:05:27 +00:00
if exists { return method, nil }
2024-02-20 02:00:20 +00:00
ty, exists := this.tree.Types[key.StripMethod()]
2023-12-03 02:45:15 +00:00
if !exists {
2023-12-15 17:40:27 +00:00
return nil, errNotFound
2023-12-03 02:45:15 +00:00
}
2023-12-20 08:05:27 +00:00
2024-02-20 02:00:20 +00:00
if method, exists := ty.Methods[key.Method]; exists {
2023-12-20 08:05:27 +00:00
return this.generateMethod(method)
2023-12-15 17:40:27 +00:00
}
2023-12-20 08:05:27 +00:00
return nil, errNotFound
2023-11-16 20:52:28 +00:00
}
2024-02-20 02:00:20 +00:00
func (this *generator) function (key entity.Key) (*llvm.Function, error) {
function, exists := this.functions[key]
2023-12-20 08:05:27 +00:00
if exists { return function, nil }
2024-02-20 02:00:20 +00:00
if function, exists := this.tree.Functions[key]; exists {
2023-12-20 08:05:27 +00:00
return this.generateFunction(function)
2023-12-15 17:40:27 +00:00
}
2023-12-20 08:05:27 +00:00
return nil, errNotFound
2023-11-16 20:52:28 +00:00
}
2023-11-17 03:04:56 +00:00
func sortMapKeys[T any] (unsorted map[string] T) []string {
keys := make([]string, len(unsorted))
index := 0
for key := range unsorted {
keys[index] = key
index ++
}
sort.Strings(keys)
return keys
}
2024-02-20 02:00:20 +00:00
type keySlice []entity.Key
func (keys keySlice) Len () int {
return len(keys)
}
func (keys keySlice) Less (lefti, righti int) bool {
left := keys[lefti]
right := keys[righti]
2024-02-20 02:57:21 +00:00
return left.String() < right.String()
2024-02-20 02:00:20 +00:00
}
func (keys keySlice) Swap (lefti, righti int) {
keys[lefti], keys[righti] = keys[righti], keys[lefti]
}
func sortKeyedMapKeys[T any] (unsorted map[entity.Key] T) keySlice {
keys := make(keySlice, len(unsorted))
index := 0
for key := range unsorted {
keys[index] = key
index ++
}
sort.Sort(keys)
return keys
}