diff --git a/src/codegen/last/x86_64.rs b/src/codegen/last/x86_64.rs index 8cb90cd..497791c 100644 --- a/src/codegen/last/x86_64.rs +++ b/src/codegen/last/x86_64.rs @@ -152,9 +152,10 @@ pub fn emit_program(prog: &TacProgram) -> EmitResult { em.blank(); em.append_str(&emit_function(func, &strings)?); } - // Marca a stack como nao-executavel (boa pratica; evita aviso do linker e - // e o que o proprio GCC adiciona a saida assembly). + // Marca a stack como nao-executavel em formatos ELF. Essa secao nao + // existe no COFF usado pelo MinGW e tornaria o assembly invalido la. em.blank(); + #[cfg(not(target_os = "windows"))] em.raw(".section .note.GNU-stack,\"\",@progbits"); Ok(em.into_string()) } diff --git a/src/ir/cfg.rs b/src/ir/cfg.rs index 6eff37d..34a236e 100644 --- a/src/ir/cfg.rs +++ b/src/ir/cfg.rs @@ -68,10 +68,8 @@ pub fn identify_leaders(instrs: &[TacInstr]) -> HashSet { for (index, instr) in instrs.iter().enumerate() { match instr { - TacInstr::Jump { .. } | TacInstr::CondJump { .. } => { - if index + 1 < instrs.len() { - leaders.insert(index + 1); - } + TacInstr::Jump { .. } | TacInstr::CondJump { .. } if index + 1 < instrs.len() => { + leaders.insert(index + 1); } TacInstr::Label(_) => { leaders.insert(index); diff --git a/tests/codegen_smoke.rs b/tests/codegen_smoke.rs index fc801b9..a545663 100644 --- a/tests/codegen_smoke.rs +++ b/tests/codegen_smoke.rs @@ -6,6 +6,8 @@ //! execucao. Se o `gcc` nao estiver disponivel no ambiente, os testes sao //! ignorados (skip) em vez de falhar. +#![cfg_attr(not(unix), allow(unused_variables))] + use std::path::PathBuf; use std::process::Command; diff --git a/tests/exe_smoke_test.rs b/tests/exe_smoke_test.rs index e75c6ad..2a190d2 100644 --- a/tests/exe_smoke_test.rs +++ b/tests/exe_smoke_test.rs @@ -8,6 +8,8 @@ //! completo. Se `gcc` nao estiver disponivel no ambiente, os testes sao //! ignorados (skip) em vez de falhar. +#![cfg_attr(not(unix), allow(unused_variables))] + use std::path::PathBuf; use std::process::{Command, ExitStatus}; @@ -143,6 +145,112 @@ fn smoke_function_call_runs() { assert_eq!(status.code(), Some(42)); } +#[test] +fn smoke_blocks_and_local_scopes_run() { + require_gcc!(); + + let status = compile_and_run( + "blocks", + "int main() { \ + int total = 0; \ + { int a = 5; total = total + a; } \ + { int b = 7; total = total + b; } \ + return total; \ + }", + ); + + #[cfg(unix)] + assert_eq!(status.code(), Some(12)); +} + +#[test] +fn smoke_if_else_chain_runs() { + require_gcc!(); + + let status = compile_and_run( + "if_else_chain", + "int classify(int n) { \ + if (n < 0) { return -1; } \ + else if (n == 0) { return 0; } \ + else { return 1; } \ + } \ + int main() { return classify(-5) + classify(0) + classify(5) + 10; }", + ); + + #[cfg(unix)] + assert_eq!(status.code(), Some(10)); +} + +#[test] +fn smoke_while_loop_runs() { + require_gcc!(); + + let status = compile_and_run( + "while", + "int main() { \ + int i = 0; \ + int total = 0; \ + while (i < 5) { total = total + i; i = i + 1; } \ + return total; \ + }", + ); + + #[cfg(unix)] + assert_eq!(status.code(), Some(10)); +} + +#[test] +fn smoke_for_loop_runs() { + require_gcc!(); + + let status = compile_and_run( + "for", + "int main() { \ + int total = 0; \ + for (int i = 0; i < 5; i = i + 1) { total = total + i; } \ + return total; \ + }", + ); + + #[cfg(unix)] + assert_eq!(status.code(), Some(10)); +} + +#[test] +fn smoke_do_while_loop_runs() { + require_gcc!(); + + let status = compile_and_run( + "do_while", + "int main() { \ + int i = 0; \ + int total = 0; \ + do { total = total + i; i = i + 1; } while (i < 5); \ + return total; \ + }", + ); + + #[cfg(unix)] + assert_eq!(status.code(), Some(10)); +} + +#[test] +fn smoke_recursive_fibonacci_runs() { + require_gcc!(); + + let status = compile_and_run( + "fib", + "int fib(int n) { \ + if (n <= 1) { return n; } \ + return fib(n - 1) + fib(n - 2); \ + } \ + int main() { return fib(10); }", + ); + + #[cfg(unix)] + assert_eq!(status.code(), Some(55)); +} + #[test] fn smoke_switch_with_default_runs() { require_gcc!();