asm done with parsing and linking. codegen all that's left
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use std::path::PathBuf;
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
|
||||
use crate::{
|
||||
AssembleError,
|
||||
@@ -6,18 +6,77 @@ use crate::{
|
||||
quick_hash,
|
||||
};
|
||||
|
||||
pub fn resolve_symbols(nodes: &mut Vec<Node>) -> Result<(), AssembleError> {
|
||||
let symbol_table = generate_symbol_table(&nodes)?;
|
||||
|
||||
for node in nodes.iter_mut() {
|
||||
match node.opcode() {
|
||||
Opcode::Lli => {
|
||||
if let Token::Symbol(symbol) = node.arg(0).unwrap() {
|
||||
if let Some(address) = symbol_table.get(&symbol) {
|
||||
node.tokens[0] = Token::Immediate(*address);
|
||||
} else {
|
||||
return Err(AssembleError::UndefinedSymbol(symbol.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
Opcode::Lui => {
|
||||
if let Token::Symbol(symbol) = node.arg(0).unwrap() {
|
||||
if let Some(address) = symbol_table.get(&symbol) {
|
||||
node.tokens[0] = Token::Immediate(*address);
|
||||
} else {
|
||||
return Err(AssembleError::UndefinedSymbol(symbol.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
Opcode::Jmp
|
||||
| Opcode::Jeq
|
||||
| Opcode::Jne
|
||||
| Opcode::Jgt
|
||||
| Opcode::Jge
|
||||
| Opcode::Jlt
|
||||
| Opcode::Jle => {
|
||||
if let Token::Symbol(symbol) = node.arg(0).unwrap() {
|
||||
if let Some(address) = symbol_table.get(&symbol) {
|
||||
node.tokens[0] = Token::Immediate(*address);
|
||||
} else {
|
||||
return Err(AssembleError::UndefinedSymbol(symbol.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_symbol_table(
|
||||
nodes: &Vec<Node>,
|
||||
) -> Result<HashMap<Symbol, u32>, AssembleError> {
|
||||
let mut table = HashMap::new();
|
||||
|
||||
for (i, node) in nodes.iter().enumerate() {
|
||||
if let Some(symbol) = node.label() {
|
||||
table.insert(symbol, 4 * i as u32);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(table)
|
||||
}
|
||||
|
||||
pub fn resolve_dependencies(mut nodes: Vec<Node>) -> Result<Vec<Node>, AssembleError> {
|
||||
// first we get a list of imports
|
||||
let mut dependencies = Vec::new();
|
||||
for node in &nodes {
|
||||
if let Opcode::Include = node.1 {
|
||||
if let Opcode::Include = node.opcode() {
|
||||
// we want the path, and the name
|
||||
let name = if let Token::Symbol(name) = node.2.get(0).unwrap() {
|
||||
let name = if let Token::Symbol(name) = node.arg(0).unwrap() {
|
||||
name.name.clone()
|
||||
} else {
|
||||
unreachable!()
|
||||
}; //node.2.get(0).unwrap()
|
||||
let path = if let Token::StringLit(path) = node.2.get(1).unwrap() {
|
||||
let path = if let Token::StringLit(path) = node.arg(1).unwrap() {
|
||||
path
|
||||
} else {
|
||||
unreachable!()
|
||||
@@ -32,7 +91,9 @@ pub fn resolve_dependencies(mut nodes: Vec<Node>) -> Result<Vec<Node>, AssembleE
|
||||
// now we resolve the symbols on all the nodes
|
||||
// we need to check all operands for unresolved signals
|
||||
for (i, node) in nodes.clone().iter().enumerate() {
|
||||
let Node(_, _, operands) = node;
|
||||
let Node {
|
||||
tokens: operands, ..
|
||||
} = node;
|
||||
for (j, token) in operands.iter().enumerate() {
|
||||
if let Token::Symbol(symbol) = token {
|
||||
for d in &dependencies {
|
||||
@@ -53,7 +114,7 @@ pub fn resolve_dependencies(mut nodes: Vec<Node>) -> Result<Vec<Node>, AssembleE
|
||||
}
|
||||
|
||||
for (i, j, symbol) in changes {
|
||||
nodes[i as usize].2[j as usize] = Token::Symbol(symbol);
|
||||
nodes[i as usize].tokens[j as usize] = Token::Symbol(symbol);
|
||||
}
|
||||
|
||||
Ok(nodes)
|
||||
|
||||
Reference in New Issue
Block a user