@@ -696,13 +696,30 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
696696 /// - Parameters:
697697 /// - ref: Label reference to be resolved
698698 /// - make: Factory closure to make an inserting instruction
699- mutating func emitWithLabel( _ ref: LabelRef , line: UInt = #line, make: @escaping InstructionFactoryWithLabel ) {
699+ mutating func emitWithLabel< Immediate: InstructionImmediate > (
700+ _ makeInstruction: @escaping ( Immediate ) -> Instruction ,
701+ _ ref: LabelRef ,
702+ line: UInt = #line,
703+ make: @escaping (
704+ ISeqBuilder ,
705+ // The position of the next slot of the creating instruction
706+ _ source: MetaProgramCounter ,
707+ // The position of the resolved label
708+ _ target: MetaProgramCounter
709+ ) -> ( Immediate )
710+ ) {
700711 let insertAt = insertingPC
701- // TODO: Skip emitting nop if the label is already pinned
702- // FIXME: ****THIS IS ABSOLUTELY WRONG. JUST FOR PERF EVALUATION**
703- // Please change placeholder size based on whether the instruction has any immediate
704- emit ( . br( 0 ) ) // Emit dummy instruction to be replaced later
705- emitWithLabel ( ref, insertAt: insertAt, line: line, make: make)
712+
713+ // Emit dummy instruction to be replaced later
714+ emitSlot ( 0 ) // dummy opcode
715+ var immediateSlots = 0
716+ Immediate . emit ( to: { _ in immediateSlots += 1 } )
717+ for _ in 0 ..< immediateSlots { emitSlot ( 0 ) }
718+
719+ // Schedule actual emission
720+ emitWithLabel ( ref, insertAt: insertAt, line: line, make: {
721+ makeInstruction ( make ( $0, $1, $2) )
722+ } )
706723 }
707724
708725 /// Emit an instruction at the specified position with resolved label position
@@ -1097,15 +1114,15 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
10971114 )
10981115 )
10991116 guard let condition = condition else { return }
1100- iseqBuilder. emitWithLabel ( endLabel) { iseqBuilder, selfPC, endPC in
1117+ iseqBuilder. emitWithLabel ( Instruction . brIfNot , endLabel) { iseqBuilder, selfPC, endPC in
11011118 let targetPC : MetaProgramCounter
11021119 if let elsePC = iseqBuilder. resolveLabel ( elseLabel) {
11031120 targetPC = elsePC
11041121 } else {
11051122 targetPC = endPC
11061123 }
11071124 let elseOrEnd = UInt32 ( targetPC. offsetFromHead - selfPC. offsetFromHead)
1108- return . brIfNot ( Instruction . BrIfOperand ( condition: LVReg ( condition) , offset: Int32 ( elseOrEnd) ) )
1125+ return Instruction . BrIfOperand ( condition: LVReg ( condition) , offset: Int32 ( elseOrEnd) )
11091126 }
11101127 }
11111128
@@ -1117,9 +1134,9 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
11171134 preserveOnStack ( depth: valueStack. height - frame. stackHeight)
11181135 try controlStack. resetReachability ( )
11191136 iseqBuilder. resetLastEmission ( )
1120- iseqBuilder. emitWithLabel ( endLabel) { _, selfPC, endPC in
1137+ iseqBuilder. emitWithLabel ( Instruction . br , endLabel) { _, selfPC, endPC in
11211138 let offset = endPC. offsetFromHead - selfPC. offsetFromHead
1122- return . br ( Int32 ( offset) )
1139+ return Int32 ( offset)
11231140 }
11241141 try valueStack. truncate ( height: frame. stackHeight)
11251142 // Re-push parameters
@@ -1191,9 +1208,10 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
11911208 return popCount
11921209 }
11931210
1194- private mutating func emitBranch(
1211+ private mutating func emitBranch< Immediate: InstructionImmediate > (
1212+ _ makeInstruction: @escaping ( Immediate ) -> Instruction ,
11951213 relativeDepth: UInt32 ,
1196- make: @escaping ( _ offset: Int32 , _ copyCount: UInt32 , _ popCount: UInt32 ) -> Instruction
1214+ make: @escaping ( _ offset: Int32 , _ copyCount: UInt32 , _ popCount: UInt32 ) -> Immediate
11971215 ) throws {
11981216 let frame = try controlStack. branchTarget ( relativeDepth: relativeDepth)
11991217 let copyCount = frame. copyCount
@@ -1202,7 +1220,7 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
12021220 currentFrame: try controlStack. currentFrame ( ) ,
12031221 currentHeight: valueStack. height
12041222 )
1205- iseqBuilder. emitWithLabel ( frame. continuation) { _, selfPC, continuation in
1223+ iseqBuilder. emitWithLabel ( makeInstruction , frame. continuation) { _, selfPC, continuation in
12061224 let relativeOffset = continuation. offsetFromHead - selfPC. offsetFromHead
12071225 return make ( Int32 ( relativeOffset) , UInt32 ( copyCount) , popCount)
12081226 }
@@ -1219,8 +1237,8 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
12191237 // +---[ i32 ]<--+ copy [2]
12201238 // [ i64 ]---+
12211239 try copyOnBranch ( targetFrame: frame)
1222- try emitBranch ( relativeDepth: relativeDepth) { offset, copyCount, popCount in
1223- return . br ( offset)
1240+ try emitBranch ( Instruction . br , relativeDepth: relativeDepth) { offset, copyCount, popCount in
1241+ return offset
12241242 }
12251243 try markUnreachable ( )
12261244 }
@@ -1231,11 +1249,11 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
12311249 let frame = try controlStack. branchTarget ( relativeDepth: relativeDepth)
12321250 if frame. copyCount == 0 {
12331251 // Optimization where we don't need copying values when the branch taken
1234- iseqBuilder. emitWithLabel ( frame. continuation) { _, selfPC, continuation in
1252+ iseqBuilder. emitWithLabel ( Instruction . brIf , frame. continuation) { _, selfPC, continuation in
12351253 let relativeOffset = continuation. offsetFromHead - selfPC. offsetFromHead
1236- return . brIf ( Instruction . BrIfOperand (
1254+ return Instruction . BrIfOperand (
12371255 condition: LVReg ( condition) , offset: Int32 ( relativeOffset)
1238- ) )
1256+ )
12391257 }
12401258 return
12411259 }
@@ -1262,13 +1280,13 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
12621280 // [0x06] (local.get 1 reg:2) <----|---------+
12631281 // [0x07] ... <-------+
12641282 let onBranchNotTaken = iseqBuilder. allocLabel ( )
1265- iseqBuilder. emitWithLabel ( onBranchNotTaken) { _, conditionCheckAt, continuation in
1283+ iseqBuilder. emitWithLabel ( Instruction . brIfNot , onBranchNotTaken) { _, conditionCheckAt, continuation in
12661284 let relativeOffset = continuation. offsetFromHead - conditionCheckAt. offsetFromHead
1267- return . brIfNot ( Instruction . BrIfOperand ( condition: LVReg ( condition) , offset: Int32 ( relativeOffset) ) )
1285+ return Instruction . BrIfOperand ( condition: LVReg ( condition) , offset: Int32 ( relativeOffset) )
12681286 }
12691287 try copyOnBranch ( targetFrame: frame)
1270- try emitBranch ( relativeDepth: relativeDepth) { offset, copyCount, popCount in
1271- return . br ( offset)
1288+ try emitBranch ( Instruction . br , relativeDepth: relativeDepth) { offset, copyCount, popCount in
1289+ return offset
12721290 }
12731291 try iseqBuilder. pinLabelHere ( onBranchNotTaken)
12741292 }
@@ -1328,9 +1346,9 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
13281346 }
13291347 let emittedCopy = try copyOnBranch ( targetFrame: frame)
13301348 if emittedCopy {
1331- iseqBuilder. emitWithLabel ( frame. continuation) { _, brAt, continuation in
1349+ iseqBuilder. emitWithLabel ( Instruction . br , frame. continuation) { _, brAt, continuation in
13321350 let relativeOffset = continuation. offsetFromHead - brAt. offsetFromHead
1333- return . br ( Int32 ( relativeOffset) )
1351+ return Int32 ( relativeOffset)
13341352 }
13351353 } else {
13361354 // Optimization: If no value is copied, we can directly jump to the target
0 commit comments