Closed Quuxplusone closed 8 years ago
Attached NeonEmitter-2e0fb6.sh
(6035 bytes, application/x-shellscript): Reproducer script
Attached NeonEmitter-2e0fb6.cpp
(4387716 bytes, text/x-c++src): reproducer source
A change might have triggered it, not the change in compiler.
My build also started failing as of September 9th with a similar error about "Alias must point to definition", and on the same symbol too (@_ZN12_GLOBAL__N_18TypeSpecD2Ev). This only occurs during bootstrapping but I'm not building with sanitizer instrumentation. Will investigate more and report back anything useful.
I've narrowed the problem down to this commit in libcxx, which when I revert
fixes the problem for me:
https://github.com/llvm-mirror/libcxx/commit/b9e6e8972a521e72192f370bb1ca98cbddee6a00
"TypeSpec" in NeonEmitter is a wrapper for std::string, and this commit
marks its destructor as 'always inline'.
Looks like the GlobalAlias is an optimization to avoid emitting duplicated code:
https://github.com/llvm-mirror/clang/blob/0d7600a4bc4258d5d4157765e1764af0efc82805/lib/CodeGen/CGCXX.cpp#L120
In particular this bit mentions libc++'s use of AlwaysInline and describes what
seems to be the issue encountered here:
https://github.com/llvm-mirror/clang/blob/0d7600a4bc4258d5d4157765e1764af0efc82805/lib/CodeGen/CGCXX.cpp#L167
I'm not quite sure where things go wrong, however.
Indeed reverting r280944 fixes the problem, great analysis Will! It would be nice if libc++ maintainers can take a look at this.
Should r280944 be reverted then? The bot has been red for almost a week now.
(In reply to comment #7)
> Should r280944 be reverted then? The bot has been red for almost a week now.
IMHO yes, this is also breaking our openSUSE trunk builds.
Looking now.
Looking now.
I think the problem comes from the class TypeSpec
which derives from std::string. Deriving from std::string is not recommended.
for reference: http://stackoverflow.com/questions/6006860/why-should-one-not-derive-from-c-std-string-class
FYI I reverted the problem commit in r281562 with the intent of recommitting it once we fix the real underlying problem.
I'm working on reducing the NeonEmitter.cpp right now.
Still not sure what's going on with Clang. Here is a reduced reproducer:
// clang++ -std=c++11 -O1 test.cpp
template <class CharT>
struct String {
String() {}
~String();
};
template <class CharT>
inline __attribute__((visibility("hidden"), always_inline))
String<CharT>::~String() {}
extern template struct String<char>;
struct Foo : public String<char> { Foo() { String<char> s; } };
Foo f;
Note that the above reproducer compiles fine at -O0 but not at -O1. Since the crash seems to be in the backend is this an LLVM bug and not a Clang one?
Could somebody with more knowledge re-bin this bug accordingly and CC anyone who might know how to fix this.
Thanks for reducing the testcase. I was able to figure out that the crash is in llc but the original file was too big to efficiently figure out the exact cause. I'll look into the problem.
For the reduced example, when compiled at -O1 clang front end does not generate
the definition of the destructor (~Foo), instead it makes ~Foo an alias of
~String.
//Generating IR at O0.
$PATH/llvm-project/build/bin/clang-3.9 -cc1 -O0 -triple x86_64-unknown-linux-
gnu -emit-llvm -emit-llvm-uselists -disable-free -main-file-name reduced.cpp -
mrelocation-model static -mthread-model posix -fmath-errno -masm-verbose -
mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -momit-
leaf-frame-pointer -v -dwarf-column-info -debugger-tuning=gdb -resource-dir
$PATH/llvm-project/build/bin/../lib/clang/4.0.0 -std=c++11 -fdeprecated-macro -
ferror-limit 19 -fmessage-length 146 -fobjc-runtime=gcc -fcxx-exceptions -
fexceptions -fdiagnostics-show-option -fcolor-diagnostics -disable-llvm-passes -
o reduced-clang-O0.ll -x c++-cpp-output reduced.ii
//Generating IR at O1.
$PATH/llvm-project/build/bin/clang-3.9 -cc1 -O1 -triple x86_64-unknown-linux-
gnu -emit-llvm -emit-llvm-uselists -disable-free -main-file-name reduced.cpp -
mrelocation-model static -mthread-model posix -fmath-errno -masm-verbose -
mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -momit-
leaf-frame-pointer -v -dwarf-column-info -debugger-tuning=gdb -resource-dir
$PATH/llvm-project/build/bin/../lib/clang/4.0.0 -std=c++11 -fdeprecated-macro -
ferror-limit 19 -fmessage-length 146 -fobjc-runtime=gcc -fcxx-exceptions -
fexceptions -fdiagnostics-show-option -fcolor-diagnostics -disable-llvm-passes -
o reduced-clang-O1.ll -x c++-cpp-output reduced.ii
Specifically, "define linkonce_odr void @_ZN3FooD2Ev(%struct.Foo* %this)"
is not there when compiled at -O1. But it generates,
@_ZN3FooD2Ev = linkonce_odr alias void (%struct.Foo*), bitcast (void
(%struct.String*)* @_ZN6StringIcED2Ev to void (%struct.Foo*)*)
Still debugging...
$ diff reduced-clang-O0.ll reduced-clang-O1.ll
11,12d10
< $_ZN3FooD2Ev = comdat any
<
16a15,16
> @_ZN3FooD2Ev = linkonce_odr alias void (%struct.Foo*), bitcast (void
(%struct.String*)* @_ZN6StringIcED2Ev to void (%struct.Foo*)*)
>
21c21
< %0 = call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.Foo*)*
@_ZN3FooD2Ev to void (i8*)*), i8* getelementptr inbounds (%struct.Foo,
%struct.Foo* @f, i32 0, i32 0), i8* @__dso_handle) #2
---
> %0 = call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.Foo*)*
@_ZN3FooD2Ev to void (i8*)*), i8* getelementptr inbounds (%struct.Foo,
%struct.Foo* @f, i32 0, i32 0), i8* @__dso_handle) #1
32c32
< store %struct.Foo* %this, %struct.Foo** %this.addr, align 8
---
> store %struct.Foo* %this, %struct.Foo** %this.addr, align 8, !tbaa !1
36c36,38
< invoke void @_ZN6StringIcEC1Ev(%struct.String* %s)
---
> %1 = bitcast %struct.String* %s to i8*
> call void @llvm.lifetime.start(i64 1, i8* %1) #1
> invoke void @_ZN6StringIcEC2Ev(%struct.String* %s)
40c42,44
< call void @_ZN6StringIcED2Ev(%struct.String* %s) #2
---
> call void @_ZN6StringIcED2Ev(%struct.String* %s) #1
> %2 = bitcast %struct.String* %s to i8*
> call void @llvm.lifetime.end(i64 1, i8* %2) #1
44c48
< %1 = landingpad { i8*, i32 }
---
> %3 = landingpad { i8*, i32 }
46,51c50,55
< %2 = extractvalue { i8*, i32 } %1, 0
< store i8* %2, i8** %exn.slot, align 8
< %3 = extractvalue { i8*, i32 } %1, 1
< store i32 %3, i32* %ehselector.slot, align 4
< %4 = bitcast %struct.Foo* %this1 to %struct.String*
< call void @_ZN6StringIcED2Ev(%struct.String* %4) #2
---
> %4 = extractvalue { i8*, i32 } %3, 0
> store i8* %4, i8** %exn.slot, align 8
> %5 = extractvalue { i8*, i32 } %3, 1
> store i32 %5, i32* %ehselector.slot, align 4
> %6 = bitcast %struct.Foo* %this1 to %struct.String*
> call void @_ZN6StringIcED2Ev(%struct.String* %6) #1
60,70d63
< }
<
< ; Function Attrs: inlinehint nounwind uwtable
< define linkonce_odr void @_ZN3FooD2Ev(%struct.Foo* %this) unnamed_addr #1
comdat align 2 {
< entry:
< %this.addr = alloca %struct.Foo*, align 8
< store %struct.Foo* %this, %struct.Foo** %this.addr, align 8
< %this1 = load %struct.Foo*, %struct.Foo** %this.addr, align 8
< %0 = bitcast %struct.Foo* %this1 to %struct.String*
< call void @_ZN6StringIcED2Ev(%struct.String* %0) #2
< ret void
73c66
< uselistorder void (%struct.String*)* @_ZN6StringIcED2Ev, { 1, 2, 0 }
---
> uselistorder void (%struct.String*)* @_ZN6StringIcED2Ev, { 2, 0, 1 }
77c70
< declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*) #2
---
> declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*) #1
79c72,73
< declare void @_ZN6StringIcEC2Ev(%struct.String*) unnamed_addr #3
---
> ; Function Attrs: argmemonly nounwind
> declare void @llvm.lifetime.start(i64, i8* nocapture) #2
81c75,82
< declare void @_ZN6StringIcEC1Ev(%struct.String*) unnamed_addr #3
---
> ; Function Attrs: nounwind uwtable
> define available_externally void @_ZN6StringIcEC2Ev(%struct.String* %this)
unnamed_addr #3 align 2 {
> entry:
> %this.addr = alloca %struct.String*, align 8
> store %struct.String* %this, %struct.String** %this.addr, align 8, !tbaa !1
> %this1 = load %struct.String*, %struct.String** %this.addr, align 8
> ret void
> }
89c90
< store %struct.String* %this, %struct.String** %this.addr, align 8
---
> store %struct.String* %this, %struct.String** %this.addr, align 8, !tbaa !1
92,94d92
<
< ; uselistorder directives
< uselistorder i32 1, { 1, 0, 2, 3, 4, 5 }
96a95,97
> ; Function Attrs: argmemonly nounwind
> declare void @llvm.lifetime.end(i64, i8* nocapture) #2
>
105,107c106,108
< attributes #1 = { inlinehint nounwind uwtable "correctly-rounded-divide-sqrt-
fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-
frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false"
"no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-
math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-
features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-
float"="false" }
< attributes #2 = { nounwind }
< attributes #3 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-
tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-
elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-
zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-
size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87"
"unsafe-fp-math"="false" "use-soft-float"="false" }
---
> attributes #1 = { nounwind }
> attributes #2 = { argmemonly nounwind }
> attributes #3 = { nounwind uwtable "correctly-rounded-divide-sqrt-fp-
math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-
frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false"
"no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-
math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-
features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-
float"="false" }
112a114,117
> !1 = !{!2, !2, i64 0}
> !2 = !{!"any pointer", !3, i64 0}
> !3 = !{!"omnipotent char", !4, i64 0}
> !4 = !{!"Simple C++ TBAA"}
Since the base class String<char> is 'available_externally', the verifier does
not count these definitions as available and aborts. I'll add Rafael for his
insights.
commit 8ca97044ad94547f4e3740515a4c483824422813
Author: Rafael Espindola <rafael.espindola@gmail.com>, Thu Nov 26 19:22:59 2015
+0000 (10 months ago)
Committer: Rafael Espindola <rafael.espindola@gmail.com>, Thu Nov 26 19:22:59
2015 +0000 (10 months ago)
Branches: <Expand>
Disallow aliases to available_externally.
(In reply to comment #17)
> Since the base class String<char> is 'available_externally', the verifier
> does not count these definitions as available and aborts. I'll add Rafael
> for his insights.
>
> commit 8ca97044ad94547f4e3740515a4c483824422813
> Author: Rafael Espindola <rafael.espindola@gmail.com>, Thu Nov 26 19:22:59
> 2015 +0000 (10 months ago)
> Committer: Rafael Espindola <rafael.espindola@gmail.com>, Thu Nov 26
> 19:22:59 2015 +0000 (10 months ago)
> Branches: <Expand>
>
> Disallow aliases to available_externally.
That is correct. The available_externally will not be there in the end to allow
the creation of the alias. The bug seems to be in clang trying to create such
an alias.
Patch for review: https://reviews.llvm.org/D24682
NeonEmitter-2e0fb6.sh
(6035 bytes, application/x-shellscript)NeonEmitter-2e0fb6.cpp
(4387716 bytes, text/x-c++src)