LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 22576 - Assertion failed: (LIsBuiltins && RIsBuiltins && "Non-built-in locations must be rooted in the main file"), function isBeforeInTranslationUnit
Summary: Assertion failed: (LIsBuiltins && RIsBuiltins && "Non-built-in locations must...
Status: NEW
Alias: None
Product: new-bugs
Classification: Unclassified
Component: new bugs (show other bugs)
Version: trunk
Hardware: Other All
: P normal
Assignee: Douglas Gregor
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-02-13 06:05 PST by Dimitry Andric
Modified: 2015-03-12 20:57 PDT (History)
6 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dimitry Andric 2015-02-13 06:05:39 PST
This assertion was originally reported in a FreeBSD PR: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=197527

It reproduces with clang trunk r228967, and occurs during compilation of WebKit's LowLevelInterpreter.cpp, which is file containing quite a lot of generated inline assembly for the JavaScript engine.

I reduced the test case to just this two-liner:

    #pragma clang diagnostic ignored "-Wmissing-noreturn"
    __asm__(".Lfoo: movw r2, #:lower16:.Lbar - .Lfoo");

Compile this with:

    clang -cc1 -triple armv6 -emit-obj bug197527-reduced.c

Results in:

    Assertion failed: (LIsBuiltins && RIsBuiltins && "Non-built-in locations must be rooted in the main file"), function isBeforeInTranslationUnit, file /share/dim/src/llvm/trunk/tools/clang/lib/Basic/SourceManager.cpp, line 2091.
    Abort trap
Comment 1 Dimitry Andric 2015-02-13 06:08:01 PST
Additional note: removing the #pragma makes the assertion disappear!
Comment 2 Dimitry Andric 2015-02-13 06:43:50 PST
Backtrace (didn't have debug symbols on this build, so will have to do with just function names):

#0  0x2ae3a50b in thr_kill () from /lib/libc.so.7
#1  0x2ae3a4bc in raise () from /lib/libc.so.7
#2  0x2ae38b53 in abort () from /lib/libc.so.7
#3  0x2ae18e78 in __assert () from /lib/libc.so.7
#4  0x0944b068 in clang::SourceManager::isBeforeInTranslationUnit(clang::SourceLocation, clang::SourceLocation) const ()
#5  0x09442de7 in clang::FullSourceLoc::isBeforeInTranslationUnitThan(clang::SourceLocation) const ()
#6  0x09427847 in clang::DiagnosticsEngine::GetDiagStatePointForLoc(clang::SourceLocation) const ()
#7  0x0942df16 in clang::DiagnosticIDs::getDiagnosticSeverity(unsigned int, clang::SourceLocation, clang::DiagnosticsEngine const&) const ()
#8  0x0942de29 in clang::DiagnosticIDs::getDiagnosticLevel(unsigned int, clang::SourceLocation, clang::DiagnosticsEngine const&) const ()
#9  0x0942e702 in clang::DiagnosticIDs::ProcessDiag(clang::DiagnosticsEngine&) const ()
#10 0x09428ca0 in clang::DiagnosticsEngine::EmitCurrentDiagnostic(bool) ()
#11 0x08549745 in clang::BackendConsumer::InlineAsmDiagHandler2(llvm::SMDiagnostic const&, clang::SourceLocation) ()
#12 0x0854d0d7 in clang::BackendConsumer::InlineAsmDiagHandler(llvm::SMDiagnostic const&, void*, unsigned int) ()
#13 0x09e497b3 in srcMgrDiagHandler(llvm::SMDiagnostic const&, void*) ()
#14 0x0a40d4d7 in (anonymous namespace)::AsmParser::DiagHandler(llvm::SMDiagnostic const&, void*) ()
#15 0x0a656101 in llvm::SourceMgr::PrintMessage(llvm::raw_ostream&, llvm::SMDiagnostic const&, bool) const ()
#16 0x0a656ff5 in llvm::SourceMgr::PrintMessage(llvm::raw_ostream&, llvm::SMLoc, llvm::SourceMgr::DiagKind, llvm::Twine const&, llvm::ArrayRef<llvm::SMRange>, llvm::ArrayRef<llvm::SMFixIt>, bool) const ()
#17 0x0a65712d in llvm::SourceMgr::PrintMessage(llvm::SMLoc, llvm::SourceMgr::DiagKind, llvm::Twine const&, llvm::ArrayRef<llvm::SMRange>, llvm::ArrayRef<llvm::SMFixIt>, bool) const ()
#18 0x0a40ff81 in (anonymous namespace)::AsmParser::Error(llvm::SMLoc, llvm::Twine const&, llvm::ArrayRef<llvm::SMRange>) ()
#19 0x098568ba in (anonymous namespace)::ARMAsmParser::MatchAndEmitInstruction(llvm::SMLoc, unsigned int&, llvm::SmallVectorImpl<std::__1::unique_ptr<llvm::MCParsedAsmOperand, std::__1::default_delete<llvm::MCParsedAsmOperand> > >&, llvm::MCStreamer&, unsigned long long&, bool) ()
#20 0x0a414374 in (anonymous namespace)::AsmParser::parseStatement((anonymous namespace)::ParseStatementInfo&, llvm::MCAsmParserSemaCallback*) ()
#21 0x0a40de13 in (anonymous namespace)::AsmParser::Run(bool, bool) ()
#22 0x09e49513 in llvm::AsmPrinter::EmitInlineAsm(llvm::StringRef, llvm::MDNode const*, llvm::InlineAsm::AsmDialect) const ()
#23 0x09e3c58f in llvm::AsmPrinter::doInitialization(llvm::Module&) ()
#24 0x0a5c804b in llvm::FPPassManager::doInitialization(llvm::Module&) ()
#25 0x0a5c837c in llvm::legacy::PassManagerImpl::run(llvm::Module&) ()
#26 0x0a5c8c08 in llvm::legacy::PassManager::run(llvm::Module&) ()
#27 0x0855aee4 in clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::raw_ostream*) ()
#28 0x0854cbff in clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) ()
#29 0x08763085 in clang::ParseAST(clang::Sema&, bool, bool) ()
#30 0x0833ab97 in clang::ASTFrontendAction::ExecuteAction() ()
#31 0x0854b821 in clang::CodeGenAction::ExecuteAction() ()
#32 0x0833a499 in clang::FrontendAction::Execute() ()
#33 0x0830a593 in clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) ()
#34 0x082ed9aa in clang::ExecuteCompilerInvocation(clang::CompilerInstance*) ()
#35 0x082e3869 in cc1_main(llvm::ArrayRef<char const*>, char const*, void*) ()
#36 0x082eb885 in main ()
Comment 3 Dimitry Andric 2015-02-13 13:49:37 PST
Actually, the assembly itself is rather misleading, it does not have anything to do with ARM or the target CPU whatsoever.  It is some unexpected case in the diagnostics engine, since this also triggers it:

    #pragma clang diagnostic ignored "-Wmissing-noreturn"
    asm("0");

E.g., just the fact that *any* warning is triggered for a top-level asm construct causes the assertion.  The key word is "top-level", since obviously this does not happen when the asm construct is within a function.
Comment 4 Roman Divacky 2015-02-17 15:59:30 PST
This happens because the LHS is "<inline asm>" which is a string that is created in llvm MC, the RHS is "name_of_the_file.c". Then the LOffs is {first = {ID = 3}, second = 1} while the ROffs is {first = {ID = 1}, second = 14}. Ie. the method thinks those two are from different files.

I dont know if thats expected (the buffer is independent of the file but there seems to be some translation in clang::BackendConsumer::InlineAsmDiagHandler2()) or not. In case this is expected there's some code to handle (I think) similar situation with "<built-in>" which we handle specially.

In either case, this patch (probably wrong) makes clang not crash on this and emit reasonable error:

Index: ../tools/clang/lib/Basic/SourceManager.cpp
===================================================================
--- ../tools/clang/lib/Basic/SourceManager.cpp  (revision 229486)
+++ ../tools/clang/lib/Basic/SourceManager.cpp  (working copy)
@@ -2084,9 +2084,15 @@
                             getBuffer(LOffs.first)->getBufferIdentifier()) == 0;
   bool RIsBuiltins = strcmp("<built-in>",
                             getBuffer(ROffs.first)->getBufferIdentifier()) == 0;
+  bool LIsInlineAsm = strcmp("<inline asm>",
+                            getBuffer(LOffs.first)->getBufferIdentifier()) == 0;
+  bool RIsInlineAsm = strcmp("<inline asm>",
+                            getBuffer(ROffs.first)->getBufferIdentifier()) == 0;
   // built-in is before non-built-in
   if (LIsBuiltins != RIsBuiltins)
     return LIsBuiltins;
+  if (LIsInlineAsm != RIsInlineAsm)
+    return LIsInlineAsm;
   assert(LIsBuiltins && RIsBuiltins &&
          "Non-built-in locations must be rooted in the main file");
   // Both are in built-in buffers, but from different files. We just claim that

the output:

./bin/clang crash.c
<inline asm>:1:2: error: unexpected token at start of statement
0
 ^
1 error generated.


Doug, as you seem to be the person who commited this... can you comment and/or fix this?
Comment 5 Jörg Sonnenberger 2015-03-12 20:57:03 PDT
The central issue seems to be that a module's global inline assembler doesn't have a location attached. It would be possible to extend llvm::Module::appendModuleInlineAsm to also pass a location field in or alternatively, keep track of it the location on the clang side before extending it. I'm not sure such a change can be done non-intrusive for merging into 3.6.
As such, I believe Roman's approach is the right step forward. Open questions for me are:
(1) How to best identify the problematic buffers. I think we want to restrict this to the global module context, in-function asm doesn't have this problem.
(2) Which order is desirable?