Skip to content

Commit d569dfe

Browse files
committed
auto merge of #17871 : michaelwoerister/rust/lldb-versioning, r=alexcrichton
Apart from making the build system determine the LLDB version, this PR also fixes an issue with enums in LLDB pretty printers. In order for GDB's pretty printers to know for sure if a field of some value is an enum discriminant, I had rustc mark discriminant fields with the `artificial` DWARF tag. This worked out nicely for GDB but it turns out that one can't access artificial fields from LLDB. So I changed the debuginfo representation so that enum discriminants are marked by the special field name `RUST$ENUM$DISR` instead, which works in both cases. The PR does not activate the LLDB test suite yet.
2 parents 63fe80e + 98a0f91 commit d569dfe

19 files changed

+152
-48
lines changed

configure

+5-1
Original file line numberDiff line numberDiff line change
@@ -535,13 +535,17 @@ probe CFG_LLDB lldb
535535

536536
if [ ! -z "$CFG_GDB" ]
537537
then
538-
# Extract the version
538+
# Store GDB's version
539539
CFG_GDB_VERSION=$($CFG_GDB --version 2>/dev/null | head -1)
540540
putvar CFG_GDB_VERSION
541541
fi
542542

543543
if [ ! -z "$CFG_LLDB" ]
544544
then
545+
# Store LLDB's version
546+
CFG_LLDB_VERSION=$($CFG_LLDB --version 2>/dev/null | head -1)
547+
putvar CFG_LLDB_VERSION
548+
545549
# If CFG_LLDB_PYTHON_DIR is not already set from the outside and valid, try to read it from
546550
# LLDB via the -P commandline options.
547551
if [ -z "$CFG_LLDB_PYTHON_DIR" ] || [ ! -d "$CFG_LLDB_PYTHON_DIR" ]

mk/tests.mk

+1
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,7 @@ CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3) := \
625625
--target $(2) \
626626
--host $(3) \
627627
--gdb-version="$(CFG_GDB_VERSION)" \
628+
--lldb-version="$(CFG_LLDB_VERSION)" \
628629
--android-cross-path=$(CFG_ANDROID_CROSS_PATH) \
629630
--adb-path=$(CFG_ADB) \
630631
--adb-test-dir=$(CFG_ADB_TEST_DIR) \

src/compiletest/common.rs

+3
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ pub struct Config {
133133
// Version of GDB
134134
pub gdb_version: Option<String>,
135135

136+
// Version of LLDB
137+
pub lldb_version: Option<String>,
138+
136139
// Path to the android tools
137140
pub android_cross_path: Path,
138141

src/compiletest/compiletest.rs

+37-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ pub fn parse_config(args: Vec<String> ) -> Config {
7171
optflag("", "jit", "run tests under the JIT"),
7272
optopt("", "target", "the target to build for", "TARGET"),
7373
optopt("", "host", "the host to build for", "HOST"),
74-
optopt("", "gdb-version", "the version of GDB used", "MAJOR.MINOR"),
74+
optopt("", "gdb-version", "the version of GDB used", "VERSION STRING"),
75+
optopt("", "lldb-version", "the version of LLDB used", "VERSION STRING"),
7576
optopt("", "android-cross-path", "Android NDK standalone path", "PATH"),
7677
optopt("", "adb-path", "path to the android debugger", "PATH"),
7778
optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH"),
@@ -149,6 +150,7 @@ pub fn parse_config(args: Vec<String> ) -> Config {
149150
target: opt_str2(matches.opt_str("target")),
150151
host: opt_str2(matches.opt_str("host")),
151152
gdb_version: extract_gdb_version(matches.opt_str("gdb-version")),
153+
lldb_version: extract_lldb_version(matches.opt_str("lldb-version")),
152154
android_cross_path: opt_path(matches, "android-cross-path"),
153155
adb_path: opt_str2(matches.opt_str("adb-path")),
154156
adb_test_dir: opt_str2(matches.opt_str("adb-test-dir")),
@@ -391,3 +393,37 @@ fn extract_gdb_version(full_version_line: Option<String>) -> Option<String> {
391393
_ => None
392394
}
393395
}
396+
397+
fn extract_lldb_version(full_version_line: Option<String>) -> Option<String> {
398+
// Extract the major LLDB version from the given version string.
399+
// LLDB version strings are different for Apple and non-Apple platforms.
400+
// At the moment, this function only supports the Apple variant, which looks
401+
// like this:
402+
//
403+
// LLDB-179.5 (older versions)
404+
// lldb-300.2.51 (new versions)
405+
//
406+
// We are only interested in the major version number, so this function
407+
// will return `Some("179")` and `Some("300")` respectively.
408+
409+
match full_version_line {
410+
Some(ref full_version_line)
411+
if full_version_line.as_slice().trim().len() > 0 => {
412+
let full_version_line = full_version_line.as_slice().trim();
413+
414+
let re = Regex::new(r"[Ll][Ll][Dd][Bb]-([0-9]+)").unwrap();
415+
416+
match re.captures(full_version_line) {
417+
Some(captures) => {
418+
Some(captures.at(1).to_string())
419+
}
420+
None => {
421+
println!("Could not extract LLDB version from line '{}'",
422+
full_version_line);
423+
None
424+
}
425+
}
426+
},
427+
_ => None
428+
}
429+
}

src/compiletest/header.rs

+38-1
Original file line numberDiff line numberDiff line change
@@ -181,14 +181,42 @@ pub fn is_test_ignored(config: &Config, testfile: &Path) -> bool {
181181
}
182182
}
183183

184+
fn ignore_lldb(config: &Config, line: &str) -> bool {
185+
if config.mode != common::DebugInfoLldb {
186+
return false;
187+
}
188+
189+
if parse_name_directive(line, "ignore-lldb") {
190+
return true;
191+
}
192+
193+
match config.lldb_version {
194+
Some(ref actual_version) => {
195+
if line.contains("min-lldb-version") {
196+
let min_version = line.trim()
197+
.split(' ')
198+
.last()
199+
.expect("Malformed lldb version directive");
200+
// Ignore if actual version is smaller the minimum required
201+
// version
202+
lldb_version_to_int(actual_version.as_slice()) <
203+
lldb_version_to_int(min_version.as_slice())
204+
} else {
205+
false
206+
}
207+
}
208+
None => false
209+
}
210+
}
211+
184212
let val = iter_header(testfile, |ln| {
185213
!parse_name_directive(ln, "ignore-test") &&
186214
!parse_name_directive(ln, ignore_target(config).as_slice()) &&
187215
!parse_name_directive(ln, ignore_stage(config).as_slice()) &&
188216
!(config.mode == common::Pretty && parse_name_directive(ln, "ignore-pretty")) &&
189217
!(config.target != config.host && parse_name_directive(ln, "ignore-cross-compile")) &&
190218
!ignore_gdb(config, ln) &&
191-
!(config.mode == common::DebugInfoLldb && parse_name_directive(ln, "ignore-lldb"))
219+
!ignore_lldb(config, ln)
192220
});
193221

194222
!val
@@ -330,3 +358,12 @@ pub fn gdb_version_to_int(version_string: &str) -> int {
330358

331359
return major * 1000 + minor;
332360
}
361+
362+
pub fn lldb_version_to_int(version_string: &str) -> int {
363+
let error_string = format!(
364+
"Encountered LLDB version string with unexpected format: {}",
365+
version_string);
366+
let error_string = error_string.as_slice();
367+
let major: int = FromStr::from_str(version_string).expect(error_string);
368+
return major;
369+
}

src/compiletest/runtest.rs

+11
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,17 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path)
626626

627627
let exe_file = make_exe_name(config, testfile);
628628

629+
match config.lldb_version {
630+
Some(ref version) => {
631+
println!("NOTE: compiletest thinks it is using LLDB version {}",
632+
version.as_slice());
633+
}
634+
_ => {
635+
println!("NOTE: compiletest does not know which version of \
636+
LLDB it is using");
637+
}
638+
}
639+
629640
// Parse debugger commands etc from test files
630641
let DebuggerCommands {
631642
commands,

src/etc/gdb_rust_pretty_printing.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ def classify_struct(type):
196196
if field_count == 0:
197197
return STRUCT_KIND_REGULAR_STRUCT
198198

199-
if fields[0].artificial:
199+
if fields[0].name == "RUST$ENUM$DISR":
200200
if field_count == 1:
201201
return STRUCT_KIND_CSTYLE_VARIANT
202202
elif fields[1].name == None:

src/etc/lldb_rust_formatters.py

+16-3
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,19 @@ def print_enum_val(val, internal_dict):
117117

118118
assert val.GetType().GetTypeClass() == lldb.eTypeClassUnion
119119

120+
120121
if val.num_children == 1:
122+
# This is either an enum with just one variant, or it is an Option-like enum
123+
# where the discriminant is encoded in a non-nullable pointer field. We find
124+
# out which one it is by looking at the member name of the sole union
125+
# variant. If it starts with "RUST$ENCODED$ENUM$" then we have an
126+
# Option-like enum.
121127
first_variant_name = val.GetChildAtIndex(0).GetName()
122128
if first_variant_name and first_variant_name.startswith("RUST$ENCODED$ENUM$"):
123-
# Try to extract the
124129

130+
# This is an Option-like enum. The position of the discriminator field is
131+
# encoded in the name which has the format:
132+
# RUST$ENCODED$ENUM$<index of discriminator field>$<name of null variant>
125133
last_separator_index = first_variant_name.rfind("$")
126134
if last_separator_index == -1:
127135
return "<invalid enum encoding: %s>" % first_variant_name
@@ -130,25 +138,30 @@ def print_enum_val(val, internal_dict):
130138
if second_last_separator_index == -1:
131139
return "<invalid enum encoding: %s>" % first_variant_name
132140

141+
# Extract index of the discriminator field
133142
try:
134143
disr_field_index = first_variant_name[second_last_separator_index + 1 :
135144
last_separator_index]
136145
disr_field_index = int(disr_field_index)
137146
except:
138147
return "<invalid enum encoding: %s>" % first_variant_name
139148

149+
# Read the discriminant
140150
disr_val = val.GetChildAtIndex(0).GetChildAtIndex(disr_field_index).GetValueAsUnsigned()
141151

142152
if disr_val == 0:
153+
# Null case: Print the name of the null-variant
143154
null_variant_name = first_variant_name[last_separator_index + 1:]
144155
return null_variant_name
145156
else:
157+
# Non-null case: Interpret the data as a value of the non-null variant type
146158
return print_struct_val_starting_from(0, val.GetChildAtIndex(0), internal_dict)
147159
else:
160+
# This is just a regular uni-variant enum without discriminator field
148161
return print_struct_val_starting_from(0, val.GetChildAtIndex(0), internal_dict)
149162

150-
# extract the discriminator value by
151-
disr_val = val.GetChildAtIndex(0).GetChildAtIndex(0)
163+
# If we are here, this is a regular enum with more than one variant
164+
disr_val = val.GetChildAtIndex(0).GetChildMemberWithName("RUST$ENUM$DISR")
152165
disr_type = disr_val.GetType()
153166

154167
if disr_type.GetTypeClass() != lldb.eTypeClassEnumeration:

src/librustc/middle/trans/debuginfo.rs

+5-10
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,6 @@ static UNKNOWN_FILE_METADATA: DIFile = (0 as DIFile);
242242
static UNKNOWN_SCOPE_METADATA: DIScope = (0 as DIScope);
243243

244244
static FLAGS_NONE: c_uint = 0;
245-
static FLAGS_ARTIFICAL: c_uint = llvm::debuginfo::FlagArtificial as c_uint;
246245

247246
//=-----------------------------------------------------------------------------
248247
// Public Interface of debuginfo module
@@ -2276,11 +2275,7 @@ impl VariantMemberDescriptionFactory {
22762275
_ => type_metadata(cx, ty, self.span)
22772276
},
22782277
offset: ComputedMemberOffset,
2279-
flags: if self.discriminant_type_metadata.is_some() && i == 0 {
2280-
FLAGS_ARTIFICAL
2281-
} else {
2282-
FLAGS_NONE
2283-
}
2278+
flags: FLAGS_NONE
22842279
}
22852280
}).collect()
22862281
}
@@ -2339,9 +2334,9 @@ fn describe_enum_variant(cx: &CrateContext,
23392334
None => variant_info.args.iter().map(|_| "".to_string()).collect()
23402335
};
23412336

2342-
// If this is not a univariant enum, there is also the (unnamed) discriminant field.
2337+
// If this is not a univariant enum, there is also the discriminant field.
23432338
match discriminant_info {
2344-
RegularDiscriminant(_) => arg_names.insert(0, "".to_string()),
2339+
RegularDiscriminant(_) => arg_names.insert(0, "RUST$ENUM$DISR".to_string()),
23452340
_ => { /* do nothing */ }
23462341
};
23472342

@@ -2713,14 +2708,14 @@ fn vec_slice_metadata(cx: &CrateContext,
27132708
llvm_type: *member_llvm_types.get(0),
27142709
type_metadata: element_type_metadata,
27152710
offset: ComputedMemberOffset,
2716-
flags: FLAGS_ARTIFICAL
2711+
flags: FLAGS_NONE
27172712
},
27182713
MemberDescription {
27192714
name: "length".to_string(),
27202715
llvm_type: *member_llvm_types.get(1),
27212716
type_metadata: type_metadata(cx, ty::mk_uint(), span),
27222717
offset: ComputedMemberOffset,
2723-
flags: FLAGS_ARTIFICAL
2718+
flags: FLAGS_NONE
27242719
},
27252720
];
27262721

src/test/debuginfo/borrowed-enum.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// ignore-tidy-linelength
1112
// ignore-android: FIXME(#10381)
1213

1314
// compile-flags:-g
@@ -19,10 +20,10 @@
1920
// gdb-command:finish
2021

2122
// gdb-command:print *the_a_ref
22-
// gdb-check:$1 = {{TheA, x = 0, y = 8970181431921507452}, {TheA, 0, 2088533116, 2088533116}}
23+
// gdb-check:$1 = {{RUST$ENUM$DISR = TheA, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = TheA, 0, 2088533116, 2088533116}}
2324

2425
// gdb-command:print *the_b_ref
25-
// gdb-check:$2 = {{TheB, x = 0, y = 1229782938247303441}, {TheB, 0, 286331153, 286331153}}
26+
// gdb-check:$2 = {{RUST$ENUM$DISR = TheB, x = 0, y = 1229782938247303441}, {RUST$ENUM$DISR = TheB, 0, 286331153, 286331153}}
2627

2728
// gdb-command:print *univariant_ref
2829
// gdb-check:$3 = {{4820353753753434}}

src/test/debuginfo/by-value-non-immediate-argument.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// ignore-tidy-linelength
1112
// ignore-android: FIXME(#10381)
1213

1314
// compile-flags:-g
@@ -43,7 +44,7 @@
4344

4445
// gdb-command:finish
4546
// gdb-command:print x
46-
// gdb-check:$7 = {{Case1, x = 0, y = 8970181431921507452}, {Case1, 0, 2088533116, 2088533116}}
47+
// gdb-check:$7 = {{RUST$ENUM$DISR = Case1, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = Case1, 0, 2088533116, 2088533116}}
4748
// gdb-command:continue
4849

4950

src/test/debuginfo/generic-struct-style-enum.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@
1818
// gdb-command:finish
1919

2020
// gdb-command:print case1
21-
// gdb-check:$1 = {{Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {Case1, a = 0, b = 2088533116, c = 2088533116}, {Case1, a = 0, b = 8970181431921507452}}
21+
// gdb-check:$1 = {{RUST$ENUM$DISR = Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {RUST$ENUM$DISR = Case1, a = 0, b = 2088533116, c = 2088533116}, {RUST$ENUM$DISR = Case1, a = 0, b = 8970181431921507452}}
2222

2323
// gdb-command:print case2
24-
// gdb-check:$2 = {{Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {Case2, a = 0, b = 286331153, c = 286331153}, {Case2, a = 0, b = 1229782938247303441}}
24+
// gdb-check:$2 = {{RUST$ENUM$DISR = Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {RUST$ENUM$DISR = Case2, a = 0, b = 286331153, c = 286331153}, {RUST$ENUM$DISR = Case2, a = 0, b = 1229782938247303441}}
2525

2626
// gdb-command:print case3
27-
// gdb-check:$3 = {{Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {Case3, a = 0, b = 1499027801, c = 1499027801}, {Case3, a = 0, b = 6438275382588823897}}
27+
// gdb-check:$3 = {{RUST$ENUM$DISR = Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {RUST$ENUM$DISR = Case3, a = 0, b = 1499027801, c = 1499027801}, {RUST$ENUM$DISR = Case3, a = 0, b = 6438275382588823897}}
2828

2929
// gdb-command:print univariant
3030
// gdb-check:$4 = {{a = -1}}

src/test/debuginfo/generic-tuple-style-enum.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@
2121
// gdb-command:finish
2222

2323
// gdb-command:print case1
24-
// gdb-check:$1 = {{Case1, 0, 31868, 31868, 31868, 31868}, {Case1, 0, 2088533116, 2088533116}, {Case1, 0, 8970181431921507452}}
24+
// gdb-check:$1 = {{RUST$ENUM$DISR = Case1, 0, 31868, 31868, 31868, 31868}, {RUST$ENUM$DISR = Case1, 0, 2088533116, 2088533116}, {RUST$ENUM$DISR = Case1, 0, 8970181431921507452}}
2525

2626
// gdb-command:print case2
27-
// gdb-check:$2 = {{Case2, 0, 4369, 4369, 4369, 4369}, {Case2, 0, 286331153, 286331153}, {Case2, 0, 1229782938247303441}}
27+
// gdb-check:$2 = {{RUST$ENUM$DISR = Case2, 0, 4369, 4369, 4369, 4369}, {RUST$ENUM$DISR = Case2, 0, 286331153, 286331153}, {RUST$ENUM$DISR = Case2, 0, 1229782938247303441}}
2828

2929
// gdb-command:print case3
30-
// gdb-check:$3 = {{Case3, 0, 22873, 22873, 22873, 22873}, {Case3, 0, 1499027801, 1499027801}, {Case3, 0, 6438275382588823897}}
30+
// gdb-check:$3 = {{RUST$ENUM$DISR = Case3, 0, 22873, 22873, 22873, 22873}, {RUST$ENUM$DISR = Case3, 0, 1499027801, 1499027801}, {RUST$ENUM$DISR = Case3, 0, 6438275382588823897}}
3131

3232
// gdb-command:print univariant
3333
// gdb-check:$4 = {{-1}}

0 commit comments

Comments
 (0)