Skip to content

Commit ccde51a

Browse files
committed
Auto merge of #102717 - beetrees:repr128-c-style-debuginfo, r=nagisa
Pass 128-bit C-style enum enumerator values to LLVM Pass the full 128 bits of C-style enum enumerators through to LLVM. This means that debuginfo for C-style repr128 enums is now emitted correctly for DWARF platforms (as compared to not being correctly emitted on any platform). Tracking issue: #56071
2 parents a102dc8 + 6f6eebd commit ccde51a

File tree

6 files changed

+51
-14
lines changed

6 files changed

+51
-14
lines changed

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ fn build_variant_names_type_di_node<'ll, 'tcx>(
462462
cx,
463463
"VariantNames",
464464
variant_names_enum_base_type(cx),
465-
variants.map(|(variant_index, variant_name)| (variant_name, variant_index.as_u32() as u64)),
465+
variants.map(|(variant_index, variant_name)| (variant_name, variant_index.as_u32().into())),
466466
containing_scope,
467467
)
468468
}

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,7 @@ fn build_c_style_enum_di_node<'ll, 'tcx>(
9191
tag_base_type(cx, enum_type_and_layout),
9292
enum_adt_def.discriminants(cx.tcx).map(|(variant_index, discr)| {
9393
let name = Cow::from(enum_adt_def.variant(variant_index).name.as_str());
94-
// Is there anything we can do to support 128-bit C-Style enums?
95-
let value = discr.val as u64;
96-
(name, value)
94+
(name, discr.val)
9795
}),
9896
containing_scope,
9997
),
@@ -147,36 +145,34 @@ fn tag_base_type<'ll, 'tcx>(
147145
/// This is a helper function and does not register anything in the type map by itself.
148146
///
149147
/// `variants` is an iterator of (discr-value, variant-name).
150-
///
151-
// NOTE: Handling of discriminant values is somewhat inconsistent. They can appear as u128,
152-
// u64, and i64. Here everything gets mapped to i64 because that's what LLVM's API expects.
153148
fn build_enumeration_type_di_node<'ll, 'tcx>(
154149
cx: &CodegenCx<'ll, 'tcx>,
155150
type_name: &str,
156151
base_type: Ty<'tcx>,
157-
enumerators: impl Iterator<Item = (Cow<'tcx, str>, u64)>,
152+
enumerators: impl Iterator<Item = (Cow<'tcx, str>, u128)>,
158153
containing_scope: &'ll DIType,
159154
) -> &'ll DIType {
160155
let is_unsigned = match base_type.kind() {
161156
ty::Int(_) => false,
162157
ty::Uint(_) => true,
163158
_ => bug!("build_enumeration_type_di_node() called with non-integer tag type."),
164159
};
160+
let (size, align) = cx.size_and_align_of(base_type);
165161

166162
let enumerator_di_nodes: SmallVec<Option<&'ll DIType>> = enumerators
167163
.map(|(name, value)| unsafe {
164+
let value = [value as u64, (value >> 64) as u64];
168165
Some(llvm::LLVMRustDIBuilderCreateEnumerator(
169166
DIB(cx),
170167
name.as_ptr().cast(),
171168
name.len(),
172-
value as i64,
169+
value.as_ptr(),
170+
size.bits() as libc::c_uint,
173171
is_unsigned,
174172
))
175173
})
176174
.collect();
177175

178-
let (size, align) = cx.size_and_align_of(base_type);
179-
180176
unsafe {
181177
llvm::LLVMRustDIBuilderCreateEnumerationType(
182178
DIB(cx),

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2127,7 +2127,8 @@ extern "C" {
21272127
Builder: &DIBuilder<'a>,
21282128
Name: *const c_char,
21292129
NameLen: size_t,
2130-
Value: i64,
2130+
Value: *const u64,
2131+
SizeInBits: c_uint,
21312132
IsUnsigned: bool,
21322133
) -> &'a DIEnumerator;
21332134

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -1036,8 +1036,9 @@ extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
10361036

10371037
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
10381038
LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
1039-
int64_t Value, bool IsUnsigned) {
1040-
return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
1039+
const uint64_t Value[2], unsigned SizeInBits, bool IsUnsigned) {
1040+
return wrap(Builder->createEnumerator(StringRef(Name, NameLen),
1041+
APSInt(APInt(SizeInBits, makeArrayRef(Value, 2)), IsUnsigned)));
10411042
}
10421043

10431044
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# ignore-windows
2+
# This test should be replaced with one in src/test/debuginfo once GDB or LLDB support 128-bit
3+
# enums.
4+
5+
include ../../run-make-fulldeps/tools.mk
6+
7+
all:
8+
$(RUSTC) -Cdebuginfo=2 lib.rs -o $(TMPDIR)/repr128.rlib
9+
"$(LLVM_BIN_DIR)"/llvm-dwarfdump -n U128A $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value (<0x10> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 )"
10+
"$(LLVM_BIN_DIR)"/llvm-dwarfdump -n U128B $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value (<0x10> 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 )"
11+
"$(LLVM_BIN_DIR)"/llvm-dwarfdump -n U128C $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value (<0x10> 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 )"
12+
"$(LLVM_BIN_DIR)"/llvm-dwarfdump -n U128D $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value (<0x10> ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff )"
13+
"$(LLVM_BIN_DIR)"/llvm-dwarfdump -n I128A $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value (<0x10> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 )"
14+
"$(LLVM_BIN_DIR)"/llvm-dwarfdump -n I128B $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value (<0x10> ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff )"
15+
"$(LLVM_BIN_DIR)"/llvm-dwarfdump -n I128C $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value (<0x10> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 )"
16+
"$(LLVM_BIN_DIR)"/llvm-dwarfdump -n I128D $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value (<0x10> ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 7f )"
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#![crate_type = "lib"]
2+
#![feature(repr128)]
3+
4+
// Use .to_le() to ensure that the bytes are in the same order on both little- and big-endian
5+
// platforms.
6+
7+
#[repr(u128)]
8+
pub enum U128Enum {
9+
U128A = 0_u128.to_le(),
10+
U128B = 1_u128.to_le(),
11+
U128C = (u64::MAX as u128 + 1).to_le(),
12+
U128D = u128::MAX.to_le(),
13+
}
14+
15+
#[repr(i128)]
16+
pub enum I128Enum {
17+
I128A = 0_i128.to_le(),
18+
I128B = (-1_i128).to_le(),
19+
I128C = i128::MIN.to_le(),
20+
I128D = i128::MAX.to_le(),
21+
}
22+
23+
pub fn f(_: U128Enum, _: I128Enum) {}

0 commit comments

Comments
 (0)