mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 12:26:52 +08:00
[Serialization] Add support for (de)serializing #pragma pack
Serialization of tokens is required when PCH is used with late parsed templates, including annotation tokens used for pragmas. This patch implements the serialization for annot_pragma_pack. Fixes https://github.com/llvm/llvm-project/issues/60543 Differential Revision: https://reviews.llvm.org/D143410
This commit is contained in:
@@ -483,6 +483,12 @@ public:
|
||||
PSK_Pop_Set = PSK_Pop | PSK_Set, // #pragma (pop[, id], value)
|
||||
};
|
||||
|
||||
struct PragmaPackInfo {
|
||||
PragmaMsStackAction Action;
|
||||
StringRef SlotLabel;
|
||||
Token Alignment;
|
||||
};
|
||||
|
||||
// #pragma pack and align.
|
||||
class AlignPackInfo {
|
||||
public:
|
||||
|
||||
@@ -2236,7 +2236,7 @@ public:
|
||||
unsigned &Idx, LocSeq *Seq = nullptr);
|
||||
|
||||
// Read a string
|
||||
static std::string ReadString(const RecordData &Record, unsigned &Idx);
|
||||
static std::string ReadString(const RecordDataImpl &Record, unsigned &Idx);
|
||||
|
||||
// Skip a string
|
||||
static void SkipString(const RecordData &Record, unsigned &Idx) {
|
||||
|
||||
@@ -665,18 +665,10 @@ void Parser::HandlePragmaVisibility() {
|
||||
Actions.ActOnPragmaVisibility(VisType, VisLoc);
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct PragmaPackInfo {
|
||||
Sema::PragmaMsStackAction Action;
|
||||
StringRef SlotLabel;
|
||||
Token Alignment;
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
void Parser::HandlePragmaPack() {
|
||||
assert(Tok.is(tok::annot_pragma_pack));
|
||||
PragmaPackInfo *Info =
|
||||
static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
|
||||
Sema::PragmaPackInfo *Info =
|
||||
static_cast<Sema::PragmaPackInfo *>(Tok.getAnnotationValue());
|
||||
SourceLocation PragmaLoc = Tok.getLocation();
|
||||
ExprResult Alignment;
|
||||
if (Info->Alignment.is(tok::numeric_constant)) {
|
||||
@@ -2110,8 +2102,8 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP,
|
||||
return;
|
||||
}
|
||||
|
||||
PragmaPackInfo *Info =
|
||||
PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
|
||||
Sema::PragmaPackInfo *Info =
|
||||
PP.getPreprocessorAllocator().Allocate<Sema::PragmaPackInfo>(1);
|
||||
Info->Action = Action;
|
||||
Info->SlotLabel = SlotLabel;
|
||||
Info->Alignment = Alignment;
|
||||
|
||||
@@ -1687,6 +1687,16 @@ Token ASTReader::ReadToken(ModuleFile &F, const RecordDataImpl &Record,
|
||||
Tok.setAnnotationValue(static_cast<void *>(Info));
|
||||
break;
|
||||
}
|
||||
case tok::annot_pragma_pack: {
|
||||
auto *Info = new (PP.getPreprocessorAllocator()) Sema::PragmaPackInfo;
|
||||
Info->Action = static_cast<Sema::PragmaMsStackAction>(Record[Idx++]);
|
||||
auto SlotLabel = ReadString(Record, Idx);
|
||||
Info->SlotLabel =
|
||||
llvm::StringRef(SlotLabel).copy(PP.getPreprocessorAllocator());
|
||||
Info->Alignment = ReadToken(F, Record, Idx);
|
||||
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:
|
||||
@@ -9084,7 +9094,7 @@ llvm::APFloat ASTRecordReader::readAPFloat(const llvm::fltSemantics &Sem) {
|
||||
}
|
||||
|
||||
// Read a string
|
||||
std::string ASTReader::ReadString(const RecordData &Record, unsigned &Idx) {
|
||||
std::string ASTReader::ReadString(const RecordDataImpl &Record, unsigned &Idx) {
|
||||
unsigned Len = Record[Idx++];
|
||||
std::string Result(Record.data() + Idx, Record.data() + Idx + Len);
|
||||
Idx += Len;
|
||||
|
||||
@@ -4412,6 +4412,14 @@ void ASTWriter::AddToken(const Token &Tok, RecordDataImpl &Record) {
|
||||
AddToken(T, Record);
|
||||
break;
|
||||
}
|
||||
case tok::annot_pragma_pack: {
|
||||
auto *Info =
|
||||
static_cast<Sema::PragmaPackInfo *>(Tok.getAnnotationValue());
|
||||
Record.push_back(static_cast<unsigned>(Info->Action));
|
||||
AddString(Info->SlotLabel, Record);
|
||||
AddToken(Info->Alignment, Record);
|
||||
break;
|
||||
}
|
||||
// Some annotation tokens do not use the PtrData field.
|
||||
case tok::annot_pragma_openmp:
|
||||
case tok::annot_pragma_openmp_end:
|
||||
|
||||
78
clang/test/PCH/delayed-template-with-pragma-pack.cpp
Normal file
78
clang/test/PCH/delayed-template-with-pragma-pack.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -emit-pch -o %t.pch %s
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fdelayed-template-parsing -emit-pch -o %t.delayed.pch %s
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -DMAIN_FILE \
|
||||
// RUN: -include-pch %t.pch \
|
||||
// RUN: -emit-llvm -verify -o - %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -DMAIN_FILE -fdelayed-template-parsing \
|
||||
// RUN: -include-pch %t.delayed.pch \
|
||||
// RUN: -emit-llvm -verify -o - %s | FileCheck %s
|
||||
|
||||
#ifndef MAIN_FILE
|
||||
|
||||
extern "C" void consume(int b);
|
||||
|
||||
template <int I>
|
||||
void function() {
|
||||
#pragma pack(push, 1)
|
||||
struct packedAt1 {
|
||||
char a;
|
||||
unsigned long long b;
|
||||
char c;
|
||||
unsigned long long d;
|
||||
// 18 bytes total
|
||||
};
|
||||
#pragma pack(push, slot1, 2)
|
||||
struct packedAt2 {
|
||||
char a; // +1 byte of padding
|
||||
unsigned long long b;
|
||||
char c; // +1 byte of padding
|
||||
unsigned long long d;
|
||||
// 20 bytes total
|
||||
};
|
||||
#pragma pack(push, 4)
|
||||
struct packedAt4 {
|
||||
char a; // +3 bytes of padding
|
||||
unsigned long long b;
|
||||
char c; // +3 bytes of padding
|
||||
unsigned long long d;
|
||||
// 24 bytes total
|
||||
};
|
||||
#pragma pack(push, 16)
|
||||
struct packedAt16 {
|
||||
char a; // +7 bytes of padding
|
||||
unsigned long long b;
|
||||
char c; // +7 bytes of padding
|
||||
unsigned long long d;
|
||||
// 32 bytes total
|
||||
};
|
||||
#pragma pack(pop, slot1) // This should return packing to 1 (established before push(slot1))
|
||||
struct packedAfterPopBackTo1 {
|
||||
char a;
|
||||
unsigned long long b;
|
||||
char c;
|
||||
unsigned long long d;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
consume(sizeof(packedAt1)); // 18
|
||||
consume(sizeof(packedAt2)); // 20
|
||||
consume(sizeof(packedAt4)); // 24
|
||||
consume(sizeof(packedAt16)); // 32
|
||||
consume(sizeof(packedAfterPopBackTo1)); // 18 again
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// CHECK-LABEL: define linkonce_odr dso_local void @"??$function@$0A@@@YAXXZ"(
|
||||
// CHECK: call void @consume(i32 noundef 18)
|
||||
// CHECK-NEXT: call void @consume(i32 noundef 20)
|
||||
// CHECK-NEXT: call void @consume(i32 noundef 24)
|
||||
// CHECK-NEXT: call void @consume(i32 noundef 32)
|
||||
// CHECK-NEXT: call void @consume(i32 noundef 18)
|
||||
void foo() {
|
||||
function<0>();
|
||||
}
|
||||
|
||||
// expected-no-diagnostics
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user