compiler: add support for type parameters (aka generics)

...that was surprisingly easy.
This commit is contained in:
Ayke van Laethem
2022-06-11 16:25:34 +02:00
committed by Ron Evans
parent 283fed16a5
commit bb65c5ce2b
11 changed files with 83 additions and 17 deletions
+9
View File
@@ -21,6 +21,10 @@ import (
"tinygo.org/x/go-llvm"
)
var typeParamUnderlyingType = func(t types.Type) types.Type {
return t
}
func init() {
llvm.InitializeAllTargets()
llvm.InitializeAllTargetMCs()
@@ -335,6 +339,7 @@ func (c *compilerContext) getLLVMType(goType types.Type) llvm.Type {
// makeLLVMType creates a LLVM type for a Go type. Don't call this, use
// getLLVMType instead.
func (c *compilerContext) makeLLVMType(goType types.Type) llvm.Type {
goType = typeParamUnderlyingType(goType)
switch typ := goType.(type) {
case *types.Array:
elemType := c.getLLVMType(typ.Elem())
@@ -444,6 +449,7 @@ func (c *compilerContext) getDIType(typ types.Type) llvm.Metadata {
// createDIType creates a new DWARF type. Don't call this function directly,
// call getDIType instead.
func (c *compilerContext) createDIType(typ types.Type) llvm.Metadata {
typ = typeParamUnderlyingType(typ)
llvmType := c.getLLVMType(typ)
sizeInBytes := c.targetData.TypeAllocSize(llvmType)
switch typ := typ.(type) {
@@ -794,6 +800,9 @@ func (c *compilerContext) createPackage(irbuilder llvm.Builder, pkg *ssa.Package
for _, method := range methods {
// Parse this method.
fn := pkg.Prog.MethodValue(method)
if fn == nil {
continue // probably a generic method
}
if fn.Blocks == nil {
continue // external function
}
+18
View File
@@ -0,0 +1,18 @@
//go:build go1.18
// +build go1.18
package compiler
// Workaround for Go 1.17 support. Should be removed once we drop Go 1.17
// support.
import "go/types"
func init() {
typeParamUnderlyingType = func(t types.Type) types.Type {
if t, ok := t.(*types.TypeParam); ok {
return t.Underlying()
}
return t
}
}
+1 -1
View File
@@ -191,7 +191,7 @@ func (c *compilerContext) getFunction(fn *ssa.Function) llvm.Value {
// should be created right away.
// The exception is the package initializer, which does appear in the
// *ssa.Package members and so shouldn't be created here.
if fn.Synthetic != "" && fn.Synthetic != "package initializer" {
if fn.Synthetic != "" && fn.Synthetic != "package initializer" && fn.Synthetic != "generic function" {
irbuilder := c.ctx.NewBuilder()
b := newBuilder(c, irbuilder, fn)
b.createFunction()