Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP New Dev Backend Representation #7397

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/compiler/build/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ target-arm = []
target-wasm32 = []
target-x86 = []
target-x86_64 = ["roc_gen_dev/target-x86_64"]
use_roar = ["roc_gen_dev/use_roar"]

# This is used to enable fuzzing and sanitizers.
# Example use is describe here: https://github.com/bhansconnect/roc-fuzz
Expand Down
5 changes: 4 additions & 1 deletion crates/compiler/build/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,12 +449,15 @@ fn gen_from_mono_module_dev<'a>(
preprocessed_host.display()
),
(_, Architecture::X86_64 | Architecture::Aarch64) => {
#[cfg(not(feature = "target-wasm32"))]
//FIXME revert this, this is not a permanent change
//Like really, this is bad, and litterally only works with roar
//#[cfg(not(feature = "target-wasm32"))]
{
gen_from_mono_module_dev_assembly(arena, loaded, target, backend_mode)
}

#[cfg(feature = "target-wasm32")]
#[cfg(not(feature = "use_roar"))]
{
internal_error!("Compiler was not built with feature 'target-wasm32'.")
}
Expand Down
1 change: 1 addition & 0 deletions crates/compiler/gen_dev/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@ capstone.workspace = true
[features]
target-aarch64 = []
target-x86_64 = []
use_roar = []
4 changes: 4 additions & 0 deletions crates/compiler/gen_dev/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ Disassembly of section .text.1000000000:

The output lines contain the hexadecimal representation of the x86 opcodes and fields followed by the `intel` assembly syntax. This setup is very useful for figuring out the causes of invalid pointer references (or equivalent) when running the resulting x86 assembly.

## Roc Optimizable Abstract Representation (ROAR)

Roc Optimizable Abstract Representation (ROAR) is a planned step in between monomorphization and the `dev` backend, intended to not be as low-level as a [assembly representation](https://en.wikipedia.org/wiki/Assembly_language) but more specific than a [bytecode](https://en.wikipedia.org/wiki/Assembly_language). More detail may be found at the ROAR [README](src/roar/README.md)

## Helpful Resources

- [Compiler Explorer](https://godbolt.org/) -
Expand Down
1 change: 1 addition & 0 deletions crates/compiler/gen_dev/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ mod object_builder;
pub use object_builder::build_module;
use roc_target::Target;
mod run_roc;
mod roar;

#[derive(Debug, Clone, Copy)]
pub enum AssemblyBackendMode {
Expand Down
182 changes: 99 additions & 83 deletions crates/compiler/gen_dev/src/object_builder.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use super::roar;
use crate::generic64::{aarch64, new_backend_64bit, x86_64};
use crate::roar::convert::build_roar;
use crate::{AssemblyBackendMode, Backend, Env, Relocation};
use bumpalo::collections::Vec;
use object::write::{self, SectionId, SymbolId};
use object::write::{Object, StandardSection, StandardSegment, Symbol, SymbolSection};
use object::{
Architecture, BinaryFormat, Endianness, RelocationEncoding, RelocationKind, SectionKind,
SymbolFlags, SymbolKind, SymbolScope,
Architecture, BinaryFormat, Endianness, RelocationEncoding, RelocationKind, Section,
SectionKind, SymbolFlags, SymbolKind, SymbolScope,
};
use roc_collections::all::MutMap;
use roc_error_macros::internal_error;
Expand All @@ -22,7 +24,7 @@ use roc_target::Target;

/// build_module is the high level builder/delegator.
/// It takes the request to build a module and output the object file for the module.
pub fn build_module<'a, 'r>(
pub fn build_module<'a, 'r : 'a>(
env: &'r Env<'a>,
interns: &'r mut Interns,
layout_interner: &'r mut STLayoutInterner<'a>,
Expand All @@ -44,93 +46,107 @@ pub fn build_module<'a, 'r>(
module_object
}

fn build_module_help<'a, 'r>(
fn build_module_help<'a, 'r : 'a>(
env: &'r Env<'a>,
interns: &'r mut Interns,
layout_interner: &'r mut STLayoutInterner<'a>,
target: Target,
procedures: MutMap<(symbol::Symbol, ProcLayout<'a>), Proc<'a>>,
) -> Object<'a> {
match target {
Target::LinuxX64 if cfg!(feature = "target-x86_64") => {
let backend = new_backend_64bit::<
x86_64::X86_64GeneralReg,
x86_64::X86_64FloatReg,
x86_64::X86_64Assembler,
x86_64::X86_64SystemV,
>(env, target, interns, layout_interner);
// Newer version of `ld` require `.note.GNU-stack` for security reasons.
// It specifies that we will not execute code stored on the stack.
let mut object =
Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little);
object.add_section(
vec![],
b".note.GNU-stack".to_vec(),
SectionKind::Elf(object::elf::SHT_PROGBITS),
);
build_object(procedures, backend, object)
}
Target::MacX64 if cfg!(feature = "target-x86_64") => {
let backend = new_backend_64bit::<
x86_64::X86_64GeneralReg,
x86_64::X86_64FloatReg,
x86_64::X86_64Assembler,
x86_64::X86_64SystemV,
>(env, target, interns, layout_interner);
build_object(
procedures,
backend,
Object::new(
BinaryFormat::MachO,
Architecture::X86_64,
Endianness::Little,
),
)
}
Target::WinX64 if cfg!(feature = "target-x86_64") => {
let backend = new_backend_64bit::<
x86_64::X86_64GeneralReg,
x86_64::X86_64FloatReg,
x86_64::X86_64Assembler,
x86_64::X86_64WindowsFastcall,
>(env, target, interns, layout_interner);
build_object(
procedures,
backend,
Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little),
)
}
Target::LinuxArm64 if cfg!(feature = "target-aarch64") => {
let backend = new_backend_64bit::<
aarch64::AArch64GeneralReg,
aarch64::AArch64FloatReg,
aarch64::AArch64Assembler,
aarch64::AArch64Call,
>(env, target, interns, layout_interner);
build_object(
procedures,
backend,
Object::new(BinaryFormat::Elf, Architecture::Aarch64, Endianness::Little),
)
}
Target::MacArm64 if cfg!(feature = "target-aarch64") => {
let backend = new_backend_64bit::<
aarch64::AArch64GeneralReg,
aarch64::AArch64FloatReg,
aarch64::AArch64Assembler,
aarch64::AArch64Call,
>(env, target, interns, layout_interner);
build_object(
procedures,
backend,
Object::new(
BinaryFormat::MachO,
Architecture::Aarch64,
Endianness::Little,
),
)
println!("Running...");
if cfg!(feature = "use_roar") {
//TODO clean this back up
//For using experimental ROAR pipeline
let Ok(section) = build_roar(procedures, layout_interner, env) else {
todo!()
};
println!("roar is {:?}", section);
match target {
_ => todo!(),
};
todo!()
} else {
match target {
Target::LinuxX64 if cfg!(feature = "target-x86_64") => {
let backend = new_backend_64bit::<
x86_64::X86_64GeneralReg,
x86_64::X86_64FloatReg,
x86_64::X86_64Assembler,
x86_64::X86_64SystemV,
>(env, target, interns, layout_interner);
// Newer version of `ld` require `.note.GNU-stack` for security reasons.
// It specifies that we will not execute code stored on the stack.
let mut object =
Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little);
object.add_section(
vec![],
b".note.GNU-stack".to_vec(),
SectionKind::Elf(object::elf::SHT_PROGBITS),
);
build_object(procedures, backend, object)
}
Target::MacX64 if cfg!(feature = "target-x86_64") => {
let backend = new_backend_64bit::<
x86_64::X86_64GeneralReg,
x86_64::X86_64FloatReg,
x86_64::X86_64Assembler,
x86_64::X86_64SystemV,
>(env, target, interns, layout_interner);
build_object(
procedures,
backend,
Object::new(
BinaryFormat::MachO,
Architecture::X86_64,
Endianness::Little,
),
)
}
Target::WinX64 if cfg!(feature = "target-x86_64") => {
let backend = new_backend_64bit::<
x86_64::X86_64GeneralReg,
x86_64::X86_64FloatReg,
x86_64::X86_64Assembler,
x86_64::X86_64WindowsFastcall,
>(env, target, interns, layout_interner);
build_object(
procedures,
backend,
Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little),
)
}
Target::LinuxArm64 if cfg!(feature = "target-aarch64") => {
let backend = new_backend_64bit::<
aarch64::AArch64GeneralReg,
aarch64::AArch64FloatReg,
aarch64::AArch64Assembler,
aarch64::AArch64Call,
>(env, target, interns, layout_interner);
build_object(
procedures,
backend,
Object::new(BinaryFormat::Elf, Architecture::Aarch64, Endianness::Little),
)
}
Target::MacArm64 if cfg!(feature = "target-aarch64") => {
let backend = new_backend_64bit::<
aarch64::AArch64GeneralReg,
aarch64::AArch64FloatReg,
aarch64::AArch64Assembler,
aarch64::AArch64Call,
>(env, target, interns, layout_interner);
build_object(
procedures,
backend,
Object::new(
BinaryFormat::MachO,
Architecture::Aarch64,
Endianness::Little,
),
)
}
x => unimplemented!("the target, {:?}", x),
}
x => unimplemented!("the target, {:?}", x),
}
}

Expand Down
Loading