clang: lib/CodeGen/CodeGenTBAA.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

28#include "llvm/IR/LLVMContext.h"

29#include "llvm/IR/Metadata.h"

30#include "llvm/IR/Module.h"

31#include "llvm/IR/Type.h"

32#include "llvm/Support/Debug.h"

33using namespace clang;

34using namespace CodeGen;

35

39 : Context(Ctx), CGTypes(CGTypes), Module(M), CodeGenOpts(CGO),

40 Features(Features),

42 MDHelper(M.getContext()), Root(nullptr), Char(nullptr) {}

43

45}

46

47llvm::MDNode *CodeGenTBAA::getRoot() {

48

49

50

51

52 if (!Root) {

53 if (Features.CPlusPlus)

54 Root = MDHelper.createTBAARoot("Simple C++ TBAA");

55 else

56 Root = MDHelper.createTBAARoot("Simple C/C++ TBAA");

57 }

58

59 return Root;

60}

61

62llvm::MDNode *CodeGenTBAA::createScalarTypeNode(StringRef Name,

64 uint64_t Size) {

65 if (CodeGenOpts.NewStructPathTBAA) {

66 llvm::Metadata *Id = MDHelper.createString(Name);

67 return MDHelper.createTBAATypeNode(Parent, Size, Id);

68 }

69 return MDHelper.createTBAAScalarTypeNode(Name, Parent);

70}

71

72llvm::MDNode *CodeGenTBAA::getChar() {

73

74

75

76

77 if (!Char)

78 Char = createScalarTypeNode("omnipotent char", getRoot(), 1);

79

80 return Char;

81}

82

84

86 if (TD->hasAttr())

87 return true;

88

89

90

91

93 if (TT->getDecl()->hasAttr())

94 return true;

95 QTy = TT->desugar();

96 }

97 return false;

98}

99

100

104

105 if (!RD)

106 return false;

108 return false;

109

110

112 return true;

113 }

114 return false;

115}

116

117llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {

119

120

121 if (const BuiltinType *BTy = dyn_cast(Ty)) {

122 switch (BTy->getKind()) {

123

124

125

126

127

128 case BuiltinType::Char_U:

129 case BuiltinType::Char_S:

130 case BuiltinType::UChar:

131 case BuiltinType::SChar:

132 return getChar();

133

134

135 case BuiltinType::UShort:

137 case BuiltinType::UInt:

139 case BuiltinType::ULong:

141 case BuiltinType::ULongLong:

143 case BuiltinType::UInt128:

145

146 case BuiltinType::UShortFract:

148 case BuiltinType::UFract:

150 case BuiltinType::ULongFract:

152

153 case BuiltinType::SatUShortFract:

155 case BuiltinType::SatUFract:

157 case BuiltinType::SatULongFract:

159

160 case BuiltinType::UShortAccum:

162 case BuiltinType::UAccum:

164 case BuiltinType::ULongAccum:

166

167 case BuiltinType::SatUShortAccum:

169 case BuiltinType::SatUAccum:

171 case BuiltinType::SatULongAccum:

173

174

175

176

177 default:

178 return createScalarTypeNode(BTy->getName(Features), getChar(), Size);

179 }

180 }

181

182

183

184

186 return getChar();

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

205 llvm::MDNode *AnyPtr = createScalarTypeNode("any pointer", getChar(), Size);

206 if (!CodeGenOpts.PointerTBAA)

207 return AnyPtr;

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224 unsigned PtrDepth = 0;

225 do {

226 PtrDepth++;

229 assert(!isa(Ty));

230

231

232

233

234

235

236

238 if (isa(Ty)) {

239 llvm::MDNode *ScalarMD = getTypeInfoHelper(Ty);

240 StringRef Name =

241 castllvm::MDString(

242 ScalarMD->getOperand(CodeGenOpts.NewStructPathTBAA ? 2 : 0))

243 ->getString();

244 TyName = Name;

245 } else {

246

247

248

250 if (!RT)

251 return AnyPtr;

252

253

254

255

256

257

258

259

260

261

262

263

264 if (!RT->getDecl()->getDeclName())

265 return AnyPtr;

266

267

268 llvm::raw_svector_ostream TyOut(TyName);

269 MangleCtx->mangleCanonicalTypeName(QualType(Ty, 0), TyOut);

270 }

271

273 OutName += std::to_string(PtrDepth);

274 OutName += " ";

275 OutName += TyName;

276 return createScalarTypeNode(OutName, AnyPtr, Size);

277 }

278

279

280 if (CodeGenOpts.NewStructPathTBAA && Ty->isArrayType())

281 return getTypeInfo(cast(Ty)->getElementType());

282

283

284

285 if (const EnumType *ETy = dyn_cast(Ty)) {

286 if (!Features.CPlusPlus)

287 return getTypeInfo(ETy->getDecl()->getIntegerType());

288

289

290

291

292

293 if (!ETy->getDecl()->isExternallyVisible())

294 return getChar();

295

297 llvm::raw_svector_ostream Out(OutName);

300 return createScalarTypeNode(OutName, getChar(), Size);

301 }

302

303 if (const auto *EIT = dyn_cast(Ty)) {

305 llvm::raw_svector_ostream Out(OutName);

306

307

308 Out << "_BitInt(" << EIT->getNumBits() << ')';

309 return createScalarTypeNode(OutName, getChar(), Size);

310 }

311

312

313 return getChar();

314}

315

317

318

319 if (!Features.Sanitize.has(SanitizerKind::Type) &&

320 (CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing))

321 return nullptr;

322

323

324

326 return getChar();

327

328

329

330

331

332

333

334

336 return getValidBaseTypeInfo(QTy);

337

339 if (llvm::MDNode *N = MetadataCache[Ty])

340 return N;

341

342

343

344

345 llvm::MDNode *TypeNode = getTypeInfoHelper(Ty);

346 return MetadataCache[Ty] = TypeNode;

347}

348

350

351

354

357

360}

361

363 const llvm::DataLayout &DL = Module.getDataLayout();

364 unsigned Size = DL.getPointerTypeSize(VTablePtrType);

365 return TBAAAccessInfo(createScalarTypeNode("vtable pointer", getRoot(), Size),

366 Size);

367}

368

369bool

370CodeGenTBAA::CollectFields(uint64_t BaseOffset,

373 Fields,

375

376

378 if (TTy->isUnionType()) {

380 llvm::MDNode *TBAAType = getChar();

382 Fields.push_back(

383 llvm::MDBuilder::TBAAStructField(BaseOffset, Size, TBAATag));

384 return true;

385 }

388 return false;

389

390

392 if (Decl->bases_begin() != Decl->bases_end())

393 return false;

394

397

398 unsigned idx = 0;

400 i != e; ++i, ++idx) {

402 continue;

403

404 uint64_t Offset =

406

407

408

409 if ((*i)->isBitField()) {

411

412

413

417 if (!IsFirst)

418 continue;

419 unsigned CurrentBitFieldSize = Info.StorageSize;

420 uint64_t Size =

421 llvm::divideCeil(CurrentBitFieldSize, Context.getCharWidth());

422 llvm::MDNode *TBAAType = getChar();

423 llvm::MDNode *TBAATag =

425 Fields.push_back(

426 llvm::MDBuilder::TBAAStructField(Offset, Size, TBAATag));

427 continue;

428 }

429

430 QualType FieldQTy = i->getType();

431 if (!CollectFields(Offset, FieldQTy, Fields,

433 return false;

434 }

435 return true;

436 }

437

438

439 uint64_t Offset = BaseOffset;

443 Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size, TBAATag));

444 return true;

445}

446

447llvm::MDNode *

449 if (CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing)

450 return nullptr;

451

453

454 if (llvm::MDNode *N = StructMetadataCache[Ty])

455 return N;

456

459 return MDHelper.createTBAAStructNode(Fields);

460

461

462 return StructMetadataCache[Ty] = nullptr;

463}

464

465llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) {

466 if (auto *TTy = dyn_cast(Ty)) {

469 using TBAAStructField = llvm::MDBuilder::TBAAStructField;

471 if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) {

472

473

474

475 if (CodeGenOpts.NewStructPathTBAA && CXXRD->getNumVBases() != 0)

476 return nullptr;

478 if (B.isVirtual())

479 continue;

480 QualType BaseQTy = B.getType();

483 continue;

485 ? getValidBaseTypeInfo(BaseQTy)

487 if (!TypeNode)

488 return nullptr;

490 uint64_t Size =

492 Fields.push_back(

493 llvm::MDBuilder::TBAAStructField(Offset, Size, TypeNode));

494 }

495

496

497

498

499

500 llvm::sort(Fields,

501 [](const TBAAStructField &A, const TBAAStructField &B) {

502 return A.Offset < B.Offset;

503 });

504 }

506 if (Field->isZeroSize(Context) || Field->isUnnamedBitField())

507 continue;

510 ? getValidBaseTypeInfo(FieldQTy)

512 if (!TypeNode)

513 return nullptr;

514

518 Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size,

519 TypeNode));

520 }

521

523 if (Features.CPlusPlus) {

524

525 llvm::raw_svector_ostream Out(OutName);

528 } else {

530 }

531

532 if (CodeGenOpts.NewStructPathTBAA) {

533 llvm::MDNode *Parent = getChar();

535 llvm::Metadata *Id = MDHelper.createString(OutName);

536 return MDHelper.createTBAATypeNode(Parent, Size, Id, Fields);

537 }

538

539

541 for (const auto &Field : Fields)

542 OffsetsAndTypes.push_back(std::make_pair(Field.Type, Field.Offset));

543 return MDHelper.createTBAAStructTypeNode(OutName, OffsetsAndTypes);

544 }

545

546 return nullptr;

547}

548

549llvm::MDNode *CodeGenTBAA::getValidBaseTypeInfo(QualType QTy) {

550 assert(isValidBaseType(QTy) && "Must be a valid base type");

551

553

554

555 auto I = BaseTypeMetadataCache.find(Ty);

556 if (I != BaseTypeMetadataCache.end())

557 return I->second;

558

559

560

561 llvm::MDNode *TypeNode = getBaseTypeInfoHelper(Ty);

562 LLVM_ATTRIBUTE_UNUSED auto inserted =

563 BaseTypeMetadataCache.insert({Ty, TypeNode});

564 assert(inserted.second && "BaseType metadata was already inserted");

565

566 return TypeNode;

567}

568

570 return isValidBaseType(QTy) ? getValidBaseTypeInfo(QTy) : nullptr;

571}

572

574 assert(!Info.isIncomplete() && "Access to an object of an incomplete type!");

575

578

580 return nullptr;

581

582 if (!CodeGenOpts.StructPathTBAA)

584

585 llvm::MDNode *&N = AccessTagMetadataCache[Info];

586 if (N)

587 return N;

588

591 assert(!Info.Offset && "Nonzero offset for an access with no base type!");

592 }

593 if (CodeGenOpts.NewStructPathTBAA) {

594 return N = MDHelper.createTBAAAccessTag(Info.BaseType, Info.AccessType,

596 }

597 return N = MDHelper.createTBAAStructTagNode(Info.BaseType, Info.AccessType,

599}

600

606}

607

611 if (InfoA == InfoB)

612 return InfoA;

613

614 if (!InfoA || !InfoB)

616

619

620

621

622

624}

625

629 if (DestInfo == SrcInfo)

630 return DestInfo;

631

632 if (!DestInfo || !SrcInfo)

634

637

638

639

640

642}

Defines the clang::ASTContext interface.

static bool TypeHasMayAlias(QualType QTy)

static bool isValidBaseType(QualType QTy)

Check if the given type is a valid base type to be used in access tags.

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const

Get or compute information about the layout of the specified record (struct/union/class) D,...

CanQualType getCanonicalType(QualType T) const

Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...

CanQualType SatLongAccumTy

CanQualType SatShortFractTy

CharUnits getTypeSizeInChars(QualType T) const

Return the size of the specified (complete) type T, in characters.

CanQualType SatLongFractTy

const TargetInfo & getTargetInfo() const

CanQualType SatShortAccumTy

CharUnits toCharUnitsFromBits(int64_t BitSize) const

Convert a size in bits to a size in characters.

uint64_t getCharWidth() const

Return the size of the character type, in bits.

ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...

uint64_t getFieldOffset(unsigned FieldNo) const

getFieldOffset - Get the offset of the given field index, in bits.

CharUnits getDataSize() const

getDataSize() - Get the record data size, which is the record size without tail padding,...

CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const

getBaseClassOffset - Get the offset, in chars, for the given base class.

This class is used for builtin types like 'int'.

Represents a base class of a C++ class.

Represents a C++ struct/union/class.

bool isEmpty() const

Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).

const T * getTypePtr() const

Retrieve the underlying type pointer, which refers to a canonical type.

QuantityType getQuantity() const

getQuantity - Get the raw integer representation of this quantity.

CodeGenOptions - Track various options which control how the code is optimized and passed to the back...

MangleContext & getMangleContext()

Gets the mangle context.

CGRecordLayout - This class handles struct and union layout info while lowering AST types to LLVM typ...

const CGBitFieldInfo & getBitFieldInfo(const FieldDecl *FD) const

Return the BitFieldInfo that corresponds to the field FD.

llvm::MDNode * getBaseTypeInfo(QualType QTy)

getBaseTypeInfo - Get metadata that describes the given base access type.

llvm::MDNode * getTypeInfo(QualType QTy)

getTypeInfo - Get metadata used to describe accesses to objects of the given type.

TBAAAccessInfo getVTablePtrAccessInfo(llvm::Type *VTablePtrType)

getVTablePtrAccessInfo - Get the TBAA information that describes an access to a virtual table pointer...

TBAAAccessInfo mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo DestInfo, TBAAAccessInfo SrcInfo)

mergeTBAAInfoForMemoryTransfer - Get merged TBAA information for the purpose of memory transfer calls...

TBAAAccessInfo mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo, TBAAAccessInfo TargetInfo)

mergeTBAAInfoForCast - Get merged TBAA information for the purpose of type casts.

TBAAAccessInfo mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA, TBAAAccessInfo InfoB)

mergeTBAAInfoForConditionalOperator - Get merged TBAA information for the purpose of conditional oper...

llvm::MDNode * getAccessTagInfo(TBAAAccessInfo Info)

getAccessTagInfo - Get TBAA tag for a given memory access.

llvm::MDNode * getTBAAStructInfo(QualType QTy)

getTBAAStructInfo - Get the TBAAStruct MDNode to be used for a memcpy of the given type.

CodeGenTBAA(ASTContext &Ctx, CodeGenTypes &CGTypes, llvm::Module &M, const CodeGenOptions &CGO, const LangOptions &Features)

TBAAAccessInfo getAccessInfo(QualType AccessType)

getAccessInfo - Get TBAA information that describes an access to an object of the given type.

This class organizes the cross-module state that is used while lowering AST types to LLVM types.

CGCXXABI & getCXXABI() const

const CGRecordLayout & getCGRecordLayout(const RecordDecl *)

getCGRecordLayout - Return record layout info for the given record decl.

specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...

Decl - This represents one declaration (or definition), e.g.

A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.

Represents a member of a struct/union/class.

Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...

SanitizerSet Sanitize

Set of enabled sanitizers.

virtual void mangleCanonicalTypeName(QualType T, raw_ostream &, bool NormalizeIntegers=false)=0

Generates a unique string for an externally visible type for use with TBAA or type uniquing.

Describes a module or submodule.

StringRef getName() const

Get the name of identifier for this declaration as a StringRef.

A (possibly-)qualified type.

Represents a struct/union/class.

bool hasFlexibleArrayMember() const

field_iterator field_end() const

field_range fields() const

RecordDecl * getDefinition() const

Returns the RecordDecl that actually defines this struct/union/class.

field_iterator field_begin() const

A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...

Exposes information about the current target.

The base class of the type hierarchy.

CXXRecordDecl * getAsCXXRecordDecl() const

Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...

bool isPointerType() const

bool isReferenceType() const

QualType getPointeeType() const

If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.

const Type * getBaseElementTypeUnsafe() const

Get the base element type of this type, potentially discarding type qualifiers.

bool isStdByteType() const

bool isIncompleteType(NamedDecl **Def=nullptr) const

Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...

const T * getAs() const

Member-template getAs'.

TagDecl * getAsTagDecl() const

Retrieves the TagDecl that this type refers to, either because the type is a TagType or because it is...

Defines the clang::TargetInfo interface.

bool isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD)

isEmptyFieldForLayout - Return true iff the field is "empty", that is, either a zero-width bit-field ...

The JSON file list parser is used to communicate input to InstallAPI.

if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))

Structure with information about how a bitfield should be accessed.

unsigned Offset

The offset within a contiguous run of bitfields that are represented as a single "field" within the L...

unsigned Size

The total size of the bit-field, in bits.

unsigned StorageSize

The storage size in bits which should be used when accessing this bitfield.

llvm::MDNode * AccessType

AccessType - The final access type.

uint64_t Offset

Offset - The byte offset of the final access within the base one.

static TBAAAccessInfo getMayAliasInfo()

uint64_t Size

Size - The size of access, in bytes.

static TBAAAccessInfo getIncompleteInfo()

llvm::MDNode * BaseType

BaseType - The base/leading access type.

bool isIncomplete() const

bool has(SanitizerMask K) const

Check if a certain (single) sanitizer is enabled.