Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions harm-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,9 @@

pub mod builder;
pub mod labels;
#[macro_use]
mod macros;
pub mod memory;
pub mod runtime;

pub use self::runtime::{Assembler, AssemblerError};
55 changes: 55 additions & 0 deletions harm-runtime/src/macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* Copyright (C) 2026 Ivan Boldyrev
*
* This document is licensed under the BSD 3-clause license.
*/

/// A helper macro to append multiple instructions to the assembler, and return the first error if any of them fails.
#[macro_export]
macro_rules! harm {
($asm:expr; $($inst:expr),*) => {
{
let asm = &mut $asm;
'block: {
$(
if let Err(e) = asm.append($inst) {
break 'block Err(e);
}
)*
Ok(())
}
}
};

($asm:expr; $($inst:expr,)*) => {
harm!{ $asm; $($inst),* }
};
}

#[cfg(test)]
mod tests {
#[test]
#[cfg(feature = "memmap2")]
fn test_harm_macro() -> Result<(), Box<dyn std::error::Error>> {
use crate::*;
use harm::{
instructions::{dpimm::movz, logical::and},
register::Reg64,
};

use crate::memory::MmapBuffer;

let mem = MmapBuffer::allocate(16).unwrap();
let mut asm = Assembler::new(mem);

harm! {
asm;
movz(Reg64::X0, 0),
and(Reg64::X3, Reg64::X3, 8)? // instruction-level error.
}
.unwrap(); // memory buffer level error.

asm.build::<_, ()>().unwrap();

Ok(())
}
}
33 changes: 25 additions & 8 deletions harm-runtime/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub enum AssemblerError<MemErr, PMErr, EMErr> {
#[error("executable memory error: {0}")]
ExecutableMemory(EMErr),
}

// N.B. we keep here internal relocation type, and convert it to external on serialization.
#[derive(Default)]
pub struct Assembler<Mem: Memory> {
Expand Down Expand Up @@ -167,11 +168,19 @@ mod tests {
addend: 0,
};

asm.append(add(Reg64::X0, Reg64::X0, Reg64::X1));
asm.append(b(finish_ref));
asm.append(movz(Reg64::X0, 0));
harm! {
asm;
add(Reg64::X0, Reg64::X0, Reg64::X1),
b(finish_ref),
movz(Reg64::X0, 0),
}
.unwrap();
asm.assign_forward_label(finish_label);
asm.append(ret());
harm! {
asm;
ret()
}
.unwrap();

let (fm, _) = asm.build::<ForeignMemory, ()>().unwrap();

Expand Down Expand Up @@ -201,11 +210,19 @@ mod tests {
};

let _start = asm.current_named_label("_start");
asm.append(add(Reg64::X0, Reg64::X0, Reg64::X1)).unwrap();
asm.append(b(finish_ref)).unwrap();
asm.append(movz(Reg64::X0, 0)).unwrap();
harm! {
asm;
add(Reg64::X0, Reg64::X0, Reg64::X1),
b(finish_ref),
movz(Reg64::X0, 0),
}
.unwrap();
asm.assign_forward_label(finish_label);
asm.append(ret()).unwrap();
harm! {
asm;
ret()
}
.unwrap();

let (fm, labels) = asm.compile().unwrap();
let start_addr = labels.get("_start").cloned().unwrap() as usize;
Expand Down