Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support debug information for 64-bit or unsigned enums #14081

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions spec/debug/large_enums.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
enum SignedEnum : Int64
X = 0x0123_4567_89ab_cdef_i64
end

enum UnsignedEnum : UInt64
Y = 0xfedc_ba98_7654_3210_u64
end

x = SignedEnum::X
y = UnsignedEnum::Y
# print: x
# lldb-check: (SignedEnum) $0 = X
# print: y
# lldb-check: (UnsignedEnum) $1 = Y
debugger
1 change: 1 addition & 0 deletions spec/debug/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,4 @@ $driver $SCRIPT_ROOT/top_level.cr $debugger
$driver $SCRIPT_ROOT/strings.cr $debugger
$driver $SCRIPT_ROOT/arrays.cr $debugger
$driver $SCRIPT_ROOT/blocks.cr $debugger
$driver $SCRIPT_ROOT/large_enums.cr $debugger
29 changes: 15 additions & 14 deletions src/compiler/crystal/codegen/debug.cr
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,21 @@ module Crystal

def create_debug_type(type : EnumType, original_type : Type)
elements = type.types.map do |name, item|
value = if item.is_a?(Const) && (value2 = item.value).is_a?(NumberLiteral)
value2.value.to_i64 rescue value2.value.to_u64
else
0
end
str_value = item.as?(Const).try &.value.as?(NumberLiteral).try &.value

value =
if type.base_type.kind.unsigned_int?
str_value.try(&.to_u64?) || 0_u64
else
str_value.try(&.to_i64?) || 0_i64
end

di_builder.create_enumerator(name, value)
end
di_builder.create_enumeration_type(nil, original_type.to_s, nil, 1, 32, 32, elements, get_debug_type(type.base_type))

size_in_bits = type.base_type.kind.bytesize
align_in_bits = align_of(type.base_type)
di_builder.create_enumeration_type(nil, original_type.to_s, nil, 1, size_in_bits, align_in_bits, elements, get_debug_type(type.base_type))
end

def create_debug_type(type : InstanceVarContainer, original_type : Type)
Expand Down Expand Up @@ -202,7 +209,7 @@ module Crystal
if ivar_debug_type = get_debug_type(ivar_type)
embedded_type = llvm_type(ivar_type)
size = @program.target_machine.data_layout.size_in_bits(embedded_type)
align = llvm_typer.align_of(embedded_type) * 8u64
align = align_of(ivar_type)
member = di_builder.create_member_type(nil, ivar_type.to_s, nil, 1, size, align, 0, LLVM::DIFlags::Zero, ivar_debug_type)
element_types << member
end
Expand Down Expand Up @@ -342,13 +349,7 @@ module Crystal
end

private def align_of(type)
case type
when CharType then 32
when IntegerType then type.bits
when FloatType then type.bytes * 8
when BoolType then 8
else 0 # unsupported
end
@program.target_machine.data_layout.abi_alignment(llvm_type(type)) * 8
end

private def declare_local(type, alloca, location, basic_block : LLVM::BasicBlock? = nil, &)
Expand Down
7 changes: 2 additions & 5 deletions src/llvm/di_builder.cr
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,8 @@ struct LLVM::DIBuilder
end

def create_enumerator(name, value)
{% if LibLLVM::IS_LT_90 %}
LibLLVMExt.di_builder_create_enumerator(self, name, value)
{% else %}
LibLLVM.di_builder_create_enumerator(self, name, name.bytesize, value, 0)
{% end %}
{{ LibLLVM::IS_LT_90 ? LibLLVMExt : LibLLVM }}.di_builder_create_enumerator(
self, name, name.bytesize, value.to_i64!, value.is_a?(Int::Unsigned) ? 1 : 0)
end

def create_enumeration_type(scope, name, file, line_number, size_in_bits, align_in_bits, elements, underlying_type)
Expand Down
10 changes: 6 additions & 4 deletions src/llvm/ext/llvm_ext.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ using namespace llvm;
extern "C" {

#if !LLVM_VERSION_GE(9, 0)
LLVMMetadataRef LLVMExtDIBuilderCreateEnumerator(
LLVMDIBuilderRef Dref, const char *Name, int64_t Value) {
DIEnumerator *e = unwrap(Dref)->createEnumerator(Name, Value);
return wrap(e);
LLVMMetadataRef LLVMExtDIBuilderCreateEnumerator(LLVMDIBuilderRef Builder,
const char *Name, size_t NameLen,
int64_t Value,
LLVMBool IsUnsigned) {
return wrap(unwrap(Builder)->createEnumerator({Name, NameLen}, Value,
IsUnsigned != 0));
}

void LLVMExtClearCurrentDebugLocation(LLVMBuilderRef B) {
Expand Down
18 changes: 9 additions & 9 deletions src/llvm/lib_llvm/debug_info.cr
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ lib LibLLVM
{% if LibLLVM::IS_LT_110 %}
fun di_builder_create_compile_unit = LLVMDIBuilderCreateCompileUnit(
builder : DIBuilderRef, lang : LLVM::DwarfSourceLanguage, file_ref : MetadataRef, producer : Char*,
producer_len : SizeT, is_optimized : Int, flags : Char*, flags_len : SizeT, runtime_ver : UInt,
producer_len : SizeT, is_optimized : Bool, flags : Char*, flags_len : SizeT, runtime_ver : UInt,
split_name : Char*, split_name_len : SizeT, kind : DWARFEmissionKind, dwo_id : UInt,
split_debug_inlining : Int, debug_info_for_profiling : Int
split_debug_inlining : Bool, debug_info_for_profiling : Bool
) : MetadataRef
{% else %}
fun di_builder_create_compile_unit = LLVMDIBuilderCreateCompileUnit(
builder : DIBuilderRef, lang : LLVM::DwarfSourceLanguage, file_ref : MetadataRef, producer : Char*,
producer_len : SizeT, is_optimized : Int, flags : Char*, flags_len : SizeT, runtime_ver : UInt,
producer_len : SizeT, is_optimized : Bool, flags : Char*, flags_len : SizeT, runtime_ver : UInt,
split_name : Char*, split_name_len : SizeT, kind : DWARFEmissionKind, dwo_id : UInt,
split_debug_inlining : Int, debug_info_for_profiling : Int, sys_root : Char*,
split_debug_inlining : Bool, debug_info_for_profiling : Bool, sys_root : Char*,
sys_root_len : SizeT, sdk : Char*, sdk_len : SizeT
) : MetadataRef
{% end %}
Expand All @@ -34,8 +34,8 @@ lib LibLLVM
fun di_builder_create_function = LLVMDIBuilderCreateFunction(
builder : DIBuilderRef, scope : MetadataRef, name : Char*, name_len : SizeT,
linkage_name : Char*, linkage_name_len : SizeT, file : MetadataRef, line_no : UInt,
ty : MetadataRef, is_local_to_unit : Int, is_definition : Int, scope_line : UInt,
flags : LLVM::DIFlags, is_optimized : Int
ty : MetadataRef, is_local_to_unit : Bool, is_definition : Bool, scope_line : UInt,
flags : LLVM::DIFlags, is_optimized : Bool
) : MetadataRef

fun di_builder_create_lexical_block = LLVMDIBuilderCreateLexicalBlock(
Expand All @@ -57,7 +57,7 @@ lib LibLLVM
) : MetadataRef
{% unless LibLLVM::IS_LT_90 %}
fun di_builder_create_enumerator = LLVMDIBuilderCreateEnumerator(
builder : DIBuilderRef, name : Char*, name_len : SizeT, value : Int64, is_unsigned : Int
builder : DIBuilderRef, name : Char*, name_len : SizeT, value : Int64, is_unsigned : Bool
) : MetadataRef
{% end %}
fun di_builder_create_enumeration_type = LLVMDIBuilderCreateEnumerationType(
Expand Down Expand Up @@ -118,11 +118,11 @@ lib LibLLVM

fun di_builder_create_auto_variable = LLVMDIBuilderCreateAutoVariable(
builder : DIBuilderRef, scope : MetadataRef, name : Char*, name_len : SizeT, file : MetadataRef,
line_no : UInt, ty : MetadataRef, always_preserve : Int, flags : LLVM::DIFlags, align_in_bits : UInt32
line_no : UInt, ty : MetadataRef, always_preserve : Bool, flags : LLVM::DIFlags, align_in_bits : UInt32
) : MetadataRef
fun di_builder_create_parameter_variable = LLVMDIBuilderCreateParameterVariable(
builder : DIBuilderRef, scope : MetadataRef, name : Char*, name_len : SizeT, arg_no : UInt,
file : MetadataRef, line_no : UInt, ty : MetadataRef, always_preserve : Int, flags : LLVM::DIFlags
file : MetadataRef, line_no : UInt, ty : MetadataRef, always_preserve : Bool, flags : LLVM::DIFlags
) : MetadataRef

fun set_subprogram = LLVMSetSubprogram(func : ValueRef, sp : MetadataRef)
Expand Down
4 changes: 3 additions & 1 deletion src/llvm/lib_llvm_ext.cr
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ lib LibLLVMExt
alias Int = LibC::Int
alias UInt = LibC::UInt

alias SizeT = LibC::SizeT

type OperandBundleDefRef = Void*

{% if LibLLVM::IS_LT_90 %}
fun di_builder_create_enumerator = LLVMExtDIBuilderCreateEnumerator(builder : LibLLVM::DIBuilderRef, name : Char*, value : Int64) : LibLLVM::MetadataRef
fun di_builder_create_enumerator = LLVMExtDIBuilderCreateEnumerator(builder : LibLLVM::DIBuilderRef, name : Char*, name_len : SizeT, value : Int64, is_unsigned : LibLLVM::Bool) : LibLLVM::MetadataRef
fun clear_current_debug_location = LLVMExtClearCurrentDebugLocation(b : LibLLVM::BuilderRef)
{% end %}

Expand Down