Skip to content

Commit

Permalink
Merge pull request #1574 from hylo-lang/fix-mangling
Browse files Browse the repository at this point in the history
Fix the mangling algorithm
  • Loading branch information
kyouko-taiga authored Aug 30, 2024
2 parents 263d7e5 + 26ee883 commit f7d5964
Show file tree
Hide file tree
Showing 18 changed files with 804 additions and 574 deletions.
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

0 comments on commit f7d5964

Please sign in to comment.