Clang's NRVO debug info is still poor |
|||||
Issue descriptionWhat steps will reproduce the problem? (1) Build following code. (you can download it from https://chromium-review.googlesource.com/c/chromium/src/+/1126694) (2) Set a break point on the bottom of |GetFoo()| function and run. struct Foo { STACK_ALLOCATED(); Foo() = default; Foo(Foo&& other) { x = other.x; } int x; private: DISALLOW_COPY_AND_ASSIGN(Foo); }; static Foo GetFoo() { Foo foo; foo.x = 3; #if DCHECK_IS_ON() DCHECK(foo.x); #endif return foo; // Break point here losts |foo|. } TEST_F(NGLayoutSelectionTest, Foobar) { Foo bar = GetFoo(); EXPECT_EQ(3, bar.x); } What is the expected result? Visual studio debugger shows |foo|. What happens instead? It is lost in debugger view while showing the message "Variable is optimized away and not available." If I remove the #if close, it shows. Actually |foo.x = 3| is a for-loop and the return row is a only place to view final value in this function with other local variables. That's really prohibiting me debugging code.
,
Jul 5
Could you tell me how do you pass such flags with gn ?
,
Jul 5
,
Jul 5
,
Jul 6
It looks clang-cl doesn't have "--fno-elide-constructors" option. https://clang.llvm.org/docs/UsersManual.html#clang-cl And also we're using "/Od" option already.
,
Jul 6
Ah, clang has the flag. https://github.com/llvm-project/llvm-project-20170507/blob/b2b804a99452ff4d41643cd9f29043986fadff6c/clang/include/clang/Driver/Options.td#L842 But you need to pass the flag like -Xclang -fno-elide-constructors to clang-cl.
,
Jul 9
It made skia build failed. $ autoninja skia ninja.exe skia -j 1120 -l 56 [1/1] LINK(DLL) skia.dll skia.dll.lib skia.dll.pdb FAILED: skia.dll skia.dll.lib skia.dll.pdb C:/src/build/depot_tools/win_tools-2_7_6_bin/python/bin/python.exe ../../build/toolchain/win/tool_wrapper.py link-wrapper environment.x86 False link.exe /nologo /IMPLIB:./skia.dll.lib /DLL /OUT:./skia.dll /PDB:./skia.dll.pdb @./skia.dll.rsp SkDisplacementMapEffect.obj : error LNK2001: unresolved external symbol "private: __thiscall GrContextPriv::GrContextPriv(class GrContextPriv const &)" (??0GrContextPriv@@AAE@ABV0@@Z) SkLightingImageFilter.obj : error LNK2001: unresolved external symbol "private: __thiscall GrContextPriv::GrContextPriv(class GrContextPriv const &)" (??0GrContextPriv@@AAE@ABV0@@Z) ,,,
,
Jul 9
Hmm, does that fails on lld too?
,
Jul 9
Looks similar. target_cpu = "x86" enable_nacl = false is_component_build = true is_debug = true use_lld = true use_goma = true ninja.exe skia -j 1120 -l 56 [1/1] LINK(DLL) skia.dll skia.dll.lib skia.dll.pdb FAILED: skia.dll skia.dll.lib skia.dll.pdb ninja -t msvc -e environment.x86 -- ../../third_party/llvm-build/Release+Asserts/bin/lld-link.exe /nologo /IMPLIB:./skia.dll.lib /DLL /OUT:./skia.dll /PDB:./skia.dll.pdb @./skia.dll.rsp ../../third_party/llvm-build/Release+Asserts/bin\lld-link.exe: error: undefined symbol: ??0GrContextPriv@@AAE@ABV0@@Z >>> referenced by C:\src\build\src\chrome3\src\third_party\skia\src\gpu\GrContextPriv.h:299 >>> obj/skia/skia/GrBackendTextureImageGenerator.obj:(?contextPriv@GrContext@@QAE?AVGrContextPriv@@XZ) >>> referenced by C:\src\build\src\chrome3\src\third_party\skia\src\gpu\GrContextPriv.h:302 >>> obj/skia/skia/GrBackendTextureImageGenerator.obj:(?contextPriv@GrContext@@QBE?BVGrContextPriv@@XZ) ../../third_party/llvm-build/Release+Asserts/bin\lld-link.exe: error: undefined symbol: ??0GrResourceProviderPriv@@AAE@ABV0@@Z >>> referenced by C:\src\build\src\chrome3\src\third_party\skia\src\gpu\GrResourceProviderPriv.h:33 >>> obj/skia/skia/GrBackendTextureImageGenerator.obj:(?priv@GrResourceProvider@@QAE?AVGrResourceProviderPriv@@XZ) ../../third_party/llvm-build/Release+Asserts/bin\lld-link.exe: error: undefined symbol: ??0GrContextPriv@@AAE@ABV0@@Z >>> referenced by obj/skia/skia/GrBitmapTextureMaker.obj
,
Jul 9
Hmm, seems clang's bug. I confirmed that the flag does not work even on non-debug build. Also I tried to specify /Ob[012] in debug build and those did not work too. But I cannot do anymore.
,
Jul 19
I'd recommend against using -fno-elide-constructors. It was never tested and implemented on Windows. I'll try to look at this at some point.
,
Jul 20
I wasn't able to reproduce with this simple program:
#include <cassert>
struct Foo {
Foo() = default;
Foo(Foo &&other) { x = other.x; }
int x;
private:
Foo(const Foo &o) = delete;
Foo &operator=(const Foo &o) = delete;
__attribute__((annotate("blink_stack_allocated")))
void * operator new(size_t) = delete;
void *operator new(size_t, void *) = delete;
};
static Foo GetFoo() {
Foo foo;
foo.x = 3;
assert(foo.x == 3);
return foo; // Break point here losts |foo|.
}
int main() {
Foo bar = GetFoo();
assert(bar.x == 3);
}
I compiled with just clang-cl -Z7 t.cpp, and I could put a breakpoint on the return statement in VS and see foo. I'm trying in Chromium now.
,
Jul 20
I understand the issue now. Foo is not trivially copyable, so it is passed and returned indirectly by address. The caller of GetFoo allocates space for the return value, and passes it in as the first register parameter, RCX for x64. CodeView is capable of describing variable locations as being in memory pointed to by some register plus an offset, so in this case we say that 'foo' is in memory at RCX+0. This variable location is valid up until the DCHECK, which performs a function call, which clobbers RCX, and the variable is "optimized out". For some reason Bob's register hack isn't firing.
,
Jul 23
> For some reason Bob's register hack isn't firing. r312034 adds support for translating some previously unsupported DWARF expressions - among them emulating DW_OP_deref by changing the type from Foo to Foo&, which we needed for NRVO. It seems we are able to encode the NRVO location of foo just fine here; only we lose track of where the variable lives later on (rax+0, perhaps?). |
|||||
►
Sign in to add a comment |
|||||
Comment 1 by tikuta@chromium.org
, Jul 5Labels: OS-Windows