20 changes: 20 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,21 @@ Attribute Changes in Clang
added a new extension query ``__has_extension(swiftcc)`` corresponding to the
``__attribute__((swiftcc))`` attribute.

- The ``_Nullable`` and ``_Nonnull`` family of type attributes can now apply
to certain C++ class types, such as smart pointers:
``void useObject(std::unique_ptr<Object> _Nonnull obj);``.

This works for standard library types including ``unique_ptr``, ``shared_ptr``,
and ``function``. See
`the attribute reference documentation <https://llvm.org/docs/AttributeReference.html#nullability-attributes>`_
for the full list.

- The ``_Nullable`` attribute can be applied to C++ class declarations:
``template <class T> class _Nullable MySmartPointer {};``.

This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to
apply to this class.

Improvements to Clang's diagnostics
-----------------------------------
- Clang now applies syntax highlighting to the code snippets it
Expand Down Expand Up @@ -304,6 +319,9 @@ Improvements to Clang's diagnostics
annotated with the ``clang::always_destroy`` attribute.
Fixes #GH68686, #GH86486

- ``-Wmicrosoft``, ``-Wgnu``, or ``-pedantic`` is now required to diagnose C99
flexible array members in a union or alone in a struct. Fixes GH#84565.

Improvements to Clang's time-trace
----------------------------------

Expand Down Expand Up @@ -454,6 +472,8 @@ Bug Fixes to C++ Support
- Fix a crash when instantiating a lambda that captures ``this`` outside of its context. Fixes (#GH85343).
- Fix an issue where a namespace alias could be defined using a qualified name (all name components
following the first `::` were ignored).
- Fix an out-of-bounds crash when checking the validity of template partial specializations. (part of #GH86757).
- Fix an issue caused by not handling invalid cases when substituting into the parameter mapping of a constraint. Fixes (#GH86757).

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
149 changes: 133 additions & 16 deletions clang/docs/analyzer/checkers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -849,10 +849,89 @@ Check for performance anti-patterns when using Grand Central Dispatch.
.. _optin-performance-Padding:
optin.performance.Padding
"""""""""""""""""""""""""
optin.performance.Padding (C, C++, ObjC)
""""""""""""""""""""""""""""""""""""""""
Check for excessively padded structs.
This checker detects structs with excessive padding, which can lead to wasted
memory thus decreased performance by reducing the effectiveness of the
processor cache. Padding bytes are added by compilers to align data accesses
as some processors require data to be aligned to certain boundaries. On others,
unaligned data access are possible, but impose significantly larger latencies.
To avoid padding bytes, the fields of a struct should be ordered by decreasing
by alignment. Usually, its easier to think of the ``sizeof`` of the fields, and
ordering the fields by ``sizeof`` would usually also lead to the same optimal
layout.
In rare cases, one can use the ``#pragma pack(1)`` directive to enforce a packed
layout too, but it can significantly increase the access times, so reordering the
fields is usually a better solution.
.. code-block:: cpp
// warn: Excessive padding in 'struct NonOptimal' (35 padding bytes, where 3 is optimal)
struct NonOptimal {
char c1;
// 7 bytes of padding
std::int64_t big1; // 8 bytes
char c2;
// 7 bytes of padding
std::int64_t big2; // 8 bytes
char c3;
// 7 bytes of padding
std::int64_t big3; // 8 bytes
char c4;
// 7 bytes of padding
std::int64_t big4; // 8 bytes
char c5;
// 7 bytes of padding
};
static_assert(sizeof(NonOptimal) == 4*8+5+5*7);
// no-warning: The fields are nicely aligned to have the minimal amount of padding bytes.
struct Optimal {
std::int64_t big1; // 8 bytes
std::int64_t big2; // 8 bytes
std::int64_t big3; // 8 bytes
std::int64_t big4; // 8 bytes
char c1;
char c2;
char c3;
char c4;
char c5;
// 3 bytes of padding
};
static_assert(sizeof(Optimal) == 4*8+5+3);
// no-warning: Bit packing representation is also accepted by this checker, but
// it can significantly increase access times, so prefer reordering the fields.
#pragma pack(1)
struct BitPacked {
char c1;
std::int64_t big1; // 8 bytes
char c2;
std::int64_t big2; // 8 bytes
char c3;
std::int64_t big3; // 8 bytes
char c4;
std::int64_t big4; // 8 bytes
char c5;
};
static_assert(sizeof(BitPacked) == 4*8+5);
The ``AllowedPad`` option can be used to specify a threshold for the number
padding bytes raising the warning. If the number of padding bytes of the struct
and the optimal number of padding bytes differ by more than the threshold value,
a warning will be raised.
By default, the ``AllowedPad`` threshold is 24 bytes.
To override this threshold to e.g. 4 bytes, use the
``-analyzer-config optin.performance.Padding:AllowedPad=4`` option.
.. _optin-portability-UnixAPI:
optin.portability.UnixAPI
Expand Down Expand Up @@ -3041,44 +3120,82 @@ Check for misuses of stream APIs. Check for misuses of stream APIs: ``fopen, fcl
alpha.unix.Stream (C)
"""""""""""""""""""""
Check stream handling functions: ``fopen, tmpfile, fclose, fread, fwrite, fseek, ftell, rewind, fgetpos,``
``fsetpos, clearerr, feof, ferror, fileno``.
Check C stream handling functions:
``fopen, fdopen, freopen, tmpfile, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, fprintf, fscanf, ungetc, getdelim, getline, fseek, fseeko, ftell, ftello, fflush, rewind, fgetpos, fsetpos, clearerr, feof, ferror, fileno``.
The checker maintains information about the C stream objects (``FILE *``) and
can detect error conditions related to use of streams. The following conditions
are detected:
* The ``FILE *`` pointer passed to the function is NULL (the single exception is
``fflush`` where NULL is allowed).
* Use of stream after close.
* Opened stream is not closed.
* Read from a stream after end-of-file. (This is not a fatal error but reported
by the checker. Stream remains in EOF state and the read operation fails.)
* Use of stream when the file position is indeterminate after a previous failed
operation. Some functions (like ``ferror``, ``clearerr``, ``fseek``) are
allowed in this state.
* Invalid 3rd ("``whence``") argument to ``fseek``.
The checker does not track the correspondence between integer file descriptors
and ``FILE *`` pointers. Operations on standard streams like ``stdin`` are not
treated specially and are therefore often not recognized (because these streams
are usually not opened explicitly by the program, and are global variables).
.. code-block:: c
void test() {
void test1() {
FILE *p = fopen("foo", "r");
} // warn: opened file is never closed
void test() {
void test2() {
FILE *p = fopen("foo", "r");
fseek(p, 1, SEEK_SET); // warn: stream pointer might be NULL
fclose(p);
}
void test() {
void test3() {
FILE *p = fopen("foo", "r");
if (p) {
fseek(p, 1, 3); // warn: third arg should be SEEK_SET, SEEK_END, or SEEK_CUR
fclose(p);
}
}
if (p)
fseek(p, 1, 3);
// warn: third arg should be SEEK_SET, SEEK_END, or SEEK_CUR
void test4() {
FILE *p = fopen("foo", "r");
if (!p)
return;
fclose(p);
fclose(p); // warn: stream already closed
}
void test() {
void test5() {
FILE *p = fopen("foo", "r");
if (!p)
return;
fgetc(p);
if (!ferror(p))
fgetc(p); // warn: possible read after end-of-file
fclose(p);
fclose(p); // warn: already closed
}
void test() {
FILE *p = tmpfile();
ftell(p); // warn: stream pointer might be NULL
void test6() {
FILE *p = fopen("foo", "r");
if (!p)
return;
fgetc(p);
if (!feof(p))
fgetc(p); // warn: file position may be indeterminate after I/O error
fclose(p);
}
.. _alpha-unix-cstring-BufferOverlap:
alpha.unix.cstring.BufferOverlap (C)
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang-c/Index.h
Original file line number Diff line number Diff line change
Expand Up @@ -2991,6 +2991,7 @@ enum CXCallingConv {
CXCallingConv_AArch64SVEPCS = 18,
CXCallingConv_M68kRTD = 19,
CXCallingConv_PreserveNone = 20,
CXCallingConv_RISCVVectorCall = 21,

CXCallingConv_Invalid = 100,
CXCallingConv_Unexposed = 200
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/AST/TextNodeDumper.h
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ class TextNodeDumper
void VisitEnumConstantDecl(const EnumConstantDecl *D);
void VisitIndirectFieldDecl(const IndirectFieldDecl *D);
void VisitFunctionDecl(const FunctionDecl *D);
void VisitCXXDeductionGuideDecl(const CXXDeductionGuideDecl *D);
void VisitFieldDecl(const FieldDecl *D);
void VisitVarDecl(const VarDecl *D);
void VisitBindingDecl(const BindingDecl *D);
Expand Down
29 changes: 29 additions & 0 deletions clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,35 @@ RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
std::vector<const FieldDecl *>
getFieldsForInitListExpr(const InitListExpr *InitList);

/// Helper class for initialization of a record with an `InitListExpr`.
/// `InitListExpr::inits()` contains the initializers for both the base classes
/// and the fields of the record; this helper class separates these out into two
/// different lists. In addition, it deals with special cases associated with
/// unions.
class RecordInitListHelper {
public:
// `InitList` must have record type.
RecordInitListHelper(const InitListExpr *InitList);

// Base classes with their associated initializer expressions.
ArrayRef<std::pair<const CXXBaseSpecifier *, Expr *>> base_inits() const {
return BaseInits;
}

// Fields with their associated initializer expressions.
ArrayRef<std::pair<const FieldDecl *, Expr *>> field_inits() const {
return FieldInits;
}

private:
SmallVector<std::pair<const CXXBaseSpecifier *, Expr *>> BaseInits;
SmallVector<std::pair<const FieldDecl *, Expr *>> FieldInits;

// We potentially synthesize an `ImplicitValueInitExpr` for unions. It's a
// member variable because we store a pointer to it in `FieldInits`.
std::optional<ImplicitValueInitExpr> ImplicitValueInitForUnion;
};

/// Associates a new `RecordValue` with `Loc` and returns the new value.
RecordValue &refreshRecordValue(RecordStorageLocation &Loc, Environment &Env);

Expand Down
10 changes: 9 additions & 1 deletion clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -2178,9 +2178,10 @@ def TypeNonNull : TypeAttr {
let Documentation = [TypeNonNullDocs];
}

def TypeNullable : TypeAttr {
def TypeNullable : DeclOrTypeAttr {
let Spellings = [CustomKeyword<"_Nullable">];
let Documentation = [TypeNullableDocs];
// let Subjects = SubjectList<[CXXRecord], ErrorDiag>;
}

def TypeNullableResult : TypeAttr {
Expand Down Expand Up @@ -3011,6 +3012,13 @@ def PreserveNone : DeclOrTypeAttr, TargetSpecificAttr<TargetAnyX86> {
let Documentation = [PreserveNoneDocs];
}

def RISCVVectorCC: DeclOrTypeAttr, TargetSpecificAttr<TargetRISCV> {
let Spellings = [CXX11<"riscv", "vector_cc">,
C23<"riscv", "vector_cc">,
Clang<"riscv_vector_cc">];
let Documentation = [RISCVVectorCCDocs];
}

def Target : InheritableAttr {
let Spellings = [GCC<"target">];
let Args = [StringArgument<"featuresStr">];
Expand Down
36 changes: 36 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -4151,6 +4151,20 @@ non-underscored keywords. For example:
@property (assign, nullable) NSView *superview;
@property (readonly, nonnull) NSArray *subviews;
@end

As well as built-in pointer types, the nullability attributes can be attached
to C++ classes marked with the ``_Nullable`` attribute.

The following C++ standard library types are considered nullable:
``unique_ptr``, ``shared_ptr``, ``auto_ptr``, ``exception_ptr``, ``function``,
``move_only_function`` and ``coroutine_handle``.

Types should be marked nullable only where the type itself leaves nullability
ambiguous. For example, ``std::optional`` is not marked ``_Nullable``, because
``optional<int> _Nullable`` is redundant and ``optional<int> _Nonnull`` is
not a useful type. ``std::weak_ptr`` is not nullable, because its nullability
can change with no visible modification, so static annotation is unlikely to be
unhelpful.
}];
}

Expand Down Expand Up @@ -4185,6 +4199,17 @@ The ``_Nullable`` nullability qualifier indicates that a value of the
int fetch_or_zero(int * _Nullable ptr);

a caller of ``fetch_or_zero`` can provide null.

The ``_Nullable`` attribute on classes indicates that the given class can
represent null values, and so the ``_Nullable``, ``_Nonnull`` etc qualifiers
make sense for this type. For example:

.. code-block:: c

class _Nullable ArenaPointer { ... };

ArenaPointer _Nonnull x = ...;
ArenaPointer _Nullable y = nullptr;
}];
}

Expand Down Expand Up @@ -5494,6 +5519,17 @@ for clang builtin functions.
}];
}

def RISCVVectorCCDocs : Documentation {
let Category = DocCatCallingConvs;
let Heading = "riscv::vector_cc, riscv_vector_cc, clang::riscv_vector_cc";
let Content = [{
The ``riscv_vector_cc`` attribute can be applied to a function. It preserves 15
registers namely, v1-v7 and v24-v31 as callee-saved. Callers thus don't need
to save these registers before function calls, and callees only need to save
them if they use them.
}];
}

def PreferredNameDocs : Documentation {
let Category = DocCatDecl;
let Content = [{
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 @@ -4599,6 +4599,12 @@ def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
let Prototype = "unsigned int(bool)";
}

def HLSLWaveGetLaneIndex : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_wave_get_lane_index"];
let Attributes = [NoThrow, Const];
let Prototype = "unsigned int()";
}

def HLSLClamp : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_elementwise_clamp"];
let Attributes = [NoThrow, Const];
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Basic/DiagnosticDriverKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,8 @@ def err_drv_hlsl_unsupported_target : Error<
"HLSL code generation is unsupported for target '%0'">;
def err_drv_hlsl_bad_shader_required_in_target : Error<
"%select{shader model|Vulkan environment|shader stage}0 is required as %select{OS|environment}1 in target '%2' for HLSL code generation">;

def err_drv_hlsl_16bit_types_unsupported: Error<
"'%0' option requires target HLSL Version >= 2018%select{| and shader model >= 6.2}1, but HLSL Version is '%2'%select{| and shader model is '%3'}1">;
def err_drv_hlsl_bad_shader_unsupported : Error<
"%select{shader model|Vulkan environment|shader stage}0 '%1' in target '%2' is invalid for HLSL code generation">;
def warn_drv_dxc_missing_dxv : Warning<"dxv not found. "
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/DiagnosticInstallAPIKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def err_no_output_file: Error<"no output file specified">;
def err_no_such_header_file : Error<"no such %select{public|private|project}1 header file: '%0'">;
def warn_no_such_excluded_header_file : Warning<"no such excluded %select{public|private}0 header file: '%1'">, InGroup<InstallAPIViolation>;
def warn_glob_did_not_match: Warning<"glob '%0' did not match any header file">, InGroup<InstallAPIViolation>;
def err_no_such_umbrella_header_file : Error<"%select{public|private|project}1 umbrella header file not found in input: '%0'">;
} // end of command line category.

let CategoryName = "Verification" in {
Expand Down
5 changes: 0 additions & 5 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -6464,9 +6464,6 @@ def ext_c99_flexible_array_member : Extension<
def err_flexible_array_virtual_base : Error<
"flexible array member %0 not allowed in "
"%select{struct|interface|union|class|enum}1 which has a virtual base class">;
def err_flexible_array_empty_aggregate : Error<
"flexible array member %0 not allowed in otherwise empty "
"%select{struct|interface|union|class|enum}1">;
def err_flexible_array_has_nontrivial_dtor : Error<
"flexible array member %0 of type %1 with non-trivial destruction">;
def ext_flexible_array_in_struct : Extension<
Expand All @@ -6481,8 +6478,6 @@ def ext_flexible_array_empty_aggregate_ms : Extension<
"flexible array member %0 in otherwise empty "
"%select{struct|interface|union|class|enum}1 is a Microsoft extension">,
InGroup<MicrosoftFlexibleArray>;
def err_flexible_array_union : Error<
"flexible array member %0 in a union is not allowed">;
def ext_flexible_array_union_ms : Extension<
"flexible array member %0 in a union is a Microsoft extension">,
InGroup<MicrosoftFlexibleArray>;
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ EXTENSION(define_target_os_macros,
FEATURE(enumerator_attributes, true)
FEATURE(nullability, true)
FEATURE(nullability_on_arrays, true)
FEATURE(nullability_on_classes, true)
FEATURE(nullability_nullable_result, true)
FEATURE(memory_sanitizer,
LangOpts.Sanitize.hasOneOf(SanitizerKind::Memory |
Expand Down
43 changes: 22 additions & 21 deletions clang/include/clang/Basic/Specifiers.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,29 +273,30 @@ namespace clang {

/// CallingConv - Specifies the calling convention that a function uses.
enum CallingConv {
CC_C, // __attribute__((cdecl))
CC_X86StdCall, // __attribute__((stdcall))
CC_X86FastCall, // __attribute__((fastcall))
CC_X86ThisCall, // __attribute__((thiscall))
CC_X86VectorCall, // __attribute__((vectorcall))
CC_X86Pascal, // __attribute__((pascal))
CC_Win64, // __attribute__((ms_abi))
CC_X86_64SysV, // __attribute__((sysv_abi))
CC_X86RegCall, // __attribute__((regcall))
CC_AAPCS, // __attribute__((pcs("aapcs")))
CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp")))
CC_IntelOclBicc, // __attribute__((intel_ocl_bicc))
CC_SpirFunction, // default for OpenCL functions on SPIR target
CC_OpenCLKernel, // inferred for OpenCL kernels
CC_Swift, // __attribute__((swiftcall))
CC_C, // __attribute__((cdecl))
CC_X86StdCall, // __attribute__((stdcall))
CC_X86FastCall, // __attribute__((fastcall))
CC_X86ThisCall, // __attribute__((thiscall))
CC_X86VectorCall, // __attribute__((vectorcall))
CC_X86Pascal, // __attribute__((pascal))
CC_Win64, // __attribute__((ms_abi))
CC_X86_64SysV, // __attribute__((sysv_abi))
CC_X86RegCall, // __attribute__((regcall))
CC_AAPCS, // __attribute__((pcs("aapcs")))
CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp")))
CC_IntelOclBicc, // __attribute__((intel_ocl_bicc))
CC_SpirFunction, // default for OpenCL functions on SPIR target
CC_OpenCLKernel, // inferred for OpenCL kernels
CC_Swift, // __attribute__((swiftcall))
CC_SwiftAsync, // __attribute__((swiftasynccall))
CC_PreserveMost, // __attribute__((preserve_most))
CC_PreserveAll, // __attribute__((preserve_all))
CC_PreserveMost, // __attribute__((preserve_most))
CC_PreserveAll, // __attribute__((preserve_all))
CC_AArch64VectorCall, // __attribute__((aarch64_vector_pcs))
CC_AArch64SVEPCS, // __attribute__((aarch64_sve_pcs))
CC_AMDGPUKernelCall, // __attribute__((amdgpu_kernel))
CC_M68kRTD, // __attribute__((m68k_rtd))
CC_PreserveNone, // __attribute__((preserve_none))
CC_AArch64SVEPCS, // __attribute__((aarch64_sve_pcs))
CC_AMDGPUKernelCall, // __attribute__((amdgpu_kernel))
CC_M68kRTD, // __attribute__((m68k_rtd))
CC_PreserveNone, // __attribute__((preserve_none))
CC_RISCVVectorCall, // __attribute__((riscv_vector_cc))
};

/// Checks whether the given calling convention supports variadic
Expand Down
16 changes: 11 additions & 5 deletions clang/include/clang/InstallAPI/HeaderFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@

namespace clang::installapi {
enum class HeaderType {
/// Unset or unknown type.
Unknown,
/// Represents declarations accessible to all clients.
Public,
/// Represents declarations accessible to a disclosed set of clients.
Private,
/// Represents declarations only accessible as implementation details to the
/// input library.
Project,
/// Unset or unknown type.
Unknown,
};

inline StringRef getName(const HeaderType T) {
Expand Down Expand Up @@ -62,6 +62,8 @@ class HeaderFile {
bool Excluded{false};
/// Add header file to processing.
bool Extra{false};
/// Specify that header file is the umbrella header for library.
bool Umbrella{false};

public:
HeaderFile() = delete;
Expand All @@ -79,17 +81,21 @@ class HeaderFile {

void setExtra(bool V = true) { Extra = V; }
void setExcluded(bool V = true) { Excluded = V; }
void setUmbrellaHeader(bool V = true) { Umbrella = V; }
bool isExtra() const { return Extra; }
bool isExcluded() const { return Excluded; }
bool isUmbrellaHeader() const { return Umbrella; }

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

bool operator==(const HeaderFile &Other) const {
return std::tie(Type, FullPath, IncludeName, Language, Excluded, Extra) ==
std::tie(Other.Type, Other.FullPath, Other.IncludeName,
Other.Language, Other.Excluded, Other.Extra);
return std::tie(Type, FullPath, IncludeName, Language, Excluded, Extra,
Umbrella) == std::tie(Other.Type, Other.FullPath,
Other.IncludeName, Other.Language,
Other.Excluded, Other.Extra,
Other.Umbrella);
}
};

Expand Down
15 changes: 8 additions & 7 deletions clang/include/clang/Lex/ModuleMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,8 @@ class ModuleMap {
Attributes Attrs;

/// If \c InferModules is non-zero, the module map file that allowed
/// inferred modules. Otherwise, nullopt.
OptionalFileEntryRef ModuleMapFile;
/// inferred modules. Otherwise, invalid.
FileID ModuleMapFID;

/// The names of modules that cannot be inferred within this
/// directory.
Expand All @@ -279,8 +279,7 @@ class ModuleMap {

/// A mapping from an inferred module to the module map that allowed the
/// inference.
// FIXME: Consider making the values non-optional.
llvm::DenseMap<const Module *, OptionalFileEntryRef> InferredModuleAllowedBy;
llvm::DenseMap<const Module *, FileID> InferredModuleAllowedBy;

llvm::DenseMap<const Module *, AdditionalModMapsSet> AdditionalModMaps;

Expand Down Expand Up @@ -618,8 +617,9 @@ class ModuleMap {
///
/// \param Module The module whose module map file will be returned, if known.
///
/// \returns The file entry for the module map file containing the given
/// module, or nullptr if the module definition was inferred.
/// \returns The FileID for the module map file containing the given module,
/// invalid if the module definition was inferred.
FileID getContainingModuleMapFileID(const Module *Module) const;
OptionalFileEntryRef getContainingModuleMapFile(const Module *Module) const;

/// Get the module map file that (along with the module name) uniquely
Expand All @@ -631,9 +631,10 @@ class ModuleMap {
/// of inferred modules, returns the module map that allowed the inference
/// (e.g. contained 'module *'). Otherwise, returns
/// getContainingModuleMapFile().
FileID getModuleMapFileIDForUniquing(const Module *M) const;
OptionalFileEntryRef getModuleMapFileForUniquing(const Module *M) const;

void setInferredModuleAllowedBy(Module *M, OptionalFileEntryRef ModMap);
void setInferredModuleAllowedBy(Module *M, FileID ModMapFID);

/// Canonicalize \p Path in a manner suitable for a module map file. In
/// particular, this canonicalizes the parent directory separately from the
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -3014,6 +3014,7 @@ class Parser : public CodeCompletionHandler {
void DiagnoseAndSkipExtendedMicrosoftTypeAttributes();
SourceLocation SkipExtendedMicrosoftTypeAttributes();
void ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs);
void ParseNullabilityClassAttributes(ParsedAttributes &attrs);
void ParseBorlandTypeAttributes(ParsedAttributes &attrs);
void ParseOpenCLKernelAttributes(ParsedAttributes &attrs);
void ParseOpenCLQualifiers(ParsedAttributes &Attrs);
Expand Down
6 changes: 5 additions & 1 deletion clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -1655,6 +1655,9 @@ class Sema final {
/// Add [[gsl::Pointer]] attributes for std:: types.
void inferGslPointerAttribute(TypedefNameDecl *TD);

/// Add _Nullable attributes for std:: types.
void inferNullableClassAttribute(CXXRecordDecl *CRD);

enum PragmaOptionsAlignKind {
POAK_Native, // #pragma options align=native
POAK_Natural, // #pragma options align=natural
Expand Down Expand Up @@ -2234,7 +2237,8 @@ class Sema final {
bool CheckRISCVLMUL(CallExpr *TheCall, unsigned ArgNum);
bool CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);
void checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D);
void checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D,
const llvm::StringMap<bool> &FeatureMap);
bool CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI,
unsigned BuiltinID, CallExpr *TheCall);
bool CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI,
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
Original file line number Diff line number Diff line change
Expand Up @@ -908,7 +908,7 @@ def PaddingChecker : Checker<"Padding">,
"24",
Released>
]>,
Documentation<NotDocumented>;
Documentation<HasDocumentation>;

} // end: "padding"

Expand Down
5 changes: 5 additions & 0 deletions clang/lib/APINotes/APINotesManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ APINotesManager::getCurrentModuleAPINotes(Module *M, bool LookInModule,
ArrayRef<std::string> SearchPaths) {
FileManager &FM = SM.getFileManager();
auto ModuleName = M->getTopLevelModuleName();
auto ExportedModuleName = M->getTopLevelModule()->ExportAsModule;
llvm::SmallVector<FileEntryRef, 2> APINotes;

// First, look relative to the module itself.
Expand All @@ -233,6 +234,10 @@ APINotesManager::getCurrentModuleAPINotes(Module *M, bool LookInModule,

APINotes.push_back(*File);
}
// If module FooCore is re-exported through module Foo, try Foo.apinotes.
if (!ExportedModuleName.empty())
if (auto File = findAPINotesFile(Dir, ExportedModuleName, WantPublic))
APINotes.push_back(*File);
};

if (M->IsFramework) {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/APINotes/APINotesWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ void emitVersionedInfo(
std::sort(VI.begin(), VI.end(),
[](const std::pair<VersionTuple, T> &LHS,
const std::pair<VersionTuple, T> &RHS) -> bool {
assert(LHS.first != RHS.first &&
assert((&LHS == &RHS || LHS.first != RHS.first) &&
"two entries for the same version");
return LHS.first < RHS.first;
});
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9600,11 +9600,11 @@ static uint64_t getRVVTypeSize(ASTContext &Context, const BuiltinType *Ty) {

ASTContext::BuiltinVectorTypeInfo Info = Context.getBuiltinVectorTypeInfo(Ty);

unsigned EltSize = Context.getTypeSize(Info.ElementType);
uint64_t EltSize = Context.getTypeSize(Info.ElementType);
if (Info.ElementType == Context.BoolTy)
EltSize = 1;

unsigned MinElts = Info.EC.getKnownMinValue();
uint64_t MinElts = Info.EC.getKnownMinValue();
return VScale->first * MinElts * EltSize;
}

Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3445,6 +3445,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
case CC_PreserveAll:
case CC_M68kRTD:
case CC_PreserveNone:
case CC_RISCVVectorCall:
// FIXME: we should be mangling all of the above.
return "";

Expand Down
13 changes: 13 additions & 0 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1990,6 +1990,19 @@ void TextNodeDumper::VisitFunctionDecl(const FunctionDecl *D) {
}
}

void TextNodeDumper::VisitCXXDeductionGuideDecl(
const CXXDeductionGuideDecl *D) {
VisitFunctionDecl(D);
switch (D->getDeductionCandidateKind()) {
case DeductionCandidate::Normal:
case DeductionCandidate::Copy:
return;
case DeductionCandidate::Aggregate:
OS << " aggregate ";
break;
}
}

void TextNodeDumper::VisitLifetimeExtendedTemporaryDecl(
const LifetimeExtendedTemporaryDecl *D) {
OS << " extended by ";
Expand Down
33 changes: 23 additions & 10 deletions clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3484,6 +3484,9 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
case CC_PreserveAll: return "preserve_all";
case CC_M68kRTD: return "m68k_rtd";
case CC_PreserveNone: return "preserve_none";
// clang-format off
case CC_RISCVVectorCall: return "riscv_vector_cc";
// clang-format on
}

llvm_unreachable("Invalid calling convention.");
Expand Down Expand Up @@ -4074,6 +4077,7 @@ bool AttributedType::isCallingConv() const {
case attr::PreserveAll:
case attr::M68kRTD:
case attr::PreserveNone:
case attr::RISCVVectorCC:
return true;
}
llvm_unreachable("invalid attr kind");
Expand Down Expand Up @@ -4638,16 +4642,15 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
case Type::Auto:
return ResultIfUnknown;

// Dependent template specializations can instantiate to pointer
// types unless they're known to be specializations of a class
// template.
// Dependent template specializations could instantiate to pointer types.
case Type::TemplateSpecialization:
if (TemplateDecl *templateDecl
= cast<TemplateSpecializationType>(type.getTypePtr())
->getTemplateName().getAsTemplateDecl()) {
if (isa<ClassTemplateDecl>(templateDecl))
return false;
}
// If it's a known class template, we can already check if it's nullable.
if (TemplateDecl *templateDecl =
cast<TemplateSpecializationType>(type.getTypePtr())
->getTemplateName()
.getAsTemplateDecl())
if (auto *CTD = dyn_cast<ClassTemplateDecl>(templateDecl))
return CTD->getTemplatedDecl()->hasAttr<TypeNullableAttr>();
return ResultIfUnknown;

case Type::Builtin:
Expand Down Expand Up @@ -4704,6 +4707,17 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
}
llvm_unreachable("unknown builtin type");

case Type::Record: {
const RecordDecl *RD = cast<RecordType>(type)->getDecl();
// For template specializations, look only at primary template attributes.
// This is a consistent regardless of whether the instantiation is known.
if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
return CTSD->getSpecializedTemplate()
->getTemplatedDecl()
->hasAttr<TypeNullableAttr>();
return RD->hasAttr<TypeNullableAttr>();
}

// Non-pointer types.
case Type::Complex:
case Type::LValueReference:
Expand All @@ -4721,7 +4735,6 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
case Type::DependentAddressSpace:
case Type::FunctionProto:
case Type::FunctionNoProto:
case Type::Record:
case Type::DeducedTemplateSpecialization:
case Type::Enum:
case Type::InjectedClassName:
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/AST/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1071,6 +1071,9 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,
case CC_PreserveNone:
OS << " __attribute__((preserve_none))";
break;
case CC_RISCVVectorCall:
OS << "__attribute__((riscv_vector_cc))";
break;
}
}

Expand Down Expand Up @@ -1960,6 +1963,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
case attr::PreserveNone:
OS << "preserve_none";
break;
case attr::RISCVVectorCC:
OS << "riscv_vector_cc";
break;
case attr::NoDeref:
OS << "noderef";
break;
Expand Down
36 changes: 36 additions & 0 deletions clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1169,6 +1169,42 @@ getFieldsForInitListExpr(const InitListExpr *InitList) {
return Fields;
}

RecordInitListHelper::RecordInitListHelper(const InitListExpr *InitList) {
auto *RD = InitList->getType()->getAsCXXRecordDecl();
assert(RD != nullptr);

std::vector<const FieldDecl *> Fields = getFieldsForInitListExpr(InitList);
ArrayRef<Expr *> Inits = InitList->inits();

// Unions initialized with an empty initializer list need special treatment.
// For structs/classes initialized with an empty initializer list, Clang
// puts `ImplicitValueInitExpr`s in `InitListExpr::inits()`, but for unions,
// it doesn't do this -- so we create an `ImplicitValueInitExpr` ourselves.
SmallVector<Expr *> InitsForUnion;
if (InitList->getType()->isUnionType() && Inits.empty()) {
assert(Fields.size() == 1);
ImplicitValueInitForUnion.emplace(Fields.front()->getType());
InitsForUnion.push_back(&*ImplicitValueInitForUnion);
Inits = InitsForUnion;
}

size_t InitIdx = 0;

assert(Fields.size() + RD->getNumBases() == Inits.size());
for (const CXXBaseSpecifier &Base : RD->bases()) {
assert(InitIdx < Inits.size());
Expr *Init = Inits[InitIdx++];
BaseInits.emplace_back(&Base, Init);
}

assert(Fields.size() == Inits.size() - InitIdx);
for (const FieldDecl *Field : Fields) {
assert(InitIdx < Inits.size());
Expr *Init = Inits[InitIdx++];
FieldInits.emplace_back(Field, Init);
}
}

RecordValue &refreshRecordValue(RecordStorageLocation &Loc, Environment &Env) {
auto &NewVal = Env.create<RecordValue>(Loc);
Env.setValue(Loc, NewVal);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -512,27 +512,26 @@ void constructOptionalValue(const Expr &E, Environment &Env,
/// Returns a symbolic value for the "has_value" property of an `optional<T>`
/// value that is constructed/assigned from a value of type `U` or `optional<U>`
/// where `T` is constructible from `U`.
BoolValue &valueOrConversionHasValue(const FunctionDecl &F, const Expr &E,
BoolValue &valueOrConversionHasValue(QualType DestType, const Expr &E,
const MatchFinder::MatchResult &MatchRes,
LatticeTransferState &State) {
assert(F.getTemplateSpecializationArgs() != nullptr);
assert(F.getTemplateSpecializationArgs()->size() > 0);

const int TemplateParamOptionalWrappersCount =
countOptionalWrappers(*MatchRes.Context, F.getTemplateSpecializationArgs()
->get(0)
.getAsType()
.getNonReferenceType());
const int DestTypeOptionalWrappersCount =
countOptionalWrappers(*MatchRes.Context, DestType);
const int ArgTypeOptionalWrappersCount = countOptionalWrappers(
*MatchRes.Context, E.getType().getNonReferenceType());

// Check if this is a constructor/assignment call for `optional<T>` with
// argument of type `U` such that `T` is constructible from `U`.
if (TemplateParamOptionalWrappersCount == ArgTypeOptionalWrappersCount)
// Is this an constructor of the form `template<class U> optional(U &&)` /
// assignment of the form `template<class U> optional& operator=(U &&)`
// (where `T` is assignable / constructible from `U`)?
// We recognize this because the number of optionals in the optional being
// assigned to is different from the function argument type.
if (DestTypeOptionalWrappersCount != ArgTypeOptionalWrappersCount)
return State.Env.getBoolLiteralValue(true);

// This is a constructor/assignment call for `optional<T>` with argument of
// type `optional<U>` such that `T` is constructible from `U`.
// Otherwise, this must be a constructor of the form
// `template <class U> optional<optional<U> &&)` / assignment of the form
// `template <class U> optional& operator=(optional<U> &&)
// (where, again, `T` is assignable / constructible from `U`).
auto *Loc = State.Env.get<RecordStorageLocation>(E);
if (auto *HasValueVal = getHasValue(State.Env, Loc))
return *HasValueVal;
Expand All @@ -544,10 +543,11 @@ void transferValueOrConversionConstructor(
LatticeTransferState &State) {
assert(E->getNumArgs() > 0);

constructOptionalValue(*E, State.Env,
valueOrConversionHasValue(*E->getConstructor(),
*E->getArg(0), MatchRes,
State));
constructOptionalValue(
*E, State.Env,
valueOrConversionHasValue(
E->getConstructor()->getThisType()->getPointeeType(), *E->getArg(0),
MatchRes, State));
}

void transferAssignment(const CXXOperatorCallExpr *E, BoolValue &HasValueVal,
Expand All @@ -566,10 +566,11 @@ void transferValueOrConversionAssignment(
const CXXOperatorCallExpr *E, const MatchFinder::MatchResult &MatchRes,
LatticeTransferState &State) {
assert(E->getNumArgs() > 1);
transferAssignment(E,
valueOrConversionHasValue(*E->getDirectCallee(),
*E->getArg(1), MatchRes, State),
State);
transferAssignment(
E,
valueOrConversionHasValue(E->getArg(0)->getType().getNonReferenceType(),
*E->getArg(1), MatchRes, State),
State);
}

void transferNulloptAssignment(const CXXOperatorCallExpr *E,
Expand Down
61 changes: 16 additions & 45 deletions clang/lib/Analysis/FlowSensitive/Transfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -689,51 +689,22 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
}

llvm::DenseMap<const ValueDecl *, StorageLocation *> FieldLocs;

// This only contains the direct fields for the given type.
std::vector<const FieldDecl *> FieldsForInit = getFieldsForInitListExpr(S);

// `S->inits()` contains all the initializer expressions, including the
// ones for direct base classes.
ArrayRef<Expr *> Inits = S->inits();
size_t InitIdx = 0;

// Unions initialized with an empty initializer list need special treatment.
// For structs/classes initialized with an empty initializer list, Clang
// puts `ImplicitValueInitExpr`s in `InitListExpr::inits()`, but for unions,
// it doesn't do this -- so we create an `ImplicitValueInitExpr` ourselves.
std::optional<ImplicitValueInitExpr> ImplicitValueInitForUnion;
SmallVector<Expr *> InitsForUnion;
if (S->getType()->isUnionType() && Inits.empty()) {
assert(FieldsForInit.size() == 1);
ImplicitValueInitForUnion.emplace(FieldsForInit.front()->getType());
InitsForUnion.push_back(&*ImplicitValueInitForUnion);
Inits = InitsForUnion;
}

// Initialize base classes.
if (auto* R = S->getType()->getAsCXXRecordDecl()) {
assert(FieldsForInit.size() + R->getNumBases() == Inits.size());
for ([[maybe_unused]] const CXXBaseSpecifier &Base : R->bases()) {
assert(InitIdx < Inits.size());
auto Init = Inits[InitIdx++];
assert(Base.getType().getCanonicalType() ==
Init->getType().getCanonicalType());
auto *BaseVal = Env.get<RecordValue>(*Init);
if (!BaseVal)
BaseVal = cast<RecordValue>(Env.createValue(Init->getType()));
// Take ownership of the fields of the `RecordValue` for the base class
// and incorporate them into the "flattened" set of fields for the
// derived class.
auto Children = BaseVal->getLoc().children();
FieldLocs.insert(Children.begin(), Children.end());
}
}

assert(FieldsForInit.size() == Inits.size() - InitIdx);
for (auto Field : FieldsForInit) {
assert(InitIdx < Inits.size());
auto Init = Inits[InitIdx++];
RecordInitListHelper InitListHelper(S);

for (auto [Base, Init] : InitListHelper.base_inits()) {
assert(Base->getType().getCanonicalType() ==
Init->getType().getCanonicalType());
auto *BaseVal = Env.get<RecordValue>(*Init);
if (!BaseVal)
BaseVal = cast<RecordValue>(Env.createValue(Init->getType()));
// Take ownership of the fields of the `RecordValue` for the base class
// and incorporate them into the "flattened" set of fields for the
// derived class.
auto Children = BaseVal->getLoc().children();
FieldLocs.insert(Children.begin(), Children.end());
}

for (auto [Field, Init] : InitListHelper.field_inits()) {
assert(
// The types are same, or
Field->getType().getCanonicalType().getUnqualifiedType() ==
Expand Down
11 changes: 11 additions & 0 deletions clang/lib/Basic/Targets/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,3 +467,14 @@ ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const {
}
return Ret;
}

TargetInfo::CallingConvCheckResult
RISCVTargetInfo::checkCallingConvention(CallingConv CC) const {
switch (CC) {
default:
return CCCR_Warning;
case CC_C:
case CC_RISCVVectorCall:
return CCCR_OK;
}
}
2 changes: 2 additions & 0 deletions clang/lib/Basic/Targets/RISCV.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ class RISCVTargetInfo : public TargetInfo {

bool hasBFloat16Type() const override { return true; }

CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;

bool useFP16ConversionIntrinsics() const override {
return false;
}
Expand Down
10 changes: 5 additions & 5 deletions clang/lib/CodeGen/ABIInfoImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ CodeGen::emitVoidPtrDirectVAArg(CodeGenFunction &CGF, Address VAListAddr,
CharUnits FullDirectSize = DirectSize.alignTo(SlotSize);
Address NextPtr =
CGF.Builder.CreateConstInBoundsByteGEP(Addr, FullDirectSize, "argp.next");
CGF.Builder.CreateStore(NextPtr.getPointer(), VAListAddr);
CGF.Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr);

// If the argument is smaller than a slot, and this is a big-endian
// target, the argument will be right-adjusted in its slot.
Expand Down Expand Up @@ -239,8 +239,8 @@ Address CodeGen::emitMergePHI(CodeGenFunction &CGF, Address Addr1,
const llvm::Twine &Name) {
assert(Addr1.getType() == Addr2.getType());
llvm::PHINode *PHI = CGF.Builder.CreatePHI(Addr1.getType(), 2, Name);
PHI->addIncoming(Addr1.getPointer(), Block1);
PHI->addIncoming(Addr2.getPointer(), Block2);
PHI->addIncoming(Addr1.emitRawPointer(CGF), Block1);
PHI->addIncoming(Addr2.emitRawPointer(CGF), Block2);
CharUnits Align = std::min(Addr1.getAlignment(), Addr2.getAlignment());
return Address(PHI, Addr1.getElementType(), Align);
}
Expand Down Expand Up @@ -400,7 +400,7 @@ Address CodeGen::EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr,
llvm::Type *ElementTy = CGF.ConvertTypeForMem(Ty);
llvm::Type *BaseTy = llvm::PointerType::getUnqual(ElementTy);
llvm::Value *Addr =
CGF.Builder.CreateVAArg(VAListAddr.getPointer(), BaseTy);
CGF.Builder.CreateVAArg(VAListAddr.emitRawPointer(CGF), BaseTy);
return Address(Addr, ElementTy, TyAlignForABI);
} else {
assert((AI.isDirect() || AI.isExtend()) &&
Expand All @@ -416,7 +416,7 @@ Address CodeGen::EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr,
"Unexpected CoerceToType seen in arginfo in generic VAArg emitter!");

Address Temp = CGF.CreateMemTemp(Ty, "varet");
Val = CGF.Builder.CreateVAArg(VAListAddr.getPointer(),
Val = CGF.Builder.CreateVAArg(VAListAddr.emitRawPointer(CGF),
CGF.ConvertTypeForMem(Ty));
CGF.Builder.CreateStore(Val, Temp);
return Temp;
Expand Down
195 changes: 167 additions & 28 deletions clang/lib/CodeGen/Address.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,49 @@
#define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H

#include "clang/AST/CharUnits.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/IR/Constants.h"
#include "llvm/Support/MathExtras.h"

namespace clang {
namespace CodeGen {

class Address;
class CGBuilderTy;
class CodeGenFunction;
class CodeGenModule;

// Indicates whether a pointer is known not to be null.
enum KnownNonNull_t { NotKnownNonNull, KnownNonNull };

/// An aligned address.
class Address {
/// An abstract representation of an aligned address. This is designed to be an
/// IR-level abstraction, carrying just the information necessary to perform IR
/// operations on an address like loads and stores. In particular, it doesn't
/// carry C type information or allow the representation of things like
/// bit-fields; clients working at that level should generally be using
/// `LValue`.
/// The pointer contained in this class is known to be unsigned.
class RawAddress {
llvm::PointerIntPair<llvm::Value *, 1, bool> PointerAndKnownNonNull;
llvm::Type *ElementType;
CharUnits Alignment;

protected:
Address(std::nullptr_t) : ElementType(nullptr) {}
RawAddress(std::nullptr_t) : ElementType(nullptr) {}

public:
Address(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment,
KnownNonNull_t IsKnownNonNull = NotKnownNonNull)
RawAddress(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment,
KnownNonNull_t IsKnownNonNull = NotKnownNonNull)
: PointerAndKnownNonNull(Pointer, IsKnownNonNull),
ElementType(ElementType), Alignment(Alignment) {
assert(Pointer != nullptr && "Pointer cannot be null");
assert(ElementType != nullptr && "Element type cannot be null");
}

static Address invalid() { return Address(nullptr); }
inline RawAddress(Address Addr);

static RawAddress invalid() { return RawAddress(nullptr); }
bool isValid() const {
return PointerAndKnownNonNull.getPointer() != nullptr;
}
Expand Down Expand Up @@ -80,6 +94,133 @@ class Address {
return Alignment;
}

/// Return address with different element type, but same pointer and
/// alignment.
RawAddress withElementType(llvm::Type *ElemTy) const {
return RawAddress(getPointer(), ElemTy, getAlignment(), isKnownNonNull());
}

KnownNonNull_t isKnownNonNull() const {
assert(isValid());
return (KnownNonNull_t)PointerAndKnownNonNull.getInt();
}
};

/// Like RawAddress, an abstract representation of an aligned address, but the
/// pointer contained in this class is possibly signed.
class Address {
friend class CGBuilderTy;

// The boolean flag indicates whether the pointer is known to be non-null.
llvm::PointerIntPair<llvm::Value *, 1, bool> Pointer;

/// The expected IR type of the pointer. Carrying accurate element type
/// information in Address makes it more convenient to work with Address
/// values and allows frontend assertions to catch simple mistakes.
llvm::Type *ElementType = nullptr;

CharUnits Alignment;

/// Offset from the base pointer.
llvm::Value *Offset = nullptr;

llvm::Value *emitRawPointerSlow(CodeGenFunction &CGF) const;

protected:
Address(std::nullptr_t) : ElementType(nullptr) {}

public:
Address(llvm::Value *pointer, llvm::Type *elementType, CharUnits alignment,
KnownNonNull_t IsKnownNonNull = NotKnownNonNull)
: Pointer(pointer, IsKnownNonNull), ElementType(elementType),
Alignment(alignment) {
assert(pointer != nullptr && "Pointer cannot be null");
assert(elementType != nullptr && "Element type cannot be null");
assert(!alignment.isZero() && "Alignment cannot be zero");
}

Address(llvm::Value *BasePtr, llvm::Type *ElementType, CharUnits Alignment,
llvm::Value *Offset, KnownNonNull_t IsKnownNonNull = NotKnownNonNull)
: Pointer(BasePtr, IsKnownNonNull), ElementType(ElementType),
Alignment(Alignment), Offset(Offset) {}

Address(RawAddress RawAddr)
: Pointer(RawAddr.isValid() ? RawAddr.getPointer() : nullptr),
ElementType(RawAddr.isValid() ? RawAddr.getElementType() : nullptr),
Alignment(RawAddr.isValid() ? RawAddr.getAlignment()
: CharUnits::Zero()) {}

static Address invalid() { return Address(nullptr); }
bool isValid() const { return Pointer.getPointer() != nullptr; }

/// This function is used in situations where the caller is doing some sort of
/// opaque "laundering" of the pointer.
void replaceBasePointer(llvm::Value *P) {
assert(isValid() && "pointer isn't valid");
assert(P->getType() == Pointer.getPointer()->getType() &&
"Pointer's type changed");
Pointer.setPointer(P);
assert(isValid() && "pointer is invalid after replacement");
}

CharUnits getAlignment() const { return Alignment; }

void setAlignment(CharUnits Value) { Alignment = Value; }

llvm::Value *getBasePointer() const {
assert(isValid() && "pointer isn't valid");
return Pointer.getPointer();
}

/// Return the type of the pointer value.
llvm::PointerType *getType() const {
return llvm::PointerType::get(
ElementType,
llvm::cast<llvm::PointerType>(Pointer.getPointer()->getType())
->getAddressSpace());
}

/// Return the type of the values stored in this address.
llvm::Type *getElementType() const {
assert(isValid());
return ElementType;
}

/// Return the address space that this address resides in.
unsigned getAddressSpace() const { return getType()->getAddressSpace(); }

/// Return the IR name of the pointer value.
llvm::StringRef getName() const { return Pointer.getPointer()->getName(); }

// This function is called only in CGBuilderBaseTy::CreateElementBitCast.
void setElementType(llvm::Type *Ty) {
assert(hasOffset() &&
"this funcion shouldn't be called when there is no offset");
ElementType = Ty;
}

/// Whether the pointer is known not to be null.
KnownNonNull_t isKnownNonNull() const {
assert(isValid());
return (KnownNonNull_t)Pointer.getInt();
}

Address setKnownNonNull() {
assert(isValid());
Pointer.setInt(KnownNonNull);
return *this;
}

bool hasOffset() const { return Offset; }

llvm::Value *getOffset() const { return Offset; }

/// Return the pointer contained in this class after authenticating it and
/// adding offset to it if necessary.
llvm::Value *emitRawPointer(CodeGenFunction &CGF) const {
return getBasePointer();
}

/// Return address with different pointer, but same element type and
/// alignment.
Address withPointer(llvm::Value *NewPointer,
Expand All @@ -91,61 +232,59 @@ class Address {
/// Return address with different alignment, but same pointer and element
/// type.
Address withAlignment(CharUnits NewAlignment) const {
return Address(getPointer(), getElementType(), NewAlignment,
return Address(Pointer.getPointer(), getElementType(), NewAlignment,
isKnownNonNull());
}

/// Return address with different element type, but same pointer and
/// alignment.
Address withElementType(llvm::Type *ElemTy) const {
return Address(getPointer(), ElemTy, getAlignment(), isKnownNonNull());
}

/// Whether the pointer is known not to be null.
KnownNonNull_t isKnownNonNull() const {
assert(isValid());
return (KnownNonNull_t)PointerAndKnownNonNull.getInt();
}

/// Set the non-null bit.
Address setKnownNonNull() {
assert(isValid());
PointerAndKnownNonNull.setInt(true);
return *this;
if (!hasOffset())
return Address(getBasePointer(), ElemTy, getAlignment(), nullptr,
isKnownNonNull());
Address A(*this);
A.ElementType = ElemTy;
return A;
}
};

inline RawAddress::RawAddress(Address Addr)
: PointerAndKnownNonNull(Addr.isValid() ? Addr.getBasePointer() : nullptr,
Addr.isValid() ? Addr.isKnownNonNull()
: NotKnownNonNull),
ElementType(Addr.isValid() ? Addr.getElementType() : nullptr),
Alignment(Addr.isValid() ? Addr.getAlignment() : CharUnits::Zero()) {}

/// A specialization of Address that requires the address to be an
/// LLVM Constant.
class ConstantAddress : public Address {
ConstantAddress(std::nullptr_t) : Address(nullptr) {}
class ConstantAddress : public RawAddress {
ConstantAddress(std::nullptr_t) : RawAddress(nullptr) {}

public:
ConstantAddress(llvm::Constant *pointer, llvm::Type *elementType,
CharUnits alignment)
: Address(pointer, elementType, alignment) {}
: RawAddress(pointer, elementType, alignment) {}

static ConstantAddress invalid() {
return ConstantAddress(nullptr);
}

llvm::Constant *getPointer() const {
return llvm::cast<llvm::Constant>(Address::getPointer());
return llvm::cast<llvm::Constant>(RawAddress::getPointer());
}

ConstantAddress withElementType(llvm::Type *ElemTy) const {
return ConstantAddress(getPointer(), ElemTy, getAlignment());
}

static bool isaImpl(Address addr) {
static bool isaImpl(RawAddress addr) {
return llvm::isa<llvm::Constant>(addr.getPointer());
}
static ConstantAddress castImpl(Address addr) {
static ConstantAddress castImpl(RawAddress addr) {
return ConstantAddress(llvm::cast<llvm::Constant>(addr.getPointer()),
addr.getElementType(), addr.getAlignment());
}
};

}

// Present a minimal LLVM-like casting interface.
Expand Down
53 changes: 28 additions & 25 deletions clang/lib/CodeGen/CGAtomic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ namespace {
AtomicSizeInBits = C.toBits(
C.toCharUnitsFromBits(Offset + OrigBFI.Size + C.getCharWidth() - 1)
.alignTo(lvalue.getAlignment()));
llvm::Value *BitFieldPtr = lvalue.getBitFieldPointer();
llvm::Value *BitFieldPtr = lvalue.getRawBitFieldPointer(CGF);
auto OffsetInChars =
(C.toCharUnitsFromBits(OrigBFI.Offset) / lvalue.getAlignment()) *
lvalue.getAlignment();
Expand Down Expand Up @@ -139,13 +139,13 @@ namespace {
const LValue &getAtomicLValue() const { return LVal; }
llvm::Value *getAtomicPointer() const {
if (LVal.isSimple())
return LVal.getPointer(CGF);
return LVal.emitRawPointer(CGF);
else if (LVal.isBitField())
return LVal.getBitFieldPointer();
return LVal.getRawBitFieldPointer(CGF);
else if (LVal.isVectorElt())
return LVal.getVectorPointer();
return LVal.getRawVectorPointer(CGF);
assert(LVal.isExtVectorElt());
return LVal.getExtVectorPointer();
return LVal.getRawExtVectorPointer(CGF);
}
Address getAtomicAddress() const {
llvm::Type *ElTy;
Expand Down Expand Up @@ -368,7 +368,7 @@ bool AtomicInfo::emitMemSetZeroIfNecessary() const {
return false;

CGF.Builder.CreateMemSet(
addr.getPointer(), llvm::ConstantInt::get(CGF.Int8Ty, 0),
addr.emitRawPointer(CGF), llvm::ConstantInt::get(CGF.Int8Ty, 0),
CGF.getContext().toCharUnitsFromBits(AtomicSizeInBits).getQuantity(),
LVal.getAlignment().getAsAlign());
return true;
Expand Down Expand Up @@ -1055,7 +1055,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
return getTargetHooks().performAddrSpaceCast(
*this, V, AS, LangAS::opencl_generic, DestType, false);
};
Args.add(RValue::get(CastToGenericAddrSpace(Ptr.getPointer(),

Args.add(RValue::get(CastToGenericAddrSpace(Ptr.emitRawPointer(*this),
E->getPtr()->getType())),
getContext().VoidPtrTy);

Expand Down Expand Up @@ -1086,10 +1087,10 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
LibCallName = "__atomic_compare_exchange";
RetTy = getContext().BoolTy;
HaveRetTy = true;
Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(),
Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this),
E->getVal1()->getType())),
getContext().VoidPtrTy);
Args.add(RValue::get(CastToGenericAddrSpace(Val2.getPointer(),
Args.add(RValue::get(CastToGenericAddrSpace(Val2.emitRawPointer(*this),
E->getVal2()->getType())),
getContext().VoidPtrTy);
Args.add(RValue::get(Order), getContext().IntTy);
Expand All @@ -1105,7 +1106,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__scoped_atomic_exchange:
case AtomicExpr::AO__scoped_atomic_exchange_n:
LibCallName = "__atomic_exchange";
Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(),
Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this),
E->getVal1()->getType())),
getContext().VoidPtrTy);
break;
Expand All @@ -1120,7 +1121,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
LibCallName = "__atomic_store";
RetTy = getContext().VoidTy;
HaveRetTy = true;
Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(),
Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this),
E->getVal1()->getType())),
getContext().VoidPtrTy);
break;
Expand Down Expand Up @@ -1199,7 +1200,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
if (!HaveRetTy) {
// Value is returned through parameter before the order.
RetTy = getContext().VoidTy;
Args.add(RValue::get(CastToGenericAddrSpace(Dest.getPointer(), RetTy)),
Args.add(RValue::get(
CastToGenericAddrSpace(Dest.emitRawPointer(*this), RetTy)),
getContext().VoidPtrTy);
}
// Order is always the last parameter.
Expand Down Expand Up @@ -1513,7 +1515,7 @@ RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc,
} else
TempAddr = CreateTempAlloca();

EmitAtomicLoadLibcall(TempAddr.getPointer(), AO, IsVolatile);
EmitAtomicLoadLibcall(TempAddr.emitRawPointer(CGF), AO, IsVolatile);

// Okay, turn that back into the original value or whole atomic (for
// non-simple lvalues) type.
Expand Down Expand Up @@ -1673,9 +1675,9 @@ std::pair<RValue, llvm::Value *> AtomicInfo::EmitAtomicCompareExchange(
if (shouldUseLibcall()) {
// Produce a source address.
Address ExpectedAddr = materializeRValue(Expected);
Address DesiredAddr = materializeRValue(Desired);
auto *Res = EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(),
DesiredAddr.getPointer(),
llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF);
llvm::Value *DesiredPtr = materializeRValue(Desired).emitRawPointer(CGF);
auto *Res = EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr,
Success, Failure);
return std::make_pair(
convertAtomicTempToRValue(ExpectedAddr, AggValueSlot::ignored(),
Expand Down Expand Up @@ -1757,7 +1759,7 @@ void AtomicInfo::EmitAtomicUpdateLibcall(

Address ExpectedAddr = CreateTempAlloca();

EmitAtomicLoadLibcall(ExpectedAddr.getPointer(), AO, IsVolatile);
EmitAtomicLoadLibcall(ExpectedAddr.emitRawPointer(CGF), AO, IsVolatile);
auto *ContBB = CGF.createBasicBlock("atomic_cont");
auto *ExitBB = CGF.createBasicBlock("atomic_exit");
CGF.EmitBlock(ContBB);
Expand All @@ -1771,10 +1773,10 @@ void AtomicInfo::EmitAtomicUpdateLibcall(
AggValueSlot::ignored(),
SourceLocation(), /*AsValue=*/false);
EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, DesiredAddr);
llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF);
llvm::Value *DesiredPtr = DesiredAddr.emitRawPointer(CGF);
auto *Res =
EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(),
DesiredAddr.getPointer(),
AO, Failure);
EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, AO, Failure);
CGF.Builder.CreateCondBr(Res, ExitBB, ContBB);
CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
}
Expand Down Expand Up @@ -1843,7 +1845,7 @@ void AtomicInfo::EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO,

Address ExpectedAddr = CreateTempAlloca();

EmitAtomicLoadLibcall(ExpectedAddr.getPointer(), AO, IsVolatile);
EmitAtomicLoadLibcall(ExpectedAddr.emitRawPointer(CGF), AO, IsVolatile);
auto *ContBB = CGF.createBasicBlock("atomic_cont");
auto *ExitBB = CGF.createBasicBlock("atomic_exit");
CGF.EmitBlock(ContBB);
Expand All @@ -1854,10 +1856,10 @@ void AtomicInfo::EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO,
CGF.Builder.CreateStore(OldVal, DesiredAddr);
}
EmitAtomicUpdateValue(CGF, *this, UpdateRVal, DesiredAddr);
llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF);
llvm::Value *DesiredPtr = DesiredAddr.emitRawPointer(CGF);
auto *Res =
EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(),
DesiredAddr.getPointer(),
AO, Failure);
EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, AO, Failure);
CGF.Builder.CreateCondBr(Res, ExitBB, ContBB);
CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
}
Expand Down Expand Up @@ -1957,7 +1959,8 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest,
args.add(RValue::get(atomics.getAtomicSizeValue()),
getContext().getSizeType());
args.add(RValue::get(atomics.getAtomicPointer()), getContext().VoidPtrTy);
args.add(RValue::get(srcAddr.getPointer()), getContext().VoidPtrTy);
args.add(RValue::get(srcAddr.emitRawPointer(*this)),
getContext().VoidPtrTy);
args.add(
RValue::get(llvm::ConstantInt::get(IntTy, (int)llvm::toCABI(AO))),
getContext().IntTy);
Expand Down
34 changes: 19 additions & 15 deletions clang/lib/CodeGen/CGBlocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name)
: Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false),
NoEscape(false), HasCXXObject(false), UsesStret(false),
HasCapturedVariableLayout(false), CapturesNonExternalType(false),
LocalAddress(Address::invalid()), StructureType(nullptr), Block(block) {
LocalAddress(RawAddress::invalid()), StructureType(nullptr),
Block(block) {

// Skip asm prefix, if any. 'name' is usually taken directly from
// the mangled name of the enclosing function.
Expand Down Expand Up @@ -794,7 +795,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {

// Otherwise, we have to emit this as a local block.

Address blockAddr = blockInfo.LocalAddress;
RawAddress blockAddr = blockInfo.LocalAddress;
assert(blockAddr.isValid() && "block has no address!");

llvm::Constant *isa;
Expand Down Expand Up @@ -939,7 +940,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
if (CI.isNested())
byrefPointer = Builder.CreateLoad(src, "byref.capture");
else
byrefPointer = src.getPointer();
byrefPointer = src.emitRawPointer(*this);

// Write that void* into the capture field.
Builder.CreateStore(byrefPointer, blockField);
Expand All @@ -961,10 +962,10 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
}

// If it's a reference variable, copy the reference into the block field.
} else if (type->isReferenceType()) {
Builder.CreateStore(src.getPointer(), blockField);
} else if (auto refType = type->getAs<ReferenceType>()) {
Builder.CreateStore(src.emitRawPointer(*this), blockField);

// If type is const-qualified, copy the value into the block field.
// If type is const-qualified, copy the value into the block field.
} else if (type.isConstQualified() &&
type.getObjCLifetime() == Qualifiers::OCL_Strong &&
CGM.getCodeGenOpts().OptimizationLevel != 0) {
Expand Down Expand Up @@ -1377,7 +1378,7 @@ void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D,

// Allocate a stack slot like for any local variable to guarantee optimal
// debug info at -O0. The mem2reg pass will eliminate it when optimizing.
Address alloc = CreateMemTemp(D->getType(), D->getName() + ".addr");
RawAddress alloc = CreateMemTemp(D->getType(), D->getName() + ".addr");
Builder.CreateStore(arg, alloc);
if (CGDebugInfo *DI = getDebugInfo()) {
if (CGM.getCodeGenOpts().hasReducedDebugInfo()) {
Expand Down Expand Up @@ -1497,7 +1498,7 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction(
// frame setup instruction by llvm::DwarfDebug::beginFunction().
auto NL = ApplyDebugLocation::CreateEmpty(*this);
Builder.CreateStore(BlockPointer, Alloca);
BlockPointerDbgLoc = Alloca.getPointer();
BlockPointerDbgLoc = Alloca.emitRawPointer(*this);
}

// If we have a C++ 'this' reference, go ahead and force it into
Expand Down Expand Up @@ -1557,8 +1558,8 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction(
const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
if (capture.isConstant()) {
auto addr = LocalDeclMap.find(variable)->second;
(void)DI->EmitDeclareOfAutoVariable(variable, addr.getPointer(),
Builder);
(void)DI->EmitDeclareOfAutoVariable(
variable, addr.emitRawPointer(*this), Builder);
continue;
}

Expand Down Expand Up @@ -1662,7 +1663,7 @@ struct CallBlockRelease final : EHScopeStack::Cleanup {
if (LoadBlockVarAddr) {
BlockVarAddr = CGF.Builder.CreateLoad(Addr);
} else {
BlockVarAddr = Addr.getPointer();
BlockVarAddr = Addr.emitRawPointer(CGF);
}

CGF.BuildBlockRelease(BlockVarAddr, FieldFlags, CanThrow);
Expand Down Expand Up @@ -1962,13 +1963,15 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
// it. It's not quite worth the annoyance to avoid creating it in the
// first place.
if (!needsEHCleanup(captureType.isDestructedType()))
cast<llvm::Instruction>(dstField.getPointer())->eraseFromParent();
if (auto *I =
cast_or_null<llvm::Instruction>(dstField.getBasePointer()))
I->eraseFromParent();
}
break;
}
case BlockCaptureEntityKind::BlockObject: {
llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src");
llvm::Value *dstAddr = dstField.getPointer();
llvm::Value *dstAddr = dstField.emitRawPointer(*this);
llvm::Value *args[] = {
dstAddr, srcValue, llvm::ConstantInt::get(Int32Ty, flags.getBitMask())
};
Expand Down Expand Up @@ -2139,7 +2142,7 @@ class ObjectByrefHelpers final : public BlockByrefHelpers {
llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.Int32Ty, flags);
llvm::FunctionCallee fn = CGF.CGM.getBlockObjectAssign();

llvm::Value *args[] = { destField.getPointer(), srcValue, flagsVal };
llvm::Value *args[] = {destField.emitRawPointer(CGF), srcValue, flagsVal};
CGF.EmitNounwindRuntimeCall(fn, args);
}

Expand Down Expand Up @@ -2696,7 +2699,8 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
storeHeaderField(V, getPointerSize(), "byref.isa");

// Store the address of the variable into its own forwarding pointer.
storeHeaderField(addr.getPointer(), getPointerSize(), "byref.forwarding");
storeHeaderField(addr.emitRawPointer(*this), getPointerSize(),
"byref.forwarding");

// Blocks ABI:
// c) the flags field is set to either 0 if no helper functions are
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CGBlocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,8 @@ class CGBlockInfo {
/// The block's captures. Non-constant captures are sorted by their offsets.
llvm::SmallVector<Capture, 4> SortedCaptures;

Address LocalAddress;
// Currently we assume that block-pointer types are never signed.
RawAddress LocalAddress;
llvm::StructType *StructureType;
const BlockDecl *Block;
const BlockExpr *BlockExpression;
Expand Down
234 changes: 160 additions & 74 deletions clang/lib/CodeGen/CGBuilder.h

Large diffs are not rendered by default.

272 changes: 187 additions & 85 deletions clang/lib/CodeGen/CGBuiltin.cpp

Large diffs are not rendered by default.

19 changes: 10 additions & 9 deletions clang/lib/CodeGen/CGCUDANV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -331,11 +331,11 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF,
llvm::ConstantInt::get(SizeTy, std::max<size_t>(1, Args.size())));
// Store pointers to the arguments in a locally allocated launch_args.
for (unsigned i = 0; i < Args.size(); ++i) {
llvm::Value* VarPtr = CGF.GetAddrOfLocalVar(Args[i]).getPointer();
llvm::Value *VarPtr = CGF.GetAddrOfLocalVar(Args[i]).emitRawPointer(CGF);
llvm::Value *VoidVarPtr = CGF.Builder.CreatePointerCast(VarPtr, PtrTy);
CGF.Builder.CreateDefaultAlignedStore(
VoidVarPtr,
CGF.Builder.CreateConstGEP1_32(PtrTy, KernelArgs.getPointer(), i));
VoidVarPtr, CGF.Builder.CreateConstGEP1_32(
PtrTy, KernelArgs.emitRawPointer(CGF), i));
}

llvm::BasicBlock *EndBlock = CGF.createBasicBlock("setup.end");
Expand Down Expand Up @@ -393,9 +393,10 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF,
/*isVarArg=*/false),
addUnderscoredPrefixToName("PopCallConfiguration"));

CGF.EmitRuntimeCallOrInvoke(cudaPopConfigFn,
{GridDim.getPointer(), BlockDim.getPointer(),
ShmemSize.getPointer(), Stream.getPointer()});
CGF.EmitRuntimeCallOrInvoke(cudaPopConfigFn, {GridDim.emitRawPointer(CGF),
BlockDim.emitRawPointer(CGF),
ShmemSize.emitRawPointer(CGF),
Stream.emitRawPointer(CGF)});

// Emit the call to cudaLaunch
llvm::Value *Kernel =
Expand All @@ -405,7 +406,7 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF,
cudaLaunchKernelFD->getParamDecl(0)->getType());
LaunchKernelArgs.add(RValue::getAggregate(GridDim), Dim3Ty);
LaunchKernelArgs.add(RValue::getAggregate(BlockDim), Dim3Ty);
LaunchKernelArgs.add(RValue::get(KernelArgs.getPointer()),
LaunchKernelArgs.add(RValue::get(KernelArgs, CGF),
cudaLaunchKernelFD->getParamDecl(3)->getType());
LaunchKernelArgs.add(RValue::get(CGF.Builder.CreateLoad(ShmemSize)),
cudaLaunchKernelFD->getParamDecl(4)->getType());
Expand Down Expand Up @@ -438,8 +439,8 @@ void CGNVCUDARuntime::emitDeviceStubBodyLegacy(CodeGenFunction &CGF,
auto TInfo = CGM.getContext().getTypeInfoInChars(A->getType());
Offset = Offset.alignTo(TInfo.Align);
llvm::Value *Args[] = {
CGF.Builder.CreatePointerCast(CGF.GetAddrOfLocalVar(A).getPointer(),
PtrTy),
CGF.Builder.CreatePointerCast(
CGF.GetAddrOfLocalVar(A).emitRawPointer(CGF), PtrTy),
llvm::ConstantInt::get(SizeTy, TInfo.Width.getQuantity()),
llvm::ConstantInt::get(SizeTy, Offset.getQuantity()),
};
Expand Down
21 changes: 15 additions & 6 deletions clang/lib/CodeGen/CGCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ using namespace CodeGen;

CGCXXABI::~CGCXXABI() { }

Address CGCXXABI::getThisAddress(CodeGenFunction &CGF) {
return CGF.makeNaturalAddressForPointer(
CGF.CXXABIThisValue, CGF.CXXABIThisDecl->getType()->getPointeeType(),
CGF.CXXABIThisAlignment);
}

void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) {
DiagnosticsEngine &Diags = CGF.CGM.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
Expand All @@ -44,8 +50,12 @@ CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer(
llvm::Value *MemPtr, const MemberPointerType *MPT) {
ErrorUnsupportedABI(CGF, "calls through member pointers");

ThisPtrForCall = This.getPointer();
const auto *FPT = MPT->getPointeeType()->castAs<FunctionProtoType>();
const auto *RD =
cast<CXXRecordDecl>(MPT->getClass()->castAs<RecordType>()->getDecl());
ThisPtrForCall =
CGF.getAsNaturalPointerTo(This, CGF.getContext().getRecordType(RD));
const FunctionProtoType *FPT =
MPT->getPointeeType()->getAs<FunctionProtoType>();
llvm::Constant *FnPtr = llvm::Constant::getNullValue(
llvm::PointerType::getUnqual(CGM.getLLVMContext()));
return CGCallee::forDirect(FnPtr, FPT);
Expand Down Expand Up @@ -251,16 +261,15 @@ void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr,

// If we don't need an array cookie, bail out early.
if (!requiresArrayCookie(expr, eltTy)) {
allocPtr = ptr.getPointer();
allocPtr = ptr.emitRawPointer(CGF);
numElements = nullptr;
cookieSize = CharUnits::Zero();
return;
}

cookieSize = getArrayCookieSizeImpl(eltTy);
Address allocAddr =
CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize);
allocPtr = allocAddr.getPointer();
Address allocAddr = CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize);
allocPtr = allocAddr.emitRawPointer(CGF);
numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize);
}

Expand Down
14 changes: 2 additions & 12 deletions clang/lib/CodeGen/CGCXXABI.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,8 @@ class CGCXXABI {
llvm::Value *getThisValue(CodeGenFunction &CGF) {
return CGF.CXXABIThisValue;
}
Address getThisAddress(CodeGenFunction &CGF) {
return Address(
CGF.CXXABIThisValue,
CGF.ConvertTypeForMem(CGF.CXXABIThisDecl->getType()->getPointeeType()),
CGF.CXXABIThisAlignment);
}

Address getThisAddress(CodeGenFunction &CGF);

/// Issue a diagnostic about unsupported features in the ABI.
void ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S);
Expand Down Expand Up @@ -475,12 +471,6 @@ class CGCXXABI {
BaseSubobject Base,
const CXXRecordDecl *NearestVBase) = 0;

/// Get the address point of the vtable for the given base subobject while
/// building a constexpr.
virtual llvm::Constant *
getVTableAddressPointForConstExpr(BaseSubobject Base,
const CXXRecordDecl *VTableClass) = 0;

/// Get the address of the vtable for the given record decl which should be
/// used for the vptr at the given offset in RD.
virtual llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,
Expand Down
183 changes: 108 additions & 75 deletions clang/lib/CodeGen/CGCall.cpp

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions clang/lib/CodeGen/CGCall.h
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ class ReturnValueSlot {
Address getValue() const { return Addr; }
bool isUnused() const { return IsUnused; }
bool isExternallyDestructed() const { return IsExternallyDestructed; }
Address getAddress() const { return Addr; }
};

/// Adds attributes to \p F according to our \p CodeGenOpts and \p LangOpts, as
Expand Down
76 changes: 45 additions & 31 deletions clang/lib/CodeGen/CGClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,9 @@ Address CodeGenFunction::LoadCXXThisAddress() {
CXXThisAlignment = CGM.getClassPointerAlignment(MD->getParent());
}

llvm::Type *Ty = ConvertType(MD->getFunctionObjectParameterType());
return Address(LoadCXXThis(), Ty, CXXThisAlignment, KnownNonNull);
return makeNaturalAddressForPointer(
LoadCXXThis(), MD->getFunctionObjectParameterType(), CXXThisAlignment,
false, nullptr, nullptr, KnownNonNull);
}

/// Emit the address of a field using a member data pointer.
Expand Down Expand Up @@ -270,7 +271,7 @@ ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, Address addr,
}

// Apply the base offset.
llvm::Value *ptr = addr.getPointer();
llvm::Value *ptr = addr.emitRawPointer(CGF);
ptr = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ptr, baseOffset, "add.ptr");

// If we have a virtual component, the alignment of the result will
Expand Down Expand Up @@ -338,8 +339,8 @@ Address CodeGenFunction::GetAddressOfBaseClass(
if (sanitizePerformTypeCheck()) {
SanitizerSet SkippedChecks;
SkippedChecks.set(SanitizerKind::Null, !NullCheckValue);
EmitTypeCheck(TCK_Upcast, Loc, Value.getPointer(),
DerivedTy, DerivedAlign, SkippedChecks);
EmitTypeCheck(TCK_Upcast, Loc, Value.emitRawPointer(*this), DerivedTy,
DerivedAlign, SkippedChecks);
}
return Value.withElementType(BaseValueTy);
}
Expand All @@ -354,7 +355,7 @@ Address CodeGenFunction::GetAddressOfBaseClass(
llvm::BasicBlock *notNullBB = createBasicBlock("cast.notnull");
endBB = createBasicBlock("cast.end");

llvm::Value *isNull = Builder.CreateIsNull(Value.getPointer());
llvm::Value *isNull = Builder.CreateIsNull(Value);
Builder.CreateCondBr(isNull, endBB, notNullBB);
EmitBlock(notNullBB);
}
Expand All @@ -363,14 +364,15 @@ Address CodeGenFunction::GetAddressOfBaseClass(
SanitizerSet SkippedChecks;
SkippedChecks.set(SanitizerKind::Null, true);
EmitTypeCheck(VBase ? TCK_UpcastToVirtualBase : TCK_Upcast, Loc,
Value.getPointer(), DerivedTy, DerivedAlign, SkippedChecks);
Value.emitRawPointer(*this), DerivedTy, DerivedAlign,
SkippedChecks);
}

// Compute the virtual offset.
llvm::Value *VirtualOffset = nullptr;
if (VBase) {
VirtualOffset =
CGM.getCXXABI().GetVirtualBaseClassOffset(*this, Value, Derived, VBase);
CGM.getCXXABI().GetVirtualBaseClassOffset(*this, Value, Derived, VBase);
}

// Apply both offsets.
Expand All @@ -387,7 +389,7 @@ Address CodeGenFunction::GetAddressOfBaseClass(
EmitBlock(endBB);

llvm::PHINode *PHI = Builder.CreatePHI(PtrTy, 2, "cast.result");
PHI->addIncoming(Value.getPointer(), notNullBB);
PHI->addIncoming(Value.emitRawPointer(*this), notNullBB);
PHI->addIncoming(llvm::Constant::getNullValue(PtrTy), origBB);
Value = Value.withPointer(PHI, NotKnownNonNull);
}
Expand Down Expand Up @@ -424,15 +426,19 @@ CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr,
CastNotNull = createBasicBlock("cast.notnull");
CastEnd = createBasicBlock("cast.end");

llvm::Value *IsNull = Builder.CreateIsNull(BaseAddr.getPointer());
llvm::Value *IsNull = Builder.CreateIsNull(BaseAddr);
Builder.CreateCondBr(IsNull, CastNull, CastNotNull);
EmitBlock(CastNotNull);
}

// Apply the offset.
llvm::Value *Value = BaseAddr.getPointer();
Value = Builder.CreateInBoundsGEP(
Int8Ty, Value, Builder.CreateNeg(NonVirtualOffset), "sub.ptr");
Address Addr = BaseAddr.withElementType(Int8Ty);
Addr = Builder.CreateInBoundsGEP(
Addr, Builder.CreateNeg(NonVirtualOffset), Int8Ty,
CGM.getClassPointerAlignment(Derived), "sub.ptr");

// Just cast.
Addr = Addr.withElementType(DerivedValueTy);

// Produce a PHI if we had a null-check.
if (NullCheckValue) {
Expand All @@ -441,13 +447,15 @@ CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr,
Builder.CreateBr(CastEnd);
EmitBlock(CastEnd);

llvm::Value *Value = Addr.emitRawPointer(*this);
llvm::PHINode *PHI = Builder.CreatePHI(Value->getType(), 2);
PHI->addIncoming(Value, CastNotNull);
PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), CastNull);
Value = PHI;
return Address(PHI, Addr.getElementType(),
CGM.getClassPointerAlignment(Derived));
}

return Address(Value, DerivedValueTy, CGM.getClassPointerAlignment(Derived));
return Addr;
}

llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD,
Expand Down Expand Up @@ -1719,7 +1727,7 @@ namespace {
// Use the base class declaration location as inline DebugLocation. All
// fields of the class are destroyed.
DeclAsInlineDebugLocation InlineHere(CGF, *BaseClass);
EmitSanitizerDtorFieldsCallback(CGF, Addr.getPointer(),
EmitSanitizerDtorFieldsCallback(CGF, Addr.emitRawPointer(CGF),
BaseSize.getQuantity());

// Prevent the current stack frame from disappearing from the stack trace.
Expand Down Expand Up @@ -2022,7 +2030,7 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,

// Find the end of the array.
llvm::Type *elementType = arrayBase.getElementType();
llvm::Value *arrayBegin = arrayBase.getPointer();
llvm::Value *arrayBegin = arrayBase.emitRawPointer(*this);
llvm::Value *arrayEnd = Builder.CreateInBoundsGEP(
elementType, arrayBegin, numElements, "arrayctor.end");

Expand Down Expand Up @@ -2118,14 +2126,15 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
Address This = ThisAVS.getAddress();
LangAS SlotAS = ThisAVS.getQualifiers().getAddressSpace();
LangAS ThisAS = D->getFunctionObjectParameterType().getAddressSpace();
llvm::Value *ThisPtr = This.getPointer();
llvm::Value *ThisPtr =
getAsNaturalPointerTo(This, D->getThisType()->getPointeeType());

if (SlotAS != ThisAS) {
unsigned TargetThisAS = getContext().getTargetAddressSpace(ThisAS);
llvm::Type *NewType =
llvm::PointerType::get(getLLVMContext(), TargetThisAS);
ThisPtr = getTargetHooks().performAddrSpaceCast(*this, This.getPointer(),
ThisAS, SlotAS, NewType);
ThisPtr = getTargetHooks().performAddrSpaceCast(*this, ThisPtr, ThisAS,
SlotAS, NewType);
}

// Push the this ptr.
Expand Down Expand Up @@ -2194,7 +2203,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
const CXXRecordDecl *ClassDecl = D->getParent();

if (!NewPointerIsChecked)
EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This.getPointer(),
EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This,
getContext().getRecordType(ClassDecl), CharUnits::Zero());

if (D->isTrivial() && D->isDefaultConstructor()) {
Expand All @@ -2207,10 +2216,9 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
// model that copy.
if (isMemcpyEquivalentSpecialMember(D)) {
assert(Args.size() == 2 && "unexpected argcount for trivial ctor");

QualType SrcTy = D->getParamDecl(0)->getType().getNonReferenceType();
Address Src = Address(Args[1].getRValue(*this).getScalarVal(), ConvertTypeForMem(SrcTy),
CGM.getNaturalTypeAlignment(SrcTy));
Address Src = makeNaturalAddressForPointer(
Args[1].getRValue(*this).getScalarVal(), SrcTy);
LValue SrcLVal = MakeAddrLValue(Src, SrcTy);
QualType DestTy = getContext().getTypeDeclType(ClassDecl);
LValue DestLVal = MakeAddrLValue(This, DestTy);
Expand Down Expand Up @@ -2263,7 +2271,9 @@ void CodeGenFunction::EmitInheritedCXXConstructorCall(
const CXXConstructorDecl *D, bool ForVirtualBase, Address This,
bool InheritedFromVBase, const CXXInheritedCtorInitExpr *E) {
CallArgList Args;
CallArg ThisArg(RValue::get(This.getPointer()), D->getThisType());
CallArg ThisArg(RValue::get(getAsNaturalPointerTo(
This, D->getThisType()->getPointeeType())),
D->getThisType());

// Forward the parameters.
if (InheritedFromVBase &&
Expand Down Expand Up @@ -2388,12 +2398,14 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
CallArgList Args;

// Push the this ptr.
Args.add(RValue::get(This.getPointer()), D->getThisType());
Args.add(RValue::get(getAsNaturalPointerTo(This, D->getThisType())),
D->getThisType());

// Push the src ptr.
QualType QT = *(FPT->param_type_begin());
llvm::Type *t = CGM.getTypes().ConvertType(QT);
llvm::Value *SrcVal = Builder.CreateBitCast(Src.getPointer(), t);
llvm::Value *Val = getAsNaturalPointerTo(Src, D->getThisType());
llvm::Value *SrcVal = Builder.CreateBitCast(Val, t);
Args.add(RValue::get(SrcVal), QT);

// Skip over first argument (Src).
Expand All @@ -2418,7 +2430,9 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,

// this
Address This = LoadCXXThisAddress();
DelegateArgs.add(RValue::get(This.getPointer()), (*I)->getType());
DelegateArgs.add(RValue::get(getAsNaturalPointerTo(
This, (*I)->getType()->getPointeeType())),
(*I)->getType());
++I;

// FIXME: The location of the VTT parameter in the parameter list is
Expand Down Expand Up @@ -2775,7 +2789,7 @@ void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, Address Derived,

if (MayBeNull) {
llvm::Value *DerivedNotNull =
Builder.CreateIsNotNull(Derived.getPointer(), "cast.nonnull");
Builder.CreateIsNotNull(Derived.emitRawPointer(*this), "cast.nonnull");

llvm::BasicBlock *CheckBlock = createBasicBlock("cast.check");
ContBlock = createBasicBlock("cast.cont");
Expand Down Expand Up @@ -2976,7 +2990,7 @@ void CodeGenFunction::EmitLambdaBlockInvokeBody() {

QualType ThisType = getContext().getPointerType(getContext().getRecordType(Lambda));
Address ThisPtr = GetAddrOfBlockDecl(variable);
CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType);
CallArgs.add(RValue::get(getAsNaturalPointerTo(ThisPtr, ThisType)), ThisType);

// Add the rest of the parameters.
for (auto *param : BD->parameters())
Expand Down Expand Up @@ -3004,7 +3018,7 @@ void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) {
QualType LambdaType = getContext().getRecordType(Lambda);
QualType ThisType = getContext().getPointerType(LambdaType);
Address ThisPtr = CreateMemTemp(LambdaType, "unused.capture");
CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType);
CallArgs.add(RValue::get(ThisPtr.emitRawPointer(*this)), ThisType);

EmitLambdaDelegatingInvokeBody(MD, CallArgs);
}
Expand Down
110 changes: 41 additions & 69 deletions clang/lib/CodeGen/CGCleanup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,77 +27,48 @@ bool DominatingValue<RValue>::saved_type::needsSaving(RValue rv) {
if (rv.isScalar())
return DominatingLLVMValue::needsSaving(rv.getScalarVal());
if (rv.isAggregate())
return DominatingLLVMValue::needsSaving(rv.getAggregatePointer());
return DominatingValue<Address>::needsSaving(rv.getAggregateAddress());
return true;
}

DominatingValue<RValue>::saved_type
DominatingValue<RValue>::saved_type::save(CodeGenFunction &CGF, RValue rv) {
if (rv.isScalar()) {
llvm::Value *V = rv.getScalarVal();

// These automatically dominate and don't need to be saved.
if (!DominatingLLVMValue::needsSaving(V))
return saved_type(V, nullptr, ScalarLiteral);

// Everything else needs an alloca.
Address addr =
CGF.CreateDefaultAlignTempAlloca(V->getType(), "saved-rvalue");
CGF.Builder.CreateStore(V, addr);
return saved_type(addr.getPointer(), nullptr, ScalarAddress);
return saved_type(DominatingLLVMValue::save(CGF, V),
DominatingLLVMValue::needsSaving(V) ? ScalarAddress
: ScalarLiteral);
}

if (rv.isComplex()) {
CodeGenFunction::ComplexPairTy V = rv.getComplexVal();
llvm::Type *ComplexTy =
llvm::StructType::get(V.first->getType(), V.second->getType());
Address addr = CGF.CreateDefaultAlignTempAlloca(ComplexTy, "saved-complex");
CGF.Builder.CreateStore(V.first, CGF.Builder.CreateStructGEP(addr, 0));
CGF.Builder.CreateStore(V.second, CGF.Builder.CreateStructGEP(addr, 1));
return saved_type(addr.getPointer(), nullptr, ComplexAddress);
return saved_type(DominatingLLVMValue::save(CGF, V.first),
DominatingLLVMValue::save(CGF, V.second));
}

assert(rv.isAggregate());
Address V = rv.getAggregateAddress(); // TODO: volatile?
if (!DominatingLLVMValue::needsSaving(V.getPointer()))
return saved_type(V.getPointer(), V.getElementType(), AggregateLiteral,
V.getAlignment().getQuantity());

Address addr =
CGF.CreateTempAlloca(V.getType(), CGF.getPointerAlign(), "saved-rvalue");
CGF.Builder.CreateStore(V.getPointer(), addr);
return saved_type(addr.getPointer(), V.getElementType(), AggregateAddress,
V.getAlignment().getQuantity());
Address V = rv.getAggregateAddress();
return saved_type(
DominatingValue<Address>::save(CGF, V), rv.isVolatileQualified(),
DominatingValue<Address>::needsSaving(V) ? AggregateAddress
: AggregateLiteral);
}

/// Given a saved r-value produced by SaveRValue, perform the code
/// necessary to restore it to usability at the current insertion
/// point.
RValue DominatingValue<RValue>::saved_type::restore(CodeGenFunction &CGF) {
auto getSavingAddress = [&](llvm::Value *value) {
auto *AI = cast<llvm::AllocaInst>(value);
return Address(value, AI->getAllocatedType(),
CharUnits::fromQuantity(AI->getAlign().value()));
};
switch (K) {
case ScalarLiteral:
return RValue::get(Value);
case ScalarAddress:
return RValue::get(CGF.Builder.CreateLoad(getSavingAddress(Value)));
return RValue::get(DominatingLLVMValue::restore(CGF, Vals.first));
case AggregateLiteral:
case AggregateAddress:
return RValue::getAggregate(
Address(Value, ElementType, CharUnits::fromQuantity(Align)));
case AggregateAddress: {
auto addr = CGF.Builder.CreateLoad(getSavingAddress(Value));
return RValue::getAggregate(
Address(addr, ElementType, CharUnits::fromQuantity(Align)));
}
DominatingValue<Address>::restore(CGF, AggregateAddr), IsVolatile);
case ComplexAddress: {
Address address = getSavingAddress(Value);
llvm::Value *real =
CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(address, 0));
llvm::Value *imag =
CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(address, 1));
llvm::Value *real = DominatingLLVMValue::restore(CGF, Vals.first);
llvm::Value *imag = DominatingLLVMValue::restore(CGF, Vals.second);
return RValue::getComplex(real, imag);
}
}
Expand Down Expand Up @@ -294,22 +265,22 @@ void EHScopeStack::popNullFixups() {
BranchFixups.pop_back();
}

Address CodeGenFunction::createCleanupActiveFlag() {
RawAddress CodeGenFunction::createCleanupActiveFlag() {
// Create a variable to decide whether the cleanup needs to be run.
Address active = CreateTempAllocaWithoutCast(
RawAddress active = CreateTempAllocaWithoutCast(
Builder.getInt1Ty(), CharUnits::One(), "cleanup.cond");

// Initialize it to false at a site that's guaranteed to be run
// before each evaluation.
setBeforeOutermostConditional(Builder.getFalse(), active);
setBeforeOutermostConditional(Builder.getFalse(), active, *this);

// Initialize it to true at the current location.
Builder.CreateStore(Builder.getTrue(), active);

return active;
}

void CodeGenFunction::initFullExprCleanupWithFlag(Address ActiveFlag) {
void CodeGenFunction::initFullExprCleanupWithFlag(RawAddress ActiveFlag) {
// Set that as the active flag in the cleanup.
EHCleanupScope &cleanup = cast<EHCleanupScope>(*EHStack.begin());
assert(!cleanup.hasActiveFlag() && "cleanup already has active flag?");
Expand All @@ -322,15 +293,17 @@ void CodeGenFunction::initFullExprCleanupWithFlag(Address ActiveFlag) {
void EHScopeStack::Cleanup::anchor() {}

static void createStoreInstBefore(llvm::Value *value, Address addr,
llvm::Instruction *beforeInst) {
auto store = new llvm::StoreInst(value, addr.getPointer(), beforeInst);
llvm::Instruction *beforeInst,
CodeGenFunction &CGF) {
auto store = new llvm::StoreInst(value, addr.emitRawPointer(CGF), beforeInst);
store->setAlignment(addr.getAlignment().getAsAlign());
}

static llvm::LoadInst *createLoadInstBefore(Address addr, const Twine &name,
llvm::Instruction *beforeInst) {
return new llvm::LoadInst(addr.getElementType(), addr.getPointer(), name,
false, addr.getAlignment().getAsAlign(),
llvm::Instruction *beforeInst,
CodeGenFunction &CGF) {
return new llvm::LoadInst(addr.getElementType(), addr.emitRawPointer(CGF),
name, false, addr.getAlignment().getAsAlign(),
beforeInst);
}

Expand All @@ -357,8 +330,8 @@ static void ResolveAllBranchFixups(CodeGenFunction &CGF,
// entry which we're currently popping.
if (Fixup.OptimisticBranchBlock == nullptr) {
createStoreInstBefore(CGF.Builder.getInt32(Fixup.DestinationIndex),
CGF.getNormalCleanupDestSlot(),
Fixup.InitialBranch);
CGF.getNormalCleanupDestSlot(), Fixup.InitialBranch,
CGF);
Fixup.InitialBranch->setSuccessor(0, CleanupEntry);
}

Expand All @@ -385,7 +358,7 @@ static llvm::SwitchInst *TransitionToCleanupSwitch(CodeGenFunction &CGF,
if (llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Term)) {
assert(Br->isUnconditional());
auto Load = createLoadInstBefore(CGF.getNormalCleanupDestSlot(),
"cleanup.dest", Term);
"cleanup.dest", Term, CGF);
llvm::SwitchInst *Switch =
llvm::SwitchInst::Create(Load, Br->getSuccessor(0), 4, Block);
Br->eraseFromParent();
Expand Down Expand Up @@ -513,8 +486,8 @@ void CodeGenFunction::PopCleanupBlocks(
I += Header.getSize();

if (Header.isConditional()) {
Address ActiveFlag =
reinterpret_cast<Address &>(LifetimeExtendedCleanupStack[I]);
RawAddress ActiveFlag =
reinterpret_cast<RawAddress &>(LifetimeExtendedCleanupStack[I]);
initFullExprCleanupWithFlag(ActiveFlag);
I += sizeof(ActiveFlag);
}
Expand Down Expand Up @@ -888,7 +861,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
if (NormalCleanupDestSlot->hasOneUse()) {
NormalCleanupDestSlot->user_back()->eraseFromParent();
NormalCleanupDestSlot->eraseFromParent();
NormalCleanupDest = Address::invalid();
NormalCleanupDest = RawAddress::invalid();
}

llvm::BasicBlock *BranchAfter = Scope.getBranchAfterBlock(0);
Expand All @@ -912,9 +885,8 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
// pass the abnormal exit flag to Fn (SEH cleanup)
cleanupFlags.setHasExitSwitch();

llvm::LoadInst *Load =
createLoadInstBefore(getNormalCleanupDestSlot(), "cleanup.dest",
nullptr);
llvm::LoadInst *Load = createLoadInstBefore(
getNormalCleanupDestSlot(), "cleanup.dest", nullptr, *this);
llvm::SwitchInst *Switch =
llvm::SwitchInst::Create(Load, Default, SwitchCapacity);

Expand Down Expand Up @@ -961,8 +933,8 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
if (!Fixup.Destination) continue;
if (!Fixup.OptimisticBranchBlock) {
createStoreInstBefore(Builder.getInt32(Fixup.DestinationIndex),
getNormalCleanupDestSlot(),
Fixup.InitialBranch);
getNormalCleanupDestSlot(), Fixup.InitialBranch,
*this);
Fixup.InitialBranch->setSuccessor(0, NormalEntry);
}
Fixup.OptimisticBranchBlock = NormalExit;
Expand Down Expand Up @@ -1135,7 +1107,7 @@ void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) {

// Store the index at the start.
llvm::ConstantInt *Index = Builder.getInt32(Dest.getDestIndex());
createStoreInstBefore(Index, getNormalCleanupDestSlot(), BI);
createStoreInstBefore(Index, getNormalCleanupDestSlot(), BI, *this);

// Adjust BI to point to the first cleanup block.
{
Expand Down Expand Up @@ -1269,9 +1241,9 @@ static void SetupCleanupBlockActivation(CodeGenFunction &CGF,
// If we're in a conditional block, ignore the dominating IP and
// use the outermost conditional branch.
if (CGF.isInConditionalBranch()) {
CGF.setBeforeOutermostConditional(value, var);
CGF.setBeforeOutermostConditional(value, var, CGF);
} else {
createStoreInstBefore(value, var, dominatingIP);
createStoreInstBefore(value, var, dominatingIP, CGF);
}
}

Expand Down Expand Up @@ -1321,7 +1293,7 @@ void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C,
Scope.setActive(false);
}

Address CodeGenFunction::getNormalCleanupDestSlot() {
RawAddress CodeGenFunction::getNormalCleanupDestSlot() {
if (!NormalCleanupDest.isValid())
NormalCleanupDest =
CreateDefaultAlignTempAlloca(Builder.getInt32Ty(), "cleanup.dest.slot");
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGCleanup.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ class alignas(8) EHCleanupScope : public EHScope {
Address getActiveFlag() const {
return ActiveFlag;
}
void setActiveFlag(Address Var) {
void setActiveFlag(RawAddress Var) {
assert(Var.getAlignment().isOne());
ActiveFlag = Var;
}
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CGCoroutine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -867,8 +867,8 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
EmitStmt(S.getPromiseDeclStmt());

Address PromiseAddr = GetAddrOfLocalVar(S.getPromiseDecl());
auto *PromiseAddrVoidPtr =
new llvm::BitCastInst(PromiseAddr.getPointer(), VoidPtrTy, "", CoroId);
auto *PromiseAddrVoidPtr = new llvm::BitCastInst(
PromiseAddr.emitRawPointer(*this), VoidPtrTy, "", CoroId);
// Update CoroId to refer to the promise. We could not do it earlier because
// promise local variable was not emitted yet.
CoroId->setArgOperand(1, PromiseAddrVoidPtr);
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1440,8 +1440,7 @@ static unsigned getDwarfCC(CallingConv CC) {
case CC_Swift:
return llvm::dwarf::DW_CC_LLVM_Swift;
case CC_SwiftAsync:
// [FIXME: swiftasynccc] Update to SwiftAsync once LLVM support lands.
return llvm::dwarf::DW_CC_LLVM_Swift;
return llvm::dwarf::DW_CC_LLVM_SwiftTail;
case CC_PreserveMost:
return llvm::dwarf::DW_CC_LLVM_PreserveMost;
case CC_PreserveAll:
Expand All @@ -1452,6 +1451,8 @@ static unsigned getDwarfCC(CallingConv CC) {
return llvm::dwarf::DW_CC_LLVM_M68kRTD;
case CC_PreserveNone:
return llvm::dwarf::DW_CC_LLVM_PreserveNone;
case CC_RISCVVectorCall:
return llvm::dwarf::DW_CC_LLVM_RISCVVectorCall;
}
return 0;
}
Expand Down
28 changes: 16 additions & 12 deletions clang/lib/CodeGen/CGDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1461,7 +1461,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
bool EmitDebugInfo = DI && CGM.getCodeGenOpts().hasReducedDebugInfo();

Address address = Address::invalid();
Address AllocaAddr = Address::invalid();
RawAddress AllocaAddr = RawAddress::invalid();
Address OpenMPLocalAddr = Address::invalid();
if (CGM.getLangOpts().OpenMPIRBuilder)
OpenMPLocalAddr = OMPBuilderCBHelpers::getAddressOfLocalVariable(*this, &D);
Expand Down Expand Up @@ -1524,7 +1524,10 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// return slot, so that we can elide the copy when returning this
// variable (C++0x [class.copy]p34).
address = ReturnValue;
AllocaAddr = ReturnValue;
AllocaAddr =
RawAddress(ReturnValue.emitRawPointer(*this),
ReturnValue.getElementType(), ReturnValue.getAlignment());
;

if (const RecordType *RecordTy = Ty->getAs<RecordType>()) {
const auto *RD = RecordTy->getDecl();
Expand All @@ -1535,7 +1538,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// to this variable. Set it to zero to indicate that NRVO was not
// applied.
llvm::Value *Zero = Builder.getFalse();
Address NRVOFlag =
RawAddress NRVOFlag =
CreateTempAlloca(Zero->getType(), CharUnits::One(), "nrvo");
EnsureInsertPoint();
Builder.CreateStore(Zero, NRVOFlag);
Expand Down Expand Up @@ -1678,7 +1681,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
}

if (D.hasAttr<AnnotateAttr>() && HaveInsertPoint())
EmitVarAnnotations(&D, address.getPointer());
EmitVarAnnotations(&D, address.emitRawPointer(*this));

// Make sure we call @llvm.lifetime.end.
if (emission.useLifetimeMarkers())
Expand Down Expand Up @@ -1851,12 +1854,13 @@ void CodeGenFunction::emitZeroOrPatternForAutoVarInit(QualType type,
llvm::Value *BaseSizeInChars =
llvm::ConstantInt::get(IntPtrTy, EltSize.getQuantity());
Address Begin = Loc.withElementType(Int8Ty);
llvm::Value *End = Builder.CreateInBoundsGEP(
Begin.getElementType(), Begin.getPointer(), SizeVal, "vla.end");
llvm::Value *End = Builder.CreateInBoundsGEP(Begin.getElementType(),
Begin.emitRawPointer(*this),
SizeVal, "vla.end");
llvm::BasicBlock *OriginBB = Builder.GetInsertBlock();
EmitBlock(LoopBB);
llvm::PHINode *Cur = Builder.CreatePHI(Begin.getType(), 2, "vla.cur");
Cur->addIncoming(Begin.getPointer(), OriginBB);
Cur->addIncoming(Begin.emitRawPointer(*this), OriginBB);
CharUnits CurAlign = Loc.getAlignment().alignmentOfArrayElement(EltSize);
auto *I =
Builder.CreateMemCpy(Address(Cur, Int8Ty, CurAlign),
Expand Down Expand Up @@ -2283,7 +2287,7 @@ void CodeGenFunction::emitDestroy(Address addr, QualType type,
checkZeroLength = false;
}

llvm::Value *begin = addr.getPointer();
llvm::Value *begin = addr.emitRawPointer(*this);
llvm::Value *end =
Builder.CreateInBoundsGEP(addr.getElementType(), begin, length);
emitArrayDestroy(begin, end, type, elementAlign, destroyer,
Expand Down Expand Up @@ -2543,7 +2547,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
}

Address DeclPtr = Address::invalid();
Address AllocaPtr = Address::invalid();
RawAddress AllocaPtr = Address::invalid();
bool DoStore = false;
bool IsScalar = hasScalarEvaluationKind(Ty);
bool UseIndirectDebugAddress = false;
Expand All @@ -2555,8 +2559,8 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
// Indirect argument is in alloca address space, which may be different
// from the default address space.
auto AllocaAS = CGM.getASTAllocaAddressSpace();
auto *V = DeclPtr.getPointer();
AllocaPtr = DeclPtr;
auto *V = DeclPtr.emitRawPointer(*this);
AllocaPtr = RawAddress(V, DeclPtr.getElementType(), DeclPtr.getAlignment());

// For truly ABI indirect arguments -- those that are not `byval` -- store
// the address of the argument on the stack to preserve debug information.
Expand Down Expand Up @@ -2695,7 +2699,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
}

if (D.hasAttr<AnnotateAttr>())
EmitVarAnnotations(&D, DeclPtr.getPointer());
EmitVarAnnotations(&D, DeclPtr.emitRawPointer(*this));

// We can only check return value nullability if all arguments to the
// function satisfy their nullability preconditions. This makes it necessary
Expand Down
Loading