Пример #1
0
func isTypeRecursive(typ ast.Type) (bool, []ast.Type) {
	typ = typ.ActualType()

	var check func(current ast.Type, path *[]ast.Type, traversed map[ast.Type]bool) bool
	check = func(current ast.Type, path *[]ast.Type, traversed map[ast.Type]bool) bool {
		switch current.(type) {
		case *ast.NamedType:
			if traversed[current] {
				return true
			}
		}

		switch typ := current.(type) {
		case ast.StructType:
			for _, mem := range typ.Members {
				if check(mem.Type.BaseType, path, traversed) {
					*path = append(*path, mem.Type.BaseType)
					return true
				}
			}

		case ast.TupleType:
			for _, mem := range typ.Members {
				if check(mem.BaseType, path, traversed) {
					*path = append(*path, mem.BaseType)
					return true
				}
			}

		case ast.EnumType:
			for _, mem := range typ.Members {
				if check(mem.Type, path, traversed) {
					*path = append(*path, mem.Type)
					return true
				}
			}

		case *ast.NamedType:
			traversed[current] = true
			if check(typ.Type, path, traversed) {
				*path = append(*path, typ.Type)
				return true
			}
			traversed[current] = false

		case ast.ArrayType:
			if typ.IsFixedLength && check(typ.MemberType.BaseType, path, traversed) {
				*path = append(*path, typ.MemberType.BaseType)
				return true
			}
		}
		return false
	}

	var path []ast.Type
	return check(typ, &path, make(map[ast.Type]bool)), path
}
Пример #2
0
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")
	}
}
Пример #3
0
func typeContainsReferenceType(typ ast.Type, visited map[*ast.TypeReference]struct{ visited, value bool }) bool {
	switch typ := typ.ActualType().(type) {
	case ast.ReferenceType:
		return true

	case ast.PointerType:
		return typeReferenceContainsReferenceType(typ.Addressee, visited)

	case ast.ArrayType:
		return typeReferenceContainsReferenceType(typ.MemberType, visited)

	case ast.StructType:
		for _, field := range typ.Members {
			if typeReferenceContainsReferenceType(field.Type, visited) {
				return true
			}
		}
		return false

	case ast.EnumType:
		for _, member := range typ.Members {
			if typeContainsReferenceType(member.Type, visited) {
				return true
			}
		}
		return false

	case ast.TupleType:
		for _, field := range typ.Members {
			if typeReferenceContainsReferenceType(field, visited) {
				return true
			}
		}
		return false

	case *ast.SubstitutionType, ast.PrimitiveType, ast.FunctionType:
		return false

	default:
		panic("unimplemented type: " + reflect.TypeOf(typ).String())
	}
}