Closed Quuxplusone closed 8 years ago
Bugzilla Link | PR25958 |
Status | RESOLVED FIXED |
Importance | P normal |
Reported by | Mark Millard (marklmi26-fbsd@yahoo.com) |
Reported on | 2015-12-28 14:54:50 -0800 |
Last modified on | 2016-01-05 13:38:24 -0800 |
Version | 3.7 |
Hardware | Other FreeBSD |
CC | dimitry@andric.com, ditaliano@apple.com, emaste@freebsd.org, james@jamesmolloy.co.uk, jyknight@google.com, llvm-bugs@lists.llvm.org |
Fixed by commit(s) | |
Attachments | |
Blocks | |
Blocked by | |
See also |
This llvm.org submittal is basically a duplicate of what I submitted to FreeBSD's bugzilla:
Hi Mark,
Thanks for raising this. Before checking the specifics of what you found - did you compile Clang with -mno-unaligned-access? We will by default compile assuming SCTLR.A is 0. -mno-unaligned-access switches this assumption off and enables strict alignment mode.
Cheers,
James
I've built clang++ for an rpi2 many ways. All crash in the SCTLR bit[1]==1
context on arm. FreeBSD 11.0-CURRENT (including clang) at was in sue for the
report was cross built from amd64 FreeBSD with:
-target armv6--freebsd11.0-gnueabi
-march=armv7a
-fmax-type-align=4
-mno-unaligned-access
-target armv6-gnueabi-freebsd11.0
(Yea, two "-targets" ended up being involved in that order --via the build
system adding one to mine.)
That is per the below extraction from the script log of the build showing the
specific clang++ source code file that has the source code that I reported:
--- Type.o ---
/usr/bin/clang++ -target armv6--freebsd11.0-gnueabi -march=armv7a -fmax-type-
align=4 -mno-unaligned-access -target armv6-gnueabi-freebsd11.0 --
sysroot=/usr/obj/clang/arm.armv6/usr/src/tmp -B/usr/local
/arm-gnueabi-freebsd/bin/ --sysroot=/usr/obj/clang/arm.armv6/usr/src/tmp -
B/usr/local/arm-gnueabi-freebsd/bin/ -O -pipe -mfloat-abi=softfp -
I/usr/src/lib/clang/libclangast/../../../contrib/llvm/inclu
de -I/usr/src/lib/clang/libclangast/../../../contrib/llvm/tools/clang/include -
I/usr/src/lib/clang/libclangast/../../../contrib/llvm/tools/clang/lib/AST -I. -
I/usr/src/lib/clang/libclangast/../../../c
ontrib/llvm/../../lib/clang/include -DLLVM_ON_UNIX -DLLVM_ON_FREEBSD -
D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -DCLANG_ENABLE_ARCMT -
DCLANG_ENABLE_STATIC_ANALYZER -fno-strict-aliasing -DLLVM_DEFA
ULT_TARGET_TRIPLE=\"armv6-gnueabi-freebsd11.0\" -DLLVM_HOST_TRIPLE=\"armv6-
unknown-freebsd11.0\" -DDEFAULT_SYSROOT=\"\" -MD -MP -MF.depend.Type.o -
MTType.o -Qunused-arguments -std=c++11 -fno-exceptio
ns -fno-rtti -stdlib=libc++ -Wno-c++11-extensions -c
/usr/src/lib/clang/libclangast/../../../contrib/llvm/tools/clang/lib/AST/Type.cpp
-o Type.o
Given that clang++ build installed on an rpi2, here is an example using it on
the 11 line example source:
# /usr/bin/clang++ -target armv6--freebsd11.0-gnueabi -march=armv7a -fmax-type-
align=4 -mno-unaligned-access main.cc
clang++: error: unable to execute command: Bus error (core dumped)
clang++: error: clang frontend command failed due to signal (use -v to see
invocation)
FreeBSD clang version 3.7.1 (tags/RELEASE_371/final 255217) 20151225
Target: armv6--freebsd11.0-gnueabi
Thread model: posix
clang++: note: diagnostic msg: PLEASE submit a bug report to
https://bugs.freebsd.org/submit/ and include the crash backtrace, preprocessed
source, and associated run script.
clang++: note: diagnostic msg:
********************
PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang++: note: diagnostic msg: /tmp/main-29523a.cpp
clang++: note: diagnostic msg: /tmp/main-29523a.sh
clang++: note: diagnostic msg:
********************
# more /tmp/main-29523a.sh
# Crash reproducer for FreeBSD clang version 3.7.1 (tags/RELEASE_371/final
255217) 20151225
# Driver args: "--driver-mode=g++" "--target=armv6--freebsd11.0-gnueabi" "-
march=armv7a" "-fmax-type-align=4" "-mno-unaligned-access" "main.cc"
# Original command: "/usr/bin/clang++" "-cc1" "-triple" "armv7--freebsd11.0-
gnueabi" "-emit-obj" "-mrelax-all" "-disable-free" "-main-file-name" "main.cc"
"-mrelocation-model" "static" "-mthread-model" "posix" "-mdisable-fp-elim" "-
masm-verbose" "-mconstructor-aliases" "-target-cpu" "cortex-a8" "-target-
feature" "+soft-float" "-target-feature" "+soft-float-abi" "-target-feature" "-
neon" "-target-feature" "-crypto" "-target-abi" "aapcs-linux" "-msoft-float" "-
mfloat-abi" "soft" "-backend-option" "-arm-strict-align" "-dwarf-column-info" "-
resource-dir" "/usr/bin/../lib/clang/3.7.1" "-internal-isystem"
"/usr/include/c++/v1" "-fdeprecated-macro" "-fdebug-compilation-dir"
"/root/c_tests" "-ferror-limit" "19" "-fmessage-length" "338" "-mstackrealign"
"-fno-signed-char" "-fobjc-runtime=gnustep" "-fcxx-exceptions" "-fexceptions" "-
fmax-type-align=4" "-fdiagnostics-show-option" "-fcolor-diagnostics" "-o"
"/tmp/main-147b93.o" "-x" "c++" "main.cc"
"/usr/bin/clang++" "-cc1" "-triple" "armv7--freebsd11.0-gnueabi" "-emit-obj" "-mrelax-all" "-disable-free" "-main-file-name" "main.cc" "-mrelocation-model" "static" "-mthread-model" "posix" "-mdisable-fp-elim" "-masm-verbose" "-mconstructor-aliases" "-target-cpu" "cortex-a8" "-target-feature" "+soft-float" "-target-feature" "+soft-float-abi" "-target-feature" "-neon" "-target-feature" "-crypto" "-target-abi" "aapcs-linux" "-msoft-float" "-mfloat-abi" "soft" "-backend-option" "-arm-strict-align" "-dwarf-column-info" "-fdeprecated-macro" "-ferror-limit" "19" "-fmessage-length" "338" "-mstackrealign" "-fno-signed-char" "-fobjc-runtime=gnustep" "-fcxx-exceptions" "-fexceptions" "-fmax-type-align=4" "-fdiagnostics-show-option" "-fcolor-diagnostics" "-x" "c++" "main-29523a.cpp"
# more /tmp/main-29523a.cpp
# 1 "<built-in>"
# 1 "main.cc"
template <class _Tp, class _Up>
struct __has_rebind
{
template <class _Xp> static char __test(typename _Xp::template rebind<_Up>* = 0);
};
int
main ()
{
return 0;
}
Anything including <memory> from libc++ hits the problem via such a template
usage.
I'll note that for gcc "-mno-unaligned-access" is described in a way that
packed data structures are mentioned as involved but no data structure is
explicitly marked as packed for the code in question in the clang++ source code
I talked about:
-munaligned-access
-mno-unaligned-access
Enables (or disables) reading and writing of 16- and 32- bit values from
addresses that are not 16- or 32- bit aligned. By default unaligned access is
disabled for all pre-ARMv6 and all ARMv6-M architectures, and enabled for all
other architectures. If unaligned access is not enabled then words in packed
data structures are accessed a byte at a time.
Of course when the code generator is using vst1.64's there can also be 64-bit
(8-Byte) alignment requirements, as it happening in clang++'s internal code for
how it was compiled (see above and the original submittal).
The following change eliminates the specific Bus Error in clang and allows the
11 line program to compile on an rpi2 --but causes include/clang/AST/Type.h to
pollute a namespace via <cstddef> use:
# svnlite diff /usr/src/contrib/llvm/
Index: /usr/src/contrib/llvm/tools/clang/include/clang/AST/Type.h
===================================================================
--- /usr/src/contrib/llvm/tools/clang/include/clang/AST/Type.h (revision 292858)
+++ /usr/src/contrib/llvm/tools/clang/include/clang/AST/Type.h (working copy)
@@ -14,6 +14,8 @@
#ifndef LLVM_CLANG_AST_TYPE_H
#define LLVM_CLANG_AST_TYPE_H
+#include <cstddef> // for std::max_align_t
+
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateName.h"
#include "clang/Basic/AddressSpaces.h"
@@ -4336,7 +4338,7 @@
/// DependentTemplateSpecializationType - Represents a template
/// specialization type whose template cannot be resolved, e.g.
/// A<T>::template B<T>
-class DependentTemplateSpecializationType :
+class alignas(alignof(std::max_align_t)) DependentTemplateSpecializationType :
public TypeWithKeyword, public llvm::FoldingSetNode {
/// \brief The nested name specifier containing the qualifier.
alignof(TemplateArgument) is not used because Types.h is used in contexts where
TemplateArgument is an incomplete type and the notation would be rejected.
The command that built a Type.o that worked was (from the script log of the
build):
--- Type.o ---
/usr/bin/clang++ -target armv6--freebsd11.0-gnueabi -march=armv7a -mno-
unaligned-access -target armv6-gnueabi-freebsd11.0 --
sysroot=/usr/obj/clang/arm.armv6/usr/src/tmp -B/usr/local/arm-gnueabi-freebs
d/bin/ --sysroot=/usr/obj/clang/arm.armv6/usr/src/tmp -B/usr/local/arm-gnueabi-
freebsd/bin/ -O -pipe -mfloat-abi=softfp -
I/usr/src/lib/clang/libclangast/../../../contrib/llvm/include -I/usr/src/lib/c
lang/libclangast/../../../contrib/llvm/tools/clang/include -
I/usr/src/lib/clang/libclangast/../../../contrib/llvm/tools/clang/lib/AST -I. -
I/usr/src/lib/clang/libclangast/../../../contrib/llvm/../../l
ib/clang/include -DLLVM_ON_UNIX -DLLVM_ON_FREEBSD -D__STDC_LIMIT_MACROS -
D__STDC_CONSTANT_MACROS -DCLANG_ENABLE_ARCMT -DCLANG_ENABLE_STATIC_ANALYZER -
fno-strict-aliasing -DLLVM_DEFAULT_TARGET_TRIPLE=\
"armv6-gnueabi-freebsd11.0\" -DLLVM_HOST_TRIPLE=\"armv6-unknown-freebsd11.0\" -
DDEFAULT_SYSROOT=\"\" -MD -MP -MF.depend.Type.o -MTType.o -Qunused-arguments -
std=c++11 -fno-exceptions -fno-rtti -stdli
b=libc++ -Wno-c++11-extensions -c
/usr/src/lib/clang/libclangast/../../../contrib/llvm/tools/clang/lib/AST/Type.cpp
-o Type.o
So it used (in order):
-target armv6--freebsd11.0-gnueabi
-march=armv7a
-mno-unaligned-access
-target armv6-gnueabi-freebsd11.0
(The first -target is what I supplied, the 2nd is from the FreeBSD build
environment.)
STILL FAILS OVERALL HOWEVER. . .
Unfortunately clang++ on the rpi2 with SCTLR bit[1]==1 dies for other c++
syntax when trying to build part of llvm (early in FreeBSD's buildworld):
Program terminated with signal 10, Bus error.
#0 0x00c43d28 in clang::ASTTemplateArgumentListInfo::initializeFrom ()
[New Thread 22a18000 (LWP 100079/<unknown>)]
(gdb) bt
#0 0x00c43d28 in clang::ASTTemplateArgumentListInfo::initializeFrom ()
#1 0x00c43f10 in clang::ASTTemplateKWAndArgsInfo::initializeFrom ()
#2 0x00cdc788 in
clang::CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr ()
#3 0x00cdc99c in clang::CXXDependentScopeMemberExpr::Create ()
#4 0x00685384 in clang::Sema::ActOnDependentMemberExpr ()
#5 0x0068abec in clang::Sema::ActOnMemberAccessExpr ()
#6 0x0044a938 in clang::Parser::ParsePostfixExpressionSuffix ()
#7 0x00000000 in ?? ()
(gdb) x/i 0x00c43d28
0xc43d28
<_ZN5clang27ASTTemplateArgumentListInfo14initializeFromERKNS_24TemplateArgumentListInfoERbS4_S4_+396>: vst1.64 {d16-
d17}, [r0]!
(gdb) info all-regsisters
Undefined info command: "all-regsisters". Try "help info".
(gdb) info all-registers
r0 0x234b96dc 592156380
. . .
There are lots of places using "this + 1" and reinterpret_cast that therefore
have the potential for a mis-matched alignment between the two types involved,
just like the one I initially reported (some of the below might not be at risk,
I've not inspected all the details of each):
# grep "reinterpret_cast.*this" lib/*/*
lib/AST/Decl.cpp: SourceLocation *StoredLocs = reinterpret_cast<SourceLocation
*>(this + 1);
lib/AST/Decl.cpp: *reinterpret_cast<SourceLocation *>(this + 1) = EndLoc;
lib/AST/Decl.cpp: = reinterpret_cast<const SourceLocation *>(this + 1);
lib/AST/Decl.cpp: *reinterpret_cast<const SourceLocation
*>(this + 1));
lib/AST/DeclCXX.cpp: VarDecl **MyIndices = reinterpret_cast<VarDecl **> (this
+ 1);
lib/AST/DeclOpenMP.cpp: Expr **Vars = reinterpret_cast<Expr **>(this + 1);
lib/AST/DeclTemplate.cpp: void **TypesAndInfos = reinterpret_cast<void
**>(this + 1);
lib/AST/DeclTemplate.cpp: std::memcpy(reinterpret_cast<void*>(this + 1),
Expansions,
lib/AST/Expr.cpp: return
reinterpret_cast<CXXBaseSpecifier**>(static_cast<Type*>(this)+1);
lib/AST/Expr.cpp: Stmt *const *SubExprs = reinterpret_cast<Stmt *const *>(this
+ 1);
lib/AST/Expr.cpp: Stmt *const *SubExprs = reinterpret_cast<Stmt *const *>(this
+ 1);
lib/AST/Expr.cpp: Stmt *const *SubExprs = reinterpret_cast<Stmt *const *>(this
+ 1);
lib/AST/Expr.cpp: begin = reinterpret_cast<Stmt **>(this + 1);
lib/AST/ExprCXX.cpp: Stmt **StoredArgs = reinterpret_cast<Stmt **>(this + 1);
lib/AST/ExprCXX.cpp:
reinterpret_cast<Decl**>(this+1));
lib/AST/Stmt.cpp: Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1);
lib/AST/Stmt.cpp: reinterpret_cast<char *>(const_cast<CapturedStmt
*>(this))
lib/AST/Type.cpp: QualType *argSlot = reinterpret_cast<QualType*>(this+1);
lib/AST/Type.cpp: = reinterpret_cast<TemplateArgument *>(this + 1);
lib/AST/Type.cpp: TemplateArgument *Begin =
reinterpret_cast<TemplateArgument *>(this + 1);
lib/Basic/IdentifierTable.cpp: IdentifierInfo **KeyInfo =
reinterpret_cast<IdentifierInfo **>(this+1);
lib/Basic/IdentifierTable.cpp: return
reinterpret_cast<keyword_iterator>(this+1);
lib/CodeGen/CGCleanup.h: return reinterpret_cast<Handler*>(this+1);
lib/CodeGen/CGCleanup.h: return reinterpret_cast<const Handler*>(this+1);
lib/CodeGen/CGCleanup.h: return reinterpret_cast<llvm::Value**>(this+1);
lib/CodeGen/CGCleanup.h: return reinterpret_cast<llvm::Value* const
*>(this+1);
lib/CodeGen/CGExprCXX.cpp: RValue *getPlacementArgs() { return
reinterpret_cast<RValue*>(this+1); }
lib/CodeGen/CGExprCXX.cpp: return
reinterpret_cast<DominatingValue<RValue>::saved_type*>(this+1);
lib/Sema/CodeCompleteConsumer.cpp: Chunk *StoredChunks =
reinterpret_cast<Chunk *>(this + 1);
But there is lots more use of reinterpret_cast where "this" is not involved
that might also have problems. Compare:
# grep -l "reinterpret_cast.*this" lib/*/*
lib/AST/Decl.cpp
lib/AST/DeclCXX.cpp
lib/AST/DeclOpenMP.cpp
lib/AST/DeclTemplate.cpp
lib/AST/Expr.cpp
lib/AST/ExprCXX.cpp
lib/AST/Stmt.cpp
lib/AST/Type.cpp
lib/Basic/IdentifierTable.cpp
lib/CodeGen/CGCleanup.h
lib/CodeGen/CGExprCXX.cpp
lib/Sema/CodeCompleteConsumer.cpp
vs.
# grep -l "reinterpret_cast" lib/*/*
lib/AST/APValue.cpp
lib/AST/ASTDiagnostic.cpp
lib/AST/Decl.cpp
lib/AST/DeclCXX.cpp
lib/AST/DeclOpenMP.cpp
lib/AST/DeclTemplate.cpp
lib/AST/DeclarationName.cpp
lib/AST/Expr.cpp
lib/AST/ExprCXX.cpp
lib/AST/ExprConstant.cpp
lib/AST/ItaniumMangle.cpp
lib/AST/NestedNameSpecifier.cpp
lib/AST/ParentMap.cpp
lib/AST/Stmt.cpp
lib/AST/StmtIterator.cpp
lib/AST/Type.cpp
lib/AST/TypeLoc.cpp
lib/Analysis/CFG.cpp
lib/Basic/Diagnostic.cpp
lib/Basic/FileManager.cpp
lib/Basic/IdentifierTable.cpp
lib/CodeGen/CGBlocks.h
lib/CodeGen/CGCleanup.cpp
lib/CodeGen/CGCleanup.h
lib/CodeGen/CGExpr.cpp
lib/CodeGen/CGExprCXX.cpp
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/MicrosoftCXXABI.cpp
lib/Driver/MSVCToolChain.cpp
lib/Driver/Tools.h
lib/Format/Encoding.h
lib/Frontend/CacheTokens.cpp
lib/Frontend/DependencyFile.cpp
lib/Frontend/TextDiagnostic.cpp
lib/Lex/HeaderMap.cpp
lib/Lex/LiteralSupport.cpp
lib/Parse/ParseExpr.cpp
lib/Parse/ParseExprCXX.cpp
lib/Parse/ParseObjc.cpp
lib/Parse/ParsePragma.cpp
lib/Parse/ParseTentative.cpp
lib/Parse/Parser.cpp
lib/Rewrite/RewriteRope.cpp
lib/Sema/CodeCompleteConsumer.cpp
lib/Sema/IdentifierResolver.cpp
lib/Sema/SemaCast.cpp
lib/Sema/SemaCodeComplete.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaDeclObjC.cpp
lib/Sema/SemaExprMember.cpp
lib/Sema/SemaExprObjC.cpp
lib/Sema/SemaInit.cpp
lib/Sema/SemaLookup.cpp
lib/Sema/SemaStmt.cpp
lib/Sema/SemaStmtAsm.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTReaderStmt.cpp
lib/Serialization/ASTWriter.cpp
I've gradually removed more and more Bus Error places by adding
alignas(alignof(std::max_align_t)) to various class/struct declarations. But
now that I'm up to about 76 such additions I think I'm going to give up on
having a personal workaround to enable the clang++ compiler to be used on c++
source code with -march=arm7a with SCTLR bit[1]==1 as the context.
Every single example Bus Error so far is a vst1.64 instruction in clang++
getting a Bus Error for an address that is not aligned appropriately for that
instruction. In every case so far forcing alignment with alignas in the
involved class/struct declarations has allowed the vst1.64 instruction to work.
(No vld1.64 failures have happened so far: the places copied from have been
aligned sufficiently.)
Here are the 76 or so examples (not showing #include <cstddef>'s):
# find -s . -exec grep "alignas.*max_align_t" {} \; | more
class alignas(alignof(std::max_align_t)) StringMapEntry : public
StringMapEntryBase {
class alignas(alignof(std::max_align_t)) RegionNodeBase {
class alignas(alignof(std::max_align_t)) RegionBase : public RegionNodeBase<Tr>
{
class alignas(alignof(std::max_align_t)) FunctionType : public Type {
class alignas(alignof(std::max_align_t)) AttributeSetNode : public
FoldingSetNode {
class alignas(alignof(std::max_align_t)) AttributeSetImpl : public
FoldingSetNode {
class alignas(alignof(std::max_align_t)) MemoryBufferMem : public MemoryBuffer {
class alignas(alignof(std::max_align_t)) MemoryBufferMMapFile : public
MemoryBuffer {
class alignas(alignof(std::max_align_t)) ImportDecl : public Decl {
class alignas(alignof(std::max_align_t)) CXXCtorInitializer {
class alignas(alignof(std::max_align_t)) FriendDecl : public Decl {
class alignas(alignof(std::max_align_t)) ObjCTypeParamList {
class alignas(alignof(std::max_align_t)) OMPThreadPrivateDecl : public Decl {
class alignas(alignof(std::max_align_t)) TemplateParameterList {
class alignas(alignof(std::max_align_t))
DependentFunctionTemplateSpecializationInfo {
class alignas(alignof(std::max_align_t)) NonTypeTemplateParmDecl
class alignas(alignof(std::max_align_t)) TemplateTemplateParmDecl : public
TemplateDecl,
class alignas(alignof(std::max_align_t)) DeclRefExpr : public Expr {
class alignas(alignof(std::max_align_t)) OffsetOfExpr : public Expr {
class alignas(alignof(std::max_align_t)) MemberExpr : public Expr {
class alignas(alignof(std::max_align_t)) CastExpr : public Expr {
class alignas(alignof(std::max_align_t)) DesignatedInitExpr : public Expr {
class alignas(alignof(std::max_align_t)) Designator {
class alignas(alignof(std::max_align_t)) PseudoObjectExpr : public Expr {
class alignas(alignof(std::max_align_t)) CXXDefaultArgExpr : public Expr {
class alignas(alignof(std::max_align_t)) LambdaExpr : public Expr {
class alignas(alignof(std::max_align_t)) TypeTraitExpr : public Expr {
class alignas(alignof(std::max_align_t)) OverloadExpr : public Expr {
class alignas(alignof(std::max_align_t)) DependentScopeDeclRefExpr : public
Expr {
class alignas(alignof(std::max_align_t)) ExprWithCleanups : public Expr {
class alignas(alignof(std::max_align_t)) CXXUnresolvedConstructExpr : public
Expr {
class alignas(alignof(std::max_align_t)) CXXDependentScopeMemberExpr : public
Expr {
class alignas(alignof(std::max_align_t)) FunctionParmPackExpr : public Expr {
class alignas(alignof(std::max_align_t)) ObjCArrayLiteral : public Expr {
class alignas(alignof(std::max_align_t)) ObjCDictionaryLiteral : public Expr {
class alignas(alignof(std::max_align_t)) ObjCMessageExpr : public Expr {
template <class T> class alignas(alignof(std::max_align_t)) OMPVarListClause :
public OMPClause {
class alignas(alignof(std::max_align_t)) OMPPrivateClause : public
OMPVarListClause<OMPPrivateClause> {
class alignas(alignof(std::max_align_t)) OMPFirstprivateClause : public
OMPVarListClause<OMPFirstprivateClause> {
class alignas(alignof(std::max_align_t)) OMPLastprivateClause : public
OMPVarListClause<OMPLastprivateClause> {
class alignas(alignof(std::max_align_t)) OMPSharedClause : public
OMPVarListClause<OMPSharedClause> {
class alignas(alignof(std::max_align_t)) OMPReductionClause : public
OMPVarListClause<OMPReductionClause> {
class alignas(alignof(std::max_align_t)) OMPLinearClause : public
OMPVarListClause<OMPLinearClause> {
class alignas(alignof(std::max_align_t)) OMPAlignedClause : public
OMPVarListClause<OMPAlignedClause> {
class alignas(alignof(std::max_align_t)) OMPCopyinClause : public
OMPVarListClause<OMPCopyinClause> {
class alignas(alignof(std::max_align_t)) OMPCopyprivateClause : public
OMPVarListClause<OMPCopyprivateClause> {
class alignas(alignof(std::max_align_t)) OMPFlushClause : public
OMPVarListClause<OMPFlushClause> {
class alignas(alignof(std::max_align_t)) OMPDependClause : public
OMPVarListClause<OMPDependClause> {
class alignas(alignof(std::max_align_t)) AttributedStmt : public Stmt {
class alignas(alignof(std::max_align_t)) CapturedStmt : public Stmt {
class alignas(alignof(std::max_align_t)) CXXTryStmt : public Stmt {
class alignas(alignof(std::max_align_t)) ObjCAtTryStmt : public Stmt {
class alignas(alignof(std::max_align_t)) OMPExecutableDirective : public Stmt {
class alignas(alignof(std::max_align_t)) OMPLoopDirective : public
OMPExecutableDirective {
class alignas(alignof(std::max_align_t)) TemplateArgument {
struct alignas(alignof(std::max_align_t)) TemplateArgumentLocInfo {
class alignas(alignof(std::max_align_t)) TemplateArgumentLoc {
struct alignas(alignof(std::max_align_t)) ASTTemplateArgumentListInfo {
class alignas(alignof(std::max_align_t)) UncommonTemplateNameStorage {
class alignas(alignof(std::max_align_t)) OverloadedTemplateStorage : public
UncommonTemplateNameStorage {
class alignas(alignof(std::max_align_t)) FunctionProtoType : public
FunctionType, public llvm::FoldingSetNode {
class alignas(alignof(std::max_align_t)) TemplateSpecializationType
class alignas(alignof(std::max_align_t)) DependentTemplateSpecializationType :
class alignas(alignof(std::max_align_t)) ObjCObjectType : public Type {
class alignas(alignof(std::max_align_t)) CGFunctionInfo : public
llvm::FoldingSetNode {
class alignas(alignof(std::max_align_t)) ModuleMacro : public
llvm::FoldingSetNode {
class alignas(alignof(std::max_align_t)) AttributeList { // TODO: This should
really be called ParsedAttribute
class alignas(alignof(std::max_align_t)) CodeCompletionString {
class alignas(alignof(std::max_align_t)) ImplicitConversionSequence {
struct alignas(alignof(std::max_align_t)) TemplateIdAnnotation {
class alignas(alignof(std::max_align_t)) MultiKeywordSelector
class alignas(alignof(std::max_align_t)) EHCatchScope : public EHScope {
class alignas(alignof(std::max_align_t)) EHCleanupScope : public EHScope {
class alignas(alignof(std::max_align_t)) EHFilterScope : public EHScope {
class alignas(alignof(std::max_align_t)) CallDeleteDuringNew : public EHScopeStack::Cleanup {
class alignas(alignof(std::max_align_t)) CallDeleteDuringConditionalNew : public EHScopeStack::Cleanup {
A bunch of these deal with aligning this+1 that is then reinterpret_cast. (So
"this" itself ends up being aligned too but the size may have bene adjusted so
that the +1 result is aligned too.)
A few are tied to aligning array entries for when there might be multiple
entries (given that the above sort of thing got the start of the array aligned):
# find . -exec grep "new[ \t]*([^)]*\[" {} \;
new (&C.Conversions[i]) ImplicitConversionSequence();
new (&ArgsArray[I]) TemplateArgumentLoc(TArgs[I]);
new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]);
Without such alignas usage [0] would work from the this+1 handling but [1]
would fail. (When I found an example for one type I tended to find similar code
structure for other types and adjust them at the same time.)
Other examples that I've not gotten around to adjusting may have the array
activity inside a method that is called with the index to use, for example the
TL.setArgLocInfo below Bus Errors (but was inlined):
TypeSourceInfo *
ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name,
SourceLocation NameLoc,
const TemplateArgumentListInfo &Args,
QualType Underlying) const {
assert(!Name.getAsDependentTemplateName() &&
"No dependent template names here!");
QualType TST = getTemplateSpecializationType(Name, Args, Underlying);
TypeSourceInfo *DI = CreateTypeSourceInfo(TST);
TemplateSpecializationTypeLoc TL =
DI->getTypeLoc().castAs<TemplateSpecializationTypeLoc>();
TL.setTemplateKeywordLoc(SourceLocation());
TL.setTemplateNameLoc(NameLoc);
TL.setLAngleLoc(Args.getLAngleLoc());
TL.setRAngleLoc(Args.getRAngleLoc());
for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
TL.setArgLocInfo(i, Args[i].getLocInfo());
return DI;
}
It appears that much of the reinterpret_cast use in clang++ (and llvm more
generally?) for copying to a new place is suspect and should be validated
relative to alignment requirements, such as for when SCTLR bit[1]==1 for armv7a
contexts.
Context: RPI2B (cortex-a7) with SCTLR bit[1]==1.
The a.out from compiling the later-below 28 or so non-comment/non-blank line
program gets a Bus Error during the placement-new construction activity. THis
is true for both of the following ways of compiling it (and more):
# clang++ -v -std=c++11 -target armv6--freebsd11.0-gnueabi -march=armv7a -
mcpu=cortex-a7 -mfloat-abi=softfp -mno-unaligned-access main.cc
or via:
# clang++ -v -std=c++11 -target armv6--freebsd11.0-gnueabi -mno-unaligned-
access main.cc
The 28 or so code-line program is designed to use somewhat similar techniques
to some of those used in the clang++/llvm source code base that get Bus Errors
during c++ compiles of source code that uses various parts of C++ notation,
just for a much simpler context.
For an armv7 context the -mfloat-abi=softfp compile enables generation of the
neon vast1.64 style of instruction that gets the error in the clang++ crashes
that I've reported. But that is not required to get the Bus Error. (FreeBSD's
buildworld build environment specifies -mfloat-abi=softfp normally for arm
variants and so with -march=armv7a involved it then implicitly uses neon in the
code generation.)
# more main.cc
// Avoid needing headers that will make the compiler crash on rpi2 with SCTLR
bit[1]==1:
void* operator new(unsigned,void* p) { return p; }
struct t0 { // The implicit Copy Constructor requires an alignment
long long t0_f0; // appropriate to the sizeof/alignof(long long) for SCTLR bit[1]==1.
char t0_f1;
} c_t0; // sizeof(t0) is an integral multiple of alignof(long long) so that
array use can work.
struct /* alignas(alignof(struct t0)) */ t1 {
char t1_f0; // Unlikely to get default align(t1) being an integral multiple (>=1) of
// alignof(long long).
struct t0* t0_start(void) { return reinterpret_cast<struct t0*>(this+1); }
// The returned pointer need not be implicitly aligned to the sizeof/alignof(long long)
// unless the alignas is uncommented.
};
struct t2 {
struct t1 t2_f0;
char t2_f1[2*sizeof(struct t0)]; // t2_f0.t0_start() causes use of this area.
};
struct t0 g[2];
extern struct t0 g[2]; // These and their use prevent optimizing everything
away.
int
main ()
{
struct t2 t2_v0;
for (int i=0; i<2; i++)
new(t2_v0.t2_f0.t0_start()+i) t0(c_t0); // i==0 gets Bus Error.
for (int i=0; i<2; i++)
g[i] = *(t2_v0.t2_f0.t0_start()+i);
return 0;
}
Uncommenting the alignas for struct t1 avoids the Bus Errors. "struct t0" does
not need alignas. In code where what is analogous to struct t0 is supposed to
be an incomplete type at that point the alignas would need to be independent of
the struct t0 details, more like:
alignas(alignof(std::max_align_t))
(with #include <cstddef> having been used first). This is true in the
llvm/clang code.
The compilation commands with -v outputs that show the differing neon status
are:
# clang++ -v -std=c++11 -target armv6--freebsd11.0-gnueabi -march=armv7a -
mcpu=cortex-a7 -mfloat-abi=softfp -mno-unaligned-access main.cc
FreeBSD clang version 3.7.1 (tags/RELEASE_371/final 255217) 20151225
Target: armv6--freebsd11.0-gnueabi
Thread model: posix
"/usr/bin/clang++" -cc1 -triple armv7--freebsd11.0-gnueabi -emit-obj -mrelax-all -disable-free -main-file-name main.cc -mrelocation-model static -mthread-model posix -mdisable-fp-elim -masm-verbose -mconstructor-aliases -target-cpu cortex-a7 -target-feature +soft-float-abi -target-abi aapcs-linux -mfloat-abi soft -backend-option -arm-strict-align -v -dwarf-column-info -resource-dir /usr/bin/../lib/clang/3.7.1 -internal-isystem /usr/include/c++/v1 -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /root/c_tests -ferror-limit 19 -fmessage-length 200 -mstackrealign -fno-signed-char -fobjc-runtime=gnustep -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -o /tmp/main-615940.o -x c++ main.cc
clang -cc1 version 3.7.1 based upon LLVM 3.7.1 default target armv6--
freebsd11.0-gnueabi
#include "..." search starts here:
#include <...> search starts here:
/usr/include/c++/v1
/usr/bin/../lib/clang/3.7.1/include
/usr/include
End of search list.
"/usr/bin/ld" --eh-frame-hdr -dynamic-linker /libexec/ld-elf.so.1 --hash-style=both --enable-new-dtags -o a.out /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/crtbegin.o -L/usr/lib /tmp/main-615940.o -lc++ -lm -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/crtend.o /usr/lib/crtn.o
# clang++ -v -std=c++11 -target armv6--freebsd11.0-gnueabi -mno-unaligned-
access main.cc
FreeBSD clang version 3.7.1 (tags/RELEASE_371/final 255217) 20151225
Target: armv6--freebsd11.0-gnueabi
Thread model: posix
"/usr/bin/clang++" -cc1 -triple armv6k--freebsd11.0-gnueabi -emit-obj -mrelax-all -disable-free -main-file-name main.cc -mrelocation-model static -mthread-model posix -mdisable-fp-elim -masm-verbose -mconstructor-aliases -target-cpu arm1176jzf-s -target-feature +soft-float -target-feature +soft-float-abi -target-feature -neon -target-feature -crypto -target-abi aapcs-linux -msoft-float -mfloat-abi soft -backend-option -arm-strict-align -v -dwarf-column-info -resource-dir /usr/bin/../lib/clang/3.7.1 -internal-isystem /usr/include/c++/v1 -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /root/c_tests -ferror-limit 19 -fmessage-length 200 -mstackrealign -fno-signed-char -fobjc-runtime=gnustep -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -o /tmp/main-b1e5fb.o -x c++ main.cc
clang -cc1 version 3.7.1 based upon LLVM 3.7.1 default target armv6--
freebsd11.0-gnueabi
#include "..." search starts here:
#include <...> search starts here:
/usr/include/c++/v1
/usr/bin/../lib/clang/3.7.1/include
/usr/include
End of search list.
"/usr/bin/ld" --eh-frame-hdr -dynamic-linker /libexec/ld-elf.so.1 --hash-style=both --enable-new-dtags -o a.out /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/crtbegin.o -L/usr/lib /tmp/main-b1e5fb.o -lc++ -lm -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/crtend.o /usr/lib/crtn.o
FreeBSD folks such as Ian Lepore report things like "I'm using gcc 4.2.1
for arm v4/v5, because clang 3.7 is broken (works to crossbuild, but
fails to run native)." [2015-Dec-24 note in an exchange about an 11.0-CURRENT
svn commit (r291937).]
To get a quick handle on the size of the investigation effort for alignments of
reinterpret_casts to pointer types in llvm/clang I've tried to get
*approximations* of:
A) count of reinterpret_cast's to pointer types that do not involve base types
with "char" or "int8" text (on the same line).
and
B) How many files have such reinterpret_cast's.
# pwd
/usr/src/contrib/llvm
# find -s . -exec grep -E "reinterpret_cast[ \t]*<[^>]*\*" {} \; | grep -v char
| grep -v int8 | wc
789 3453 51918
# find -s . -exec grep -E "reinterpret_cast[ \t]*<[^>]*(char|int8)[^>]*\*" {}
\; | wc
171 854 11326
(Some files may have a mix of both with and without char/int8.)
# find -s . -exec grep -E "reinterpret_cast[ \t]*<[^>]*\*" {} \; -print | grep
"^\.\/" | wc
264 264 10517
# find -s . -exec grep -E "reinterpret_cast[ \t]*<[^>]*(char|int8)[^>]*\*" {}
\; -print | grep "^\.\/" | wc
71 71 2781
(So 264-71==193 to 264 files.)
And also:
C) How many reinterpret_cast's directly involve the text "this" (on the same
line):
# find -s . -exec grep -E "reinterpret_cast[ \t]*<[^>]*\*.*this" {} \; | grep -
v char | grep -v int8 | wc
132 739 8443
D) How many files is that?
# find -s . -exec grep -E "reinterpret_cast[ \t]*<[^>]*\*.*this" {} \; -print |
grep "^\.\/" | wc
47 47 1914
# find -s . -exec grep -E "reinterpret_cast[
\t]*<[^>]*(char|int8)[^>]*\*.*this" {} \; -print | grep "^\.\/" | wc
5 5 185
(So 47-5==42 to 47 files.)
E) How many reinterpret_cast's do not mention "this", "char", or "int8" (on the
same line):
# find -s . -exec grep -E "reinterpret_cast[ \t]*<[^>]*\*" {} \; | grep -v this
| grep -v char | grep -v int8 | wc
647 2663 42647
This is the majority of the reinterpret_cast's, by far.
It looks non-trivial to find and adjust the llvm/clang source so that all the
places that do not currently deal with proper alignment for SCTLR bit[1]==1
contexts instead do so.
So it is not likely to be happen time soon, much less finish any time soon.
This will limit FreeBSD 11.0's "self hosting on arm" c++ support via the
system/clang++ tool chain greatly based on the CTLR bit[1]==1 status: cross
builds required from a host not requiring alignment, such as from amd64. (Once
some other C++ tool chain is in place on an arm more native work may then be
possible.)
The C part of clang does appear to compile okay for buildkernel use in the
SCTRL bit[1]==1 context. So far all the misalignments have happened in
compiling-c++ contexts, which is involved for buildworld and for building many
ports.
Hi Mark,
Thanks for your detailed investigation. I can confirm that this is fixed on trunk and therefore will be fixed for LLVM 3.8.
The fixes were done for SPARC, which requires strict accesses much as ARM does with SCTLR=1.
There was a sequence of commits by James Knight that fixed these, but an example is http://reviews.llvm.org/rL242554 .
The fixes were in a similar vein to yours, but required changes in fewer places and there were a few more sticky issues to solve too. I'll CC James here in case he wants to comment on the current state of the clang codebase for self-hosting in a strict alignment environment.
Cheers,
James
Thanks for reporting that the issue reported is fixed for 3.8.
Unfortunately for FreeBSD, Ian Lapore now reports:
It's a non-starter for us, because unfortunately they appear to have
removed support for the -arm-use-movt=0 command line option, so now we
can't build ubldr or kernel modules.
-- Ian
I do not know the details in this area but it certainly would be a separate
submittal.
(In reply to comment #9)
> Thanks for reporting that the issue reported is fixed for 3.8.
>
> Unfortunately for FreeBSD, Ian Lapore now reports:
>
> It's a non-starter for us, because unfortunately they appear to have
> removed support for the -arm-use-movt=0 command line option
This was changed to a subfeature, but I am unsure how to pass a specific
subfeature on the clang command line itself.
In any case the point has become a little moot now, since Davide Italiano has
turned off movt altogether for FreeBSD in r256641:
http://reviews.llvm.org/rL256641
This is because our linker is currently too old to support the necessary
relocation types.