Signed-off-by: ale <ale@manalejandro.com>
Este commit está contenido en:
ale
2025-08-23 11:48:39 +02:00
padre 39587e85d4
commit f2047ef283
Se han modificado 10 ficheros con 1003 adiciones y 55 borrados

Ver fichero

@@ -20,6 +20,12 @@
- **Seguridad**: Detección temprana de errores y manejo seguro de memoria
- **Velocidad**: Compilación rápida con paralelización cuando es posible
## ⚠️ Limitaciones Actuales
- **Bibliotecas estándar**: No incluye implementación completa de la biblioteca estándar de C
- **Headers del sistema**: Actualmente no procesa headers complejos del sistema
- **Funciones estándar**: `printf` y otras funciones estándar requieren enlaces externos
## 🏗️ Arquitecturas Soportadas
| Arquitectura | Estado | Descripción |
@@ -114,7 +120,7 @@ alecc --static programa.c -o programa_static
#### Inclusión de Headers
```bash
# Directorios de headers adicionales
alecc -I./include -I/usr/local/include programa.c -o programa
alecc -I/usr/local/include programa.c -o programa
# Definir macros
alecc -DDEBUG -DVERSION=1.0 programa.c -o programa

Ver fichero

@@ -1,4 +1,4 @@
use crate::parser::{Program, Function, Expression, Statement, Type, BinaryOperator};
use crate::parser::{Program, Function, Expression, Statement, Type, BinaryOperator, UnaryOperator};
use crate::targets::Target;
use crate::error::{AleccError, Result};
use std::collections::HashMap;
@@ -9,6 +9,10 @@ pub struct CodeGenerator {
label_counter: usize,
string_literals: HashMap<String, String>,
current_function_params: Vec<(String, i32)>, // (name, stack_offset)
epilogue_emitted: bool,
local_variables: HashMap<String, i32>, // (name, stack_offset)
stack_offset: i32, // Current stack offset for local variables
last_call_stack_cleanup: usize, // Stack bytes to clean up after last call
}
impl CodeGenerator {
@@ -19,10 +23,19 @@ impl CodeGenerator {
label_counter: 0,
string_literals: HashMap::new(),
current_function_params: Vec::new(),
epilogue_emitted: false,
local_variables: HashMap::new(),
stack_offset: 0,
last_call_stack_cleanup: 0,
}
}
pub fn generate(&mut self, program: &Program) -> Result<String> {
// First pass: collect all string literals
for function in &program.functions {
self.collect_string_literals_from_statement(&function.body)?;
}
self.emit_header();
// Generate string literals section
@@ -66,8 +79,9 @@ impl CodeGenerator {
self.emit_line(" push rbp");
self.emit_line(" mov rbp, rsp");
// Reserve space for temporary operations (prevents stack corruption)
self.emit_line(" sub rsp, 128");
// Reserve space for temporary operations (ensures proper stack alignment)
// 120 bytes = 15*8, so after rbp push (8 bytes), total is 128 bytes = multiple of 16
self.emit_line(" sub rsp, 120");
// Call main function
self.emit_line(" call main");
@@ -97,11 +111,27 @@ impl CodeGenerator {
}
fn generate_function(&mut self, function: &Function) -> Result<()> {
// Check if function has a body (implementation) or is just a declaration
match &function.body {
Statement::Block(statements) if statements.is_empty() => {
// This is a forward declaration, generate an external reference
self.emit_line(&format!(".extern {}", function.name));
return Ok(());
}
_ => {
// This is a function definition, generate the actual function
}
}
self.emit_line(&format!(".globl {}", function.name));
self.emit_line(&format!("{}:", function.name));
// Set up parameter tracking
self.current_function_params.clear();
self.local_variables.clear();
// Start local variables after parameters to avoid collision
self.stack_offset = -(function.parameters.len() as i32 * 8);
self.epilogue_emitted = false;
// Function prologue
self.emit_function_prologue(&function.parameters)?;
@@ -109,7 +139,8 @@ impl CodeGenerator {
// Function body
self.generate_statement(&function.body)?;
// Function epilogue (if no explicit return)
// Function epilogue (always ensure we have a proper function ending)
// This handles cases where there might not be explicit returns in all paths
self.emit_function_epilogue()?;
self.emit_line("");
@@ -122,9 +153,11 @@ impl CodeGenerator {
self.emit_line(" push ebp");
self.emit_line(" mov ebp, esp");
// Reserve space for parameters + 128 bytes for temporaries
let stack_space = parameters.len() * 4 + 128;
self.emit_line(&format!(" sub esp, {}", stack_space));
// Reserve space for parameters only (no extra temporaries for now)
let stack_space = parameters.len() * 4;
if stack_space > 0 {
self.emit_line(&format!(" sub esp, {}", stack_space));
}
// Store parameters from stack (i386 calling convention)
for (i, (name, _)) in parameters.iter().enumerate() {
@@ -139,9 +172,12 @@ impl CodeGenerator {
self.emit_line(" push rbp");
self.emit_line(" mov rbp, rsp");
// Reserve space for parameters + 128 bytes for temporaries
let stack_space = parameters.len() * 8 + 128;
self.emit_line(&format!(" sub rsp, {}", stack_space));
// Reserve space for parameters + ensure 16-byte alignment
let stack_space = parameters.len() * 8;
// Always reserve at least 8 bytes to maintain 16-byte alignment after rbp push
let min_space = if stack_space == 0 { 8 } else { stack_space };
let aligned_space = ((min_space + 15) / 16) * 16; // Round up to 16-byte boundary
self.emit_line(&format!(" sub rsp, {}", aligned_space));
// Store parameters from registers (x86_64 calling convention)
let param_registers = ["rdi", "rsi", "rdx", "rcx", "r8", "r9"];
@@ -163,8 +199,11 @@ impl CodeGenerator {
self.emit_line(" stp x29, x30, [sp, #-16]!");
self.emit_line(" mov x29, sp");
let stack_space = (parameters.len() * 8 + 128 + 15) & !15; // 16-byte aligned
self.emit_line(&format!(" sub sp, sp, #{}", stack_space));
let stack_space = parameters.len() * 8;
if stack_space > 0 {
let aligned_space = (stack_space + 15) & !15; // 16-byte aligned
self.emit_line(&format!(" sub sp, sp, #{}", aligned_space));
}
// Store parameters from registers (ARM64 calling convention)
for (i, (name, _)) in parameters.iter().enumerate() {
@@ -186,6 +225,10 @@ impl CodeGenerator {
}
fn emit_function_epilogue(&mut self) -> Result<()> {
if self.epilogue_emitted {
return Ok(()); // Don't emit duplicate epilogues
}
match self.target {
Target::I386 => {
self.emit_line(" mov esp, ebp");
@@ -203,6 +246,32 @@ impl CodeGenerator {
self.emit_line(" ret");
}
}
self.epilogue_emitted = true;
Ok(())
}
fn emit_function_epilogue_force(&mut self) -> Result<()> {
// Force emit epilogue regardless of epilogue_emitted flag
match self.target {
Target::I386 => {
self.emit_line(" mov esp, ebp");
self.emit_line(" pop ebp");
self.emit_line(" ret");
}
Target::Amd64 => {
self.emit_line(" mov rsp, rbp");
self.emit_line(" pop rbp");
self.emit_line(" ret");
}
Target::Arm64 => {
self.emit_line(" mov sp, x29");
self.emit_line(" ldp x29, x30, [sp], #16");
self.emit_line(" ret");
}
}
self.epilogue_emitted = true;
Ok(())
}
@@ -211,6 +280,37 @@ impl CodeGenerator {
Statement::Expression(expr) => {
self.generate_expression(expr)?;
}
Statement::Declaration { name, var_type, initializer } => {
// Calculate space needed based on type
let size = match var_type {
Type::Array(_, Some(length)) => length * 8, // Assuming 8-byte elements
Type::Array(_, None) => 80, // Default size for unsized arrays
_ => 8, // Default 8 bytes for simple types
};
// Allocate space for variable/array
self.stack_offset -= size as i32;
let var_offset = self.stack_offset;
// Store variable name and offset for later reference
self.local_variables.insert(name.clone(), var_offset);
if let Some(init_expr) = initializer {
self.generate_expression(init_expr)?;
// Store the value in the local variable slot
match self.target {
Target::Amd64 => {
self.emit_line(&format!(" mov QWORD PTR [rbp + {}], rax", var_offset));
}
Target::I386 => {
self.emit_line(&format!(" mov DWORD PTR [ebp + {}], eax", var_offset));
}
Target::Arm64 => {
self.emit_line(&format!(" str x0, [x29, #{}]", var_offset));
}
}
}
}
Statement::Return(expr) => {
if let Some(expr) = expr {
self.generate_expression(expr)?;
@@ -227,7 +327,8 @@ impl CodeGenerator {
}
}
}
self.emit_function_epilogue()?;
// Force emit epilogue for each return statement
self.emit_function_epilogue_force()?;
}
Statement::Block(statements) => {
for stmt in statements {
@@ -246,7 +347,14 @@ impl CodeGenerator {
self.emit_line(&format!("{}:", else_label));
if let Some(else_stmt) = else_stmt {
// Reset epilogue flag for else branch in case it contains a return
let saved_epilogue_state = self.epilogue_emitted;
self.epilogue_emitted = false;
self.generate_statement(else_stmt)?;
// If else branch didn't emit epilogue, restore the saved state
if !self.epilogue_emitted {
self.epilogue_emitted = saved_epilogue_state;
}
}
self.emit_line(&format!("{}:", end_label));
@@ -264,6 +372,34 @@ impl CodeGenerator {
self.emit_line(&format!("{}:", end_label));
}
Statement::For { init, condition, increment, body } => {
// Generate initialization
if let Some(init_stmt) = init {
self.generate_statement(init_stmt)?;
}
let loop_label = self.new_label("forloop");
let end_label = self.new_label("endfor");
self.emit_line(&format!("{}:", loop_label));
// Generate condition check
if let Some(cond_expr) = condition {
self.generate_expression(cond_expr)?;
self.emit_conditional_jump(false, &end_label)?;
}
// Generate body
self.generate_statement(body)?;
// Generate increment
if let Some(inc_expr) = increment {
self.generate_expression(inc_expr)?;
}
self.emit_jump(&loop_label)?;
self.emit_line(&format!("{}:", end_label));
}
_ => {
// Other statements not implemented yet
return Err(AleccError::CodegenError {
@@ -319,6 +455,19 @@ impl CodeGenerator {
self.emit_line(&format!(" ldr x0, [x29, #{}]", offset));
}
}
} else if let Some(offset) = self.local_variables.get(name) {
// Load local variable from stack
match self.target {
Target::I386 => {
self.emit_line(&format!(" mov eax, DWORD PTR [ebp + {}]", offset));
}
Target::Amd64 => {
self.emit_line(&format!(" mov rax, QWORD PTR [rbp + {}]", offset));
}
Target::Arm64 => {
self.emit_line(&format!(" ldr x0, [x29, #{}]", offset));
}
}
} else {
// Load global variable
match self.target {
@@ -350,31 +499,61 @@ impl CodeGenerator {
// x86_64: first 6 args in registers, rest on stack
let param_registers = ["rdi", "rsi", "rdx", "rcx", "r8", "r9"];
// Generate arguments and store in registers/stack
for (i, arg) in arguments.iter().enumerate() {
self.generate_expression(arg)?;
if i < param_registers.len() {
// Move to parameter register
self.emit_line(&format!(" mov {}, rax", param_registers[i]));
} else {
// Push to stack (reverse order for stack args)
// Ensure stack alignment before function call
// Stack must be 16-byte aligned before 'call' instruction
// Since 'call' pushes 8 bytes (return address), we need stack to be 8 bytes off 16-byte boundary
let stack_args = if arguments.len() > param_registers.len() { arguments.len() - param_registers.len() } else { 0 };
let mut stack_cleanup_size = 0;
// Handle stack arguments if any
if stack_args > 0 {
let total_stack_bytes = stack_args * 8;
// Ensure alignment: if total_stack_bytes is odd multiple of 8, add 8 bytes for alignment
if (total_stack_bytes / 8) % 2 != 0 {
self.emit_line(" sub rsp, 8 # Stack alignment");
stack_cleanup_size += 8;
}
stack_cleanup_size += stack_args * 8;
}
// Note: No additional alignment for register-only calls since function prologue handles it
// First, save any arguments that go on the stack (in reverse order)
if arguments.len() > param_registers.len() {
for arg in arguments.iter().skip(param_registers.len()).rev() {
self.generate_expression(arg)?;
self.emit_line(" push rax");
}
}
// Then handle register arguments in reverse order to avoid overwriting
let reg_args: Vec<_> = arguments.iter().take(param_registers.len()).collect();
for (i, arg) in reg_args.iter().enumerate().rev() {
self.generate_expression(arg)?;
self.emit_line(&format!(" mov {}, rax", param_registers[i]));
}
// Store cleanup size for later use
self.last_call_stack_cleanup = stack_cleanup_size;
}
Target::Arm64 => {
// ARM64: first 8 args in x0-x7, rest on stack
for (i, arg) in arguments.iter().enumerate() {
self.generate_expression(arg)?;
if i < 8 {
if i > 0 {
self.emit_line(&format!(" mov x{}, x0", i));
}
// x0 already has the result for first argument
} else {
// Save stack arguments first
if arguments.len() > 8 {
for arg in arguments.iter().skip(8).rev() {
self.generate_expression(arg)?;
self.emit_line(" str x0, [sp, #-16]!");
}
}
// Then handle register arguments in reverse order
let reg_args: Vec<_> = arguments.iter().take(8).collect();
for (i, arg) in reg_args.iter().enumerate().rev() {
self.generate_expression(arg)?;
if i > 0 {
self.emit_line(&format!(" mov x{}, x0", i));
}
// x0 already has the result for first argument
}
}
}
@@ -395,10 +574,9 @@ impl CodeGenerator {
}
}
Target::Amd64 => {
// Clean up stack arguments (if any)
let stack_args = if arguments.len() > 6 { arguments.len() - 6 } else { 0 };
if stack_args > 0 {
self.emit_line(&format!(" add rsp, {}", stack_args * 8));
// Clean up stack using stored cleanup size
if self.last_call_stack_cleanup > 0 {
self.emit_line(&format!(" add rsp, {}", self.last_call_stack_cleanup));
}
}
Target::Arm64 => {
@@ -441,6 +619,11 @@ impl CodeGenerator {
self.emit_line(" cdq"); // Sign extend eax to edx:eax
self.emit_line(" idiv ebx");
}
BinaryOperator::Modulo => {
self.emit_line(" cdq"); // Sign extend eax to edx:eax
self.emit_line(" idiv ebx");
self.emit_line(" mov eax, edx"); // Remainder is in edx
}
_ => {
return Err(AleccError::CodegenError {
message: format!("Binary operator {:?} not implemented for i386", operator),
@@ -458,6 +641,11 @@ impl CodeGenerator {
self.emit_line(" cqo"); // Sign extend rax to rdx:rax
self.emit_line(" idiv rbx");
}
BinaryOperator::Modulo => {
self.emit_line(" cqo"); // Sign extend rax to rdx:rax
self.emit_line(" idiv rbx");
self.emit_line(" mov rax, rdx"); // Remainder is in rdx
}
// Comparison operators
BinaryOperator::Equal => {
self.emit_line(" cmp rax, rbx");
@@ -489,10 +677,35 @@ impl CodeGenerator {
self.emit_line(" setge al");
self.emit_line(" movzx rax, al");
}
_ => {
return Err(AleccError::CodegenError {
message: format!("Binary operator {:?} not implemented for amd64", operator),
});
// Logical operators
BinaryOperator::LogicalAnd => {
self.emit_line(" test rax, rax");
self.emit_line(" setne al");
self.emit_line(" test rbx, rbx");
self.emit_line(" setne bl");
self.emit_line(" and al, bl");
self.emit_line(" movzx rax, al");
}
BinaryOperator::LogicalOr => {
self.emit_line(" test rax, rax");
self.emit_line(" setne al");
self.emit_line(" test rbx, rbx");
self.emit_line(" setne bl");
self.emit_line(" or al, bl");
self.emit_line(" movzx rax, al");
}
// Bitwise operators
BinaryOperator::BitwiseAnd => self.emit_line(" and rax, rbx"),
BinaryOperator::BitwiseOr => self.emit_line(" or rax, rbx"),
BinaryOperator::BitwiseXor => self.emit_line(" xor rax, rbx"),
// Shift operators
BinaryOperator::LeftShift => {
self.emit_line(" mov rcx, rbx"); // Shift count in rcx
self.emit_line(" shl rax, cl");
}
BinaryOperator::RightShift => {
self.emit_line(" mov rcx, rbx"); // Shift count in rcx
self.emit_line(" sar rax, cl"); // Arithmetic right shift
}
}
}
@@ -503,6 +716,10 @@ impl CodeGenerator {
BinaryOperator::Subtract => self.emit_line(" sub x0, x0, x1"),
BinaryOperator::Multiply => self.emit_line(" mul x0, x0, x1"),
BinaryOperator::Divide => self.emit_line(" sdiv x0, x0, x1"),
BinaryOperator::Modulo => {
self.emit_line(" sdiv x2, x0, x1"); // x2 = x0 / x1
self.emit_line(" msub x0, x2, x1, x0"); // x0 = x0 - (x2 * x1)
}
_ => {
return Err(AleccError::CodegenError {
message: format!("Binary operator {:?} not implemented for arm64", operator),
@@ -512,6 +729,322 @@ impl CodeGenerator {
}
}
}
Expression::Unary { operator, operand } => {
match operator {
UnaryOperator::Minus => {
self.generate_expression(operand)?;
match self.target {
Target::I386 => {
self.emit_line(" neg eax");
}
Target::Amd64 => {
self.emit_line(" neg rax");
}
Target::Arm64 => {
self.emit_line(" neg x0, x0");
}
}
}
UnaryOperator::Plus => {
// Plus is a no-op, just generate the operand
self.generate_expression(operand)?;
}
UnaryOperator::LogicalNot => {
self.generate_expression(operand)?;
match self.target {
Target::I386 => {
self.emit_line(" test eax, eax");
self.emit_line(" setz al");
self.emit_line(" movzx eax, al");
}
Target::Amd64 => {
self.emit_line(" test rax, rax");
self.emit_line(" setz al");
self.emit_line(" movzx rax, al");
}
Target::Arm64 => {
self.emit_line(" cmp x0, #0");
self.emit_line(" cset x0, eq");
}
}
}
UnaryOperator::BitwiseNot => {
self.generate_expression(operand)?;
match self.target {
Target::I386 => {
self.emit_line(" not eax");
}
Target::Amd64 => {
self.emit_line(" not rax");
}
Target::Arm64 => {
self.emit_line(" mvn x0, x0");
}
}
}
UnaryOperator::PreIncrement => {
// Load variable, increment, store back, and leave incremented value in register
if let Expression::Identifier(name) = operand.as_ref() {
if let Some(&offset) = self.local_variables.get(name) {
match self.target {
Target::I386 => {
self.emit_line(&format!(" inc DWORD PTR [ebp + {}]", offset));
self.emit_line(&format!(" mov eax, DWORD PTR [ebp + {}]", offset));
}
Target::Amd64 => {
self.emit_line(&format!(" inc QWORD PTR [rbp + {}]", offset));
self.emit_line(&format!(" mov rax, QWORD PTR [rbp + {}]", offset));
}
Target::Arm64 => {
self.emit_line(&format!(" ldr x0, [x29, #{}]", offset));
self.emit_line(" add x0, x0, #1");
self.emit_line(&format!(" str x0, [x29, #{}]", offset));
}
}
} else {
return Err(AleccError::CodegenError {
message: format!("Undefined variable: {}", name),
});
}
} else {
return Err(AleccError::CodegenError {
message: "Pre-increment can only be applied to variables".to_string(),
});
}
}
UnaryOperator::PostIncrement => {
// Load variable, store incremented value, but leave original value in register
if let Expression::Identifier(name) = operand.as_ref() {
if let Some(&offset) = self.local_variables.get(name) {
match self.target {
Target::I386 => {
self.emit_line(&format!(" mov eax, DWORD PTR [ebp + {}]", offset));
self.emit_line(&format!(" inc DWORD PTR [ebp + {}]", offset));
}
Target::Amd64 => {
self.emit_line(&format!(" mov rax, QWORD PTR [rbp + {}]", offset));
self.emit_line(&format!(" inc QWORD PTR [rbp + {}]", offset));
}
Target::Arm64 => {
self.emit_line(&format!(" ldr x0, [x29, #{}]", offset));
self.emit_line(&format!(" ldr x1, [x29, #{}]", offset));
self.emit_line(" add x1, x1, #1");
self.emit_line(&format!(" str x1, [x29, #{}]", offset));
}
}
} else {
return Err(AleccError::CodegenError {
message: format!("Undefined variable: {}", name),
});
}
} else {
return Err(AleccError::CodegenError {
message: "Post-increment can only be applied to variables".to_string(),
});
}
}
UnaryOperator::PreDecrement => {
// Similar to PreIncrement but with decrement
if let Expression::Identifier(name) = operand.as_ref() {
if let Some(&offset) = self.local_variables.get(name) {
match self.target {
Target::I386 => {
self.emit_line(&format!(" dec DWORD PTR [ebp + {}]", offset));
self.emit_line(&format!(" mov eax, DWORD PTR [ebp + {}]", offset));
}
Target::Amd64 => {
self.emit_line(&format!(" dec QWORD PTR [rbp + {}]", offset));
self.emit_line(&format!(" mov rax, QWORD PTR [rbp + {}]", offset));
}
Target::Arm64 => {
self.emit_line(&format!(" ldr x0, [x29, #{}]", offset));
self.emit_line(" sub x0, x0, #1");
self.emit_line(&format!(" str x0, [x29, #{}]", offset));
}
}
} else {
return Err(AleccError::CodegenError {
message: format!("Undefined variable: {}", name),
});
}
} else {
return Err(AleccError::CodegenError {
message: "Pre-decrement can only be applied to variables".to_string(),
});
}
}
UnaryOperator::PostDecrement => {
// Similar to PostIncrement but with decrement
if let Expression::Identifier(name) = operand.as_ref() {
if let Some(&offset) = self.local_variables.get(name) {
match self.target {
Target::I386 => {
self.emit_line(&format!(" mov eax, DWORD PTR [ebp + {}]", offset));
self.emit_line(&format!(" dec DWORD PTR [ebp + {}]", offset));
}
Target::Amd64 => {
self.emit_line(&format!(" mov rax, QWORD PTR [rbp + {}]", offset));
self.emit_line(&format!(" dec QWORD PTR [rbp + {}]", offset));
}
Target::Arm64 => {
self.emit_line(&format!(" ldr x0, [x29, #{}]", offset));
self.emit_line(&format!(" ldr x1, [x29, #{}]", offset));
self.emit_line(" sub x1, x1, #1");
self.emit_line(&format!(" str x1, [x29, #{}]", offset));
}
}
} else {
return Err(AleccError::CodegenError {
message: format!("Undefined variable: {}", name),
});
}
} else {
return Err(AleccError::CodegenError {
message: "Post-decrement can only be applied to variables".to_string(),
});
}
}
UnaryOperator::AddressOf => {
// Get address of a variable
if let Expression::Identifier(name) = operand.as_ref() {
if let Some(&offset) = self.local_variables.get(name) {
match self.target {
Target::I386 => {
self.emit_line(&format!(" lea eax, [ebp + {}]", offset));
}
Target::Amd64 => {
self.emit_line(&format!(" lea rax, [rbp + {}]", offset));
}
Target::Arm64 => {
self.emit_line(&format!(" add x0, x29, #{}", offset));
}
}
} else {
return Err(AleccError::CodegenError {
message: format!("Undefined variable: {}", name),
});
}
} else {
return Err(AleccError::CodegenError {
message: "Address-of can only be applied to variables".to_string(),
});
}
}
UnaryOperator::Dereference => {
// Dereference a pointer (load value from address)
self.generate_expression(operand)?; // Get the address
match self.target {
Target::I386 => {
self.emit_line(" mov eax, DWORD PTR [eax]");
}
Target::Amd64 => {
self.emit_line(" mov rax, QWORD PTR [rax]");
}
Target::Arm64 => {
self.emit_line(" ldr x0, [x0]");
}
}
}
}
}
Expression::Index { array, index } => {
// Generate the array base address
if let Expression::Identifier(array_name) = array.as_ref() {
if let Some(&base_offset) = self.local_variables.get(array_name) {
// Generate the index expression
self.generate_expression(index)?;
// Calculate the array element address: base + index * element_size
match self.target {
Target::Amd64 => {
// Multiply index by 8 (assuming int is 8 bytes for simplicity)
self.emit_line(" imul rax, 8"); // Use imul instead of mul
// Add base address
self.emit_line(&format!(" lea rbx, [rbp + {}]", base_offset));
self.emit_line(" add rax, rbx");
// Load the value at that address
self.emit_line(" mov rax, QWORD PTR [rax]");
}
Target::I386 => {
// Similar for 32-bit
self.emit_line(" imul eax, 4"); // Use imul instead of mul
self.emit_line(&format!(" lea ebx, [ebp + {}]", base_offset));
self.emit_line(" add eax, ebx");
self.emit_line(" mov eax, DWORD PTR [eax]");
}
Target::Arm64 => {
// ARM64 implementation
self.emit_line(" lsl x0, x0, #3"); // multiply by 8
self.emit_line(&format!(" add x1, x29, #{}", base_offset));
self.emit_line(" add x0, x0, x1");
self.emit_line(" ldr x0, [x0]");
}
}
} else {
return Err(AleccError::CodegenError {
message: format!("Array '{}' not found", array_name),
});
}
} else {
return Err(AleccError::CodegenError {
message: "Complex array expressions not yet supported".to_string(),
});
}
}
Expression::Assignment { target, operator, value } => {
// Handle compound assignment operators
match operator {
crate::parser::AssignmentOperator::Assign => {
// Simple assignment: target = value
self.generate_expression(value)?;
self.store_in_target(target)?;
}
crate::parser::AssignmentOperator::PlusAssign => {
// target += value => target = target + value
self.load_from_target(target)?; // Load current value
self.emit_line(" push rax"); // Save current value
self.generate_expression(value)?; // Generate RHS
self.emit_line(" pop rbx"); // Restore current value
self.emit_line(" add rax, rbx"); // target + value
self.store_in_target(target)?; // Store result
}
crate::parser::AssignmentOperator::MinusAssign => {
// target -= value => target = target - value
self.load_from_target(target)?;
self.emit_line(" push rax");
self.generate_expression(value)?;
self.emit_line(" mov rbx, rax"); // RHS in rbx
self.emit_line(" pop rax"); // Current value in rax
self.emit_line(" sub rax, rbx"); // target - value
self.store_in_target(target)?;
}
crate::parser::AssignmentOperator::MultiplyAssign => {
// target *= value => target = target * value
self.load_from_target(target)?;
self.emit_line(" push rax");
self.generate_expression(value)?;
self.emit_line(" pop rbx");
self.emit_line(" imul rax, rbx"); // target * value
self.store_in_target(target)?;
}
crate::parser::AssignmentOperator::DivideAssign => {
// target /= value => target = target / value
self.load_from_target(target)?;
self.emit_line(" push rax");
self.generate_expression(value)?;
self.emit_line(" mov rbx, rax"); // RHS in rbx
self.emit_line(" pop rax"); // Current value in rax
self.emit_line(" cqo"); // Sign extend for division
self.emit_line(" idiv rbx"); // target / value
self.store_in_target(target)?;
}
_ => {
return Err(AleccError::CodegenError {
message: "Assignment operator not implemented".to_string(),
});
}
}
}
_ => {
return Err(AleccError::CodegenError {
message: "Expression type not implemented".to_string(),
@@ -521,6 +1054,7 @@ impl CodeGenerator {
Ok(())
}
#[allow(dead_code)]
fn push_argument(&mut self, _index: usize) -> Result<()> {
match self.target {
Target::I386 => {
@@ -538,6 +1072,84 @@ impl CodeGenerator {
Ok(())
}
fn load_from_target(&mut self, target: &Expression) -> Result<()> {
// Load the current value of target into rax
if let Expression::Identifier(name) = target {
if let Some(&offset) = self.local_variables.get(name) {
match self.target {
Target::Amd64 => {
self.emit_line(&format!(" mov rax, QWORD PTR [rbp + {}]", offset));
}
Target::I386 => {
self.emit_line(&format!(" mov eax, DWORD PTR [ebp + {}]", offset));
}
Target::Arm64 => {
self.emit_line(&format!(" ldr x0, [x29, #{}]", offset));
}
}
} else {
// Global variable
match self.target {
Target::Amd64 => {
self.emit_line(&format!(" mov rax, QWORD PTR [{}]", name));
}
Target::I386 => {
self.emit_line(&format!(" mov eax, DWORD PTR [{}]", name));
}
Target::Arm64 => {
self.emit_line(&format!(" adrp x1, {}", name));
self.emit_line(&format!(" add x1, x1, :lo12:{}", name));
self.emit_line(" ldr x0, [x1]");
}
}
}
} else {
return Err(AleccError::CodegenError {
message: "Complex assignment targets not supported for compound operators yet".to_string(),
});
}
Ok(())
}
fn store_in_target(&mut self, target: &Expression) -> Result<()> {
// Store rax value into target
if let Expression::Identifier(name) = target {
if let Some(&offset) = self.local_variables.get(name) {
match self.target {
Target::Amd64 => {
self.emit_line(&format!(" mov QWORD PTR [rbp + {}], rax", offset));
}
Target::I386 => {
self.emit_line(&format!(" mov DWORD PTR [ebp + {}], eax", offset));
}
Target::Arm64 => {
self.emit_line(&format!(" str x0, [x29, #{}]", offset));
}
}
} else {
// Global variable
match self.target {
Target::Amd64 => {
self.emit_line(&format!(" mov QWORD PTR [{}], rax", name));
}
Target::I386 => {
self.emit_line(&format!(" mov DWORD PTR [{}], eax", name));
}
Target::Arm64 => {
self.emit_line(&format!(" adrp x1, {}", name));
self.emit_line(&format!(" add x1, x1, :lo12:{}", name));
self.emit_line(" str x0, [x1]");
}
}
}
} else {
return Err(AleccError::CodegenError {
message: "Complex assignment targets not supported for compound operators yet".to_string(),
});
}
Ok(())
}
fn emit_conditional_jump(&mut self, condition: bool, label: &str) -> Result<()> {
let instruction = if condition { "jnz" } else { "jz" };
@@ -620,4 +1232,86 @@ impl CodeGenerator {
.replace('\t', "\\t")
.replace('\r', "\\r")
}
fn collect_string_literals_from_statement(&mut self, stmt: &Statement) -> Result<()> {
match stmt {
Statement::Expression(expr) => self.collect_string_literals_from_expression(expr),
Statement::Block(statements) => {
for stmt in statements {
self.collect_string_literals_from_statement(stmt)?;
}
Ok(())
}
Statement::Return(expr) => {
if let Some(expr) = expr {
self.collect_string_literals_from_expression(expr)?;
}
Ok(())
}
Statement::If { condition, then_stmt, else_stmt } => {
self.collect_string_literals_from_expression(condition)?;
self.collect_string_literals_from_statement(then_stmt)?;
if let Some(else_statement) = else_stmt {
self.collect_string_literals_from_statement(else_statement)?;
}
Ok(())
}
Statement::While { condition, body } => {
self.collect_string_literals_from_expression(condition)?;
self.collect_string_literals_from_statement(body)?;
Ok(())
}
Statement::For { init, condition, increment, body } => {
if let Some(init_stmt) = init {
self.collect_string_literals_from_statement(init_stmt)?;
}
if let Some(cond_expr) = condition {
self.collect_string_literals_from_expression(cond_expr)?;
}
if let Some(inc_expr) = increment {
self.collect_string_literals_from_expression(inc_expr)?;
}
self.collect_string_literals_from_statement(body)?;
Ok(())
}
Statement::Declaration { initializer, .. } => {
if let Some(expr) = initializer {
self.collect_string_literals_from_expression(expr)?;
}
Ok(())
}
_ => Ok(()) // Other statement types don't have expressions we need to collect
}
}
fn collect_string_literals_from_expression(&mut self, expr: &Expression) -> Result<()> {
match expr {
Expression::StringLiteral(value) => {
self.get_string_literal_label(value);
Ok(())
}
Expression::Binary { left, right, .. } => {
self.collect_string_literals_from_expression(left)?;
self.collect_string_literals_from_expression(right)?;
Ok(())
}
Expression::Unary { operand, .. } => {
self.collect_string_literals_from_expression(operand)?;
Ok(())
}
Expression::Call { function, arguments } => {
self.collect_string_literals_from_expression(function)?;
for arg in arguments {
self.collect_string_literals_from_expression(arg)?;
}
Ok(())
}
Expression::Assignment { target, value, .. } => {
self.collect_string_literals_from_expression(target)?;
self.collect_string_literals_from_expression(value)?;
Ok(())
}
_ => Ok(()) // Other expression types don't contain string literals
}
}
}

Ver fichero

@@ -16,6 +16,7 @@ pub enum AleccError {
message: String,
},
#[allow(dead_code)]
#[error("Semantic error: {message}")]
SemanticError { message: String },
@@ -37,6 +38,7 @@ pub enum AleccError {
#[error("Invalid argument: {message}")]
InvalidArgument { message: String },
#[allow(dead_code)]
#[error("Internal compiler error: {message}")]
InternalError { message: String },
}

Ver fichero

@@ -38,6 +38,7 @@ pub enum TokenType {
LeftBrace, RightBrace,
LeftBracket, RightBracket,
Semicolon, Comma,
Ellipsis, // ...
// Preprocessor
Hash, HashHash,
@@ -52,6 +53,7 @@ pub struct Token {
pub token_type: TokenType,
pub line: usize,
pub column: usize,
#[allow(dead_code)]
pub length: usize,
}
@@ -249,7 +251,22 @@ impl Lexer {
']' => Ok(Some(TokenType::RightBracket)),
';' => Ok(Some(TokenType::Semicolon)),
',' => Ok(Some(TokenType::Comma)),
'.' => Ok(Some(TokenType::Dot)),
'.' => {
if self.match_char('.') {
if self.match_char('.') {
Ok(Some(TokenType::Ellipsis)) // ...
} else {
// Error: .. is not valid
Err(crate::error::AleccError::ParseError {
line: self.line,
column: self.column,
message: "Invalid token '..'".to_string(),
})
}
} else {
Ok(Some(TokenType::Dot))
}
}
'?' => Ok(Some(TokenType::Question)),
':' => Ok(Some(TokenType::Colon)),
'#' => {

9
src/lib.rs Archivo normal
Ver fichero

@@ -0,0 +1,9 @@
pub mod lexer;
pub mod parser;
pub mod codegen;
pub mod targets;
pub mod compiler;
pub mod cli;
pub mod error;
pub mod optimizer;
pub mod linker;

Ver fichero

@@ -210,18 +210,15 @@ impl Linker {
command.push(lib.clone());
}
// Standard libraries - skip for now to avoid conflicts
// Our programs use custom runtime with syscalls
/*
// Standard libraries
if !self.static_link {
command.push("-lc".to_string());
}
*/
Ok(command)
}
fn add_standard_startup_files(&self, command: &mut Vec<String>) -> Result<()> {
fn add_standard_startup_files(&self, _command: &mut Vec<String>) -> Result<()> {
// Skip startup files when we have our own _start
// This prevents conflicts with our custom _start implementation
Ok(())
@@ -320,6 +317,7 @@ impl Linker {
Ok(())
}
#[allow(dead_code)]
pub async fn link_static_library(&self) -> Result<()> {
// Use ar to create static library
let mut command = vec!["ar".to_string(), "rcs".to_string()];

Ver fichero

@@ -225,8 +225,10 @@ impl Optimizer {
}
// Additional optimization passes that can be applied independently
#[allow(dead_code)]
pub struct OptimizationPasses;
#[allow(dead_code)]
impl OptimizationPasses {
pub fn constant_propagation(_program: &mut Program) -> Result<()> {
// TODO: Implement constant propagation

Ver fichero

@@ -12,34 +12,44 @@ pub enum Type {
Float,
Double,
Bool,
#[allow(dead_code)]
Pointer(Box<Type>),
#[allow(dead_code)]
Array(Box<Type>, Option<usize>),
#[allow(dead_code)]
Function {
return_type: Box<Type>,
parameters: Vec<Type>,
variadic: bool,
},
#[allow(dead_code)]
Struct {
name: String,
fields: Vec<(String, Type)>,
},
#[allow(dead_code)]
Union {
name: String,
fields: Vec<(String, Type)>,
},
#[allow(dead_code)]
Enum {
name: String,
variants: Vec<(String, i64)>,
},
#[allow(dead_code)]
Typedef(String, Box<Type>),
}
#[derive(Debug, Clone)]
pub enum Expression {
IntegerLiteral(i64),
#[allow(dead_code)]
FloatLiteral(f64),
StringLiteral(String),
#[allow(dead_code)]
CharLiteral(char),
#[allow(dead_code)]
BooleanLiteral(bool),
Identifier(String),
Binary {
@@ -55,6 +65,7 @@ pub enum Expression {
function: Box<Expression>,
arguments: Vec<Expression>,
},
#[allow(dead_code)]
Member {
object: Box<Expression>,
member: String,
@@ -64,16 +75,19 @@ pub enum Expression {
array: Box<Expression>,
index: Box<Expression>,
},
#[allow(dead_code)]
Cast {
target_type: Type,
expression: Box<Expression>,
},
#[allow(dead_code)]
Sizeof(Type),
Assignment {
target: Box<Expression>,
operator: AssignmentOperator,
value: Box<Expression>,
},
#[allow(dead_code)]
Conditional {
condition: Box<Expression>,
then_expr: Box<Expression>,
@@ -100,9 +114,13 @@ pub enum UnaryOperator {
#[derive(Debug, Clone)]
pub enum AssignmentOperator {
Assign, PlusAssign, MinusAssign, MultiplyAssign, DivideAssign, ModuloAssign,
BitwiseAndAssign, BitwiseOrAssign, BitwiseXorAssign,
LeftShiftAssign, RightShiftAssign,
Assign, PlusAssign, MinusAssign, MultiplyAssign, DivideAssign,
#[allow(dead_code)] ModuloAssign,
#[allow(dead_code)] BitwiseAndAssign,
#[allow(dead_code)] BitwiseOrAssign,
#[allow(dead_code)] BitwiseXorAssign,
#[allow(dead_code)] LeftShiftAssign,
#[allow(dead_code)] RightShiftAssign,
}
#[derive(Debug, Clone)]
@@ -129,36 +147,49 @@ pub enum Statement {
increment: Option<Expression>,
body: Box<Statement>,
},
#[allow(dead_code)]
DoWhile {
body: Box<Statement>,
condition: Expression,
},
#[allow(dead_code)]
Switch {
expression: Expression,
cases: Vec<(Option<Expression>, Vec<Statement>)>,
},
Return(Option<Expression>),
#[allow(dead_code)]
Break,
#[allow(dead_code)]
Continue,
#[allow(dead_code)]
Goto(String),
#[allow(dead_code)]
Label(String),
}
#[derive(Debug, Clone)]
pub struct Function {
pub name: String,
#[allow(dead_code)]
pub return_type: Type,
pub parameters: Vec<(String, Type)>,
pub body: Statement,
#[allow(dead_code)]
pub is_inline: bool,
#[allow(dead_code)]
pub is_static: bool,
#[allow(dead_code)]
pub is_extern: bool,
#[allow(dead_code)]
pub is_variadic: bool,
}
#[derive(Debug, Clone)]
pub struct Program {
pub functions: Vec<Function>,
pub global_variables: Vec<(String, Type, Option<Expression>)>,
#[allow(dead_code)]
pub type_definitions: HashMap<String, Type>,
}
@@ -215,6 +246,11 @@ impl Parser {
}
fn parse_type(&mut self) -> Result<Type> {
// Skip type qualifiers like const, volatile
while self.match_token(&TokenType::Const) || self.match_token(&TokenType::Volatile) {
// Just consume the qualifier for now
}
let mut base_type = match &self.advance()?.token_type {
TokenType::Void => Type::Void,
TokenType::Char => Type::Char,
@@ -242,6 +278,10 @@ impl Parser {
// Handle pointer declarators
while self.match_token(&TokenType::Multiply) {
// Skip const after *
while self.match_token(&TokenType::Const) || self.match_token(&TokenType::Volatile) {
// Just consume the qualifier for now
}
base_type = Type::Pointer(Box::new(base_type));
}
@@ -500,7 +540,14 @@ impl Parser {
self.consume(&TokenType::LeftParen, "Expected '(' after function name")?;
let mut parameters = Vec::new();
let mut is_variadic = false;
while !self.check(&TokenType::RightParen) && !self.is_at_end() {
if self.match_token(&TokenType::Ellipsis) {
is_variadic = true;
break;
}
let param_type = self.parse_type()?;
let param_name = if let TokenType::Identifier(name) = &self.advance()?.token_type {
name.clone()
@@ -537,6 +584,7 @@ impl Parser {
is_inline: false,
is_static: false,
is_extern: false,
is_variadic,
}))
}
@@ -593,7 +641,7 @@ impl Parser {
self.parse_block_statement()
} else if self.is_type(&self.current_token()?.token_type) {
// Variable declaration - convert to Statement format
let var_type = self.parse_type()?;
let mut var_type = self.parse_type()?;
let name = if let TokenType::Identifier(name) = &self.advance()?.token_type {
name.clone()
} else {
@@ -604,6 +652,24 @@ impl Parser {
});
};
// Check for array declaration
if self.match_token(&TokenType::LeftBracket) {
let size = if self.check(&TokenType::RightBracket) {
None
} else {
// Parse array size (should be a constant expression)
let size_expr = self.parse_expression()?;
if let Expression::IntegerLiteral(size) = size_expr {
Some(size as usize)
} else {
// For now, just use a default size if not a simple integer
Some(10)
}
};
self.consume(&TokenType::RightBracket, "Expected ']' after array size")?;
var_type = Type::Array(Box::new(var_type), size);
}
let initializer = if self.match_token(&TokenType::Assign) {
Some(self.parse_expression()?)
} else {
@@ -698,7 +764,50 @@ impl Parser {
}
fn parse_expression(&mut self) -> Result<Expression> {
self.parse_logical_or()
self.parse_assignment()
}
fn parse_assignment(&mut self) -> Result<Expression> {
let expr = self.parse_logical_or()?;
if self.match_token(&TokenType::Assign) {
let value = self.parse_assignment()?; // Right associative
return Ok(Expression::Assignment {
target: Box::new(expr),
operator: AssignmentOperator::Assign,
value: Box::new(value),
});
} else if self.match_token(&TokenType::PlusAssign) {
let value = self.parse_assignment()?;
return Ok(Expression::Assignment {
target: Box::new(expr),
operator: AssignmentOperator::PlusAssign,
value: Box::new(value),
});
} else if self.match_token(&TokenType::MinusAssign) {
let value = self.parse_assignment()?;
return Ok(Expression::Assignment {
target: Box::new(expr),
operator: AssignmentOperator::MinusAssign,
value: Box::new(value),
});
} else if self.match_token(&TokenType::MultiplyAssign) {
let value = self.parse_assignment()?;
return Ok(Expression::Assignment {
target: Box::new(expr),
operator: AssignmentOperator::MultiplyAssign,
value: Box::new(value),
});
} else if self.match_token(&TokenType::DivideAssign) {
let value = self.parse_assignment()?;
return Ok(Expression::Assignment {
target: Box::new(expr),
operator: AssignmentOperator::DivideAssign,
value: Box::new(value),
});
}
Ok(expr)
}
fn parse_logical_or(&mut self) -> Result<Expression> {
@@ -718,10 +827,58 @@ impl Parser {
}
fn parse_logical_and(&mut self) -> Result<Expression> {
let mut expr = self.parse_equality()?;
let mut expr = self.parse_bitwise_or()?;
while self.match_token(&TokenType::LogicalAnd) {
let operator = BinaryOperator::LogicalAnd;
let right = self.parse_bitwise_or()?;
expr = Expression::Binary {
left: Box::new(expr),
operator,
right: Box::new(right),
};
}
Ok(expr)
}
fn parse_bitwise_or(&mut self) -> Result<Expression> {
let mut expr = self.parse_bitwise_xor()?;
while self.match_token(&TokenType::BitwiseOr) {
let operator = BinaryOperator::BitwiseOr;
let right = self.parse_bitwise_xor()?;
expr = Expression::Binary {
left: Box::new(expr),
operator,
right: Box::new(right),
};
}
Ok(expr)
}
fn parse_bitwise_xor(&mut self) -> Result<Expression> {
let mut expr = self.parse_bitwise_and()?;
while self.match_token(&TokenType::BitwiseXor) {
let operator = BinaryOperator::BitwiseXor;
let right = self.parse_bitwise_and()?;
expr = Expression::Binary {
left: Box::new(expr),
operator,
right: Box::new(right),
};
}
Ok(expr)
}
fn parse_bitwise_and(&mut self) -> Result<Expression> {
let mut expr = self.parse_equality()?;
while self.match_token(&TokenType::BitwiseAnd) {
let operator = BinaryOperator::BitwiseAnd;
let right = self.parse_equality()?;
expr = Expression::Binary {
left: Box::new(expr),
@@ -754,7 +911,7 @@ impl Parser {
}
fn parse_comparison(&mut self) -> Result<Expression> {
let mut expr = self.parse_term()?;
let mut expr = self.parse_shift()?;
while self.match_tokens(&[TokenType::Greater, TokenType::GreaterEqual,
TokenType::Less, TokenType::LessEqual]) {
@@ -765,6 +922,26 @@ impl Parser {
TokenType::LessEqual => BinaryOperator::LessEqual,
_ => unreachable!(),
};
let right = self.parse_shift()?;
expr = Expression::Binary {
left: Box::new(expr),
operator,
right: Box::new(right),
};
}
Ok(expr)
}
fn parse_shift(&mut self) -> Result<Expression> {
let mut expr = self.parse_term()?;
while self.match_tokens(&[TokenType::LeftShift, TokenType::RightShift]) {
let operator = match self.previous()?.token_type {
TokenType::LeftShift => BinaryOperator::LeftShift,
TokenType::RightShift => BinaryOperator::RightShift,
_ => unreachable!(),
};
let right = self.parse_term()?;
expr = Expression::Binary {
left: Box::new(expr),
@@ -818,11 +995,16 @@ impl Parser {
}
fn parse_unary(&mut self) -> Result<Expression> {
if self.match_tokens(&[TokenType::LogicalNot, TokenType::Minus, TokenType::Plus]) {
if self.match_tokens(&[TokenType::LogicalNot, TokenType::Minus, TokenType::Plus, TokenType::Increment, TokenType::Decrement, TokenType::BitwiseAnd, TokenType::Multiply, TokenType::BitwiseNot]) {
let operator = match self.previous()?.token_type {
TokenType::LogicalNot => UnaryOperator::LogicalNot,
TokenType::Minus => UnaryOperator::Minus,
TokenType::Plus => UnaryOperator::Plus,
TokenType::Increment => UnaryOperator::PreIncrement,
TokenType::Decrement => UnaryOperator::PreDecrement,
TokenType::BitwiseAnd => UnaryOperator::AddressOf,
TokenType::Multiply => UnaryOperator::Dereference,
TokenType::BitwiseNot => UnaryOperator::BitwiseNot,
_ => unreachable!(),
};
let right = self.parse_unary()?;
@@ -838,8 +1020,30 @@ impl Parser {
fn parse_call(&mut self) -> Result<Expression> {
let mut expr = self.parse_primary()?;
while self.match_token(&TokenType::LeftParen) {
expr = self.finish_call(expr)?;
loop {
if self.match_token(&TokenType::LeftParen) {
expr = self.finish_call(expr)?;
} else if self.match_token(&TokenType::LeftBracket) {
// Array indexing
let index = self.parse_expression()?;
self.consume(&TokenType::RightBracket, "Expected ']' after array index")?;
expr = Expression::Index {
array: Box::new(expr),
index: Box::new(index),
};
} else if self.match_token(&TokenType::Increment) {
expr = Expression::Unary {
operator: UnaryOperator::PostIncrement,
operand: Box::new(expr),
};
} else if self.match_token(&TokenType::Decrement) {
expr = Expression::Unary {
operator: UnaryOperator::PostDecrement,
operand: Box::new(expr),
};
} else {
break;
}
}
Ok(expr)
@@ -898,8 +1102,12 @@ enum Declaration {
#[derive(Debug, Clone)]
enum StorageClass {
None,
#[allow(dead_code)]
Static,
#[allow(dead_code)]
Extern,
#[allow(dead_code)]
Auto,
#[allow(dead_code)]
Register,
}

Ver fichero

@@ -38,6 +38,7 @@ impl Target {
}
}
#[allow(dead_code)]
pub fn alignment(&self) -> usize {
match self {
Target::I386 => 4,
@@ -54,6 +55,7 @@ impl Target {
}
}
#[allow(dead_code)]
pub fn triple(&self) -> &'static str {
match self {
Target::I386 => "i386-unknown-linux-gnu",
@@ -62,6 +64,7 @@ impl Target {
}
}
#[allow(dead_code)]
pub fn assembler(&self) -> &'static str {
match self {
Target::I386 => "as --32",
@@ -70,6 +73,7 @@ impl Target {
}
}
#[allow(dead_code)]
pub fn linker(&self) -> &'static str {
match self {
Target::I386 => "ld -m elf_i386",
@@ -78,6 +82,7 @@ impl Target {
}
}
#[allow(dead_code)]
pub fn object_format(&self) -> &'static str {
match self {
Target::I386 => "elf32",
@@ -86,6 +91,7 @@ impl Target {
}
}
#[allow(dead_code)]
pub fn calling_convention(&self) -> CallingConvention {
match self {
Target::I386 => CallingConvention::Cdecl,
@@ -94,6 +100,7 @@ impl Target {
}
}
#[allow(dead_code)]
pub fn register_names(&self) -> RegisterSet {
match self {
Target::I386 => RegisterSet::X86_32,
@@ -103,6 +110,7 @@ impl Target {
}
}
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
pub enum CallingConvention {
Cdecl, // x86-32
@@ -110,6 +118,7 @@ pub enum CallingConvention {
Aapcs64, // ARM64
}
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
pub enum RegisterSet {
X86_32,
@@ -117,6 +126,7 @@ pub enum RegisterSet {
Aarch64,
}
#[allow(dead_code)]
impl RegisterSet {
pub fn general_purpose_registers(&self) -> &'static [&'static str] {
match self {
@@ -159,6 +169,7 @@ impl RegisterSet {
}
}
#[allow(dead_code)]
pub struct TargetInfo {
pub target: Target,
pub endianness: Endianness,
@@ -168,12 +179,14 @@ pub struct TargetInfo {
pub supports_pie: bool,
}
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
pub enum Endianness {
Little,
Big,
}
#[allow(dead_code)]
impl TargetInfo {
pub fn new(target: Target) -> Self {
let (word_size, max_align) = match target {

Ver fichero

@@ -1,6 +1,5 @@
#[cfg(test)]
mod tests {
use super::*;
use alecc::lexer::{Lexer, TokenType};
use alecc::parser::Parser;
use alecc::codegen::CodeGenerator;