1 //! Cursor library. 2 //! 3 //! This module defines cursor data types that can be used for inserting instructions. 4 5 use crate::ir; 6 use crate::isa::TargetIsa; 7 8 /// The possible positions of a cursor. 9 #[derive(Clone, Copy, PartialEq, Eq, Debug)] 10 pub enum CursorPosition { 11 /// Cursor is not pointing anywhere. No instructions can be inserted. 12 Nowhere, 13 /// Cursor is pointing at an existing instruction. 14 /// New instructions will be inserted *before* the current instruction. 15 At(ir::Inst), 16 /// Cursor is before the beginning of an EBB. No instructions can be inserted. Calling 17 /// `next_inst()` will move to the first instruction in the EBB. 18 Before(ir::Ebb), 19 /// Cursor is pointing after the end of an EBB. 20 /// New instructions will be appended to the EBB. 21 After(ir::Ebb), 22 } 23 24 /// All cursor types implement the `Cursor` which provides common navigation operations. 25 pub trait Cursor { 26 /// Get the current cursor position. 27 fn position(&self) -> CursorPosition; 28 29 /// Set the current position. 30 fn set_position(&mut self, pos: CursorPosition); 31 32 /// Get the source location that should be assigned to new instructions. 33 fn srcloc(&self) -> ir::SourceLoc; 34 35 /// Set the source location that should be assigned to new instructions. 36 fn set_srcloc(&mut self, srcloc: ir::SourceLoc); 37 38 /// Borrow a reference to the function layout that this cursor is navigating. 39 fn layout(&self) -> &ir::Layout; 40 41 /// Borrow a mutable reference to the function layout that this cursor is navigating. 42 fn layout_mut(&mut self) -> &mut ir::Layout; 43 44 /// Exchange this cursor for one with a set source location. 45 /// 46 /// This is intended to be used as a builder method: 47 /// 48 /// ``` 49 /// # use cranelift_codegen::ir::{Function, Ebb, SourceLoc}; 50 /// # use cranelift_codegen::cursor::{Cursor, FuncCursor}; 51 /// fn edit_func(func: &mut Function, srcloc: SourceLoc) { 52 /// let mut pos = FuncCursor::new(func).with_srcloc(srcloc); 53 /// 54 /// // Use `pos`... 55 /// } 56 /// ``` 57 fn with_srcloc(mut self, srcloc: ir::SourceLoc) -> Self 58 where 59 Self: Sized, 60 { 61 self.set_srcloc(srcloc); 62 self 63 } 64 65 /// Rebuild this cursor positioned at `pos`. 66 fn at_position(mut self, pos: CursorPosition) -> Self 67 where 68 Self: Sized, 69 { 70 self.set_position(pos); 71 self 72 } 73 74 /// Rebuild this cursor positioned at `inst`. 75 /// 76 /// This is intended to be used as a builder method: 77 /// 78 /// ``` 79 /// # use cranelift_codegen::ir::{Function, Ebb, Inst}; 80 /// # use cranelift_codegen::cursor::{Cursor, FuncCursor}; 81 /// fn edit_func(func: &mut Function, inst: Inst) { 82 /// let mut pos = FuncCursor::new(func).at_inst(inst); 83 /// 84 /// // Use `pos`... 85 /// } 86 /// ``` 87 fn at_inst(mut self, inst: ir::Inst) -> Self 88 where 89 Self: Sized, 90 { 91 self.goto_inst(inst); 92 self 93 } 94 95 /// Rebuild this cursor positioned at the first insertion point for `ebb`. 96 /// This differs from `at_first_inst` in that it doesn't assume that any 97 /// instructions have been inserted into `ebb` yet. 98 /// 99 /// This is intended to be used as a builder method: 100 /// 101 /// ``` 102 /// # use cranelift_codegen::ir::{Function, Ebb, Inst}; 103 /// # use cranelift_codegen::cursor::{Cursor, FuncCursor}; 104 /// fn edit_func(func: &mut Function, ebb: Ebb) { 105 /// let mut pos = FuncCursor::new(func).at_first_insertion_point(ebb); 106 /// 107 /// // Use `pos`... 108 /// } 109 /// ``` 110 fn at_first_insertion_point(mut self, ebb: ir::Ebb) -> Self 111 where 112 Self: Sized, 113 { 114 self.goto_first_insertion_point(ebb); 115 self 116 } 117 118 /// Rebuild this cursor positioned at the first instruction in `ebb`. 119 /// 120 /// This is intended to be used as a builder method: 121 /// 122 /// ``` 123 /// # use cranelift_codegen::ir::{Function, Ebb, Inst}; 124 /// # use cranelift_codegen::cursor::{Cursor, FuncCursor}; 125 /// fn edit_func(func: &mut Function, ebb: Ebb) { 126 /// let mut pos = FuncCursor::new(func).at_first_inst(ebb); 127 /// 128 /// // Use `pos`... 129 /// } 130 /// ``` 131 fn at_first_inst(mut self, ebb: ir::Ebb) -> Self 132 where 133 Self: Sized, 134 { 135 self.goto_first_inst(ebb); 136 self 137 } 138 139 /// Rebuild this cursor positioned at the last instruction in `ebb`. 140 /// 141 /// This is intended to be used as a builder method: 142 /// 143 /// ``` 144 /// # use cranelift_codegen::ir::{Function, Ebb, Inst}; 145 /// # use cranelift_codegen::cursor::{Cursor, FuncCursor}; 146 /// fn edit_func(func: &mut Function, ebb: Ebb) { 147 /// let mut pos = FuncCursor::new(func).at_last_inst(ebb); 148 /// 149 /// // Use `pos`... 150 /// } 151 /// ``` 152 fn at_last_inst(mut self, ebb: ir::Ebb) -> Self 153 where 154 Self: Sized, 155 { 156 self.goto_last_inst(ebb); 157 self 158 } 159 160 /// Rebuild this cursor positioned after `inst`. 161 /// 162 /// This is intended to be used as a builder method: 163 /// 164 /// ``` 165 /// # use cranelift_codegen::ir::{Function, Ebb, Inst}; 166 /// # use cranelift_codegen::cursor::{Cursor, FuncCursor}; 167 /// fn edit_func(func: &mut Function, inst: Inst) { 168 /// let mut pos = FuncCursor::new(func).after_inst(inst); 169 /// 170 /// // Use `pos`... 171 /// } 172 /// ``` 173 fn after_inst(mut self, inst: ir::Inst) -> Self 174 where 175 Self: Sized, 176 { 177 self.goto_after_inst(inst); 178 self 179 } 180 181 /// Rebuild this cursor positioned at the top of `ebb`. 182 /// 183 /// This is intended to be used as a builder method: 184 /// 185 /// ``` 186 /// # use cranelift_codegen::ir::{Function, Ebb, Inst}; 187 /// # use cranelift_codegen::cursor::{Cursor, FuncCursor}; 188 /// fn edit_func(func: &mut Function, ebb: Ebb) { 189 /// let mut pos = FuncCursor::new(func).at_top(ebb); 190 /// 191 /// // Use `pos`... 192 /// } 193 /// ``` 194 fn at_top(mut self, ebb: ir::Ebb) -> Self 195 where 196 Self: Sized, 197 { 198 self.goto_top(ebb); 199 self 200 } 201 202 /// Rebuild this cursor positioned at the bottom of `ebb`. 203 /// 204 /// This is intended to be used as a builder method: 205 /// 206 /// ``` 207 /// # use cranelift_codegen::ir::{Function, Ebb, Inst}; 208 /// # use cranelift_codegen::cursor::{Cursor, FuncCursor}; 209 /// fn edit_func(func: &mut Function, ebb: Ebb) { 210 /// let mut pos = FuncCursor::new(func).at_bottom(ebb); 211 /// 212 /// // Use `pos`... 213 /// } 214 /// ``` 215 fn at_bottom(mut self, ebb: ir::Ebb) -> Self 216 where 217 Self: Sized, 218 { 219 self.goto_bottom(ebb); 220 self 221 } 222 223 /// Get the EBB corresponding to the current position. 224 fn current_ebb(&self) -> Option<ir::Ebb> { 225 use self::CursorPosition::*; 226 match self.position() { 227 Nowhere => None, 228 At(inst) => self.layout().inst_ebb(inst), 229 Before(ebb) | After(ebb) => Some(ebb), 230 } 231 } 232 233 /// Get the instruction corresponding to the current position, if any. 234 fn current_inst(&self) -> Option<ir::Inst> { 235 use self::CursorPosition::*; 236 match self.position() { 237 At(inst) => Some(inst), 238 _ => None, 239 } 240 } 241 242 /// Go to the position after a specific instruction, which must be inserted 243 /// in the layout. New instructions will be inserted after `inst`. 244 fn goto_after_inst(&mut self, inst: ir::Inst) { 245 debug_assert!(self.layout().inst_ebb(inst).is_some()); 246 let new_pos = if let Some(next) = self.layout().next_inst(inst) { 247 CursorPosition::At(next) 248 } else { 249 CursorPosition::After( 250 self.layout() 251 .inst_ebb(inst) 252 .expect("current instruction removed?"), 253 ) 254 }; 255 self.set_position(new_pos); 256 } 257 258 /// Go to a specific instruction which must be inserted in the layout. 259 /// New instructions will be inserted before `inst`. 260 fn goto_inst(&mut self, inst: ir::Inst) { 261 debug_assert!(self.layout().inst_ebb(inst).is_some()); 262 self.set_position(CursorPosition::At(inst)); 263 } 264 265 /// Go to the position for inserting instructions at the beginning of `ebb`, 266 /// which unlike `goto_first_inst` doesn't assume that any instructions have 267 /// been inserted into `ebb` yet. 268 fn goto_first_insertion_point(&mut self, ebb: ir::Ebb) { 269 if let Some(inst) = self.layout().first_inst(ebb) { 270 self.goto_inst(inst); 271 } else { 272 self.goto_bottom(ebb); 273 } 274 } 275 276 /// Go to the first instruction in `ebb`. 277 fn goto_first_inst(&mut self, ebb: ir::Ebb) { 278 let inst = self.layout().first_inst(ebb).expect("Empty EBB"); 279 self.goto_inst(inst); 280 } 281 282 /// Go to the last instruction in `ebb`. 283 fn goto_last_inst(&mut self, ebb: ir::Ebb) { 284 let inst = self.layout().last_inst(ebb).expect("Empty EBB"); 285 self.goto_inst(inst); 286 } 287 288 /// Go to the top of `ebb` which must be inserted into the layout. 289 /// At this position, instructions cannot be inserted, but `next_inst()` will move to the first 290 /// instruction in `ebb`. 291 fn goto_top(&mut self, ebb: ir::Ebb) { 292 debug_assert!(self.layout().is_ebb_inserted(ebb)); 293 self.set_position(CursorPosition::Before(ebb)); 294 } 295 296 /// Go to the bottom of `ebb` which must be inserted into the layout. 297 /// At this position, inserted instructions will be appended to `ebb`. 298 fn goto_bottom(&mut self, ebb: ir::Ebb) { 299 debug_assert!(self.layout().is_ebb_inserted(ebb)); 300 self.set_position(CursorPosition::After(ebb)); 301 } 302 303 /// Go to the top of the next EBB in layout order and return it. 304 /// 305 /// - If the cursor wasn't pointing at anything, go to the top of the first EBB in the 306 /// function. 307 /// - If there are no more EBBs, leave the cursor pointing at nothing and return `None`. 308 /// 309 /// # Examples 310 /// 311 /// The `next_ebb()` method is intended for iterating over the EBBs in layout order: 312 /// 313 /// ``` 314 /// # use cranelift_codegen::ir::{Function, Ebb}; 315 /// # use cranelift_codegen::cursor::{Cursor, FuncCursor}; 316 /// fn edit_func(func: &mut Function) { 317 /// let mut cursor = FuncCursor::new(func); 318 /// while let Some(ebb) = cursor.next_ebb() { 319 /// // Edit ebb. 320 /// } 321 /// } 322 /// ``` 323 fn next_ebb(&mut self) -> Option<ir::Ebb> { 324 let next = if let Some(ebb) = self.current_ebb() { 325 self.layout().next_ebb(ebb) 326 } else { 327 self.layout().entry_block() 328 }; 329 self.set_position(match next { 330 Some(ebb) => CursorPosition::Before(ebb), 331 None => CursorPosition::Nowhere, 332 }); 333 next 334 } 335 336 /// Go to the bottom of the previous EBB in layout order and return it. 337 /// 338 /// - If the cursor wasn't pointing at anything, go to the bottom of the last EBB in the 339 /// function. 340 /// - If there are no more EBBs, leave the cursor pointing at nothing and return `None`. 341 /// 342 /// # Examples 343 /// 344 /// The `prev_ebb()` method is intended for iterating over the EBBs in backwards layout order: 345 /// 346 /// ``` 347 /// # use cranelift_codegen::ir::{Function, Ebb}; 348 /// # use cranelift_codegen::cursor::{Cursor, FuncCursor}; 349 /// fn edit_func(func: &mut Function) { 350 /// let mut cursor = FuncCursor::new(func); 351 /// while let Some(ebb) = cursor.prev_ebb() { 352 /// // Edit ebb. 353 /// } 354 /// } 355 /// ``` 356 fn prev_ebb(&mut self) -> Option<ir::Ebb> { 357 let prev = if let Some(ebb) = self.current_ebb() { 358 self.layout().prev_ebb(ebb) 359 } else { 360 self.layout().last_ebb() 361 }; 362 self.set_position(match prev { 363 Some(ebb) => CursorPosition::After(ebb), 364 None => CursorPosition::Nowhere, 365 }); 366 prev 367 } 368 369 /// Move to the next instruction in the same EBB and return it. 370 /// 371 /// - If the cursor was positioned before an EBB, go to the first instruction in that EBB. 372 /// - If there are no more instructions in the EBB, go to the `After(ebb)` position and return 373 /// `None`. 374 /// - If the cursor wasn't pointing anywhere, keep doing that. 375 /// 376 /// This method will never move the cursor to a different EBB. 377 /// 378 /// # Examples 379 /// 380 /// The `next_inst()` method is intended for iterating over the instructions in an EBB like 381 /// this: 382 /// 383 /// ``` 384 /// # use cranelift_codegen::ir::{Function, Ebb}; 385 /// # use cranelift_codegen::cursor::{Cursor, FuncCursor}; 386 /// fn edit_ebb(func: &mut Function, ebb: Ebb) { 387 /// let mut cursor = FuncCursor::new(func).at_top(ebb); 388 /// while let Some(inst) = cursor.next_inst() { 389 /// // Edit instructions... 390 /// } 391 /// } 392 /// ``` 393 /// The loop body can insert and remove instructions via the cursor. 394 /// 395 /// Iterating over all the instructions in a function looks like this: 396 /// 397 /// ``` 398 /// # use cranelift_codegen::ir::{Function, Ebb}; 399 /// # use cranelift_codegen::cursor::{Cursor, FuncCursor}; 400 /// fn edit_func(func: &mut Function) { 401 /// let mut cursor = FuncCursor::new(func); 402 /// while let Some(ebb) = cursor.next_ebb() { 403 /// while let Some(inst) = cursor.next_inst() { 404 /// // Edit instructions... 405 /// } 406 /// } 407 /// } 408 /// ``` 409 fn next_inst(&mut self) -> Option<ir::Inst> { 410 use self::CursorPosition::*; 411 match self.position() { 412 Nowhere | After(..) => None, 413 At(inst) => { 414 if let Some(next) = self.layout().next_inst(inst) { 415 self.set_position(At(next)); 416 Some(next) 417 } else { 418 let pos = After( 419 self.layout() 420 .inst_ebb(inst) 421 .expect("current instruction removed?"), 422 ); 423 self.set_position(pos); 424 None 425 } 426 } 427 Before(ebb) => { 428 if let Some(next) = self.layout().first_inst(ebb) { 429 self.set_position(At(next)); 430 Some(next) 431 } else { 432 self.set_position(After(ebb)); 433 None 434 } 435 } 436 } 437 } 438 439 /// Move to the previous instruction in the same EBB and return it. 440 /// 441 /// - If the cursor was positioned after an EBB, go to the last instruction in that EBB. 442 /// - If there are no more instructions in the EBB, go to the `Before(ebb)` position and return 443 /// `None`. 444 /// - If the cursor wasn't pointing anywhere, keep doing that. 445 /// 446 /// This method will never move the cursor to a different EBB. 447 /// 448 /// # Examples 449 /// 450 /// The `prev_inst()` method is intended for iterating backwards over the instructions in an 451 /// EBB like this: 452 /// 453 /// ``` 454 /// # use cranelift_codegen::ir::{Function, Ebb}; 455 /// # use cranelift_codegen::cursor::{Cursor, FuncCursor}; 456 /// fn edit_ebb(func: &mut Function, ebb: Ebb) { 457 /// let mut cursor = FuncCursor::new(func).at_bottom(ebb); 458 /// while let Some(inst) = cursor.prev_inst() { 459 /// // Edit instructions... 460 /// } 461 /// } 462 /// ``` 463 fn prev_inst(&mut self) -> Option<ir::Inst> { 464 use self::CursorPosition::*; 465 match self.position() { 466 Nowhere | Before(..) => None, 467 At(inst) => { 468 if let Some(prev) = self.layout().prev_inst(inst) { 469 self.set_position(At(prev)); 470 Some(prev) 471 } else { 472 let pos = Before( 473 self.layout() 474 .inst_ebb(inst) 475 .expect("current instruction removed?"), 476 ); 477 self.set_position(pos); 478 None 479 } 480 } 481 After(ebb) => { 482 if let Some(prev) = self.layout().last_inst(ebb) { 483 self.set_position(At(prev)); 484 Some(prev) 485 } else { 486 self.set_position(Before(ebb)); 487 None 488 } 489 } 490 } 491 } 492 493 /// Insert an instruction at the current position. 494 /// 495 /// - If pointing at an instruction, the new instruction is inserted before the current 496 /// instruction. 497 /// - If pointing at the bottom of an EBB, the new instruction is appended to the EBB. 498 /// - Otherwise panic. 499 /// 500 /// In either case, the cursor is not moved, such that repeated calls to `insert_inst()` causes 501 /// instructions to appear in insertion order in the EBB. 502 fn insert_inst(&mut self, inst: ir::Inst) { 503 use self::CursorPosition::*; 504 match self.position() { 505 Nowhere | Before(..) => panic!("Invalid insert_inst position"), 506 At(cur) => self.layout_mut().insert_inst(inst, cur), 507 After(ebb) => self.layout_mut().append_inst(inst, ebb), 508 } 509 } 510 511 /// Remove the instruction under the cursor. 512 /// 513 /// The cursor is left pointing at the position following the current instruction. 514 /// 515 /// Return the instruction that was removed. 516 fn remove_inst(&mut self) -> ir::Inst { 517 let inst = self.current_inst().expect("No instruction to remove"); 518 self.next_inst(); 519 self.layout_mut().remove_inst(inst); 520 inst 521 } 522 523 /// Remove the instruction under the cursor. 524 /// 525 /// The cursor is left pointing at the position preceding the current instruction. 526 /// 527 /// Return the instruction that was removed. 528 fn remove_inst_and_step_back(&mut self) -> ir::Inst { 529 let inst = self.current_inst().expect("No instruction to remove"); 530 self.prev_inst(); 531 self.layout_mut().remove_inst(inst); 532 inst 533 } 534 535 /// Insert an EBB at the current position and switch to it. 536 /// 537 /// As far as possible, this method behaves as if the EBB header were an instruction inserted 538 /// at the current position. 539 /// 540 /// - If the cursor is pointing at an existing instruction, *the current EBB is split in two* 541 /// and the current instruction becomes the first instruction in the inserted EBB. 542 /// - If the cursor points at the bottom of an EBB, the new EBB is inserted after the current 543 /// one, and moved to the bottom of the new EBB where instructions can be appended. 544 /// - If the cursor points to the top of an EBB, the new EBB is inserted above the current one. 545 /// - If the cursor is not pointing at anything, the new EBB is placed last in the layout. 546 /// 547 /// This means that it is always valid to call this method, and it always leaves the cursor in 548 /// a state that will insert instructions into the new EBB. 549 fn insert_ebb(&mut self, new_ebb: ir::Ebb) { 550 use self::CursorPosition::*; 551 match self.position() { 552 At(inst) => { 553 self.layout_mut().split_ebb(new_ebb, inst); 554 // All other cases move to `After(ebb)`, but in this case we'll stay `At(inst)`. 555 return; 556 } 557 Nowhere => self.layout_mut().append_ebb(new_ebb), 558 Before(ebb) => self.layout_mut().insert_ebb(new_ebb, ebb), 559 After(ebb) => self.layout_mut().insert_ebb_after(new_ebb, ebb), 560 } 561 // For everything but `At(inst)` we end up appending to the new EBB. 562 self.set_position(After(new_ebb)); 563 } 564 } 565 566 /// Function cursor. 567 /// 568 /// A `FuncCursor` holds a mutable reference to a whole `ir::Function` while keeping a position 569 /// too. The function can be re-borrowed by accessing the public `cur.func` member. 570 /// 571 /// This cursor is for use before legalization. The inserted instructions are not given an 572 /// encoding. 573 pub struct FuncCursor<'f> { 574 pos: CursorPosition, 575 srcloc: ir::SourceLoc, 576 577 /// The referenced function. 578 pub func: &'f mut ir::Function, 579 } 580 581 impl<'f> FuncCursor<'f> { 582 /// Create a new `FuncCursor` pointing nowhere. 583 pub fn new(func: &'f mut ir::Function) -> Self { 584 Self { 585 pos: CursorPosition::Nowhere, 586 srcloc: Default::default(), 587 func, 588 } 589 } 590 591 /// Use the source location of `inst` for future instructions. 592 pub fn use_srcloc(&mut self, inst: ir::Inst) { 593 self.srcloc = self.func.srclocs[inst]; 594 } 595 596 /// Create an instruction builder that inserts an instruction at the current position. 597 pub fn ins(&mut self) -> ir::InsertBuilder<&mut FuncCursor<'f>> { 598 ir::InsertBuilder::new(self) 599 } 600 } 601 602 impl<'f> Cursor for FuncCursor<'f> { 603 fn position(&self) -> CursorPosition { 604 self.pos 605 } 606 607 fn set_position(&mut self, pos: CursorPosition) { 608 self.pos = pos 609 } 610 611 fn srcloc(&self) -> ir::SourceLoc { 612 self.srcloc 613 } 614 615 fn set_srcloc(&mut self, srcloc: ir::SourceLoc) { 616 self.srcloc = srcloc; 617 } 618 619 fn layout(&self) -> &ir::Layout { 620 &self.func.layout 621 } 622 623 fn layout_mut(&mut self) -> &mut ir::Layout { 624 &mut self.func.layout 625 } 626 } 627 628 impl<'c, 'f> ir::InstInserterBase<'c> for &'c mut FuncCursor<'f> { 629 fn data_flow_graph(&self) -> &ir::DataFlowGraph { 630 &self.func.dfg 631 } 632 633 fn data_flow_graph_mut(&mut self) -> &mut ir::DataFlowGraph { 634 &mut self.func.dfg 635 } 636 637 fn insert_built_inst(self, inst: ir::Inst, _: ir::Type) -> &'c mut ir::DataFlowGraph { 638 self.insert_inst(inst); 639 if !self.srcloc.is_default() { 640 self.func.srclocs[inst] = self.srcloc; 641 } 642 &mut self.func.dfg 643 } 644 } 645 646 /// Encoding cursor. 647 /// 648 /// An `EncCursor` can be used to insert instructions that are immediately assigned an encoding. 649 /// The cursor holds a mutable reference to the whole function which can be re-borrowed from the 650 /// public `pos.func` member. 651 pub struct EncCursor<'f> { 652 pos: CursorPosition, 653 srcloc: ir::SourceLoc, 654 built_inst: Option<ir::Inst>, 655 656 /// The referenced function. 657 pub func: &'f mut ir::Function, 658 659 /// The target ISA that will be used to encode instructions. 660 pub isa: &'f dyn TargetIsa, 661 } 662 663 impl<'f> EncCursor<'f> { 664 /// Create a new `EncCursor` pointing nowhere. 665 pub fn new(func: &'f mut ir::Function, isa: &'f dyn TargetIsa) -> Self { 666 Self { 667 pos: CursorPosition::Nowhere, 668 srcloc: Default::default(), 669 built_inst: None, 670 func, 671 isa, 672 } 673 } 674 675 /// Use the source location of `inst` for future instructions. 676 pub fn use_srcloc(&mut self, inst: ir::Inst) { 677 self.srcloc = self.func.srclocs[inst]; 678 } 679 680 /// Create an instruction builder that will insert an encoded instruction at the current 681 /// position. 682 /// 683 /// The builder will panic if it is used to insert an instruction that can't be encoded for 684 /// `self.isa`. 685 pub fn ins(&mut self) -> ir::InsertBuilder<&mut EncCursor<'f>> { 686 ir::InsertBuilder::new(self) 687 } 688 689 /// Get the last built instruction. 690 /// 691 /// This returns the last instruction that was built using the `ins()` method on this cursor. 692 /// Panics if no instruction was built. 693 pub fn built_inst(&self) -> ir::Inst { 694 self.built_inst.expect("No instruction was inserted") 695 } 696 697 /// Return an object that can display `inst`. 698 /// 699 /// This is a convenience wrapper for the DFG equivalent. 700 pub fn display_inst(&self, inst: ir::Inst) -> ir::dfg::DisplayInst { 701 self.func.dfg.display_inst(inst, self.isa) 702 } 703 } 704 705 impl<'f> Cursor for EncCursor<'f> { 706 fn position(&self) -> CursorPosition { 707 self.pos 708 } 709 710 fn set_position(&mut self, pos: CursorPosition) { 711 self.pos = pos 712 } 713 714 fn srcloc(&self) -> ir::SourceLoc { 715 self.srcloc 716 } 717 718 fn set_srcloc(&mut self, srcloc: ir::SourceLoc) { 719 self.srcloc = srcloc; 720 } 721 722 fn layout(&self) -> &ir::Layout { 723 &self.func.layout 724 } 725 726 fn layout_mut(&mut self) -> &mut ir::Layout { 727 &mut self.func.layout 728 } 729 } 730 731 impl<'c, 'f> ir::InstInserterBase<'c> for &'c mut EncCursor<'f> { 732 fn data_flow_graph(&self) -> &ir::DataFlowGraph { 733 &self.func.dfg 734 } 735 736 fn data_flow_graph_mut(&mut self) -> &mut ir::DataFlowGraph { 737 &mut self.func.dfg 738 } 739 740 fn insert_built_inst( 741 self, 742 inst: ir::Inst, 743 ctrl_typevar: ir::Type, 744 ) -> &'c mut ir::DataFlowGraph { 745 // Insert the instruction and remember the reference. 746 self.insert_inst(inst); 747 self.built_inst = Some(inst); 748 749 if !self.srcloc.is_default() { 750 self.func.srclocs[inst] = self.srcloc; 751 } 752 // Assign an encoding. 753 // XXX Is there a way to describe this error to the user? 754 #[cfg_attr(feature = "cargo-clippy", allow(clippy::match_wild_err_arm))] 755 match self 756 .isa 757 .encode(&self.func, &self.func.dfg[inst], ctrl_typevar) 758 { 759 Ok(e) => self.func.encodings[inst] = e, 760 Err(_) => panic!("can't encode {}", self.display_inst(inst)), 761 } 762 763 &mut self.func.dfg 764 } 765 } 766