File: StaticCanonicalStoring.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (140 lines) | stat: -rw-r--r-- 5,647 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import WIT

struct StaticCanonicalStoring: CanonicalStoring {
    typealias Operand = StaticMetaOperand
    typealias Pointer = StaticMetaPointer

    let printer: SourcePrinter
    let builder: SwiftFunctionBuilder
    let definitionMapping: DefinitionMapping

    private func storeByteSwappable(at pointer: Pointer, value: Operand, type: String) {
        let boundPointer = "\(pointer).assumingMemoryBound(to: \(type).self)"
        printer.write(line: "\(boundPointer).pointee = \(type)(\(value))")
    }

    private func storeUInt(at pointer: Pointer, value: Operand, bitWidth: Int) {
        storeByteSwappable(at: pointer, value: value, type: "UInt\(bitWidth)")
    }
    private func storeInt(at pointer: Pointer, value: Operand, bitWidth: Int) {
        storeByteSwappable(at: pointer, value: value, type: "Int\(bitWidth)")
    }
    private func storeFloat(at pointer: Pointer, value: Operand, bitWidth: Int) {
        storeUInt(at: pointer, value: .accessField(value, name: "bitPattern"), bitWidth: bitWidth)
    }

    func storeUInt8(at pointer: Pointer, _ value: Operand) {
        storeUInt(at: pointer, value: value, bitWidth: 8)
    }
    func storeUInt16(at pointer: Pointer, _ value: Operand) {
        storeUInt(at: pointer, value: value, bitWidth: 16)
    }
    func storeUInt32(at pointer: Pointer, _ value: Operand) {
        storeUInt(at: pointer, value: value, bitWidth: 32)
    }
    func storeUInt64(at pointer: Pointer, _ value: Operand) {
        storeUInt(at: pointer, value: value, bitWidth: 64)
    }
    func storeInt8(at pointer: Pointer, _ value: Operand) {
        storeInt(at: pointer, value: value, bitWidth: 8)
    }
    func storeInt16(at pointer: Pointer, _ value: Operand) {
        storeInt(at: pointer, value: value, bitWidth: 16)
    }
    func storeInt32(at pointer: Pointer, _ value: Operand) {
        storeInt(at: pointer, value: value, bitWidth: 32)
    }
    func storeInt64(at pointer: Pointer, _ value: Operand) {
        storeInt(at: pointer, value: value, bitWidth: 64)
    }
    func storeFloat32(at pointer: Pointer, _ value: Operand) {
        storeFloat(at: pointer, value: value, bitWidth: 32)
    }
    func storeFloat64(at pointer: Pointer, _ value: Operand) {
        storeFloat(at: pointer, value: value, bitWidth: 64)
    }

    func storeFlags(at pointer: Pointer, _ value: Operand, type: WITFlags) throws {
        let rawValueType = CanonicalABI.rawType(ofFlags: type.flags.count)
        let rawValue = Operand.accessField(value, name: "rawValue")
        switch rawValueType {
        case .u8: storeUInt8(at: pointer, rawValue)
        case .u16: storeUInt16(at: pointer, rawValue)
        case .u32(1): storeUInt32(at: pointer, rawValue)
        case .u32(let numberOfU32):
            for i in 0..<numberOfU32 {
                storeUInt32(at: pointer.advanced(by: i * 4), .accessField(rawValue, name: "field\(i)"))
            }
        }
    }

    func storeOption(
        at pointer: Pointer, _ value: Operand,
        storeDiscriminant: (Operand) throws -> Void,
        storePayload: (Operand) throws -> Void
    ) throws {
        printer.write(line: "switch \(value) {")
        let wrappedVar = builder.variable("wrapped")
        printer.write(line: "case .some(let \(wrappedVar)):")
        try printer.indent {
            try storeDiscriminant(.literal("1"))
            try storePayload(.variable(wrappedVar))
        }
        printer.write(line: "case .none:")
        try printer.indent {
            try storeDiscriminant(.literal("0"))
        }
        printer.write(line: "}")
    }

    func storeResult(
        at pointer: Pointer, _ value: Operand, ok: WITType?, error: WITType?,
        storeDiscriminant: (Operand) throws -> Void,
        storePayload: (Bool, Operand) throws -> Void
    ) throws {
        try storeVariantLike(
            at: pointer, value, variants: [ok, error],
            swiftCaseNames: ["success", "failure"],
            storeDiscriminant: storeDiscriminant,
            storePayload: { caseIndex, payload in
                let isFailure = caseIndex == 1
                try storePayload(isFailure, isFailure ? .accessField(payload, name: "content") : payload)
            })
    }

    func storeVariant(
        at pointer: Pointer, _ value: Operand, type: WITVariant,
        storeDiscriminant: (Operand) throws -> Void,
        storePayload: (Int, Operand) throws -> Void
    ) throws {
        try storeVariantLike(
            at: pointer, value, variants: type.cases.map(\.type),
            swiftCaseNames: definitionMapping.enumCaseSwiftNames(variantType: type),
            storeDiscriminant: storeDiscriminant, storePayload: storePayload
        )
    }

    func storeVariantLike(
        at pointer: Pointer, _ value: Operand,
        variants: [WITType?], swiftCaseNames: [String],
        storeDiscriminant: (Operand) throws -> Void,
        storePayload: (Int, Operand) throws -> Void
    ) throws {
        printer.write(line: "switch \(value) {")
        let payloadVar = builder.variable("payload")
        for (i, variantCaseType) in variants.enumerated() {
            let caseName = swiftCaseNames[i]
            if variantCaseType != nil {
                // Emit case-let only when it has payload type
                printer.write(line: "case .\(caseName)(let \(payloadVar)):")
            } else {
                printer.write(line: "case .\(caseName):")
            }
            try printer.indent {
                try storeDiscriminant(.literal(i.description))
                try storePayload(i, .variable(payloadVar))
            }
        }
        printer.write(line: "}")
    }
}