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

Fixes and improvements for debugging output #3469

Merged
merged 3 commits into from
Oct 25, 2016

Conversation

ggiraldez
Copy link
Contributor

@ggiraldez ggiraldez commented Oct 24, 2016

  • Output declarations of both parameters and local variables when emitting function debugging information.
  • Add functions for forward declaration of types in LLVM >= 3.8 (wrap llvm::DIBuilder.createReplaceableCompositeType and llvm::DIBuilder.replaceTemporary
  • 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

Eg. when compiling with debug info the following code

def my_add(x, y)
  z = x + y
  z
end

my_add(10, 20)

you can now display the values of the parameters x and y, like so:

(gdb) break my_add
Breakpoint 1 at 0x1000041ca: file /Users/ggiraldez/ScratchPad/crystal-debug/foo.cr, line 1.
(gdb) run
...
Breakpoint 1, my_add (x=10, y=20) at /Users/ggiraldez/ScratchPad/crystal-debug/foo.cr:1
1   def my_add(x, y)
(gdb) info locals
z = 0
(gdb) info arg
x = 10
y = 20
(gdb) 

Regarding the new functions to handle forward declarations, using LLVMTemporaryMDNode and LLVMMetadataReplaceAllUsesWith no longer works in LLVM 3.8. I run into this issue simply by compiling with LLVM 3.8.1 from Homebrew, then trying to compile this program with debug info:

class Foo
  @parent = uninitialized Foo
end

def test
  f = Foo.new
end

test

This crashed the compiler with a failed assertion:

Using compiled compiler at .build/crystal
Assertion failed: ((!MD || isa<MDString>(MD) || isa<T>(MD)) && "Expected valid ref"), function TypedDINodeRef, file /private/tmp/llvm38-20161006-73093-mrdx69/llvm-3.8.1.src/include/llvm/IR/DebugInfoMetadata.h, line 60.
Abort trap: 6

Found the solution here: https://groups.google.com/d/msg/llvm-dev/9C3yuck4JZY/yDxxP9ypEwAJ

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
- 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
Copy link
Contributor

@ysbaddaden ysbaddaden left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Improvements to debug are always welcome. Could you refer to the LLVM documentation or expose a little bit the benefits. I don't know much of LLVM, and the documentation is sometimes a little abrupt to search.

@@ -86,8 +94,17 @@ lib LibLLVMExt
align_in_bits : UInt64,
name : LibC::Char*) : Metadata

{% if LibLLVM::IS_38 %}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be the other way around: if IS_35 or IS_36, because we also support 3.9 now, and I expect the functions to be available in 4.x too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are absolutely right. It should be fixed in 0ca0868.

@@ -31,27 +31,37 @@ 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 %}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for hidding discrepancies into the LLVM module!

{% end %}
builder.set_metadata(declare, @dbg_kind, builder.current_debug_location)
{% end %}
# TODO: This is redundant for LLVM >= 3.8, but currently we don't have access to builder from DIBuilder
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it avoidable? Or could the method be a noop on 3.8+?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep! Moved the logic to set the debug location to the C++ extension for LLVM <= 3.6 as well.

I also refactored these methods to avoid code repetition.

@@ -3,6 +3,8 @@ require "./codegen"
module Crystal
class CodeGenVisitor
CRYSTAL_LANG_DEBUG_IDENTIFIER = 0x8002_u32
# TODO: for correctness, eventually this should come from the current LLVM context
DBG_KIND = LibLLVM.get_md_kind_id("dbg", 3)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about making it a method, so it would come from the current context?

Copy link
Contributor Author

@ggiraldez ggiraldez Oct 24, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No longer relevant in 0ca0868, as I removed it altogether

- 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 ggiraldez force-pushed the feature/improve-debugging branch from 218f974 to 0ca0868 Compare October 24, 2016 21:48
@ggiraldez
Copy link
Contributor Author

Agreed, the LLVM documentation is a bit hard to browse through. I'm a LLVM noob myself. Mostly, I've been referring to the source code directly, but the debugging chapter from the Kaleidoscope tutorial provided a nice introduction.

Anyway, I updated the opening comment explaining some of the changes.

@ysbaddaden
Copy link
Contributor

ysbaddaden commented Oct 25, 2016

Thank you! This looks all good to me, Travis is happy, and it should still compile against LLVM 3.6. @asterite what do you think?

@asterite
Copy link
Member

Looks really good to me! Merge? :-) (or rebase?)

@ysbaddaden ysbaddaden merged commit ac92a36 into crystal-lang:master Oct 25, 2016
@ysbaddaden ysbaddaden added this to the 0.20.0 milestone Oct 25, 2016
@ysbaddaden
Copy link
Contributor

ysbaddaden commented Oct 25, 2016

@ggiraldez we can't compile llvm_ext.cc with LLVM 3.5 anymore. If it fixable?

It happened in 0ca0868

@ggiraldez
Copy link
Contributor Author

Heh, I just opened #3472 but I see you already fixed it in #3471 :) I think I like your PR better, feel free to discard mine.

@ggiraldez ggiraldez deleted the feature/improve-debugging branch October 27, 2016 17:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants