gccrs: Add metadata output pass
authorPhilip Herron <philip.herron@embecosm.com>
Tue, 23 Aug 2022 15:36:29 +0000 (16:36 +0100)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 13 Dec 2022 13:00:06 +0000 (14:00 +0100)
commit509e4c32c6a80ede6c6dda0f4cfc96f94d24c4d6
tree3f7098374abe40dd509147ba01526ffad98e6b36
parent4d67468d1d40f4d60a3760d47b74912c13621ada
gccrs: Add metadata output pass

Extern crates statements to tell the front-end to look for another library.
The mechanism here is heavily inspired from gccgo, so when we compile a
library for example we invoke:

  gccrs -g -O2 -frust-crate=mylib -c src/lib.rs -o src/mylib.o

All going well this object file will now contain extra data inside
.rust-export section inside the object file which will be preserved inside
archives and shared objects. When we have another application which uses
this library 'mylib'.

  extern crate mylib;
  use mylib::foo;

  fn main() {
    foo();
  }

We compile using:

  gcc -g -O2 -frust-crate=test -c src/main.rs -o src/main.o

When the extern crate line is hit the front-end will look for mylib.o,
libmylib.a, mylib.rox. If it finds a raw object file it will read the
.rust-export section directly from the object for the public metadata
such as public functions, types constants etc. If it fails to find an
object it might find .rox which is the objdump of the .rust-export to a
raw file, it might even find libmylib.a and read the export directly out
of the archive file reusing code from gccgo to do so.

The full compiler pipeline is reused here, so the metatadata is actually
just real rust code. The benifit here is that Rust supports exporting,
macros and generics so this requires the name-resolution and type info
all to be generated and inserted into the apropriate context classes. Since
the metadata is real rust code it means we can reuse the full pipeline to
generate the code as necessary. So for the simple case of a public struct
we simply emit the AST dump of this struct directly into the metadata. If
its a non-generic public function we emit and extern rust abi block for
that function. If its a trait we can simply emit the trait with the public
memebers. Generics are more complicated since we need to emit the function
fully for it to be compiled correctly this still needs tests to be added.
The hardest part is non generic impl blocks which is still a WIP.

To finally link the two crates together you run:

  gcc -g -O2 -o rust-program.exe src/main.o src/mylib.o

gcc/rust/
* metadata/rust-export-metadata.cc: New.
* metadata/rust-export-metadata.h: New.
* metadata/rust-extern-crate.cc: New.
* metadata/rust-extern-crate.h: New.
* metadata/rust-import-archive.cc: New.
* metadata/rust-imports.cc: New.
* metadata/rust-imports.h: New.
* rust-object-export.cc: New.
* rust-object-export.h: New.
gcc/rust/metadata/rust-export-metadata.cc [new file with mode: 0644]
gcc/rust/metadata/rust-export-metadata.h [new file with mode: 0644]
gcc/rust/metadata/rust-extern-crate.cc [new file with mode: 0644]
gcc/rust/metadata/rust-extern-crate.h [new file with mode: 0644]
gcc/rust/metadata/rust-import-archive.cc [new file with mode: 0644]
gcc/rust/metadata/rust-imports.cc [new file with mode: 0644]
gcc/rust/metadata/rust-imports.h [new file with mode: 0644]
gcc/rust/rust-object-export.cc [new file with mode: 0644]
gcc/rust/rust-object-export.h [new file with mode: 0644]