Skip to content

Commit e5c4e9f

Browse files
committed
use llvm target info to get size
1 parent a0c1033 commit e5c4e9f

11 files changed

+118
-52
lines changed

src/codegen/debug.rs

Lines changed: 63 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use inkwell::{
99
DWARFEmissionKind, DebugInfoBuilder,
1010
},
1111
module::Module,
12+
targets::TargetData,
1213
values::{BasicMetadataValueEnum, FunctionValue, GlobalValue, PointerValue},
1314
};
1415
use rustc_hash::FxHashMap;
@@ -18,13 +19,15 @@ use plc_diagnostics::diagnostics::Diagnostic;
1819
use plc_source::source_location::SourceLocation;
1920

2021
use crate::{
21-
datalayout::{Bytes, MemoryLocation},
2222
index::{Index, PouIndexEntry, VariableIndexEntry},
2323
typesystem::{DataType, DataTypeInformation, Dimension, StringEncoding, CHAR_TYPE, WCHAR_TYPE},
2424
DebugLevel, OptimizationLevel,
2525
};
2626

27-
use super::generators::{llvm::Llvm, statement_generator::FunctionContext, ADDRESS_SPACE_GLOBAL};
27+
use super::{
28+
generators::{llvm::Llvm, statement_generator::FunctionContext, ADDRESS_SPACE_GLOBAL},
29+
llvm_index::LlvmTypedIndex,
30+
};
2831

2932
#[derive(PartialEq, Eq)]
3033
#[allow(non_camel_case_types)]
@@ -83,6 +86,7 @@ pub trait Debug<'ink> {
8386
name: &str,
8487
datatype: &'idx DataType,
8588
index: &'idx Index,
89+
types_index: &'idx LlvmTypedIndex,
8690
) -> Result<(), Diagnostic>;
8791

8892
/// Creates a globally accessible variable with the given datatype.
@@ -167,6 +171,7 @@ pub struct DebugBuilder<'ink> {
167171
variables: FxHashMap<VariableKey, DILocalVariable<'ink>>,
168172
optimization: OptimizationLevel,
169173
files: FxHashMap<&'static str, DIFile<'ink>>,
174+
target_data: TargetData,
170175
}
171176

172177
/// A wrapper that redirects to correct debug builder implementation based on the debug context.
@@ -230,6 +235,9 @@ impl<'ink> DebugBuilderEnum<'ink> {
230235
"",
231236
);
232237

238+
let data_layout = module.get_data_layout();
239+
let data_layout = data_layout.as_str().to_str().expect("Data layout is valid");
240+
let target_data = TargetData::create(data_layout);
233241
let dbg_obj = DebugBuilder {
234242
context,
235243
debug_info,
@@ -238,6 +246,7 @@ impl<'ink> DebugBuilderEnum<'ink> {
238246
variables: Default::default(),
239247
optimization,
240248
files: Default::default(),
249+
target_data,
241250
};
242251
match debug_level {
243252
DebugLevel::VariablesOnly(_) => DebugBuilderEnum::VariablesOnly(dbg_obj),
@@ -273,8 +282,9 @@ impl<'ink> DebugBuilder<'ink> {
273282
&mut self,
274283
name: &str,
275284
members: &[VariableIndexEntry],
276-
index: &Index,
277285
location: &SourceLocation,
286+
index: &Index,
287+
types_index: &LlvmTypedIndex,
278288
) -> Result<(), Diagnostic> {
279289
//Create each type
280290
let index_types = members
@@ -285,21 +295,23 @@ impl<'ink> DebugBuilder<'ink> {
285295
index.get_type(type_name.as_ref()).map(|dt| (name, dt, location))
286296
})
287297
.collect::<Result<Vec<_>, Diagnostic>>()?;
298+
let struct_type = types_index.get_associated_type(name).map(|it| it.into_struct_type())?;
288299

289300
let file = location
290301
.get_file_name()
291302
.map(|it| self.get_or_create_debug_file(it))
292303
.unwrap_or_else(|| self.compile_unit.get_file());
293304

294305
let mut types = vec![];
295-
let mut running_offset = MemoryLocation::new(0);
296-
for (member_name, dt, location) in index_types.into_iter() {
297-
let di_type = self.get_or_create_debug_type(dt, index)?;
306+
let mut offset = 0; //self.target_data.offset_of_element(&struct_type, element_index as u32).unwrap_or(0);
307+
for (element_index, (member_name, dt, location)) in index_types.into_iter().enumerate() {
308+
let di_type = self.get_or_create_debug_type(dt, index, types_index)?;
298309

299310
//Adjust the offset based on the field alignment
300-
let type_info = dt.get_type_information();
301-
// let alignment = type_info.get_alignment(index);
302-
let size = type_info.get_size(index).unwrap();
311+
let size = types_index
312+
.find_associated_type(dt.get_name())
313+
.map(|llvm_type| self.target_data.get_bit_size(&llvm_type))
314+
.unwrap_or(0);
303315

304316
types.push(
305317
self.debug_info
@@ -308,24 +320,25 @@ impl<'ink> DebugBuilder<'ink> {
308320
member_name,
309321
file,
310322
location.get_line_plus_one() as u32,
311-
size.bits().into(),
323+
size,
312324
0, // no alignment for now
313-
running_offset.bits().into(),
325+
offset,
314326
DIFlags::PUBLIC,
315327
di_type.into(),
316328
)
317329
.as_type(),
318330
);
319-
running_offset += size;
331+
offset += size;
320332
}
321333

334+
let size = self.target_data.get_bit_size(&struct_type);
322335
//Create a struct type
323336
let struct_type = self.debug_info.create_struct_type(
324337
file.as_debug_info_scope(),
325338
name,
326339
file,
327340
location.get_line_plus_one() as u32,
328-
running_offset.bits().into(),
341+
size,
329342
0, // no alignment for now
330343
DIFlags::PUBLIC,
331344
None,
@@ -344,9 +357,9 @@ impl<'ink> DebugBuilder<'ink> {
344357
name: &str,
345358
inner_type: &str,
346359
dimensions: &[Dimension],
347-
size: Bytes,
348-
alignment: Bytes,
360+
size: u64,
349361
index: &Index,
362+
types_index: &LlvmTypedIndex,
350363
) -> Result<(), Diagnostic> {
351364
//find the inner type debug info
352365
let inner_type = index.get_type(inner_type)?;
@@ -357,11 +370,11 @@ impl<'ink> DebugBuilder<'ink> {
357370
//Convert to normal range
358371
.collect::<Result<Vec<Range<i64>>, _>>()
359372
.map_err(|err| Diagnostic::codegen_error(err, SourceLocation::undefined()))?;
360-
let inner_type = self.get_or_create_debug_type(inner_type, index)?;
373+
let inner_type = self.get_or_create_debug_type(inner_type, index, types_index)?;
361374
let array_type = self.debug_info.create_array_type(
362375
inner_type.into(),
363-
size.bits().into(),
364-
alignment.bits(),
376+
size,
377+
0, //No set alignment
365378
subscript.as_slice(),
366379
);
367380
self.register_concrete_type(name, DebugType::Composite(array_type));
@@ -372,17 +385,17 @@ impl<'ink> DebugBuilder<'ink> {
372385
&mut self,
373386
name: &str,
374387
inner_type: &str,
375-
size: Bytes,
376-
alignment: Bytes,
388+
size: u64,
377389
index: &Index,
390+
types_index: &LlvmTypedIndex,
378391
) -> Result<(), Diagnostic> {
379392
let inner_type = index.get_type(inner_type)?;
380-
let inner_type = self.get_or_create_debug_type(inner_type, index)?;
393+
let inner_type = self.get_or_create_debug_type(inner_type, index, types_index)?;
381394
let pointer_type = self.debug_info.create_pointer_type(
382395
name,
383396
inner_type.into(),
384-
size.bits().into(),
385-
alignment.bits(),
397+
size,
398+
0, //No set alignment
386399
inkwell::AddressSpace::from(ADDRESS_SPACE_GLOBAL),
387400
);
388401
self.register_concrete_type(name, DebugType::Derived(pointer_type));
@@ -393,14 +406,15 @@ impl<'ink> DebugBuilder<'ink> {
393406
&mut self,
394407
dt: &DataType,
395408
index: &Index,
409+
types_index: &LlvmTypedIndex,
396410
) -> Result<DebugType<'ink>, Diagnostic> {
397411
//Try to find a type in the types
398-
let dt_name = dt.get_name().to_lowercase();
412+
let dt_name = dt.get_name();
399413
//Attempt to re-register the type, this will do nothing if the type exists.
400414
//TODO: This will crash on recursive datatypes
401-
self.register_debug_type(&dt_name, dt, index)?;
415+
self.register_debug_type(dt_name, dt, index, types_index)?;
402416
self.types
403-
.get(&dt_name)
417+
.get(&dt_name.to_lowercase())
404418
.ok_or_else(|| {
405419
Diagnostic::new(format!("Cannot find debug information for type {dt_name}"))
406420
.with_error_code("E076")
@@ -413,21 +427,21 @@ impl<'ink> DebugBuilder<'ink> {
413427
name: &str,
414428
length: i64,
415429
encoding: StringEncoding,
416-
size: Bytes,
417-
alignment: Bytes,
430+
size: u64,
418431
index: &Index,
432+
types_index: &LlvmTypedIndex,
419433
) -> Result<(), Diagnostic> {
420434
// Register a utf8 or 16 basic type
421435
let inner_type = match encoding {
422436
StringEncoding::Utf8 => index.get_effective_type_or_void_by_name(CHAR_TYPE),
423437
StringEncoding::Utf16 => index.get_effective_type_or_void_by_name(WCHAR_TYPE),
424438
};
425-
let inner_type = self.get_or_create_debug_type(inner_type, index)?;
439+
let inner_type = self.get_or_create_debug_type(inner_type, index, types_index)?;
426440
//Register an array
427441
let array_type = self.debug_info.create_array_type(
428442
inner_type.into(),
429-
size.bits().into(),
430-
alignment.bits(),
443+
size,
444+
0, //No set alignment
431445
#[allow(clippy::single_range_in_vec_init)]
432446
&[(0..length)],
433447
);
@@ -439,11 +453,12 @@ impl<'ink> DebugBuilder<'ink> {
439453
&mut self,
440454
name: &str,
441455
referenced_type: &str,
442-
index: &Index,
443456
location: &SourceLocation,
457+
index: &Index,
458+
types_index: &LlvmTypedIndex,
444459
) -> Result<(), Diagnostic> {
445460
let inner_dt = index.get_effective_type_by_name(referenced_type)?;
446-
let inner_type = self.get_or_create_debug_type(inner_dt, index)?;
461+
let inner_type = self.get_or_create_debug_type(inner_dt, index, types_index)?;
447462
let file = location
448463
.get_file_name()
449464
.map(|it| self.get_or_create_debug_file(it))
@@ -627,21 +642,26 @@ impl<'ink> Debug<'ink> for DebugBuilder<'ink> {
627642
name: &str,
628643
datatype: &'idx DataType,
629644
index: &'idx Index,
645+
types_index: &LlvmTypedIndex,
630646
) -> Result<(), Diagnostic> {
631647
//check if the type is currently registered
632648
if !self.types.contains_key(&name.to_lowercase()) {
633649
let type_info = datatype.get_type_information();
634-
let size = type_info.get_size(index).unwrap();
650+
let size = types_index
651+
.find_associated_type(name)
652+
.map(|llvm_type| self.target_data.get_bit_size(&llvm_type))
653+
.unwrap_or(0);
635654
let location = &datatype.location;
636655
match type_info {
637656
DataTypeInformation::Struct { members, .. } => {
638-
self.create_struct_type(name, members.as_slice(), index, location)
657+
//TODO: we can only register this after expansion
658+
self.create_struct_type(name, members.as_slice(), location, index, types_index)
639659
}
640660
DataTypeInformation::Array { name, inner_type_name, dimensions, .. } => {
641-
self.create_array_type(name, inner_type_name, dimensions, size, Bytes::new(0), index)
661+
self.create_array_type(name, inner_type_name, dimensions, size, index, types_index)
642662
}
643663
DataTypeInformation::Pointer { name, inner_type_name, .. } => {
644-
self.create_pointer_type(name, inner_type_name, size, Bytes::new(0), index)
664+
self.create_pointer_type(name, inner_type_name, size, index, types_index)
645665
}
646666
DataTypeInformation::Integer { signed, size, .. } => {
647667
let encoding = if type_info.is_bool() {
@@ -663,11 +683,11 @@ impl<'ink> Debug<'ink> for DebugBuilder<'ink> {
663683
let length = string_size
664684
.as_int_value(index)
665685
.map_err(|err| Diagnostic::codegen_error(err, SourceLocation::undefined()))?;
666-
self.create_string_type(name, length, *encoding, size, Bytes::new(0), index)
686+
self.create_string_type(name, length, *encoding, size, index, types_index)
667687
}
668688
DataTypeInformation::Alias { name, referenced_type }
669689
| DataTypeInformation::Enum { name, referenced_type, .. } => {
670-
self.create_typedef_type(name, referenced_type, index, location)
690+
self.create_typedef_type(name, referenced_type, location, index, types_index)
671691
}
672692
// Other types are just derived basic types
673693
_ => Ok(()),
@@ -897,10 +917,13 @@ impl<'ink> Debug<'ink> for DebugBuilderEnum<'ink> {
897917
name: &str,
898918
datatype: &'idx DataType,
899919
index: &'idx Index,
920+
types_index: &'idx LlvmTypedIndex,
900921
) -> Result<(), Diagnostic> {
901922
match self {
902923
Self::None => Ok(()),
903-
Self::VariablesOnly(obj) | Self::Full(obj) => obj.register_debug_type(name, datatype, index),
924+
Self::VariablesOnly(obj) | Self::Full(obj) => {
925+
obj.register_debug_type(name, datatype, index, types_index)
926+
}
904927
}
905928
}
906929

src/codegen/generators/data_type_generator.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ pub fn generate_data_types<'ink>(
117117
generator.expand_opaque_types(user_type)?;
118118
}
119119

120+
// Now generate debug information for all types
121+
generator.generate_debug_types()?;
122+
120123
let mut tries = 0;
121124
let mut errors = FxHashMap::default();
122125

@@ -198,7 +201,6 @@ impl<'ink> DataTypeGenerator<'ink, '_> {
198201
/// Generates only an opaque type for structs.
199202
/// Eagerly generates but does not associate nested array and referenced aliased types
200203
fn create_type(&mut self, name: &str, data_type: &DataType) -> Result<BasicTypeEnum<'ink>, Diagnostic> {
201-
self.debug.register_debug_type(name, data_type, self.index)?;
202204
let information = data_type.get_type_information();
203205
match information {
204206
DataTypeInformation::Struct { source, .. } => match source {
@@ -462,6 +464,30 @@ impl<'ink> DataTypeGenerator<'ink, '_> {
462464

463465
Ok(result)
464466
}
467+
468+
fn generate_debug_types(&mut self) -> Result<(), Diagnostic> {
469+
for data_type in self
470+
.index
471+
.get_types()
472+
.entries()
473+
.flat_map(|(_, data_type)| data_type.first())
474+
.filter(|data_type| !data_type.is_generic(self.index))
475+
{
476+
self.debug.register_debug_type(data_type.get_name(), data_type, self.index, &self.types_index)?;
477+
}
478+
for data_type in self
479+
.index
480+
.get_pou_types()
481+
.entries()
482+
.flat_map(|(_, data_type)| data_type.first())
483+
.filter(|data_type| !data_type.is_generic(self.index))
484+
.filter(|data_type| data_type.is_backed_by_struct())
485+
{
486+
self.debug.register_debug_type(data_type.get_name(), data_type, self.index, &self.types_index)?;
487+
}
488+
489+
Ok(())
490+
}
465491
}
466492

467493
pub fn get_default_for(basic_type: BasicTypeEnum) -> BasicValueEnum {

src/codegen/generators/expression_generator.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2402,6 +2402,7 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
24022402
.as_int_value(self.index)
24032403
.map_err(|err| Diagnostic::codegen_error(err.as_str(), right_location))?;
24042404
let size = std::cmp::min(target_size - 1, value_size);
2405+
//FIXME: use the target_layout for this operation
24052406
let alignment = left_type.get_string_character_width(self.index).value();
24062407
//Multiply by the string alignment to copy enough for widestrings
24072408
//This is done at compile time to avoid generating an extra mul

src/codegen/tests/debug_tests/snapshots/rusty__codegen__tests__debug_tests__expression_debugging__aggregate_return_value_variable_in_function.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ attributes #1 = { argmemonly nofree nounwind willreturn }
3939
!7 = !{null, !8}
4040
!8 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "__auto_pointer_to_STRING", baseType: !9, size: 64, dwarfAddressSpace: 1)
4141
!9 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 648, elements: !11)
42-
!10 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_UTF, flags: DIFlagPublic)
42+
!10 = !DIBasicType(name: "CHAR", size: 8, encoding: DW_ATE_UTF, flags: DIFlagPublic)
4343
!11 = !{!12}
4444
!12 = !DISubrange(count: 81, lowerBound: 0)
4545
!13 = !{}

src/codegen/tests/debug_tests/snapshots/rusty__codegen__tests__debug_tests__expression_debugging__string_size_correctly_set_in_dwarf_info.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ source_filename = "<internal>"
1414
!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !2, line: 3, type: !3, isLocal: false, isDefinition: true)
1515
!2 = !DIFile(filename: "<internal>", directory: "")
1616
!3 = !DICompositeType(tag: DW_TAG_array_type, baseType: !4, size: 520, elements: !5)
17-
!4 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_UTF, flags: DIFlagPublic)
17+
!4 = !DIBasicType(name: "CHAR", size: 8, encoding: DW_ATE_UTF, flags: DIFlagPublic)
1818
!5 = !{!6}
1919
!6 = !DISubrange(count: 65, lowerBound: 0)
2020
!7 = !{i32 2, !"Dwarf Version", i32 5}

src/codegen/tests/oop_tests/debug_tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ fn members_from_base_class_are_available_in_subclasses() {
8282
!6 = !DIBasicType(name: "INT", size: 16, encoding: DW_ATE_signed, flags: DIFlagPublic)
8383
!7 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !2, file: !2, line: 5, baseType: !8, size: 648, offset: 16, flags: DIFlagPublic)
8484
!8 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, size: 648, elements: !10)
85-
!9 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_UTF, flags: DIFlagPublic)
85+
!9 = !DIBasicType(name: "CHAR", size: 8, encoding: DW_ATE_UTF, flags: DIFlagPublic)
8686
!10 = !{!11}
8787
!11 = !DISubrange(count: 81, lowerBound: 0)
8888
!12 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !2, file: !2, line: 6, baseType: !13, size: 7128, offset: 664, flags: DIFlagPublic)
@@ -389,7 +389,7 @@ fn write_to_parent_variable_in_instance() {
389389
!7 = !{!8}
390390
!8 = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: !2, file: !2, line: 4, baseType: !9, size: 648, flags: DIFlagPublic)
391391
!9 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 648, elements: !11)
392-
!10 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_UTF, flags: DIFlagPublic)
392+
!10 = !DIBasicType(name: "CHAR", size: 8, encoding: DW_ATE_UTF, flags: DIFlagPublic)
393393
!11 = !{!12}
394394
!12 = !DISubrange(count: 81, lowerBound: 0)
395395
!13 = !DIGlobalVariableExpression(var: !14, expr: !DIExpression())

0 commit comments

Comments
 (0)