Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 34 additions & 9 deletions clang/lib/CodeGen/CGStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2572,24 +2572,49 @@ CodeGenFunction::EmitAsmInput(const TargetInfo::ConstraintInfo &Info,
static llvm::MDNode *getAsmSrcLocInfo(const StringLiteral *Str,
CodeGenFunction &CGF) {
SmallVector<llvm::Metadata *, 8> Locs;

// We need these to find the correct location for the first line.
StringRef StrVal = Str->getString();
const SourceManager &SM = CGF.CGM.getContext().getSourceManager();
const LangOptions &LangOpts = CGF.CGM.getLangOpts();
unsigned StartToken = 0;
unsigned ByteOffset = 0;

// Add the location of the first line to the MDNode.

// Find the offset of the first character that isn't horizontal whitespace.
size_t FirstLocOffset = StrVal.find_first_not_of(" \t\v\f");

// If the string is empty or all-whitespace, default to offset 0.
if (FirstLocOffset == StringRef::npos)
FirstLocOffset = 0;

SourceLocation FirstLineLoc = Str->getLocationOfByte(
FirstLocOffset, SM, LangOpts, CGF.getTarget(), &StartToken, &ByteOffset);

Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
CGF.Int64Ty, Str->getBeginLoc().getRawEncoding())));
StringRef StrVal = Str->getString();
if (!StrVal.empty()) {
const SourceManager &SM = CGF.CGM.getContext().getSourceManager();
const LangOptions &LangOpts = CGF.CGM.getLangOpts();
unsigned StartToken = 0;
unsigned ByteOffset = 0;
CGF.Int64Ty, FirstLineLoc.getRawEncoding())));

if (!StrVal.empty()) {
// Add the location of the start of each subsequent line of the asm to the
// MDNode.
for (unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
if (StrVal[i] != '\n') continue;

// The next line starts at byte offset i + 1.
// Find the first non-horizontal-whitespace at or after this offset.
size_t NextLineOffset = StrVal.find_first_not_of(" \t\v\f", i + 1);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you rearrange the loop so you don't have to duplicate the code for the first line?


// If the rest of the string is empty or all-whitespace,
// just use the location right after the newline (i + 1).
if (NextLineOffset == StringRef::npos)
NextLineOffset = i + 1;

SourceLocation LineLoc = Str->getLocationOfByte(
i + 1, SM, LangOpts, CGF.getTarget(), &StartToken, &ByteOffset);
NextLineOffset, SM, LangOpts, CGF.getTarget(), &StartToken, &ByteOffset);

Locs.push_back(llvm::ConstantAsMetadata::get(
llvm::ConstantInt::get(CGF.Int64Ty, LineLoc.getRawEncoding())));
llvm::ConstantInt::get(CGF.Int64Ty, LineLoc.getRawEncoding())));
}
}

Expand Down
23 changes: 23 additions & 0 deletions clang/test/CodeGen/asm-srcloc-split-literal.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/// Test that inline asm source location corresponds to the actual
/// instruction line, not the first line of the asm block.
///
/// RUN: not %clang_cc1 -triple x86_64-pc-linux-gnu -emit-obj %s 2>&1 | FileCheck %s
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add -o %t or something like that so we don't accidentally get output files in weird places.

Needs // REQUIRES: x86-registered-target somewhere because this uses the x86 asm parser.


// #include <stdint.h>
// #include <string.h>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary comments.


void *memset(void *dest, int c, int n)__attribute__((naked));
void *memset(void *dest, int c, int n) {
__asm__(
"\t" // <-- line with only a tab
"xchg %eax, %eax\n" // <-- A valid instruction
"\t" // <-- line with only a tab
"mov rdi, 1\n" // <-- An invalid instruction
);
}

int main() { return 0; }

// CHECK: error: unknown use of instruction mnemonic
// CHECK-NEXT: mov rdi, 1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CHECK lines here don't seem to actually check the line numbers.


Loading