31 changes: 31 additions & 0 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3473,6 +3473,37 @@ builtin, the mangler emits their usual pattern without any special treatment.
// Computes a unique stable name for the given type.
constexpr const char * __builtin_sycl_unique_stable_name( type-id );
``__builtin_popcountg``
-----------------------
``__builtin_popcountg`` returns the number of 1 bits in the argument. The
argument can be of any integer type.
**Syntax**:
.. code-block:: c++
int __builtin_popcountg(type x)
**Examples**:
.. code-block:: c++
int x = 1;
int x_pop = __builtin_popcountg(x);
unsigned long y = 3;
int y_pop = __builtin_popcountg(y);
_BitInt(128) z = 7;
int z_pop = __builtin_popcountg(z);
**Description**:
``__builtin_popcountg`` is meant to be a type-generic alternative to the
``__builtin_popcount{,l,ll}`` builtins, with support for other integer types,
such as ``__int128`` and C23 ``_BitInt(N)``.
Multiprecision Arithmetic Builtins
----------------------------------
Expand Down
14 changes: 7 additions & 7 deletions clang/docs/LibASTMatchersReference.html
Original file line number Diff line number Diff line change
Expand Up @@ -7049,7 +7049,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
</pre></td></tr>


<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>&gt;</td><td class="name" onclick="toggle('hasFoldInit0')"><a name="hasFoldInit0Anchor">hasFoldInit</a></td><td>ast_matchers::Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMacher</td></tr>
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>&gt;</td><td class="name" onclick="toggle('hasFoldInit0')"><a name="hasFoldInit0Anchor">hasFoldInit</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMacher</td></tr>
<tr><td colspan="4" class="doc" id="hasFoldInit0"><pre>Matches the operand that does not contain the parameter pack.

Example matches `(0 + ... + args)` and `(args * ... * 1)`
Expand Down Expand Up @@ -7089,7 +7089,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
</pre></td></tr>


<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>&gt;</td><td class="name" onclick="toggle('hasPattern0')"><a name="hasPattern0Anchor">hasPattern</a></td><td>ast_matchers::Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMacher</td></tr>
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>&gt;</td><td class="name" onclick="toggle('hasPattern0')"><a name="hasPattern0Anchor">hasPattern</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMacher</td></tr>
<tr><td colspan="4" class="doc" id="hasPattern0"><pre>Matches the operand that contains the parameter pack.

Example matches `(0 + ... + args)`
Expand Down Expand Up @@ -7859,7 +7859,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
</pre></td></tr>


<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>&gt;</td><td class="name" onclick="toggle('forEachTemplateArgument0')"><a name="forEachTemplateArgument0Anchor">forEachTemplateArgument</a></td><td>clang::ast_matchers::Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>&gt;</td><td class="name" onclick="toggle('forEachTemplateArgument0')"><a name="forEachTemplateArgument0Anchor">forEachTemplateArgument</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="forEachTemplateArgument0"><pre>Matches classTemplateSpecialization, templateSpecializationType and
functionDecl nodes where the template argument matches the inner matcher.
This matcher may produce multiple matches.
Expand Down Expand Up @@ -8454,7 +8454,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
</pre></td></tr>


<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('ignoringElidableConstructorCall0')"><a name="ignoringElidableConstructorCall0Anchor">ignoringElidableConstructorCall</a></td><td>ast_matchers::Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('ignoringElidableConstructorCall0')"><a name="ignoringElidableConstructorCall0Anchor">ignoringElidableConstructorCall</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="ignoringElidableConstructorCall0"><pre>Matches expressions that match InnerMatcher that are possibly wrapped in an
elidable constructor and other corresponding bookkeeping nodes.

Expand Down Expand Up @@ -8691,7 +8691,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
</pre></td></tr>


<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('forEachTemplateArgument2')"><a name="forEachTemplateArgument2Anchor">forEachTemplateArgument</a></td><td>clang::ast_matchers::Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('forEachTemplateArgument2')"><a name="forEachTemplateArgument2Anchor">forEachTemplateArgument</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="forEachTemplateArgument2"><pre>Matches classTemplateSpecialization, templateSpecializationType and
functionDecl nodes where the template argument matches the inner matcher.
This matcher may produce multiple matches.
Expand Down Expand Up @@ -8959,7 +8959,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
</pre></td></tr>


<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InitListExpr.html">InitListExpr</a>&gt;</td><td class="name" onclick="toggle('hasInit0')"><a name="hasInit0Anchor">hasInit</a></td><td>unsigned N, ast_matchers::Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InitListExpr.html">InitListExpr</a>&gt;</td><td class="name" onclick="toggle('hasInit0')"><a name="hasInit0Anchor">hasInit</a></td><td>unsigned N, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasInit0"><pre>Matches the n'th item of an initializer list expression.

Example matches y.
Expand Down Expand Up @@ -10026,7 +10026,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
</pre></td></tr>


<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;</td><td class="name" onclick="toggle('forEachTemplateArgument1')"><a name="forEachTemplateArgument1Anchor">forEachTemplateArgument</a></td><td>clang::ast_matchers::Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;</td><td class="name" onclick="toggle('forEachTemplateArgument1')"><a name="forEachTemplateArgument1Anchor">forEachTemplateArgument</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="forEachTemplateArgument1"><pre>Matches classTemplateSpecialization, templateSpecializationType and
functionDecl nodes where the template argument matches the inner matcher.
This matcher may produce multiple matches.
Expand Down
7 changes: 7 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,9 @@ Improvements to Clang's time-trace

Bug Fixes in This Version
-------------------------
- Fixed missing warnings when comparing mismatched enumeration constants
in C (`#29217 <https://github.com/llvm/llvm-project/issues/29217>`).

- Clang now accepts elaborated-type-specifiers that explicitly specialize
a member class template for an implicit instantiation of a class template.

Expand Down Expand Up @@ -283,6 +286,10 @@ Bug Fixes to C++ Support
(`#78524 <https://github.com/llvm/llvm-project/issues/78524>`_)
- Clang no longer instantiates the exception specification of discarded candidate function
templates when determining the primary template of an explicit specialization.
- Fixed a crash in Microsoft compatibility mode where unqualified dependent base class
lookup searches the bases of an incomplete class.
- Fix a crash when an unresolved overload set is encountered on the RHS of a ``.*`` operator.
(`#53815 <https://github.com/llvm/llvm-project/issues/53815>`_)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
2 changes: 2 additions & 0 deletions clang/docs/tools/dump_ast_matchers.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ def strip_doxygen(comment):

def unify_arguments(args):
"""Gets rid of anything the user doesn't care about in the argument list."""
args = re.sub(r"clang::ast_matchers::internal::", r"", args)
args = re.sub(r"ast_matchers::internal::", r"", args)
args = re.sub(r"internal::", r"", args)
args = re.sub(r"extern const\s+(.*)&", r"\1 ", args)
args = re.sub(r"&", r" ", args)
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -2981,6 +2981,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
// corresponding saturated type for a given fixed point type.
QualType getCorrespondingSaturatedType(QualType Ty) const;

// Per ISO N1169, this method accepts fixed point types and returns the
// corresponding non-saturated type for a given fixed point type.
QualType getCorrespondingUnsaturatedType(QualType Ty) const;

// This method accepts fixed point types and returns the corresponding signed
// type. Unlike getCorrespondingUnsignedType(), this only accepts unsigned
// fixed point types because there are unsigned integer types like bool and
Expand Down
13 changes: 13 additions & 0 deletions clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,12 @@ class Expr : public ValueStmt {
TR = t;
}

/// If this expression is an enumeration constant, return the
/// enumeration type under which said constant was declared.
/// Otherwise return the expression's type.
/// Note this effectively circumvents the weak typing of C's enum constants
QualType getEnumCoercedType(const ASTContext &Ctx) const;

ExprDependence getDependence() const {
return static_cast<ExprDependence>(ExprBits.Dependent);
}
Expand Down Expand Up @@ -471,6 +477,13 @@ class Expr : public ValueStmt {
/// bit-fields, but it will return null for a conditional bit-field.
FieldDecl *getSourceBitField();

/// If this expression refers to an enum constant, retrieve its declaration
EnumConstantDecl *getEnumConstantDecl();

const EnumConstantDecl *getEnumConstantDecl() const {
return const_cast<Expr *>(this)->getEnumConstantDecl();
}

const FieldDecl *getSourceBitField() const {
return const_cast<Expr*>(this)->getSourceBitField();
}
Expand Down
11 changes: 11 additions & 0 deletions clang/include/clang/AST/FormatString.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,14 @@ class ConversionSpecifier {

ZArg, // MS extension

// ISO/IEC TR 18037 (fixed-point) specific specifiers.
kArg, // %k for signed accum types
KArg, // %K for unsigned accum types
rArg, // %r for signed fract types
RArg, // %R for unsigned fract types
FixedPointArgBeg = kArg,
FixedPointArgEnd = RArg,

// Objective-C specific specifiers.
ObjCObjArg, // '@'
ObjCBeg = ObjCObjArg,
Expand Down Expand Up @@ -237,6 +245,9 @@ class ConversionSpecifier {
bool isDoubleArg() const {
return kind >= DoubleArgBeg && kind <= DoubleArgEnd;
}
bool isFixedPointArg() const {
return kind >= FixedPointArgBeg && kind <= FixedPointArgEnd;
}

const char *toString() const;

Expand Down
16 changes: 7 additions & 9 deletions clang/include/clang/ASTMatchers/ASTMatchers.h
Original file line number Diff line number Diff line change
Expand Up @@ -4580,8 +4580,7 @@ AST_POLYMORPHIC_MATCHER_P2(hasArgument,
/// return (args * ... * 1);
/// }
/// \endcode
AST_MATCHER_P(CXXFoldExpr, hasFoldInit, ast_matchers::internal::Matcher<Expr>,
InnerMacher) {
AST_MATCHER_P(CXXFoldExpr, hasFoldInit, internal::Matcher<Expr>, InnerMacher) {
const auto *const Init = Node.getInit();
return Init && InnerMacher.matches(*Init, Finder, Builder);
}
Expand All @@ -4603,8 +4602,7 @@ AST_MATCHER_P(CXXFoldExpr, hasFoldInit, ast_matchers::internal::Matcher<Expr>,
/// return (args * ... * 1);
/// }
/// \endcode
AST_MATCHER_P(CXXFoldExpr, hasPattern, ast_matchers::internal::Matcher<Expr>,
InnerMacher) {
AST_MATCHER_P(CXXFoldExpr, hasPattern, internal::Matcher<Expr>, InnerMacher) {
const Expr *const Pattern = Node.getPattern();
return Pattern && InnerMacher.matches(*Pattern, Finder, Builder);
}
Expand Down Expand Up @@ -4685,8 +4683,8 @@ AST_MATCHER(CXXFoldExpr, isBinaryFold) { return Node.getInit() != nullptr; }
/// \code
/// int x{y}.
/// \endcode
AST_MATCHER_P2(InitListExpr, hasInit, unsigned, N,
ast_matchers::internal::Matcher<Expr>, InnerMatcher) {
AST_MATCHER_P2(InitListExpr, hasInit, unsigned, N, internal::Matcher<Expr>,
InnerMatcher) {
return N < Node.getNumInits() &&
InnerMatcher.matches(*Node.getInit(N), Finder, Builder);
}
Expand Down Expand Up @@ -5309,7 +5307,7 @@ AST_POLYMORPHIC_MATCHER_P(
forEachTemplateArgument,
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
TemplateSpecializationType, FunctionDecl),
clang::ast_matchers::internal::Matcher<TemplateArgument>, InnerMatcher) {
internal::Matcher<TemplateArgument>, InnerMatcher) {
ArrayRef<TemplateArgument> TemplateArgs =
clang::ast_matchers::internal::getTemplateSpecializationArgs(Node);
clang::ast_matchers::internal::BoundNodesTreeBuilder Result;
Expand Down Expand Up @@ -8525,8 +8523,8 @@ AST_MATCHER(FunctionDecl, hasTrailingReturn) {
///
/// ``varDecl(hasInitializer(ignoringElidableConstructorCall(callExpr())))``
/// matches ``H D = G()`` in C++11 through C++17 (and beyond).
AST_MATCHER_P(Expr, ignoringElidableConstructorCall,
ast_matchers::internal::Matcher<Expr>, InnerMatcher) {
AST_MATCHER_P(Expr, ignoringElidableConstructorCall, internal::Matcher<Expr>,
InnerMatcher) {
// E tracks the node that we are examining.
const Expr *E = &Node;
// If present, remove an outer `ExprWithCleanups` corresponding to the
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -527,8 +527,10 @@ class SExprBuilder {
BlockInfo *CurrentBlockInfo = nullptr;
};

#ifndef NDEBUG
// Dump an SCFG to llvm::errs().
void printSCFG(CFGWalker &Walker);
#endif // NDEBUG

} // namespace threadSafety
} // namespace clang
Expand Down
7 changes: 3 additions & 4 deletions clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,9 @@ namespace dataflow {
/// Environment &Env)` - applies the analysis transfer
/// function for a given edge from a CFG block of a conditional statement.
///
/// `Derived` can optionally override the following members:
/// * `bool merge(QualType, const Value &, const Value &, Value &,
/// Environment &)` - joins distinct values. This could be a strict
/// lattice join or a more general widening operation.
/// `Derived` can optionally override the virtual functions in the
/// `Environment::ValueModel` interface (which is an indirect base class of
/// this class).
///
/// `LatticeT` is a bounded join-semilattice that is used by `Derived` and must
/// provide the following public members:
Expand Down
32 changes: 1 addition & 31 deletions clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,32 +79,6 @@ class Environment {
return ComparisonResult::Unknown;
}

/// DEPRECATED. Override `join` and/or `widen`, instead.
///
/// Modifies `MergedVal` to approximate both `Val1` and `Val2`. This could
/// be a strict lattice join or a more general widening operation.
///
/// If this function returns true, `MergedVal` will be assigned to a storage
/// location of type `Type` in `MergedEnv`.
///
/// `Env1` and `Env2` can be used to query child values and path condition
/// implications of `Val1` and `Val2` respectively.
///
/// Requirements:
///
/// `Val1` and `Val2` must be distinct.
///
/// `Val1`, `Val2`, and `MergedVal` must model values of type `Type`.
///
/// `Val1` and `Val2` must be assigned to the same storage location in
/// `Env1` and `Env2` respectively.
virtual bool merge(QualType Type, const Value &Val1,
const Environment &Env1, const Value &Val2,
const Environment &Env2, Value &MergedVal,
Environment &MergedEnv) {
return true;
}

/// Modifies `JoinedVal` to approximate both `Val1` and `Val2`. This should
/// obey the properties of a lattice join.
///
Expand All @@ -121,11 +95,7 @@ class Environment {
/// `Env1` and `Env2` respectively.
virtual void join(QualType Type, const Value &Val1, const Environment &Env1,
const Value &Val2, const Environment &Env2,
Value &JoinedVal, Environment &JoinedEnv) {
[[maybe_unused]] bool ShouldKeep =
merge(Type, Val1, Env1, Val2, Env2, JoinedVal, JoinedEnv);
assert(ShouldKeep && "dropping merged value is unsupported");
}
Value &JoinedVal, Environment &JoinedEnv) {}

/// This function may widen the current value -- replace it with an
/// approximation that can reach a fixed point more quickly than iterated
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/Builtins.td
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,12 @@ def Popcount : Builtin, BitInt_Long_LongLongTemplate {
let Prototype = "int(unsigned T)";
}

def Popcountg : Builtin {
let Spellings = ["__builtin_popcountg"];
let Attributes = [NoThrow, Const];
let Prototype = "int(...)";
}

def Clrsb : Builtin, BitInt_Long_LongLongTemplate {
let Spellings = ["__builtin_clrsb"];
let Attributes = [NoThrow, Const, Constexpr];
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -11983,7 +11983,8 @@ def err_builtin_invalid_arg_type: Error <
"pointer to a valid matrix element type|"
"signed integer or floating point type|vector type|"
"floating point type|"
"vector of integers}1 (was %2)">;
"vector of integers|"
"type of integer}1 (was %2)">;

def err_builtin_matrix_disabled: Error<
"matrix types extension is disabled. Pass -fenable-matrix to enable it">;
Expand Down
5 changes: 3 additions & 2 deletions clang/include/clang/Basic/TargetOSMacros.def
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,19 @@ TARGET_OS(TARGET_OS_UNIX, Triple.isOSNetBSD() ||
TARGET_OS(TARGET_OS_MAC, Triple.isOSDarwin())
TARGET_OS(TARGET_OS_OSX, Triple.isMacOSX())
TARGET_OS(TARGET_OS_IPHONE, Triple.isiOS() || Triple.isTvOS() ||
Triple.isWatchOS())
Triple.isWatchOS() || Triple.isXROS())
// Triple::isiOS() also includes tvOS
TARGET_OS(TARGET_OS_IOS, Triple.getOS() == llvm::Triple::IOS)
TARGET_OS(TARGET_OS_TV, Triple.isTvOS())
TARGET_OS(TARGET_OS_WATCH, Triple.isWatchOS())
TARGET_OS(TARGET_OS_VISION, Triple.isXROS())
TARGET_OS(TARGET_OS_DRIVERKIT, Triple.isDriverKit())
TARGET_OS(TARGET_OS_MACCATALYST, Triple.isMacCatalystEnvironment())
TARGET_OS(TARGET_OS_SIMULATOR, Triple.isSimulatorEnvironment())

// Deprecated Apple target conditionals.
TARGET_OS(TARGET_OS_EMBEDDED, (Triple.isiOS() || Triple.isTvOS() \
|| Triple.isWatchOS()) \
|| Triple.isWatchOS() || Triple.isXROS()) \
&& !Triple.isMacCatalystEnvironment() \
&& !Triple.isSimulatorEnvironment())
TARGET_OS(TARGET_OS_NANO, Triple.isWatchOS())
Expand Down
12 changes: 12 additions & 0 deletions clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,16 @@ struct FormatStyle {
/// \version 19
AlignConsecutiveStyle AlignConsecutiveTableGenCondOperatorColons;

/// Style of aligning consecutive TableGen definition colons.
/// This aligns the inheritance colons of consecutive definitions.
/// \code
/// def Def : Parent {}
/// def DefDef : Parent {}
/// def DefDefDef : Parent {}
/// \endcode
/// \version 19
AlignConsecutiveStyle AlignConsecutiveTableGenDefinitionColons;

/// Different styles for aligning escaped newlines.
enum EscapedNewlineAlignmentStyle : int8_t {
/// Don't align escaped newlines.
Expand Down Expand Up @@ -4817,6 +4827,8 @@ struct FormatStyle {
R.AlignConsecutiveShortCaseStatements &&
AlignConsecutiveTableGenCondOperatorColons ==
R.AlignConsecutiveTableGenCondOperatorColons &&
AlignConsecutiveTableGenDefinitionColons ==
R.AlignConsecutiveTableGenDefinitionColons &&
AlignEscapedNewlines == R.AlignEscapedNewlines &&
AlignOperands == R.AlignOperands &&
AlignTrailingComments == R.AlignTrailingComments &&
Expand Down
22 changes: 20 additions & 2 deletions clang/include/clang/InstallAPI/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#ifndef LLVM_CLANG_INSTALLAPI_CONTEXT_H
#define LLVM_CLANG_INSTALLAPI_CONTEXT_H

#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/InstallAPI/HeaderFile.h"
#include "llvm/TextAPI/InterfaceFile.h"
#include "llvm/TextAPI/RecordVisitor.h"
#include "llvm/TextAPI/RecordsSlice.h"
Expand All @@ -24,8 +27,23 @@ struct InstallAPIContext {
/// Library attributes that are typically passed as linker inputs.
llvm::MachO::RecordsSlice::BinaryAttrs BA;

/// Active target triple to parse.
llvm::Triple TargetTriple{};
/// All headers that represent a library.
HeaderSeq InputHeaders;

/// Active language mode to parse in.
Language LangMode = Language::ObjC;

/// Active header access type.
HeaderType Type = HeaderType::Unknown;

/// Active TargetSlice for symbol record collection.
std::shared_ptr<llvm::MachO::RecordsSlice> Slice;

/// FileManager for all I/O operations.
FileManager *FM = nullptr;

/// DiagnosticsEngine for all error reporting.
DiagnosticsEngine *Diags = nullptr;

/// File Path of output location.
llvm::StringRef OutputLoc{};
Expand Down
48 changes: 48 additions & 0 deletions clang/include/clang/InstallAPI/Frontend.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//===- InstallAPI/Frontend.h -----------------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
///
/// Top level wrappers for InstallAPI frontend operations.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_INSTALLAPI_FRONTEND_H
#define LLVM_CLANG_INSTALLAPI_FRONTEND_H

#include "clang/AST/ASTConsumer.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/InstallAPI/Context.h"
#include "clang/InstallAPI/Visitor.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/MemoryBuffer.h"

namespace clang {
namespace installapi {

/// Create a buffer that contains all headers to scan
/// for global symbols with.
std::unique_ptr<llvm::MemoryBuffer>
createInputBuffer(const InstallAPIContext &Ctx);

class InstallAPIAction : public ASTFrontendAction {
public:
explicit InstallAPIAction(llvm::MachO::RecordsSlice &Records)
: Records(Records) {}

std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override {
return std::make_unique<InstallAPIVisitor>(CI.getASTContext(), Records);
}

private:
llvm::MachO::RecordsSlice &Records;
};
} // namespace installapi
} // namespace clang

#endif // LLVM_CLANG_INSTALLAPI_FRONTEND_H
23 changes: 23 additions & 0 deletions clang/include/clang/InstallAPI/HeaderFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include "clang/Basic/LangStandard.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Regex.h"
#include <optional>
#include <string>
Expand All @@ -32,6 +33,20 @@ enum class HeaderType {
Project,
};

inline StringRef getName(const HeaderType T) {
switch (T) {
case HeaderType::Public:
return "Public";
case HeaderType::Private:
return "Private";
case HeaderType::Project:
return "Project";
case HeaderType::Unknown:
return "Unknown";
}
llvm_unreachable("unexpected header type");
}

class HeaderFile {
/// Full input path to header.
std::string FullPath;
Expand All @@ -52,6 +67,14 @@ class HeaderFile {

static llvm::Regex getFrameworkIncludeRule();

HeaderType getType() const { return Type; }
StringRef getIncludeName() const { return IncludeName; }
StringRef getPath() const { return FullPath; }

bool useIncludeName() const {
return Type != HeaderType::Project && !IncludeName.empty();
}

bool operator==(const HeaderFile &Other) const {
return std::tie(Type, FullPath, IncludeName, Language) ==
std::tie(Other.Type, Other.FullPath, Other.IncludeName,
Expand Down
51 changes: 51 additions & 0 deletions clang/include/clang/InstallAPI/Visitor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//===- InstallAPI/Visitor.h -----------------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
///
/// ASTVisitor Interface for InstallAPI frontend operations.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_INSTALLAPI_VISITOR_H
#define LLVM_CLANG_INSTALLAPI_VISITOR_H

#include "clang/AST/Mangle.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/FrontendActions.h"
#include "llvm/ADT/Twine.h"
#include "llvm/TextAPI/RecordsSlice.h"

namespace clang {
namespace installapi {

/// ASTVisitor for collecting declarations that represent global symbols.
class InstallAPIVisitor final : public ASTConsumer,
public RecursiveASTVisitor<InstallAPIVisitor> {
public:
InstallAPIVisitor(ASTContext &ASTCtx, llvm::MachO::RecordsSlice &Slice)
: Slice(Slice),
MC(ItaniumMangleContext::create(ASTCtx, ASTCtx.getDiagnostics())),
Layout(ASTCtx.getTargetInfo().getDataLayoutString()) {}
void HandleTranslationUnit(ASTContext &ASTCtx) override;

/// Collect global variables.
bool VisitVarDecl(const VarDecl *D);

private:
std::string getMangledName(const NamedDecl *D) const;
std::string getBackendMangledName(llvm::Twine Name) const;

llvm::MachO::RecordsSlice &Slice;
std::unique_ptr<clang::ItaniumMangleContext> MC;
StringRef Layout;
};

} // namespace installapi
} // namespace clang

#endif // LLVM_CLANG_INSTALLAPI_VISITOR_H
8 changes: 4 additions & 4 deletions clang/lib/APINotes/APINotesReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ class VersionedTableInfo {
auto version = ReadVersionTuple(Data);
const auto *DataBefore = Data;
(void)DataBefore;
auto UnversionedData = Derived::readUnversioned(Key, Data);
assert(Data != DataBefore &&
"Unversioned data reader didn't move pointer");
auto UnversionedData = Derived::readUnversioned(Key, Data);
Result.push_back({version, UnversionedData});
}
return Result;
Expand Down Expand Up @@ -148,7 +148,7 @@ class IdentifierTableInfo {
external_key_type GetExternalKey(internal_key_type Key) { return Key; }

hash_value_type ComputeHash(internal_key_type Key) {
return llvm::hash_value(Key);
return llvm::djbHash(Key);
}

static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
Expand Down Expand Up @@ -1797,8 +1797,8 @@ APINotesReader::Create(std::unique_ptr<llvm::MemoryBuffer> InputBuffer,
template <typename T>
APINotesReader::VersionedInfo<T>::VersionedInfo(
llvm::VersionTuple Version,
llvm::SmallVector<std::pair<llvm::VersionTuple, T>, 1> Results)
: Results(std::move(Results)) {
llvm::SmallVector<std::pair<llvm::VersionTuple, T>, 1> R)
: Results(std::move(R)) {

assert(!Results.empty());
assert(std::is_sorted(
Expand Down
1 change: 1 addition & 0 deletions clang/lib/APINotes/APINotesWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ class APINotesWriter::Implementation {
SelectorID getSelector(ObjCSelectorRef SelectorRef) {
// Translate the selector reference into a stored selector.
StoredObjCSelector Selector;
Selector.NumArgs = SelectorRef.NumArgs;
Selector.Identifiers.reserve(SelectorRef.Identifiers.size());
for (auto piece : SelectorRef.Identifiers)
Selector.Identifiers.push_back(getIdentifier(piece));
Expand Down
36 changes: 36 additions & 0 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13314,6 +13314,42 @@ QualType ASTContext::getCommonSugaredType(QualType X, QualType Y,
return R;
}

QualType ASTContext::getCorrespondingUnsaturatedType(QualType Ty) const {
assert(Ty->isFixedPointType());

if (Ty->isUnsaturatedFixedPointType())
return Ty;

switch (Ty->castAs<BuiltinType>()->getKind()) {
default:
llvm_unreachable("Not a saturated fixed point type!");
case BuiltinType::SatShortAccum:
return ShortAccumTy;
case BuiltinType::SatAccum:
return AccumTy;
case BuiltinType::SatLongAccum:
return LongAccumTy;
case BuiltinType::SatUShortAccum:
return UnsignedShortAccumTy;
case BuiltinType::SatUAccum:
return UnsignedAccumTy;
case BuiltinType::SatULongAccum:
return UnsignedLongAccumTy;
case BuiltinType::SatShortFract:
return ShortFractTy;
case BuiltinType::SatFract:
return FractTy;
case BuiltinType::SatLongFract:
return LongFractTy;
case BuiltinType::SatUShortFract:
return UnsignedShortFractTy;
case BuiltinType::SatUFract:
return UnsignedFractTy;
case BuiltinType::SatULongFract:
return UnsignedLongFractTy;
}
}

QualType ASTContext::getCorrespondingSaturatedType(QualType Ty) const {
assert(Ty->isFixedPointType());

Expand Down
15 changes: 15 additions & 0 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,14 @@ namespace {
}
}

QualType Expr::getEnumCoercedType(const ASTContext &Ctx) const {
if (isa<EnumType>(this->getType()))
return this->getType();
else if (const auto *ECD = this->getEnumConstantDecl())
return Ctx.getTypeDeclType(cast<EnumDecl>(ECD->getDeclContext()));
return this->getType();
}

SourceLocation Expr::getExprLoc() const {
switch (getStmtClass()) {
case Stmt::NoStmtClass: llvm_unreachable("statement without class");
Expand Down Expand Up @@ -4098,6 +4106,13 @@ FieldDecl *Expr::getSourceBitField() {
return nullptr;
}

EnumConstantDecl *Expr::getEnumConstantDecl() {
Expr *E = this->IgnoreParenImpCasts();
if (auto *DRE = dyn_cast<DeclRefExpr>(E))
return dyn_cast<EnumConstantDecl>(DRE->getDecl());
return nullptr;
}

bool Expr::refersToVectorElement() const {
// FIXME: Why do we not just look at the ObjectKind here?
const Expr *E = this->IgnoreParens();
Expand Down
25 changes: 25 additions & 0 deletions clang/lib/AST/FormatString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,10 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const {
else if (ETy->isUnscopedEnumerationType())
argTy = ETy->getDecl()->getIntegerType();
}

if (argTy->isSaturatedFixedPointType())
argTy = C.getCorrespondingUnsaturatedType(argTy);

argTy = C.getCanonicalType(argTy).getUnqualifiedType();

if (T == argTy)
Expand Down Expand Up @@ -761,6 +765,16 @@ const char *ConversionSpecifier::toString() const {

// MS specific specifiers.
case ZArg: return "Z";

// ISO/IEC TR 18037 (fixed-point) specific specifiers.
case rArg:
return "r";
case RArg:
return "R";
case kArg:
return "k";
case KArg:
return "K";
}
return nullptr;
}
Expand Down Expand Up @@ -825,6 +839,9 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target,
if (LO.OpenCL && CS.isDoubleArg())
return !VectorNumElts.isInvalid();

if (CS.isFixedPointArg())
return true;

if (Target.getTriple().isOSMSVCRT()) {
switch (CS.getKind()) {
case ConversionSpecifier::cArg:
Expand Down Expand Up @@ -877,6 +894,9 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target,
return true;
}

if (CS.isFixedPointArg())
return true;

switch (CS.getKind()) {
case ConversionSpecifier::bArg:
case ConversionSpecifier::BArg:
Expand Down Expand Up @@ -1043,6 +1063,11 @@ bool FormatSpecifier::hasStandardConversionSpecifier(
case ConversionSpecifier::UArg:
case ConversionSpecifier::ZArg:
return false;
case ConversionSpecifier::rArg:
case ConversionSpecifier::RArg:
case ConversionSpecifier::kArg:
case ConversionSpecifier::KArg:
return LangOpt.FixedPoint;
}
llvm_unreachable("Invalid ConversionSpecifier Kind!");
}
Expand Down
85 changes: 65 additions & 20 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -897,7 +897,7 @@ bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
if (!this->visitInitializer(Init))
return false;

if (!this->emitInitPtrPop(E))
if (!this->emitFinishInitPop(E))
return false;
// Base initializers don't increase InitIndex, since they don't count
// into the Record's fields.
Expand Down Expand Up @@ -940,7 +940,7 @@ bool ByteCodeExprGen<Emitter>::visitArrayElemInit(unsigned ElemIndex,
return false;
if (!this->visitInitializer(Init))
return false;
return this->emitInitPtrPop(Init);
return this->emitFinishInitPop(Init);
}

template <class Emitter>
Expand Down Expand Up @@ -1700,19 +1700,35 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundLiteralExpr(
}

// Otherwise, use a local variable.
if (T) {
if (T && !E->isLValue()) {
// For primitive types, we just visit the initializer.
return this->delegate(Init);
} else {
if (std::optional<unsigned> LocalIndex = allocateLocal(Init)) {
if (!this->emitGetPtrLocal(*LocalIndex, E))
unsigned LocalIndex;

if (T)
LocalIndex = this->allocateLocalPrimitive(Init, *T, false, false);
else if (std::optional<unsigned> MaybeIndex = this->allocateLocal(Init))
LocalIndex = *MaybeIndex;
else
return false;

if (!this->emitGetPtrLocal(LocalIndex, E))
return false;

if (T) {
if (!this->visit(Init)) {
return false;
}
return this->emitInit(*T, E);
} else {
if (!this->visitInitializer(Init))
return false;
if (DiscardResult)
return this->emitPopPtr(E);
return true;
}

if (DiscardResult)
return this->emitPopPtr(E);
return true;
}

return false;
Expand Down Expand Up @@ -2151,7 +2167,7 @@ bool ByteCodeExprGen<Emitter>::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
}
}

return this->emitInitPtr(E);
return this->emitFinishInit(E);
}

template <class Emitter>
Expand All @@ -2173,6 +2189,31 @@ bool ByteCodeExprGen<Emitter>::VisitCXXRewrittenBinaryOperator(
return this->delegate(E->getSemanticForm());
}

template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitPseudoObjectExpr(
const PseudoObjectExpr *E) {

for (const Expr *SemE : E->semantics()) {
if (auto *OVE = dyn_cast<OpaqueValueExpr>(SemE)) {
if (SemE == E->getResultExpr())
return false;

if (OVE->isUnique())
continue;

if (!this->discard(OVE))
return false;
} else if (SemE == E->getResultExpr()) {
if (!this->delegate(SemE))
return false;
} else {
if (!this->discard(SemE))
return false;
}
}
return true;
}

template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
if (E->containsErrors())
return false;
Expand Down Expand Up @@ -2364,7 +2405,7 @@ bool ByteCodeExprGen<Emitter>::visitZeroRecordInitializer(const Record *R,
return false;
if (!this->visitZeroRecordInitializer(B.R, E))
return false;
if (!this->emitInitPtrPop(E))
if (!this->emitFinishInitPop(E))
return false;
}

Expand Down Expand Up @@ -2544,9 +2585,12 @@ bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *E) {
if (!visitInitializer(E))
return false;

if (!this->emitInitPtr(E))
if (!this->emitFinishInit(E))
return false;
return this->emitRetValue(E);
// We are destroying the locals AFTER the Ret op.
// The Ret op needs to copy the (alive) values, but the
// destructors may still turn the entire expression invalid.
return this->emitRetValue(E) && RootScope.destroyLocals();
}

return false;
Expand Down Expand Up @@ -3373,14 +3417,15 @@ bool ByteCodeExprGen<Emitter>::emitRecordDestruction(const Record *R) {
// Now emit the destructor and recurse into base classes.
if (const CXXDestructorDecl *Dtor = R->getDestructor();
Dtor && !Dtor->isTrivial()) {
if (const Function *DtorFunc = getFunction(Dtor)) {
assert(DtorFunc->hasThisPointer());
assert(DtorFunc->getNumParams() == 1);
if (!this->emitDupPtr(SourceInfo{}))
return false;
if (!this->emitCall(DtorFunc, 0, SourceInfo{}))
return false;
}
const Function *DtorFunc = getFunction(Dtor);
if (!DtorFunc)
return false;
assert(DtorFunc->hasThisPointer());
assert(DtorFunc->getNumParams() == 1);
if (!this->emitDupPtr(SourceInfo{}))
return false;
if (!this->emitCall(DtorFunc, 0, SourceInfo{}))
return false;
}

for (const Record::Base &Base : llvm::reverse(R->bases())) {
Expand Down
36 changes: 24 additions & 12 deletions clang/lib/AST/Interp/ByteCodeExprGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
bool VisitRequiresExpr(const RequiresExpr *E);
bool VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E);
bool VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *E);
bool VisitPseudoObjectExpr(const PseudoObjectExpr *E);

protected:
bool visitExpr(const Expr *E) override;
Expand Down Expand Up @@ -182,7 +183,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
if (!visitInitializer(Init))
return false;

if (!this->emitInitPtr(Init))
if (!this->emitFinishInit(Init))
return false;

return this->emitPopPtr(Init);
Expand All @@ -196,7 +197,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
if (!visitInitializer(Init))
return false;

if (!this->emitInitPtr(Init))
if (!this->emitFinishInit(Init))
return false;

return this->emitPopPtr(Init);
Expand All @@ -210,7 +211,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
if (!visitInitializer(I))
return false;

return this->emitInitPtrPop(I);
return this->emitFinishInitPop(I);
}

bool visitInitList(ArrayRef<const Expr *> Inits, const Expr *E);
Expand Down Expand Up @@ -331,7 +332,7 @@ template <class Emitter> class VariableScope {
}

virtual void emitDestruction() {}
virtual void emitDestructors() {}
virtual bool emitDestructors() { return true; }
VariableScope *getParent() const { return Parent; }

protected:
Expand All @@ -355,13 +356,18 @@ template <class Emitter> class LocalScope : public VariableScope<Emitter> {
}

/// Overriden to support explicit destruction.
void emitDestruction() override {
void emitDestruction() override { destroyLocals(); }

/// Explicit destruction of local variables.
bool destroyLocals() {
if (!Idx)
return;
this->emitDestructors();
return true;

bool Success = this->emitDestructors();
this->Ctx->emitDestroy(*Idx, SourceInfo{});
removeStoredOpaqueValues();
this->Idx = std::nullopt;
return Success;
}

void addLocal(const Scope::Local &Local) override {
Expand All @@ -373,19 +379,25 @@ template <class Emitter> class LocalScope : public VariableScope<Emitter> {
this->Ctx->Descriptors[*Idx].emplace_back(Local);
}

void emitDestructors() override {
bool emitDestructors() override {
if (!Idx)
return;
return true;
// Emit destructor calls for local variables of record
// type with a destructor.
for (Scope::Local &Local : this->Ctx->Descriptors[*Idx]) {
if (!Local.Desc->isPrimitive() && !Local.Desc->isPrimitiveArray()) {
this->Ctx->emitGetPtrLocal(Local.Offset, SourceInfo{});
this->Ctx->emitDestruction(Local.Desc);
this->Ctx->emitPopPtr(SourceInfo{});
if (!this->Ctx->emitGetPtrLocal(Local.Offset, SourceInfo{}))
return false;

if (!this->Ctx->emitDestruction(Local.Desc))
return false;

if (!this->Ctx->emitPopPtr(SourceInfo{}))
return false;
removeIfStoredOpaqueValue(Local);
}
}
return true;
}

void removeStoredOpaqueValues() {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/ByteCodeStmtGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ bool ByteCodeStmtGen<Emitter>::visitFunc(const FunctionDecl *F) {
return false;
if (!this->visitInitializer(InitExpr))
return false;
if (!this->emitInitPtrPop(InitExpr))
if (!this->emitFinishInitPop(InitExpr))
return false;
} else if (const IndirectFieldDecl *IFD = Init->getIndirectMember()) {
assert(IFD->getChainingSize() >= 2);
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/AST/Interp/EvalEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ EvaluationResult EvalEmitter::interpretExpr(const Expr *E,
this->ConvertResultToRValue = ConvertResultToRValue;
EvalResult.setSource(E);

if (!this->visitExpr(E) && EvalResult.empty())
if (!this->visitExpr(E)) {
// EvalResult may already have a result set, but something failed
// after that (e.g. evaluating destructors).
EvalResult.setInvalid();
}

return std::move(this->EvalResult);
}
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/Interp/EvaluationResult.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc,
Result &= CheckFieldsInitialized(S, Loc, FieldPtr, FieldPtr.getRecord());
} else if (FieldType->isIncompleteArrayType()) {
// Nothing to do here.
} else if (F.Decl->isUnnamedBitfield()) {
// Nothing do do here.
} else if (FieldType->isArrayType()) {
const auto *CAT =
cast<ConstantArrayType>(FieldType->getAsArrayTypeUnsafe());
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/AST/Interp/EvaluationResult.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ class EvaluationResult final {
Kind = LValue;
}
void setInvalid() {
assert(empty());
// We are NOT asserting empty() here, since setting it to invalid
// is allowed even if there is already a result.
Kind = Invalid;
}
void setValid() {
Expand Down
21 changes: 17 additions & 4 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1280,14 +1280,14 @@ inline bool GetPtrThisBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
return true;
}

inline bool InitPtrPop(InterpState &S, CodePtr OpPC) {
inline bool FinishInitPop(InterpState &S, CodePtr OpPC) {
const Pointer &Ptr = S.Stk.pop<Pointer>();
if (Ptr.canBeInitialized())
Ptr.initialize();
return true;
}

inline bool InitPtr(InterpState &S, CodePtr OpPC) {
inline bool FinishInit(InterpState &S, CodePtr OpPC) {
const Pointer &Ptr = S.Stk.peek<Pointer>();

if (Ptr.canBeInitialized())
Expand Down Expand Up @@ -1399,6 +1399,19 @@ bool StoreBitFieldPop(InterpState &S, CodePtr OpPC) {
return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Init(InterpState &S, CodePtr OpPC) {
const T &Value = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.peek<Pointer>();
if (!CheckInit(S, OpPC, Ptr)) {
assert(false);
return false;
}
Ptr.initialize();
new (&Ptr.deref<T>()) T(Value);
return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitPop(InterpState &S, CodePtr OpPC) {
const T &Value = S.Stk.pop<T>();
Expand Down Expand Up @@ -1667,7 +1680,7 @@ bool CastFloatingIntegral(InterpState &S, CodePtr OpPC) {
auto Status = F.convertToInteger(Result);

// Float-to-Integral overflow check.
if ((Status & APFloat::opStatus::opInvalidOp) && F.isFinite()) {
if ((Status & APFloat::opStatus::opInvalidOp)) {
const Expr *E = S.Current->getExpr(OpPC);
QualType Type = E->getType();

Expand Down Expand Up @@ -1920,7 +1933,7 @@ inline bool ArrayElemPop(InterpState &S, CodePtr OpPC, uint32_t Index) {
inline bool ArrayDecay(InterpState &S, CodePtr OpPC) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isDummy()) {
if (Ptr.isZero() || Ptr.isDummy()) {
S.Stk.push<Pointer>(Ptr);
return true;
}
Expand Down
10 changes: 4 additions & 6 deletions clang/lib/AST/Interp/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ static void pushInteger(InterpState &S, T Val, QualType QT) {
pushInteger(S, APSInt(Val, !std::is_signed_v<T>), QT);
else
pushInteger(S,
APSInt(APInt(sizeof(T) * 8, Val, std::is_signed_v<T>),
APSInt(APInt(sizeof(T) * 8, static_cast<uint64_t>(Val),
std::is_signed_v<T>),
!std::is_signed_v<T>),
QT);
}
Expand Down Expand Up @@ -464,7 +465,7 @@ static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC,

PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
APSInt Val = peekToAPSInt(S.Stk, ArgT);
pushInteger(S, APSInt(APInt(32, Val.popcount())), Call->getType());
pushInteger(S, Val.popcount(), Call->getType());
return true;
}

Expand Down Expand Up @@ -492,7 +493,6 @@ static bool interp__builtin_bitreverse(InterpState &S, CodePtr OpPC,
const CallExpr *Call) {
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
APSInt Val = peekToAPSInt(S.Stk, ArgT);
// pushAPSInt(S, APSInt(Val.reverseBits(), /*IsUnsigned=*/true));
pushInteger(S, Val.reverseBits(), Call->getType());
return true;
}
Expand Down Expand Up @@ -551,7 +551,6 @@ static bool interp__builtin_rotate(InterpState &S, CodePtr OpPC,
Result = APSInt(Value.rotl(Amount.urem(Value.getBitWidth())),
/*IsUnsigned=*/true);

// pushAPSInt(S, Result);
pushInteger(S, Result, Call->getType());
return true;
}
Expand Down Expand Up @@ -784,7 +783,6 @@ static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC,
CarryOutPtr.initialize();

assert(Call->getType() == Call->getArg(0)->getType());
// pushAPSInt(S, Result);
pushInteger(S, Result, Call->getType());
return true;
}
Expand All @@ -805,7 +803,7 @@ static bool interp__builtin_clz(InterpState &S, CodePtr OpPC,
if (ZeroIsUndefined && Val == 0)
return false;

pushInteger(S, APSInt(APInt(32, Val.countl_zero())), Call->getType());
pushInteger(S, Val.countl_zero(), Call->getType());
return true;
}

Expand Down
5 changes: 3 additions & 2 deletions clang/lib/AST/Interp/Opcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -326,8 +326,8 @@ def GetPtrBasePop : Opcode {
let Args = [ArgUint32];
}

def InitPtrPop : Opcode;
def InitPtr : Opcode;
def FinishInitPop : Opcode;
def FinishInit : Opcode;

def GetPtrDerivedPop : Opcode {
let Args = [ArgUint32];
Expand Down Expand Up @@ -476,6 +476,7 @@ def StoreBitField : StoreBitFieldOpcode {}
def StoreBitFieldPop : StoreBitFieldOpcode {}

// [Pointer, Value] -> []
def Init : StoreOpcode {}
def InitPop : StoreOpcode {}
// [Pointer, Value] -> [Pointer]
def InitElem : Opcode {
Expand Down
1 change: 0 additions & 1 deletion clang/lib/AST/Interp/Pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,6 @@ class Pointer {
assert(Offset == PastEndMark && "cannot get base of a block");
return Pointer(Pointee, Base, 0);
}
assert(Offset == Base && "not an inner field");
unsigned NewBase = Base - getInlineDesc()->Offset;
return Pointer(Pointee, NewBase, NewBase);
}
Expand Down
85 changes: 82 additions & 3 deletions clang/lib/AST/PrintfFormatString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,8 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
case 'r':
if (isFreeBSDKPrintf)
k = ConversionSpecifier::FreeBSDrArg; // int
else if (LO.FixedPoint)
k = ConversionSpecifier::rArg;
break;
case 'y':
if (isFreeBSDKPrintf)
Expand All @@ -373,6 +375,20 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
if (Target.getTriple().isOSMSVCRT())
k = ConversionSpecifier::ZArg;
break;
// ISO/IEC TR 18037 (fixed-point) specific.
// NOTE: 'r' is handled up above since FreeBSD also supports %r.
case 'k':
if (LO.FixedPoint)
k = ConversionSpecifier::kArg;
break;
case 'K':
if (LO.FixedPoint)
k = ConversionSpecifier::KArg;
break;
case 'R':
if (LO.FixedPoint)
k = ConversionSpecifier::RArg;
break;
}

// Check to see if we used the Objective-C modifier flags with
Expand Down Expand Up @@ -627,6 +643,9 @@ ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx,
}
}

if (CS.isFixedPointArg() && !Ctx.getLangOpts().FixedPoint)
return ArgType::Invalid();

switch (CS.getKind()) {
case ConversionSpecifier::sArg:
if (LM.getKind() == LengthModifier::AsWideChar) {
Expand Down Expand Up @@ -658,6 +677,50 @@ ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx,
return ArgType::CPointerTy;
case ConversionSpecifier::ObjCObjArg:
return ArgType::ObjCPointerTy;
case ConversionSpecifier::kArg:
switch (LM.getKind()) {
case LengthModifier::None:
return Ctx.AccumTy;
case LengthModifier::AsShort:
return Ctx.ShortAccumTy;
case LengthModifier::AsLong:
return Ctx.LongAccumTy;
default:
return ArgType::Invalid();
}
case ConversionSpecifier::KArg:
switch (LM.getKind()) {
case LengthModifier::None:
return Ctx.UnsignedAccumTy;
case LengthModifier::AsShort:
return Ctx.UnsignedShortAccumTy;
case LengthModifier::AsLong:
return Ctx.UnsignedLongAccumTy;
default:
return ArgType::Invalid();
}
case ConversionSpecifier::rArg:
switch (LM.getKind()) {
case LengthModifier::None:
return Ctx.FractTy;
case LengthModifier::AsShort:
return Ctx.ShortFractTy;
case LengthModifier::AsLong:
return Ctx.LongFractTy;
default:
return ArgType::Invalid();
}
case ConversionSpecifier::RArg:
switch (LM.getKind()) {
case LengthModifier::None:
return Ctx.UnsignedFractTy;
case LengthModifier::AsShort:
return Ctx.UnsignedShortFractTy;
case LengthModifier::AsLong:
return Ctx.UnsignedLongFractTy;
default:
return ArgType::Invalid();
}
default:
break;
}
Expand Down Expand Up @@ -955,6 +1018,8 @@ bool PrintfSpecifier::hasValidPlusPrefix() const {
case ConversionSpecifier::AArg:
case ConversionSpecifier::FreeBSDrArg:
case ConversionSpecifier::FreeBSDyArg:
case ConversionSpecifier::rArg:
case ConversionSpecifier::kArg:
return true;

default:
Expand All @@ -966,7 +1031,7 @@ bool PrintfSpecifier::hasValidAlternativeForm() const {
if (!HasAlternativeForm)
return true;

// Alternate form flag only valid with the bBoxXaAeEfFgG conversions
// Alternate form flag only valid with the bBoxXaAeEfFgGrRkK conversions
switch (CS.getKind()) {
case ConversionSpecifier::bArg:
case ConversionSpecifier::BArg:
Expand All @@ -984,6 +1049,10 @@ bool PrintfSpecifier::hasValidAlternativeForm() const {
case ConversionSpecifier::GArg:
case ConversionSpecifier::FreeBSDrArg:
case ConversionSpecifier::FreeBSDyArg:
case ConversionSpecifier::rArg:
case ConversionSpecifier::RArg:
case ConversionSpecifier::kArg:
case ConversionSpecifier::KArg:
return true;

default:
Expand All @@ -995,7 +1064,7 @@ bool PrintfSpecifier::hasValidLeadingZeros() const {
if (!HasLeadingZeroes)
return true;

// Leading zeroes flag only valid with the bBdiouxXaAeEfFgG conversions
// Leading zeroes flag only valid with the bBdiouxXaAeEfFgGrRkK conversions
switch (CS.getKind()) {
case ConversionSpecifier::bArg:
case ConversionSpecifier::BArg:
Expand All @@ -1018,6 +1087,10 @@ bool PrintfSpecifier::hasValidLeadingZeros() const {
case ConversionSpecifier::GArg:
case ConversionSpecifier::FreeBSDrArg:
case ConversionSpecifier::FreeBSDyArg:
case ConversionSpecifier::rArg:
case ConversionSpecifier::RArg:
case ConversionSpecifier::kArg:
case ConversionSpecifier::KArg:
return true;

default:
Expand All @@ -1044,6 +1117,8 @@ bool PrintfSpecifier::hasValidSpacePrefix() const {
case ConversionSpecifier::AArg:
case ConversionSpecifier::FreeBSDrArg:
case ConversionSpecifier::FreeBSDyArg:
case ConversionSpecifier::rArg:
case ConversionSpecifier::kArg:
return true;

default:
Expand Down Expand Up @@ -1089,7 +1164,7 @@ bool PrintfSpecifier::hasValidPrecision() const {
if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
return true;

// Precision is only valid with the bBdiouxXaAeEfFgGsP conversions
// Precision is only valid with the bBdiouxXaAeEfFgGsPrRkK conversions
switch (CS.getKind()) {
case ConversionSpecifier::bArg:
case ConversionSpecifier::BArg:
Expand All @@ -1114,6 +1189,10 @@ bool PrintfSpecifier::hasValidPrecision() const {
case ConversionSpecifier::FreeBSDrArg:
case ConversionSpecifier::FreeBSDyArg:
case ConversionSpecifier::PArg:
case ConversionSpecifier::rArg:
case ConversionSpecifier::RArg:
case ConversionSpecifier::kArg:
case ConversionSpecifier::KArg:
return true;

default:
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Analysis/ThreadSafetyCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -995,7 +995,7 @@ void SExprBuilder::exitCFG(const CFGBlock *Last) {
IncompleteArgs.clear();
}

/*
#ifndef NDEBUG
namespace {

class TILPrinter :
Expand All @@ -1016,4 +1016,4 @@ void printSCFG(CFGWalker &Walker) {

} // namespace threadSafety
} // namespace clang
*/
#endif // NDEBUG
259 changes: 129 additions & 130 deletions clang/lib/Analysis/UnsafeBufferUsage.cpp

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion clang/lib/Basic/Targets/Mips.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,12 +237,14 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
case 'r': // CPU registers.
case 'd': // Equivalent to "r" unless generating MIPS16 code.
case 'y': // Equivalent to "r", backward compatibility only.
case 'f': // floating-point registers.
case 'c': // $25 for indirect jumps
case 'l': // lo register
case 'x': // hilo register pair
Info.setAllowsRegister();
return true;
case 'f': // floating-point registers.
Info.setAllowsRegister();
return FloatABI != SoftFloat;
case 'I': // Signed 16-bit constant
case 'J': // Integer 0
case 'K': // Unsigned 16-bit constant
Expand Down
52 changes: 52 additions & 0 deletions clang/lib/CodeGen/ABIInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,58 @@ ABIArgInfo ABIInfo::getNaturalAlignIndirectInReg(QualType Ty,
/*ByVal*/ false, Realign);
}

void ABIInfo::appendAttributeMangling(TargetAttr *Attr,
raw_ostream &Out) const {
if (Attr->isDefaultVersion())
return;
appendAttributeMangling(Attr->getFeaturesStr(), Out);
}

void ABIInfo::appendAttributeMangling(TargetVersionAttr *Attr,
raw_ostream &Out) const {
appendAttributeMangling(Attr->getNamesStr(), Out);
}

void ABIInfo::appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index,
raw_ostream &Out) const {
appendAttributeMangling(Attr->getFeatureStr(Index), Out);
Out << '.' << Attr->getMangledIndex(Index);
}

void ABIInfo::appendAttributeMangling(StringRef AttrStr,
raw_ostream &Out) const {
if (AttrStr == "default") {
Out << ".default";
return;
}

Out << '.';
const TargetInfo &TI = CGT.getTarget();
ParsedTargetAttr Info = TI.parseTargetAttr(AttrStr);

llvm::sort(Info.Features, [&TI](StringRef LHS, StringRef RHS) {
// Multiversioning doesn't allow "no-${feature}", so we can
// only have "+" prefixes here.
assert(LHS.starts_with("+") && RHS.starts_with("+") &&
"Features should always have a prefix.");
return TI.multiVersionSortPriority(LHS.substr(1)) >
TI.multiVersionSortPriority(RHS.substr(1));
});

bool IsFirst = true;
if (!Info.CPU.empty()) {
IsFirst = false;
Out << "arch_" << Info.CPU;
}

for (StringRef Feat : Info.Features) {
if (!IsFirst)
Out << '_';
IsFirst = false;
Out << Feat.substr(1);
}
}

// Pin the vtable to this file.
SwiftABIInfo::~SwiftABIInfo() = default;

Expand Down
10 changes: 10 additions & 0 deletions clang/lib/CodeGen/ABIInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef LLVM_CLANG_LIB_CODEGEN_ABIINFO_H
#define LLVM_CLANG_LIB_CODEGEN_ABIINFO_H

#include "clang/AST/Attr.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Type.h"
#include "llvm/IR/CallingConv.h"
Expand Down Expand Up @@ -111,6 +112,15 @@ class ABIInfo {

CodeGen::ABIArgInfo getNaturalAlignIndirectInReg(QualType Ty,
bool Realign = false) const;

virtual void appendAttributeMangling(TargetAttr *Attr,
raw_ostream &Out) const;
virtual void appendAttributeMangling(TargetVersionAttr *Attr,
raw_ostream &Out) const;
virtual void appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index,
raw_ostream &Out) const;
virtual void appendAttributeMangling(StringRef AttrStr,
raw_ostream &Out) const;
};

/// Target specific hooks for defining how a type should be passed or returned
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3217,7 +3217,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__popcnt64:
case Builtin::BI__builtin_popcount:
case Builtin::BI__builtin_popcountl:
case Builtin::BI__builtin_popcountll: {
case Builtin::BI__builtin_popcountll:
case Builtin::BI__builtin_popcountg: {
Value *ArgValue = EmitScalarExpr(E->getArg(0));

llvm::Type *ArgType = ArgValue->getType();
Expand Down
17 changes: 8 additions & 9 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3221,12 +3221,11 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,

llvm::StructType *STy =
dyn_cast<llvm::StructType>(ArgI.getCoerceToType());
llvm::TypeSize StructSize;
llvm::TypeSize PtrElementSize;
if (ArgI.isDirect() && !ArgI.getCanBeFlattened() && STy &&
STy->getNumElements() > 1) {
StructSize = CGM.getDataLayout().getTypeAllocSize(STy);
PtrElementSize =
[[maybe_unused]] llvm::TypeSize StructSize =
CGM.getDataLayout().getTypeAllocSize(STy);
[[maybe_unused]] llvm::TypeSize PtrElementSize =
CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(Ty));
if (STy->containsHomogeneousScalableVectorTypes()) {
assert(StructSize == PtrElementSize &&
Expand Down Expand Up @@ -5310,12 +5309,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,

llvm::StructType *STy =
dyn_cast<llvm::StructType>(ArgInfo.getCoerceToType());
llvm::Type *SrcTy = ConvertTypeForMem(I->Ty);
llvm::TypeSize SrcTypeSize;
llvm::TypeSize DstTypeSize;
if (STy && ArgInfo.isDirect() && !ArgInfo.getCanBeFlattened()) {
SrcTypeSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
DstTypeSize = CGM.getDataLayout().getTypeAllocSize(STy);
llvm::Type *SrcTy = ConvertTypeForMem(I->Ty);
[[maybe_unused]] llvm::TypeSize SrcTypeSize =
CGM.getDataLayout().getTypeAllocSize(SrcTy);
[[maybe_unused]] llvm::TypeSize DstTypeSize =
CGM.getDataLayout().getTypeAllocSize(STy);
if (STy->containsHomogeneousScalableVectorTypes()) {
assert(SrcTypeSize == DstTypeSize &&
"Only allow non-fractional movement of structure with "
Expand Down
13 changes: 12 additions & 1 deletion clang/lib/CodeGen/CGExprAgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ using namespace CodeGen;
// Aggregate Expression Emitter
//===----------------------------------------------------------------------===//

namespace llvm {
extern cl::opt<bool> EnableSingleByteCoverage;
} // namespace llvm

namespace {
class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
CodeGenFunction &CGF;
Expand Down Expand Up @@ -1279,7 +1283,10 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {

eval.begin(CGF);
CGF.EmitBlock(LHSBlock);
CGF.incrementProfileCounter(E);
if (llvm::EnableSingleByteCoverage)
CGF.incrementProfileCounter(E->getTrueExpr());
else
CGF.incrementProfileCounter(E);
Visit(E->getTrueExpr());
eval.end(CGF);

Expand All @@ -1294,6 +1301,8 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {

eval.begin(CGF);
CGF.EmitBlock(RHSBlock);
if (llvm::EnableSingleByteCoverage)
CGF.incrementProfileCounter(E->getFalseExpr());
Visit(E->getFalseExpr());
eval.end(CGF);

Expand All @@ -1302,6 +1311,8 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
E->getType());

CGF.EmitBlock(ContBlock);
if (llvm::EnableSingleByteCoverage)
CGF.incrementProfileCounter(E);
}

void AggExprEmitter::VisitChooseExpr(const ChooseExpr *CE) {
Expand Down
14 changes: 13 additions & 1 deletion clang/lib/CodeGen/CGExprComplex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ using namespace CodeGen;
// Complex Expression Emitter
//===----------------------------------------------------------------------===//

namespace llvm {
extern cl::opt<bool> EnableSingleByteCoverage;
} // namespace llvm

typedef CodeGenFunction::ComplexPairTy ComplexPairTy;

/// Return the complex type that we are meant to emit.
Expand Down Expand Up @@ -1330,17 +1334,25 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {

eval.begin(CGF);
CGF.EmitBlock(LHSBlock);
CGF.incrementProfileCounter(E);
if (llvm::EnableSingleByteCoverage)
CGF.incrementProfileCounter(E->getTrueExpr());
else
CGF.incrementProfileCounter(E);

ComplexPairTy LHS = Visit(E->getTrueExpr());
LHSBlock = Builder.GetInsertBlock();
CGF.EmitBranch(ContBlock);
eval.end(CGF);

eval.begin(CGF);
CGF.EmitBlock(RHSBlock);
if (llvm::EnableSingleByteCoverage)
CGF.incrementProfileCounter(E->getFalseExpr());
ComplexPairTy RHS = Visit(E->getFalseExpr());
RHSBlock = Builder.GetInsertBlock();
CGF.EmitBlock(ContBlock);
if (llvm::EnableSingleByteCoverage)
CGF.incrementProfileCounter(E);
eval.end(CGF);

// Create a PHI node for the real part.
Expand Down
32 changes: 29 additions & 3 deletions clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ using llvm::Value;
// Scalar Expression Emitter
//===----------------------------------------------------------------------===//

namespace llvm {
extern cl::opt<bool> EnableSingleByteCoverage;
} // namespace llvm

namespace {

/// Determine whether the given binary operation may overflow.
Expand Down Expand Up @@ -4925,8 +4929,13 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {

// If the dead side doesn't have labels we need, just emit the Live part.
if (!CGF.ContainsLabel(dead)) {
if (CondExprBool)
if (CondExprBool) {
if (llvm::EnableSingleByteCoverage) {
CGF.incrementProfileCounter(lhsExpr);
CGF.incrementProfileCounter(rhsExpr);
}
CGF.incrementProfileCounter(E);
}
Value *Result = Visit(live);

// If the live part is a throw expression, it acts like it has a void
Expand Down Expand Up @@ -5005,7 +5014,12 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
llvm::Value *CondV = CGF.EvaluateExprAsBool(condExpr);
llvm::Value *StepV = Builder.CreateZExtOrBitCast(CondV, CGF.Int64Ty);

CGF.incrementProfileCounter(E, StepV);
if (llvm::EnableSingleByteCoverage) {
CGF.incrementProfileCounter(lhsExpr);
CGF.incrementProfileCounter(rhsExpr);
CGF.incrementProfileCounter(E);
} else
CGF.incrementProfileCounter(E, StepV);

llvm::Value *LHS = Visit(lhsExpr);
llvm::Value *RHS = Visit(rhsExpr);
Expand Down Expand Up @@ -5037,7 +5051,11 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
if (CGF.MCDCLogOpStack.empty())
CGF.maybeUpdateMCDCTestVectorBitmap(condExpr);

CGF.incrementProfileCounter(E);
if (llvm::EnableSingleByteCoverage)
CGF.incrementProfileCounter(lhsExpr);
else
CGF.incrementProfileCounter(E);

eval.begin(CGF);
Value *LHS = Visit(lhsExpr);
eval.end(CGF);
Expand All @@ -5053,6 +5071,9 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
if (CGF.MCDCLogOpStack.empty())
CGF.maybeUpdateMCDCTestVectorBitmap(condExpr);

if (llvm::EnableSingleByteCoverage)
CGF.incrementProfileCounter(rhsExpr);

eval.begin(CGF);
Value *RHS = Visit(rhsExpr);
eval.end(CGF);
Expand All @@ -5071,6 +5092,11 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
PN->addIncoming(LHS, LHSBlock);
PN->addIncoming(RHS, RHSBlock);

// When single byte coverage mode is enabled, add a counter to continuation
// block.
if (llvm::EnableSingleByteCoverage)
CGF.incrementProfileCounter(E);

return PN;
}

Expand Down
73 changes: 68 additions & 5 deletions clang/lib/CodeGen/CGStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ using namespace CodeGen;
// Statement Emission
//===----------------------------------------------------------------------===//

namespace llvm {
extern cl::opt<bool> EnableSingleByteCoverage;
} // namespace llvm

void CodeGenFunction::EmitStopPoint(const Stmt *S) {
if (CGDebugInfo *DI = getDebugInfo()) {
SourceLocation Loc;
Expand Down Expand Up @@ -856,7 +860,10 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {

// Emit the 'then' code.
EmitBlock(ThenBlock);
incrementProfileCounter(&S);
if (llvm::EnableSingleByteCoverage)
incrementProfileCounter(S.getThen());
else
incrementProfileCounter(&S);
{
RunCleanupsScope ThenScope(*this);
EmitStmt(S.getThen());
Expand All @@ -870,6 +877,9 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
auto NL = ApplyDebugLocation::CreateEmpty(*this);
EmitBlock(ElseBlock);
}
// When single byte coverage mode is enabled, add a counter to else block.
if (llvm::EnableSingleByteCoverage)
incrementProfileCounter(Else);
{
RunCleanupsScope ElseScope(*this);
EmitStmt(Else);
Expand All @@ -883,6 +893,11 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {

// Emit the continuation block for code after the if.
EmitBlock(ContBlock, true);

// When single byte coverage mode is enabled, add a counter to continuation
// block.
if (llvm::EnableSingleByteCoverage)
incrementProfileCounter(&S);
}

void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
Expand Down Expand Up @@ -927,6 +942,10 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
SourceLocToDebugLoc(R.getEnd()),
checkIfLoopMustProgress(CondIsConstInt));

// When single byte coverage mode is enabled, add a counter to loop condition.
if (llvm::EnableSingleByteCoverage)
incrementProfileCounter(S.getCond());

// As long as the condition is true, go to the loop body.
llvm::BasicBlock *LoopBody = createBasicBlock("while.body");
if (EmitBoolCondBranch) {
Expand Down Expand Up @@ -959,7 +978,11 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
{
RunCleanupsScope BodyScope(*this);
EmitBlock(LoopBody);
incrementProfileCounter(&S);
// When single byte coverage mode is enabled, add a counter to the body.
if (llvm::EnableSingleByteCoverage)
incrementProfileCounter(S.getBody());
else
incrementProfileCounter(&S);
EmitStmt(S.getBody());
}

Expand All @@ -981,6 +1004,11 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
// a branch, try to erase it.
if (!EmitBoolCondBranch)
SimplifyForwardingBlocks(LoopHeader.getBlock());

// When single byte coverage mode is enabled, add a counter to continuation
// block.
if (llvm::EnableSingleByteCoverage)
incrementProfileCounter(&S);
}

void CodeGenFunction::EmitDoStmt(const DoStmt &S,
Expand All @@ -996,13 +1024,19 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S,
// Emit the body of the loop.
llvm::BasicBlock *LoopBody = createBasicBlock("do.body");

EmitBlockWithFallThrough(LoopBody, &S);
if (llvm::EnableSingleByteCoverage)
EmitBlockWithFallThrough(LoopBody, S.getBody());
else
EmitBlockWithFallThrough(LoopBody, &S);
{
RunCleanupsScope BodyScope(*this);
EmitStmt(S.getBody());
}

EmitBlock(LoopCond.getBlock());
// When single byte coverage mode is enabled, add a counter to loop condition.
if (llvm::EnableSingleByteCoverage)
incrementProfileCounter(S.getCond());

// C99 6.8.5.2: "The evaluation of the controlling expression takes place
// after each execution of the loop body."
Expand Down Expand Up @@ -1043,6 +1077,11 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S,
// emitting a branch, try to erase it.
if (!EmitBoolCondBranch)
SimplifyForwardingBlocks(LoopCond.getBlock());

// When single byte coverage mode is enabled, add a counter to continuation
// block.
if (llvm::EnableSingleByteCoverage)
incrementProfileCounter(&S);
}

void CodeGenFunction::EmitForStmt(const ForStmt &S,
Expand Down Expand Up @@ -1101,6 +1140,11 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
BreakContinueStack.back().ContinueBlock = Continue;
}

// When single byte coverage mode is enabled, add a counter to loop
// condition.
if (llvm::EnableSingleByteCoverage)
incrementProfileCounter(S.getCond());

llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
// If there are any cleanups between here and the loop-exit scope,
// create a block to stage a loop exit along.
Expand Down Expand Up @@ -1131,8 +1175,12 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
// Treat it as a non-zero constant. Don't even create a new block for the
// body, just fall into it.
}
incrementProfileCounter(&S);

// When single byte coverage mode is enabled, add a counter to the body.
if (llvm::EnableSingleByteCoverage)
incrementProfileCounter(S.getBody());
else
incrementProfileCounter(&S);
{
// Create a separate cleanup scope for the body, in case it is not
// a compound statement.
Expand All @@ -1144,6 +1192,8 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
if (S.getInc()) {
EmitBlock(Continue.getBlock());
EmitStmt(S.getInc());
if (llvm::EnableSingleByteCoverage)
incrementProfileCounter(S.getInc());
}

BreakContinueStack.pop_back();
Expand All @@ -1159,6 +1209,11 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,

// Emit the fall-through block.
EmitBlock(LoopExit.getBlock(), true);

// When single byte coverage mode is enabled, add a counter to continuation
// block.
if (llvm::EnableSingleByteCoverage)
incrementProfileCounter(&S);
}

void
Expand Down Expand Up @@ -1211,7 +1266,10 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
}

EmitBlock(ForBody);
incrementProfileCounter(&S);
if (llvm::EnableSingleByteCoverage)
incrementProfileCounter(S.getBody());
else
incrementProfileCounter(&S);

// Create a block for the increment. In case of a 'continue', we jump there.
JumpDest Continue = getJumpDestInCurrentScope("for.inc");
Expand Down Expand Up @@ -1241,6 +1299,11 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,

// Emit the fall-through block.
EmitBlock(LoopExit.getBlock(), true);

// When single byte coverage mode is enabled, add a counter to continuation
// block.
if (llvm::EnableSingleByteCoverage)
incrementProfileCounter(&S);
}

void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
Expand Down
9 changes: 8 additions & 1 deletion clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
using namespace clang;
using namespace CodeGen;

namespace llvm {
extern cl::opt<bool> EnableSingleByteCoverage;
} // namespace llvm

/// shouldEmitLifetimeMarkers - Decide whether we need emit the life-time
/// markers.
static bool shouldEmitLifetimeMarkers(const CodeGenOptions &CGOpts,
Expand Down Expand Up @@ -1270,7 +1274,10 @@ void CodeGenFunction::EmitFunctionBody(const Stmt *Body) {
void CodeGenFunction::EmitBlockWithFallThrough(llvm::BasicBlock *BB,
const Stmt *S) {
llvm::BasicBlock *SkipCountBB = nullptr;
if (HaveInsertPoint() && CGM.getCodeGenOpts().hasProfileClangInstr()) {
// Do not skip over the instrumentation when single byte coverage mode is
// enabled.
if (HaveInsertPoint() && CGM.getCodeGenOpts().hasProfileClangInstr() &&
!llvm::EnableSingleByteCoverage) {
// When instrumenting for profiling, the fallthrough to certain
// statements needs to skip over the instrumentation code so that we
// get an accurate count.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1545,7 +1545,7 @@ class CodeGenFunction : public CodeGenTypeCache {
if (CGM.getCodeGenOpts().hasProfileClangInstr() &&
!CurFn->hasFnAttribute(llvm::Attribute::NoProfile) &&
!CurFn->hasFnAttribute(llvm::Attribute::SkipProfile))
PGO.emitCounterIncrement(Builder, S, StepV);
PGO.emitCounterSetOrIncrement(Builder, S, StepV);
PGO.setCurrentStmt(S);
}

Expand Down
116 changes: 19 additions & 97 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,8 +397,8 @@ CodeGenModule::CodeGenModule(ASTContext &C,
// Enable TBAA unless it's suppressed. ThreadSanitizer needs TBAA even at O0.
if (LangOpts.Sanitize.has(SanitizerKind::Thread) ||
(!CodeGenOpts.RelaxedAliasing && CodeGenOpts.OptimizationLevel > 0))
TBAA.reset(new CodeGenTBAA(Context, TheModule, CodeGenOpts, getLangOpts(),
getCXXABI().getMangleContext()));
TBAA.reset(new CodeGenTBAA(Context, getTypes(), TheModule, CodeGenOpts,
getLangOpts(), getCXXABI().getMangleContext()));

// If debug info or coverage generation is enabled, create the CGDebugInfo
// object.
Expand Down Expand Up @@ -858,6 +858,7 @@ void CodeGenModule::Release() {
checkAliases();
EmitDeferredUnusedCoverageMappings();
CodeGenPGO(*this).setValueProfilingFlag(getModule());
CodeGenPGO(*this).setProfileVersion(getModule());
if (CoverageMapping)
CoverageMapping->emit();
if (CodeGenOpts.SanitizeCfiCrossDso) {
Expand Down Expand Up @@ -1726,59 +1727,6 @@ static void AppendCPUSpecificCPUDispatchMangling(const CodeGenModule &CGM,
Out << ".resolver";
}

static void AppendTargetVersionMangling(const CodeGenModule &CGM,
const TargetVersionAttr *Attr,
raw_ostream &Out) {
if (Attr->isDefaultVersion()) {
Out << ".default";
return;
}
Out << "._";
const TargetInfo &TI = CGM.getTarget();
llvm::SmallVector<StringRef, 8> Feats;
Attr->getFeatures(Feats);
llvm::stable_sort(Feats, [&TI](const StringRef FeatL, const StringRef FeatR) {
return TI.multiVersionSortPriority(FeatL) <
TI.multiVersionSortPriority(FeatR);
});
for (const auto &Feat : Feats) {
Out << 'M';
Out << Feat;
}
}

static void AppendTargetMangling(const CodeGenModule &CGM,
const TargetAttr *Attr, raw_ostream &Out) {
if (Attr->isDefaultVersion())
return;

Out << '.';
const TargetInfo &Target = CGM.getTarget();
ParsedTargetAttr Info = Target.parseTargetAttr(Attr->getFeaturesStr());
llvm::sort(Info.Features, [&Target](StringRef LHS, StringRef RHS) {
// Multiversioning doesn't allow "no-${feature}", so we can
// only have "+" prefixes here.
assert(LHS.starts_with("+") && RHS.starts_with("+") &&
"Features should always have a prefix.");
return Target.multiVersionSortPriority(LHS.substr(1)) >
Target.multiVersionSortPriority(RHS.substr(1));
});

bool IsFirst = true;

if (!Info.CPU.empty()) {
IsFirst = false;
Out << "arch_" << Info.CPU;
}

for (StringRef Feat : Info.Features) {
if (!IsFirst)
Out << '_';
IsFirst = false;
Out << Feat.substr(1);
}
}

// Returns true if GD is a function decl with internal linkage and
// needs a unique suffix after the mangled name.
static bool isUniqueInternalLinkageDecl(GlobalDecl GD,
Expand All @@ -1788,41 +1736,6 @@ static bool isUniqueInternalLinkageDecl(GlobalDecl GD,
(CGM.getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage);
}

static void AppendTargetClonesMangling(const CodeGenModule &CGM,
const TargetClonesAttr *Attr,
unsigned VersionIndex,
raw_ostream &Out) {
const TargetInfo &TI = CGM.getTarget();
if (TI.getTriple().isAArch64()) {
StringRef FeatureStr = Attr->getFeatureStr(VersionIndex);
if (FeatureStr == "default") {
Out << ".default";
return;
}
Out << "._";
SmallVector<StringRef, 8> Features;
FeatureStr.split(Features, "+");
llvm::stable_sort(Features,
[&TI](const StringRef FeatL, const StringRef FeatR) {
return TI.multiVersionSortPriority(FeatL) <
TI.multiVersionSortPriority(FeatR);
});
for (auto &Feat : Features) {
Out << 'M';
Out << Feat;
}
} else {
Out << '.';
StringRef FeatureStr = Attr->getFeatureStr(VersionIndex);
if (FeatureStr.starts_with("arch="))
Out << "arch_" << FeatureStr.substr(sizeof("arch=") - 1);
else
Out << FeatureStr;

Out << '.' << Attr->getMangledIndex(VersionIndex);
}
}

static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
const NamedDecl *ND,
bool OmitMultiVersionMangling = false) {
Expand Down Expand Up @@ -1876,16 +1789,25 @@ static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
FD->getAttr<CPUSpecificAttr>(),
GD.getMultiVersionIndex(), Out);
break;
case MultiVersionKind::Target:
AppendTargetMangling(CGM, FD->getAttr<TargetAttr>(), Out);
case MultiVersionKind::Target: {
auto *Attr = FD->getAttr<TargetAttr>();
const ABIInfo &Info = CGM.getTargetCodeGenInfo().getABIInfo();
Info.appendAttributeMangling(Attr, Out);
break;
case MultiVersionKind::TargetVersion:
AppendTargetVersionMangling(CGM, FD->getAttr<TargetVersionAttr>(), Out);
}
case MultiVersionKind::TargetVersion: {
auto *Attr = FD->getAttr<TargetVersionAttr>();
const ABIInfo &Info = CGM.getTargetCodeGenInfo().getABIInfo();
Info.appendAttributeMangling(Attr, Out);
break;
case MultiVersionKind::TargetClones:
AppendTargetClonesMangling(CGM, FD->getAttr<TargetClonesAttr>(),
GD.getMultiVersionIndex(), Out);
}
case MultiVersionKind::TargetClones: {
auto *Attr = FD->getAttr<TargetClonesAttr>();
unsigned Index = GD.getMultiVersionIndex();
const ABIInfo &Info = CGM.getTargetCodeGenInfo().getABIInfo();
Info.appendAttributeMangling(Attr, Index, Out);
break;
}
case MultiVersionKind::None:
llvm_unreachable("None multiversion type isn't valid here");
}
Expand Down
150 changes: 138 additions & 12 deletions clang/lib/CodeGen/CodeGenPGO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
#include "llvm/Support/MD5.h"
#include <optional>

namespace llvm {
extern cl::opt<bool> EnableSingleByteCoverage;
} // namespace llvm

static llvm::cl::opt<bool>
EnableValueProfiling("enable-value-profiling",
llvm::cl::desc("Enable value profiling"),
Expand Down Expand Up @@ -346,6 +350,14 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
return Base::VisitBinaryOperator(S);
}

bool VisitConditionalOperator(ConditionalOperator *S) {
if (llvm::EnableSingleByteCoverage && S->getTrueExpr())
CounterMap[S->getTrueExpr()] = NextCounter++;
if (llvm::EnableSingleByteCoverage && S->getFalseExpr())
CounterMap[S->getFalseExpr()] = NextCounter++;
return Base::VisitConditionalOperator(S);
}

/// Include \p S in the function hash.
bool VisitStmt(Stmt *S) {
auto Type = updateCounterMappings(S);
Expand All @@ -361,8 +373,21 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
if (Hash.getHashVersion() == PGO_HASH_V1)
return Base::TraverseIfStmt(If);

// When single byte coverage mode is enabled, add a counter to then and
// else.
bool NoSingleByteCoverage = !llvm::EnableSingleByteCoverage;
for (Stmt *CS : If->children()) {
if (!CS || NoSingleByteCoverage)
continue;
if (CS == If->getThen())
CounterMap[If->getThen()] = NextCounter++;
else if (CS == If->getElse())
CounterMap[If->getElse()] = NextCounter++;
}

// Otherwise, keep track of which branch we're in while traversing.
VisitStmt(If);

for (Stmt *CS : If->children()) {
if (!CS)
continue;
Expand All @@ -376,6 +401,81 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
return true;
}

bool TraverseWhileStmt(WhileStmt *While) {
// When single byte coverage mode is enabled, add a counter to condition and
// body.
bool NoSingleByteCoverage = !llvm::EnableSingleByteCoverage;
for (Stmt *CS : While->children()) {
if (!CS || NoSingleByteCoverage)
continue;
if (CS == While->getCond())
CounterMap[While->getCond()] = NextCounter++;
else if (CS == While->getBody())
CounterMap[While->getBody()] = NextCounter++;
}

Base::TraverseWhileStmt(While);
if (Hash.getHashVersion() != PGO_HASH_V1)
Hash.combine(PGOHash::EndOfScope);
return true;
}

bool TraverseDoStmt(DoStmt *Do) {
// When single byte coverage mode is enabled, add a counter to condition and
// body.
bool NoSingleByteCoverage = !llvm::EnableSingleByteCoverage;
for (Stmt *CS : Do->children()) {
if (!CS || NoSingleByteCoverage)
continue;
if (CS == Do->getCond())
CounterMap[Do->getCond()] = NextCounter++;
else if (CS == Do->getBody())
CounterMap[Do->getBody()] = NextCounter++;
}

Base::TraverseDoStmt(Do);
if (Hash.getHashVersion() != PGO_HASH_V1)
Hash.combine(PGOHash::EndOfScope);
return true;
}

bool TraverseForStmt(ForStmt *For) {
// When single byte coverage mode is enabled, add a counter to condition,
// increment and body.
bool NoSingleByteCoverage = !llvm::EnableSingleByteCoverage;
for (Stmt *CS : For->children()) {
if (!CS || NoSingleByteCoverage)
continue;
if (CS == For->getCond())
CounterMap[For->getCond()] = NextCounter++;
else if (CS == For->getInc())
CounterMap[For->getInc()] = NextCounter++;
else if (CS == For->getBody())
CounterMap[For->getBody()] = NextCounter++;
}

Base::TraverseForStmt(For);
if (Hash.getHashVersion() != PGO_HASH_V1)
Hash.combine(PGOHash::EndOfScope);
return true;
}

bool TraverseCXXForRangeStmt(CXXForRangeStmt *ForRange) {
// When single byte coverage mode is enabled, add a counter to body.
bool NoSingleByteCoverage = !llvm::EnableSingleByteCoverage;
for (Stmt *CS : ForRange->children()) {
if (!CS || NoSingleByteCoverage)
continue;
if (CS == ForRange->getBody())
CounterMap[ForRange->getBody()] = NextCounter++;
}

Base::TraverseCXXForRangeStmt(ForRange);
if (Hash.getHashVersion() != PGO_HASH_V1)
Hash.combine(PGOHash::EndOfScope);
return true;
}

// If the statement type \p N is nestable, and its nesting impacts profile
// stability, define a custom traversal which tracks the end of the statement
// in the hash (provided we're not using the V1 hash).
Expand All @@ -387,10 +487,6 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
return true; \
}

DEFINE_NESTABLE_TRAVERSAL(WhileStmt)
DEFINE_NESTABLE_TRAVERSAL(DoStmt)
DEFINE_NESTABLE_TRAVERSAL(ForStmt)
DEFINE_NESTABLE_TRAVERSAL(CXXForRangeStmt)
DEFINE_NESTABLE_TRAVERSAL(ObjCForCollectionStmt)
DEFINE_NESTABLE_TRAVERSAL(CXXTryStmt)
DEFINE_NESTABLE_TRAVERSAL(CXXCatchStmt)
Expand Down Expand Up @@ -1094,8 +1190,8 @@ CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
Fn->setEntryCount(FunctionCount);
}

void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S,
llvm::Value *StepV) {
void CodeGenPGO::emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S,
llvm::Value *StepV) {
if (!RegionCounterMap || !Builder.GetInsertBlock())
return;

Expand All @@ -1105,13 +1201,19 @@ void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S,
Builder.getInt64(FunctionHash),
Builder.getInt32(NumRegionCounters),
Builder.getInt32(Counter), StepV};
if (!StepV)
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment),

if (llvm::EnableSingleByteCoverage)
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_cover),
ArrayRef(Args, 4));
else
Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment_step),
ArrayRef(Args));
else {
if (!StepV)
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment),
ArrayRef(Args, 4));
else
Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment_step),
ArrayRef(Args));
}
}

bool CodeGenPGO::canEmitMCDCCoverage(const CGBuilderTy &Builder) {
Expand Down Expand Up @@ -1222,6 +1324,30 @@ void CodeGenPGO::setValueProfilingFlag(llvm::Module &M) {
uint32_t(EnableValueProfiling));
}

void CodeGenPGO::setProfileVersion(llvm::Module &M) {
if (CGM.getCodeGenOpts().hasProfileClangInstr() &&
llvm::EnableSingleByteCoverage) {
const StringRef VarName(INSTR_PROF_QUOTE(INSTR_PROF_RAW_VERSION_VAR));
llvm::Type *IntTy64 = llvm::Type::getInt64Ty(M.getContext());
uint64_t ProfileVersion =
(INSTR_PROF_RAW_VERSION | VARIANT_MASK_BYTE_COVERAGE);

auto IRLevelVersionVariable = new llvm::GlobalVariable(
M, IntTy64, true, llvm::GlobalValue::WeakAnyLinkage,
llvm::Constant::getIntegerValue(IntTy64,
llvm::APInt(64, ProfileVersion)),
VarName);

IRLevelVersionVariable->setVisibility(llvm::GlobalValue::DefaultVisibility);
llvm::Triple TT(M.getTargetTriple());
if (TT.supportsCOMDAT()) {
IRLevelVersionVariable->setLinkage(llvm::GlobalValue::ExternalLinkage);
IRLevelVersionVariable->setComdat(M.getOrInsertComdat(VarName));
}
IRLevelVersionVariable->setDSOLocal(true);
}
}

// This method either inserts a call to the profile run-time during
// instrumentation or puts profile data into metadata for PGO use.
void CodeGenPGO::valueProfile(CGBuilderTy &Builder, uint32_t ValueKind,
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/CodeGen/CodeGenPGO.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ class CodeGenPGO {
// Set a module flag indicating if value profiling is enabled.
void setValueProfilingFlag(llvm::Module &M);

void setProfileVersion(llvm::Module &M);

private:
void setFuncName(llvm::Function *Fn);
void setFuncName(StringRef Name, llvm::GlobalValue::LinkageTypes Linkage);
Expand All @@ -108,8 +110,8 @@ class CodeGenPGO {
bool canEmitMCDCCoverage(const CGBuilderTy &Builder);

public:
void emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S,
llvm::Value *StepV);
void emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S,
llvm::Value *StepV);
void emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S,
Address MCDCCondBitmapAddr);
void emitMCDCParameters(CGBuilderTy &Builder);
Expand Down
44 changes: 33 additions & 11 deletions clang/lib/CodeGen/CodeGenTBAA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
//===----------------------------------------------------------------------===//

#include "CodeGenTBAA.h"
#include "CGRecordLayout.h"
#include "CodeGenTypes.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Mangle.h"
Expand All @@ -26,16 +28,16 @@
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/Debug.h"
using namespace clang;
using namespace CodeGen;

CodeGenTBAA::CodeGenTBAA(ASTContext &Ctx, llvm::Module &M,
const CodeGenOptions &CGO,
CodeGenTBAA::CodeGenTBAA(ASTContext &Ctx, CodeGenTypes &CGTypes,
llvm::Module &M, const CodeGenOptions &CGO,
const LangOptions &Features, MangleContext &MContext)
: Context(Ctx), Module(M), CodeGenOpts(CGO),
Features(Features), MContext(MContext), MDHelper(M.getContext()),
Root(nullptr), Char(nullptr)
{}
: Context(Ctx), CGTypes(CGTypes), Module(M), CodeGenOpts(CGO),
Features(Features), MContext(MContext), MDHelper(M.getContext()),
Root(nullptr), Char(nullptr) {}

CodeGenTBAA::~CodeGenTBAA() {
}
Expand Down Expand Up @@ -294,14 +296,34 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset,
return false;

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

unsigned idx = 0;
for (RecordDecl::field_iterator i = RD->field_begin(),
e = RD->field_end(); i != e; ++i, ++idx) {
if ((*i)->isZeroSize(Context) || (*i)->isUnnamedBitfield())
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
i != e; ++i, ++idx) {
if ((*i)->isZeroSize(Context))
continue;
uint64_t Offset = BaseOffset +
Layout.getFieldOffset(idx) / Context.getCharWidth();

uint64_t Offset =
BaseOffset + Layout.getFieldOffset(idx) / Context.getCharWidth();

// Create a single field for consecutive named bitfields using char as
// base type.
if ((*i)->isBitField()) {
const CGBitFieldInfo &Info = CGRL.getBitFieldInfo(*i);
if (Info.Offset != 0)
continue;
unsigned CurrentBitFieldSize = Info.StorageSize;
uint64_t Size =
llvm::divideCeil(CurrentBitFieldSize, Context.getCharWidth());
llvm::MDNode *TBAAType = getChar();
llvm::MDNode *TBAATag =
getAccessTagInfo(TBAAAccessInfo(TBAAType, Size));
Fields.push_back(
llvm::MDBuilder::TBAAStructField(Offset, Size, TBAATag));
continue;
}

QualType FieldQTy = i->getType();
if (!CollectFields(Offset, FieldQTy, Fields,
MayAlias || TypeHasMayAlias(FieldQTy)))
Expand Down
7 changes: 5 additions & 2 deletions clang/lib/CodeGen/CodeGenTBAA.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ namespace clang {
class Type;

namespace CodeGen {
class CodeGenTypes;

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

public:
CodeGenTBAA(ASTContext &Ctx, llvm::Module &M, const CodeGenOptions &CGO,
const LangOptions &Features, MangleContext &MContext);
CodeGenTBAA(ASTContext &Ctx, CodeGenTypes &CGTypes, llvm::Module &M,
const CodeGenOptions &CGO, const LangOptions &Features,
MangleContext &MContext);
~CodeGenTBAA();

/// getTypeInfo - Get metadata used to describe accesses to objects of the
Expand Down
Loading