Walk tokens, assign addresses to labels, return the symbol table.
(tokens: &[AsmToken])
| 14 | } |
| 15 | |
| 16 | /// Walk tokens, assign addresses to labels, return the symbol table. |
| 17 | pub fn compute_layout(tokens: &[AsmToken]) -> Result<Layout, AssemblerError> { |
| 18 | let mut symbols = SymbolTable::new(); |
| 19 | let mut section_order: Vec<SectionKind> = Vec::new(); |
| 20 | let mut section_sizes: std::collections::HashMap<SectionKind, u64> = |
| 21 | std::collections::HashMap::new(); |
| 22 | |
| 23 | let mut current = SectionKind::Text; |
| 24 | let mut offset: u64 = 0; |
| 25 | |
| 26 | for token in tokens { |
| 27 | match token { |
| 28 | AsmToken::Section(kind) => { |
| 29 | *section_sizes.entry(current.clone()).or_insert(0) = offset; |
| 30 | if !section_order.contains(kind) { |
| 31 | section_order.push(kind.clone()); |
| 32 | } |
| 33 | offset = *section_sizes.entry(kind.clone()).or_insert(0); |
| 34 | current = kind.clone(); |
| 35 | } |
| 36 | AsmToken::Label(name) => { |
| 37 | if !section_order.contains(¤t) { |
| 38 | section_order.push(current.clone()); |
| 39 | } |
| 40 | if !symbols.define(format!("{}@{}", name, current.name()), offset) { |
| 41 | // Section-qualified duplicates are tolerated; the unqualified form errors. |
| 42 | } |
| 43 | if !symbols.define(name.clone(), offset) { |
| 44 | return Err(AssemblerError::new(format!( |
| 45 | "duplicate label `{name}` in section `{}`", |
| 46 | current.name() |
| 47 | ))); |
| 48 | } |
| 49 | } |
| 50 | AsmToken::Globl(name) => { |
| 51 | symbols.mark_global(name.clone()); |
| 52 | } |
| 53 | AsmToken::Align(n) => { |
| 54 | offset = align_up(offset, 1u64 << n); |
| 55 | } |
| 56 | AsmToken::Balign(n) => { |
| 57 | offset = align_up(offset, *n as u64); |
| 58 | } |
| 59 | other => { |
| 60 | if let Some(size) = other.fixed_size() { |
| 61 | if !section_order.contains(¤t) { |
| 62 | section_order.push(current.clone()); |
| 63 | } |
| 64 | offset += size as u64; |
| 65 | } |
| 66 | } |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | *section_sizes.entry(current).or_insert(0) = offset; |
| 71 | section_order = canonical_section_order(§ion_order); |
| 72 | |
| 73 | Ok(Layout { |