@@ -44,92 +44,35 @@ struct LLVReg: Equatable, ShiftedVReg {
4444 }
4545}
4646
47- extension RawUnsignedInteger {
48- init ( _ slot: CodeSlot , shiftWidth: Int ) {
49- let mask = CodeSlot ( Self . max)
50- let bitPattern = ( slot >> shiftWidth) & mask
51- self = Self ( bitPattern)
52- }
53-
54- func bits( shiftWidth: Int ) -> CodeSlot {
55- CodeSlot ( self ) << shiftWidth
56- }
57- }
58-
59- extension RawSignedInteger {
60- init ( _ slot: CodeSlot , shiftWidth: Int ) {
61- self . init ( bitPattern: Unsigned ( slot, shiftWidth: shiftWidth) )
62- }
63-
64- func bits( shiftWidth: Int ) -> CodeSlot {
65- Unsigned ( bitPattern: self ) . bits ( shiftWidth: shiftWidth)
66- }
67- }
68-
69- extension UntypedValue {
70- init ( _ slot: CodeSlot , shiftWidth: Int ) {
71- self . init ( storage: slot)
72- }
73-
74- func bits( shiftWidth: Int ) -> CodeSlot { storage }
75- }
47+ // MARK: - Immediate load/emit support
7648
49+ /// A protocol that represents an immediate associated with an instruction.
7750protocol InstructionImmediate {
51+ /// Loads an immediate from the instruction sequence.
52+ ///
53+ /// - Parameter pc: The program counter to read from.
54+ /// - Returns: The loaded immediate.
7855 static func load( from pc: inout Pc ) -> Self
56+
57+ /// Emits the layout of the immediate to be emitted.
58+ ///
59+ /// - Parameter emitSlot: The closure to schedule a slot emission.
60+ /// This closure receives a builder closure that builds the slot.
61+ ///
62+ /// - Note: This method is intended to work at meta-level to allow
63+ /// knowing the size of slots without actual immediate values.
7964 static func emit( to emitSlot: @escaping ( ( Self ) -> CodeSlot ) -> Void )
8065}
8166
8267extension InstructionImmediate {
68+ /// Emits the immediate value
69+ ///
70+ /// - Parameter emitSlot: The closure to emit a slot.
8371 func emit( to emitSlot: @escaping ( CodeSlot ) -> Void ) {
8472 Self . emit { buildCodeSlot in
8573 emitSlot ( buildCodeSlot ( self ) )
8674 }
8775 }
88- static func emit< Parent> ( to emitParent: @escaping ( ( Parent ) -> CodeSlot ) -> Void , _ child: KeyPath < Parent , Self > ) {
89- Self . emit { emitChild in
90- emitParent { emitChild ( $0 [ keyPath: child] ) }
91- }
92- }
93- }
94-
95- extension InstructionImmediate {
96- static func load( from pc: inout Pc ) -> Self {
97- pc. read ( )
98- }
99- static func emit( to emitSlot: ( ( Self ) -> CodeSlot ) -> Void ) {
100- assert ( MemoryLayout< Self> . size == 8 )
101- emitSlot { unsafeBitCast ( $0, to: CodeSlot . self) }
102- }
103- }
104-
105- extension VReg : InstructionImmediate {
106- static func load( from pc: inout Pc ) -> Self {
107- VReg ( bitPattern: UInt16 ( pc. read ( UInt64 . self) ) )
108- }
109- static func emit( to emitSlot: @escaping ( ( Self ) -> CodeSlot ) -> Void ) {
110- emitSlot { CodeSlot ( UInt16 ( bitPattern: $0) ) }
111- }
112-
113- typealias Slot2 = ( VReg , VReg , pad: UInt32 )
114- static func load2( from pc: inout Pc ) -> ( Self , Self ) {
115- let ( x, y, _) = pc. read ( Slot2 . self)
116- return ( x, y)
117- }
118- static func emit2( to emitSlot: @escaping ( ( Self , Self ) -> CodeSlot ) -> Void ) {
119- emitSlot { x, y in
120- let slot : Slot2 = ( x, y, 0 )
121- return unsafeBitCast ( slot, to: CodeSlot . self)
122- }
123- }
124- }
125-
126- extension LLVReg : InstructionImmediate {
127- static func load( from pc: inout Pc ) -> Self {
128- Self ( storage: Int64 ( bitPattern: pc. read ( ) ) )
129- }
130- static func emit( to emitSlot: ( ( Self ) -> CodeSlot ) -> Void ) {
131- emitSlot { UInt64 ( bitPattern: $0. value) }
132- }
13376}
13477
13578extension UInt32 : InstructionImmediate {
@@ -150,6 +93,8 @@ extension Int32: InstructionImmediate {
15093 }
15194}
15295
96+ // MARK: - Immediate type extensions
97+
15398extension Instruction . RefNullOperand {
15499 init ( result: VReg , type: ReferenceType ) {
155100 self . init ( result: result, rawType: type. rawValue)
@@ -210,9 +155,64 @@ extension Instruction {
210155 typealias OnExitOperand = FunctionIndex
211156}
212157
158+ extension RawUnsignedInteger {
159+ init ( _ slot: CodeSlot , shiftWidth: Int ) {
160+ let mask = CodeSlot ( Self . max)
161+ let bitPattern = ( slot >> shiftWidth) & mask
162+ self = Self ( bitPattern)
163+ }
164+
165+ func bits( shiftWidth: Int ) -> CodeSlot {
166+ CodeSlot ( self ) << shiftWidth
167+ }
168+ }
169+
170+ extension RawSignedInteger {
171+ init ( _ slot: CodeSlot , shiftWidth: Int ) {
172+ self . init ( bitPattern: Unsigned ( slot, shiftWidth: shiftWidth) )
173+ }
174+
175+ func bits( shiftWidth: Int ) -> CodeSlot {
176+ Unsigned ( bitPattern: self ) . bits ( shiftWidth: shiftWidth)
177+ }
178+ }
179+
180+ extension UntypedValue {
181+ init ( _ slot: CodeSlot , shiftWidth: Int ) {
182+ self . init ( storage: slot)
183+ }
184+
185+ func bits( shiftWidth: Int ) -> CodeSlot { storage }
186+ }
187+
213188/// The type of an opcode identifier.
214189typealias OpcodeID = UInt64
215190
191+ // MARK: - Instruction printing support
192+
193+ extension InstructionSequence {
194+ func write< Target> ( to target: inout Target , context: inout InstructionPrintingContext ) where Target : TextOutputStream {
195+ var hexOffsetWidth = String ( instructions. count - 1 , radix: 16 ) . count
196+ hexOffsetWidth = ( hexOffsetWidth + 1 ) & ~ 1
197+
198+ guard let cursorStart = instructions. baseAddress else { return }
199+ let cursorEnd = cursorStart. advanced ( by: instructions. count)
200+
201+ var cursor = cursorStart
202+ while cursor < cursorEnd {
203+ let index = cursor - cursorStart
204+ var hexOffset = String ( index, radix: 16 )
205+ while hexOffset. count < hexOffsetWidth {
206+ hexOffset = " 0 " + hexOffset
207+ }
208+ target. write ( " 0x \( hexOffset) : " )
209+ let instruction = Instruction . load ( from: & cursor)
210+ context. print ( instruction: instruction, to: & target)
211+ target. write ( " \n " )
212+ }
213+ }
214+ }
215+
216216struct InstructionPrintingContext {
217217 let shouldColor : Bool
218218 let function : Function
0 commit comments