Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: ac83b6c704f7
Choose a base ref
...
head repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: ac92a361cd52
Choose a head ref
  • 4 commits
  • 7 files changed
  • 2 contributors

Commits on Oct 24, 2016

  1. Copy the full SHA
    3e8bfd1 View commit details
  2. Fixes and improvements for debugging output

    - Declare parameters as well as local variables when emitting function
      debugging information
    - Add functions for forward declaration of types in LLVM >= 3.8
    - Push LLVM version conditionals from debug.cr into di_builder.cr
    - Add spacing and comments in preprocessor directives in llvm_ext.cc to
      improve readability
    ggiraldez committed Oct 24, 2016
    Copy the full SHA
    8a41b90 View commit details
  3. Refactor vars and parameter debug info emission

    - Refactor code to emit the `llvm.dbg.declare` instrinsic and reuse for
      both local variables and method arguments
    - Move debug location setting for debug declare instrinsic into C++
      extension for LLVM <= 3.6 (functionality is built-in for LLVM >= 3.8)
    - Reformat `llvm_ext.cc` to conform to Crystal formatter
    ggiraldez committed Oct 24, 2016
    Copy the full SHA
    0ca0868 View commit details

Commits on Oct 25, 2016

  1. Merge pull request #3469 from ggiraldez/feature/improve-debugging

    Fixes and improvements for debugging output
    ysbaddaden authored Oct 25, 2016
    Copy the full SHA
    ac92a36 View commit details
Showing with 203 additions and 144 deletions.
  1. +3 −2 Makefile
  2. +0 −2 src/compiler/crystal/codegen/codegen.cr
  3. +20 −33 src/compiler/crystal/codegen/debug.cr
  4. +11 −3 src/compiler/crystal/codegen/fun.cr
  5. +28 −14 src/llvm/di_builder.cr
  6. +118 −76 src/llvm/ext/llvm_ext.cc
  7. +23 −14 src/llvm/lib_llvm_ext.cr
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -19,7 +19,8 @@ LLVM_EXT_OBJ = $(LLVM_EXT_DIR)/llvm_ext.o
LIB_CRYSTAL_SOURCES = $(shell find src/ext -name '*.c')
LIB_CRYSTAL_OBJS = $(subst .c,.o,$(LIB_CRYSTAL_SOURCES))
LIB_CRYSTAL_TARGET = src/ext/libcrystal.a
CFLAGS += -fPIC
CFLAGS += -fPIC $(if $(debug),-g -O0)
CXXFLAGS += $(if $(debug),-g -O0)

ifeq (${LLVM_CONFIG},)
$(error Could not locate llvm-config, make sure it is installed and in your PATH, or set LLVM_CONFIG)
@@ -83,7 +84,7 @@ $(O)/crystal: deps $(SOURCES)
$(BUILD_PATH) $(EXPORTS) ./bin/crystal build $(FLAGS) -o $@ src/compiler/crystal.cr -D without_openssl -D without_zlib

$(LLVM_EXT_OBJ): $(LLVM_EXT_DIR)/llvm_ext.cc
$(CXX) -c -o $@ $< `$(LLVM_CONFIG) --cxxflags`
$(CXX) -c $(CXXFLAGS) -o $@ $< `$(LLVM_CONFIG) --cxxflags`

$(LIB_CRYSTAL_TARGET): $(LIB_CRYSTAL_OBJS)
ar -rcs $@ $^
2 changes: 0 additions & 2 deletions src/compiler/crystal/codegen/codegen.cr
Original file line number Diff line number Diff line change
@@ -158,8 +158,6 @@ module Crystal
builder = LLVM::Builder.new
@builder = wrap_builder builder

@dbg_kind = LibLLVM.get_md_kind_id("dbg", 3)

@modules = {"" => @main_mod} of String => LLVM::Module
@types_to_modules = {} of Type => LLVM::Module

53 changes: 20 additions & 33 deletions src/compiler/crystal/codegen/debug.cr
Original file line number Diff line number Diff line change
@@ -84,27 +84,24 @@ module Crystal
element_types = [] of LibLLVMExt::Metadata
struct_type = llvm_struct_type(type)

tmp_debug_type = di_builder.temporary_md_node(LLVM::Context.global)
tmp_debug_type = di_builder.create_replaceable_composite_type(nil, type.to_s, nil, 1)
debug_type_cache[type] = tmp_debug_type

# TOOD: use each_with_index
idx = 0
ivars.each do |name, ivar|
ivars.each_with_index do |(name, ivar), idx|
if (ivar_type = ivar.type?) && (ivar_debug_type = get_debug_type(ivar_type))
offset = @program.target_machine.data_layout.offset_of_element(struct_type, idx + (type.struct? ? 0 : 1))
size = @program.target_machine.data_layout.size_in_bits(llvm_embedded_type(ivar_type))
member = di_builder.create_member_type(nil, name[1..-1], nil, 1, size, size, offset * 8, 0, ivar_debug_type)
element_types << member
end
idx += 1
end

size = @program.target_machine.data_layout.size_in_bits(struct_type)
debug_type = di_builder.create_struct_type(nil, type.to_s, nil, 1, size, size, 0, nil, di_builder.get_or_create_type_array(element_types))
unless type.struct?
debug_type = di_builder.create_pointer_type(debug_type, llvm_typer.pointer_size * 8, llvm_typer.pointer_size * 8, type.to_s)
end
di_builder.replace_all_uses(tmp_debug_type, debug_type)
di_builder.replace_temporary(tmp_debug_type, debug_type)
debug_type
end

@@ -122,30 +119,34 @@ module Crystal
# puts "Unsupported type for debugging: #{type} (#{type.class})"
end

def declare_variable(var_name, var_type, alloca, target_def)
location = target_def.location
def declare_parameter(arg_name, arg_type, arg_no, alloca, location)
declare_local(arg_type, alloca, location) do |scope, file, line_number, debug_type|
di_builder.create_parameter_variable scope, arg_name, arg_no, file, line_number, debug_type
end
end

def declare_variable(var_name, var_type, alloca, location)
declare_local(var_type, alloca, location) do |scope, file, line_number, debug_type|
di_builder.create_auto_variable scope, var_name, file, line_number, debug_type
end
end

private def declare_local(type, alloca, location)
return unless location

debug_type = get_debug_type(var_type)
debug_type = get_debug_type(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
var = yield scope, file, location.line_number, debug_type
expr = di_builder.create_expression(nil, 0)

{% begin %}
{% if LibLLVM::IS_36 || LibLLVM::IS_35 %}
declare = di_builder.insert_declare_at_end(alloca, var, expr, alloca_block)
{% else %}
declare = di_builder.insert_declare_at_end(alloca, var, expr, builder.current_debug_location, alloca_block)
{% end %}
builder.set_metadata(declare, @dbg_kind, builder.current_debug_location)
{% end %}
di_builder.insert_declare_at_end(alloca, var, expr, builder.current_debug_location, alloca_block)
end

def file_and_dir(file)
@@ -222,16 +223,9 @@ module Crystal
def emit_main_def_debug_metadata(main_fun, filename)
file, dir = file_and_dir(filename)
scope = di_builder.create_file(file, dir)
{% begin %}
{% if LibLLVM::IS_36 || LibLLVM::IS_35 %}
fn_metadata = di_builder.create_function(scope, MAIN_NAME, MAIN_NAME, scope,
0, fun_metadata_type, 1, 1, 0, 0_u32, 0, main_fun)
{% else %}
fn_metadata = di_builder.create_function(scope, MAIN_NAME, MAIN_NAME, scope,
0, fun_metadata_type, true, true, 0, 0_u32, false, main_fun)
{% end %}
fun_metadatas[main_fun] = fn_metadata
{% end %}
end

def emit_def_debug_metadata(target_def)
@@ -240,16 +234,9 @@ module Crystal

file, dir = file_and_dir(location.filename)
scope = di_builder.create_file(file, dir)
{% begin %}
{% if LibLLVM::IS_36 || LibLLVM::IS_35 %}
fn_metadata = di_builder.create_function(scope, target_def.name, target_def.name, scope,
location.line_number, fun_metadata_type, 1, 1, location.line_number, 0_u32, 0, context.fun)
{% else %}
fn_metadata = di_builder.create_function(scope, target_def.name, target_def.name, scope,
location.line_number, fun_metadata_type, true, true, location.line_number, 0_u32, false, context.fun)
{% end %}
fun_metadatas[context.fun] = fn_metadata
{% end %}
end
end
end
14 changes: 11 additions & 3 deletions src/compiler/crystal/codegen/fun.cr
Original file line number Diff line number Diff line change
@@ -98,16 +98,24 @@ class Crystal::CodeGenVisitor
set_current_debug_location target_def if @debug
alloca_vars target_def.vars, target_def, args, context.closure_parent_context

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

if @debug
in_alloca_block do
args_offset = !is_fun_literal && self_type.passed_as_self? ? 2 : 1
location = target_def.location
context.vars.each do |name, var|
declare_variable(name, var.type, var.pointer, target_def)
if name == "self"
declare_parameter(name, var.type, 1, var.pointer, location)
elsif arg_no = args.index { |arg| arg.name == name }
declare_parameter(name, var.type, arg_no + args_offset, var.pointer, location)
else
declare_variable(name, var.type, var.pointer, location)
end
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?
context.return_phi = nil

42 changes: 28 additions & 14 deletions src/llvm/di_builder.cr
Original file line number Diff line number Diff line change
@@ -31,27 +31,33 @@ struct LLVM::DIBuilder

def create_function(scope, name, linkage_name, file, line, composite_type, is_local_to_unit, is_definition,
scope_line, flags, is_optimized, func)
LibLLVMExt.di_builder_create_function(self, scope, name, linkage_name, file, line, composite_type, is_local_to_unit, is_definition,
scope_line, flags, is_optimized, func)
{% if LibLLVM::IS_36 || LibLLVM::IS_35 %}
LibLLVMExt.di_builder_create_function(self, scope, name, linkage_name, file, line, composite_type,
is_local_to_unit ? 1 : 0,
is_definition ? 1 : 0,
scope_line, flags,
is_optimized ? 1 : 0, func)
{% else %}
LibLLVMExt.di_builder_create_function(self, scope, name, linkage_name, file, line, composite_type,
is_local_to_unit, is_definition, scope_line, flags, is_optimized, func)
{% end %}
end

def create_local_variable(tag, scope, name, file, line, type)
LibLLVMExt.di_builder_create_local_variable(self, tag.value, scope, name, file, line, type, 0, 0, 0)
def create_auto_variable(scope, name, file, line, type)
LibLLVMExt.di_builder_create_auto_variable(self, scope, name, file, line, type, 0, 0)
end

def create_parameter_variable(scope, name, argno, file, line, type)
LibLLVMExt.di_builder_create_parameter_variable(self, scope, name, argno, file, line, type, 0, 0)
end

def create_expression(addr, length)
LibLLVMExt.di_builder_create_expression(self, addr, length)
end

{% if LibLLVM::IS_36 || LibLLVM::IS_35 %}
def insert_declare_at_end(storage, var_info, expr, block)
LibLLVMExt.di_builder_insert_declare_at_end(self, storage, var_info, expr, block)
end
{% else %}
def insert_declare_at_end(storage, var_info, expr, dl, block)
LibLLVMExt.di_builder_insert_declare_at_end(self, storage, var_info, expr, dl, block)
end
{% end %}

def get_or_create_array(elements : Array(LibLLVMExt::Metadata))
LibLLVMExt.di_builder_get_or_create_array(self, elements, elements.size)
@@ -80,12 +86,20 @@ struct LLVM::DIBuilder
LibLLVMExt.di_builder_create_pointer_type(self, pointee, size_in_bits, align_in_bits, name)
end

def temporary_md_node(context)
LibLLVMExt.temporary_md_node(context, nil, 0).as(LibLLVMExt::Metadata)
def create_replaceable_composite_type(scope, name, file, line)
{% if LibLLVM::IS_35 || LibLLVM::IS_36 %}
LibLLVMExt.temporary_md_node(LLVM::Context.global, nil, 0).as(LibLLVMExt::Metadata)
{% else %}
LibLLVMExt.di_builder_create_replaceable_composite_type(self, scope, name, file, line)
{% end %}
end

def replace_all_uses(from, to)
LibLLVMExt.metadata_replace_all_uses_with(from, to)
def replace_temporary(from, to)
{% if LibLLVM::IS_35 || LibLLVM::IS_36 %}
LibLLVMExt.metadata_replace_all_uses_with(from, to)
{% else %}
LibLLVMExt.di_builder_replace_temporary(self, from, to)
{% end %}
end

def finalize
194 changes: 118 additions & 76 deletions src/llvm/ext/llvm_ext.cc
Original file line number Diff line number Diff line change
@@ -25,28 +25,29 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIBuilder, LLVMDIBuilderRef)
typedef LLVMValueRef LLVMMetadataRef;
typedef Value Metadata;
#define DIBuilderRef LLVMDIBuilderRef
#else

#else /* LLVM != 3.5 */
typedef struct LLVMOpaqueMetadata *LLVMMetadataRef;
DEFINE_ISA_CONVERSION_FUNCTIONS(Metadata, LLVMMetadataRef)

inline Metadata **unwrap(LLVMMetadataRef *Vals) {
return reinterpret_cast<Metadata **>(Vals);
}
#endif
#endif /* LLVM == 3.5 */

#if LLVM_VERSION_LE(3, 6)
template <typename T> T unwrapDIptr(LLVMMetadataRef v) {
return v ? T(unwrap<MDNode>(v)) : T();
}
#define DIBuilderRef LLVMDIBuilderRef
#else

#else /* LLVM > 3.6 */
typedef DIBuilder *DIBuilderRef;
#define DIArray DINodeArray

template <typename T> T *unwrapDIptr(LLVMMetadataRef v) {
return (T *)(v ? unwrap<MDNode>(v) : NULL);
}
#endif
#endif /* LLVM <= 3.6 */


#define DIDescriptor DIScope
#define unwrapDI unwrapDIptr
@@ -116,17 +117,16 @@ LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock(DIBuilderRef Dref,
unsigned Column) {
#if LLVM_VERSION_LE(3, 6)
DIBuilder *D = unwrap(Dref);
DILexicalBlock LB = D->createLexicalBlock(
#if LLVM_VERSION_EQ(3, 5)
unwrapDI<DIDescriptor>(Scope), unwrapDI<DIFile>(File), Line, Column, 0);
#else
unwrapDI<DIDescriptor>(Scope), unwrapDI<DIFile>(File), Line, Column);
#endif
# if LLVM_VERSION_EQ(3, 5)
DILexicalBlock LB = D->createLexicalBlock(unwrapDI<DIDescriptor>(Scope), unwrapDI<DIFile>(File), Line, Column, 0);
# else /* LLVM <= 3.6 && LLVM != 3.5 */
DILexicalBlock LB = D->createLexicalBlock(unwrapDI<DIDescriptor>(Scope), unwrapDI<DIFile>(File), Line, Column);
# endif
return wrap(LB);
#else
#else /* LLVM > 3.6 */
return wrap(Dref->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
unwrapDI<DIFile>(File), Line, Column));
#endif
#endif /* LLVM <= 3.6 */
}

LLVMMetadataRef LLVMDIBuilderCreateBasicType(DIBuilderRef Dref,
@@ -148,22 +148,22 @@ LLVMMetadataRef LLVMDIBuilderGetOrCreateTypeArray(DIBuilderRef Dref,
unsigned Length) {
#if LLVM_VERSION_LE(3, 6)
DIBuilder *D = unwrap(Dref);
#if LLVM_VERSION_EQ(3, 5)
# if LLVM_VERSION_EQ(3, 5)
Value **DataValue = unwrap(Data);
ArrayRef<Value *> Elements(DataValue, Length);
DIArray A = D->getOrCreateArray(Elements);
#else
# else /* LLVM <= 3.6 && LLVM != 3.5 */
Metadata **DataValue = unwrap(Data);
ArrayRef<Metadata *> Elements(DataValue, Length);
DITypeArray A = D->getOrCreateTypeArray(Elements);
#endif
# endif
return wrap(A);
#else
#else /* LLVM > 3.6 */
Metadata **DataValue = unwrap(Data);
return wrap(
Dref->getOrCreateTypeArray(ArrayRef<Metadata *>(DataValue, Length))
.get());
#endif
#endif /* LLVM <= 3.6 */
}

LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(DIBuilderRef Dref,
@@ -187,83 +187,90 @@ LLVMDIBuilderCreateSubroutineType(DIBuilderRef Dref, LLVMMetadataRef File,
LLVMMetadataRef ParameterTypes) {
#if LLVM_VERSION_LE(3, 6)
DIBuilder *D = unwrap(Dref);
DICompositeType CT = D->createSubroutineType(
#if LLVM_VERSION_EQ(3, 5)
unwrapDI<DIFile>(File), unwrapDI<DIArray>(ParameterTypes));
#else
unwrapDI<DIFile>(File), unwrapDI<DITypeArray>(ParameterTypes));
#endif
#else
DISubroutineType *CT = Dref->createSubroutineType(
DITypeRefArray(unwrap<MDTuple>(ParameterTypes)));
#endif
# if LLVM_VERSION_EQ(3, 5)
DICompositeType CT = D->createSubroutineType(unwrapDI<DIFile>(File), unwrapDI<DIArray>(ParameterTypes));
# else /* LLVM <= 3.6 && LLVM != 3.5 */
DICompositeType CT = D->createSubroutineType(unwrapDI<DIFile>(File), unwrapDI<DITypeArray>(ParameterTypes));
# endif
#else /* LLVM > 3.6 */
DISubroutineType *CT = Dref->createSubroutineType(DITypeRefArray(unwrap<MDTuple>(ParameterTypes)));
#endif /* LLVM <= 3.6 */
return wrap(CT);
}

LLVMMetadataRef LLVMDIBuilderCreateLocalVariable(
DIBuilderRef Dref, unsigned Tag, LLVMMetadataRef Scope, const char *Name,
LLVMMetadataRef File, unsigned Line, LLVMMetadataRef Ty, int AlwaysPreserve,
unsigned Flags, unsigned ArgNo) {
LLVMMetadataRef LLVMDIBuilderCreateAutoVariable(
DIBuilderRef Dref, LLVMMetadataRef Scope, const char *Name,
LLVMMetadataRef File, unsigned Line, LLVMMetadataRef Ty,
int AlwaysPreserve, unsigned Flags) {
#if LLVM_VERSION_LE(3, 6)
DIBuilder *D = unwrap(Dref);
DIVariable V = D->createLocalVariable(
Tag, unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), Line,
unwrapDI<DIType>(Ty), AlwaysPreserve, Flags, ArgNo);
llvm::dwarf::DW_TAG_auto_variable, unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), Line,
unwrapDI<DIType>(Ty), AlwaysPreserve, Flags, 0);
return wrap(V);
#else
if (Tag == 0x100) { // DW_TAG_auto_variable
DILocalVariable *V = Dref->createAutoVariable(
unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), Line,
unwrapDI<DIType>(Ty), AlwaysPreserve, Flags);
return wrap(V);
} else {
DILocalVariable *V = Dref->createParameterVariable(
unwrapDI<DIDescriptor>(Scope), Name, ArgNo, unwrapDI<DIFile>(File),
Line, unwrapDI<DIType>(Ty), AlwaysPreserve, Flags);
return wrap(V);
}
DILocalVariable *V = Dref->createAutoVariable(
unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), Line,
unwrapDI<DIType>(Ty), AlwaysPreserve, Flags);
return wrap(V);
#endif
}

LLVMMetadataRef LLVMDIBuilderCreateParameterVariable(
DIBuilderRef Dref, LLVMMetadataRef Scope, const char *Name,
unsigned ArgNo, LLVMMetadataRef File, unsigned Line,
LLVMMetadataRef Ty, int AlwaysPreserve, unsigned Flags) {
#if LLVM_VERSION_LE(3, 6)
LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef Dref,
DIBuilder *D = unwrap(Dref);
DIVariable V = D->createLocalVariable(
llvm::dwarf::DW_TAG_arg_variable, unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), Line,
unwrapDI<DIType>(Ty), AlwaysPreserve, Flags, ArgNo);
return wrap(V);
#else
DILocalVariable *V = Dref->createParameterVariable
(unwrapDI<DIDescriptor>(Scope), Name, ArgNo, unwrapDI<DIFile>(File), Line,
unwrapDI<DIType>(Ty), AlwaysPreserve, Flags);
return wrap(V);
#endif
}

LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(DIBuilderRef Dref,
LLVMValueRef Storage,
LLVMMetadataRef VarInfo,
LLVMMetadataRef Expr,
LLVMValueRef DL,
LLVMBasicBlockRef Block) {
#if LLVM_VERSION_LE(3, 6)
DIBuilder *D = unwrap(Dref);
Instruction *Instr =
D->insertDeclare(unwrap(Storage), unwrapDI<DIVariable>(VarInfo),
#if LLVM_VERSION_EQ(3, 5)
#else
unwrapDI<DIExpression>(Expr),
#endif
unwrap(Block));
#else
LLVMValueRef
LLVMDIBuilderInsertDeclareAtEnd(DIBuilderRef Dref, LLVMValueRef Storage,
LLVMMetadataRef VarInfo, LLVMMetadataRef Expr,
LLVMValueRef DL, LLVMBasicBlockRef Block) {
Instruction *Instr = Dref->insertDeclare(
unwrap(Storage), unwrap<DILocalVariable>(VarInfo),
unwrapDI<DIExpression>(Expr),
DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())),
unwrap(Block));
D->insertDeclare(unwrap(Storage), unwrapDI<DIVariable>(VarInfo),
# if !LLVM_VERSION_EQ(3, 5)
unwrapDI<DIExpression>(Expr),
# endif
unwrap(Block));
Instr->setDebugLoc(DebugLoc::getFromDILocation(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())));
#else /* LLVM > 3.6 */
Instruction *Instr =
Dref->insertDeclare(unwrap(Storage), unwrap<DILocalVariable>(VarInfo),
unwrapDI<DIExpression>(Expr),
DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())),
unwrap(Block));
#endif

return wrap(Instr);
}

LLVMMetadataRef LLVMDIBuilderCreateExpression(DIBuilderRef Dref, int64_t *Addr,
size_t Length) {
#if LLVM_VERSION_LE(3, 6)
#if LLVM_VERSION_EQ(3, 5)
# if LLVM_VERSION_EQ(3, 5)
return nullptr;
#else
# else /* LLVM <= 3.6 && LLVM != 3.5 */
DIBuilder *D = unwrap(Dref);
DIExpression Expr = D->createExpression(ArrayRef<int64_t>(Addr, Length));
return wrap(Expr);
#endif
#else
# endif
#else /* LLVM > 3.6 */
return wrap(Dref->createExpression(ArrayRef<int64_t>(Addr, Length)));
#endif
}
@@ -300,11 +307,17 @@ LLVMMetadataRef LLVMDIBuilderCreateEnumerator(DIBuilderRef Dref,
return wrap(e);
}

LLVMMetadataRef LLVMDIBuilderCreateStructType(
DIBuilderRef Dref, LLVMMetadataRef Scope, const char *Name,
LLVMMetadataRef File, unsigned Line, uint64_t SizeInBits,
uint64_t AlignInBits, unsigned Flags, LLVMMetadataRef DerivedFrom,
LLVMMetadataRef Elements) {
LLVMMetadataRef
LLVMDIBuilderCreateStructType(DIBuilderRef Dref,
LLVMMetadataRef Scope,
const char *Name,
LLVMMetadataRef File,
unsigned Line,
uint64_t SizeInBits,
uint64_t AlignInBits,
unsigned Flags,
LLVMMetadataRef DerivedFrom,
LLVMMetadataRef Elements) {
#if LLVM_VERSION_LE(3, 6)
DIBuilder *D = unwrap(Dref);
DICompositeType CT = D->createStructType(
@@ -320,6 +333,35 @@ LLVMMetadataRef LLVMDIBuilderCreateStructType(
return wrap(CT);
}

#if LLVM_VERSION_GE(3, 8)
LLVMMetadataRef
LLVMDIBuilderCreateReplaceableCompositeType(DIBuilderRef Dref,
LLVMMetadataRef Scope,
const char *Name,
LLVMMetadataRef File,
unsigned Line)
{
DICompositeType *CT = Dref->createReplaceableCompositeType(llvm::dwarf::DW_TAG_structure_type,
Name,
unwrapDI<DIScope>(Scope),
unwrapDI<DIFile>(File),
Line);
return wrap(CT);
}

void
LLVMDIBuilderReplaceTemporary(DIBuilderRef Dref,
LLVMMetadataRef From,
LLVMMetadataRef To)
{
auto *Node = unwrap<MDNode>(From);
auto *Type = unwrap<DIType>(To);

llvm::TempMDNode fwd_decl(Node);
Dref->replaceTemporary(std::move(fwd_decl), Type);
}
#endif

LLVMMetadataRef
LLVMDIBuilderCreateMemberType(DIBuilderRef Dref, LLVMMetadataRef Scope,
const char *Name, LLVMMetadataRef File,
@@ -369,12 +411,12 @@ LLVMMetadataRef LLVMTemporaryMDNode(LLVMContextRef C, LLVMMetadataRef *MDs,

void LLVMMetadataReplaceAllUsesWith(LLVMMetadataRef MD, LLVMMetadataRef New) {
#if LLVM_VERSION_LE(3, 6)
#if LLVM_VERSION_EQ(3, 5)
# if LLVM_VERSION_EQ(3, 5)
auto *Node = unwrap<MDNode>(MD);
#else
# else /* LLVM <= 3.6 && LLVM != 3.5 */
auto *Node = unwrap<MDNodeFwdDecl>(MD);
#endif
#else
# endif
#else /* LLVM > 3.6 */
auto *Node = unwrap<MDNode>(MD);
#endif
Node->replaceAllUsesWith(unwrap<MDNode>(New));
37 changes: 23 additions & 14 deletions src/llvm/lib_llvm_ext.cr
Original file line number Diff line number Diff line change
@@ -40,25 +40,25 @@ 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_create_auto_variable = LLVMDIBuilderCreateAutoVariable(builder : DIBuilder,
scope : Metadata,
name : LibC::Char*,
file : Metadata, line : LibC::UInt,
type : Metadata,
always_preserve : LibC::Int, flags : LibC::UInt) : Metadata

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

{% if LibLLVM::IS_36 || LibLLVM::IS_35 %}
fun di_builder_insert_declare_at_end = LLVMDIBuilderInsertDeclareAtEnd(builder : DIBuilder,
storage : LibLLVM::ValueRef,
var_info : Metadata,
expr : Metadata,
block : LibLLVM::BasicBlockRef) : LibLLVM::ValueRef
{% else %}
fun di_builder_insert_declare_at_end = LLVMDIBuilderInsertDeclareAtEnd(builder : DIBuilder,
storage : LibLLVM::ValueRef,
var_info : Metadata,
expr : Metadata,
dl : LibLLVM::ValueRef,
block : LibLLVM::BasicBlockRef) : LibLLVM::ValueRef
{% end %}

fun di_builder_create_expression = LLVMDIBuilderCreateExpression(builder : DIBuilder,
addr : Int64*, length : LibC::SizeT) : Metadata
@@ -86,8 +86,17 @@ lib LibLLVMExt
align_in_bits : UInt64,
name : LibC::Char*) : Metadata

fun temporary_md_node = LLVMTemporaryMDNode(context : LibLLVM::ContextRef, mds : Metadata*, count : LibC::UInt) : Metadata
fun metadata_replace_all_uses_with = LLVMMetadataReplaceAllUsesWith(Metadata, Metadata)
{% if LibLLVM::IS_35 || LibLLVM::IS_36 %}
fun temporary_md_node = LLVMTemporaryMDNode(context : LibLLVM::ContextRef, mds : Metadata*, count : LibC::UInt) : Metadata
fun metadata_replace_all_uses_with = LLVMMetadataReplaceAllUsesWith(Metadata, Metadata)
{% else %}
fun di_builder_create_replaceable_composite_type = LLVMDIBuilderCreateReplaceableCompositeType(builder : DIBuilder,
scope : Metadata,
name : LibC::Char*,
file : Metadata,
line : LibC::UInt) : Metadata
fun di_builder_replace_temporary = LLVMDIBuilderReplaceTemporary(builder : DIBuilder, from : Metadata, to : Metadata)
{% end %}

fun set_current_debug_location = LLVMSetCurrentDebugLocation2(LibLLVM::BuilderRef, LibC::Int, LibC::Int, Metadata, Metadata)