Skip to content

Commit d2a9df2

Browse files
authored
[TBAA] Handle bitfields when generating !tbaa.struct metadata. (#82922)
At the moment, clang generates what I believe are incorrect !tbaa.struct fields for named bitfields. At the moment, the base type size is used for named bifields (e.g. sizeof(int)) instead of the bifield width per field. This results in overalpping fields in !tbaa.struct metadata. This causes incorrect results when extracting individual copied fields from !tbaa.struct as in added in dc85719. This patch fixes that by skipping by combining adjacent bitfields in fields with correct sizes. Fixes #82586
1 parent 0d1f957 commit d2a9df2

File tree

4 files changed

+43
-18
lines changed

4 files changed

+43
-18
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -397,8 +397,8 @@ CodeGenModule::CodeGenModule(ASTContext &C,
397397
// Enable TBAA unless it's suppressed. ThreadSanitizer needs TBAA even at O0.
398398
if (LangOpts.Sanitize.has(SanitizerKind::Thread) ||
399399
(!CodeGenOpts.RelaxedAliasing && CodeGenOpts.OptimizationLevel > 0))
400-
TBAA.reset(new CodeGenTBAA(Context, TheModule, CodeGenOpts, getLangOpts(),
401-
getCXXABI().getMangleContext()));
400+
TBAA.reset(new CodeGenTBAA(Context, getTypes(), TheModule, CodeGenOpts,
401+
getLangOpts(), getCXXABI().getMangleContext()));
402402

403403
// If debug info or coverage generation is enabled, create the CGDebugInfo
404404
// object.

clang/lib/CodeGen/CodeGenTBAA.cpp

+33-11
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
#include "CodeGenTBAA.h"
18+
#include "CGRecordLayout.h"
19+
#include "CodeGenTypes.h"
1820
#include "clang/AST/ASTContext.h"
1921
#include "clang/AST/Attr.h"
2022
#include "clang/AST/Mangle.h"
@@ -26,16 +28,16 @@
2628
#include "llvm/IR/Metadata.h"
2729
#include "llvm/IR/Module.h"
2830
#include "llvm/IR/Type.h"
31+
#include "llvm/Support/Debug.h"
2932
using namespace clang;
3033
using namespace CodeGen;
3134

32-
CodeGenTBAA::CodeGenTBAA(ASTContext &Ctx, llvm::Module &M,
33-
const CodeGenOptions &CGO,
35+
CodeGenTBAA::CodeGenTBAA(ASTContext &Ctx, CodeGenTypes &CGTypes,
36+
llvm::Module &M, const CodeGenOptions &CGO,
3437
const LangOptions &Features, MangleContext &MContext)
35-
: Context(Ctx), Module(M), CodeGenOpts(CGO),
36-
Features(Features), MContext(MContext), MDHelper(M.getContext()),
37-
Root(nullptr), Char(nullptr)
38-
{}
38+
: Context(Ctx), CGTypes(CGTypes), Module(M), CodeGenOpts(CGO),
39+
Features(Features), MContext(MContext), MDHelper(M.getContext()),
40+
Root(nullptr), Char(nullptr) {}
3941

4042
CodeGenTBAA::~CodeGenTBAA() {
4143
}
@@ -294,14 +296,34 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset,
294296
return false;
295297

296298
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
299+
const CGRecordLayout &CGRL = CGTypes.getCGRecordLayout(RD);
297300

298301
unsigned idx = 0;
299-
for (RecordDecl::field_iterator i = RD->field_begin(),
300-
e = RD->field_end(); i != e; ++i, ++idx) {
301-
if ((*i)->isZeroSize(Context) || (*i)->isUnnamedBitfield())
302+
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
303+
i != e; ++i, ++idx) {
304+
if ((*i)->isZeroSize(Context))
302305
continue;
303-
uint64_t Offset = BaseOffset +
304-
Layout.getFieldOffset(idx) / Context.getCharWidth();
306+
307+
uint64_t Offset =
308+
BaseOffset + Layout.getFieldOffset(idx) / Context.getCharWidth();
309+
310+
// Create a single field for consecutive named bitfields using char as
311+
// base type.
312+
if ((*i)->isBitField()) {
313+
const CGBitFieldInfo &Info = CGRL.getBitFieldInfo(*i);
314+
if (Info.Offset != 0)
315+
continue;
316+
unsigned CurrentBitFieldSize = Info.StorageSize;
317+
uint64_t Size =
318+
llvm::divideCeil(CurrentBitFieldSize, Context.getCharWidth());
319+
llvm::MDNode *TBAAType = getChar();
320+
llvm::MDNode *TBAATag =
321+
getAccessTagInfo(TBAAAccessInfo(TBAAType, Size));
322+
Fields.push_back(
323+
llvm::MDBuilder::TBAAStructField(Offset, Size, TBAATag));
324+
continue;
325+
}
326+
305327
QualType FieldQTy = i->getType();
306328
if (!CollectFields(Offset, FieldQTy, Fields,
307329
MayAlias || TypeHasMayAlias(FieldQTy)))

clang/lib/CodeGen/CodeGenTBAA.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ namespace clang {
2929
class Type;
3030

3131
namespace CodeGen {
32+
class CodeGenTypes;
3233

3334
// TBAAAccessKind - A kind of TBAA memory access descriptor.
3435
enum class TBAAAccessKind : unsigned {
@@ -115,6 +116,7 @@ struct TBAAAccessInfo {
115116
/// while lowering AST types to LLVM types.
116117
class CodeGenTBAA {
117118
ASTContext &Context;
119+
CodeGenTypes &CGTypes;
118120
llvm::Module &Module;
119121
const CodeGenOptions &CodeGenOpts;
120122
const LangOptions &Features;
@@ -167,8 +169,9 @@ class CodeGenTBAA {
167169
llvm::MDNode *getBaseTypeInfoHelper(const Type *Ty);
168170

169171
public:
170-
CodeGenTBAA(ASTContext &Ctx, llvm::Module &M, const CodeGenOptions &CGO,
171-
const LangOptions &Features, MangleContext &MContext);
172+
CodeGenTBAA(ASTContext &Ctx, CodeGenTypes &CGTypes, llvm::Module &M,
173+
const CodeGenOptions &CGO, const LangOptions &Features,
174+
MangleContext &MContext);
172175
~CodeGenTBAA();
173176

174177
/// getTypeInfo - Get metadata used to describe accesses to objects of the

clang/test/CodeGen/tbaa-struct.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,11 @@ void copy10(NamedBitfields3 *a1, NamedBitfields3 *a2) {
162162
// CHECK-OLD: [[TS3]] = !{i64 0, i64 8, !{{.*}}, i64 0, i64 2, !{{.*}}, i64 4, i64 8, !{{.*}}}
163163
// CHECK-OLD: [[TS4]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]]}
164164
// CHECK-OLD: [[TS5]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 4, i64 1, [[TAG_CHAR]], i64 5, i64 1, [[TAG_CHAR]]}
165-
// CHECK-OLD: [[TS6]] = !{i64 0, i64 4, [[TAG_INT]], i64 1, i64 4, [[TAG_INT]], i64 2, i64 1, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE:!.+]]}
165+
// CHECK-OLD: [[TS6]] = !{i64 0, i64 2, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE:!.+]]}
166166
// CHECK-OLD: [[TAG_DOUBLE]] = !{[[DOUBLE:!.+]], [[DOUBLE]], i64 0}
167167
// CHECK-OLD [[DOUBLE]] = !{!"double", [[CHAR]], i64 0}
168-
// CHECK-OLD: [[TS7]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]], i64 3, i64 4, [[TAG_INT]], i64 3, i64 4, [[TAG_INT]], i64 4, i64 1, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE]], i64 16, i64 4, [[TAG_INT]]}
169-
// CHECK-OLD: [[TS8]] = !{i64 1, i64 4, [[TAG_INT]], i64 2, i64 4, [[TAG_INT]], i64 8, i64 8, [[TAG_DOUBLE]]}
168+
// CHECK-OLD: [[TS7]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]], i64 3, i64 1, [[TAG_CHAR]], i64 4, i64 1, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE]], i64 16, i64 1, [[TAG_CHAR]]}
169+
// CHECK-OLD: [[TS8]] = !{i64 0, i64 4, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE]]}
170170

171171
// CHECK-NEW-DAG: [[TYPE_char:!.*]] = !{{{.*}}, i64 1, !"omnipotent char"}
172172
// CHECK-NEW-DAG: [[TAG_char]] = !{[[TYPE_char]], [[TYPE_char]], i64 0, i64 0}

0 commit comments

Comments
 (0)