package loader
import (
"testing"
"github.com/marzeq/qk/codegen/irgen"
"github.com/marzeq/qk/ir"
"github.com/marzeq/qk/types"
)
func TestExtractGenericSpecializationsRenamesFunctionConstantCallee(t *testing.T) {
parameter := types.TypeParameter{Owner: "example.make", Name: "T", Index: 0}
baseName := irgen.MangleFunctionName("example", "make")
signature := ir.FunctionSignature{ReturnType: types.PrimitiveVoid}
templateFunction := ir.NewFunction(baseName, ir.LinkageInternal, nil)
templateFunction.Signature = signature
templateFunction.Entry = templateFunction.NewBlock("entry").ID
templateFunction.Blocks[0].Instr = append(templateFunction.Blocks[0].Instr, ir.Return{})
template := ir.GenericTemplate{
Module: "example", Name: "make", Parameters: []types.TypeParameter{parameter},
Functions: []*ir.Function{templateFunction},
}
caller := ir.NewFunction("caller", ir.LinkageInternal, nil)
caller.Signature = signature
caller.Entry = caller.NewBlock("entry").ID
callee := ir.FunctionConstOperand(baseName, types.PointerType{Base: types.FunctionType{ReturnType: types.PrimitiveVoid}})
caller.Blocks[0].Instr = append(caller.Blocks[0].Instr,
ir.Call{Callee: &callee, Signature: signature, Generic: &ir.GenericReference{
Module: "example", Name: "make", TypeArguments: []types.Type{types.PrimitiveU8},
}},
ir.Return{},
)
units, err := ExtractGenericSpecializationUnits(
map[string]*ir.Module{"main": {Functions: []*ir.Function{caller}}},
map[string][]ir.GenericTemplate{"example": {template}},
nil,
)
if err != nil {
t.Fatal(err)
}
call := caller.Blocks[0].Instr[0].(ir.Call)
if call.Generic == nil {
t.Fatal("generic demand metadata was not preserved")
}
if call.Callee == nil || call.Callee.FunctionName == baseName {
t.Fatalf("function-constant callee was not specialized: %#v", call.Callee)
}
if len(units) != 1 || units[0].DefiningModule != "example" || units[0].Key == "" {
t.Fatalf("unexpected specialization units: %#v", units)
}
if len(units[0].IR.Functions) != 1 || units[0].IR.Functions[0].Name != call.Callee.FunctionName {
t.Fatalf("specialization target %q does not match generated function", call.Callee.FunctionName)
}
}