From 12d06a4f06665a34ae751f68c9dce89f766b91e9 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Mon, 26 May 2014 14:01:18 +0800 Subject: [PATCH] Simplify compile process Changes to libcore means we need to do the compile in less passes. Added the three new lang items, pulled support into zinc, app is still the main entry point but it produces the .elf without a second call to ld. There has been a large size regression, the majority of it is from libcore pulling in the string formatting functions for error handling. I will submit a patch to provide a cfg flag for building libcore with simpler errors. --- Rakefile | 44 ++++++++++++++++------------------------ src/hal/cortex_m3/isr.rs | 12 ----------- src/hal/isr.rs | 8 -------- src/hal/layout_common.ld | 2 ++ src/hal/mod.rs | 2 ++ src/hal/stack.rs | 5 +++-- src/lib/app.rs | 5 ++--- src/lib/mod.rs | 1 + src/lib/support.rs | 31 +++++++++++++++++++++------- src/os/syscall.rs | 1 + support/build/context.rb | 4 ++++ support/rake.rb | 25 +++++++++++++++++++++-- 12 files changed, 80 insertions(+), 60 deletions(-) diff --git a/Rakefile b/Rakefile index 2bb69ac3..c1359ec9 100644 --- a/Rakefile +++ b/Rakefile @@ -26,29 +26,25 @@ compile_rust :zinc_crate, { recompile_on: [:triple, :platform, :features], } -# zinc runtime support lib -compile_rust :zinc_support, { - source: 'lib/support.rs'.in_source, - produce: 'support.o'.in_intermediate, - llvm_pass: :inline, - lto: false, - recompile_on: :triple, +# dummy archives +compile_ar :dummy_morestack, { + produce: 'libmorestack.a'.in_intermediate, } - -# zinc isr crate -compile_rust :zinc_isr, { - source: 'hal/isr.rs'.in_source, - deps: :core_crate, - produce: 'isr.o'.in_intermediate, - recompile_on: [:triple, :features], +compile_ar :dummy_compiler_rt, { + produce: 'libcompiler-rt.a'.in_intermediate, } # zinc scheduler assembly # TODO(farcaller): make platform-specific if features.include?(:multitasking) - compile_c :zinc_isr_sched, { + compile_c :zinc_isr_sched_c, { source: 'hal/cortex_m3/sched.S'.in_source, - produce: 'isr_sched.o'.in_intermediate, + produce: 'libisr_sched.o'.in_intermediate, + recompile_on: [:triple, :features], + } + compile_ar :zinc_isr_sched, { + source: 'libisr_sched.o'.in_intermediate, + produce: 'libisr_sched.a'.in_intermediate, recompile_on: [:triple, :features], } end @@ -65,22 +61,18 @@ app_tasks = Context.instance.applications.map do |a| recompile_on: [:triple, :platform, :features], } - compile_rust "app_#{a}".to_sym, { + compile_rust "app_#{a}_elf".to_sym, { + script: 'layout.ld'.in_platform, source: 'lib/app.rs'.in_source, deps: [ :core_crate, :zinc_crate, "app_#{a}_crate".to_sym, - ], - produce: "app_#{a}.o".in_intermediate(a), - search_paths: a.in_intermediate, - } - - link_binary "app_#{a}_elf".to_sym, { - script: 'layout.ld'.in_platform, - deps: ["app_#{a}".to_sym, :zinc_isr, :zinc_support] + - (features.include?(:multitasking) ? [:zinc_isr_sched] : []), + :dummy_morestack, + :dummy_compiler_rt, + ] + (features.include?(:multitasking) ? [:zinc_isr_sched] : []), produce: "app_#{a}.elf".in_build, + search_paths: [a.in_intermediate, "intermediate".in_build], } t_bin = make_binary "app_#{a}_bin".to_sym, { diff --git a/src/hal/cortex_m3/isr.rs b/src/hal/cortex_m3/isr.rs index f4282aa1..f080367b 100644 --- a/src/hal/cortex_m3/isr.rs +++ b/src/hal/cortex_m3/isr.rs @@ -30,18 +30,6 @@ extern { fn isr_systick(); } -#[no_mangle] -#[no_split_stack] -pub extern fn isr_default_fault() { - unsafe { - asm!("mrs r0, psp - mrs r1, msp - ldr r2, [r0, 0x18] - ldr r3, [r1, 0x18] - bkpt") - } -} - static ISRCount: uint = 16; #[link_section=".isr_vector"] diff --git a/src/hal/isr.rs b/src/hal/isr.rs index c82d865e..df4054e2 100644 --- a/src/hal/isr.rs +++ b/src/hal/isr.rs @@ -13,16 +13,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! This file is not part of zinc crate, it is linked separately, alongside the //! ISRs for the platform. -#![feature(asm, globs)] -#![crate_id="isr"] -#![crate_type="staticlib"] -#![no_std] - -extern crate core; - #[path="cortex_m3/isr.rs"] pub mod isr_cortex_m3; #[cfg(mcu_lpc17xx)] diff --git a/src/hal/layout_common.ld b/src/hal/layout_common.ld index 59d265c1..360f158a 100644 --- a/src/hal/layout_common.ld +++ b/src/hal/layout_common.ld @@ -12,6 +12,8 @@ SECTIONS { FILL(0xff) + /* Make sure our default fault handler isn't garbage collected */ + KEEP(*(.text.isr_default_fault)) *(.text*) *(.rodata .rodata.*) } > rom diff --git a/src/hal/mod.rs b/src/hal/mod.rs index c5738015..81db12d9 100644 --- a/src/hal/mod.rs +++ b/src/hal/mod.rs @@ -23,6 +23,8 @@ and each such struct has a `setup()` method that configures the hardware mod mem_init; +pub mod isr; + #[cfg(mcu_lpc17xx)] pub mod lpc17xx; #[cfg(mcu_stm32f4)] pub mod stm32f4; diff --git a/src/hal/stack.rs b/src/hal/stack.rs index 381d1926..884c5509 100644 --- a/src/hal/stack.rs +++ b/src/hal/stack.rs @@ -16,13 +16,14 @@ //! Stack layout information. extern { - static __STACK_BASE: u32; + // This is called an fn in ISR so needs to be an fn here. + fn __STACK_BASE(); static mut __STACK_LIMIT: u32; } /// Returns the address of main stack base (end of ram). pub fn stack_base() -> u32 { - (&__STACK_BASE as *u32) as u32 + (__STACK_BASE as *u32) as u32 } /// Returns the current stack limit. diff --git a/src/lib/app.rs b/src/lib/app.rs index 12a8f7a3..c1717097 100644 --- a/src/lib/app.rs +++ b/src/lib/app.rs @@ -17,8 +17,8 @@ //! for stack management, scheduler, ISRs and other symbols with global //! visibility. -#![crate_type="staticlib"] #![no_std] +#![no_main] extern crate core; extern crate zinc; @@ -26,7 +26,6 @@ extern crate app; #[no_split_stack] #[no_mangle] -#[start] pub extern fn main() { app::main(); } @@ -48,6 +47,6 @@ pub extern fn __morestack() { #[no_split_stack] #[no_mangle] #[cfg(cfg_multitasking)] -pub unsafe fn task_scheduler() { +pub unsafe extern fn task_scheduler() { zinc::os::task::task_scheduler(); } diff --git a/src/lib/mod.rs b/src/lib/mod.rs index 68feae63..8c267272 100644 --- a/src/lib/mod.rs +++ b/src/lib/mod.rs @@ -19,3 +19,4 @@ pub mod strconv; pub mod volatile_cell; pub mod shared; pub mod queue; +pub mod support; diff --git a/src/lib/support.rs b/src/lib/support.rs index 3002fd8a..d9aef316 100644 --- a/src/lib/support.rs +++ b/src/lib/support.rs @@ -13,17 +13,34 @@ // See the License for the specific language governing permissions and // limitations under the License. -#![no_std] -#![crate_type="rlib"] -#![feature(asm)] - -extern "rust-intrinsic" { - fn offset(dst: *T, offset: int) -> *T; -} +use core::intrinsics::offset; #[allow(non_camel_case_types)] pub type c_int = i32; +#[lang = "stack_exhausted"] +extern fn stack_exhausted() { /* ... */ } + +#[lang = "eh_personality"] +extern fn eh_personality() { /* ... */ } + +#[lang = "begin_unwind"] +extern fn begin_unwind() { + abort() +} + +#[no_mangle] +#[no_split_stack] +pub extern "C" fn isr_default_fault() { + unsafe { + asm!("mrs r0, psp + mrs r1, msp + ldr r2, [r0, 0x18] + ldr r3, [r1, 0x18] + bkpt") + } +} + #[no_mangle] #[no_split_stack] #[inline(never)] diff --git a/src/os/syscall.rs b/src/os/syscall.rs index 420578e2..ff169570 100644 --- a/src/os/syscall.rs +++ b/src/os/syscall.rs @@ -20,6 +20,7 @@ This module provides syscall interface that is implemented in assembly due to current rust restrictions (see hal/cortex_m3/sched.S for actual implementation). */ +#[link(name = "isr_sched")] extern { pub fn syscall(f: fn(u32), arg: u32); } diff --git a/support/build/context.rb b/support/build/context.rb index 688bb254..7cc01cc7 100644 --- a/support/build/context.rb +++ b/support/build/context.rb @@ -120,6 +120,10 @@ def initialize_environment! "-L#{File.join(@env[:libs_path], @platform.arch.arch)}", ] + @env[:gccflags] = [ + "-lgcc" + ] + @env[:cflags] = [ '-mthumb', "-mcpu=#{@platform.arch.cpu}", diff --git a/support/rake.rb b/support/rake.rb index 81835f42..5f961079 100644 --- a/support/rake.rb +++ b/support/rake.rb @@ -32,6 +32,7 @@ def compile_rust(n, h) crate_type = h[:crate_type] ? "--crate-type #{h[:crate_type]}" : "" ignore_warnings = h[:ignore_warnings] ? h[:ignore_warnings] : [] ignore_warnings = ignore_warnings.map { |w| "-A #{w}" }.join(' ') + script = h[:script] declared_deps = h[:deps] rust_src = h[:source] @@ -65,7 +66,18 @@ def compile_rust(n, h) '--emit asm' else '' - end + end + + mapfn = Context.instance.build_dir(File.basename(t.name, File.extname(t.name)) + '.map') + + linker = case File.extname(t.name) + when '.elf' + "-C linker=#{:gcc.in_toolchain} " + + "-C link-args=\"-T #{script} -Wl,-Map=#{mapfn} " + + :gccflags.in_env.join(' ') + '"' + else + '' + end codegen = llvm_pass ? "-C passes=#{llvm_pass}" : '' @@ -79,7 +91,7 @@ def compile_rust(n, h) sh "#{:rustc.in_env} #{flags} " + "#{do_lto ? '-Z lto' : ''} #{crate_type} #{emit} " + - "#{search_paths} #{codegen} " + + "#{search_paths} #{codegen} #{linker} " + "#{outflags} #{ignore_warnings} #{rust_src}" end end @@ -108,6 +120,15 @@ def compile_c(n, h) end end +def compile_ar(n, h) + h.resolve_deps! + Context.instance.rules[n] = h + + Rake::FileTask.define_task(h[:produce] => [h[:source], h[:deps]].flatten.compact) do |t| + sh "#{:ar.in_toolchain} cr -o #{h[:produce]} #{h[:source]}" + end +end + def listing(n, h) Rake::FileTask.define_task(h[:produce] => h[:source]) do |t| sh "#{:objdump.in_toolchain} -D #{t.prerequisites.first} > #{t.name}"