fspl/generator/function.go

107 lines
2.7 KiB
Go

package generator
import "git.tebibyte.media/fspl/fspl/llvm"
import "git.tebibyte.media/fspl/fspl/entity"
func (this *generator) generateFunction (
function *entity.Function,
) (
*llvm.Function,
error,
) {
key := entity.Key {
Unit: function.Unit(),
Name: function.Signature.Name,
}
params := make([]*llvm.Parameter, len(function.Signature.Arguments))
ret, err := this.generateType(function.Signature.Return)
if err != nil { return nil, err }
for index, argument := range function.Signature.Arguments {
paramType, err := this.generateType(argument.Type())
if err != nil { return nil, err }
params[index] = llvm.NewParameter(argument.Name, paramType)
}
var name string; if function.LinkName == "" {
name = key.LinkName()
} else {
name = function.LinkName
}
irFunc := this.module.NewFunction(name, ret, params...)
if function.Body != nil {
this.blockManager = this.pushBlockManager(irFunc)
defer this.popBlockManager()
this.blockManager.addFunctionArgumentDeclarations(function)
if function.Signature.Return == nil {
_, _, err := this.generateExpressionAny(function.Body)
if err != nil { return nil, err }
this.blockManager.NewRet(nil)
} else {
body, err := this.generateExpressionVal(function.Body)
if err != nil { return nil, err }
this.blockManager.NewRet(body)
}
}
this.functions[key] = irFunc
return irFunc, nil
}
func (this *generator) generateMethod (
method *entity.Method,
) (
*llvm.Function,
error,
) {
key := entity.Key {
Unit: method.Unit(),
Name: method.TypeName,
Method: method.Signature.Name,
}
params := make([]*llvm.Parameter, len(method.Signature.Arguments) + 1)
ret, err := this.generateType(method.Signature.Return)
if err != nil { return nil, err }
for index, argument := range method.Signature.Arguments {
paramType, err := this.generateType(argument.Type())
if err != nil { return nil, err }
params[index + 1] = llvm.NewParameter(argument.Name, paramType)
}
params[0] = llvm.NewParameter("this", new(llvm.TypePointer))
var name string; if method.LinkName == "" {
name = key.LinkName()
} else {
name = method.LinkName
}
irFunc := this.module.NewFunction(name, ret, params...)
if method.Body != nil {
this.blockManager = this.pushBlockManager(irFunc)
defer this.popBlockManager()
this.blockManager.addFunctionArgumentDeclarations(method)
if method.Signature.Return == nil {
_, _, err := this.generateExpressionAny(method.Body)
if err != nil { return nil, err }
this.blockManager.NewRet(nil)
} else {
body, err := this.generateExpressionVal(method.Body)
if err != nil { return nil, err }
this.blockManager.NewRet(body)
}
}
this.functions[key] = irFunc
return irFunc, nil
}