Skip to content

Commit 3cefab0

Browse files
committed
feat: add more compile options & fix safe cast
1. add asm compile target 2. add ability to compile ir file 3. fix a wrong load type in safe cast 4. better test file structure
1 parent 38290c1 commit 3cefab0

File tree

14 files changed

+254
-51
lines changed

14 files changed

+254
-51
lines changed

immix/src/llvm_stackmap/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,8 @@ extern "C" {
278278
pub fn CreateGlobalOrcJITEngine() -> std::ffi::c_void;
279279
pub fn AddModuleToOrcJIT(module: *mut u8) -> std::ffi::c_void;
280280
pub fn RunExpr(module: *mut u8) -> std::ffi::c_void;
281+
282+
pub fn parse_ir(ir: *const std::ffi::c_char) -> *mut u8;
281283
/// # run_module_pass
282284
///
283285
/// run the module pass

planglib/std/cols/hashtable.pi

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ impl <K:Hash+Eq<K>|V> HashTable<K|V> {
3131
if self.entries as f64 / arr_len(self.buckets) as f64 > 0.5 {
3232
let new_size = arr_len(self.buckets) * 2;
3333
let new_table = new_hash_table<K|V>(new_size as u64, self.salt +1);
34-
let iterator = self.into_inter();
34+
let iterator = self.into_iter();
3535
for let i = iterator.next(); !i is None; i = iterator.next() {
3636
let (key, value) = i as (K,V)!;
3737
new_table.insert(key, value);
@@ -42,7 +42,7 @@ impl <K:Hash+Eq<K>|V> HashTable<K|V> {
4242
}
4343
return;
4444
}
45-
gen pub fn into_inter() Iterator<(K,V)> {
45+
gen pub fn into_iter() Iterator<(K,V)> {
4646
for let i = 0; i < arr_len(self.buckets); i = i + 1 {
4747
let node = self.buckets[i];
4848
while node is *TableNode<K|V> {
@@ -143,7 +143,7 @@ pub use core::string::ToString;
143143
impl <K:ToString+Hash+Eq<K>|V:ToString> ToString for HashTable<K|V> {
144144
fn to_string() string {
145145
let ret = "HashTable{";
146-
let iterator = self.into_inter();
146+
let iterator = self.into_iter();
147147
for let i = iterator.next(); !i is None; {
148148
let (key, value) = i as (K,V)!;
149149
ret.append(key.to_string());

planglib/std/time.pi

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,26 @@ impl Duration {
116116
return self.t.sec as i128 * 1_000_000_000 + self.t.nano as i128;
117117
}
118118

119+
/// # sub_sec_nanos
120+
///
121+
/// get the number of nanoseconds that have elapsed since the last second
122+
pub fn sub_sec_nanos() u32 {
123+
return self.t.nano;
124+
}
125+
119126
/// # sub
120127
///
121128
/// subtract a duration from another duration
122129
pub fn sub(d:Duration) Duration {
123130
let sec = self.t.sec - d.t.sec;
124-
let nano = self.t.nano - d.t.nano;
131+
// check if we need to borrow from the seconds
132+
let nano;
133+
if self.t.nano < d.t.nano {
134+
sec = sec - 1;
135+
nano = self.t.nano + NANO_PER_SEC as u32 - d.t.nano;
136+
} else {
137+
nano = self.t.nano - d.t.nano;
138+
};
125139
return Duration{
126140
t:Timespec{
127141
sec: sec,

src/ast/compiler.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,35 @@ pub fn compile(db: &dyn Db, docs: MemDocsInput, out: String, op: Options) {
5858
immix::register_llvm_gc_plugins();
5959
ensure_target_folder();
6060

61+
let p = PathBuf::from(docs.file(db).to_string());
62+
if p.extension().unwrap_or_default() == "bc" || p.extension().unwrap_or_default() == "ll" {
63+
if !p.exists() {
64+
eprintln!("{} file not found", p.to_str().unwrap().red());
65+
exit(1)
66+
}
67+
let ctx = Context::create();
68+
let tm = crate::ast::builder::llvmbuilder::get_target_machine(op.optimization.to_llvm());
69+
let obj_f = &format!("{}/{}", &ASSET_PATH.lock().unwrap(), "out.o");
70+
let module = if p.extension().unwrap_or_default() == "bc" {
71+
Module::parse_bitcode_from_path(p, &ctx).unwrap()
72+
} else {
73+
let c_str = std::ffi::CString::new(p.to_str().unwrap()).unwrap();
74+
let mem = unsafe { immix::parse_ir(c_str.as_ptr()) };
75+
Module::parse_bitcode_from_buffer(
76+
unsafe { &inkwell::memory_buffer::MemoryBuffer::new(mem as _) },
77+
&ctx,
78+
)
79+
.unwrap()
80+
};
81+
tm.write_to_file(
82+
&module,
83+
inkwell::targets::FileType::Object,
84+
Path::new(obj_f),
85+
)
86+
.unwrap();
87+
pl_link(module, vec![obj_f.into()], out.clone(), op);
88+
return;
89+
}
6190
let total_steps = 3;
6291
let pb = &COMPILE_PROGRESS;
6392
prepare_prgressbar(
@@ -247,6 +276,16 @@ pub fn process_llvm_ir<'a>(
247276
output_files.push(obj_f.into());
248277
}
249278
pb.finish_with_message("中间代码优化完成");
279+
let asm_path = format!("{}/{}", &ASSET_PATH.lock().unwrap(), "out.asm");
280+
if op.asm {
281+
tm.write_to_file(
282+
&llvmmod,
283+
inkwell::targets::FileType::Assembly,
284+
Path::new(&asm_path),
285+
)
286+
.unwrap();
287+
eprintln!("asm file written to: {}", &asm_path);
288+
}
250289
(llvmmod, output_files)
251290
}
252291

src/ast/compiler/options.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use inkwell::OptimizationLevel;
44
/// Options preserves additional args to do additional works during parsing AST
55
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Copy)]
66
pub struct Options {
7+
pub asm: bool,
78
pub genir: bool,
89
/// printast will print out the generated AST and ends up the further processes.
910
pub printast: bool,

src/ast/node/cast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ impl<'a, 'ctx> Ctx<'a> {
309309
let data = builder
310310
.build_struct_gep(val, 1, "data", ori_ty, self)
311311
.unwrap();
312-
let data = builder.build_load(data, "data", &target_ty.borrow(), self);
312+
let data = builder.build_load(data, "data", &PLType::new_u8_ptr(), self);
313313
builder.build_store(result_data_field, data);
314314
builder.build_store(result_tag_field, builder.int_value(&PriType::U64, 0, false));
315315
builder.build_unconditional_branch(after_block);

src/ast/test.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ fn test_doc_symbol() {
414414

415415
#[test]
416416
#[cfg(feature = "jit")]
417+
#[cfg(not(windows))] // FIXME: windows i128 issue https://discourse.llvm.org/c/beginners/17
417418
fn test_orc_jit() {
418419
use crate::ast::compiler::{compile, Options};
419420
use std::path::PathBuf;

src/main.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ struct Cli {
156156
#[arg(long)]
157157
genir: bool,
158158

159+
/// generate
160+
#[arg(long, short = 'S')]
161+
asm: bool,
162+
159163
/// jit compile
160164
#[arg(long)]
161165
jit: bool,
@@ -188,6 +192,7 @@ impl Cli {
188192
.unwrap();
189193

190194
let op = compiler::Options {
195+
asm: self.asm,
191196
genir: self.genir,
192197
printast: self.printast,
193198
flow: self.flow,
@@ -221,13 +226,16 @@ impl Cli {
221226
// todo(griffin): make the input name more generic
222227
// currently it support file path input only,
223228
pub fn build(&mut self, name: String) {
224-
self.check(name.clone());
229+
if !(name.ends_with(".bc") || name.ends_with(".ll")) {
230+
self.check(name.clone());
231+
}
225232

226233
let db = Database::default();
227234
let filepath = Path::new(&name);
228235
let abs = crate::utils::canonicalize(filepath).unwrap();
229236

230237
let op = compiler::Options {
238+
asm: self.asm,
231239
genir: self.genir,
232240
printast: self.printast,
233241
flow: self.flow,
@@ -299,6 +307,7 @@ impl Cli {
299307
let abs = crate::utils::canonicalize(filepath).unwrap();
300308

301309
let op = compiler::Options {
310+
asm: self.asm,
302311
genir: self.genir,
303312
printast: self.printast,
304313
flow: self.flow,

src/repl/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ pub fn start_repl() {
5454
let mut db2 = Database::default();
5555

5656
let op = compiler::Options {
57+
asm: false,
5758
genir: false,
5859
printast: false,
5960
flow: false,

test/main.pi

Lines changed: 69 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,73 @@
1-
use std::cols::hashtable::*;
2-
use std::cols::arr::*;
3-
41
use project1::test::_match;
5-
6-
use std::time;
7-
2+
use project1::test::time;
3+
use project1::test::print;
4+
use project1::test::ifel;
5+
use project1::test::generic;
6+
use project1::test::st;
7+
use project1::test::method;
8+
use project1::test::global;
9+
use project1::test::traits;
10+
use project1::test::simple;
11+
use project1::test::flow;
12+
use project1::test::compiletime_reflection::test_compile_time_reflection;
13+
use project1::test::list;
14+
use project1::test::module;
15+
use project1::test::str;
16+
use project1::test::macros;
17+
use project1::test::union;
18+
use project1::test::multi_trait;
19+
use project1::test::tuple;
20+
use project1::test::fntype;
21+
use project1::test::closure;
22+
use project1::test::map;
23+
use project1::test::tree;
24+
use project1::test::fixed_point;
25+
use project1::test::sort_test;
26+
use project1::tmod2;
27+
// use pl_test::main;
28+
use project1::test::deconstruct;
29+
use project1::test::st::*;
30+
use project1::test::arr;
31+
use project1::test::iter;
32+
use project1::test::inference;
33+
use project1::test::rand;
34+
use project1::test::_hashtable;
35+
use project1::test::_io;
36+
// use std::cols::hashtable::new_hash_table;
837

938
pub fn main() i64 {
10-
let t = time::now();
11-
let a = 0.0;
12-
println!(a);
13-
let m = "🌏Hello, 世界!";
14-
println!(m);
15-
let cs = m.chars();
16-
println!(cs);
17-
let h = new_hash_table<i64|i64>(10 as u64, 1 as u64);
18-
h.insert(1, 2);
19-
h.insert(2, 3);
20-
println!(-0);
21-
println!(456 as i32);
22-
println!(-789 as i16);
23-
println!(12 as i8);
24-
println!(123);
25-
println!(456 as u32);
26-
println!(789 as u16);
27-
println!(12 as u8);
28-
println!(123.456);
29-
println!(-789.012);
30-
println!(1.0/3.0);
31-
println!(-0.123 as f32); // TODO: impl a better way to cast f32 (like f64)
32-
println!(-10.0);
33-
println!([1, 2, 3, 4]);
34-
println!(from_slice([1, 2, 3, 4]));
35-
println!(h);
36-
println!(1,2,3);
37-
println!(123);
38-
let b = '😀';
39-
println!(b);
40-
_match::test_match();
41-
let aa = 0;
42-
for let i = 0; i < 100; i = i + 1 {
43-
aa = aa + i;
44-
}
45-
let ep = t.elapsed();
46-
println!(ep);
47-
println!(0.000093999999999999994);
39+
40+
macros::test_macros();
41+
ifel::test_if_else();
42+
generic::test_generic();
43+
method::test_impl();
44+
test_struct();
45+
global::test_global();
46+
traits::test_trait();
47+
simple::test_simple();
48+
flow::test_flow();
49+
list::test_list();
50+
// main::simple_test();
51+
module::test_module();
52+
str::test_string();
53+
union::test_union();
54+
multi_trait::test_multi_trait();
55+
deconstruct::test_deconstruct();
56+
tuple::test_tuple();
57+
fntype::test_fntype()();
58+
closure::test_closure();
59+
tree::test_eva();
60+
map::test_map();
61+
fixed_point::test_fixed_point();
62+
generic::ret_generic1<i64>();
63+
test_compile_time_reflection();
64+
iter::test_generator();
65+
inference::test_inference();
66+
rand::test_rand();
67+
sort_test::test_sort();
68+
arr::test_arr();
69+
_hashtable::test_hashtable();
70+
_io::test_io();
71+
4872
return 0;
49-
}
73+
}

0 commit comments

Comments
 (0)