Skip to content

Commit

Permalink
Add debug metadata for local variables of integer types
Browse files Browse the repository at this point in the history
  • Loading branch information
waj committed Sep 17, 2015
1 parent 16202e0 commit 898ee13
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 7 deletions.
44 changes: 38 additions & 6 deletions src/compiler/crystal/codegen/debug.cr
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,40 @@ module Crystal
end

def fun_type
int = di_builder.create_basic_type("int", 32_u64, 32_u64, 0_u32)
int = di_builder.create_basic_type("int", 32_u64, 32_u64, LLVM::DwarfTypeEncoding::Signed)
int1 = di_builder.get_or_create_type_array([int])
di_builder.create_subroutine_type(nil, int1)
end

def get_debug_type(type : IntegerType)
di_builder.create_basic_type(type.to_s, type.bits, type.bits,
type.signed? ? LLVM::DwarfTypeEncoding::Signed : LLVM::DwarfTypeEncoding::Unsigned)
end

def get_debug_type(type)
# puts "Unsupported type for debugging: #{type} (#{type.class})"
end

def declare_variable(var_name, var_type, alloca, target_def)
location = target_def.location
return unless location

debug_type = get_debug_type(var_type)
return unless debug_type

scope = get_current_debug_scope(location)
return unless scope
file, dir = file_and_dir(location.filename)
file = di_builder.create_file(file, dir)

var = di_builder.create_local_variable LLVM::DwarfTag::AutoVariable,
scope, var_name, file, location.line_number, debug_type
expr = di_builder.create_expression(nil, 0)

declare = di_builder.insert_declare_at_end(alloca, var, expr, alloca_block)
builder.set_metadata(declare, @dbg_kind, builder.current_debug_location)
end

def file_and_dir(file)
# @file_and_dir ||= {} of String | VirtualFile => {String, String}
realfile = case file
Expand Down Expand Up @@ -69,19 +98,22 @@ module Crystal
end
end

def set_current_debug_location(location)
return unless location

def get_current_debug_scope(location)
if context.fun.name == MAIN_NAME
main_scopes = (@main_scopes ||= {} of {String, String} => LibLLVMExt::Metadata)
file, dir = file_and_dir(location.filename)
scope = main_scopes[{file, dir}] ||= begin
main_scopes[{file, dir}] ||= begin
file = di_builder.create_file(file, dir)
di_builder.create_lexical_block(fun_metadatas[context.fun], file, 1, 1)
end
else
scope = fun_metadatas[context.fun]?
fun_metadatas[context.fun]?
end
end

def set_current_debug_location(location)
return unless location
scope = get_current_debug_scope(location)

if scope
builder.set_current_debug_location(location.line_number || 1, location.column_number, scope)
Expand Down
8 changes: 8 additions & 0 deletions src/compiler/crystal/codegen/fun.cr
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@ class Crystal::CodeGenVisitor
set_current_debug_location target_def if @debug
alloca_vars target_def.vars, target_def, args, context.closure_parent_context

if @debug
in_alloca_block do
context.vars.each do |name, var|
declare_variable(name, var.type, var.pointer, target_def)
end
end
end

create_local_copy_of_fun_args(target_def, self_type, args, is_fun_literal, is_closure)

context.return_type = target_def.type?
Expand Down
4 changes: 4 additions & 0 deletions src/llvm/builder.cr
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ struct LLVM::Builder
LibLLVMExt.set_current_debug_location(self, line, column, scope, inlined_at)
end

def set_metadata(value, kind, node)
LibLLVM.set_metadata(value, kind, node)
end

def current_debug_location
Value.new LibLLVM.get_current_debug_location(self)
end
Expand Down
16 changes: 15 additions & 1 deletion src/llvm/di_builder.cr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ struct LLVM::DIBuilder
end

def create_basic_type(name, size_in_bits, align_in_bits, encoding)
LibLLVMExt.di_builder_create_basic_type(self, name, size_in_bits, align_in_bits, encoding)
LibLLVMExt.di_builder_create_basic_type(self, name, size_in_bits.to_u64, align_in_bits.to_u64,
LibC::UInt.new(encoding.value))
end

def get_or_create_type_array(types : Array(LibLLVMExt::Metadata))
Expand All @@ -33,6 +34,19 @@ struct LLVM::DIBuilder
LibC::UInt.new(scope_line), flags, is_optimized, func)
end

def create_local_variable(tag, scope, name, file, line, type)
LibLLVMExt.di_builder_create_local_variable(self, LibC::UInt.new(tag.value), scope, name,
file, LibC::UInt.new(line), type, 0, 0_u32, 0_u32)
end

def create_expression(addr, length)
LibLLVMExt.di_builder_create_expression(self, addr, LibC::SizeT.new(length))
end

def insert_declare_at_end(storage, var_info, expr, block)
LibLLVMExt.di_builder_insert_declare_at_end(self, storage, var_info, expr, block)
end

def finalize
LibLLVMExt.di_builder_finalize(self)
end
Expand Down
25 changes: 25 additions & 0 deletions src/llvm/enums.cr
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,29 @@ module LLVM
X86_StdCall = 64
X86_FastCall = 65
end

enum DwarfTag
AutoVariable = 0x100
end

enum DwarfTypeEncoding
Address = 0x01
Boolean = 0x02
ComplexFloat = 0x03
Float = 0x04
Signed = 0x05
SignedChar = 0x06
Unsigned = 0x07
UnsignedChar = 0x08
ImaginaryFloat = 0x09
PackedDecimal = 0x0a
NumericString = 0x0b
Edited = 0x0c
SignedFixed = 0x0d
UnsignedFixed = 0x0e
DecimalFloat = 0x0f
Utf = 0x10
LoUser = 0x80
HiUser = 0xff
end
end
39 changes: 39 additions & 0 deletions src/llvm/ext/llvm_ext.cc
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,45 @@ LLVMDIBuilderCreateSubroutineType(LLVMDIBuilderRef Dref, LLVMMetadataRef File,
return wrap(CT);
}

LLVMMetadataRef LLVMDIBuilderCreateLocalVariable(
LLVMDIBuilderRef Dref, unsigned Tag, LLVMMetadataRef Scope,
const char *Name, LLVMMetadataRef File, unsigned Line, LLVMMetadataRef Ty,
int AlwaysPreserve, unsigned Flags, unsigned ArgNo) {
DIBuilder *D = unwrap(Dref);
DIVariable V = D->createLocalVariable(
Tag, unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), Line,
unwrapDI<DIType>(Ty), AlwaysPreserve, Flags, ArgNo);
return wrap(V);
}

LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef Dref,
LLVMValueRef Storage,
LLVMMetadataRef VarInfo,
LLVMMetadataRef Expr,
LLVMBasicBlockRef Block) {
DIBuilder *D = unwrap(Dref);
Instruction *Instr =
D->insertDeclare(unwrap(Storage),
unwrapDI<DIVariable>(VarInfo),
#ifdef HAVE_LLVM_35
#else
unwrapDI<DIExpression>(Expr),
#endif
unwrap(Block));
return wrap(Instr);
}

LLVMMetadataRef LLVMDIBuilderCreateExpression(LLVMDIBuilderRef Dref,
int64_t *Addr, size_t Length) {
#ifdef HAVE_LLVM_35
return nullptr;
#else
DIBuilder *D = unwrap(Dref);
DIExpression Expr = D->createExpression(ArrayRef<int64_t>(Addr, Length));
return wrap(Expr);
#endif
}

void LLVMSetCurrentDebugLocation2(LLVMBuilderRef Bref, unsigned Line,
unsigned Col, LLVMMetadataRef Scope,
LLVMMetadataRef InlinedAt) {
Expand Down
14 changes: 14 additions & 0 deletions src/llvm/lib_llvm_ext.cr
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,20 @@ lib LibLLVMExt
align_in_bits : UInt64,
encoding : LibC::UInt) : Metadata

fun di_builder_create_local_variable = LLVMDIBuilderCreateLocalVariable(builder : DIBuilder,
tag : LibC::UInt, scope : Metadata,
name : LibC::Char*, file : Metadata, line : LibC::UInt, type : Metadata,
always_preserve : LibC::Int, flags : LibC::UInt, arg_no : LibC::UInt) : Metadata

fun di_builder_insert_declare_at_end = LLVMDIBuilderInsertDeclareAtEnd(builder : DIBuilder,
storage : LibLLVM::ValueRef,
var_info : Metadata,
expr : Metadata,
block : LibLLVM::BasicBlockRef) : LibLLVM::ValueRef

fun di_builder_create_expression = LLVMDIBuilderCreateExpression(builder : DIBuilder,
addr : Int64*, length : LibC::SizeT) : Metadata

fun di_builder_get_or_create_type_array = LLVMDIBuilderGetOrCreateTypeArray(builder : DIBuilder, data : Metadata*, length : LibC::SizeT) : Metadata
fun di_builder_create_subroutine_type = LLVMDIBuilderCreateSubroutineType(builder : DIBuilder, file : Metadata, parameter_types : Metadata) : Metadata
fun set_current_debug_location = LLVMSetCurrentDebugLocation2(LibLLVM::BuilderRef, LibC::Int, LibC::Int, Metadata, Metadata)
Expand Down

0 comments on commit 898ee13

Please sign in to comment.