452 changes: 452 additions & 0 deletions clang/lib/AST/DynamicRecursiveASTVisitor.cpp

Large diffs are not rendered by default.

23 changes: 18 additions & 5 deletions clang/lib/AST/OpenMPClause.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1023,12 +1023,17 @@ OMPPartialClause *OMPPartialClause::CreateEmpty(const ASTContext &C) {
OMPAllocateClause *
OMPAllocateClause::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc, Expr *Allocator,
SourceLocation ColonLoc, SourceLocation EndLoc,
ArrayRef<Expr *> VL) {
SourceLocation ColonLoc,
OpenMPAllocateClauseModifier AllocatorModifier,
SourceLocation AllocatorModifierLoc,
SourceLocation EndLoc, ArrayRef<Expr *> VL) {

// Allocate space for private variables and initializer expressions.
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
auto *Clause = new (Mem) OMPAllocateClause(StartLoc, LParenLoc, Allocator,
ColonLoc, EndLoc, VL.size());
auto *Clause = new (Mem) OMPAllocateClause(
StartLoc, LParenLoc, Allocator, ColonLoc, AllocatorModifier,
AllocatorModifierLoc, EndLoc, VL.size());

Clause->setVarRefs(VL);
return Clause;
}
Expand Down Expand Up @@ -2242,9 +2247,17 @@ void OMPClausePrinter::VisitOMPAllocateClause(OMPAllocateClause *Node) {
if (Node->varlist_empty())
return;
OS << "allocate";
OpenMPAllocateClauseModifier Modifier = Node->getAllocatorModifier();
if (Expr *Allocator = Node->getAllocator()) {
OS << "(";
Allocator->printPretty(OS, nullptr, Policy, 0);
if (Modifier == OMPC_ALLOCATE_allocator) {
OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), Modifier);
OS << "(";
Allocator->printPretty(OS, nullptr, Policy, 0);
OS << ")";
} else {
Allocator->printPretty(OS, nullptr, Policy, 0);
}
OS << ":";
VisitOMPClauseList(Node, ' ');
} else {
Expand Down
18 changes: 13 additions & 5 deletions clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
Expand Down Expand Up @@ -4774,7 +4775,10 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
->getTemplateName()
.getAsTemplateDecl())
if (auto *CTD = dyn_cast<ClassTemplateDecl>(templateDecl))
return CTD->getTemplatedDecl()->hasAttr<TypeNullableAttr>();
return llvm::any_of(
CTD->redecls(), [](const RedeclarableTemplateDecl *RTD) {
return RTD->getTemplatedDecl()->hasAttr<TypeNullableAttr>();
});
return ResultIfUnknown;

case Type::Builtin:
Expand Down Expand Up @@ -4841,10 +4845,14 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
// For template specializations, look only at primary template attributes.
// This is a consistent regardless of whether the instantiation is known.
if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
return CTSD->getSpecializedTemplate()
->getTemplatedDecl()
->hasAttr<TypeNullableAttr>();
return RD->hasAttr<TypeNullableAttr>();
return llvm::any_of(
CTSD->getSpecializedTemplate()->redecls(),
[](const RedeclarableTemplateDecl *RTD) {
return RTD->getTemplatedDecl()->hasAttr<TypeNullableAttr>();
});
return llvm::any_of(RD->redecls(), [](const TagDecl *RD) {
return RD->hasAttr<TypeNullableAttr>();
});
}

// Non-pointer types.
Expand Down
17 changes: 15 additions & 2 deletions clang/lib/Basic/OpenMPKinds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str,
return OMPC_NUMTASKS_unknown;
return Type;
}
case OMPC_allocate:
return llvm::StringSwitch<OpenMPAllocateClauseModifier>(Str)
#define OPENMP_ALLOCATE_MODIFIER(Name) .Case(#Name, OMPC_ALLOCATE_##Name)
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_ALLOCATE_unknown);
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:
Expand All @@ -190,7 +195,6 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str,
case OMPC_sizes:
case OMPC_permutation:
case OMPC_allocator:
case OMPC_allocate:
case OMPC_collapse:
case OMPC_private:
case OMPC_firstprivate:
Expand Down Expand Up @@ -505,6 +509,16 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
#include "clang/Basic/OpenMPKinds.def"
}
llvm_unreachable("Invalid OpenMP 'num_tasks' clause modifier");
case OMPC_allocate:
switch (Type) {
case OMPC_ALLOCATE_unknown:
return "unknown";
#define OPENMP_ALLOCATE_MODIFIER(Name) \
case OMPC_ALLOCATE_##Name: \
return #Name;
#include "clang/Basic/OpenMPKinds.def"
}
llvm_unreachable("Invalid OpenMP 'allocate' clause modifier");
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:
Expand All @@ -515,7 +529,6 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_sizes:
case OMPC_permutation:
case OMPC_allocator:
case OMPC_allocate:
case OMPC_collapse:
case OMPC_private:
case OMPC_firstprivate:
Expand Down
34 changes: 31 additions & 3 deletions clang/lib/Basic/SourceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
Expand Down Expand Up @@ -2227,6 +2228,28 @@ LLVM_DUMP_METHOD void SourceManager::dump() const {
}
}

// 123 -> "123".
// 1234 -> "1.23k".
// 123456 -> "123.46k".
// 1234567 -> "1.23M".
// 1234567890 -> "1.23G".
// 1234567890123 -> "1.23T".
static std::string humanizeNumber(uint64_t Number) {
static constexpr std::array<std::pair<uint64_t, char>, 4> Units = {
{{1'000'000'000'000UL, 'T'},
{1'000'000'000UL, 'G'},
{1'000'000UL, 'M'},
{1'000UL, 'k'}}};

for (const auto &[UnitSize, UnitSign] : Units) {
if (Number >= UnitSize) {
return llvm::formatv("{0:F}{1}", Number / static_cast<double>(UnitSize),
UnitSign);
}
}
return std::to_string(Number);
}

void SourceManager::noteSLocAddressSpaceUsage(
DiagnosticsEngine &Diag, std::optional<unsigned> MaxNotes) const {
struct Info {
Expand Down Expand Up @@ -2296,22 +2319,27 @@ void SourceManager::noteSLocAddressSpaceUsage(
int UsagePercent = static_cast<int>(100.0 * double(LocalUsage + LoadedUsage) /
MaxLoadedOffset);
Diag.Report(SourceLocation(), diag::note_total_sloc_usage)
<< LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage) << UsagePercent;
<< LocalUsage << humanizeNumber(LocalUsage) << LoadedUsage
<< humanizeNumber(LoadedUsage) << (LocalUsage + LoadedUsage)
<< humanizeNumber(LocalUsage + LoadedUsage) << UsagePercent;

// Produce notes on sloc address space usage for each file with a high usage.
uint64_t ReportedSize = 0;
for (auto &[Entry, FileInfo] :
llvm::make_range(SortedUsage.begin(), SortedEnd)) {
Diag.Report(FileInfo.Loc, diag::note_file_sloc_usage)
<< FileInfo.Inclusions << FileInfo.DirectSize
<< (FileInfo.TotalSize - FileInfo.DirectSize);
<< humanizeNumber(FileInfo.DirectSize)
<< (FileInfo.TotalSize - FileInfo.DirectSize)
<< humanizeNumber(FileInfo.TotalSize - FileInfo.DirectSize);
ReportedSize += FileInfo.TotalSize;
}

// Describe any remaining usage not reported in the per-file usage.
if (ReportedSize != CountedSize) {
Diag.Report(SourceLocation(), diag::note_file_misc_sloc_usage)
<< (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize;
<< (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize
<< humanizeNumber(CountedSize - ReportedSize);
}
}

Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Basic/Targets/Mips.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
if (ABI == "o32")
Layout = "m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64";
else if (ABI == "n32")
Layout = "m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128";
Layout = "m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128";
else if (ABI == "n64")
Layout = "m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128";
Layout = "m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128";
else
llvm_unreachable("Invalid ABI");

Expand Down
16 changes: 8 additions & 8 deletions clang/lib/Basic/Targets/SPIR.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,8 @@ class LLVM_LIBRARY_VISIBILITY SPIRVTargetInfo : public BaseSPIRVTargetInfo {

// SPIR-V IDs are represented with a single 32-bit word.
SizeType = TargetInfo::UnsignedInt;
resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
"v96:128-v192:256-v256:256-v512:512-v1024:1024-G1");
resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-"
"v256:256-v512:512-v1024:1024-n8:16:32:64-G1");
}

void getTargetDefines(const LangOptions &Opts,
Expand All @@ -334,8 +334,8 @@ class LLVM_LIBRARY_VISIBILITY SPIRV32TargetInfo : public BaseSPIRVTargetInfo {
// SPIR-V has core support for atomic ops, and Int32 is always available;
// we take the maximum because it's possible the Host supports wider types.
MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 32);
resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-"
"v96:128-v192:256-v256:256-v512:512-v1024:1024-G1");
resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-"
"v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1");
}

void getTargetDefines(const LangOptions &Opts,
Expand All @@ -358,8 +358,8 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public BaseSPIRVTargetInfo {
// SPIR-V has core support for atomic ops, and Int64 is always available;
// we take the maximum because it's possible the Host supports wider types.
MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 64);
resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
"v96:128-v192:256-v256:256-v512:512-v1024:1024-G1");
resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-"
"v256:256-v512:512-v1024:1024-n8:16:32:64-G1");
}

void getTargetDefines(const LangOptions &Opts,
Expand All @@ -384,8 +384,8 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64AMDGCNTargetInfo final
PtrDiffType = IntPtrType = TargetInfo::SignedLong;
AddrSpaceMap = &SPIRDefIsGenMap;

resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
"v96:128-v192:256-v256:256-v512:512-v1024:1024-G1-P4-A0");
resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-"
"v256:256-v512:512-v1024:1024-n32:64-S32-G1-P4-A0");

BFloat16Width = BFloat16Align = 16;
BFloat16Format = &llvm::APFloat::BFloat();
Expand Down
136 changes: 132 additions & 4 deletions clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/GlobalDecl.h"
#include "clang/Basic/SourceManager.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"

#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/Location.h"
Expand All @@ -24,9 +27,134 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &context,
clang::ASTContext &astctx,
const clang::CodeGenOptions &cgo,
DiagnosticsEngine &diags)
: astCtx(astctx), langOpts(astctx.getLangOpts()),
theModule{mlir::ModuleOp::create(mlir::UnknownLoc())},
target(astCtx.getTargetInfo()) {}
: builder(&context), astCtx(astctx), langOpts(astctx.getLangOpts()),
theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&context))},
diags(diags), target(astCtx.getTargetInfo()) {}

mlir::Location CIRGenModule::getLoc(SourceLocation cLoc) {
assert(cLoc.isValid() && "expected valid source location");
const SourceManager &sm = astCtx.getSourceManager();
PresumedLoc pLoc = sm.getPresumedLoc(cLoc);
StringRef filename = pLoc.getFilename();
return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
pLoc.getLine(), pLoc.getColumn());
}

mlir::Location CIRGenModule::getLoc(SourceRange cRange) {
assert(cRange.isValid() && "expected a valid source range");
mlir::Location begin = getLoc(cRange.getBegin());
mlir::Location end = getLoc(cRange.getEnd());
mlir::Attribute metadata;
return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());
}

void CIRGenModule::buildGlobal(clang::GlobalDecl gd) {
const auto *global = cast<ValueDecl>(gd.getDecl());

if (const auto *fd = dyn_cast<FunctionDecl>(global)) {
// Update deferred annotations with the latest declaration if the function
// was already used or defined.
if (fd->hasAttr<AnnotateAttr>())
errorNYI(fd->getSourceRange(), "deferredAnnotations");
if (!fd->doesThisDeclarationHaveABody()) {
if (!fd->doesDeclarationForceExternallyVisibleDefinition())
return;

errorNYI(fd->getSourceRange(),
"function declaration that forces code gen");
return;
}
} else {
errorNYI(global->getSourceRange(), "global variable declaration");
}

// TODO(CIR): Defer emitting some global definitions until later
buildGlobalDefinition(gd);
}

void CIRGenModule::buildGlobalFunctionDefinition(clang::GlobalDecl gd,
mlir::Operation *op) {
auto const *funcDecl = cast<FunctionDecl>(gd.getDecl());
auto funcOp = builder.create<mlir::cir::FuncOp>(
getLoc(funcDecl->getSourceRange()), funcDecl->getIdentifier()->getName());
theModule.push_back(funcOp);
}

void CIRGenModule::buildGlobalDefinition(clang::GlobalDecl gd,
mlir::Operation *op) {
const auto *decl = cast<ValueDecl>(gd.getDecl());
if (const auto *fd = dyn_cast<FunctionDecl>(decl)) {
// TODO(CIR): Skip generation of CIR for functions with available_externally
// linkage at -O0.

if (const auto *method = dyn_cast<CXXMethodDecl>(decl)) {
// Make sure to emit the definition(s) before we emit the thunks. This is
// necessary for the generation of certain thunks.
(void)method;
errorNYI(method->getSourceRange(), "member function");
return;
}

if (fd->isMultiVersion())
errorNYI(fd->getSourceRange(), "multiversion functions");
buildGlobalFunctionDefinition(gd, op);
return;
}

llvm_unreachable("Invalid argument to CIRGenModule::buildGlobalDefinition");
}

// Emit code for a single top level declaration.
void CIRGenModule::buildTopLevelDecl(Decl *decl) {}
void CIRGenModule::buildTopLevelDecl(Decl *decl) {

// Ignore dependent declarations.
if (decl->isTemplated())
return;

switch (decl->getKind()) {
default:
errorNYI(decl->getBeginLoc(), "declaration of kind",
decl->getDeclKindName());
break;

case Decl::Function: {
auto *fd = cast<FunctionDecl>(decl);
// Consteval functions shouldn't be emitted.
if (!fd->isConsteval())
buildGlobal(fd);
break;
}
}
}

DiagnosticBuilder CIRGenModule::errorNYI(llvm::StringRef feature) {
unsigned diagID = diags.getCustomDiagID(
DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
return diags.Report(diagID) << feature;
}

DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc,
llvm::StringRef feature) {
unsigned diagID = diags.getCustomDiagID(
DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
return diags.Report(loc, diagID) << feature;
}

DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc,
llvm::StringRef feature,
llvm::StringRef name) {
unsigned diagID = diags.getCustomDiagID(
DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0: %1");
return diags.Report(loc, diagID) << feature << name;
}

DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc,
llvm::StringRef feature) {
return errorNYI(loc.getBegin(), feature) << loc;
}

DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc,
llvm::StringRef feature,
llvm::StringRef name) {
return errorNYI(loc.getBegin(), feature, name) << loc;
}
34 changes: 34 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,21 @@

#include "CIRGenTypeCache.h"

#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/MLIRContext.h"
#include "llvm/ADT/StringRef.h"

namespace clang {
class ASTContext;
class CodeGenOptions;
class Decl;
class DiagnosticBuilder;
class DiagnosticsEngine;
class GlobalDecl;
class LangOptions;
class SourceLocation;
class SourceRange;
class TargetInfo;
} // namespace clang

Expand All @@ -44,6 +50,10 @@ class CIRGenModule : public CIRGenTypeCache {
~CIRGenModule() = default;

private:
// TODO(CIR) 'builder' will change to CIRGenBuilderTy once that type is
// defined
mlir::OpBuilder builder;

/// Hold Clang AST information.
clang::ASTContext &astCtx;

Expand All @@ -52,10 +62,34 @@ class CIRGenModule : public CIRGenTypeCache {
/// A "module" matches a c/cpp source file: containing a list of functions.
mlir::ModuleOp theModule;

clang::DiagnosticsEngine &diags;

const clang::TargetInfo &target;

public:
mlir::ModuleOp getModule() const { return theModule; }

/// Helpers to convert the presumed location of Clang's SourceLocation to an
/// MLIR Location.
mlir::Location getLoc(clang::SourceLocation cLoc);
mlir::Location getLoc(clang::SourceRange cRange);

void buildTopLevelDecl(clang::Decl *decl);

/// Emit code for a single global function or variable declaration. Forward
/// declarations are emitted lazily.
void buildGlobal(clang::GlobalDecl gd);

void buildGlobalDefinition(clang::GlobalDecl gd,
mlir::Operation *op = nullptr);
void buildGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op);

/// Helpers to emit "not yet implemented" error diagnostics
DiagnosticBuilder errorNYI(llvm::StringRef);
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef);
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef, llvm::StringRef);
DiagnosticBuilder errorNYI(SourceRange, llvm::StringRef);
DiagnosticBuilder errorNYI(SourceRange, llvm::StringRef, llvm::StringRef);
};
} // namespace cir

Expand Down
10 changes: 9 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@

#include "CIRGenModule.h"

#include "mlir/IR/MLIRContext.h"

#include "clang/AST/DeclGroup.h"
#include "clang/CIR/CIRGenerator.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"

using namespace cir;
using namespace clang;
Expand All @@ -31,9 +34,14 @@ void CIRGenerator::Initialize(ASTContext &astCtx) {

this->astCtx = &astCtx;

cgm = std::make_unique<CIRGenModule>(*mlirCtx, astCtx, codeGenOpts, diags);
mlirCtx = std::make_unique<mlir::MLIRContext>();
mlirCtx->loadDialect<mlir::cir::CIRDialect>();
cgm = std::make_unique<CIRGenModule>(*mlirCtx.get(), astCtx, codeGenOpts,
diags);
}

mlir::ModuleOp CIRGenerator::getModule() const { return cgm->getModule(); }

bool CIRGenerator::HandleTopLevelDecl(DeclGroupRef group) {

for (Decl *decl : group)
Expand Down
38 changes: 38 additions & 0 deletions clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//===- CIRAttrs.cpp - MLIR CIR Attributes ---------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the attributes in the CIR dialect.
//
//===----------------------------------------------------------------------===//

#include "clang/CIR/Dialect/IR/CIRDialect.h"

using namespace mlir;
using namespace mlir::cir;

//===----------------------------------------------------------------------===//
// General CIR parsing / printing
//===----------------------------------------------------------------------===//

Attribute CIRDialect::parseAttribute(DialectAsmParser &parser,
Type type) const {
// No attributes yet to parse
return Attribute{};
}

void CIRDialect::printAttribute(Attribute attr, DialectAsmPrinter &os) const {
// No attributes yet to print
}

//===----------------------------------------------------------------------===//
// CIR Dialect
//===----------------------------------------------------------------------===//

void CIRDialect::registerAttributes() {
// No attributes yet to register
}
55 changes: 54 additions & 1 deletion clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,57 @@
//
//===----------------------------------------------------------------------===//

#include <clang/CIR/Dialect/IR/CIRDialect.h>
#include "clang/CIR/Dialect/IR/CIRDialect.h"

#include "mlir/Support/LogicalResult.h"

#include "clang/CIR/Dialect/IR/CIROpsDialect.cpp.inc"

using namespace mlir;
using namespace mlir::cir;

//===----------------------------------------------------------------------===//
// CIR Dialect
//===----------------------------------------------------------------------===//

void mlir::cir::CIRDialect::initialize() {
registerTypes();
registerAttributes();
addOperations<
#define GET_OP_LIST
#include "clang/CIR/Dialect/IR/CIROps.cpp.inc"
>();
}

//===----------------------------------------------------------------------===//
// FuncOp
//===----------------------------------------------------------------------===//

void mlir::cir::FuncOp::build(OpBuilder &builder, OperationState &result,
StringRef name) {
result.addAttribute(SymbolTable::getSymbolAttrName(),
builder.getStringAttr(name));
}

ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
StringAttr nameAttr;
if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
state.attributes))
return failure();
return success();
}

void cir::FuncOp::print(OpAsmPrinter &p) {
p << ' ';
// For now the only property a function has is its name
p.printSymbolName(getSymName());
}

mlir::LogicalResult mlir::cir::FuncOp::verify() { return success(); }

//===----------------------------------------------------------------------===//
// TableGen'd op method definitions
//===----------------------------------------------------------------------===//

#define GET_OP_CLASSES
#include "clang/CIR/Dialect/IR/CIROps.cpp.inc"
37 changes: 37 additions & 0 deletions clang/lib/CIR/Dialect/IR/CIRTypes.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//===- CIRTypes.cpp - MLIR CIR Types --------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the types in the CIR dialect.
//
//===----------------------------------------------------------------------===//

#include "clang/CIR/Dialect/IR/CIRDialect.h"

using namespace mlir;
using namespace mlir::cir;

//===----------------------------------------------------------------------===//
// General CIR parsing / printing
//===----------------------------------------------------------------------===//

Type CIRDialect::parseType(DialectAsmParser &parser) const {
// No types yet to parse
return Type{};
}

void CIRDialect::printType(Type type, DialectAsmPrinter &os) const {
// No types yet to print
}

//===----------------------------------------------------------------------===//
// CIR Dialect
//===----------------------------------------------------------------------===//

void CIRDialect::registerTypes() {
// No types yet to register
}
5 changes: 5 additions & 0 deletions clang/lib/CIR/Dialect/IR/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
add_clang_library(MLIRCIR
CIRAttrs.cpp
CIRDialect.cpp
CIRTypes.cpp

LINK_LIBS PUBLIC
MLIRIR
)
41 changes: 40 additions & 1 deletion clang/lib/CIR/FrontendAction/CIRGenAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ class CIRGenConsumer : public clang::ASTConsumer {

virtual void anchor();

CIRGenAction::OutputType Action;

std::unique_ptr<raw_pwrite_stream> OutputStream;

ASTContext *Context{nullptr};
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
std::unique_ptr<CIRGenerator> Gen;

Expand All @@ -37,14 +40,37 @@ class CIRGenConsumer : public clang::ASTConsumer {
const LangOptions &LangOptions,
const FrontendOptions &FEOptions,
std::unique_ptr<raw_pwrite_stream> OS)
: OutputStream(std::move(OS)), FS(VFS),
: Action(Action), OutputStream(std::move(OS)), FS(VFS),
Gen(std::make_unique<CIRGenerator>(DiagnosticsEngine, std::move(VFS),
CodeGenOptions)) {}

void Initialize(ASTContext &Ctx) override {
assert(!Context && "initialized multiple times");
Context = &Ctx;
Gen->Initialize(Ctx);
}

bool HandleTopLevelDecl(DeclGroupRef D) override {
Gen->HandleTopLevelDecl(D);
return true;
}

void HandleTranslationUnit(ASTContext &C) override {
Gen->HandleTranslationUnit(C);
mlir::ModuleOp MlirModule = Gen->getModule();
switch (Action) {
case CIRGenAction::OutputType::EmitCIR:
if (OutputStream && MlirModule) {
mlir::OpPrintingFlags Flags;
Flags.enableDebugInfo(/*enable=*/true, /*prettyForm=*/false);
MlirModule->print(*OutputStream, Flags);
}
break;
default:
llvm_unreachable("NYI: CIRGenAction other than EmitCIR");
break;
}
}
};
} // namespace cir

Expand All @@ -55,10 +81,23 @@ CIRGenAction::CIRGenAction(OutputType Act, mlir::MLIRContext *MLIRCtx)

CIRGenAction::~CIRGenAction() { MLIRMod.release(); }

static std::unique_ptr<raw_pwrite_stream>
getOutputStream(CompilerInstance &CI, StringRef InFile,
CIRGenAction::OutputType Action) {
switch (Action) {
case CIRGenAction::OutputType::EmitCIR:
return CI.createDefaultOutputFile(false, InFile, "cir");
}
llvm_unreachable("Invalid CIRGenAction::OutputType");
}

std::unique_ptr<ASTConsumer>
CIRGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
std::unique_ptr<llvm::raw_pwrite_stream> Out = CI.takeOutputStream();

if (!Out)
Out = getOutputStream(CI, InFile, Action);

auto Result = std::make_unique<cir::CIRGenConsumer>(
Action, CI.getDiagnostics(), &CI.getVirtualFileSystem(),
CI.getHeaderSearchOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(),
Expand Down
25 changes: 14 additions & 11 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ static void addKCFIPass(const Triple &TargetTriple, const LangOptions &LangOpts,

// Ensure we lower KCFI operand bundles with -O0.
PB.registerOptimizerLastEPCallback(
[&](ModulePassManager &MPM, OptimizationLevel Level) {
[&](ModulePassManager &MPM, OptimizationLevel Level, ThinOrFullLTOPhase) {
if (Level == OptimizationLevel::O0 &&
LangOpts.Sanitize.has(SanitizerKind::KCFI))
MPM.addPass(createModuleToFunctionPassAdaptor(KCFIPass()));
Expand All @@ -693,8 +693,8 @@ static void addKCFIPass(const Triple &TargetTriple, const LangOptions &LangOpts,
static void addSanitizers(const Triple &TargetTriple,
const CodeGenOptions &CodeGenOpts,
const LangOptions &LangOpts, PassBuilder &PB) {
auto SanitizersCallback = [&](ModulePassManager &MPM,
OptimizationLevel Level) {
auto SanitizersCallback = [&](ModulePassManager &MPM, OptimizationLevel Level,
ThinOrFullLTOPhase) {
if (CodeGenOpts.hasSanitizeCoverage()) {
auto SancovOpts = getSancovOptsFromCGOpts(CodeGenOpts);
MPM.addPass(SanitizerCoveragePass(
Expand Down Expand Up @@ -778,9 +778,10 @@ static void addSanitizers(const Triple &TargetTriple,
};
if (ClSanitizeOnOptimizerEarlyEP) {
PB.registerOptimizerEarlyEPCallback(
[SanitizersCallback](ModulePassManager &MPM, OptimizationLevel Level) {
[SanitizersCallback](ModulePassManager &MPM, OptimizationLevel Level,
ThinOrFullLTOPhase Phase) {
ModulePassManager NewMPM;
SanitizersCallback(NewMPM, Level);
SanitizersCallback(NewMPM, Level, Phase);
if (!NewMPM.isEmpty()) {
// Sanitizers can abandon<GlobalsAA>.
NewMPM.addPass(RequireAnalysisPass<GlobalsAA, llvm::Module>());
Expand Down Expand Up @@ -993,7 +994,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
createModuleToFunctionPassAdaptor(ObjCARCExpandPass()));
});
PB.registerPipelineEarlySimplificationEPCallback(
[](ModulePassManager &MPM, OptimizationLevel Level) {
[](ModulePassManager &MPM, OptimizationLevel Level,
ThinOrFullLTOPhase) {
if (Level != OptimizationLevel::O0)
MPM.addPass(ObjCARCAPElimPass());
});
Expand Down Expand Up @@ -1057,11 +1059,12 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
// TODO: Consider passing the MemoryProfileOutput to the pass builder via
// the PGOOptions, and set this up there.
if (!CodeGenOpts.MemoryProfileOutput.empty()) {
PB.registerOptimizerLastEPCallback(
[](ModulePassManager &MPM, OptimizationLevel Level) {
MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass()));
MPM.addPass(ModuleMemProfilerPass());
});
PB.registerOptimizerLastEPCallback([](ModulePassManager &MPM,
OptimizationLevel Level,
ThinOrFullLTOPhase) {
MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass()));
MPM.addPass(ModuleMemProfilerPass());
});
}

if (CodeGenOpts.FatLTO) {
Expand Down
36 changes: 35 additions & 1 deletion clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18671,6 +18671,12 @@ Value *EmitAMDGPUGridSize(CodeGenFunction &CGF, unsigned Index) {
auto *GEP = CGF.Builder.CreateGEP(CGF.Int8Ty, DP, Offset);
auto *LD = CGF.Builder.CreateLoad(
Address(GEP, CGF.Int32Ty, CharUnits::fromQuantity(4)));

llvm::MDBuilder MDB(CGF.getLLVMContext());

// Known non-zero.
LD->setMetadata(llvm::LLVMContext::MD_range,
MDB.createRange(APInt(32, 1), APInt::getZero(32)));
LD->setMetadata(llvm::LLVMContext::MD_invariant_load,
llvm::MDNode::get(CGF.getLLVMContext(), {}));
return LD;
Expand Down Expand Up @@ -18767,6 +18773,15 @@ static Intrinsic::ID getDotProductIntrinsic(CGHLSLRuntime &RT, QualType QT) {
return RT.getUDotIntrinsic();
}

Intrinsic::ID getFirstBitHighIntrinsic(CGHLSLRuntime &RT, QualType QT) {
if (QT->hasSignedIntegerRepresentation()) {
return RT.getFirstBitSHighIntrinsic();
}

assert(QT->hasUnsignedIntegerRepresentation());
return RT.getFirstBitUHighIntrinsic();
}

Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
const CallExpr *E,
ReturnValueSlot ReturnValue) {
Expand Down Expand Up @@ -18855,7 +18870,26 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
/*ReturnType=*/T0->getScalarType(),
getDotProductIntrinsic(CGM.getHLSLRuntime(), VecTy0->getElementType()),
ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.dot");
} break;
}
case Builtin::BI__builtin_hlsl_dot4add_i8packed: {
Value *A = EmitScalarExpr(E->getArg(0));
Value *B = EmitScalarExpr(E->getArg(1));
Value *C = EmitScalarExpr(E->getArg(2));

Intrinsic::ID ID = CGM.getHLSLRuntime().getDot4AddI8PackedIntrinsic();
return Builder.CreateIntrinsic(
/*ReturnType=*/C->getType(), ID, ArrayRef<Value *>{A, B, C}, nullptr,
"hlsl.dot4add.i8packed");
}
case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: {

Value *X = EmitScalarExpr(E->getArg(0));

return Builder.CreateIntrinsic(
/*ReturnType=*/ConvertType(E->getType()),
getFirstBitHighIntrinsic(CGM.getHLSLRuntime(), E->getArg(0)->getType()),
ArrayRef<Value *>{X}, nullptr, "hlsl.firstbithigh");
}
case Builtin::BI__builtin_hlsl_lerp: {
Value *X = EmitScalarExpr(E->getArg(0));
Value *Y = EmitScalarExpr(E->getArg(1));
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1941,6 +1941,10 @@ bool CodeGenFunction::EmitScalarRangeCheck(llvm::Value *Value, QualType Ty,
cast<llvm::IntegerType>(Value->getType())->getBitWidth() == 1)
return false;

if (NeedsEnumCheck &&
getContext().isTypeIgnoredBySanitizer(SanitizerKind::Enum, Ty))
return false;

llvm::APInt Min, End;
if (!getRangeForType(*this, Ty, Min, End, /*StrictEnums=*/true, IsBool))
return true;
Expand Down
36 changes: 32 additions & 4 deletions clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,18 @@ static bool CanElideOverflowCheck(const ASTContext &Ctx, const BinOpInfo &Op) {
if (!Op.mayHaveIntegerOverflow())
return true;

if (Op.Ty->isSignedIntegerType() &&
Ctx.isTypeIgnoredBySanitizer(SanitizerKind::SignedIntegerOverflow,
Op.Ty)) {
return true;
}

if (Op.Ty->isUnsignedIntegerType() &&
Ctx.isTypeIgnoredBySanitizer(SanitizerKind::UnsignedIntegerOverflow,
Op.Ty)) {
return true;
}

const UnaryOperator *UO = dyn_cast<UnaryOperator>(Op.E);

if (UO && UO->getOpcode() == UO_Minus &&
Expand Down Expand Up @@ -1125,6 +1137,10 @@ void ScalarExprEmitter::EmitIntegerTruncationCheck(Value *Src, QualType SrcType,
if (!CGF.SanOpts.has(Check.second.second))
return;

// Does some SSCL ignore this type?
if (CGF.getContext().isTypeIgnoredBySanitizer(Check.second.second, DstType))
return;

llvm::Constant *StaticArgs[] = {
CGF.EmitCheckSourceLocation(Loc), CGF.EmitCheckTypeDescriptor(SrcType),
CGF.EmitCheckTypeDescriptor(DstType),
Expand Down Expand Up @@ -1235,6 +1251,15 @@ void ScalarExprEmitter::EmitIntegerSignChangeCheck(Value *Src, QualType SrcType,
// Because here sign change check is interchangeable with truncation check.
return;
}
// Does an SSCL have an entry for the DstType under its respective sanitizer
// section?
if (DstSigned && CGF.getContext().isTypeIgnoredBySanitizer(
SanitizerKind::ImplicitSignedIntegerTruncation, DstType))
return;
if (!DstSigned &&
CGF.getContext().isTypeIgnoredBySanitizer(
SanitizerKind::ImplicitUnsignedIntegerTruncation, DstType))
return;
// That's it. We can't rule out any more cases with the data we have.

CodeGenFunction::SanitizerScope SanScope(&CGF);
Expand Down Expand Up @@ -2784,10 +2809,11 @@ llvm::Value *ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
return Builder.CreateNSWAdd(InVal, Amount, Name);
[[fallthrough]];
case LangOptions::SOB_Trapping:
if (!E->canOverflow())
BinOpInfo Info = createBinOpInfoFromIncDec(
E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts()));
if (!E->canOverflow() || CanElideOverflowCheck(CGF.getContext(), Info))
return Builder.CreateNSWAdd(InVal, Amount, Name);
return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts())));
return EmitOverflowCheckedBinOp(Info);
}
llvm_unreachable("Unknown SignedOverflowBehaviorTy");
}
Expand Down Expand Up @@ -2990,7 +3016,9 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
value = EmitIncDecConsiderOverflowBehavior(E, value, isInc);
} else if (E->canOverflow() && type->isUnsignedIntegerType() &&
CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
!excludeOverflowPattern) {
!excludeOverflowPattern &&
!CGF.getContext().isTypeIgnoredBySanitizer(
SanitizerKind::UnsignedIntegerOverflow, E->getType())) {
value = EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
E, value, isInc, E->getFPFeaturesInEffect(CGF.getLangOpts())));
} else {
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/CGHLSLRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,11 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddI8Packed, dot4add_i8packed)
GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh)
GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh)

GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromBinding, handle_fromBinding)

Expand Down
28 changes: 12 additions & 16 deletions clang/lib/CodeGen/CGObjCMac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ class ObjCCommonTypesHelper {
/// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
llvm::FunctionCallee getGcReadWeakFn() {
// id objc_read_weak (id *)
llvm::Type *args[] = { ObjectPtrTy->getPointerTo() };
llvm::Type *args[] = {CGM.UnqualPtrTy};
llvm::FunctionType *FTy =
llvm::FunctionType::get(ObjectPtrTy, args, false);
return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Expand All @@ -374,7 +374,7 @@ class ObjCCommonTypesHelper {
/// GcAssignWeakFn -- LLVM objc_assign_weak function.
llvm::FunctionCallee getGcAssignWeakFn() {
// id objc_assign_weak (id, id *)
llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy};
llvm::FunctionType *FTy =
llvm::FunctionType::get(ObjectPtrTy, args, false);
return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
Expand All @@ -383,7 +383,7 @@ class ObjCCommonTypesHelper {
/// GcAssignGlobalFn -- LLVM objc_assign_global function.
llvm::FunctionCallee getGcAssignGlobalFn() {
// id objc_assign_global(id, id *)
llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy};
llvm::FunctionType *FTy =
llvm::FunctionType::get(ObjectPtrTy, args, false);
return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
Expand All @@ -392,7 +392,7 @@ class ObjCCommonTypesHelper {
/// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
llvm::FunctionCallee getGcAssignThreadLocalFn() {
// id objc_assign_threadlocal(id src, id * dest)
llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy};
llvm::FunctionType *FTy =
llvm::FunctionType::get(ObjectPtrTy, args, false);
return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
Expand All @@ -401,8 +401,7 @@ class ObjCCommonTypesHelper {
/// GcAssignIvarFn -- LLVM objc_assign_ivar function.
llvm::FunctionCallee getGcAssignIvarFn() {
// id objc_assign_ivar(id, id *, ptrdiff_t)
llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(),
CGM.PtrDiffTy };
llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy, CGM.PtrDiffTy};
llvm::FunctionType *FTy =
llvm::FunctionType::get(ObjectPtrTy, args, false);
return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
Expand All @@ -419,7 +418,7 @@ class ObjCCommonTypesHelper {
/// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
llvm::FunctionCallee getGcAssignStrongCastFn() {
// id objc_assign_strongCast(id, id *)
llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy};
llvm::FunctionType *FTy =
llvm::FunctionType::get(ObjectPtrTy, args, false);
return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
Expand Down Expand Up @@ -554,23 +553,23 @@ class ObjCTypesHelper : public ObjCCommonTypesHelper {

/// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
llvm::FunctionCallee getExceptionTryEnterFn() {
llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
llvm::Type *params[] = {CGM.UnqualPtrTy};
return CGM.CreateRuntimeFunction(
llvm::FunctionType::get(CGM.VoidTy, params, false),
"objc_exception_try_enter");
}

/// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
llvm::FunctionCallee getExceptionTryExitFn() {
llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
llvm::Type *params[] = {CGM.UnqualPtrTy};
return CGM.CreateRuntimeFunction(
llvm::FunctionType::get(CGM.VoidTy, params, false),
"objc_exception_try_exit");
}

/// ExceptionExtractFn - LLVM objc_exception_extract function.
llvm::FunctionCallee getExceptionExtractFn() {
llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
llvm::Type *params[] = {CGM.UnqualPtrTy};
return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
params, false),
"objc_exception_extract");
Expand All @@ -587,7 +586,7 @@ class ObjCTypesHelper : public ObjCCommonTypesHelper {
/// SetJmpFn - LLVM _setjmp function.
llvm::FunctionCallee getSetJmpFn() {
// This is specifically the prototype for x86.
llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() };
llvm::Type *params[] = {CGM.UnqualPtrTy};
return CGM.CreateRuntimeFunction(
llvm::FunctionType::get(CGM.Int32Ty, params, false), "_setjmp",
llvm::AttributeList::get(CGM.getLLVMContext(),
Expand Down Expand Up @@ -6051,9 +6050,7 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul
Int8PtrTy, PropertyListPtrTy);

// ImpnfABITy - LLVM for id (*)(id, SEL, ...)
llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
->getPointerTo();
ImpnfABITy = CGM.UnqualPtrTy;

// struct _class_t {
// struct _class_t *isa;
Expand Down Expand Up @@ -6469,8 +6466,7 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
llvm::GlobalValue::ExternalLinkage, nullptr,
"_objc_empty_vtable");
else
ObjCEmptyVtableVar =
llvm::ConstantPointerNull::get(ObjCTypes.ImpnfABITy->getPointerTo());
ObjCEmptyVtableVar = llvm::ConstantPointerNull::get(CGM.UnqualPtrTy);
}

// FIXME: Is this correct (that meta class size is never computed)?
Expand Down
36 changes: 29 additions & 7 deletions clang/lib/CodeGen/Targets/NVPTX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "ABIInfoImpl.h"
#include "TargetInfo.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/IntrinsicsNVPTX.h"

using namespace clang;
Expand Down Expand Up @@ -78,7 +79,13 @@ class NVPTXTargetCodeGenInfo : public TargetCodeGenInfo {
// Adds a NamedMDNode with GV, Name, and Operand as operands, and adds the
// resulting MDNode to the nvvm.annotations MDNode.
static void addNVVMMetadata(llvm::GlobalValue *GV, StringRef Name,
int Operand);
int Operand,
const SmallVectorImpl<int> &GridConstantArgs);

static void addNVVMMetadata(llvm::GlobalValue *GV, StringRef Name,
int Operand) {
addNVVMMetadata(GV, Name, Operand, SmallVector<int, 1>(0));
}

private:
static void emitBuiltinSurfTexDeviceCopy(CodeGenFunction &CGF, LValue Dst,
Expand Down Expand Up @@ -240,7 +247,8 @@ void NVPTXTargetCodeGenInfo::setTargetAttributes(
}

const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD) return;
if (!FD)
return;

llvm::Function *F = cast<llvm::Function>(GV);

Expand All @@ -263,8 +271,13 @@ void NVPTXTargetCodeGenInfo::setTargetAttributes(
// __global__ functions cannot be called from the device, we do not
// need to set the noinline attribute.
if (FD->hasAttr<CUDAGlobalAttr>()) {
SmallVector<int, 10> GCI;
for (auto IV : llvm::enumerate(FD->parameters()))
if (IV.value()->hasAttr<CUDAGridConstantAttr>())
// For some reason arg indices are 1-based in NVVM
GCI.push_back(IV.index() + 1);
// Create !{<func-ref>, metadata !"kernel", i32 1} node
addNVVMMetadata(F, "kernel", 1);
addNVVMMetadata(F, "kernel", 1, GCI);
}
if (CUDALaunchBoundsAttr *Attr = FD->getAttr<CUDALaunchBoundsAttr>())
M.handleCUDALaunchBoundsAttr(F, Attr);
Expand All @@ -276,18 +289,27 @@ void NVPTXTargetCodeGenInfo::setTargetAttributes(
}
}

void NVPTXTargetCodeGenInfo::addNVVMMetadata(llvm::GlobalValue *GV,
StringRef Name, int Operand) {
void NVPTXTargetCodeGenInfo::addNVVMMetadata(
llvm::GlobalValue *GV, StringRef Name, int Operand,
const SmallVectorImpl<int> &GridConstantArgs) {
llvm::Module *M = GV->getParent();
llvm::LLVMContext &Ctx = M->getContext();

// Get "nvvm.annotations" metadata node
llvm::NamedMDNode *MD = M->getOrInsertNamedMetadata("nvvm.annotations");

llvm::Metadata *MDVals[] = {
SmallVector<llvm::Metadata *, 5> MDVals = {
llvm::ConstantAsMetadata::get(GV), llvm::MDString::get(Ctx, Name),
llvm::ConstantAsMetadata::get(
llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx), Operand))};
if (!GridConstantArgs.empty()) {
SmallVector<llvm::Metadata *, 10> GCM;
for (int I : GridConstantArgs)
GCM.push_back(llvm::ConstantAsMetadata::get(
llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx), I)));
MDVals.append({llvm::MDString::get(Ctx, "grid_constant"),
llvm::MDNode::get(Ctx, GCM)});
}
// Append metadata to nvvm.annotations
MD->addOperand(llvm::MDNode::get(Ctx, MDVals));
}
Expand All @@ -309,7 +331,7 @@ NVPTXTargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule &CGM,
return llvm::ConstantExpr::getAddrSpaceCast(
llvm::ConstantPointerNull::get(NPT), PT);
}
}
} // namespace

void CodeGenModule::handleCUDALaunchBoundsAttr(llvm::Function *F,
const CUDALaunchBoundsAttr *Attr,
Expand Down
79 changes: 79 additions & 0 deletions clang/lib/CodeGen/Targets/SPIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class CommonSPIRTargetCodeGenInfo : public TargetCodeGenInfo {

unsigned getOpenCLKernelCallingConv() const override;
llvm::Type *getOpenCLType(CodeGenModule &CGM, const Type *T) const override;
llvm::Type *getHLSLType(CodeGenModule &CGM, const Type *Ty) const override;
llvm::Type *getSPIRVImageTypeFromHLSLResource(
const HLSLAttributedResourceType::Attributes &attributes,
llvm::Type *ElementType, llvm::LLVMContext &Ctx) const;
};
class SPIRVTargetCodeGenInfo : public CommonSPIRTargetCodeGenInfo {
public:
Expand Down Expand Up @@ -323,6 +327,81 @@ llvm::Type *CommonSPIRTargetCodeGenInfo::getOpenCLType(CodeGenModule &CGM,
return nullptr;
}

llvm::Type *CommonSPIRTargetCodeGenInfo::getHLSLType(CodeGenModule &CGM,
const Type *Ty) const {
auto *ResType = dyn_cast<HLSLAttributedResourceType>(Ty);
if (!ResType)
return nullptr;

llvm::LLVMContext &Ctx = CGM.getLLVMContext();
const HLSLAttributedResourceType::Attributes &ResAttrs = ResType->getAttrs();
switch (ResAttrs.ResourceClass) {
case llvm::dxil::ResourceClass::UAV:
case llvm::dxil::ResourceClass::SRV: {
// TypedBuffer and RawBuffer both need element type
QualType ContainedTy = ResType->getContainedType();
if (ContainedTy.isNull())
return nullptr;

assert(!ResAttrs.RawBuffer &&
"Raw buffers handles are not implemented for SPIR-V yet");
assert(!ResAttrs.IsROV &&
"Rasterizer order views not implemented for SPIR-V yet");

// convert element type
llvm::Type *ElemType = CGM.getTypes().ConvertType(ContainedTy);
return getSPIRVImageTypeFromHLSLResource(ResAttrs, ElemType, Ctx);
}
case llvm::dxil::ResourceClass::CBuffer:
llvm_unreachable("CBuffer handles are not implemented for SPIR-V yet");
break;
case llvm::dxil::ResourceClass::Sampler:
return llvm::TargetExtType::get(Ctx, "spirv.Sampler");
}
return nullptr;
}

llvm::Type *CommonSPIRTargetCodeGenInfo::getSPIRVImageTypeFromHLSLResource(
const HLSLAttributedResourceType::Attributes &attributes,
llvm::Type *ElementType, llvm::LLVMContext &Ctx) const {

if (ElementType->isVectorTy())
ElementType = ElementType->getScalarType();

assert((ElementType->isIntegerTy() || ElementType->isFloatingPointTy()) &&
"The element type for a SPIR-V resource must be a scalar integer or "
"floating point type.");

// These parameters correspond to the operands to the OpTypeImage SPIR-V
// instruction. See
// https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpTypeImage.
SmallVector<unsigned, 6> IntParams(6, 0);

// Dim
// For now we assume everything is a buffer.
IntParams[0] = 5;

// Depth
// HLSL does not indicate if it is a depth texture or not, so we use unknown.
IntParams[1] = 2;

// Arrayed
IntParams[2] = 0;

// MS
IntParams[3] = 0;

// Sampled
IntParams[4] =
attributes.ResourceClass == llvm::dxil::ResourceClass::UAV ? 2 : 1;

// Image format.
// Setting to unknown for now.
IntParams[5] = 0;

return llvm::TargetExtType::get(Ctx, "spirv.Image", {ElementType}, IntParams);
}

std::unique_ptr<TargetCodeGenInfo>
CodeGen::createCommonSPIRTargetCodeGenInfo(CodeGenModule &CGM) {
return std::make_unique<CommonSPIRTargetCodeGenInfo>(CGM.getTypes());
Expand Down
23 changes: 11 additions & 12 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,9 @@ static std::optional<llvm::Triple>
getHIPOffloadTargetTriple(const Driver &D, const ArgList &Args) {
if (!Args.hasArg(options::OPT_offload_EQ)) {
auto OffloadArchs = Args.getAllArgValues(options::OPT_offload_arch_EQ);
if (llvm::is_contained(OffloadArchs, "amdgcnspirv")) {
if (OffloadArchs.size() == 1)
return llvm::Triple("spirv64-amd-amdhsa");
// Mixing specific & SPIR-V compilation is not supported for now.
D.Diag(diag::err_drv_only_one_offload_target_supported);
return std::nullopt;
}
if (llvm::is_contained(OffloadArchs, "amdgcnspirv") &&
OffloadArchs.size() == 1)
return llvm::Triple("spirv64-amd-amdhsa");
return llvm::Triple("amdgcn-amd-amdhsa"); // Default HIP triple.
}
auto TT = getOffloadTargetTriple(D, Args);
Expand Down Expand Up @@ -458,6 +454,7 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
// some build systems. We don't try to be complete here because we don't
// care to encourage this usage model.
if (A->getOption().matches(options::OPT_Wp_COMMA) &&
A->getNumValues() > 0 &&
(A->getValue(0) == StringRef("-MD") ||
A->getValue(0) == StringRef("-MMD"))) {
// Rewrite to -MD/-MMD along with -MF.
Expand Down Expand Up @@ -3477,9 +3474,11 @@ class OffloadingActionBuilder final {
llvm::StringMap<bool> Features;
// getHIPOffloadTargetTriple() is known to return valid value as it has
// been called successfully in the CreateOffloadingDeviceToolChains().
auto ArchStr = parseTargetID(
*getHIPOffloadTargetTriple(C.getDriver(), C.getInputArgs()), IdStr,
&Features);
auto T =
(IdStr == "amdgcnspirv")
? llvm::Triple("spirv64-amd-amdhsa")
: *getHIPOffloadTargetTriple(C.getDriver(), C.getInputArgs());
auto ArchStr = parseTargetID(T, IdStr, &Features);
if (!ArchStr) {
C.getDriver().Diag(clang::diag::err_drv_bad_target_id) << IdStr;
C.setContainsError();
Expand Down Expand Up @@ -4035,7 +4034,7 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args,
if (C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment() &&
LTOMode != LTOK_None &&
!Args.getLastArgValue(options::OPT_fuse_ld_EQ)
.equals_insensitive("lld"))
.starts_with_insensitive("lld"))
Diag(clang::diag::err_drv_lto_without_lld);

// If -dumpdir is not specified, give a default prefix derived from the link
Expand Down Expand Up @@ -5755,7 +5754,7 @@ InputInfoList Driver::BuildJobsForActionNoCache(
// We only have to generate a prefix for the host if this is not a top-level
// action.
std::string OffloadingPrefix = Action::GetOffloadingFileNamePrefix(
A->getOffloadingDeviceKind(), TC->getTriple().normalize(),
A->getOffloadingDeviceKind(), EffectiveTriple.normalize(),
/*CreatePrefixForHost=*/isa<OffloadPackagerJobAction>(A) ||
!(A->getOffloadingHostActiveKinds() == Action::OFK_None ||
AtTopLevel));
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Driver/ToolChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1099,6 +1099,12 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
}
case llvm::Triple::aarch64_32:
return getTripleString();
case llvm::Triple::amdgcn: {
llvm::Triple Triple = getTriple();
if (Args.getLastArgValue(options::OPT_mcpu_EQ) == "amdgcnspirv")
Triple.setArch(llvm::Triple::ArchType::spirv64);
return Triple.getTriple();
}
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5358,6 +5358,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
} else if (JA.getType() == types::TY_RewrittenLegacyObjC) {
CmdArgs.push_back("-rewrite-objc");
rewriteKind = RK_Fragile;
} else if (JA.getType() == types::TY_CIR) {
CmdArgs.push_back("-emit-cir");
} else {
assert(JA.getType() == types::TY_PP_Asm && "Unexpected output type!");
}
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1293,6 +1293,7 @@ void tools::addFortranRuntimeLibs(const ToolChain &TC, const ArgList &Args,
}
CmdArgs.push_back("-lFortranRuntime");
CmdArgs.push_back("-lFortranDecimal");
addArchSpecificRPath(TC, Args, CmdArgs);
}

// libomp needs libatomic for atomic operations if using libgcc
Expand Down
23 changes: 12 additions & 11 deletions clang/lib/Driver/ToolChains/HIPAMD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (JA.getType() == types::TY_LLVM_BC)
return constructLlvmLinkCommand(C, JA, Inputs, Output, Args);

if (getToolChain().getTriple().isSPIRV())
if (getToolChain().getEffectiveTriple().isSPIRV())
return constructLinkAndEmitSpirvCommand(C, JA, Inputs, Output, Args);

return constructLldCommand(C, JA, Inputs, Output, Args);
Expand Down Expand Up @@ -264,12 +264,14 @@ void HIPAMDToolChain::addClangTargetOptions(
CC1Args.push_back("-fapply-global-visibility-to-externs");
}

// For SPIR-V we embed the command-line into the generated binary, in order to
// retrieve it at JIT time and be able to do target specific compilation with
// options that match the user-supplied ones.
if (getTriple().isSPIRV() &&
!DriverArgs.hasArg(options::OPT_fembed_bitcode_marker))
CC1Args.push_back("-fembed-bitcode=marker");
if (getEffectiveTriple().isSPIRV()) {
// For SPIR-V we embed the command-line into the generated binary, in order
// to retrieve it at JIT time and be able to do target specific compilation
// with options that match the user-supplied ones.
if (!DriverArgs.hasArg(options::OPT_fembed_bitcode_marker))
CC1Args.push_back("-fembed-bitcode=marker");
return; // No DeviceLibs for SPIR-V.
}

for (auto BCFile : getDeviceLibs(DriverArgs)) {
CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"
Expand Down Expand Up @@ -361,8 +363,7 @@ llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
HIPAMDToolChain::getDeviceLibs(const llvm::opt::ArgList &DriverArgs) const {
llvm::SmallVector<BitCodeLibraryInfo, 12> BCLibs;
if (DriverArgs.hasArg(options::OPT_nogpulib) ||
(getTriple().getArch() == llvm::Triple::spirv64 &&
getTriple().getVendor() == llvm::Triple::AMD))
getGPUArch(DriverArgs) == "amdgcnspirv")
return {};
ArgStringList LibraryPaths;

Expand Down Expand Up @@ -437,8 +438,8 @@ HIPAMDToolChain::getDeviceLibs(const llvm::opt::ArgList &DriverArgs) const {
void HIPAMDToolChain::checkTargetID(
const llvm::opt::ArgList &DriverArgs) const {
auto PTID = getParsedTargetID(DriverArgs);
if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
if (PTID.OptionalTargetID && !PTID.OptionalGPUArch &&
PTID.OptionalTargetID != "amdgcnspirv")
getDriver().Diag(clang::diag::err_drv_bad_target_id)
<< *PTID.OptionalTargetID;
}
}
10 changes: 7 additions & 3 deletions clang/lib/Driver/ToolChains/HIPUtility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,10 +304,14 @@ void HIP::constructHIPFatbinCommand(Compilation &C, const JobAction &JA,
for (const auto &II : Inputs) {
const auto *A = II.getAction();
auto ArchStr = llvm::StringRef(A->getOffloadingArch());
BundlerTargetArg +=
"," + OffloadKind + "-" + normalizeForBundler(TT, !ArchStr.empty());
BundlerTargetArg += ',' + OffloadKind + '-';
if (ArchStr == "amdgcnspirv")
BundlerTargetArg +=
normalizeForBundler(llvm::Triple("spirv64-amd-amdhsa"), true);
else
BundlerTargetArg += normalizeForBundler(TT, !ArchStr.empty());
if (!ArchStr.empty())
BundlerTargetArg += "-" + ArchStr.str();
BundlerTargetArg += '-' + ArchStr.str();
}
BundlerArgs.push_back(Args.MakeArgString(BundlerTargetArg));

Expand Down
14 changes: 14 additions & 0 deletions clang/lib/Driver/ToolChains/PS4CPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,10 @@ void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-z");
CmdArgs.push_back("start-stop-visibility=hidden");

// DT_DEBUG is not supported on PlayStation.
CmdArgs.push_back("-z");
CmdArgs.push_back("rodynamic");

CmdArgs.push_back("-z");
CmdArgs.push_back("common-page-size=0x4000");

Expand All @@ -293,6 +297,16 @@ void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
"dead-reloc-in-nonalloc=.debug_ranges=0xfffffffffffffffe");
CmdArgs.push_back("-z");
CmdArgs.push_back("dead-reloc-in-nonalloc=.debug_loc=0xfffffffffffffffe");

// The PlayStation loader expects linked objects to be laid out in a
// particular way. This is achieved by linker scripts that are supplied
// with the SDK. The scripts are inside <sdkroot>/target/lib, which is
// added as a search path elsewhere.
// "PRX" has long stood for "PlayStation Relocatable eXecutable".
CmdArgs.push_back("--default-script");
CmdArgs.push_back(Static ? "static.script"
: Shared ? "prx.script"
: "main.script");
}

if (Static)
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/XRayArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
case llvm::Triple::systemz:
break;
default:
D.Diag(diag::err_drv_unsupported_opt_for_target)
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1259,7 +1259,7 @@ class AnnotatingParser {

bool parseConditional() {
while (CurrentToken) {
if (CurrentToken->is(tok::colon)) {
if (CurrentToken->is(tok::colon) && CurrentToken->is(TT_Unknown)) {
CurrentToken->setType(TT_ConditionalExpr);
next();
return true;
Expand Down
8 changes: 6 additions & 2 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2091,7 +2091,8 @@ void UnwrappedLineParser::parseStructuralElement(
case tok::kw_switch:
if (Style.Language == FormatStyle::LK_Java)
parseSwitch(/*IsExpr=*/true);
nextToken();
else
nextToken();
break;
case tok::kw_case:
// Proto: there are no switch/case statements.
Expand Down Expand Up @@ -2656,7 +2657,10 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) {
nextToken();
break;
case tok::kw_switch:
parseSwitch(/*IsExpr=*/true);
if (Style.Language == FormatStyle::LK_Java)
parseSwitch(/*IsExpr=*/true);
else
nextToken();
break;
case tok::kw_requires: {
auto RequiresToken = FormatTok;
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Headers/emmintrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -4610,7 +4610,8 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_unpacklo_epi64(__m128i __a,
/// A 128-bit integer vector operand. The lower 64 bits are moved to the
/// destination.
/// \returns A 64-bit integer containing the lower 64 bits of the parameter.
static __inline__ __m64 __DEFAULT_FN_ATTRS _mm_movepi64_pi64(__m128i __a) {
static __inline__ __m64 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_movepi64_pi64(__m128i __a) {
return (__m64)__a[0];
}

Expand Down Expand Up @@ -4641,7 +4642,8 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_movpi64_epi64(__m64 __a) {
/// destination.
/// \returns A 128-bit integer vector. The lower 64 bits contain the value from
/// the operand. The upper 64 bits are assigned zeros.
static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_move_epi64(__m128i __a) {
static __inline__ __m128i __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_move_epi64(__m128i __a) {
return __builtin_shufflevector((__v2di)__a, _mm_setzero_si128(), 0, 2);
}

Expand Down
82 changes: 82 additions & 0 deletions clang/lib/Headers/hlsl/hlsl_intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,16 @@ uint64_t dot(uint64_t3, uint64_t3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_dot)
uint64_t dot(uint64_t4, uint64_t4);

//===----------------------------------------------------------------------===//
// dot4add builtins
//===----------------------------------------------------------------------===//

/// \fn int dot4add_i8packed(uint A, uint B, int C)

_HLSL_AVAILABILITY(shadermodel, 6.4)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_dot4add_i8packed)
int dot4add_i8packed(unsigned int, unsigned int, int);

//===----------------------------------------------------------------------===//
// exp builtins
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -998,6 +1008,78 @@ float3 exp2(float3);
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp2)
float4 exp2(float4);

//===----------------------------------------------------------------------===//
// firstbithigh builtins
//===----------------------------------------------------------------------===//

/// \fn T firstbithigh(T Val)
/// \brief Returns the location of the first set bit starting from the highest
/// order bit and working downward, per component.
/// \param Val the input value.

#ifdef __HLSL_ENABLE_16_BIT
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint firstbithigh(int16_t);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint2 firstbithigh(int16_t2);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint3 firstbithigh(int16_t3);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint4 firstbithigh(int16_t4);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint firstbithigh(uint16_t);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint2 firstbithigh(uint16_t2);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint3 firstbithigh(uint16_t3);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint4 firstbithigh(uint16_t4);
#endif

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint firstbithigh(int);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint2 firstbithigh(int2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint3 firstbithigh(int3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint4 firstbithigh(int4);

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint firstbithigh(uint);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint2 firstbithigh(uint2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint3 firstbithigh(uint3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint4 firstbithigh(uint4);

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint firstbithigh(int64_t);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint2 firstbithigh(int64_t2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint3 firstbithigh(int64_t3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint4 firstbithigh(int64_t4);

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint firstbithigh(uint64_t);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint2 firstbithigh(uint64_t2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint3 firstbithigh(uint64_t3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
uint4 firstbithigh(uint64_t4);

//===----------------------------------------------------------------------===//
// floor builtins
//===----------------------------------------------------------------------===//
Expand Down
83 changes: 34 additions & 49 deletions clang/lib/Lex/PPMacroExpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,84 +323,69 @@ void Preprocessor::dumpMacroInfo(const IdentifierInfo *II) {
}
}

/// RegisterBuiltinMacro - Register the specified identifier in the identifier
/// table and mark it as a builtin macro to be expanded.
static IdentifierInfo *RegisterBuiltinMacro(Preprocessor &PP, const char *Name){
// Get the identifier.
IdentifierInfo *Id = PP.getIdentifierInfo(Name);

// Mark it as being a macro that is builtin.
MacroInfo *MI = PP.AllocateMacroInfo(SourceLocation());
MI->setIsBuiltinMacro();
PP.appendDefMacroDirective(Id, MI);
return Id;
}

/// RegisterBuiltinMacros - Register builtin macros, such as __LINE__ with the
/// identifier table.
void Preprocessor::RegisterBuiltinMacros() {
Ident__LINE__ = RegisterBuiltinMacro(*this, "__LINE__");
Ident__FILE__ = RegisterBuiltinMacro(*this, "__FILE__");
Ident__DATE__ = RegisterBuiltinMacro(*this, "__DATE__");
Ident__TIME__ = RegisterBuiltinMacro(*this, "__TIME__");
Ident__COUNTER__ = RegisterBuiltinMacro(*this, "__COUNTER__");
Ident_Pragma = RegisterBuiltinMacro(*this, "_Pragma");
Ident__FLT_EVAL_METHOD__ = RegisterBuiltinMacro(*this, "__FLT_EVAL_METHOD__");
Ident__LINE__ = RegisterBuiltinMacro("__LINE__");
Ident__FILE__ = RegisterBuiltinMacro("__FILE__");
Ident__DATE__ = RegisterBuiltinMacro("__DATE__");
Ident__TIME__ = RegisterBuiltinMacro("__TIME__");
Ident__COUNTER__ = RegisterBuiltinMacro("__COUNTER__");
Ident_Pragma = RegisterBuiltinMacro("_Pragma");
Ident__FLT_EVAL_METHOD__ = RegisterBuiltinMacro("__FLT_EVAL_METHOD__");

// C++ Standing Document Extensions.
if (getLangOpts().CPlusPlus)
Ident__has_cpp_attribute =
RegisterBuiltinMacro(*this, "__has_cpp_attribute");
Ident__has_cpp_attribute = RegisterBuiltinMacro("__has_cpp_attribute");
else
Ident__has_cpp_attribute = nullptr;

// GCC Extensions.
Ident__BASE_FILE__ = RegisterBuiltinMacro(*this, "__BASE_FILE__");
Ident__INCLUDE_LEVEL__ = RegisterBuiltinMacro(*this, "__INCLUDE_LEVEL__");
Ident__TIMESTAMP__ = RegisterBuiltinMacro(*this, "__TIMESTAMP__");
Ident__BASE_FILE__ = RegisterBuiltinMacro("__BASE_FILE__");
Ident__INCLUDE_LEVEL__ = RegisterBuiltinMacro("__INCLUDE_LEVEL__");
Ident__TIMESTAMP__ = RegisterBuiltinMacro("__TIMESTAMP__");

// Microsoft Extensions.
if (getLangOpts().MicrosoftExt) {
Ident__identifier = RegisterBuiltinMacro(*this, "__identifier");
Ident__pragma = RegisterBuiltinMacro(*this, "__pragma");
Ident__identifier = RegisterBuiltinMacro("__identifier");
Ident__pragma = RegisterBuiltinMacro("__pragma");
} else {
Ident__identifier = nullptr;
Ident__pragma = nullptr;
}

// Clang Extensions.
Ident__FILE_NAME__ = RegisterBuiltinMacro(*this, "__FILE_NAME__");
Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature");
Ident__has_extension = RegisterBuiltinMacro(*this, "__has_extension");
Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin");
Ident__FILE_NAME__ = RegisterBuiltinMacro("__FILE_NAME__");
Ident__has_feature = RegisterBuiltinMacro("__has_feature");
Ident__has_extension = RegisterBuiltinMacro("__has_extension");
Ident__has_builtin = RegisterBuiltinMacro("__has_builtin");
Ident__has_constexpr_builtin =
RegisterBuiltinMacro(*this, "__has_constexpr_builtin");
Ident__has_attribute = RegisterBuiltinMacro(*this, "__has_attribute");
RegisterBuiltinMacro("__has_constexpr_builtin");
Ident__has_attribute = RegisterBuiltinMacro("__has_attribute");
if (!getLangOpts().CPlusPlus)
Ident__has_c_attribute = RegisterBuiltinMacro(*this, "__has_c_attribute");
Ident__has_c_attribute = RegisterBuiltinMacro("__has_c_attribute");
else
Ident__has_c_attribute = nullptr;

Ident__has_declspec = RegisterBuiltinMacro(*this, "__has_declspec_attribute");
Ident__has_embed = RegisterBuiltinMacro(*this, "__has_embed");
Ident__has_include = RegisterBuiltinMacro(*this, "__has_include");
Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next");
Ident__has_warning = RegisterBuiltinMacro(*this, "__has_warning");
Ident__is_identifier = RegisterBuiltinMacro(*this, "__is_identifier");
Ident__is_target_arch = RegisterBuiltinMacro(*this, "__is_target_arch");
Ident__is_target_vendor = RegisterBuiltinMacro(*this, "__is_target_vendor");
Ident__is_target_os = RegisterBuiltinMacro(*this, "__is_target_os");
Ident__has_declspec = RegisterBuiltinMacro("__has_declspec_attribute");
Ident__has_embed = RegisterBuiltinMacro("__has_embed");
Ident__has_include = RegisterBuiltinMacro("__has_include");
Ident__has_include_next = RegisterBuiltinMacro("__has_include_next");
Ident__has_warning = RegisterBuiltinMacro("__has_warning");
Ident__is_identifier = RegisterBuiltinMacro("__is_identifier");
Ident__is_target_arch = RegisterBuiltinMacro("__is_target_arch");
Ident__is_target_vendor = RegisterBuiltinMacro("__is_target_vendor");
Ident__is_target_os = RegisterBuiltinMacro("__is_target_os");
Ident__is_target_environment =
RegisterBuiltinMacro(*this, "__is_target_environment");
Ident__is_target_variant_os =
RegisterBuiltinMacro(*this, "__is_target_variant_os");
RegisterBuiltinMacro("__is_target_environment");
Ident__is_target_variant_os = RegisterBuiltinMacro("__is_target_variant_os");
Ident__is_target_variant_environment =
RegisterBuiltinMacro(*this, "__is_target_variant_environment");
RegisterBuiltinMacro("__is_target_variant_environment");

// Modules.
Ident__building_module = RegisterBuiltinMacro(*this, "__building_module");
Ident__building_module = RegisterBuiltinMacro("__building_module");
if (!getLangOpts().CurrentModule.empty())
Ident__MODULE__ = RegisterBuiltinMacro(*this, "__MODULE__");
Ident__MODULE__ = RegisterBuiltinMacro("__MODULE__");
else
Ident__MODULE__ = nullptr;
}
Expand Down
28 changes: 26 additions & 2 deletions clang/lib/Parse/ParseOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4800,7 +4800,23 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
// iterator(iterators-definition)
ExprResult Tail;
if (Kind == OMPC_allocate) {
Tail = ParseAssignmentExpression();
auto Modifier = static_cast<OpenMPAllocateClauseModifier>(
getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));
if (Modifier == OMPC_ALLOCATE_allocator) {
Data.AllocClauseModifier = Modifier;
ConsumeToken();
BalancedDelimiterTracker AllocateT(*this, tok::l_paren,
tok::annot_pragma_openmp_end);
if (Tok.is(tok::l_paren)) {
AllocateT.consumeOpen();
Tail = ParseAssignmentExpression();
AllocateT.consumeClose();
} else {
Diag(Tok, diag::err_expected) << tok::l_paren;
}
} else {
Tail = ParseAssignmentExpression();
}
} else {
HasIterator = true;
EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
Expand All @@ -4817,6 +4833,12 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
} else {
// Colon not found, parse only list of variables.
TPA.Revert();
if (Kind == OMPC_allocate &&
Data.AllocClauseModifier == OMPC_ALLOCATE_allocator) {
SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
Diag(Tok, diag::err_modifier_expected_colon) << "allocator";
}
}
} else {
// Parsing was unsuccessfull, revert and skip to the end of clause or
Expand Down Expand Up @@ -4886,7 +4908,6 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
// Parse ')' for linear clause with modifier.
if (NeedRParenForLinear)
LinearT.consumeClose();

// Parse ':' linear modifiers (val, uval, ref or step(step-size))
// or parse ':' alignment.
const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
Expand Down Expand Up @@ -5018,6 +5039,9 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
/// 'has_device_addr' '(' list ')'
/// allocate-clause:
/// 'allocate' '(' [ allocator ':' ] list ')'
/// As of OpenMP 5.1 there's also
/// 'allocate' '(' allocate-modifier: list ')'
/// where allocate-modifier is: 'allocator' '(' allocator ')'
/// nontemporal-clause:
/// 'nontemporal' '(' list ')'
/// inclusive-clause:
Expand Down
13 changes: 6 additions & 7 deletions clang/lib/Sema/CheckExprLifetime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,14 +226,14 @@ using LocalVisitor = llvm::function_ref<bool(IndirectLocalPath &Path, Local L,
ReferenceKind RK)>;
} // namespace

static bool isVarOnPath(IndirectLocalPath &Path, VarDecl *VD) {
static bool isVarOnPath(const IndirectLocalPath &Path, VarDecl *VD) {
for (auto E : Path)
if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD)
return true;
return false;
}

static bool pathContainsInit(IndirectLocalPath &Path) {
static bool pathContainsInit(const IndirectLocalPath &Path) {
return llvm::any_of(Path, [=](IndirectLocalPathEntry E) {
return E.Kind == IndirectLocalPathEntry::DefaultInit ||
E.Kind == IndirectLocalPathEntry::VarInit;
Expand Down Expand Up @@ -1076,7 +1076,7 @@ static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,
return E->getSourceRange();
}

static bool pathOnlyHandlesGslPointer(IndirectLocalPath &Path) {
static bool pathOnlyHandlesGslPointer(const IndirectLocalPath &Path) {
for (const auto &It : llvm::reverse(Path)) {
switch (It.Kind) {
case IndirectLocalPathEntry::VarInit:
Expand Down Expand Up @@ -1124,24 +1124,23 @@ static void checkExprLifetimeImpl(Sema &SemaRef,

// FIXME: consider moving the TemporaryVisitor and visitLocalsRetained*
// functions to a dedicated class.
auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L,
auto TemporaryVisitor = [&](const IndirectLocalPath &Path, Local L,
ReferenceKind RK) -> bool {
SourceRange DiagRange = nextPathEntryRange(Path, 0, L);
SourceLocation DiagLoc = DiagRange.getBegin();

auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);

bool IsGslPtrValueFromGslTempOwner = false;
bool IsLocalGslOwner = false;
if (pathOnlyHandlesGslPointer(Path)) {
if (isa<DeclRefExpr>(L)) {
// We do not want to follow the references when returning a pointer
// originating from a local owner to avoid the following false positive:
// int &p = *localUniquePtr;
// someContainer.add(std::move(localUniquePtr));
// return p;
IsLocalGslOwner = isRecordWithAttr<OwnerAttr>(L->getType());
if (pathContainsInit(Path) || !IsLocalGslOwner)
if (pathContainsInit(Path) ||
!isRecordWithAttr<OwnerAttr>(L->getType()))
return false;
} else {
IsGslPtrValueFromGslTempOwner =
Expand Down
15 changes: 2 additions & 13 deletions clang/lib/Sema/HLSLExternalSemaSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AttrKinds.h"
#include "clang/Basic/HLSLRuntime.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Sema.h"
Expand Down Expand Up @@ -164,16 +162,7 @@ struct BuiltinTypeDeclBuilder {
VD, false, NameInfo, Ty, VK_PRValue);
}

static Expr *emitResourceClassExpr(ASTContext &AST, ResourceClass RC) {
return IntegerLiteral::Create(
AST,
llvm::APInt(AST.getIntWidth(AST.UnsignedCharTy),
static_cast<uint8_t>(RC)),
AST.UnsignedCharTy, SourceLocation());
}

BuiltinTypeDeclBuilder &addDefaultHandleConstructor(Sema &S,
ResourceClass RC) {
BuiltinTypeDeclBuilder &addDefaultHandleConstructor(Sema &S) {
if (Record->isCompleteDefinition())
return *this;
ASTContext &AST = Record->getASTContext();
Expand Down Expand Up @@ -480,7 +469,7 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
bool IsROV, bool RawBuffer) {
return BuiltinTypeDeclBuilder(Decl)
.addHandleMember(S, RC, RK, IsROV, RawBuffer)
.addDefaultHandleConstructor(S, RC);
.addDefaultHandleConstructor(S);
}

void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
Expand Down
25 changes: 16 additions & 9 deletions clang/lib/Sema/SemaAPINotes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "clang/APINotes/APINotesReader.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Lexer.h"
Expand Down Expand Up @@ -415,6 +416,13 @@ static void ProcessAPINotes(Sema &S, ParmVarDecl *D,
return new (S.Context) NoEscapeAttr(S.Context, getPlaceholderAttrInfo());
});

if (auto Lifetimebound = Info.isLifetimebound())
handleAPINotedAttribute<LifetimeBoundAttr>(
S, D, *Lifetimebound, Metadata, [&] {
return new (S.Context)
LifetimeBoundAttr(S.Context, getPlaceholderAttrInfo());
});

// Retain count convention
handleAPINotedRetainCountConvention(S, D, Metadata,
Info.getRetainCountConvention());
Expand Down Expand Up @@ -860,13 +868,12 @@ void Sema::ProcessAPINotes(Decl *D) {
if (!D)
return;

auto *DC = D->getDeclContext();
// Globals.
if (D->getDeclContext()->isFileContext() ||
D->getDeclContext()->isNamespace() ||
D->getDeclContext()->isExternCContext() ||
D->getDeclContext()->isExternCXXContext()) {
if (DC->isFileContext() || DC->isNamespace() || DC->isExternCContext() ||
DC->isExternCXXContext()) {
std::optional<api_notes::Context> APINotesContext =
UnwindNamespaceContext(D->getDeclContext(), APINotes);
UnwindNamespaceContext(DC, APINotes);
// Global variables.
if (auto VD = dyn_cast<VarDecl>(D)) {
for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
Expand Down Expand Up @@ -967,8 +974,8 @@ void Sema::ProcessAPINotes(Decl *D) {
}

// Enumerators.
if (D->getDeclContext()->getRedeclContext()->isFileContext() ||
D->getDeclContext()->getRedeclContext()->isExternCContext()) {
if (DC->getRedeclContext()->isFileContext() ||
DC->getRedeclContext()->isExternCContext()) {
if (auto EnumConstant = dyn_cast<EnumConstantDecl>(D)) {
for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
auto Info = Reader->lookupEnumConstant(EnumConstant->getName());
Expand All @@ -979,7 +986,7 @@ void Sema::ProcessAPINotes(Decl *D) {
}
}

if (auto ObjCContainer = dyn_cast<ObjCContainerDecl>(D->getDeclContext())) {
if (auto ObjCContainer = dyn_cast<ObjCContainerDecl>(DC)) {
// Location function that looks up an Objective-C context.
auto GetContext = [&](api_notes::APINotesReader *Reader)
-> std::optional<api_notes::ContextID> {
Expand Down Expand Up @@ -1063,7 +1070,7 @@ void Sema::ProcessAPINotes(Decl *D) {
}
}

if (auto TagContext = dyn_cast<TagDecl>(D->getDeclContext())) {
if (auto TagContext = dyn_cast<TagDecl>(DC)) {
if (auto CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
if (!isa<CXXConstructorDecl>(CXXMethod) &&
!isa<CXXDestructorDecl>(CXXMethod) &&
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2212,7 +2212,9 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
if (CheckBuiltinTargetInSupported(
*this, TheCall,
{llvm::Triple::x86, llvm::Triple::x86_64, llvm::Triple::arm,
llvm::Triple::thumb, llvm::Triple::aarch64, llvm::Triple::amdgcn}))
llvm::Triple::thumb, llvm::Triple::aarch64, llvm::Triple::amdgcn,
llvm::Triple::ppc, llvm::Triple::ppc64, llvm::Triple::ppcle,
llvm::Triple::ppc64le}))
return ExprError();
break;

Expand Down
29 changes: 17 additions & 12 deletions clang/lib/Sema/SemaConcept.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ static bool CheckConstraintSatisfaction(

ArrayRef<TemplateArgument> TemplateArgs =
TemplateArgsLists.getNumSubstitutedLevels() > 0
? TemplateArgsLists.getInnermost()
? TemplateArgsLists.getOutermost()
: ArrayRef<TemplateArgument>{};
Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
Sema::InstantiatingTemplate::ConstraintsCheck{},
Expand Down Expand Up @@ -834,6 +834,7 @@ Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(),
/*Final=*/false, /*Innermost=*/std::nullopt,
/*RelativeToPrimary=*/true,
/*Pattern=*/nullptr,
/*ForConstraintInstantiation=*/true);
if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
return std::nullopt;
Expand Down Expand Up @@ -909,13 +910,15 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
// Figure out the to-translation-unit depth for this function declaration for
// the purpose of seeing if they differ by constraints. This isn't the same as
// getTemplateDepth, because it includes already instantiated parents.
static unsigned CalculateTemplateDepthForConstraints(Sema &S,
const NamedDecl *ND) {
static unsigned
CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND,
bool SkipForSpecialization = false) {
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
ND, ND->getLexicalDeclContext(), /*Final=*/false,
/*Innermost=*/std::nullopt,
/*RelativeToPrimary=*/true,
/*ForConstraintInstantiation=*/true);
/*Pattern=*/nullptr,
/*ForConstraintInstantiation=*/true, SkipForSpecialization);
return MLTAL.getNumLevels();
}

Expand Down Expand Up @@ -954,7 +957,8 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false,
/*Innermost=*/std::nullopt,
/*RelativeToPrimary=*/true,
/*ForConstraintInstantiation=*/true);
/*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,
/*SkipForSpecialization*/ false);

if (MLTAL.getNumSubstitutedLevels() == 0)
return ConstrExpr;
Expand All @@ -975,7 +979,7 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
std::optional<LocalInstantiationScope> ScopeForParameters;
if (const NamedDecl *ND = DeclInfo.getDecl();
ND && ND->isFunctionOrFunctionTemplate()) {
ScopeForParameters.emplace(S);
ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true);
const FunctionDecl *FD = ND->getAsFunction();
for (auto *PVD : FD->parameters()) {
if (!PVD->isParameterPack()) {
Expand Down Expand Up @@ -1064,16 +1068,16 @@ bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
assert(FD->getFriendObjectKind() && "Must be a friend!");

FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate();
// The logic for non-templates is handled in ASTContext::isSameEntity, so we
// don't have to bother checking 'DependsOnEnclosingTemplate' for a
// non-function-template.
assert(FTD && "Non-function templates don't need to be checked");
assert(FD->getDescribedFunctionTemplate() &&
"Non-function templates don't need to be checked");

SmallVector<const Expr *, 3> ACs;
FTD->getAssociatedConstraints(ACs);
FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs);

unsigned OldTemplateDepth = FTD->getTemplateParameters()->getDepth();
unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
for (const Expr *Constraint : ACs)
if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
Constraint))
Expand Down Expand Up @@ -1520,6 +1524,7 @@ static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
CSE->getNamedConcept(), CSE->getNamedConcept()->getLexicalDeclContext(),
/*Final=*/false, CSE->getTemplateArguments(),
/*RelativeToPrimary=*/true,
/*Pattern=*/nullptr,
/*ForConstraintInstantiation=*/true);

return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL,
Expand Down Expand Up @@ -1800,8 +1805,8 @@ bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,
return false;
}

unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1);
unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2);
unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);

for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
if (Depth2 > Depth1) {
Expand Down
45 changes: 30 additions & 15 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4511,10 +4511,10 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
adjustDeclContextForDeclaratorDecl(New, Old);

// Ensure the template parameters are compatible.
if (NewTemplate && !TemplateParameterListsAreEqual(
NewTemplate, NewTemplate->getTemplateParameters(),
OldTemplate, OldTemplate->getTemplateParameters(),
/*Complain=*/true, TPL_TemplateMatch))
if (NewTemplate &&
!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
OldTemplate->getTemplateParameters(),
/*Complain=*/true, TPL_TemplateMatch))
return New->setInvalidDecl();

// C++ [class.mem]p1:
Expand Down Expand Up @@ -7676,7 +7676,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
: SourceLocation();
DeclResult Res = ActOnVarTemplateSpecialization(
S, D, TInfo, Previous, TemplateKWLoc, TemplateParams, SC,
IsPartialSpecialization, IsMemberSpecialization);
IsPartialSpecialization);
if (Res.isInvalid())
return nullptr;
NewVD = cast<VarDecl>(Res.get());
Expand All @@ -7695,10 +7695,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
VarTemplateDecl::Create(Context, DC, D.getIdentifierLoc(), Name,
TemplateParams, NewVD);
NewVD->setDescribedVarTemplate(NewTemplate);
// If we are providing an explicit specialization of a static variable
// template, make a note of that.
if (IsMemberSpecialization)
NewTemplate->setMemberSpecialization();
}

// If this decl has an auto type in need of deduction, make a note of the
Expand Down Expand Up @@ -8079,6 +8075,12 @@ NamedDecl *Sema::ActOnVariableDeclarator(
? TPC_ClassTemplateMember
: TPC_VarTemplate))
NewVD->setInvalidDecl();

// If we are providing an explicit specialization of a static variable
// template, make a note of that.
if (PrevVarTemplate &&
PrevVarTemplate->getInstantiatedFromMemberTemplate())
PrevVarTemplate->setMemberSpecialization();
}
}

Expand Down Expand Up @@ -9885,8 +9887,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewFD);
FunctionTemplate->setLexicalDeclContext(CurContext);
NewFD->setDescribedFunctionTemplate(FunctionTemplate);
if (isMemberSpecialization)
FunctionTemplate->setMemberSpecialization();

// For source fidelity, store the other template param lists.
if (TemplateParamLists.size() > 1) {
Expand Down Expand Up @@ -12044,7 +12044,10 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,

// If this is an explicit specialization of a member that is a function
// template, mark it as a member specialization.
if (IsMemberSpecialization) {
if (IsMemberSpecialization &&
NewTemplateDecl->getInstantiatedFromMemberTemplate()) {
NewTemplateDecl->setMemberSpecialization();
assert(OldTemplateDecl->isMemberSpecialization());
// Explicit specializations of a member template do not inherit deleted
// status from the parent member template that they are specializing.
if (OldFD->isDeleted()) {
Expand Down Expand Up @@ -12092,6 +12095,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
if (LangOpts.OpenMP)
OpenMP().ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(NewFD);

if (LangOpts.isSYCL() && NewFD->hasAttr<SYCLKernelEntryPointAttr>())
getASTContext().registerSYCLEntryPointFunction(NewFD);

// Semantic checking for this function declaration (in isolation).

if (getLangOpts().CPlusPlus) {
Expand Down Expand Up @@ -12220,8 +12226,17 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
<< NewFD;
}

if (!Redeclaration && LangOpts.CUDA)
if (!Redeclaration && LangOpts.CUDA) {
bool IsKernel = NewFD->hasAttr<CUDAGlobalAttr>();
for (auto *Parm : NewFD->parameters()) {
if (!Parm->getType()->isDependentType() &&
Parm->hasAttr<CUDAGridConstantAttr>() &&
!(IsKernel && Parm->getType().isConstQualified()))
Diag(Parm->getAttr<CUDAGridConstantAttr>()->getLocation(),
diag::err_cuda_grid_constant_not_allowed);
}
CUDA().checkTargetOverload(NewFD, Previous);
}
}

// Check if the function definition uses any AArch64 SME features without
Expand Down Expand Up @@ -17106,8 +17121,8 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
DeclResult Result = CheckClassTemplate(
S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attrs, TemplateParams,
AS, ModulePrivateLoc,
/*FriendLoc*/ SourceLocation(), TemplateParameterLists.drop_back(),
isMemberSpecialization, SkipBody);
/*FriendLoc*/ SourceLocation(), TemplateParameterLists.size() - 1,
TemplateParameterLists.data(), SkipBody);
return Result.get();
} else {
// The "template<>" header is extraneous.
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4748,6 +4748,15 @@ static void handleManagedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
D->addAttr(CUDADeviceAttr::CreateImplicit(S.Context));
}

static void handleGridConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (D->isInvalidDecl())
return;
// Whether __grid_constant__ is allowed to be used will be checked in
// Sema::CheckFunctionDeclaration as we need complete function decl to make
// the call.
D->addAttr(::new (S.Context) CUDAGridConstantAttr(S.Context, AL));
}

static void handleGNUInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
const auto *Fn = cast<FunctionDecl>(D);
if (!Fn->isInlineSpecified()) {
Expand Down Expand Up @@ -6620,6 +6629,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
case ParsedAttr::AT_SYCLKernel:
S.SYCL().handleKernelAttr(D, AL);
break;
case ParsedAttr::AT_SYCLKernelEntryPoint:
S.SYCL().handleKernelEntryPointAttr(D, AL);
break;
case ParsedAttr::AT_SYCLSpecialClass:
handleSimpleAttribute<SYCLSpecialClassAttr>(S, D, AL);
break;
Expand All @@ -6642,6 +6654,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
case ParsedAttr::AT_CUDADevice:
handleDeviceAttr(S, D, AL);
break;
case ParsedAttr::AT_CUDAGridConstant:
handleGridConstantAttr(S, D, AL);
break;
case ParsedAttr::AT_HIPManaged:
handleManagedAttr(S, D, AL);
break;
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17410,8 +17410,8 @@ DeclResult Sema::ActOnTemplatedFriendTag(
return CheckClassTemplate(S, TagSpec, TagUseKind::Friend, TagLoc, SS,
Name, NameLoc, Attr, TemplateParams, AS_public,
/*ModulePrivateLoc=*/SourceLocation(),
FriendLoc, TempParamLists.drop_back(),
IsMemberSpecialization)
FriendLoc, TempParamLists.size() - 1,
TempParamLists.data())
.get();
} else {
// The "template<>" header is extraneous.
Expand Down
29 changes: 20 additions & 9 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5560,6 +5560,24 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
Init, InitializationContext->Context);
}

static FieldDecl *FindFieldDeclInstantiationPattern(const ASTContext &Ctx,
FieldDecl *Field) {
if (FieldDecl *Pattern = Ctx.getInstantiatedFromUnnamedFieldDecl(Field))
return Pattern;
auto *ParentRD = cast<CXXRecordDecl>(Field->getParent());
CXXRecordDecl *ClassPattern = ParentRD->getTemplateInstantiationPattern();
DeclContext::lookup_result Lookup =
ClassPattern->lookup(Field->getDeclName());
auto Rng = llvm::make_filter_range(
Lookup, [](auto &&L) { return isa<FieldDecl>(*L); });
if (Rng.empty())
return nullptr;
// FIXME: this breaks clang/test/Modules/pr28812.cpp
// assert(std::distance(Rng.begin(), Rng.end()) <= 1
// && "Duplicated instantiation pattern for field decl");
return cast<FieldDecl>(*Rng.begin());
}

ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
assert(Field->hasInClassInitializer());

Expand Down Expand Up @@ -5588,15 +5606,8 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
// Maybe we haven't instantiated the in-class initializer. Go check the
// pattern FieldDecl to see if it has one.
if (isTemplateInstantiation(ParentRD->getTemplateSpecializationKind())) {
CXXRecordDecl *ClassPattern = ParentRD->getTemplateInstantiationPattern();
DeclContext::lookup_result Lookup =
ClassPattern->lookup(Field->getDeclName());

FieldDecl *Pattern = nullptr;
for (auto *L : Lookup) {
if ((Pattern = dyn_cast<FieldDecl>(L)))
break;
}
FieldDecl *Pattern =
FindFieldDeclInstantiationPattern(getASTContext(), Field);
assert(Pattern && "We must have set the Pattern!");
if (!Pattern->hasInClassInitializer() ||
InstantiateInClassInitializer(Loc, Field, Pattern,
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5032,6 +5032,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
case UTT_IsScalar:
case UTT_IsCompound:
case UTT_IsMemberPointer:
case UTT_IsTypedResourceElementCompatible:
// Fall-through

// These traits are modeled on type predicates in C++0x [meta.unary.prop]
Expand Down Expand Up @@ -5714,6 +5715,15 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
tok::kw___builtin_hlsl_is_intangible))
return false;
return T->isHLSLIntangibleType();

case UTT_IsTypedResourceElementCompatible:
assert(Self.getLangOpts().HLSL &&
"typed resource element compatible types are an HLSL-only feature");
if (Self.RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), T,
diag::err_incomplete_type))
return false;

return Self.HLSL().IsTypedResourceElementCompatible(T);
}
}

Expand Down
16 changes: 16 additions & 0 deletions clang/lib/Sema/SemaFunctionEffects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,7 @@ class Analyzer {
PendingFunctionAnalysis &CurrentFunction;
CallableInfo &CurrentCaller;
ViolationSite VSite;
const Expr *TrailingRequiresClause = nullptr;

FunctionBodyASTVisitor(Analyzer &Outer,
PendingFunctionAnalysis &CurrentFunction,
Expand All @@ -985,6 +986,9 @@ class Analyzer {
if (auto *Dtor = dyn_cast<CXXDestructorDecl>(CurrentCaller.CDecl))
followDestructor(dyn_cast<CXXRecordDecl>(Dtor->getParent()), Dtor);

if (auto *FD = dyn_cast<FunctionDecl>(CurrentCaller.CDecl))
TrailingRequiresClause = FD->getTrailingRequiresClause();

// Do an AST traversal of the function/block body
TraverseDecl(const_cast<Decl *>(CurrentCaller.CDecl));
}
Expand Down Expand Up @@ -1259,6 +1263,17 @@ class Analyzer {
return true;
}

bool TraverseStmt(Stmt *Statement) {
// If this statement is a `requires` clause from the top-level function
// being traversed, ignore it, since it's not generating runtime code.
// We skip the traversal of lambdas (beyond their captures, see
// TraverseLambdaExpr below), so just caching this from our constructor
// should suffice.
if (Statement != TrailingRequiresClause)
return Base::TraverseStmt(Statement);
return true;
}

bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
ViolationSite PrevVS = VSite;
if (Init->isAnyMemberInitializer())
Expand Down Expand Up @@ -1297,6 +1312,7 @@ class Analyzer {
}

bool TraverseBlockExpr(BlockExpr * /*unused*/) {
// As with lambdas, don't traverse the block's body.
// TODO: are the capture expressions (ctor call?) safe?
return true;
}
Expand Down
69 changes: 69 additions & 0 deletions clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1947,6 +1947,31 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return true;
break;
}
case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: {
if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
return true;

const Expr *Arg = TheCall->getArg(0);
QualType ArgTy = Arg->getType();
QualType EltTy = ArgTy;

QualType ResTy = SemaRef.Context.UnsignedIntTy;

if (auto *VecTy = EltTy->getAs<VectorType>()) {
EltTy = VecTy->getElementType();
ResTy = SemaRef.Context.getVectorType(ResTy, VecTy->getNumElements(),
VecTy->getVectorKind());
}

if (!EltTy->isIntegerType()) {
Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
<< 1 << /* integer ty */ 6 << ArgTy;
return true;
}

TheCall->setType(ResTy);
break;
}
case Builtin::BI__builtin_hlsl_select: {
if (SemaRef.checkArgCount(TheCall, 3))
return true;
Expand Down Expand Up @@ -2199,6 +2224,50 @@ static void BuildFlattenedTypeList(QualType BaseTy,
}
}

bool SemaHLSL::IsTypedResourceElementCompatible(clang::QualType QT) {
if (QT.isNull())
return false;

// check if the outer type was an array type
if (QT->isArrayType())
return false;

llvm::SmallVector<QualType, 4> QTTypes;
BuildFlattenedTypeList(QT, QTTypes);

assert(QTTypes.size() > 0 &&
"expected at least one constituent type from non-null type");
QualType FirstQT = SemaRef.Context.getCanonicalType(QTTypes[0]);

// element count cannot exceed 4
if (QTTypes.size() > 4)
return false;

for (QualType TempQT : QTTypes) {
// ensure homogeneity
if (!getASTContext().hasSameUnqualifiedType(FirstQT, TempQT))
return false;
}

if (const BuiltinType *BT = FirstQT->getAs<BuiltinType>()) {
if (BT->isBooleanType() || BT->isEnumeralType())
return false;

// Check if it is an array type.
if (FirstQT->isArrayType())
return false;
}

// if the loop above completes without returning, then
// we've guaranteed homogeneity
int TotalSizeInBytes =
(SemaRef.Context.getTypeSize(FirstQT) / 8) * QTTypes.size();
if (TotalSizeInBytes > 16)
return false;

return true;
}

bool SemaHLSL::IsScalarizedLayoutCompatible(QualType T1, QualType T2) const {
if (T1.isNull() || T2.isNull())
return false;
Expand Down
11 changes: 7 additions & 4 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2253,6 +2253,10 @@ bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity,
return FlexArrayDiag != diag::ext_flexible_array_init;
}

static bool isInitializedStructuredList(const InitListExpr *StructuredList) {
return StructuredList && StructuredList->getNumInits() == 1U;
}

void InitListChecker::CheckStructUnionTypes(
const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType,
CXXRecordDecl::base_class_const_range Bases, RecordDecl::field_iterator Field,
Expand Down Expand Up @@ -2499,8 +2503,7 @@ void InitListChecker::CheckStructUnionTypes(
StructuredList, StructuredIndex);
InitializedSomething = true;
InitializedFields.insert(*Field);

if (RD->isUnion() && StructuredList) {
if (RD->isUnion() && isInitializedStructuredList(StructuredList)) {
// Initialize the first field within the union.
StructuredList->setInitializedFieldInUnion(*Field);
}
Expand Down Expand Up @@ -2585,7 +2588,7 @@ void InitListChecker::CheckStructUnionTypes(
CheckImplicitInitList(MemberEntity, IList, Field->getType(), Index,
StructuredList, StructuredIndex);

if (RD->isUnion() && StructuredList) {
if (RD->isUnion() && isInitializedStructuredList(StructuredList)) {
// Initialize the first field within the union.
StructuredList->setInitializedFieldInUnion(*Field);
}
Expand Down Expand Up @@ -9954,7 +9957,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
auto SynthesizeAggrGuide = [&](InitListExpr *ListInit) {
auto *Pattern = Template;
while (Pattern->getInstantiatedFromMemberTemplate()) {
if (Pattern->hasMemberSpecialization())
if (Pattern->isMemberSpecialization())
break;
Pattern = Pattern->getInstantiatedFromMemberTemplate();
}
Expand Down
Loading