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

Fix label docs (and a couple of misc bits) #92

Closed
wants to merge 7 commits into from
Closed
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
2 changes: 2 additions & 0 deletions doc/examples/hello-world/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ edition = "2018"
[[bin]]
name = "x64"
path = "src/x64.rs"
doc = false

[[bin]]
name = "aarch64"
path = "src/aarch64.rs"
doc = false

[dependencies]

Expand Down
2 changes: 0 additions & 2 deletions doc/insref/src/export.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![feature(proc_macro_hygiene)]

use std::io::{self, Write};

fn main() {
Expand Down
22 changes: 13 additions & 9 deletions doc/langref_common.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,28 +106,32 @@ dynasm!(ops

In order to describe flow control effectively, dynasm-rs supports labels. However, since the assembly templates can be combined in a variety of ways at the mercy of the program using dynasm-rs, the semantics of these labels are somewhat different from how labels work in a static assembler.

Dynasm-rs distinguishes between three different types of labels: global, local and dynamic labels. Their syntax is as follows:
Dynasm-rs distinguishes between four different types of labels: global, local, dynamic and extern. Their syntax is as follows:

Table 2: dynasm-rs label types

Type | Definition | Reference
--------|--------------|-----------
Local | `label:` | `>label` or `<label`
GLobal | `->label:` | `->label`
Dynamic | `=>expr` | `=>expr`
Extern | `-` | `extern expr`
Type | Kind | Definition | Reference
--------|---------|--------------|-----------
Local | static | `label:` | `>label` or `<label`
GLobal | static | `->label:` | `->label`
Dynamic | dynamic | `=>expr` | `=>expr`
Extern | extern | `-` | `extern expr`

All labels have their addresses resolved at `Assembler::commit()` time.

Any valid Rust identifier is a valid label name.

### Local labels

On first sight, local label definitions are similar to how labels are normally used in static assemblers. The trick with local labels is however in how they can be referenced. Local labels referenced with the `>label` syntax will be resolved to the first definition of this label after this piece of code, while local labels referenced with the `<label` will be resolved to the last definition of this label before the reference site. Any valid Rust identifier can be used as a local label name, and local labels can be defined multiple times.

### Global labels

Global labels can only be defined once, and all references to a global label will be resolved to this label. Any valid Rust identifier can be used as a local label name.
Global labels can only be defined once (per-assembler), and all references to a global label will be resolved to this label.

### Dynamic labels

Dynamic labels are similar to global labels in that they can be defined only once, but instead of a name, they are identified by an expression. New dynamic labels can be created at runtime by the assembler. This expression is evaluated at the point where the label is defined or referenced, and the labels will be resolved at only at commit time.
Dynamic labels are similar to global labels in that they can be defined only once (per-assembler), but instead of a name, they are identified by an expression. New dynamic labels can be created at runtime by the assembler. This expression is evaluated at the point where the label is defined or referenced, and the labels will be resolved at only at commit time.

### Extern labels

Expand Down
1 change: 0 additions & 1 deletion plugin/src/arch/aarch64/ast.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use syn;
use proc_macro2::Span;

use crate::common::{Size, Jump};
Expand Down
6 changes: 1 addition & 5 deletions plugin/src/arch/aarch64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@ impl Default for ArchAarch64 {
}

impl Arch for ArchAarch64 {
fn name(&self) -> &str {
"aarch64"
}

fn set_features(&mut self, features: &[syn::Ident]) {
if let Some(feature) = features.first() {
emit_error!(feature, "Arch aarch64 has no known features");
Expand Down Expand Up @@ -95,4 +91,4 @@ impl Arch for ArchAarch64 {

Ok(())
}
}
}
15 changes: 4 additions & 11 deletions plugin/src/arch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,22 @@ pub mod x64;
pub mod aarch64;

pub(crate) trait Arch : Debug + Send {
fn name(&self) -> &str;
fn set_features(&mut self, features: &[syn::Ident]);
fn handle_static_reloc(&self, stmts: &mut Vec<Stmt>, reloc: Jump, size: Size);
fn default_align(&self) -> u8;
fn compile_instruction(&self, state: &mut State, input: parse::ParseStream) -> parse::Result<()>;
}

#[derive(Clone, Debug)]
pub struct DummyArch {
name: &'static str
}
pub struct DummyArch {}

impl DummyArch {
fn new(name: &'static str) -> DummyArch {
DummyArch { name }
fn new() -> DummyArch {
DummyArch{}
}
}

impl Arch for DummyArch {
fn name(&self) -> &str {
self.name
}

fn set_features(&mut self, features: &[syn::Ident]) {
if let Some(feature) = features.first() {
emit_error!(feature, "Cannot set features when the assembling architecture is undefined. Define it using a .arch directive");
Expand All @@ -59,7 +52,7 @@ pub(crate) fn from_str(s: &str) -> Option<Box<dyn Arch>> {
"x64" => Some(Box::new(x64::Archx64::default())),
"x86" => Some(Box::new(x64::Archx86::default())),
"aarch64" => Some(Box::new(aarch64::ArchAarch64::default())),
"unknown" => Some(Box::new(DummyArch::new("unknown"))),
"unknown" => Some(Box::new(DummyArch::new())),
_ => None
}
}
Expand Down
1 change: 0 additions & 1 deletion plugin/src/arch/x64/ast.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use syn;
use proc_macro2::Span;

use crate::common::{Size, Jump};
Expand Down
8 changes: 0 additions & 8 deletions plugin/src/arch/x64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@ impl Default for Archx64 {
}

impl Arch for Archx64 {
fn name(&self) -> &str {
"x64"
}

fn set_features(&mut self, features: &[syn::Ident]) {
let mut new_features = x64data::Features::empty();
for ident in features {
Expand Down Expand Up @@ -94,10 +90,6 @@ impl Default for Archx86 {
}

impl Arch for Archx86 {
fn name(&self) -> &str {
"x86"
}

fn set_features(&mut self, features: &[syn::Ident]) {
let mut new_features = x64data::Features::empty();
for ident in features {
Expand Down
1 change: 0 additions & 1 deletion plugin/src/serialize.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use syn;
use syn::parse;
use syn::spanned::Spanned;
use proc_macro2::{Span, TokenStream, TokenTree, Literal};
Expand Down
11 changes: 7 additions & 4 deletions runtime/src/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@ use crate::mmap::{ExecutableBuffer, MutableBuffer};
use crate::relocations::{Relocation, RelocationKind, RelocationSize, ImpossibleRelocation};

/// A static label represents either a local label or a global label reference.
/// Global labels are unique names, which can be referenced multiple times, but only defined once.
///
/// Global labels are unique names, which can be referenced multiple times, but only defined once
/// (per-[crate::Assembler]).
///
/// Local labels are non-unique names. They can be referenced multiple times, and any reference
/// indicates if they refer to a label after the reference, or a label before the reference.
///
/// A static label records how many local labels with the same name have been emitted beforehand
/// so we can treat them as local labels as well.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -279,7 +283,7 @@ impl LabelRegistry {
self.dynamic_labels.get(id.0).and_then(|&e| e).ok_or_else(|| DynasmError::UnknownLabel(LabelKind::Dynamic(id)))
}

/// Returns the offset at which the global label `name` was defined, if one was defined.
/// Returns the offset at which the global label `label` was defined, if one was defined.
pub fn resolve_static(&self, label: &StaticLabel) -> Result<AssemblyOffset, DynasmError> {
self.static_labels.get(label).cloned().ok_or_else(|| DynasmError::UnknownLabel(
if label.is_global() {
Expand Down Expand Up @@ -612,8 +616,7 @@ impl LitPool {
#[cfg(test)]
mod tests {
use crate::*;
use std::fmt::Debug;
use relocations::{Relocation, RelocationSize};
use relocations::RelocationSize;

#[test]
fn test_litpool_size() {
Expand Down
6 changes: 4 additions & 2 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ use crate::components::{MemoryManager, LabelRegistry, RelocRegistry, ManagedRelo
use crate::relocations::Relocation;

use std::hash::Hash;
use std::iter::Extend;
use std::sync::{Arc, RwLock, RwLockReadGuard};
use std::io;
use std::error;
Expand Down Expand Up @@ -234,7 +233,10 @@ pub trait DynasmApi: Extend<u8> + for<'a> Extend<&'a u8> {
}
}

/// This trait extends DynasmApi to not only allow assembling, but also labels and various directives
/// This trait extends DynasmApi to not only allow assembling, but also labels and various directives.
///
/// For information on the different kinds of label, consult the common language reference in the
/// dynasm-rs docs.
pub trait DynasmLabelApi : DynasmApi {
/// The relocation info type this assembler uses.
type Relocation: Relocation;
Expand Down
Loading