Skip to content

AVR is Harvard architecture #53

Open
@gergoerdi

Description

@gergoerdi

One problem I've run into (see #47) is that Rust sometimes generates static lookup tables from code, then the generated AVR assembly tries accessing that data using ld. Of course, that doesn't work because AVR uses the Harvard architecture: the program image and RAM are in two completely separate namespaces. There's a separate lpm instruction for loading data from program memory. A similar issue applies to static strings as well.

First off, we need to know when to compile an LLVM IR load instruction into an ld and when to compile it into an lpm. My experimental hack currently selects lpm for isConstant GlobalVariables and ld for everything else.

However, this is problematic because Rust code is free to take pointers to static strings in the form of
str. To support that, we need to do what GCC does, which is to copy over these strings at startup (in a stub pasted to the start of main) to RAM, and then use those addresses with ld.

Putting it all together, my proposal for handling all this would be:

  • Static data emitted by the Rust compiler should never take up RAM. They should always reside in PROGMEM, linked into .text and accessed via lpm.

  • Static data originating from the user (e.g. static strings) should be copied to RAM at startup and that copy should be used (via ld) whenever a pointer is to be taken.

  • Open question: Come up with a nice Rust API for the user to explicitly access PROGMEM when that is what they want (similar to AVR-GCC)

This should be implementable by:

  • On the Rust side, mark lookup tables etc. emitted by Rust with some special attribute (I hope LLVM has support for target-specific attributes) so that the LLVM AVR backend has a way of recognizing them

  • In the LLVM AVR backend, collect all static globals that are not marked with the above special attribute, and generate a stub that copies them into RAM at startup.

  • In the LLVM AVR backend, LowerGlobalAddress checks for that attribute and generates an appropriate wrapper ISD that is then used to dispatch to lpm or ld during instruction selection

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions