@@ -649,53 +649,78 @@ it exists. The marker is the attribute `#[lang="..."]` and there are
649
649
various different values of ` ... ` , i.e. various different 'lang
650
650
items'.
651
651
652
- For example, ` Box ` pointers require two lang items, one for allocation
653
- and one for deallocation. A freestanding program that uses the ` Box `
654
- sugar for dynamic allocations via ` malloc ` and ` free ` :
652
+ For example, there are three lang items related to task panicking:
653
+ one, ` panic_bounds_check ` , is called on panics due to out-of-bounds
654
+ array accesses; the second, ` panic ` , is used by explicit invocations
655
+ of ` panic! ` , and a third, ` panic_fmt ` , handles unwinding the stack in
656
+ the Rust standard library.
657
+
658
+ A freestanding program that provides its own definition of the
659
+ ` panic_bounds_check ` lang item:
655
660
656
661
```
657
- #![feature(lang_items, box_syntax , start, no_std)]
662
+ #![feature(lang_items, intrinsics , start, no_std)]
658
663
#![no_std]
659
664
660
- extern crate libc;
661
-
662
- extern {
663
- fn abort() -> !;
664
- }
665
+ // To be able to print to standard output from this demonstration
666
+ // program, we link with `printf` from the C standard library. Note
667
+ // that this requires we null-terminate our strings with "\0".
665
668
666
- #[lang = "owned_box"]
667
- pub struct Box<T>(*mut T);
669
+ mod printf {
670
+ #[link(name="c")]
671
+ extern { fn printf(f: *const u8, ...); }
668
672
669
- #[lang="exchange_malloc"]
670
- unsafe fn allocate(size: usize, _align: usize ) -> *mut u8 {
671
- let p = libc::malloc(size as libc::size_t) as *mut u8;
673
+ extern "rust-intrinsic" {
674
+ pub fn transmute<T,U>(e: T ) -> U;
675
+ }
672
676
673
- // malloc failed
674
- if p as usize == 0 {
675
- abort( );
677
+ pub unsafe fn print0(s: &str) {
678
+ let (bytes, _len): (*const u8, usize) = transmute(s);
679
+ printf(bytes );
676
680
}
677
681
678
- p
682
+ pub unsafe fn print2(s: &str, arg1: u32, arg2: u32) {
683
+ let (bytes, _len): (*const u8, usize) = transmute(s);
684
+ printf(bytes, arg1, arg2);
685
+ }
679
686
}
680
- #[lang="exchange_free"]
681
- unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) {
682
- libc::free(ptr as *mut libc::c_void)
687
+
688
+ #[lang="panic_bounds_check"]
689
+ fn panic_bounds_check(_file_line: &(&'static str, usize),
690
+ index: usize, len: usize) {
691
+ // For simplicity of demonstration, just print message and exit.
692
+ extern { fn exit(status: u32) -> !; }
693
+
694
+ let index = index as u32;
695
+ let len = len as u32;
696
+ unsafe {
697
+ printf::print2("panic_bounds_check index: %d len: %d\n\0", index, len);
698
+
699
+ // (we pass 0 since this is expected behavior for the demonstration.)
700
+ exit(0);
701
+ }
683
702
}
684
703
685
704
#[start]
686
- fn main(argc: isize, argv: *const *const u8) -> isize {
687
- let x = box 1;
688
-
689
- 0
705
+ fn main(_argc: isize, _argv: *const *const u8) -> isize {
706
+ let a = [100, 200, 300];
707
+ unsafe { printf::print0("doing a[4] for a.len() == 3\n\0"); }
708
+ a[4];
709
+ unsafe { printf::print0("Should not get here.\n\0"); }
710
+ return 0;
690
711
}
691
712
713
+ // Again, these functions and traits are used by the compiler, and are
714
+ // normally provided by libstd. (The `Sized` and `Copy` lang_items
715
+ // require definitions due to the type-parametric code above.)
716
+
692
717
#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
693
718
#[lang = "eh_personality"] extern fn eh_personality() {}
694
719
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
695
- ```
696
720
697
- Note the use of ` abort ` : the ` exchange_malloc ` lang item is assumed to
698
- return a valid pointer, and so needs to do the check internally.
721
+ #[lang="sized"] pub trait Sized {}
722
+ #[lang="copy"] pub trait Copy {}
723
+ ```
699
724
700
725
Other features provided by lang items include:
701
726
@@ -712,6 +737,6 @@ Other features provided by lang items include:
712
737
` contravariant_lifetime ` , etc.
713
738
714
739
Lang items are loaded lazily by the compiler; e.g. if one never uses
715
- ` Box ` then there is no need to define functions for ` exchange_malloc `
716
- and ` exchange_free ` . ` rustc ` will emit an error when an item is needed
717
- but not found in the current crate or any that it depends on.
740
+ array indexing ` a[i] ` then there is no need to define a function for
741
+ ` panic_bounds_check ` . ` rustc ` will emit an error when an item is
742
+ needed but not found in the current crate or any that it depends on.
0 commit comments