History log of /llvm-project-15.0.7/clang/lib/CodeGen/CGExpr.cpp (Results 551 – 575 of 1262)
Revision (<<< Hide revision tags) (Show revision tags >>>) Date Author Comments
Revision tags: llvmorg-3.3.0-rc3
# f3fabd2c 03-Jun-2013 Richard Smith <[email protected]>

Fix handling of pointers-to-members and comma expressions when
lifetime-extending temporaries in reference bindings.

llvm-svn: 183089


Revision tags: llvmorg-3.3.0-rc2
# 3b4c30b7 09-May-2013 Ben Langmuir <[email protected]>

CodeGen for CapturedStmts

EmitCapturedStmt creates a captured struct containing all of the captured
variables, and then emits a call to the outlined function. This is similar in
principle to EmitBl

CodeGen for CapturedStmts

EmitCapturedStmt creates a captured struct containing all of the captured
variables, and then emits a call to the outlined function. This is similar in
principle to EmitBlockLiteral.

GenerateCapturedFunction actually produces the outlined function. It is based
on GenerateBlockFunction, but is much simpler. The function type is determined
by the parameters that are in the CapturedDecl.

Some changes have been added to this patch that were reviewed as part of the
serialization patch and moving the parameters to the captured decl.

Differential Revision: http://llvm-reviews.chandlerc.com/D640

llvm-svn: 181536

show more ...


Revision tags: llvmorg-3.3.0-rc1
# dec348f7 03-May-2013 John McCall <[email protected]>

Correctly emit certain implicit references to 'self' even within
a lambda.

Bug #1 is that CGF's CurFuncDecl was "stuck" at lambda invocation
functions. Fix that by generally improving getNonClosure

Correctly emit certain implicit references to 'self' even within
a lambda.

Bug #1 is that CGF's CurFuncDecl was "stuck" at lambda invocation
functions. Fix that by generally improving getNonClosureContext
to look through lambdas and captured statements but only report
code contexts, which is generally what's wanted. Audit uses of
CurFuncDecl and getNonClosureAncestor for correctness.

Bug #2 is that lambdas weren't specially mapping 'self' when inside
an ObjC method. Fix that by removing the requirement for that
and using the normal EmitDeclRefLValue path in LoadObjCSelf.

rdar://13800041

llvm-svn: 181000

show more ...


# 0e52166b 27-Apr-2013 Manman Ren <[email protected]>

Struct-path aware TBAA: fix handling of may_alias attribute.

llvm-svn: 180656


# 852c9db7 20-Apr-2013 Richard Smith <[email protected]>

C++1y: Allow aggregates to have default initializers.

Add a CXXDefaultInitExpr, analogous to CXXDefaultArgExpr, and use it both in
CXXCtorInitializers and in InitListExprs to represent a default ini

C++1y: Allow aggregates to have default initializers.

Add a CXXDefaultInitExpr, analogous to CXXDefaultArgExpr, and use it both in
CXXCtorInitializers and in InitListExprs to represent a default initializer.

There's an additional complication here: because the default initializer can
refer to the initialized object via its 'this' pointer, we need to make sure
that 'this' points to the right thing within the evaluation.

llvm-svn: 179958

show more ...


# 2fd1d7ae 19-Apr-2013 Richard Smith <[email protected]>

Implement CodeGen for C++11 thread_local, following the Itanium ABI specification as discussed on cxx-abi-dev.

llvm-svn: 179858


# dbf74bae 14-Apr-2013 Richard Smith <[email protected]>

CodeGen support for function-local static thread_local variables with
non-constant constructors or non-trivial destructors. Plus bugfixes for
thread_local references bound to temporaries (the tempora

CodeGen support for function-local static thread_local variables with
non-constant constructors or non-trivial destructors. Plus bugfixes for
thread_local references bound to temporaries (the temporaries themselves are
lifetime-extended to become thread_local), and the corresponding case for
std::initializer_list.

llvm-svn: 179496

show more ...


# fd3834f7 13-Apr-2013 Richard Smith <[email protected]>

Annotate flavor of TLS variable (statically or dynamically initialized) onto the AST.

llvm-svn: 179447


# e1ad74e6 11-Apr-2013 Manman Ren <[email protected]>

Struct-path aware TBAA: uniformize scalar tag and path tag.

For struct-path aware TBAA, we used to use scalar type node as the scalar tag,
which has an incompatible format with the struct path tag.

Struct-path aware TBAA: uniformize scalar tag and path tag.

For struct-path aware TBAA, we used to use scalar type node as the scalar tag,
which has an incompatible format with the struct path tag. We now use the same
format: base type, access type and offset.

We also uniformize the scalar type node and the struct type node: name, a list
of pairs (offset + pointer to MDNode). For scalar type, we have a single pair.
These are to make implementaiton of aliasing rules easier.

llvm-svn: 179335

show more ...


# b1312a54 11-Apr-2013 Jordan Rose <[email protected]>

Force a load when creating a reference to a temporary copied from a bitfield.

For this source:
const int &ref = someStruct.bitfield;

We used to generate this AST:

DeclStmt [...]
`-VarDecl [.

Force a load when creating a reference to a temporary copied from a bitfield.

For this source:
const int &ref = someStruct.bitfield;

We used to generate this AST:

DeclStmt [...]
`-VarDecl [...] ref 'const int &'
`-MaterializeTemporaryExpr [...] 'const int' lvalue
`-ImplicitCastExpr [...] 'const int' lvalue <NoOp>
`-MemberExpr [...] 'int' lvalue bitfield .bitfield [...]
`-DeclRefExpr [...] 'struct X' lvalue ParmVar [...] 'someStruct' 'struct X'

Notice the lvalue inside the MaterializeTemporaryExpr, which is very
confusing (and caused an assertion to fire in the analyzer - PR15694).

We now generate this:

DeclStmt [...]
`-VarDecl [...] ref 'const int &'
`-MaterializeTemporaryExpr [...] 'const int' lvalue
`-ImplicitCastExpr [...] 'int' <LValueToRValue>
`-MemberExpr [...] 'int' lvalue bitfield .bitfield [...]
`-DeclRefExpr [...] 'struct X' lvalue ParmVar [...] 'someStruct' 'struct X'

Which makes a lot more sense. This allows us to remove code in both
CodeGen and AST that hacked around this special case.

The commit also makes Clang accept this (legal) C++11 code:

int &&ref = std::move(someStruct).bitfield

PR15694 / <rdar://problem/13600396>

llvm-svn: 179250

show more ...


# e9846f7f 06-Apr-2013 Douglas Gregor <[email protected]>

<rdar://problem/13325066> Destroy std::initializer_list temporaries whose lifetime has been extended by reference binding.

llvm-svn: 178939


# c451e576 04-Apr-2013 Manman Ren <[email protected]>

Initial support for struct-path aware TBAA.

Added TBAABaseType and TBAAOffset in LValue. These two fields are initialized to
the actual type and 0, and are updated in EmitLValueForField.
Path-aware

Initial support for struct-path aware TBAA.

Added TBAABaseType and TBAAOffset in LValue. These two fields are initialized to
the actual type and 0, and are updated in EmitLValueForField.
Path-aware TBAA tags are enabled for EmitLoadOfScalar and EmitStoreOfScalar.
Added command line option -struct-path-tbaa.

llvm-svn: 178797

show more ...


# 092d9e8f 04-Apr-2013 Manman Ren <[email protected]>

revert r178784 since it does not have a commit message

llvm-svn: 178796


# 037d2b25 04-Apr-2013 Manman Ren <[email protected]>

Index: include/clang/Driver/CC1Options.td
===================================================================
--- include/clang/Driver/CC1Options.td (revision 178718)
+++ include/clang/Driver/CC1Opti

Index: include/clang/Driver/CC1Options.td
===================================================================
--- include/clang/Driver/CC1Options.td (revision 178718)
+++ include/clang/Driver/CC1Options.td (working copy)
@@ -161,6 +161,8 @@
HelpText<"Use register sized accesses to bit-fields, when possible.">;
def relaxed_aliasing : Flag<["-"], "relaxed-aliasing">,
HelpText<"Turn off Type Based Alias Analysis">;
+def struct_path_tbaa : Flag<["-"], "struct-path-tbaa">,
+ HelpText<"Turn on struct-path aware Type Based Alias Analysis">;
def masm_verbose : Flag<["-"], "masm-verbose">,
HelpText<"Generate verbose assembly output">;
def mcode_model : Separate<["-"], "mcode-model">,
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td (revision 178718)
+++ include/clang/Driver/Options.td (working copy)
@@ -587,6 +587,7 @@
Flags<[CC1Option]>, HelpText<"Disable spell-checking">;
def fno_stack_protector : Flag<["-"], "fno-stack-protector">, Group<f_Group>;
def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group<f_Group>;
+def fstruct_path_tbaa : Flag<["-"], "fstruct-path-tbaa">, Group<f_Group>;
def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group<f_Group>;
def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group<f_Group>;
def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group<f_Group>,
Index: include/clang/Frontend/CodeGenOptions.def
===================================================================
--- include/clang/Frontend/CodeGenOptions.def (revision 178718)
+++ include/clang/Frontend/CodeGenOptions.def (working copy)
@@ -85,6 +85,7 @@
VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified.
CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions.
CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled.
+CODEGENOPT(StructPathTBAA , 1, 0) ///< Whether or not to use struct-path TBAA.
CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels.
CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero
///< offset in AddressSanitizer.
Index: lib/CodeGen/CGExpr.cpp
===================================================================
--- lib/CodeGen/CGExpr.cpp (revision 178718)
+++ lib/CodeGen/CGExpr.cpp (working copy)
@@ -1044,7 +1044,8 @@
llvm::Value *CodeGenFunction::EmitLoadOfScalar(LValue lvalue) {
return EmitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(),
lvalue.getAlignment().getQuantity(),
- lvalue.getType(), lvalue.getTBAAInfo());
+ lvalue.getType(), lvalue.getTBAAInfo(),
+ lvalue.getTBAABaseType(), lvalue.getTBAAOffset());
}

static bool hasBooleanRepresentation(QualType Ty) {
@@ -1106,7 +1107,9 @@

llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
unsigned Alignment, QualType Ty,
- llvm::MDNode *TBAAInfo) {
+ llvm::MDNode *TBAAInfo,
+ QualType TBAABaseType,
+ uint64_t TBAAOffset) {
// For better performance, handle vector loads differently.
if (Ty->isVectorType()) {
llvm::Value *V;
@@ -1158,8 +1161,11 @@
Load->setVolatile(true);
if (Alignment)
Load->setAlignment(Alignment);
- if (TBAAInfo)
- CGM.DecorateInstruction(Load, TBAAInfo);
+ if (TBAAInfo) {
+ llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo,
+ TBAAOffset);
+ CGM.DecorateInstruction(Load, TBAAPath);
+ }

if ((SanOpts->Bool && hasBooleanRepresentation(Ty)) ||
(SanOpts->Enum && Ty->getAs<EnumType>())) {
@@ -1217,7 +1223,8 @@
bool Volatile, unsigned Alignment,
QualType Ty,
llvm::MDNode *TBAAInfo,
- bool isInit) {
+ bool isInit, QualType TBAABaseType,
+ uint64_t TBAAOffset) {

// Handle vectors differently to get better performance.
if (Ty->isVectorType()) {
@@ -1268,15 +1275,19 @@
llvm::StoreInst *Store = Builder.CreateStore(Value, Addr, Volatile);
if (Alignment)
Store->setAlignment(Alignment);
- if (TBAAInfo)
- CGM.DecorateInstruction(Store, TBAAInfo);
+ if (TBAAInfo) {
+ llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo,
+ TBAAOffset);
+ CGM.DecorateInstruction(Store, TBAAPath);
+ }
}

void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue,
bool isInit) {
EmitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(),
lvalue.getAlignment().getQuantity(), lvalue.getType(),
- lvalue.getTBAAInfo(), isInit);
+ lvalue.getTBAAInfo(), isInit, lvalue.getTBAABaseType(),
+ lvalue.getTBAAOffset());
}

/// EmitLoadOfLValue - Given an expression that represents a value lvalue, this
@@ -2494,9 +2505,12 @@

llvm::Value *addr = base.getAddress();
unsigned cvr = base.getVRQualifiers();
+ bool TBAAPath = CGM.getCodeGenOpts().StructPathTBAA;
if (rec->isUnion()) {
// For unions, there is no pointer adjustment.
assert(!type->isReferenceType() && "union has reference member");
+ // TODO: handle path-aware TBAA for union.
+ TBAAPath = false;
} else {
// For structs, we GEP to the field that the record layout suggests.
unsigned idx = CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field);
@@ -2508,6 +2522,8 @@
if (cvr & Qualifiers::Volatile) load->setVolatile(true);
load->setAlignment(alignment.getQuantity());

+ // Loading the reference will disable path-aware TBAA.
+ TBAAPath = false;
if (CGM.shouldUseTBAA()) {
llvm::MDNode *tbaa;
if (mayAlias)
@@ -2541,6 +2557,16 @@

LValue LV = MakeAddrLValue(addr, type, alignment);
LV.getQuals().addCVRQualifiers(cvr);
+ if (TBAAPath) {
+ const ASTRecordLayout &Layout =
+ getContext().getASTRecordLayout(field->getParent());
+ // Set the base type to be the base type of the base LValue and
+ // update offset to be relative to the base type.
+ LV.setTBAABaseType(base.getTBAABaseType());
+ LV.setTBAAOffset(base.getTBAAOffset() +
+ Layout.getFieldOffset(field->getFieldIndex()) /
+ getContext().getCharWidth());
+ }

// __weak attribute on a field is ignored.
if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak)
Index: lib/CodeGen/CGValue.h
===================================================================
--- lib/CodeGen/CGValue.h (revision 178718)
+++ lib/CodeGen/CGValue.h (working copy)
@@ -157,6 +157,11 @@

Expr *BaseIvarExp;

+ /// Used by struct-path-aware TBAA.
+ QualType TBAABaseType;
+ /// Offset relative to the base type.
+ uint64_t TBAAOffset;
+
/// TBAAInfo - TBAA information to attach to dereferences of this LValue.
llvm::MDNode *TBAAInfo;

@@ -175,6 +180,10 @@
this->ImpreciseLifetime = false;
this->ThreadLocalRef = false;
this->BaseIvarExp = 0;
+
+ // Initialize fields for TBAA.
+ this->TBAABaseType = Type;
+ this->TBAAOffset = 0;
this->TBAAInfo = TBAAInfo;
}

@@ -232,6 +241,12 @@
Expr *getBaseIvarExp() const { return BaseIvarExp; }
void setBaseIvarExp(Expr *V) { BaseIvarExp = V; }

+ QualType getTBAABaseType() const { return TBAABaseType; }
+ void setTBAABaseType(QualType T) { TBAABaseType = T; }
+
+ uint64_t getTBAAOffset() const { return TBAAOffset; }
+ void setTBAAOffset(uint64_t O) { TBAAOffset = O; }
+
llvm::MDNode *getTBAAInfo() const { return TBAAInfo; }
void setTBAAInfo(llvm::MDNode *N) { TBAAInfo = N; }

Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h (revision 178718)
+++ lib/CodeGen/CodeGenFunction.h (working copy)
@@ -2211,7 +2211,9 @@
/// the LLVM value representation.
llvm::Value *EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
unsigned Alignment, QualType Ty,
- llvm::MDNode *TBAAInfo = 0);
+ llvm::MDNode *TBAAInfo = 0,
+ QualType TBAABaseTy = QualType(),
+ uint64_t TBAAOffset = 0);

/// EmitLoadOfScalar - Load a scalar value from an address, taking
/// care to appropriately convert from the memory representation to
@@ -2224,7 +2226,9 @@
/// the LLVM value representation.
void EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr,
bool Volatile, unsigned Alignment, QualType Ty,
- llvm::MDNode *TBAAInfo = 0, bool isInit=false);
+ llvm::MDNode *TBAAInfo = 0, bool isInit = false,
+ QualType TBAABaseTy = QualType(),
+ uint64_t TBAAOffset = 0);

/// EmitStoreOfScalar - Store a scalar value to an address, taking
/// care to appropriately convert from the memory representation to
Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp (revision 178718)
+++ lib/CodeGen/CodeGenModule.cpp (working copy)
@@ -227,6 +227,20 @@
return TBAA->getTBAAStructInfo(QTy);
}

+llvm::MDNode *CodeGenModule::getTBAAStructTypeInfo(QualType QTy) {
+ if (!TBAA)
+ return 0;
+ return TBAA->getTBAAStructTypeInfo(QTy);
+}
+
+llvm::MDNode *CodeGenModule::getTBAAStructTagInfo(QualType BaseTy,
+ llvm::MDNode *AccessN,
+ uint64_t O) {
+ if (!TBAA)
+ return 0;
+ return TBAA->getTBAAStructTagInfo(BaseTy, AccessN, O);
+}
+
void CodeGenModule::DecorateInstruction(llvm::Instruction *Inst,
llvm::MDNode *TBAAInfo) {
Inst->setMetadata(llvm::LLVMContext::MD_tbaa, TBAAInfo);
Index: lib/CodeGen/CodeGenModule.h
===================================================================
--- lib/CodeGen/CodeGenModule.h (revision 178718)
+++ lib/CodeGen/CodeGenModule.h (working copy)
@@ -501,6 +501,11 @@
llvm::MDNode *getTBAAInfo(QualType QTy);
llvm::MDNode *getTBAAInfoForVTablePtr();
llvm::MDNode *getTBAAStructInfo(QualType QTy);
+ /// Return the MDNode in the type DAG for the given struct type.
+ llvm::MDNode *getTBAAStructTypeInfo(QualType QTy);
+ /// Return the path-aware tag for given base type, access node and offset.
+ llvm::MDNode *getTBAAStructTagInfo(QualType BaseTy, llvm::MDNode *AccessN,
+ uint64_t O);

bool isTypeConstant(QualType QTy, bool ExcludeCtorDtor);

Index: lib/CodeGen/CodeGenTBAA.cpp
===================================================================
--- lib/CodeGen/CodeGenTBAA.cpp (revision 178718)
+++ lib/CodeGen/CodeGenTBAA.cpp (working copy)
@@ -21,6 +21,7 @@
#include "clang/AST/Mangle.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Frontend/CodeGenOptions.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
@@ -225,3 +226,87 @@
// For now, handle any other kind of type conservatively.
return StructMetadataCache[Ty] = NULL;
}
+
+/// Check if the given type can be handled by path-aware TBAA.
+static bool isTBAAPathStruct(QualType QTy) {
+ if (const RecordType *TTy = QTy->getAs<RecordType>()) {
+ const RecordDecl *RD = TTy->getDecl()->getDefinition();
+ // RD can be struct, union, class, interface or enum.
+ // For now, we only handle struct.
+ if (RD->isStruct() && !RD->hasFlexibleArrayMember())
+ return true;
+ }
+ return false;
+}
+
+llvm::MDNode *
+CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) {
+ const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
+ assert(isTBAAPathStruct(QTy));
+
+ if (llvm::MDNode *N = StructTypeMetadataCache[Ty])
+ return N;
+
+ if (const RecordType *TTy = QTy->getAs<RecordType>()) {
+ const RecordDecl *RD = TTy->getDecl()->getDefinition();
+
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ SmallVector <std::pair<uint64_t, llvm::MDNode*>, 4> Fields;
+ // To reduce the size of MDNode for a given struct type, we only output
+ // once for all the fields with the same scalar types.
+ // Offsets for scalar fields in the type DAG are not used.
+ llvm::SmallSet <llvm::MDNode*, 4> ScalarFieldTypes;
+ unsigned idx = 0;
+ for (RecordDecl::field_iterator i = RD->field_begin(),
+ e = RD->field_end(); i != e; ++i, ++idx) {
+ QualType FieldQTy = i->getType();
+ llvm::MDNode *FieldNode;
+ if (isTBAAPathStruct(FieldQTy))
+ FieldNode = getTBAAStructTypeInfo(FieldQTy);
+ else {
+ FieldNode = getTBAAInfo(FieldQTy);
+ // Ignore this field if the type already exists.
+ if (ScalarFieldTypes.count(FieldNode))
+ continue;
+ ScalarFieldTypes.insert(FieldNode);
+ }
+ if (!FieldNode)
+ return StructTypeMetadataCache[Ty] = NULL;
+ Fields.push_back(std::make_pair(
+ Layout.getFieldOffset(idx) / Context.getCharWidth(), FieldNode));
+ }
+
+ // TODO: This is using the RTTI name. Is there a better way to get
+ // a unique string for a type?
+ SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ MContext.mangleCXXRTTIName(QualType(Ty, 0), Out);
+ Out.flush();
+ // Create the struct type node with a vector of pairs (offset, type).
+ return StructTypeMetadataCache[Ty] =
+ MDHelper.createTBAAStructTypeNode(OutName, Fields);
+ }
+
+ return StructMetadataCache[Ty] = NULL;
+}
+
+llvm::MDNode *
+CodeGenTBAA::getTBAAStructTagInfo(QualType BaseQTy, llvm::MDNode *AccessNode,
+ uint64_t Offset) {
+ if (!CodeGenOpts.StructPathTBAA)
+ return AccessNode;
+
+ const Type *BTy = Context.getCanonicalType(BaseQTy).getTypePtr();
+ TBAAPathTag PathTag = TBAAPathTag(BTy, AccessNode, Offset);
+ if (llvm::MDNode *N = StructTagMetadataCache[PathTag])
+ return N;
+
+ llvm::MDNode *BNode = 0;
+ if (isTBAAPathStruct(BaseQTy))
+ BNode = getTBAAStructTypeInfo(BaseQTy);
+ if (!BNode)
+ return StructTagMetadataCache[PathTag] = AccessNode;
+
+ return StructTagMetadataCache[PathTag] =
+ MDHelper.createTBAAStructTagNode(BNode, AccessNode, Offset);
+}
Index: lib/CodeGen/CodeGenTBAA.h
===================================================================
--- lib/CodeGen/CodeGenTBAA.h (revision 178718)
+++ lib/CodeGen/CodeGenTBAA.h (working copy)
@@ -35,6 +35,14 @@
namespace CodeGen {
class CGRecordLayout;

+ struct TBAAPathTag {
+ TBAAPathTag(const Type *B, const llvm::MDNode *A, uint64_t O)
+ : BaseT(B), AccessN(A), Offset(O) {}
+ const Type *BaseT;
+ const llvm::MDNode *AccessN;
+ uint64_t Offset;
+ };
+
/// CodeGenTBAA - This class organizes the cross-module state that is used
/// while lowering AST types to LLVM types.
class CodeGenTBAA {
@@ -46,8 +54,13 @@
// MDHelper - Helper for creating metadata.
llvm::MDBuilder MDHelper;

- /// MetadataCache - This maps clang::Types to llvm::MDNodes describing them.
+ /// MetadataCache - This maps clang::Types to scalar llvm::MDNodes describing
+ /// them.
llvm::DenseMap<const Type *, llvm::MDNode *> MetadataCache;
+ /// This maps clang::Types to a struct node in the type DAG.
+ llvm::DenseMap<const Type *, llvm::MDNode *> StructTypeMetadataCache;
+ /// This maps TBAAPathTags to a tag node.
+ llvm::DenseMap<TBAAPathTag, llvm::MDNode *> StructTagMetadataCache;

/// StructMetadataCache - This maps clang::Types to llvm::MDNodes describing
/// them for struct assignments.
@@ -89,9 +102,49 @@
/// getTBAAStructInfo - Get the TBAAStruct MDNode to be used for a memcpy of
/// the given type.
llvm::MDNode *getTBAAStructInfo(QualType QTy);
+
+ /// Get the MDNode in the type DAG for given struct type QType.
+ llvm::MDNode *getTBAAStructTypeInfo(QualType QType);
+ /// Get the tag MDNode for a given base type, the actual sclar access MDNode
+ /// and offset into the base type.
+ llvm::MDNode *getTBAAStructTagInfo(QualType BaseQType,
+ llvm::MDNode *AccessNode, uint64_t Offset);
};

} // end namespace CodeGen
} // end namespace clang

+namespace llvm {
+
+template<> struct DenseMapInfo<clang::CodeGen::TBAAPathTag> {
+ static clang::CodeGen::TBAAPathTag getEmptyKey() {
+ return clang::CodeGen::TBAAPathTag(
+ DenseMapInfo<const clang::Type *>::getEmptyKey(),
+ DenseMapInfo<const MDNode *>::getEmptyKey(),
+ DenseMapInfo<uint64_t>::getEmptyKey());
+ }
+
+ static clang::CodeGen::TBAAPathTag getTombstoneKey() {
+ return clang::CodeGen::TBAAPathTag(
+ DenseMapInfo<const clang::Type *>::getTombstoneKey(),
+ DenseMapInfo<const MDNode *>::getTombstoneKey(),
+ DenseMapInfo<uint64_t>::getTombstoneKey());
+ }
+
+ static unsigned getHashValue(const clang::CodeGen::TBAAPathTag &Val) {
+ return DenseMapInfo<const clang::Type *>::getHashValue(Val.BaseT) ^
+ DenseMapInfo<const MDNode *>::getHashValue(Val.AccessN) ^
+ DenseMapInfo<uint64_t>::getHashValue(Val.Offset);
+ }
+
+ static bool isEqual(const clang::CodeGen::TBAAPathTag &LHS,
+ const clang::CodeGen::TBAAPathTag &RHS) {
+ return LHS.BaseT == RHS.BaseT &&
+ LHS.AccessN == RHS.AccessN &&
+ LHS.Offset == RHS.Offset;
+ }
+};
+
+} // end namespace llvm
+
#endif
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp (revision 178718)
+++ lib/Driver/Tools.cpp (working copy)
@@ -2105,6 +2105,8 @@
options::OPT_fno_strict_aliasing,
getToolChain().IsStrictAliasingDefault()))
CmdArgs.push_back("-relaxed-aliasing");
+ if (Args.hasArg(options::OPT_fstruct_path_tbaa))
+ CmdArgs.push_back("-struct-path-tbaa");
if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums,
false))
CmdArgs.push_back("-fstrict-enums");
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp (revision 178718)
+++ lib/Frontend/CompilerInvocation.cpp (working copy)
@@ -324,6 +324,7 @@
Opts.UseRegisterSizedBitfieldAccess = Args.hasArg(
OPT_fuse_register_sized_bitfield_access);
Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing);
+ Opts.StructPathTBAA = Args.hasArg(OPT_struct_path_tbaa);
Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags);
Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants);
Opts.NoCommon = Args.hasArg(OPT_fno_common);
Index: test/CodeGen/tbaa.cpp
===================================================================
--- test/CodeGen/tbaa.cpp (revision 0)
+++ test/CodeGen/tbaa.cpp (working copy)
@@ -0,0 +1,217 @@
+// RUN: %clang_cc1 -O1 -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -O1 -struct-path-tbaa -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s -check-prefix=PATH
+// Test TBAA metadata generated by front-end.
+
+#include <stdint.h>
+typedef struct
+{
+ uint16_t f16;
+ uint32_t f32;
+ uint16_t f16_2;
+ uint32_t f32_2;
+} StructA;
+typedef struct
+{
+ uint16_t f16;
+ StructA a;
+ uint32_t f32;
+} StructB;
+typedef struct
+{
+ uint16_t f16;
+ StructB b;
+ uint32_t f32;
+} StructC;
+typedef struct
+{
+ uint16_t f16;
+ StructB b;
+ uint32_t f32;
+ uint8_t f8;
+} StructD;
+
+typedef struct
+{
+ uint16_t f16;
+ uint32_t f32;
+} StructS;
+typedef struct
+{
+ uint16_t f16;
+ uint32_t f32;
+} StructS2;
+
+uint32_t g(uint32_t *s, StructA *A, uint64_t count) {
+// CHECK: define i32 @{{.*}}(
+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4
+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4
+// PATH: define i32 @{{.*}}(
+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !4
+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !5
+ *s = 1;
+ A->f32 = 4;
+ return *s;
+}
+
+uint32_t g2(uint32_t *s, StructA *A, uint64_t count) {
+// CHECK: define i32 @{{.*}}(
+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4
+// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5
+// PATH: define i32 @{{.*}}(
+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !4
+// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !8
+ *s = 1;
+ A->f16 = 4;
+ return *s;
+}
+
+uint32_t g3(StructA *A, StructB *B, uint64_t count) {
+// CHECK: define i32 @{{.*}}(
+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4
+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4
+// PATH: define i32 @{{.*}}(
+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5
+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !9
+ A->f32 = 1;
+ B->a.f32 = 4;
+ return A->f32;
+}
+
+uint32_t g4(StructA *A, StructB *B, uint64_t count) {
+// CHECK: define i32 @{{.*}}(
+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4
+// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5
+// PATH: define i32 @{{.*}}(
+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5
+// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !11
+ A->f32 = 1;
+ B->a.f16 = 4;
+ return A->f32;
+}
+
+uint32_t g5(StructA *A, StructB *B, uint64_t count) {
+// CHECK: define i32 @{{.*}}(
+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4
+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4
+// PATH: define i32 @{{.*}}(
+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5
+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !12
+ A->f32 = 1;
+ B->f32 = 4;
+ return A->f32;
+}
+
+uint32_t g6(StructA *A, StructB *B, uint64_t count) {
+// CHECK: define i32 @{{.*}}(
+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4
+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4
+// PATH: define i32 @{{.*}}(
+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5
+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !13
+ A->f32 = 1;
+ B->a.f32_2 = 4;
+ return A->f32;
+}
+
+uint32_t g7(StructA *A, StructS *S, uint64_t count) {
+// CHECK: define i32 @{{.*}}(
+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4
+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4
+// PATH: define i32 @{{.*}}(
+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5
+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !14
+ A->f32 = 1;
+ S->f32 = 4;
+ return A->f32;
+}
+
+uint32_t g8(StructA *A, StructS *S, uint64_t count) {
+// CHECK: define i32 @{{.*}}(
+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4
+// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5
+// PATH: define i32 @{{.*}}(
+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5
+// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !16
+ A->f32 = 1;
+ S->f16 = 4;
+ return A->f32;
+}
+
+uint32_t g9(StructS *S, StructS2 *S2, uint64_t count) {
+// CHECK: define i32 @{{.*}}(
+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4
+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4
+// PATH: define i32 @{{.*}}(
+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !14
+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !17
+ S->f32 = 1;
+ S2->f32 = 4;
+ return S->f32;
+}
+
+uint32_t g10(StructS *S, StructS2 *S2, uint64_t count) {
+// CHECK: define i32 @{{.*}}(
+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4
+// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5
+// PATH: define i32 @{{.*}}(
+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !14
+// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !19
+ S->f32 = 1;
+ S2->f16 = 4;
+ return S->f32;
+}
+
+uint32_t g11(StructC *C, StructD *D, uint64_t count) {
+// CHECK: define i32 @{{.*}}(
+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4
+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4
+// PATH: define i32 @{{.*}}(
+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !20
+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !22
+ C->b.a.f32 = 1;
+ D->b.a.f32 = 4;
+ return C->b.a.f32;
+}
+
+uint32_t g12(StructC *C, StructD *D, uint64_t count) {
+// CHECK: define i32 @{{.*}}(
+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4
+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4
+// TODO: differentiate the two accesses.
+// PATH: define i32 @{{.*}}(
+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !9
+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !9
+ StructB *b1 = &(C->b);
+ StructB *b2 = &(D->b);
+ // b1, b2 have different context.
+ b1->a.f32 = 1;
+ b2->a.f32 = 4;
+ return b1->a.f32;
+}
+
+// CHECK: !1 = metadata !{metadata !"omnipotent char", metadata !2}
+// CHECK: !2 = metadata !{metadata !"Simple C/C++ TBAA"}
+// CHECK: !4 = metadata !{metadata !"int", metadata !1}
+// CHECK: !5 = metadata !{metadata !"short", metadata !1}
+
+// PATH: !1 = metadata !{metadata !"omnipotent char", metadata !2}
+// PATH: !4 = metadata !{metadata !"int", metadata !1}
+// PATH: !5 = metadata !{metadata !6, metadata !4, i64 4}
+// PATH: !6 = metadata !{metadata !"_ZTS7StructA", i64 0, metadata !7, i64 4, metadata !4}
+// PATH: !7 = metadata !{metadata !"short", metadata !1}
+// PATH: !8 = metadata !{metadata !6, metadata !7, i64 0}
+// PATH: !9 = metadata !{metadata !10, metadata !4, i64 8}
+// PATH: !10 = metadata !{metadata !"_ZTS7StructB", i64 0, metadata !7, i64 4, metadata !6, i64 20, metadata !4}
+// PATH: !11 = metadata !{metadata !10, metadata !7, i64 4}
+// PATH: !12 = metadata !{metadata !10, metadata !4, i64 20}
+// PATH: !13 = metadata !{metadata !10, metadata !4, i64 16}
+// PATH: !14 = metadata !{metadata !15, metadata !4, i64 4}
+// PATH: !15 = metadata !{metadata !"_ZTS7StructS", i64 0, metadata !7, i64 4, metadata !4}
+// PATH: !16 = metadata !{metadata !15, metadata !7, i64 0}
+// PATH: !17 = metadata !{metadata !18, metadata !4, i64 4}
+// PATH: !18 = metadata !{metadata !"_ZTS8StructS2", i64 0, metadata !7, i64 4, metadata !4}
+// PATH: !19 = metadata !{metadata !18, metadata !7, i64 0}
+// PATH: !20 = metadata !{metadata !21, metadata !4, i64 12}
+// PATH: !21 = metadata !{metadata !"_ZTS7StructC", i64 0, metadata !7, i64 4, metadata !10, i64 28, metadata !4}
+// PATH: !22 = metadata !{metadata !23, metadata !4, i64 12}
+// PATH: !23 = metadata !{metadata !"_ZTS7StructD", i64 0, metadata !7, i64 4, metadata !10, i64 28, metadata !4, i64 32, metadata !1}

llvm-svn: 178784

show more ...


# 48366f7a 22-Mar-2013 Richard Smith <[email protected]>

ubsan: Pass floating-point arguments to the runtime by value if they fit the
value argument. If not, be sure we don't accidentally use a dynamic alloca.

llvm-svn: 177690


# 5acf8a3a 15-Mar-2013 Adrian Prantl <[email protected]>

Force column info only for direct inlined functions. This should strike
the balance between expected behavior and compatibility with the gdb
testsuite.
(GDB gets confused if we break an expression in

Force column info only for direct inlined functions. This should strike
the balance between expected behavior and compatibility with the gdb
testsuite.
(GDB gets confused if we break an expression into multiple debug
stmts so we enable this behavior only for inlined functions. For the
full experience people can still use -gcolumn-info.)

llvm-svn: 177164

show more ...


# cdda29c9 13-Mar-2013 John McCall <[email protected]>

Tighten up the rules for precise lifetime and document
the requirements on the ARC optimizer.

rdar://13407451

llvm-svn: 176924


# c782242a 12-Mar-2013 Adrian Prantl <[email protected]>

Force column info to be generated for call expressions so we can
differentiate multiple inlined call sites on the same line
in the debug info.

Fixes rdar://problem/13036237

llvm-svn: 176895


# 36f89ccc 09-Mar-2013 Benjamin Kramer <[email protected]>

Make helper function static.

llvm-svn: 176767


# a8ec7eb9 07-Mar-2013 John McCall <[email protected]>

Promote atomic type sizes up to a power of two, capped by
MaxAtomicPromoteWidth. Fix a ton of terrible bugs with
_Atomic types and (non-intrinsic-mediated) loads and stores
thereto.

llvm-svn: 176658


# fc207f2d 07-Mar-2013 John McCall <[email protected]>

Move the atomics code into its own file.

llvm-svn: 176657


# 47fb9508 07-Mar-2013 John McCall <[email protected]>

Change hasAggregateLLVMType, which conflates complex and
aggregate types in a profoundly wrong way that has to be
worked around in every call site, to getEvaluationKind,
which classifies and distingu

Change hasAggregateLLVMType, which conflates complex and
aggregate types in a profoundly wrong way that has to be
worked around in every call site, to getEvaluationKind,
which classifies and distinguishes between all of these
cases.

Also, normalize the API for loading and storing complexes.

I'm working on a larger patch and wanted to pull these
changes out, but it would have be annoying to detangle
them from each other.

llvm-svn: 176656

show more ...


# 882987f3 28-Feb-2013 John McCall <[email protected]>

Use the actual ABI-determined C calling convention for runtime
calls and declarations.

LLVM has a default CC determined by the target triple. This is
not always the actual default CC for the ABI we

Use the actual ABI-determined C calling convention for runtime
calls and declarations.

LLVM has a default CC determined by the target triple. This is
not always the actual default CC for the ABI we've been asked to
target, and so we sometimes find ourselves annotating all user
functions with an explicit calling convention. Since these
calling conventions usually agree for the simple set of argument
types passed to most runtime functions, using the LLVM-default CC
in principle has no effect. However, the LLVM optimizer goes
into histrionics if it sees this kind of formal CC mismatch,
since it has no concept of CC compatibility. Therefore, if this
module happens to define the "runtime" function, or got LTO'ed
with such a definition, we can miscompile; so it's quite
important to get this right.

Defining runtime functions locally is quite common in embedded
applications.

llvm-svn: 176286

show more ...


# 2847b220 24-Feb-2013 Richard Smith <[email protected]>

PR15338: Don't assert if -fsanitize=bounds sees array indexing on an incomplete
array type.

llvm-svn: 175982


# 539e4a77 23-Feb-2013 Richard Smith <[email protected]>

ubsan: Emit bounds checks for array indexing, vector indexing, and (in really simple cases) pointer arithmetic. This augments the existing bounds checking with language-level array bounds information

ubsan: Emit bounds checks for array indexing, vector indexing, and (in really simple cases) pointer arithmetic. This augments the existing bounds checking with language-level array bounds information.

llvm-svn: 175949

show more ...


1...<<21222324252627282930>>...51