Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the mangling algorithm #1574

Merged
merged 9 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .typos.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[default.extend-words]
inout = "inout" # Mutable projection keyword
olt = "olt" # Abbreviation for "ordered less than"

[files]
extend-exclude = ["Tests/ManglingTests/MangledStrings.swift"]
1 change: 1 addition & 0 deletions Sources/FrontEnd/AST/Decl/SynthesizedFunctionDecl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public struct SynthesizedFunctionDecl: Hashable {
parameterizedBy genericParameters: [GenericParameterDecl.ID],
in scope: AnyScopeID
) {
precondition(type[.isCanonical])
precondition(type.environment.base is TupleType)
self.type = type
self.genericParameters = genericParameters
Expand Down
5 changes: 5 additions & 0 deletions Sources/FrontEnd/CompileTimeValues/CompileTimeValue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ public enum CompileTimeValue: Hashable {
}
}

/// `true` iff self is in canonical form.
public var isCanonical: Bool {
if let t = asType { t[.isCanonical] } else { true }
}

/// `true` if `self` is a `TypeVariable`.
public var isTypeVariable: Bool {
asType?.base is TypeVariable
Expand Down
10 changes: 10 additions & 0 deletions Sources/FrontEnd/TypedProgram.swift
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,16 @@ public struct TypedProgram {
self.base = base
}

/// Returns the canonical form of `d`'s type.
public func canonical<T: DeclID>(typeOf d: T) -> AnyType {
canonical(declType[d]!, in: nodeToScope[d]!)
}

/// Returns the canonical form of `e`'s type.
public func canonical<T: ExprID>(typeOf e: T) -> AnyType {
canonical(exprType[e]!, in: nodeToScope[e]!)
}

/// Returns the canonical form of `t` in `scopeOfUse`.
public func canonical(_ t: AnyType, in scopeOfUse: AnyScopeID) -> AnyType {
if t[.isCanonical] { return t }
Expand Down
3 changes: 2 additions & 1 deletion Sources/IR/Analysis/Module+Depolymorphize.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ extension IR.Program {

// TODO: Use existentialization unless the subscript is inlinable

let g = monomorphize(s.callee, for: s.specialization, usedIn: modules[m]!.scope(containing: i))
let z = base.canonical(s.specialization, in: modules[m]!.scope(containing: i))
let g = monomorphize(s.callee, for: z, usedIn: modules[m]!.scope(containing: i))
let new = modules[m]!.makeProject(
s.projection, applying: g, specializedBy: .empty, to: s.operands, at: s.site)
modules[m]!.replace(i, with: new)
Expand Down
2 changes: 1 addition & 1 deletion Sources/IR/Emitter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ struct Emitter {
precondition(program.isGlobal(d))
precondition(read(program[d].pattern.introducer.value, { ($0 == .let) || ($0 == .sinklet) }))

let r = RemoteType(.set, program[d].type)
let r = RemoteType(.set, program.canonical(typeOf: d))
let l = ArrowType(
receiverEffect: .set, environment: ^TupleType(types: [^r]), inputs: [], output: .void)
let f = SynthesizedFunctionDecl(
Expand Down
6 changes: 4 additions & 2 deletions Sources/IR/FunctionID.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,21 @@ extension Function {

/// Creates the identity of the lowered form of `s`.
init(_ s: SynthesizedFunctionDecl) {
precondition(s.type[.isCanonical])
self.value = .synthesized(s)
}

/// Creates the identity of the existentialized form of `base`.
public init(existentialized base: Function.ID) {
init(existentialized base: Function.ID) {
self.value = .existentialized(base: base)
}

/// Creates the identity of the monomorphized form of `base` for `arguments`.
///
/// - Requires: `arguments` is not empty.
public init(monomorphized base: Function.ID, for arguments: GenericArguments) {
init(monomorphized base: Function.ID, for arguments: GenericArguments) {
precondition(!arguments.isEmpty)
precondition(arguments.allSatisfy(\.value.isCanonical))
self.value = .monomorphized(base: base, arguments: arguments)
}

Expand Down
36 changes: 22 additions & 14 deletions Sources/IR/Mangling/DemangledEntity.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Utils
public struct DemangledEntity: Hashable {

/// The qualification of the symbol, if any.
public let qualification: Indirect<DemangledEntity>?
public let qualification: DemangledQualification?

/// The kind of the symbol, if known.
public let kind: NodeKind?
Expand All @@ -24,13 +24,13 @@ public struct DemangledEntity: Hashable {

/// Creates an instance with the given properties.
public init(
qualification: DemangledEntity?,
qualification: DemangledQualification?,
kind: NodeKind,
name: Name,
genericArgumentLabels: [String?] = [],
type: DemangledType? = nil
) {
self.qualification = qualification.map(Indirect.init(_:))
self.qualification = qualification
self.kind = kind
self.name = name
self.genericArgumentLabels = genericArgumentLabels
Expand All @@ -39,8 +39,8 @@ public struct DemangledEntity: Hashable {
}

/// Creates an instance identifying an anonymous scope.
public init(anonymousScope id: Int, qualifiedBy q: DemangledEntity) {
self.qualification = Indirect(q)
public init(anonymousScope id: Int, qualifiedBy q: DemangledQualification) {
self.qualification = q
self.kind = nil
self.name = Name(stem: id.description)
self.genericArgumentLabels = []
Expand All @@ -51,7 +51,9 @@ public struct DemangledEntity: Hashable {
/// Creates an instance representing a core type declaration.
public init(coreType: String) {
self.init(
qualification: .hylo, kind: NodeKind(ProductTypeDecl.self), name: Name(stem: coreType))
qualification: .entity(.hylo),
kind: NodeKind(ProductTypeDecl.self),
name: Name(stem: coreType))
}

/// The `Hylo` module.
Expand Down Expand Up @@ -121,20 +123,26 @@ extension DemangledEntity: CustomStringConvertible {
}

let i = inputs.reduce(into: "", { (s, p) in s += (p.label ?? "_") + ":" })
return "\(name)(\(i))"
return "\(name)[\(i)]"
}

/// Returns the textual description of a qualification.
private static func describe(qualification: Indirect<DemangledEntity>?) -> String {
guard let q = qualification else {
private static func describe(qualification: DemangledQualification?) -> String {
switch qualification {
case .some(.entity(let q)):
if q.kind?.value == TranslationUnit.self {
return describe(qualification: q.qualification)
} else {
return q.description + "."
}

case .some(let q):
return q.description

case nil:
return ""
}

if q.value.kind?.value == TranslationUnit.self {
return describe(qualification: q.value.qualification)
} else {
return q.description + "."
}
}

}
41 changes: 41 additions & 0 deletions Sources/IR/Mangling/DemangledQualification.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/// The demangled qualification of a symbol.
public indirect enum DemangledQualification: Hashable {

/// An entity.
case entity(DemangledEntity)

/// A reference to the innermost enclosing entity.
case relative

/// Creates an instance wrapping `e` iff it is not `nil`.
init?(_ e: DemangledEntity?) {
if let s = e {
self = .entity(s)
} else {
return nil
}
}

/// The entity wrapped in `self` if its payload is `.entity`, or `nil` otherwise.
public var entity: DemangledEntity? {
if case .entity(let e) = self {
return e
} else {
return nil
}
}

}

extension DemangledQualification: CustomStringConvertible {

public var description: String {
switch self {
case .entity(let d):
return d.description
case .relative:
return ".."
}
}

}
17 changes: 16 additions & 1 deletion Sources/IR/Mangling/DemangledSymbol.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Utils

/// The demangled description of a or entity.
public enum DemangledSymbol: Hashable {
public indirect enum DemangledSymbol: Hashable {

/// Creates an instance decoding the symbol mangled in `s`, returning `nil` if decoding failed.
public init?(_ s: String) {
Expand Down Expand Up @@ -41,6 +41,15 @@ public enum DemangledSymbol: Hashable {
/// The declaration of an entity or bundle.
case entity(DemangledEntity)

/// A binding declaration.
case binding(names: [DemangledEntity])

/// A synthesized declaration.
case synthesized(DemangledSynthesizedFunction)

/// A monomorphized symbols.
case monomorphized(DemangledSymbol, arguments: [DemangledSymbol])

/// A type.
case type(DemangledType)

Expand All @@ -61,6 +70,12 @@ extension DemangledSymbol: CustomStringConvertible {
switch self {
case .entity(let e):
return e.description
case .binding(let n):
return n.description
case .synthesized(let d):
return d.description
case .monomorphized(let e, let z):
return "\(e) for \(z)"
case .type(let t):
return t.description
}
Expand Down
49 changes: 49 additions & 0 deletions Sources/IR/Mangling/DemangledSynthesizedFunction.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Utils

/// The demangled description of a synthesized function.
public struct DemangledSynthesizedFunction: Hashable {

/// The kind of a synthesized declaration.
public indirect enum Kind: Hashable {

/// A deinitializer.
case deinitialize

/// A move-initialization method.
case moveInitialization

/// A move-assignment method.
case moveAssignment

/// A copy method.
case copy

/// An equality method.
case equal

/// A global initializer for a binding declaration.
case globalInitialization(DemangledSymbol)

/// Lambda generated for an autoclosure argument.
case autoclosure(Int)

}

/// The type of this declaration.
public let type: DemangledType

/// The scope in which the declaration is defined.
public let scope: Indirect<DemangledSymbol>

/// The kind of the declaration.
public let kind: Kind

}

extension DemangledSynthesizedFunction: CustomStringConvertible {

public var description: String {
"\(scope).\(kind)"
}

}
4 changes: 2 additions & 2 deletions Sources/IR/Mangling/DemangledType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ extension DemangledType: CustomStringConvertible {
let i = inputs.map { (p) -> String in
(p.label.map({ $0 + ": " }) ?? "") + p.type.description
}
return "[\(environment)](\(list: i) \(effect) -> \(output)"
return "[\(environment)](\(list: i)) \(effect) -> \(output)"

case .associatedType(let domain, let name):
return "\(domain).\(name)"
Expand Down Expand Up @@ -135,7 +135,7 @@ extension DemangledType: CustomStringConvertible {
(p.label.map({ $0 + ": " }) ?? "") + p.type.description
}
let cs = capabilities.elements.descriptions(joinedBy: " ")
return "[\(environment)](\(list: i) : \(output) { \(cs) }"
return "[\(environment)](\(list: i)) : \(output) { \(cs) }"

case .union(let elements):
return "Union<\(list: elements)>"
Expand Down
Loading