Skip to content

Commit 554a1e4

Browse files
committed
basic panic done
1 parent cad285d commit 554a1e4

File tree

17 files changed

+336
-714
lines changed

17 files changed

+336
-714
lines changed

langref.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ You also include paths using strings, not identifiers, due to not having a `mod
2424

2525
The use keyword also allows for importing multiple exported items using the familiar `"file"::{a, b, c, ...}` syntax. If you want to just include the module, you can use `"file" as <name>`.
2626

27+
Also note that most primitive types (all integers, bools and strings) have a `.print` and `.println` function, `"Hello, World!".println();` would've had the same output.
28+
2729
# Comments
2830

2931
Mira supports the standard c-style comments of line-comments using `//` and multiline comments using `/* ... */`.

lib/mirastd/langitems.mr

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
use "./lib.mr"::{print_str, print_char, print_newline};
2+
3+
pub fn print_u64(val: u64) {
4+
if (val == 0) {
5+
return print_str("0");
6+
}
7+
let chars: [u8; 20] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
8+
let char_idx = 0usize;
9+
10+
while (val > 0) {
11+
chars[char_idx] = (val % 10) as u8 + 48; // 48 = '0'
12+
val = val / 10;
13+
char_idx += 1;
14+
}
15+
16+
while (char_idx > 0) {
17+
char_idx -= 1;
18+
print_char(chars[char_idx]);
19+
}
20+
}
21+
pub fn print_i64(val: i64) {
22+
if (val == 0) {
23+
return print_str("0");
24+
}
25+
let chars: [u8; 20] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
26+
let char_idx = 0usize;
27+
let is_neg = val < 0;
28+
if (is_neg) val = -val;
29+
while (val > 0) {
30+
chars[char_idx] = (val % 10) as u8 + 48; // 48 = '0'
31+
val = val / 10;
32+
char_idx += 1;
33+
}
34+
35+
if (is_neg) print_char(45); // b'-'
36+
while (char_idx > 0) {
37+
char_idx -= 1;
38+
print_char(chars[char_idx]);
39+
}
40+
}
41+
42+
43+
44+
@lang("u8")
45+
struct u8_t {;
46+
fn print(self: u8) = print_u64(self as u64);
47+
fn println(self: u8) { print_u64(self as u64); print_newline(); }
48+
}
49+
@lang("u16")
50+
struct u16_t {;
51+
fn print(self: u16) = print_u64(self as u64);
52+
fn println(self: u16) { print_u64(self as u64); print_newline(); }
53+
}
54+
@lang("u32")
55+
struct u32_t {;
56+
fn print(self: u32) = print_u64(self as u64);
57+
fn println(self: u32) { print_u64(self as u64); print_newline(); }
58+
}
59+
@lang("u64")
60+
struct u64_t {;
61+
fn print(self: u64) = print_u64(self);
62+
fn println(self: u64) { print_u64(self); print_newline(); }
63+
}
64+
@lang("usize")
65+
struct usize_t {;
66+
fn print(self: usize) = print_u64(self as u64);
67+
fn println(self: usize) { print_u64(self as u64); print_newline(); }
68+
}
69+
70+
@lang("i8")
71+
struct i8_t {;
72+
fn print(self: i8) = print_i64(self as i64);
73+
fn println(self: i8) { print_i64(self as i64); print_newline(); }
74+
}
75+
@lang("i16")
76+
struct i16_t {;
77+
fn print(self: i16) = print_i64(self as i64);
78+
fn println(self: i16) { print_i64(self as i64); print_newline(); }
79+
}
80+
@lang("i32")
81+
struct i32_t {;
82+
fn print(self: i32) = print_i64(self as i64);
83+
fn println(self: i32) { print_i64(self as i64); print_newline(); }
84+
}
85+
@lang("i64")
86+
struct i64_t {;
87+
fn print(self: i64) = print_i64(self);
88+
fn println(self: i64) { print_i64(self); print_newline(); }
89+
}
90+
@lang("isize")
91+
struct isize_t {;
92+
fn print(self: isize) = print_i64(self as i64);
93+
fn println(self: isize) { print_i64(self as i64); print_newline(); }
94+
}
95+
@lang("bool")
96+
struct bool_t {;
97+
fn print(self: bool) { if (self) print_str("true"); else print_str("false"); }
98+
fn println(self: bool) { if (self) print_str("true\n"); else print_str("false\n"); }
99+
}
100+
@lang("str")
101+
struct str_t {;
102+
fn print(self: &str) = print_str(self);
103+
fn println(self: &str) { print_str(self); print_newline(); }
104+
fn len(self: &str) -> usize {
105+
let strn_addr = &self as &void as usize;
106+
return asm(
107+
"movq 8(%[straddr]), %[out]"
108+
: [out] "=r" (usize)
109+
: [straddr] "r" (strn_addr)
110+
);
111+
}
112+
}

lib/mirastd/lib.mr

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,28 @@ use "./os.mr"::write;
33
export Clone;
44
export Copy;
55

6-
pub fn print_str(string: &str) = write(1, string as &u8, strlen(string));
6+
pub fn print_str(string: &str) = write(1, string as &u8, string.len());
77
pub fn print_char(c: u8) = write(1, &c, 1);
88
pub fn print_newline() = print_char(0xa);
99
pub fn print_str_newline(string: &str) {
1010
print_str(string);
1111
print_newline();
1212
}
13-
pub fn print_usize_hex(val: usize) {
13+
14+
pub fn cstrlen(cstr: &u8) -> usize {
15+
let len = 0usize;
16+
while (*cstr != 0) {
17+
len += 1;
18+
cstr = (cstr as &void as usize + 1) as &void as &u8;
19+
}
20+
return len;
21+
}
22+
use "./langitems.mr"::{print_u64, print_i64};
23+
use "./panic.mr"::panic;
24+
export print_u64;
25+
export print_i64;
26+
export panic;
27+
pub fn print_u64_hex(val: u64) {
1428
print_str("0x");
1529
if (val == 0) {
1630
return print_str("0");
@@ -31,39 +45,3 @@ pub fn print_usize_hex(val: usize) {
3145
print_char(chars[char_idx]);
3246
}
3347
}
34-
pub fn print_usize(val: usize) {
35-
if (val == 0) {
36-
return print_str("0");
37-
}
38-
let chars: [u8; 20] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
39-
let char_idx = 0usize;
40-
41-
while (val > 0) {
42-
chars[char_idx] = (val % 10) as u8 + 48; // 48 = '0'
43-
val = val / 10;
44-
char_idx += 1;
45-
}
46-
47-
while (char_idx > 0) {
48-
char_idx -= 1;
49-
print_char(chars[char_idx]);
50-
}
51-
}
52-
53-
pub fn strlen(strn: &str) -> usize {
54-
let strn_addr = &strn as &void as usize;
55-
return asm(
56-
"movq 8(%[straddr]), %[out]"
57-
: [out] "=r" (usize)
58-
: [straddr] "r" (strn_addr)
59-
);
60-
}
61-
62-
pub fn cstrlen(cstr: &u8) -> usize {
63-
let len = 0usize;
64-
while (*cstr != 0) {
65-
len += 1;
66-
cstr = (cstr as &void as usize + 1) as &void as &u8;
67-
}
68-
return len;
69-
}

lib/mirastd/panic.mr

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use "./lib.mr"::{print_u64_hex, cstrlen};
2+
use "./os.mr"::write;
3+
4+
struct unw_cursor { inner: [u64; 127] }
5+
struct unw_context { inner: [u64; 121] }
6+
let UNW_REG_IP: u32 = 16;
7+
8+
@alias("_Ux86_64_getcontext")
9+
extern fn unw_getcontext(v: &unw_context);
10+
@alias("_Ux86_64_init_local")
11+
extern fn unw_init_local(cursor: &unw_cursor, v: &unw_context);
12+
@alias("_Ux86_64_step")
13+
extern fn unw_step(cursor: &unw_cursor) -> i32;
14+
@alias("_Ux86_64_get_reg")
15+
extern fn unw_get_reg(cursor: &unw_cursor, register: u32, value: &usize);
16+
@alias("_Ux86_64_get_proc_name")
17+
extern fn unw_get_proc_name(cursor: &unw_cursor, name: &u8, name_size: usize, offset: &usize) -> i32;
18+
19+
pub fn show_bt() {
20+
let cursor = unw_cursor { inner: [0u64; 127] };
21+
let context = unw_context { inner: [0u64; 121] };
22+
let ip = 0usize;
23+
let offset = 0usize;
24+
25+
unw_getcontext(&context);
26+
unw_init_local(&cursor, &context);
27+
let name_buf = [0u8; 4096];
28+
while (unw_step(&cursor) > 0) {
29+
unw_get_reg(&cursor, UNW_REG_IP, &ip);
30+
print_u64_hex(ip as u64);
31+
": ".print();
32+
name_buf[0] = 0;
33+
if (unw_get_proc_name(&cursor, &name_buf as &[u8] as &u8, 4096, &offset) == 0) {
34+
"(".print();
35+
write(1, &name_buf as &[u8] as &u8, cstrlen(&name_buf as &[u8] as &u8));
36+
"+".print();
37+
print_u64_hex(offset as u64);
38+
")".println();
39+
} else "-- no symbol name was found".println();
40+
}
41+
}
42+
43+
pub fn panic(message: &str) {
44+
"panic: ".print();
45+
message.println();
46+
"".println();
47+
show_bt();
48+
}

lib/mirastd/prelude.mr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
use "./start.mr";
22
use "./allocate.mr";
33
use "./clone_copy.mr";
4+
use "./langitems.mr";

meow.mr

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
fn meow() -> usize = 3;
1+
use "std"::panic;
22

3-
export meow;
3+
pub fn main(argc: usize, argv: &&u8) {
4+
"meow meow" |> panic();
5+
}

mira/src/codegen/mod.rs

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,34 @@ impl<'ctx> TypedLiteral {
376376
.const_named_struct(&[ptr, len_const])
377377
.into()
378378
}
379+
380+
TypedLiteral::ArrayInit(ty, _, 0) => ty
381+
.to_llvm_basic_type(default_types, structs, ctx)
382+
.array_type(0)
383+
.const_zero()
384+
.into(),
385+
TypedLiteral::ArrayInit(_, elem, amount) => {
386+
let elem = elem.to_basic_value(
387+
scope_get_value,
388+
default_types,
389+
structs,
390+
builder,
391+
statics,
392+
functions,
393+
ext_functions,
394+
string_map,
395+
ctx,
396+
);
397+
let mut array_value = elem.get_type().array_type(*amount as u32).const_zero();
398+
for i in 0..*amount {
399+
array_value = builder
400+
.build_insert_value(array_value, elem, i as u32, "")
401+
.expect("i should never be out of bounds")
402+
.into_array_value();
403+
}
404+
405+
array_value.into()
406+
}
379407
TypedLiteral::Array(ty, elements) => {
380408
if elements.is_empty() {
381409
return ty
@@ -1263,9 +1291,27 @@ impl TypecheckedExpression {
12631291
ctx.push_value(*dst, src.fn_ctx_to_basic_value(ctx));
12641292
Ok(())
12651293
}
1266-
TypecheckedExpression::Neg(..) => todo!(),
1267-
TypecheckedExpression::LNot(..) => todo!(),
1268-
TypecheckedExpression::BNot(..) => todo!(),
1294+
TypecheckedExpression::Neg(_, dst, src) => {
1295+
let src = src.fn_ctx_to_basic_value(ctx);
1296+
let value = match src {
1297+
BasicValueEnum::IntValue(int_value) => ctx
1298+
.builder
1299+
.build_int_neg(int_value, "")?
1300+
.as_basic_value_enum(),
1301+
BasicValueEnum::FloatValue(float_value) => ctx
1302+
.builder
1303+
.build_float_neg(float_value, "")?
1304+
.as_basic_value_enum(),
1305+
_ => unreachable!(),
1306+
};
1307+
ctx.push_value(*dst, value);
1308+
Ok(())
1309+
}
1310+
TypecheckedExpression::BNot(_, dst, src) | TypecheckedExpression::LNot(_, dst, src) => {
1311+
let src = src.fn_ctx_to_basic_value(ctx).into_int_value();
1312+
ctx.push_value(*dst, ctx.builder.build_not(src, "")?.as_basic_value_enum());
1313+
Ok(())
1314+
}
12691315
TypecheckedExpression::Add(_, dst, lhs, rhs) => {
12701316
let lhs = lhs.fn_ctx_to_basic_value(ctx);
12711317
let rhs = rhs.fn_ctx_to_basic_value(ctx);

mira/src/globals.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ impl PartialEq<&str> for GlobalStr {
9898

9999
impl Clone for GlobalStr {
100100
fn clone(&self) -> Self {
101+
if self.0 == 0 {
102+
return Self(self.0);
103+
}
101104
STRINGS.with_borrow_mut(|strings: &mut GlobalStrs| {
102105
if let Some(v) = strings.get_mut(self.0) {
103106
v.refs += 1;
@@ -134,6 +137,9 @@ impl GlobalStr {
134137
for (idx, v) in strings.entries.iter_mut().enumerate() {
135138
if let Some(v) = v {
136139
if (*v.value).eq(value) {
140+
if idx == 0 {
141+
return Self(0);
142+
}
137143
v.refs += 1;
138144
return Self(idx);
139145
}
@@ -151,6 +157,9 @@ impl GlobalStr {
151157
for (idx, v) in strings.entries.iter_mut().enumerate() {
152158
if let Some(v) = v {
153159
if (*v.value).eq(&*value) {
160+
if idx == 0 {
161+
return Self(0);
162+
}
154163
v.refs += 1;
155164
return Self(idx);
156165
}

mira/src/linking.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,10 @@ pub fn run_full_compilation_pipeline(
647647
.link(LinkOptions {
648648
linker_path,
649649
object_files: &[obj_path],
650-
inputs: &[],
650+
inputs: &[
651+
LinkerInput::LinkLibrary("unwind".into()),
652+
LinkerInput::LinkLibrary("unwind-x86_64".into()),
653+
],
651654
output: &exec_path,
652655
args: opts.additional_linker_args,
653656
link_crt: opts.link_with_crt,

mira/src/parser.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ use crate::{
88
globals::GlobalStr,
99
tokenizer::{Location, Token, TokenType},
1010
};
11-
pub use expression::{BinaryOp, Expression, LiteralValue, Path, PathWithoutGenerics, UnaryOp};
11+
pub use expression::{
12+
ArrayLiteral, BinaryOp, Expression, LiteralValue, Path, PathWithoutGenerics, UnaryOp,
13+
};
1214
pub use statement::{Argument, BakableFunction, FunctionContract, Statement, Trait};
1315
pub use types::{Generic, Implementation, Struct, TypeRef, RESERVED_TYPE_NAMES};
1416
mod expression;

0 commit comments

Comments
 (0)