pub struct SymbolTable { /* private fields */ }
Expand description
The symbol table created in the first assembler pass that encodes source code mappings to memory addresses in the object file.
The symbol table consists of:
- A mapping from source code labels to memory addresses.
- A mapping from source code line numbers to memory addresses (if debug symbols are enabled).
- The source text (if debug symbols are enabled).
Here is a table of the mappings that the symbol table provides:
from ↓, to → | label | memory address | source line/span |
---|---|---|---|
label | - | SymbolTable::lookup_label | SymbolTable::get_label_source |
memory address | SymbolTable::rev_lookup_label | - | SymbolTable::rev_lookup_line |
source line | none | SymbolTable::lookup_line | - |
§Debug symbols
Debug symbols are optional data added to this symbol table which can help users debug their code.
Without debug symbols, the symbol table only consists of mappings from labels to spans (and vice-versa).
These are used to translate labels in source code to addresses during the assembly process.
After the completion of this assembly process, the SymbolTable
is dropped and is not part of the resultant
ObjectFile
.
However, with debug symbols, this information persists in the resultant ObjectFile
, allowing
the label mappings to be accessed during simulation time. Additionally, more information from the source
text is available during simulation time:
- Mappings from source code line numbers to memory addresses
- Source code text (which grants access to line contents from a given line number; see
SourceInfo
for more details)
Implementations§
Source§impl SymbolTable
impl SymbolTable
Sourcepub fn new(stmts: &[Stmt], src: Option<&str>) -> Result<Self, AsmErr>
pub fn new(stmts: &[Stmt], src: Option<&str>) -> Result<Self, AsmErr>
Creates a new symbol table.
This performs the first assembler pass, calculating the memory address of labels at each provided statement.
If a src
argument is provided, debug symbols are also computed for the symbol table.
§Example
use lc3_ensemble::parse::parse_ast;
use lc3_ensemble::asm::SymbolTable;
let src = "
.orig x3000
LABEL: HALT
.end
";
let ast = parse_ast(src).unwrap();
// without debug symbols
let sym = SymbolTable::new(&ast, None).unwrap();
assert_eq!(sym.lookup_label("LABEL"), Some(0x3000));
assert_eq!(sym.lookup_line(2), None);
// with debug symbols
let sym = SymbolTable::new(&ast, Some(src)).unwrap();
assert_eq!(sym.lookup_label("LABEL"), Some(0x3000));
assert_eq!(sym.lookup_line(2), Some(0x3000));
Sourcepub fn lookup_label(&self, label: &str) -> Option<u16>
pub fn lookup_label(&self, label: &str) -> Option<u16>
Gets the memory address of a given label (if it exists).
§Example
use lc3_ensemble::parse::parse_ast;
use lc3_ensemble::asm::SymbolTable;
let src = "
.orig x3000
LOOP:
ADD R0, R0, #1
BR LOOP
LOOP2:
ADD R0, R0, #2
BR LOOP2
LOOP3:
ADD R0, R0, #3
BR LOOP3
.end
";
let ast = parse_ast(src).unwrap();
let sym = SymbolTable::new(&ast, None).unwrap();
assert_eq!(sym.lookup_label("LOOP"), Some(0x3000));
assert_eq!(sym.lookup_label("LOOP2"), Some(0x3002));
assert_eq!(sym.lookup_label("LOOP3"), Some(0x3004));
assert_eq!(sym.lookup_label("LOOP_DE_LOOP"), None);
Sourcepub fn rev_lookup_label(&self, addr: u16) -> Option<&str>
pub fn rev_lookup_label(&self, addr: u16) -> Option<&str>
Gets the label at a given memory address (if it exists).
§Example
use lc3_ensemble::parse::parse_ast;
use lc3_ensemble::asm::SymbolTable;
let src = "
.orig x3000
LOOP:
ADD R0, R0, #1
BR LOOP
LOOP2:
ADD R0, R0, #2
BR LOOP2
LOOP3:
ADD R0, R0, #3
BR LOOP3
.end
";
let ast = parse_ast(src).unwrap();
let sym = SymbolTable::new(&ast, None).unwrap();
assert_eq!(sym.rev_lookup_label(0x3000), Some("LOOP"));
assert_eq!(sym.rev_lookup_label(0x3002), Some("LOOP2"));
assert_eq!(sym.rev_lookup_label(0x3004), Some("LOOP3"));
assert_eq!(sym.rev_lookup_label(0x2110), None);
Sourcepub fn get_label_source(&self, label: &str) -> Option<Range<usize>>
pub fn get_label_source(&self, label: &str) -> Option<Range<usize>>
Gets the source span of a given label (if it exists).
§Example
use lc3_ensemble::parse::parse_ast;
use lc3_ensemble::asm::SymbolTable;
let src = "
.orig x3000
LOOPY:
ADD R0, R0, #1
BR LOOPY
.end
";
let ast = parse_ast(src).unwrap();
let sym = SymbolTable::new(&ast, None).unwrap();
assert_eq!(sym.get_label_source("LOOPY"), Some(21..26));
assert_eq!(sym.get_label_source("LOOP_DE_LOOP"), None);
Sourcepub fn lookup_line(&self, line: usize) -> Option<u16>
pub fn lookup_line(&self, line: usize) -> Option<u16>
Gets the address of a given source line.
If debug symbols are not enabled, this unconditionally returns None
.
Note that each address is mapped to at most one source code line.
§Example
use lc3_ensemble::parse::parse_ast;
use lc3_ensemble::asm::SymbolTable;
let src = " ;; 0
.orig x3000 ;; 1
LOOP: ;; 2
ADD R0, R0, #1 ;; 3
BR LOOP ;; 4
.fill x9999 ;; 5
.blkw 10 ;; 6
LOOP2: ;; 7
ADD R0, R0, #3 ;; 8
BR LOOP3 ;; 9
.end ;; 10
";
let ast = parse_ast(src).unwrap();
// Debug symbols required:
let sym = SymbolTable::new(&ast, Some(src)).unwrap();
assert_eq!(sym.lookup_line(0), None);
assert_eq!(sym.lookup_line(1), None);
assert_eq!(sym.lookup_line(2), None);
assert_eq!(sym.lookup_line(3), Some(0x3000));
assert_eq!(sym.lookup_line(4), Some(0x3001));
assert_eq!(sym.lookup_line(5), Some(0x3002));
assert_eq!(sym.lookup_line(6), Some(0x3003));
assert_eq!(sym.lookup_line(7), None);
assert_eq!(sym.lookup_line(8), Some(0x300D));
assert_eq!(sym.lookup_line(9), Some(0x300E));
assert_eq!(sym.lookup_line(10), None);
Sourcepub fn rev_lookup_line(&self, addr: u16) -> Option<usize>
pub fn rev_lookup_line(&self, addr: u16) -> Option<usize>
Gets the source line of a given memory address (if it exists.)
The result can be converted into a source span (range of characters encompassed by the instruction)
using SymbolTable::source_info
and SourceInfo::line_span
.
If debug symbols are not enabled, this unconditionally returns None
.
Note that each source code line is mapped to at most one address.
§Example
use lc3_ensemble::parse::parse_ast;
use lc3_ensemble::asm::SymbolTable;
let src = " ;; 0
.orig x3000 ;; 1
LOOP: ;; 2
ADD R0, R0, #1 ;; 3
BR LOOP ;; 4
.fill x9999 ;; 5
.blkw 10 ;; 6
LOOP2: ;; 7
ADD R0, R0, #3 ;; 8
BR LOOP3 ;; 9
.end ;; 10
";
let ast = parse_ast(src).unwrap();
// Debug symbols required:
let sym = SymbolTable::new(&ast, Some(src)).unwrap();
assert_eq!(sym.rev_lookup_line(0x3000), Some(3));
assert_eq!(sym.rev_lookup_line(0x3001), Some(4));
assert_eq!(sym.rev_lookup_line(0x3002), Some(5));
assert_eq!(sym.rev_lookup_line(0x3003), Some(6));
assert_eq!(sym.rev_lookup_line(0x3004), None);
assert_eq!(sym.rev_lookup_line(0x3005), None);
assert_eq!(sym.rev_lookup_line(0x3006), None);
assert_eq!(sym.rev_lookup_line(0x3007), None);
assert_eq!(sym.rev_lookup_line(0x3008), None);
assert_eq!(sym.rev_lookup_line(0x3009), None);
assert_eq!(sym.rev_lookup_line(0x300A), None);
assert_eq!(sym.rev_lookup_line(0x300B), None);
assert_eq!(sym.rev_lookup_line(0x300C), None);
assert_eq!(sym.rev_lookup_line(0x300D), Some(8));
assert_eq!(sym.rev_lookup_line(0x300E), Some(9));
assert_eq!(sym.rev_lookup_line(0x300F), None);
Sourcepub fn source_info(&self) -> Option<&SourceInfo>
pub fn source_info(&self) -> Option<&SourceInfo>
Reads the source info from this symbol table (if debug symbols are enabled).
Trait Implementations§
Source§impl Clone for SymbolTable
impl Clone for SymbolTable
Source§fn clone(&self) -> SymbolTable
fn clone(&self) -> SymbolTable
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read more