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

BIR needs to include debug info about variables #935

Closed
Tracked by #919
jclark opened this issue Feb 17, 2022 · 10 comments
Closed
Tracked by #919

BIR needs to include debug info about variables #935

jclark opened this issue Feb 17, 2022 · 10 comments
Assignees
Milestone

Comments

@jclark
Copy link
Contributor

jclark commented Feb 17, 2022

For registers corresponding to source variables and parameters, we will need to generate debug info which will require additional information in the BIR such as variable scope and probably location of definition.

We need to figure out what is necessary for JVM and DWARF.

@jclark jclark mentioned this issue Feb 17, 2022
11 tasks
@jclark
Copy link
Contributor Author

jclark commented Feb 17, 2022

Note that scope for narrowed variables will be relevant to #883.

@warunalakshitha
Copy link

JVM use localvariable table to store the debug information related to variables. Local variable tables require start label (starting of visibility), end label (termination of visibility), variable name, type etc.

Bir contains bir scope and end basic block for each variable. Bir scope will be created for each variable definition. Bir scope will have an incremental integer id and the reference to parent. Bir scopes are generated hierarchically and scope of the variable has been enclosed by parent scope. End bb will be determined by which extent variable is alive.

So the start label will be generated based on bir scope id and the end label on end bb.ATM bir does not use any positions when it comes to variable debug information.

@jclark
Copy link
Contributor Author

jclark commented Feb 22, 2022

@warunalakshitha A couple of questions

  • Does every local variable has a separate scope? If so, what about parameters?
  • How are basic blocks in the BIR associated with scopes? Does a scope have to correspond to a contiguous range of BIR blocks?

@warunalakshitha
Copy link

warunalakshitha commented Feb 23, 2022

@warunalakshitha A couple of questions

  • Does every local variable has a separate scope? If so, what about parameters?

Yes. Every local variables have separate BIR Scope. parameters are also added to local variable table. But we are not adding BIR Scope or either startBB, endBB for parameters. Since parameters should have the visibility scopes from the beginning to end of a function, we are using methodStartLabel and methodEndLabel to add parameters to the variable table.

  • How are basic blocks in the BIR associated with scopes? Does a scope have to correspond to a contiguous range of BIR blocks?

There is no association between BIR scope and basic blocks. Initially we use only start block and end block. But we got a debugger issue since different variable definitions will have same start block but their visibility ranges are different. So BIR scope is introduced. Still we use end basic block to mark the termination point of variable visibility.

@jclark jclark added this to the Improve milestone Feb 24, 2022
@jclark jclark modified the milestones: Subset 14 improved, Subset 15 Mar 10, 2022
@jclark jclark added the in progress Currently being implemented label Mar 10, 2022
@jclark
Copy link
Contributor Author

jclark commented Mar 10, 2022

@jclark jclark removed the in progress Currently being implemented label Mar 10, 2022
@heshanpadmasiri heshanpadmasiri self-assigned this Apr 18, 2022
@heshanpadmasiri heshanpadmasiri added the in progress Currently being implemented label Apr 18, 2022
@heshanpadmasiri
Copy link
Member

heshanpadmasiri commented Apr 18, 2022

@jclark for LLVM we will have to use 2 intrinsics

1.llvm.dbg.addr / llvm.dbg.declare

For our purposes I think we can use either one llvm documentation says llvm.dbg.addr is the preferred option but clang still uses llvm.dbg.declare. We have to call this at the point declaration of the source variable. second argument gives the metadata for the variable and debug information attached to this function call will have a location that contains the scope of the variable (!11 also has the scope but documentation specifically says !12 give the scope)

  %2 = alloca i32, align 4
  call void @llvm.dbg.declare(metadata i32* %2, metadata !11, metadata !DIExpression()), !dbg !12
  ...
 
  !11 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !1, line: 1, type: !10)
  !12 = !DILocation(line: 1, column: 13, scope: !7)
  !7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)

2.llvm.dbg.value
We have to use this for variable that have been turned in to SSA values (instead of 1). Here first argument to the function call gives the value, second the corresponding variable (which has the location of declaration) and third is a DIExpression that describe how the referenced LLVM variable relates to the source variable. (I am not sure whether we need detailed information for this argument or whether ignoring it by sending empty expression is sufficient for our needs). Again scope information is passed similar to llvm.dbg.declare.

  call void @llvm.dbg.value(metadata i32 20, metadata !13, metadata !DIExpression()), !dbg !20
  call void @llvm.dbg.value(metadata i32 %0, metadata !13, metadata !DIExpression(DW_OP_plus_uconst, 20, DW_OP_stack_value)), !dbg !20
  call void @llvm.dbg.value(metadata i32 %5, metadata !13, metadata !DIExpression()), !dbg !20
  ...
  !20 = !DILocation(line: 0, scope: !7)
  !13 = !DILocalVariable(name: "x", scope: !7, file: !1, line: 2, type: !10)
  !7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)

So the minimum information we need are

  1. location of definition
  2. scope
  3. variable name in the source

@manuranga
Copy link
Contributor

This Rust issue claims that only using llvm.dbg.value is not viable. We'll have to verify this.

@jclark
Copy link
Contributor Author

jclark commented Apr 21, 2022

I wonder why that issue doesn't mention llvm.dbg.addr. We discussed using a mix of llvm.dbg.addr and llvm.dbg.value, right?

@heshanpadmasiri
Copy link
Member

heshanpadmasiri commented Apr 24, 2022

I wonder why that issue doesn't mention llvm.dbg.addr. We discussed using a mix of llvm.dbg.addr and llvm.dbg.value, right?

Yes. There is a small issue with that approach. It seems llvm c api only support llvm.dbg.value and llvm.dbg.declare intrinsic. While we can use our own solution in print.llvm this will cause a problem with jni.llvm

@heshanpadmasiri heshanpadmasiri removed the in progress Currently being implemented label Jul 6, 2022
@heshanpadmasiri
Copy link
Member

As far an nBallerina is concerned this is resolved with #1006. Will reopen if any changes are needed for jBallerina in the future

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

No branches or pull requests

5 participants