diff --git a/README.md b/README.md index 6ec2913..a63184b 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/src/codegen.rs b/src/codegen.rs index d1f046b..f31609c 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -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, current_function_params: Vec<(String, i32)>, // (name, stack_offset) + epilogue_emitted: bool, + local_variables: HashMap, // (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 { + // 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 + } + } } diff --git a/src/error.rs b/src/error.rs index 337b2db..db11498 100644 --- a/src/error.rs +++ b/src/error.rs @@ -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 }, } diff --git a/src/lexer.rs b/src/lexer.rs index a02dda5..971f084 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -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)), '#' => { diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..65c148e --- /dev/null +++ b/src/lib.rs @@ -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; diff --git a/src/linker.rs b/src/linker.rs index 00f594f..d773f0d 100644 --- a/src/linker.rs +++ b/src/linker.rs @@ -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) -> Result<()> { + fn add_standard_startup_files(&self, _command: &mut Vec) -> 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()]; diff --git a/src/optimizer.rs b/src/optimizer.rs index 038e1d7..96f443c 100644 --- a/src/optimizer.rs +++ b/src/optimizer.rs @@ -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 diff --git a/src/parser.rs b/src/parser.rs index 516de90..65cc99b 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -12,34 +12,44 @@ pub enum Type { Float, Double, Bool, + #[allow(dead_code)] Pointer(Box), + #[allow(dead_code)] Array(Box, Option), + #[allow(dead_code)] Function { return_type: Box, parameters: Vec, 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), } #[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, arguments: Vec, }, + #[allow(dead_code)] Member { object: Box, member: String, @@ -64,16 +75,19 @@ pub enum Expression { array: Box, index: Box, }, + #[allow(dead_code)] Cast { target_type: Type, expression: Box, }, + #[allow(dead_code)] Sizeof(Type), Assignment { target: Box, operator: AssignmentOperator, value: Box, }, + #[allow(dead_code)] Conditional { condition: Box, then_expr: Box, @@ -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, body: Box, }, + #[allow(dead_code)] DoWhile { body: Box, condition: Expression, }, + #[allow(dead_code)] Switch { expression: Expression, cases: Vec<(Option, Vec)>, }, Return(Option), + #[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, pub global_variables: Vec<(String, Type, Option)>, + #[allow(dead_code)] pub type_definitions: HashMap, } @@ -215,6 +246,11 @@ impl Parser { } fn parse_type(&mut self) -> Result { + // 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 { - self.parse_logical_or() + self.parse_assignment() + } + + fn parse_assignment(&mut self) -> Result { + 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 { @@ -718,10 +827,58 @@ impl Parser { } fn parse_logical_and(&mut self) -> Result { - 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 { + 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 { + 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 { + 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 { - 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 { + 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 { - 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 { 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, } diff --git a/src/targets.rs b/src/targets.rs index d978bb1..f101239 100644 --- a/src/targets.rs +++ b/src/targets.rs @@ -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 { diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 6a49327..183ea39 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -1,6 +1,5 @@ #[cfg(test)] mod tests { - use super::*; use alecc::lexer::{Lexer, TokenType}; use alecc::parser::Parser; use alecc::codegen::CodeGenerator;