[clang] Add serialization for loop hint annotation tokens
When late parsed templates are used with PCH tokens are serialized. The existing code does not handle annotation tokens which can occur due to various pragmas. This patch implements the serialization for annot_pragma_loop_hint. This also enables use of OpenMP pragmas and #pragma unused which do not need special serialization of the PtrData field. Fixes https://github.com/llvm/llvm-project/issues/39504 Differential Revision: https://reviews.llvm.org/D138453
This commit is contained in:
parent
65df5bf2d1
commit
530eb263c0
|
@ -450,6 +450,10 @@ Non-comprehensive list of changes in this release
|
|||
It can be used to writing conditionally constexpr code that uses builtins.
|
||||
- The time profiler (using ``-ftime-trace`` option) now traces various constant
|
||||
evaluation events.
|
||||
- Clang can now generate a PCH when using ``-fdelayed-template-parsing`` for
|
||||
code with templates containing loop hint pragmas, OpenMP pragmas, and
|
||||
``#pragma unused``.
|
||||
|
||||
|
||||
New Compiler Flags
|
||||
------------------
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/Basic/TokenKinds.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <cassert>
|
||||
|
||||
|
@ -330,6 +331,12 @@ struct PPConditionalInfo {
|
|||
bool FoundElse;
|
||||
};
|
||||
|
||||
// Extra information needed for annonation tokens.
|
||||
struct PragmaLoopHintInfo {
|
||||
Token PragmaName;
|
||||
Token Option;
|
||||
ArrayRef<Token> Toks;
|
||||
};
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_LEX_TOKEN_H
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace serialization {
|
|||
/// Version 4 of AST files also requires that the version control branch and
|
||||
/// revision match exactly, since there is no backward compatibility of
|
||||
/// AST files at this time.
|
||||
const unsigned VERSION_MAJOR = 23;
|
||||
const unsigned VERSION_MAJOR = 24;
|
||||
|
||||
/// AST file minor version number supported by this version of
|
||||
/// Clang.
|
||||
|
|
|
@ -1293,14 +1293,6 @@ bool Parser::HandlePragmaMSAllocText(StringRef PragmaName,
|
|||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct PragmaLoopHintInfo {
|
||||
Token PragmaName;
|
||||
Token Option;
|
||||
ArrayRef<Token> Toks;
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
|
||||
StringRef Str = PragmaName.getIdentifierInfo()->getName();
|
||||
std::string ClangLoopStr("clang loop ");
|
||||
|
|
|
@ -1669,11 +1669,38 @@ Token ASTReader::ReadToken(ModuleFile &F, const RecordDataImpl &Record,
|
|||
Token Tok;
|
||||
Tok.startToken();
|
||||
Tok.setLocation(ReadSourceLocation(F, Record, Idx));
|
||||
Tok.setLength(Record[Idx++]);
|
||||
if (IdentifierInfo *II = getLocalIdentifier(F, Record[Idx++]))
|
||||
Tok.setIdentifierInfo(II);
|
||||
Tok.setKind((tok::TokenKind)Record[Idx++]);
|
||||
Tok.setFlag((Token::TokenFlags)Record[Idx++]);
|
||||
|
||||
if (Tok.isAnnotation()) {
|
||||
Tok.setAnnotationEndLoc(ReadSourceLocation(F, Record, Idx));
|
||||
switch (Tok.getKind()) {
|
||||
case tok::annot_pragma_loop_hint: {
|
||||
auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
|
||||
Info->PragmaName = ReadToken(F, Record, Idx);
|
||||
Info->Option = ReadToken(F, Record, Idx);
|
||||
unsigned NumTokens = Record[Idx++];
|
||||
SmallVector<Token, 4> Toks;
|
||||
Toks.reserve(NumTokens);
|
||||
for (unsigned I = 0; I < NumTokens; ++I)
|
||||
Toks.push_back(ReadToken(F, Record, Idx));
|
||||
Info->Toks = llvm::makeArrayRef(Toks).copy(PP.getPreprocessorAllocator());
|
||||
Tok.setAnnotationValue(static_cast<void *>(Info));
|
||||
break;
|
||||
}
|
||||
// Some annotation tokens do not use the PtrData field.
|
||||
case tok::annot_pragma_openmp:
|
||||
case tok::annot_pragma_openmp_end:
|
||||
case tok::annot_pragma_unused:
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("missing deserialization code for annotation token");
|
||||
}
|
||||
} else {
|
||||
Tok.setLength(Record[Idx++]);
|
||||
if (IdentifierInfo *II = getLocalIdentifier(F, Record[Idx++]))
|
||||
Tok.setIdentifierInfo(II);
|
||||
}
|
||||
return Tok;
|
||||
}
|
||||
|
||||
|
|
|
@ -4372,15 +4372,37 @@ void ASTRecordWriter::AddAttributes(ArrayRef<const Attr *> Attrs) {
|
|||
|
||||
void ASTWriter::AddToken(const Token &Tok, RecordDataImpl &Record) {
|
||||
AddSourceLocation(Tok.getLocation(), Record);
|
||||
Record.push_back(Tok.getLength());
|
||||
|
||||
// FIXME: When reading literal tokens, reconstruct the literal pointer
|
||||
// if it is needed.
|
||||
AddIdentifierRef(Tok.getIdentifierInfo(), Record);
|
||||
// FIXME: Should translate token kind to a stable encoding.
|
||||
Record.push_back(Tok.getKind());
|
||||
// FIXME: Should translate token flags to a stable encoding.
|
||||
Record.push_back(Tok.getFlags());
|
||||
|
||||
if (Tok.isAnnotation()) {
|
||||
AddSourceLocation(Tok.getAnnotationEndLoc(), Record);
|
||||
switch (Tok.getKind()) {
|
||||
case tok::annot_pragma_loop_hint: {
|
||||
auto *Info = static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
|
||||
AddToken(Info->PragmaName, Record);
|
||||
AddToken(Info->Option, Record);
|
||||
Record.push_back(Info->Toks.size());
|
||||
for (const auto &T : Info->Toks)
|
||||
AddToken(T, Record);
|
||||
break;
|
||||
}
|
||||
// Some annotation tokens do not use the PtrData field.
|
||||
case tok::annot_pragma_openmp:
|
||||
case tok::annot_pragma_openmp_end:
|
||||
case tok::annot_pragma_unused:
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("missing serialization code for annotation token");
|
||||
}
|
||||
} else {
|
||||
Record.push_back(Tok.getLength());
|
||||
// FIXME: When reading literal tokens, reconstruct the literal pointer if it
|
||||
// is needed.
|
||||
AddIdentifierRef(Tok.getIdentifierInfo(), Record);
|
||||
}
|
||||
}
|
||||
|
||||
void ASTWriter::AddString(StringRef Str, RecordDataImpl &Record) {
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
// RUN: %clang_cc1 -fopenmp -emit-pch -o %t.pch %s
|
||||
// RUN: %clang_cc1 -fopenmp -fdelayed-template-parsing -emit-pch -o %t.delayed.pch %s
|
||||
// RUN: %clang_cc1 -DMAIN_FILE -fopenmp -include-pch %t.pch \
|
||||
// RUN: -emit-llvm -o - %s -fopenmp | FileCheck %s
|
||||
// RUN: %clang_cc1 -DMAIN_FILE -fopenmp -fdelayed-template-parsing -verify \
|
||||
// RUN: -Wunused-variable -include-pch %t.delayed.pch \
|
||||
// RUN: -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
#ifndef MAIN_FILE
|
||||
template <typename T>
|
||||
void a(T t) {
|
||||
#pragma clang loop unroll_count(4)
|
||||
for(int i=0;i<8;++i) {}
|
||||
#pragma omp simd
|
||||
for(int i=0;i<8;++i) {}
|
||||
{
|
||||
int x, y, z, zz;
|
||||
#pragma unused(x)
|
||||
#pragma unused(y, z)
|
||||
}
|
||||
}
|
||||
#else
|
||||
// CHECK: !llvm.loop !3
|
||||
// CHECK: !llvm.loop !7
|
||||
// CHECK: !3 = distinct !{!3, !4, !5}
|
||||
// CHECK: !4 = !{!"llvm.loop.mustprogress"}
|
||||
// CHECK: !5 = !{!"llvm.loop.unroll.count", i32 4}
|
||||
// CHECK: !7 = distinct !{!7, !8, !9}
|
||||
// CHECK: !8 = !{!"llvm.loop.parallel_accesses", !6}
|
||||
// CHECK: !9 = !{!"llvm.loop.vectorize.enable", i1 true}
|
||||
// expected-warning@17 {{unused variable 'zz'}}
|
||||
void foo()
|
||||
{
|
||||
a(1);
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue