func (v *Codegen) addNamedTypeReference(n *ast.TypeReference, gcon *ast.GenericContext) { outer := gcon gcon = ast.NewGenericContextFromTypeReference(n) gcon.Outer = outer v.addNamedType(n.BaseType.(*ast.NamedType), ast.TypeReferenceMangledName(ast.MANGLE_ARK_UNSTABLE, n, gcon), gcon) }
// if outer is not nil, this function does not add the current function gcon as outer, as it assumes it is already there func (v *Codegen) typeRefToLLVMTypeWithOuter(typ *ast.TypeReference, outer *ast.GenericContext) llvm.Type { var gcon *ast.GenericContext if len(typ.GenericArguments) > 0 { gcon = ast.NewGenericContextFromTypeReference(typ) } else { gcon = ast.NewGenericContext(nil, nil) } if outer != nil { gcon.Outer = outer } else if v.inFunction() { gcon.Outer = v.currentFunction().gcon } return v.typeRefToLLVMTypeWithGenericContext(typ, gcon) }
func (v *Codegen) typeToLLVMType(typ ast.Type, gcon *ast.GenericContext) llvm.Type { switch typ := typ.(type) { case ast.PrimitiveType: return v.primitiveTypeToLLVMType(typ) case ast.FunctionType: return v.functionTypeToLLVMType(typ, true, gcon) case ast.StructType: return v.structTypeToLLVMType(typ, gcon) case ast.PointerType: return llvm.PointerType(v.typeRefToLLVMTypeWithOuter(typ.Addressee, gcon), 0) case ast.ArrayType: return v.arrayTypeToLLVMType(typ, gcon) case ast.TupleType: return v.tupleTypeToLLVMType(typ, gcon) case ast.EnumType: return v.enumTypeToLLVMType(typ, gcon) case ast.ReferenceType: return llvm.PointerType(v.typeRefToLLVMTypeWithOuter(typ.Referrer, gcon), 0) case *ast.NamedType: switch typ.Type.(type) { case ast.StructType, ast.EnumType: // If something seems wrong with the code and thie problems seems to come from here, // make sure the type doesn't need generics arguments as well. // This here ignores them. name := ast.TypeReferenceMangledName(ast.MANGLE_ARK_UNSTABLE, &ast.TypeReference{BaseType: typ}, gcon) v.addNamedType(typ, name, gcon) lt := v.namedTypeLookup[name] return lt default: return v.typeToLLVMType(typ.Type, gcon) } case *ast.SubstitutionType: if gcon == nil { panic("gcon == nil when getting substitution type") } if gcon.GetSubstitutionType(typ) == nil { panic("missing generic map entry for type " + typ.TypeName() + " " + fmt.Sprintf("(%p)", typ)) } return v.typeRefToLLVMTypeWithOuter(gcon.GetSubstitutionType(typ), gcon) default: log.Debugln("codegen", "Type was %s (%s)", typ.TypeName(), reflect.TypeOf(typ)) panic("Unimplemented type category in LLVM codegen") } }
// parentEnum is nil if not in enum func (v *TypeCheck) CheckTupleLiteral(s *SemanticAnalyzer, lit *ast.TupleLiteral) { tupleType, ok := lit.GetType().BaseType.ActualType().(ast.TupleType) if !ok { panic("Type of tuple literal was not `TupleType`") } memberTypes := tupleType.Members if len(lit.Members) != len(memberTypes) { s.Err(lit, "Invalid amount of entries in tuple") } var gcon *ast.GenericContext if lit.ParentEnumLiteral != nil { gcon = ast.NewGenericContext(lit.ParentEnumLiteral.GetType().BaseType.ActualType().(ast.EnumType).GenericParameters, lit.ParentEnumLiteral.Type.GenericArguments) } else { gcon = ast.NewGenericContext(nil, nil) } for idx, mem := range lit.Members { expectType(s, mem, gcon.Get(memberTypes[idx]), &mem) } }