Skip to content

Commit 36101c7

Browse files
committed
add target datalayout and triple to IR
1 parent f2f442e commit 36101c7

File tree

4 files changed

+73
-70
lines changed

4 files changed

+73
-70
lines changed

compiler/plc_driver/src/pipelines.rs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,7 @@ impl<T: SourceContainer> Pipeline for BuildPipeline<T> {
410410
dependencies,
411411
literals,
412412
&got_layout,
413+
self.compile_parameters.as_ref().and_then(|it| it.target.as_ref()),
413414
)?;
414415
self.participants.iter().try_fold((), |_, participant| participant.generate(&module))
415416
})
@@ -684,8 +685,16 @@ impl AnnotatedProject {
684685
.iter()
685686
.map(|AnnotatedUnit { unit, dependencies, literals }| {
686687
let context = CodegenContext::create();
687-
self.generate_module(&context, compile_options, unit, dependencies, literals, &got_layout)
688-
.map(|it| it.persist_to_string())
688+
self.generate_module(
689+
&context,
690+
compile_options,
691+
unit,
692+
dependencies,
693+
literals,
694+
&got_layout,
695+
None,
696+
)
697+
.map(|it| it.persist_to_string())
689698
})
690699
.collect()
691700
}
@@ -707,7 +716,15 @@ impl AnnotatedProject {
707716
.iter()
708717
// TODO: this can be parallelized
709718
.map(|AnnotatedUnit { unit, dependencies, literals }| {
710-
self.generate_module(context, compile_options, unit, dependencies, literals, &got_layout)
719+
self.generate_module(
720+
context,
721+
compile_options,
722+
unit,
723+
dependencies,
724+
literals,
725+
&got_layout,
726+
None,
727+
)
711728
})
712729
.reduce(|a, b| {
713730
let a = a?;
@@ -720,6 +737,7 @@ impl AnnotatedProject {
720737
module.map(Some)
721738
}
722739

740+
#[allow(clippy::too_many_arguments)]
723741
fn generate_module<'ctx>(
724742
&self,
725743
context: &'ctx CodegenContext,
@@ -728,7 +746,11 @@ impl AnnotatedProject {
728746
dependencies: &FxIndexSet<Dependency>,
729747
literals: &StringLiterals,
730748
got_layout: &Mutex<HashMap<String, u64>>,
749+
target: Option<&Target>,
731750
) -> Result<GeneratedModule<'ctx>, Diagnostic> {
751+
// Determine target from compile_options or use default
752+
let target = target.unwrap_or(&Target::System);
753+
732754
let mut code_generator = plc::codegen::CodeGen::new(
733755
context,
734756
compile_options.root.as_deref(),
@@ -737,6 +759,7 @@ impl AnnotatedProject {
737759
compile_options.debug_level,
738760
//FIXME don't clone here
739761
compile_options.online_change.clone(),
762+
target,
740763
);
741764
//Create a types codegen, this contains all the type declarations
742765
//Associate the index type with LLVM types
@@ -796,7 +819,15 @@ impl AnnotatedProject {
796819
self.units
797820
.iter()
798821
.map(|AnnotatedUnit { unit, dependencies, literals }| {
799-
self.generate_module(context, compile_options, unit, dependencies, literals, &got_layout)
822+
self.generate_module(
823+
context,
824+
compile_options,
825+
unit,
826+
dependencies,
827+
literals,
828+
&got_layout,
829+
None,
830+
)
800831
})
801832
.collect()
802833
}

src/codegen.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,38 @@ impl<'ink> CodeGen<'ink> {
9999
optimization_level: OptimizationLevel,
100100
debug_level: DebugLevel,
101101
online_change: OnlineChange,
102+
target: &Target,
102103
) -> CodeGen<'ink> {
103104
let module_location = file_marker.get_name().unwrap_or_default();
104105
let module = context.create_module(module_location);
105106
module.set_source_file_name(module_location);
107+
108+
// Initialize all targets
109+
let initialization_config = &InitializationConfig::default();
110+
inkwell::targets::Target::initialize_all(initialization_config);
111+
let triple = target.get_target_triple();
112+
113+
// Create target from triple
114+
let target_obj =
115+
inkwell::targets::Target::from_triple(&triple).expect("Failed to create target from triple");
116+
117+
// Create a target machine with default options
118+
let target_machine = target_obj
119+
.create_target_machine(
120+
&triple,
121+
"generic", // CPU features - generic for portability
122+
"", // CPU features - empty string for default
123+
optimization_level.into(),
124+
inkwell::targets::RelocMode::Default,
125+
inkwell::targets::CodeModel::Default,
126+
)
127+
.expect("Failed to create target machine");
128+
129+
// Get the data layout from the target machine and set the module's data layout and triple
130+
let target_data = target_machine.get_target_data();
131+
module.set_data_layout(&target_data.get_data_layout());
132+
module.set_triple(&triple);
133+
106134
let debug_level = if file_marker.is_internal() { DebugLevel::None } else { debug_level };
107135
let debug = debug::DebugBuilderEnum::new(context, &module, root, optimization_level, debug_level);
108136
CodeGen { module, debug, module_location: module_location.to_string(), online_change }

src/codegen/debug.rs

Lines changed: 7 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -303,60 +303,24 @@ impl<'ink> DebugBuilder<'ink> {
303303
.unwrap_or_else(|| self.compile_unit.get_file());
304304

305305
let mut types = vec![];
306-
let mut last_offset_bits = 0;
307-
let mut last_size_bits = 0;
308306

309307
for (element_index, (member_name, dt, location)) in index_types.iter().enumerate() {
310308
let di_type = self.get_or_create_debug_type(dt, index, types_index)?;
311309

312-
// Get the size and alignment
310+
// Get the size and alignment from LLVM
313311
let llvm_type = types_index.find_associated_type(dt.get_name());
314312
let align_bits =
315313
llvm_type.map(|ty| self.target_data.get_preferred_alignment(&ty) * 8).unwrap_or(0);
316314
let size_bits = llvm_type.map(|ty| self.target_data.get_bit_size(&ty)).unwrap_or(0);
317315

318316
// Get LLVM's calculated offset
319-
let llvm_offset_bits = self
317+
let offset_bits = self
320318
.target_data
321319
.offset_of_element(&struct_type, element_index as u32)
322320
.map(|offset| offset * 8)
323321
.unwrap_or(0);
324322

325-
// Calculate the properly aligned offset based on the previous field
326-
// and this field's alignment requirements
327-
let offset_bits = if size_bits == 0 || (last_size_bits == 0 && element_index > 0) {
328-
// For zero-sized types, always use LLVM's offset directly
329-
// This ensures they don't contribute to the overall layout calculation
330-
// If the previous field was zero-sized, use LLVM's offset
331-
// for proper alignment of fields after zero-sized types
332-
llvm_offset_bits
333-
} else {
334-
let next_offset_bits: u64 = last_offset_bits + last_size_bits;
335-
336-
// Special handling based on alignment requirements:
337-
// - Fields with alignment of 64 bits need to be explicitly aligned
338-
// to their alignment boundary to prevent misaligned accesses
339-
// - Fields with a lower alignment can use LLVM's natural layout
340-
// This differentiation is crucial for correctly representing complex structures
341-
// where some fields (like LWORD, LINT) need specific alignment while others (like BYTE, BOOL)
342-
// can be packed more efficiently
343-
if align_bits == 64 {
344-
// For fields requiring special alignment (64 bit types),
345-
// round up to the nearest alignment boundary
346-
next_offset_bits.div_ceil(align_bits as u64) * align_bits as u64
347-
} else {
348-
// For smaller fields fields (BYTE, BOOL, DINT), we still ensure we don't
349-
// overlap with previous fields by using the maximum of our calculated offset
350-
// and LLVM's calculated offset
351-
std::cmp::max(next_offset_bits, llvm_offset_bits)
352-
}
353-
};
354-
355-
// Update tracking variables for next field
356-
last_offset_bits = offset_bits;
357-
last_size_bits = size_bits;
358-
359-
// Create the member type with calculated offset
323+
// Create the member type with LLVM's calculated offset
360324
types.push(
361325
self.debug_info
362326
.create_member_type(
@@ -374,39 +338,17 @@ impl<'ink> DebugBuilder<'ink> {
374338
);
375339
}
376340

377-
// Calculate struct size based on the last field's offset + size, properly aligned
341+
// Use LLVM's calculation for the struct size
378342
let llvm_size = self.target_data.get_bit_size(&struct_type);
379-
// Calculate our manual size based on adjusted offsets
380-
let calculated_size = {
381-
// Get struct alignment requirement (usually 8 bytes/64 bits for 64-bit architectures)
382-
let struct_align_bits = self.target_data.get_preferred_alignment(&struct_type) * 8;
383-
384-
// Calculate total size based on last field offset + size, rounded up to alignment
385-
let last_field_end_bits = last_offset_bits + last_size_bits;
386-
let aligned_size_bits =
387-
last_field_end_bits.div_ceil(struct_align_bits as u64) * struct_align_bits as u64;
388-
389-
// If our calculated size is larger than LLVM's, use ours
390-
if aligned_size_bits > llvm_size {
391-
log::trace!(
392-
"Struct {}: adjusted size from {} to {} bits due to field alignment",
393-
name,
394-
llvm_size,
395-
aligned_size_bits
396-
);
397-
aligned_size_bits
398-
} else {
399-
llvm_size
400-
}
401-
};
343+
let struct_align_bits = self.target_data.get_preferred_alignment(&struct_type) * 8;
402344

403345
let struct_type = self.debug_info.create_struct_type(
404346
file.as_debug_info_scope(),
405347
name,
406348
file,
407349
location.get_line_plus_one() as u32,
408-
calculated_size,
409-
self.target_data.get_preferred_alignment(&struct_type) * 8,
350+
llvm_size,
351+
struct_align_bits,
410352
DIFlags::PUBLIC,
411353
None,
412354
types.as_slice(),

src/test_utils.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub mod tests {
2525
StringLiterals, TypeAnnotator,
2626
},
2727
typesystem::get_builtin_types,
28-
DebugLevel, OnlineChange, Validator,
28+
DebugLevel, OnlineChange, Target, Validator,
2929
};
3030

3131
pub fn parse(src: &str) -> (CompilationUnit, Vec<Diagnostic>) {
@@ -254,6 +254,7 @@ pub mod tests {
254254
crate::OptimizationLevel::None,
255255
debug_level,
256256
online_change.clone(),
257+
&Target::System,
257258
);
258259
let llvm_index = code_generator
259260
.generate_llvm_index(&context, &annotations, &literals, &dependencies, &index, &got_layout)
@@ -321,6 +322,7 @@ pub mod tests {
321322
crate::OptimizationLevel::None,
322323
debug_level,
323324
crate::OnlineChange::Disabled,
325+
&Target::System,
324326
);
325327
let got_layout = Mutex::new(HashMap::default());
326328

0 commit comments

Comments
 (0)