From 8c3f6c72c07e853e28cf7226a3f76da2fd5a9c6e Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Mon, 26 Aug 2024 23:37:03 -0400 Subject: [PATCH] Dwarf: fix and test string format --- ci/x86_64-linux-debug.sh | 2 +- ci/x86_64-linux-release.sh | 2 +- src/Value.zig | 64 ++++++++-------------- src/arch/wasm/CodeGen.zig | 2 +- src/codegen/llvm.zig | 2 +- src/link.zig | 3 +- src/link/Dwarf.zig | 106 ++++++++++++++++++++++++++++++------- test/src/Debugger.zig | 76 ++++++++++++++++++++++++++ 8 files changed, 193 insertions(+), 64 deletions(-) diff --git a/ci/x86_64-linux-debug.sh b/ci/x86_64-linux-debug.sh index f4a4e0e13b..b058b5005e 100755 --- a/ci/x86_64-linux-debug.sh +++ b/ci/x86_64-linux-debug.sh @@ -64,7 +64,7 @@ stage3-debug/bin/zig build \ stage3-debug/bin/zig build test docs \ --maxrss 21000000000 \ - -Dlldb=$HOME/deps/lldb-zig/Debug-62538077d/bin/lldb \ + -Dlldb=$HOME/deps/lldb-zig/Debug-70b8227f1/bin/lldb \ -fqemu \ -fwasmtime \ -Dstatic-llvm \ diff --git a/ci/x86_64-linux-release.sh b/ci/x86_64-linux-release.sh index f9ebad2ade..f976439d67 100755 --- a/ci/x86_64-linux-release.sh +++ b/ci/x86_64-linux-release.sh @@ -64,7 +64,7 @@ stage3-release/bin/zig build \ stage3-release/bin/zig build test docs \ --maxrss 21000000000 \ - -Dlldb=$HOME/deps/lldb-zig/Release-62538077d/bin/lldb \ + -Dlldb=$HOME/deps/lldb-zig/Release-70b8227f1/bin/lldb \ -fqemu \ -fwasmtime \ -Dstatic-llvm \ diff --git a/src/Value.zig b/src/Value.zig index 516561d581..0843045f75 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -192,11 +192,12 @@ pub fn toBigIntAdvanced( zcu: *Zcu, tid: strat.Tid(), ) Zcu.CompileError!BigIntConst { + const ip = &zcu.intern_pool; return switch (val.toIntern()) { .bool_false => BigIntMutable.init(&space.limbs, 0).toConst(), .bool_true => BigIntMutable.init(&space.limbs, 1).toConst(), .null_value => BigIntMutable.init(&space.limbs, 0).toConst(), - else => switch (zcu.intern_pool.indexToKey(val.toIntern())) { + else => switch (ip.indexToKey(val.toIntern())) { .int => |int| switch (int.storage) { .u64, .i64, .big_int => int.storage.toBigInt(space), .lazy_align, .lazy_size => |ty| { @@ -214,6 +215,7 @@ pub fn toBigIntAdvanced( &space.limbs, (try val.getUnsignedIntInner(strat, zcu, tid)).?, ).toConst(), + .err => |err| BigIntMutable.init(&space.limbs, ip.getErrorValueIfExists(err.name).?).toConst(), else => unreachable, }, }; @@ -326,15 +328,11 @@ pub fn toBool(val: Value) bool { }; } -fn ptrHasIntAddr(val: Value, zcu: *Zcu) bool { - return zcu.intern_pool.getBackingAddrTag(val.toIntern()).? == .int; -} - /// Write a Value's contents to `buffer`. /// /// Asserts that buffer.len >= ty.abiSize(). The buffer is allowed to extend past /// the end of the value in memory. -pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) error{ +pub fn writeToMemory(val: Value, pt: Zcu.PerThread, buffer: []u8) error{ ReinterpretDeclRef, IllDefinedMemoryLayout, Unimplemented, @@ -343,19 +341,25 @@ pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) erro const zcu = pt.zcu; const target = zcu.getTarget(); const endian = target.cpu.arch.endian(); + const ip = &zcu.intern_pool; + const ty = val.typeOf(zcu); if (val.isUndef(zcu)) { const size: usize = @intCast(ty.abiSize(zcu)); @memset(buffer[0..size], 0xaa); return; } - const ip = &zcu.intern_pool; switch (ty.zigTypeTag(zcu)) { .Void => {}, .Bool => { buffer[0] = @intFromBool(val.toBool()); }, - .Int, .Enum => { - const int_info = ty.intInfo(zcu); + .Int, .Enum, .ErrorSet, .Pointer => |tag| { + const int_ty = if (tag == .Pointer) int_ty: { + if (ty.isSlice(zcu)) return error.IllDefinedMemoryLayout; + if (ip.getBackingAddrTag(val.toIntern()).? != .int) return error.ReinterpretDeclRef; + break :int_ty Type.usize; + } else ty; + const int_info = int_ty.intInfo(zcu); const bits = int_info.bits; const byte_count: u16 = @intCast((@as(u17, bits) + 7) / 8); @@ -379,7 +383,7 @@ pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) erro var buf_off: usize = 0; while (elem_i < len) : (elem_i += 1) { const elem_val = try val.elemValue(pt, elem_i); - try elem_val.writeToMemory(elem_ty, pt, buffer[buf_off..]); + try elem_val.writeToMemory(pt, buffer[buf_off..]); buf_off += elem_size; } }, @@ -403,8 +407,7 @@ pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) erro .elems => |elems| elems[field_index], .repeated_elem => |elem| elem, }); - const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); - try writeToMemory(field_val, field_ty, pt, buffer[off..]); + try writeToMemory(field_val, pt, buffer[off..]); }, .@"packed" => { const byte_count = (@as(usize, @intCast(ty.bitSize(zcu))) + 7) / 8; @@ -412,22 +415,6 @@ pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) erro }, } }, - .ErrorSet => { - const bits = zcu.errorSetBits(); - const byte_count: u16 = @intCast((@as(u17, bits) + 7) / 8); - - const name = switch (ip.indexToKey(val.toIntern())) { - .err => |err| err.name, - .error_union => |error_union| error_union.val.err_name, - else => unreachable, - }; - var bigint_buffer: BigIntSpace = undefined; - const bigint = BigIntMutable.init( - &bigint_buffer.limbs, - ip.getErrorValueIfExists(name).?, - ).toConst(); - bigint.writeTwosComplement(buffer[0..byte_count], endian); - }, .Union => switch (ty.containerLayout(zcu)) { .auto => return error.IllDefinedMemoryLayout, // Sema is supposed to have emitted a compile error already .@"extern" => { @@ -437,11 +424,11 @@ pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) erro const field_type = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); const field_val = try val.fieldValue(pt, field_index); const byte_count: usize = @intCast(field_type.abiSize(zcu)); - return writeToMemory(field_val, field_type, pt, buffer[0..byte_count]); + return writeToMemory(field_val, pt, buffer[0..byte_count]); } else { const backing_ty = try ty.unionBackingType(pt); const byte_count: usize = @intCast(backing_ty.abiSize(zcu)); - return writeToMemory(val.unionValue(zcu), backing_ty, pt, buffer[0..byte_count]); + return writeToMemory(val.unionValue(zcu), pt, buffer[0..byte_count]); } }, .@"packed" => { @@ -450,19 +437,13 @@ pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) erro return writeToPackedMemory(val, ty, pt, buffer[0..byte_count], 0); }, }, - .Pointer => { - if (ty.isSlice(zcu)) return error.IllDefinedMemoryLayout; - if (!val.ptrHasIntAddr(zcu)) return error.ReinterpretDeclRef; - return val.writeToMemory(Type.usize, pt, buffer); - }, .Optional => { if (!ty.isPtrLikeOptional(zcu)) return error.IllDefinedMemoryLayout; - const child = ty.optionalChild(zcu); const opt_val = val.optionalValue(zcu); if (opt_val) |some| { - return some.writeToMemory(child, pt, buffer); + return some.writeToMemory(pt, buffer); } else { - return writeToMemory(try pt.intValue(Type.usize, 0), Type.usize, pt, buffer); + return writeToMemory(try pt.intValue(Type.usize, 0), pt, buffer); } }, else => return error.Unimplemented, @@ -582,7 +563,7 @@ pub fn writeToPackedMemory( }, .Pointer => { assert(!ty.isSlice(zcu)); // No well defined layout. - if (!val.ptrHasIntAddr(zcu)) return error.ReinterpretDeclRef; + if (ip.getBackingAddrTag(val.toIntern()).? != .int) return error.ReinterpretDeclRef; return val.writeToPackedMemory(Type.usize, pt, buffer, bit_offset); }, .Optional => { @@ -3658,14 +3639,15 @@ pub fn mulAddScalar( /// If the value is represented in-memory as a series of bytes that all /// have the same value, return that byte value, otherwise null. -pub fn hasRepeatedByteRepr(val: Value, ty: Type, pt: Zcu.PerThread) !?u8 { +pub fn hasRepeatedByteRepr(val: Value, pt: Zcu.PerThread) !?u8 { const zcu = pt.zcu; + const ty = val.typeOf(zcu); const abi_size = std.math.cast(usize, ty.abiSize(zcu)) orelse return null; assert(abi_size >= 1); const byte_buffer = try zcu.gpa.alloc(u8, abi_size); defer zcu.gpa.free(byte_buffer); - writeToMemory(val, ty, pt, byte_buffer) catch |err| switch (err) { + writeToMemory(val, pt, byte_buffer) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.ReinterpretDeclRef => return null, // TODO: The writeToMemory function was originally created for the purpose diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index fbe63925dc..7627d3b277 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -3357,7 +3357,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue { .vector_type => { assert(determineSimdStoreStrategy(ty, zcu, func.target.*) == .direct); var buf: [16]u8 = undefined; - val.writeToMemory(ty, pt, &buf) catch unreachable; + val.writeToMemory(pt, &buf) catch unreachable; return func.storeSimdImmd(buf); }, .struct_type => { diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index eec46b8379..1352e6e3a1 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -9412,7 +9412,7 @@ pub const FuncGen = struct { // repeating byte pattern, for example, `@as(u64, 0)` has a // repeating byte pattern of 0 bytes. In such case, the memset // intrinsic can be used. - if (try elem_val.hasRepeatedByteRepr(elem_ty, pt)) |byte_val| { + if (try elem_val.hasRepeatedByteRepr(pt)) |byte_val| { const fill_byte = try o.builder.intValue(.i8, byte_val); const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); if (intrinsic_len0_traps) { diff --git a/src/link.zig b/src/link.zig index 635fdb49fa..409a504073 100644 --- a/src/link.zig +++ b/src/link.zig @@ -589,7 +589,8 @@ pub const File = struct { fs.File.WriteFileError || fs.File.OpenError || std.process.Child.SpawnError || - fs.Dir.CopyFileError; + fs.Dir.CopyFileError || + FlushDebugInfoError; /// Commit pending changes and write headers. Takes into account final output mode /// and `use_lld`, not only `effectiveOutputMode`. diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 68579e3282..2de8852916 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -17,13 +17,21 @@ debug_loclists: DebugLocLists, debug_rnglists: DebugRngLists, debug_str: StringSection, -pub const UpdateError = +pub const UpdateError = error{ + ReinterpretDeclRef, + IllDefinedMemoryLayout, + Unimplemented, + OutOfMemory, + EndOfStream, + Overflow, + Underflow, + UnexpectedEndOfFile, +} || std.fs.File.OpenError || std.fs.File.SetEndPosError || std.fs.File.CopyRangeError || std.fs.File.PReadError || - std.fs.File.PWriteError || - error{ EndOfStream, Overflow, Underflow, UnexpectedEndOfFile }; + std.fs.File.PWriteError; pub const FlushError = UpdateError || @@ -1401,7 +1409,7 @@ pub const WipNav = struct { else => Type.fromInterned(loaded_enum.tag_ty).intInfo(zcu).signedness, }; if (loaded_enum.values.len > 0) { - var big_int_space: InternPool.Key.Int.Storage.BigIntSpace = undefined; + var big_int_space: Value.BigIntSpace = undefined; const big_int = ip.indexToKey(loaded_enum.values.get(ip)[field_index]).int.storage.toBigInt(&big_int_space); const bits = @max(1, big_int.bitCountTwosCompForSignedness(signedness)); if (bits <= 64) { @@ -1429,9 +1437,12 @@ pub const WipNav = struct { } } else { try wip_nav.abbrevCode(abbrev_code.block); - const bytes = Type.fromInterned(loaded_enum.tag_ty).abiSize(wip_nav.pt.zcu); + const bytes = Type.fromInterned(loaded_enum.tag_ty).abiSize(zcu); try uleb128(diw, bytes); - big_int.writeTwosComplement(try wip_nav.debug_info.addManyAsSlice(wip_nav.dwarf.gpa, @intCast(bytes)), wip_nav.dwarf.endian); + big_int.writeTwosComplement( + try wip_nav.debug_info.addManyAsSlice(wip_nav.dwarf.gpa, @intCast(bytes)), + wip_nav.dwarf.endian, + ); } } else switch (signedness) { .signed => { @@ -2566,8 +2577,17 @@ fn updateType( .ptr_type => |ptr_type| switch (ptr_type.flags.size) { .One, .Many, .C => { const ptr_child_type = Type.fromInterned(ptr_type.child); - try wip_nav.abbrevCode(.ptr_type); + try wip_nav.abbrevCode(if (ptr_type.sentinel == .none) .ptr_type else .ptr_sentinel_type); try wip_nav.strp(name); + if (ptr_type.sentinel != .none) { + const bytes = ptr_child_type.abiSize(zcu); + try uleb128(diw, bytes); + const mem = try wip_nav.debug_info.addManyAsSlice(dwarf.gpa, @intCast(bytes)); + Value.fromInterned(ptr_type.sentinel).writeToMemory(pt, mem) catch |err| switch (err) { + error.IllDefinedMemoryLayout => @memset(mem, 0), + else => |e| return e, + }; + } try uleb128(diw, ptr_type.flags.alignment.toByteUnits() orelse ptr_child_type.abiAlignment(zcu).toByteUnits().?); try diw.writeByte(@intFromEnum(ptr_type.flags.address_space)); @@ -2609,16 +2629,34 @@ fn updateType( try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, }, - inline .array_type, .vector_type => |array_type, ty_tag| { - try wip_nav.abbrevCode(.array_type); + .array_type => |array_type| { + const array_child_type = Type.fromInterned(array_type.child); + try wip_nav.abbrevCode(if (array_type.sentinel == .none) .array_type else .array_sentinel_type); try wip_nav.strp(name); - try wip_nav.refType(Type.fromInterned(array_type.child)); - try diw.writeByte(@intFromBool(ty_tag == .vector_type)); + if (array_type.sentinel != .none) { + const bytes = array_child_type.abiSize(zcu); + try uleb128(diw, bytes); + const mem = try wip_nav.debug_info.addManyAsSlice(dwarf.gpa, @intCast(bytes)); + Value.fromInterned(array_type.sentinel).writeToMemory(pt, mem) catch |err| switch (err) { + error.IllDefinedMemoryLayout => @memset(mem, 0), + else => |e| return e, + }; + } + try wip_nav.refType(array_child_type); try wip_nav.abbrevCode(.array_index); try wip_nav.refType(Type.usize); try uleb128(diw, array_type.len); try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, + .vector_type => |vector_type| { + try wip_nav.abbrevCode(.vector_type); + try wip_nav.strp(name); + try wip_nav.refType(Type.fromInterned(vector_type.child)); + try wip_nav.abbrevCode(.array_index); + try wip_nav.refType(Type.usize); + try uleb128(diw, vector_type.len); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); + }, .opt_type => |opt_child_type_index| { const opt_child_type = Type.fromInterned(opt_child_type_index); try wip_nav.abbrevCode(.union_type); @@ -2660,7 +2698,7 @@ fn updateType( .error_set => { try wip_nav.refType(Type.fromInterned(try pt.intern(.{ .int_type = .{ .signedness = .unsigned, - .bits = pt.zcu.errorSetBits(), + .bits = zcu.errorSetBits(), } }))); try uleb128(diw, 0); }, @@ -2729,7 +2767,7 @@ fn updateType( try wip_nav.strp("is_error"); try wip_nav.refType(Type.fromInterned(try pt.intern(.{ .int_type = .{ .signedness = .unsigned, - .bits = pt.zcu.errorSetBits(), + .bits = zcu.errorSetBits(), } }))); try uleb128(diw, error_union_error_set_offset); @@ -2892,7 +2930,7 @@ fn updateType( try wip_nav.strp(name); try wip_nav.refType(Type.fromInterned(try pt.intern(.{ .int_type = .{ .signedness = .unsigned, - .bits = pt.zcu.errorSetBits(), + .bits = zcu.errorSetBits(), } }))); for (0..error_set_type.names.len) |field_index| { const field_name = error_set_type.names.get(ip)[field_index]; @@ -3204,7 +3242,8 @@ fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(A } pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { - const ip = &pt.zcu.intern_pool; + const zcu = pt.zcu; + const ip = &zcu.intern_pool; if (dwarf.types.get(.anyerror_type)) |entry| { var wip_nav: WipNav = .{ .dwarf = dwarf, @@ -3228,7 +3267,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { try wip_nav.strp("anyerror"); try wip_nav.refType(Type.fromInterned(try pt.intern(.{ .int_type = .{ .signedness = .unsigned, - .bits = pt.zcu.errorSetBits(), + .bits = zcu.errorSetBits(), } }))); for (global_error_set_names, 1..) |name, value| { try wip_nav.abbrevCode(.unsigned_enum_field); @@ -3455,7 +3494,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { uleb128(header.fixedWriter(), DW.FORM.line_strp) catch unreachable; uleb128(header.fixedWriter(), mod_info.files.count()) catch unreachable; for (mod_info.files.keys()) |file_index| { - const file = pt.zcu.fileByIndex(file_index); + const file = zcu.fileByIndex(file_index); unit.cross_section_relocs.appendAssumeCapacity(.{ .source_off = @intCast(header.items.len), .target_sec = .debug_line_str, @@ -3602,9 +3641,12 @@ const AbbrevCode = enum { numeric_type, inferred_error_set_type, ptr_type, + ptr_sentinel_type, is_const, is_volatile, array_type, + array_sentinel_type, + vector_type, array_index, nullary_func_type, func_type, @@ -3913,6 +3955,16 @@ const AbbrevCode = enum { .{ .type, .ref_addr }, }, }, + .ptr_sentinel_type = .{ + .tag = .pointer_type, + .attrs = &.{ + .{ .name, .strp }, + .{ .ZIG_sentinel, .block }, + .{ .alignment, .udata }, + .{ .address_class, .data1 }, + .{ .type, .ref_addr }, + }, + }, .is_const = .{ .tag = .const_type, .attrs = &.{ @@ -3931,7 +3983,24 @@ const AbbrevCode = enum { .attrs = &.{ .{ .name, .strp }, .{ .type, .ref_addr }, - .{ .GNU_vector, .flag }, + }, + }, + .array_sentinel_type = .{ + .tag = .array_type, + .children = true, + .attrs = &.{ + .{ .name, .strp }, + .{ .ZIG_sentinel, .block }, + .{ .type, .ref_addr }, + }, + }, + .vector_type = .{ + .tag = .array_type, + .children = true, + .attrs = &.{ + .{ .name, .strp }, + .{ .type, .ref_addr }, + .{ .GNU_vector, .flag_present }, }, }, .array_index = .{ @@ -4132,6 +4201,7 @@ const Dwarf = @This(); const InternPool = @import("../InternPool.zig"); const Module = @import("../Package.zig").Module; const Type = @import("../Type.zig"); +const Value = @import("../Value.zig"); const Zcu = @import("../Zcu.zig"); const Zir = std.zig.Zir; const assert = std.debug.assert; diff --git a/test/src/Debugger.zig b/test/src/Debugger.zig index 718d89dd1c..dcb07ba476 100644 --- a/test/src/Debugger.zig +++ b/test/src/Debugger.zig @@ -305,6 +305,82 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void { \\1 breakpoints deleted; 0 breakpoint locations disabled. }, ); + db.addLldbTest( + "strings", + target, + &.{ + .{ + .path = "strings.zig", + .source = + \\const Strings = struct { + \\ c_ptr: [*c]const u8 = "c_ptr\x07\x08\t", + \\ many_ptr: [*:0]const u8 = "many_ptr\n\x0b\x0c", + \\ ptr_array: *const [12:0]u8 = "ptr_array\x00\r\x1b", + \\ slice: [:0]const u8 = "slice\"\'\\\x00", + \\}; + \\fn testStrings(strings: Strings) void { + \\ _ = strings; + \\} + \\pub fn main() void { + \\ testStrings(.{}); + \\} + \\ + , + }, + }, + \\breakpoint set --file strings.zig --source-pattern-regexp '_ = strings;' + \\process launch + \\frame variable --show-types strings.slice + \\frame variable --show-types --format character strings.slice + \\frame variable --show-types --format c-string strings + \\breakpoint delete --force 1 + , + &.{ + \\(lldb) frame variable --show-types strings.slice + \\([:0]const u8) strings.slice = len=9 { + \\ (u8) [0] = 115 + \\ (u8) [1] = 108 + \\ (u8) [2] = 105 + \\ (u8) [3] = 99 + \\ (u8) [4] = 101 + \\ (u8) [5] = 34 + \\ (u8) [6] = 39 + \\ (u8) [7] = 92 + \\ (u8) [8] = 0 + \\} + \\(lldb) frame variable --show-types --format character strings.slice + \\([:0]const u8) strings.slice = len=9 { + \\ (u8) [0] = 's' + \\ (u8) [1] = 'l' + \\ (u8) [2] = 'i' + \\ (u8) [3] = 'c' + \\ (u8) [4] = 'e' + \\ (u8) [5] = '\"' + \\ (u8) [6] = '\'' + \\ (u8) [7] = '\\' + \\ (u8) [8] = '\x00' + \\} + \\(lldb) frame variable --show-types --format c-string strings + \\(root.strings.Strings) strings = { + \\ ([*c]const u8) c_ptr = "c_ptr\x07\x08\t" + \\ ([*:0]const u8) many_ptr = "many_ptr\n\x0b\x0c" + \\ (*const [12:0]u8) ptr_array = "ptr_array\x00\r\x1b" + \\ ([:0]const u8) slice = "slice\"\'\\\x00" len=9 { + \\ (u8) [0] = "s" + \\ (u8) [1] = "l" + \\ (u8) [2] = "i" + \\ (u8) [3] = "c" + \\ (u8) [4] = "e" + \\ (u8) [5] = "\"" + \\ (u8) [6] = "\'" + \\ (u8) [7] = "\\" + \\ (u8) [8] = "\x00" + \\ } + \\} + \\(lldb) breakpoint delete --force 1 + \\1 breakpoints deleted; 0 breakpoint locations disabled. + }, + ); db.addLldbTest( "enums", target,