Skip to content

Commit dde8058

Browse files
committed
big refactor part 2: migrate to parameterised constructors for object init
1 parent 6d50cff commit dde8058

21 files changed

Lines changed: 796 additions & 265 deletions

File tree

.github/workflows/ci.yml

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,50 +11,37 @@ jobs:
1111
runs-on: ubuntu-latest
1212

1313
steps:
14-
# 1. Checkout Code
1514
- name: Checkout repository
1615
uses: actions/checkout@v4
1716

18-
# 2. Set up Rust
1917
- name: Set up Rust (nightly)
2018
uses: dtolnay/rust-toolchain@stable
2119
with:
2220
toolchain: nightly
2321
components: rustc-dev llvm-tools cargo
2422

25-
# 4. Set up Java
2623
- name: Set up Java
2724
uses: actions/setup-java@v4
2825
with:
2926
distribution: 'temurin'
3027
java-version: '25'
3128

32-
# 5. Set up Python
3329
- name: Set up Python
3430
uses: actions/setup-python@v5
3531
with:
3632
python-version: '3.x'
3733

38-
# 6. Set up Gradle
3934
- name: Set up Gradle
4035
uses: gradle/actions/setup-gradle@v4
4136

42-
# 7. make just the files needed to cargo cache
43-
- name: Gen Files
44-
run: python3 build.py gen-files
45-
46-
# 8. Cargo Caching (Crucial for speed)
4737
- name: Cache cargo dependencies
4838
uses: Swatinem/rust-cache@v2
4939

50-
# 9. Build using the CI-specific target
51-
- name: Build CI Target
40+
- name: Build backend and tools
5241
run: python3 build.py ci
5342

54-
# 10. Run tests
5543
- name: Run integration tests (debug mode)
5644
run: python3 Tester.py
5745

58-
# 11. Run tests in release mode
5946
- name: Run integration tests (release mode)
60-
run: python3 Tester.py --release
47+
run: python3 Tester.py --release

build.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,8 @@ def all_tasks():
259259
"""Runs all necessary build tasks in the correct order."""
260260
if not Config.IS_CI:
261261
install_rust_components()
262-
generate_config_files()
262+
263+
generate_config_files()
263264

264265
# The order defines the dependency chain.
265266
build_library()
@@ -311,4 +312,4 @@ def help_message():
311312

312313
# Execute the chosen target function
313314
target_func, _ = TARGETS[args.target]
314-
target_func()
315+
target_func()

src/lib.rs

Lines changed: 172 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use rustc_codegen_ssa::back::archive::{ArArchiveBuilder, ArchiveBuilder, Archive
2828
use rustc_codegen_ssa::{
2929
CompiledModule, CompiledModules, CrateInfo, ModuleKind, traits::CodegenBackend,
3030
};
31-
use std::collections::HashMap;
31+
use std::collections::{HashMap, HashSet};
3232

3333
use rustc_data_structures::fx::FxIndexMap;
3434
use rustc_hir::{QPath, TyKind as HirTyKind};
@@ -123,6 +123,124 @@ fn lower_closure_to_oomir<'tcx>(
123123
oomir_module.merge_data_types(&data_types);
124124
}
125125

126+
fn placeholder_operand_for_constructor_field(ty: &Type) -> Operand {
127+
let constant = match ty {
128+
Type::Boolean => oomir::Constant::Boolean(false),
129+
Type::Char => oomir::Constant::Char('\0'),
130+
Type::I8 => oomir::Constant::I8(0),
131+
Type::I16 => oomir::Constant::I16(0),
132+
Type::I32 => oomir::Constant::I32(0),
133+
Type::I64 => oomir::Constant::I64(0),
134+
Type::F32 => oomir::Constant::F32(0.0),
135+
Type::F64 => oomir::Constant::F64(0.0),
136+
Type::String
137+
| Type::Class(_)
138+
| Type::Interface(_)
139+
| Type::Array(_)
140+
| Type::MutableReference(_)
141+
| Type::Reference(_) => oomir::Constant::Null(ty.clone()),
142+
Type::Void => panic!("unexpected Void field type in constructor placeholder"),
143+
};
144+
Operand::Constant(constant)
145+
}
146+
147+
fn constructor_args_from_fields(
148+
fields: &[(String, Type)],
149+
values: &[(&str, Operand)],
150+
) -> Vec<(Operand, Type)> {
151+
fields
152+
.iter()
153+
.map(|(field_name, field_ty)| {
154+
let operand = values
155+
.iter()
156+
.find_map(|(name, operand)| (*name == field_name).then(|| operand.clone()))
157+
.unwrap_or_else(|| {
158+
breadcrumbs::log!(
159+
breadcrumbs::LogLevel::Info,
160+
"shim",
161+
format!(
162+
"Info: Using constructor placeholder for missing shim field '{}' ({:?})",
163+
field_name, field_ty
164+
)
165+
);
166+
placeholder_operand_for_constructor_field(field_ty)
167+
});
168+
(operand, field_ty.clone())
169+
})
170+
.collect()
171+
}
172+
173+
fn pad_construct_object_args_in_function(
174+
function: &mut oomir::Function,
175+
class_fields: &HashMap<String, Vec<(String, Type)>>,
176+
) {
177+
for block in function.body.basic_blocks.values_mut() {
178+
for instruction in &mut block.instructions {
179+
let oomir::Instruction::ConstructObject {
180+
class_name, args, ..
181+
} = instruction
182+
else {
183+
continue;
184+
};
185+
186+
let Some(fields) = class_fields.get(class_name) else {
187+
continue;
188+
};
189+
190+
if args.len() >= fields.len() {
191+
continue;
192+
}
193+
194+
for (field_name, field_ty) in fields.iter().skip(args.len()) {
195+
breadcrumbs::log!(
196+
breadcrumbs::LogLevel::Info,
197+
"shim",
198+
format!(
199+
"Info: Padding constructor for '{}' with placeholder field '{}' ({:?})",
200+
class_name, field_name, field_ty
201+
)
202+
);
203+
args.push((
204+
placeholder_operand_for_constructor_field(field_ty),
205+
field_ty.clone(),
206+
));
207+
}
208+
}
209+
}
210+
}
211+
212+
fn pad_construct_object_args_for_field_constructors(oomir_module: &mut oomir::Module) {
213+
let class_fields: HashMap<String, Vec<(String, Type)>> = oomir_module
214+
.data_types
215+
.iter()
216+
.filter_map(|(class_name, data_type)| match data_type {
217+
oomir::DataType::Class { fields, .. } => {
218+
let mut fields = fields.clone();
219+
let mut seen_fields = HashSet::new();
220+
fields.retain(|(name, _)| seen_fields.insert(name.clone()));
221+
Some((class_name.clone(), fields))
222+
}
223+
oomir::DataType::Interface { .. } => None,
224+
})
225+
.collect();
226+
227+
for function in oomir_module.functions.values_mut() {
228+
pad_construct_object_args_in_function(function, &class_fields);
229+
}
230+
231+
for data_type in oomir_module.data_types.values_mut() {
232+
let oomir::DataType::Class { methods, .. } = data_type else {
233+
continue;
234+
};
235+
236+
for method in methods.values_mut() {
237+
if let oomir::DataTypeMethod::Function(function) = method {
238+
pad_construct_object_args_in_function(function, &class_fields);
239+
}
240+
}
241+
}
242+
}
243+
126244
fn install_fmt_arguments_shim(oomir_module: &mut oomir::Module) {
127245
let class_name = "Arguments__".to_string();
128246
let Some(oomir::DataType::Class {
@@ -154,23 +272,24 @@ fn install_fmt_arguments_shim(oomir_module: &mut oomir::Module) {
154272
ty
155273
});
156274

275+
let from_str_fields = fields.clone();
157276
methods.entry("from_str".to_string()).or_insert_with(|| {
158277
let block = oomir::BasicBlock {
159278
label: "bb0".to_string(),
160279
instructions: vec![
161280
oomir::Instruction::ConstructObject {
162281
dest: "_args".to_string(),
163282
class_name: class_name.clone(),
164-
},
165-
oomir::Instruction::SetField {
166-
object: "_args".to_string(),
167-
field_name: "message".to_string(),
168-
value: Operand::Variable {
169-
name: "_1".to_string(),
170-
ty: Type::String,
171-
},
172-
field_ty: Type::String,
173-
owner_class: class_name.clone(),
283+
args: constructor_args_from_fields(
284+
&from_str_fields,
285+
&[(
286+
"message",
287+
Operand::Variable {
288+
name: "_1".to_string(),
289+
ty: Type::String,
290+
},
291+
)],
292+
),
174293
},
175294
oomir::Instruction::Return {
176295
operand: Some(Operand::Variable {
@@ -194,6 +313,7 @@ fn install_fmt_arguments_shim(oomir_module: &mut oomir::Module) {
194313
})
195314
});
196315

316+
let new_fields = fields.clone();
197317
methods.entry("new".to_string()).or_insert_with(|| {
198318
let argument_class = "core_fmt_rt_Argument__".to_string();
199319
let block = oomir::BasicBlock {
@@ -228,16 +348,32 @@ fn install_fmt_arguments_shim(oomir_module: &mut oomir::Module) {
228348
oomir::Instruction::ConstructObject {
229349
dest: "_args".to_string(),
230350
class_name: class_name.clone(),
231-
},
232-
oomir::Instruction::SetField {
233-
object: "_args".to_string(),
234-
field_name: "message".to_string(),
235-
value: Operand::Variable {
236-
name: "_message".to_string(),
237-
ty: Type::String,
238-
},
239-
field_ty: Type::String,
240-
owner_class: class_name.clone(),
351+
args: constructor_args_from_fields(
352+
&new_fields,
353+
&[
354+
(
355+
"message",
356+
Operand::Variable {
357+
name: "_message".to_string(),
358+
ty: Type::String,
359+
},
360+
),
361+
(
362+
"template",
363+
Operand::Variable {
364+
name: "_1".to_string(),
365+
ty: Type::Array(Box::new(Type::I16)),
366+
},
367+
),
368+
(
369+
"args",
370+
Operand::Variable {
371+
name: "_2".to_string(),
372+
ty: Type::Array(Box::new(Type::Class(argument_class.clone()))),
373+
},
374+
),
375+
],
376+
),
241377
},
242378
oomir::Instruction::Return {
243379
operand: Some(Operand::Variable {
@@ -371,14 +507,11 @@ fn install_fmt_argument_shim(oomir_module: &mut oomir::Module) {
371507
fields.push(("value".to_string(), Type::String));
372508
}
373509

510+
let argument_fields = fields.clone();
374511
methods.entry("new_display".to_string()).or_insert_with(|| {
375512
let block = oomir::BasicBlock {
376513
label: "bb0".to_string(),
377514
instructions: vec![
378-
oomir::Instruction::ConstructObject {
379-
dest: "_arg".to_string(),
380-
class_name: class_name.clone(),
381-
},
382515
oomir::Instruction::InvokeStatic {
383516
dest: Some("_value".to_string()),
384517
class_name: "java/lang/String".to_string(),
@@ -393,15 +526,19 @@ fn install_fmt_argument_shim(oomir_module: &mut oomir::Module) {
393526
ty: Type::I32,
394527
}],
395528
},
396-
oomir::Instruction::SetField {
397-
object: "_arg".to_string(),
398-
field_name: "value".to_string(),
399-
value: Operand::Variable {
400-
name: "_value".to_string(),
401-
ty: Type::String,
402-
},
403-
field_ty: Type::String,
404-
owner_class: class_name.clone(),
529+
oomir::Instruction::ConstructObject {
530+
dest: "_arg".to_string(),
531+
class_name: class_name.clone(),
532+
args: constructor_args_from_fields(
533+
&argument_fields,
534+
&[(
535+
"value",
536+
Operand::Variable {
537+
name: "_value".to_string(),
538+
ty: Type::String,
539+
},
540+
)],
541+
),
405542
},
406543
oomir::Instruction::Return {
407544
operand: Some(Operand::Variable {
@@ -1265,6 +1402,7 @@ impl CodegenBackend for MyBackend {
12651402

12661403
install_fmt_argument_shim(&mut oomir_module);
12671404
install_fmt_arguments_shim(&mut oomir_module);
1405+
pad_construct_object_args_for_field_constructors(&mut oomir_module);
12681406

12691407
breadcrumbs::log!(
12701408
breadcrumbs::LogLevel::Info,

src/lower1/control_flow/checked_intrinsics.rs

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -263,26 +263,22 @@ pub fn emit_checked_arithmetic_intrinsic(
263263
instrs.push(Instruction::ConstructObject {
264264
dest: tmp_struct.clone(),
265265
class_name: result_struct_name.clone(),
266-
});
267-
instrs.push(Instruction::SetField {
268-
object: tmp_struct.clone(),
269-
field_name: "field0".to_string(),
270-
value: Operand::Variable {
271-
name: result.clone(),
272-
ty: ty.clone(),
273-
},
274-
field_ty: ty.clone(),
275-
owner_class: result_struct_name.clone(),
276-
});
277-
instrs.push(Instruction::SetField {
278-
object: tmp_struct.clone(),
279-
field_name: "field1".to_string(),
280-
value: Operand::Variable {
281-
name: overflow.clone(),
282-
ty: Type::Boolean,
283-
},
284-
field_ty: Type::Boolean,
285-
owner_class: result_struct_name.clone(),
266+
args: vec![
267+
(
268+
Operand::Variable {
269+
name: result.clone(),
270+
ty: ty.clone(),
271+
},
272+
ty.clone(),
273+
),
274+
(
275+
Operand::Variable {
276+
name: overflow.clone(),
277+
ty: Type::Boolean,
278+
},
279+
Type::Boolean,
280+
),
281+
],
286282
});
287283
instrs.push(Instruction::Return {
288284
operand: Some(Operand::Variable {

0 commit comments

Comments
 (0)