Skip to content

Commit f514381

Browse files
committed
Can now build a very broken Rust compiler
1 parent 7bebe0f commit f514381

File tree

30 files changed

+548
-444
lines changed

30 files changed

+548
-444
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ crate-type = ["dylib"]
2727
members = [ "cilly", "dotnet_aot",
2828
"mycorrhiza",
2929
]
30-
exclude = ["rust/src/bootstrap"]
30+
exclude = ["rust/src/bootstrap","backup_rust/src/bootstrap"]
3131
[profile.release]
3232
debug = true
3333

cargo_tests/build_std/src/main.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,9 @@ fn should_fail() {
77
}
88
pub fn main() {
99
let vec = vec![0, 1, 2, 3, 4, 5, 6, 7, 8_u8];
10-
println!("A");
1110
let mut s = String::new();
12-
println!("B");
1311
s.push_str("Hi. Message");
14-
println!("C");
1512
s.push_str("Hi. Message message messafe message mesasage!");
16-
println!("D");
1713
s.push_str("Hi. Message");
18-
println!("E");
19-
println!("Hi! UWU:{vec:?} {s:?}");
20-
println!("F all is well, when all is well. Right?");
14+
println!("Hello world! vec:{vec:?} s:{s:?}");
2115
}

cilly/src/asm.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
pub type Assembly = crate::v2::Assembly;
1+

cilly/src/bin/asmedit.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ fn main() {
160160
let start = Instant::now();
161161
println!("Preparing to export the assembly");
162162
#[cfg(not(miri))]
163-
asm.export(path, CExporter::new(false));
163+
asm.export(path, CExporter::new(false, vec![], vec![]));
164164
println!(
165165
"Exported the assembly in {} ms",
166166
start.elapsed().as_millis()
@@ -257,6 +257,15 @@ fn main() {
257257
);
258258
println!("strings:{:?}", encoded_stats(asm.strings()));
259259
}
260+
"nonstaticfn" => {
261+
let nonstaticfns = asm
262+
.method_defs()
263+
.iter()
264+
.filter(|(_, def)| !def.accesses_statics(&asm))
265+
.count();
266+
let total_fns = asm.method_defs().len();
267+
println!("{}%", (nonstaticfns as f64 / total_fns as f64) * 100.0);
268+
}
260269
"top_methods" => {
261270
let mut keys: Vec<_> = asm
262271
.method_refs()
@@ -301,7 +310,13 @@ fn find_invalid_c(asm: &Assembly) {
301310
fn is_valid_c(asm: &Assembly, id: u32) -> bool {
302311
#[cfg(not(miri))]
303312
{
304-
catch_unwind(|| asm.export(format!("/tmp/test{id}.out"), CExporter::new(false))).is_ok()
313+
catch_unwind(|| {
314+
asm.export(
315+
format!("/tmp/test{id}.out"),
316+
CExporter::new(false, vec![], vec![]),
317+
)
318+
})
319+
.is_ok()
305320
}
306321
#[cfg(miri)]
307322
{

cilly/src/bin/linker/main.rs

+28-4
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use fxhash::FxHashMap;
2222
use patch::call_alias;
2323
use std::{
2424
env,
25-
io::Write,
25+
io::{Read, Write},
2626
num::NonZeroU32,
2727
path::{Path, PathBuf},
2828
};
@@ -43,7 +43,8 @@ fn add_mandatory_statics(asm: &mut cilly::v2::Assembly) {
4343
main_module,
4444
);
4545
}
46-
46+
static FORCE_FAIL: std::sync::LazyLock<bool> =
47+
std::sync::LazyLock::new(|| std::env::var("FORCE_FAIL").is_ok());
4748
static LIBC: std::sync::LazyLock<String> = std::sync::LazyLock::new(get_libc_);
4849
static LIBM: std::sync::LazyLock<String> = std::sync::LazyLock::new(get_libm_);
4950
static BACKUP_STD: std::sync::LazyLock<Option<PathBuf>> = std::sync::LazyLock::new(|| {
@@ -172,6 +173,19 @@ fn link_backup_std(to_link: &[&String], ar_to_link: &mut Vec<String>, backup: &P
172173
link_dir(backup, ar_to_link);
173174
}
174175
}
176+
fn extract_libs(args: &[String]) -> Vec<String> {
177+
args.iter()
178+
.filter(|arg| arg[..2] == *"-l")
179+
.map(|arg| arg.to_string())
180+
.collect()
181+
}
182+
fn extract_dirs(args: &[String]) -> Vec<String> {
183+
args.iter()
184+
.filter(|arg| arg[..2] == *"-B")
185+
.map(|arg| arg.to_string())
186+
.collect()
187+
}
188+
175189
fn main() {
176190
// Parse command line arguments
177191

@@ -258,6 +272,7 @@ fn main() {
258272
}
259273
}),
260274
);
275+
261276
// Override allocator
262277
if !*C_MODE {
263278
// Get the marshal class
@@ -426,6 +441,7 @@ fn main() {
426441
cilly::v2::builtins::transmute(&mut final_assembly, &mut overrides);
427442
cilly::v2::builtins::create_slice(&mut final_assembly, &mut overrides);
428443
cilly::v2::builtins::math::bitreverse(&mut final_assembly, &mut overrides);
444+
429445
if *C_MODE {
430446
cilly::v2::builtins::insert_exeception_stub(&mut final_assembly, &mut overrides);
431447
externs.insert("__dso_handle", LIBC.clone());
@@ -447,7 +463,7 @@ fn main() {
447463
"pthread_key_delete",
448464
"pthread_join",
449465
"pthread_setspecific",
450-
"ldexpf"
466+
"ldexpf",
451467
] {
452468
externs.insert(fnc, LIBC.clone());
453469
}
@@ -487,6 +503,7 @@ fn main() {
487503
cilly::v2::Access::Public,
488504
NonZeroU32::new(16),
489505
NonZeroU32::new(16),
506+
true,
490507
));
491508

492509
final_assembly.patch_missing_methods(&externs, &modifies_errno, &overrides);
@@ -505,8 +522,15 @@ fn main() {
505522
final_assembly
506523
.save_tmp(&mut std::fs::File::create(path.with_extension("cilly2")).unwrap())
507524
.unwrap();
525+
let libs = extract_libs(args);
526+
let dirs = extract_dirs(args);
527+
if *FORCE_FAIL {
528+
panic!("FORCE_FAIL");
529+
}
508530
if *C_MODE {
509-
final_assembly.export(&path, cilly::v2::c_exporter::CExporter::new(is_lib));
531+
let cexport = cilly::v2::c_exporter::CExporter::new(is_lib, libs, dirs);
532+
533+
final_assembly.export(&path, cexport);
510534
} else if *JAVA_MODE {
511535
final_assembly.export(&path, cilly::v2::java_exporter::JavaExporter::new(is_lib));
512536
if cargo_support {

cilly/src/libc_fns.rs

+2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ pub const LIBC_FNS: &[&str] = &[
4343
"clock_gettime",
4444
"close",
4545
"closedir",
46+
"sigemptyset",
47+
"sigaction",
4648
"closelog",
4749
"confstr",
4850
"connect",

cilly/src/utilis.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use crate::method::Method;
44

55
use crate::v2::cilnode::MethodKind;
66
use crate::v2::{ClassRef, FnSig, Int, MethodRef, MethodRefIdx, StaticFieldDesc};
7-
use crate::{asm::Assembly, cil_node::CILNode, cil_root::CILRoot};
87
use crate::{call, call_virt, conv_usize, IntoAsmIndex, MethodDef, Type};
8+
use crate::{cil_node::CILNode, cil_root::CILRoot, Assembly};
99

1010
pub fn argc_argv_init_method(asm: &mut Assembly) -> MethodRefIdx {
1111
let init_cs = MethodRef::new(

cilly/src/v2/asm.rs

+52-10
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use super::{
77
MethodRefIdx, NodeIdx, RootIdx, SigIdx, StaticFieldDesc, StaticFieldIdx, StringIdx, Type,
88
TypeIdx,
99
};
10-
use crate::{asm::Assembly as V1Asm, utilis::encode, v2::MethodImpl};
1110
use crate::{config, IString};
11+
use crate::{utilis::encode, v2::MethodImpl};
1212
use fxhash::{hash64, FxHashMap, FxHashSet};
1313

1414
use serde::{Deserialize, Serialize};
@@ -33,6 +33,7 @@ pub struct Assembly {
3333
fields: BiMap<FieldIdx, FieldDesc>,
3434
statics: BiMap<StaticFieldIdx, StaticFieldDesc>,
3535
method_defs: FxHashMap<MethodDefIdx, MethodDef>,
36+
sections: FxHashMap<String, Vec<u8>>,
3637
// Cache containing information about the stack usage of a CIL node.
3738
//#[serde(skip)]
3839
//cache: CachedAssemblyInfo<NodeIdx, NonMaxU32, StackUsage>,
@@ -416,6 +417,7 @@ impl Assembly {
416417
Access::Public,
417418
None,
418419
None,
420+
true,
419421
);
420422
let cref = class_def.ref_to();
421423
let cref = self.class_refs.alloc(cref);
@@ -540,6 +542,7 @@ impl Assembly {
540542
Access::Public,
541543
None,
542544
None,
545+
true,
543546
);
544547

545548
let Some(cref) = self.get_prealllocated_class_ref(class_def.ref_to()) else {
@@ -685,7 +688,7 @@ impl Assembly {
685688
}
686689
/// Converts the old assembly repr to the new one.
687690
#[must_use]
688-
pub fn from_v1(v1: &V1Asm) -> Self {
691+
pub fn from_v1(v1: &Assembly) -> Self {
689692
let mut empty: Assembly = v1.clone();
690693
let rust_void = empty.alloc_string("RustVoid");
691694
empty.class_def(ClassDef::new(
@@ -698,6 +701,7 @@ impl Assembly {
698701
Access::Public,
699702
None,
700703
None,
704+
true,
701705
));
702706

703707
#[cfg(debug_assertions)]
@@ -1023,10 +1027,11 @@ impl Assembly {
10231027
}
10241028
}
10251029
assert_eq!(self.alloc_string(MAIN_MODULE), original_str);
1030+
self.sections.extend(other.sections);
10261031
self
10271032
}
10281033

1029-
pub(crate) fn method_defs(&self) -> &FxHashMap<MethodDefIdx, MethodDef> {
1034+
pub fn method_defs(&self) -> &FxHashMap<MethodDefIdx, MethodDef> {
10301035
&self.method_defs
10311036
}
10321037

@@ -1172,26 +1177,29 @@ impl Assembly {
11721177
pub fn split_to_parts(&self, parts: u32) -> impl Iterator<Item = Self> + use<'_> {
11731178
let lib_name = StringIdx::from_index(std::num::NonZeroU32::new(1).unwrap());
11741179
let div = (self.method_refs.len().div_ceil(parts as usize)) as u32;
1180+
// Into 1st. Only split out the methods where it is known, for sure, that they don't access any statics.
11751181
(0..parts).map(move |rem| {
11761182
let mut part = self.clone();
11771183
part.method_defs.iter_mut().for_each(|(idx, def)| {
1178-
if idx.as_bimap_index().get() / div != rem {
1179-
/*if let MethodImpl::MethodBody {
1180-
blocks: _,
1181-
locals: _,
1182-
} = def.resolved_implementation(self).clone()
1183-
{
1184+
if def.accesses_statics(self) {
1185+
if 0 != rem {
11841186
*def.implementation_mut() = MethodImpl::Extern {
11851187
lib: lib_name,
11861188
preserve_errno: false,
11871189
}
1188-
}*/
1190+
}
1191+
} else if idx.as_bimap_index().get() / div != rem {
11891192
*def.implementation_mut() = MethodImpl::Extern {
11901193
lib: lib_name,
11911194
preserve_errno: false,
11921195
}
11931196
}
11941197
});
1198+
if 0 != rem {
1199+
part.class_defs
1200+
.iter_mut()
1201+
.for_each(|(_, def)| *def.static_fields_mut() = vec![]);
1202+
}
11951203
part.eliminate_dead_types();
11961204
//part.eliminate_dead_fns(true);
11971205
part = part.link_gc();
@@ -1267,6 +1275,40 @@ impl Assembly {
12671275
clone = clone.link(self);
12681276
clone
12691277
}
1278+
pub(crate) fn ptr_size(&self) -> u32 {
1279+
8
1280+
}
1281+
pub(crate) fn sizeof_type(&self, field_tpe: Type) -> u32 {
1282+
match field_tpe {
1283+
Type::Ref(_) | Type::Ptr(_) => self.ptr_size(),
1284+
Type::Int(int) => int
1285+
.size()
1286+
.unwrap_or(self.ptr_size().try_into().unwrap())
1287+
.into(),
1288+
Type::ClassRef(class_ref_idx) => self[self.class_ref_to_def(class_ref_idx).unwrap()]
1289+
.explict_size()
1290+
.unwrap()
1291+
.into(),
1292+
Type::Float(float) => float.size().into(),
1293+
Type::PlatformString => self.ptr_size(),
1294+
Type::PlatformChar => 1,
1295+
Type::PlatformGeneric(_, generic_kind) => todo!(),
1296+
Type::PlatformObject => self.ptr_size(),
1297+
Type::Bool => 1,
1298+
Type::Void => 0,
1299+
Type::PlatformArray { elem, dims } => todo!(),
1300+
Type::FnPtr(sig_idx) => self.ptr_size(),
1301+
Type::SIMDVector(simdvector) => (simdvector.bits() / 8).into(),
1302+
}
1303+
}
1304+
1305+
pub fn add_section(&mut self, arg: &str, packed_metadata: impl Into<Vec<u8>>) {
1306+
self.sections.insert(arg.into(), packed_metadata.into());
1307+
}
1308+
1309+
pub(crate) fn get_section(&self, arg: &str) -> Option<&Vec<u8>> {
1310+
self.sections.get(arg)
1311+
}
12701312
}
12711313
/// An initializer, which runs before everything else. By convention, it is used to initialize static / const data. Should not execute any user code
12721314
pub const CCTOR: &str = ".cctor";

cilly/src/v2/asm_link.rs

+1
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,7 @@ impl Assembly {
611611
*def.access(),
612612
def.explict_size(),
613613
def.align(),
614+
def.has_nonveralpping_layout(),
614615
);
615616
let class_ref = self.alloc_class_ref(translated.ref_to());
616617
let (defs_mut, _) = self.class_defs_mut_strings();

cilly/src/v2/builtins/math.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,8 @@ pub fn math(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) {
148148
sinh(asm, patcher);
149149
coshf(asm, patcher);
150150
cosh(asm, patcher);
151-
152151
}
153-
pub fn bitreverse(asm: &mut Assembly, patcher: &mut MissingMethodPatcher){
152+
pub fn bitreverse(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) {
154153
bitreverse_u32(asm, patcher);
155154
bitreverse_u64(asm, patcher);
156155
bitreverse_u128(asm, patcher);

cilly/src/v2/builtins/mod.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ fn insert_rust_realloc(asm: &mut Assembly, patcher: &mut MissingMethodPatcher, u
175175
Box::new(super::cilnode::PtrCastRes::Ptr(void_idx)),
176176
));
177177
let align = asm.alloc_node(CILNode::LdArg(2));
178-
178+
179179
let align = asm.alloc_node(CILNode::IntCast {
180180
input: align,
181181
target: Int::USize,
@@ -345,6 +345,7 @@ pub fn insert_exeception_stub(asm: &mut Assembly, patcher: &mut MissingMethodPat
345345
Access::Public,
346346
Some(NonZeroU32::new(8).unwrap()),
347347
None,
348+
true,
348349
));
349350
insert_catch_unwind_stub(asm, patcher);
350351
}
@@ -363,6 +364,7 @@ pub fn insert_exception(asm: &mut Assembly, patcher: &mut MissingMethodPatcher)
363364
Access::Public,
364365
None,
365366
None,
367+
true,
366368
));
367369
let ctor = asm.alloc_string(".ctor");
368370
let sig = asm.sig(
@@ -556,7 +558,7 @@ pub fn transmute(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) {
556558
let source = asm.alloc_type(source);
557559
let target_idx = asm.alloc_type(target);
558560
let addr = asm.alloc_node(CILNode::LdArgA(0));
559-
if asm.alignof_type(source) >= asm.alignof_type(target_idx){
561+
if asm.alignof_type(source) >= asm.alignof_type(target_idx) {
560562
let ptr = asm.alloc_node(CILNode::RefToPtr(addr));
561563
let ptr = asm.alloc_node(CILNode::PtrCast(ptr, Box::new(PtrCastRes::Ptr(target_idx))));
562564
let valuetype = asm.alloc_node(CILNode::LdInd {
@@ -569,20 +571,17 @@ pub fn transmute(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) {
569571
blocks: vec![BasicBlock::new(vec![ret], 0, None)],
570572
locals: vec![],
571573
}
572-
}else{
574+
} else {
573575
let dst = asm.alloc_node(CILNode::LdLocA(0));
574576
let size = asm.alloc_node(CILNode::SizeOf(source));
575-
let load = asm.alloc_root(CILRoot::CpBlk(Box::new((dst,addr,size))));
577+
let load = asm.alloc_root(CILRoot::CpBlk(Box::new((dst, addr, size))));
576578
let ret = asm.alloc_node(CILNode::LdLoc(0));
577579
let ret = asm.alloc_root(CILRoot::Ret(ret));
578580
MethodImpl::MethodBody {
579-
blocks: vec![BasicBlock::new(vec![load,ret], 0, None)],
581+
blocks: vec![BasicBlock::new(vec![load, ret], 0, None)],
580582
locals: vec![(None, target_idx)],
581583
}
582-
583584
}
584-
585-
586585
};
587586
patcher.insert(name, Box::new(generator));
588587
}

0 commit comments

Comments
 (0)