Skip to content

Commit 284832f

Browse files
author
z1_cciauto
authored
merge main into amd-staging (llvm#4433)
2 parents 6e75bea + 554be6b commit 284832f

File tree

110 files changed

+4085
-2490
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

110 files changed

+4085
-2490
lines changed

clang/docs/AllocToken.rst

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,35 @@ which encodes the token ID hint in the allocation function name.
122122
This ABI provides a more efficient alternative where
123123
``-falloc-token-max`` is small.
124124

125+
Instrumenting Non-Standard Allocation Functions
126+
-----------------------------------------------
127+
128+
By default, AllocToken only instruments standard library allocation functions.
129+
This simplifies adoption, as a compatible allocator only needs to provide
130+
token-enabled variants for a well-defined set of standard functions.
131+
132+
To extend instrumentation to custom allocation functions, enable broader
133+
coverage with ``-fsanitize-alloc-token-extended``. Such functions require being
134+
marked with the `malloc
135+
<https://clang.llvm.org/docs/AttributeReference.html#malloc>`_ or `alloc_size
136+
<https://clang.llvm.org/docs/AttributeReference.html#alloc-size>`_ attributes
137+
(or a combination).
138+
139+
For example:
140+
141+
.. code-block:: c
142+
143+
void *custom_malloc(size_t size) __attribute__((malloc));
144+
void *my_malloc(size_t size) __attribute__((alloc_size(1)));
145+
146+
// Original:
147+
ptr1 = custom_malloc(size);
148+
ptr2 = my_malloc(size);
149+
150+
// Instrumented:
151+
ptr1 = __alloc_token_custom_malloc(size, token_id);
152+
ptr2 = __alloc_token_my_malloc(size, token_id);
153+
125154
Disabling Instrumentation
126155
-------------------------
127156

clang/include/clang/AST/TypeBase.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7082,10 +7082,6 @@ class SubstBuiltinTemplatePackType : public SubstPackType {
70827082
class SubstTemplateTypeParmPackType : public SubstPackType {
70837083
friend class ASTContext;
70847084

7085-
/// A pointer to the set of template arguments that this
7086-
/// parameter pack is instantiated with.
7087-
const TemplateArgument *Arguments;
7088-
70897085
llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal;
70907086

70917087
SubstTemplateTypeParmPackType(QualType Canon, Decl *AssociatedDecl,

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -950,10 +950,13 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
950950
assert((BT->getKind() != BuiltinType::SveCount || Info.NumVectors == 1) &&
951951
"Unsupported number of vectors for svcount_t");
952952

953-
// Debuggers can't extract 1bit from a vector, so will display a
954-
// bitpattern for predicates instead.
955953
unsigned NumElems = Info.EC.getKnownMinValue() * Info.NumVectors;
956-
if (Info.ElementType == CGM.getContext().BoolTy) {
954+
llvm::Metadata *BitStride = nullptr;
955+
if (BT->getKind() == BuiltinType::SveBool) {
956+
Info.ElementType = CGM.getContext().UnsignedCharTy;
957+
BitStride = llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(
958+
llvm::Type::getInt64Ty(CGM.getLLVMContext()), 1));
959+
} else if (BT->getKind() == BuiltinType::SveCount) {
957960
NumElems /= 8;
958961
Info.ElementType = CGM.getContext().UnsignedCharTy;
959962
}
@@ -979,7 +982,7 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
979982
getOrCreateType(Info.ElementType, TheCU->getFile());
980983
auto Align = getTypeAlignIfRequired(BT, CGM.getContext());
981984
return DBuilder.createVectorType(/*Size*/ 0, Align, ElemTy,
982-
SubscriptArray);
985+
SubscriptArray, BitStride);
983986
}
984987
// It doesn't make sense to generate debug info for PowerPC MMA vector types.
985988
// So we return a safe type here to avoid generating an error.

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 125 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "clang/AST/Attr.h"
3131
#include "clang/AST/DeclObjC.h"
3232
#include "clang/AST/NSAPI.h"
33+
#include "clang/AST/ParentMapContext.h"
3334
#include "clang/AST/StmtVisitor.h"
3435
#include "clang/Basic/Builtins.h"
3536
#include "clang/Basic/CodeGenOptions.h"
@@ -1353,6 +1354,115 @@ void CodeGenFunction::EmitAllocToken(llvm::CallBase *CB, QualType AllocType) {
13531354
CB->setMetadata(llvm::LLVMContext::MD_alloc_token, MDN);
13541355
}
13551356

1357+
namespace {
1358+
/// Infer type from a simple sizeof expression.
1359+
QualType inferTypeFromSizeofExpr(const Expr *E) {
1360+
const Expr *Arg = E->IgnoreParenImpCasts();
1361+
if (const auto *UET = dyn_cast<UnaryExprOrTypeTraitExpr>(Arg)) {
1362+
if (UET->getKind() == UETT_SizeOf) {
1363+
if (UET->isArgumentType())
1364+
return UET->getArgumentTypeInfo()->getType();
1365+
else
1366+
return UET->getArgumentExpr()->getType();
1367+
}
1368+
}
1369+
return QualType();
1370+
}
1371+
1372+
/// Infer type from an arithmetic expression involving a sizeof. For example:
1373+
///
1374+
/// malloc(sizeof(MyType) + padding); // infers 'MyType'
1375+
/// malloc(sizeof(MyType) * 32); // infers 'MyType'
1376+
/// malloc(32 * sizeof(MyType)); // infers 'MyType'
1377+
/// malloc(sizeof(MyType) << 1); // infers 'MyType'
1378+
/// ...
1379+
///
1380+
/// More complex arithmetic expressions are supported, but are a heuristic, e.g.
1381+
/// when considering allocations for structs with flexible array members:
1382+
///
1383+
/// malloc(sizeof(HasFlexArray) + sizeof(int) * 32); // infers 'HasFlexArray'
1384+
///
1385+
QualType inferPossibleTypeFromArithSizeofExpr(const Expr *E) {
1386+
const Expr *Arg = E->IgnoreParenImpCasts();
1387+
// The argument is a lone sizeof expression.
1388+
if (QualType T = inferTypeFromSizeofExpr(Arg); !T.isNull())
1389+
return T;
1390+
if (const auto *BO = dyn_cast<BinaryOperator>(Arg)) {
1391+
// Argument is an arithmetic expression. Cover common arithmetic patterns
1392+
// involving sizeof.
1393+
switch (BO->getOpcode()) {
1394+
case BO_Add:
1395+
case BO_Div:
1396+
case BO_Mul:
1397+
case BO_Shl:
1398+
case BO_Shr:
1399+
case BO_Sub:
1400+
if (QualType T = inferPossibleTypeFromArithSizeofExpr(BO->getLHS());
1401+
!T.isNull())
1402+
return T;
1403+
if (QualType T = inferPossibleTypeFromArithSizeofExpr(BO->getRHS());
1404+
!T.isNull())
1405+
return T;
1406+
break;
1407+
default:
1408+
break;
1409+
}
1410+
}
1411+
return QualType();
1412+
}
1413+
1414+
/// If the expression E is a reference to a variable, infer the type from a
1415+
/// variable's initializer if it contains a sizeof. Beware, this is a heuristic
1416+
/// and ignores if a variable is later reassigned. For example:
1417+
///
1418+
/// size_t my_size = sizeof(MyType);
1419+
/// void *x = malloc(my_size); // infers 'MyType'
1420+
///
1421+
QualType inferPossibleTypeFromVarInitSizeofExpr(const Expr *E) {
1422+
const Expr *Arg = E->IgnoreParenImpCasts();
1423+
if (const auto *DRE = dyn_cast<DeclRefExpr>(Arg)) {
1424+
if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
1425+
if (const Expr *Init = VD->getInit())
1426+
return inferPossibleTypeFromArithSizeofExpr(Init);
1427+
}
1428+
}
1429+
return QualType();
1430+
}
1431+
1432+
/// Deduces the allocated type by checking if the allocation call's result
1433+
/// is immediately used in a cast expression. For example:
1434+
///
1435+
/// MyType *x = (MyType *)malloc(4096); // infers 'MyType'
1436+
///
1437+
QualType inferPossibleTypeFromCastExpr(const CallExpr *CallE,
1438+
const CastExpr *CastE) {
1439+
if (!CastE)
1440+
return QualType();
1441+
QualType PtrType = CastE->getType();
1442+
if (PtrType->isPointerType())
1443+
return PtrType->getPointeeType();
1444+
return QualType();
1445+
}
1446+
} // end anonymous namespace
1447+
1448+
void CodeGenFunction::EmitAllocToken(llvm::CallBase *CB, const CallExpr *E) {
1449+
QualType AllocType;
1450+
// First check arguments.
1451+
for (const Expr *Arg : E->arguments()) {
1452+
AllocType = inferPossibleTypeFromArithSizeofExpr(Arg);
1453+
if (AllocType.isNull())
1454+
AllocType = inferPossibleTypeFromVarInitSizeofExpr(Arg);
1455+
if (!AllocType.isNull())
1456+
break;
1457+
}
1458+
// Then check later casts.
1459+
if (AllocType.isNull())
1460+
AllocType = inferPossibleTypeFromCastExpr(E, CurCast);
1461+
// Emit if we were able to infer the type.
1462+
if (!AllocType.isNull())
1463+
EmitAllocToken(CB, AllocType);
1464+
}
1465+
13561466
CodeGenFunction::ComplexPairTy CodeGenFunction::
13571467
EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV,
13581468
bool isInc, bool isPre) {
@@ -5723,6 +5833,9 @@ LValue CodeGenFunction::EmitConditionalOperatorLValue(
57235833
/// are permitted with aggregate result, including noop aggregate casts, and
57245834
/// cast from scalar to union.
57255835
LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
5836+
auto RestoreCurCast =
5837+
llvm::make_scope_exit([this, Prev = CurCast] { CurCast = Prev; });
5838+
CurCast = E;
57265839
switch (E->getCastKind()) {
57275840
case CK_ToVoid:
57285841
case CK_BitCast:
@@ -6683,16 +6796,24 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType,
66836796
RValue Call = EmitCall(FnInfo, Callee, ReturnValue, Args, &LocalCallOrInvoke,
66846797
E == MustTailCall, E->getExprLoc());
66856798

6686-
// Generate function declaration DISuprogram in order to be used
6687-
// in debug info about call sites.
6688-
if (CGDebugInfo *DI = getDebugInfo()) {
6689-
if (auto *CalleeDecl = dyn_cast_or_null<FunctionDecl>(TargetDecl)) {
6799+
if (auto *CalleeDecl = dyn_cast_or_null<FunctionDecl>(TargetDecl)) {
6800+
// Generate function declaration DISuprogram in order to be used
6801+
// in debug info about call sites.
6802+
if (CGDebugInfo *DI = getDebugInfo()) {
66906803
FunctionArgList Args;
66916804
QualType ResTy = BuildFunctionArgList(CalleeDecl, Args);
66926805
DI->EmitFuncDeclForCallSite(LocalCallOrInvoke,
66936806
DI->getFunctionType(CalleeDecl, ResTy, Args),
66946807
CalleeDecl);
66956808
}
6809+
if (CalleeDecl->hasAttr<RestrictAttr>() ||
6810+
CalleeDecl->hasAttr<AllocSizeAttr>()) {
6811+
// Function has 'malloc' (aka. 'restrict') or 'alloc_size' attribute.
6812+
if (SanOpts.has(SanitizerKind::AllocToken)) {
6813+
// Set !alloc_token metadata.
6814+
EmitAllocToken(LocalCallOrInvoke, E);
6815+
}
6816+
}
66966817
}
66976818
if (CallOrInvoke)
66986819
*CallOrInvoke = LocalCallOrInvoke;

clang/lib/CodeGen/CGExprCXX.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,8 +1371,16 @@ RValue CodeGenFunction::EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,
13711371

13721372
for (auto *Decl : Ctx.getTranslationUnitDecl()->lookup(Name))
13731373
if (auto *FD = dyn_cast<FunctionDecl>(Decl))
1374-
if (Ctx.hasSameType(FD->getType(), QualType(Type, 0)))
1375-
return EmitNewDeleteCall(*this, FD, Type, Args);
1374+
if (Ctx.hasSameType(FD->getType(), QualType(Type, 0))) {
1375+
RValue RV = EmitNewDeleteCall(*this, FD, Type, Args);
1376+
if (auto *CB = dyn_cast_if_present<llvm::CallBase>(RV.getScalarVal())) {
1377+
if (SanOpts.has(SanitizerKind::AllocToken)) {
1378+
// Set !alloc_token metadata.
1379+
EmitAllocToken(CB, TheCall);
1380+
}
1381+
}
1382+
return RV;
1383+
}
13761384
llvm_unreachable("predeclared global operator new/delete is missing");
13771385
}
13781386

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "clang/Basic/DiagnosticTrap.h"
3434
#include "clang/Basic/TargetInfo.h"
3535
#include "llvm/ADT/APFixedPoint.h"
36+
#include "llvm/ADT/ScopeExit.h"
3637
#include "llvm/IR/Argument.h"
3738
#include "llvm/IR/CFG.h"
3839
#include "llvm/IR/Constants.h"
@@ -2438,6 +2439,10 @@ static Value *EmitHLSLElementwiseCast(CodeGenFunction &CGF, LValue SrcVal,
24382439
// have to handle a more broad range of conversions than explicit casts, as they
24392440
// handle things like function to ptr-to-function decay etc.
24402441
Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
2442+
auto RestoreCurCast =
2443+
llvm::make_scope_exit([this, Prev = CGF.CurCast] { CGF.CurCast = Prev; });
2444+
CGF.CurCast = CE;
2445+
24412446
Expr *E = CE->getSubExpr();
24422447
QualType DestTy = CE->getType();
24432448
CastKind Kind = CE->getCastKind();

clang/lib/CodeGen/CodeGenFunction.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,10 @@ class CodeGenFunction : public CodeGenTypeCache {
348348
QualType FnRetTy;
349349
llvm::Function *CurFn = nullptr;
350350

351+
/// If a cast expression is being visited, this holds the current cast's
352+
/// expression.
353+
const CastExpr *CurCast = nullptr;
354+
351355
/// Save Parameter Decl for coroutine.
352356
llvm::SmallVector<const ParmVarDecl *, 4> FnArgs;
353357

@@ -3356,6 +3360,9 @@ class CodeGenFunction : public CodeGenTypeCache {
33563360

33573361
/// Emit additional metadata used by the AllocToken instrumentation.
33583362
void EmitAllocToken(llvm::CallBase *CB, QualType AllocType);
3363+
/// Emit additional metadata used by the AllocToken instrumentation,
3364+
/// inferring the type from an allocation call expression.
3365+
void EmitAllocToken(llvm::CallBase *CB, const CallExpr *E);
33593366

33603367
llvm::Value *GetCountedByFieldExprGEP(const Expr *Base, const FieldDecl *FD,
33613368
const FieldDecl *CountDecl);

clang/lib/Driver/ToolChains/Darwin.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1609,7 +1609,12 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
16091609
if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) {
16101610
AddLinkSanitizerLibArgs(Args, CmdArgs, "fuzzer", /*shared=*/false);
16111611

1612-
// Libfuzzer is written in C++ and requires libcxx.
1612+
// Libfuzzer is written in C++ and requires libcxx.
1613+
// Since darwin::Linker::ConstructJob already adds -lc++ for clang++
1614+
// by default if ShouldLinkCXXStdlib(Args), we only add the option if
1615+
// !ShouldLinkCXXStdlib(Args). This avoids duplicate library errors
1616+
// on Darwin.
1617+
if (!ShouldLinkCXXStdlib(Args))
16131618
AddCXXStdlibLibArgs(Args, CmdArgs);
16141619
}
16151620
if (Sanitize.needsStatsRt()) {

clang/lib/Driver/ToolChains/HIPAMD.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,12 @@ void AMDGCN::Linker::constructLinkAndEmitSpirvCommand(
177177
const InputInfo &Output, const llvm::opt::ArgList &Args) const {
178178
assert(!Inputs.empty() && "Must have at least one input.");
179179

180-
constructLlvmLinkCommand(C, JA, Inputs, Output, Args);
180+
std::string LinkedBCFilePrefix(
181+
Twine(llvm::sys::path::stem(Output.getFilename()), "-linked").str());
182+
const char *LinkedBCFilePath = HIP::getTempFile(C, LinkedBCFilePrefix, "bc");
183+
InputInfo LinkedBCFile(&JA, LinkedBCFilePath, Output.getBaseInput());
181184

182-
// Linked BC is now in Output
185+
constructLlvmLinkCommand(C, JA, Inputs, LinkedBCFile, Args);
183186

184187
// Emit SPIR-V binary.
185188
llvm::opt::ArgStringList TrArgs{
@@ -189,7 +192,7 @@ void AMDGCN::Linker::constructLinkAndEmitSpirvCommand(
189192
"--spirv-lower-const-expr",
190193
"--spirv-preserve-auxdata",
191194
"--spirv-debug-info-version=nonsemantic-shader-200"};
192-
SPIRV::constructTranslateCommand(C, *this, JA, Output, Output, TrArgs);
195+
SPIRV::constructTranslateCommand(C, *this, JA, Output, LinkedBCFile, TrArgs);
193196
}
194197

195198
// For amdgcn the inputs of the linker job are device bitcode and output is

clang/lib/Driver/ToolChains/HIPSPV.cpp

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,6 @@ using namespace clang::driver::tools;
2222
using namespace clang;
2323
using namespace llvm::opt;
2424

25-
// Convenience function for creating temporary file for both modes of
26-
// isSaveTempsEnabled().
27-
static const char *getTempFile(Compilation &C, StringRef Prefix,
28-
StringRef Extension) {
29-
if (C.getDriver().isSaveTempsEnabled()) {
30-
return C.getArgs().MakeArgString(Prefix + "." + Extension);
31-
}
32-
auto TmpFile = C.getDriver().GetTemporaryPath(Prefix, Extension);
33-
return C.addTempFile(C.getArgs().MakeArgString(TmpFile));
34-
}
35-
3625
// Locates HIP pass plugin.
3726
static std::string findPassPlugin(const Driver &D,
3827
const llvm::opt::ArgList &Args) {
@@ -65,7 +54,7 @@ void HIPSPV::Linker::constructLinkAndEmitSpirvCommand(
6554

6655
assert(!Inputs.empty() && "Must have at least one input.");
6756
std::string Name = std::string(llvm::sys::path::stem(Output.getFilename()));
68-
const char *TempFile = getTempFile(C, Name + "-link", "bc");
57+
const char *TempFile = HIP::getTempFile(C, Name + "-link", "bc");
6958

7059
// Link LLVM bitcode.
7160
ArgStringList LinkArgs{};
@@ -95,7 +84,7 @@ void HIPSPV::Linker::constructLinkAndEmitSpirvCommand(
9584
auto PassPluginPath = findPassPlugin(C.getDriver(), Args);
9685
if (!PassPluginPath.empty()) {
9786
const char *PassPathCStr = C.getArgs().MakeArgString(PassPluginPath);
98-
const char *OptOutput = getTempFile(C, Name + "-lower", "bc");
87+
const char *OptOutput = HIP::getTempFile(C, Name + "-lower", "bc");
9988
ArgStringList OptArgs{TempFile, "-load-pass-plugin",
10089
PassPathCStr, "-passes=hip-post-link-passes",
10190
"-o", OptOutput};

0 commit comments

Comments
 (0)