diff options
Diffstat (limited to 'clang-r353983/include/clang/CodeGen')
9 files changed, 1992 insertions, 0 deletions
diff --git a/clang-r353983/include/clang/CodeGen/BackendUtil.h b/clang-r353983/include/clang/CodeGen/BackendUtil.h new file mode 100644 index 00000000..01b1f5bb --- /dev/null +++ b/clang-r353983/include/clang/CodeGen/BackendUtil.h @@ -0,0 +1,55 @@ +//===--- BackendUtil.h - LLVM Backend Utilities -----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGEN_BACKENDUTIL_H +#define LLVM_CLANG_CODEGEN_BACKENDUTIL_H + +#include "clang/Basic/LLVM.h" +#include "llvm/IR/ModuleSummaryIndex.h" +#include <memory> + +namespace llvm { + class BitcodeModule; + template <typename T> class Expected; + class Module; + class MemoryBufferRef; +} + +namespace clang { + class DiagnosticsEngine; + class HeaderSearchOptions; + class CodeGenOptions; + class TargetOptions; + class LangOptions; + + enum BackendAction { + Backend_EmitAssembly, ///< Emit native assembly files + Backend_EmitBC, ///< Emit LLVM bitcode files + Backend_EmitLL, ///< Emit human-readable LLVM assembly + Backend_EmitNothing, ///< Don't emit anything (benchmarking mode) + Backend_EmitMCNull, ///< Run CodeGen, but don't emit anything + Backend_EmitObj ///< Emit native object files + }; + + void EmitBackendOutput(DiagnosticsEngine &Diags, const HeaderSearchOptions &, + const CodeGenOptions &CGOpts, + const TargetOptions &TOpts, const LangOptions &LOpts, + const llvm::DataLayout &TDesc, llvm::Module *M, + BackendAction Action, + std::unique_ptr<raw_pwrite_stream> OS); + + void EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts, + llvm::MemoryBufferRef Buf); + + llvm::Expected<llvm::BitcodeModule> + FindThinLTOModule(llvm::MemoryBufferRef MBRef); + llvm::BitcodeModule * + FindThinLTOModule(llvm::MutableArrayRef<llvm::BitcodeModule> BMs); +} + +#endif diff --git a/clang-r353983/include/clang/CodeGen/CGFunctionInfo.h b/clang-r353983/include/clang/CodeGen/CGFunctionInfo.h new file mode 100644 index 00000000..52157f0c --- /dev/null +++ b/clang-r353983/include/clang/CodeGen/CGFunctionInfo.h @@ -0,0 +1,728 @@ +//==-- CGFunctionInfo.h - Representation of function argument/return types -==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Defines CGFunctionInfo and associated types used in representing the +// LLVM source types and ABI-coerced types for function arguments and +// return values. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H +#define LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H + +#include "clang/AST/Attr.h" +#include "clang/AST/CanonicalType.h" +#include "clang/AST/CharUnits.h" +#include "clang/AST/Decl.h" +#include "clang/AST/Type.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/TrailingObjects.h" +#include <cassert> + +namespace clang { +namespace CodeGen { + +/// ABIArgInfo - Helper class to encapsulate information about how a +/// specific C type should be passed to or returned from a function. +class ABIArgInfo { +public: + enum Kind : uint8_t { + /// Direct - Pass the argument directly using the normal converted LLVM + /// type, or by coercing to another specified type stored in + /// 'CoerceToType'). If an offset is specified (in UIntData), then the + /// argument passed is offset by some number of bytes in the memory + /// representation. A dummy argument is emitted before the real argument + /// if the specified type stored in "PaddingType" is not zero. + Direct, + + /// Extend - Valid only for integer argument types. Same as 'direct' + /// but also emit a zero/sign extension attribute. + Extend, + + /// Indirect - Pass the argument indirectly via a hidden pointer + /// with the specified alignment (0 indicates default alignment). + Indirect, + + /// Ignore - Ignore the argument (treat as void). Useful for void and + /// empty structs. + Ignore, + + /// Expand - Only valid for aggregate argument types. The structure should + /// be expanded into consecutive arguments for its constituent fields. + /// Currently expand is only allowed on structures whose fields + /// are all scalar types or are themselves expandable types. + Expand, + + /// CoerceAndExpand - Only valid for aggregate argument types. The + /// structure should be expanded into consecutive arguments corresponding + /// to the non-array elements of the type stored in CoerceToType. + /// Array elements in the type are assumed to be padding and skipped. + CoerceAndExpand, + + /// InAlloca - Pass the argument directly using the LLVM inalloca attribute. + /// This is similar to indirect with byval, except it only applies to + /// arguments stored in memory and forbids any implicit copies. When + /// applied to a return type, it means the value is returned indirectly via + /// an implicit sret parameter stored in the argument struct. + InAlloca, + KindFirst = Direct, + KindLast = InAlloca + }; + +private: + llvm::Type *TypeData; // canHaveCoerceToType() + union { + llvm::Type *PaddingType; // canHavePaddingType() + llvm::Type *UnpaddedCoerceAndExpandType; // isCoerceAndExpand() + }; + union { + unsigned DirectOffset; // isDirect() || isExtend() + unsigned IndirectAlign; // isIndirect() + unsigned AllocaFieldIndex; // isInAlloca() + }; + Kind TheKind; + bool PaddingInReg : 1; + bool InAllocaSRet : 1; // isInAlloca() + bool IndirectByVal : 1; // isIndirect() + bool IndirectRealign : 1; // isIndirect() + bool SRetAfterThis : 1; // isIndirect() + bool InReg : 1; // isDirect() || isExtend() || isIndirect() + bool CanBeFlattened: 1; // isDirect() + bool SignExt : 1; // isExtend() + bool SuppressSRet : 1; // isIndirect() + + bool canHavePaddingType() const { + return isDirect() || isExtend() || isIndirect() || isExpand(); + } + void setPaddingType(llvm::Type *T) { + assert(canHavePaddingType()); + PaddingType = T; + } + + void setUnpaddedCoerceToType(llvm::Type *T) { + assert(isCoerceAndExpand()); + UnpaddedCoerceAndExpandType = T; + } + + ABIArgInfo(Kind K) + : TheKind(K), PaddingInReg(false), InReg(false), SuppressSRet(false) { + } + +public: + ABIArgInfo() + : TypeData(nullptr), PaddingType(nullptr), DirectOffset(0), + TheKind(Direct), PaddingInReg(false), InReg(false), + SuppressSRet(false) {} + + static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0, + llvm::Type *Padding = nullptr, + bool CanBeFlattened = true) { + auto AI = ABIArgInfo(Direct); + AI.setCoerceToType(T); + AI.setPaddingType(Padding); + AI.setDirectOffset(Offset); + AI.setCanBeFlattened(CanBeFlattened); + return AI; + } + static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) { + auto AI = getDirect(T); + AI.setInReg(true); + return AI; + } + + static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T = nullptr) { + assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType"); + auto AI = ABIArgInfo(Extend); + AI.setCoerceToType(T); + AI.setPaddingType(nullptr); + AI.setDirectOffset(0); + AI.setSignExt(true); + return AI; + } + + static ABIArgInfo getZeroExtend(QualType Ty, llvm::Type *T = nullptr) { + assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType"); + auto AI = ABIArgInfo(Extend); + AI.setCoerceToType(T); + AI.setPaddingType(nullptr); + AI.setDirectOffset(0); + AI.setSignExt(false); + return AI; + } + + // ABIArgInfo will record the argument as being extended based on the sign + // of its type. + static ABIArgInfo getExtend(QualType Ty, llvm::Type *T = nullptr) { + assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType"); + if (Ty->hasSignedIntegerRepresentation()) + return getSignExtend(Ty, T); + return getZeroExtend(Ty, T); + } + + static ABIArgInfo getExtendInReg(QualType Ty, llvm::Type *T = nullptr) { + auto AI = getExtend(Ty, T); + AI.setInReg(true); + return AI; + } + static ABIArgInfo getIgnore() { + return ABIArgInfo(Ignore); + } + static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal = true, + bool Realign = false, + llvm::Type *Padding = nullptr) { + auto AI = ABIArgInfo(Indirect); + AI.setIndirectAlign(Alignment); + AI.setIndirectByVal(ByVal); + AI.setIndirectRealign(Realign); + AI.setSRetAfterThis(false); + AI.setPaddingType(Padding); + return AI; + } + static ABIArgInfo getIndirectInReg(CharUnits Alignment, bool ByVal = true, + bool Realign = false) { + auto AI = getIndirect(Alignment, ByVal, Realign); + AI.setInReg(true); + return AI; + } + static ABIArgInfo getInAlloca(unsigned FieldIndex) { + auto AI = ABIArgInfo(InAlloca); + AI.setInAllocaFieldIndex(FieldIndex); + return AI; + } + static ABIArgInfo getExpand() { + auto AI = ABIArgInfo(Expand); + AI.setPaddingType(nullptr); + return AI; + } + static ABIArgInfo getExpandWithPadding(bool PaddingInReg, + llvm::Type *Padding) { + auto AI = getExpand(); + AI.setPaddingInReg(PaddingInReg); + AI.setPaddingType(Padding); + return AI; + } + + /// \param unpaddedCoerceToType The coerce-to type with padding elements + /// removed, canonicalized to a single element if it would otherwise + /// have exactly one element. + static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType, + llvm::Type *unpaddedCoerceToType) { +#ifndef NDEBUG + // Sanity checks on unpaddedCoerceToType. + + // Assert that we only have a struct type if there are multiple elements. + auto unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoerceToType); + assert(!unpaddedStruct || unpaddedStruct->getNumElements() != 1); + + // Assert that all the non-padding elements have a corresponding element + // in the unpadded type. + unsigned unpaddedIndex = 0; + for (auto eltType : coerceToType->elements()) { + if (isPaddingForCoerceAndExpand(eltType)) continue; + if (unpaddedStruct) { + assert(unpaddedStruct->getElementType(unpaddedIndex) == eltType); + } else { + assert(unpaddedIndex == 0 && unpaddedCoerceToType == eltType); + } + unpaddedIndex++; + } + + // Assert that there aren't extra elements in the unpadded type. + if (unpaddedStruct) { + assert(unpaddedStruct->getNumElements() == unpaddedIndex); + } else { + assert(unpaddedIndex == 1); + } +#endif + + auto AI = ABIArgInfo(CoerceAndExpand); + AI.setCoerceToType(coerceToType); + AI.setUnpaddedCoerceToType(unpaddedCoerceToType); + return AI; + } + + static bool isPaddingForCoerceAndExpand(llvm::Type *eltType) { + if (eltType->isArrayTy()) { + assert(eltType->getArrayElementType()->isIntegerTy(8)); + return true; + } else { + return false; + } + } + + Kind getKind() const { return TheKind; } + bool isDirect() const { return TheKind == Direct; } + bool isInAlloca() const { return TheKind == InAlloca; } + bool isExtend() const { return TheKind == Extend; } + bool isIgnore() const { return TheKind == Ignore; } + bool isIndirect() const { return TheKind == Indirect; } + bool isExpand() const { return TheKind == Expand; } + bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; } + + bool canHaveCoerceToType() const { + return isDirect() || isExtend() || isCoerceAndExpand(); + } + + // Direct/Extend accessors + unsigned getDirectOffset() const { + assert((isDirect() || isExtend()) && "Not a direct or extend kind"); + return DirectOffset; + } + void setDirectOffset(unsigned Offset) { + assert((isDirect() || isExtend()) && "Not a direct or extend kind"); + DirectOffset = Offset; + } + + bool isSignExt() const { + assert(isExtend() && "Invalid kind!"); + return SignExt; + } + void setSignExt(bool SExt) { + assert(isExtend() && "Invalid kind!"); + SignExt = SExt; + } + + llvm::Type *getPaddingType() const { + return (canHavePaddingType() ? PaddingType : nullptr); + } + + bool getPaddingInReg() const { + return PaddingInReg; + } + void setPaddingInReg(bool PIR) { + PaddingInReg = PIR; + } + + llvm::Type *getCoerceToType() const { + assert(canHaveCoerceToType() && "Invalid kind!"); + return TypeData; + } + + void setCoerceToType(llvm::Type *T) { + assert(canHaveCoerceToType() && "Invalid kind!"); + TypeData = T; + } + + llvm::StructType *getCoerceAndExpandType() const { + assert(isCoerceAndExpand()); + return cast<llvm::StructType>(TypeData); + } + + llvm::Type *getUnpaddedCoerceAndExpandType() const { + assert(isCoerceAndExpand()); + return UnpaddedCoerceAndExpandType; + } + + ArrayRef<llvm::Type *>getCoerceAndExpandTypeSequence() const { + assert(isCoerceAndExpand()); + if (auto structTy = + dyn_cast<llvm::StructType>(UnpaddedCoerceAndExpandType)) { + return structTy->elements(); + } else { + return llvm::makeArrayRef(&UnpaddedCoerceAndExpandType, 1); + } + } + + bool getInReg() const { + assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!"); + return InReg; + } + + void setInReg(bool IR) { + assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!"); + InReg = IR; + } + + // Indirect accessors + CharUnits getIndirectAlign() const { + assert(isIndirect() && "Invalid kind!"); + return CharUnits::fromQuantity(IndirectAlign); + } + void setIndirectAlign(CharUnits IA) { + assert(isIndirect() && "Invalid kind!"); + IndirectAlign = IA.getQuantity(); + } + + bool getIndirectByVal() const { + assert(isIndirect() && "Invalid kind!"); + return IndirectByVal; + } + void setIndirectByVal(bool IBV) { + assert(isIndirect() && "Invalid kind!"); + IndirectByVal = IBV; + } + + bool getIndirectRealign() const { + assert(isIndirect() && "Invalid kind!"); + return IndirectRealign; + } + void setIndirectRealign(bool IR) { + assert(isIndirect() && "Invalid kind!"); + IndirectRealign = IR; + } + + bool isSRetAfterThis() const { + assert(isIndirect() && "Invalid kind!"); + return SRetAfterThis; + } + void setSRetAfterThis(bool AfterThis) { + assert(isIndirect() && "Invalid kind!"); + SRetAfterThis = AfterThis; + } + + unsigned getInAllocaFieldIndex() const { + assert(isInAlloca() && "Invalid kind!"); + return AllocaFieldIndex; + } + void setInAllocaFieldIndex(unsigned FieldIndex) { + assert(isInAlloca() && "Invalid kind!"); + AllocaFieldIndex = FieldIndex; + } + + /// Return true if this field of an inalloca struct should be returned + /// to implement a struct return calling convention. + bool getInAllocaSRet() const { + assert(isInAlloca() && "Invalid kind!"); + return InAllocaSRet; + } + + void setInAllocaSRet(bool SRet) { + assert(isInAlloca() && "Invalid kind!"); + InAllocaSRet = SRet; + } + + bool getCanBeFlattened() const { + assert(isDirect() && "Invalid kind!"); + return CanBeFlattened; + } + + void setCanBeFlattened(bool Flatten) { + assert(isDirect() && "Invalid kind!"); + CanBeFlattened = Flatten; + } + + bool getSuppressSRet() const { + assert(isIndirect() && "Invalid kind!"); + return SuppressSRet; + } + + void setSuppressSRet(bool Suppress) { + assert(isIndirect() && "Invalid kind!"); + SuppressSRet = Suppress; + } + + void dump() const; +}; + +/// A class for recording the number of arguments that a function +/// signature requires. +class RequiredArgs { + /// The number of required arguments, or ~0 if the signature does + /// not permit optional arguments. + unsigned NumRequired; +public: + enum All_t { All }; + + RequiredArgs(All_t _) : NumRequired(~0U) {} + explicit RequiredArgs(unsigned n) : NumRequired(n) { + assert(n != ~0U); + } + + /// Compute the arguments required by the given formal prototype, + /// given that there may be some additional, non-formal arguments + /// in play. + /// + /// If FD is not null, this will consider pass_object_size params in FD. + static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype, + unsigned additional) { + if (!prototype->isVariadic()) return All; + + if (prototype->hasExtParameterInfos()) + additional += llvm::count_if( + prototype->getExtParameterInfos(), + [](const FunctionProtoType::ExtParameterInfo &ExtInfo) { + return ExtInfo.hasPassObjectSize(); + }); + + return RequiredArgs(prototype->getNumParams() + additional); + } + + static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype, + unsigned additional) { + return forPrototypePlus(prototype.getTypePtr(), additional); + } + + static RequiredArgs forPrototype(const FunctionProtoType *prototype) { + return forPrototypePlus(prototype, 0); + } + + static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) { + return forPrototypePlus(prototype.getTypePtr(), 0); + } + + bool allowsOptionalArgs() const { return NumRequired != ~0U; } + unsigned getNumRequiredArgs() const { + assert(allowsOptionalArgs()); + return NumRequired; + } + + unsigned getOpaqueData() const { return NumRequired; } + static RequiredArgs getFromOpaqueData(unsigned value) { + if (value == ~0U) return All; + return RequiredArgs(value); + } +}; + +// Implementation detail of CGFunctionInfo, factored out so it can be named +// in the TrailingObjects base class of CGFunctionInfo. +struct CGFunctionInfoArgInfo { + CanQualType type; + ABIArgInfo info; +}; + +/// CGFunctionInfo - Class to encapsulate the information about a +/// function definition. +class CGFunctionInfo final + : public llvm::FoldingSetNode, + private llvm::TrailingObjects<CGFunctionInfo, CGFunctionInfoArgInfo, + FunctionProtoType::ExtParameterInfo> { + typedef CGFunctionInfoArgInfo ArgInfo; + typedef FunctionProtoType::ExtParameterInfo ExtParameterInfo; + + /// The LLVM::CallingConv to use for this function (as specified by the + /// user). + unsigned CallingConvention : 8; + + /// The LLVM::CallingConv to actually use for this function, which may + /// depend on the ABI. + unsigned EffectiveCallingConvention : 8; + + /// The clang::CallingConv that this was originally created with. + unsigned ASTCallingConvention : 6; + + /// Whether this is an instance method. + unsigned InstanceMethod : 1; + + /// Whether this is a chain call. + unsigned ChainCall : 1; + + /// Whether this function is noreturn. + unsigned NoReturn : 1; + + /// Whether this function is returns-retained. + unsigned ReturnsRetained : 1; + + /// Whether this function saved caller registers. + unsigned NoCallerSavedRegs : 1; + + /// How many arguments to pass inreg. + unsigned HasRegParm : 1; + unsigned RegParm : 3; + + /// Whether this function has nocf_check attribute. + unsigned NoCfCheck : 1; + + RequiredArgs Required; + + /// The struct representing all arguments passed in memory. Only used when + /// passing non-trivial types with inalloca. Not part of the profile. + llvm::StructType *ArgStruct; + unsigned ArgStructAlign : 31; + unsigned HasExtParameterInfos : 1; + + unsigned NumArgs; + + ArgInfo *getArgsBuffer() { + return getTrailingObjects<ArgInfo>(); + } + const ArgInfo *getArgsBuffer() const { + return getTrailingObjects<ArgInfo>(); + } + + ExtParameterInfo *getExtParameterInfosBuffer() { + return getTrailingObjects<ExtParameterInfo>(); + } + const ExtParameterInfo *getExtParameterInfosBuffer() const{ + return getTrailingObjects<ExtParameterInfo>(); + } + + CGFunctionInfo() : Required(RequiredArgs::All) {} + +public: + static CGFunctionInfo *create(unsigned llvmCC, + bool instanceMethod, + bool chainCall, + const FunctionType::ExtInfo &extInfo, + ArrayRef<ExtParameterInfo> paramInfos, + CanQualType resultType, + ArrayRef<CanQualType> argTypes, + RequiredArgs required); + void operator delete(void *p) { ::operator delete(p); } + + // Friending class TrailingObjects is apparently not good enough for MSVC, + // so these have to be public. + friend class TrailingObjects; + size_t numTrailingObjects(OverloadToken<ArgInfo>) const { + return NumArgs + 1; + } + size_t numTrailingObjects(OverloadToken<ExtParameterInfo>) const { + return (HasExtParameterInfos ? NumArgs : 0); + } + + typedef const ArgInfo *const_arg_iterator; + typedef ArgInfo *arg_iterator; + + typedef llvm::iterator_range<arg_iterator> arg_range; + typedef llvm::iterator_range<const_arg_iterator> const_arg_range; + + arg_range arguments() { return arg_range(arg_begin(), arg_end()); } + const_arg_range arguments() const { + return const_arg_range(arg_begin(), arg_end()); + } + + const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; } + const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; } + arg_iterator arg_begin() { return getArgsBuffer() + 1; } + arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; } + + unsigned arg_size() const { return NumArgs; } + + bool isVariadic() const { return Required.allowsOptionalArgs(); } + RequiredArgs getRequiredArgs() const { return Required; } + unsigned getNumRequiredArgs() const { + return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size(); + } + + bool isInstanceMethod() const { return InstanceMethod; } + + bool isChainCall() const { return ChainCall; } + + bool isNoReturn() const { return NoReturn; } + + /// In ARC, whether this function retains its return value. This + /// is not always reliable for call sites. + bool isReturnsRetained() const { return ReturnsRetained; } + + /// Whether this function no longer saves caller registers. + bool isNoCallerSavedRegs() const { return NoCallerSavedRegs; } + + /// Whether this function has nocf_check attribute. + bool isNoCfCheck() const { return NoCfCheck; } + + /// getASTCallingConvention() - Return the AST-specified calling + /// convention. + CallingConv getASTCallingConvention() const { + return CallingConv(ASTCallingConvention); + } + + /// getCallingConvention - Return the user specified calling + /// convention, which has been translated into an LLVM CC. + unsigned getCallingConvention() const { return CallingConvention; } + + /// getEffectiveCallingConvention - Return the actual calling convention to + /// use, which may depend on the ABI. + unsigned getEffectiveCallingConvention() const { + return EffectiveCallingConvention; + } + void setEffectiveCallingConvention(unsigned Value) { + EffectiveCallingConvention = Value; + } + + bool getHasRegParm() const { return HasRegParm; } + unsigned getRegParm() const { return RegParm; } + + FunctionType::ExtInfo getExtInfo() const { + return FunctionType::ExtInfo(isNoReturn(), getHasRegParm(), getRegParm(), + getASTCallingConvention(), isReturnsRetained(), + isNoCallerSavedRegs(), isNoCfCheck()); + } + + CanQualType getReturnType() const { return getArgsBuffer()[0].type; } + + ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; } + const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; } + + ArrayRef<ExtParameterInfo> getExtParameterInfos() const { + if (!HasExtParameterInfos) return {}; + return llvm::makeArrayRef(getExtParameterInfosBuffer(), NumArgs); + } + ExtParameterInfo getExtParameterInfo(unsigned argIndex) const { + assert(argIndex <= NumArgs); + if (!HasExtParameterInfos) return ExtParameterInfo(); + return getExtParameterInfos()[argIndex]; + } + + /// Return true if this function uses inalloca arguments. + bool usesInAlloca() const { return ArgStruct; } + + /// Get the struct type used to represent all the arguments in memory. + llvm::StructType *getArgStruct() const { return ArgStruct; } + CharUnits getArgStructAlignment() const { + return CharUnits::fromQuantity(ArgStructAlign); + } + void setArgStruct(llvm::StructType *Ty, CharUnits Align) { + ArgStruct = Ty; + ArgStructAlign = Align.getQuantity(); + } + + void Profile(llvm::FoldingSetNodeID &ID) { + ID.AddInteger(getASTCallingConvention()); + ID.AddBoolean(InstanceMethod); + ID.AddBoolean(ChainCall); + ID.AddBoolean(NoReturn); + ID.AddBoolean(ReturnsRetained); + ID.AddBoolean(NoCallerSavedRegs); + ID.AddBoolean(HasRegParm); + ID.AddInteger(RegParm); + ID.AddBoolean(NoCfCheck); + ID.AddInteger(Required.getOpaqueData()); + ID.AddBoolean(HasExtParameterInfos); + if (HasExtParameterInfos) { + for (auto paramInfo : getExtParameterInfos()) + ID.AddInteger(paramInfo.getOpaqueValue()); + } + getReturnType().Profile(ID); + for (const auto &I : arguments()) + I.type.Profile(ID); + } + static void Profile(llvm::FoldingSetNodeID &ID, + bool InstanceMethod, + bool ChainCall, + const FunctionType::ExtInfo &info, + ArrayRef<ExtParameterInfo> paramInfos, + RequiredArgs required, + CanQualType resultType, + ArrayRef<CanQualType> argTypes) { + ID.AddInteger(info.getCC()); + ID.AddBoolean(InstanceMethod); + ID.AddBoolean(ChainCall); + ID.AddBoolean(info.getNoReturn()); + ID.AddBoolean(info.getProducesResult()); + ID.AddBoolean(info.getNoCallerSavedRegs()); + ID.AddBoolean(info.getHasRegParm()); + ID.AddInteger(info.getRegParm()); + ID.AddBoolean(info.getNoCfCheck()); + ID.AddInteger(required.getOpaqueData()); + ID.AddBoolean(!paramInfos.empty()); + if (!paramInfos.empty()) { + for (auto paramInfo : paramInfos) + ID.AddInteger(paramInfo.getOpaqueValue()); + } + resultType.Profile(ID); + for (ArrayRef<CanQualType>::iterator + i = argTypes.begin(), e = argTypes.end(); i != e; ++i) { + i->Profile(ID); + } + } +}; + +} // end namespace CodeGen +} // end namespace clang + +#endif diff --git a/clang-r353983/include/clang/CodeGen/CodeGenABITypes.h b/clang-r353983/include/clang/CodeGen/CodeGenABITypes.h new file mode 100644 index 00000000..febb25aa --- /dev/null +++ b/clang-r353983/include/clang/CodeGen/CodeGenABITypes.h @@ -0,0 +1,89 @@ +//==---- CodeGenABITypes.h - Convert Clang types to LLVM types for ABI -----==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// CodeGenABITypes is a simple interface for getting LLVM types for +// the parameters and the return value of a function given the Clang +// types. +// +// The class is implemented as a public wrapper around the private +// CodeGenTypes class in lib/CodeGen. +// +// It allows other clients, like LLDB, to determine the LLVM types that are +// actually used in function calls, which makes it possible to then determine +// the actual ABI locations (e.g. registers, stack locations, etc.) that +// these parameters are stored in. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGEN_CODEGENABITYPES_H +#define LLVM_CLANG_CODEGEN_CODEGENABITYPES_H + +#include "clang/AST/CanonicalType.h" +#include "clang/AST/Type.h" +#include "clang/CodeGen/CGFunctionInfo.h" + +namespace llvm { + class DataLayout; + class Module; + class FunctionType; + class Type; +} + +namespace clang { +class ASTContext; +class CXXRecordDecl; +class CXXMethodDecl; +class CodeGenOptions; +class CoverageSourceInfo; +class DiagnosticsEngine; +class HeaderSearchOptions; +class ObjCMethodDecl; +class PreprocessorOptions; + +namespace CodeGen { +class CGFunctionInfo; +class CodeGenModule; + +const CGFunctionInfo &arrangeObjCMessageSendSignature(CodeGenModule &CGM, + const ObjCMethodDecl *MD, + QualType receiverType); + +const CGFunctionInfo &arrangeFreeFunctionType(CodeGenModule &CGM, + CanQual<FunctionProtoType> Ty); + +const CGFunctionInfo &arrangeFreeFunctionType(CodeGenModule &CGM, + CanQual<FunctionNoProtoType> Ty); + +const CGFunctionInfo &arrangeCXXMethodType(CodeGenModule &CGM, + const CXXRecordDecl *RD, + const FunctionProtoType *FTP, + const CXXMethodDecl *MD); + +const CGFunctionInfo &arrangeFreeFunctionCall(CodeGenModule &CGM, + CanQualType returnType, + ArrayRef<CanQualType> argTypes, + FunctionType::ExtInfo info, + RequiredArgs args); + +/// Returns null if the function type is incomplete and can't be lowered. +llvm::FunctionType *convertFreeFunctionType(CodeGenModule &CGM, + const FunctionDecl *FD); + +llvm::Type *convertTypeForMemory(CodeGenModule &CGM, QualType T); + +/// Given a non-bitfield struct field, return its index within the elements of +/// the struct's converted type. The returned index refers to a field number in +/// the complete object type which is returned by convertTypeForMemory. FD must +/// be a field in RD directly (i.e. not an inherited field). +unsigned getLLVMFieldNumber(CodeGenModule &CGM, + const RecordDecl *RD, const FieldDecl *FD); + +} // end namespace CodeGen +} // end namespace clang + +#endif diff --git a/clang-r353983/include/clang/CodeGen/CodeGenAction.h b/clang-r353983/include/clang/CodeGen/CodeGenAction.h new file mode 100644 index 00000000..1db904ea --- /dev/null +++ b/clang-r353983/include/clang/CodeGen/CodeGenAction.h @@ -0,0 +1,121 @@ +//===--- CodeGenAction.h - LLVM Code Generation Frontend Action -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGEN_CODEGENACTION_H +#define LLVM_CLANG_CODEGEN_CODEGENACTION_H + +#include "clang/Frontend/FrontendAction.h" +#include <memory> + +namespace llvm { + class LLVMContext; + class Module; +} + +namespace clang { +class BackendConsumer; + +class CodeGenAction : public ASTFrontendAction { +private: + // Let BackendConsumer access LinkModule. + friend class BackendConsumer; + + /// Info about module to link into a module we're generating. + struct LinkModule { + /// The module to link in. + std::unique_ptr<llvm::Module> Module; + + /// If true, we set attributes on Module's functions according to our + /// CodeGenOptions and LangOptions, as though we were generating the + /// function ourselves. + bool PropagateAttrs; + + /// If true, we use LLVM module internalizer. + bool Internalize; + + /// Bitwise combination of llvm::LinkerFlags used when we link the module. + unsigned LinkFlags; + }; + + unsigned Act; + std::unique_ptr<llvm::Module> TheModule; + + /// Bitcode modules to link in to our module. + SmallVector<LinkModule, 4> LinkModules; + llvm::LLVMContext *VMContext; + bool OwnsVMContext; + + std::unique_ptr<llvm::Module> loadModule(llvm::MemoryBufferRef MBRef); + +protected: + /// Create a new code generation action. If the optional \p _VMContext + /// parameter is supplied, the action uses it without taking ownership, + /// otherwise it creates a fresh LLVM context and takes ownership. + CodeGenAction(unsigned _Act, llvm::LLVMContext *_VMContext = nullptr); + + bool hasIRSupport() const override; + + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + + void ExecuteAction() override; + + void EndSourceFileAction() override; + +public: + ~CodeGenAction() override; + + /// Take the generated LLVM module, for use after the action has been run. + /// The result may be null on failure. + std::unique_ptr<llvm::Module> takeModule(); + + /// Take the LLVM context used by this action. + llvm::LLVMContext *takeLLVMContext(); + + BackendConsumer *BEConsumer; +}; + +class EmitAssemblyAction : public CodeGenAction { + virtual void anchor(); +public: + EmitAssemblyAction(llvm::LLVMContext *_VMContext = nullptr); +}; + +class EmitBCAction : public CodeGenAction { + virtual void anchor(); +public: + EmitBCAction(llvm::LLVMContext *_VMContext = nullptr); +}; + +class EmitLLVMAction : public CodeGenAction { + virtual void anchor(); +public: + EmitLLVMAction(llvm::LLVMContext *_VMContext = nullptr); +}; + +class EmitLLVMOnlyAction : public CodeGenAction { + virtual void anchor(); +public: + EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext = nullptr); +}; + +class EmitCodeGenOnlyAction : public CodeGenAction { + virtual void anchor(); +public: + EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext = nullptr); +}; + +class EmitObjAction : public CodeGenAction { + virtual void anchor(); +public: + EmitObjAction(llvm::LLVMContext *_VMContext = nullptr); +}; + +} + +#endif diff --git a/clang-r353983/include/clang/CodeGen/ConstantInitBuilder.h b/clang-r353983/include/clang/CodeGen/ConstantInitBuilder.h new file mode 100644 index 00000000..fd07e91b --- /dev/null +++ b/clang-r353983/include/clang/CodeGen/ConstantInitBuilder.h @@ -0,0 +1,560 @@ +//===- ConstantInitBuilder.h - Builder for LLVM IR constants ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This class provides a convenient interface for building complex +// global initializers of the sort that are frequently required for +// language ABIs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H +#define LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/GlobalValue.h" +#include "clang/AST/CharUnits.h" +#include "clang/CodeGen/ConstantInitFuture.h" + +#include <vector> + +namespace clang { +namespace CodeGen { + +class CodeGenModule; + +/// A convenience builder class for complex constant initializers, +/// especially for anonymous global structures used by various language +/// runtimes. +/// +/// The basic usage pattern is expected to be something like: +/// ConstantInitBuilder builder(CGM); +/// auto toplevel = builder.beginStruct(); +/// toplevel.addInt(CGM.SizeTy, widgets.size()); +/// auto widgetArray = builder.beginArray(); +/// for (auto &widget : widgets) { +/// auto widgetDesc = widgetArray.beginStruct(); +/// widgetDesc.addInt(CGM.SizeTy, widget.getPower()); +/// widgetDesc.add(CGM.GetAddrOfConstantString(widget.getName())); +/// widgetDesc.add(CGM.GetAddrOfGlobal(widget.getInitializerDecl())); +/// widgetDesc.finishAndAddTo(widgetArray); +/// } +/// widgetArray.finishAndAddTo(toplevel); +/// auto global = toplevel.finishAndCreateGlobal("WIDGET_LIST", Align, +/// /*constant*/ true); +class ConstantInitBuilderBase { + struct SelfReference { + llvm::GlobalVariable *Dummy; + llvm::SmallVector<llvm::Constant*, 4> Indices; + + SelfReference(llvm::GlobalVariable *dummy) : Dummy(dummy) {} + }; + CodeGenModule &CGM; + llvm::SmallVector<llvm::Constant*, 16> Buffer; + std::vector<SelfReference> SelfReferences; + bool Frozen = false; + + friend class ConstantInitFuture; + friend class ConstantAggregateBuilderBase; + template <class, class> + friend class ConstantAggregateBuilderTemplateBase; + +protected: + explicit ConstantInitBuilderBase(CodeGenModule &CGM) : CGM(CGM) {} + + ~ConstantInitBuilderBase() { + assert(Buffer.empty() && "didn't claim all values out of buffer"); + assert(SelfReferences.empty() && "didn't apply all self-references"); + } + +private: + llvm::GlobalVariable *createGlobal(llvm::Constant *initializer, + const llvm::Twine &name, + CharUnits alignment, + bool constant = false, + llvm::GlobalValue::LinkageTypes linkage + = llvm::GlobalValue::InternalLinkage, + unsigned addressSpace = 0); + + ConstantInitFuture createFuture(llvm::Constant *initializer); + + void setGlobalInitializer(llvm::GlobalVariable *GV, + llvm::Constant *initializer); + + void resolveSelfReferences(llvm::GlobalVariable *GV); + + void abandon(size_t newEnd); +}; + +/// A concrete base class for struct and array aggregate +/// initializer builders. +class ConstantAggregateBuilderBase { +protected: + ConstantInitBuilderBase &Builder; + ConstantAggregateBuilderBase *Parent; + size_t Begin; + mutable size_t CachedOffsetEnd = 0; + bool Finished = false; + bool Frozen = false; + bool Packed = false; + mutable CharUnits CachedOffsetFromGlobal; + + llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() { + return Builder.Buffer; + } + + const llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() const { + return Builder.Buffer; + } + + ConstantAggregateBuilderBase(ConstantInitBuilderBase &builder, + ConstantAggregateBuilderBase *parent) + : Builder(builder), Parent(parent), Begin(builder.Buffer.size()) { + if (parent) { + assert(!parent->Frozen && "parent already has child builder active"); + parent->Frozen = true; + } else { + assert(!builder.Frozen && "builder already has child builder active"); + builder.Frozen = true; + } + } + + ~ConstantAggregateBuilderBase() { + assert(Finished && "didn't finish aggregate builder"); + } + + void markFinished() { + assert(!Frozen && "child builder still active"); + assert(!Finished && "builder already finished"); + Finished = true; + if (Parent) { + assert(Parent->Frozen && + "parent not frozen while child builder active"); + Parent->Frozen = false; + } else { + assert(Builder.Frozen && + "builder not frozen while child builder active"); + Builder.Frozen = false; + } + } + +public: + // Not copyable. + ConstantAggregateBuilderBase(const ConstantAggregateBuilderBase &) = delete; + ConstantAggregateBuilderBase &operator=(const ConstantAggregateBuilderBase &) + = delete; + + // Movable, mostly to allow returning. But we have to write this out + // properly to satisfy the assert in the destructor. + ConstantAggregateBuilderBase(ConstantAggregateBuilderBase &&other) + : Builder(other.Builder), Parent(other.Parent), Begin(other.Begin), + CachedOffsetEnd(other.CachedOffsetEnd), + Finished(other.Finished), Frozen(other.Frozen), Packed(other.Packed), + CachedOffsetFromGlobal(other.CachedOffsetFromGlobal) { + other.Finished = true; + } + ConstantAggregateBuilderBase &operator=(ConstantAggregateBuilderBase &&other) + = delete; + + /// Return the number of elements that have been added to + /// this struct or array. + size_t size() const { + assert(!this->Finished && "cannot query after finishing builder"); + assert(!this->Frozen && "cannot query while sub-builder is active"); + assert(this->Begin <= this->getBuffer().size()); + return this->getBuffer().size() - this->Begin; + } + + /// Return true if no elements have yet been added to this struct or array. + bool empty() const { + return size() == 0; + } + + /// Abandon this builder completely. + void abandon() { + markFinished(); + Builder.abandon(Begin); + } + + /// Add a new value to this initializer. + void add(llvm::Constant *value) { + assert(value && "adding null value to constant initializer"); + assert(!Finished && "cannot add more values after finishing builder"); + assert(!Frozen && "cannot add values while subbuilder is active"); + Builder.Buffer.push_back(value); + } + + /// Add an integer value of type size_t. + void addSize(CharUnits size); + + /// Add an integer value of a specific type. + void addInt(llvm::IntegerType *intTy, uint64_t value, + bool isSigned = false) { + add(llvm::ConstantInt::get(intTy, value, isSigned)); + } + + /// Add a null pointer of a specific type. + void addNullPointer(llvm::PointerType *ptrTy) { + add(llvm::ConstantPointerNull::get(ptrTy)); + } + + /// Add a bitcast of a value to a specific type. + void addBitCast(llvm::Constant *value, llvm::Type *type) { + add(llvm::ConstantExpr::getBitCast(value, type)); + } + + /// Add a bunch of new values to this initializer. + void addAll(llvm::ArrayRef<llvm::Constant *> values) { + assert(!Finished && "cannot add more values after finishing builder"); + assert(!Frozen && "cannot add values while subbuilder is active"); + Builder.Buffer.append(values.begin(), values.end()); + } + + /// Add a relative offset to the given target address, i.e. the + /// static difference between the target address and the address + /// of the relative offset. The target must be known to be defined + /// in the current linkage unit. The offset will have the given + /// integer type, which must be no wider than intptr_t. Some + /// targets may not fully support this operation. + void addRelativeOffset(llvm::IntegerType *type, llvm::Constant *target) { + add(getRelativeOffset(type, target)); + } + + /// Add a relative offset to the target address, plus a small + /// constant offset. This is primarily useful when the relative + /// offset is known to be a multiple of (say) four and therefore + /// the tag can be used to express an extra two bits of information. + void addTaggedRelativeOffset(llvm::IntegerType *type, + llvm::Constant *address, + unsigned tag) { + llvm::Constant *offset = getRelativeOffset(type, address); + if (tag) { + offset = llvm::ConstantExpr::getAdd(offset, + llvm::ConstantInt::get(type, tag)); + } + add(offset); + } + + /// Return the offset from the start of the initializer to the + /// next position, assuming no padding is required prior to it. + /// + /// This operation will not succeed if any unsized placeholders are + /// currently in place in the initializer. + CharUnits getNextOffsetFromGlobal() const { + assert(!Finished && "cannot add more values after finishing builder"); + assert(!Frozen && "cannot add values while subbuilder is active"); + return getOffsetFromGlobalTo(Builder.Buffer.size()); + } + + /// An opaque class to hold the abstract position of a placeholder. + class PlaceholderPosition { + size_t Index; + friend class ConstantAggregateBuilderBase; + PlaceholderPosition(size_t index) : Index(index) {} + }; + + /// Add a placeholder value to the structure. The returned position + /// can be used to set the value later; it will not be invalidated by + /// any intermediate operations except (1) filling the same position or + /// (2) finishing the entire builder. + /// + /// This is useful for emitting certain kinds of structure which + /// contain some sort of summary field, generally a count, before any + /// of the data. By emitting a placeholder first, the structure can + /// be emitted eagerly. + PlaceholderPosition addPlaceholder() { + assert(!Finished && "cannot add more values after finishing builder"); + assert(!Frozen && "cannot add values while subbuilder is active"); + Builder.Buffer.push_back(nullptr); + return Builder.Buffer.size() - 1; + } + + /// Add a placeholder, giving the expected type that will be filled in. + PlaceholderPosition addPlaceholderWithSize(llvm::Type *expectedType); + + /// Fill a previously-added placeholder. + void fillPlaceholderWithInt(PlaceholderPosition position, + llvm::IntegerType *type, uint64_t value, + bool isSigned = false) { + fillPlaceholder(position, llvm::ConstantInt::get(type, value, isSigned)); + } + + /// Fill a previously-added placeholder. + void fillPlaceholder(PlaceholderPosition position, llvm::Constant *value) { + assert(!Finished && "cannot change values after finishing builder"); + assert(!Frozen && "cannot add values while subbuilder is active"); + llvm::Constant *&slot = Builder.Buffer[position.Index]; + assert(slot == nullptr && "placeholder already filled"); + slot = value; + } + + /// Produce an address which will eventually point to the next + /// position to be filled. This is computed with an indexed + /// getelementptr rather than by computing offsets. + /// + /// The returned pointer will have type T*, where T is the given + /// position. + llvm::Constant *getAddrOfCurrentPosition(llvm::Type *type); + + llvm::ArrayRef<llvm::Constant*> getGEPIndicesToCurrentPosition( + llvm::SmallVectorImpl<llvm::Constant*> &indices) { + getGEPIndicesTo(indices, Builder.Buffer.size()); + return indices; + } + +protected: + llvm::Constant *finishArray(llvm::Type *eltTy); + llvm::Constant *finishStruct(llvm::StructType *structTy); + +private: + void getGEPIndicesTo(llvm::SmallVectorImpl<llvm::Constant*> &indices, + size_t position) const; + + llvm::Constant *getRelativeOffset(llvm::IntegerType *offsetType, + llvm::Constant *target); + + CharUnits getOffsetFromGlobalTo(size_t index) const; +}; + +template <class Impl, class Traits> +class ConstantAggregateBuilderTemplateBase + : public Traits::AggregateBuilderBase { + using super = typename Traits::AggregateBuilderBase; +public: + using InitBuilder = typename Traits::InitBuilder; + using ArrayBuilder = typename Traits::ArrayBuilder; + using StructBuilder = typename Traits::StructBuilder; + using AggregateBuilderBase = typename Traits::AggregateBuilderBase; + +protected: + ConstantAggregateBuilderTemplateBase(InitBuilder &builder, + AggregateBuilderBase *parent) + : super(builder, parent) {} + + Impl &asImpl() { return *static_cast<Impl*>(this); } + +public: + ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) { + return ArrayBuilder(static_cast<InitBuilder&>(this->Builder), this, eltTy); + } + + StructBuilder beginStruct(llvm::StructType *ty = nullptr) { + return StructBuilder(static_cast<InitBuilder&>(this->Builder), this, ty); + } + + /// Given that this builder was created by beginning an array or struct + /// component on the given parent builder, finish the array/struct + /// component and add it to the parent. + /// + /// It is an intentional choice that the parent is passed in explicitly + /// despite it being redundant with information already kept in the + /// builder. This aids in readability by making it easier to find the + /// places that add components to a builder, as well as "bookending" + /// the sub-builder more explicitly. + void finishAndAddTo(AggregateBuilderBase &parent) { + assert(this->Parent == &parent && "adding to non-parent builder"); + parent.add(asImpl().finishImpl()); + } + + /// Given that this builder was created by beginning an array or struct + /// directly on a ConstantInitBuilder, finish the array/struct and + /// create a global variable with it as the initializer. + template <class... As> + llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { + assert(!this->Parent && "finishing non-root builder"); + return this->Builder.createGlobal(asImpl().finishImpl(), + std::forward<As>(args)...); + } + + /// Given that this builder was created by beginning an array or struct + /// directly on a ConstantInitBuilder, finish the array/struct and + /// set it as the initializer of the given global variable. + void finishAndSetAsInitializer(llvm::GlobalVariable *global) { + assert(!this->Parent && "finishing non-root builder"); + return this->Builder.setGlobalInitializer(global, asImpl().finishImpl()); + } + + /// Given that this builder was created by beginning an array or struct + /// directly on a ConstantInitBuilder, finish the array/struct and + /// return a future which can be used to install the initializer in + /// a global later. + /// + /// This is useful for allowing a finished initializer to passed to + /// an API which will build the global. However, the "future" preserves + /// a dependency on the original builder; it is an error to pass it aside. + ConstantInitFuture finishAndCreateFuture() { + assert(!this->Parent && "finishing non-root builder"); + return this->Builder.createFuture(asImpl().finishImpl()); + } +}; + +template <class Traits> +class ConstantArrayBuilderTemplateBase + : public ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder, + Traits> { + using super = + ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder, Traits>; + +public: + using InitBuilder = typename Traits::InitBuilder; + using AggregateBuilderBase = typename Traits::AggregateBuilderBase; + +private: + llvm::Type *EltTy; + + template <class, class> + friend class ConstantAggregateBuilderTemplateBase; + +protected: + ConstantArrayBuilderTemplateBase(InitBuilder &builder, + AggregateBuilderBase *parent, + llvm::Type *eltTy) + : super(builder, parent), EltTy(eltTy) {} + +private: + /// Form an array constant from the values that have been added to this + /// builder. + llvm::Constant *finishImpl() { + return AggregateBuilderBase::finishArray(EltTy); + } +}; + +/// A template class designed to allow other frontends to +/// easily customize the builder classes used by ConstantInitBuilder, +/// and thus to extend the API to work with the abstractions they +/// prefer. This would probably not be necessary if C++ just +/// supported extension methods. +template <class Traits> +class ConstantStructBuilderTemplateBase + : public ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder, + Traits> { + using super = + ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder,Traits>; + +public: + using InitBuilder = typename Traits::InitBuilder; + using AggregateBuilderBase = typename Traits::AggregateBuilderBase; + +private: + llvm::StructType *StructTy; + + template <class, class> + friend class ConstantAggregateBuilderTemplateBase; + +protected: + ConstantStructBuilderTemplateBase(InitBuilder &builder, + AggregateBuilderBase *parent, + llvm::StructType *structTy) + : super(builder, parent), StructTy(structTy) { + if (structTy) this->Packed = structTy->isPacked(); + } + +public: + void setPacked(bool packed) { + this->Packed = packed; + } + + /// Use the given type for the struct if its element count is correct. + /// Don't add more elements after calling this. + void suggestType(llvm::StructType *structTy) { + if (this->size() == structTy->getNumElements()) { + StructTy = structTy; + } + } + +private: + /// Form an array constant from the values that have been added to this + /// builder. + llvm::Constant *finishImpl() { + return AggregateBuilderBase::finishStruct(StructTy); + } +}; + +/// A template class designed to allow other frontends to +/// easily customize the builder classes used by ConstantInitBuilder, +/// and thus to extend the API to work with the abstractions they +/// prefer. This would probably not be necessary if C++ just +/// supported extension methods. +template <class Traits> +class ConstantInitBuilderTemplateBase : public ConstantInitBuilderBase { +protected: + ConstantInitBuilderTemplateBase(CodeGenModule &CGM) + : ConstantInitBuilderBase(CGM) {} + +public: + using InitBuilder = typename Traits::InitBuilder; + using ArrayBuilder = typename Traits::ArrayBuilder; + using StructBuilder = typename Traits::StructBuilder; + + ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) { + return ArrayBuilder(static_cast<InitBuilder&>(*this), nullptr, eltTy); + } + + StructBuilder beginStruct(llvm::StructType *structTy = nullptr) { + return StructBuilder(static_cast<InitBuilder&>(*this), nullptr, structTy); + } +}; + +class ConstantInitBuilder; +class ConstantStructBuilder; +class ConstantArrayBuilder; + +struct ConstantInitBuilderTraits { + using InitBuilder = ConstantInitBuilder; + using AggregateBuilderBase = ConstantAggregateBuilderBase; + using ArrayBuilder = ConstantArrayBuilder; + using StructBuilder = ConstantStructBuilder; +}; + +/// The standard implementation of ConstantInitBuilder used in Clang. +class ConstantInitBuilder + : public ConstantInitBuilderTemplateBase<ConstantInitBuilderTraits> { +public: + explicit ConstantInitBuilder(CodeGenModule &CGM) : + ConstantInitBuilderTemplateBase(CGM) {} +}; + +/// A helper class of ConstantInitBuilder, used for building constant +/// array initializers. +class ConstantArrayBuilder + : public ConstantArrayBuilderTemplateBase<ConstantInitBuilderTraits> { + template <class Traits> + friend class ConstantInitBuilderTemplateBase; + + // The use of explicit qualification is a GCC workaround. + template <class Impl, class Traits> + friend class CodeGen::ConstantAggregateBuilderTemplateBase; + + ConstantArrayBuilder(ConstantInitBuilder &builder, + ConstantAggregateBuilderBase *parent, + llvm::Type *eltTy) + : ConstantArrayBuilderTemplateBase(builder, parent, eltTy) {} +}; + +/// A helper class of ConstantInitBuilder, used for building constant +/// struct initializers. +class ConstantStructBuilder + : public ConstantStructBuilderTemplateBase<ConstantInitBuilderTraits> { + template <class Traits> + friend class ConstantInitBuilderTemplateBase; + + // The use of explicit qualification is a GCC workaround. + template <class Impl, class Traits> + friend class CodeGen::ConstantAggregateBuilderTemplateBase; + + ConstantStructBuilder(ConstantInitBuilder &builder, + ConstantAggregateBuilderBase *parent, + llvm::StructType *structTy) + : ConstantStructBuilderTemplateBase(builder, parent, structTy) {} +}; + +} // end namespace CodeGen +} // end namespace clang + +#endif diff --git a/clang-r353983/include/clang/CodeGen/ConstantInitFuture.h b/clang-r353983/include/clang/CodeGen/ConstantInitFuture.h new file mode 100644 index 00000000..b08f5287 --- /dev/null +++ b/clang-r353983/include/clang/CodeGen/ConstantInitFuture.h @@ -0,0 +1,108 @@ +//===- ConstantInitFuture.h - "Future" constant initializers ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This class defines the ConstantInitFuture class. This is split out +// from ConstantInitBuilder.h in order to allow APIs to work with it +// without having to include that entire header. This is particularly +// important because it is often useful to be able to default-construct +// a future in, say, a default argument. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGEN_CONSTANTINITFUTURE_H +#define LLVM_CLANG_CODEGEN_CONSTANTINITFUTURE_H + +#include "llvm/ADT/PointerUnion.h" +#include "llvm/IR/Constant.h" + +// Forward-declare ConstantInitBuilderBase and give it a +// PointerLikeTypeTraits specialization so that we can safely use it +// in a PointerUnion below. +namespace clang { +namespace CodeGen { +class ConstantInitBuilderBase; +} +} +namespace llvm { +template <> +struct PointerLikeTypeTraits< ::clang::CodeGen::ConstantInitBuilderBase*> { + using T = ::clang::CodeGen::ConstantInitBuilderBase*; + + static inline void *getAsVoidPointer(T p) { return p; } + static inline T getFromVoidPointer(void *p) {return static_cast<T>(p);} + enum { NumLowBitsAvailable = 2 }; +}; +} + +namespace clang { +namespace CodeGen { + +/// A "future" for a completed constant initializer, which can be passed +/// around independently of any sub-builders (but not the original parent). +class ConstantInitFuture { + using PairTy = llvm::PointerUnion<ConstantInitBuilderBase*, llvm::Constant*>; + + PairTy Data; + + friend class ConstantInitBuilderBase; + explicit ConstantInitFuture(ConstantInitBuilderBase *builder); + +public: + ConstantInitFuture() {} + + /// A future can be explicitly created from a fixed initializer. + explicit ConstantInitFuture(llvm::Constant *initializer) : Data(initializer) { + assert(initializer && "creating null future"); + } + + /// Is this future non-null? + explicit operator bool() const { return bool(Data); } + + /// Return the type of the initializer. + llvm::Type *getType() const; + + /// Abandon this initializer. + void abandon(); + + /// Install the initializer into a global variable. This cannot + /// be called multiple times. + void installInGlobal(llvm::GlobalVariable *global); + + void *getOpaqueValue() const { return Data.getOpaqueValue(); } + static ConstantInitFuture getFromOpaqueValue(void *value) { + ConstantInitFuture result; + result.Data = PairTy::getFromOpaqueValue(value); + return result; + } + enum { + NumLowBitsAvailable = + llvm::PointerLikeTypeTraits<PairTy>::NumLowBitsAvailable + }; +}; + +} // end namespace CodeGen +} // end namespace clang + +namespace llvm { + +template <> +struct PointerLikeTypeTraits< ::clang::CodeGen::ConstantInitFuture> { + using T = ::clang::CodeGen::ConstantInitFuture; + + static inline void *getAsVoidPointer(T future) { + return future.getOpaqueValue(); + } + static inline T getFromVoidPointer(void *p) { + return T::getFromOpaqueValue(p); + } + enum { NumLowBitsAvailable = T::NumLowBitsAvailable }; +}; + +} // end namespace llvm + +#endif diff --git a/clang-r353983/include/clang/CodeGen/ModuleBuilder.h b/clang-r353983/include/clang/CodeGen/ModuleBuilder.h new file mode 100644 index 00000000..f9d056ed --- /dev/null +++ b/clang-r353983/include/clang/CodeGen/ModuleBuilder.h @@ -0,0 +1,105 @@ +//===--- CodeGen/ModuleBuilder.h - Build LLVM from ASTs ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the ModuleBuilder interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGEN_MODULEBUILDER_H +#define LLVM_CLANG_CODEGEN_MODULEBUILDER_H + +#include "clang/AST/ASTConsumer.h" + +namespace llvm { + class Constant; + class LLVMContext; + class Module; + class StringRef; +} + +namespace clang { + class CodeGenOptions; + class CoverageSourceInfo; + class Decl; + class DiagnosticsEngine; + class GlobalDecl; + class HeaderSearchOptions; + class LangOptions; + class PreprocessorOptions; + +namespace CodeGen { + class CodeGenModule; + class CGDebugInfo; +} + +/// The primary public interface to the Clang code generator. +/// +/// This is not really an abstract interface. +class CodeGenerator : public ASTConsumer { + virtual void anchor(); + +public: + /// Return an opaque reference to the CodeGenModule object, which can + /// be used in various secondary APIs. It is valid as long as the + /// CodeGenerator exists. + CodeGen::CodeGenModule &CGM(); + + /// Return the module that this code generator is building into. + /// + /// This may return null after HandleTranslationUnit is called; + /// this signifies that there was an error generating code. A + /// diagnostic will have been generated in this case, and the module + /// will be deleted. + /// + /// It will also return null if the module is released. + llvm::Module *GetModule(); + + /// Release ownership of the module to the caller. + /// + /// It is illegal to call methods other than GetModule on the + /// CodeGenerator after releasing its module. + llvm::Module *ReleaseModule(); + + /// Return debug info code generator. + CodeGen::CGDebugInfo *getCGDebugInfo(); + + /// Given a mangled name, return a declaration which mangles that way + /// which has been added to this code generator via a Handle method. + /// + /// This may return null if there was no matching declaration. + const Decl *GetDeclForMangledName(llvm::StringRef MangledName); + + /// Return the LLVM address of the given global entity. + /// + /// \param isForDefinition If true, the caller intends to define the + /// entity; the object returned will be an llvm::GlobalValue of + /// some sort. If false, the caller just intends to use the entity; + /// the object returned may be any sort of constant value, and the + /// code generator will schedule the entity for emission if a + /// definition has been registered with this code generator. + llvm::Constant *GetAddrOfGlobal(GlobalDecl decl, bool isForDefinition); + + /// Create a new \c llvm::Module after calling HandleTranslationUnit. This + /// enable codegen in interactive processing environments. + llvm::Module* StartModule(llvm::StringRef ModuleName, llvm::LLVMContext &C); +}; + +/// CreateLLVMCodeGen - Create a CodeGenerator instance. +/// It is the responsibility of the caller to call delete on +/// the allocated CodeGenerator instance. +CodeGenerator *CreateLLVMCodeGen(DiagnosticsEngine &Diags, + llvm::StringRef ModuleName, + const HeaderSearchOptions &HeaderSearchOpts, + const PreprocessorOptions &PreprocessorOpts, + const CodeGenOptions &CGO, + llvm::LLVMContext& C, + CoverageSourceInfo *CoverageInfo = nullptr); + +} // end namespace clang + +#endif diff --git a/clang-r353983/include/clang/CodeGen/ObjectFilePCHContainerOperations.h b/clang-r353983/include/clang/CodeGen/ObjectFilePCHContainerOperations.h new file mode 100644 index 00000000..8821cd70 --- /dev/null +++ b/clang-r353983/include/clang/CodeGen/ObjectFilePCHContainerOperations.h @@ -0,0 +1,42 @@ +//===-- CodeGen/ObjectFilePCHContainerOperations.h - ------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGEN_OBJECT_FILE_PCH_CONTAINER_OPERATIONS_H +#define LLVM_CLANG_CODEGEN_OBJECT_FILE_PCH_CONTAINER_OPERATIONS_H + +#include "clang/Frontend/PCHContainerOperations.h" + +namespace clang { + +/// A PCHContainerWriter implementation that uses LLVM to +/// wraps Clang modules inside a COFF, ELF, or Mach-O container. +class ObjectFilePCHContainerWriter : public PCHContainerWriter { + StringRef getFormat() const override { return "obj"; } + + /// Return an ASTConsumer that can be chained with a + /// PCHGenerator that produces a wrapper file format + /// that also contains full debug info for the module. + std::unique_ptr<ASTConsumer> + CreatePCHContainerGenerator(CompilerInstance &CI, + const std::string &MainFileName, + const std::string &OutputFileName, + std::unique_ptr<llvm::raw_pwrite_stream> OS, + std::shared_ptr<PCHBuffer> Buffer) const override; +}; + +/// A PCHContainerReader implementation that uses LLVM to +/// wraps Clang modules inside a COFF, ELF, or Mach-O container. +class ObjectFilePCHContainerReader : public PCHContainerReader { + StringRef getFormat() const override { return "obj"; } + + /// Returns the serialized AST inside the PCH container Buffer. + StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const override; +}; +} + +#endif diff --git a/clang-r353983/include/clang/CodeGen/SwiftCallingConv.h b/clang-r353983/include/clang/CodeGen/SwiftCallingConv.h new file mode 100644 index 00000000..2c5e9a6d --- /dev/null +++ b/clang-r353983/include/clang/CodeGen/SwiftCallingConv.h @@ -0,0 +1,184 @@ +//==-- SwiftCallingConv.h - Swift ABI lowering ------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Defines constants and types related to Swift ABI lowering. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGEN_SWIFTCALLINGCONV_H +#define LLVM_CLANG_CODEGEN_SWIFTCALLINGCONV_H + +#include "clang/AST/CanonicalType.h" +#include "clang/AST/CharUnits.h" +#include "clang/AST/Type.h" +#include "llvm/Support/TrailingObjects.h" +#include <cassert> + +namespace llvm { + class IntegerType; + class Type; + class StructType; + class VectorType; +} + +namespace clang { +class Decl; +class FieldDecl; +class ASTRecordLayout; + +namespace CodeGen { +class ABIArgInfo; +class CodeGenModule; +class CGFunctionInfo; + +namespace swiftcall { + +class SwiftAggLowering { + CodeGenModule &CGM; + + struct StorageEntry { + CharUnits Begin; + CharUnits End; + llvm::Type *Type; + + CharUnits getWidth() const { + return End - Begin; + } + }; + SmallVector<StorageEntry, 4> Entries; + bool Finished = false; + +public: + SwiftAggLowering(CodeGenModule &CGM) : CGM(CGM) {} + + void addOpaqueData(CharUnits begin, CharUnits end) { + addEntry(nullptr, begin, end); + } + + void addTypedData(QualType type, CharUnits begin); + void addTypedData(const RecordDecl *record, CharUnits begin); + void addTypedData(const RecordDecl *record, CharUnits begin, + const ASTRecordLayout &layout); + void addTypedData(llvm::Type *type, CharUnits begin); + void addTypedData(llvm::Type *type, CharUnits begin, CharUnits end); + + void finish(); + + /// Does this lowering require passing any data? + bool empty() const { + assert(Finished && "didn't finish lowering before calling empty()"); + return Entries.empty(); + } + + /// According to the target Swift ABI, should a value with this lowering + /// be passed indirectly? + /// + /// Note that this decision is based purely on the data layout of the + /// value and does not consider whether the type is address-only, + /// must be passed indirectly to match a function abstraction pattern, or + /// anything else that is expected to be handled by high-level lowering. + /// + /// \param asReturnValue - if true, answer whether it should be passed + /// indirectly as a return value; if false, answer whether it should be + /// passed indirectly as an argument + bool shouldPassIndirectly(bool asReturnValue) const; + + using EnumerationCallback = + llvm::function_ref<void(CharUnits offset, CharUnits end, llvm::Type *type)>; + + /// Enumerate the expanded components of this type. + /// + /// The component types will always be legal vector, floating-point, + /// integer, or pointer types. + void enumerateComponents(EnumerationCallback callback) const; + + /// Return the types for a coerce-and-expand operation. + /// + /// The first type matches the memory layout of the data that's been + /// added to this structure, including explicit [N x i8] arrays for any + /// internal padding. + /// + /// The second type removes any internal padding members and, if only + /// one element remains, is simply that element type. + std::pair<llvm::StructType*, llvm::Type*> getCoerceAndExpandTypes() const; + +private: + void addBitFieldData(const FieldDecl *field, CharUnits begin, + uint64_t bitOffset); + void addLegalTypedData(llvm::Type *type, CharUnits begin, CharUnits end); + void addEntry(llvm::Type *type, CharUnits begin, CharUnits end); + void splitVectorEntry(unsigned index); + static bool shouldMergeEntries(const StorageEntry &first, + const StorageEntry &second, + CharUnits chunkSize); +}; + +/// Should an aggregate which expands to the given type sequence +/// be passed/returned indirectly under swiftcall? +bool shouldPassIndirectly(CodeGenModule &CGM, + ArrayRef<llvm::Type*> types, + bool asReturnValue); + +/// Return the maximum voluntary integer size for the current target. +CharUnits getMaximumVoluntaryIntegerSize(CodeGenModule &CGM); + +/// Return the Swift CC's notion of the natural alignment of a type. +CharUnits getNaturalAlignment(CodeGenModule &CGM, llvm::Type *type); + +/// Is the given integer type "legal" for Swift's perspective on the +/// current platform? +bool isLegalIntegerType(CodeGenModule &CGM, llvm::IntegerType *type); + +/// Is the given vector type "legal" for Swift's perspective on the +/// current platform? +bool isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize, + llvm::VectorType *vectorTy); +bool isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize, + llvm::Type *eltTy, unsigned numElts); + +/// Minimally split a legal vector type. +std::pair<llvm::Type*, unsigned> +splitLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize, + llvm::VectorType *vectorTy); + +/// Turn a vector type in a sequence of legal component vector types. +/// +/// The caller may assume that the sum of the data sizes of the resulting +/// types will equal the data size of the vector type. +void legalizeVectorType(CodeGenModule &CGM, CharUnits vectorSize, + llvm::VectorType *vectorTy, + llvm::SmallVectorImpl<llvm::Type*> &types); + +/// Is the given record type required to be passed and returned indirectly +/// because of language restrictions? +/// +/// This considers *only* mandatory indirectness due to language restrictions, +/// such as C++'s non-trivially-copyable types and Objective-C's __weak +/// references. A record for which this returns true may still be passed +/// indirectly for other reasons, such as being too large to fit in a +/// reasonable number of registers. +bool mustPassRecordIndirectly(CodeGenModule &CGM, const RecordDecl *record); + +/// Classify the rules for how to return a particular type. +ABIArgInfo classifyReturnType(CodeGenModule &CGM, CanQualType type); + +/// Classify the rules for how to pass a particular type. +ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type); + +/// Compute the ABI information of a swiftcall function. This is a +/// private interface for Clang. +void computeABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI); + +/// Is swifterror lowered to a register by the target ABI? +bool isSwiftErrorLoweredInRegister(CodeGenModule &CGM); + +} // end namespace swiftcall +} // end namespace CodeGen +} // end namespace clang + +#endif |
