emit debug flag

This commit is contained in:
2026-06-07 12:03:22 +02:00
parent 802a6d8b53
commit d4fe032a3a
4 changed files with 36 additions and 18 deletions

View File

@@ -77,12 +77,14 @@ pub struct CodegenX86_64<'a> {
data_counter: usize, data_counter: usize,
pub symbol_table: &'a SymbolTable, pub symbol_table: &'a SymbolTable,
pub expr_types: &'a HashMap<usize, String>, pub expr_types: &'a HashMap<usize, String>,
emit_debug: bool,
} }
impl<'a> CodegenX86_64<'a> { impl<'a> CodegenX86_64<'a> {
pub fn new( pub fn new(
symbol_table: &'a SymbolTable, symbol_table: &'a SymbolTable,
expr_types: &'a HashMap<usize, String>, expr_types: &'a HashMap<usize, String>,
emit_debug: bool,
) -> CodegenX86_64<'a> { ) -> CodegenX86_64<'a> {
CodegenX86_64 { CodegenX86_64 {
output: String::new(), output: String::new(),
@@ -91,6 +93,7 @@ impl<'a> CodegenX86_64<'a> {
data_counter: 1, data_counter: 1,
symbol_table, symbol_table,
expr_types, expr_types,
emit_debug,
} }
} }
@@ -344,11 +347,15 @@ _builtin_environ:
body, body,
exported, exported,
} => { } => {
if *exported || name.lexeme == "main" { let name = &name.lexeme;
emit!(&mut self.output, "global {}", name.lexeme); if self.emit_debug || *exported || name == "main" {
emit!(
&mut self.output,
"global {name}:function (__end_{name} - {name})",
);
} }
emit!(&mut self.output, "section .text.{}", name.lexeme); emit!(&mut self.output, "section .text.{}", name);
emit!(&mut self.output, "{}:", name.lexeme); emit!(&mut self.output, "{}:", name);
emit!(&mut self.output, " push rbp"); emit!(&mut self.output, " push rbp");
emit!(&mut self.output, " mov rbp, rsp"); emit!(&mut self.output, " mov rbp, rsp");
@@ -398,6 +405,10 @@ _builtin_environ:
emit!(&mut self.output, " ret"); emit!(&mut self.output, " ret");
} }
if self.emit_debug || *exported || name == "main" {
emit!(&mut self.output, "__end_{}:", name);
}
// patch the stack size after we know how much we actually need // patch the stack size after we know how much we actually need
let patch = format!(" sub rsp, {:<10}", (env.next_offset + 15) & !15); let patch = format!(" sub rsp, {:<10}", (env.next_offset + 15) & !15);
self.output self.output

View File

@@ -54,7 +54,8 @@ fn compile_file(args: Args) -> Result<(), ZernError> {
typechecker.typecheck_stmt(&mut typechecker::Env::new(), stmt)?; typechecker.typecheck_stmt(&mut typechecker::Env::new(), stmt)?;
} }
let mut codegen = codegen_x86_64::CodegenX86_64::new(&symbol_table, &typechecker.expr_types); let mut codegen =
codegen_x86_64::CodegenX86_64::new(&symbol_table, &typechecker.expr_types, args.emit_debug);
codegen.emit_prologue(args.use_crt)?; codegen.emit_prologue(args.use_crt)?;
for stmt in statements { for stmt in statements {
codegen.compile_stmt(&mut codegen_x86_64::Env::new(), &stmt)?; codegen.compile_stmt(&mut codegen_x86_64::Env::new(), &stmt)?;
@@ -63,19 +64,18 @@ fn compile_file(args: Args) -> Result<(), ZernError> {
if !args.emit_only { if !args.emit_only {
let out = args.out.unwrap_or_else(|| "out".into()); let out = args.out.unwrap_or_else(|| "out".into());
fs::write(format!("{}.s", out), codegen.get_output()).unwrap(); fs::write(format!("{out}.s"), codegen.get_output()).unwrap();
run_command(format!("nasm -f elf64 -o {}.o {}.s", out, out)); run_command(format!("nasm -f elf64 -o {out}.o {out}.s"));
if args.use_crt { if args.use_crt {
run_command(format!( run_command(format!(
"cc -no-pie -o {} {}.o -flto -Wl,--gc-sections {}", "cc -no-pie -o {out} {out}.o -flto -Wl,--gc-sections {}",
out, out, args.cflags args.cflags
)); ));
} else { } else {
run_command(format!( run_command(format!(
"ld -static -o {} {}.o --gc-sections -e _start", "ld -static -o {out} {out}.o --gc-sections -e _start"
out, out
)); ));
} }
@@ -113,6 +113,7 @@ struct Args {
path: String, path: String,
out: Option<String>, out: Option<String>,
emit_only: bool, emit_only: bool,
emit_debug: bool,
include_stdlib: bool, include_stdlib: bool,
run_exe: bool, run_exe: bool,
use_crt: bool, use_crt: bool,
@@ -127,6 +128,7 @@ impl Args {
path: String::new(), path: String::new(),
out: None, out: None,
emit_only: false, emit_only: false,
emit_debug: false,
include_stdlib: true, include_stdlib: true,
run_exe: false, run_exe: false,
use_crt: false, use_crt: false,
@@ -150,6 +152,8 @@ impl Args {
out.run_exe = true; out.run_exe = true;
} else if arg == "-m" { } else if arg == "-m" {
out.use_crt = true; out.use_crt = true;
} else if arg == "-g" {
out.emit_debug = true;
} else if arg == "-C" { } else if arg == "-C" {
match args.next() { match args.next() {
Some(s) => out.cflags = s, Some(s) => out.cflags = s,
@@ -160,16 +164,16 @@ impl Args {
} }
} else if arg == "-h" || arg == "--help" { } else if arg == "-h" || arg == "--help" {
println!( println!(
"Usage: zern [-o path] [-r] [-m] [-C cflags] [--emit-only] [--no-stdlib] path" "Usage: zern [-o path] [-r] [-m] [-g] [-C cflags] [--emit-only] [--no-stdlib] path"
); );
process::exit(0); process::exit(0);
} else if arg.starts_with('-') { } else if arg.starts_with('-') {
eprintln!("\x1b[91mERROR\x1b[0m: unrecognized option: {}", arg); eprintln!("\x1b[91mERROR\x1b[0m: unrecognized option: {arg}");
process::exit(1); process::exit(1);
} else if out.path.is_empty() { } else if out.path.is_empty() {
out.path = arg out.path = arg
} else { } else {
eprintln!("\x1b[91mERROR\x1b[0m: unrecognized argument: {}", arg); eprintln!("\x1b[91mERROR\x1b[0m: unrecognized argument: {arg}");
process::exit(1); process::exit(1);
} }
} }

View File

@@ -495,9 +495,6 @@ func str.find[haystack: str, needle: str] : i64
return -1 return -1
func str.substr[s: str, start: i64, length: i64] : str func str.substr[s: str, start: i64, length: i64] : str
if start < 0 || length < 0 || start + length > str.len(s)
panic("str.substr out of bounds")
out := mem.alloc(length + 1) as str out := mem.alloc(length + 1) as str
mem.copy(s as ptr + start, out as ptr, length) mem.copy(s as ptr + start, out as ptr, length)
out[length] = 0 out[length] = 0
@@ -1038,6 +1035,12 @@ func os.exit[code: i64] : void
func os.getpid[] : i64 func os.getpid[] : i64
return _builtin_syscall(SYS_getpid) return _builtin_syscall(SYS_getpid)
func os.basename[path: str] : str
i := path->len() - 1
while i >= 0 && path[i] != '/'
i -= 1
return path->substr(i + 1, path->len() - i - 1)
struct os.Timespec struct os.Timespec
tv_sec: i64 tv_sec: i64
tv_nsec: i64 tv_nsec: i64

View File

@@ -260,7 +260,7 @@ impl Tokenizer {
break; break;
} else if self.peek() == '\n' { } else if self.peek() == '\n' {
self.loc.line += 1; self.loc.line += 1;
self.loc.column = 1; self.loc.column = 0;
} }
self.advance(); self.advance();
} }