-
Notifications
You must be signed in to change notification settings - Fork 835
[DebugInfo] Copy debug info in call-utils.h #6652
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
Changes from 6 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| /* | ||
| * Copyright 2019 WebAssembly Community Group participants | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| #ifndef wasm_ir_debuginfo_h | ||
| #define wasm_ir_debuginfo_h | ||
|
|
||
| #include "wasm.h" | ||
|
|
||
| namespace wasm::debuginfo { | ||
|
|
||
| // Given an expression and another that it replaces, copy the debug info from | ||
| // the latter to the former. Note that the expression may not be an exclusive | ||
| // replacement of the other (the other may be replaced by several expressions, | ||
| // all of whom may end up with the same debug info). | ||
| inline void copyDebugInfoToReplacement(Expression* replacement, | ||
| Expression* original, | ||
| Function* func) { | ||
| auto& debugLocations = func->debugLocations; | ||
| // Early exit if there is no debug info at all. Also, leave if we already | ||
| // have debug info on the new replacement, which we don't want to trample: | ||
| // if there is no debug info we do want to copy, as a replacement operation | ||
| // suggests the new code plays the same role (it is an optimized version of | ||
| // the old), but if the code is already annotated, trust that. | ||
| if (debugLocations.empty() || debugLocations.count(replacement)) { | ||
| return; | ||
| } | ||
|
|
||
| auto iter = debugLocations.find(original); | ||
| if (iter != debugLocations.end()) { | ||
| debugLocations[replacement] = iter->second; | ||
| // Note that we do *not* erase the debug info of the expression being | ||
| // replaced, because it may still exist: we might replace | ||
| // | ||
| // (call | ||
| // (block .. | ||
| // | ||
| // with | ||
| // | ||
| // (block | ||
| // (call .. | ||
| // | ||
| // We still want the call here to have its old debug info. | ||
| // | ||
| // (In most cases, of course, we do remove the replaced expression, | ||
| // which means we accumulate unused garbage in debugLocations, but | ||
| // that's not that bad; we use arena allocation for Expressions, after | ||
| // all.) | ||
| } | ||
| } | ||
|
|
||
| // Given an expression and a copy of it in another function, copy the debug | ||
| // info into the second function. | ||
| void copyDebugInfoBetweenFunctions(Expression* origin, | ||
| Expression* copy, | ||
| Function* originFunc, | ||
| Function* copyFunc); | ||
| } // namespace wasm::debuginfo | ||
|
|
||
| #endif // wasm_ir_debuginfo_h | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,13 +44,16 @@ | |
| ) | ||
|
|
||
| ;; CHECK: (func $call_ref-to-direct (type $i32_i32_=>_none) (param $x i32) (param $y i32) | ||
| ;; CHECK-NEXT: ;;@ file.cpp:10:1 | ||
| ;; CHECK-NEXT: (call $foo | ||
| ;; CHECK-NEXT: (local.get $x) | ||
| ;; CHECK-NEXT: (local.get $y) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: ) | ||
| (func $call_ref-to-direct (param $x i32) (param $y i32) | ||
| ;; This call_ref should become a direct call. | ||
| ;; This call_ref should become a direct call. The debuginfo should transfer as | ||
| ;; well. | ||
| ;;@ file.cpp:10:1 | ||
| (call_ref $i32_i32_=>_none | ||
| (local.get $x) | ||
| (local.get $y) | ||
|
|
@@ -253,29 +256,42 @@ | |
| ;; CHECK: (func $call_ref-to-select (type $5) (param $x i32) (param $y i32) (param $z i32) (param $f (ref $i32_i32_=>_none)) | ||
| ;; CHECK-NEXT: (local $4 i32) | ||
| ;; CHECK-NEXT: (local $5 i32) | ||
| ;; CHECK-NEXT: ;;@ file.cpp:20:2 | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How did these
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The outer block gets it because we replace the original instruction with the block, so the debuginfo is copied by default in
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But the debug info was already being copied in
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I think I figured it out: these
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Specifically
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
But why did the
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The block gets debug info after this PR because the test had no debug info before. See line 310. Maybe a separate NFC PR that just modified the test would have made that clearer, sorry. The ;;@ file.cpp:20:2
(call_ref $i32_i32_=>_none
(local.get $x)
(local.get $y)
(select
(ref.func $foo)
(ref.func $bar)
(local.get $z)
)
)Not only the (If a child had different debug info we'd print that, or if it was marked as having no debug info we'd add
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I see. Also I missed the newly added debug info. Thanks for the explanation! |
||
| ;; CHECK-NEXT: (block | ||
| ;; CHECK-NEXT: ;;@ | ||
| ;; CHECK-NEXT: (local.set $4 | ||
| ;; CHECK-NEXT: ;;@ file.cpp:20:2 | ||
| ;; CHECK-NEXT: (local.get $x) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: ;;@ | ||
| ;; CHECK-NEXT: (local.set $5 | ||
| ;; CHECK-NEXT: ;;@ file.cpp:20:2 | ||
| ;; CHECK-NEXT: (local.get $y) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: ;;@ | ||
| ;; CHECK-NEXT: (if | ||
| ;; CHECK-NEXT: ;;@ file.cpp:20:2 | ||
| ;; CHECK-NEXT: (local.get $z) | ||
| ;; CHECK-NEXT: (then | ||
| ;; CHECK-NEXT: (call $foo | ||
| ;; CHECK-NEXT: ;;@ | ||
| ;; CHECK-NEXT: (local.get $4) | ||
| ;; CHECK-NEXT: ;;@ | ||
| ;; CHECK-NEXT: (local.get $5) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: (else | ||
| ;; CHECK-NEXT: ;;@ file.cpp:20:2 | ||
| ;; CHECK-NEXT: (call $bar | ||
| ;; CHECK-NEXT: ;;@ | ||
| ;; CHECK-NEXT: (local.get $4) | ||
| ;; CHECK-NEXT: ;;@ | ||
| ;; CHECK-NEXT: (local.get $5) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: ;;@ file.cpp:30:3 | ||
| ;; CHECK-NEXT: (call_ref $i32_i32_=>_none | ||
| ;; CHECK-NEXT: (local.get $x) | ||
| ;; CHECK-NEXT: (local.get $y) | ||
|
|
@@ -287,7 +303,11 @@ | |
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: ) | ||
| (func $call_ref-to-select (param $x i32) (param $y i32) (param $z i32) (param $f (ref $i32_i32_=>_none)) | ||
| ;; This call_ref should become an if over two direct calls. | ||
| ;; This call_ref should become an if over two direct calls. The debuginfo | ||
| ;; should transfer as well to the two new calls (and some of the new helper | ||
| ;; code that is generated, but the critical part is the call_ref is being | ||
| ;; replaced by two calls, which should have the same info). | ||
| ;;@ file.cpp:20:2 | ||
| (call_ref $i32_i32_=>_none | ||
| (local.get $x) | ||
| (local.get $y) | ||
|
|
@@ -299,6 +319,7 @@ | |
| ) | ||
|
|
||
| ;; But here one arm is not constant, so we do not optimize. | ||
| ;;@ file.cpp:30:3 | ||
| (call_ref $i32_i32_=>_none | ||
| (local.get $x) | ||
| (local.get $y) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: How about putting the
originalfirst? Source first and then the destination seems more intuitive to me, but if you like the current order it's fine too.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, yeah, this was not that clear. I reversed the order now and also renamed it so it is totally unambiguous,
copyOriginalToReplacement. I also removedDebugInfofrom the name as they are always called asdebuginfo::copyFoo()anyhow, so it is clear we are copying debuginfo.