@@ -1314,26 +1314,25 @@ impl MachBufferFinalized {
13141314 let mut next_trap = 0 ;
13151315 let mut next_call_site = 0 ;
13161316 for ( idx, byte) in self . data . iter ( ) . enumerate ( ) {
1317- if next_reloc < self . relocs . len ( ) {
1317+ while next_reloc < self . relocs . len ( )
1318+ && self . relocs [ next_reloc] . offset == idx as CodeOffset
1319+ {
13181320 let reloc = & self . relocs [ next_reloc] ;
1319- if reloc. offset == idx as CodeOffset {
1320- sink. reloc_external ( reloc. srcloc , reloc. kind , & reloc. name , reloc. addend ) ;
1321- next_reloc += 1 ;
1322- }
1321+ sink. reloc_external ( reloc. srcloc , reloc. kind , & reloc. name , reloc. addend ) ;
1322+ next_reloc += 1 ;
13231323 }
1324- if next_trap < self . traps . len ( ) {
1324+ while next_trap < self . traps . len ( ) && self . traps [ next_trap] . offset == idx as CodeOffset
1325+ {
13251326 let trap = & self . traps [ next_trap] ;
1326- if trap. offset == idx as CodeOffset {
1327- sink. trap ( trap. code , trap. srcloc ) ;
1328- next_trap += 1 ;
1329- }
1327+ sink. trap ( trap. code , trap. srcloc ) ;
1328+ next_trap += 1 ;
13301329 }
1331- if next_call_site < self . call_sites . len ( ) {
1330+ while next_call_site < self . call_sites . len ( )
1331+ && self . call_sites [ next_call_site] . ret_addr == idx as CodeOffset
1332+ {
13321333 let call_site = & self . call_sites [ next_call_site] ;
1333- if call_site. ret_addr == idx as CodeOffset {
1334- sink. add_call_site ( call_site. opcode , call_site. srcloc ) ;
1335- next_call_site += 1 ;
1336- }
1334+ sink. add_call_site ( call_site. opcode , call_site. srcloc ) ;
1335+ next_call_site += 1 ;
13371336 }
13381337 sink. put1 ( * byte) ;
13391338 }
@@ -1468,11 +1467,14 @@ impl MachBranch {
14681467#[ cfg( all( test, feature = "arm64" ) ) ]
14691468mod test {
14701469 use super :: * ;
1470+ use crate :: ir:: { ConstantOffset , Function , JumpTable , Value } ;
14711471 use crate :: isa:: aarch64:: inst:: xreg;
14721472 use crate :: isa:: aarch64:: inst:: { BranchTarget , CondBrKind , EmitInfo , Inst } ;
1473+ use crate :: isa:: TargetIsa ;
14731474 use crate :: machinst:: MachInstEmit ;
14741475 use crate :: settings;
14751476 use std:: default:: Default ;
1477+ use std:: vec:: Vec ;
14761478
14771479 fn label ( n : u32 ) -> MachLabel {
14781480 MachLabel :: from_block ( n)
@@ -1819,4 +1821,90 @@ mod test {
18191821
18201822 assert_eq ! ( & golden_data[ ..] , & buf. data[ ..] ) ;
18211823 }
1824+
1825+ #[ test]
1826+ fn metadata_records ( ) {
1827+ let mut buf = MachBuffer :: < Inst > :: new ( ) ;
1828+
1829+ buf. reserve_labels_for_blocks ( 1 ) ;
1830+
1831+ buf. bind_label ( label ( 0 ) ) ;
1832+ buf. put1 ( 1 ) ;
1833+ buf. add_trap ( SourceLoc :: default ( ) , TrapCode :: HeapOutOfBounds ) ;
1834+ buf. put1 ( 2 ) ;
1835+ buf. add_trap ( SourceLoc :: default ( ) , TrapCode :: IntegerOverflow ) ;
1836+ buf. add_trap ( SourceLoc :: default ( ) , TrapCode :: IntegerDivisionByZero ) ;
1837+ buf. add_call_site ( SourceLoc :: default ( ) , Opcode :: Call ) ;
1838+ buf. add_reloc (
1839+ SourceLoc :: default ( ) ,
1840+ Reloc :: Abs4 ,
1841+ & ExternalName :: user ( 0 , 0 ) ,
1842+ 0 ,
1843+ ) ;
1844+ buf. put1 ( 3 ) ;
1845+ buf. add_reloc (
1846+ SourceLoc :: default ( ) ,
1847+ Reloc :: Abs8 ,
1848+ & ExternalName :: user ( 1 , 1 ) ,
1849+ 1 ,
1850+ ) ;
1851+ buf. put1 ( 4 ) ;
1852+
1853+ let buf = buf. finish ( ) ;
1854+
1855+ #[ derive( Default ) ]
1856+ struct TestCodeSink {
1857+ offset : CodeOffset ,
1858+ traps : Vec < ( CodeOffset , TrapCode ) > ,
1859+ callsites : Vec < ( CodeOffset , Opcode ) > ,
1860+ relocs : Vec < ( CodeOffset , Reloc ) > ,
1861+ }
1862+ impl CodeSink for TestCodeSink {
1863+ fn offset ( & self ) -> CodeOffset {
1864+ self . offset
1865+ }
1866+ fn put1 ( & mut self , _: u8 ) {
1867+ self . offset += 1 ;
1868+ }
1869+ fn put2 ( & mut self , _: u16 ) {
1870+ self . offset += 2 ;
1871+ }
1872+ fn put4 ( & mut self , _: u32 ) {
1873+ self . offset += 4 ;
1874+ }
1875+ fn put8 ( & mut self , _: u64 ) {
1876+ self . offset += 8 ;
1877+ }
1878+ fn reloc_external ( & mut self , _: SourceLoc , r : Reloc , _: & ExternalName , _: Addend ) {
1879+ self . relocs . push ( ( self . offset , r) ) ;
1880+ }
1881+ fn reloc_constant ( & mut self , _: Reloc , _: ConstantOffset ) { }
1882+ fn reloc_jt ( & mut self , _: Reloc , _: JumpTable ) { }
1883+ fn trap ( & mut self , t : TrapCode , _: SourceLoc ) {
1884+ self . traps . push ( ( self . offset , t) ) ;
1885+ }
1886+ fn begin_jumptables ( & mut self ) { }
1887+ fn begin_rodata ( & mut self ) { }
1888+ fn end_codegen ( & mut self ) { }
1889+ fn add_stack_map ( & mut self , _: & [ Value ] , _: & Function , _: & dyn TargetIsa ) { }
1890+ fn add_call_site ( & mut self , op : Opcode , _: SourceLoc ) {
1891+ self . callsites . push ( ( self . offset , op) ) ;
1892+ }
1893+ }
1894+
1895+ let mut sink = TestCodeSink :: default ( ) ;
1896+ buf. emit ( & mut sink) ;
1897+
1898+ assert_eq ! ( sink. offset, 4 ) ;
1899+ assert_eq ! (
1900+ sink. traps,
1901+ vec![
1902+ ( 1 , TrapCode :: HeapOutOfBounds ) ,
1903+ ( 2 , TrapCode :: IntegerOverflow ) ,
1904+ ( 2 , TrapCode :: IntegerDivisionByZero )
1905+ ]
1906+ ) ;
1907+ assert_eq ! ( sink. callsites, vec![ ( 2 , Opcode :: Call ) , ] ) ;
1908+ assert_eq ! ( sink. relocs, vec![ ( 2 , Reloc :: Abs4 ) , ( 3 , Reloc :: Abs8 ) ] ) ;
1909+ }
18221910}
0 commit comments