@@ -306,3 +306,133 @@ extension OptionalBridgedSuccessor {
306306 return nil
307307 }
308308}
309+
310+ //===--------------------------------------------------------------------===//
311+ // Tests
312+ //===--------------------------------------------------------------------===//
313+
314+ /// Most basic test of a BasicBlock and its contents
315+ let basicBlockTest = Test ( " basic_block " ) {
316+ function, arguments, context in
317+
318+ print ( " run SILPrinter on function: \( function. name) " )
319+
320+ for (bbIdx, block) in function. blocks. enumerated ( ) {
321+ print ( " bb \( bbIdx) : " )
322+
323+ print ( " predecessors: \( block. predecessors) " )
324+ print ( " successors: \( block. successors) " )
325+
326+ print ( " arguments: " )
327+ for arg in block. arguments {
328+ print ( " arg: \( arg) " )
329+ for use in arg. uses {
330+ print ( " user: \( use. instruction) " )
331+ }
332+ if let phi = Phi ( arg) {
333+ for incoming in phi. incomingValues {
334+ print ( " incoming: \( incoming) " )
335+ }
336+ }
337+ }
338+
339+ print ( " instructions: " )
340+ for inst in block. instructions {
341+ print ( " \( inst) " )
342+ for op in inst. operands {
343+ print ( " op: \( op. value) " )
344+ }
345+ for (resultIdx, result) in inst. results. enumerated ( ) {
346+ for use in result. uses {
347+ print ( " user of result \( resultIdx) : \( use. instruction) " )
348+ }
349+ }
350+ }
351+ }
352+ }
353+
354+ /// Tests instruction iteration while modifying the instruction list.
355+ ///
356+ /// This test iterates over the instruction list of the function's block and performs
357+ /// modifications of the instruction list - mostly deleting instructions.
358+ /// Modifications are triggered by `string_literal` instructions with known "commands".
359+ /// E.g. if a
360+ /// ```
361+ /// %1 = string_literal utf8 "delete_strings"
362+ /// ```
363+ /// is encountered during the iteration, it triggers the deletion of all `string_literal`
364+ /// instructions of the basic block (including the current one).
365+ ///
366+ let instructionIterationTest = Test ( " instruction_iteration " ) {
367+ function, arguments, context in
368+
369+ print ( " Test instruction iteration in \( function. name) : " )
370+
371+ let reverse = function. name. string. hasSuffix ( " backward " )
372+
373+ for block in function. blocks {
374+ print ( " \( block. name) : " )
375+ let termLoc = block. terminator. location
376+ if reverse {
377+ for inst in block. instructions. reversed ( ) {
378+ handle ( instruction: inst, context)
379+ }
380+ } else {
381+ for inst in block. instructions {
382+ handle ( instruction: inst, context)
383+ }
384+ }
385+ if block. instructions. isEmpty || !( block. instructions. reversed ( ) . first is TermInst ) {
386+ let builder = Builder ( atEndOf: block, location: termLoc, context)
387+ builder. createUnreachable ( )
388+ }
389+ }
390+ print ( " End function \( function. name) : " )
391+ }
392+
393+ private func handle( instruction: Instruction , _ context: TestContext ) {
394+ print ( instruction)
395+ if let sl = instruction as? StringLiteralInst {
396+ switch sl. value {
397+ case " delete_strings " :
398+ deleteAllInstructions ( ofType: StringLiteralInst . self, in: instruction. parentBlock, context)
399+ case " delete_ints " :
400+ deleteAllInstructions ( ofType: IntegerLiteralInst . self, in: instruction. parentBlock, context)
401+ case " delete_branches " :
402+ deleteAllInstructions ( ofType: BranchInst . self, in: instruction. parentBlock, context)
403+ case " split_block " :
404+ _ = context. splitBlock ( before: instruction)
405+ case " print_uses " :
406+ for use in sl. uses {
407+ print ( " use: \( use) " )
408+ }
409+ case " delete_first_user " :
410+ deleteUser ( of: sl, at: 0 , context)
411+ case " delete_second_user " :
412+ deleteUser ( of: sl, at: 1 , context)
413+ default :
414+ break
415+ }
416+ }
417+ }
418+
419+ private func deleteAllInstructions< InstType: Instruction > ( ofType: InstType . Type ,
420+ in block: BasicBlock ,
421+ _ context: TestContext )
422+ {
423+ for inst in block. instructions {
424+ if inst is InstType {
425+ context. erase ( instruction: inst)
426+ }
427+ }
428+ }
429+
430+ private func deleteUser( of value: Value , at deleteIndex: Int , _ context: TestContext ) {
431+ for (idx, use) in value. uses. enumerated ( ) {
432+ if idx == deleteIndex {
433+ context. erase ( instruction: use. instruction)
434+ } else {
435+ print ( " use: \( use) " )
436+ }
437+ }
438+ }
0 commit comments