string example
This commit is contained in:
12
examples/strings.zr
Normal file
12
examples/strings.zr
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
func print_i64[x: I64] : I64
|
||||||
|
printf("%ld\n", x)
|
||||||
|
|
||||||
|
func i64_to_string[n: I64] : String
|
||||||
|
let x: I64 = malloc(21)
|
||||||
|
sprintf(x, "%d", n)
|
||||||
|
return x
|
||||||
|
|
||||||
|
func main[] : I64
|
||||||
|
let s: String = i64_to_string(58394)
|
||||||
|
print_i64(strlen(s))
|
||||||
|
free(s)
|
||||||
@@ -57,6 +57,9 @@ macro_rules! emit {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static REGISTERS: [&str; 6] = ["rdi", "rsi", "rdx", "rcx", "r8", "r9"];
|
||||||
|
static TYPES: [&str; 2] = ["I64", "String"];
|
||||||
|
|
||||||
pub struct CodegenX86_64 {
|
pub struct CodegenX86_64 {
|
||||||
output: String,
|
output: String,
|
||||||
data_section: String,
|
data_section: String,
|
||||||
@@ -74,18 +77,6 @@ impl CodegenX86_64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nth_register(n: usize) -> &'static str {
|
|
||||||
match n {
|
|
||||||
0 => "rdi",
|
|
||||||
1 => "rsi",
|
|
||||||
2 => "rdx",
|
|
||||||
3 => "rcx",
|
|
||||||
4 => "r8",
|
|
||||||
5 => "r9",
|
|
||||||
_ => todo!("only up to 6 arguments supported"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn label(&mut self) -> String {
|
fn label(&mut self) -> String {
|
||||||
self.label_counter += 1;
|
self.label_counter += 1;
|
||||||
format!(".L{}", self.label_counter)
|
format!(".L{}", self.label_counter)
|
||||||
@@ -94,8 +85,7 @@ impl CodegenX86_64 {
|
|||||||
pub fn get_output(&self) -> String {
|
pub fn get_output(&self) -> String {
|
||||||
format!(
|
format!(
|
||||||
"section .data
|
"section .data
|
||||||
{}
|
{}{}",
|
||||||
{}",
|
|
||||||
self.data_section, self.output
|
self.data_section, self.output
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -105,7 +95,11 @@ impl CodegenX86_64 {
|
|||||||
&mut self.output,
|
&mut self.output,
|
||||||
"
|
"
|
||||||
section .text
|
section .text
|
||||||
|
extern malloc
|
||||||
|
extern free
|
||||||
extern printf
|
extern printf
|
||||||
|
extern sprintf
|
||||||
|
extern strlen
|
||||||
extern puts
|
extern puts
|
||||||
print equ puts
|
print equ puts
|
||||||
",
|
",
|
||||||
@@ -128,7 +122,9 @@ print equ puts
|
|||||||
initializer,
|
initializer,
|
||||||
} => {
|
} => {
|
||||||
// TODO: types
|
// TODO: types
|
||||||
assert!(var_type.lexeme == "I64");
|
if !TYPES.contains(&var_type.lexeme.as_str()) {
|
||||||
|
return error!(&name.loc, format!("unknown type: {}", var_type.lexeme));
|
||||||
|
}
|
||||||
|
|
||||||
self.compile_expr(env, initializer)?;
|
self.compile_expr(env, initializer)?;
|
||||||
let offset = env.define_var(name.lexeme.clone(), var_type.lexeme);
|
let offset = env.define_var(name.lexeme.clone(), var_type.lexeme);
|
||||||
@@ -176,7 +172,9 @@ print equ puts
|
|||||||
return_type,
|
return_type,
|
||||||
body,
|
body,
|
||||||
} => {
|
} => {
|
||||||
assert!(return_type.lexeme == "I64"); // TODO
|
if !TYPES.contains(&return_type.lexeme.as_str()) {
|
||||||
|
return error!(&name.loc, format!("unknown type: {}", return_type.lexeme));
|
||||||
|
}
|
||||||
|
|
||||||
emit!(&mut self.output, "global {}", name.lexeme);
|
emit!(&mut self.output, "global {}", name.lexeme);
|
||||||
emit!(&mut self.output, "{}:", name.lexeme);
|
emit!(&mut self.output, "{}:", name.lexeme);
|
||||||
@@ -187,12 +185,11 @@ print equ puts
|
|||||||
for (i, param) in params.iter().enumerate() {
|
for (i, param) in params.iter().enumerate() {
|
||||||
let offset = env
|
let offset = env
|
||||||
.define_var(param.var_name.lexeme.clone(), param.var_type.lexeme.clone());
|
.define_var(param.var_name.lexeme.clone(), param.var_type.lexeme.clone());
|
||||||
emit!(
|
let reg = match REGISTERS.get(i) {
|
||||||
&mut self.output,
|
Some(x) => x,
|
||||||
" mov QWORD [rbp-{}], {}",
|
None => return error!(&name.loc, "only up to 6 params allowed"),
|
||||||
offset,
|
};
|
||||||
CodegenX86_64::nth_register(i),
|
emit!(&mut self.output, " mov QWORD [rbp-{}], {}", offset, reg,);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.compile_stmt(env, *body)?;
|
self.compile_stmt(env, *body)?;
|
||||||
@@ -350,7 +347,7 @@ print equ puts
|
|||||||
}
|
}
|
||||||
Expr::Call {
|
Expr::Call {
|
||||||
callee,
|
callee,
|
||||||
paren: _,
|
paren,
|
||||||
args,
|
args,
|
||||||
} => {
|
} => {
|
||||||
let callee = match *callee {
|
let callee = match *callee {
|
||||||
@@ -360,11 +357,11 @@ print equ puts
|
|||||||
|
|
||||||
for (i, arg) in args.iter().enumerate() {
|
for (i, arg) in args.iter().enumerate() {
|
||||||
self.compile_expr(env, arg.clone())?;
|
self.compile_expr(env, arg.clone())?;
|
||||||
emit!(
|
let reg = match REGISTERS.get(i) {
|
||||||
&mut self.output,
|
Some(x) => x,
|
||||||
" mov {}, rax",
|
None => return error!(&paren.loc, "only up to 6 args allowed"),
|
||||||
CodegenX86_64::nth_register(i),
|
};
|
||||||
);
|
emit!(&mut self.output, " mov {}, rax", reg,);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit!(&mut self.output, " call {}", callee);
|
emit!(&mut self.output, " call {}", callee);
|
||||||
|
|||||||
Reference in New Issue
Block a user