[AST][RISCV] Preserve RISC-V intrinsic pragma in AST (#171981)

RISC-V vector intrinsic is generated dynamically at runtime, thus it's
note preserved in AST yet when using precompile header, neither do
information in SemaRISCV. We need to write these information to ast
record to be able to use precompile header for RISC-V.

Fixes #109634
This commit is contained in:
Brandon Wu 2025-12-17 12:53:58 +08:00 committed by GitHub
parent 282e8ea78e
commit fe577b1f3a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 83 additions and 0 deletions

View File

@ -66,6 +66,7 @@
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaBase.h"
#include "clang/Sema/SemaConcept.h"
#include "clang/Sema/SemaRISCV.h"
#include "clang/Sema/TypoCorrection.h"
#include "clang/Sema/Weak.h"
#include "llvm/ADT/APInt.h"

View File

@ -745,6 +745,9 @@ enum ASTRecordTypes {
UPDATE_MODULE_LOCAL_VISIBLE = 76,
UPDATE_TU_LOCAL_VISIBLE = 77,
/// Record code for #pragma clang riscv intrinsic vector.
RISCV_VECTOR_INTRINSICS_PRAGMA = 78,
};
/// Record types used within a source manager block.

View File

@ -1079,6 +1079,9 @@ private:
/// The IDs of all decls with function effects to be checked.
SmallVector<GlobalDeclID> DeclsWithEffectsToVerify;
/// The RISC-V intrinsic pragma(including RVV, SiFive and Andes).
SmallVector<bool, 3> RISCVVecIntrinsicPragma;
private:
struct ImportedSubmodule {
serialization::SubmoduleID ID;

View File

@ -640,6 +640,7 @@ private:
void WriteDeclsWithEffectsToVerify(Sema &SemaRef);
void WriteModuleFileExtension(Sema &SemaRef,
ModuleFileExtensionWriter &Writer);
void WriteRISCVIntrinsicPragmas(Sema &SemaRef);
unsigned DeclParmVarAbbrev = 0;
unsigned DeclContextLexicalAbbrev = 0;

View File

@ -4465,6 +4465,22 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/)
DeclsToCheckForDeferredDiags.insert(ReadDeclID(F, Record, I));
break;
case RISCV_VECTOR_INTRINSICS_PRAGMA: {
unsigned NumRecords = Record.front();
// Last record which is used to keep number of valid records.
if (Record.size() - 1 != NumRecords)
return llvm::createStringError(std::errc::illegal_byte_sequence,
"invalid rvv intrinsic pragma record");
if (RISCVVecIntrinsicPragma.empty())
RISCVVecIntrinsicPragma.append(NumRecords, 0);
// There might be multiple precompiled modules imported, we need to union
// them all.
for (unsigned i = 0; i < NumRecords; ++i)
RISCVVecIntrinsicPragma[i] |= Record[i + 1];
break;
}
}
}
}
@ -9099,6 +9115,13 @@ void ASTReader::UpdateSema() {
PointersToMembersPragmaLocation);
}
SemaObj->CUDA().ForceHostDeviceDepth = ForceHostDeviceDepth;
if (!RISCVVecIntrinsicPragma.empty()) {
assert(RISCVVecIntrinsicPragma.size() == 3 &&
"Wrong number of RISCVVecIntrinsicPragma");
SemaObj->RISCV().DeclareRVVBuiltins = RISCVVecIntrinsicPragma[0];
SemaObj->RISCV().DeclareSiFiveVectorBuiltins = RISCVVecIntrinsicPragma[1];
SemaObj->RISCV().DeclareAndesVectorBuiltins = RISCVVecIntrinsicPragma[2];
}
if (PragmaAlignPackCurrentValue) {
// The bottom of the stack might have a default value. It must be adjusted

View File

@ -972,6 +972,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(PP_ASSUME_NONNULL_LOC);
RECORD(PP_UNSAFE_BUFFER_USAGE);
RECORD(VTABLES_TO_EMIT);
RECORD(RISCV_VECTOR_INTRINSICS_PRAGMA);
// SourceManager Block.
BLOCK(SOURCE_MANAGER_BLOCK);
@ -5250,6 +5251,16 @@ void ASTWriter::WriteModuleFileExtension(Sema &SemaRef,
Stream.ExitBlock();
}
void ASTWriter::WriteRISCVIntrinsicPragmas(Sema &SemaRef) {
RecordData Record;
// Need to update this when new intrinsic class is added.
Record.push_back(/*size*/ 3);
Record.push_back(SemaRef.RISCV().DeclareRVVBuiltins);
Record.push_back(SemaRef.RISCV().DeclareSiFiveVectorBuiltins);
Record.push_back(SemaRef.RISCV().DeclareAndesVectorBuiltins);
Stream.EmitRecord(RISCV_VECTOR_INTRINSICS_PRAGMA, Record);
}
//===----------------------------------------------------------------------===//
// General Serialization Routines
//===----------------------------------------------------------------------===//
@ -6148,6 +6159,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema *SemaPtr, StringRef isysroot,
WriteFPPragmaOptions(SemaPtr->CurFPFeatureOverrides());
WriteOpenCLExtensions(*SemaPtr);
WriteCUDAPragmas(*SemaPtr);
WriteRISCVIntrinsicPragmas(*SemaPtr);
}
// If we're emitting a module, write out the submodule information.

View File

@ -0,0 +1,40 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
// Test precompiled header
// RUN: %clang_cc1 -triple riscv64-linux-gnu -target-feature +v -emit-pch -o %t/test_pch.pch %t/test_pch.h
// RUN: %clang_cc1 -triple riscv64-linux-gnu -target-feature +v -include-pch %t/test_pch.pch \
// RUN: -fsyntax-only -verify %t/test_pch_src.c
//
// Test precompiled module(only available after C++20)
// RUN: %clang_cc1 -triple riscv64-linux-gnu -target-feature +v -std=c++20 -xc++-user-header -emit-header-unit -o %t/test_module1.pcm %t/test_module1.h
// RUN: %clang_cc1 -triple riscv64-linux-gnu -target-feature +v -std=c++20 -xc++-user-header -emit-header-unit -o %t/test_module2.pcm %t/test_module2.h
// RUN: %clang_cc1 -triple riscv64-linux-gnu -target-feature +v -std=c++20 -fmodule-file=%t/test_module1.pcm -fmodule-file=%t/test_module2.pcm \
// RUN: -fsyntax-only %t/test_module_src.cpp
//--- test_pch.h
// expected-no-diagnostics
#include <riscv_vector.h>
//--- test_pch_src.c
// expected-no-diagnostics
vuint64m4_t v_add(vuint64m4_t a, vuint64m4_t b, size_t vl) {
return __riscv_vadd_vv_u64m4(a, b, vl);
}
//--- test_module1.h
// expected-no-diagnostics
#include <riscv_vector.h>
//--- test_module2.h
// expected-no-diagnostics
// empty header
//--- test_module_src.cpp
// expected-no-diagnostics
import "test_module1.h";
import "test_module2.h";
vuint64m4_t v_add(vuint64m4_t a, vuint64m4_t b, size_t vl) {
return __riscv_vadd_vv_u64m4(a, b, vl);
}