[rust-dev] Cross-compilation with plugins is effectively dead?
I have some concerns related to https://github.com/rust-lang/rust/issues/18699 and I'd like to get some advice from the team. Support for cross-compiling code with plugins was broken for a few months now for anything but linux. Finally it seems to be broken for linux as well halting all our efforts. How important is cross-compilation support for rust at all? zinc is barely the only embedded project based on rust but we do use plugins and macros extensively throughout the code and we can't just stop using them, unfortunately; so for us any breakage of plugins system is a halt. We can deal with internal libs changing syntax but fixing up compiler itself is not that easy. Any chance we'll see it fixed before 1.0 hits? -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Declaring the API unsafe while keeping the internal safety checks
Well, strictly speaking it *is* memory safety, as it all gets down to an unsafe volatile store. Although I think I extend the 'unsafety' a bit by considering code that can cause CPU to halt as unsafe too. On Fri, Jan 2, 2015 at 2:11 AM, Kevin McGuire kmcg3...@gmail.com wrote: Yes unsafe is primarily for memory safety. However! Your idea is good. It would be really good if you could have something like that. I am just not sure what the best way to do it is. It could be done by an attribute and lint with the ability to toggle it off with a module level, function level, or scope level second attribute, lol, possibilities are endless. But indeed unsafe is likely only, currently, for memory safety. Still I like the idea! I love the idea. I read your email earlier today but only shortly ago I realize what you mean. On Jan 1, 2015 5:17 AM, Vladimir Pouzanov farcal...@gmail.com wrote: I had this idea for some time and I'd like to discuss it to see if it is something reasonable to be proposed for rust to implement or there are other ways around the problem. Let's say I have a low level function that manipulates the hardware clock using some platform-specific argument. Internally this function will do an unsafe volatile mem write to store value in the register, but this is the only part of the code that is unsafe compiler-wise, whatever else is in there in the function is safe and I want the compiler to warn me if any other unsafe operation happens. Now, given that this function is actually unsafe in terms of its realtime consequences (it does not do any validation of the input for speed) I want to mark it as unsafe fn and make a safer wrapper for end users, while keeping this for the little subset of users that will need the actual speed benefits. Unfortunately, marking it unsafe will now allow any other unsafe operation in the body of the function, when what I wanted is just to force users of it to be aware of unsafety via compiler validation. A safe {} block could have helped me in this case. But is it a good idea overall? Some pseudo-code to illustrate pub unsafe fn set_clock_mode(mode: uint32) { // ... // doing some required computations // this code must be 'safe' for the compiler unsafe { // ... // writing the value to mmaped register, this one is unsafe but validated by programmer } } pub fn set_clock_mode_safe(mode: uint32) - bool { // ... // validate input unsafe { // I want this call to require unsafe block set_clock_mode(mode); } } -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Problems cross-compiling to ARM9
FWIW, we're just disabling segmented stack in zinc for now exactly because of the same problem. I have a patch for llvm but I didn't really push it upstream hard enough. On Tue, Dec 30, 2014 at 11:23 AM, Valerii Hiora valerii.hi...@gmail.com wrote: Hi Tomi, Anyone have any idea if that's a larger problem, or simply something nobody has written the small handcoded ASMs needed for ARMv5 or v4? If latter, I might be able to wrap my head around this. The problem you've got is related to segmented stack support. It need fix on 2 levels: - Rust - can be relatively easy fixed by providing (or patching) a target and marking it as a target which doesn't support segmented stacks, see example [1] Once it works you can play a bit to provide a correct implementation in record_sp.S and morestack.S - LLVM - as I remember some time ago LLVM generated a function prologue which uses the same instruction for any ARM device, may be that was patched in upstream, may be not. You can also ask Vladimir Pouzanov and zinc.rs [2] team, AFAIK they had the similar problem too and definitely have a workaround. [1] https://github.com/rust-lang/rust/blob/master/src/librustc_back/target/arm_apple_ios.rs#L33 [2] https://zinc.rs/ -- Valerii ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] Programmaticaly accessing compiler warnings
Hi all. Is there any way to access compiler warnings and errors other than parsing stdout? I'd prefer a bit more structured approach. -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] A shiny test framework
I've just published a tiny test framework: shiny at https://github.com/farcaller/shiny. It's best used with hamcrest-rust. This library exists because I find it ugly to redefine all the initialisation code in every test case and I can't simply move it to a function due to problems with moving [T] out. Here's how shiny looks: #[cfg(test)] mod test { describe!( before_each { let awesome = true; } it is awesome { assert!(awesome); } it injects before_each into all test cases { let still_awesome = awesome; assert!(still_awesome); } ) } -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] A shiny test framework
One note on why there's no after_each: You cannot really make sure that the epilogue is being called, so if you need to do anything after your test case, use RAII in before_each. On Tue, Jul 22, 2014 at 8:10 PM, Benjamin Gudehus hasteb...@gmail.com wrote: Nice to see an RSpec-like test framework and Hamcrest assertions/matchers for Rust! On Tue, Jul 22, 2014 at 9:09 PM, Ilya Dmitrichenko errordevelo...@gmail.com wrote: Dude, that's pretty much rspec ;) sweet! On 22 Jul 2014 20:07, Vladimir Pouzanov farcal...@gmail.com wrote: I've just published a tiny test framework: shiny at https://github.com/farcaller/shiny. It's best used with hamcrest-rust. This library exists because I find it ugly to redefine all the initialisation code in every test case and I can't simply move it to a function due to problems with moving [T] out. Here's how shiny looks: #[cfg(test)] mod test { describe!( before_each { let awesome = true; } it is awesome { assert!(awesome); } it injects before_each into all test cases { let still_awesome = awesome; assert!(still_awesome); } ) } -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] What do I do if I need several muts into a struct?
I have a problem figuring the reasonable data access pattern for my code, here's a brief description. I have a tree structure where each node has a path and an optional name. Path is used to locate the node in tree hierarchy, names are stored in a flat namespace as node aliases: lpx17xx@mcu { clock { attr = value; } } os { thread { entry = start; ref = lpx17xx; } } this tree has 4 nodes, /mcu, /mcu/clock, /os and /os/thread. /mcu is also known as lpx17xx. I use the following structure to hold root nodes: #[deriving(Show)] pub struct PlatformTree { nodes: HashMapString, GcNode, named: HashMapString, GcNode, } Everything works fine up to the point of references. References allow some nodes to modify other nodes. So, the first pass — I parse that snippet into PlatformTree/Nodes struct. Second pass — I walk over the tree and for each reference I invoke some handling code, e.g. in the handler of thread node it might add some attribute to lpx17xx node. Which is not really possible as it's in immutable Gc box. Also, such modifications are performed through `named` hashmap, so I can't even store muts in `nodes`, as I still can store only immutable pointers in `named`. How would you solve this problem? -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] Flatten a tree into HashMap, how do I pass a mut around?
I have a tree of Nodes where each node might have a name. I'm trying to convert the tree into a HashMap of named nodes, but my code is getting extremely complex due to the fact that I cannot pass mut HashMap around. let mut named_nodes = HashMap::new(); let nodes = vec!( ... ); named_nodes = self.collect_node_names(named_nodes, nodes); println!('{}', named_nodes); fn collect_node_names(self, map: HashMapString, Gcnode::Node, nodes: VecGcnode::Node) - HashMapString, Gcnode::Node { let mut local_map: HashMapString, Gcnode::Node = HashMap::new(); for (k,v) in map.iter() { local_map.insert(k.clone(), *v); } for n in nodes.iter() { for (k,v) in self.collect_node_names(local_map, n.subnodes).iter() { local_map.insert(k.clone(), *v); } match n.name { Some(ref name) = { if local_map.contains_key(name) { } else { local_map.insert(name.clone(), *n); } }, None = (), } } local_map } this one works, but it's bloated and slow. Any hints on how to improve the code? -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Flatten a tree into HashMap, how do I pass a mut around?
After a few hints on IRC I managed to simplify it to: fn collect_node_names(self, map: mut HashMapString, Gcnode::Node, nodes: VecGcnode::Node) - bool { for n in nodes.iter() { if !self.collect_node_names(map, n.subnodes) { return false; } match n.name { Some(ref name) = { if map.contains_key(name) { self.sess.span_diagnostic.span_err(n.name_span, format!( duplicate `{}` definition, name).as_slice()); self.sess.span_diagnostic.span_warn( map.get(name).name_span, previously defined here); return false; } else { map.insert(name.clone(), *n); } }, None = (), } } true } My failure point was that I didn't realise you cannot access mut while yo have a reference to anything you pass mut to. On Sun, Jun 15, 2014 at 8:14 AM, Vladimir Pouzanov farcal...@gmail.com wrote: I have a tree of Nodes where each node might have a name. I'm trying to convert the tree into a HashMap of named nodes, but my code is getting extremely complex due to the fact that I cannot pass mut HashMap around. let mut named_nodes = HashMap::new(); let nodes = vec!( ... ); named_nodes = self.collect_node_names(named_nodes, nodes); println!('{}', named_nodes); fn collect_node_names(self, map: HashMapString, Gcnode::Node, nodes: VecGcnode::Node) - HashMapString, Gcnode::Node { let mut local_map: HashMapString, Gcnode::Node = HashMap::new(); for (k,v) in map.iter() { local_map.insert(k.clone(), *v); } for n in nodes.iter() { for (k,v) in self.collect_node_names(local_map, n.subnodes).iter() { local_map.insert(k.clone(), *v); } match n.name { Some(ref name) = { if local_map.contains_key(name) { } else { local_map.insert(name.clone(), *n); } }, None = (), } } local_map } this one works, but it's bloated and slow. Any hints on how to improve the code? -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Nightly docs for Dash
Funnily enough I did the same yesterday. I made a small extension to https://github.com/indirect/dash-rust, my fork can be found here: https://github.com/farcaller/dash-rust It removes the left side navigation panel from docs and adds TOC generation. On Sat, Jun 14, 2014 at 2:55 AM, Valerii Hiora valerii.hi...@gmail.com wrote: Hi, Being a big fan of offline documentation I've prepared a fresh docset for Dash (zeal, helm-dash, any other compatible software). Here is the link for subscription: dash-feed://https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fnet. vhbit.rust-doc%2FRustNightly.xml It's a beta and has a couple of known issues in it. If there would be enough interest - it could be also integrated with existing buildbots. -- Valerii ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] how is Rust bootstrapped?
Rustc runs on arm just fine. On Mon, Jun 9, 2014 at 11:32 AM, Kevin Cantu m...@kevincantu.org wrote: Perl and Python may still be dependencies for small things on some platforms, IIRC, too. Anyways, to get `rustc` on a new architecture, it must be one LLVM supports, and then you should cross-compile `rustc` onto it. I don't remember for sure whether `rustc` even runs on ARM, or if people just cross-compile binaries for it, actually, though... Kevin On Mon, Jun 9, 2014 at 3:16 AM, Leo Testard leo.test...@gmail.com wrote: Hello, The OCaml compiler is not used anymore for years. As you said, the Rust build system now downloads a precompiled snapshot of the new implementation, which is written in Rust. Unfortunately, you won't be able to compile it yourself.if you don't have Rust already setup on your machine. For C++, I believe it's used to compile the modified LLVM Rustc uses. Others may confirm this. Leo -- Envoyé de mon téléphone Android avec K-9 Mail. Excusez la brièveté. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] How do I bootstrap rust form armhf?
Thanks, I managed to bootstrap my rustc already with a few hints. On Fri, Jun 6, 2014 at 4:19 PM, Valerii Hiora valerii.hi...@gmail.com wrote: I'm trying to run rustc on an arm board, but obviously there's no precompiled stage0 to build the compiler. Is there a procedure to cross-compile stage0 on other host machine where I do have rustc? Disclaimer: haven't tried anything like this, but just a couple of hints: - configure script checks for CFG_ENABLE_LOCAL_RUST, so it should be possible to use any rustc - in src/etc there are make_snapshot.py, snapshot.py, local_stage0.sh which might be useful for study - there are a couple of mentions of cfg(stage0) in sources, probably compiling rust for stage0 will require additionally setting --cfg stage0 -- Valerii ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] How do I bootstrap rust form armhf?
I'm trying to run rustc on an arm board, but obviously there's no precompiled stage0 to build the compiler. Is there a procedure to cross-compile stage0 on other host machine where I do have rustc? -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] morestack prologue contains broken machine code
Is there any good reason why kSplitStackAvailable is hard-coded to 256 (given that I have tasks with their whole stack on 512 bytes)? I guess, this constant should actually be externally configurable. On Fri, Apr 25, 2014 at 5:20 PM, Alex Crichton a...@crichton.co wrote: The prologue is run on every single function executed in a program, so I believe that in the hopes of keeping it as light as possible it never makes any function calls. I do agree though, that it's at tricky situation in that case. How does TLS otherwise work for that platform? On Fri, Apr 25, 2014 at 8:14 AM, Vladimir Pouzanov farcal...@gmail.com wrote: I have a side question related to the same code. Currently __STACK_LIMIT is constant, but I would like the preamble to verify stack overflow for multithreaded context, i.e. __STACK_LIMIT will depend on the current running thread. Is there any reason, why it's not a function? Any objections if I do some refactoring and make it a function? For a simple case that could be a weak symbol that returns a constant. On Tue, Apr 22, 2014 at 9:00 AM, Alex Crichton a...@crichton.co wrote: I agree with Corey, it's much better to send it upstream first. I'd be more than willing to help you out with writing tests or taking a peek at the patch if you want! I'm acrichto on IRC On Tue, Apr 22, 2014 at 12:43 AM, Vladimir Pouzanov farcal...@gmail.com wrote: The problem is that mrc is generated unless target is thumb1, but cortex-m3 is thumb2 that still doesn't support mrc: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka398.html , so an additional check to ST-TargetTriple.Data is required to verify it's not thumbv7m. Do I need to submit patch against https://github.com/rust-lang/llvmor send it to upstream? On Mon, Apr 21, 2014 at 6:34 PM, Vladimir Pouzanov farcal...@gmail.com wrote: Hm, it seems to have precautions to stop mrc from materializing on Thumb1. I guess I need to take a better look into what's going wrong on my side. I'll see what I can do with that. On Mon, Apr 21, 2014 at 5:23 PM, Alex Crichton a...@crichton.co wrote: The split stack patches for ARM were recently upstreamed, and they were modified when being upstreamed as well. Primarily the location of the split stack is no longer at a magic address for thumb, but rather it uses the same instruction as ARM (some thumb processors do indeed have the coprocessor). More information is in the long thread starting at the initial attempt to upstream [1]. For now you'll have to use no_split_stack because the thumb split stack will always use a coprocessor, but I'm sure that the upstream LLVM devs would be quite welcoming to tweaks to the slit-stack support (I'd also be willing to help). You can find the initial commit for support at rust-lang/llvm [2]. [1] - http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20140224/205968.html [2] - https://github.com/rust-lang/llvm/pull/4 On Mon, Apr 21, 2014 at 6:50 AM, Vladimir Pouzanov farcal...@gmail.com wrote: Starting recently (no more than two weeks), rustc is generating a broken prologue for arm. Here's the sample assembly: 0x0f44 +0: push {r4, r5} = 0x0f46 +2: mrc 15, 0, r4, cr13, cr0, {3} 0x0f4a +6: mov r5, sp 0x0f4c +8: b.n 0xa78 main+2616 0x0f4e +10: ands r4, r0 0x0f50 +12: cmp r4, r5 0x0f52 +14: bcc.n 0xf66 _ZN7drivers3lcd6c1233244C12332$LT$$x27a$C$$x20S$C$$x20T$GT$.lcd..LCD5flush20h76589116290686712394v0.0E+34 0x0f54 +16: movs r4, #16 0x0f56 +18: movs r5, #0 0x0f58 +20: push {lr} 0x0f5a +22: bl 0x19d8 __morestack 0x0f5e +26: ldr.w lr, [sp], #4 0x0f62 +30: pop {r4, r5} 0x0f64 +32: bx lr The problem is at 0x0f46, where code tries to read from coprocessor 15 register 13, which is process id register. Well, coprocessor 15 (actually, all of the coprocessors) are missing from my target thumbv7m-linux-eabi (with added flavour of -Ctarget-cpu=cortex-m3, which should be redundant anyway), so I'm getting hardfaults in every function that rust doesn't inline. Any ideas on what might be going wrong? I assume that this is actually llvm's fault, as llvm should not materialize machine code which is not available for target anyway. Wrapping everything in #[no_split_stack] is a temporary workaround and surely not a long-term strategy. -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller
Re: [rust-dev] morestack prologue contains broken machine code
I guess I've misread how __STACK_LIMIT works, it seems that I can change it's value on context switch so that it keeps track of the current running task. Works flawlessly, so I'm going to proceed with my original patch now. On Fri, Apr 25, 2014 at 6:33 PM, Vladimir Pouzanov farcal...@gmail.comwrote: AFAIK, it's emulated in software with __tls_get_addr. Mind that Cortex-M MCUs that I'm toying with aren't usually compatible with any full-blown OS, and all the RTOSes out there have different implementations of multithreading and TLS, utilising the none OS target of gcc. The best way to deal with this would be to specify arm-none-eabi ABI for llvm, that would include tls behaviour amongst other things, but that sounds like a very complex task. On Fri, Apr 25, 2014 at 5:20 PM, Alex Crichton a...@crichton.co wrote: The prologue is run on every single function executed in a program, so I believe that in the hopes of keeping it as light as possible it never makes any function calls. I do agree though, that it's at tricky situation in that case. How does TLS otherwise work for that platform? On Fri, Apr 25, 2014 at 8:14 AM, Vladimir Pouzanov farcal...@gmail.com wrote: I have a side question related to the same code. Currently __STACK_LIMIT is constant, but I would like the preamble to verify stack overflow for multithreaded context, i.e. __STACK_LIMIT will depend on the current running thread. Is there any reason, why it's not a function? Any objections if I do some refactoring and make it a function? For a simple case that could be a weak symbol that returns a constant. On Tue, Apr 22, 2014 at 9:00 AM, Alex Crichton a...@crichton.co wrote: I agree with Corey, it's much better to send it upstream first. I'd be more than willing to help you out with writing tests or taking a peek at the patch if you want! I'm acrichto on IRC On Tue, Apr 22, 2014 at 12:43 AM, Vladimir Pouzanov farcal...@gmail.com wrote: The problem is that mrc is generated unless target is thumb1, but cortex-m3 is thumb2 that still doesn't support mrc: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka398.html , so an additional check to ST-TargetTriple.Data is required to verify it's not thumbv7m. Do I need to submit patch against https://github.com/rust-lang/llvmor send it to upstream? On Mon, Apr 21, 2014 at 6:34 PM, Vladimir Pouzanov farcal...@gmail.com wrote: Hm, it seems to have precautions to stop mrc from materializing on Thumb1. I guess I need to take a better look into what's going wrong on my side. I'll see what I can do with that. On Mon, Apr 21, 2014 at 5:23 PM, Alex Crichton a...@crichton.co wrote: The split stack patches for ARM were recently upstreamed, and they were modified when being upstreamed as well. Primarily the location of the split stack is no longer at a magic address for thumb, but rather it uses the same instruction as ARM (some thumb processors do indeed have the coprocessor). More information is in the long thread starting at the initial attempt to upstream [1]. For now you'll have to use no_split_stack because the thumb split stack will always use a coprocessor, but I'm sure that the upstream LLVM devs would be quite welcoming to tweaks to the slit-stack support (I'd also be willing to help). You can find the initial commit for support at rust-lang/llvm [2]. [1] - http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20140224/205968.html [2] - https://github.com/rust-lang/llvm/pull/4 On Mon, Apr 21, 2014 at 6:50 AM, Vladimir Pouzanov farcal...@gmail.com wrote: Starting recently (no more than two weeks), rustc is generating a broken prologue for arm. Here's the sample assembly: 0x0f44 +0: push {r4, r5} = 0x0f46 +2: mrc 15, 0, r4, cr13, cr0, {3} 0x0f4a +6: mov r5, sp 0x0f4c +8: b.n 0xa78 main+2616 0x0f4e +10: ands r4, r0 0x0f50 +12: cmp r4, r5 0x0f52 +14: bcc.n 0xf66 _ZN7drivers3lcd6c1233244C12332$LT$$x27a$C$$x20S$C$$x20T$GT$.lcd..LCD5flush20h76589116290686712394v0.0E+34 0x0f54 +16: movs r4, #16 0x0f56 +18: movs r5, #0 0x0f58 +20: push {lr} 0x0f5a +22: bl 0x19d8 __morestack 0x0f5e +26: ldr.w lr, [sp], #4 0x0f62 +30: pop {r4, r5} 0x0f64 +32: bx lr The problem is at 0x0f46, where code tries to read from coprocessor 15 register 13, which is process id register. Well, coprocessor 15 (actually, all of the coprocessors) are missing from my target thumbv7m-linux-eabi (with added flavour of -Ctarget-cpu=cortex-m3, which should be redundant anyway), so I'm getting hardfaults in every function that rust doesn't inline. Any ideas on what might be going wrong
[rust-dev] Symbol visibility problem
I have the following setup: libzinc, compiles as rlib, provides all the stuff support, compiles as obj, provides __morestack, memset/memcpy and other required things libapp, compiles as staticlib emitting obj, depends on libzinc, builds with lto. I link libapp.o and support.o to get the final binary. Now, to make multitasking work, I need to move __morestack into libzinc, so that I can access task API from the function. The problem is that publicly visible __morestack in libzinc is not visible from libapp, which requires it implicitly via function prologues. Other static symbols (like __STACK_LIMIT) are not available as well. Is there any way to promote the visibility of symbols from libzinc to libapp in this case? -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Symbol visibility problem
Right, so I have a publicly reachable symbol __STACK_LIMIT inside my libzinc rlib: #[no_mangle] pub static mut __STACK_LIMIT: u32 = 0; which is present in rlib's object file: % arm-none-eabi-nm zinc.o|grep __STACK_LIMIT B __STACK_LIMIT Now, I compile my application, which is a staticlib, emiting an obj (I could change staticlib to binary, that doesn't really change anything at this emit level): rustc -Z no-landing-pads -C relocation_model=static --target thumbv7m-linux-eabi -Ctarget-cpu=cortex-m3 --opt-level 2 -Z lto --emit obj -L ./build -o ./build/intermediate/app.o ./apps/app_sched.rs Which implicitly links to libzinc-de5e5c68-0.0.rlib. Given the lto nature, ./build/intermediate/app.o will contain all the required code from libzinc (and libcore), so I proceed to linker: arm-none-eabi-ld -Map ./build/zinc.map -o ./build/zinc.elf -T ./src/hal/lpc17xx/layout.ld ./build/intermediate/app.o -L/opt/gcc-arm-none-eabi-4_7-2013q3/lib/gcc/arm-none-eabi/4.7.4/armv7-m --gc-sections -lgcc Which fails due to undefined reference to `__STACK_LIMIT', as the lto step didn't keep the __STACK_LIMIT (which is, along with __morestack, used implicitly). I have the same problem with ISRs that re defined in libzinc. For now, I make trampolines in the app code: #[no_mangle] #[inline(never)] #[no_split_stack] pub unsafe fn task_scheduler() { task::task_scheduler(); } that look bad, but I don't yet know a better way to do it. I cannot move __STACK_LIMIT or __morestack in a dedicated object file and pass it to linker, as those depend on libzinc which isn't reaching the linker explicitly. On Wed, Apr 30, 2014 at 5:17 PM, Alex Crichton a...@crichton.co wrote: In an rlib, all publicly reachable symbols will be exported from the object, for example: mod foo { pub static BAR: int = 3; } That symbol is not exported because BAR is not reachable from the outside world. pub use foo::BAR; mod foo { pub static BAR: int = 3; } This time, BAR will be an exported symbol because it is publicly reachable (you could also make 'foo' public). Would that help your use case, or are you thinking of something more complex? On Wed, Apr 30, 2014 at 6:49 AM, Vladimir Pouzanov farcal...@gmail.com wrote: I have the following setup: libzinc, compiles as rlib, provides all the stuff support, compiles as obj, provides __morestack, memset/memcpy and other required things libapp, compiles as staticlib emitting obj, depends on libzinc, builds with lto. I link libapp.o and support.o to get the final binary. Now, to make multitasking work, I need to move __morestack into libzinc, so that I can access task API from the function. The problem is that publicly visible __morestack in libzinc is not visible from libapp, which requires it implicitly via function prologues. Other static symbols (like __STACK_LIMIT) are not available as well. Is there any way to promote the visibility of symbols from libzinc to libapp in this case? -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Symbol visibility problem
Ok, seems that I found a reasonably good solution. The app is now an rlib, and the actual staticlib app that gets linked is a wrapper, that sources all external crates and re-exports required symbols like this: #[no_split_stack] #[no_mangle] #[start] pub extern fn main() { app::main(); } I also had to move __STACK_LIMIT into external C file, as I couldn't define it as external in one crate and provide it in another crate down the chain. On Wed, Apr 30, 2014 at 5:29 PM, Vladimir Pouzanov farcal...@gmail.comwrote: Right, so I have a publicly reachable symbol __STACK_LIMIT inside my libzinc rlib: #[no_mangle] pub static mut __STACK_LIMIT: u32 = 0; which is present in rlib's object file: % arm-none-eabi-nm zinc.o|grep __STACK_LIMIT B __STACK_LIMIT Now, I compile my application, which is a staticlib, emiting an obj (I could change staticlib to binary, that doesn't really change anything at this emit level): rustc -Z no-landing-pads -C relocation_model=static --target thumbv7m-linux-eabi -Ctarget-cpu=cortex-m3 --opt-level 2 -Z lto --emit obj -L ./build -o ./build/intermediate/app.o ./apps/app_sched.rs Which implicitly links to libzinc-de5e5c68-0.0.rlib. Given the lto nature, ./build/intermediate/app.o will contain all the required code from libzinc (and libcore), so I proceed to linker: arm-none-eabi-ld -Map ./build/zinc.map -o ./build/zinc.elf -T ./src/hal/lpc17xx/layout.ld ./build/intermediate/app.o -L/opt/gcc-arm-none-eabi-4_7-2013q3/lib/gcc/arm-none-eabi/4.7.4/armv7-m --gc-sections -lgcc Which fails due to undefined reference to `__STACK_LIMIT', as the lto step didn't keep the __STACK_LIMIT (which is, along with __morestack, used implicitly). I have the same problem with ISRs that re defined in libzinc. For now, I make trampolines in the app code: #[no_mangle] #[inline(never)] #[no_split_stack] pub unsafe fn task_scheduler() { task::task_scheduler(); } that look bad, but I don't yet know a better way to do it. I cannot move __STACK_LIMIT or __morestack in a dedicated object file and pass it to linker, as those depend on libzinc which isn't reaching the linker explicitly. On Wed, Apr 30, 2014 at 5:17 PM, Alex Crichton a...@crichton.co wrote: In an rlib, all publicly reachable symbols will be exported from the object, for example: mod foo { pub static BAR: int = 3; } That symbol is not exported because BAR is not reachable from the outside world. pub use foo::BAR; mod foo { pub static BAR: int = 3; } This time, BAR will be an exported symbol because it is publicly reachable (you could also make 'foo' public). Would that help your use case, or are you thinking of something more complex? On Wed, Apr 30, 2014 at 6:49 AM, Vladimir Pouzanov farcal...@gmail.com wrote: I have the following setup: libzinc, compiles as rlib, provides all the stuff support, compiles as obj, provides __morestack, memset/memcpy and other required things libapp, compiles as staticlib emitting obj, depends on libzinc, builds with lto. I link libapp.o and support.o to get the final binary. Now, to make multitasking work, I need to move __morestack into libzinc, so that I can access task API from the function. The problem is that publicly visible __morestack in libzinc is not visible from libapp, which requires it implicitly via function prologues. Other static symbols (like __STACK_LIMIT) are not available as well. Is there any way to promote the visibility of symbols from libzinc to libapp in this case? -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] A small announcement for zinc, the bare metal rust stack
A few ideas: * make a static P that manages *T storage inside it. *T could be statically pointed to heap block in ram, P will wrap the API to make it less verbose. * use Cell to make internals of immutable mutable back again. This would not work with statics, obviously, as they will land in .rodata, but we have #[link_section] to deal with that. * same as above, but use extern with further linker script placement (same way as I deal with ioregs in zinc). On Thu, Apr 24, 2014 at 11:37 PM, Ben Gamari bgam...@gmail.com wrote: Ben Gamari bgam...@gmail.com writes: Vladimir Pouzanov farcal...@gmail.com writes: ... My current idea is to make dedicated pools that could hold a compile-time configurable number of objects of same size, e.g. an IncomingPacketPool that can hold up to 3 frames where one frame is 128 bytes long. This way no other running process can interfere with code that processes incoming packets and that code can offload incoming packets into the pool for later processing, but up to three, and it will act in user-defined fashion (drop packets) if the pool is full. The implementation of that would be quite simple, and I think that it might be possible to extend ~T ownership for something like that. I tried playing around (warning: code written by new Rust-er, expect eye damage, feedback welcome) with a simple buffer pool implementation this morning; unfortunately I found that Rust's restrictions on function application in constant expressions makes static allocation quite difficult (impossible?), Tonight I played around with using the macro system to work around the static initializer limitation. The result[1] isn't terrible, but it didn't take long for me to run into a mutability issue. In short, I was inadvertently declaring my static pool as immutable, causing it to end up in the data.rel.ro section, resulting in a segfault when I attempt to increment the reference count (held in an `Unsafe`). I thought the obvious way around this would be to declare the pool as `static mut` but this unfortunately makes things quite verbose as one must declare each point of usage as `unsafe`. Moreover, for reasons I don't quite yet understand it seems that some data is still being placed in a read-only section and therefore the crash reappears. Regardless, it seems that mutable statics might be another sticking point in embedded contexts where static allocation is often desirable. Anyone have any clever ideas for dealing with this? Cheers, - Ben [1] https://gist.github.com/bgamari/033379d82f179eac8688 -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] morestack prologue contains broken machine code
I have a side question related to the same code. Currently __STACK_LIMIT is constant, but I would like the preamble to verify stack overflow for multithreaded context, i.e. __STACK_LIMIT will depend on the current running thread. Is there any reason, why it's not a function? Any objections if I do some refactoring and make it a function? For a simple case that could be a weak symbol that returns a constant. On Tue, Apr 22, 2014 at 9:00 AM, Alex Crichton a...@crichton.co wrote: I agree with Corey, it's much better to send it upstream first. I'd be more than willing to help you out with writing tests or taking a peek at the patch if you want! I'm acrichto on IRC On Tue, Apr 22, 2014 at 12:43 AM, Vladimir Pouzanov farcal...@gmail.com wrote: The problem is that mrc is generated unless target is thumb1, but cortex-m3 is thumb2 that still doesn't support mrc: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka398.html , so an additional check to ST-TargetTriple.Data is required to verify it's not thumbv7m. Do I need to submit patch against https://github.com/rust-lang/llvm or send it to upstream? On Mon, Apr 21, 2014 at 6:34 PM, Vladimir Pouzanov farcal...@gmail.com wrote: Hm, it seems to have precautions to stop mrc from materializing on Thumb1. I guess I need to take a better look into what's going wrong on my side. I'll see what I can do with that. On Mon, Apr 21, 2014 at 5:23 PM, Alex Crichton a...@crichton.co wrote: The split stack patches for ARM were recently upstreamed, and they were modified when being upstreamed as well. Primarily the location of the split stack is no longer at a magic address for thumb, but rather it uses the same instruction as ARM (some thumb processors do indeed have the coprocessor). More information is in the long thread starting at the initial attempt to upstream [1]. For now you'll have to use no_split_stack because the thumb split stack will always use a coprocessor, but I'm sure that the upstream LLVM devs would be quite welcoming to tweaks to the slit-stack support (I'd also be willing to help). You can find the initial commit for support at rust-lang/llvm [2]. [1] - http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20140224/205968.html [2] - https://github.com/rust-lang/llvm/pull/4 On Mon, Apr 21, 2014 at 6:50 AM, Vladimir Pouzanov farcal...@gmail.com wrote: Starting recently (no more than two weeks), rustc is generating a broken prologue for arm. Here's the sample assembly: 0x0f44 +0: push {r4, r5} = 0x0f46 +2: mrc 15, 0, r4, cr13, cr0, {3} 0x0f4a +6: mov r5, sp 0x0f4c +8: b.n 0xa78 main+2616 0x0f4e +10: ands r4, r0 0x0f50 +12: cmp r4, r5 0x0f52 +14: bcc.n 0xf66 _ZN7drivers3lcd6c1233244C12332$LT$$x27a$C$$x20S$C$$x20T$GT$.lcd..LCD5flush20h76589116290686712394v0.0E+34 0x0f54 +16: movs r4, #16 0x0f56 +18: movs r5, #0 0x0f58 +20: push {lr} 0x0f5a +22: bl 0x19d8 __morestack 0x0f5e +26: ldr.w lr, [sp], #4 0x0f62 +30: pop {r4, r5} 0x0f64 +32: bx lr The problem is at 0x0f46, where code tries to read from coprocessor 15 register 13, which is process id register. Well, coprocessor 15 (actually, all of the coprocessors) are missing from my target thumbv7m-linux-eabi (with added flavour of -Ctarget-cpu=cortex-m3, which should be redundant anyway), so I'm getting hardfaults in every function that rust doesn't inline. Any ideas on what might be going wrong? I assume that this is actually llvm's fault, as llvm should not materialize machine code which is not available for target anyway. Wrapping everything in #[no_split_stack] is a temporary workaround and surely not a long-term strategy. -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] morestack prologue contains broken machine code
AFAIK, it's emulated in software with __tls_get_addr. Mind that Cortex-M MCUs that I'm toying with aren't usually compatible with any full-blown OS, and all the RTOSes out there have different implementations of multithreading and TLS, utilising the none OS target of gcc. The best way to deal with this would be to specify arm-none-eabi ABI for llvm, that would include tls behaviour amongst other things, but that sounds like a very complex task. On Fri, Apr 25, 2014 at 5:20 PM, Alex Crichton a...@crichton.co wrote: The prologue is run on every single function executed in a program, so I believe that in the hopes of keeping it as light as possible it never makes any function calls. I do agree though, that it's at tricky situation in that case. How does TLS otherwise work for that platform? On Fri, Apr 25, 2014 at 8:14 AM, Vladimir Pouzanov farcal...@gmail.com wrote: I have a side question related to the same code. Currently __STACK_LIMIT is constant, but I would like the preamble to verify stack overflow for multithreaded context, i.e. __STACK_LIMIT will depend on the current running thread. Is there any reason, why it's not a function? Any objections if I do some refactoring and make it a function? For a simple case that could be a weak symbol that returns a constant. On Tue, Apr 22, 2014 at 9:00 AM, Alex Crichton a...@crichton.co wrote: I agree with Corey, it's much better to send it upstream first. I'd be more than willing to help you out with writing tests or taking a peek at the patch if you want! I'm acrichto on IRC On Tue, Apr 22, 2014 at 12:43 AM, Vladimir Pouzanov farcal...@gmail.com wrote: The problem is that mrc is generated unless target is thumb1, but cortex-m3 is thumb2 that still doesn't support mrc: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka398.html , so an additional check to ST-TargetTriple.Data is required to verify it's not thumbv7m. Do I need to submit patch against https://github.com/rust-lang/llvmor send it to upstream? On Mon, Apr 21, 2014 at 6:34 PM, Vladimir Pouzanov farcal...@gmail.com wrote: Hm, it seems to have precautions to stop mrc from materializing on Thumb1. I guess I need to take a better look into what's going wrong on my side. I'll see what I can do with that. On Mon, Apr 21, 2014 at 5:23 PM, Alex Crichton a...@crichton.co wrote: The split stack patches for ARM were recently upstreamed, and they were modified when being upstreamed as well. Primarily the location of the split stack is no longer at a magic address for thumb, but rather it uses the same instruction as ARM (some thumb processors do indeed have the coprocessor). More information is in the long thread starting at the initial attempt to upstream [1]. For now you'll have to use no_split_stack because the thumb split stack will always use a coprocessor, but I'm sure that the upstream LLVM devs would be quite welcoming to tweaks to the slit-stack support (I'd also be willing to help). You can find the initial commit for support at rust-lang/llvm [2]. [1] - http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20140224/205968.html [2] - https://github.com/rust-lang/llvm/pull/4 On Mon, Apr 21, 2014 at 6:50 AM, Vladimir Pouzanov farcal...@gmail.com wrote: Starting recently (no more than two weeks), rustc is generating a broken prologue for arm. Here's the sample assembly: 0x0f44 +0: push {r4, r5} = 0x0f46 +2: mrc 15, 0, r4, cr13, cr0, {3} 0x0f4a +6: mov r5, sp 0x0f4c +8: b.n 0xa78 main+2616 0x0f4e +10: ands r4, r0 0x0f50 +12: cmp r4, r5 0x0f52 +14: bcc.n 0xf66 _ZN7drivers3lcd6c1233244C12332$LT$$x27a$C$$x20S$C$$x20T$GT$.lcd..LCD5flush20h76589116290686712394v0.0E+34 0x0f54 +16: movs r4, #16 0x0f56 +18: movs r5, #0 0x0f58 +20: push {lr} 0x0f5a +22: bl 0x19d8 __morestack 0x0f5e +26: ldr.w lr, [sp], #4 0x0f62 +30: pop {r4, r5} 0x0f64 +32: bx lr The problem is at 0x0f46, where code tries to read from coprocessor 15 register 13, which is process id register. Well, coprocessor 15 (actually, all of the coprocessors) are missing from my target thumbv7m-linux-eabi (with added flavour of -Ctarget-cpu=cortex-m3, which should be redundant anyway), so I'm getting hardfaults in every function that rust doesn't inline. Any ideas on what might be going wrong? I assume that this is actually llvm's fault, as llvm should not materialize machine code which is not available for target anyway. Wrapping everything in #[no_split_stack] is a temporary workaround and surely not a long-term strategy. -- Sincerely, Vladimir
Re: [rust-dev] A small announcement for zinc, the bare metal rust stack
On Thu, Apr 24, 2014 at 9:01 AM, Ben Gamari bgam...@gmail.com wrote: Unfortunately this replaces the ugly possibility of unpredictable crashes with the slightly less ugly possiblity of unpredictable deadlocks if we run out of stack in the middle of execution. Perhaps threads could be annotated with their maximum expected stack size, allowing stack chunks to be allocated at spawn-time. It wouldn't be allowed to grow, it's exactly that — maximum expected stack size, task either fits in there or dies. -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] A small announcement for zinc, the bare metal rust stack
Luckily enough, I had the concept for zinc even before I started coding in rust :-) And yes, there are lots of different oxides in rust world. On Wed, Apr 23, 2014 at 3:58 AM, Thad Guidry thadgui...@gmail.com wrote: Actually...I do not. :) On Tue, Apr 22, 2014 at 9:05 PM, Chris Morgan m...@chrismorgan.info wrote: On Wed, Apr 23, 2014 at 10:35 AM, Thad Guidry thadgui...@gmail.com wrote: I would have named it ... oxide instead of zinc ;-) ... rust = iron oxide Do you know how many projects written in Rust have already been named “oxide”? -- -Thad +ThadGuidry https://www.google.com/+ThadGuidry Thad on LinkedIn http://www.linkedin.com/in/thadguidry/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] A small announcement for zinc, the bare metal rust stack
There is a number of options on the memory side of things. I feel that stack usage could be estimated a bit more simply with rust and it's __morestack support, so that it would be possible to run a few threads with preemptive scheduling (__morestack also guarantees that no memory corruption would occur due to stack overflow). I'm totally against unmanaged heap support and ~T on embedded, that just doesn't work. It's a very big burden to support that reasonably in existing C/C++ RTOSes out there, so I don't want to spend lots of time trying to solve the same problems. Still, heap is really useful in some cases (as I've figured out while working on 802.15.4 stack for zinc). My current idea is to make dedicated pools that could hold a compile-time configurable number of objects of same size, e.g. an IncomingPacketPool that can hold up to 3 frames where one frame is 128 bytes long. This way no other running process can interfere with code that processes incoming packets and that code can offload incoming packets into the pool for later processing, but up to three, and it will act in user-defined fashion (drop packets) if the pool is full. The implementation of that would be quite simple, and I think that it might be possible to extend ~T ownership for something like that. On Wed, Apr 23, 2014 at 3:47 PM, Ben Gamari bgam...@gmail.com wrote: Vladimir Pouzanov farcal...@gmail.com writes: This is the project I've been tinkering with for a good number of weekends zinc, the bare metal stack for rust is available at https://github.com/hackndev/zinc. I've just finished a major refactoring work for LPC1768 code, so STM32F4 is kind of broken yet, and LPC1114 is totally dropped, but I'll fix that soon. The current code supports GPIO operations, UART and SSP in SPI mode for NXP LPC1768, also featuring a driver for http://mbed.org/cookbook/mbed-application-board TFT LCD and for ILI9341-based TFT LCDs commonly found on ebay. My plan is to fix support for STM32F4, bring it to the level of NXP part and try to expand this to a small RTOS, which would be a nice demo of rust capabilities for embedded development. The code is licensed under Apache-2.0. There's no readme yet, but you can see the demo applications written with zinc here: https://github.com/hackndev/zinc/tree/master/apps. Thanks for the release! I've been looking forward to seeing this ever since your Reddit post a few weeks back as I too have been recently thinking about how Rust might be used in an embedded environment. Lately I've been contributing to the mchck[1] project, its associated library, and a project I've built on top of it[2]. One of the things that I feel the mchck library gets right is the ubiquitous use of asynchronous completion notification (e.g. [3]) instead of polling. In my experience asynchronous code both maps onto hardware more naturally and produces more composable user code. Unfortunately, C makes continuation passing very painful due to the broken up flow of control that results from the sea of callbacks and the boilerplate (e.g. passing and casting of `void*` pointers to structs of intermediate state) necessary for propagation of state between callbacks. As far as I can tell, there are two paths by which Rust might improve this situation. The most straightforward approach would be to implement continuation passing directly by passing around continuation `procs`. While this approach reduces the amount of boilerplate due to state propagation, it does not really resolve the broken flow of control due to explicit continuations. Another approach which addresses this latter issue is to use Rust's native tasks, allowing requests to peripherals to be treated as blocking. While this seems like this could be very convenient, I am a bit concerned that the memory footprint of multiple stacks and associated bookkeeping data structures might be asking too much of the typical MCU (the devices I work with typically have 16kByte of SRAM). This memory footprint issue is especially concerning due to Rust's[4] heavy dependence on stack allocation. I am very much accustomed to avoiding dynamic allocation at all costs on embedded platforms; I appreciate knowing at compile time whether my program will fit on my device (up to stack allocations, which in my C code are intentionally minimal). With the uncertainty of dynamic allocation against the stack and dynamic task creation, it seems one literally has no idea whether a program will fit without either static analysis, simulation, or trial on real hardware. However, it seems that one loses a great deal by reverting to static allocation in Rust (e.g. losing safety of ownership, memory model becomes burdensome), so perhaps dynamic allocation coupled with robust allocation analysis tools is a reasonable trade-off. I'd be very interested to hear what others have to say about these issues. Cheers, - Ben [1] http
Re: [rust-dev] morestack prologue contains broken machine code
The problem is that mrc is generated unless target is thumb1, but cortex-m3 is thumb2 that still doesn't support mrc: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka398.html, so an additional check to ST-TargetTriple.Data is required to verify it's not thumbv7m. Do I need to submit patch against https://github.com/rust-lang/llvm or send it to upstream? On Mon, Apr 21, 2014 at 6:34 PM, Vladimir Pouzanov farcal...@gmail.comwrote: Hm, it seems to have precautions to stop mrc from materializing on Thumb1. I guess I need to take a better look into what's going wrong on my side. I'll see what I can do with that. On Mon, Apr 21, 2014 at 5:23 PM, Alex Crichton a...@crichton.co wrote: The split stack patches for ARM were recently upstreamed, and they were modified when being upstreamed as well. Primarily the location of the split stack is no longer at a magic address for thumb, but rather it uses the same instruction as ARM (some thumb processors do indeed have the coprocessor). More information is in the long thread starting at the initial attempt to upstream [1]. For now you'll have to use no_split_stack because the thumb split stack will always use a coprocessor, but I'm sure that the upstream LLVM devs would be quite welcoming to tweaks to the slit-stack support (I'd also be willing to help). You can find the initial commit for support at rust-lang/llvm [2]. [1] - http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20140224/205968.html [2] - https://github.com/rust-lang/llvm/pull/4 On Mon, Apr 21, 2014 at 6:50 AM, Vladimir Pouzanov farcal...@gmail.com wrote: Starting recently (no more than two weeks), rustc is generating a broken prologue for arm. Here's the sample assembly: 0x0f44 +0: push {r4, r5} = 0x0f46 +2: mrc 15, 0, r4, cr13, cr0, {3} 0x0f4a +6: mov r5, sp 0x0f4c +8: b.n 0xa78 main+2616 0x0f4e +10: ands r4, r0 0x0f50 +12: cmp r4, r5 0x0f52 +14: bcc.n 0xf66 _ZN7drivers3lcd6c1233244C12332$LT$$x27a$C$$x20S$C$$x20T$GT$.lcd..LCD5flush20h76589116290686712394v0.0E+34 0x0f54 +16: movs r4, #16 0x0f56 +18: movs r5, #0 0x0f58 +20: push {lr} 0x0f5a +22: bl 0x19d8 __morestack 0x0f5e +26: ldr.w lr, [sp], #4 0x0f62 +30: pop {r4, r5} 0x0f64 +32: bx lr The problem is at 0x0f46, where code tries to read from coprocessor 15 register 13, which is process id register. Well, coprocessor 15 (actually, all of the coprocessors) are missing from my target thumbv7m-linux-eabi (with added flavour of -Ctarget-cpu=cortex-m3, which should be redundant anyway), so I'm getting hardfaults in every function that rust doesn't inline. Any ideas on what might be going wrong? I assume that this is actually llvm's fault, as llvm should not materialize machine code which is not available for target anyway. Wrapping everything in #[no_split_stack] is a temporary workaround and surely not a long-term strategy. -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] A small announcement for zinc, the bare metal rust stack
This is the project I've been tinkering with for a good number of weekends — zinc, the bare metal stack for rust is available at https://github.com/hackndev/zinc. I've just finished a major refactoring work for LPC1768 code, so STM32F4 is kind of broken yet, and LPC1114 is totally dropped, but I'll fix that soon. The current code supports GPIO operations, UART and SSP in SPI mode for NXP LPC1768, also featuring a driver for http://mbed.org/cookbook/mbed-application-board TFT LCD and for ILI9341-based TFT LCDs commonly found on ebay. My plan is to fix support for STM32F4, bring it to the level of NXP part and try to expand this to a small RTOS, which would be a nice demo of rust capabilities for embedded development. The code is licensed under Apache-2.0. There's no readme yet, but you can see the demo applications written with zinc here: https://github.com/hackndev/zinc/tree/master/apps. -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] morestack prologue contains broken machine code
Starting recently (no more than two weeks), rustc is generating a broken prologue for arm. Here's the sample assembly: 0x0f44 +0: push {r4, r5} = 0x0f46 +2: mrc 15, 0, r4, cr13, cr0, {3} 0x0f4a +6: mov r5, sp 0x0f4c +8: b.n 0xa78 main+2616 0x0f4e +10: ands r4, r0 0x0f50 +12: cmp r4, r5 0x0f52 +14: bcc.n 0xf66 _ZN7drivers3lcd6c1233244C12332$LT$$x27a$C$$x20S$C$$x20T$GT$.lcd..LCD5flush20h76589116290686712394v0.0E+34 0x0f54 +16: movs r4, #16 0x0f56 +18: movs r5, #0 0x0f58 +20: push {lr} 0x0f5a +22: bl 0x19d8 __morestack 0x0f5e +26: ldr.w lr, [sp], #4 0x0f62 +30: pop {r4, r5} 0x0f64 +32: bx lr The problem is at 0x0f46, where code tries to read from coprocessor 15 register 13, which is process id register. Well, coprocessor 15 (actually, all of the coprocessors) are missing from my target thumbv7m-linux-eabi (with added flavour of -Ctarget-cpu=cortex-m3, which should be redundant anyway), so I'm getting hardfaults in every function that rust doesn't inline. Any ideas on what might be going wrong? I assume that this is actually llvm's fault, as llvm should not materialize machine code which is not available for target anyway. Wrapping everything in #[no_split_stack] is a temporary workaround and surely not a long-term strategy. -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] morestack prologue contains broken machine code
Hm, it seems to have precautions to stop mrc from materializing on Thumb1. I guess I need to take a better look into what's going wrong on my side. I'll see what I can do with that. On Mon, Apr 21, 2014 at 5:23 PM, Alex Crichton a...@crichton.co wrote: The split stack patches for ARM were recently upstreamed, and they were modified when being upstreamed as well. Primarily the location of the split stack is no longer at a magic address for thumb, but rather it uses the same instruction as ARM (some thumb processors do indeed have the coprocessor). More information is in the long thread starting at the initial attempt to upstream [1]. For now you'll have to use no_split_stack because the thumb split stack will always use a coprocessor, but I'm sure that the upstream LLVM devs would be quite welcoming to tweaks to the slit-stack support (I'd also be willing to help). You can find the initial commit for support at rust-lang/llvm [2]. [1] - http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20140224/205968.html [2] - https://github.com/rust-lang/llvm/pull/4 On Mon, Apr 21, 2014 at 6:50 AM, Vladimir Pouzanov farcal...@gmail.com wrote: Starting recently (no more than two weeks), rustc is generating a broken prologue for arm. Here's the sample assembly: 0x0f44 +0: push {r4, r5} = 0x0f46 +2: mrc 15, 0, r4, cr13, cr0, {3} 0x0f4a +6: mov r5, sp 0x0f4c +8: b.n 0xa78 main+2616 0x0f4e +10: ands r4, r0 0x0f50 +12: cmp r4, r5 0x0f52 +14: bcc.n 0xf66 _ZN7drivers3lcd6c1233244C12332$LT$$x27a$C$$x20S$C$$x20T$GT$.lcd..LCD5flush20h76589116290686712394v0.0E+34 0x0f54 +16: movs r4, #16 0x0f56 +18: movs r5, #0 0x0f58 +20: push {lr} 0x0f5a +22: bl 0x19d8 __morestack 0x0f5e +26: ldr.w lr, [sp], #4 0x0f62 +30: pop {r4, r5} 0x0f64 +32: bx lr The problem is at 0x0f46, where code tries to read from coprocessor 15 register 13, which is process id register. Well, coprocessor 15 (actually, all of the coprocessors) are missing from my target thumbv7m-linux-eabi (with added flavour of -Ctarget-cpu=cortex-m3, which should be redundant anyway), so I'm getting hardfaults in every function that rust doesn't inline. Any ideas on what might be going wrong? I assume that this is actually llvm's fault, as llvm should not materialize machine code which is not available for target anyway. Wrapping everything in #[no_split_stack] is a temporary workaround and surely not a long-term strategy. -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] LLVM doesn't inline my static, any good reason for that?
I'm working on a proof-of-concept implementation for https://github.com/rust-lang/rfcs/pull/44 [Linker placement attribute], and I actually got code that is working, but the outcome is worse than I expected. Consider the following snippet: #[unsafe_override_address] static Tinst : T = 1000; What it is expected to do is to create a '1000 as *T' with the semantics of T (the reasons for that are in RFC). My patch actually works as expected in this regard, I evaluate the expr as uint, and store a LLVMConstIntToPtr made from that uint in ccx.const_values. The results in the following IR: @Tinst = internal constant %struct.T* inttoptr (i32 1000 to %struct.T*) The problem is that llvm never inlines the constant (even with #[address_insignificant]), so instead of making the binary smaller as llvm can optimize integer addresses better (as it knows them) it makes the binary bigger, as it takes 4 bytes to store address value in .rodata, and two instructions to fetch it. Any ideas on what I could be missing? -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] LLVM doesn't inline my static, any good reason for that?
Apparently I had a problem of double pointer. The solution was to use static Tinst : 'static T = 1000; though I have modified the code now so that T works as well. On Sun, Apr 20, 2014 at 2:04 PM, György Andrasek jur...@gmail.com wrote: On Sun, Apr 20, 2014 at 10:46 AM, Vladimir Pouzanov farcal...@gmail.com wrote: The results in the following IR: @Tinst = internal constant %struct.T* inttoptr (i32 1000 to %struct.T*) The problem is that llvm never inlines the constant (even with #[address_insignificant]), so instead of making the binary smaller as llvm can optimize integer addresses better (as it knows them) it makes the binary bigger, as it takes 4 bytes to store address value in .rodata, and two instructions to fetch it. Does it show up in the asm after optimizations? After LTO? -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Convincing compiler that *T is safe
Well, the Dev as a pointer would be immutable in terms of that you can't change its address, and all access to fields is done via getter/setter methods using volatiles. It seems that I cannot use transmute in a context of static though and I can't trade runtime size over better syntax. On Mon, Apr 14, 2014 at 10:19 AM, Huon Wilson dbau...@gmail.com wrote: On 14/04/14 06:12, Vladimir Pouzanov wrote: I have a number of I/O mapped registers that look like: struct Dev { .. // u32 fields } pub static Dev0 : *mut Dev = 0xsomeaddr as *mut Dev; with macro-generated getters and setters: pub fn $getter_name(self) - u32 { unsafe { volatile_load((self.$reg)) } } unfortunately, calling a getter is calling a method on *Reg, which is unsafe and looks like: unsafe { (*Dev0).SOME_REG() }; is there any way to simplify the syntax, hopefully to simple Dev0.SOME_REG()? I'm ok with any unsafe tricks including transmuting it to Dev (that doesn't seem to be possible though), as the getter/setter methods are always safe in this scenario. -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing listRust-dev@mozilla.orghttps://mail.mozilla.org/listinfo/rust-dev The compiler cannot verify that these method calls are safe, so they `unsafe`'s are asserting trust me compiler, I know more than you. You could write a macro like `get!(Dev0, SOME_REG)` that expanded to the `unsafe { (*Dev0).SOME_REG() }` invocation. But... I don't understand why transmuting to Dev wouldn't be possible. I'd strongly recommend the weaker version `unsafe { *Dev0 }`, to go from *mut Dev to Dev0. However, this likely breaks the guarantees of , since the data to which they point is supposed to be immutable, but being I/O mapped registers it would imply that external events can change the values. (I guess this is where Flavio's suggestion of storing a *UnsafeDev comes into play, but this still leaves you dealing with an *mut pointer to get at the data, at the end of the day.) Huon ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] Convincing compiler that *T is safe
I have a number of I/O mapped registers that look like: struct Dev { .. // u32 fields } pub static Dev0 : *mut Dev = 0xsomeaddr as *mut Dev; with macro-generated getters and setters: pub fn $getter_name(self) - u32 { unsafe { volatile_load((self.$reg)) } } unfortunately, calling a getter is calling a method on *Reg, which is unsafe and looks like: unsafe { (*Dev0).SOME_REG() }; is there any way to simplify the syntax, hopefully to simple Dev0.SOME_REG()? I'm ok with any unsafe tricks including transmuting it to Dev (that doesn't seem to be possible though), as the getter/setter methods are always safe in this scenario. -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] matching on a few bits in int
Awesome use of unreachable! On Tue, Apr 8, 2014 at 4:53 PM, Peter Marheine pe...@taricorp.net wrote: I had a go at building a macro to do this sort of thing, and it turned out to be easier than I expected. https://gist.github.com/tari/10144385 Use like this: let x = match_bitfield!(do_something(), bits 4 to 8 { 0 = DivideBy1, 1 = DivideBy2, 2 = DivideBy4, _ = UnknownDivisor }; On Fri, Apr 4, 2014 at 7:11 AM, Vladimir Pouzanov farcal...@gmail.com wrote: I've submitted an RFC for this one: https://github.com/rust-lang/rfcs/pull/29 On Sat, Mar 29, 2014 at 6:14 PM, Bill Myers bill_my...@outlook.com wrote: I think the best solution is to add uN and sN types where N is not a power of two, which LLVM should already support. Then you can write your match like this: match (val 6) as u2 { ... } And it will work as desired. Biggest issue is that to make it work nicely you'd need to add some way to generalize over the bit-length and integers, and that's going to require generics with int parameters and work to add those. -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Peter Marheine Don't Panic -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Porting some nesC features to rust?
I might have found an unsupported case. Consider the following: trait SPI { ... } struct McuSPI; impl SPI for McuSPI { ... } struct LCD { spi: SPI, ... } This code results in a dynamic dispatch to SPI, as trait bounds are not allowed in structure definitions. Is it in any way possible to use static dispatch from LCD to SPI given the exact implementations are known at compile time? On Thu, Apr 3, 2014 at 2:46 AM, Ashish Myles marci...@gmail.com wrote: And just in case there is a confusion (as I have noticed others to have), it might help to see a specific example comparing static dispatch with dynamic. // This is a single function for all types implementing the LCD Trait. fn foo(x : LCD) { // x's type is LCD rather than the actual type of the object being passed in x.line(); // dynamic dispatch } // Like C++ templates, this generates a function for each type T that implements LCD. fn fooT : LCD(x : T) { // x's type is T rather than LCD x.line(); // static dispatch based on type T known at compile-time } On Wed, Apr 2, 2014 at 8:32 AM, Daniel Micay danielmi...@gmail.com wrote: On 02/04/14 06:25 AM, Vladimir Pouzanov wrote: If I get it right, calls to traits are resolved in runtime (so, traits are kind of similar to C++ virtual methods). All method calls on regular types are resolved via static dispatch, whether or not they come from a trait. For example, consider a generic function like the following: fn minT: TotalOrd(a: T, b: T) - T { if a b { a } else { b } } This function performs a *static* call of the `lt` method defined on the `Ord` trait that `TotalOrd` inherits from. Generics are fully expanded at compile-time just as C++ templates are. Rust also allows using traits as boxed objects, but this is an entirely transparent choice. They're almost always used for static dispatch via trait bounds on generics, or simply outside of generics. What I'm proposing here is a compile-time approach. Let's say we have the following trait: pub trait LCD { fn line(mut self, x0_b: i32, y0_b: i32, x1: i32, y1: i32, color: u8); fn rect(mut self, x0: i32, y0: i32, x1: i32, y1: i32, color: u8); fn fillrect(mut self, x0_b: i32, y0_b: i32, x1_b: i32, y1_b: i32, color: u8); fn putc(mut self, value: char); fn puts(mut self, s: str); fn flush(self); fn clear(mut self); } which defined a LED screen. There are two structs implementing it: C12832 and ILI9341 (two different lcd controllers). So I want my app to print hello world on lcd, I write the following code: let mut lcd = lcd_c12832::C12832::new(spi); let mut l: mut lcd::LCD = lcd as mut lcd::LCD; l.puts(hello, world); Which results in a runtime dispatch, a slower and bigger code than the one I'd have without a trait. You can call methods defined on a trait without boxing the object as a trait object. The ability to perform dynamic dispatch via a trait object is totally optional. The methods can also be called directly, including inside a generic function by specifying the trait as a type parameter bound. You can simply call the `puts` method directly on the `lcd` object without a cast. A second problem is there is no easy way to write unified code that supports both the lcds based on passed in --cfg, as I can't apply #[cfg(lcd_c12832)] to a chunk of code in fn, and it's kind of problematic to return a LCD out from it given that there is no heap and no analog of placement new from C++. Rust supports generic functions, and you can write code supporting both types by making it generic. The choice between static dispatch and dynamic dispatch is entirely up to you in the current system. Proposed binding concept solves those two problems: #[cfg(lcd_c12832)] let Binding: binding { let lcd: lcd_c12832::C12832; let main: Main; bind main.lcd = lcd; } at this point of time compiler can be sure about what struct is implementing LCD trait for main.lcd and can bind the function bodies as compile time, inlining them if applicable. This also might be something that is already implemented, please advice. The goal here is to minimise runtime code being executed and its size. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Porting some nesC features to rust?
That actually worked much better than I expected inlining everything and getting rid of vtables (I don't have support for .data section at the moment :-) ). I can't say the syntax is very clear to me, but I can get used to it. Still, one more question remains. I have a debug output concept, which means that debug::d(str) gets delivered to either LCD or UART, whatever is configured at runtime. I do it via static mut: pub trait Debugger { fn debugs(mut self, s: str); } pub static mut debug_output: *mut c12332::C12332'static, 'static spi::SPI = unsafe { init() }; pub fn d(s: str) { let debugger = unsafe { mut (*debug_output) as mut Debugger }; // failed to find an implementation of trait hal::spi::SPI for 'static hal::spi::SPI:'static debugger.debugs(s); } pub fn set_debugger(lcd: *mut c12332::C12332spi::SPI) { unsafe { debug_output = lcd; }; } I don't really support UART now, but I'd still like to access my LCD via a globally known static getter. How can I re-write that with typed struct? On Tue, Apr 8, 2014 at 6:26 PM, Corey Richardson co...@octayn.net wrote: You don't use bounds in the struct, you put them in the impl. So you would instead say struct LCDS { spi: S, ... } and then: implS: SPI LCDS { ... } On Tue, Apr 8, 2014 at 1:23 PM, Vladimir Pouzanov farcal...@gmail.com wrote: I might have found an unsupported case. Consider the following: trait SPI { ... } struct McuSPI; impl SPI for McuSPI { ... } struct LCD { spi: SPI, ... } This code results in a dynamic dispatch to SPI, as trait bounds are not allowed in structure definitions. Is it in any way possible to use static dispatch from LCD to SPI given the exact implementations are known at compile time? On Thu, Apr 3, 2014 at 2:46 AM, Ashish Myles marci...@gmail.com wrote: And just in case there is a confusion (as I have noticed others to have), it might help to see a specific example comparing static dispatch with dynamic. // This is a single function for all types implementing the LCD Trait. fn foo(x : LCD) { // x's type is LCD rather than the actual type of the object being passed in x.line(); // dynamic dispatch } // Like C++ templates, this generates a function for each type T that implements LCD. fn fooT : LCD(x : T) { // x's type is T rather than LCD x.line(); // static dispatch based on type T known at compile-time } On Wed, Apr 2, 2014 at 8:32 AM, Daniel Micay danielmi...@gmail.com wrote: On 02/04/14 06:25 AM, Vladimir Pouzanov wrote: If I get it right, calls to traits are resolved in runtime (so, traits are kind of similar to C++ virtual methods). All method calls on regular types are resolved via static dispatch, whether or not they come from a trait. For example, consider a generic function like the following: fn minT: TotalOrd(a: T, b: T) - T { if a b { a } else { b } } This function performs a *static* call of the `lt` method defined on the `Ord` trait that `TotalOrd` inherits from. Generics are fully expanded at compile-time just as C++ templates are. Rust also allows using traits as boxed objects, but this is an entirely transparent choice. They're almost always used for static dispatch via trait bounds on generics, or simply outside of generics. What I'm proposing here is a compile-time approach. Let's say we have the following trait: pub trait LCD { fn line(mut self, x0_b: i32, y0_b: i32, x1: i32, y1: i32, color: u8); fn rect(mut self, x0: i32, y0: i32, x1: i32, y1: i32, color: u8); fn fillrect(mut self, x0_b: i32, y0_b: i32, x1_b: i32, y1_b: i32, color: u8); fn putc(mut self, value: char); fn puts(mut self, s: str); fn flush(self); fn clear(mut self); } which defined a LED screen. There are two structs implementing it: C12832 and ILI9341 (two different lcd controllers). So I want my app to print hello world on lcd, I write the following code: let mut lcd = lcd_c12832::C12832::new(spi); let mut l: mut lcd::LCD = lcd as mut lcd::LCD; l.puts(hello, world); Which results in a runtime dispatch, a slower and bigger code than the one I'd have without a trait. You can call methods defined on a trait without boxing the object as a trait object. The ability to perform dynamic dispatch via a trait object is totally optional. The methods can also be called directly, including inside a generic function by specifying the trait as a type parameter bound. You can simply call the `puts` method directly on the `lcd` object without a cast. A second problem is there is no easy way to write unified code that supports both the lcds based on passed in --cfg, as I can't apply #[cfg(lcd_c12832)] to a chunk of code in fn, and it's kind of problematic to return a LCD out from it given
Re: [rust-dev] Porting some nesC features to rust?
Yes, in the end I decided to implement .data section copy over from flash to ram to get vtables :-) On Tue, Apr 8, 2014 at 7:34 PM, Corey Richardson co...@octayn.net wrote: `'static SPI` is going to be a trait object (with dynamic dispatch). The error it's giving is that `SPI` (the trait object) doesn't implement `SPI` (the trait). You would have to explicitly implement `SPI` for `SPI`. I'm not really sure how to solve this without using trait objects; you seem to want an inherently dynamically-dispatched system. On Tue, Apr 8, 2014 at 2:08 PM, Vladimir Pouzanov farcal...@gmail.com wrote: That actually worked much better than I expected inlining everything and getting rid of vtables (I don't have support for .data section at the moment :-) ). I can't say the syntax is very clear to me, but I can get used to it. Still, one more question remains. I have a debug output concept, which means that debug::d(str) gets delivered to either LCD or UART, whatever is configured at runtime. I do it via static mut: pub trait Debugger { fn debugs(mut self, s: str); } pub static mut debug_output: *mut c12332::C12332'static, 'static spi::SPI = unsafe { init() }; pub fn d(s: str) { let debugger = unsafe { mut (*debug_output) as mut Debugger }; // failed to find an implementation of trait hal::spi::SPI for 'static hal::spi::SPI:'static debugger.debugs(s); } pub fn set_debugger(lcd: *mut c12332::C12332spi::SPI) { unsafe { debug_output = lcd; }; } I don't really support UART now, but I'd still like to access my LCD via a globally known static getter. How can I re-write that with typed struct? On Tue, Apr 8, 2014 at 6:26 PM, Corey Richardson co...@octayn.net wrote: You don't use bounds in the struct, you put them in the impl. So you would instead say struct LCDS { spi: S, ... } and then: implS: SPI LCDS { ... } On Tue, Apr 8, 2014 at 1:23 PM, Vladimir Pouzanov farcal...@gmail.com wrote: I might have found an unsupported case. Consider the following: trait SPI { ... } struct McuSPI; impl SPI for McuSPI { ... } struct LCD { spi: SPI, ... } This code results in a dynamic dispatch to SPI, as trait bounds are not allowed in structure definitions. Is it in any way possible to use static dispatch from LCD to SPI given the exact implementations are known at compile time? On Thu, Apr 3, 2014 at 2:46 AM, Ashish Myles marci...@gmail.com wrote: And just in case there is a confusion (as I have noticed others to have), it might help to see a specific example comparing static dispatch with dynamic. // This is a single function for all types implementing the LCD Trait. fn foo(x : LCD) { // x's type is LCD rather than the actual type of the object being passed in x.line(); // dynamic dispatch } // Like C++ templates, this generates a function for each type T that implements LCD. fn fooT : LCD(x : T) { // x's type is T rather than LCD x.line(); // static dispatch based on type T known at compile-time } On Wed, Apr 2, 2014 at 8:32 AM, Daniel Micay danielmi...@gmail.com wrote: On 02/04/14 06:25 AM, Vladimir Pouzanov wrote: If I get it right, calls to traits are resolved in runtime (so, traits are kind of similar to C++ virtual methods). All method calls on regular types are resolved via static dispatch, whether or not they come from a trait. For example, consider a generic function like the following: fn minT: TotalOrd(a: T, b: T) - T { if a b { a } else { b } } This function performs a *static* call of the `lt` method defined on the `Ord` trait that `TotalOrd` inherits from. Generics are fully expanded at compile-time just as C++ templates are. Rust also allows using traits as boxed objects, but this is an entirely transparent choice. They're almost always used for static dispatch via trait bounds on generics, or simply outside of generics. What I'm proposing here is a compile-time approach. Let's say we have the following trait: pub trait LCD { fn line(mut self, x0_b: i32, y0_b: i32, x1: i32, y1: i32, color: u8); fn rect(mut self, x0: i32, y0: i32, x1: i32, y1: i32, color: u8); fn fillrect(mut self, x0_b: i32, y0_b: i32, x1_b: i32, y1_b: i32, color: u8); fn putc(mut self, value: char); fn puts(mut self, s: str); fn flush(self); fn clear(mut self); } which defined a LED screen. There are two structs implementing it: C12832 and ILI9341 (two different lcd controllers). So I want my app to print hello world on lcd, I write the following code: let mut lcd = lcd_c12832::C12832::new(spi); let mut l: mut lcd::LCD = lcd as mut lcd
Re: [rust-dev] Building a static array of pointers
Ended up specifying array size as per Simon's suggestion: #[link_section=.isr_vector_temp] #[no_mangle] pub static ISRVectors: [extern unsafe fn(), ..4] = [ _stack_base, main, isr_nmi, isr_hardfault, ]; Given that table size is an architecture-dependent time constant, it also adds a tiny bit of verification that all ISRs are defined. Also tried defining something along the lines of *[extern unsafe fn()], but I guess size is also required in this case. Thanks all! On Sat, Apr 5, 2014 at 12:00 PM, Corey Richardson co...@octayn.net wrote: A C-style array is written `*T`, much like in C (note: I'm not saying `T*` and `T[]` are the same type, I know they aren't) On Sat, Apr 5, 2014 at 6:53 AM, Simon Sapin simon.sa...@exyr.org wrote: On 05/04/2014 11:39, Vladimir Pouzanov wrote: The problem is that [extern unsafe fn()] results in 8 bytes, pointer to the actual array and its size. Is there any way I can get a plain C-style array in rust? If the size is known as compile-time you can use: static table: [extern unsafe fn(), ..2] = [foo, bar]; -- Simon Sapin ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- http://octayn.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] matching on a few bits in int
I've submitted an RFC for this one: https://github.com/rust-lang/rfcs/pull/29 On Sat, Mar 29, 2014 at 6:14 PM, Bill Myers bill_my...@outlook.com wrote: I think the best solution is to add uN and sN types where N is not a power of two, which LLVM should already support. Then you can write your match like this: match (val 6) as u2 { ... } And it will work as desired. Biggest issue is that to make it work nicely you'd need to add some way to generalize over the bit-length and integers, and that's going to require generics with int parameters and work to add those. -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] Building a static array of pointers
Is it possible to port the following C code to rust? __attribute__ ((section(.isr_vector))) void (* const isr_vector_table[])(void) = { _stack_base, main, // Reset isr_nmi, // NMI isr_hardfault,// Hard Fault 0,// CM3 Memory Management Fault 0,// CM3 Bus Fault 0,// CM3 Usage Fault _boot_checksum, // NXP Checksum code 0,// Reserved 0,// Reserved 0,// Reserved isr_svcall, // SVCall 0,// Reserved for debug 0,// Reserved isr_pendsv, // PendSV isr_systick, // SysTick }; here main and isr_* are rust external functions, and _stack_base is defined as extern void _stack_base() and gets loaded from linker script. Also, is it possible to make a weak symbol in rust or somehow emulate it? Weak symbols are used in C code to provide the following functionality: isr_* functions are stubs with default implementation (morse out id code with led, loop forever), but if any of those requires actual code, than it is overrides the weak morse-blinking function symbol. -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Porting some nesC features to rust?
If I get it right, calls to traits are resolved in runtime (so, traits are kind of similar to C++ virtual methods). What I'm proposing here is a compile-time approach. Let's say we have the following trait: pub trait LCD { fn line(mut self, x0_b: i32, y0_b: i32, x1: i32, y1: i32, color: u8); fn rect(mut self, x0: i32, y0: i32, x1: i32, y1: i32, color: u8); fn fillrect(mut self, x0_b: i32, y0_b: i32, x1_b: i32, y1_b: i32, color: u8); fn putc(mut self, value: char); fn puts(mut self, s: str); fn flush(self); fn clear(mut self); } which defined a LED screen. There are two structs implementing it: C12832 and ILI9341 (two different lcd controllers). So I want my app to print hello world on lcd, I write the following code: let mut lcd = lcd_c12832::C12832::new(spi); let mut l: mut lcd::LCD = lcd as mut lcd::LCD; l.puts(hello, world); Which results in a runtime dispatch, a slower and bigger code than the one I'd have without a trait. A second problem is there is no easy way to write unified code that supports both the lcds based on passed in --cfg, as I can't apply #[cfg(lcd_c12832)] to a chunk of code in fn, and it's kind of problematic to return a LCD out from it given that there is no heap and no analog of placement new from C++. Proposed binding concept solves those two problems: #[cfg(lcd_c12832)] let Binding: binding { let lcd: lcd_c12832::C12832; let main: Main; bind main.lcd = lcd; } at this point of time compiler can be sure about what struct is implementing LCD trait for main.lcd and can bind the function bodies as compile time, inlining them if applicable. This also might be something that is already implemented, please advice. The goal here is to minimise runtime code being executed and its size. On Mon, Mar 31, 2014 at 3:06 PM, Daniel Micay danielmi...@gmail.com wrote: I'm not really sure exactly what it being proposed here. Rust's generic types and functions are already entirely expanded at compile-time. You *can* use traits as objects for dynamic dispatch, but it's not how they're used in the vast majority of cases. -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] A new better way to build rust apps
I decided to switch away from Rakefiles (after I switched to them from Makefiles) and make a dependency generator / build system in rust to get 20% more coolness factor. Here's a sample config file: https://gist.github.com/farcaller/4c08908fe526e0631989. As you can see, the syntax is somewhat similar to rust code itself, with a few interesting bits like ~ sigil resolving to 'build' dir and @ sigil resolving to 'src' dir, so you can use relative paths safely (Rustfiles are all about safety, you know). It also supports named chainable configurations, so that you can define all the possible build options in one single file, generics (for rules expansion) and a background daemon that looks for files being modified in @ scope to make compilation even faster. TL;DR: Happy April fools' day :-) -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Static_assert on a hash
That actually sounds like a good option, thanks! On Sun, Mar 30, 2014 at 11:22 PM, comex com...@gmail.com wrote: On Sun, Mar 30, 2014 at 8:08 AM, Vladimir Pouzanov farcal...@gmail.com wrote: gpio::Pin::new(0, 15, gpio::Out, gpio::UART1_TXD); // p13 - TXD compiles, but something like gpio::Pin::new(0, 15, gpio::Out, gpio::SPI_MISO); // p13 - TXD would fail, because there's no SPI_MISO defined for port 0 pin 15. I would have each port/pin combination be a separate function or object which takes an appropriate enum as an argument for the function, maybe fn new_port0_pin15(func: Port0Pin15Func) or set up objects so that port0.pin15.init(...) works. You could use a macro to define these more easily. If you really want to write '(0, 15', you could use a macro to turn that into the preceding, but I wouldn't. -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] Porting some nesC features to rust?
I'd like to propose to extend the language with some concepts from nesC, which is a nice but quite unknown C superset outside of TinyOS world. The concept would allow better static polymorphism and better code optimisations and is loosely based on nesC modules/components. It might be possible to implement the same in rust without extending the syntax and compiler, please tell me if that's the case. unbound struct S { reg: u32, comp: ~T, } defines a struct that has a u32 value and some trait. Those values could be used in S impls as usual. It is impossible to create an instance of S, the only way to get it is to bind it in compile time: let Binding: binding { let SImpl: S; let TImpl: T; bind SImpl.reg = 0x12345678; bind SImpl.comp = TImpl; } The result of this is that all references to reg and comp are replaced by actual values (TImpl must obviously be an unbound struct as well), so that the whole SImpl could be optimised away and don't use any storage bytes other than required by constants. Why is it useful? Embedded systems are commonly represented as a tree of components hooked up to one another. Also, resources on embedded are used to be expensive. This code allows to define a configuration of a system which is completely resolved in compile time, allowing better optimisation of the code while maintaining readable code. Some close-to-real-life example: unbound struct Led; impl Led { pub fn set_enabled(self, enabled: bool) { // set the led state } } trait Callable { fn callback(self); } unbound struct Timer { actor: ~Callable, } impl Timer { pub fn start(self) { // init the timer, hardware will call fired() via ISR } fn fired(self) { actor.callback(); } } unbound struct Blinker { mut state: bool, led: Led, timer: Timer, } impl Callable for Blinker { fn callback(self) { self.state != self.state; led.set_enabled(self.state); } } impl Blinker { pub fn main(self) { self.timer.start(); } } let Binding: binding { let timer = Timer; let led = Led; let blinker = Blinker { state: false }; // we can also set the mut property here. This one is static mut by nature, but available only in Blinker impl. bind timer.actor = blinker; bind blinker.timer = timer; bind blinker.led = led; } pub fn main() { Binding.blinker.start(); } -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Static_assert on a hash
That shifts the issue even more into runtime, doesn't it? My goal is to find a way to resolve a tuple of (u8, u8, FuncNameEnum) to u8, where FuncNameEnum is a long enum of all possible functions. And I need to do that in compile time. One way I see that is to make a really long list of enums like: PORT0_PIN0_GPIO, PORT0_PIN0_RD1, ... for all possible port/pin/function combinations, then I can make a macro to match on that to port/pin/fun u8 (that are actually used to configure registers). The only thing is that I'd like to pass port and pin in as u8 values, that makes it much more readable. Well... Maybe it's time to do some big macro for matching all the stuff and hope that compiler will optimise it anyway. On Sun, Mar 30, 2014 at 10:12 AM, Simon Sapin simon.sa...@exyr.org wrote: On 30/03/2014 09:50, Vladimir Pouzanov wrote: I have a chunk of code that toggles different functions on hardware pins, that looks like this: enum Function { GPIO = 0, F1 = 1, F2 = 2, F3 = 3, } fn set_mode(port: u8, pin: u8, fun: Function) What I would like to have is an enum of human-readable values instead of F1/F2/F3 [...] let fun_idx: u8 = FUNCTIONS[port][pin][fun] I don’t know if you can directly access the static strings for the variants’ names behind this, but you can use #[deriving(Show)] to get a string representation of any enum value: For example: #[deriving(Show)] enum Function { GPIO = 0, F1 = 1, F2 = 2, F3 = 3, } fn main() { let f = GPIO; println!({:?}, f) let s: ~str = format!({:?}, f); println!({}, s) } Output: GPIO GPIO -- Simon Sapin ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Static_assert on a hash
Ok, so I have a number of hardware pins which are defined by port+pin numbers. Each pin can be connected to different peripheral (e.g. generic purpose i/o, serial, analog in) which defines it's function. So, to configure that I have a few u32 registers where each pair of bits defines a function for a pin, so my configuration function is: fn set_mode(port: u8, pin: u8, fun: Function) You pass in port, pin and it's function, and i/o is being reconfigured appropriately. What I have now is this enum: enum Function { GPIO = 0, F1 = 1, F2 = 2, F3 = 3, } which defines pin's function (function 0 is always GPIO on all the pins, functions 1-3 are different based on the pin). Now, in some peripheral init code I write something like: gpio::Pin::new(0, 15, gpio::Out, gpio::F1); // p13 - TXD and I know that function 1 on port 0 pin 15 is TXD for UART1. I could have misread the docs and write F2, which would compile, but the code wouldn't configure the UART pin but do something else, so I want the compiler to check code for me so that gpio::Pin::new(0, 15, gpio::Out, gpio::UART1_TXD); // p13 - TXD compiles, but something like gpio::Pin::new(0, 15, gpio::Out, gpio::SPI_MISO); // p13 - TXD would fail, because there's no SPI_MISO defined for port 0 pin 15. On Sun, Mar 30, 2014 at 11:41 AM, Simon Sapin simon.sa...@exyr.org wrote: On 30/03/2014 10:30, Vladimir Pouzanov wrote: That shifts the issue even more into runtime, doesn't it? My goal is to find a way to resolve a tuple of (u8, u8, FuncNameEnum) to u8, where FuncNameEnum is a long enum of all possible functions. And I need to do that in compile time. One way I see that is to make a really long list of enums like: PORT0_PIN0_GPIO, PORT0_PIN0_RD1, ... for all possible port/pin/function combinations, then I can make a macro to match on that to port/pin/fun u8 (that are actually used to configure registers). The only thing is that I'd like to pass port and pin in as u8 values, that makes it much more readable. Well... Maybe it's time to do some big macro for matching all the stuff and hope that compiler will optimise it anyway. I’m sorry, it looks like I completely misunderstood your original message. But then it’s still not clear to me what you’re trying to do. Could you explain in more details, with more context? For example, what is it you call a function? It seems not to be Rust function declared with the `fn` keyword. -- Simon Sapin -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] matching on a few bits in int
There's one thing that I often have to deal in embedded code — doing match on a few bits from an I/O register, which is commonly u32: let val : u32 = ...; match (val 0b11) 6 { 0b00 = ..., 0b01 = ..., 0b10 = ..., _ = {} } You can clearly see two problems here: I need to provide a catch-all match, even if the code guarantees a limited set of values; also I lost 0b11, and there's no warning due to catch all. Is it possible to make rustc aware of such cases? What would be totally awesome is some kind of [] operator for ints, that would extract bits, like that: match val[6..7] { ... } Is that something of interest to community? I would be willing to write an RFC for that, and possibly extend the compiler. -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] matching on a few bits in int
Sorry, that's definitely a typo, (val 6) 0b11 makes sense, (val 0b11) 6 does not. On Fri, Mar 28, 2014 at 1:04 PM, Clark Gaebel cgae...@uwaterloo.ca wrote: I like this! Although I think that match might've been better written `(val 6) 0b11`, but it'd be really nice for the compiler to catch those type of errors! - Clark On Fri, Mar 28, 2014 at 5:54 AM, Vladimir Pouzanov farcal...@gmail.comwrote: There's one thing that I often have to deal in embedded code — doing match on a few bits from an I/O register, which is commonly u32: let val : u32 = ...; match (val 0b11) 6 { 0b00 = ..., 0b01 = ..., 0b10 = ..., _ = {} } You can clearly see two problems here: I need to provide a catch-all match, even if the code guarantees a limited set of values; also I lost 0b11, and there's no warning due to catch all. Is it possible to make rustc aware of such cases? What would be totally awesome is some kind of [] operator for ints, that would extract bits, like that: match val[6..7] { ... } Is that something of interest to community? I would be willing to write an RFC for that, and possibly extend the compiler. -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Clark. Key ID : 0x78099922 Fingerprint: B292 493C 51AE F3AB D016 DD04 E5E3 C36F 5534 F907 -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] How do I pass -march down to llvm from rustc?
I'm trying to experiment with rust and some embedded code. Currently I have to do a three-pass compilation: rustc --target arm-linux-eabi -O --emit bc main.rs -o main.bc llc -mtriple arm-none-eabi -march=thumb -mcpu=cortex-m0 main.bc -o main.s arm-none-linux-gnueabi-as main.s -o main.o First, I'm not sure how relevant is --target flag for rustc. I seems to change target datalayout/triple in generated bc, but that should be overriden by llc -mtriple anyway, right? Second, I can pass -Ctarget-cpu=cortex-m0, but I cannot pass down -march=thumb, tried this way: -Cllvm-args='--march=thumb', failed with rustc: Unknown command line argument '--march=thumb'. Any hints on how can I drop explicit llc and as steps here? -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] How do I pass -march down to llvm from rustc?
Nevermind, I lost -O somewhere in between copying and pasting command line flags. Optimised version doesn't have any morestack references (which is strange concept though). On Sun, Mar 23, 2014 at 5:44 PM, Vladimir Pouzanov farcal...@gmail.comwrote: Figured out I can use --target thumbv6m-linux-eabi, which implies -mthumb. Now the problem is that if I use rustc --target thumbv6m-linux-eabi -O --emit obj main.rs -o main.o instead of three-step process I mentioned before, I get a valid object file for cortex-m0, but functions have big prologues and symbol table is much bigger: U STACK_LIMIT U _GLOBAL_OFFSET_TABLE_ D _ZN20_rust_crate_map_main16ad67637f924a5c794v0.0E 0008 r _ZN2hw11GPIO_PIN_NO20hb0b70c1482b61788Gaa4v0.0E r _ZN2hw12GPIO_DIR_REG20hb0b70c1482b61788yaa4v0.0E 0004 r _ZN2hw12GPIO_REG_VAL20hb0b70c1482b61788Caa4v0.0E 0078 t _ZN4main10__rust_abiE t _ZN4wait20h53ffb23463e08f19Maa4v0.0E U __aeabi_unwind_cpp_pr0 U __morestack 004c T main vs. D _ZN23_rust_crate_map_main.c016ad67637f924a5c794v0.0E T main in the initial version. Also, I now need to provide __morestack (no idea what's that about). On Sun, Mar 23, 2014 at 5:17 PM, Alex Crichton a...@crichton.co wrote: You should be able to assemble standalone objects for any triple through rustc itself, you'll likely have to specify a different linker or assembler though: rustc foo.rs --target arm-non-linux-gnueabi \ -C linker=arm-non-linux-gnueabi-ld \ -C ar=arm-non-linux-gnueabi-ar As you discovered, you can pass through arguments to LLVM via the -C llvm-args=foo command line option to rustc. If you get complaints that it's an unknown command line argument, it's LLVM telling you those complaints, not rustc. On Sun, Mar 23, 2014 at 8:54 AM, Vladimir Pouzanov farcal...@gmail.com wrote: I'm trying to experiment with rust and some embedded code. Currently I have to do a three-pass compilation: rustc --target arm-linux-eabi -O --emit bc main.rs -o main.bc llc -mtriple arm-none-eabi -march=thumb -mcpu=cortex-m0 main.bc -o main.s arm-none-linux-gnueabi-as main.s -o main.o First, I'm not sure how relevant is --target flag for rustc. I seems to change target datalayout/triple in generated bc, but that should be overriden by llc -mtriple anyway, right? Second, I can pass -Ctarget-cpu=cortex-m0, but I cannot pass down -march=thumb, tried this way: -Cllvm-args='--march=thumb', failed with rustc: Unknown command line argument '--march=thumb'. Any hints on how can I drop explicit llc and as steps here? -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] How do I pass -march down to llvm from rustc?
So it doesn't work in the end. rustc --emit bc with flags set for cortex-m0 provides exact same bc with only difference in target triple (which makes perfect sense) However, replacing llc step with rustc --emit asm provides a different assembler file, which requires __morestack. Should I expect rustc to generate freestanding code given some additional options? On Sun, Mar 23, 2014 at 5:55 PM, Vladimir Pouzanov farcal...@gmail.comwrote: Nevermind, I lost -O somewhere in between copying and pasting command line flags. Optimised version doesn't have any morestack references (which is strange concept though). On Sun, Mar 23, 2014 at 5:44 PM, Vladimir Pouzanov farcal...@gmail.comwrote: Figured out I can use --target thumbv6m-linux-eabi, which implies -mthumb. Now the problem is that if I use rustc --target thumbv6m-linux-eabi -O --emit obj main.rs -o main.o instead of three-step process I mentioned before, I get a valid object file for cortex-m0, but functions have big prologues and symbol table is much bigger: U STACK_LIMIT U _GLOBAL_OFFSET_TABLE_ D _ZN20_rust_crate_map_main16ad67637f924a5c794v0.0E 0008 r _ZN2hw11GPIO_PIN_NO20hb0b70c1482b61788Gaa4v0.0E r _ZN2hw12GPIO_DIR_REG20hb0b70c1482b61788yaa4v0.0E 0004 r _ZN2hw12GPIO_REG_VAL20hb0b70c1482b61788Caa4v0.0E 0078 t _ZN4main10__rust_abiE t _ZN4wait20h53ffb23463e08f19Maa4v0.0E U __aeabi_unwind_cpp_pr0 U __morestack 004c T main vs. D _ZN23_rust_crate_map_main.c016ad67637f924a5c794v0.0E T main in the initial version. Also, I now need to provide __morestack (no idea what's that about). On Sun, Mar 23, 2014 at 5:17 PM, Alex Crichton a...@crichton.co wrote: You should be able to assemble standalone objects for any triple through rustc itself, you'll likely have to specify a different linker or assembler though: rustc foo.rs --target arm-non-linux-gnueabi \ -C linker=arm-non-linux-gnueabi-ld \ -C ar=arm-non-linux-gnueabi-ar As you discovered, you can pass through arguments to LLVM via the -C llvm-args=foo command line option to rustc. If you get complaints that it's an unknown command line argument, it's LLVM telling you those complaints, not rustc. On Sun, Mar 23, 2014 at 8:54 AM, Vladimir Pouzanov farcal...@gmail.com wrote: I'm trying to experiment with rust and some embedded code. Currently I have to do a three-pass compilation: rustc --target arm-linux-eabi -O --emit bc main.rs -o main.bc llc -mtriple arm-none-eabi -march=thumb -mcpu=cortex-m0 main.bc -o main.s arm-none-linux-gnueabi-as main.s -o main.o First, I'm not sure how relevant is --target flag for rustc. I seems to change target datalayout/triple in generated bc, but that should be overriden by llc -mtriple anyway, right? Second, I can pass -Ctarget-cpu=cortex-m0, but I cannot pass down -march=thumb, tried this way: -Cllvm-args='--march=thumb', failed with rustc: Unknown command line argument '--march=thumb'. Any hints on how can I drop explicit llc and as steps here? -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] How do I pass -march down to llvm from rustc?
Thanks for links to bugs. Is there anything to read on the whole morestack thing? I thought that it's connected to segmented stacks that are (are they?) going away. It seems that I can use #[no_split_stack] before each and every function to generate a valid freestanding binary. If I just could use that in header... On Sun, Mar 23, 2014 at 6:24 PM, Corey Richardson co...@octayn.net wrote: No. See https://github.com/mozilla/rust/pull/8955 and https://github.com/mozilla/rust/issues/11871 for discussion. You can stub out morestack but that won't remove the stack size checks. It's sanest to just compile the IR yourself (the stack checking is a target-specific machine pass, which is why it shows up with --emit asm but not --emit bc) On Sun, Mar 23, 2014 at 2:09 PM, Vladimir Pouzanov farcal...@gmail.com wrote: So it doesn't work in the end. rustc --emit bc with flags set for cortex-m0 provides exact same bc with only difference in target triple (which makes perfect sense) However, replacing llc step with rustc --emit asm provides a different assembler file, which requires __morestack. Should I expect rustc to generate freestanding code given some additional options? On Sun, Mar 23, 2014 at 5:55 PM, Vladimir Pouzanov farcal...@gmail.com wrote: Nevermind, I lost -O somewhere in between copying and pasting command line flags. Optimised version doesn't have any morestack references (which is strange concept though). On Sun, Mar 23, 2014 at 5:44 PM, Vladimir Pouzanov farcal...@gmail.com wrote: Figured out I can use --target thumbv6m-linux-eabi, which implies -mthumb. Now the problem is that if I use rustc --target thumbv6m-linux-eabi -O --emit obj main.rs -o main.o instead of three-step process I mentioned before, I get a valid object file for cortex-m0, but functions have big prologues and symbol table is much bigger: U STACK_LIMIT U _GLOBAL_OFFSET_TABLE_ D _ZN20_rust_crate_map_main16ad67637f924a5c794v0.0E 0008 r _ZN2hw11GPIO_PIN_NO20hb0b70c1482b61788Gaa4v0.0E r _ZN2hw12GPIO_DIR_REG20hb0b70c1482b61788yaa4v0.0E 0004 r _ZN2hw12GPIO_REG_VAL20hb0b70c1482b61788Caa4v0.0E 0078 t _ZN4main10__rust_abiE t _ZN4wait20h53ffb23463e08f19Maa4v0.0E U __aeabi_unwind_cpp_pr0 U __morestack 004c T main vs. D _ZN23_rust_crate_map_main.c016ad67637f924a5c794v0.0E T main in the initial version. Also, I now need to provide __morestack (no idea what's that about). On Sun, Mar 23, 2014 at 5:17 PM, Alex Crichton a...@crichton.co wrote: You should be able to assemble standalone objects for any triple through rustc itself, you'll likely have to specify a different linker or assembler though: rustc foo.rs --target arm-non-linux-gnueabi \ -C linker=arm-non-linux-gnueabi-ld \ -C ar=arm-non-linux-gnueabi-ar As you discovered, you can pass through arguments to LLVM via the -C llvm-args=foo command line option to rustc. If you get complaints that it's an unknown command line argument, it's LLVM telling you those complaints, not rustc. On Sun, Mar 23, 2014 at 8:54 AM, Vladimir Pouzanov farcal...@gmail.com wrote: I'm trying to experiment with rust and some embedded code. Currently I have to do a three-pass compilation: rustc --target arm-linux-eabi -O --emit bc main.rs -o main.bc llc -mtriple arm-none-eabi -march=thumb -mcpu=cortex-m0 main.bc -o main.s arm-none-linux-gnueabi-as main.s -o main.o First, I'm not sure how relevant is --target flag for rustc. I seems to change target datalayout/triple in generated bc, but that should be overriden by llc -mtriple anyway, right? Second, I can pass -Ctarget-cpu=cortex-m0, but I cannot pass down -march=thumb, tried this way: -Cllvm-args='--march=thumb', failed with rustc: Unknown command line argument '--march=thumb'. Any hints on how can I drop explicit llc and as steps here? -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- http://octayn.net/ -- Sincerely, Vladimir Farcaller Pouzanov http://farcaller.net/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev