diff options
| author | 2020-08-03 15:06:44 +0000 | |
|---|---|---|
| committer | 2020-08-03 15:06:44 +0000 | |
| commit | b64793999546ed8adebaeebd9d8345d18db8927d (patch) | |
| tree | 4357c27b561d73b0e089727c6ed659f2ceff5f47 /gnu/llvm/tools/clang/lib/CodeGen | |
| parent | Add support for UTF-8 DISPLAY-HINTs with octet length. For now only (diff) | |
| download | wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.tar.xz wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.zip | |
Remove LLVM 8.0.1 files.
Diffstat (limited to 'gnu/llvm/tools/clang/lib/CodeGen')
87 files changed, 0 insertions, 148271 deletions
diff --git a/gnu/llvm/tools/clang/lib/CodeGen/ABIInfo.h b/gnu/llvm/tools/clang/lib/CodeGen/ABIInfo.h deleted file mode 100644 index feed3833f24..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/ABIInfo.h +++ /dev/null @@ -1,146 +0,0 @@ -//===----- ABIInfo.h - ABI information access & encapsulation ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_ABIINFO_H -#define LLVM_CLANG_LIB_CODEGEN_ABIINFO_H - -#include "clang/AST/CharUnits.h" -#include "clang/AST/Type.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/IR/Type.h" - -namespace llvm { - class Value; - class LLVMContext; - class DataLayout; - class Type; -} - -namespace clang { - class ASTContext; - class CodeGenOptions; - class TargetInfo; - -namespace CodeGen { - class ABIArgInfo; - class Address; - class CGCXXABI; - class CGFunctionInfo; - class CodeGenFunction; - class CodeGenTypes; - class SwiftABIInfo; - -namespace swiftcall { - class SwiftAggLowering; -} - - // FIXME: All of this stuff should be part of the target interface - // somehow. It is currently here because it is not clear how to factor - // the targets to support this, since the Targets currently live in a - // layer below types n'stuff. - - - /// ABIInfo - Target specific hooks for defining how a type should be - /// passed or returned from functions. - class ABIInfo { - public: - CodeGen::CodeGenTypes &CGT; - protected: - llvm::CallingConv::ID RuntimeCC; - public: - ABIInfo(CodeGen::CodeGenTypes &cgt) - : CGT(cgt), RuntimeCC(llvm::CallingConv::C) {} - - virtual ~ABIInfo(); - - virtual bool supportsSwift() const { return false; } - - CodeGen::CGCXXABI &getCXXABI() const; - ASTContext &getContext() const; - llvm::LLVMContext &getVMContext() const; - const llvm::DataLayout &getDataLayout() const; - const TargetInfo &getTarget() const; - const CodeGenOptions &getCodeGenOpts() const; - - /// Return the calling convention to use for system runtime - /// functions. - llvm::CallingConv::ID getRuntimeCC() const { - return RuntimeCC; - } - - virtual void computeInfo(CodeGen::CGFunctionInfo &FI) const = 0; - - /// EmitVAArg - Emit the target dependent code to load a value of - /// \arg Ty from the va_list pointed to by \arg VAListAddr. - - // FIXME: This is a gaping layering violation if we wanted to drop - // the ABI information any lower than CodeGen. Of course, for - // VAArg handling it has to be at this level; there is no way to - // abstract this out. - virtual CodeGen::Address EmitVAArg(CodeGen::CodeGenFunction &CGF, - CodeGen::Address VAListAddr, - QualType Ty) const = 0; - - bool isAndroid() const; - - /// Emit the target dependent code to load a value of - /// \arg Ty from the \c __builtin_ms_va_list pointed to by \arg VAListAddr. - virtual CodeGen::Address EmitMSVAArg(CodeGen::CodeGenFunction &CGF, - CodeGen::Address VAListAddr, - QualType Ty) const; - - virtual bool isHomogeneousAggregateBaseType(QualType Ty) const; - - virtual bool isHomogeneousAggregateSmallEnough(const Type *Base, - uint64_t Members) const; - - bool isHomogeneousAggregate(QualType Ty, const Type *&Base, - uint64_t &Members) const; - - /// A convenience method to return an indirect ABIArgInfo with an - /// expected alignment equal to the ABI alignment of the given type. - CodeGen::ABIArgInfo - getNaturalAlignIndirect(QualType Ty, bool ByRef = true, - bool Realign = false, - llvm::Type *Padding = nullptr) const; - - CodeGen::ABIArgInfo - getNaturalAlignIndirectInReg(QualType Ty, bool Realign = false) const; - - - }; - - /// A refining implementation of ABIInfo for targets that support swiftcall. - /// - /// If we find ourselves wanting multiple such refinements, they'll probably - /// be independent refinements, and we should probably find another way - /// to do it than simple inheritance. - class SwiftABIInfo : public ABIInfo { - public: - SwiftABIInfo(CodeGen::CodeGenTypes &cgt) : ABIInfo(cgt) {} - - bool supportsSwift() const final override { return true; } - - virtual bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> types, - bool asReturnValue) const = 0; - - virtual bool isLegalVectorTypeForSwift(CharUnits totalSize, - llvm::Type *eltTy, - unsigned elts) const; - - virtual bool isSwiftErrorInRegister() const = 0; - - static bool classof(const ABIInfo *info) { - return info->supportsSwift(); - } - }; -} // end namespace CodeGen -} // end namespace clang - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/Address.h b/gnu/llvm/tools/clang/lib/CodeGen/Address.h deleted file mode 100644 index 334308081ff..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/Address.h +++ /dev/null @@ -1,118 +0,0 @@ -//===-- Address.h - An aligned address -------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This class provides a simple wrapper for a pair of a pointer and an -// alignment. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_ADDRESS_H -#define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H - -#include "llvm/IR/Constants.h" -#include "clang/AST/CharUnits.h" - -namespace clang { -namespace CodeGen { - -/// An aligned address. -class Address { - llvm::Value *Pointer; - CharUnits Alignment; -public: - Address(llvm::Value *pointer, CharUnits alignment) - : Pointer(pointer), Alignment(alignment) { - assert((!alignment.isZero() || pointer == nullptr) && - "creating valid address with invalid alignment"); - } - - static Address invalid() { return Address(nullptr, CharUnits()); } - bool isValid() const { return Pointer != nullptr; } - - llvm::Value *getPointer() const { - assert(isValid()); - return Pointer; - } - - /// Return the type of the pointer value. - llvm::PointerType *getType() const { - return llvm::cast<llvm::PointerType>(getPointer()->getType()); - } - - /// Return the type of the values stored in this address. - /// - /// When IR pointer types lose their element type, we should simply - /// store it in Address instead for the convenience of writing code. - llvm::Type *getElementType() const { - return getType()->getElementType(); - } - - /// 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 getPointer()->getName(); - } - - /// Return the alignment of this pointer. - CharUnits getAlignment() const { - assert(isValid()); - return Alignment; - } -}; - -/// A specialization of Address that requires the address to be an -/// LLVM Constant. -class ConstantAddress : public Address { -public: - ConstantAddress(llvm::Constant *pointer, CharUnits alignment) - : Address(pointer, alignment) {} - - static ConstantAddress invalid() { - return ConstantAddress(nullptr, CharUnits()); - } - - llvm::Constant *getPointer() const { - return llvm::cast<llvm::Constant>(Address::getPointer()); - } - - ConstantAddress getBitCast(llvm::Type *ty) const { - return ConstantAddress(llvm::ConstantExpr::getBitCast(getPointer(), ty), - getAlignment()); - } - - ConstantAddress getElementBitCast(llvm::Type *ty) const { - return getBitCast(ty->getPointerTo(getAddressSpace())); - } - - static bool isaImpl(Address addr) { - return llvm::isa<llvm::Constant>(addr.getPointer()); - } - static ConstantAddress castImpl(Address addr) { - return ConstantAddress(llvm::cast<llvm::Constant>(addr.getPointer()), - addr.getAlignment()); - } -}; - -} - -// Present a minimal LLVM-like casting interface. -template <class U> inline U cast(CodeGen::Address addr) { - return U::castImpl(addr); -} -template <class U> inline bool isa(CodeGen::Address addr) { - return U::isaImpl(addr); -} - -} - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp b/gnu/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp deleted file mode 100644 index b927acabac5..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp +++ /dev/null @@ -1,1452 +0,0 @@ -//===--- BackendUtil.cpp - LLVM Backend Utilities -------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "clang/CodeGen/BackendUtil.h" -#include "clang/Basic/CodeGenOptions.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/TargetOptions.h" -#include "clang/Frontend/FrontendDiagnostic.h" -#include "clang/Frontend/Utils.h" -#include "clang/Lex/HeaderSearchOptions.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/Triple.h" -#include "llvm/Analysis/TargetLibraryInfo.h" -#include "llvm/Analysis/TargetTransformInfo.h" -#include "llvm/Bitcode/BitcodeReader.h" -#include "llvm/Bitcode/BitcodeWriter.h" -#include "llvm/Bitcode/BitcodeWriterPass.h" -#include "llvm/CodeGen/RegAllocRegistry.h" -#include "llvm/CodeGen/SchedulerRegistry.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/IRPrintingPasses.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/ModuleSummaryIndex.h" -#include "llvm/IR/Verifier.h" -#include "llvm/LTO/LTOBackend.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/SubtargetFeature.h" -#include "llvm/Passes/PassBuilder.h" -#include "llvm/Support/BuryPointer.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/Timer.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Transforms/Coroutines.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/IPO/AlwaysInliner.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" -#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" -#include "llvm/Transforms/InstCombine/InstCombine.h" -#include "llvm/Transforms/Instrumentation.h" -#include "llvm/Transforms/Instrumentation/BoundsChecking.h" -#include "llvm/Transforms/Instrumentation/GCOVProfiler.h" -#include "llvm/Transforms/Instrumentation/MemorySanitizer.h" -#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" -#include "llvm/Transforms/ObjCARC.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Scalar/GVN.h" -#include "llvm/Transforms/Utils.h" -#include "llvm/Transforms/Utils/CanonicalizeAliases.h" -#include "llvm/Transforms/Utils/NameAnonGlobals.h" -#include "llvm/Transforms/Utils/SymbolRewriter.h" -#include <memory> -using namespace clang; -using namespace llvm; - -namespace { - -// Default filename used for profile generation. -static constexpr StringLiteral DefaultProfileGenName = "default_%m.profraw"; - -class EmitAssemblyHelper { - DiagnosticsEngine &Diags; - const HeaderSearchOptions &HSOpts; - const CodeGenOptions &CodeGenOpts; - const clang::TargetOptions &TargetOpts; - const LangOptions &LangOpts; - Module *TheModule; - - Timer CodeGenerationTime; - - std::unique_ptr<raw_pwrite_stream> OS; - - TargetIRAnalysis getTargetIRAnalysis() const { - if (TM) - return TM->getTargetIRAnalysis(); - - return TargetIRAnalysis(); - } - - void CreatePasses(legacy::PassManager &MPM, legacy::FunctionPassManager &FPM); - - /// Generates the TargetMachine. - /// Leaves TM unchanged if it is unable to create the target machine. - /// Some of our clang tests specify triples which are not built - /// into clang. This is okay because these tests check the generated - /// IR, and they require DataLayout which depends on the triple. - /// In this case, we allow this method to fail and not report an error. - /// When MustCreateTM is used, we print an error if we are unable to load - /// the requested target. - void CreateTargetMachine(bool MustCreateTM); - - /// Add passes necessary to emit assembly or LLVM IR. - /// - /// \return True on success. - bool AddEmitPasses(legacy::PassManager &CodeGenPasses, BackendAction Action, - raw_pwrite_stream &OS, raw_pwrite_stream *DwoOS); - - std::unique_ptr<llvm::ToolOutputFile> openOutputFile(StringRef Path) { - std::error_code EC; - auto F = llvm::make_unique<llvm::ToolOutputFile>(Path, EC, - llvm::sys::fs::F_None); - if (EC) { - Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message(); - F.reset(); - } - return F; - } - -public: - EmitAssemblyHelper(DiagnosticsEngine &_Diags, - const HeaderSearchOptions &HeaderSearchOpts, - const CodeGenOptions &CGOpts, - const clang::TargetOptions &TOpts, - const LangOptions &LOpts, Module *M) - : Diags(_Diags), HSOpts(HeaderSearchOpts), CodeGenOpts(CGOpts), - TargetOpts(TOpts), LangOpts(LOpts), TheModule(M), - CodeGenerationTime("codegen", "Code Generation Time") {} - - ~EmitAssemblyHelper() { - if (CodeGenOpts.DisableFree) - BuryPointer(std::move(TM)); - } - - std::unique_ptr<TargetMachine> TM; - - void EmitAssembly(BackendAction Action, - std::unique_ptr<raw_pwrite_stream> OS); - - void EmitAssemblyWithNewPassManager(BackendAction Action, - std::unique_ptr<raw_pwrite_stream> OS); -}; - -// We need this wrapper to access LangOpts and CGOpts from extension functions -// that we add to the PassManagerBuilder. -class PassManagerBuilderWrapper : public PassManagerBuilder { -public: - PassManagerBuilderWrapper(const Triple &TargetTriple, - const CodeGenOptions &CGOpts, - const LangOptions &LangOpts) - : PassManagerBuilder(), TargetTriple(TargetTriple), CGOpts(CGOpts), - LangOpts(LangOpts) {} - const Triple &getTargetTriple() const { return TargetTriple; } - const CodeGenOptions &getCGOpts() const { return CGOpts; } - const LangOptions &getLangOpts() const { return LangOpts; } - -private: - const Triple &TargetTriple; - const CodeGenOptions &CGOpts; - const LangOptions &LangOpts; -}; -} - -static void addObjCARCAPElimPass(const PassManagerBuilder &Builder, PassManagerBase &PM) { - if (Builder.OptLevel > 0) - PM.add(createObjCARCAPElimPass()); -} - -static void addObjCARCExpandPass(const PassManagerBuilder &Builder, PassManagerBase &PM) { - if (Builder.OptLevel > 0) - PM.add(createObjCARCExpandPass()); -} - -static void addObjCARCOptPass(const PassManagerBuilder &Builder, PassManagerBase &PM) { - if (Builder.OptLevel > 0) - PM.add(createObjCARCOptPass()); -} - -static void addAddDiscriminatorsPass(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { - PM.add(createAddDiscriminatorsPass()); -} - -static void addBoundsCheckingPass(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { - PM.add(createBoundsCheckingLegacyPass()); -} - -static void addSanitizerCoveragePass(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { - const PassManagerBuilderWrapper &BuilderWrapper = - static_cast<const PassManagerBuilderWrapper&>(Builder); - const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); - SanitizerCoverageOptions Opts; - Opts.CoverageType = - static_cast<SanitizerCoverageOptions::Type>(CGOpts.SanitizeCoverageType); - Opts.IndirectCalls = CGOpts.SanitizeCoverageIndirectCalls; - Opts.TraceBB = CGOpts.SanitizeCoverageTraceBB; - Opts.TraceCmp = CGOpts.SanitizeCoverageTraceCmp; - Opts.TraceDiv = CGOpts.SanitizeCoverageTraceDiv; - Opts.TraceGep = CGOpts.SanitizeCoverageTraceGep; - Opts.Use8bitCounters = CGOpts.SanitizeCoverage8bitCounters; - Opts.TracePC = CGOpts.SanitizeCoverageTracePC; - Opts.TracePCGuard = CGOpts.SanitizeCoverageTracePCGuard; - Opts.NoPrune = CGOpts.SanitizeCoverageNoPrune; - Opts.Inline8bitCounters = CGOpts.SanitizeCoverageInline8bitCounters; - Opts.PCTable = CGOpts.SanitizeCoveragePCTable; - Opts.StackDepth = CGOpts.SanitizeCoverageStackDepth; - PM.add(createSanitizerCoverageModulePass(Opts)); -} - -// Check if ASan should use GC-friendly instrumentation for globals. -// First of all, there is no point if -fdata-sections is off (expect for MachO, -// where this is not a factor). Also, on ELF this feature requires an assembler -// extension that only works with -integrated-as at the moment. -static bool asanUseGlobalsGC(const Triple &T, const CodeGenOptions &CGOpts) { - if (!CGOpts.SanitizeAddressGlobalsDeadStripping) - return false; - switch (T.getObjectFormat()) { - case Triple::MachO: - case Triple::COFF: - return true; - case Triple::ELF: - return CGOpts.DataSections && !CGOpts.DisableIntegratedAS; - default: - return false; - } -} - -static void addAddressSanitizerPasses(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { - const PassManagerBuilderWrapper &BuilderWrapper = - static_cast<const PassManagerBuilderWrapper&>(Builder); - const Triple &T = BuilderWrapper.getTargetTriple(); - const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); - bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::Address); - bool UseAfterScope = CGOpts.SanitizeAddressUseAfterScope; - bool UseOdrIndicator = CGOpts.SanitizeAddressUseOdrIndicator; - bool UseGlobalsGC = asanUseGlobalsGC(T, CGOpts); - PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/ false, Recover, - UseAfterScope)); - PM.add(createAddressSanitizerModulePass(/*CompileKernel*/ false, Recover, - UseGlobalsGC, UseOdrIndicator)); -} - -static void addKernelAddressSanitizerPasses(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { - PM.add(createAddressSanitizerFunctionPass( - /*CompileKernel*/ true, /*Recover*/ true, /*UseAfterScope*/ false)); - PM.add(createAddressSanitizerModulePass( - /*CompileKernel*/ true, /*Recover*/ true, /*UseGlobalsGC*/ true, - /*UseOdrIndicator*/ false)); -} - -static void addHWAddressSanitizerPasses(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { - const PassManagerBuilderWrapper &BuilderWrapper = - static_cast<const PassManagerBuilderWrapper &>(Builder); - const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); - bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::HWAddress); - PM.add(createHWAddressSanitizerPass(/*CompileKernel*/ false, Recover)); -} - -static void addKernelHWAddressSanitizerPasses(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { - PM.add(createHWAddressSanitizerPass( - /*CompileKernel*/ true, /*Recover*/ true)); -} - -static void addGeneralOptsForMemorySanitizer(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM, - bool CompileKernel) { - const PassManagerBuilderWrapper &BuilderWrapper = - static_cast<const PassManagerBuilderWrapper&>(Builder); - const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); - int TrackOrigins = CGOpts.SanitizeMemoryTrackOrigins; - bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::Memory); - PM.add(createMemorySanitizerLegacyPassPass(TrackOrigins, Recover, CompileKernel)); - - // MemorySanitizer inserts complex instrumentation that mostly follows - // the logic of the original code, but operates on "shadow" values. - // It can benefit from re-running some general purpose optimization passes. - if (Builder.OptLevel > 0) { - PM.add(createEarlyCSEPass()); - PM.add(createReassociatePass()); - PM.add(createLICMPass()); - PM.add(createGVNPass()); - PM.add(createInstructionCombiningPass()); - PM.add(createDeadStoreEliminationPass()); - } -} - -static void addMemorySanitizerPass(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { - addGeneralOptsForMemorySanitizer(Builder, PM, /*CompileKernel*/ false); -} - -static void addKernelMemorySanitizerPass(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { - addGeneralOptsForMemorySanitizer(Builder, PM, /*CompileKernel*/ true); -} - -static void addThreadSanitizerPass(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { - PM.add(createThreadSanitizerLegacyPassPass()); -} - -static void addDataFlowSanitizerPass(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { - const PassManagerBuilderWrapper &BuilderWrapper = - static_cast<const PassManagerBuilderWrapper&>(Builder); - const LangOptions &LangOpts = BuilderWrapper.getLangOpts(); - PM.add(createDataFlowSanitizerPass(LangOpts.SanitizerBlacklistFiles)); -} - -static void addEfficiencySanitizerPass(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { - const PassManagerBuilderWrapper &BuilderWrapper = - static_cast<const PassManagerBuilderWrapper&>(Builder); - const LangOptions &LangOpts = BuilderWrapper.getLangOpts(); - EfficiencySanitizerOptions Opts; - if (LangOpts.Sanitize.has(SanitizerKind::EfficiencyCacheFrag)) - Opts.ToolType = EfficiencySanitizerOptions::ESAN_CacheFrag; - else if (LangOpts.Sanitize.has(SanitizerKind::EfficiencyWorkingSet)) - Opts.ToolType = EfficiencySanitizerOptions::ESAN_WorkingSet; - PM.add(createEfficiencySanitizerPass(Opts)); -} - -static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple, - const CodeGenOptions &CodeGenOpts) { - TargetLibraryInfoImpl *TLII = new TargetLibraryInfoImpl(TargetTriple); - if (!CodeGenOpts.SimplifyLibCalls) - TLII->disableAllFunctions(); - else { - // Disable individual libc/libm calls in TargetLibraryInfo. - LibFunc F; - for (auto &FuncName : CodeGenOpts.getNoBuiltinFuncs()) - if (TLII->getLibFunc(FuncName, F)) - TLII->setUnavailable(F); - } - - switch (CodeGenOpts.getVecLib()) { - case CodeGenOptions::Accelerate: - TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::Accelerate); - break; - case CodeGenOptions::SVML: - TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::SVML); - break; - default: - break; - } - return TLII; -} - -static void addSymbolRewriterPass(const CodeGenOptions &Opts, - legacy::PassManager *MPM) { - llvm::SymbolRewriter::RewriteDescriptorList DL; - - llvm::SymbolRewriter::RewriteMapParser MapParser; - for (const auto &MapFile : Opts.RewriteMapFiles) - MapParser.parse(MapFile, &DL); - - MPM->add(createRewriteSymbolsPass(DL)); -} - -static CodeGenOpt::Level getCGOptLevel(const CodeGenOptions &CodeGenOpts) { - switch (CodeGenOpts.OptimizationLevel) { - default: - llvm_unreachable("Invalid optimization level!"); - case 0: - return CodeGenOpt::None; - case 1: - return CodeGenOpt::Less; - case 2: - return CodeGenOpt::Default; // O2/Os/Oz - case 3: - return CodeGenOpt::Aggressive; - } -} - -static Optional<llvm::CodeModel::Model> -getCodeModel(const CodeGenOptions &CodeGenOpts) { - unsigned CodeModel = llvm::StringSwitch<unsigned>(CodeGenOpts.CodeModel) - .Case("tiny", llvm::CodeModel::Tiny) - .Case("small", llvm::CodeModel::Small) - .Case("kernel", llvm::CodeModel::Kernel) - .Case("medium", llvm::CodeModel::Medium) - .Case("large", llvm::CodeModel::Large) - .Case("default", ~1u) - .Default(~0u); - assert(CodeModel != ~0u && "invalid code model!"); - if (CodeModel == ~1u) - return None; - return static_cast<llvm::CodeModel::Model>(CodeModel); -} - -static TargetMachine::CodeGenFileType getCodeGenFileType(BackendAction Action) { - if (Action == Backend_EmitObj) - return TargetMachine::CGFT_ObjectFile; - else if (Action == Backend_EmitMCNull) - return TargetMachine::CGFT_Null; - else { - assert(Action == Backend_EmitAssembly && "Invalid action!"); - return TargetMachine::CGFT_AssemblyFile; - } -} - -static void initTargetOptions(llvm::TargetOptions &Options, - const CodeGenOptions &CodeGenOpts, - const clang::TargetOptions &TargetOpts, - const LangOptions &LangOpts, - const HeaderSearchOptions &HSOpts) { - Options.ThreadModel = - llvm::StringSwitch<llvm::ThreadModel::Model>(CodeGenOpts.ThreadModel) - .Case("posix", llvm::ThreadModel::POSIX) - .Case("single", llvm::ThreadModel::Single); - - // Set float ABI type. - assert((CodeGenOpts.FloatABI == "soft" || CodeGenOpts.FloatABI == "softfp" || - CodeGenOpts.FloatABI == "hard" || CodeGenOpts.FloatABI.empty()) && - "Invalid Floating Point ABI!"); - Options.FloatABIType = - llvm::StringSwitch<llvm::FloatABI::ABIType>(CodeGenOpts.FloatABI) - .Case("soft", llvm::FloatABI::Soft) - .Case("softfp", llvm::FloatABI::Soft) - .Case("hard", llvm::FloatABI::Hard) - .Default(llvm::FloatABI::Default); - - // Set FP fusion mode. - switch (LangOpts.getDefaultFPContractMode()) { - case LangOptions::FPC_Off: - // Preserve any contraction performed by the front-end. (Strict performs - // splitting of the muladd intrinsic in the backend.) - Options.AllowFPOpFusion = llvm::FPOpFusion::Standard; - break; - case LangOptions::FPC_On: - Options.AllowFPOpFusion = llvm::FPOpFusion::Standard; - break; - case LangOptions::FPC_Fast: - Options.AllowFPOpFusion = llvm::FPOpFusion::Fast; - break; - } - - Options.UseInitArray = CodeGenOpts.UseInitArray; - Options.DisableIntegratedAS = CodeGenOpts.DisableIntegratedAS; - Options.CompressDebugSections = CodeGenOpts.getCompressDebugSections(); - Options.RelaxELFRelocations = CodeGenOpts.RelaxELFRelocations; - - // Set EABI version. - Options.EABIVersion = TargetOpts.EABIVersion; - - if (LangOpts.SjLjExceptions) - Options.ExceptionModel = llvm::ExceptionHandling::SjLj; - if (LangOpts.SEHExceptions) - Options.ExceptionModel = llvm::ExceptionHandling::WinEH; - if (LangOpts.DWARFExceptions) - Options.ExceptionModel = llvm::ExceptionHandling::DwarfCFI; - - Options.NoInfsFPMath = CodeGenOpts.NoInfsFPMath; - Options.NoNaNsFPMath = CodeGenOpts.NoNaNsFPMath; - Options.NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS; - Options.UnsafeFPMath = CodeGenOpts.UnsafeFPMath; - Options.StackAlignmentOverride = CodeGenOpts.StackAlignment; - Options.FunctionSections = CodeGenOpts.FunctionSections; - Options.DataSections = CodeGenOpts.DataSections; - Options.UniqueSectionNames = CodeGenOpts.UniqueSectionNames; - Options.EmulatedTLS = CodeGenOpts.EmulatedTLS; - Options.ExplicitEmulatedTLS = CodeGenOpts.ExplicitEmulatedTLS; - Options.DebuggerTuning = CodeGenOpts.getDebuggerTuning(); - Options.EmitStackSizeSection = CodeGenOpts.StackSizeSection; - Options.EmitAddrsig = CodeGenOpts.Addrsig; - - if (CodeGenOpts.getSplitDwarfMode() != CodeGenOptions::NoFission) - Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile; - Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll; - Options.MCOptions.MCSaveTempLabels = CodeGenOpts.SaveTempLabels; - Options.MCOptions.MCUseDwarfDirectory = !CodeGenOpts.NoDwarfDirectoryAsm; - Options.MCOptions.MCNoExecStack = CodeGenOpts.NoExecStack; - Options.MCOptions.MCIncrementalLinkerCompatible = - CodeGenOpts.IncrementalLinkerCompatible; - Options.MCOptions.MCPIECopyRelocations = CodeGenOpts.PIECopyRelocations; - Options.MCOptions.MCFatalWarnings = CodeGenOpts.FatalWarnings; - Options.MCOptions.AsmVerbose = CodeGenOpts.AsmVerbose; - Options.MCOptions.PreserveAsmComments = CodeGenOpts.PreserveAsmComments; - Options.MCOptions.ABIName = TargetOpts.ABI; - for (const auto &Entry : HSOpts.UserEntries) - if (!Entry.IsFramework && - (Entry.Group == frontend::IncludeDirGroup::Quoted || - Entry.Group == frontend::IncludeDirGroup::Angled || - Entry.Group == frontend::IncludeDirGroup::System)) - Options.MCOptions.IASSearchPaths.push_back( - Entry.IgnoreSysRoot ? Entry.Path : HSOpts.Sysroot + Entry.Path); -} -static Optional<GCOVOptions> getGCOVOptions(const CodeGenOptions &CodeGenOpts) { - if (CodeGenOpts.DisableGCov) - return None; - if (!CodeGenOpts.EmitGcovArcs && !CodeGenOpts.EmitGcovNotes) - return None; - // Not using 'GCOVOptions::getDefault' allows us to avoid exiting if - // LLVM's -default-gcov-version flag is set to something invalid. - GCOVOptions Options; - Options.EmitNotes = CodeGenOpts.EmitGcovNotes; - Options.EmitData = CodeGenOpts.EmitGcovArcs; - llvm::copy(CodeGenOpts.CoverageVersion, std::begin(Options.Version)); - Options.UseCfgChecksum = CodeGenOpts.CoverageExtraChecksum; - Options.NoRedZone = CodeGenOpts.DisableRedZone; - Options.FunctionNamesInData = !CodeGenOpts.CoverageNoFunctionNamesInData; - Options.Filter = CodeGenOpts.ProfileFilterFiles; - Options.Exclude = CodeGenOpts.ProfileExcludeFiles; - Options.ExitBlockBeforeBody = CodeGenOpts.CoverageExitBlockBeforeBody; - return Options; -} - -void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM, - legacy::FunctionPassManager &FPM) { - // Handle disabling of all LLVM passes, where we want to preserve the - // internal module before any optimization. - if (CodeGenOpts.DisableLLVMPasses) - return; - - // Figure out TargetLibraryInfo. This needs to be added to MPM and FPM - // manually (and not via PMBuilder), since some passes (eg. InstrProfiling) - // are inserted before PMBuilder ones - they'd get the default-constructed - // TLI with an unknown target otherwise. - Triple TargetTriple(TheModule->getTargetTriple()); - std::unique_ptr<TargetLibraryInfoImpl> TLII( - createTLII(TargetTriple, CodeGenOpts)); - - PassManagerBuilderWrapper PMBuilder(TargetTriple, CodeGenOpts, LangOpts); - - // At O0 and O1 we only run the always inliner which is more efficient. At - // higher optimization levels we run the normal inliner. - if (CodeGenOpts.OptimizationLevel <= 1) { - bool InsertLifetimeIntrinsics = (CodeGenOpts.OptimizationLevel != 0 && - !CodeGenOpts.DisableLifetimeMarkers); - PMBuilder.Inliner = createAlwaysInlinerLegacyPass(InsertLifetimeIntrinsics); - } else { - // We do not want to inline hot callsites for SamplePGO module-summary build - // because profile annotation will happen again in ThinLTO backend, and we - // want the IR of the hot path to match the profile. - PMBuilder.Inliner = createFunctionInliningPass( - CodeGenOpts.OptimizationLevel, CodeGenOpts.OptimizeSize, - (!CodeGenOpts.SampleProfileFile.empty() && - CodeGenOpts.PrepareForThinLTO)); - } - - PMBuilder.OptLevel = CodeGenOpts.OptimizationLevel; - PMBuilder.SizeLevel = CodeGenOpts.OptimizeSize; - PMBuilder.SLPVectorize = CodeGenOpts.VectorizeSLP; - PMBuilder.LoopVectorize = CodeGenOpts.VectorizeLoop; - - PMBuilder.DisableUnrollLoops = !CodeGenOpts.UnrollLoops; - PMBuilder.MergeFunctions = CodeGenOpts.MergeFunctions; - PMBuilder.PrepareForThinLTO = CodeGenOpts.PrepareForThinLTO; - PMBuilder.PrepareForLTO = CodeGenOpts.PrepareForLTO; - PMBuilder.RerollLoops = CodeGenOpts.RerollLoops; - - MPM.add(new TargetLibraryInfoWrapperPass(*TLII)); - - if (TM) - TM->adjustPassManager(PMBuilder); - - if (CodeGenOpts.DebugInfoForProfiling || - !CodeGenOpts.SampleProfileFile.empty()) - PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible, - addAddDiscriminatorsPass); - - // In ObjC ARC mode, add the main ARC optimization passes. - if (LangOpts.ObjCAutoRefCount) { - PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible, - addObjCARCExpandPass); - PMBuilder.addExtension(PassManagerBuilder::EP_ModuleOptimizerEarly, - addObjCARCAPElimPass); - PMBuilder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate, - addObjCARCOptPass); - } - - if (LangOpts.CoroutinesTS) - addCoroutinePassesToExtensionPoints(PMBuilder); - - if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds)) { - PMBuilder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate, - addBoundsCheckingPass); - PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, - addBoundsCheckingPass); - } - - if (CodeGenOpts.SanitizeCoverageType || - CodeGenOpts.SanitizeCoverageIndirectCalls || - CodeGenOpts.SanitizeCoverageTraceCmp) { - PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, - addSanitizerCoveragePass); - PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, - addSanitizerCoveragePass); - } - - if (LangOpts.Sanitize.has(SanitizerKind::Address)) { - PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, - addAddressSanitizerPasses); - PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, - addAddressSanitizerPasses); - } - - if (LangOpts.Sanitize.has(SanitizerKind::KernelAddress)) { - PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, - addKernelAddressSanitizerPasses); - PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, - addKernelAddressSanitizerPasses); - } - - if (LangOpts.Sanitize.has(SanitizerKind::HWAddress)) { - PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, - addHWAddressSanitizerPasses); - PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, - addHWAddressSanitizerPasses); - } - - if (LangOpts.Sanitize.has(SanitizerKind::KernelHWAddress)) { - PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, - addKernelHWAddressSanitizerPasses); - PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, - addKernelHWAddressSanitizerPasses); - } - - if (LangOpts.Sanitize.has(SanitizerKind::Memory)) { - PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, - addMemorySanitizerPass); - PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, - addMemorySanitizerPass); - } - - if (LangOpts.Sanitize.has(SanitizerKind::KernelMemory)) { - PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, - addKernelMemorySanitizerPass); - PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, - addKernelMemorySanitizerPass); - } - - if (LangOpts.Sanitize.has(SanitizerKind::Thread)) { - PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, - addThreadSanitizerPass); - PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, - addThreadSanitizerPass); - } - - if (LangOpts.Sanitize.has(SanitizerKind::DataFlow)) { - PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, - addDataFlowSanitizerPass); - PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, - addDataFlowSanitizerPass); - } - - if (LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency)) { - PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, - addEfficiencySanitizerPass); - PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, - addEfficiencySanitizerPass); - } - - // Set up the per-function pass manager. - FPM.add(new TargetLibraryInfoWrapperPass(*TLII)); - if (CodeGenOpts.VerifyModule) - FPM.add(createVerifierPass()); - - // Set up the per-module pass manager. - if (!CodeGenOpts.RewriteMapFiles.empty()) - addSymbolRewriterPass(CodeGenOpts, &MPM); - - if (Optional<GCOVOptions> Options = getGCOVOptions(CodeGenOpts)) { - MPM.add(createGCOVProfilerPass(*Options)); - if (CodeGenOpts.getDebugInfo() == codegenoptions::NoDebugInfo) - MPM.add(createStripSymbolsPass(true)); - } - - if (CodeGenOpts.hasProfileClangInstr()) { - InstrProfOptions Options; - Options.NoRedZone = CodeGenOpts.DisableRedZone; - Options.InstrProfileOutput = CodeGenOpts.InstrProfileOutput; - - // TODO: Surface the option to emit atomic profile counter increments at - // the driver level. - Options.Atomic = LangOpts.Sanitize.has(SanitizerKind::Thread); - - MPM.add(createInstrProfilingLegacyPass(Options)); - } - if (CodeGenOpts.hasProfileIRInstr()) { - PMBuilder.EnablePGOInstrGen = true; - if (!CodeGenOpts.InstrProfileOutput.empty()) - PMBuilder.PGOInstrGen = CodeGenOpts.InstrProfileOutput; - else - PMBuilder.PGOInstrGen = DefaultProfileGenName; - } - if (CodeGenOpts.hasProfileIRUse()) - PMBuilder.PGOInstrUse = CodeGenOpts.ProfileInstrumentUsePath; - - if (!CodeGenOpts.SampleProfileFile.empty()) - PMBuilder.PGOSampleUse = CodeGenOpts.SampleProfileFile; - - PMBuilder.populateFunctionPassManager(FPM); - PMBuilder.populateModulePassManager(MPM); -} - -static void setCommandLineOpts(const CodeGenOptions &CodeGenOpts) { - SmallVector<const char *, 16> BackendArgs; - BackendArgs.push_back("clang"); // Fake program name. - if (!CodeGenOpts.DebugPass.empty()) { - BackendArgs.push_back("-debug-pass"); - BackendArgs.push_back(CodeGenOpts.DebugPass.c_str()); - } - if (!CodeGenOpts.LimitFloatPrecision.empty()) { - BackendArgs.push_back("-limit-float-precision"); - BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str()); - } - BackendArgs.push_back(nullptr); - llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1, - BackendArgs.data()); -} - -void EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) { - // Create the TargetMachine for generating code. - std::string Error; - std::string Triple = TheModule->getTargetTriple(); - const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error); - if (!TheTarget) { - if (MustCreateTM) - Diags.Report(diag::err_fe_unable_to_create_target) << Error; - return; - } - - Optional<llvm::CodeModel::Model> CM = getCodeModel(CodeGenOpts); - std::string FeaturesStr = - llvm::join(TargetOpts.Features.begin(), TargetOpts.Features.end(), ","); - llvm::Reloc::Model RM = CodeGenOpts.RelocationModel; - CodeGenOpt::Level OptLevel = getCGOptLevel(CodeGenOpts); - - llvm::TargetOptions Options; - initTargetOptions(Options, CodeGenOpts, TargetOpts, LangOpts, HSOpts); - TM.reset(TheTarget->createTargetMachine(Triple, TargetOpts.CPU, FeaturesStr, - Options, RM, CM, OptLevel)); -} - -bool EmitAssemblyHelper::AddEmitPasses(legacy::PassManager &CodeGenPasses, - BackendAction Action, - raw_pwrite_stream &OS, - raw_pwrite_stream *DwoOS) { - // Add LibraryInfo. - llvm::Triple TargetTriple(TheModule->getTargetTriple()); - std::unique_ptr<TargetLibraryInfoImpl> TLII( - createTLII(TargetTriple, CodeGenOpts)); - CodeGenPasses.add(new TargetLibraryInfoWrapperPass(*TLII)); - - // Normal mode, emit a .s or .o file by running the code generator. Note, - // this also adds codegenerator level optimization passes. - TargetMachine::CodeGenFileType CGFT = getCodeGenFileType(Action); - - // Add ObjC ARC final-cleanup optimizations. This is done as part of the - // "codegen" passes so that it isn't run multiple times when there is - // inlining happening. - if (CodeGenOpts.OptimizationLevel > 0) - CodeGenPasses.add(createObjCARCContractPass()); - - if (TM->addPassesToEmitFile(CodeGenPasses, OS, DwoOS, CGFT, - /*DisableVerify=*/!CodeGenOpts.VerifyModule)) { - Diags.Report(diag::err_fe_unable_to_interface_with_target); - return false; - } - - return true; -} - -void EmitAssemblyHelper::EmitAssembly(BackendAction Action, - std::unique_ptr<raw_pwrite_stream> OS) { - TimeRegion Region(FrontendTimesIsEnabled ? &CodeGenerationTime : nullptr); - - setCommandLineOpts(CodeGenOpts); - - bool UsesCodeGen = (Action != Backend_EmitNothing && - Action != Backend_EmitBC && - Action != Backend_EmitLL); - CreateTargetMachine(UsesCodeGen); - - if (UsesCodeGen && !TM) - return; - if (TM) - TheModule->setDataLayout(TM->createDataLayout()); - - legacy::PassManager PerModulePasses; - PerModulePasses.add( - createTargetTransformInfoWrapperPass(getTargetIRAnalysis())); - - legacy::FunctionPassManager PerFunctionPasses(TheModule); - PerFunctionPasses.add( - createTargetTransformInfoWrapperPass(getTargetIRAnalysis())); - - CreatePasses(PerModulePasses, PerFunctionPasses); - - legacy::PassManager CodeGenPasses; - CodeGenPasses.add( - createTargetTransformInfoWrapperPass(getTargetIRAnalysis())); - - std::unique_ptr<llvm::ToolOutputFile> ThinLinkOS, DwoOS; - - switch (Action) { - case Backend_EmitNothing: - break; - - case Backend_EmitBC: - if (CodeGenOpts.PrepareForThinLTO && !CodeGenOpts.DisableLLVMPasses) { - if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) { - ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile); - if (!ThinLinkOS) - return; - } - TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit", - CodeGenOpts.EnableSplitLTOUnit); - PerModulePasses.add(createWriteThinLTOBitcodePass( - *OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr)); - } else { - // Emit a module summary by default for Regular LTO except for ld64 - // targets - bool EmitLTOSummary = - (CodeGenOpts.PrepareForLTO && - !CodeGenOpts.DisableLLVMPasses && - llvm::Triple(TheModule->getTargetTriple()).getVendor() != - llvm::Triple::Apple); - if (EmitLTOSummary) { - if (!TheModule->getModuleFlag("ThinLTO")) - TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0)); - TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit", - CodeGenOpts.EnableSplitLTOUnit); - } - - PerModulePasses.add(createBitcodeWriterPass( - *OS, CodeGenOpts.EmitLLVMUseLists, EmitLTOSummary)); - } - break; - - case Backend_EmitLL: - PerModulePasses.add( - createPrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists)); - break; - - default: - if (!CodeGenOpts.SplitDwarfFile.empty() && - (CodeGenOpts.getSplitDwarfMode() == CodeGenOptions::SplitFileFission)) { - DwoOS = openOutputFile(CodeGenOpts.SplitDwarfFile); - if (!DwoOS) - return; - } - if (!AddEmitPasses(CodeGenPasses, Action, *OS, - DwoOS ? &DwoOS->os() : nullptr)) - return; - } - - // Before executing passes, print the final values of the LLVM options. - cl::PrintOptionValues(); - - // Run passes. For now we do all passes at once, but eventually we - // would like to have the option of streaming code generation. - - { - PrettyStackTraceString CrashInfo("Per-function optimization"); - - PerFunctionPasses.doInitialization(); - for (Function &F : *TheModule) - if (!F.isDeclaration()) - PerFunctionPasses.run(F); - PerFunctionPasses.doFinalization(); - } - - { - PrettyStackTraceString CrashInfo("Per-module optimization passes"); - PerModulePasses.run(*TheModule); - } - - { - PrettyStackTraceString CrashInfo("Code generation"); - CodeGenPasses.run(*TheModule); - } - - if (ThinLinkOS) - ThinLinkOS->keep(); - if (DwoOS) - DwoOS->keep(); -} - -static PassBuilder::OptimizationLevel mapToLevel(const CodeGenOptions &Opts) { - switch (Opts.OptimizationLevel) { - default: - llvm_unreachable("Invalid optimization level!"); - - case 1: - return PassBuilder::O1; - - case 2: - switch (Opts.OptimizeSize) { - default: - llvm_unreachable("Invalid optimization level for size!"); - - case 0: - return PassBuilder::O2; - - case 1: - return PassBuilder::Os; - - case 2: - return PassBuilder::Oz; - } - - case 3: - return PassBuilder::O3; - } -} - -/// A clean version of `EmitAssembly` that uses the new pass manager. -/// -/// Not all features are currently supported in this system, but where -/// necessary it falls back to the legacy pass manager to at least provide -/// basic functionality. -/// -/// This API is planned to have its functionality finished and then to replace -/// `EmitAssembly` at some point in the future when the default switches. -void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( - BackendAction Action, std::unique_ptr<raw_pwrite_stream> OS) { - TimeRegion Region(FrontendTimesIsEnabled ? &CodeGenerationTime : nullptr); - setCommandLineOpts(CodeGenOpts); - - // The new pass manager always makes a target machine available to passes - // during construction. - CreateTargetMachine(/*MustCreateTM*/ true); - if (!TM) - // This will already be diagnosed, just bail. - return; - TheModule->setDataLayout(TM->createDataLayout()); - - Optional<PGOOptions> PGOOpt; - - if (CodeGenOpts.hasProfileIRInstr()) - // -fprofile-generate. - PGOOpt = PGOOptions(CodeGenOpts.InstrProfileOutput.empty() - ? DefaultProfileGenName - : CodeGenOpts.InstrProfileOutput, - "", "", "", true, - CodeGenOpts.DebugInfoForProfiling); - else if (CodeGenOpts.hasProfileIRUse()) - // -fprofile-use. - PGOOpt = PGOOptions("", CodeGenOpts.ProfileInstrumentUsePath, "", - CodeGenOpts.ProfileRemappingFile, false, - CodeGenOpts.DebugInfoForProfiling); - else if (!CodeGenOpts.SampleProfileFile.empty()) - // -fprofile-sample-use - PGOOpt = PGOOptions("", "", CodeGenOpts.SampleProfileFile, - CodeGenOpts.ProfileRemappingFile, false, - CodeGenOpts.DebugInfoForProfiling); - else if (CodeGenOpts.DebugInfoForProfiling) - // -fdebug-info-for-profiling - PGOOpt = PGOOptions("", "", "", "", false, true); - - PassBuilder PB(TM.get(), PGOOpt); - - LoopAnalysisManager LAM(CodeGenOpts.DebugPassManager); - FunctionAnalysisManager FAM(CodeGenOpts.DebugPassManager); - CGSCCAnalysisManager CGAM(CodeGenOpts.DebugPassManager); - ModuleAnalysisManager MAM(CodeGenOpts.DebugPassManager); - - // Register the AA manager first so that our version is the one used. - FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); }); - - // Register the target library analysis directly and give it a customized - // preset TLI. - Triple TargetTriple(TheModule->getTargetTriple()); - std::unique_ptr<TargetLibraryInfoImpl> TLII( - createTLII(TargetTriple, CodeGenOpts)); - FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); }); - MAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); }); - - // Register all the basic analyses with the managers. - PB.registerModuleAnalyses(MAM); - PB.registerCGSCCAnalyses(CGAM); - PB.registerFunctionAnalyses(FAM); - PB.registerLoopAnalyses(LAM); - PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); - - ModulePassManager MPM(CodeGenOpts.DebugPassManager); - - if (!CodeGenOpts.DisableLLVMPasses) { - bool IsThinLTO = CodeGenOpts.PrepareForThinLTO; - bool IsLTO = CodeGenOpts.PrepareForLTO; - - if (CodeGenOpts.OptimizationLevel == 0) { - if (Optional<GCOVOptions> Options = getGCOVOptions(CodeGenOpts)) - MPM.addPass(GCOVProfilerPass(*Options)); - - // Build a minimal pipeline based on the semantics required by Clang, - // which is just that always inlining occurs. - MPM.addPass(AlwaysInlinerPass()); - - // At -O0 we directly run necessary sanitizer passes. - if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds)) - MPM.addPass(createModuleToFunctionPassAdaptor(BoundsCheckingPass())); - - // Lastly, add semantically necessary passes for LTO. - if (IsLTO || IsThinLTO) { - MPM.addPass(CanonicalizeAliasesPass()); - MPM.addPass(NameAnonGlobalPass()); - } - } else { - // Map our optimization levels into one of the distinct levels used to - // configure the pipeline. - PassBuilder::OptimizationLevel Level = mapToLevel(CodeGenOpts); - - // Register callbacks to schedule sanitizer passes at the appropriate part of - // the pipeline. - if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds)) - PB.registerScalarOptimizerLateEPCallback( - [](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { - FPM.addPass(BoundsCheckingPass()); - }); - if (Optional<GCOVOptions> Options = getGCOVOptions(CodeGenOpts)) - PB.registerPipelineStartEPCallback([Options](ModulePassManager &MPM) { - MPM.addPass(GCOVProfilerPass(*Options)); - }); - - if (IsThinLTO) { - MPM = PB.buildThinLTOPreLinkDefaultPipeline( - Level, CodeGenOpts.DebugPassManager); - MPM.addPass(CanonicalizeAliasesPass()); - MPM.addPass(NameAnonGlobalPass()); - } else if (IsLTO) { - MPM = PB.buildLTOPreLinkDefaultPipeline(Level, - CodeGenOpts.DebugPassManager); - MPM.addPass(CanonicalizeAliasesPass()); - MPM.addPass(NameAnonGlobalPass()); - } else { - MPM = PB.buildPerModuleDefaultPipeline(Level, - CodeGenOpts.DebugPassManager); - } - } - } - - // FIXME: We still use the legacy pass manager to do code generation. We - // create that pass manager here and use it as needed below. - legacy::PassManager CodeGenPasses; - bool NeedCodeGen = false; - std::unique_ptr<llvm::ToolOutputFile> ThinLinkOS, DwoOS; - - // Append any output we need to the pass manager. - switch (Action) { - case Backend_EmitNothing: - break; - - case Backend_EmitBC: - if (CodeGenOpts.PrepareForThinLTO && !CodeGenOpts.DisableLLVMPasses) { - if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) { - ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile); - if (!ThinLinkOS) - return; - } - TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit", - CodeGenOpts.EnableSplitLTOUnit); - MPM.addPass(ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ? &ThinLinkOS->os() - : nullptr)); - } else { - // Emit a module summary by default for Regular LTO except for ld64 - // targets - bool EmitLTOSummary = - (CodeGenOpts.PrepareForLTO && - !CodeGenOpts.DisableLLVMPasses && - llvm::Triple(TheModule->getTargetTriple()).getVendor() != - llvm::Triple::Apple); - if (EmitLTOSummary) { - if (!TheModule->getModuleFlag("ThinLTO")) - TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0)); - TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit", - CodeGenOpts.EnableSplitLTOUnit); - } - MPM.addPass( - BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, EmitLTOSummary)); - } - break; - - case Backend_EmitLL: - MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists)); - break; - - case Backend_EmitAssembly: - case Backend_EmitMCNull: - case Backend_EmitObj: - NeedCodeGen = true; - CodeGenPasses.add( - createTargetTransformInfoWrapperPass(getTargetIRAnalysis())); - if (!CodeGenOpts.SplitDwarfFile.empty()) { - DwoOS = openOutputFile(CodeGenOpts.SplitDwarfFile); - if (!DwoOS) - return; - } - if (!AddEmitPasses(CodeGenPasses, Action, *OS, - DwoOS ? &DwoOS->os() : nullptr)) - // FIXME: Should we handle this error differently? - return; - break; - } - - // Before executing passes, print the final values of the LLVM options. - cl::PrintOptionValues(); - - // Now that we have all of the passes ready, run them. - { - PrettyStackTraceString CrashInfo("Optimizer"); - MPM.run(*TheModule, MAM); - } - - // Now if needed, run the legacy PM for codegen. - if (NeedCodeGen) { - PrettyStackTraceString CrashInfo("Code generation"); - CodeGenPasses.run(*TheModule); - } - - if (ThinLinkOS) - ThinLinkOS->keep(); - if (DwoOS) - DwoOS->keep(); -} - -Expected<BitcodeModule> clang::FindThinLTOModule(MemoryBufferRef MBRef) { - Expected<std::vector<BitcodeModule>> BMsOrErr = getBitcodeModuleList(MBRef); - if (!BMsOrErr) - return BMsOrErr.takeError(); - - // The bitcode file may contain multiple modules, we want the one that is - // marked as being the ThinLTO module. - if (const BitcodeModule *Bm = FindThinLTOModule(*BMsOrErr)) - return *Bm; - - return make_error<StringError>("Could not find module summary", - inconvertibleErrorCode()); -} - -BitcodeModule *clang::FindThinLTOModule(MutableArrayRef<BitcodeModule> BMs) { - for (BitcodeModule &BM : BMs) { - Expected<BitcodeLTOInfo> LTOInfo = BM.getLTOInfo(); - if (LTOInfo && LTOInfo->IsThinLTO) - return &BM; - } - return nullptr; -} - -static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M, - const HeaderSearchOptions &HeaderOpts, - const CodeGenOptions &CGOpts, - const clang::TargetOptions &TOpts, - const LangOptions &LOpts, - std::unique_ptr<raw_pwrite_stream> OS, - std::string SampleProfile, - std::string ProfileRemapping, - BackendAction Action) { - StringMap<DenseMap<GlobalValue::GUID, GlobalValueSummary *>> - ModuleToDefinedGVSummaries; - CombinedIndex->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries); - - setCommandLineOpts(CGOpts); - - // We can simply import the values mentioned in the combined index, since - // we should only invoke this using the individual indexes written out - // via a WriteIndexesThinBackend. - FunctionImporter::ImportMapTy ImportList; - for (auto &GlobalList : *CombinedIndex) { - // Ignore entries for undefined references. - if (GlobalList.second.SummaryList.empty()) - continue; - - auto GUID = GlobalList.first; - for (auto &Summary : GlobalList.second.SummaryList) { - // Skip the summaries for the importing module. These are included to - // e.g. record required linkage changes. - if (Summary->modulePath() == M->getModuleIdentifier()) - continue; - // Add an entry to provoke importing by thinBackend. - ImportList[Summary->modulePath()].insert(GUID); - } - } - - std::vector<std::unique_ptr<llvm::MemoryBuffer>> OwnedImports; - MapVector<llvm::StringRef, llvm::BitcodeModule> ModuleMap; - - for (auto &I : ImportList) { - ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MBOrErr = - llvm::MemoryBuffer::getFile(I.first()); - if (!MBOrErr) { - errs() << "Error loading imported file '" << I.first() - << "': " << MBOrErr.getError().message() << "\n"; - return; - } - - Expected<BitcodeModule> BMOrErr = FindThinLTOModule(**MBOrErr); - if (!BMOrErr) { - handleAllErrors(BMOrErr.takeError(), [&](ErrorInfoBase &EIB) { - errs() << "Error loading imported file '" << I.first() - << "': " << EIB.message() << '\n'; - }); - return; - } - ModuleMap.insert({I.first(), *BMOrErr}); - - OwnedImports.push_back(std::move(*MBOrErr)); - } - auto AddStream = [&](size_t Task) { - return llvm::make_unique<lto::NativeObjectStream>(std::move(OS)); - }; - lto::Config Conf; - if (CGOpts.SaveTempsFilePrefix != "") { - if (Error E = Conf.addSaveTemps(CGOpts.SaveTempsFilePrefix + ".", - /* UseInputModulePath */ false)) { - handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) { - errs() << "Error setting up ThinLTO save-temps: " << EIB.message() - << '\n'; - }); - } - } - Conf.CPU = TOpts.CPU; - Conf.CodeModel = getCodeModel(CGOpts); - Conf.MAttrs = TOpts.Features; - Conf.RelocModel = CGOpts.RelocationModel; - Conf.CGOptLevel = getCGOptLevel(CGOpts); - initTargetOptions(Conf.Options, CGOpts, TOpts, LOpts, HeaderOpts); - Conf.SampleProfile = std::move(SampleProfile); - Conf.ProfileRemapping = std::move(ProfileRemapping); - Conf.UseNewPM = CGOpts.ExperimentalNewPassManager; - Conf.DebugPassManager = CGOpts.DebugPassManager; - Conf.RemarksWithHotness = CGOpts.DiagnosticsWithHotness; - Conf.RemarksFilename = CGOpts.OptRecordFile; - Conf.DwoPath = CGOpts.SplitDwarfFile; - switch (Action) { - case Backend_EmitNothing: - Conf.PreCodeGenModuleHook = [](size_t Task, const Module &Mod) { - return false; - }; - break; - case Backend_EmitLL: - Conf.PreCodeGenModuleHook = [&](size_t Task, const Module &Mod) { - M->print(*OS, nullptr, CGOpts.EmitLLVMUseLists); - return false; - }; - break; - case Backend_EmitBC: - Conf.PreCodeGenModuleHook = [&](size_t Task, const Module &Mod) { - WriteBitcodeToFile(*M, *OS, CGOpts.EmitLLVMUseLists); - return false; - }; - break; - default: - Conf.CGFileType = getCodeGenFileType(Action); - break; - } - if (Error E = thinBackend( - Conf, -1, AddStream, *M, *CombinedIndex, ImportList, - ModuleToDefinedGVSummaries[M->getModuleIdentifier()], ModuleMap)) { - handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) { - errs() << "Error running ThinLTO backend: " << EIB.message() << '\n'; - }); - } -} - -void clang::EmitBackendOutput(DiagnosticsEngine &Diags, - const HeaderSearchOptions &HeaderOpts, - const CodeGenOptions &CGOpts, - const clang::TargetOptions &TOpts, - const LangOptions &LOpts, - const llvm::DataLayout &TDesc, Module *M, - BackendAction Action, - std::unique_ptr<raw_pwrite_stream> OS) { - std::unique_ptr<llvm::Module> EmptyModule; - if (!CGOpts.ThinLTOIndexFile.empty()) { - // If we are performing a ThinLTO importing compile, load the function index - // into memory and pass it into runThinLTOBackend, which will run the - // function importer and invoke LTO passes. - Expected<std::unique_ptr<ModuleSummaryIndex>> IndexOrErr = - llvm::getModuleSummaryIndexForFile(CGOpts.ThinLTOIndexFile, - /*IgnoreEmptyThinLTOIndexFile*/true); - if (!IndexOrErr) { - logAllUnhandledErrors(IndexOrErr.takeError(), errs(), - "Error loading index file '" + - CGOpts.ThinLTOIndexFile + "': "); - return; - } - std::unique_ptr<ModuleSummaryIndex> CombinedIndex = std::move(*IndexOrErr); - // A null CombinedIndex means we should skip ThinLTO compilation - // (LLVM will optionally ignore empty index files, returning null instead - // of an error). - if (CombinedIndex) { - if (!CombinedIndex->skipModuleByDistributedBackend()) { - runThinLTOBackend(CombinedIndex.get(), M, HeaderOpts, CGOpts, TOpts, - LOpts, std::move(OS), CGOpts.SampleProfileFile, - CGOpts.ProfileRemappingFile, Action); - return; - } - // Distributed indexing detected that nothing from the module is needed - // for the final linking. So we can skip the compilation. We sill need to - // output an empty object file to make sure that a linker does not fail - // trying to read it. Also for some features, like CFI, we must skip - // the compilation as CombinedIndex does not contain all required - // information. - EmptyModule = llvm::make_unique<llvm::Module>("empty", M->getContext()); - EmptyModule->setTargetTriple(M->getTargetTriple()); - M = EmptyModule.get(); - } - } - - EmitAssemblyHelper AsmHelper(Diags, HeaderOpts, CGOpts, TOpts, LOpts, M); - - if (CGOpts.ExperimentalNewPassManager) - AsmHelper.EmitAssemblyWithNewPassManager(Action, std::move(OS)); - else - AsmHelper.EmitAssembly(Action, std::move(OS)); - - // Verify clang's TargetInfo DataLayout against the LLVM TargetMachine's - // DataLayout. - if (AsmHelper.TM) { - std::string DLDesc = M->getDataLayout().getStringRepresentation(); - if (DLDesc != TDesc.getStringRepresentation()) { - unsigned DiagID = Diags.getCustomDiagID( - DiagnosticsEngine::Error, "backend data layout '%0' does not match " - "expected target description '%1'"); - Diags.Report(DiagID) << DLDesc << TDesc.getStringRepresentation(); - } - } -} - -static const char* getSectionNameForBitcode(const Triple &T) { - switch (T.getObjectFormat()) { - case Triple::MachO: - return "__LLVM,__bitcode"; - case Triple::COFF: - case Triple::ELF: - case Triple::Wasm: - case Triple::UnknownObjectFormat: - return ".llvmbc"; - } - llvm_unreachable("Unimplemented ObjectFormatType"); -} - -static const char* getSectionNameForCommandline(const Triple &T) { - switch (T.getObjectFormat()) { - case Triple::MachO: - return "__LLVM,__cmdline"; - case Triple::COFF: - case Triple::ELF: - case Triple::Wasm: - case Triple::UnknownObjectFormat: - return ".llvmcmd"; - } - llvm_unreachable("Unimplemented ObjectFormatType"); -} - -// With -fembed-bitcode, save a copy of the llvm IR as data in the -// __LLVM,__bitcode section. -void clang::EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts, - llvm::MemoryBufferRef Buf) { - if (CGOpts.getEmbedBitcode() == CodeGenOptions::Embed_Off) - return; - - // Save llvm.compiler.used and remote it. - SmallVector<Constant*, 2> UsedArray; - SmallPtrSet<GlobalValue*, 4> UsedGlobals; - Type *UsedElementType = Type::getInt8Ty(M->getContext())->getPointerTo(0); - GlobalVariable *Used = collectUsedGlobalVariables(*M, UsedGlobals, true); - for (auto *GV : UsedGlobals) { - if (GV->getName() != "llvm.embedded.module" && - GV->getName() != "llvm.cmdline") - UsedArray.push_back( - ConstantExpr::getPointerBitCastOrAddrSpaceCast(GV, UsedElementType)); - } - if (Used) - Used->eraseFromParent(); - - // Embed the bitcode for the llvm module. - std::string Data; - ArrayRef<uint8_t> ModuleData; - Triple T(M->getTargetTriple()); - // Create a constant that contains the bitcode. - // In case of embedding a marker, ignore the input Buf and use the empty - // ArrayRef. It is also legal to create a bitcode marker even Buf is empty. - if (CGOpts.getEmbedBitcode() != CodeGenOptions::Embed_Marker) { - if (!isBitcode((const unsigned char *)Buf.getBufferStart(), - (const unsigned char *)Buf.getBufferEnd())) { - // If the input is LLVM Assembly, bitcode is produced by serializing - // the module. Use-lists order need to be perserved in this case. - llvm::raw_string_ostream OS(Data); - llvm::WriteBitcodeToFile(*M, OS, /* ShouldPreserveUseListOrder */ true); - ModuleData = - ArrayRef<uint8_t>((const uint8_t *)OS.str().data(), OS.str().size()); - } else - // If the input is LLVM bitcode, write the input byte stream directly. - ModuleData = ArrayRef<uint8_t>((const uint8_t *)Buf.getBufferStart(), - Buf.getBufferSize()); - } - llvm::Constant *ModuleConstant = - llvm::ConstantDataArray::get(M->getContext(), ModuleData); - llvm::GlobalVariable *GV = new llvm::GlobalVariable( - *M, ModuleConstant->getType(), true, llvm::GlobalValue::PrivateLinkage, - ModuleConstant); - GV->setSection(getSectionNameForBitcode(T)); - UsedArray.push_back( - ConstantExpr::getPointerBitCastOrAddrSpaceCast(GV, UsedElementType)); - if (llvm::GlobalVariable *Old = - M->getGlobalVariable("llvm.embedded.module", true)) { - assert(Old->hasOneUse() && - "llvm.embedded.module can only be used once in llvm.compiler.used"); - GV->takeName(Old); - Old->eraseFromParent(); - } else { - GV->setName("llvm.embedded.module"); - } - - // Skip if only bitcode needs to be embedded. - if (CGOpts.getEmbedBitcode() != CodeGenOptions::Embed_Bitcode) { - // Embed command-line options. - ArrayRef<uint8_t> CmdData(const_cast<uint8_t *>(CGOpts.CmdArgs.data()), - CGOpts.CmdArgs.size()); - llvm::Constant *CmdConstant = - llvm::ConstantDataArray::get(M->getContext(), CmdData); - GV = new llvm::GlobalVariable(*M, CmdConstant->getType(), true, - llvm::GlobalValue::PrivateLinkage, - CmdConstant); - GV->setSection(getSectionNameForCommandline(T)); - UsedArray.push_back( - ConstantExpr::getPointerBitCastOrAddrSpaceCast(GV, UsedElementType)); - if (llvm::GlobalVariable *Old = - M->getGlobalVariable("llvm.cmdline", true)) { - assert(Old->hasOneUse() && - "llvm.cmdline can only be used once in llvm.compiler.used"); - GV->takeName(Old); - Old->eraseFromParent(); - } else { - GV->setName("llvm.cmdline"); - } - } - - if (UsedArray.empty()) - return; - - // Recreate llvm.compiler.used. - ArrayType *ATy = ArrayType::get(UsedElementType, UsedArray.size()); - auto *NewUsed = new GlobalVariable( - *M, ATy, false, llvm::GlobalValue::AppendingLinkage, - llvm::ConstantArray::get(ATy, UsedArray), "llvm.compiler.used"); - NewUsed->setSection("llvm.metadata"); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp deleted file mode 100644 index 24056a449de..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp +++ /dev/null @@ -1,2043 +0,0 @@ -//===--- CGAtomic.cpp - Emit LLVM IR for atomic operations ----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the code for emitting atomic operations. -// -//===----------------------------------------------------------------------===// - -#include "CGCall.h" -#include "CGRecordLayout.h" -#include "CodeGenFunction.h" -#include "CodeGenModule.h" -#include "TargetInfo.h" -#include "clang/AST/ASTContext.h" -#include "clang/CodeGen/CGFunctionInfo.h" -#include "clang/Frontend/FrontendDiagnostic.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Operator.h" - -using namespace clang; -using namespace CodeGen; - -namespace { - class AtomicInfo { - CodeGenFunction &CGF; - QualType AtomicTy; - QualType ValueTy; - uint64_t AtomicSizeInBits; - uint64_t ValueSizeInBits; - CharUnits AtomicAlign; - CharUnits ValueAlign; - CharUnits LValueAlign; - TypeEvaluationKind EvaluationKind; - bool UseLibcall; - LValue LVal; - CGBitFieldInfo BFI; - public: - AtomicInfo(CodeGenFunction &CGF, LValue &lvalue) - : CGF(CGF), AtomicSizeInBits(0), ValueSizeInBits(0), - EvaluationKind(TEK_Scalar), UseLibcall(true) { - assert(!lvalue.isGlobalReg()); - ASTContext &C = CGF.getContext(); - if (lvalue.isSimple()) { - AtomicTy = lvalue.getType(); - if (auto *ATy = AtomicTy->getAs<AtomicType>()) - ValueTy = ATy->getValueType(); - else - ValueTy = AtomicTy; - EvaluationKind = CGF.getEvaluationKind(ValueTy); - - uint64_t ValueAlignInBits; - uint64_t AtomicAlignInBits; - TypeInfo ValueTI = C.getTypeInfo(ValueTy); - ValueSizeInBits = ValueTI.Width; - ValueAlignInBits = ValueTI.Align; - - TypeInfo AtomicTI = C.getTypeInfo(AtomicTy); - AtomicSizeInBits = AtomicTI.Width; - AtomicAlignInBits = AtomicTI.Align; - - assert(ValueSizeInBits <= AtomicSizeInBits); - assert(ValueAlignInBits <= AtomicAlignInBits); - - AtomicAlign = C.toCharUnitsFromBits(AtomicAlignInBits); - ValueAlign = C.toCharUnitsFromBits(ValueAlignInBits); - if (lvalue.getAlignment().isZero()) - lvalue.setAlignment(AtomicAlign); - - LVal = lvalue; - } else if (lvalue.isBitField()) { - ValueTy = lvalue.getType(); - ValueSizeInBits = C.getTypeSize(ValueTy); - auto &OrigBFI = lvalue.getBitFieldInfo(); - auto Offset = OrigBFI.Offset % C.toBits(lvalue.getAlignment()); - AtomicSizeInBits = C.toBits( - C.toCharUnitsFromBits(Offset + OrigBFI.Size + C.getCharWidth() - 1) - .alignTo(lvalue.getAlignment())); - auto VoidPtrAddr = CGF.EmitCastToVoidPtr(lvalue.getBitFieldPointer()); - auto OffsetInChars = - (C.toCharUnitsFromBits(OrigBFI.Offset) / lvalue.getAlignment()) * - lvalue.getAlignment(); - VoidPtrAddr = CGF.Builder.CreateConstGEP1_64( - VoidPtrAddr, OffsetInChars.getQuantity()); - auto Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - VoidPtrAddr, - CGF.Builder.getIntNTy(AtomicSizeInBits)->getPointerTo(), - "atomic_bitfield_base"); - BFI = OrigBFI; - BFI.Offset = Offset; - BFI.StorageSize = AtomicSizeInBits; - BFI.StorageOffset += OffsetInChars; - LVal = LValue::MakeBitfield(Address(Addr, lvalue.getAlignment()), - BFI, lvalue.getType(), lvalue.getBaseInfo(), - lvalue.getTBAAInfo()); - AtomicTy = C.getIntTypeForBitwidth(AtomicSizeInBits, OrigBFI.IsSigned); - if (AtomicTy.isNull()) { - llvm::APInt Size( - /*numBits=*/32, - C.toCharUnitsFromBits(AtomicSizeInBits).getQuantity()); - AtomicTy = C.getConstantArrayType(C.CharTy, Size, ArrayType::Normal, - /*IndexTypeQuals=*/0); - } - AtomicAlign = ValueAlign = lvalue.getAlignment(); - } else if (lvalue.isVectorElt()) { - ValueTy = lvalue.getType()->getAs<VectorType>()->getElementType(); - ValueSizeInBits = C.getTypeSize(ValueTy); - AtomicTy = lvalue.getType(); - AtomicSizeInBits = C.getTypeSize(AtomicTy); - AtomicAlign = ValueAlign = lvalue.getAlignment(); - LVal = lvalue; - } else { - assert(lvalue.isExtVectorElt()); - ValueTy = lvalue.getType(); - ValueSizeInBits = C.getTypeSize(ValueTy); - AtomicTy = ValueTy = CGF.getContext().getExtVectorType( - lvalue.getType(), lvalue.getExtVectorAddress() - .getElementType()->getVectorNumElements()); - AtomicSizeInBits = C.getTypeSize(AtomicTy); - AtomicAlign = ValueAlign = lvalue.getAlignment(); - LVal = lvalue; - } - UseLibcall = !C.getTargetInfo().hasBuiltinAtomic( - AtomicSizeInBits, C.toBits(lvalue.getAlignment())); - } - - QualType getAtomicType() const { return AtomicTy; } - QualType getValueType() const { return ValueTy; } - CharUnits getAtomicAlignment() const { return AtomicAlign; } - CharUnits getValueAlignment() const { return ValueAlign; } - uint64_t getAtomicSizeInBits() const { return AtomicSizeInBits; } - uint64_t getValueSizeInBits() const { return ValueSizeInBits; } - TypeEvaluationKind getEvaluationKind() const { return EvaluationKind; } - bool shouldUseLibcall() const { return UseLibcall; } - const LValue &getAtomicLValue() const { return LVal; } - llvm::Value *getAtomicPointer() const { - if (LVal.isSimple()) - return LVal.getPointer(); - else if (LVal.isBitField()) - return LVal.getBitFieldPointer(); - else if (LVal.isVectorElt()) - return LVal.getVectorPointer(); - assert(LVal.isExtVectorElt()); - return LVal.getExtVectorPointer(); - } - Address getAtomicAddress() const { - return Address(getAtomicPointer(), getAtomicAlignment()); - } - - Address getAtomicAddressAsAtomicIntPointer() const { - return emitCastToAtomicIntPointer(getAtomicAddress()); - } - - /// Is the atomic size larger than the underlying value type? - /// - /// Note that the absence of padding does not mean that atomic - /// objects are completely interchangeable with non-atomic - /// objects: we might have promoted the alignment of a type - /// without making it bigger. - bool hasPadding() const { - return (ValueSizeInBits != AtomicSizeInBits); - } - - bool emitMemSetZeroIfNecessary() const; - - llvm::Value *getAtomicSizeValue() const { - CharUnits size = CGF.getContext().toCharUnitsFromBits(AtomicSizeInBits); - return CGF.CGM.getSize(size); - } - - /// Cast the given pointer to an integer pointer suitable for atomic - /// operations if the source. - Address emitCastToAtomicIntPointer(Address Addr) const; - - /// If Addr is compatible with the iN that will be used for an atomic - /// operation, bitcast it. Otherwise, create a temporary that is suitable - /// and copy the value across. - Address convertToAtomicIntPointer(Address Addr) const; - - /// Turn an atomic-layout object into an r-value. - RValue convertAtomicTempToRValue(Address addr, AggValueSlot resultSlot, - SourceLocation loc, bool AsValue) const; - - /// Converts a rvalue to integer value. - llvm::Value *convertRValueToInt(RValue RVal) const; - - RValue ConvertIntToValueOrAtomic(llvm::Value *IntVal, - AggValueSlot ResultSlot, - SourceLocation Loc, bool AsValue) const; - - /// Copy an atomic r-value into atomic-layout memory. - void emitCopyIntoMemory(RValue rvalue) const; - - /// Project an l-value down to the value field. - LValue projectValue() const { - assert(LVal.isSimple()); - Address addr = getAtomicAddress(); - if (hasPadding()) - addr = CGF.Builder.CreateStructGEP(addr, 0, CharUnits()); - - return LValue::MakeAddr(addr, getValueType(), CGF.getContext(), - LVal.getBaseInfo(), LVal.getTBAAInfo()); - } - - /// Emits atomic load. - /// \returns Loaded value. - RValue EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc, - bool AsValue, llvm::AtomicOrdering AO, - bool IsVolatile); - - /// Emits atomic compare-and-exchange sequence. - /// \param Expected Expected value. - /// \param Desired Desired value. - /// \param Success Atomic ordering for success operation. - /// \param Failure Atomic ordering for failed operation. - /// \param IsWeak true if atomic operation is weak, false otherwise. - /// \returns Pair of values: previous value from storage (value type) and - /// boolean flag (i1 type) with true if success and false otherwise. - std::pair<RValue, llvm::Value *> - EmitAtomicCompareExchange(RValue Expected, RValue Desired, - llvm::AtomicOrdering Success = - llvm::AtomicOrdering::SequentiallyConsistent, - llvm::AtomicOrdering Failure = - llvm::AtomicOrdering::SequentiallyConsistent, - bool IsWeak = false); - - /// Emits atomic update. - /// \param AO Atomic ordering. - /// \param UpdateOp Update operation for the current lvalue. - void EmitAtomicUpdate(llvm::AtomicOrdering AO, - const llvm::function_ref<RValue(RValue)> &UpdateOp, - bool IsVolatile); - /// Emits atomic update. - /// \param AO Atomic ordering. - void EmitAtomicUpdate(llvm::AtomicOrdering AO, RValue UpdateRVal, - bool IsVolatile); - - /// Materialize an atomic r-value in atomic-layout memory. - Address materializeRValue(RValue rvalue) const; - - /// Creates temp alloca for intermediate operations on atomic value. - Address CreateTempAlloca() const; - private: - bool requiresMemSetZero(llvm::Type *type) const; - - - /// Emits atomic load as a libcall. - void EmitAtomicLoadLibcall(llvm::Value *AddForLoaded, - llvm::AtomicOrdering AO, bool IsVolatile); - /// Emits atomic load as LLVM instruction. - llvm::Value *EmitAtomicLoadOp(llvm::AtomicOrdering AO, bool IsVolatile); - /// Emits atomic compare-and-exchange op as a libcall. - llvm::Value *EmitAtomicCompareExchangeLibcall( - llvm::Value *ExpectedAddr, llvm::Value *DesiredAddr, - llvm::AtomicOrdering Success = - llvm::AtomicOrdering::SequentiallyConsistent, - llvm::AtomicOrdering Failure = - llvm::AtomicOrdering::SequentiallyConsistent); - /// Emits atomic compare-and-exchange op as LLVM instruction. - std::pair<llvm::Value *, llvm::Value *> EmitAtomicCompareExchangeOp( - llvm::Value *ExpectedVal, llvm::Value *DesiredVal, - llvm::AtomicOrdering Success = - llvm::AtomicOrdering::SequentiallyConsistent, - llvm::AtomicOrdering Failure = - llvm::AtomicOrdering::SequentiallyConsistent, - bool IsWeak = false); - /// Emit atomic update as libcalls. - void - EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO, - const llvm::function_ref<RValue(RValue)> &UpdateOp, - bool IsVolatile); - /// Emit atomic update as LLVM instructions. - void EmitAtomicUpdateOp(llvm::AtomicOrdering AO, - const llvm::function_ref<RValue(RValue)> &UpdateOp, - bool IsVolatile); - /// Emit atomic update as libcalls. - void EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO, RValue UpdateRVal, - bool IsVolatile); - /// Emit atomic update as LLVM instructions. - void EmitAtomicUpdateOp(llvm::AtomicOrdering AO, RValue UpdateRal, - bool IsVolatile); - }; -} - -Address AtomicInfo::CreateTempAlloca() const { - Address TempAlloca = CGF.CreateMemTemp( - (LVal.isBitField() && ValueSizeInBits > AtomicSizeInBits) ? ValueTy - : AtomicTy, - getAtomicAlignment(), - "atomic-temp"); - // Cast to pointer to value type for bitfields. - if (LVal.isBitField()) - return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - TempAlloca, getAtomicAddress().getType()); - return TempAlloca; -} - -static RValue emitAtomicLibcall(CodeGenFunction &CGF, - StringRef fnName, - QualType resultType, - CallArgList &args) { - const CGFunctionInfo &fnInfo = - CGF.CGM.getTypes().arrangeBuiltinFunctionCall(resultType, args); - llvm::FunctionType *fnTy = CGF.CGM.getTypes().GetFunctionType(fnInfo); - llvm::Constant *fn = CGF.CGM.CreateRuntimeFunction(fnTy, fnName); - auto callee = CGCallee::forDirect(fn); - return CGF.EmitCall(fnInfo, callee, ReturnValueSlot(), args); -} - -/// Does a store of the given IR type modify the full expected width? -static bool isFullSizeType(CodeGenModule &CGM, llvm::Type *type, - uint64_t expectedSize) { - return (CGM.getDataLayout().getTypeStoreSize(type) * 8 == expectedSize); -} - -/// Does the atomic type require memsetting to zero before initialization? -/// -/// The IR type is provided as a way of making certain queries faster. -bool AtomicInfo::requiresMemSetZero(llvm::Type *type) const { - // If the atomic type has size padding, we definitely need a memset. - if (hasPadding()) return true; - - // Otherwise, do some simple heuristics to try to avoid it: - switch (getEvaluationKind()) { - // For scalars and complexes, check whether the store size of the - // type uses the full size. - case TEK_Scalar: - return !isFullSizeType(CGF.CGM, type, AtomicSizeInBits); - case TEK_Complex: - return !isFullSizeType(CGF.CGM, type->getStructElementType(0), - AtomicSizeInBits / 2); - - // Padding in structs has an undefined bit pattern. User beware. - case TEK_Aggregate: - return false; - } - llvm_unreachable("bad evaluation kind"); -} - -bool AtomicInfo::emitMemSetZeroIfNecessary() const { - assert(LVal.isSimple()); - llvm::Value *addr = LVal.getPointer(); - if (!requiresMemSetZero(addr->getType()->getPointerElementType())) - return false; - - CGF.Builder.CreateMemSet( - addr, llvm::ConstantInt::get(CGF.Int8Ty, 0), - CGF.getContext().toCharUnitsFromBits(AtomicSizeInBits).getQuantity(), - LVal.getAlignment().getQuantity()); - return true; -} - -static void emitAtomicCmpXchg(CodeGenFunction &CGF, AtomicExpr *E, bool IsWeak, - Address Dest, Address Ptr, - Address Val1, Address Val2, - uint64_t Size, - llvm::AtomicOrdering SuccessOrder, - llvm::AtomicOrdering FailureOrder, - llvm::SyncScope::ID Scope) { - // Note that cmpxchg doesn't support weak cmpxchg, at least at the moment. - llvm::Value *Expected = CGF.Builder.CreateLoad(Val1); - llvm::Value *Desired = CGF.Builder.CreateLoad(Val2); - - llvm::AtomicCmpXchgInst *Pair = CGF.Builder.CreateAtomicCmpXchg( - Ptr.getPointer(), Expected, Desired, SuccessOrder, FailureOrder, - Scope); - Pair->setVolatile(E->isVolatile()); - Pair->setWeak(IsWeak); - - // Cmp holds the result of the compare-exchange operation: true on success, - // false on failure. - llvm::Value *Old = CGF.Builder.CreateExtractValue(Pair, 0); - llvm::Value *Cmp = CGF.Builder.CreateExtractValue(Pair, 1); - - // This basic block is used to hold the store instruction if the operation - // failed. - llvm::BasicBlock *StoreExpectedBB = - CGF.createBasicBlock("cmpxchg.store_expected", CGF.CurFn); - - // This basic block is the exit point of the operation, we should end up - // here regardless of whether or not the operation succeeded. - llvm::BasicBlock *ContinueBB = - CGF.createBasicBlock("cmpxchg.continue", CGF.CurFn); - - // Update Expected if Expected isn't equal to Old, otherwise branch to the - // exit point. - CGF.Builder.CreateCondBr(Cmp, ContinueBB, StoreExpectedBB); - - CGF.Builder.SetInsertPoint(StoreExpectedBB); - // Update the memory at Expected with Old's value. - CGF.Builder.CreateStore(Old, Val1); - // Finally, branch to the exit point. - CGF.Builder.CreateBr(ContinueBB); - - CGF.Builder.SetInsertPoint(ContinueBB); - // Update the memory at Dest with Cmp's value. - CGF.EmitStoreOfScalar(Cmp, CGF.MakeAddrLValue(Dest, E->getType())); -} - -/// Given an ordering required on success, emit all possible cmpxchg -/// instructions to cope with the provided (but possibly only dynamically known) -/// FailureOrder. -static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E, - bool IsWeak, Address Dest, Address Ptr, - Address Val1, Address Val2, - llvm::Value *FailureOrderVal, - uint64_t Size, - llvm::AtomicOrdering SuccessOrder, - llvm::SyncScope::ID Scope) { - llvm::AtomicOrdering FailureOrder; - if (llvm::ConstantInt *FO = dyn_cast<llvm::ConstantInt>(FailureOrderVal)) { - auto FOS = FO->getSExtValue(); - if (!llvm::isValidAtomicOrderingCABI(FOS)) - FailureOrder = llvm::AtomicOrdering::Monotonic; - else - switch ((llvm::AtomicOrderingCABI)FOS) { - case llvm::AtomicOrderingCABI::relaxed: - case llvm::AtomicOrderingCABI::release: - case llvm::AtomicOrderingCABI::acq_rel: - FailureOrder = llvm::AtomicOrdering::Monotonic; - break; - case llvm::AtomicOrderingCABI::consume: - case llvm::AtomicOrderingCABI::acquire: - FailureOrder = llvm::AtomicOrdering::Acquire; - break; - case llvm::AtomicOrderingCABI::seq_cst: - FailureOrder = llvm::AtomicOrdering::SequentiallyConsistent; - break; - } - if (isStrongerThan(FailureOrder, SuccessOrder)) { - // Don't assert on undefined behavior "failure argument shall be no - // stronger than the success argument". - FailureOrder = - llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(SuccessOrder); - } - emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, SuccessOrder, - FailureOrder, Scope); - return; - } - - // Create all the relevant BB's - llvm::BasicBlock *MonotonicBB = nullptr, *AcquireBB = nullptr, - *SeqCstBB = nullptr; - MonotonicBB = CGF.createBasicBlock("monotonic_fail", CGF.CurFn); - if (SuccessOrder != llvm::AtomicOrdering::Monotonic && - SuccessOrder != llvm::AtomicOrdering::Release) - AcquireBB = CGF.createBasicBlock("acquire_fail", CGF.CurFn); - if (SuccessOrder == llvm::AtomicOrdering::SequentiallyConsistent) - SeqCstBB = CGF.createBasicBlock("seqcst_fail", CGF.CurFn); - - llvm::BasicBlock *ContBB = CGF.createBasicBlock("atomic.continue", CGF.CurFn); - - llvm::SwitchInst *SI = CGF.Builder.CreateSwitch(FailureOrderVal, MonotonicBB); - - // Emit all the different atomics - - // MonotonicBB is arbitrarily chosen as the default case; in practice, this - // doesn't matter unless someone is crazy enough to use something that - // doesn't fold to a constant for the ordering. - CGF.Builder.SetInsertPoint(MonotonicBB); - emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, - Size, SuccessOrder, llvm::AtomicOrdering::Monotonic, Scope); - CGF.Builder.CreateBr(ContBB); - - if (AcquireBB) { - CGF.Builder.SetInsertPoint(AcquireBB); - emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, - Size, SuccessOrder, llvm::AtomicOrdering::Acquire, Scope); - CGF.Builder.CreateBr(ContBB); - SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::consume), - AcquireBB); - SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::acquire), - AcquireBB); - } - if (SeqCstBB) { - CGF.Builder.SetInsertPoint(SeqCstBB); - emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, SuccessOrder, - llvm::AtomicOrdering::SequentiallyConsistent, Scope); - CGF.Builder.CreateBr(ContBB); - SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::seq_cst), - SeqCstBB); - } - - CGF.Builder.SetInsertPoint(ContBB); -} - -static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest, - Address Ptr, Address Val1, Address Val2, - llvm::Value *IsWeak, llvm::Value *FailureOrder, - uint64_t Size, llvm::AtomicOrdering Order, - llvm::SyncScope::ID Scope) { - llvm::AtomicRMWInst::BinOp Op = llvm::AtomicRMWInst::Add; - llvm::Instruction::BinaryOps PostOp = (llvm::Instruction::BinaryOps)0; - - switch (E->getOp()) { - case AtomicExpr::AO__c11_atomic_init: - case AtomicExpr::AO__opencl_atomic_init: - llvm_unreachable("Already handled!"); - - case AtomicExpr::AO__c11_atomic_compare_exchange_strong: - case AtomicExpr::AO__opencl_atomic_compare_exchange_strong: - emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2, - FailureOrder, Size, Order, Scope); - return; - case AtomicExpr::AO__c11_atomic_compare_exchange_weak: - case AtomicExpr::AO__opencl_atomic_compare_exchange_weak: - emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2, - FailureOrder, Size, Order, Scope); - return; - case AtomicExpr::AO__atomic_compare_exchange: - case AtomicExpr::AO__atomic_compare_exchange_n: { - if (llvm::ConstantInt *IsWeakC = dyn_cast<llvm::ConstantInt>(IsWeak)) { - emitAtomicCmpXchgFailureSet(CGF, E, IsWeakC->getZExtValue(), Dest, Ptr, - Val1, Val2, FailureOrder, Size, Order, Scope); - } else { - // Create all the relevant BB's - llvm::BasicBlock *StrongBB = - CGF.createBasicBlock("cmpxchg.strong", CGF.CurFn); - llvm::BasicBlock *WeakBB = CGF.createBasicBlock("cmxchg.weak", CGF.CurFn); - llvm::BasicBlock *ContBB = - CGF.createBasicBlock("cmpxchg.continue", CGF.CurFn); - - llvm::SwitchInst *SI = CGF.Builder.CreateSwitch(IsWeak, WeakBB); - SI->addCase(CGF.Builder.getInt1(false), StrongBB); - - CGF.Builder.SetInsertPoint(StrongBB); - emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2, - FailureOrder, Size, Order, Scope); - CGF.Builder.CreateBr(ContBB); - - CGF.Builder.SetInsertPoint(WeakBB); - emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2, - FailureOrder, Size, Order, Scope); - CGF.Builder.CreateBr(ContBB); - - CGF.Builder.SetInsertPoint(ContBB); - } - return; - } - case AtomicExpr::AO__c11_atomic_load: - case AtomicExpr::AO__opencl_atomic_load: - case AtomicExpr::AO__atomic_load_n: - case AtomicExpr::AO__atomic_load: { - llvm::LoadInst *Load = CGF.Builder.CreateLoad(Ptr); - Load->setAtomic(Order, Scope); - Load->setVolatile(E->isVolatile()); - CGF.Builder.CreateStore(Load, Dest); - return; - } - - case AtomicExpr::AO__c11_atomic_store: - case AtomicExpr::AO__opencl_atomic_store: - case AtomicExpr::AO__atomic_store: - case AtomicExpr::AO__atomic_store_n: { - llvm::Value *LoadVal1 = CGF.Builder.CreateLoad(Val1); - llvm::StoreInst *Store = CGF.Builder.CreateStore(LoadVal1, Ptr); - Store->setAtomic(Order, Scope); - Store->setVolatile(E->isVolatile()); - return; - } - - case AtomicExpr::AO__c11_atomic_exchange: - case AtomicExpr::AO__opencl_atomic_exchange: - case AtomicExpr::AO__atomic_exchange_n: - case AtomicExpr::AO__atomic_exchange: - Op = llvm::AtomicRMWInst::Xchg; - break; - - case AtomicExpr::AO__atomic_add_fetch: - PostOp = llvm::Instruction::Add; - LLVM_FALLTHROUGH; - case AtomicExpr::AO__c11_atomic_fetch_add: - case AtomicExpr::AO__opencl_atomic_fetch_add: - case AtomicExpr::AO__atomic_fetch_add: - Op = llvm::AtomicRMWInst::Add; - break; - - case AtomicExpr::AO__atomic_sub_fetch: - PostOp = llvm::Instruction::Sub; - LLVM_FALLTHROUGH; - case AtomicExpr::AO__c11_atomic_fetch_sub: - case AtomicExpr::AO__opencl_atomic_fetch_sub: - case AtomicExpr::AO__atomic_fetch_sub: - Op = llvm::AtomicRMWInst::Sub; - break; - - case AtomicExpr::AO__opencl_atomic_fetch_min: - case AtomicExpr::AO__atomic_fetch_min: - Op = E->getValueType()->isSignedIntegerType() ? llvm::AtomicRMWInst::Min - : llvm::AtomicRMWInst::UMin; - break; - - case AtomicExpr::AO__opencl_atomic_fetch_max: - case AtomicExpr::AO__atomic_fetch_max: - Op = E->getValueType()->isSignedIntegerType() ? llvm::AtomicRMWInst::Max - : llvm::AtomicRMWInst::UMax; - break; - - case AtomicExpr::AO__atomic_and_fetch: - PostOp = llvm::Instruction::And; - LLVM_FALLTHROUGH; - case AtomicExpr::AO__c11_atomic_fetch_and: - case AtomicExpr::AO__opencl_atomic_fetch_and: - case AtomicExpr::AO__atomic_fetch_and: - Op = llvm::AtomicRMWInst::And; - break; - - case AtomicExpr::AO__atomic_or_fetch: - PostOp = llvm::Instruction::Or; - LLVM_FALLTHROUGH; - case AtomicExpr::AO__c11_atomic_fetch_or: - case AtomicExpr::AO__opencl_atomic_fetch_or: - case AtomicExpr::AO__atomic_fetch_or: - Op = llvm::AtomicRMWInst::Or; - break; - - case AtomicExpr::AO__atomic_xor_fetch: - PostOp = llvm::Instruction::Xor; - LLVM_FALLTHROUGH; - case AtomicExpr::AO__c11_atomic_fetch_xor: - case AtomicExpr::AO__opencl_atomic_fetch_xor: - case AtomicExpr::AO__atomic_fetch_xor: - Op = llvm::AtomicRMWInst::Xor; - break; - - case AtomicExpr::AO__atomic_nand_fetch: - PostOp = llvm::Instruction::And; // the NOT is special cased below - LLVM_FALLTHROUGH; - case AtomicExpr::AO__atomic_fetch_nand: - Op = llvm::AtomicRMWInst::Nand; - break; - } - - llvm::Value *LoadVal1 = CGF.Builder.CreateLoad(Val1); - llvm::AtomicRMWInst *RMWI = - CGF.Builder.CreateAtomicRMW(Op, Ptr.getPointer(), LoadVal1, Order, Scope); - RMWI->setVolatile(E->isVolatile()); - - // For __atomic_*_fetch operations, perform the operation again to - // determine the value which was written. - llvm::Value *Result = RMWI; - if (PostOp) - Result = CGF.Builder.CreateBinOp(PostOp, RMWI, LoadVal1); - if (E->getOp() == AtomicExpr::AO__atomic_nand_fetch) - Result = CGF.Builder.CreateNot(Result); - CGF.Builder.CreateStore(Result, Dest); -} - -// This function emits any expression (scalar, complex, or aggregate) -// into a temporary alloca. -static Address -EmitValToTemp(CodeGenFunction &CGF, Expr *E) { - Address DeclPtr = CGF.CreateMemTemp(E->getType(), ".atomictmp"); - CGF.EmitAnyExprToMem(E, DeclPtr, E->getType().getQualifiers(), - /*Init*/ true); - return DeclPtr; -} - -static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *Expr, Address Dest, - Address Ptr, Address Val1, Address Val2, - llvm::Value *IsWeak, llvm::Value *FailureOrder, - uint64_t Size, llvm::AtomicOrdering Order, - llvm::Value *Scope) { - auto ScopeModel = Expr->getScopeModel(); - - // LLVM atomic instructions always have synch scope. If clang atomic - // expression has no scope operand, use default LLVM synch scope. - if (!ScopeModel) { - EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, IsWeak, FailureOrder, Size, - Order, CGF.CGM.getLLVMContext().getOrInsertSyncScopeID("")); - return; - } - - // Handle constant scope. - if (auto SC = dyn_cast<llvm::ConstantInt>(Scope)) { - auto SCID = CGF.getTargetHooks().getLLVMSyncScopeID( - ScopeModel->map(SC->getZExtValue()), CGF.CGM.getLLVMContext()); - EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, IsWeak, FailureOrder, Size, - Order, SCID); - return; - } - - // Handle non-constant scope. - auto &Builder = CGF.Builder; - auto Scopes = ScopeModel->getRuntimeValues(); - llvm::DenseMap<unsigned, llvm::BasicBlock *> BB; - for (auto S : Scopes) - BB[S] = CGF.createBasicBlock(getAsString(ScopeModel->map(S)), CGF.CurFn); - - llvm::BasicBlock *ContBB = - CGF.createBasicBlock("atomic.scope.continue", CGF.CurFn); - - auto *SC = Builder.CreateIntCast(Scope, Builder.getInt32Ty(), false); - // If unsupported synch scope is encountered at run time, assume a fallback - // synch scope value. - auto FallBack = ScopeModel->getFallBackValue(); - llvm::SwitchInst *SI = Builder.CreateSwitch(SC, BB[FallBack]); - for (auto S : Scopes) { - auto *B = BB[S]; - if (S != FallBack) - SI->addCase(Builder.getInt32(S), B); - - Builder.SetInsertPoint(B); - EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, IsWeak, FailureOrder, Size, - Order, - CGF.getTargetHooks().getLLVMSyncScopeID(ScopeModel->map(S), - CGF.getLLVMContext())); - Builder.CreateBr(ContBB); - } - - Builder.SetInsertPoint(ContBB); -} - -static void -AddDirectArgument(CodeGenFunction &CGF, CallArgList &Args, - bool UseOptimizedLibcall, llvm::Value *Val, QualType ValTy, - SourceLocation Loc, CharUnits SizeInChars) { - if (UseOptimizedLibcall) { - // Load value and pass it to the function directly. - CharUnits Align = CGF.getContext().getTypeAlignInChars(ValTy); - int64_t SizeInBits = CGF.getContext().toBits(SizeInChars); - ValTy = - CGF.getContext().getIntTypeForBitwidth(SizeInBits, /*Signed=*/false); - llvm::Type *IPtrTy = llvm::IntegerType::get(CGF.getLLVMContext(), - SizeInBits)->getPointerTo(); - Address Ptr = Address(CGF.Builder.CreateBitCast(Val, IPtrTy), Align); - Val = CGF.EmitLoadOfScalar(Ptr, false, - CGF.getContext().getPointerType(ValTy), - Loc); - // Coerce the value into an appropriately sized integer type. - Args.add(RValue::get(Val), ValTy); - } else { - // Non-optimized functions always take a reference. - Args.add(RValue::get(CGF.EmitCastToVoidPtr(Val)), - CGF.getContext().VoidPtrTy); - } -} - -RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { - QualType AtomicTy = E->getPtr()->getType()->getPointeeType(); - QualType MemTy = AtomicTy; - if (const AtomicType *AT = AtomicTy->getAs<AtomicType>()) - MemTy = AT->getValueType(); - llvm::Value *IsWeak = nullptr, *OrderFail = nullptr; - - Address Val1 = Address::invalid(); - Address Val2 = Address::invalid(); - Address Dest = Address::invalid(); - Address Ptr = EmitPointerWithAlignment(E->getPtr()); - - if (E->getOp() == AtomicExpr::AO__c11_atomic_init || - E->getOp() == AtomicExpr::AO__opencl_atomic_init) { - LValue lvalue = MakeAddrLValue(Ptr, AtomicTy); - EmitAtomicInit(E->getVal1(), lvalue); - return RValue::get(nullptr); - } - - CharUnits sizeChars, alignChars; - std::tie(sizeChars, alignChars) = getContext().getTypeInfoInChars(AtomicTy); - uint64_t Size = sizeChars.getQuantity(); - unsigned MaxInlineWidthInBits = getTarget().getMaxAtomicInlineWidth(); - - bool Oversized = getContext().toBits(sizeChars) > MaxInlineWidthInBits; - bool Misaligned = (Ptr.getAlignment() % sizeChars) != 0; - bool UseLibcall = Misaligned | Oversized; - - if (UseLibcall) { - CGM.getDiags().Report(E->getBeginLoc(), diag::warn_atomic_op_misaligned) - << !Oversized; - } - - llvm::Value *Order = EmitScalarExpr(E->getOrder()); - llvm::Value *Scope = - E->getScopeModel() ? EmitScalarExpr(E->getScope()) : nullptr; - - switch (E->getOp()) { - case AtomicExpr::AO__c11_atomic_init: - case AtomicExpr::AO__opencl_atomic_init: - llvm_unreachable("Already handled above with EmitAtomicInit!"); - - case AtomicExpr::AO__c11_atomic_load: - case AtomicExpr::AO__opencl_atomic_load: - case AtomicExpr::AO__atomic_load_n: - break; - - case AtomicExpr::AO__atomic_load: - Dest = EmitPointerWithAlignment(E->getVal1()); - break; - - case AtomicExpr::AO__atomic_store: - Val1 = EmitPointerWithAlignment(E->getVal1()); - break; - - case AtomicExpr::AO__atomic_exchange: - Val1 = EmitPointerWithAlignment(E->getVal1()); - Dest = EmitPointerWithAlignment(E->getVal2()); - break; - - case AtomicExpr::AO__c11_atomic_compare_exchange_strong: - case AtomicExpr::AO__c11_atomic_compare_exchange_weak: - case AtomicExpr::AO__opencl_atomic_compare_exchange_strong: - case AtomicExpr::AO__opencl_atomic_compare_exchange_weak: - case AtomicExpr::AO__atomic_compare_exchange_n: - case AtomicExpr::AO__atomic_compare_exchange: - Val1 = EmitPointerWithAlignment(E->getVal1()); - if (E->getOp() == AtomicExpr::AO__atomic_compare_exchange) - Val2 = EmitPointerWithAlignment(E->getVal2()); - else - Val2 = EmitValToTemp(*this, E->getVal2()); - OrderFail = EmitScalarExpr(E->getOrderFail()); - if (E->getOp() == AtomicExpr::AO__atomic_compare_exchange_n || - E->getOp() == AtomicExpr::AO__atomic_compare_exchange) - IsWeak = EmitScalarExpr(E->getWeak()); - break; - - case AtomicExpr::AO__c11_atomic_fetch_add: - case AtomicExpr::AO__c11_atomic_fetch_sub: - case AtomicExpr::AO__opencl_atomic_fetch_add: - case AtomicExpr::AO__opencl_atomic_fetch_sub: - if (MemTy->isPointerType()) { - // For pointer arithmetic, we're required to do a bit of math: - // adding 1 to an int* is not the same as adding 1 to a uintptr_t. - // ... but only for the C11 builtins. The GNU builtins expect the - // user to multiply by sizeof(T). - QualType Val1Ty = E->getVal1()->getType(); - llvm::Value *Val1Scalar = EmitScalarExpr(E->getVal1()); - CharUnits PointeeIncAmt = - getContext().getTypeSizeInChars(MemTy->getPointeeType()); - Val1Scalar = Builder.CreateMul(Val1Scalar, CGM.getSize(PointeeIncAmt)); - auto Temp = CreateMemTemp(Val1Ty, ".atomictmp"); - Val1 = Temp; - EmitStoreOfScalar(Val1Scalar, MakeAddrLValue(Temp, Val1Ty)); - break; - } - LLVM_FALLTHROUGH; - case AtomicExpr::AO__atomic_fetch_add: - case AtomicExpr::AO__atomic_fetch_sub: - case AtomicExpr::AO__atomic_add_fetch: - case AtomicExpr::AO__atomic_sub_fetch: - case AtomicExpr::AO__c11_atomic_store: - case AtomicExpr::AO__c11_atomic_exchange: - case AtomicExpr::AO__opencl_atomic_store: - case AtomicExpr::AO__opencl_atomic_exchange: - case AtomicExpr::AO__atomic_store_n: - case AtomicExpr::AO__atomic_exchange_n: - case AtomicExpr::AO__c11_atomic_fetch_and: - case AtomicExpr::AO__c11_atomic_fetch_or: - case AtomicExpr::AO__c11_atomic_fetch_xor: - case AtomicExpr::AO__opencl_atomic_fetch_and: - case AtomicExpr::AO__opencl_atomic_fetch_or: - case AtomicExpr::AO__opencl_atomic_fetch_xor: - case AtomicExpr::AO__opencl_atomic_fetch_min: - case AtomicExpr::AO__opencl_atomic_fetch_max: - case AtomicExpr::AO__atomic_fetch_and: - case AtomicExpr::AO__atomic_fetch_or: - case AtomicExpr::AO__atomic_fetch_xor: - case AtomicExpr::AO__atomic_fetch_nand: - case AtomicExpr::AO__atomic_and_fetch: - case AtomicExpr::AO__atomic_or_fetch: - case AtomicExpr::AO__atomic_xor_fetch: - case AtomicExpr::AO__atomic_nand_fetch: - case AtomicExpr::AO__atomic_fetch_min: - case AtomicExpr::AO__atomic_fetch_max: - Val1 = EmitValToTemp(*this, E->getVal1()); - break; - } - - QualType RValTy = E->getType().getUnqualifiedType(); - - // The inlined atomics only function on iN types, where N is a power of 2. We - // need to make sure (via temporaries if necessary) that all incoming values - // are compatible. - LValue AtomicVal = MakeAddrLValue(Ptr, AtomicTy); - AtomicInfo Atomics(*this, AtomicVal); - - Ptr = Atomics.emitCastToAtomicIntPointer(Ptr); - if (Val1.isValid()) Val1 = Atomics.convertToAtomicIntPointer(Val1); - if (Val2.isValid()) Val2 = Atomics.convertToAtomicIntPointer(Val2); - if (Dest.isValid()) - Dest = Atomics.emitCastToAtomicIntPointer(Dest); - else if (E->isCmpXChg()) - Dest = CreateMemTemp(RValTy, "cmpxchg.bool"); - else if (!RValTy->isVoidType()) - Dest = Atomics.emitCastToAtomicIntPointer(Atomics.CreateTempAlloca()); - - // Use a library call. See: http://gcc.gnu.org/wiki/Atomic/GCCMM/LIbrary . - if (UseLibcall) { - bool UseOptimizedLibcall = false; - switch (E->getOp()) { - case AtomicExpr::AO__c11_atomic_init: - case AtomicExpr::AO__opencl_atomic_init: - llvm_unreachable("Already handled above with EmitAtomicInit!"); - - case AtomicExpr::AO__c11_atomic_fetch_add: - case AtomicExpr::AO__opencl_atomic_fetch_add: - case AtomicExpr::AO__atomic_fetch_add: - case AtomicExpr::AO__c11_atomic_fetch_and: - case AtomicExpr::AO__opencl_atomic_fetch_and: - case AtomicExpr::AO__atomic_fetch_and: - case AtomicExpr::AO__c11_atomic_fetch_or: - case AtomicExpr::AO__opencl_atomic_fetch_or: - case AtomicExpr::AO__atomic_fetch_or: - case AtomicExpr::AO__atomic_fetch_nand: - case AtomicExpr::AO__c11_atomic_fetch_sub: - case AtomicExpr::AO__opencl_atomic_fetch_sub: - case AtomicExpr::AO__atomic_fetch_sub: - case AtomicExpr::AO__c11_atomic_fetch_xor: - case AtomicExpr::AO__opencl_atomic_fetch_xor: - case AtomicExpr::AO__opencl_atomic_fetch_min: - case AtomicExpr::AO__opencl_atomic_fetch_max: - case AtomicExpr::AO__atomic_fetch_xor: - case AtomicExpr::AO__atomic_add_fetch: - case AtomicExpr::AO__atomic_and_fetch: - case AtomicExpr::AO__atomic_nand_fetch: - case AtomicExpr::AO__atomic_or_fetch: - case AtomicExpr::AO__atomic_sub_fetch: - case AtomicExpr::AO__atomic_xor_fetch: - case AtomicExpr::AO__atomic_fetch_min: - case AtomicExpr::AO__atomic_fetch_max: - // For these, only library calls for certain sizes exist. - UseOptimizedLibcall = true; - break; - - case AtomicExpr::AO__atomic_load: - case AtomicExpr::AO__atomic_store: - case AtomicExpr::AO__atomic_exchange: - case AtomicExpr::AO__atomic_compare_exchange: - // Use the generic version if we don't know that the operand will be - // suitably aligned for the optimized version. - if (Misaligned) - break; - LLVM_FALLTHROUGH; - case AtomicExpr::AO__c11_atomic_load: - case AtomicExpr::AO__c11_atomic_store: - case AtomicExpr::AO__c11_atomic_exchange: - case AtomicExpr::AO__c11_atomic_compare_exchange_weak: - case AtomicExpr::AO__c11_atomic_compare_exchange_strong: - case AtomicExpr::AO__opencl_atomic_load: - case AtomicExpr::AO__opencl_atomic_store: - case AtomicExpr::AO__opencl_atomic_exchange: - case AtomicExpr::AO__opencl_atomic_compare_exchange_weak: - case AtomicExpr::AO__opencl_atomic_compare_exchange_strong: - case AtomicExpr::AO__atomic_load_n: - case AtomicExpr::AO__atomic_store_n: - case AtomicExpr::AO__atomic_exchange_n: - case AtomicExpr::AO__atomic_compare_exchange_n: - // Only use optimized library calls for sizes for which they exist. - // FIXME: Size == 16 optimized library functions exist too. - if (Size == 1 || Size == 2 || Size == 4 || Size == 8) - UseOptimizedLibcall = true; - break; - } - - CallArgList Args; - if (!UseOptimizedLibcall) { - // For non-optimized library calls, the size is the first parameter - Args.add(RValue::get(llvm::ConstantInt::get(SizeTy, Size)), - getContext().getSizeType()); - } - // Atomic address is the first or second parameter - // The OpenCL atomic library functions only accept pointer arguments to - // generic address space. - auto CastToGenericAddrSpace = [&](llvm::Value *V, QualType PT) { - if (!E->isOpenCL()) - return V; - auto AS = PT->getAs<PointerType>()->getPointeeType().getAddressSpace(); - if (AS == LangAS::opencl_generic) - return V; - auto DestAS = getContext().getTargetAddressSpace(LangAS::opencl_generic); - auto T = V->getType(); - auto *DestType = T->getPointerElementType()->getPointerTo(DestAS); - - return getTargetHooks().performAddrSpaceCast( - *this, V, AS, LangAS::opencl_generic, DestType, false); - }; - - Args.add(RValue::get(CastToGenericAddrSpace( - EmitCastToVoidPtr(Ptr.getPointer()), E->getPtr()->getType())), - getContext().VoidPtrTy); - - std::string LibCallName; - QualType LoweredMemTy = - MemTy->isPointerType() ? getContext().getIntPtrType() : MemTy; - QualType RetTy; - bool HaveRetTy = false; - llvm::Instruction::BinaryOps PostOp = (llvm::Instruction::BinaryOps)0; - switch (E->getOp()) { - case AtomicExpr::AO__c11_atomic_init: - case AtomicExpr::AO__opencl_atomic_init: - llvm_unreachable("Already handled!"); - - // There is only one libcall for compare an exchange, because there is no - // optimisation benefit possible from a libcall version of a weak compare - // and exchange. - // bool __atomic_compare_exchange(size_t size, void *mem, void *expected, - // void *desired, int success, int failure) - // bool __atomic_compare_exchange_N(T *mem, T *expected, T desired, - // int success, int failure) - case AtomicExpr::AO__c11_atomic_compare_exchange_weak: - case AtomicExpr::AO__c11_atomic_compare_exchange_strong: - case AtomicExpr::AO__opencl_atomic_compare_exchange_weak: - case AtomicExpr::AO__opencl_atomic_compare_exchange_strong: - case AtomicExpr::AO__atomic_compare_exchange: - case AtomicExpr::AO__atomic_compare_exchange_n: - LibCallName = "__atomic_compare_exchange"; - RetTy = getContext().BoolTy; - HaveRetTy = true; - Args.add( - RValue::get(CastToGenericAddrSpace( - EmitCastToVoidPtr(Val1.getPointer()), E->getVal1()->getType())), - getContext().VoidPtrTy); - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val2.getPointer(), - MemTy, E->getExprLoc(), sizeChars); - Args.add(RValue::get(Order), getContext().IntTy); - Order = OrderFail; - break; - // void __atomic_exchange(size_t size, void *mem, void *val, void *return, - // int order) - // T __atomic_exchange_N(T *mem, T val, int order) - case AtomicExpr::AO__c11_atomic_exchange: - case AtomicExpr::AO__opencl_atomic_exchange: - case AtomicExpr::AO__atomic_exchange_n: - case AtomicExpr::AO__atomic_exchange: - LibCallName = "__atomic_exchange"; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - MemTy, E->getExprLoc(), sizeChars); - break; - // void __atomic_store(size_t size, void *mem, void *val, int order) - // void __atomic_store_N(T *mem, T val, int order) - case AtomicExpr::AO__c11_atomic_store: - case AtomicExpr::AO__opencl_atomic_store: - case AtomicExpr::AO__atomic_store: - case AtomicExpr::AO__atomic_store_n: - LibCallName = "__atomic_store"; - RetTy = getContext().VoidTy; - HaveRetTy = true; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - MemTy, E->getExprLoc(), sizeChars); - break; - // void __atomic_load(size_t size, void *mem, void *return, int order) - // T __atomic_load_N(T *mem, int order) - case AtomicExpr::AO__c11_atomic_load: - case AtomicExpr::AO__opencl_atomic_load: - case AtomicExpr::AO__atomic_load: - case AtomicExpr::AO__atomic_load_n: - LibCallName = "__atomic_load"; - break; - // T __atomic_add_fetch_N(T *mem, T val, int order) - // T __atomic_fetch_add_N(T *mem, T val, int order) - case AtomicExpr::AO__atomic_add_fetch: - PostOp = llvm::Instruction::Add; - LLVM_FALLTHROUGH; - case AtomicExpr::AO__c11_atomic_fetch_add: - case AtomicExpr::AO__opencl_atomic_fetch_add: - case AtomicExpr::AO__atomic_fetch_add: - LibCallName = "__atomic_fetch_add"; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - LoweredMemTy, E->getExprLoc(), sizeChars); - break; - // T __atomic_and_fetch_N(T *mem, T val, int order) - // T __atomic_fetch_and_N(T *mem, T val, int order) - case AtomicExpr::AO__atomic_and_fetch: - PostOp = llvm::Instruction::And; - LLVM_FALLTHROUGH; - case AtomicExpr::AO__c11_atomic_fetch_and: - case AtomicExpr::AO__opencl_atomic_fetch_and: - case AtomicExpr::AO__atomic_fetch_and: - LibCallName = "__atomic_fetch_and"; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - MemTy, E->getExprLoc(), sizeChars); - break; - // T __atomic_or_fetch_N(T *mem, T val, int order) - // T __atomic_fetch_or_N(T *mem, T val, int order) - case AtomicExpr::AO__atomic_or_fetch: - PostOp = llvm::Instruction::Or; - LLVM_FALLTHROUGH; - case AtomicExpr::AO__c11_atomic_fetch_or: - case AtomicExpr::AO__opencl_atomic_fetch_or: - case AtomicExpr::AO__atomic_fetch_or: - LibCallName = "__atomic_fetch_or"; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - MemTy, E->getExprLoc(), sizeChars); - break; - // T __atomic_sub_fetch_N(T *mem, T val, int order) - // T __atomic_fetch_sub_N(T *mem, T val, int order) - case AtomicExpr::AO__atomic_sub_fetch: - PostOp = llvm::Instruction::Sub; - LLVM_FALLTHROUGH; - case AtomicExpr::AO__c11_atomic_fetch_sub: - case AtomicExpr::AO__opencl_atomic_fetch_sub: - case AtomicExpr::AO__atomic_fetch_sub: - LibCallName = "__atomic_fetch_sub"; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - LoweredMemTy, E->getExprLoc(), sizeChars); - break; - // T __atomic_xor_fetch_N(T *mem, T val, int order) - // T __atomic_fetch_xor_N(T *mem, T val, int order) - case AtomicExpr::AO__atomic_xor_fetch: - PostOp = llvm::Instruction::Xor; - LLVM_FALLTHROUGH; - case AtomicExpr::AO__c11_atomic_fetch_xor: - case AtomicExpr::AO__opencl_atomic_fetch_xor: - case AtomicExpr::AO__atomic_fetch_xor: - LibCallName = "__atomic_fetch_xor"; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - MemTy, E->getExprLoc(), sizeChars); - break; - case AtomicExpr::AO__atomic_fetch_min: - case AtomicExpr::AO__opencl_atomic_fetch_min: - LibCallName = E->getValueType()->isSignedIntegerType() - ? "__atomic_fetch_min" - : "__atomic_fetch_umin"; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - LoweredMemTy, E->getExprLoc(), sizeChars); - break; - case AtomicExpr::AO__atomic_fetch_max: - case AtomicExpr::AO__opencl_atomic_fetch_max: - LibCallName = E->getValueType()->isSignedIntegerType() - ? "__atomic_fetch_max" - : "__atomic_fetch_umax"; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - LoweredMemTy, E->getExprLoc(), sizeChars); - break; - // T __atomic_nand_fetch_N(T *mem, T val, int order) - // T __atomic_fetch_nand_N(T *mem, T val, int order) - case AtomicExpr::AO__atomic_nand_fetch: - PostOp = llvm::Instruction::And; // the NOT is special cased below - LLVM_FALLTHROUGH; - case AtomicExpr::AO__atomic_fetch_nand: - LibCallName = "__atomic_fetch_nand"; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - MemTy, E->getExprLoc(), sizeChars); - break; - } - - if (E->isOpenCL()) { - LibCallName = std::string("__opencl") + - StringRef(LibCallName).drop_front(1).str(); - - } - // Optimized functions have the size in their name. - if (UseOptimizedLibcall) - LibCallName += "_" + llvm::utostr(Size); - // By default, assume we return a value of the atomic type. - if (!HaveRetTy) { - if (UseOptimizedLibcall) { - // Value is returned directly. - // The function returns an appropriately sized integer type. - RetTy = getContext().getIntTypeForBitwidth( - getContext().toBits(sizeChars), /*Signed=*/false); - } else { - // Value is returned through parameter before the order. - RetTy = getContext().VoidTy; - Args.add(RValue::get(EmitCastToVoidPtr(Dest.getPointer())), - getContext().VoidPtrTy); - } - } - // order is always the last parameter - Args.add(RValue::get(Order), - getContext().IntTy); - if (E->isOpenCL()) - Args.add(RValue::get(Scope), getContext().IntTy); - - // PostOp is only needed for the atomic_*_fetch operations, and - // thus is only needed for and implemented in the - // UseOptimizedLibcall codepath. - assert(UseOptimizedLibcall || !PostOp); - - RValue Res = emitAtomicLibcall(*this, LibCallName, RetTy, Args); - // The value is returned directly from the libcall. - if (E->isCmpXChg()) - return Res; - - // The value is returned directly for optimized libcalls but the expr - // provided an out-param. - if (UseOptimizedLibcall && Res.getScalarVal()) { - llvm::Value *ResVal = Res.getScalarVal(); - if (PostOp) { - llvm::Value *LoadVal1 = Args[1].getRValue(*this).getScalarVal(); - ResVal = Builder.CreateBinOp(PostOp, ResVal, LoadVal1); - } - if (E->getOp() == AtomicExpr::AO__atomic_nand_fetch) - ResVal = Builder.CreateNot(ResVal); - - Builder.CreateStore( - ResVal, - Builder.CreateBitCast(Dest, ResVal->getType()->getPointerTo())); - } - - if (RValTy->isVoidType()) - return RValue::get(nullptr); - - return convertTempToRValue( - Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo()), - RValTy, E->getExprLoc()); - } - - bool IsStore = E->getOp() == AtomicExpr::AO__c11_atomic_store || - E->getOp() == AtomicExpr::AO__opencl_atomic_store || - E->getOp() == AtomicExpr::AO__atomic_store || - E->getOp() == AtomicExpr::AO__atomic_store_n; - bool IsLoad = E->getOp() == AtomicExpr::AO__c11_atomic_load || - E->getOp() == AtomicExpr::AO__opencl_atomic_load || - E->getOp() == AtomicExpr::AO__atomic_load || - E->getOp() == AtomicExpr::AO__atomic_load_n; - - if (isa<llvm::ConstantInt>(Order)) { - auto ord = cast<llvm::ConstantInt>(Order)->getZExtValue(); - // We should not ever get to a case where the ordering isn't a valid C ABI - // value, but it's hard to enforce that in general. - if (llvm::isValidAtomicOrderingCABI(ord)) - switch ((llvm::AtomicOrderingCABI)ord) { - case llvm::AtomicOrderingCABI::relaxed: - EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, - llvm::AtomicOrdering::Monotonic, Scope); - break; - case llvm::AtomicOrderingCABI::consume: - case llvm::AtomicOrderingCABI::acquire: - if (IsStore) - break; // Avoid crashing on code with undefined behavior - EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, - llvm::AtomicOrdering::Acquire, Scope); - break; - case llvm::AtomicOrderingCABI::release: - if (IsLoad) - break; // Avoid crashing on code with undefined behavior - EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, - llvm::AtomicOrdering::Release, Scope); - break; - case llvm::AtomicOrderingCABI::acq_rel: - if (IsLoad || IsStore) - break; // Avoid crashing on code with undefined behavior - EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, - llvm::AtomicOrdering::AcquireRelease, Scope); - break; - case llvm::AtomicOrderingCABI::seq_cst: - EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, - llvm::AtomicOrdering::SequentiallyConsistent, Scope); - break; - } - if (RValTy->isVoidType()) - return RValue::get(nullptr); - - return convertTempToRValue( - Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo( - Dest.getAddressSpace())), - RValTy, E->getExprLoc()); - } - - // Long case, when Order isn't obviously constant. - - // Create all the relevant BB's - llvm::BasicBlock *MonotonicBB = nullptr, *AcquireBB = nullptr, - *ReleaseBB = nullptr, *AcqRelBB = nullptr, - *SeqCstBB = nullptr; - MonotonicBB = createBasicBlock("monotonic", CurFn); - if (!IsStore) - AcquireBB = createBasicBlock("acquire", CurFn); - if (!IsLoad) - ReleaseBB = createBasicBlock("release", CurFn); - if (!IsLoad && !IsStore) - AcqRelBB = createBasicBlock("acqrel", CurFn); - SeqCstBB = createBasicBlock("seqcst", CurFn); - llvm::BasicBlock *ContBB = createBasicBlock("atomic.continue", CurFn); - - // Create the switch for the split - // MonotonicBB is arbitrarily chosen as the default case; in practice, this - // doesn't matter unless someone is crazy enough to use something that - // doesn't fold to a constant for the ordering. - Order = Builder.CreateIntCast(Order, Builder.getInt32Ty(), false); - llvm::SwitchInst *SI = Builder.CreateSwitch(Order, MonotonicBB); - - // Emit all the different atomics - Builder.SetInsertPoint(MonotonicBB); - EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, - llvm::AtomicOrdering::Monotonic, Scope); - Builder.CreateBr(ContBB); - if (!IsStore) { - Builder.SetInsertPoint(AcquireBB); - EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, - llvm::AtomicOrdering::Acquire, Scope); - Builder.CreateBr(ContBB); - SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::consume), - AcquireBB); - SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::acquire), - AcquireBB); - } - if (!IsLoad) { - Builder.SetInsertPoint(ReleaseBB); - EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, - llvm::AtomicOrdering::Release, Scope); - Builder.CreateBr(ContBB); - SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::release), - ReleaseBB); - } - if (!IsLoad && !IsStore) { - Builder.SetInsertPoint(AcqRelBB); - EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, - llvm::AtomicOrdering::AcquireRelease, Scope); - Builder.CreateBr(ContBB); - SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::acq_rel), - AcqRelBB); - } - Builder.SetInsertPoint(SeqCstBB); - EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, - llvm::AtomicOrdering::SequentiallyConsistent, Scope); - Builder.CreateBr(ContBB); - SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::seq_cst), - SeqCstBB); - - // Cleanup and return - Builder.SetInsertPoint(ContBB); - if (RValTy->isVoidType()) - return RValue::get(nullptr); - - assert(Atomics.getValueSizeInBits() <= Atomics.getAtomicSizeInBits()); - return convertTempToRValue( - Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo( - Dest.getAddressSpace())), - RValTy, E->getExprLoc()); -} - -Address AtomicInfo::emitCastToAtomicIntPointer(Address addr) const { - unsigned addrspace = - cast<llvm::PointerType>(addr.getPointer()->getType())->getAddressSpace(); - llvm::IntegerType *ty = - llvm::IntegerType::get(CGF.getLLVMContext(), AtomicSizeInBits); - return CGF.Builder.CreateBitCast(addr, ty->getPointerTo(addrspace)); -} - -Address AtomicInfo::convertToAtomicIntPointer(Address Addr) const { - llvm::Type *Ty = Addr.getElementType(); - uint64_t SourceSizeInBits = CGF.CGM.getDataLayout().getTypeSizeInBits(Ty); - if (SourceSizeInBits != AtomicSizeInBits) { - Address Tmp = CreateTempAlloca(); - CGF.Builder.CreateMemCpy(Tmp, Addr, - std::min(AtomicSizeInBits, SourceSizeInBits) / 8); - Addr = Tmp; - } - - return emitCastToAtomicIntPointer(Addr); -} - -RValue AtomicInfo::convertAtomicTempToRValue(Address addr, - AggValueSlot resultSlot, - SourceLocation loc, - bool asValue) const { - if (LVal.isSimple()) { - if (EvaluationKind == TEK_Aggregate) - return resultSlot.asRValue(); - - // Drill into the padding structure if we have one. - if (hasPadding()) - addr = CGF.Builder.CreateStructGEP(addr, 0, CharUnits()); - - // Otherwise, just convert the temporary to an r-value using the - // normal conversion routine. - return CGF.convertTempToRValue(addr, getValueType(), loc); - } - if (!asValue) - // Get RValue from temp memory as atomic for non-simple lvalues - return RValue::get(CGF.Builder.CreateLoad(addr)); - if (LVal.isBitField()) - return CGF.EmitLoadOfBitfieldLValue( - LValue::MakeBitfield(addr, LVal.getBitFieldInfo(), LVal.getType(), - LVal.getBaseInfo(), TBAAAccessInfo()), loc); - if (LVal.isVectorElt()) - return CGF.EmitLoadOfLValue( - LValue::MakeVectorElt(addr, LVal.getVectorIdx(), LVal.getType(), - LVal.getBaseInfo(), TBAAAccessInfo()), loc); - assert(LVal.isExtVectorElt()); - return CGF.EmitLoadOfExtVectorElementLValue(LValue::MakeExtVectorElt( - addr, LVal.getExtVectorElts(), LVal.getType(), - LVal.getBaseInfo(), TBAAAccessInfo())); -} - -RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal, - AggValueSlot ResultSlot, - SourceLocation Loc, - bool AsValue) const { - // Try not to in some easy cases. - assert(IntVal->getType()->isIntegerTy() && "Expected integer value"); - if (getEvaluationKind() == TEK_Scalar && - (((!LVal.isBitField() || - LVal.getBitFieldInfo().Size == ValueSizeInBits) && - !hasPadding()) || - !AsValue)) { - auto *ValTy = AsValue - ? CGF.ConvertTypeForMem(ValueTy) - : getAtomicAddress().getType()->getPointerElementType(); - if (ValTy->isIntegerTy()) { - assert(IntVal->getType() == ValTy && "Different integer types."); - return RValue::get(CGF.EmitFromMemory(IntVal, ValueTy)); - } else if (ValTy->isPointerTy()) - return RValue::get(CGF.Builder.CreateIntToPtr(IntVal, ValTy)); - else if (llvm::CastInst::isBitCastable(IntVal->getType(), ValTy)) - return RValue::get(CGF.Builder.CreateBitCast(IntVal, ValTy)); - } - - // Create a temporary. This needs to be big enough to hold the - // atomic integer. - Address Temp = Address::invalid(); - bool TempIsVolatile = false; - if (AsValue && getEvaluationKind() == TEK_Aggregate) { - assert(!ResultSlot.isIgnored()); - Temp = ResultSlot.getAddress(); - TempIsVolatile = ResultSlot.isVolatile(); - } else { - Temp = CreateTempAlloca(); - } - - // Slam the integer into the temporary. - Address CastTemp = emitCastToAtomicIntPointer(Temp); - CGF.Builder.CreateStore(IntVal, CastTemp) - ->setVolatile(TempIsVolatile); - - return convertAtomicTempToRValue(Temp, ResultSlot, Loc, AsValue); -} - -void AtomicInfo::EmitAtomicLoadLibcall(llvm::Value *AddForLoaded, - llvm::AtomicOrdering AO, bool) { - // void __atomic_load(size_t size, void *mem, void *return, int order); - CallArgList Args; - Args.add(RValue::get(getAtomicSizeValue()), CGF.getContext().getSizeType()); - Args.add(RValue::get(CGF.EmitCastToVoidPtr(getAtomicPointer())), - CGF.getContext().VoidPtrTy); - Args.add(RValue::get(CGF.EmitCastToVoidPtr(AddForLoaded)), - CGF.getContext().VoidPtrTy); - Args.add( - RValue::get(llvm::ConstantInt::get(CGF.IntTy, (int)llvm::toCABI(AO))), - CGF.getContext().IntTy); - emitAtomicLibcall(CGF, "__atomic_load", CGF.getContext().VoidTy, Args); -} - -llvm::Value *AtomicInfo::EmitAtomicLoadOp(llvm::AtomicOrdering AO, - bool IsVolatile) { - // Okay, we're doing this natively. - Address Addr = getAtomicAddressAsAtomicIntPointer(); - llvm::LoadInst *Load = CGF.Builder.CreateLoad(Addr, "atomic-load"); - Load->setAtomic(AO); - - // Other decoration. - if (IsVolatile) - Load->setVolatile(true); - CGF.CGM.DecorateInstructionWithTBAA(Load, LVal.getTBAAInfo()); - return Load; -} - -/// An LValue is a candidate for having its loads and stores be made atomic if -/// we are operating under /volatile:ms *and* the LValue itself is volatile and -/// performing such an operation can be performed without a libcall. -bool CodeGenFunction::LValueIsSuitableForInlineAtomic(LValue LV) { - if (!CGM.getCodeGenOpts().MSVolatile) return false; - AtomicInfo AI(*this, LV); - bool IsVolatile = LV.isVolatile() || hasVolatileMember(LV.getType()); - // An atomic is inline if we don't need to use a libcall. - bool AtomicIsInline = !AI.shouldUseLibcall(); - // MSVC doesn't seem to do this for types wider than a pointer. - if (getContext().getTypeSize(LV.getType()) > - getContext().getTypeSize(getContext().getIntPtrType())) - return false; - return IsVolatile && AtomicIsInline; -} - -RValue CodeGenFunction::EmitAtomicLoad(LValue LV, SourceLocation SL, - AggValueSlot Slot) { - llvm::AtomicOrdering AO; - bool IsVolatile = LV.isVolatileQualified(); - if (LV.getType()->isAtomicType()) { - AO = llvm::AtomicOrdering::SequentiallyConsistent; - } else { - AO = llvm::AtomicOrdering::Acquire; - IsVolatile = true; - } - return EmitAtomicLoad(LV, SL, AO, IsVolatile, Slot); -} - -RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc, - bool AsValue, llvm::AtomicOrdering AO, - bool IsVolatile) { - // Check whether we should use a library call. - if (shouldUseLibcall()) { - Address TempAddr = Address::invalid(); - if (LVal.isSimple() && !ResultSlot.isIgnored()) { - assert(getEvaluationKind() == TEK_Aggregate); - TempAddr = ResultSlot.getAddress(); - } else - TempAddr = CreateTempAlloca(); - - EmitAtomicLoadLibcall(TempAddr.getPointer(), AO, IsVolatile); - - // Okay, turn that back into the original value or whole atomic (for - // non-simple lvalues) type. - return convertAtomicTempToRValue(TempAddr, ResultSlot, Loc, AsValue); - } - - // Okay, we're doing this natively. - auto *Load = EmitAtomicLoadOp(AO, IsVolatile); - - // If we're ignoring an aggregate return, don't do anything. - if (getEvaluationKind() == TEK_Aggregate && ResultSlot.isIgnored()) - return RValue::getAggregate(Address::invalid(), false); - - // Okay, turn that back into the original value or atomic (for non-simple - // lvalues) type. - return ConvertIntToValueOrAtomic(Load, ResultSlot, Loc, AsValue); -} - -/// Emit a load from an l-value of atomic type. Note that the r-value -/// we produce is an r-value of the atomic *value* type. -RValue CodeGenFunction::EmitAtomicLoad(LValue src, SourceLocation loc, - llvm::AtomicOrdering AO, bool IsVolatile, - AggValueSlot resultSlot) { - AtomicInfo Atomics(*this, src); - return Atomics.EmitAtomicLoad(resultSlot, loc, /*AsValue=*/true, AO, - IsVolatile); -} - -/// Copy an r-value into memory as part of storing to an atomic type. -/// This needs to create a bit-pattern suitable for atomic operations. -void AtomicInfo::emitCopyIntoMemory(RValue rvalue) const { - assert(LVal.isSimple()); - // If we have an r-value, the rvalue should be of the atomic type, - // which means that the caller is responsible for having zeroed - // any padding. Just do an aggregate copy of that type. - if (rvalue.isAggregate()) { - LValue Dest = CGF.MakeAddrLValue(getAtomicAddress(), getAtomicType()); - LValue Src = CGF.MakeAddrLValue(rvalue.getAggregateAddress(), - getAtomicType()); - bool IsVolatile = rvalue.isVolatileQualified() || - LVal.isVolatileQualified(); - CGF.EmitAggregateCopy(Dest, Src, getAtomicType(), - AggValueSlot::DoesNotOverlap, IsVolatile); - return; - } - - // Okay, otherwise we're copying stuff. - - // Zero out the buffer if necessary. - emitMemSetZeroIfNecessary(); - - // Drill past the padding if present. - LValue TempLVal = projectValue(); - - // Okay, store the rvalue in. - if (rvalue.isScalar()) { - CGF.EmitStoreOfScalar(rvalue.getScalarVal(), TempLVal, /*init*/ true); - } else { - CGF.EmitStoreOfComplex(rvalue.getComplexVal(), TempLVal, /*init*/ true); - } -} - - -/// Materialize an r-value into memory for the purposes of storing it -/// to an atomic type. -Address AtomicInfo::materializeRValue(RValue rvalue) const { - // Aggregate r-values are already in memory, and EmitAtomicStore - // requires them to be values of the atomic type. - if (rvalue.isAggregate()) - return rvalue.getAggregateAddress(); - - // Otherwise, make a temporary and materialize into it. - LValue TempLV = CGF.MakeAddrLValue(CreateTempAlloca(), getAtomicType()); - AtomicInfo Atomics(CGF, TempLV); - Atomics.emitCopyIntoMemory(rvalue); - return TempLV.getAddress(); -} - -llvm::Value *AtomicInfo::convertRValueToInt(RValue RVal) const { - // If we've got a scalar value of the right size, try to avoid going - // through memory. - if (RVal.isScalar() && (!hasPadding() || !LVal.isSimple())) { - llvm::Value *Value = RVal.getScalarVal(); - if (isa<llvm::IntegerType>(Value->getType())) - return CGF.EmitToMemory(Value, ValueTy); - else { - llvm::IntegerType *InputIntTy = llvm::IntegerType::get( - CGF.getLLVMContext(), - LVal.isSimple() ? getValueSizeInBits() : getAtomicSizeInBits()); - if (isa<llvm::PointerType>(Value->getType())) - return CGF.Builder.CreatePtrToInt(Value, InputIntTy); - else if (llvm::BitCastInst::isBitCastable(Value->getType(), InputIntTy)) - return CGF.Builder.CreateBitCast(Value, InputIntTy); - } - } - // Otherwise, we need to go through memory. - // Put the r-value in memory. - Address Addr = materializeRValue(RVal); - - // Cast the temporary to the atomic int type and pull a value out. - Addr = emitCastToAtomicIntPointer(Addr); - return CGF.Builder.CreateLoad(Addr); -} - -std::pair<llvm::Value *, llvm::Value *> AtomicInfo::EmitAtomicCompareExchangeOp( - llvm::Value *ExpectedVal, llvm::Value *DesiredVal, - llvm::AtomicOrdering Success, llvm::AtomicOrdering Failure, bool IsWeak) { - // Do the atomic store. - Address Addr = getAtomicAddressAsAtomicIntPointer(); - auto *Inst = CGF.Builder.CreateAtomicCmpXchg(Addr.getPointer(), - ExpectedVal, DesiredVal, - Success, Failure); - // Other decoration. - Inst->setVolatile(LVal.isVolatileQualified()); - Inst->setWeak(IsWeak); - - // Okay, turn that back into the original value type. - auto *PreviousVal = CGF.Builder.CreateExtractValue(Inst, /*Idxs=*/0); - auto *SuccessFailureVal = CGF.Builder.CreateExtractValue(Inst, /*Idxs=*/1); - return std::make_pair(PreviousVal, SuccessFailureVal); -} - -llvm::Value * -AtomicInfo::EmitAtomicCompareExchangeLibcall(llvm::Value *ExpectedAddr, - llvm::Value *DesiredAddr, - llvm::AtomicOrdering Success, - llvm::AtomicOrdering Failure) { - // bool __atomic_compare_exchange(size_t size, void *obj, void *expected, - // void *desired, int success, int failure); - CallArgList Args; - Args.add(RValue::get(getAtomicSizeValue()), CGF.getContext().getSizeType()); - Args.add(RValue::get(CGF.EmitCastToVoidPtr(getAtomicPointer())), - CGF.getContext().VoidPtrTy); - Args.add(RValue::get(CGF.EmitCastToVoidPtr(ExpectedAddr)), - CGF.getContext().VoidPtrTy); - Args.add(RValue::get(CGF.EmitCastToVoidPtr(DesiredAddr)), - CGF.getContext().VoidPtrTy); - Args.add(RValue::get( - llvm::ConstantInt::get(CGF.IntTy, (int)llvm::toCABI(Success))), - CGF.getContext().IntTy); - Args.add(RValue::get( - llvm::ConstantInt::get(CGF.IntTy, (int)llvm::toCABI(Failure))), - CGF.getContext().IntTy); - auto SuccessFailureRVal = emitAtomicLibcall(CGF, "__atomic_compare_exchange", - CGF.getContext().BoolTy, Args); - - return SuccessFailureRVal.getScalarVal(); -} - -std::pair<RValue, llvm::Value *> AtomicInfo::EmitAtomicCompareExchange( - RValue Expected, RValue Desired, llvm::AtomicOrdering Success, - llvm::AtomicOrdering Failure, bool IsWeak) { - if (isStrongerThan(Failure, Success)) - // Don't assert on undefined behavior "failure argument shall be no stronger - // than the success argument". - Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(Success); - - // Check whether we should use a library call. - if (shouldUseLibcall()) { - // Produce a source address. - Address ExpectedAddr = materializeRValue(Expected); - Address DesiredAddr = materializeRValue(Desired); - auto *Res = EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(), - DesiredAddr.getPointer(), - Success, Failure); - return std::make_pair( - convertAtomicTempToRValue(ExpectedAddr, AggValueSlot::ignored(), - SourceLocation(), /*AsValue=*/false), - Res); - } - - // If we've got a scalar value of the right size, try to avoid going - // through memory. - auto *ExpectedVal = convertRValueToInt(Expected); - auto *DesiredVal = convertRValueToInt(Desired); - auto Res = EmitAtomicCompareExchangeOp(ExpectedVal, DesiredVal, Success, - Failure, IsWeak); - return std::make_pair( - ConvertIntToValueOrAtomic(Res.first, AggValueSlot::ignored(), - SourceLocation(), /*AsValue=*/false), - Res.second); -} - -static void -EmitAtomicUpdateValue(CodeGenFunction &CGF, AtomicInfo &Atomics, RValue OldRVal, - const llvm::function_ref<RValue(RValue)> &UpdateOp, - Address DesiredAddr) { - RValue UpRVal; - LValue AtomicLVal = Atomics.getAtomicLValue(); - LValue DesiredLVal; - if (AtomicLVal.isSimple()) { - UpRVal = OldRVal; - DesiredLVal = CGF.MakeAddrLValue(DesiredAddr, AtomicLVal.getType()); - } else { - // Build new lvalue for temp address - Address Ptr = Atomics.materializeRValue(OldRVal); - LValue UpdateLVal; - if (AtomicLVal.isBitField()) { - UpdateLVal = - LValue::MakeBitfield(Ptr, AtomicLVal.getBitFieldInfo(), - AtomicLVal.getType(), - AtomicLVal.getBaseInfo(), - AtomicLVal.getTBAAInfo()); - DesiredLVal = - LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(), - AtomicLVal.getType(), AtomicLVal.getBaseInfo(), - AtomicLVal.getTBAAInfo()); - } else if (AtomicLVal.isVectorElt()) { - UpdateLVal = LValue::MakeVectorElt(Ptr, AtomicLVal.getVectorIdx(), - AtomicLVal.getType(), - AtomicLVal.getBaseInfo(), - AtomicLVal.getTBAAInfo()); - DesiredLVal = LValue::MakeVectorElt( - DesiredAddr, AtomicLVal.getVectorIdx(), AtomicLVal.getType(), - AtomicLVal.getBaseInfo(), AtomicLVal.getTBAAInfo()); - } else { - assert(AtomicLVal.isExtVectorElt()); - UpdateLVal = LValue::MakeExtVectorElt(Ptr, AtomicLVal.getExtVectorElts(), - AtomicLVal.getType(), - AtomicLVal.getBaseInfo(), - AtomicLVal.getTBAAInfo()); - DesiredLVal = LValue::MakeExtVectorElt( - DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(), - AtomicLVal.getBaseInfo(), AtomicLVal.getTBAAInfo()); - } - UpRVal = CGF.EmitLoadOfLValue(UpdateLVal, SourceLocation()); - } - // Store new value in the corresponding memory area - RValue NewRVal = UpdateOp(UpRVal); - if (NewRVal.isScalar()) { - CGF.EmitStoreThroughLValue(NewRVal, DesiredLVal); - } else { - assert(NewRVal.isComplex()); - CGF.EmitStoreOfComplex(NewRVal.getComplexVal(), DesiredLVal, - /*isInit=*/false); - } -} - -void AtomicInfo::EmitAtomicUpdateLibcall( - llvm::AtomicOrdering AO, const llvm::function_ref<RValue(RValue)> &UpdateOp, - bool IsVolatile) { - auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO); - - Address ExpectedAddr = CreateTempAlloca(); - - EmitAtomicLoadLibcall(ExpectedAddr.getPointer(), AO, IsVolatile); - auto *ContBB = CGF.createBasicBlock("atomic_cont"); - auto *ExitBB = CGF.createBasicBlock("atomic_exit"); - CGF.EmitBlock(ContBB); - Address DesiredAddr = CreateTempAlloca(); - if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) || - requiresMemSetZero(getAtomicAddress().getElementType())) { - auto *OldVal = CGF.Builder.CreateLoad(ExpectedAddr); - CGF.Builder.CreateStore(OldVal, DesiredAddr); - } - auto OldRVal = convertAtomicTempToRValue(ExpectedAddr, - AggValueSlot::ignored(), - SourceLocation(), /*AsValue=*/false); - EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, DesiredAddr); - auto *Res = - EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(), - DesiredAddr.getPointer(), - AO, Failure); - CGF.Builder.CreateCondBr(Res, ExitBB, ContBB); - CGF.EmitBlock(ExitBB, /*IsFinished=*/true); -} - -void AtomicInfo::EmitAtomicUpdateOp( - llvm::AtomicOrdering AO, const llvm::function_ref<RValue(RValue)> &UpdateOp, - bool IsVolatile) { - auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO); - - // Do the atomic load. - auto *OldVal = EmitAtomicLoadOp(AO, IsVolatile); - // For non-simple lvalues perform compare-and-swap procedure. - auto *ContBB = CGF.createBasicBlock("atomic_cont"); - auto *ExitBB = CGF.createBasicBlock("atomic_exit"); - auto *CurBB = CGF.Builder.GetInsertBlock(); - CGF.EmitBlock(ContBB); - llvm::PHINode *PHI = CGF.Builder.CreatePHI(OldVal->getType(), - /*NumReservedValues=*/2); - PHI->addIncoming(OldVal, CurBB); - Address NewAtomicAddr = CreateTempAlloca(); - Address NewAtomicIntAddr = emitCastToAtomicIntPointer(NewAtomicAddr); - if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) || - requiresMemSetZero(getAtomicAddress().getElementType())) { - CGF.Builder.CreateStore(PHI, NewAtomicIntAddr); - } - auto OldRVal = ConvertIntToValueOrAtomic(PHI, AggValueSlot::ignored(), - SourceLocation(), /*AsValue=*/false); - EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, NewAtomicAddr); - auto *DesiredVal = CGF.Builder.CreateLoad(NewAtomicIntAddr); - // Try to write new value using cmpxchg operation - auto Res = EmitAtomicCompareExchangeOp(PHI, DesiredVal, AO, Failure); - PHI->addIncoming(Res.first, CGF.Builder.GetInsertBlock()); - CGF.Builder.CreateCondBr(Res.second, ExitBB, ContBB); - CGF.EmitBlock(ExitBB, /*IsFinished=*/true); -} - -static void EmitAtomicUpdateValue(CodeGenFunction &CGF, AtomicInfo &Atomics, - RValue UpdateRVal, Address DesiredAddr) { - LValue AtomicLVal = Atomics.getAtomicLValue(); - LValue DesiredLVal; - // Build new lvalue for temp address - if (AtomicLVal.isBitField()) { - DesiredLVal = - LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(), - AtomicLVal.getType(), AtomicLVal.getBaseInfo(), - AtomicLVal.getTBAAInfo()); - } else if (AtomicLVal.isVectorElt()) { - DesiredLVal = - LValue::MakeVectorElt(DesiredAddr, AtomicLVal.getVectorIdx(), - AtomicLVal.getType(), AtomicLVal.getBaseInfo(), - AtomicLVal.getTBAAInfo()); - } else { - assert(AtomicLVal.isExtVectorElt()); - DesiredLVal = LValue::MakeExtVectorElt( - DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(), - AtomicLVal.getBaseInfo(), AtomicLVal.getTBAAInfo()); - } - // Store new value in the corresponding memory area - assert(UpdateRVal.isScalar()); - CGF.EmitStoreThroughLValue(UpdateRVal, DesiredLVal); -} - -void AtomicInfo::EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO, - RValue UpdateRVal, bool IsVolatile) { - auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO); - - Address ExpectedAddr = CreateTempAlloca(); - - EmitAtomicLoadLibcall(ExpectedAddr.getPointer(), AO, IsVolatile); - auto *ContBB = CGF.createBasicBlock("atomic_cont"); - auto *ExitBB = CGF.createBasicBlock("atomic_exit"); - CGF.EmitBlock(ContBB); - Address DesiredAddr = CreateTempAlloca(); - if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) || - requiresMemSetZero(getAtomicAddress().getElementType())) { - auto *OldVal = CGF.Builder.CreateLoad(ExpectedAddr); - CGF.Builder.CreateStore(OldVal, DesiredAddr); - } - EmitAtomicUpdateValue(CGF, *this, UpdateRVal, DesiredAddr); - auto *Res = - EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(), - DesiredAddr.getPointer(), - AO, Failure); - CGF.Builder.CreateCondBr(Res, ExitBB, ContBB); - CGF.EmitBlock(ExitBB, /*IsFinished=*/true); -} - -void AtomicInfo::EmitAtomicUpdateOp(llvm::AtomicOrdering AO, RValue UpdateRVal, - bool IsVolatile) { - auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO); - - // Do the atomic load. - auto *OldVal = EmitAtomicLoadOp(AO, IsVolatile); - // For non-simple lvalues perform compare-and-swap procedure. - auto *ContBB = CGF.createBasicBlock("atomic_cont"); - auto *ExitBB = CGF.createBasicBlock("atomic_exit"); - auto *CurBB = CGF.Builder.GetInsertBlock(); - CGF.EmitBlock(ContBB); - llvm::PHINode *PHI = CGF.Builder.CreatePHI(OldVal->getType(), - /*NumReservedValues=*/2); - PHI->addIncoming(OldVal, CurBB); - Address NewAtomicAddr = CreateTempAlloca(); - Address NewAtomicIntAddr = emitCastToAtomicIntPointer(NewAtomicAddr); - if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) || - requiresMemSetZero(getAtomicAddress().getElementType())) { - CGF.Builder.CreateStore(PHI, NewAtomicIntAddr); - } - EmitAtomicUpdateValue(CGF, *this, UpdateRVal, NewAtomicAddr); - auto *DesiredVal = CGF.Builder.CreateLoad(NewAtomicIntAddr); - // Try to write new value using cmpxchg operation - auto Res = EmitAtomicCompareExchangeOp(PHI, DesiredVal, AO, Failure); - PHI->addIncoming(Res.first, CGF.Builder.GetInsertBlock()); - CGF.Builder.CreateCondBr(Res.second, ExitBB, ContBB); - CGF.EmitBlock(ExitBB, /*IsFinished=*/true); -} - -void AtomicInfo::EmitAtomicUpdate( - llvm::AtomicOrdering AO, const llvm::function_ref<RValue(RValue)> &UpdateOp, - bool IsVolatile) { - if (shouldUseLibcall()) { - EmitAtomicUpdateLibcall(AO, UpdateOp, IsVolatile); - } else { - EmitAtomicUpdateOp(AO, UpdateOp, IsVolatile); - } -} - -void AtomicInfo::EmitAtomicUpdate(llvm::AtomicOrdering AO, RValue UpdateRVal, - bool IsVolatile) { - if (shouldUseLibcall()) { - EmitAtomicUpdateLibcall(AO, UpdateRVal, IsVolatile); - } else { - EmitAtomicUpdateOp(AO, UpdateRVal, IsVolatile); - } -} - -void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue lvalue, - bool isInit) { - bool IsVolatile = lvalue.isVolatileQualified(); - llvm::AtomicOrdering AO; - if (lvalue.getType()->isAtomicType()) { - AO = llvm::AtomicOrdering::SequentiallyConsistent; - } else { - AO = llvm::AtomicOrdering::Release; - IsVolatile = true; - } - return EmitAtomicStore(rvalue, lvalue, AO, IsVolatile, isInit); -} - -/// Emit a store to an l-value of atomic type. -/// -/// Note that the r-value is expected to be an r-value *of the atomic -/// type*; this means that for aggregate r-values, it should include -/// storage for any padding that was necessary. -void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, - llvm::AtomicOrdering AO, bool IsVolatile, - bool isInit) { - // If this is an aggregate r-value, it should agree in type except - // maybe for address-space qualification. - assert(!rvalue.isAggregate() || - rvalue.getAggregateAddress().getElementType() - == dest.getAddress().getElementType()); - - AtomicInfo atomics(*this, dest); - LValue LVal = atomics.getAtomicLValue(); - - // If this is an initialization, just put the value there normally. - if (LVal.isSimple()) { - if (isInit) { - atomics.emitCopyIntoMemory(rvalue); - return; - } - - // Check whether we should use a library call. - if (atomics.shouldUseLibcall()) { - // Produce a source address. - Address srcAddr = atomics.materializeRValue(rvalue); - - // void __atomic_store(size_t size, void *mem, void *val, int order) - CallArgList args; - args.add(RValue::get(atomics.getAtomicSizeValue()), - getContext().getSizeType()); - args.add(RValue::get(EmitCastToVoidPtr(atomics.getAtomicPointer())), - getContext().VoidPtrTy); - args.add(RValue::get(EmitCastToVoidPtr(srcAddr.getPointer())), - getContext().VoidPtrTy); - args.add( - RValue::get(llvm::ConstantInt::get(IntTy, (int)llvm::toCABI(AO))), - getContext().IntTy); - emitAtomicLibcall(*this, "__atomic_store", getContext().VoidTy, args); - return; - } - - // Okay, we're doing this natively. - llvm::Value *intValue = atomics.convertRValueToInt(rvalue); - - // Do the atomic store. - Address addr = - atomics.emitCastToAtomicIntPointer(atomics.getAtomicAddress()); - intValue = Builder.CreateIntCast( - intValue, addr.getElementType(), /*isSigned=*/false); - llvm::StoreInst *store = Builder.CreateStore(intValue, addr); - - // Initializations don't need to be atomic. - if (!isInit) - store->setAtomic(AO); - - // Other decoration. - if (IsVolatile) - store->setVolatile(true); - CGM.DecorateInstructionWithTBAA(store, dest.getTBAAInfo()); - return; - } - - // Emit simple atomic update operation. - atomics.EmitAtomicUpdate(AO, rvalue, IsVolatile); -} - -/// Emit a compare-and-exchange op for atomic type. -/// -std::pair<RValue, llvm::Value *> CodeGenFunction::EmitAtomicCompareExchange( - LValue Obj, RValue Expected, RValue Desired, SourceLocation Loc, - llvm::AtomicOrdering Success, llvm::AtomicOrdering Failure, bool IsWeak, - AggValueSlot Slot) { - // If this is an aggregate r-value, it should agree in type except - // maybe for address-space qualification. - assert(!Expected.isAggregate() || - Expected.getAggregateAddress().getElementType() == - Obj.getAddress().getElementType()); - assert(!Desired.isAggregate() || - Desired.getAggregateAddress().getElementType() == - Obj.getAddress().getElementType()); - AtomicInfo Atomics(*this, Obj); - - return Atomics.EmitAtomicCompareExchange(Expected, Desired, Success, Failure, - IsWeak); -} - -void CodeGenFunction::EmitAtomicUpdate( - LValue LVal, llvm::AtomicOrdering AO, - const llvm::function_ref<RValue(RValue)> &UpdateOp, bool IsVolatile) { - AtomicInfo Atomics(*this, LVal); - Atomics.EmitAtomicUpdate(AO, UpdateOp, IsVolatile); -} - -void CodeGenFunction::EmitAtomicInit(Expr *init, LValue dest) { - AtomicInfo atomics(*this, dest); - - switch (atomics.getEvaluationKind()) { - case TEK_Scalar: { - llvm::Value *value = EmitScalarExpr(init); - atomics.emitCopyIntoMemory(RValue::get(value)); - return; - } - - case TEK_Complex: { - ComplexPairTy value = EmitComplexExpr(init); - atomics.emitCopyIntoMemory(RValue::getComplex(value)); - return; - } - - case TEK_Aggregate: { - // Fix up the destination if the initializer isn't an expression - // of atomic type. - bool Zeroed = false; - if (!init->getType()->isAtomicType()) { - Zeroed = atomics.emitMemSetZeroIfNecessary(); - dest = atomics.projectValue(); - } - - // Evaluate the expression directly into the destination. - AggValueSlot slot = AggValueSlot::forLValue(dest, - AggValueSlot::IsNotDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - AggValueSlot::DoesNotOverlap, - Zeroed ? AggValueSlot::IsZeroed : - AggValueSlot::IsNotZeroed); - - EmitAggExpr(init, slot); - return; - } - } - llvm_unreachable("bad evaluation kind"); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp deleted file mode 100644 index fa3c3ee8610..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp +++ /dev/null @@ -1,3036 +0,0 @@ -//===--- CGBlocks.cpp - Emit LLVM Code for declarations ---------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code to emit blocks. -// -//===----------------------------------------------------------------------===// - -#include "CGBlocks.h" -#include "CGCXXABI.h" -#include "CGDebugInfo.h" -#include "CGObjCRuntime.h" -#include "CGOpenCLRuntime.h" -#include "CodeGenFunction.h" -#include "CodeGenModule.h" -#include "ConstantEmitter.h" -#include "TargetInfo.h" -#include "clang/AST/DeclObjC.h" -#include "clang/CodeGen/ConstantInitBuilder.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/ScopedPrinter.h" -#include <algorithm> -#include <cstdio> - -using namespace clang; -using namespace CodeGen; - -CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name) - : Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false), - HasCXXObject(false), UsesStret(false), HasCapturedVariableLayout(false), - CapturesNonExternalType(false), LocalAddress(Address::invalid()), - StructureType(nullptr), Block(block), DominatingIP(nullptr) { - - // Skip asm prefix, if any. 'name' is usually taken directly from - // the mangled name of the enclosing function. - if (!name.empty() && name[0] == '\01') - name = name.substr(1); -} - -// Anchor the vtable to this translation unit. -BlockByrefHelpers::~BlockByrefHelpers() {} - -/// Build the given block as a global block. -static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, - const CGBlockInfo &blockInfo, - llvm::Constant *blockFn); - -/// Build the helper function to copy a block. -static llvm::Constant *buildCopyHelper(CodeGenModule &CGM, - const CGBlockInfo &blockInfo) { - return CodeGenFunction(CGM).GenerateCopyHelperFunction(blockInfo); -} - -/// Build the helper function to dispose of a block. -static llvm::Constant *buildDisposeHelper(CodeGenModule &CGM, - const CGBlockInfo &blockInfo) { - return CodeGenFunction(CGM).GenerateDestroyHelperFunction(blockInfo); -} - -namespace { - -/// Represents a type of copy/destroy operation that should be performed for an -/// entity that's captured by a block. -enum class BlockCaptureEntityKind { - CXXRecord, // Copy or destroy - ARCWeak, - ARCStrong, - NonTrivialCStruct, - BlockObject, // Assign or release - None -}; - -/// Represents a captured entity that requires extra operations in order for -/// this entity to be copied or destroyed correctly. -struct BlockCaptureManagedEntity { - BlockCaptureEntityKind CopyKind, DisposeKind; - BlockFieldFlags CopyFlags, DisposeFlags; - const BlockDecl::Capture *CI; - const CGBlockInfo::Capture *Capture; - - BlockCaptureManagedEntity(BlockCaptureEntityKind CopyType, - BlockCaptureEntityKind DisposeType, - BlockFieldFlags CopyFlags, - BlockFieldFlags DisposeFlags, - const BlockDecl::Capture &CI, - const CGBlockInfo::Capture &Capture) - : CopyKind(CopyType), DisposeKind(DisposeType), CopyFlags(CopyFlags), - DisposeFlags(DisposeFlags), CI(&CI), Capture(&Capture) {} - - bool operator<(const BlockCaptureManagedEntity &Other) const { - return Capture->getOffset() < Other.Capture->getOffset(); - } -}; - -enum class CaptureStrKind { - // String for the copy helper. - CopyHelper, - // String for the dispose helper. - DisposeHelper, - // Merge the strings for the copy helper and dispose helper. - Merged -}; - -} // end anonymous namespace - -static void findBlockCapturedManagedEntities( - const CGBlockInfo &BlockInfo, const LangOptions &LangOpts, - SmallVectorImpl<BlockCaptureManagedEntity> &ManagedCaptures); - -static std::string getBlockCaptureStr(const BlockCaptureManagedEntity &E, - CaptureStrKind StrKind, - CharUnits BlockAlignment, - CodeGenModule &CGM); - -static std::string getBlockDescriptorName(const CGBlockInfo &BlockInfo, - CodeGenModule &CGM) { - std::string Name = "__block_descriptor_"; - Name += llvm::to_string(BlockInfo.BlockSize.getQuantity()) + "_"; - - if (BlockInfo.needsCopyDisposeHelpers()) { - if (CGM.getLangOpts().Exceptions) - Name += "e"; - if (CGM.getCodeGenOpts().ObjCAutoRefCountExceptions) - Name += "a"; - Name += llvm::to_string(BlockInfo.BlockAlign.getQuantity()) + "_"; - - SmallVector<BlockCaptureManagedEntity, 4> ManagedCaptures; - findBlockCapturedManagedEntities(BlockInfo, CGM.getContext().getLangOpts(), - ManagedCaptures); - - for (const BlockCaptureManagedEntity &E : ManagedCaptures) { - Name += llvm::to_string(E.Capture->getOffset().getQuantity()); - - if (E.CopyKind == E.DisposeKind) { - // If CopyKind and DisposeKind are the same, merge the capture - // information. - assert(E.CopyKind != BlockCaptureEntityKind::None && - "shouldn't see BlockCaptureManagedEntity that is None"); - Name += getBlockCaptureStr(E, CaptureStrKind::Merged, - BlockInfo.BlockAlign, CGM); - } else { - // If CopyKind and DisposeKind are not the same, which can happen when - // either Kind is None or the captured object is a __strong block, - // concatenate the copy and dispose strings. - Name += getBlockCaptureStr(E, CaptureStrKind::CopyHelper, - BlockInfo.BlockAlign, CGM); - Name += getBlockCaptureStr(E, CaptureStrKind::DisposeHelper, - BlockInfo.BlockAlign, CGM); - } - } - Name += "_"; - } - - std::string TypeAtEncoding = - CGM.getContext().getObjCEncodingForBlock(BlockInfo.getBlockExpr()); - /// Replace occurrences of '@' with '\1'. '@' is reserved on ELF platforms as - /// a separator between symbol name and symbol version. - std::replace(TypeAtEncoding.begin(), TypeAtEncoding.end(), '@', '\1'); - Name += "e" + llvm::to_string(TypeAtEncoding.size()) + "_" + TypeAtEncoding; - Name += "l" + CGM.getObjCRuntime().getRCBlockLayoutStr(CGM, BlockInfo); - return Name; -} - -/// buildBlockDescriptor - Build the block descriptor meta-data for a block. -/// buildBlockDescriptor is accessed from 5th field of the Block_literal -/// meta-data and contains stationary information about the block literal. -/// Its definition will have 4 (or optionally 6) words. -/// \code -/// struct Block_descriptor { -/// unsigned long reserved; -/// unsigned long size; // size of Block_literal metadata in bytes. -/// void *copy_func_helper_decl; // optional copy helper. -/// void *destroy_func_decl; // optional destructor helper. -/// void *block_method_encoding_address; // @encode for block literal signature. -/// void *block_layout_info; // encoding of captured block variables. -/// }; -/// \endcode -static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM, - const CGBlockInfo &blockInfo) { - ASTContext &C = CGM.getContext(); - - llvm::IntegerType *ulong = - cast<llvm::IntegerType>(CGM.getTypes().ConvertType(C.UnsignedLongTy)); - llvm::PointerType *i8p = nullptr; - if (CGM.getLangOpts().OpenCL) - i8p = - llvm::Type::getInt8PtrTy( - CGM.getLLVMContext(), C.getTargetAddressSpace(LangAS::opencl_constant)); - else - i8p = CGM.VoidPtrTy; - - std::string descName; - - // If an equivalent block descriptor global variable exists, return it. - if (C.getLangOpts().ObjC && - CGM.getLangOpts().getGC() == LangOptions::NonGC) { - descName = getBlockDescriptorName(blockInfo, CGM); - if (llvm::GlobalValue *desc = CGM.getModule().getNamedValue(descName)) - return llvm::ConstantExpr::getBitCast(desc, - CGM.getBlockDescriptorType()); - } - - // If there isn't an equivalent block descriptor global variable, create a new - // one. - ConstantInitBuilder builder(CGM); - auto elements = builder.beginStruct(); - - // reserved - elements.addInt(ulong, 0); - - // Size - // FIXME: What is the right way to say this doesn't fit? We should give - // a user diagnostic in that case. Better fix would be to change the - // API to size_t. - elements.addInt(ulong, blockInfo.BlockSize.getQuantity()); - - // Optional copy/dispose helpers. - bool hasInternalHelper = false; - if (blockInfo.needsCopyDisposeHelpers()) { - // copy_func_helper_decl - llvm::Constant *copyHelper = buildCopyHelper(CGM, blockInfo); - elements.add(copyHelper); - - // destroy_func_decl - llvm::Constant *disposeHelper = buildDisposeHelper(CGM, blockInfo); - elements.add(disposeHelper); - - if (cast<llvm::Function>(copyHelper->getOperand(0))->hasInternalLinkage() || - cast<llvm::Function>(disposeHelper->getOperand(0)) - ->hasInternalLinkage()) - hasInternalHelper = true; - } - - // Signature. Mandatory ObjC-style method descriptor @encode sequence. - std::string typeAtEncoding = - CGM.getContext().getObjCEncodingForBlock(blockInfo.getBlockExpr()); - elements.add(llvm::ConstantExpr::getBitCast( - CGM.GetAddrOfConstantCString(typeAtEncoding).getPointer(), i8p)); - - // GC layout. - if (C.getLangOpts().ObjC) { - if (CGM.getLangOpts().getGC() != LangOptions::NonGC) - elements.add(CGM.getObjCRuntime().BuildGCBlockLayout(CGM, blockInfo)); - else - elements.add(CGM.getObjCRuntime().BuildRCBlockLayout(CGM, blockInfo)); - } - else - elements.addNullPointer(i8p); - - unsigned AddrSpace = 0; - if (C.getLangOpts().OpenCL) - AddrSpace = C.getTargetAddressSpace(LangAS::opencl_constant); - - llvm::GlobalValue::LinkageTypes linkage; - if (descName.empty()) { - linkage = llvm::GlobalValue::InternalLinkage; - descName = "__block_descriptor_tmp"; - } else if (hasInternalHelper) { - // If either the copy helper or the dispose helper has internal linkage, - // the block descriptor must have internal linkage too. - linkage = llvm::GlobalValue::InternalLinkage; - } else { - linkage = llvm::GlobalValue::LinkOnceODRLinkage; - } - - llvm::GlobalVariable *global = - elements.finishAndCreateGlobal(descName, CGM.getPointerAlign(), - /*constant*/ true, linkage, AddrSpace); - - if (linkage == llvm::GlobalValue::LinkOnceODRLinkage) { - global->setVisibility(llvm::GlobalValue::HiddenVisibility); - global->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - } - - return llvm::ConstantExpr::getBitCast(global, CGM.getBlockDescriptorType()); -} - -/* - Purely notional variadic template describing the layout of a block. - - template <class _ResultType, class... _ParamTypes, class... _CaptureTypes> - struct Block_literal { - /// Initialized to one of: - /// extern void *_NSConcreteStackBlock[]; - /// extern void *_NSConcreteGlobalBlock[]; - /// - /// In theory, we could start one off malloc'ed by setting - /// BLOCK_NEEDS_FREE, giving it a refcount of 1, and using - /// this isa: - /// extern void *_NSConcreteMallocBlock[]; - struct objc_class *isa; - - /// These are the flags (with corresponding bit number) that the - /// compiler is actually supposed to know about. - /// 23. BLOCK_IS_NOESCAPE - indicates that the block is non-escaping - /// 25. BLOCK_HAS_COPY_DISPOSE - indicates that the block - /// descriptor provides copy and dispose helper functions - /// 26. BLOCK_HAS_CXX_OBJ - indicates that there's a captured - /// object with a nontrivial destructor or copy constructor - /// 28. BLOCK_IS_GLOBAL - indicates that the block is allocated - /// as global memory - /// 29. BLOCK_USE_STRET - indicates that the block function - /// uses stret, which objc_msgSend needs to know about - /// 30. BLOCK_HAS_SIGNATURE - indicates that the block has an - /// @encoded signature string - /// And we're not supposed to manipulate these: - /// 24. BLOCK_NEEDS_FREE - indicates that the block has been moved - /// to malloc'ed memory - /// 27. BLOCK_IS_GC - indicates that the block has been moved to - /// to GC-allocated memory - /// Additionally, the bottom 16 bits are a reference count which - /// should be zero on the stack. - int flags; - - /// Reserved; should be zero-initialized. - int reserved; - - /// Function pointer generated from block literal. - _ResultType (*invoke)(Block_literal *, _ParamTypes...); - - /// Block description metadata generated from block literal. - struct Block_descriptor *block_descriptor; - - /// Captured values follow. - _CapturesTypes captures...; - }; - */ - -namespace { - /// A chunk of data that we actually have to capture in the block. - struct BlockLayoutChunk { - CharUnits Alignment; - CharUnits Size; - Qualifiers::ObjCLifetime Lifetime; - const BlockDecl::Capture *Capture; // null for 'this' - llvm::Type *Type; - QualType FieldType; - - BlockLayoutChunk(CharUnits align, CharUnits size, - Qualifiers::ObjCLifetime lifetime, - const BlockDecl::Capture *capture, - llvm::Type *type, QualType fieldType) - : Alignment(align), Size(size), Lifetime(lifetime), - Capture(capture), Type(type), FieldType(fieldType) {} - - /// Tell the block info that this chunk has the given field index. - void setIndex(CGBlockInfo &info, unsigned index, CharUnits offset) { - if (!Capture) { - info.CXXThisIndex = index; - info.CXXThisOffset = offset; - } else { - auto C = CGBlockInfo::Capture::makeIndex(index, offset, FieldType); - info.Captures.insert({Capture->getVariable(), C}); - } - } - }; - - /// Order by 1) all __strong together 2) next, all byfref together 3) next, - /// all __weak together. Preserve descending alignment in all situations. - bool operator<(const BlockLayoutChunk &left, const BlockLayoutChunk &right) { - if (left.Alignment != right.Alignment) - return left.Alignment > right.Alignment; - - auto getPrefOrder = [](const BlockLayoutChunk &chunk) { - if (chunk.Capture && chunk.Capture->isByRef()) - return 1; - if (chunk.Lifetime == Qualifiers::OCL_Strong) - return 0; - if (chunk.Lifetime == Qualifiers::OCL_Weak) - return 2; - return 3; - }; - - return getPrefOrder(left) < getPrefOrder(right); - } -} // end anonymous namespace - -/// Determines if the given type is safe for constant capture in C++. -static bool isSafeForCXXConstantCapture(QualType type) { - const RecordType *recordType = - type->getBaseElementTypeUnsafe()->getAs<RecordType>(); - - // Only records can be unsafe. - if (!recordType) return true; - - const auto *record = cast<CXXRecordDecl>(recordType->getDecl()); - - // Maintain semantics for classes with non-trivial dtors or copy ctors. - if (!record->hasTrivialDestructor()) return false; - if (record->hasNonTrivialCopyConstructor()) return false; - - // Otherwise, we just have to make sure there aren't any mutable - // fields that might have changed since initialization. - return !record->hasMutableFields(); -} - -/// It is illegal to modify a const object after initialization. -/// Therefore, if a const object has a constant initializer, we don't -/// actually need to keep storage for it in the block; we'll just -/// rematerialize it at the start of the block function. This is -/// acceptable because we make no promises about address stability of -/// captured variables. -static llvm::Constant *tryCaptureAsConstant(CodeGenModule &CGM, - CodeGenFunction *CGF, - const VarDecl *var) { - // Return if this is a function parameter. We shouldn't try to - // rematerialize default arguments of function parameters. - if (isa<ParmVarDecl>(var)) - return nullptr; - - QualType type = var->getType(); - - // We can only do this if the variable is const. - if (!type.isConstQualified()) return nullptr; - - // Furthermore, in C++ we have to worry about mutable fields: - // C++ [dcl.type.cv]p4: - // Except that any class member declared mutable can be - // modified, any attempt to modify a const object during its - // lifetime results in undefined behavior. - if (CGM.getLangOpts().CPlusPlus && !isSafeForCXXConstantCapture(type)) - return nullptr; - - // If the variable doesn't have any initializer (shouldn't this be - // invalid?), it's not clear what we should do. Maybe capture as - // zero? - const Expr *init = var->getInit(); - if (!init) return nullptr; - - return ConstantEmitter(CGM, CGF).tryEmitAbstractForInitializer(*var); -} - -/// Get the low bit of a nonzero character count. This is the -/// alignment of the nth byte if the 0th byte is universally aligned. -static CharUnits getLowBit(CharUnits v) { - return CharUnits::fromQuantity(v.getQuantity() & (~v.getQuantity() + 1)); -} - -static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info, - SmallVectorImpl<llvm::Type*> &elementTypes) { - - assert(elementTypes.empty()); - if (CGM.getLangOpts().OpenCL) { - // The header is basically 'struct { int; int; generic void *; - // custom_fields; }'. Assert that struct is packed. - auto GenericAS = - CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic); - auto GenPtrAlign = - CharUnits::fromQuantity(CGM.getTarget().getPointerAlign(GenericAS) / 8); - auto GenPtrSize = - CharUnits::fromQuantity(CGM.getTarget().getPointerWidth(GenericAS) / 8); - assert(CGM.getIntSize() <= GenPtrSize); - assert(CGM.getIntAlign() <= GenPtrAlign); - assert((2 * CGM.getIntSize()).isMultipleOf(GenPtrAlign)); - elementTypes.push_back(CGM.IntTy); /* total size */ - elementTypes.push_back(CGM.IntTy); /* align */ - elementTypes.push_back( - CGM.getOpenCLRuntime() - .getGenericVoidPointerType()); /* invoke function */ - unsigned Offset = - 2 * CGM.getIntSize().getQuantity() + GenPtrSize.getQuantity(); - unsigned BlockAlign = GenPtrAlign.getQuantity(); - if (auto *Helper = - CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) { - for (auto I : Helper->getCustomFieldTypes()) /* custom fields */ { - // TargetOpenCLBlockHelp needs to make sure the struct is packed. - // If necessary, add padding fields to the custom fields. - unsigned Align = CGM.getDataLayout().getABITypeAlignment(I); - if (BlockAlign < Align) - BlockAlign = Align; - assert(Offset % Align == 0); - Offset += CGM.getDataLayout().getTypeAllocSize(I); - elementTypes.push_back(I); - } - } - info.BlockAlign = CharUnits::fromQuantity(BlockAlign); - info.BlockSize = CharUnits::fromQuantity(Offset); - } else { - // The header is basically 'struct { void *; int; int; void *; void *; }'. - // Assert that the struct is packed. - assert(CGM.getIntSize() <= CGM.getPointerSize()); - assert(CGM.getIntAlign() <= CGM.getPointerAlign()); - assert((2 * CGM.getIntSize()).isMultipleOf(CGM.getPointerAlign())); - info.BlockAlign = CGM.getPointerAlign(); - info.BlockSize = 3 * CGM.getPointerSize() + 2 * CGM.getIntSize(); - elementTypes.push_back(CGM.VoidPtrTy); - elementTypes.push_back(CGM.IntTy); - elementTypes.push_back(CGM.IntTy); - elementTypes.push_back(CGM.VoidPtrTy); - elementTypes.push_back(CGM.getBlockDescriptorType()); - } -} - -static QualType getCaptureFieldType(const CodeGenFunction &CGF, - const BlockDecl::Capture &CI) { - const VarDecl *VD = CI.getVariable(); - - // If the variable is captured by an enclosing block or lambda expression, - // use the type of the capture field. - if (CGF.BlockInfo && CI.isNested()) - return CGF.BlockInfo->getCapture(VD).fieldType(); - if (auto *FD = CGF.LambdaCaptureFields.lookup(VD)) - return FD->getType(); - // If the captured variable is a non-escaping __block variable, the field - // type is the reference type. If the variable is a __block variable that - // already has a reference type, the field type is the variable's type. - return VD->isNonEscapingByref() ? - CGF.getContext().getLValueReferenceType(VD->getType()) : VD->getType(); -} - -/// Compute the layout of the given block. Attempts to lay the block -/// out with minimal space requirements. -static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF, - CGBlockInfo &info) { - ASTContext &C = CGM.getContext(); - const BlockDecl *block = info.getBlockDecl(); - - SmallVector<llvm::Type*, 8> elementTypes; - initializeForBlockHeader(CGM, info, elementTypes); - bool hasNonConstantCustomFields = false; - if (auto *OpenCLHelper = - CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) - hasNonConstantCustomFields = - !OpenCLHelper->areAllCustomFieldValuesConstant(info); - if (!block->hasCaptures() && !hasNonConstantCustomFields) { - info.StructureType = - llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); - info.CanBeGlobal = true; - return; - } - else if (C.getLangOpts().ObjC && - CGM.getLangOpts().getGC() == LangOptions::NonGC) - info.HasCapturedVariableLayout = true; - - // Collect the layout chunks. - SmallVector<BlockLayoutChunk, 16> layout; - layout.reserve(block->capturesCXXThis() + - (block->capture_end() - block->capture_begin())); - - CharUnits maxFieldAlign; - - // First, 'this'. - if (block->capturesCXXThis()) { - assert(CGF && CGF->CurFuncDecl && isa<CXXMethodDecl>(CGF->CurFuncDecl) && - "Can't capture 'this' outside a method"); - QualType thisType = cast<CXXMethodDecl>(CGF->CurFuncDecl)->getThisType(); - - // Theoretically, this could be in a different address space, so - // don't assume standard pointer size/align. - llvm::Type *llvmType = CGM.getTypes().ConvertType(thisType); - std::pair<CharUnits,CharUnits> tinfo - = CGM.getContext().getTypeInfoInChars(thisType); - maxFieldAlign = std::max(maxFieldAlign, tinfo.second); - - layout.push_back(BlockLayoutChunk(tinfo.second, tinfo.first, - Qualifiers::OCL_None, - nullptr, llvmType, thisType)); - } - - // Next, all the block captures. - for (const auto &CI : block->captures()) { - const VarDecl *variable = CI.getVariable(); - - if (CI.isEscapingByref()) { - // We have to copy/dispose of the __block reference. - info.NeedsCopyDispose = true; - - // Just use void* instead of a pointer to the byref type. - CharUnits align = CGM.getPointerAlign(); - maxFieldAlign = std::max(maxFieldAlign, align); - - // Since a __block variable cannot be captured by lambdas, its type and - // the capture field type should always match. - assert(getCaptureFieldType(*CGF, CI) == variable->getType() && - "capture type differs from the variable type"); - layout.push_back(BlockLayoutChunk(align, CGM.getPointerSize(), - Qualifiers::OCL_None, &CI, - CGM.VoidPtrTy, variable->getType())); - continue; - } - - // Otherwise, build a layout chunk with the size and alignment of - // the declaration. - if (llvm::Constant *constant = tryCaptureAsConstant(CGM, CGF, variable)) { - info.Captures[variable] = CGBlockInfo::Capture::makeConstant(constant); - continue; - } - - QualType VT = getCaptureFieldType(*CGF, CI); - - // If we have a lifetime qualifier, honor it for capture purposes. - // That includes *not* copying it if it's __unsafe_unretained. - Qualifiers::ObjCLifetime lifetime = VT.getObjCLifetime(); - if (lifetime) { - switch (lifetime) { - case Qualifiers::OCL_None: llvm_unreachable("impossible"); - case Qualifiers::OCL_ExplicitNone: - case Qualifiers::OCL_Autoreleasing: - break; - - case Qualifiers::OCL_Strong: - case Qualifiers::OCL_Weak: - info.NeedsCopyDispose = true; - } - - // Block pointers require copy/dispose. So do Objective-C pointers. - } else if (VT->isObjCRetainableType()) { - // But honor the inert __unsafe_unretained qualifier, which doesn't - // actually make it into the type system. - if (VT->isObjCInertUnsafeUnretainedType()) { - lifetime = Qualifiers::OCL_ExplicitNone; - } else { - info.NeedsCopyDispose = true; - // used for mrr below. - lifetime = Qualifiers::OCL_Strong; - } - - // So do types that require non-trivial copy construction. - } else if (CI.hasCopyExpr()) { - info.NeedsCopyDispose = true; - info.HasCXXObject = true; - if (!VT->getAsCXXRecordDecl()->isExternallyVisible()) - info.CapturesNonExternalType = true; - - // So do C structs that require non-trivial copy construction or - // destruction. - } else if (VT.isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct || - VT.isDestructedType() == QualType::DK_nontrivial_c_struct) { - info.NeedsCopyDispose = true; - - // And so do types with destructors. - } else if (CGM.getLangOpts().CPlusPlus) { - if (const CXXRecordDecl *record = VT->getAsCXXRecordDecl()) { - if (!record->hasTrivialDestructor()) { - info.HasCXXObject = true; - info.NeedsCopyDispose = true; - if (!record->isExternallyVisible()) - info.CapturesNonExternalType = true; - } - } - } - - CharUnits size = C.getTypeSizeInChars(VT); - CharUnits align = C.getDeclAlign(variable); - - maxFieldAlign = std::max(maxFieldAlign, align); - - llvm::Type *llvmType = - CGM.getTypes().ConvertTypeForMem(VT); - - layout.push_back( - BlockLayoutChunk(align, size, lifetime, &CI, llvmType, VT)); - } - - // If that was everything, we're done here. - if (layout.empty()) { - info.StructureType = - llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); - info.CanBeGlobal = true; - return; - } - - // Sort the layout by alignment. We have to use a stable sort here - // to get reproducible results. There should probably be an - // llvm::array_pod_stable_sort. - std::stable_sort(layout.begin(), layout.end()); - - // Needed for blocks layout info. - info.BlockHeaderForcedGapOffset = info.BlockSize; - info.BlockHeaderForcedGapSize = CharUnits::Zero(); - - CharUnits &blockSize = info.BlockSize; - info.BlockAlign = std::max(maxFieldAlign, info.BlockAlign); - - // Assuming that the first byte in the header is maximally aligned, - // get the alignment of the first byte following the header. - CharUnits endAlign = getLowBit(blockSize); - - // If the end of the header isn't satisfactorily aligned for the - // maximum thing, look for things that are okay with the header-end - // alignment, and keep appending them until we get something that's - // aligned right. This algorithm is only guaranteed optimal if - // that condition is satisfied at some point; otherwise we can get - // things like: - // header // next byte has alignment 4 - // something_with_size_5; // next byte has alignment 1 - // something_with_alignment_8; - // which has 7 bytes of padding, as opposed to the naive solution - // which might have less (?). - if (endAlign < maxFieldAlign) { - SmallVectorImpl<BlockLayoutChunk>::iterator - li = layout.begin() + 1, le = layout.end(); - - // Look for something that the header end is already - // satisfactorily aligned for. - for (; li != le && endAlign < li->Alignment; ++li) - ; - - // If we found something that's naturally aligned for the end of - // the header, keep adding things... - if (li != le) { - SmallVectorImpl<BlockLayoutChunk>::iterator first = li; - for (; li != le; ++li) { - assert(endAlign >= li->Alignment); - - li->setIndex(info, elementTypes.size(), blockSize); - elementTypes.push_back(li->Type); - blockSize += li->Size; - endAlign = getLowBit(blockSize); - - // ...until we get to the alignment of the maximum field. - if (endAlign >= maxFieldAlign) { - break; - } - } - // Don't re-append everything we just appended. - layout.erase(first, li); - } - } - - assert(endAlign == getLowBit(blockSize)); - - // At this point, we just have to add padding if the end align still - // isn't aligned right. - if (endAlign < maxFieldAlign) { - CharUnits newBlockSize = blockSize.alignTo(maxFieldAlign); - CharUnits padding = newBlockSize - blockSize; - - // If we haven't yet added any fields, remember that there was an - // initial gap; this need to go into the block layout bit map. - if (blockSize == info.BlockHeaderForcedGapOffset) { - info.BlockHeaderForcedGapSize = padding; - } - - elementTypes.push_back(llvm::ArrayType::get(CGM.Int8Ty, - padding.getQuantity())); - blockSize = newBlockSize; - endAlign = getLowBit(blockSize); // might be > maxFieldAlign - } - - assert(endAlign >= maxFieldAlign); - assert(endAlign == getLowBit(blockSize)); - // Slam everything else on now. This works because they have - // strictly decreasing alignment and we expect that size is always a - // multiple of alignment. - for (SmallVectorImpl<BlockLayoutChunk>::iterator - li = layout.begin(), le = layout.end(); li != le; ++li) { - if (endAlign < li->Alignment) { - // size may not be multiple of alignment. This can only happen with - // an over-aligned variable. We will be adding a padding field to - // make the size be multiple of alignment. - CharUnits padding = li->Alignment - endAlign; - elementTypes.push_back(llvm::ArrayType::get(CGM.Int8Ty, - padding.getQuantity())); - blockSize += padding; - endAlign = getLowBit(blockSize); - } - assert(endAlign >= li->Alignment); - li->setIndex(info, elementTypes.size(), blockSize); - elementTypes.push_back(li->Type); - blockSize += li->Size; - endAlign = getLowBit(blockSize); - } - - info.StructureType = - llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); -} - -/// Enter the scope of a block. This should be run at the entrance to -/// a full-expression so that the block's cleanups are pushed at the -/// right place in the stack. -static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) { - assert(CGF.HaveInsertPoint()); - - // Allocate the block info and place it at the head of the list. - CGBlockInfo &blockInfo = - *new CGBlockInfo(block, CGF.CurFn->getName()); - blockInfo.NextBlockInfo = CGF.FirstBlockInfo; - CGF.FirstBlockInfo = &blockInfo; - - // Compute information about the layout, etc., of this block, - // pushing cleanups as necessary. - computeBlockInfo(CGF.CGM, &CGF, blockInfo); - - // Nothing else to do if it can be global. - if (blockInfo.CanBeGlobal) return; - - // Make the allocation for the block. - blockInfo.LocalAddress = CGF.CreateTempAlloca(blockInfo.StructureType, - blockInfo.BlockAlign, "block"); - - // If there are cleanups to emit, enter them (but inactive). - if (!blockInfo.NeedsCopyDispose) return; - - // Walk through the captures (in order) and find the ones not - // captured by constant. - for (const auto &CI : block->captures()) { - // Ignore __block captures; there's nothing special in the - // on-stack block that we need to do for them. - if (CI.isByRef()) continue; - - // Ignore variables that are constant-captured. - const VarDecl *variable = CI.getVariable(); - CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); - if (capture.isConstant()) continue; - - // Ignore objects that aren't destructed. - QualType VT = getCaptureFieldType(CGF, CI); - QualType::DestructionKind dtorKind = VT.isDestructedType(); - if (dtorKind == QualType::DK_none) continue; - - CodeGenFunction::Destroyer *destroyer; - - // Block captures count as local values and have imprecise semantics. - // They also can't be arrays, so need to worry about that. - // - // For const-qualified captures, emit clang.arc.use to ensure the captured - // object doesn't get released while we are still depending on its validity - // within the block. - if (VT.isConstQualified() && - VT.getObjCLifetime() == Qualifiers::OCL_Strong && - CGF.CGM.getCodeGenOpts().OptimizationLevel != 0) { - assert(CGF.CGM.getLangOpts().ObjCAutoRefCount && - "expected ObjC ARC to be enabled"); - destroyer = CodeGenFunction::emitARCIntrinsicUse; - } else if (dtorKind == QualType::DK_objc_strong_lifetime) { - destroyer = CodeGenFunction::destroyARCStrongImprecise; - } else { - destroyer = CGF.getDestroyer(dtorKind); - } - - // GEP down to the address. - Address addr = CGF.Builder.CreateStructGEP(blockInfo.LocalAddress, - capture.getIndex(), - capture.getOffset()); - - // We can use that GEP as the dominating IP. - if (!blockInfo.DominatingIP) - blockInfo.DominatingIP = cast<llvm::Instruction>(addr.getPointer()); - - CleanupKind cleanupKind = InactiveNormalCleanup; - bool useArrayEHCleanup = CGF.needsEHCleanup(dtorKind); - if (useArrayEHCleanup) - cleanupKind = InactiveNormalAndEHCleanup; - - CGF.pushDestroy(cleanupKind, addr, VT, - destroyer, useArrayEHCleanup); - - // Remember where that cleanup was. - capture.setCleanup(CGF.EHStack.stable_begin()); - } -} - -/// Enter a full-expression with a non-trivial number of objects to -/// clean up. This is in this file because, at the moment, the only -/// kind of cleanup object is a BlockDecl*. -void CodeGenFunction::enterNonTrivialFullExpression(const FullExpr *E) { - if (const auto EWC = dyn_cast<ExprWithCleanups>(E)) { - assert(EWC->getNumObjects() != 0); - for (const ExprWithCleanups::CleanupObject &C : EWC->getObjects()) - enterBlockScope(*this, C); - } -} - -/// Find the layout for the given block in a linked list and remove it. -static CGBlockInfo *findAndRemoveBlockInfo(CGBlockInfo **head, - const BlockDecl *block) { - while (true) { - assert(head && *head); - CGBlockInfo *cur = *head; - - // If this is the block we're looking for, splice it out of the list. - if (cur->getBlockDecl() == block) { - *head = cur->NextBlockInfo; - return cur; - } - - head = &cur->NextBlockInfo; - } -} - -/// Destroy a chain of block layouts. -void CodeGenFunction::destroyBlockInfos(CGBlockInfo *head) { - assert(head && "destroying an empty chain"); - do { - CGBlockInfo *cur = head; - head = cur->NextBlockInfo; - delete cur; - } while (head != nullptr); -} - -/// Emit a block literal expression in the current function. -llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) { - // If the block has no captures, we won't have a pre-computed - // layout for it. - if (!blockExpr->getBlockDecl()->hasCaptures()) { - // The block literal is emitted as a global variable, and the block invoke - // function has to be extracted from its initializer. - if (llvm::Constant *Block = CGM.getAddrOfGlobalBlockIfEmitted(blockExpr)) { - return Block; - } - CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName()); - computeBlockInfo(CGM, this, blockInfo); - blockInfo.BlockExpression = blockExpr; - return EmitBlockLiteral(blockInfo); - } - - // Find the block info for this block and take ownership of it. - std::unique_ptr<CGBlockInfo> blockInfo; - blockInfo.reset(findAndRemoveBlockInfo(&FirstBlockInfo, - blockExpr->getBlockDecl())); - - blockInfo->BlockExpression = blockExpr; - return EmitBlockLiteral(*blockInfo); -} - -llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { - bool IsOpenCL = CGM.getContext().getLangOpts().OpenCL; - auto GenVoidPtrTy = - IsOpenCL ? CGM.getOpenCLRuntime().getGenericVoidPointerType() : VoidPtrTy; - LangAS GenVoidPtrAddr = IsOpenCL ? LangAS::opencl_generic : LangAS::Default; - auto GenVoidPtrSize = CharUnits::fromQuantity( - CGM.getTarget().getPointerWidth( - CGM.getContext().getTargetAddressSpace(GenVoidPtrAddr)) / - 8); - // Using the computed layout, generate the actual block function. - bool isLambdaConv = blockInfo.getBlockDecl()->isConversionFromLambda(); - CodeGenFunction BlockCGF{CGM, true}; - BlockCGF.SanOpts = SanOpts; - auto *InvokeFn = BlockCGF.GenerateBlockFunction( - CurGD, blockInfo, LocalDeclMap, isLambdaConv, blockInfo.CanBeGlobal); - auto *blockFn = llvm::ConstantExpr::getPointerCast(InvokeFn, GenVoidPtrTy); - - // If there is nothing to capture, we can emit this as a global block. - if (blockInfo.CanBeGlobal) - return CGM.getAddrOfGlobalBlockIfEmitted(blockInfo.BlockExpression); - - // Otherwise, we have to emit this as a local block. - - Address blockAddr = blockInfo.LocalAddress; - assert(blockAddr.isValid() && "block has no address!"); - - llvm::Constant *isa; - llvm::Constant *descriptor; - BlockFlags flags; - if (!IsOpenCL) { - // If the block is non-escaping, set field 'isa 'to NSConcreteGlobalBlock - // and set the BLOCK_IS_GLOBAL bit of field 'flags'. Copying a non-escaping - // block just returns the original block and releasing it is a no-op. - llvm::Constant *blockISA = blockInfo.getBlockDecl()->doesNotEscape() - ? CGM.getNSConcreteGlobalBlock() - : CGM.getNSConcreteStackBlock(); - isa = llvm::ConstantExpr::getBitCast(blockISA, VoidPtrTy); - - // Build the block descriptor. - descriptor = buildBlockDescriptor(CGM, blockInfo); - - // Compute the initial on-stack block flags. - flags = BLOCK_HAS_SIGNATURE; - if (blockInfo.HasCapturedVariableLayout) - flags |= BLOCK_HAS_EXTENDED_LAYOUT; - if (blockInfo.needsCopyDisposeHelpers()) - flags |= BLOCK_HAS_COPY_DISPOSE; - if (blockInfo.HasCXXObject) - flags |= BLOCK_HAS_CXX_OBJ; - if (blockInfo.UsesStret) - flags |= BLOCK_USE_STRET; - if (blockInfo.getBlockDecl()->doesNotEscape()) - flags |= BLOCK_IS_NOESCAPE | BLOCK_IS_GLOBAL; - } - - auto projectField = - [&](unsigned index, CharUnits offset, const Twine &name) -> Address { - return Builder.CreateStructGEP(blockAddr, index, offset, name); - }; - auto storeField = - [&](llvm::Value *value, unsigned index, CharUnits offset, - const Twine &name) { - Builder.CreateStore(value, projectField(index, offset, name)); - }; - - // Initialize the block header. - { - // We assume all the header fields are densely packed. - unsigned index = 0; - CharUnits offset; - auto addHeaderField = - [&](llvm::Value *value, CharUnits size, const Twine &name) { - storeField(value, index, offset, name); - offset += size; - index++; - }; - - if (!IsOpenCL) { - addHeaderField(isa, getPointerSize(), "block.isa"); - addHeaderField(llvm::ConstantInt::get(IntTy, flags.getBitMask()), - getIntSize(), "block.flags"); - addHeaderField(llvm::ConstantInt::get(IntTy, 0), getIntSize(), - "block.reserved"); - } else { - addHeaderField( - llvm::ConstantInt::get(IntTy, blockInfo.BlockSize.getQuantity()), - getIntSize(), "block.size"); - addHeaderField( - llvm::ConstantInt::get(IntTy, blockInfo.BlockAlign.getQuantity()), - getIntSize(), "block.align"); - } - addHeaderField(blockFn, GenVoidPtrSize, "block.invoke"); - if (!IsOpenCL) - addHeaderField(descriptor, getPointerSize(), "block.descriptor"); - else if (auto *Helper = - CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) { - for (auto I : Helper->getCustomFieldValues(*this, blockInfo)) { - addHeaderField( - I.first, - CharUnits::fromQuantity( - CGM.getDataLayout().getTypeAllocSize(I.first->getType())), - I.second); - } - } - } - - // Finally, capture all the values into the block. - const BlockDecl *blockDecl = blockInfo.getBlockDecl(); - - // First, 'this'. - if (blockDecl->capturesCXXThis()) { - Address addr = projectField(blockInfo.CXXThisIndex, blockInfo.CXXThisOffset, - "block.captured-this.addr"); - Builder.CreateStore(LoadCXXThis(), addr); - } - - // Next, captured variables. - for (const auto &CI : blockDecl->captures()) { - const VarDecl *variable = CI.getVariable(); - const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); - - // Ignore constant captures. - if (capture.isConstant()) continue; - - QualType type = capture.fieldType(); - - // This will be a [[type]]*, except that a byref entry will just be - // an i8**. - Address blockField = - projectField(capture.getIndex(), capture.getOffset(), "block.captured"); - - // Compute the address of the thing we're going to move into the - // block literal. - Address src = Address::invalid(); - - if (blockDecl->isConversionFromLambda()) { - // The lambda capture in a lambda's conversion-to-block-pointer is - // special; we'll simply emit it directly. - src = Address::invalid(); - } else if (CI.isEscapingByref()) { - if (BlockInfo && CI.isNested()) { - // We need to use the capture from the enclosing block. - const CGBlockInfo::Capture &enclosingCapture = - BlockInfo->getCapture(variable); - - // This is a [[type]]*, except that a byref entry will just be an i8**. - src = Builder.CreateStructGEP(LoadBlockStruct(), - enclosingCapture.getIndex(), - enclosingCapture.getOffset(), - "block.capture.addr"); - } else { - auto I = LocalDeclMap.find(variable); - assert(I != LocalDeclMap.end()); - src = I->second; - } - } else { - DeclRefExpr declRef(getContext(), const_cast<VarDecl *>(variable), - /*RefersToEnclosingVariableOrCapture*/ CI.isNested(), - type.getNonReferenceType(), VK_LValue, - SourceLocation()); - src = EmitDeclRefLValue(&declRef).getAddress(); - }; - - // For byrefs, we just write the pointer to the byref struct into - // the block field. There's no need to chase the forwarding - // pointer at this point, since we're building something that will - // live a shorter life than the stack byref anyway. - if (CI.isEscapingByref()) { - // Get a void* that points to the byref struct. - llvm::Value *byrefPointer; - if (CI.isNested()) - byrefPointer = Builder.CreateLoad(src, "byref.capture"); - else - byrefPointer = Builder.CreateBitCast(src.getPointer(), VoidPtrTy); - - // Write that void* into the capture field. - Builder.CreateStore(byrefPointer, blockField); - - // If we have a copy constructor, evaluate that into the block field. - } else if (const Expr *copyExpr = CI.getCopyExpr()) { - if (blockDecl->isConversionFromLambda()) { - // If we have a lambda conversion, emit the expression - // directly into the block instead. - AggValueSlot Slot = - AggValueSlot::forAddr(blockField, Qualifiers(), - AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - AggValueSlot::DoesNotOverlap); - EmitAggExpr(copyExpr, Slot); - } else { - EmitSynthesizedCXXCopyCtor(blockField, src, copyExpr); - } - - // If it's a reference variable, copy the reference into the block field. - } else if (type->isReferenceType()) { - Builder.CreateStore(src.getPointer(), blockField); - - // 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) { - llvm::Value *value = Builder.CreateLoad(src, "captured"); - Builder.CreateStore(value, blockField); - - // If this is an ARC __strong block-pointer variable, don't do a - // block copy. - // - // TODO: this can be generalized into the normal initialization logic: - // we should never need to do a block-copy when initializing a local - // variable, because the local variable's lifetime should be strictly - // contained within the stack block's. - } else if (type.getObjCLifetime() == Qualifiers::OCL_Strong && - type->isBlockPointerType()) { - // Load the block and do a simple retain. - llvm::Value *value = Builder.CreateLoad(src, "block.captured_block"); - value = EmitARCRetainNonBlock(value); - - // Do a primitive store to the block field. - Builder.CreateStore(value, blockField); - - // Otherwise, fake up a POD copy into the block field. - } else { - // Fake up a new variable so that EmitScalarInit doesn't think - // we're referring to the variable in its own initializer. - ImplicitParamDecl BlockFieldPseudoVar(getContext(), type, - ImplicitParamDecl::Other); - - // We use one of these or the other depending on whether the - // reference is nested. - DeclRefExpr declRef(getContext(), const_cast<VarDecl *>(variable), - /*RefersToEnclosingVariableOrCapture*/ CI.isNested(), - type, VK_LValue, SourceLocation()); - - ImplicitCastExpr l2r(ImplicitCastExpr::OnStack, type, CK_LValueToRValue, - &declRef, VK_RValue); - // FIXME: Pass a specific location for the expr init so that the store is - // attributed to a reasonable location - otherwise it may be attributed to - // locations of subexpressions in the initialization. - EmitExprAsInit(&l2r, &BlockFieldPseudoVar, - MakeAddrLValue(blockField, type, AlignmentSource::Decl), - /*captured by init*/ false); - } - - // Activate the cleanup if layout pushed one. - if (!CI.isByRef()) { - EHScopeStack::stable_iterator cleanup = capture.getCleanup(); - if (cleanup.isValid()) - ActivateCleanupBlock(cleanup, blockInfo.DominatingIP); - } - } - - // Cast to the converted block-pointer type, which happens (somewhat - // unfortunately) to be a pointer to function type. - llvm::Value *result = Builder.CreatePointerCast( - blockAddr.getPointer(), ConvertType(blockInfo.getBlockExpr()->getType())); - - if (IsOpenCL) { - CGM.getOpenCLRuntime().recordBlockInfo(blockInfo.BlockExpression, InvokeFn, - result); - } - - return result; -} - - -llvm::Type *CodeGenModule::getBlockDescriptorType() { - if (BlockDescriptorType) - return BlockDescriptorType; - - llvm::Type *UnsignedLongTy = - getTypes().ConvertType(getContext().UnsignedLongTy); - - // struct __block_descriptor { - // unsigned long reserved; - // unsigned long block_size; - // - // // later, the following will be added - // - // struct { - // void (*copyHelper)(); - // void (*copyHelper)(); - // } helpers; // !!! optional - // - // const char *signature; // the block signature - // const char *layout; // reserved - // }; - BlockDescriptorType = llvm::StructType::create( - "struct.__block_descriptor", UnsignedLongTy, UnsignedLongTy); - - // Now form a pointer to that. - unsigned AddrSpace = 0; - if (getLangOpts().OpenCL) - AddrSpace = getContext().getTargetAddressSpace(LangAS::opencl_constant); - BlockDescriptorType = llvm::PointerType::get(BlockDescriptorType, AddrSpace); - return BlockDescriptorType; -} - -llvm::Type *CodeGenModule::getGenericBlockLiteralType() { - if (GenericBlockLiteralType) - return GenericBlockLiteralType; - - llvm::Type *BlockDescPtrTy = getBlockDescriptorType(); - - if (getLangOpts().OpenCL) { - // struct __opencl_block_literal_generic { - // int __size; - // int __align; - // __generic void *__invoke; - // /* custom fields */ - // }; - SmallVector<llvm::Type *, 8> StructFields( - {IntTy, IntTy, getOpenCLRuntime().getGenericVoidPointerType()}); - if (auto *Helper = getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) { - for (auto I : Helper->getCustomFieldTypes()) - StructFields.push_back(I); - } - GenericBlockLiteralType = llvm::StructType::create( - StructFields, "struct.__opencl_block_literal_generic"); - } else { - // struct __block_literal_generic { - // void *__isa; - // int __flags; - // int __reserved; - // void (*__invoke)(void *); - // struct __block_descriptor *__descriptor; - // }; - GenericBlockLiteralType = - llvm::StructType::create("struct.__block_literal_generic", VoidPtrTy, - IntTy, IntTy, VoidPtrTy, BlockDescPtrTy); - } - - return GenericBlockLiteralType; -} - -RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E, - ReturnValueSlot ReturnValue) { - const BlockPointerType *BPT = - E->getCallee()->getType()->getAs<BlockPointerType>(); - - llvm::Value *BlockPtr = EmitScalarExpr(E->getCallee()); - - // Get a pointer to the generic block literal. - // For OpenCL we generate generic AS void ptr to be able to reuse the same - // block definition for blocks with captures generated as private AS local - // variables and without captures generated as global AS program scope - // variables. - unsigned AddrSpace = 0; - if (getLangOpts().OpenCL) - AddrSpace = getContext().getTargetAddressSpace(LangAS::opencl_generic); - - llvm::Type *BlockLiteralTy = - llvm::PointerType::get(CGM.getGenericBlockLiteralType(), AddrSpace); - - // Bitcast the callee to a block literal. - BlockPtr = - Builder.CreatePointerCast(BlockPtr, BlockLiteralTy, "block.literal"); - - // Get the function pointer from the literal. - llvm::Value *FuncPtr = - Builder.CreateStructGEP(CGM.getGenericBlockLiteralType(), BlockPtr, - CGM.getLangOpts().OpenCL ? 2 : 3); - - // Add the block literal. - CallArgList Args; - - QualType VoidPtrQualTy = getContext().VoidPtrTy; - llvm::Type *GenericVoidPtrTy = VoidPtrTy; - if (getLangOpts().OpenCL) { - GenericVoidPtrTy = CGM.getOpenCLRuntime().getGenericVoidPointerType(); - VoidPtrQualTy = - getContext().getPointerType(getContext().getAddrSpaceQualType( - getContext().VoidTy, LangAS::opencl_generic)); - } - - BlockPtr = Builder.CreatePointerCast(BlockPtr, GenericVoidPtrTy); - Args.add(RValue::get(BlockPtr), VoidPtrQualTy); - - QualType FnType = BPT->getPointeeType(); - - // And the rest of the arguments. - EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), E->arguments()); - - // Load the function. - llvm::Value *Func = Builder.CreateAlignedLoad(FuncPtr, getPointerAlign()); - - const FunctionType *FuncTy = FnType->castAs<FunctionType>(); - const CGFunctionInfo &FnInfo = - CGM.getTypes().arrangeBlockFunctionCall(Args, FuncTy); - - // Cast the function pointer to the right type. - llvm::Type *BlockFTy = CGM.getTypes().GetFunctionType(FnInfo); - - llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy); - Func = Builder.CreatePointerCast(Func, BlockFTyPtr); - - // Prepare the callee. - CGCallee Callee(CGCalleeInfo(), Func); - - // And call the block. - return EmitCall(FnInfo, Callee, ReturnValue, Args); -} - -Address CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable) { - assert(BlockInfo && "evaluating block ref without block information?"); - const CGBlockInfo::Capture &capture = BlockInfo->getCapture(variable); - - // Handle constant captures. - if (capture.isConstant()) return LocalDeclMap.find(variable)->second; - - Address addr = - Builder.CreateStructGEP(LoadBlockStruct(), capture.getIndex(), - capture.getOffset(), "block.capture.addr"); - - if (variable->isEscapingByref()) { - // addr should be a void** right now. Load, then cast the result - // to byref*. - - auto &byrefInfo = getBlockByrefInfo(variable); - addr = Address(Builder.CreateLoad(addr), byrefInfo.ByrefAlignment); - - auto byrefPointerType = llvm::PointerType::get(byrefInfo.Type, 0); - addr = Builder.CreateBitCast(addr, byrefPointerType, "byref.addr"); - - addr = emitBlockByrefAddress(addr, byrefInfo, /*follow*/ true, - variable->getName()); - } - - assert((!variable->isNonEscapingByref() || - capture.fieldType()->isReferenceType()) && - "the capture field of a non-escaping variable should have a " - "reference type"); - if (capture.fieldType()->isReferenceType()) - addr = EmitLoadOfReference(MakeAddrLValue(addr, capture.fieldType())); - - return addr; -} - -void CodeGenModule::setAddrOfGlobalBlock(const BlockExpr *BE, - llvm::Constant *Addr) { - bool Ok = EmittedGlobalBlocks.insert(std::make_pair(BE, Addr)).second; - (void)Ok; - assert(Ok && "Trying to replace an already-existing global block!"); -} - -llvm::Constant * -CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *BE, - StringRef Name) { - if (llvm::Constant *Block = getAddrOfGlobalBlockIfEmitted(BE)) - return Block; - - CGBlockInfo blockInfo(BE->getBlockDecl(), Name); - blockInfo.BlockExpression = BE; - - // Compute information about the layout, etc., of this block. - computeBlockInfo(*this, nullptr, blockInfo); - - // Using that metadata, generate the actual block function. - { - CodeGenFunction::DeclMapTy LocalDeclMap; - CodeGenFunction(*this).GenerateBlockFunction( - GlobalDecl(), blockInfo, LocalDeclMap, - /*IsLambdaConversionToBlock*/ false, /*BuildGlobalBlock*/ true); - } - - return getAddrOfGlobalBlockIfEmitted(BE); -} - -static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, - const CGBlockInfo &blockInfo, - llvm::Constant *blockFn) { - assert(blockInfo.CanBeGlobal); - // Callers should detect this case on their own: calling this function - // generally requires computing layout information, which is a waste of time - // if we've already emitted this block. - assert(!CGM.getAddrOfGlobalBlockIfEmitted(blockInfo.BlockExpression) && - "Refusing to re-emit a global block."); - - // Generate the constants for the block literal initializer. - ConstantInitBuilder builder(CGM); - auto fields = builder.beginStruct(); - - bool IsOpenCL = CGM.getLangOpts().OpenCL; - bool IsWindows = CGM.getTarget().getTriple().isOSWindows(); - if (!IsOpenCL) { - // isa - if (IsWindows) - fields.addNullPointer(CGM.Int8PtrPtrTy); - else - fields.add(CGM.getNSConcreteGlobalBlock()); - - // __flags - BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE; - if (blockInfo.UsesStret) - flags |= BLOCK_USE_STRET; - - fields.addInt(CGM.IntTy, flags.getBitMask()); - - // Reserved - fields.addInt(CGM.IntTy, 0); - } else { - fields.addInt(CGM.IntTy, blockInfo.BlockSize.getQuantity()); - fields.addInt(CGM.IntTy, blockInfo.BlockAlign.getQuantity()); - } - - // Function - fields.add(blockFn); - - if (!IsOpenCL) { - // Descriptor - fields.add(buildBlockDescriptor(CGM, blockInfo)); - } else if (auto *Helper = - CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) { - for (auto I : Helper->getCustomFieldValues(CGM, blockInfo)) { - fields.add(I); - } - } - - unsigned AddrSpace = 0; - if (CGM.getContext().getLangOpts().OpenCL) - AddrSpace = CGM.getContext().getTargetAddressSpace(LangAS::opencl_global); - - llvm::Constant *literal = fields.finishAndCreateGlobal( - "__block_literal_global", blockInfo.BlockAlign, - /*constant*/ !IsWindows, llvm::GlobalVariable::InternalLinkage, AddrSpace); - - // Windows does not allow globals to be initialised to point to globals in - // different DLLs. Any such variables must run code to initialise them. - if (IsWindows) { - auto *Init = llvm::Function::Create(llvm::FunctionType::get(CGM.VoidTy, - {}), llvm::GlobalValue::InternalLinkage, ".block_isa_init", - &CGM.getModule()); - llvm::IRBuilder<> b(llvm::BasicBlock::Create(CGM.getLLVMContext(), "entry", - Init)); - b.CreateAlignedStore(CGM.getNSConcreteGlobalBlock(), - b.CreateStructGEP(literal, 0), CGM.getPointerAlign().getQuantity()); - b.CreateRetVoid(); - // We can't use the normal LLVM global initialisation array, because we - // need to specify that this runs early in library initialisation. - auto *InitVar = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), - /*isConstant*/true, llvm::GlobalValue::InternalLinkage, - Init, ".block_isa_init_ptr"); - InitVar->setSection(".CRT$XCLa"); - CGM.addUsedGlobal(InitVar); - } - - // Return a constant of the appropriately-casted type. - llvm::Type *RequiredType = - CGM.getTypes().ConvertType(blockInfo.getBlockExpr()->getType()); - llvm::Constant *Result = - llvm::ConstantExpr::getPointerCast(literal, RequiredType); - CGM.setAddrOfGlobalBlock(blockInfo.BlockExpression, Result); - if (CGM.getContext().getLangOpts().OpenCL) - CGM.getOpenCLRuntime().recordBlockInfo( - blockInfo.BlockExpression, - cast<llvm::Function>(blockFn->stripPointerCasts()), Result); - return Result; -} - -void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D, - unsigned argNum, - llvm::Value *arg) { - assert(BlockInfo && "not emitting prologue of block invocation function?!"); - - // 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"); - Builder.CreateStore(arg, alloc); - if (CGDebugInfo *DI = getDebugInfo()) { - if (CGM.getCodeGenOpts().getDebugInfo() >= - codegenoptions::LimitedDebugInfo) { - DI->setLocation(D->getLocation()); - DI->EmitDeclareOfBlockLiteralArgVariable( - *BlockInfo, D->getName(), argNum, - cast<llvm::AllocaInst>(alloc.getPointer()), Builder); - } - } - - SourceLocation StartLoc = BlockInfo->getBlockExpr()->getBody()->getBeginLoc(); - ApplyDebugLocation Scope(*this, StartLoc); - - // Instead of messing around with LocalDeclMap, just set the value - // directly as BlockPointer. - BlockPointer = Builder.CreatePointerCast( - arg, - BlockInfo->StructureType->getPointerTo( - getContext().getLangOpts().OpenCL - ? getContext().getTargetAddressSpace(LangAS::opencl_generic) - : 0), - "block"); -} - -Address CodeGenFunction::LoadBlockStruct() { - assert(BlockInfo && "not in a block invocation function!"); - assert(BlockPointer && "no block pointer set!"); - return Address(BlockPointer, BlockInfo->BlockAlign); -} - -llvm::Function * -CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, - const CGBlockInfo &blockInfo, - const DeclMapTy &ldm, - bool IsLambdaConversionToBlock, - bool BuildGlobalBlock) { - const BlockDecl *blockDecl = blockInfo.getBlockDecl(); - - CurGD = GD; - - CurEHLocation = blockInfo.getBlockExpr()->getEndLoc(); - - BlockInfo = &blockInfo; - - // Arrange for local static and local extern declarations to appear - // to be local to this function as well, in case they're directly - // referenced in a block. - for (DeclMapTy::const_iterator i = ldm.begin(), e = ldm.end(); i != e; ++i) { - const auto *var = dyn_cast<VarDecl>(i->first); - if (var && !var->hasLocalStorage()) - setAddrOfLocalVar(var, i->second); - } - - // Begin building the function declaration. - - // Build the argument list. - FunctionArgList args; - - // The first argument is the block pointer. Just take it as a void* - // and cast it later. - QualType selfTy = getContext().VoidPtrTy; - - // For OpenCL passed block pointer can be private AS local variable or - // global AS program scope variable (for the case with and without captures). - // Generic AS is used therefore to be able to accommodate both private and - // generic AS in one implementation. - if (getLangOpts().OpenCL) - selfTy = getContext().getPointerType(getContext().getAddrSpaceQualType( - getContext().VoidTy, LangAS::opencl_generic)); - - IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor"); - - ImplicitParamDecl SelfDecl(getContext(), const_cast<BlockDecl *>(blockDecl), - SourceLocation(), II, selfTy, - ImplicitParamDecl::ObjCSelf); - args.push_back(&SelfDecl); - - // Now add the rest of the parameters. - args.append(blockDecl->param_begin(), blockDecl->param_end()); - - // Create the function declaration. - const FunctionProtoType *fnType = blockInfo.getBlockExpr()->getFunctionType(); - const CGFunctionInfo &fnInfo = - CGM.getTypes().arrangeBlockFunctionDeclaration(fnType, args); - if (CGM.ReturnSlotInterferesWithArgs(fnInfo)) - blockInfo.UsesStret = true; - - llvm::FunctionType *fnLLVMType = CGM.getTypes().GetFunctionType(fnInfo); - - StringRef name = CGM.getBlockMangledName(GD, blockDecl); - llvm::Function *fn = llvm::Function::Create( - fnLLVMType, llvm::GlobalValue::InternalLinkage, name, &CGM.getModule()); - CGM.SetInternalFunctionAttributes(blockDecl, fn, fnInfo); - - if (BuildGlobalBlock) { - auto GenVoidPtrTy = getContext().getLangOpts().OpenCL - ? CGM.getOpenCLRuntime().getGenericVoidPointerType() - : VoidPtrTy; - buildGlobalBlock(CGM, blockInfo, - llvm::ConstantExpr::getPointerCast(fn, GenVoidPtrTy)); - } - - // Begin generating the function. - StartFunction(blockDecl, fnType->getReturnType(), fn, fnInfo, args, - blockDecl->getLocation(), - blockInfo.getBlockExpr()->getBody()->getBeginLoc()); - - // Okay. Undo some of what StartFunction did. - - // At -O0 we generate an explicit alloca for the BlockPointer, so the RA - // won't delete the dbg.declare intrinsics for captured variables. - llvm::Value *BlockPointerDbgLoc = BlockPointer; - if (CGM.getCodeGenOpts().OptimizationLevel == 0) { - // Allocate a stack slot for it, so we can point the debugger to it - Address Alloca = CreateTempAlloca(BlockPointer->getType(), - getPointerAlign(), - "block.addr"); - // Set the DebugLocation to empty, so the store is recognized as a - // frame setup instruction by llvm::DwarfDebug::beginFunction(). - auto NL = ApplyDebugLocation::CreateEmpty(*this); - Builder.CreateStore(BlockPointer, Alloca); - BlockPointerDbgLoc = Alloca.getPointer(); - } - - // If we have a C++ 'this' reference, go ahead and force it into - // existence now. - if (blockDecl->capturesCXXThis()) { - Address addr = - Builder.CreateStructGEP(LoadBlockStruct(), blockInfo.CXXThisIndex, - blockInfo.CXXThisOffset, "block.captured-this"); - CXXThisValue = Builder.CreateLoad(addr, "this"); - } - - // Also force all the constant captures. - for (const auto &CI : blockDecl->captures()) { - const VarDecl *variable = CI.getVariable(); - const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); - if (!capture.isConstant()) continue; - - CharUnits align = getContext().getDeclAlign(variable); - Address alloca = - CreateMemTemp(variable->getType(), align, "block.captured-const"); - - Builder.CreateStore(capture.getConstant(), alloca); - - setAddrOfLocalVar(variable, alloca); - } - - // Save a spot to insert the debug information for all the DeclRefExprs. - llvm::BasicBlock *entry = Builder.GetInsertBlock(); - llvm::BasicBlock::iterator entry_ptr = Builder.GetInsertPoint(); - --entry_ptr; - - if (IsLambdaConversionToBlock) - EmitLambdaBlockInvokeBody(); - else { - PGO.assignRegionCounters(GlobalDecl(blockDecl), fn); - incrementProfileCounter(blockDecl->getBody()); - EmitStmt(blockDecl->getBody()); - } - - // Remember where we were... - llvm::BasicBlock *resume = Builder.GetInsertBlock(); - - // Go back to the entry. - ++entry_ptr; - Builder.SetInsertPoint(entry, entry_ptr); - - // Emit debug information for all the DeclRefExprs. - // FIXME: also for 'this' - if (CGDebugInfo *DI = getDebugInfo()) { - for (const auto &CI : blockDecl->captures()) { - const VarDecl *variable = CI.getVariable(); - DI->EmitLocation(Builder, variable->getLocation()); - - if (CGM.getCodeGenOpts().getDebugInfo() >= - codegenoptions::LimitedDebugInfo) { - const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); - if (capture.isConstant()) { - auto addr = LocalDeclMap.find(variable)->second; - (void)DI->EmitDeclareOfAutoVariable(variable, addr.getPointer(), - Builder); - continue; - } - - DI->EmitDeclareOfBlockDeclRefVariable( - variable, BlockPointerDbgLoc, Builder, blockInfo, - entry_ptr == entry->end() ? nullptr : &*entry_ptr); - } - } - // Recover location if it was changed in the above loop. - DI->EmitLocation(Builder, - cast<CompoundStmt>(blockDecl->getBody())->getRBracLoc()); - } - - // And resume where we left off. - if (resume == nullptr) - Builder.ClearInsertionPoint(); - else - Builder.SetInsertPoint(resume); - - FinishFunction(cast<CompoundStmt>(blockDecl->getBody())->getRBracLoc()); - - return fn; -} - -static std::pair<BlockCaptureEntityKind, BlockFieldFlags> -computeCopyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T, - const LangOptions &LangOpts) { - if (CI.getCopyExpr()) { - assert(!CI.isByRef()); - // don't bother computing flags - return std::make_pair(BlockCaptureEntityKind::CXXRecord, BlockFieldFlags()); - } - BlockFieldFlags Flags; - if (CI.isEscapingByref()) { - Flags = BLOCK_FIELD_IS_BYREF; - if (T.isObjCGCWeak()) - Flags |= BLOCK_FIELD_IS_WEAK; - return std::make_pair(BlockCaptureEntityKind::BlockObject, Flags); - } - - Flags = BLOCK_FIELD_IS_OBJECT; - bool isBlockPointer = T->isBlockPointerType(); - if (isBlockPointer) - Flags = BLOCK_FIELD_IS_BLOCK; - - switch (T.isNonTrivialToPrimitiveCopy()) { - case QualType::PCK_Struct: - return std::make_pair(BlockCaptureEntityKind::NonTrivialCStruct, - BlockFieldFlags()); - case QualType::PCK_ARCWeak: - // We need to register __weak direct captures with the runtime. - return std::make_pair(BlockCaptureEntityKind::ARCWeak, Flags); - case QualType::PCK_ARCStrong: - // We need to retain the copied value for __strong direct captures. - // If it's a block pointer, we have to copy the block and assign that to - // the destination pointer, so we might as well use _Block_object_assign. - // Otherwise we can avoid that. - return std::make_pair(!isBlockPointer ? BlockCaptureEntityKind::ARCStrong - : BlockCaptureEntityKind::BlockObject, - Flags); - case QualType::PCK_Trivial: - case QualType::PCK_VolatileTrivial: { - if (!T->isObjCRetainableType()) - // For all other types, the memcpy is fine. - return std::make_pair(BlockCaptureEntityKind::None, BlockFieldFlags()); - - // Special rules for ARC captures: - Qualifiers QS = T.getQualifiers(); - - // Non-ARC captures of retainable pointers are strong and - // therefore require a call to _Block_object_assign. - if (!QS.getObjCLifetime() && !LangOpts.ObjCAutoRefCount) - return std::make_pair(BlockCaptureEntityKind::BlockObject, Flags); - - // Otherwise the memcpy is fine. - return std::make_pair(BlockCaptureEntityKind::None, BlockFieldFlags()); - } - } - llvm_unreachable("after exhaustive PrimitiveCopyKind switch"); -} - -static std::pair<BlockCaptureEntityKind, BlockFieldFlags> -computeDestroyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T, - const LangOptions &LangOpts); - -/// Find the set of block captures that need to be explicitly copied or destroy. -static void findBlockCapturedManagedEntities( - const CGBlockInfo &BlockInfo, const LangOptions &LangOpts, - SmallVectorImpl<BlockCaptureManagedEntity> &ManagedCaptures) { - for (const auto &CI : BlockInfo.getBlockDecl()->captures()) { - const VarDecl *Variable = CI.getVariable(); - const CGBlockInfo::Capture &Capture = BlockInfo.getCapture(Variable); - if (Capture.isConstant()) - continue; - - QualType VT = Capture.fieldType(); - auto CopyInfo = computeCopyInfoForBlockCapture(CI, VT, LangOpts); - auto DisposeInfo = computeDestroyInfoForBlockCapture(CI, VT, LangOpts); - if (CopyInfo.first != BlockCaptureEntityKind::None || - DisposeInfo.first != BlockCaptureEntityKind::None) - ManagedCaptures.emplace_back(CopyInfo.first, DisposeInfo.first, - CopyInfo.second, DisposeInfo.second, CI, - Capture); - } - - // Sort the captures by offset. - llvm::sort(ManagedCaptures); -} - -namespace { -/// Release a __block variable. -struct CallBlockRelease final : EHScopeStack::Cleanup { - Address Addr; - BlockFieldFlags FieldFlags; - bool LoadBlockVarAddr, CanThrow; - - CallBlockRelease(Address Addr, BlockFieldFlags Flags, bool LoadValue, - bool CT) - : Addr(Addr), FieldFlags(Flags), LoadBlockVarAddr(LoadValue), - CanThrow(CT) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - llvm::Value *BlockVarAddr; - if (LoadBlockVarAddr) { - BlockVarAddr = CGF.Builder.CreateLoad(Addr); - BlockVarAddr = CGF.Builder.CreateBitCast(BlockVarAddr, CGF.VoidPtrTy); - } else { - BlockVarAddr = Addr.getPointer(); - } - - CGF.BuildBlockRelease(BlockVarAddr, FieldFlags, CanThrow); - } -}; -} // end anonymous namespace - -/// Check if \p T is a C++ class that has a destructor that can throw. -bool CodeGenFunction::cxxDestructorCanThrow(QualType T) { - if (const auto *RD = T->getAsCXXRecordDecl()) - if (const CXXDestructorDecl *DD = RD->getDestructor()) - return DD->getType()->getAs<FunctionProtoType>()->canThrow(); - return false; -} - -// Return a string that has the information about a capture. -static std::string getBlockCaptureStr(const BlockCaptureManagedEntity &E, - CaptureStrKind StrKind, - CharUnits BlockAlignment, - CodeGenModule &CGM) { - std::string Str; - ASTContext &Ctx = CGM.getContext(); - const BlockDecl::Capture &CI = *E.CI; - QualType CaptureTy = CI.getVariable()->getType(); - - BlockCaptureEntityKind Kind; - BlockFieldFlags Flags; - - // CaptureStrKind::Merged should be passed only when the operations and the - // flags are the same for copy and dispose. - assert((StrKind != CaptureStrKind::Merged || - (E.CopyKind == E.DisposeKind && E.CopyFlags == E.DisposeFlags)) && - "different operations and flags"); - - if (StrKind == CaptureStrKind::DisposeHelper) { - Kind = E.DisposeKind; - Flags = E.DisposeFlags; - } else { - Kind = E.CopyKind; - Flags = E.CopyFlags; - } - - switch (Kind) { - case BlockCaptureEntityKind::CXXRecord: { - Str += "c"; - SmallString<256> TyStr; - llvm::raw_svector_ostream Out(TyStr); - CGM.getCXXABI().getMangleContext().mangleTypeName(CaptureTy, Out); - Str += llvm::to_string(TyStr.size()) + TyStr.c_str(); - break; - } - case BlockCaptureEntityKind::ARCWeak: - Str += "w"; - break; - case BlockCaptureEntityKind::ARCStrong: - Str += "s"; - break; - case BlockCaptureEntityKind::BlockObject: { - const VarDecl *Var = CI.getVariable(); - unsigned F = Flags.getBitMask(); - if (F & BLOCK_FIELD_IS_BYREF) { - Str += "r"; - if (F & BLOCK_FIELD_IS_WEAK) - Str += "w"; - else { - // If CaptureStrKind::Merged is passed, check both the copy expression - // and the destructor. - if (StrKind != CaptureStrKind::DisposeHelper) { - if (Ctx.getBlockVarCopyInit(Var).canThrow()) - Str += "c"; - } - if (StrKind != CaptureStrKind::CopyHelper) { - if (CodeGenFunction::cxxDestructorCanThrow(CaptureTy)) - Str += "d"; - } - } - } else { - assert((F & BLOCK_FIELD_IS_OBJECT) && "unexpected flag value"); - if (F == BLOCK_FIELD_IS_BLOCK) - Str += "b"; - else - Str += "o"; - } - break; - } - case BlockCaptureEntityKind::NonTrivialCStruct: { - bool IsVolatile = CaptureTy.isVolatileQualified(); - CharUnits Alignment = - BlockAlignment.alignmentAtOffset(E.Capture->getOffset()); - - Str += "n"; - std::string FuncStr; - if (StrKind == CaptureStrKind::DisposeHelper) - FuncStr = CodeGenFunction::getNonTrivialDestructorStr( - CaptureTy, Alignment, IsVolatile, Ctx); - else - // If CaptureStrKind::Merged is passed, use the copy constructor string. - // It has all the information that the destructor string has. - FuncStr = CodeGenFunction::getNonTrivialCopyConstructorStr( - CaptureTy, Alignment, IsVolatile, Ctx); - // The underscore is necessary here because non-trivial copy constructor - // and destructor strings can start with a number. - Str += llvm::to_string(FuncStr.size()) + "_" + FuncStr; - break; - } - case BlockCaptureEntityKind::None: - break; - } - - return Str; -} - -static std::string getCopyDestroyHelperFuncName( - const SmallVectorImpl<BlockCaptureManagedEntity> &Captures, - CharUnits BlockAlignment, CaptureStrKind StrKind, CodeGenModule &CGM) { - assert((StrKind == CaptureStrKind::CopyHelper || - StrKind == CaptureStrKind::DisposeHelper) && - "unexpected CaptureStrKind"); - std::string Name = StrKind == CaptureStrKind::CopyHelper - ? "__copy_helper_block_" - : "__destroy_helper_block_"; - if (CGM.getLangOpts().Exceptions) - Name += "e"; - if (CGM.getCodeGenOpts().ObjCAutoRefCountExceptions) - Name += "a"; - Name += llvm::to_string(BlockAlignment.getQuantity()) + "_"; - - for (const BlockCaptureManagedEntity &E : Captures) { - Name += llvm::to_string(E.Capture->getOffset().getQuantity()); - Name += getBlockCaptureStr(E, StrKind, BlockAlignment, CGM); - } - - return Name; -} - -static void pushCaptureCleanup(BlockCaptureEntityKind CaptureKind, - Address Field, QualType CaptureType, - BlockFieldFlags Flags, bool ForCopyHelper, - VarDecl *Var, CodeGenFunction &CGF) { - bool EHOnly = ForCopyHelper; - - switch (CaptureKind) { - case BlockCaptureEntityKind::CXXRecord: - case BlockCaptureEntityKind::ARCWeak: - case BlockCaptureEntityKind::NonTrivialCStruct: - case BlockCaptureEntityKind::ARCStrong: { - if (CaptureType.isDestructedType() && - (!EHOnly || CGF.needsEHCleanup(CaptureType.isDestructedType()))) { - CodeGenFunction::Destroyer *Destroyer = - CaptureKind == BlockCaptureEntityKind::ARCStrong - ? CodeGenFunction::destroyARCStrongImprecise - : CGF.getDestroyer(CaptureType.isDestructedType()); - CleanupKind Kind = - EHOnly ? EHCleanup - : CGF.getCleanupKind(CaptureType.isDestructedType()); - CGF.pushDestroy(Kind, Field, CaptureType, Destroyer, Kind & EHCleanup); - } - break; - } - case BlockCaptureEntityKind::BlockObject: { - if (!EHOnly || CGF.getLangOpts().Exceptions) { - CleanupKind Kind = EHOnly ? EHCleanup : NormalAndEHCleanup; - // Calls to _Block_object_dispose along the EH path in the copy helper - // function don't throw as newly-copied __block variables always have a - // reference count of 2. - bool CanThrow = - !ForCopyHelper && CGF.cxxDestructorCanThrow(CaptureType); - CGF.enterByrefCleanup(Kind, Field, Flags, /*LoadBlockVarAddr*/ true, - CanThrow); - } - break; - } - case BlockCaptureEntityKind::None: - break; - } -} - -static void setBlockHelperAttributesVisibility(bool CapturesNonExternalType, - llvm::Function *Fn, - const CGFunctionInfo &FI, - CodeGenModule &CGM) { - if (CapturesNonExternalType) { - CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI); - } else { - Fn->setVisibility(llvm::GlobalValue::HiddenVisibility); - Fn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Fn); - CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Fn); - } -} -/// Generate the copy-helper function for a block closure object: -/// static void block_copy_helper(block_t *dst, block_t *src); -/// The runtime will have previously initialized 'dst' by doing a -/// bit-copy of 'src'. -/// -/// Note that this copies an entire block closure object to the heap; -/// it should not be confused with a 'byref copy helper', which moves -/// the contents of an individual __block variable to the heap. -llvm::Constant * -CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { - SmallVector<BlockCaptureManagedEntity, 4> CopiedCaptures; - findBlockCapturedManagedEntities(blockInfo, getLangOpts(), CopiedCaptures); - std::string FuncName = - getCopyDestroyHelperFuncName(CopiedCaptures, blockInfo.BlockAlign, - CaptureStrKind::CopyHelper, CGM); - - if (llvm::GlobalValue *Func = CGM.getModule().getNamedValue(FuncName)) - return llvm::ConstantExpr::getBitCast(Func, VoidPtrTy); - - ASTContext &C = getContext(); - - QualType ReturnTy = C.VoidTy; - - FunctionArgList args; - ImplicitParamDecl DstDecl(C, C.VoidPtrTy, ImplicitParamDecl::Other); - args.push_back(&DstDecl); - ImplicitParamDecl SrcDecl(C, C.VoidPtrTy, ImplicitParamDecl::Other); - args.push_back(&SrcDecl); - - const CGFunctionInfo &FI = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args); - - // FIXME: it would be nice if these were mergeable with things with - // identical semantics. - llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI); - - llvm::Function *Fn = - llvm::Function::Create(LTy, llvm::GlobalValue::LinkOnceODRLinkage, - FuncName, &CGM.getModule()); - - IdentifierInfo *II = &C.Idents.get(FuncName); - - SmallVector<QualType, 2> ArgTys; - ArgTys.push_back(C.VoidPtrTy); - ArgTys.push_back(C.VoidPtrTy); - QualType FunctionTy = C.getFunctionType(ReturnTy, ArgTys, {}); - - FunctionDecl *FD = FunctionDecl::Create( - C, C.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II, - FunctionTy, nullptr, SC_Static, false, false); - - setBlockHelperAttributesVisibility(blockInfo.CapturesNonExternalType, Fn, FI, - CGM); - StartFunction(FD, ReturnTy, Fn, FI, args); - ApplyDebugLocation NL{*this, blockInfo.getBlockExpr()->getBeginLoc()}; - llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); - - Address src = GetAddrOfLocalVar(&SrcDecl); - src = Address(Builder.CreateLoad(src), blockInfo.BlockAlign); - src = Builder.CreateBitCast(src, structPtrTy, "block.source"); - - Address dst = GetAddrOfLocalVar(&DstDecl); - dst = Address(Builder.CreateLoad(dst), blockInfo.BlockAlign); - dst = Builder.CreateBitCast(dst, structPtrTy, "block.dest"); - - for (const auto &CopiedCapture : CopiedCaptures) { - const BlockDecl::Capture &CI = *CopiedCapture.CI; - const CGBlockInfo::Capture &capture = *CopiedCapture.Capture; - QualType captureType = CI.getVariable()->getType(); - BlockFieldFlags flags = CopiedCapture.CopyFlags; - - unsigned index = capture.getIndex(); - Address srcField = Builder.CreateStructGEP(src, index, capture.getOffset()); - Address dstField = Builder.CreateStructGEP(dst, index, capture.getOffset()); - - switch (CopiedCapture.CopyKind) { - case BlockCaptureEntityKind::CXXRecord: - // If there's an explicit copy expression, we do that. - assert(CI.getCopyExpr() && "copy expression for variable is missing"); - EmitSynthesizedCXXCopyCtor(dstField, srcField, CI.getCopyExpr()); - break; - case BlockCaptureEntityKind::ARCWeak: - EmitARCCopyWeak(dstField, srcField); - break; - case BlockCaptureEntityKind::NonTrivialCStruct: { - // If this is a C struct that requires non-trivial copy construction, - // emit a call to its copy constructor. - QualType varType = CI.getVariable()->getType(); - callCStructCopyConstructor(MakeAddrLValue(dstField, varType), - MakeAddrLValue(srcField, varType)); - break; - } - case BlockCaptureEntityKind::ARCStrong: { - llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src"); - // At -O0, store null into the destination field (so that the - // storeStrong doesn't over-release) and then call storeStrong. - // This is a workaround to not having an initStrong call. - if (CGM.getCodeGenOpts().OptimizationLevel == 0) { - auto *ty = cast<llvm::PointerType>(srcValue->getType()); - llvm::Value *null = llvm::ConstantPointerNull::get(ty); - Builder.CreateStore(null, dstField); - EmitARCStoreStrongCall(dstField, srcValue, true); - - // With optimization enabled, take advantage of the fact that - // the blocks runtime guarantees a memcpy of the block data, and - // just emit a retain of the src field. - } else { - EmitARCRetainNonBlock(srcValue); - - // Unless EH cleanup is required, we don't need this anymore, so kill - // 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(); - } - break; - } - case BlockCaptureEntityKind::BlockObject: { - llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src"); - srcValue = Builder.CreateBitCast(srcValue, VoidPtrTy); - llvm::Value *dstAddr = - Builder.CreateBitCast(dstField.getPointer(), VoidPtrTy); - llvm::Value *args[] = { - dstAddr, srcValue, llvm::ConstantInt::get(Int32Ty, flags.getBitMask()) - }; - - if (CI.isByRef() && C.getBlockVarCopyInit(CI.getVariable()).canThrow()) - EmitRuntimeCallOrInvoke(CGM.getBlockObjectAssign(), args); - else - EmitNounwindRuntimeCall(CGM.getBlockObjectAssign(), args); - break; - } - case BlockCaptureEntityKind::None: - continue; - } - - // Ensure that we destroy the copied object if an exception is thrown later - // in the helper function. - pushCaptureCleanup(CopiedCapture.CopyKind, dstField, captureType, flags, - /*ForCopyHelper*/ true, CI.getVariable(), *this); - } - - FinishFunction(); - - return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy); -} - -static BlockFieldFlags -getBlockFieldFlagsForObjCObjectPointer(const BlockDecl::Capture &CI, - QualType T) { - BlockFieldFlags Flags = BLOCK_FIELD_IS_OBJECT; - if (T->isBlockPointerType()) - Flags = BLOCK_FIELD_IS_BLOCK; - return Flags; -} - -static std::pair<BlockCaptureEntityKind, BlockFieldFlags> -computeDestroyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T, - const LangOptions &LangOpts) { - if (CI.isEscapingByref()) { - BlockFieldFlags Flags = BLOCK_FIELD_IS_BYREF; - if (T.isObjCGCWeak()) - Flags |= BLOCK_FIELD_IS_WEAK; - return std::make_pair(BlockCaptureEntityKind::BlockObject, Flags); - } - - switch (T.isDestructedType()) { - case QualType::DK_cxx_destructor: - return std::make_pair(BlockCaptureEntityKind::CXXRecord, BlockFieldFlags()); - case QualType::DK_objc_strong_lifetime: - // Use objc_storeStrong for __strong direct captures; the - // dynamic tools really like it when we do this. - return std::make_pair(BlockCaptureEntityKind::ARCStrong, - getBlockFieldFlagsForObjCObjectPointer(CI, T)); - case QualType::DK_objc_weak_lifetime: - // Support __weak direct captures. - return std::make_pair(BlockCaptureEntityKind::ARCWeak, - getBlockFieldFlagsForObjCObjectPointer(CI, T)); - case QualType::DK_nontrivial_c_struct: - return std::make_pair(BlockCaptureEntityKind::NonTrivialCStruct, - BlockFieldFlags()); - case QualType::DK_none: { - // Non-ARC captures are strong, and we need to use _Block_object_dispose. - if (T->isObjCRetainableType() && !T.getQualifiers().hasObjCLifetime() && - !LangOpts.ObjCAutoRefCount) - return std::make_pair(BlockCaptureEntityKind::BlockObject, - getBlockFieldFlagsForObjCObjectPointer(CI, T)); - // Otherwise, we have nothing to do. - return std::make_pair(BlockCaptureEntityKind::None, BlockFieldFlags()); - } - } - llvm_unreachable("after exhaustive DestructionKind switch"); -} - -/// Generate the destroy-helper function for a block closure object: -/// static void block_destroy_helper(block_t *theBlock); -/// -/// Note that this destroys a heap-allocated block closure object; -/// it should not be confused with a 'byref destroy helper', which -/// destroys the heap-allocated contents of an individual __block -/// variable. -llvm::Constant * -CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { - SmallVector<BlockCaptureManagedEntity, 4> DestroyedCaptures; - findBlockCapturedManagedEntities(blockInfo, getLangOpts(), DestroyedCaptures); - std::string FuncName = - getCopyDestroyHelperFuncName(DestroyedCaptures, blockInfo.BlockAlign, - CaptureStrKind::DisposeHelper, CGM); - - if (llvm::GlobalValue *Func = CGM.getModule().getNamedValue(FuncName)) - return llvm::ConstantExpr::getBitCast(Func, VoidPtrTy); - - ASTContext &C = getContext(); - - QualType ReturnTy = C.VoidTy; - - FunctionArgList args; - ImplicitParamDecl SrcDecl(C, C.VoidPtrTy, ImplicitParamDecl::Other); - args.push_back(&SrcDecl); - - const CGFunctionInfo &FI = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args); - - // FIXME: We'd like to put these into a mergable by content, with - // internal linkage. - llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI); - - llvm::Function *Fn = - llvm::Function::Create(LTy, llvm::GlobalValue::LinkOnceODRLinkage, - FuncName, &CGM.getModule()); - - IdentifierInfo *II = &C.Idents.get(FuncName); - - SmallVector<QualType, 1> ArgTys; - ArgTys.push_back(C.VoidPtrTy); - QualType FunctionTy = C.getFunctionType(ReturnTy, ArgTys, {}); - - FunctionDecl *FD = FunctionDecl::Create( - C, C.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II, - FunctionTy, nullptr, SC_Static, false, false); - - setBlockHelperAttributesVisibility(blockInfo.CapturesNonExternalType, Fn, FI, - CGM); - StartFunction(FD, ReturnTy, Fn, FI, args); - markAsIgnoreThreadCheckingAtRuntime(Fn); - - ApplyDebugLocation NL{*this, blockInfo.getBlockExpr()->getBeginLoc()}; - - llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); - - Address src = GetAddrOfLocalVar(&SrcDecl); - src = Address(Builder.CreateLoad(src), blockInfo.BlockAlign); - src = Builder.CreateBitCast(src, structPtrTy, "block"); - - CodeGenFunction::RunCleanupsScope cleanups(*this); - - for (const auto &DestroyedCapture : DestroyedCaptures) { - const BlockDecl::Capture &CI = *DestroyedCapture.CI; - const CGBlockInfo::Capture &capture = *DestroyedCapture.Capture; - BlockFieldFlags flags = DestroyedCapture.DisposeFlags; - - Address srcField = - Builder.CreateStructGEP(src, capture.getIndex(), capture.getOffset()); - - pushCaptureCleanup(DestroyedCapture.DisposeKind, srcField, - CI.getVariable()->getType(), flags, - /*ForCopyHelper*/ false, CI.getVariable(), *this); - } - - cleanups.ForceCleanup(); - - FinishFunction(); - - return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy); -} - -namespace { - -/// Emits the copy/dispose helper functions for a __block object of id type. -class ObjectByrefHelpers final : public BlockByrefHelpers { - BlockFieldFlags Flags; - -public: - ObjectByrefHelpers(CharUnits alignment, BlockFieldFlags flags) - : BlockByrefHelpers(alignment), Flags(flags) {} - - void emitCopy(CodeGenFunction &CGF, Address destField, - Address srcField) override { - destField = CGF.Builder.CreateBitCast(destField, CGF.VoidPtrTy); - - srcField = CGF.Builder.CreateBitCast(srcField, CGF.VoidPtrPtrTy); - llvm::Value *srcValue = CGF.Builder.CreateLoad(srcField); - - unsigned flags = (Flags | BLOCK_BYREF_CALLER).getBitMask(); - - llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.Int32Ty, flags); - llvm::Value *fn = CGF.CGM.getBlockObjectAssign(); - - llvm::Value *args[] = { destField.getPointer(), srcValue, flagsVal }; - CGF.EmitNounwindRuntimeCall(fn, args); - } - - void emitDispose(CodeGenFunction &CGF, Address field) override { - field = CGF.Builder.CreateBitCast(field, CGF.Int8PtrTy->getPointerTo(0)); - llvm::Value *value = CGF.Builder.CreateLoad(field); - - CGF.BuildBlockRelease(value, Flags | BLOCK_BYREF_CALLER, false); - } - - void profileImpl(llvm::FoldingSetNodeID &id) const override { - id.AddInteger(Flags.getBitMask()); - } -}; - -/// Emits the copy/dispose helpers for an ARC __block __weak variable. -class ARCWeakByrefHelpers final : public BlockByrefHelpers { -public: - ARCWeakByrefHelpers(CharUnits alignment) : BlockByrefHelpers(alignment) {} - - void emitCopy(CodeGenFunction &CGF, Address destField, - Address srcField) override { - CGF.EmitARCMoveWeak(destField, srcField); - } - - void emitDispose(CodeGenFunction &CGF, Address field) override { - CGF.EmitARCDestroyWeak(field); - } - - void profileImpl(llvm::FoldingSetNodeID &id) const override { - // 0 is distinguishable from all pointers and byref flags - id.AddInteger(0); - } -}; - -/// Emits the copy/dispose helpers for an ARC __block __strong variable -/// that's not of block-pointer type. -class ARCStrongByrefHelpers final : public BlockByrefHelpers { -public: - ARCStrongByrefHelpers(CharUnits alignment) : BlockByrefHelpers(alignment) {} - - void emitCopy(CodeGenFunction &CGF, Address destField, - Address srcField) override { - // Do a "move" by copying the value and then zeroing out the old - // variable. - - llvm::Value *value = CGF.Builder.CreateLoad(srcField); - - llvm::Value *null = - llvm::ConstantPointerNull::get(cast<llvm::PointerType>(value->getType())); - - if (CGF.CGM.getCodeGenOpts().OptimizationLevel == 0) { - CGF.Builder.CreateStore(null, destField); - CGF.EmitARCStoreStrongCall(destField, value, /*ignored*/ true); - CGF.EmitARCStoreStrongCall(srcField, null, /*ignored*/ true); - return; - } - CGF.Builder.CreateStore(value, destField); - CGF.Builder.CreateStore(null, srcField); - } - - void emitDispose(CodeGenFunction &CGF, Address field) override { - CGF.EmitARCDestroyStrong(field, ARCImpreciseLifetime); - } - - void profileImpl(llvm::FoldingSetNodeID &id) const override { - // 1 is distinguishable from all pointers and byref flags - id.AddInteger(1); - } -}; - -/// Emits the copy/dispose helpers for an ARC __block __strong -/// variable that's of block-pointer type. -class ARCStrongBlockByrefHelpers final : public BlockByrefHelpers { -public: - ARCStrongBlockByrefHelpers(CharUnits alignment) - : BlockByrefHelpers(alignment) {} - - void emitCopy(CodeGenFunction &CGF, Address destField, - Address srcField) override { - // Do the copy with objc_retainBlock; that's all that - // _Block_object_assign would do anyway, and we'd have to pass the - // right arguments to make sure it doesn't get no-op'ed. - llvm::Value *oldValue = CGF.Builder.CreateLoad(srcField); - llvm::Value *copy = CGF.EmitARCRetainBlock(oldValue, /*mandatory*/ true); - CGF.Builder.CreateStore(copy, destField); - } - - void emitDispose(CodeGenFunction &CGF, Address field) override { - CGF.EmitARCDestroyStrong(field, ARCImpreciseLifetime); - } - - void profileImpl(llvm::FoldingSetNodeID &id) const override { - // 2 is distinguishable from all pointers and byref flags - id.AddInteger(2); - } -}; - -/// Emits the copy/dispose helpers for a __block variable with a -/// nontrivial copy constructor or destructor. -class CXXByrefHelpers final : public BlockByrefHelpers { - QualType VarType; - const Expr *CopyExpr; - -public: - CXXByrefHelpers(CharUnits alignment, QualType type, - const Expr *copyExpr) - : BlockByrefHelpers(alignment), VarType(type), CopyExpr(copyExpr) {} - - bool needsCopy() const override { return CopyExpr != nullptr; } - void emitCopy(CodeGenFunction &CGF, Address destField, - Address srcField) override { - if (!CopyExpr) return; - CGF.EmitSynthesizedCXXCopyCtor(destField, srcField, CopyExpr); - } - - void emitDispose(CodeGenFunction &CGF, Address field) override { - EHScopeStack::stable_iterator cleanupDepth = CGF.EHStack.stable_begin(); - CGF.PushDestructorCleanup(VarType, field); - CGF.PopCleanupBlocks(cleanupDepth); - } - - void profileImpl(llvm::FoldingSetNodeID &id) const override { - id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr()); - } -}; - -/// Emits the copy/dispose helpers for a __block variable that is a non-trivial -/// C struct. -class NonTrivialCStructByrefHelpers final : public BlockByrefHelpers { - QualType VarType; - -public: - NonTrivialCStructByrefHelpers(CharUnits alignment, QualType type) - : BlockByrefHelpers(alignment), VarType(type) {} - - void emitCopy(CodeGenFunction &CGF, Address destField, - Address srcField) override { - CGF.callCStructMoveConstructor(CGF.MakeAddrLValue(destField, VarType), - CGF.MakeAddrLValue(srcField, VarType)); - } - - bool needsDispose() const override { - return VarType.isDestructedType(); - } - - void emitDispose(CodeGenFunction &CGF, Address field) override { - EHScopeStack::stable_iterator cleanupDepth = CGF.EHStack.stable_begin(); - CGF.pushDestroy(VarType.isDestructedType(), field, VarType); - CGF.PopCleanupBlocks(cleanupDepth); - } - - void profileImpl(llvm::FoldingSetNodeID &id) const override { - id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr()); - } -}; -} // end anonymous namespace - -static llvm::Constant * -generateByrefCopyHelper(CodeGenFunction &CGF, const BlockByrefInfo &byrefInfo, - BlockByrefHelpers &generator) { - ASTContext &Context = CGF.getContext(); - - QualType ReturnTy = Context.VoidTy; - - FunctionArgList args; - ImplicitParamDecl Dst(Context, Context.VoidPtrTy, ImplicitParamDecl::Other); - args.push_back(&Dst); - - ImplicitParamDecl Src(Context, Context.VoidPtrTy, ImplicitParamDecl::Other); - args.push_back(&Src); - - const CGFunctionInfo &FI = - CGF.CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args); - - llvm::FunctionType *LTy = CGF.CGM.getTypes().GetFunctionType(FI); - - // FIXME: We'd like to put these into a mergable by content, with - // internal linkage. - llvm::Function *Fn = - llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, - "__Block_byref_object_copy_", &CGF.CGM.getModule()); - - IdentifierInfo *II - = &Context.Idents.get("__Block_byref_object_copy_"); - - SmallVector<QualType, 2> ArgTys; - ArgTys.push_back(Context.VoidPtrTy); - ArgTys.push_back(Context.VoidPtrTy); - QualType FunctionTy = Context.getFunctionType(ReturnTy, ArgTys, {}); - - FunctionDecl *FD = FunctionDecl::Create( - Context, Context.getTranslationUnitDecl(), SourceLocation(), - SourceLocation(), II, FunctionTy, nullptr, SC_Static, false, false); - - CGF.CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI); - - CGF.StartFunction(FD, ReturnTy, Fn, FI, args); - - if (generator.needsCopy()) { - llvm::Type *byrefPtrType = byrefInfo.Type->getPointerTo(0); - - // dst->x - Address destField = CGF.GetAddrOfLocalVar(&Dst); - destField = Address(CGF.Builder.CreateLoad(destField), - byrefInfo.ByrefAlignment); - destField = CGF.Builder.CreateBitCast(destField, byrefPtrType); - destField = CGF.emitBlockByrefAddress(destField, byrefInfo, false, - "dest-object"); - - // src->x - Address srcField = CGF.GetAddrOfLocalVar(&Src); - srcField = Address(CGF.Builder.CreateLoad(srcField), - byrefInfo.ByrefAlignment); - srcField = CGF.Builder.CreateBitCast(srcField, byrefPtrType); - srcField = CGF.emitBlockByrefAddress(srcField, byrefInfo, false, - "src-object"); - - generator.emitCopy(CGF, destField, srcField); - } - - CGF.FinishFunction(); - - return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy); -} - -/// Build the copy helper for a __block variable. -static llvm::Constant *buildByrefCopyHelper(CodeGenModule &CGM, - const BlockByrefInfo &byrefInfo, - BlockByrefHelpers &generator) { - CodeGenFunction CGF(CGM); - return generateByrefCopyHelper(CGF, byrefInfo, generator); -} - -/// Generate code for a __block variable's dispose helper. -static llvm::Constant * -generateByrefDisposeHelper(CodeGenFunction &CGF, - const BlockByrefInfo &byrefInfo, - BlockByrefHelpers &generator) { - ASTContext &Context = CGF.getContext(); - QualType R = Context.VoidTy; - - FunctionArgList args; - ImplicitParamDecl Src(CGF.getContext(), Context.VoidPtrTy, - ImplicitParamDecl::Other); - args.push_back(&Src); - - const CGFunctionInfo &FI = - CGF.CGM.getTypes().arrangeBuiltinFunctionDeclaration(R, args); - - llvm::FunctionType *LTy = CGF.CGM.getTypes().GetFunctionType(FI); - - // FIXME: We'd like to put these into a mergable by content, with - // internal linkage. - llvm::Function *Fn = - llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, - "__Block_byref_object_dispose_", - &CGF.CGM.getModule()); - - IdentifierInfo *II - = &Context.Idents.get("__Block_byref_object_dispose_"); - - SmallVector<QualType, 1> ArgTys; - ArgTys.push_back(Context.VoidPtrTy); - QualType FunctionTy = Context.getFunctionType(R, ArgTys, {}); - - FunctionDecl *FD = FunctionDecl::Create( - Context, Context.getTranslationUnitDecl(), SourceLocation(), - SourceLocation(), II, FunctionTy, nullptr, SC_Static, false, false); - - CGF.CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI); - - CGF.StartFunction(FD, R, Fn, FI, args); - - if (generator.needsDispose()) { - Address addr = CGF.GetAddrOfLocalVar(&Src); - addr = Address(CGF.Builder.CreateLoad(addr), byrefInfo.ByrefAlignment); - auto byrefPtrType = byrefInfo.Type->getPointerTo(0); - addr = CGF.Builder.CreateBitCast(addr, byrefPtrType); - addr = CGF.emitBlockByrefAddress(addr, byrefInfo, false, "object"); - - generator.emitDispose(CGF, addr); - } - - CGF.FinishFunction(); - - return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy); -} - -/// Build the dispose helper for a __block variable. -static llvm::Constant *buildByrefDisposeHelper(CodeGenModule &CGM, - const BlockByrefInfo &byrefInfo, - BlockByrefHelpers &generator) { - CodeGenFunction CGF(CGM); - return generateByrefDisposeHelper(CGF, byrefInfo, generator); -} - -/// Lazily build the copy and dispose helpers for a __block variable -/// with the given information. -template <class T> -static T *buildByrefHelpers(CodeGenModule &CGM, const BlockByrefInfo &byrefInfo, - T &&generator) { - llvm::FoldingSetNodeID id; - generator.Profile(id); - - void *insertPos; - BlockByrefHelpers *node - = CGM.ByrefHelpersCache.FindNodeOrInsertPos(id, insertPos); - if (node) return static_cast<T*>(node); - - generator.CopyHelper = buildByrefCopyHelper(CGM, byrefInfo, generator); - generator.DisposeHelper = buildByrefDisposeHelper(CGM, byrefInfo, generator); - - T *copy = new (CGM.getContext()) T(std::forward<T>(generator)); - CGM.ByrefHelpersCache.InsertNode(copy, insertPos); - return copy; -} - -/// Build the copy and dispose helpers for the given __block variable -/// emission. Places the helpers in the global cache. Returns null -/// if no helpers are required. -BlockByrefHelpers * -CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType, - const AutoVarEmission &emission) { - const VarDecl &var = *emission.Variable; - assert(var.isEscapingByref() && - "only escaping __block variables need byref helpers"); - - QualType type = var.getType(); - - auto &byrefInfo = getBlockByrefInfo(&var); - - // The alignment we care about for the purposes of uniquing byref - // helpers is the alignment of the actual byref value field. - CharUnits valueAlignment = - byrefInfo.ByrefAlignment.alignmentAtOffset(byrefInfo.FieldOffset); - - if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) { - const Expr *copyExpr = - CGM.getContext().getBlockVarCopyInit(&var).getCopyExpr(); - if (!copyExpr && record->hasTrivialDestructor()) return nullptr; - - return ::buildByrefHelpers( - CGM, byrefInfo, CXXByrefHelpers(valueAlignment, type, copyExpr)); - } - - // If type is a non-trivial C struct type that is non-trivial to - // destructly move or destroy, build the copy and dispose helpers. - if (type.isNonTrivialToPrimitiveDestructiveMove() == QualType::PCK_Struct || - type.isDestructedType() == QualType::DK_nontrivial_c_struct) - return ::buildByrefHelpers( - CGM, byrefInfo, NonTrivialCStructByrefHelpers(valueAlignment, type)); - - // Otherwise, if we don't have a retainable type, there's nothing to do. - // that the runtime does extra copies. - if (!type->isObjCRetainableType()) return nullptr; - - Qualifiers qs = type.getQualifiers(); - - // If we have lifetime, that dominates. - if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) { - switch (lifetime) { - case Qualifiers::OCL_None: llvm_unreachable("impossible"); - - // These are just bits as far as the runtime is concerned. - case Qualifiers::OCL_ExplicitNone: - case Qualifiers::OCL_Autoreleasing: - return nullptr; - - // Tell the runtime that this is ARC __weak, called by the - // byref routines. - case Qualifiers::OCL_Weak: - return ::buildByrefHelpers(CGM, byrefInfo, - ARCWeakByrefHelpers(valueAlignment)); - - // ARC __strong __block variables need to be retained. - case Qualifiers::OCL_Strong: - // Block pointers need to be copied, and there's no direct - // transfer possible. - if (type->isBlockPointerType()) { - return ::buildByrefHelpers(CGM, byrefInfo, - ARCStrongBlockByrefHelpers(valueAlignment)); - - // Otherwise, we transfer ownership of the retain from the stack - // to the heap. - } else { - return ::buildByrefHelpers(CGM, byrefInfo, - ARCStrongByrefHelpers(valueAlignment)); - } - } - llvm_unreachable("fell out of lifetime switch!"); - } - - BlockFieldFlags flags; - if (type->isBlockPointerType()) { - flags |= BLOCK_FIELD_IS_BLOCK; - } else if (CGM.getContext().isObjCNSObjectType(type) || - type->isObjCObjectPointerType()) { - flags |= BLOCK_FIELD_IS_OBJECT; - } else { - return nullptr; - } - - if (type.isObjCGCWeak()) - flags |= BLOCK_FIELD_IS_WEAK; - - return ::buildByrefHelpers(CGM, byrefInfo, - ObjectByrefHelpers(valueAlignment, flags)); -} - -Address CodeGenFunction::emitBlockByrefAddress(Address baseAddr, - const VarDecl *var, - bool followForward) { - auto &info = getBlockByrefInfo(var); - return emitBlockByrefAddress(baseAddr, info, followForward, var->getName()); -} - -Address CodeGenFunction::emitBlockByrefAddress(Address baseAddr, - const BlockByrefInfo &info, - bool followForward, - const llvm::Twine &name) { - // Chase the forwarding address if requested. - if (followForward) { - Address forwardingAddr = - Builder.CreateStructGEP(baseAddr, 1, getPointerSize(), "forwarding"); - baseAddr = Address(Builder.CreateLoad(forwardingAddr), info.ByrefAlignment); - } - - return Builder.CreateStructGEP(baseAddr, info.FieldIndex, - info.FieldOffset, name); -} - -/// BuildByrefInfo - This routine changes a __block variable declared as T x -/// into: -/// -/// struct { -/// void *__isa; -/// void *__forwarding; -/// int32_t __flags; -/// int32_t __size; -/// void *__copy_helper; // only if needed -/// void *__destroy_helper; // only if needed -/// void *__byref_variable_layout;// only if needed -/// char padding[X]; // only if needed -/// T x; -/// } x -/// -const BlockByrefInfo &CodeGenFunction::getBlockByrefInfo(const VarDecl *D) { - auto it = BlockByrefInfos.find(D); - if (it != BlockByrefInfos.end()) - return it->second; - - llvm::StructType *byrefType = - llvm::StructType::create(getLLVMContext(), - "struct.__block_byref_" + D->getNameAsString()); - - QualType Ty = D->getType(); - - CharUnits size; - SmallVector<llvm::Type *, 8> types; - - // void *__isa; - types.push_back(Int8PtrTy); - size += getPointerSize(); - - // void *__forwarding; - types.push_back(llvm::PointerType::getUnqual(byrefType)); - size += getPointerSize(); - - // int32_t __flags; - types.push_back(Int32Ty); - size += CharUnits::fromQuantity(4); - - // int32_t __size; - types.push_back(Int32Ty); - size += CharUnits::fromQuantity(4); - - // Note that this must match *exactly* the logic in buildByrefHelpers. - bool hasCopyAndDispose = getContext().BlockRequiresCopying(Ty, D); - if (hasCopyAndDispose) { - /// void *__copy_helper; - types.push_back(Int8PtrTy); - size += getPointerSize(); - - /// void *__destroy_helper; - types.push_back(Int8PtrTy); - size += getPointerSize(); - } - - bool HasByrefExtendedLayout = false; - Qualifiers::ObjCLifetime Lifetime; - if (getContext().getByrefLifetime(Ty, Lifetime, HasByrefExtendedLayout) && - HasByrefExtendedLayout) { - /// void *__byref_variable_layout; - types.push_back(Int8PtrTy); - size += CharUnits::fromQuantity(PointerSizeInBytes); - } - - // T x; - llvm::Type *varTy = ConvertTypeForMem(Ty); - - bool packed = false; - CharUnits varAlign = getContext().getDeclAlign(D); - CharUnits varOffset = size.alignTo(varAlign); - - // We may have to insert padding. - if (varOffset != size) { - llvm::Type *paddingTy = - llvm::ArrayType::get(Int8Ty, (varOffset - size).getQuantity()); - - types.push_back(paddingTy); - size = varOffset; - - // Conversely, we might have to prevent LLVM from inserting padding. - } else if (CGM.getDataLayout().getABITypeAlignment(varTy) - > varAlign.getQuantity()) { - packed = true; - } - types.push_back(varTy); - - byrefType->setBody(types, packed); - - BlockByrefInfo info; - info.Type = byrefType; - info.FieldIndex = types.size() - 1; - info.FieldOffset = varOffset; - info.ByrefAlignment = std::max(varAlign, getPointerAlign()); - - auto pair = BlockByrefInfos.insert({D, info}); - assert(pair.second && "info was inserted recursively?"); - return pair.first->second; -} - -/// Initialize the structural components of a __block variable, i.e. -/// everything but the actual object. -void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) { - // Find the address of the local. - Address addr = emission.Addr; - - // That's an alloca of the byref structure type. - llvm::StructType *byrefType = cast<llvm::StructType>( - cast<llvm::PointerType>(addr.getPointer()->getType())->getElementType()); - - unsigned nextHeaderIndex = 0; - CharUnits nextHeaderOffset; - auto storeHeaderField = [&](llvm::Value *value, CharUnits fieldSize, - const Twine &name) { - auto fieldAddr = Builder.CreateStructGEP(addr, nextHeaderIndex, - nextHeaderOffset, name); - Builder.CreateStore(value, fieldAddr); - - nextHeaderIndex++; - nextHeaderOffset += fieldSize; - }; - - // Build the byref helpers if necessary. This is null if we don't need any. - BlockByrefHelpers *helpers = buildByrefHelpers(*byrefType, emission); - - const VarDecl &D = *emission.Variable; - QualType type = D.getType(); - - bool HasByrefExtendedLayout; - Qualifiers::ObjCLifetime ByrefLifetime; - bool ByRefHasLifetime = - getContext().getByrefLifetime(type, ByrefLifetime, HasByrefExtendedLayout); - - llvm::Value *V; - - // Initialize the 'isa', which is just 0 or 1. - int isa = 0; - if (type.isObjCGCWeak()) - isa = 1; - V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa"); - storeHeaderField(V, getPointerSize(), "byref.isa"); - - // Store the address of the variable into its own forwarding pointer. - storeHeaderField(addr.getPointer(), getPointerSize(), "byref.forwarding"); - - // Blocks ABI: - // c) the flags field is set to either 0 if no helper functions are - // needed or BLOCK_BYREF_HAS_COPY_DISPOSE if they are, - BlockFlags flags; - if (helpers) flags |= BLOCK_BYREF_HAS_COPY_DISPOSE; - if (ByRefHasLifetime) { - if (HasByrefExtendedLayout) flags |= BLOCK_BYREF_LAYOUT_EXTENDED; - else switch (ByrefLifetime) { - case Qualifiers::OCL_Strong: - flags |= BLOCK_BYREF_LAYOUT_STRONG; - break; - case Qualifiers::OCL_Weak: - flags |= BLOCK_BYREF_LAYOUT_WEAK; - break; - case Qualifiers::OCL_ExplicitNone: - flags |= BLOCK_BYREF_LAYOUT_UNRETAINED; - break; - case Qualifiers::OCL_None: - if (!type->isObjCObjectPointerType() && !type->isBlockPointerType()) - flags |= BLOCK_BYREF_LAYOUT_NON_OBJECT; - break; - default: - break; - } - if (CGM.getLangOpts().ObjCGCBitmapPrint) { - printf("\n Inline flag for BYREF variable layout (%d):", flags.getBitMask()); - if (flags & BLOCK_BYREF_HAS_COPY_DISPOSE) - printf(" BLOCK_BYREF_HAS_COPY_DISPOSE"); - if (flags & BLOCK_BYREF_LAYOUT_MASK) { - BlockFlags ThisFlag(flags.getBitMask() & BLOCK_BYREF_LAYOUT_MASK); - if (ThisFlag == BLOCK_BYREF_LAYOUT_EXTENDED) - printf(" BLOCK_BYREF_LAYOUT_EXTENDED"); - if (ThisFlag == BLOCK_BYREF_LAYOUT_STRONG) - printf(" BLOCK_BYREF_LAYOUT_STRONG"); - if (ThisFlag == BLOCK_BYREF_LAYOUT_WEAK) - printf(" BLOCK_BYREF_LAYOUT_WEAK"); - if (ThisFlag == BLOCK_BYREF_LAYOUT_UNRETAINED) - printf(" BLOCK_BYREF_LAYOUT_UNRETAINED"); - if (ThisFlag == BLOCK_BYREF_LAYOUT_NON_OBJECT) - printf(" BLOCK_BYREF_LAYOUT_NON_OBJECT"); - } - printf("\n"); - } - } - storeHeaderField(llvm::ConstantInt::get(IntTy, flags.getBitMask()), - getIntSize(), "byref.flags"); - - CharUnits byrefSize = CGM.GetTargetTypeStoreSize(byrefType); - V = llvm::ConstantInt::get(IntTy, byrefSize.getQuantity()); - storeHeaderField(V, getIntSize(), "byref.size"); - - if (helpers) { - storeHeaderField(helpers->CopyHelper, getPointerSize(), - "byref.copyHelper"); - storeHeaderField(helpers->DisposeHelper, getPointerSize(), - "byref.disposeHelper"); - } - - if (ByRefHasLifetime && HasByrefExtendedLayout) { - auto layoutInfo = CGM.getObjCRuntime().BuildByrefLayout(CGM, type); - storeHeaderField(layoutInfo, getPointerSize(), "byref.layout"); - } -} - -void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags, - bool CanThrow) { - llvm::Value *F = CGM.getBlockObjectDispose(); - llvm::Value *args[] = { - Builder.CreateBitCast(V, Int8PtrTy), - llvm::ConstantInt::get(Int32Ty, flags.getBitMask()) - }; - - if (CanThrow) - EmitRuntimeCallOrInvoke(F, args); - else - EmitNounwindRuntimeCall(F, args); -} - -void CodeGenFunction::enterByrefCleanup(CleanupKind Kind, Address Addr, - BlockFieldFlags Flags, - bool LoadBlockVarAddr, bool CanThrow) { - EHStack.pushCleanup<CallBlockRelease>(Kind, Addr, Flags, LoadBlockVarAddr, - CanThrow); -} - -/// Adjust the declaration of something from the blocks API. -static void configureBlocksRuntimeObject(CodeGenModule &CGM, - llvm::Constant *C) { - auto *GV = cast<llvm::GlobalValue>(C->stripPointerCasts()); - - if (CGM.getTarget().getTriple().isOSBinFormatCOFF()) { - IdentifierInfo &II = CGM.getContext().Idents.get(C->getName()); - TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl(); - DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl); - - assert((isa<llvm::Function>(C->stripPointerCasts()) || - isa<llvm::GlobalVariable>(C->stripPointerCasts())) && - "expected Function or GlobalVariable"); - - const NamedDecl *ND = nullptr; - for (const auto &Result : DC->lookup(&II)) - if ((ND = dyn_cast<FunctionDecl>(Result)) || - (ND = dyn_cast<VarDecl>(Result))) - break; - - // TODO: support static blocks runtime - if (GV->isDeclaration() && (!ND || !ND->hasAttr<DLLExportAttr>())) { - GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); - GV->setLinkage(llvm::GlobalValue::ExternalLinkage); - } else { - GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); - GV->setLinkage(llvm::GlobalValue::ExternalLinkage); - } - } - - if (CGM.getLangOpts().BlocksRuntimeOptional && GV->isDeclaration() && - GV->hasExternalLinkage()) - GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); - - CGM.setDSOLocal(GV); -} - -llvm::Constant *CodeGenModule::getBlockObjectDispose() { - if (BlockObjectDispose) - return BlockObjectDispose; - - llvm::Type *args[] = { Int8PtrTy, Int32Ty }; - llvm::FunctionType *fty - = llvm::FunctionType::get(VoidTy, args, false); - BlockObjectDispose = CreateRuntimeFunction(fty, "_Block_object_dispose"); - configureBlocksRuntimeObject(*this, BlockObjectDispose); - return BlockObjectDispose; -} - -llvm::Constant *CodeGenModule::getBlockObjectAssign() { - if (BlockObjectAssign) - return BlockObjectAssign; - - llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, Int32Ty }; - llvm::FunctionType *fty - = llvm::FunctionType::get(VoidTy, args, false); - BlockObjectAssign = CreateRuntimeFunction(fty, "_Block_object_assign"); - configureBlocksRuntimeObject(*this, BlockObjectAssign); - return BlockObjectAssign; -} - -llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() { - if (NSConcreteGlobalBlock) - return NSConcreteGlobalBlock; - - NSConcreteGlobalBlock = GetOrCreateLLVMGlobal("_NSConcreteGlobalBlock", - Int8PtrTy->getPointerTo(), - nullptr); - configureBlocksRuntimeObject(*this, NSConcreteGlobalBlock); - return NSConcreteGlobalBlock; -} - -llvm::Constant *CodeGenModule::getNSConcreteStackBlock() { - if (NSConcreteStackBlock) - return NSConcreteStackBlock; - - NSConcreteStackBlock = GetOrCreateLLVMGlobal("_NSConcreteStackBlock", - Int8PtrTy->getPointerTo(), - nullptr); - configureBlocksRuntimeObject(*this, NSConcreteStackBlock); - return NSConcreteStackBlock; -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGBlocks.h b/gnu/llvm/tools/clang/lib/CodeGen/CGBlocks.h deleted file mode 100644 index 3f9fc16d9b1..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGBlocks.h +++ /dev/null @@ -1,299 +0,0 @@ -//===-- CGBlocks.h - state for LLVM CodeGen for blocks ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This is the internal state used for llvm translation for block literals. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CGBLOCKS_H -#define LLVM_CLANG_LIB_CODEGEN_CGBLOCKS_H - -#include "CGBuilder.h" -#include "CGCall.h" -#include "CGValue.h" -#include "CodeGenFunction.h" -#include "CodeGenTypes.h" -#include "clang/AST/CharUnits.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/ExprObjC.h" -#include "clang/AST/Type.h" -#include "clang/Basic/TargetInfo.h" - -namespace llvm { -class Constant; -class Function; -class GlobalValue; -class DataLayout; -class FunctionType; -class PointerType; -class Value; -class LLVMContext; -} - -namespace clang { -namespace CodeGen { - -class CGBlockInfo; - -// Flags stored in __block variables. -enum BlockByrefFlags { - BLOCK_BYREF_HAS_COPY_DISPOSE = (1 << 25), // compiler - BLOCK_BYREF_LAYOUT_MASK = (0xF << 28), // compiler - BLOCK_BYREF_LAYOUT_EXTENDED = (1 << 28), - BLOCK_BYREF_LAYOUT_NON_OBJECT = (2 << 28), - BLOCK_BYREF_LAYOUT_STRONG = (3 << 28), - BLOCK_BYREF_LAYOUT_WEAK = (4 << 28), - BLOCK_BYREF_LAYOUT_UNRETAINED = (5 << 28) -}; - -enum BlockLiteralFlags { - BLOCK_IS_NOESCAPE = (1 << 23), - BLOCK_HAS_COPY_DISPOSE = (1 << 25), - BLOCK_HAS_CXX_OBJ = (1 << 26), - BLOCK_IS_GLOBAL = (1 << 28), - BLOCK_USE_STRET = (1 << 29), - BLOCK_HAS_SIGNATURE = (1 << 30), - BLOCK_HAS_EXTENDED_LAYOUT = (1u << 31) -}; -class BlockFlags { - uint32_t flags; - -public: - BlockFlags(uint32_t flags) : flags(flags) {} - BlockFlags() : flags(0) {} - BlockFlags(BlockLiteralFlags flag) : flags(flag) {} - BlockFlags(BlockByrefFlags flag) : flags(flag) {} - - uint32_t getBitMask() const { return flags; } - bool empty() const { return flags == 0; } - - friend BlockFlags operator|(BlockFlags l, BlockFlags r) { - return BlockFlags(l.flags | r.flags); - } - friend BlockFlags &operator|=(BlockFlags &l, BlockFlags r) { - l.flags |= r.flags; - return l; - } - friend bool operator&(BlockFlags l, BlockFlags r) { - return (l.flags & r.flags); - } - bool operator==(BlockFlags r) { - return (flags == r.flags); - } -}; -inline BlockFlags operator|(BlockLiteralFlags l, BlockLiteralFlags r) { - return BlockFlags(l) | BlockFlags(r); -} - -enum BlockFieldFlag_t { - BLOCK_FIELD_IS_OBJECT = 0x03, /* id, NSObject, __attribute__((NSObject)), - block, ... */ - BLOCK_FIELD_IS_BLOCK = 0x07, /* a block variable */ - - BLOCK_FIELD_IS_BYREF = 0x08, /* the on stack structure holding the __block - variable */ - BLOCK_FIELD_IS_WEAK = 0x10, /* declared __weak, only used in byref copy - helpers */ - BLOCK_FIELD_IS_ARC = 0x40, /* field has ARC-specific semantics */ - BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose - support routines */ - BLOCK_BYREF_CURRENT_MAX = 256 -}; - -class BlockFieldFlags { - uint32_t flags; - - BlockFieldFlags(uint32_t flags) : flags(flags) {} -public: - BlockFieldFlags() : flags(0) {} - BlockFieldFlags(BlockFieldFlag_t flag) : flags(flag) {} - - uint32_t getBitMask() const { return flags; } - bool empty() const { return flags == 0; } - - /// Answers whether the flags indicate that this field is an object - /// or block pointer that requires _Block_object_assign/dispose. - bool isSpecialPointer() const { return flags & BLOCK_FIELD_IS_OBJECT; } - - friend BlockFieldFlags operator|(BlockFieldFlags l, BlockFieldFlags r) { - return BlockFieldFlags(l.flags | r.flags); - } - friend BlockFieldFlags &operator|=(BlockFieldFlags &l, BlockFieldFlags r) { - l.flags |= r.flags; - return l; - } - friend bool operator&(BlockFieldFlags l, BlockFieldFlags r) { - return (l.flags & r.flags); - } - bool operator==(BlockFieldFlags Other) const { - return flags == Other.flags; - } -}; -inline BlockFieldFlags operator|(BlockFieldFlag_t l, BlockFieldFlag_t r) { - return BlockFieldFlags(l) | BlockFieldFlags(r); -} - -/// Information about the layout of a __block variable. -class BlockByrefInfo { -public: - llvm::StructType *Type; - unsigned FieldIndex; - CharUnits ByrefAlignment; - CharUnits FieldOffset; -}; - -/// CGBlockInfo - Information to generate a block literal. -class CGBlockInfo { -public: - /// Name - The name of the block, kindof. - StringRef Name; - - /// The field index of 'this' within the block, if there is one. - unsigned CXXThisIndex; - - class Capture { - uintptr_t Data; - EHScopeStack::stable_iterator Cleanup; - CharUnits::QuantityType Offset; - - /// Type of the capture field. Normally, this is identical to the type of - /// the capture's VarDecl, but can be different if there is an enclosing - /// lambda. - QualType FieldType; - - public: - bool isIndex() const { return (Data & 1) != 0; } - bool isConstant() const { return !isIndex(); } - - unsigned getIndex() const { - assert(isIndex()); - return Data >> 1; - } - CharUnits getOffset() const { - assert(isIndex()); - return CharUnits::fromQuantity(Offset); - } - EHScopeStack::stable_iterator getCleanup() const { - assert(isIndex()); - return Cleanup; - } - void setCleanup(EHScopeStack::stable_iterator cleanup) { - assert(isIndex()); - Cleanup = cleanup; - } - - llvm::Value *getConstant() const { - assert(isConstant()); - return reinterpret_cast<llvm::Value*>(Data); - } - - QualType fieldType() const { - return FieldType; - } - - static Capture makeIndex(unsigned index, CharUnits offset, - QualType FieldType) { - Capture v; - v.Data = (index << 1) | 1; - v.Offset = offset.getQuantity(); - v.FieldType = FieldType; - return v; - } - - static Capture makeConstant(llvm::Value *value) { - Capture v; - v.Data = reinterpret_cast<uintptr_t>(value); - return v; - } - }; - - /// CanBeGlobal - True if the block can be global, i.e. it has - /// no non-constant captures. - bool CanBeGlobal : 1; - - /// True if the block has captures that would necessitate custom copy or - /// dispose helper functions if the block were escaping. - bool NeedsCopyDispose : 1; - - /// HasCXXObject - True if the block's custom copy/dispose functions - /// need to be run even in GC mode. - bool HasCXXObject : 1; - - /// UsesStret : True if the block uses an stret return. Mutable - /// because it gets set later in the block-creation process. - mutable bool UsesStret : 1; - - /// HasCapturedVariableLayout : True if block has captured variables - /// and their layout meta-data has been generated. - bool HasCapturedVariableLayout : 1; - - /// Indicates whether an object of a non-external C++ class is captured. This - /// bit is used to determine the linkage of the block copy/destroy helper - /// functions. - bool CapturesNonExternalType : 1; - - /// The mapping of allocated indexes within the block. - llvm::DenseMap<const VarDecl*, Capture> Captures; - - Address LocalAddress; - llvm::StructType *StructureType; - const BlockDecl *Block; - const BlockExpr *BlockExpression; - CharUnits BlockSize; - CharUnits BlockAlign; - CharUnits CXXThisOffset; - - // Offset of the gap caused by block header having a smaller - // alignment than the alignment of the block descriptor. This - // is the gap offset before the first capturued field. - CharUnits BlockHeaderForcedGapOffset; - // Gap size caused by aligning first field after block header. - // This could be zero if no forced alignment is required. - CharUnits BlockHeaderForcedGapSize; - - /// An instruction which dominates the full-expression that the - /// block is inside. - llvm::Instruction *DominatingIP; - - /// The next block in the block-info chain. Invalid if this block - /// info is not part of the CGF's block-info chain, which is true - /// if it corresponds to a global block or a block whose expression - /// has been encountered. - CGBlockInfo *NextBlockInfo; - - const Capture &getCapture(const VarDecl *var) const { - return const_cast<CGBlockInfo*>(this)->getCapture(var); - } - Capture &getCapture(const VarDecl *var) { - llvm::DenseMap<const VarDecl*, Capture>::iterator - it = Captures.find(var); - assert(it != Captures.end() && "no entry for variable!"); - return it->second; - } - - const BlockDecl *getBlockDecl() const { return Block; } - const BlockExpr *getBlockExpr() const { - assert(BlockExpression); - assert(BlockExpression->getBlockDecl() == Block); - return BlockExpression; - } - - CGBlockInfo(const BlockDecl *blockDecl, StringRef Name); - - // Indicates whether the block needs a custom copy or dispose function. - bool needsCopyDisposeHelpers() const { - return NeedsCopyDispose && !Block->doesNotEscape(); - } -}; - -} // end namespace CodeGen -} // end namespace clang - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGBuilder.h b/gnu/llvm/tools/clang/lib/CodeGen/CGBuilder.h deleted file mode 100644 index 654ef72060b..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGBuilder.h +++ /dev/null @@ -1,306 +0,0 @@ -//===-- CGBuilder.h - Choose IRBuilder implementation ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H -#define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H - -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/IRBuilder.h" -#include "Address.h" -#include "CodeGenTypeCache.h" - -namespace clang { -namespace CodeGen { - -class CodeGenFunction; - -/// This is an IRBuilder insertion helper that forwards to -/// CodeGenFunction::InsertHelper, which adds necessary metadata to -/// instructions. -class CGBuilderInserter : protected llvm::IRBuilderDefaultInserter { -public: - CGBuilderInserter() = default; - explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {} - -protected: - /// This forwards to CodeGenFunction::InsertHelper. - void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name, - llvm::BasicBlock *BB, - llvm::BasicBlock::iterator InsertPt) const; -private: - CodeGenFunction *CGF = nullptr; -}; - -typedef CGBuilderInserter CGBuilderInserterTy; - -typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy> - CGBuilderBaseTy; - -class CGBuilderTy : public CGBuilderBaseTy { - /// Storing a reference to the type cache here makes it a lot easier - /// to build natural-feeling, target-specific IR. - const CodeGenTypeCache &TypeCache; -public: - CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C) - : CGBuilderBaseTy(C), TypeCache(TypeCache) {} - CGBuilderTy(const CodeGenTypeCache &TypeCache, - llvm::LLVMContext &C, const llvm::ConstantFolder &F, - const CGBuilderInserterTy &Inserter) - : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {} - CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I) - : CGBuilderBaseTy(I), TypeCache(TypeCache) {} - CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB) - : CGBuilderBaseTy(BB), TypeCache(TypeCache) {} - - llvm::ConstantInt *getSize(CharUnits N) { - return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity()); - } - llvm::ConstantInt *getSize(uint64_t N) { - return llvm::ConstantInt::get(TypeCache.SizeTy, N); - } - - // Note that we intentionally hide the CreateLoad APIs that don't - // take an alignment. - llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") { - return CreateAlignedLoad(Addr.getPointer(), - Addr.getAlignment().getQuantity(), - Name); - } - llvm::LoadInst *CreateLoad(Address Addr, const char *Name) { - // This overload is required to prevent string literals from - // ending up in the IsVolatile overload. - return CreateAlignedLoad(Addr.getPointer(), - Addr.getAlignment().getQuantity(), - Name); - } - llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile, - const llvm::Twine &Name = "") { - return CreateAlignedLoad(Addr.getPointer(), - Addr.getAlignment().getQuantity(), - IsVolatile, - Name); - } - - using CGBuilderBaseTy::CreateAlignedLoad; - llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align, - const llvm::Twine &Name = "") { - return CreateAlignedLoad(Addr, Align.getQuantity(), Name); - } - llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align, - const char *Name) { - return CreateAlignedLoad(Addr, Align.getQuantity(), Name); - } - llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, - CharUnits Align, - const llvm::Twine &Name = "") { - assert(Addr->getType()->getPointerElementType() == Ty); - return CreateAlignedLoad(Addr, Align.getQuantity(), Name); - } - - // Note that we intentionally hide the CreateStore APIs that don't - // take an alignment. - llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr, - bool IsVolatile = false) { - return CreateAlignedStore(Val, Addr.getPointer(), - Addr.getAlignment().getQuantity(), IsVolatile); - } - - using CGBuilderBaseTy::CreateAlignedStore; - llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr, - CharUnits Align, bool IsVolatile = false) { - return CreateAlignedStore(Val, Addr, Align.getQuantity(), IsVolatile); - } - - // FIXME: these "default-aligned" APIs should be removed, - // but I don't feel like fixing all the builtin code right now. - llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val, - llvm::Value *Addr, - bool IsVolatile = false) { - return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile); - } - - /// Emit a load from an i1 flag variable. - llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr, - const llvm::Twine &Name = "") { - assert(Addr->getType()->getPointerElementType() == getInt1Ty()); - return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name); - } - - /// Emit a store to an i1 flag variable. - llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) { - assert(Addr->getType()->getPointerElementType() == getInt1Ty()); - return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One()); - } - - using CGBuilderBaseTy::CreateBitCast; - Address CreateBitCast(Address Addr, llvm::Type *Ty, - const llvm::Twine &Name = "") { - return Address(CreateBitCast(Addr.getPointer(), Ty, Name), - Addr.getAlignment()); - } - - using CGBuilderBaseTy::CreateAddrSpaceCast; - Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, - const llvm::Twine &Name = "") { - return Address(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name), - Addr.getAlignment()); - } - - /// Cast the element type of the given address to a different type, - /// preserving information like the alignment and address space. - Address CreateElementBitCast(Address Addr, llvm::Type *Ty, - const llvm::Twine &Name = "") { - auto PtrTy = Ty->getPointerTo(Addr.getAddressSpace()); - return CreateBitCast(Addr, PtrTy, Name); - } - - using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast; - Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, - const llvm::Twine &Name = "") { - llvm::Value *Ptr = - CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name); - return Address(Ptr, Addr.getAlignment()); - } - - using CGBuilderBaseTy::CreateStructGEP; - Address CreateStructGEP(Address Addr, unsigned Index, CharUnits Offset, - const llvm::Twine &Name = "") { - return Address(CreateStructGEP(Addr.getElementType(), - Addr.getPointer(), Index, Name), - Addr.getAlignment().alignmentAtOffset(Offset)); - } - Address CreateStructGEP(Address Addr, unsigned Index, - const llvm::StructLayout *Layout, - const llvm::Twine &Name = "") { - auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); - return CreateStructGEP(Addr, Index, Offset, Name); - } - - /// Given - /// %addr = [n x T]* ... - /// produce - /// %name = getelementptr inbounds %addr, i64 0, i64 index - /// where i64 is actually the target word size. - /// - /// This API assumes that drilling into an array like this is always - /// an inbounds operation. - /// - /// \param EltSize - the size of the type T in bytes - Address CreateConstArrayGEP(Address Addr, uint64_t Index, CharUnits EltSize, - const llvm::Twine &Name = "") { - return Address(CreateInBoundsGEP(Addr.getPointer(), - {getSize(CharUnits::Zero()), - getSize(Index)}, - Name), - Addr.getAlignment().alignmentAtOffset(Index * EltSize)); - } - - /// Given - /// %addr = T* ... - /// produce - /// %name = getelementptr inbounds %addr, i64 index - /// where i64 is actually the target word size. - /// - /// \param EltSize - the size of the type T in bytes - Address CreateConstInBoundsGEP(Address Addr, uint64_t Index, - CharUnits EltSize, - const llvm::Twine &Name = "") { - return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), - getSize(Index), Name), - Addr.getAlignment().alignmentAtOffset(Index * EltSize)); - } - - /// Given - /// %addr = T* ... - /// produce - /// %name = getelementptr inbounds %addr, i64 index - /// where i64 is actually the target word size. - /// - /// \param EltSize - the size of the type T in bytes - Address CreateConstGEP(Address Addr, uint64_t Index, CharUnits EltSize, - const llvm::Twine &Name = "") { - return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), - getSize(Index), Name), - Addr.getAlignment().alignmentAtOffset(Index * EltSize)); - } - - /// Given a pointer to i8, adjust it by a given constant offset. - Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, - const llvm::Twine &Name = "") { - assert(Addr.getElementType() == TypeCache.Int8Ty); - return Address(CreateInBoundsGEP(Addr.getPointer(), getSize(Offset), Name), - Addr.getAlignment().alignmentAtOffset(Offset)); - } - Address CreateConstByteGEP(Address Addr, CharUnits Offset, - const llvm::Twine &Name = "") { - assert(Addr.getElementType() == TypeCache.Int8Ty); - return Address(CreateGEP(Addr.getPointer(), getSize(Offset), Name), - Addr.getAlignment().alignmentAtOffset(Offset)); - } - - using CGBuilderBaseTy::CreateConstInBoundsGEP2_32; - Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, - unsigned Idx1, const llvm::DataLayout &DL, - const llvm::Twine &Name = "") { - auto *GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32( - Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name)); - llvm::APInt Offset( - DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0, - /*IsSigned=*/true); - if (!GEP->accumulateConstantOffset(DL, Offset)) - llvm_unreachable("offset of GEP with constants is always computable"); - return Address(GEP, Addr.getAlignment().alignmentAtOffset( - CharUnits::fromQuantity(Offset.getSExtValue()))); - } - - llvm::Value *CreateConstInBoundsByteGEP(llvm::Value *Ptr, CharUnits Offset, - const llvm::Twine &Name = "") { - assert(Ptr->getType()->getPointerElementType() == TypeCache.Int8Ty); - return CreateInBoundsGEP(Ptr, getSize(Offset), Name); - } - llvm::Value *CreateConstByteGEP(llvm::Value *Ptr, CharUnits Offset, - const llvm::Twine &Name = "") { - assert(Ptr->getType()->getPointerElementType() == TypeCache.Int8Ty); - return CreateGEP(Ptr, getSize(Offset), Name); - } - - using CGBuilderBaseTy::CreateMemCpy; - llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, - bool IsVolatile = false) { - return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getQuantity(), - Src.getPointer(), Src.getAlignment().getQuantity(), - Size,IsVolatile); - } - llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size, - bool IsVolatile = false) { - return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getQuantity(), - Src.getPointer(), Src.getAlignment().getQuantity(), - Size, IsVolatile); - } - - using CGBuilderBaseTy::CreateMemMove; - llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size, - bool IsVolatile = false) { - return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getQuantity(), - Src.getPointer(), Src.getAlignment().getQuantity(), - Size, IsVolatile); - } - - using CGBuilderBaseTy::CreateMemSet; - llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value, - llvm::Value *Size, bool IsVolatile = false) { - return CreateMemSet(Dest.getPointer(), Value, Size, - Dest.getAlignment().getQuantity(), IsVolatile); - } -}; - -} // end namespace CodeGen -} // end namespace clang - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp deleted file mode 100644 index ccc657493b2..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp +++ /dev/null @@ -1,13508 +0,0 @@ -//===---- CGBuiltin.cpp - Emit LLVM Code for builtins ---------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code to emit Builtin calls as LLVM code. -// -//===----------------------------------------------------------------------===// - -#include "CGCXXABI.h" -#include "CGObjCRuntime.h" -#include "CGOpenCLRuntime.h" -#include "CGRecordLayout.h" -#include "CodeGenFunction.h" -#include "CodeGenModule.h" -#include "ConstantEmitter.h" -#include "TargetInfo.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" -#include "clang/AST/OSLog.h" -#include "clang/Basic/TargetBuiltins.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/CodeGen/CGFunctionInfo.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/MDBuilder.h" -#include "llvm/Support/ConvertUTF.h" -#include "llvm/Support/ScopedPrinter.h" -#include "llvm/Support/TargetParser.h" -#include <sstream> - -using namespace clang; -using namespace CodeGen; -using namespace llvm; - -static -int64_t clamp(int64_t Value, int64_t Low, int64_t High) { - return std::min(High, std::max(Low, Value)); -} - -/// getBuiltinLibFunction - Given a builtin id for a function like -/// "__builtin_fabsf", return a Function* for "fabsf". -llvm::Constant *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD, - unsigned BuiltinID) { - assert(Context.BuiltinInfo.isLibFunction(BuiltinID)); - - // Get the name, skip over the __builtin_ prefix (if necessary). - StringRef Name; - GlobalDecl D(FD); - - // If the builtin has been declared explicitly with an assembler label, - // use the mangled name. This differs from the plain label on platforms - // that prefix labels. - if (FD->hasAttr<AsmLabelAttr>()) - Name = getMangledName(D); - else - Name = Context.BuiltinInfo.getName(BuiltinID) + 10; - - llvm::FunctionType *Ty = - cast<llvm::FunctionType>(getTypes().ConvertType(FD->getType())); - - return GetOrCreateLLVMFunction(Name, Ty, D, /*ForVTable=*/false); -} - -/// Emit the conversions required to turn the given value into an -/// integer of the given size. -static Value *EmitToInt(CodeGenFunction &CGF, llvm::Value *V, - QualType T, llvm::IntegerType *IntType) { - V = CGF.EmitToMemory(V, T); - - if (V->getType()->isPointerTy()) - return CGF.Builder.CreatePtrToInt(V, IntType); - - assert(V->getType() == IntType); - return V; -} - -static Value *EmitFromInt(CodeGenFunction &CGF, llvm::Value *V, - QualType T, llvm::Type *ResultType) { - V = CGF.EmitFromMemory(V, T); - - if (ResultType->isPointerTy()) - return CGF.Builder.CreateIntToPtr(V, ResultType); - - assert(V->getType() == ResultType); - return V; -} - -/// Utility to insert an atomic instruction based on Intrinsic::ID -/// and the expression node. -static Value *MakeBinaryAtomicValue( - CodeGenFunction &CGF, llvm::AtomicRMWInst::BinOp Kind, const CallExpr *E, - AtomicOrdering Ordering = AtomicOrdering::SequentiallyConsistent) { - QualType T = E->getType(); - assert(E->getArg(0)->getType()->isPointerType()); - assert(CGF.getContext().hasSameUnqualifiedType(T, - E->getArg(0)->getType()->getPointeeType())); - assert(CGF.getContext().hasSameUnqualifiedType(T, E->getArg(1)->getType())); - - llvm::Value *DestPtr = CGF.EmitScalarExpr(E->getArg(0)); - unsigned AddrSpace = DestPtr->getType()->getPointerAddressSpace(); - - llvm::IntegerType *IntType = - llvm::IntegerType::get(CGF.getLLVMContext(), - CGF.getContext().getTypeSize(T)); - llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace); - - llvm::Value *Args[2]; - Args[0] = CGF.Builder.CreateBitCast(DestPtr, IntPtrType); - Args[1] = CGF.EmitScalarExpr(E->getArg(1)); - llvm::Type *ValueType = Args[1]->getType(); - Args[1] = EmitToInt(CGF, Args[1], T, IntType); - - llvm::Value *Result = CGF.Builder.CreateAtomicRMW( - Kind, Args[0], Args[1], Ordering); - return EmitFromInt(CGF, Result, T, ValueType); -} - -static Value *EmitNontemporalStore(CodeGenFunction &CGF, const CallExpr *E) { - Value *Val = CGF.EmitScalarExpr(E->getArg(0)); - Value *Address = CGF.EmitScalarExpr(E->getArg(1)); - - // Convert the type of the pointer to a pointer to the stored type. - Val = CGF.EmitToMemory(Val, E->getArg(0)->getType()); - Value *BC = CGF.Builder.CreateBitCast( - Address, llvm::PointerType::getUnqual(Val->getType()), "cast"); - LValue LV = CGF.MakeNaturalAlignAddrLValue(BC, E->getArg(0)->getType()); - LV.setNontemporal(true); - CGF.EmitStoreOfScalar(Val, LV, false); - return nullptr; -} - -static Value *EmitNontemporalLoad(CodeGenFunction &CGF, const CallExpr *E) { - Value *Address = CGF.EmitScalarExpr(E->getArg(0)); - - LValue LV = CGF.MakeNaturalAlignAddrLValue(Address, E->getType()); - LV.setNontemporal(true); - return CGF.EmitLoadOfScalar(LV, E->getExprLoc()); -} - -static RValue EmitBinaryAtomic(CodeGenFunction &CGF, - llvm::AtomicRMWInst::BinOp Kind, - const CallExpr *E) { - return RValue::get(MakeBinaryAtomicValue(CGF, Kind, E)); -} - -/// Utility to insert an atomic instruction based Intrinsic::ID and -/// the expression node, where the return value is the result of the -/// operation. -static RValue EmitBinaryAtomicPost(CodeGenFunction &CGF, - llvm::AtomicRMWInst::BinOp Kind, - const CallExpr *E, - Instruction::BinaryOps Op, - bool Invert = false) { - QualType T = E->getType(); - assert(E->getArg(0)->getType()->isPointerType()); - assert(CGF.getContext().hasSameUnqualifiedType(T, - E->getArg(0)->getType()->getPointeeType())); - assert(CGF.getContext().hasSameUnqualifiedType(T, E->getArg(1)->getType())); - - llvm::Value *DestPtr = CGF.EmitScalarExpr(E->getArg(0)); - unsigned AddrSpace = DestPtr->getType()->getPointerAddressSpace(); - - llvm::IntegerType *IntType = - llvm::IntegerType::get(CGF.getLLVMContext(), - CGF.getContext().getTypeSize(T)); - llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace); - - llvm::Value *Args[2]; - Args[1] = CGF.EmitScalarExpr(E->getArg(1)); - llvm::Type *ValueType = Args[1]->getType(); - Args[1] = EmitToInt(CGF, Args[1], T, IntType); - Args[0] = CGF.Builder.CreateBitCast(DestPtr, IntPtrType); - - llvm::Value *Result = CGF.Builder.CreateAtomicRMW( - Kind, Args[0], Args[1], llvm::AtomicOrdering::SequentiallyConsistent); - Result = CGF.Builder.CreateBinOp(Op, Result, Args[1]); - if (Invert) - Result = CGF.Builder.CreateBinOp(llvm::Instruction::Xor, Result, - llvm::ConstantInt::get(IntType, -1)); - Result = EmitFromInt(CGF, Result, T, ValueType); - return RValue::get(Result); -} - -/// Utility to insert an atomic cmpxchg instruction. -/// -/// @param CGF The current codegen function. -/// @param E Builtin call expression to convert to cmpxchg. -/// arg0 - address to operate on -/// arg1 - value to compare with -/// arg2 - new value -/// @param ReturnBool Specifies whether to return success flag of -/// cmpxchg result or the old value. -/// -/// @returns result of cmpxchg, according to ReturnBool -/// -/// Note: In order to lower Microsoft's _InterlockedCompareExchange* intrinsics -/// invoke the function EmitAtomicCmpXchgForMSIntrin. -static Value *MakeAtomicCmpXchgValue(CodeGenFunction &CGF, const CallExpr *E, - bool ReturnBool) { - QualType T = ReturnBool ? E->getArg(1)->getType() : E->getType(); - llvm::Value *DestPtr = CGF.EmitScalarExpr(E->getArg(0)); - unsigned AddrSpace = DestPtr->getType()->getPointerAddressSpace(); - - llvm::IntegerType *IntType = llvm::IntegerType::get( - CGF.getLLVMContext(), CGF.getContext().getTypeSize(T)); - llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace); - - Value *Args[3]; - Args[0] = CGF.Builder.CreateBitCast(DestPtr, IntPtrType); - Args[1] = CGF.EmitScalarExpr(E->getArg(1)); - llvm::Type *ValueType = Args[1]->getType(); - Args[1] = EmitToInt(CGF, Args[1], T, IntType); - Args[2] = EmitToInt(CGF, CGF.EmitScalarExpr(E->getArg(2)), T, IntType); - - Value *Pair = CGF.Builder.CreateAtomicCmpXchg( - Args[0], Args[1], Args[2], llvm::AtomicOrdering::SequentiallyConsistent, - llvm::AtomicOrdering::SequentiallyConsistent); - if (ReturnBool) - // Extract boolean success flag and zext it to int. - return CGF.Builder.CreateZExt(CGF.Builder.CreateExtractValue(Pair, 1), - CGF.ConvertType(E->getType())); - else - // Extract old value and emit it using the same type as compare value. - return EmitFromInt(CGF, CGF.Builder.CreateExtractValue(Pair, 0), T, - ValueType); -} - -/// This function should be invoked to emit atomic cmpxchg for Microsoft's -/// _InterlockedCompareExchange* intrinsics which have the following signature: -/// T _InterlockedCompareExchange(T volatile *Destination, -/// T Exchange, -/// T Comparand); -/// -/// Whereas the llvm 'cmpxchg' instruction has the following syntax: -/// cmpxchg *Destination, Comparand, Exchange. -/// So we need to swap Comparand and Exchange when invoking -/// CreateAtomicCmpXchg. That is the reason we could not use the above utility -/// function MakeAtomicCmpXchgValue since it expects the arguments to be -/// already swapped. - -static -Value *EmitAtomicCmpXchgForMSIntrin(CodeGenFunction &CGF, const CallExpr *E, - AtomicOrdering SuccessOrdering = AtomicOrdering::SequentiallyConsistent) { - assert(E->getArg(0)->getType()->isPointerType()); - assert(CGF.getContext().hasSameUnqualifiedType( - E->getType(), E->getArg(0)->getType()->getPointeeType())); - assert(CGF.getContext().hasSameUnqualifiedType(E->getType(), - E->getArg(1)->getType())); - assert(CGF.getContext().hasSameUnqualifiedType(E->getType(), - E->getArg(2)->getType())); - - auto *Destination = CGF.EmitScalarExpr(E->getArg(0)); - auto *Comparand = CGF.EmitScalarExpr(E->getArg(2)); - auto *Exchange = CGF.EmitScalarExpr(E->getArg(1)); - - // For Release ordering, the failure ordering should be Monotonic. - auto FailureOrdering = SuccessOrdering == AtomicOrdering::Release ? - AtomicOrdering::Monotonic : - SuccessOrdering; - - auto *Result = CGF.Builder.CreateAtomicCmpXchg( - Destination, Comparand, Exchange, - SuccessOrdering, FailureOrdering); - Result->setVolatile(true); - return CGF.Builder.CreateExtractValue(Result, 0); -} - -static Value *EmitAtomicIncrementValue(CodeGenFunction &CGF, const CallExpr *E, - AtomicOrdering Ordering = AtomicOrdering::SequentiallyConsistent) { - assert(E->getArg(0)->getType()->isPointerType()); - - auto *IntTy = CGF.ConvertType(E->getType()); - auto *Result = CGF.Builder.CreateAtomicRMW( - AtomicRMWInst::Add, - CGF.EmitScalarExpr(E->getArg(0)), - ConstantInt::get(IntTy, 1), - Ordering); - return CGF.Builder.CreateAdd(Result, ConstantInt::get(IntTy, 1)); -} - -static Value *EmitAtomicDecrementValue(CodeGenFunction &CGF, const CallExpr *E, - AtomicOrdering Ordering = AtomicOrdering::SequentiallyConsistent) { - assert(E->getArg(0)->getType()->isPointerType()); - - auto *IntTy = CGF.ConvertType(E->getType()); - auto *Result = CGF.Builder.CreateAtomicRMW( - AtomicRMWInst::Sub, - CGF.EmitScalarExpr(E->getArg(0)), - ConstantInt::get(IntTy, 1), - Ordering); - return CGF.Builder.CreateSub(Result, ConstantInt::get(IntTy, 1)); -} - -// Emit a simple mangled intrinsic that has 1 argument and a return type -// matching the argument type. -static Value *emitUnaryBuiltin(CodeGenFunction &CGF, - const CallExpr *E, - unsigned IntrinsicID) { - llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0)); - - Value *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType()); - return CGF.Builder.CreateCall(F, Src0); -} - -// Emit an intrinsic that has 2 operands of the same type as its result. -static Value *emitBinaryBuiltin(CodeGenFunction &CGF, - const CallExpr *E, - unsigned IntrinsicID) { - llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0)); - llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1)); - - Value *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType()); - return CGF.Builder.CreateCall(F, { Src0, Src1 }); -} - -// Emit an intrinsic that has 3 operands of the same type as its result. -static Value *emitTernaryBuiltin(CodeGenFunction &CGF, - const CallExpr *E, - unsigned IntrinsicID) { - llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0)); - llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1)); - llvm::Value *Src2 = CGF.EmitScalarExpr(E->getArg(2)); - - Value *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType()); - return CGF.Builder.CreateCall(F, { Src0, Src1, Src2 }); -} - -// Emit an intrinsic that has 1 float or double operand, and 1 integer. -static Value *emitFPIntBuiltin(CodeGenFunction &CGF, - const CallExpr *E, - unsigned IntrinsicID) { - llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0)); - llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1)); - - Value *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType()); - return CGF.Builder.CreateCall(F, {Src0, Src1}); -} - -/// EmitFAbs - Emit a call to @llvm.fabs(). -static Value *EmitFAbs(CodeGenFunction &CGF, Value *V) { - Value *F = CGF.CGM.getIntrinsic(Intrinsic::fabs, V->getType()); - llvm::CallInst *Call = CGF.Builder.CreateCall(F, V); - Call->setDoesNotAccessMemory(); - return Call; -} - -/// Emit the computation of the sign bit for a floating point value. Returns -/// the i1 sign bit value. -static Value *EmitSignBit(CodeGenFunction &CGF, Value *V) { - LLVMContext &C = CGF.CGM.getLLVMContext(); - - llvm::Type *Ty = V->getType(); - int Width = Ty->getPrimitiveSizeInBits(); - llvm::Type *IntTy = llvm::IntegerType::get(C, Width); - V = CGF.Builder.CreateBitCast(V, IntTy); - if (Ty->isPPC_FP128Ty()) { - // We want the sign bit of the higher-order double. The bitcast we just - // did works as if the double-double was stored to memory and then - // read as an i128. The "store" will put the higher-order double in the - // lower address in both little- and big-Endian modes, but the "load" - // will treat those bits as a different part of the i128: the low bits in - // little-Endian, the high bits in big-Endian. Therefore, on big-Endian - // we need to shift the high bits down to the low before truncating. - Width >>= 1; - if (CGF.getTarget().isBigEndian()) { - Value *ShiftCst = llvm::ConstantInt::get(IntTy, Width); - V = CGF.Builder.CreateLShr(V, ShiftCst); - } - // We are truncating value in order to extract the higher-order - // double, which we will be using to extract the sign from. - IntTy = llvm::IntegerType::get(C, Width); - V = CGF.Builder.CreateTrunc(V, IntTy); - } - Value *Zero = llvm::Constant::getNullValue(IntTy); - return CGF.Builder.CreateICmpSLT(V, Zero); -} - -static RValue emitLibraryCall(CodeGenFunction &CGF, const FunctionDecl *FD, - const CallExpr *E, llvm::Constant *calleeValue) { - CGCallee callee = CGCallee::forDirect(calleeValue, GlobalDecl(FD)); - return CGF.EmitCall(E->getCallee()->getType(), callee, E, ReturnValueSlot()); -} - -/// Emit a call to llvm.{sadd,uadd,ssub,usub,smul,umul}.with.overflow.* -/// depending on IntrinsicID. -/// -/// \arg CGF The current codegen function. -/// \arg IntrinsicID The ID for the Intrinsic we wish to generate. -/// \arg X The first argument to the llvm.*.with.overflow.*. -/// \arg Y The second argument to the llvm.*.with.overflow.*. -/// \arg Carry The carry returned by the llvm.*.with.overflow.*. -/// \returns The result (i.e. sum/product) returned by the intrinsic. -static llvm::Value *EmitOverflowIntrinsic(CodeGenFunction &CGF, - const llvm::Intrinsic::ID IntrinsicID, - llvm::Value *X, llvm::Value *Y, - llvm::Value *&Carry) { - // Make sure we have integers of the same width. - assert(X->getType() == Y->getType() && - "Arguments must be the same type. (Did you forget to make sure both " - "arguments have the same integer width?)"); - - llvm::Value *Callee = CGF.CGM.getIntrinsic(IntrinsicID, X->getType()); - llvm::Value *Tmp = CGF.Builder.CreateCall(Callee, {X, Y}); - Carry = CGF.Builder.CreateExtractValue(Tmp, 1); - return CGF.Builder.CreateExtractValue(Tmp, 0); -} - -static Value *emitRangedBuiltin(CodeGenFunction &CGF, - unsigned IntrinsicID, - int low, int high) { - llvm::MDBuilder MDHelper(CGF.getLLVMContext()); - llvm::MDNode *RNode = MDHelper.createRange(APInt(32, low), APInt(32, high)); - Value *F = CGF.CGM.getIntrinsic(IntrinsicID, {}); - llvm::Instruction *Call = CGF.Builder.CreateCall(F); - Call->setMetadata(llvm::LLVMContext::MD_range, RNode); - return Call; -} - -namespace { - struct WidthAndSignedness { - unsigned Width; - bool Signed; - }; -} - -static WidthAndSignedness -getIntegerWidthAndSignedness(const clang::ASTContext &context, - const clang::QualType Type) { - assert(Type->isIntegerType() && "Given type is not an integer."); - unsigned Width = Type->isBooleanType() ? 1 : context.getTypeInfo(Type).Width; - bool Signed = Type->isSignedIntegerType(); - return {Width, Signed}; -} - -// Given one or more integer types, this function produces an integer type that -// encompasses them: any value in one of the given types could be expressed in -// the encompassing type. -static struct WidthAndSignedness -EncompassingIntegerType(ArrayRef<struct WidthAndSignedness> Types) { - assert(Types.size() > 0 && "Empty list of types."); - - // If any of the given types is signed, we must return a signed type. - bool Signed = false; - for (const auto &Type : Types) { - Signed |= Type.Signed; - } - - // The encompassing type must have a width greater than or equal to the width - // of the specified types. Additionally, if the encompassing type is signed, - // its width must be strictly greater than the width of any unsigned types - // given. - unsigned Width = 0; - for (const auto &Type : Types) { - unsigned MinWidth = Type.Width + (Signed && !Type.Signed); - if (Width < MinWidth) { - Width = MinWidth; - } - } - - return {Width, Signed}; -} - -Value *CodeGenFunction::EmitVAStartEnd(Value *ArgValue, bool IsStart) { - llvm::Type *DestType = Int8PtrTy; - if (ArgValue->getType() != DestType) - ArgValue = - Builder.CreateBitCast(ArgValue, DestType, ArgValue->getName().data()); - - Intrinsic::ID inst = IsStart ? Intrinsic::vastart : Intrinsic::vaend; - return Builder.CreateCall(CGM.getIntrinsic(inst), ArgValue); -} - -/// Checks if using the result of __builtin_object_size(p, @p From) in place of -/// __builtin_object_size(p, @p To) is correct -static bool areBOSTypesCompatible(int From, int To) { - // Note: Our __builtin_object_size implementation currently treats Type=0 and - // Type=2 identically. Encoding this implementation detail here may make - // improving __builtin_object_size difficult in the future, so it's omitted. - return From == To || (From == 0 && To == 1) || (From == 3 && To == 2); -} - -static llvm::Value * -getDefaultBuiltinObjectSizeResult(unsigned Type, llvm::IntegerType *ResType) { - return ConstantInt::get(ResType, (Type & 2) ? 0 : -1, /*isSigned=*/true); -} - -llvm::Value * -CodeGenFunction::evaluateOrEmitBuiltinObjectSize(const Expr *E, unsigned Type, - llvm::IntegerType *ResType, - llvm::Value *EmittedE) { - uint64_t ObjectSize; - if (!E->tryEvaluateObjectSize(ObjectSize, getContext(), Type)) - return emitBuiltinObjectSize(E, Type, ResType, EmittedE); - return ConstantInt::get(ResType, ObjectSize, /*isSigned=*/true); -} - -/// Returns a Value corresponding to the size of the given expression. -/// This Value may be either of the following: -/// - A llvm::Argument (if E is a param with the pass_object_size attribute on -/// it) -/// - A call to the @llvm.objectsize intrinsic -/// -/// EmittedE is the result of emitting `E` as a scalar expr. If it's non-null -/// and we wouldn't otherwise try to reference a pass_object_size parameter, -/// we'll call @llvm.objectsize on EmittedE, rather than emitting E. -llvm::Value * -CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type, - llvm::IntegerType *ResType, - llvm::Value *EmittedE) { - // We need to reference an argument if the pointer is a parameter with the - // pass_object_size attribute. - if (auto *D = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) { - auto *Param = dyn_cast<ParmVarDecl>(D->getDecl()); - auto *PS = D->getDecl()->getAttr<PassObjectSizeAttr>(); - if (Param != nullptr && PS != nullptr && - areBOSTypesCompatible(PS->getType(), Type)) { - auto Iter = SizeArguments.find(Param); - assert(Iter != SizeArguments.end()); - - const ImplicitParamDecl *D = Iter->second; - auto DIter = LocalDeclMap.find(D); - assert(DIter != LocalDeclMap.end()); - - return EmitLoadOfScalar(DIter->second, /*volatile=*/false, - getContext().getSizeType(), E->getBeginLoc()); - } - } - - // LLVM can't handle Type=3 appropriately, and __builtin_object_size shouldn't - // evaluate E for side-effects. In either case, we shouldn't lower to - // @llvm.objectsize. - if (Type == 3 || (!EmittedE && E->HasSideEffects(getContext()))) - return getDefaultBuiltinObjectSizeResult(Type, ResType); - - Value *Ptr = EmittedE ? EmittedE : EmitScalarExpr(E); - assert(Ptr->getType()->isPointerTy() && - "Non-pointer passed to __builtin_object_size?"); - - Value *F = CGM.getIntrinsic(Intrinsic::objectsize, {ResType, Ptr->getType()}); - - // LLVM only supports 0 and 2, make sure that we pass along that as a boolean. - Value *Min = Builder.getInt1((Type & 2) != 0); - // For GCC compatibility, __builtin_object_size treat NULL as unknown size. - Value *NullIsUnknown = Builder.getTrue(); - return Builder.CreateCall(F, {Ptr, Min, NullIsUnknown}); -} - -namespace { -/// A struct to generically describe a bit test intrinsic. -struct BitTest { - enum ActionKind : uint8_t { TestOnly, Complement, Reset, Set }; - enum InterlockingKind : uint8_t { - Unlocked, - Sequential, - Acquire, - Release, - NoFence - }; - - ActionKind Action; - InterlockingKind Interlocking; - bool Is64Bit; - - static BitTest decodeBitTestBuiltin(unsigned BuiltinID); -}; -} // namespace - -BitTest BitTest::decodeBitTestBuiltin(unsigned BuiltinID) { - switch (BuiltinID) { - // Main portable variants. - case Builtin::BI_bittest: - return {TestOnly, Unlocked, false}; - case Builtin::BI_bittestandcomplement: - return {Complement, Unlocked, false}; - case Builtin::BI_bittestandreset: - return {Reset, Unlocked, false}; - case Builtin::BI_bittestandset: - return {Set, Unlocked, false}; - case Builtin::BI_interlockedbittestandreset: - return {Reset, Sequential, false}; - case Builtin::BI_interlockedbittestandset: - return {Set, Sequential, false}; - - // X86-specific 64-bit variants. - case Builtin::BI_bittest64: - return {TestOnly, Unlocked, true}; - case Builtin::BI_bittestandcomplement64: - return {Complement, Unlocked, true}; - case Builtin::BI_bittestandreset64: - return {Reset, Unlocked, true}; - case Builtin::BI_bittestandset64: - return {Set, Unlocked, true}; - case Builtin::BI_interlockedbittestandreset64: - return {Reset, Sequential, true}; - case Builtin::BI_interlockedbittestandset64: - return {Set, Sequential, true}; - - // ARM/AArch64-specific ordering variants. - case Builtin::BI_interlockedbittestandset_acq: - return {Set, Acquire, false}; - case Builtin::BI_interlockedbittestandset_rel: - return {Set, Release, false}; - case Builtin::BI_interlockedbittestandset_nf: - return {Set, NoFence, false}; - case Builtin::BI_interlockedbittestandreset_acq: - return {Reset, Acquire, false}; - case Builtin::BI_interlockedbittestandreset_rel: - return {Reset, Release, false}; - case Builtin::BI_interlockedbittestandreset_nf: - return {Reset, NoFence, false}; - } - llvm_unreachable("expected only bittest intrinsics"); -} - -static char bitActionToX86BTCode(BitTest::ActionKind A) { - switch (A) { - case BitTest::TestOnly: return '\0'; - case BitTest::Complement: return 'c'; - case BitTest::Reset: return 'r'; - case BitTest::Set: return 's'; - } - llvm_unreachable("invalid action"); -} - -static llvm::Value *EmitX86BitTestIntrinsic(CodeGenFunction &CGF, - BitTest BT, - const CallExpr *E, Value *BitBase, - Value *BitPos) { - char Action = bitActionToX86BTCode(BT.Action); - char SizeSuffix = BT.Is64Bit ? 'q' : 'l'; - - // Build the assembly. - SmallString<64> Asm; - raw_svector_ostream AsmOS(Asm); - if (BT.Interlocking != BitTest::Unlocked) - AsmOS << "lock "; - AsmOS << "bt"; - if (Action) - AsmOS << Action; - AsmOS << SizeSuffix << " $2, ($1)\n\tsetc ${0:b}"; - - // Build the constraints. FIXME: We should support immediates when possible. - std::string Constraints = "=r,r,r,~{cc},~{flags},~{fpsr}"; - llvm::IntegerType *IntType = llvm::IntegerType::get( - CGF.getLLVMContext(), - CGF.getContext().getTypeSize(E->getArg(1)->getType())); - llvm::Type *IntPtrType = IntType->getPointerTo(); - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGF.Int8Ty, {IntPtrType, IntType}, false); - - llvm::InlineAsm *IA = - llvm::InlineAsm::get(FTy, Asm, Constraints, /*SideEffects=*/true); - return CGF.Builder.CreateCall(IA, {BitBase, BitPos}); -} - -static llvm::AtomicOrdering -getBitTestAtomicOrdering(BitTest::InterlockingKind I) { - switch (I) { - case BitTest::Unlocked: return llvm::AtomicOrdering::NotAtomic; - case BitTest::Sequential: return llvm::AtomicOrdering::SequentiallyConsistent; - case BitTest::Acquire: return llvm::AtomicOrdering::Acquire; - case BitTest::Release: return llvm::AtomicOrdering::Release; - case BitTest::NoFence: return llvm::AtomicOrdering::Monotonic; - } - llvm_unreachable("invalid interlocking"); -} - -/// Emit a _bittest* intrinsic. These intrinsics take a pointer to an array of -/// bits and a bit position and read and optionally modify the bit at that -/// position. The position index can be arbitrarily large, i.e. it can be larger -/// than 31 or 63, so we need an indexed load in the general case. -static llvm::Value *EmitBitTestIntrinsic(CodeGenFunction &CGF, - unsigned BuiltinID, - const CallExpr *E) { - Value *BitBase = CGF.EmitScalarExpr(E->getArg(0)); - Value *BitPos = CGF.EmitScalarExpr(E->getArg(1)); - - BitTest BT = BitTest::decodeBitTestBuiltin(BuiltinID); - - // X86 has special BT, BTC, BTR, and BTS instructions that handle the array - // indexing operation internally. Use them if possible. - llvm::Triple::ArchType Arch = CGF.getTarget().getTriple().getArch(); - if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) - return EmitX86BitTestIntrinsic(CGF, BT, E, BitBase, BitPos); - - // Otherwise, use generic code to load one byte and test the bit. Use all but - // the bottom three bits as the array index, and the bottom three bits to form - // a mask. - // Bit = BitBaseI8[BitPos >> 3] & (1 << (BitPos & 0x7)) != 0; - Value *ByteIndex = CGF.Builder.CreateAShr( - BitPos, llvm::ConstantInt::get(BitPos->getType(), 3), "bittest.byteidx"); - Value *BitBaseI8 = CGF.Builder.CreatePointerCast(BitBase, CGF.Int8PtrTy); - Address ByteAddr(CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, BitBaseI8, - ByteIndex, "bittest.byteaddr"), - CharUnits::One()); - Value *PosLow = - CGF.Builder.CreateAnd(CGF.Builder.CreateTrunc(BitPos, CGF.Int8Ty), - llvm::ConstantInt::get(CGF.Int8Ty, 0x7)); - - // The updating instructions will need a mask. - Value *Mask = nullptr; - if (BT.Action != BitTest::TestOnly) { - Mask = CGF.Builder.CreateShl(llvm::ConstantInt::get(CGF.Int8Ty, 1), PosLow, - "bittest.mask"); - } - - // Check the action and ordering of the interlocked intrinsics. - llvm::AtomicOrdering Ordering = getBitTestAtomicOrdering(BT.Interlocking); - - Value *OldByte = nullptr; - if (Ordering != llvm::AtomicOrdering::NotAtomic) { - // Emit a combined atomicrmw load/store operation for the interlocked - // intrinsics. - llvm::AtomicRMWInst::BinOp RMWOp = llvm::AtomicRMWInst::Or; - if (BT.Action == BitTest::Reset) { - Mask = CGF.Builder.CreateNot(Mask); - RMWOp = llvm::AtomicRMWInst::And; - } - OldByte = CGF.Builder.CreateAtomicRMW(RMWOp, ByteAddr.getPointer(), Mask, - Ordering); - } else { - // Emit a plain load for the non-interlocked intrinsics. - OldByte = CGF.Builder.CreateLoad(ByteAddr, "bittest.byte"); - Value *NewByte = nullptr; - switch (BT.Action) { - case BitTest::TestOnly: - // Don't store anything. - break; - case BitTest::Complement: - NewByte = CGF.Builder.CreateXor(OldByte, Mask); - break; - case BitTest::Reset: - NewByte = CGF.Builder.CreateAnd(OldByte, CGF.Builder.CreateNot(Mask)); - break; - case BitTest::Set: - NewByte = CGF.Builder.CreateOr(OldByte, Mask); - break; - } - if (NewByte) - CGF.Builder.CreateStore(NewByte, ByteAddr); - } - - // However we loaded the old byte, either by plain load or atomicrmw, shift - // the bit into the low position and mask it to 0 or 1. - Value *ShiftedByte = CGF.Builder.CreateLShr(OldByte, PosLow, "bittest.shr"); - return CGF.Builder.CreateAnd( - ShiftedByte, llvm::ConstantInt::get(CGF.Int8Ty, 1), "bittest.res"); -} - -namespace { -enum class MSVCSetJmpKind { - _setjmpex, - _setjmp3, - _setjmp -}; -} - -/// MSVC handles setjmp a bit differently on different platforms. On every -/// architecture except 32-bit x86, the frame address is passed. On x86, extra -/// parameters can be passed as variadic arguments, but we always pass none. -static RValue EmitMSVCRTSetJmp(CodeGenFunction &CGF, MSVCSetJmpKind SJKind, - const CallExpr *E) { - llvm::Value *Arg1 = nullptr; - llvm::Type *Arg1Ty = nullptr; - StringRef Name; - bool IsVarArg = false; - if (SJKind == MSVCSetJmpKind::_setjmp3) { - Name = "_setjmp3"; - Arg1Ty = CGF.Int32Ty; - Arg1 = llvm::ConstantInt::get(CGF.IntTy, 0); - IsVarArg = true; - } else { - Name = SJKind == MSVCSetJmpKind::_setjmp ? "_setjmp" : "_setjmpex"; - Arg1Ty = CGF.Int8PtrTy; - if (CGF.getTarget().getTriple().getArch() == llvm::Triple::aarch64) { - Arg1 = CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(Intrinsic::sponentry)); - } else - Arg1 = CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(Intrinsic::frameaddress), - llvm::ConstantInt::get(CGF.Int32Ty, 0)); - } - - // Mark the call site and declaration with ReturnsTwice. - llvm::Type *ArgTypes[2] = {CGF.Int8PtrTy, Arg1Ty}; - llvm::AttributeList ReturnsTwiceAttr = llvm::AttributeList::get( - CGF.getLLVMContext(), llvm::AttributeList::FunctionIndex, - llvm::Attribute::ReturnsTwice); - llvm::Constant *SetJmpFn = CGF.CGM.CreateRuntimeFunction( - llvm::FunctionType::get(CGF.IntTy, ArgTypes, IsVarArg), Name, - ReturnsTwiceAttr, /*Local=*/true); - - llvm::Value *Buf = CGF.Builder.CreateBitOrPointerCast( - CGF.EmitScalarExpr(E->getArg(0)), CGF.Int8PtrTy); - llvm::Value *Args[] = {Buf, Arg1}; - llvm::CallSite CS = CGF.EmitRuntimeCallOrInvoke(SetJmpFn, Args); - CS.setAttributes(ReturnsTwiceAttr); - return RValue::get(CS.getInstruction()); -} - -// Many of MSVC builtins are on x64, ARM and AArch64; to avoid repeating code, -// we handle them here. -enum class CodeGenFunction::MSVCIntrin { - _BitScanForward, - _BitScanReverse, - _InterlockedAnd, - _InterlockedDecrement, - _InterlockedExchange, - _InterlockedExchangeAdd, - _InterlockedExchangeSub, - _InterlockedIncrement, - _InterlockedOr, - _InterlockedXor, - _InterlockedExchangeAdd_acq, - _InterlockedExchangeAdd_rel, - _InterlockedExchangeAdd_nf, - _InterlockedExchange_acq, - _InterlockedExchange_rel, - _InterlockedExchange_nf, - _InterlockedCompareExchange_acq, - _InterlockedCompareExchange_rel, - _InterlockedCompareExchange_nf, - _InterlockedOr_acq, - _InterlockedOr_rel, - _InterlockedOr_nf, - _InterlockedXor_acq, - _InterlockedXor_rel, - _InterlockedXor_nf, - _InterlockedAnd_acq, - _InterlockedAnd_rel, - _InterlockedAnd_nf, - _InterlockedIncrement_acq, - _InterlockedIncrement_rel, - _InterlockedIncrement_nf, - _InterlockedDecrement_acq, - _InterlockedDecrement_rel, - _InterlockedDecrement_nf, - __fastfail, -}; - -Value *CodeGenFunction::EmitMSVCBuiltinExpr(MSVCIntrin BuiltinID, - const CallExpr *E) { - switch (BuiltinID) { - case MSVCIntrin::_BitScanForward: - case MSVCIntrin::_BitScanReverse: { - Value *ArgValue = EmitScalarExpr(E->getArg(1)); - - llvm::Type *ArgType = ArgValue->getType(); - llvm::Type *IndexType = - EmitScalarExpr(E->getArg(0))->getType()->getPointerElementType(); - llvm::Type *ResultType = ConvertType(E->getType()); - - Value *ArgZero = llvm::Constant::getNullValue(ArgType); - Value *ResZero = llvm::Constant::getNullValue(ResultType); - Value *ResOne = llvm::ConstantInt::get(ResultType, 1); - - BasicBlock *Begin = Builder.GetInsertBlock(); - BasicBlock *End = createBasicBlock("bitscan_end", this->CurFn); - Builder.SetInsertPoint(End); - PHINode *Result = Builder.CreatePHI(ResultType, 2, "bitscan_result"); - - Builder.SetInsertPoint(Begin); - Value *IsZero = Builder.CreateICmpEQ(ArgValue, ArgZero); - BasicBlock *NotZero = createBasicBlock("bitscan_not_zero", this->CurFn); - Builder.CreateCondBr(IsZero, End, NotZero); - Result->addIncoming(ResZero, Begin); - - Builder.SetInsertPoint(NotZero); - Address IndexAddress = EmitPointerWithAlignment(E->getArg(0)); - - if (BuiltinID == MSVCIntrin::_BitScanForward) { - Value *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType); - Value *ZeroCount = Builder.CreateCall(F, {ArgValue, Builder.getTrue()}); - ZeroCount = Builder.CreateIntCast(ZeroCount, IndexType, false); - Builder.CreateStore(ZeroCount, IndexAddress, false); - } else { - unsigned ArgWidth = cast<llvm::IntegerType>(ArgType)->getBitWidth(); - Value *ArgTypeLastIndex = llvm::ConstantInt::get(IndexType, ArgWidth - 1); - - Value *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType); - Value *ZeroCount = Builder.CreateCall(F, {ArgValue, Builder.getTrue()}); - ZeroCount = Builder.CreateIntCast(ZeroCount, IndexType, false); - Value *Index = Builder.CreateNSWSub(ArgTypeLastIndex, ZeroCount); - Builder.CreateStore(Index, IndexAddress, false); - } - Builder.CreateBr(End); - Result->addIncoming(ResOne, NotZero); - - Builder.SetInsertPoint(End); - return Result; - } - case MSVCIntrin::_InterlockedAnd: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::And, E); - case MSVCIntrin::_InterlockedExchange: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xchg, E); - case MSVCIntrin::_InterlockedExchangeAdd: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::Add, E); - case MSVCIntrin::_InterlockedExchangeSub: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::Sub, E); - case MSVCIntrin::_InterlockedOr: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::Or, E); - case MSVCIntrin::_InterlockedXor: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xor, E); - case MSVCIntrin::_InterlockedExchangeAdd_acq: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::Add, E, - AtomicOrdering::Acquire); - case MSVCIntrin::_InterlockedExchangeAdd_rel: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::Add, E, - AtomicOrdering::Release); - case MSVCIntrin::_InterlockedExchangeAdd_nf: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::Add, E, - AtomicOrdering::Monotonic); - case MSVCIntrin::_InterlockedExchange_acq: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xchg, E, - AtomicOrdering::Acquire); - case MSVCIntrin::_InterlockedExchange_rel: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xchg, E, - AtomicOrdering::Release); - case MSVCIntrin::_InterlockedExchange_nf: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xchg, E, - AtomicOrdering::Monotonic); - case MSVCIntrin::_InterlockedCompareExchange_acq: - return EmitAtomicCmpXchgForMSIntrin(*this, E, AtomicOrdering::Acquire); - case MSVCIntrin::_InterlockedCompareExchange_rel: - return EmitAtomicCmpXchgForMSIntrin(*this, E, AtomicOrdering::Release); - case MSVCIntrin::_InterlockedCompareExchange_nf: - return EmitAtomicCmpXchgForMSIntrin(*this, E, AtomicOrdering::Monotonic); - case MSVCIntrin::_InterlockedOr_acq: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::Or, E, - AtomicOrdering::Acquire); - case MSVCIntrin::_InterlockedOr_rel: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::Or, E, - AtomicOrdering::Release); - case MSVCIntrin::_InterlockedOr_nf: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::Or, E, - AtomicOrdering::Monotonic); - case MSVCIntrin::_InterlockedXor_acq: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xor, E, - AtomicOrdering::Acquire); - case MSVCIntrin::_InterlockedXor_rel: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xor, E, - AtomicOrdering::Release); - case MSVCIntrin::_InterlockedXor_nf: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xor, E, - AtomicOrdering::Monotonic); - case MSVCIntrin::_InterlockedAnd_acq: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::And, E, - AtomicOrdering::Acquire); - case MSVCIntrin::_InterlockedAnd_rel: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::And, E, - AtomicOrdering::Release); - case MSVCIntrin::_InterlockedAnd_nf: - return MakeBinaryAtomicValue(*this, AtomicRMWInst::And, E, - AtomicOrdering::Monotonic); - case MSVCIntrin::_InterlockedIncrement_acq: - return EmitAtomicIncrementValue(*this, E, AtomicOrdering::Acquire); - case MSVCIntrin::_InterlockedIncrement_rel: - return EmitAtomicIncrementValue(*this, E, AtomicOrdering::Release); - case MSVCIntrin::_InterlockedIncrement_nf: - return EmitAtomicIncrementValue(*this, E, AtomicOrdering::Monotonic); - case MSVCIntrin::_InterlockedDecrement_acq: - return EmitAtomicDecrementValue(*this, E, AtomicOrdering::Acquire); - case MSVCIntrin::_InterlockedDecrement_rel: - return EmitAtomicDecrementValue(*this, E, AtomicOrdering::Release); - case MSVCIntrin::_InterlockedDecrement_nf: - return EmitAtomicDecrementValue(*this, E, AtomicOrdering::Monotonic); - - case MSVCIntrin::_InterlockedDecrement: - return EmitAtomicDecrementValue(*this, E); - case MSVCIntrin::_InterlockedIncrement: - return EmitAtomicIncrementValue(*this, E); - - case MSVCIntrin::__fastfail: { - // Request immediate process termination from the kernel. The instruction - // sequences to do this are documented on MSDN: - // https://msdn.microsoft.com/en-us/library/dn774154.aspx - llvm::Triple::ArchType ISA = getTarget().getTriple().getArch(); - StringRef Asm, Constraints; - switch (ISA) { - default: - ErrorUnsupported(E, "__fastfail call for this architecture"); - break; - case llvm::Triple::x86: - case llvm::Triple::x86_64: - Asm = "int $$0x29"; - Constraints = "{cx}"; - break; - case llvm::Triple::thumb: - Asm = "udf #251"; - Constraints = "{r0}"; - break; - } - llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, {Int32Ty}, false); - llvm::InlineAsm *IA = - llvm::InlineAsm::get(FTy, Asm, Constraints, /*SideEffects=*/true); - llvm::AttributeList NoReturnAttr = llvm::AttributeList::get( - getLLVMContext(), llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoReturn); - CallSite CS = Builder.CreateCall(IA, EmitScalarExpr(E->getArg(0))); - CS.setAttributes(NoReturnAttr); - return CS.getInstruction(); - } - } - llvm_unreachable("Incorrect MSVC intrinsic!"); -} - -namespace { -// ARC cleanup for __builtin_os_log_format -struct CallObjCArcUse final : EHScopeStack::Cleanup { - CallObjCArcUse(llvm::Value *object) : object(object) {} - llvm::Value *object; - - void Emit(CodeGenFunction &CGF, Flags flags) override { - CGF.EmitARCIntrinsicUse(object); - } -}; -} - -Value *CodeGenFunction::EmitCheckedArgForBuiltin(const Expr *E, - BuiltinCheckKind Kind) { - assert((Kind == BCK_CLZPassedZero || Kind == BCK_CTZPassedZero) - && "Unsupported builtin check kind"); - - Value *ArgValue = EmitScalarExpr(E); - if (!SanOpts.has(SanitizerKind::Builtin) || !getTarget().isCLZForZeroUndef()) - return ArgValue; - - SanitizerScope SanScope(this); - Value *Cond = Builder.CreateICmpNE( - ArgValue, llvm::Constant::getNullValue(ArgValue->getType())); - EmitCheck(std::make_pair(Cond, SanitizerKind::Builtin), - SanitizerHandler::InvalidBuiltin, - {EmitCheckSourceLocation(E->getExprLoc()), - llvm::ConstantInt::get(Builder.getInt8Ty(), Kind)}, - None); - return ArgValue; -} - -/// Get the argument type for arguments to os_log_helper. -static CanQualType getOSLogArgType(ASTContext &C, int Size) { - QualType UnsignedTy = C.getIntTypeForBitwidth(Size * 8, /*Signed=*/false); - return C.getCanonicalType(UnsignedTy); -} - -llvm::Function *CodeGenFunction::generateBuiltinOSLogHelperFunction( - const analyze_os_log::OSLogBufferLayout &Layout, - CharUnits BufferAlignment) { - ASTContext &Ctx = getContext(); - - llvm::SmallString<64> Name; - { - raw_svector_ostream OS(Name); - OS << "__os_log_helper"; - OS << "_" << BufferAlignment.getQuantity(); - OS << "_" << int(Layout.getSummaryByte()); - OS << "_" << int(Layout.getNumArgsByte()); - for (const auto &Item : Layout.Items) - OS << "_" << int(Item.getSizeByte()) << "_" - << int(Item.getDescriptorByte()); - } - - if (llvm::Function *F = CGM.getModule().getFunction(Name)) - return F; - - llvm::SmallVector<QualType, 4> ArgTys; - llvm::SmallVector<ImplicitParamDecl, 4> Params; - Params.emplace_back(Ctx, nullptr, SourceLocation(), &Ctx.Idents.get("buffer"), - Ctx.VoidPtrTy, ImplicitParamDecl::Other); - ArgTys.emplace_back(Ctx.VoidPtrTy); - - for (unsigned int I = 0, E = Layout.Items.size(); I < E; ++I) { - char Size = Layout.Items[I].getSizeByte(); - if (!Size) - continue; - - QualType ArgTy = getOSLogArgType(Ctx, Size); - Params.emplace_back( - Ctx, nullptr, SourceLocation(), - &Ctx.Idents.get(std::string("arg") + llvm::to_string(I)), ArgTy, - ImplicitParamDecl::Other); - ArgTys.emplace_back(ArgTy); - } - - FunctionArgList Args; - for (auto &P : Params) - Args.push_back(&P); - - QualType ReturnTy = Ctx.VoidTy; - QualType FuncionTy = Ctx.getFunctionType(ReturnTy, ArgTys, {}); - - // The helper function has linkonce_odr linkage to enable the linker to merge - // identical functions. To ensure the merging always happens, 'noinline' is - // attached to the function when compiling with -Oz. - const CGFunctionInfo &FI = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, Args); - llvm::FunctionType *FuncTy = CGM.getTypes().GetFunctionType(FI); - llvm::Function *Fn = llvm::Function::Create( - FuncTy, llvm::GlobalValue::LinkOnceODRLinkage, Name, &CGM.getModule()); - Fn->setVisibility(llvm::GlobalValue::HiddenVisibility); - CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Fn); - CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Fn); - - // Attach 'noinline' at -Oz. - if (CGM.getCodeGenOpts().OptimizeSize == 2) - Fn->addFnAttr(llvm::Attribute::NoInline); - - auto NL = ApplyDebugLocation::CreateEmpty(*this); - IdentifierInfo *II = &Ctx.Idents.get(Name); - FunctionDecl *FD = FunctionDecl::Create( - Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II, - FuncionTy, nullptr, SC_PrivateExtern, false, false); - - StartFunction(FD, ReturnTy, Fn, FI, Args); - - // Create a scope with an artificial location for the body of this function. - auto AL = ApplyDebugLocation::CreateArtificial(*this); - - CharUnits Offset; - Address BufAddr(Builder.CreateLoad(GetAddrOfLocalVar(&Params[0]), "buf"), - BufferAlignment); - Builder.CreateStore(Builder.getInt8(Layout.getSummaryByte()), - Builder.CreateConstByteGEP(BufAddr, Offset++, "summary")); - Builder.CreateStore(Builder.getInt8(Layout.getNumArgsByte()), - Builder.CreateConstByteGEP(BufAddr, Offset++, "numArgs")); - - unsigned I = 1; - for (const auto &Item : Layout.Items) { - Builder.CreateStore( - Builder.getInt8(Item.getDescriptorByte()), - Builder.CreateConstByteGEP(BufAddr, Offset++, "argDescriptor")); - Builder.CreateStore( - Builder.getInt8(Item.getSizeByte()), - Builder.CreateConstByteGEP(BufAddr, Offset++, "argSize")); - - CharUnits Size = Item.size(); - if (!Size.getQuantity()) - continue; - - Address Arg = GetAddrOfLocalVar(&Params[I]); - Address Addr = Builder.CreateConstByteGEP(BufAddr, Offset, "argData"); - Addr = Builder.CreateBitCast(Addr, Arg.getPointer()->getType(), - "argDataCast"); - Builder.CreateStore(Builder.CreateLoad(Arg), Addr); - Offset += Size; - ++I; - } - - FinishFunction(); - - return Fn; -} - -RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) { - assert(E.getNumArgs() >= 2 && - "__builtin_os_log_format takes at least 2 arguments"); - ASTContext &Ctx = getContext(); - analyze_os_log::OSLogBufferLayout Layout; - analyze_os_log::computeOSLogBufferLayout(Ctx, &E, Layout); - Address BufAddr = EmitPointerWithAlignment(E.getArg(0)); - llvm::SmallVector<llvm::Value *, 4> RetainableOperands; - - // Ignore argument 1, the format string. It is not currently used. - CallArgList Args; - Args.add(RValue::get(BufAddr.getPointer()), Ctx.VoidPtrTy); - - for (const auto &Item : Layout.Items) { - int Size = Item.getSizeByte(); - if (!Size) - continue; - - llvm::Value *ArgVal; - - if (Item.getKind() == analyze_os_log::OSLogBufferItem::MaskKind) { - uint64_t Val = 0; - for (unsigned I = 0, E = Item.getMaskType().size(); I < E; ++I) - Val |= ((uint64_t)Item.getMaskType()[I]) << I * 8; - ArgVal = llvm::Constant::getIntegerValue(Int64Ty, llvm::APInt(64, Val)); - } else if (const Expr *TheExpr = Item.getExpr()) { - ArgVal = EmitScalarExpr(TheExpr, /*Ignore*/ false); - - // Check if this is a retainable type. - if (TheExpr->getType()->isObjCRetainableType()) { - assert(getEvaluationKind(TheExpr->getType()) == TEK_Scalar && - "Only scalar can be a ObjC retainable type"); - // Check if the object is constant, if not, save it in - // RetainableOperands. - if (!isa<Constant>(ArgVal)) - RetainableOperands.push_back(ArgVal); - } - } else { - ArgVal = Builder.getInt32(Item.getConstValue().getQuantity()); - } - - unsigned ArgValSize = - CGM.getDataLayout().getTypeSizeInBits(ArgVal->getType()); - llvm::IntegerType *IntTy = llvm::Type::getIntNTy(getLLVMContext(), - ArgValSize); - ArgVal = Builder.CreateBitOrPointerCast(ArgVal, IntTy); - CanQualType ArgTy = getOSLogArgType(Ctx, Size); - // If ArgVal has type x86_fp80, zero-extend ArgVal. - ArgVal = Builder.CreateZExtOrBitCast(ArgVal, ConvertType(ArgTy)); - Args.add(RValue::get(ArgVal), ArgTy); - } - - const CGFunctionInfo &FI = - CGM.getTypes().arrangeBuiltinFunctionCall(Ctx.VoidTy, Args); - llvm::Function *F = CodeGenFunction(CGM).generateBuiltinOSLogHelperFunction( - Layout, BufAddr.getAlignment()); - EmitCall(FI, CGCallee::forDirect(F), ReturnValueSlot(), Args); - - // Push a clang.arc.use cleanup for each object in RetainableOperands. The - // cleanup will cause the use to appear after the final log call, keeping - // the object valid while it’s held in the log buffer. Note that if there’s - // a release cleanup on the object, it will already be active; since - // cleanups are emitted in reverse order, the use will occur before the - // object is released. - if (!RetainableOperands.empty() && getLangOpts().ObjCAutoRefCount && - CGM.getCodeGenOpts().OptimizationLevel != 0) - for (llvm::Value *Object : RetainableOperands) - pushFullExprCleanup<CallObjCArcUse>(getARCCleanupKind(), Object); - - return RValue::get(BufAddr.getPointer()); -} - -/// Determine if a binop is a checked mixed-sign multiply we can specialize. -static bool isSpecialMixedSignMultiply(unsigned BuiltinID, - WidthAndSignedness Op1Info, - WidthAndSignedness Op2Info, - WidthAndSignedness ResultInfo) { - return BuiltinID == Builtin::BI__builtin_mul_overflow && - std::max(Op1Info.Width, Op2Info.Width) >= ResultInfo.Width && - Op1Info.Signed != Op2Info.Signed; -} - -/// Emit a checked mixed-sign multiply. This is a cheaper specialization of -/// the generic checked-binop irgen. -static RValue -EmitCheckedMixedSignMultiply(CodeGenFunction &CGF, const clang::Expr *Op1, - WidthAndSignedness Op1Info, const clang::Expr *Op2, - WidthAndSignedness Op2Info, - const clang::Expr *ResultArg, QualType ResultQTy, - WidthAndSignedness ResultInfo) { - assert(isSpecialMixedSignMultiply(Builtin::BI__builtin_mul_overflow, Op1Info, - Op2Info, ResultInfo) && - "Not a mixed-sign multipliction we can specialize"); - - // Emit the signed and unsigned operands. - const clang::Expr *SignedOp = Op1Info.Signed ? Op1 : Op2; - const clang::Expr *UnsignedOp = Op1Info.Signed ? Op2 : Op1; - llvm::Value *Signed = CGF.EmitScalarExpr(SignedOp); - llvm::Value *Unsigned = CGF.EmitScalarExpr(UnsignedOp); - unsigned SignedOpWidth = Op1Info.Signed ? Op1Info.Width : Op2Info.Width; - unsigned UnsignedOpWidth = Op1Info.Signed ? Op2Info.Width : Op1Info.Width; - - // One of the operands may be smaller than the other. If so, [s|z]ext it. - if (SignedOpWidth < UnsignedOpWidth) - Signed = CGF.Builder.CreateSExt(Signed, Unsigned->getType(), "op.sext"); - if (UnsignedOpWidth < SignedOpWidth) - Unsigned = CGF.Builder.CreateZExt(Unsigned, Signed->getType(), "op.zext"); - - llvm::Type *OpTy = Signed->getType(); - llvm::Value *Zero = llvm::Constant::getNullValue(OpTy); - Address ResultPtr = CGF.EmitPointerWithAlignment(ResultArg); - llvm::Type *ResTy = ResultPtr.getElementType(); - unsigned OpWidth = std::max(Op1Info.Width, Op2Info.Width); - - // Take the absolute value of the signed operand. - llvm::Value *IsNegative = CGF.Builder.CreateICmpSLT(Signed, Zero); - llvm::Value *AbsOfNegative = CGF.Builder.CreateSub(Zero, Signed); - llvm::Value *AbsSigned = - CGF.Builder.CreateSelect(IsNegative, AbsOfNegative, Signed); - - // Perform a checked unsigned multiplication. - llvm::Value *UnsignedOverflow; - llvm::Value *UnsignedResult = - EmitOverflowIntrinsic(CGF, llvm::Intrinsic::umul_with_overflow, AbsSigned, - Unsigned, UnsignedOverflow); - - llvm::Value *Overflow, *Result; - if (ResultInfo.Signed) { - // Signed overflow occurs if the result is greater than INT_MAX or lesser - // than INT_MIN, i.e when |Result| > (INT_MAX + IsNegative). - auto IntMax = - llvm::APInt::getSignedMaxValue(ResultInfo.Width).zextOrSelf(OpWidth); - llvm::Value *MaxResult = - CGF.Builder.CreateAdd(llvm::ConstantInt::get(OpTy, IntMax), - CGF.Builder.CreateZExt(IsNegative, OpTy)); - llvm::Value *SignedOverflow = - CGF.Builder.CreateICmpUGT(UnsignedResult, MaxResult); - Overflow = CGF.Builder.CreateOr(UnsignedOverflow, SignedOverflow); - - // Prepare the signed result (possibly by negating it). - llvm::Value *NegativeResult = CGF.Builder.CreateNeg(UnsignedResult); - llvm::Value *SignedResult = - CGF.Builder.CreateSelect(IsNegative, NegativeResult, UnsignedResult); - Result = CGF.Builder.CreateTrunc(SignedResult, ResTy); - } else { - // Unsigned overflow occurs if the result is < 0 or greater than UINT_MAX. - llvm::Value *Underflow = CGF.Builder.CreateAnd( - IsNegative, CGF.Builder.CreateIsNotNull(UnsignedResult)); - Overflow = CGF.Builder.CreateOr(UnsignedOverflow, Underflow); - if (ResultInfo.Width < OpWidth) { - auto IntMax = - llvm::APInt::getMaxValue(ResultInfo.Width).zext(OpWidth); - llvm::Value *TruncOverflow = CGF.Builder.CreateICmpUGT( - UnsignedResult, llvm::ConstantInt::get(OpTy, IntMax)); - Overflow = CGF.Builder.CreateOr(Overflow, TruncOverflow); - } - - // Negate the product if it would be negative in infinite precision. - Result = CGF.Builder.CreateSelect( - IsNegative, CGF.Builder.CreateNeg(UnsignedResult), UnsignedResult); - - Result = CGF.Builder.CreateTrunc(Result, ResTy); - } - assert(Overflow && Result && "Missing overflow or result"); - - bool isVolatile = - ResultArg->getType()->getPointeeType().isVolatileQualified(); - CGF.Builder.CreateStore(CGF.EmitToMemory(Result, ResultQTy), ResultPtr, - isVolatile); - return RValue::get(Overflow); -} - -static llvm::Value *dumpRecord(CodeGenFunction &CGF, QualType RType, - Value *&RecordPtr, CharUnits Align, Value *Func, - int Lvl) { - const auto *RT = RType->getAs<RecordType>(); - ASTContext &Context = CGF.getContext(); - RecordDecl *RD = RT->getDecl()->getDefinition(); - ASTContext &Ctx = RD->getASTContext(); - const ASTRecordLayout &RL = Ctx.getASTRecordLayout(RD); - std::string Pad = std::string(Lvl * 4, ' '); - - Value *GString = - CGF.Builder.CreateGlobalStringPtr(RType.getAsString() + " {\n"); - Value *Res = CGF.Builder.CreateCall(Func, {GString}); - - static llvm::DenseMap<QualType, const char *> Types; - if (Types.empty()) { - Types[Context.CharTy] = "%c"; - Types[Context.BoolTy] = "%d"; - Types[Context.SignedCharTy] = "%hhd"; - Types[Context.UnsignedCharTy] = "%hhu"; - Types[Context.IntTy] = "%d"; - Types[Context.UnsignedIntTy] = "%u"; - Types[Context.LongTy] = "%ld"; - Types[Context.UnsignedLongTy] = "%lu"; - Types[Context.LongLongTy] = "%lld"; - Types[Context.UnsignedLongLongTy] = "%llu"; - Types[Context.ShortTy] = "%hd"; - Types[Context.UnsignedShortTy] = "%hu"; - Types[Context.VoidPtrTy] = "%p"; - Types[Context.FloatTy] = "%f"; - Types[Context.DoubleTy] = "%f"; - Types[Context.LongDoubleTy] = "%Lf"; - Types[Context.getPointerType(Context.CharTy)] = "%s"; - Types[Context.getPointerType(Context.getConstType(Context.CharTy))] = "%s"; - } - - for (const auto *FD : RD->fields()) { - uint64_t Off = RL.getFieldOffset(FD->getFieldIndex()); - Off = Ctx.toCharUnitsFromBits(Off).getQuantity(); - - Value *FieldPtr = RecordPtr; - if (RD->isUnion()) - FieldPtr = CGF.Builder.CreatePointerCast( - FieldPtr, CGF.ConvertType(Context.getPointerType(FD->getType()))); - else - FieldPtr = CGF.Builder.CreateStructGEP(CGF.ConvertType(RType), FieldPtr, - FD->getFieldIndex()); - - GString = CGF.Builder.CreateGlobalStringPtr( - llvm::Twine(Pad) - .concat(FD->getType().getAsString()) - .concat(llvm::Twine(' ')) - .concat(FD->getNameAsString()) - .concat(" : ") - .str()); - Value *TmpRes = CGF.Builder.CreateCall(Func, {GString}); - Res = CGF.Builder.CreateAdd(Res, TmpRes); - - QualType CanonicalType = - FD->getType().getUnqualifiedType().getCanonicalType(); - - // We check whether we are in a recursive type - if (CanonicalType->isRecordType()) { - Value *TmpRes = - dumpRecord(CGF, CanonicalType, FieldPtr, Align, Func, Lvl + 1); - Res = CGF.Builder.CreateAdd(TmpRes, Res); - continue; - } - - // We try to determine the best format to print the current field - llvm::Twine Format = Types.find(CanonicalType) == Types.end() - ? Types[Context.VoidPtrTy] - : Types[CanonicalType]; - - Address FieldAddress = Address(FieldPtr, Align); - FieldPtr = CGF.Builder.CreateLoad(FieldAddress); - - // FIXME Need to handle bitfield here - GString = CGF.Builder.CreateGlobalStringPtr( - Format.concat(llvm::Twine('\n')).str()); - TmpRes = CGF.Builder.CreateCall(Func, {GString, FieldPtr}); - Res = CGF.Builder.CreateAdd(Res, TmpRes); - } - - GString = CGF.Builder.CreateGlobalStringPtr(Pad + "}\n"); - Value *TmpRes = CGF.Builder.CreateCall(Func, {GString}); - Res = CGF.Builder.CreateAdd(Res, TmpRes); - return Res; -} - -static bool -TypeRequiresBuiltinLaunderImp(const ASTContext &Ctx, QualType Ty, - llvm::SmallPtrSetImpl<const Decl *> &Seen) { - if (const auto *Arr = Ctx.getAsArrayType(Ty)) - Ty = Ctx.getBaseElementType(Arr); - - const auto *Record = Ty->getAsCXXRecordDecl(); - if (!Record) - return false; - - // We've already checked this type, or are in the process of checking it. - if (!Seen.insert(Record).second) - return false; - - assert(Record->hasDefinition() && - "Incomplete types should already be diagnosed"); - - if (Record->isDynamicClass()) - return true; - - for (FieldDecl *F : Record->fields()) { - if (TypeRequiresBuiltinLaunderImp(Ctx, F->getType(), Seen)) - return true; - } - return false; -} - -/// Determine if the specified type requires laundering by checking if it is a -/// dynamic class type or contains a subobject which is a dynamic class type. -static bool TypeRequiresBuiltinLaunder(CodeGenModule &CGM, QualType Ty) { - if (!CGM.getCodeGenOpts().StrictVTablePointers) - return false; - llvm::SmallPtrSet<const Decl *, 16> Seen; - return TypeRequiresBuiltinLaunderImp(CGM.getContext(), Ty, Seen); -} - -RValue CodeGenFunction::emitRotate(const CallExpr *E, bool IsRotateRight) { - llvm::Value *Src = EmitScalarExpr(E->getArg(0)); - llvm::Value *ShiftAmt = EmitScalarExpr(E->getArg(1)); - - // The builtin's shift arg may have a different type than the source arg and - // result, but the LLVM intrinsic uses the same type for all values. - llvm::Type *Ty = Src->getType(); - ShiftAmt = Builder.CreateIntCast(ShiftAmt, Ty, false); - - // Rotate is a special case of LLVM funnel shift - 1st 2 args are the same. - unsigned IID = IsRotateRight ? Intrinsic::fshr : Intrinsic::fshl; - Value *F = CGM.getIntrinsic(IID, Ty); - return RValue::get(Builder.CreateCall(F, { Src, Src, ShiftAmt })); -} - -RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, - const CallExpr *E, - ReturnValueSlot ReturnValue) { - const FunctionDecl *FD = GD.getDecl()->getAsFunction(); - // See if we can constant fold this builtin. If so, don't emit it at all. - Expr::EvalResult Result; - if (E->EvaluateAsRValue(Result, CGM.getContext()) && - !Result.hasSideEffects()) { - if (Result.Val.isInt()) - return RValue::get(llvm::ConstantInt::get(getLLVMContext(), - Result.Val.getInt())); - if (Result.Val.isFloat()) - return RValue::get(llvm::ConstantFP::get(getLLVMContext(), - Result.Val.getFloat())); - } - - // There are LLVM math intrinsics/instructions corresponding to math library - // functions except the LLVM op will never set errno while the math library - // might. Also, math builtins have the same semantics as their math library - // twins. Thus, we can transform math library and builtin calls to their - // LLVM counterparts if the call is marked 'const' (known to never set errno). - if (FD->hasAttr<ConstAttr>()) { - switch (BuiltinID) { - case Builtin::BIceil: - case Builtin::BIceilf: - case Builtin::BIceill: - case Builtin::BI__builtin_ceil: - case Builtin::BI__builtin_ceilf: - case Builtin::BI__builtin_ceill: - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::ceil)); - - case Builtin::BIcopysign: - case Builtin::BIcopysignf: - case Builtin::BIcopysignl: - case Builtin::BI__builtin_copysign: - case Builtin::BI__builtin_copysignf: - case Builtin::BI__builtin_copysignl: - case Builtin::BI__builtin_copysignf128: - return RValue::get(emitBinaryBuiltin(*this, E, Intrinsic::copysign)); - - case Builtin::BIcos: - case Builtin::BIcosf: - case Builtin::BIcosl: - case Builtin::BI__builtin_cos: - case Builtin::BI__builtin_cosf: - case Builtin::BI__builtin_cosl: - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::cos)); - - case Builtin::BIexp: - case Builtin::BIexpf: - case Builtin::BIexpl: - case Builtin::BI__builtin_exp: - case Builtin::BI__builtin_expf: - case Builtin::BI__builtin_expl: - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::exp)); - - case Builtin::BIexp2: - case Builtin::BIexp2f: - case Builtin::BIexp2l: - case Builtin::BI__builtin_exp2: - case Builtin::BI__builtin_exp2f: - case Builtin::BI__builtin_exp2l: - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::exp2)); - - case Builtin::BIfabs: - case Builtin::BIfabsf: - case Builtin::BIfabsl: - case Builtin::BI__builtin_fabs: - case Builtin::BI__builtin_fabsf: - case Builtin::BI__builtin_fabsl: - case Builtin::BI__builtin_fabsf128: - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::fabs)); - - case Builtin::BIfloor: - case Builtin::BIfloorf: - case Builtin::BIfloorl: - case Builtin::BI__builtin_floor: - case Builtin::BI__builtin_floorf: - case Builtin::BI__builtin_floorl: - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::floor)); - - case Builtin::BIfma: - case Builtin::BIfmaf: - case Builtin::BIfmal: - case Builtin::BI__builtin_fma: - case Builtin::BI__builtin_fmaf: - case Builtin::BI__builtin_fmal: - return RValue::get(emitTernaryBuiltin(*this, E, Intrinsic::fma)); - - case Builtin::BIfmax: - case Builtin::BIfmaxf: - case Builtin::BIfmaxl: - case Builtin::BI__builtin_fmax: - case Builtin::BI__builtin_fmaxf: - case Builtin::BI__builtin_fmaxl: - return RValue::get(emitBinaryBuiltin(*this, E, Intrinsic::maxnum)); - - case Builtin::BIfmin: - case Builtin::BIfminf: - case Builtin::BIfminl: - case Builtin::BI__builtin_fmin: - case Builtin::BI__builtin_fminf: - case Builtin::BI__builtin_fminl: - return RValue::get(emitBinaryBuiltin(*this, E, Intrinsic::minnum)); - - // fmod() is a special-case. It maps to the frem instruction rather than an - // LLVM intrinsic. - case Builtin::BIfmod: - case Builtin::BIfmodf: - case Builtin::BIfmodl: - case Builtin::BI__builtin_fmod: - case Builtin::BI__builtin_fmodf: - case Builtin::BI__builtin_fmodl: { - Value *Arg1 = EmitScalarExpr(E->getArg(0)); - Value *Arg2 = EmitScalarExpr(E->getArg(1)); - return RValue::get(Builder.CreateFRem(Arg1, Arg2, "fmod")); - } - - case Builtin::BIlog: - case Builtin::BIlogf: - case Builtin::BIlogl: - case Builtin::BI__builtin_log: - case Builtin::BI__builtin_logf: - case Builtin::BI__builtin_logl: - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::log)); - - case Builtin::BIlog10: - case Builtin::BIlog10f: - case Builtin::BIlog10l: - case Builtin::BI__builtin_log10: - case Builtin::BI__builtin_log10f: - case Builtin::BI__builtin_log10l: - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::log10)); - - case Builtin::BIlog2: - case Builtin::BIlog2f: - case Builtin::BIlog2l: - case Builtin::BI__builtin_log2: - case Builtin::BI__builtin_log2f: - case Builtin::BI__builtin_log2l: - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::log2)); - - case Builtin::BInearbyint: - case Builtin::BInearbyintf: - case Builtin::BInearbyintl: - case Builtin::BI__builtin_nearbyint: - case Builtin::BI__builtin_nearbyintf: - case Builtin::BI__builtin_nearbyintl: - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::nearbyint)); - - case Builtin::BIpow: - case Builtin::BIpowf: - case Builtin::BIpowl: - case Builtin::BI__builtin_pow: - case Builtin::BI__builtin_powf: - case Builtin::BI__builtin_powl: - return RValue::get(emitBinaryBuiltin(*this, E, Intrinsic::pow)); - - case Builtin::BIrint: - case Builtin::BIrintf: - case Builtin::BIrintl: - case Builtin::BI__builtin_rint: - case Builtin::BI__builtin_rintf: - case Builtin::BI__builtin_rintl: - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::rint)); - - case Builtin::BIround: - case Builtin::BIroundf: - case Builtin::BIroundl: - case Builtin::BI__builtin_round: - case Builtin::BI__builtin_roundf: - case Builtin::BI__builtin_roundl: - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::round)); - - case Builtin::BIsin: - case Builtin::BIsinf: - case Builtin::BIsinl: - case Builtin::BI__builtin_sin: - case Builtin::BI__builtin_sinf: - case Builtin::BI__builtin_sinl: - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::sin)); - - case Builtin::BIsqrt: - case Builtin::BIsqrtf: - case Builtin::BIsqrtl: - case Builtin::BI__builtin_sqrt: - case Builtin::BI__builtin_sqrtf: - case Builtin::BI__builtin_sqrtl: - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::sqrt)); - - case Builtin::BItrunc: - case Builtin::BItruncf: - case Builtin::BItruncl: - case Builtin::BI__builtin_trunc: - case Builtin::BI__builtin_truncf: - case Builtin::BI__builtin_truncl: - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::trunc)); - - default: - break; - } - } - - switch (BuiltinID) { - default: break; - case Builtin::BI__builtin___CFStringMakeConstantString: - case Builtin::BI__builtin___NSStringMakeConstantString: - return RValue::get(ConstantEmitter(*this).emitAbstract(E, E->getType())); - case Builtin::BI__builtin_stdarg_start: - case Builtin::BI__builtin_va_start: - case Builtin::BI__va_start: - case Builtin::BI__builtin_va_end: - return RValue::get( - EmitVAStartEnd(BuiltinID == Builtin::BI__va_start - ? EmitScalarExpr(E->getArg(0)) - : EmitVAListRef(E->getArg(0)).getPointer(), - BuiltinID != Builtin::BI__builtin_va_end)); - case Builtin::BI__builtin_va_copy: { - Value *DstPtr = EmitVAListRef(E->getArg(0)).getPointer(); - Value *SrcPtr = EmitVAListRef(E->getArg(1)).getPointer(); - - llvm::Type *Type = Int8PtrTy; - - DstPtr = Builder.CreateBitCast(DstPtr, Type); - SrcPtr = Builder.CreateBitCast(SrcPtr, Type); - return RValue::get(Builder.CreateCall(CGM.getIntrinsic(Intrinsic::vacopy), - {DstPtr, SrcPtr})); - } - case Builtin::BI__builtin_abs: - case Builtin::BI__builtin_labs: - case Builtin::BI__builtin_llabs: { - // X < 0 ? -X : X - // The negation has 'nsw' because abs of INT_MIN is undefined. - Value *ArgValue = EmitScalarExpr(E->getArg(0)); - Value *NegOp = Builder.CreateNSWNeg(ArgValue, "neg"); - Constant *Zero = llvm::Constant::getNullValue(ArgValue->getType()); - Value *CmpResult = Builder.CreateICmpSLT(ArgValue, Zero, "abscond"); - Value *Result = Builder.CreateSelect(CmpResult, NegOp, ArgValue, "abs"); - return RValue::get(Result); - } - case Builtin::BI__builtin_conj: - case Builtin::BI__builtin_conjf: - case Builtin::BI__builtin_conjl: { - ComplexPairTy ComplexVal = EmitComplexExpr(E->getArg(0)); - Value *Real = ComplexVal.first; - Value *Imag = ComplexVal.second; - Value *Zero = - Imag->getType()->isFPOrFPVectorTy() - ? llvm::ConstantFP::getZeroValueForNegation(Imag->getType()) - : llvm::Constant::getNullValue(Imag->getType()); - - Imag = Builder.CreateFSub(Zero, Imag, "sub"); - return RValue::getComplex(std::make_pair(Real, Imag)); - } - case Builtin::BI__builtin_creal: - case Builtin::BI__builtin_crealf: - case Builtin::BI__builtin_creall: - case Builtin::BIcreal: - case Builtin::BIcrealf: - case Builtin::BIcreall: { - ComplexPairTy ComplexVal = EmitComplexExpr(E->getArg(0)); - return RValue::get(ComplexVal.first); - } - - case Builtin::BI__builtin_dump_struct: { - Value *Func = EmitScalarExpr(E->getArg(1)->IgnoreImpCasts()); - CharUnits Arg0Align = EmitPointerWithAlignment(E->getArg(0)).getAlignment(); - - const Expr *Arg0 = E->getArg(0)->IgnoreImpCasts(); - QualType Arg0Type = Arg0->getType()->getPointeeType(); - - Value *RecordPtr = EmitScalarExpr(Arg0); - Value *Res = dumpRecord(*this, Arg0Type, RecordPtr, Arg0Align, Func, 0); - return RValue::get(Res); - } - - case Builtin::BI__builtin_cimag: - case Builtin::BI__builtin_cimagf: - case Builtin::BI__builtin_cimagl: - case Builtin::BIcimag: - case Builtin::BIcimagf: - case Builtin::BIcimagl: { - ComplexPairTy ComplexVal = EmitComplexExpr(E->getArg(0)); - return RValue::get(ComplexVal.second); - } - - case Builtin::BI__builtin_clrsb: - case Builtin::BI__builtin_clrsbl: - case Builtin::BI__builtin_clrsbll: { - // clrsb(x) -> clz(x < 0 ? ~x : x) - 1 or - Value *ArgValue = EmitScalarExpr(E->getArg(0)); - - llvm::Type *ArgType = ArgValue->getType(); - Value *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType); - - llvm::Type *ResultType = ConvertType(E->getType()); - Value *Zero = llvm::Constant::getNullValue(ArgType); - Value *IsNeg = Builder.CreateICmpSLT(ArgValue, Zero, "isneg"); - Value *Inverse = Builder.CreateNot(ArgValue, "not"); - Value *Tmp = Builder.CreateSelect(IsNeg, Inverse, ArgValue); - Value *Ctlz = Builder.CreateCall(F, {Tmp, Builder.getFalse()}); - Value *Result = Builder.CreateSub(Ctlz, llvm::ConstantInt::get(ArgType, 1)); - Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, - "cast"); - return RValue::get(Result); - } - case Builtin::BI__builtin_ctzs: - case Builtin::BI__builtin_ctz: - case Builtin::BI__builtin_ctzl: - case Builtin::BI__builtin_ctzll: { - Value *ArgValue = EmitCheckedArgForBuiltin(E->getArg(0), BCK_CTZPassedZero); - - llvm::Type *ArgType = ArgValue->getType(); - Value *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType); - - llvm::Type *ResultType = ConvertType(E->getType()); - Value *ZeroUndef = Builder.getInt1(getTarget().isCLZForZeroUndef()); - Value *Result = Builder.CreateCall(F, {ArgValue, ZeroUndef}); - if (Result->getType() != ResultType) - Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, - "cast"); - return RValue::get(Result); - } - case Builtin::BI__builtin_clzs: - case Builtin::BI__builtin_clz: - case Builtin::BI__builtin_clzl: - case Builtin::BI__builtin_clzll: { - Value *ArgValue = EmitCheckedArgForBuiltin(E->getArg(0), BCK_CLZPassedZero); - - llvm::Type *ArgType = ArgValue->getType(); - Value *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType); - - llvm::Type *ResultType = ConvertType(E->getType()); - Value *ZeroUndef = Builder.getInt1(getTarget().isCLZForZeroUndef()); - Value *Result = Builder.CreateCall(F, {ArgValue, ZeroUndef}); - if (Result->getType() != ResultType) - Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, - "cast"); - return RValue::get(Result); - } - case Builtin::BI__builtin_ffs: - case Builtin::BI__builtin_ffsl: - case Builtin::BI__builtin_ffsll: { - // ffs(x) -> x ? cttz(x) + 1 : 0 - Value *ArgValue = EmitScalarExpr(E->getArg(0)); - - llvm::Type *ArgType = ArgValue->getType(); - Value *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType); - - llvm::Type *ResultType = ConvertType(E->getType()); - Value *Tmp = - Builder.CreateAdd(Builder.CreateCall(F, {ArgValue, Builder.getTrue()}), - llvm::ConstantInt::get(ArgType, 1)); - Value *Zero = llvm::Constant::getNullValue(ArgType); - Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero, "iszero"); - Value *Result = Builder.CreateSelect(IsZero, Zero, Tmp, "ffs"); - if (Result->getType() != ResultType) - Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, - "cast"); - return RValue::get(Result); - } - case Builtin::BI__builtin_parity: - case Builtin::BI__builtin_parityl: - case Builtin::BI__builtin_parityll: { - // parity(x) -> ctpop(x) & 1 - Value *ArgValue = EmitScalarExpr(E->getArg(0)); - - llvm::Type *ArgType = ArgValue->getType(); - Value *F = CGM.getIntrinsic(Intrinsic::ctpop, ArgType); - - llvm::Type *ResultType = ConvertType(E->getType()); - Value *Tmp = Builder.CreateCall(F, ArgValue); - Value *Result = Builder.CreateAnd(Tmp, llvm::ConstantInt::get(ArgType, 1)); - if (Result->getType() != ResultType) - Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, - "cast"); - return RValue::get(Result); - } - case Builtin::BI__lzcnt16: - case Builtin::BI__lzcnt: - case Builtin::BI__lzcnt64: { - Value *ArgValue = EmitScalarExpr(E->getArg(0)); - - llvm::Type *ArgType = ArgValue->getType(); - Value *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType); - - llvm::Type *ResultType = ConvertType(E->getType()); - Value *Result = Builder.CreateCall(F, {ArgValue, Builder.getFalse()}); - if (Result->getType() != ResultType) - Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, - "cast"); - return RValue::get(Result); - } - case Builtin::BI__popcnt16: - case Builtin::BI__popcnt: - case Builtin::BI__popcnt64: - case Builtin::BI__builtin_popcount: - case Builtin::BI__builtin_popcountl: - case Builtin::BI__builtin_popcountll: { - Value *ArgValue = EmitScalarExpr(E->getArg(0)); - - llvm::Type *ArgType = ArgValue->getType(); - Value *F = CGM.getIntrinsic(Intrinsic::ctpop, ArgType); - - llvm::Type *ResultType = ConvertType(E->getType()); - Value *Result = Builder.CreateCall(F, ArgValue); - if (Result->getType() != ResultType) - Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, - "cast"); - return RValue::get(Result); - } - case Builtin::BI__builtin_unpredictable: { - // Always return the argument of __builtin_unpredictable. LLVM does not - // handle this builtin. Metadata for this builtin should be added directly - // to instructions such as branches or switches that use it. - return RValue::get(EmitScalarExpr(E->getArg(0))); - } - case Builtin::BI__builtin_expect: { - Value *ArgValue = EmitScalarExpr(E->getArg(0)); - llvm::Type *ArgType = ArgValue->getType(); - - Value *ExpectedValue = EmitScalarExpr(E->getArg(1)); - // Don't generate llvm.expect on -O0 as the backend won't use it for - // anything. - // Note, we still IRGen ExpectedValue because it could have side-effects. - if (CGM.getCodeGenOpts().OptimizationLevel == 0) - return RValue::get(ArgValue); - - Value *FnExpect = CGM.getIntrinsic(Intrinsic::expect, ArgType); - Value *Result = - Builder.CreateCall(FnExpect, {ArgValue, ExpectedValue}, "expval"); - return RValue::get(Result); - } - case Builtin::BI__builtin_assume_aligned: { - const Expr *Ptr = E->getArg(0); - Value *PtrValue = EmitScalarExpr(Ptr); - Value *OffsetValue = - (E->getNumArgs() > 2) ? EmitScalarExpr(E->getArg(2)) : nullptr; - - Value *AlignmentValue = EmitScalarExpr(E->getArg(1)); - ConstantInt *AlignmentCI = cast<ConstantInt>(AlignmentValue); - unsigned Alignment = (unsigned)AlignmentCI->getZExtValue(); - - EmitAlignmentAssumption(PtrValue, Ptr, /*The expr loc is sufficient.*/ SourceLocation(), - Alignment, OffsetValue); - return RValue::get(PtrValue); - } - case Builtin::BI__assume: - case Builtin::BI__builtin_assume: { - if (E->getArg(0)->HasSideEffects(getContext())) - return RValue::get(nullptr); - - Value *ArgValue = EmitScalarExpr(E->getArg(0)); - Value *FnAssume = CGM.getIntrinsic(Intrinsic::assume); - return RValue::get(Builder.CreateCall(FnAssume, ArgValue)); - } - case Builtin::BI__builtin_bswap16: - case Builtin::BI__builtin_bswap32: - case Builtin::BI__builtin_bswap64: { - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::bswap)); - } - case Builtin::BI__builtin_bitreverse8: - case Builtin::BI__builtin_bitreverse16: - case Builtin::BI__builtin_bitreverse32: - case Builtin::BI__builtin_bitreverse64: { - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::bitreverse)); - } - case Builtin::BI__builtin_rotateleft8: - case Builtin::BI__builtin_rotateleft16: - case Builtin::BI__builtin_rotateleft32: - case Builtin::BI__builtin_rotateleft64: - case Builtin::BI_rotl8: // Microsoft variants of rotate left - case Builtin::BI_rotl16: - case Builtin::BI_rotl: - case Builtin::BI_lrotl: - case Builtin::BI_rotl64: - return emitRotate(E, false); - - case Builtin::BI__builtin_rotateright8: - case Builtin::BI__builtin_rotateright16: - case Builtin::BI__builtin_rotateright32: - case Builtin::BI__builtin_rotateright64: - case Builtin::BI_rotr8: // Microsoft variants of rotate right - case Builtin::BI_rotr16: - case Builtin::BI_rotr: - case Builtin::BI_lrotr: - case Builtin::BI_rotr64: - return emitRotate(E, true); - - case Builtin::BI__builtin_constant_p: { - llvm::Type *ResultType = ConvertType(E->getType()); - if (CGM.getCodeGenOpts().OptimizationLevel == 0) - // At -O0, we don't perform inlining, so we don't need to delay the - // processing. - return RValue::get(ConstantInt::get(ResultType, 0)); - - const Expr *Arg = E->getArg(0); - QualType ArgType = Arg->getType(); - if (!hasScalarEvaluationKind(ArgType) || ArgType->isFunctionType()) - // We can only reason about scalar types. - return RValue::get(ConstantInt::get(ResultType, 0)); - - Value *ArgValue = EmitScalarExpr(Arg); - Value *F = CGM.getIntrinsic(Intrinsic::is_constant, ConvertType(ArgType)); - Value *Result = Builder.CreateCall(F, ArgValue); - if (Result->getType() != ResultType) - Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/false); - return RValue::get(Result); - } - case Builtin::BI__builtin_object_size: { - unsigned Type = - E->getArg(1)->EvaluateKnownConstInt(getContext()).getZExtValue(); - auto *ResType = cast<llvm::IntegerType>(ConvertType(E->getType())); - - // We pass this builtin onto the optimizer so that it can figure out the - // object size in more complex cases. - return RValue::get(emitBuiltinObjectSize(E->getArg(0), Type, ResType, - /*EmittedE=*/nullptr)); - } - case Builtin::BI__builtin_prefetch: { - Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0)); - // FIXME: Technically these constants should of type 'int', yes? - RW = (E->getNumArgs() > 1) ? EmitScalarExpr(E->getArg(1)) : - llvm::ConstantInt::get(Int32Ty, 0); - Locality = (E->getNumArgs() > 2) ? EmitScalarExpr(E->getArg(2)) : - llvm::ConstantInt::get(Int32Ty, 3); - Value *Data = llvm::ConstantInt::get(Int32Ty, 1); - Value *F = CGM.getIntrinsic(Intrinsic::prefetch); - return RValue::get(Builder.CreateCall(F, {Address, RW, Locality, Data})); - } - case Builtin::BI__builtin_readcyclecounter: { - Value *F = CGM.getIntrinsic(Intrinsic::readcyclecounter); - return RValue::get(Builder.CreateCall(F)); - } - case Builtin::BI__builtin___clear_cache: { - Value *Begin = EmitScalarExpr(E->getArg(0)); - Value *End = EmitScalarExpr(E->getArg(1)); - Value *F = CGM.getIntrinsic(Intrinsic::clear_cache); - return RValue::get(Builder.CreateCall(F, {Begin, End})); - } - case Builtin::BI__builtin_trap: - return RValue::get(EmitTrapCall(Intrinsic::trap)); - case Builtin::BI__debugbreak: - return RValue::get(EmitTrapCall(Intrinsic::debugtrap)); - case Builtin::BI__builtin_unreachable: { - EmitUnreachable(E->getExprLoc()); - - // We do need to preserve an insertion point. - EmitBlock(createBasicBlock("unreachable.cont")); - - return RValue::get(nullptr); - } - - case Builtin::BI__builtin_powi: - case Builtin::BI__builtin_powif: - case Builtin::BI__builtin_powil: { - Value *Base = EmitScalarExpr(E->getArg(0)); - Value *Exponent = EmitScalarExpr(E->getArg(1)); - llvm::Type *ArgType = Base->getType(); - Value *F = CGM.getIntrinsic(Intrinsic::powi, ArgType); - return RValue::get(Builder.CreateCall(F, {Base, Exponent})); - } - - case Builtin::BI__builtin_isgreater: - case Builtin::BI__builtin_isgreaterequal: - case Builtin::BI__builtin_isless: - case Builtin::BI__builtin_islessequal: - case Builtin::BI__builtin_islessgreater: - case Builtin::BI__builtin_isunordered: { - // Ordered comparisons: we know the arguments to these are matching scalar - // floating point values. - Value *LHS = EmitScalarExpr(E->getArg(0)); - Value *RHS = EmitScalarExpr(E->getArg(1)); - - switch (BuiltinID) { - default: llvm_unreachable("Unknown ordered comparison"); - case Builtin::BI__builtin_isgreater: - LHS = Builder.CreateFCmpOGT(LHS, RHS, "cmp"); - break; - case Builtin::BI__builtin_isgreaterequal: - LHS = Builder.CreateFCmpOGE(LHS, RHS, "cmp"); - break; - case Builtin::BI__builtin_isless: - LHS = Builder.CreateFCmpOLT(LHS, RHS, "cmp"); - break; - case Builtin::BI__builtin_islessequal: - LHS = Builder.CreateFCmpOLE(LHS, RHS, "cmp"); - break; - case Builtin::BI__builtin_islessgreater: - LHS = Builder.CreateFCmpONE(LHS, RHS, "cmp"); - break; - case Builtin::BI__builtin_isunordered: - LHS = Builder.CreateFCmpUNO(LHS, RHS, "cmp"); - break; - } - // ZExt bool to int type. - return RValue::get(Builder.CreateZExt(LHS, ConvertType(E->getType()))); - } - case Builtin::BI__builtin_isnan: { - Value *V = EmitScalarExpr(E->getArg(0)); - V = Builder.CreateFCmpUNO(V, V, "cmp"); - return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType()))); - } - - case Builtin::BIfinite: - case Builtin::BI__finite: - case Builtin::BIfinitef: - case Builtin::BI__finitef: - case Builtin::BIfinitel: - case Builtin::BI__finitel: - case Builtin::BI__builtin_isinf: - case Builtin::BI__builtin_isfinite: { - // isinf(x) --> fabs(x) == infinity - // isfinite(x) --> fabs(x) != infinity - // x != NaN via the ordered compare in either case. - Value *V = EmitScalarExpr(E->getArg(0)); - Value *Fabs = EmitFAbs(*this, V); - Constant *Infinity = ConstantFP::getInfinity(V->getType()); - CmpInst::Predicate Pred = (BuiltinID == Builtin::BI__builtin_isinf) - ? CmpInst::FCMP_OEQ - : CmpInst::FCMP_ONE; - Value *FCmp = Builder.CreateFCmp(Pred, Fabs, Infinity, "cmpinf"); - return RValue::get(Builder.CreateZExt(FCmp, ConvertType(E->getType()))); - } - - case Builtin::BI__builtin_isinf_sign: { - // isinf_sign(x) -> fabs(x) == infinity ? (signbit(x) ? -1 : 1) : 0 - Value *Arg = EmitScalarExpr(E->getArg(0)); - Value *AbsArg = EmitFAbs(*this, Arg); - Value *IsInf = Builder.CreateFCmpOEQ( - AbsArg, ConstantFP::getInfinity(Arg->getType()), "isinf"); - Value *IsNeg = EmitSignBit(*this, Arg); - - llvm::Type *IntTy = ConvertType(E->getType()); - Value *Zero = Constant::getNullValue(IntTy); - Value *One = ConstantInt::get(IntTy, 1); - Value *NegativeOne = ConstantInt::get(IntTy, -1); - Value *SignResult = Builder.CreateSelect(IsNeg, NegativeOne, One); - Value *Result = Builder.CreateSelect(IsInf, SignResult, Zero); - return RValue::get(Result); - } - - case Builtin::BI__builtin_isnormal: { - // isnormal(x) --> x == x && fabsf(x) < infinity && fabsf(x) >= float_min - Value *V = EmitScalarExpr(E->getArg(0)); - Value *Eq = Builder.CreateFCmpOEQ(V, V, "iseq"); - - Value *Abs = EmitFAbs(*this, V); - Value *IsLessThanInf = - Builder.CreateFCmpULT(Abs, ConstantFP::getInfinity(V->getType()),"isinf"); - APFloat Smallest = APFloat::getSmallestNormalized( - getContext().getFloatTypeSemantics(E->getArg(0)->getType())); - Value *IsNormal = - Builder.CreateFCmpUGE(Abs, ConstantFP::get(V->getContext(), Smallest), - "isnormal"); - V = Builder.CreateAnd(Eq, IsLessThanInf, "and"); - V = Builder.CreateAnd(V, IsNormal, "and"); - return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType()))); - } - - case Builtin::BI__builtin_fpclassify: { - Value *V = EmitScalarExpr(E->getArg(5)); - llvm::Type *Ty = ConvertType(E->getArg(5)->getType()); - - // Create Result - BasicBlock *Begin = Builder.GetInsertBlock(); - BasicBlock *End = createBasicBlock("fpclassify_end", this->CurFn); - Builder.SetInsertPoint(End); - PHINode *Result = - Builder.CreatePHI(ConvertType(E->getArg(0)->getType()), 4, - "fpclassify_result"); - - // if (V==0) return FP_ZERO - Builder.SetInsertPoint(Begin); - Value *IsZero = Builder.CreateFCmpOEQ(V, Constant::getNullValue(Ty), - "iszero"); - Value *ZeroLiteral = EmitScalarExpr(E->getArg(4)); - BasicBlock *NotZero = createBasicBlock("fpclassify_not_zero", this->CurFn); - Builder.CreateCondBr(IsZero, End, NotZero); - Result->addIncoming(ZeroLiteral, Begin); - - // if (V != V) return FP_NAN - Builder.SetInsertPoint(NotZero); - Value *IsNan = Builder.CreateFCmpUNO(V, V, "cmp"); - Value *NanLiteral = EmitScalarExpr(E->getArg(0)); - BasicBlock *NotNan = createBasicBlock("fpclassify_not_nan", this->CurFn); - Builder.CreateCondBr(IsNan, End, NotNan); - Result->addIncoming(NanLiteral, NotZero); - - // if (fabs(V) == infinity) return FP_INFINITY - Builder.SetInsertPoint(NotNan); - Value *VAbs = EmitFAbs(*this, V); - Value *IsInf = - Builder.CreateFCmpOEQ(VAbs, ConstantFP::getInfinity(V->getType()), - "isinf"); - Value *InfLiteral = EmitScalarExpr(E->getArg(1)); - BasicBlock *NotInf = createBasicBlock("fpclassify_not_inf", this->CurFn); - Builder.CreateCondBr(IsInf, End, NotInf); - Result->addIncoming(InfLiteral, NotNan); - - // if (fabs(V) >= MIN_NORMAL) return FP_NORMAL else FP_SUBNORMAL - Builder.SetInsertPoint(NotInf); - APFloat Smallest = APFloat::getSmallestNormalized( - getContext().getFloatTypeSemantics(E->getArg(5)->getType())); - Value *IsNormal = - Builder.CreateFCmpUGE(VAbs, ConstantFP::get(V->getContext(), Smallest), - "isnormal"); - Value *NormalResult = - Builder.CreateSelect(IsNormal, EmitScalarExpr(E->getArg(2)), - EmitScalarExpr(E->getArg(3))); - Builder.CreateBr(End); - Result->addIncoming(NormalResult, NotInf); - - // return Result - Builder.SetInsertPoint(End); - return RValue::get(Result); - } - - case Builtin::BIalloca: - case Builtin::BI_alloca: - case Builtin::BI__builtin_alloca: { - Value *Size = EmitScalarExpr(E->getArg(0)); - const TargetInfo &TI = getContext().getTargetInfo(); - // The alignment of the alloca should correspond to __BIGGEST_ALIGNMENT__. - unsigned SuitableAlignmentInBytes = - CGM.getContext() - .toCharUnitsFromBits(TI.getSuitableAlign()) - .getQuantity(); - AllocaInst *AI = Builder.CreateAlloca(Builder.getInt8Ty(), Size); - AI->setAlignment(SuitableAlignmentInBytes); - return RValue::get(AI); - } - - case Builtin::BI__builtin_alloca_with_align: { - Value *Size = EmitScalarExpr(E->getArg(0)); - Value *AlignmentInBitsValue = EmitScalarExpr(E->getArg(1)); - auto *AlignmentInBitsCI = cast<ConstantInt>(AlignmentInBitsValue); - unsigned AlignmentInBits = AlignmentInBitsCI->getZExtValue(); - unsigned AlignmentInBytes = - CGM.getContext().toCharUnitsFromBits(AlignmentInBits).getQuantity(); - AllocaInst *AI = Builder.CreateAlloca(Builder.getInt8Ty(), Size); - AI->setAlignment(AlignmentInBytes); - return RValue::get(AI); - } - - case Builtin::BIbzero: - case Builtin::BI__builtin_bzero: { - Address Dest = EmitPointerWithAlignment(E->getArg(0)); - Value *SizeVal = EmitScalarExpr(E->getArg(1)); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), - E->getArg(0)->getExprLoc(), FD, 0); - Builder.CreateMemSet(Dest, Builder.getInt8(0), SizeVal, false); - return RValue::get(nullptr); - } - case Builtin::BImemcpy: - case Builtin::BI__builtin_memcpy: { - Address Dest = EmitPointerWithAlignment(E->getArg(0)); - Address Src = EmitPointerWithAlignment(E->getArg(1)); - Value *SizeVal = EmitScalarExpr(E->getArg(2)); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), - E->getArg(0)->getExprLoc(), FD, 0); - EmitNonNullArgCheck(RValue::get(Src.getPointer()), E->getArg(1)->getType(), - E->getArg(1)->getExprLoc(), FD, 1); - Builder.CreateMemCpy(Dest, Src, SizeVal, false); - return RValue::get(Dest.getPointer()); - } - - case Builtin::BI__builtin_char_memchr: - BuiltinID = Builtin::BI__builtin_memchr; - break; - - case Builtin::BI__builtin___memcpy_chk: { - // fold __builtin_memcpy_chk(x, y, cst1, cst2) to memcpy iff cst1<=cst2. - Expr::EvalResult SizeResult, DstSizeResult; - if (!E->getArg(2)->EvaluateAsInt(SizeResult, CGM.getContext()) || - !E->getArg(3)->EvaluateAsInt(DstSizeResult, CGM.getContext())) - break; - llvm::APSInt Size = SizeResult.Val.getInt(); - llvm::APSInt DstSize = DstSizeResult.Val.getInt(); - if (Size.ugt(DstSize)) - break; - Address Dest = EmitPointerWithAlignment(E->getArg(0)); - Address Src = EmitPointerWithAlignment(E->getArg(1)); - Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); - Builder.CreateMemCpy(Dest, Src, SizeVal, false); - return RValue::get(Dest.getPointer()); - } - - case Builtin::BI__builtin_objc_memmove_collectable: { - Address DestAddr = EmitPointerWithAlignment(E->getArg(0)); - Address SrcAddr = EmitPointerWithAlignment(E->getArg(1)); - Value *SizeVal = EmitScalarExpr(E->getArg(2)); - CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, - DestAddr, SrcAddr, SizeVal); - return RValue::get(DestAddr.getPointer()); - } - - case Builtin::BI__builtin___memmove_chk: { - // fold __builtin_memmove_chk(x, y, cst1, cst2) to memmove iff cst1<=cst2. - Expr::EvalResult SizeResult, DstSizeResult; - if (!E->getArg(2)->EvaluateAsInt(SizeResult, CGM.getContext()) || - !E->getArg(3)->EvaluateAsInt(DstSizeResult, CGM.getContext())) - break; - llvm::APSInt Size = SizeResult.Val.getInt(); - llvm::APSInt DstSize = DstSizeResult.Val.getInt(); - if (Size.ugt(DstSize)) - break; - Address Dest = EmitPointerWithAlignment(E->getArg(0)); - Address Src = EmitPointerWithAlignment(E->getArg(1)); - Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); - Builder.CreateMemMove(Dest, Src, SizeVal, false); - return RValue::get(Dest.getPointer()); - } - - case Builtin::BImemmove: - case Builtin::BI__builtin_memmove: { - Address Dest = EmitPointerWithAlignment(E->getArg(0)); - Address Src = EmitPointerWithAlignment(E->getArg(1)); - Value *SizeVal = EmitScalarExpr(E->getArg(2)); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), - E->getArg(0)->getExprLoc(), FD, 0); - EmitNonNullArgCheck(RValue::get(Src.getPointer()), E->getArg(1)->getType(), - E->getArg(1)->getExprLoc(), FD, 1); - Builder.CreateMemMove(Dest, Src, SizeVal, false); - return RValue::get(Dest.getPointer()); - } - case Builtin::BImemset: - case Builtin::BI__builtin_memset: { - Address Dest = EmitPointerWithAlignment(E->getArg(0)); - Value *ByteVal = Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), - Builder.getInt8Ty()); - Value *SizeVal = EmitScalarExpr(E->getArg(2)); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), - E->getArg(0)->getExprLoc(), FD, 0); - Builder.CreateMemSet(Dest, ByteVal, SizeVal, false); - return RValue::get(Dest.getPointer()); - } - case Builtin::BI__builtin___memset_chk: { - // fold __builtin_memset_chk(x, y, cst1, cst2) to memset iff cst1<=cst2. - Expr::EvalResult SizeResult, DstSizeResult; - if (!E->getArg(2)->EvaluateAsInt(SizeResult, CGM.getContext()) || - !E->getArg(3)->EvaluateAsInt(DstSizeResult, CGM.getContext())) - break; - llvm::APSInt Size = SizeResult.Val.getInt(); - llvm::APSInt DstSize = DstSizeResult.Val.getInt(); - if (Size.ugt(DstSize)) - break; - Address Dest = EmitPointerWithAlignment(E->getArg(0)); - Value *ByteVal = Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), - Builder.getInt8Ty()); - Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); - Builder.CreateMemSet(Dest, ByteVal, SizeVal, false); - return RValue::get(Dest.getPointer()); - } - case Builtin::BI__builtin_wmemcmp: { - // The MSVC runtime library does not provide a definition of wmemcmp, so we - // need an inline implementation. - if (!getTarget().getTriple().isOSMSVCRT()) - break; - - llvm::Type *WCharTy = ConvertType(getContext().WCharTy); - - Value *Dst = EmitScalarExpr(E->getArg(0)); - Value *Src = EmitScalarExpr(E->getArg(1)); - Value *Size = EmitScalarExpr(E->getArg(2)); - - BasicBlock *Entry = Builder.GetInsertBlock(); - BasicBlock *CmpGT = createBasicBlock("wmemcmp.gt"); - BasicBlock *CmpLT = createBasicBlock("wmemcmp.lt"); - BasicBlock *Next = createBasicBlock("wmemcmp.next"); - BasicBlock *Exit = createBasicBlock("wmemcmp.exit"); - Value *SizeEq0 = Builder.CreateICmpEQ(Size, ConstantInt::get(SizeTy, 0)); - Builder.CreateCondBr(SizeEq0, Exit, CmpGT); - - EmitBlock(CmpGT); - PHINode *DstPhi = Builder.CreatePHI(Dst->getType(), 2); - DstPhi->addIncoming(Dst, Entry); - PHINode *SrcPhi = Builder.CreatePHI(Src->getType(), 2); - SrcPhi->addIncoming(Src, Entry); - PHINode *SizePhi = Builder.CreatePHI(SizeTy, 2); - SizePhi->addIncoming(Size, Entry); - CharUnits WCharAlign = - getContext().getTypeAlignInChars(getContext().WCharTy); - Value *DstCh = Builder.CreateAlignedLoad(WCharTy, DstPhi, WCharAlign); - Value *SrcCh = Builder.CreateAlignedLoad(WCharTy, SrcPhi, WCharAlign); - Value *DstGtSrc = Builder.CreateICmpUGT(DstCh, SrcCh); - Builder.CreateCondBr(DstGtSrc, Exit, CmpLT); - - EmitBlock(CmpLT); - Value *DstLtSrc = Builder.CreateICmpULT(DstCh, SrcCh); - Builder.CreateCondBr(DstLtSrc, Exit, Next); - - EmitBlock(Next); - Value *NextDst = Builder.CreateConstInBoundsGEP1_32(WCharTy, DstPhi, 1); - Value *NextSrc = Builder.CreateConstInBoundsGEP1_32(WCharTy, SrcPhi, 1); - Value *NextSize = Builder.CreateSub(SizePhi, ConstantInt::get(SizeTy, 1)); - Value *NextSizeEq0 = - Builder.CreateICmpEQ(NextSize, ConstantInt::get(SizeTy, 0)); - Builder.CreateCondBr(NextSizeEq0, Exit, CmpGT); - DstPhi->addIncoming(NextDst, Next); - SrcPhi->addIncoming(NextSrc, Next); - SizePhi->addIncoming(NextSize, Next); - - EmitBlock(Exit); - PHINode *Ret = Builder.CreatePHI(IntTy, 4); - Ret->addIncoming(ConstantInt::get(IntTy, 0), Entry); - Ret->addIncoming(ConstantInt::get(IntTy, 1), CmpGT); - Ret->addIncoming(ConstantInt::get(IntTy, -1), CmpLT); - Ret->addIncoming(ConstantInt::get(IntTy, 0), Next); - return RValue::get(Ret); - } - case Builtin::BI__builtin_dwarf_cfa: { - // The offset in bytes from the first argument to the CFA. - // - // Why on earth is this in the frontend? Is there any reason at - // all that the backend can't reasonably determine this while - // lowering llvm.eh.dwarf.cfa()? - // - // TODO: If there's a satisfactory reason, add a target hook for - // this instead of hard-coding 0, which is correct for most targets. - int32_t Offset = 0; - - Value *F = CGM.getIntrinsic(Intrinsic::eh_dwarf_cfa); - return RValue::get(Builder.CreateCall(F, - llvm::ConstantInt::get(Int32Ty, Offset))); - } - case Builtin::BI__builtin_return_address: { - Value *Depth = ConstantEmitter(*this).emitAbstract(E->getArg(0), - getContext().UnsignedIntTy); - Value *F = CGM.getIntrinsic(Intrinsic::returnaddress); - return RValue::get(Builder.CreateCall(F, Depth)); - } - case Builtin::BI_ReturnAddress: { - Value *F = CGM.getIntrinsic(Intrinsic::returnaddress); - return RValue::get(Builder.CreateCall(F, Builder.getInt32(0))); - } - case Builtin::BI__builtin_frame_address: { - Value *Depth = ConstantEmitter(*this).emitAbstract(E->getArg(0), - getContext().UnsignedIntTy); - Value *F = CGM.getIntrinsic(Intrinsic::frameaddress); - return RValue::get(Builder.CreateCall(F, Depth)); - } - case Builtin::BI__builtin_extract_return_addr: { - Value *Address = EmitScalarExpr(E->getArg(0)); - Value *Result = getTargetHooks().decodeReturnAddress(*this, Address); - return RValue::get(Result); - } - case Builtin::BI__builtin_frob_return_addr: { - Value *Address = EmitScalarExpr(E->getArg(0)); - Value *Result = getTargetHooks().encodeReturnAddress(*this, Address); - return RValue::get(Result); - } - case Builtin::BI__builtin_dwarf_sp_column: { - llvm::IntegerType *Ty - = cast<llvm::IntegerType>(ConvertType(E->getType())); - int Column = getTargetHooks().getDwarfEHStackPointer(CGM); - if (Column == -1) { - CGM.ErrorUnsupported(E, "__builtin_dwarf_sp_column"); - return RValue::get(llvm::UndefValue::get(Ty)); - } - return RValue::get(llvm::ConstantInt::get(Ty, Column, true)); - } - case Builtin::BI__builtin_init_dwarf_reg_size_table: { - Value *Address = EmitScalarExpr(E->getArg(0)); - if (getTargetHooks().initDwarfEHRegSizeTable(*this, Address)) - CGM.ErrorUnsupported(E, "__builtin_init_dwarf_reg_size_table"); - return RValue::get(llvm::UndefValue::get(ConvertType(E->getType()))); - } - case Builtin::BI__builtin_eh_return: { - Value *Int = EmitScalarExpr(E->getArg(0)); - Value *Ptr = EmitScalarExpr(E->getArg(1)); - - llvm::IntegerType *IntTy = cast<llvm::IntegerType>(Int->getType()); - assert((IntTy->getBitWidth() == 32 || IntTy->getBitWidth() == 64) && - "LLVM's __builtin_eh_return only supports 32- and 64-bit variants"); - Value *F = CGM.getIntrinsic(IntTy->getBitWidth() == 32 - ? Intrinsic::eh_return_i32 - : Intrinsic::eh_return_i64); - Builder.CreateCall(F, {Int, Ptr}); - Builder.CreateUnreachable(); - - // We do need to preserve an insertion point. - EmitBlock(createBasicBlock("builtin_eh_return.cont")); - - return RValue::get(nullptr); - } - case Builtin::BI__builtin_unwind_init: { - Value *F = CGM.getIntrinsic(Intrinsic::eh_unwind_init); - return RValue::get(Builder.CreateCall(F)); - } - case Builtin::BI__builtin_extend_pointer: { - // Extends a pointer to the size of an _Unwind_Word, which is - // uint64_t on all platforms. Generally this gets poked into a - // register and eventually used as an address, so if the - // addressing registers are wider than pointers and the platform - // doesn't implicitly ignore high-order bits when doing - // addressing, we need to make sure we zext / sext based on - // the platform's expectations. - // - // See: http://gcc.gnu.org/ml/gcc-bugs/2002-02/msg00237.html - - // Cast the pointer to intptr_t. - Value *Ptr = EmitScalarExpr(E->getArg(0)); - Value *Result = Builder.CreatePtrToInt(Ptr, IntPtrTy, "extend.cast"); - - // If that's 64 bits, we're done. - if (IntPtrTy->getBitWidth() == 64) - return RValue::get(Result); - - // Otherwise, ask the codegen data what to do. - if (getTargetHooks().extendPointerWithSExt()) - return RValue::get(Builder.CreateSExt(Result, Int64Ty, "extend.sext")); - else - return RValue::get(Builder.CreateZExt(Result, Int64Ty, "extend.zext")); - } - case Builtin::BI__builtin_setjmp: { - // Buffer is a void**. - Address Buf = EmitPointerWithAlignment(E->getArg(0)); - - // Store the frame pointer to the setjmp buffer. - Value *FrameAddr = - Builder.CreateCall(CGM.getIntrinsic(Intrinsic::frameaddress), - ConstantInt::get(Int32Ty, 0)); - Builder.CreateStore(FrameAddr, Buf); - - // Store the stack pointer to the setjmp buffer. - Value *StackAddr = - Builder.CreateCall(CGM.getIntrinsic(Intrinsic::stacksave)); - Address StackSaveSlot = - Builder.CreateConstInBoundsGEP(Buf, 2, getPointerSize()); - Builder.CreateStore(StackAddr, StackSaveSlot); - - // Call LLVM's EH setjmp, which is lightweight. - Value *F = CGM.getIntrinsic(Intrinsic::eh_sjlj_setjmp); - Buf = Builder.CreateBitCast(Buf, Int8PtrTy); - return RValue::get(Builder.CreateCall(F, Buf.getPointer())); - } - case Builtin::BI__builtin_longjmp: { - Value *Buf = EmitScalarExpr(E->getArg(0)); - Buf = Builder.CreateBitCast(Buf, Int8PtrTy); - - // Call LLVM's EH longjmp, which is lightweight. - Builder.CreateCall(CGM.getIntrinsic(Intrinsic::eh_sjlj_longjmp), Buf); - - // longjmp doesn't return; mark this as unreachable. - Builder.CreateUnreachable(); - - // We do need to preserve an insertion point. - EmitBlock(createBasicBlock("longjmp.cont")); - - return RValue::get(nullptr); - } - case Builtin::BI__builtin_launder: { - const Expr *Arg = E->getArg(0); - QualType ArgTy = Arg->getType()->getPointeeType(); - Value *Ptr = EmitScalarExpr(Arg); - if (TypeRequiresBuiltinLaunder(CGM, ArgTy)) - Ptr = Builder.CreateLaunderInvariantGroup(Ptr); - - return RValue::get(Ptr); - } - case Builtin::BI__sync_fetch_and_add: - case Builtin::BI__sync_fetch_and_sub: - case Builtin::BI__sync_fetch_and_or: - case Builtin::BI__sync_fetch_and_and: - case Builtin::BI__sync_fetch_and_xor: - case Builtin::BI__sync_fetch_and_nand: - case Builtin::BI__sync_add_and_fetch: - case Builtin::BI__sync_sub_and_fetch: - case Builtin::BI__sync_and_and_fetch: - case Builtin::BI__sync_or_and_fetch: - case Builtin::BI__sync_xor_and_fetch: - case Builtin::BI__sync_nand_and_fetch: - case Builtin::BI__sync_val_compare_and_swap: - case Builtin::BI__sync_bool_compare_and_swap: - case Builtin::BI__sync_lock_test_and_set: - case Builtin::BI__sync_lock_release: - case Builtin::BI__sync_swap: - llvm_unreachable("Shouldn't make it through sema"); - case Builtin::BI__sync_fetch_and_add_1: - case Builtin::BI__sync_fetch_and_add_2: - case Builtin::BI__sync_fetch_and_add_4: - case Builtin::BI__sync_fetch_and_add_8: - case Builtin::BI__sync_fetch_and_add_16: - return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Add, E); - case Builtin::BI__sync_fetch_and_sub_1: - case Builtin::BI__sync_fetch_and_sub_2: - case Builtin::BI__sync_fetch_and_sub_4: - case Builtin::BI__sync_fetch_and_sub_8: - case Builtin::BI__sync_fetch_and_sub_16: - return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Sub, E); - case Builtin::BI__sync_fetch_and_or_1: - case Builtin::BI__sync_fetch_and_or_2: - case Builtin::BI__sync_fetch_and_or_4: - case Builtin::BI__sync_fetch_and_or_8: - case Builtin::BI__sync_fetch_and_or_16: - return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Or, E); - case Builtin::BI__sync_fetch_and_and_1: - case Builtin::BI__sync_fetch_and_and_2: - case Builtin::BI__sync_fetch_and_and_4: - case Builtin::BI__sync_fetch_and_and_8: - case Builtin::BI__sync_fetch_and_and_16: - return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::And, E); - case Builtin::BI__sync_fetch_and_xor_1: - case Builtin::BI__sync_fetch_and_xor_2: - case Builtin::BI__sync_fetch_and_xor_4: - case Builtin::BI__sync_fetch_and_xor_8: - case Builtin::BI__sync_fetch_and_xor_16: - return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Xor, E); - case Builtin::BI__sync_fetch_and_nand_1: - case Builtin::BI__sync_fetch_and_nand_2: - case Builtin::BI__sync_fetch_and_nand_4: - case Builtin::BI__sync_fetch_and_nand_8: - case Builtin::BI__sync_fetch_and_nand_16: - return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Nand, E); - - // Clang extensions: not overloaded yet. - case Builtin::BI__sync_fetch_and_min: - return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Min, E); - case Builtin::BI__sync_fetch_and_max: - return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Max, E); - case Builtin::BI__sync_fetch_and_umin: - return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::UMin, E); - case Builtin::BI__sync_fetch_and_umax: - return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::UMax, E); - - case Builtin::BI__sync_add_and_fetch_1: - case Builtin::BI__sync_add_and_fetch_2: - case Builtin::BI__sync_add_and_fetch_4: - case Builtin::BI__sync_add_and_fetch_8: - case Builtin::BI__sync_add_and_fetch_16: - return EmitBinaryAtomicPost(*this, llvm::AtomicRMWInst::Add, E, - llvm::Instruction::Add); - case Builtin::BI__sync_sub_and_fetch_1: - case Builtin::BI__sync_sub_and_fetch_2: - case Builtin::BI__sync_sub_and_fetch_4: - case Builtin::BI__sync_sub_and_fetch_8: - case Builtin::BI__sync_sub_and_fetch_16: - return EmitBinaryAtomicPost(*this, llvm::AtomicRMWInst::Sub, E, - llvm::Instruction::Sub); - case Builtin::BI__sync_and_and_fetch_1: - case Builtin::BI__sync_and_and_fetch_2: - case Builtin::BI__sync_and_and_fetch_4: - case Builtin::BI__sync_and_and_fetch_8: - case Builtin::BI__sync_and_and_fetch_16: - return EmitBinaryAtomicPost(*this, llvm::AtomicRMWInst::And, E, - llvm::Instruction::And); - case Builtin::BI__sync_or_and_fetch_1: - case Builtin::BI__sync_or_and_fetch_2: - case Builtin::BI__sync_or_and_fetch_4: - case Builtin::BI__sync_or_and_fetch_8: - case Builtin::BI__sync_or_and_fetch_16: - return EmitBinaryAtomicPost(*this, llvm::AtomicRMWInst::Or, E, - llvm::Instruction::Or); - case Builtin::BI__sync_xor_and_fetch_1: - case Builtin::BI__sync_xor_and_fetch_2: - case Builtin::BI__sync_xor_and_fetch_4: - case Builtin::BI__sync_xor_and_fetch_8: - case Builtin::BI__sync_xor_and_fetch_16: - return EmitBinaryAtomicPost(*this, llvm::AtomicRMWInst::Xor, E, - llvm::Instruction::Xor); - case Builtin::BI__sync_nand_and_fetch_1: - case Builtin::BI__sync_nand_and_fetch_2: - case Builtin::BI__sync_nand_and_fetch_4: - case Builtin::BI__sync_nand_and_fetch_8: - case Builtin::BI__sync_nand_and_fetch_16: - return EmitBinaryAtomicPost(*this, llvm::AtomicRMWInst::Nand, E, - llvm::Instruction::And, true); - - case Builtin::BI__sync_val_compare_and_swap_1: - case Builtin::BI__sync_val_compare_and_swap_2: - case Builtin::BI__sync_val_compare_and_swap_4: - case Builtin::BI__sync_val_compare_and_swap_8: - case Builtin::BI__sync_val_compare_and_swap_16: - return RValue::get(MakeAtomicCmpXchgValue(*this, E, false)); - - case Builtin::BI__sync_bool_compare_and_swap_1: - case Builtin::BI__sync_bool_compare_and_swap_2: - case Builtin::BI__sync_bool_compare_and_swap_4: - case Builtin::BI__sync_bool_compare_and_swap_8: - case Builtin::BI__sync_bool_compare_and_swap_16: - return RValue::get(MakeAtomicCmpXchgValue(*this, E, true)); - - case Builtin::BI__sync_swap_1: - case Builtin::BI__sync_swap_2: - case Builtin::BI__sync_swap_4: - case Builtin::BI__sync_swap_8: - case Builtin::BI__sync_swap_16: - return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Xchg, E); - - case Builtin::BI__sync_lock_test_and_set_1: - case Builtin::BI__sync_lock_test_and_set_2: - case Builtin::BI__sync_lock_test_and_set_4: - case Builtin::BI__sync_lock_test_and_set_8: - case Builtin::BI__sync_lock_test_and_set_16: - return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Xchg, E); - - case Builtin::BI__sync_lock_release_1: - case Builtin::BI__sync_lock_release_2: - case Builtin::BI__sync_lock_release_4: - case Builtin::BI__sync_lock_release_8: - case Builtin::BI__sync_lock_release_16: { - Value *Ptr = EmitScalarExpr(E->getArg(0)); - QualType ElTy = E->getArg(0)->getType()->getPointeeType(); - CharUnits StoreSize = getContext().getTypeSizeInChars(ElTy); - llvm::Type *ITy = llvm::IntegerType::get(getLLVMContext(), - StoreSize.getQuantity() * 8); - Ptr = Builder.CreateBitCast(Ptr, ITy->getPointerTo()); - llvm::StoreInst *Store = - Builder.CreateAlignedStore(llvm::Constant::getNullValue(ITy), Ptr, - StoreSize); - Store->setAtomic(llvm::AtomicOrdering::Release); - return RValue::get(nullptr); - } - - case Builtin::BI__sync_synchronize: { - // We assume this is supposed to correspond to a C++0x-style - // sequentially-consistent fence (i.e. this is only usable for - // synchronization, not device I/O or anything like that). This intrinsic - // is really badly designed in the sense that in theory, there isn't - // any way to safely use it... but in practice, it mostly works - // to use it with non-atomic loads and stores to get acquire/release - // semantics. - Builder.CreateFence(llvm::AtomicOrdering::SequentiallyConsistent); - return RValue::get(nullptr); - } - - case Builtin::BI__builtin_nontemporal_load: - return RValue::get(EmitNontemporalLoad(*this, E)); - case Builtin::BI__builtin_nontemporal_store: - return RValue::get(EmitNontemporalStore(*this, E)); - case Builtin::BI__c11_atomic_is_lock_free: - case Builtin::BI__atomic_is_lock_free: { - // Call "bool __atomic_is_lock_free(size_t size, void *ptr)". For the - // __c11 builtin, ptr is 0 (indicating a properly-aligned object), since - // _Atomic(T) is always properly-aligned. - const char *LibCallName = "__atomic_is_lock_free"; - CallArgList Args; - Args.add(RValue::get(EmitScalarExpr(E->getArg(0))), - getContext().getSizeType()); - if (BuiltinID == Builtin::BI__atomic_is_lock_free) - Args.add(RValue::get(EmitScalarExpr(E->getArg(1))), - getContext().VoidPtrTy); - else - Args.add(RValue::get(llvm::Constant::getNullValue(VoidPtrTy)), - getContext().VoidPtrTy); - const CGFunctionInfo &FuncInfo = - CGM.getTypes().arrangeBuiltinFunctionCall(E->getType(), Args); - llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FuncInfo); - llvm::Constant *Func = CGM.CreateRuntimeFunction(FTy, LibCallName); - return EmitCall(FuncInfo, CGCallee::forDirect(Func), - ReturnValueSlot(), Args); - } - - case Builtin::BI__atomic_test_and_set: { - // Look at the argument type to determine whether this is a volatile - // operation. The parameter type is always volatile. - QualType PtrTy = E->getArg(0)->IgnoreImpCasts()->getType(); - bool Volatile = - PtrTy->castAs<PointerType>()->getPointeeType().isVolatileQualified(); - - Value *Ptr = EmitScalarExpr(E->getArg(0)); - unsigned AddrSpace = Ptr->getType()->getPointerAddressSpace(); - Ptr = Builder.CreateBitCast(Ptr, Int8Ty->getPointerTo(AddrSpace)); - Value *NewVal = Builder.getInt8(1); - Value *Order = EmitScalarExpr(E->getArg(1)); - if (isa<llvm::ConstantInt>(Order)) { - int ord = cast<llvm::ConstantInt>(Order)->getZExtValue(); - AtomicRMWInst *Result = nullptr; - switch (ord) { - case 0: // memory_order_relaxed - default: // invalid order - Result = Builder.CreateAtomicRMW(llvm::AtomicRMWInst::Xchg, Ptr, NewVal, - llvm::AtomicOrdering::Monotonic); - break; - case 1: // memory_order_consume - case 2: // memory_order_acquire - Result = Builder.CreateAtomicRMW(llvm::AtomicRMWInst::Xchg, Ptr, NewVal, - llvm::AtomicOrdering::Acquire); - break; - case 3: // memory_order_release - Result = Builder.CreateAtomicRMW(llvm::AtomicRMWInst::Xchg, Ptr, NewVal, - llvm::AtomicOrdering::Release); - break; - case 4: // memory_order_acq_rel - - Result = Builder.CreateAtomicRMW(llvm::AtomicRMWInst::Xchg, Ptr, NewVal, - llvm::AtomicOrdering::AcquireRelease); - break; - case 5: // memory_order_seq_cst - Result = Builder.CreateAtomicRMW( - llvm::AtomicRMWInst::Xchg, Ptr, NewVal, - llvm::AtomicOrdering::SequentiallyConsistent); - break; - } - Result->setVolatile(Volatile); - return RValue::get(Builder.CreateIsNotNull(Result, "tobool")); - } - - llvm::BasicBlock *ContBB = createBasicBlock("atomic.continue", CurFn); - - llvm::BasicBlock *BBs[5] = { - createBasicBlock("monotonic", CurFn), - createBasicBlock("acquire", CurFn), - createBasicBlock("release", CurFn), - createBasicBlock("acqrel", CurFn), - createBasicBlock("seqcst", CurFn) - }; - llvm::AtomicOrdering Orders[5] = { - llvm::AtomicOrdering::Monotonic, llvm::AtomicOrdering::Acquire, - llvm::AtomicOrdering::Release, llvm::AtomicOrdering::AcquireRelease, - llvm::AtomicOrdering::SequentiallyConsistent}; - - Order = Builder.CreateIntCast(Order, Builder.getInt32Ty(), false); - llvm::SwitchInst *SI = Builder.CreateSwitch(Order, BBs[0]); - - Builder.SetInsertPoint(ContBB); - PHINode *Result = Builder.CreatePHI(Int8Ty, 5, "was_set"); - - for (unsigned i = 0; i < 5; ++i) { - Builder.SetInsertPoint(BBs[i]); - AtomicRMWInst *RMW = Builder.CreateAtomicRMW(llvm::AtomicRMWInst::Xchg, - Ptr, NewVal, Orders[i]); - RMW->setVolatile(Volatile); - Result->addIncoming(RMW, BBs[i]); - Builder.CreateBr(ContBB); - } - - SI->addCase(Builder.getInt32(0), BBs[0]); - SI->addCase(Builder.getInt32(1), BBs[1]); - SI->addCase(Builder.getInt32(2), BBs[1]); - SI->addCase(Builder.getInt32(3), BBs[2]); - SI->addCase(Builder.getInt32(4), BBs[3]); - SI->addCase(Builder.getInt32(5), BBs[4]); - - Builder.SetInsertPoint(ContBB); - return RValue::get(Builder.CreateIsNotNull(Result, "tobool")); - } - - case Builtin::BI__atomic_clear: { - QualType PtrTy = E->getArg(0)->IgnoreImpCasts()->getType(); - bool Volatile = - PtrTy->castAs<PointerType>()->getPointeeType().isVolatileQualified(); - - Address Ptr = EmitPointerWithAlignment(E->getArg(0)); - unsigned AddrSpace = Ptr.getPointer()->getType()->getPointerAddressSpace(); - Ptr = Builder.CreateBitCast(Ptr, Int8Ty->getPointerTo(AddrSpace)); - Value *NewVal = Builder.getInt8(0); - Value *Order = EmitScalarExpr(E->getArg(1)); - if (isa<llvm::ConstantInt>(Order)) { - int ord = cast<llvm::ConstantInt>(Order)->getZExtValue(); - StoreInst *Store = Builder.CreateStore(NewVal, Ptr, Volatile); - switch (ord) { - case 0: // memory_order_relaxed - default: // invalid order - Store->setOrdering(llvm::AtomicOrdering::Monotonic); - break; - case 3: // memory_order_release - Store->setOrdering(llvm::AtomicOrdering::Release); - break; - case 5: // memory_order_seq_cst - Store->setOrdering(llvm::AtomicOrdering::SequentiallyConsistent); - break; - } - return RValue::get(nullptr); - } - - llvm::BasicBlock *ContBB = createBasicBlock("atomic.continue", CurFn); - - llvm::BasicBlock *BBs[3] = { - createBasicBlock("monotonic", CurFn), - createBasicBlock("release", CurFn), - createBasicBlock("seqcst", CurFn) - }; - llvm::AtomicOrdering Orders[3] = { - llvm::AtomicOrdering::Monotonic, llvm::AtomicOrdering::Release, - llvm::AtomicOrdering::SequentiallyConsistent}; - - Order = Builder.CreateIntCast(Order, Builder.getInt32Ty(), false); - llvm::SwitchInst *SI = Builder.CreateSwitch(Order, BBs[0]); - - for (unsigned i = 0; i < 3; ++i) { - Builder.SetInsertPoint(BBs[i]); - StoreInst *Store = Builder.CreateStore(NewVal, Ptr, Volatile); - Store->setOrdering(Orders[i]); - Builder.CreateBr(ContBB); - } - - SI->addCase(Builder.getInt32(0), BBs[0]); - SI->addCase(Builder.getInt32(3), BBs[1]); - SI->addCase(Builder.getInt32(5), BBs[2]); - - Builder.SetInsertPoint(ContBB); - return RValue::get(nullptr); - } - - case Builtin::BI__atomic_thread_fence: - case Builtin::BI__atomic_signal_fence: - case Builtin::BI__c11_atomic_thread_fence: - case Builtin::BI__c11_atomic_signal_fence: { - llvm::SyncScope::ID SSID; - if (BuiltinID == Builtin::BI__atomic_signal_fence || - BuiltinID == Builtin::BI__c11_atomic_signal_fence) - SSID = llvm::SyncScope::SingleThread; - else - SSID = llvm::SyncScope::System; - Value *Order = EmitScalarExpr(E->getArg(0)); - if (isa<llvm::ConstantInt>(Order)) { - int ord = cast<llvm::ConstantInt>(Order)->getZExtValue(); - switch (ord) { - case 0: // memory_order_relaxed - default: // invalid order - break; - case 1: // memory_order_consume - case 2: // memory_order_acquire - Builder.CreateFence(llvm::AtomicOrdering::Acquire, SSID); - break; - case 3: // memory_order_release - Builder.CreateFence(llvm::AtomicOrdering::Release, SSID); - break; - case 4: // memory_order_acq_rel - Builder.CreateFence(llvm::AtomicOrdering::AcquireRelease, SSID); - break; - case 5: // memory_order_seq_cst - Builder.CreateFence(llvm::AtomicOrdering::SequentiallyConsistent, SSID); - break; - } - return RValue::get(nullptr); - } - - llvm::BasicBlock *AcquireBB, *ReleaseBB, *AcqRelBB, *SeqCstBB; - AcquireBB = createBasicBlock("acquire", CurFn); - ReleaseBB = createBasicBlock("release", CurFn); - AcqRelBB = createBasicBlock("acqrel", CurFn); - SeqCstBB = createBasicBlock("seqcst", CurFn); - llvm::BasicBlock *ContBB = createBasicBlock("atomic.continue", CurFn); - - Order = Builder.CreateIntCast(Order, Builder.getInt32Ty(), false); - llvm::SwitchInst *SI = Builder.CreateSwitch(Order, ContBB); - - Builder.SetInsertPoint(AcquireBB); - Builder.CreateFence(llvm::AtomicOrdering::Acquire, SSID); - Builder.CreateBr(ContBB); - SI->addCase(Builder.getInt32(1), AcquireBB); - SI->addCase(Builder.getInt32(2), AcquireBB); - - Builder.SetInsertPoint(ReleaseBB); - Builder.CreateFence(llvm::AtomicOrdering::Release, SSID); - Builder.CreateBr(ContBB); - SI->addCase(Builder.getInt32(3), ReleaseBB); - - Builder.SetInsertPoint(AcqRelBB); - Builder.CreateFence(llvm::AtomicOrdering::AcquireRelease, SSID); - Builder.CreateBr(ContBB); - SI->addCase(Builder.getInt32(4), AcqRelBB); - - Builder.SetInsertPoint(SeqCstBB); - Builder.CreateFence(llvm::AtomicOrdering::SequentiallyConsistent, SSID); - Builder.CreateBr(ContBB); - SI->addCase(Builder.getInt32(5), SeqCstBB); - - Builder.SetInsertPoint(ContBB); - return RValue::get(nullptr); - } - - case Builtin::BI__builtin_signbit: - case Builtin::BI__builtin_signbitf: - case Builtin::BI__builtin_signbitl: { - return RValue::get( - Builder.CreateZExt(EmitSignBit(*this, EmitScalarExpr(E->getArg(0))), - ConvertType(E->getType()))); - } - case Builtin::BI__annotation: { - // Re-encode each wide string to UTF8 and make an MDString. - SmallVector<Metadata *, 1> Strings; - for (const Expr *Arg : E->arguments()) { - const auto *Str = cast<StringLiteral>(Arg->IgnoreParenCasts()); - assert(Str->getCharByteWidth() == 2); - StringRef WideBytes = Str->getBytes(); - std::string StrUtf8; - if (!convertUTF16ToUTF8String( - makeArrayRef(WideBytes.data(), WideBytes.size()), StrUtf8)) { - CGM.ErrorUnsupported(E, "non-UTF16 __annotation argument"); - continue; - } - Strings.push_back(llvm::MDString::get(getLLVMContext(), StrUtf8)); - } - - // Build and MDTuple of MDStrings and emit the intrinsic call. - llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::codeview_annotation, {}); - MDTuple *StrTuple = MDTuple::get(getLLVMContext(), Strings); - Builder.CreateCall(F, MetadataAsValue::get(getLLVMContext(), StrTuple)); - return RValue::getIgnored(); - } - case Builtin::BI__builtin_annotation: { - llvm::Value *AnnVal = EmitScalarExpr(E->getArg(0)); - llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::annotation, - AnnVal->getType()); - - // Get the annotation string, go through casts. Sema requires this to be a - // non-wide string literal, potentially casted, so the cast<> is safe. - const Expr *AnnotationStrExpr = E->getArg(1)->IgnoreParenCasts(); - StringRef Str = cast<StringLiteral>(AnnotationStrExpr)->getString(); - return RValue::get(EmitAnnotationCall(F, AnnVal, Str, E->getExprLoc())); - } - case Builtin::BI__builtin_addcb: - case Builtin::BI__builtin_addcs: - case Builtin::BI__builtin_addc: - case Builtin::BI__builtin_addcl: - case Builtin::BI__builtin_addcll: - case Builtin::BI__builtin_subcb: - case Builtin::BI__builtin_subcs: - case Builtin::BI__builtin_subc: - case Builtin::BI__builtin_subcl: - case Builtin::BI__builtin_subcll: { - - // We translate all of these builtins from expressions of the form: - // int x = ..., y = ..., carryin = ..., carryout, result; - // result = __builtin_addc(x, y, carryin, &carryout); - // - // to LLVM IR of the form: - // - // %tmp1 = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %x, i32 %y) - // %tmpsum1 = extractvalue {i32, i1} %tmp1, 0 - // %carry1 = extractvalue {i32, i1} %tmp1, 1 - // %tmp2 = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %tmpsum1, - // i32 %carryin) - // %result = extractvalue {i32, i1} %tmp2, 0 - // %carry2 = extractvalue {i32, i1} %tmp2, 1 - // %tmp3 = or i1 %carry1, %carry2 - // %tmp4 = zext i1 %tmp3 to i32 - // store i32 %tmp4, i32* %carryout - - // Scalarize our inputs. - llvm::Value *X = EmitScalarExpr(E->getArg(0)); - llvm::Value *Y = EmitScalarExpr(E->getArg(1)); - llvm::Value *Carryin = EmitScalarExpr(E->getArg(2)); - Address CarryOutPtr = EmitPointerWithAlignment(E->getArg(3)); - - // Decide if we are lowering to a uadd.with.overflow or usub.with.overflow. - llvm::Intrinsic::ID IntrinsicId; - switch (BuiltinID) { - default: llvm_unreachable("Unknown multiprecision builtin id."); - case Builtin::BI__builtin_addcb: - case Builtin::BI__builtin_addcs: - case Builtin::BI__builtin_addc: - case Builtin::BI__builtin_addcl: - case Builtin::BI__builtin_addcll: - IntrinsicId = llvm::Intrinsic::uadd_with_overflow; - break; - case Builtin::BI__builtin_subcb: - case Builtin::BI__builtin_subcs: - case Builtin::BI__builtin_subc: - case Builtin::BI__builtin_subcl: - case Builtin::BI__builtin_subcll: - IntrinsicId = llvm::Intrinsic::usub_with_overflow; - break; - } - - // Construct our resulting LLVM IR expression. - llvm::Value *Carry1; - llvm::Value *Sum1 = EmitOverflowIntrinsic(*this, IntrinsicId, - X, Y, Carry1); - llvm::Value *Carry2; - llvm::Value *Sum2 = EmitOverflowIntrinsic(*this, IntrinsicId, - Sum1, Carryin, Carry2); - llvm::Value *CarryOut = Builder.CreateZExt(Builder.CreateOr(Carry1, Carry2), - X->getType()); - Builder.CreateStore(CarryOut, CarryOutPtr); - return RValue::get(Sum2); - } - - case Builtin::BI__builtin_add_overflow: - case Builtin::BI__builtin_sub_overflow: - case Builtin::BI__builtin_mul_overflow: { - const clang::Expr *LeftArg = E->getArg(0); - const clang::Expr *RightArg = E->getArg(1); - const clang::Expr *ResultArg = E->getArg(2); - - clang::QualType ResultQTy = - ResultArg->getType()->castAs<PointerType>()->getPointeeType(); - - WidthAndSignedness LeftInfo = - getIntegerWidthAndSignedness(CGM.getContext(), LeftArg->getType()); - WidthAndSignedness RightInfo = - getIntegerWidthAndSignedness(CGM.getContext(), RightArg->getType()); - WidthAndSignedness ResultInfo = - getIntegerWidthAndSignedness(CGM.getContext(), ResultQTy); - - // Handle mixed-sign multiplication as a special case, because adding - // runtime or backend support for our generic irgen would be too expensive. - if (isSpecialMixedSignMultiply(BuiltinID, LeftInfo, RightInfo, ResultInfo)) - return EmitCheckedMixedSignMultiply(*this, LeftArg, LeftInfo, RightArg, - RightInfo, ResultArg, ResultQTy, - ResultInfo); - - WidthAndSignedness EncompassingInfo = - EncompassingIntegerType({LeftInfo, RightInfo, ResultInfo}); - - llvm::Type *EncompassingLLVMTy = - llvm::IntegerType::get(CGM.getLLVMContext(), EncompassingInfo.Width); - - llvm::Type *ResultLLVMTy = CGM.getTypes().ConvertType(ResultQTy); - - llvm::Intrinsic::ID IntrinsicId; - switch (BuiltinID) { - default: - llvm_unreachable("Unknown overflow builtin id."); - case Builtin::BI__builtin_add_overflow: - IntrinsicId = EncompassingInfo.Signed - ? llvm::Intrinsic::sadd_with_overflow - : llvm::Intrinsic::uadd_with_overflow; - break; - case Builtin::BI__builtin_sub_overflow: - IntrinsicId = EncompassingInfo.Signed - ? llvm::Intrinsic::ssub_with_overflow - : llvm::Intrinsic::usub_with_overflow; - break; - case Builtin::BI__builtin_mul_overflow: - IntrinsicId = EncompassingInfo.Signed - ? llvm::Intrinsic::smul_with_overflow - : llvm::Intrinsic::umul_with_overflow; - break; - } - - llvm::Value *Left = EmitScalarExpr(LeftArg); - llvm::Value *Right = EmitScalarExpr(RightArg); - Address ResultPtr = EmitPointerWithAlignment(ResultArg); - - // Extend each operand to the encompassing type. - Left = Builder.CreateIntCast(Left, EncompassingLLVMTy, LeftInfo.Signed); - Right = Builder.CreateIntCast(Right, EncompassingLLVMTy, RightInfo.Signed); - - // Perform the operation on the extended values. - llvm::Value *Overflow, *Result; - Result = EmitOverflowIntrinsic(*this, IntrinsicId, Left, Right, Overflow); - - if (EncompassingInfo.Width > ResultInfo.Width) { - // The encompassing type is wider than the result type, so we need to - // truncate it. - llvm::Value *ResultTrunc = Builder.CreateTrunc(Result, ResultLLVMTy); - - // To see if the truncation caused an overflow, we will extend - // the result and then compare it to the original result. - llvm::Value *ResultTruncExt = Builder.CreateIntCast( - ResultTrunc, EncompassingLLVMTy, ResultInfo.Signed); - llvm::Value *TruncationOverflow = - Builder.CreateICmpNE(Result, ResultTruncExt); - - Overflow = Builder.CreateOr(Overflow, TruncationOverflow); - Result = ResultTrunc; - } - - // Finally, store the result using the pointer. - bool isVolatile = - ResultArg->getType()->getPointeeType().isVolatileQualified(); - Builder.CreateStore(EmitToMemory(Result, ResultQTy), ResultPtr, isVolatile); - - return RValue::get(Overflow); - } - - case Builtin::BI__builtin_uadd_overflow: - case Builtin::BI__builtin_uaddl_overflow: - case Builtin::BI__builtin_uaddll_overflow: - case Builtin::BI__builtin_usub_overflow: - case Builtin::BI__builtin_usubl_overflow: - case Builtin::BI__builtin_usubll_overflow: - case Builtin::BI__builtin_umul_overflow: - case Builtin::BI__builtin_umull_overflow: - case Builtin::BI__builtin_umulll_overflow: - case Builtin::BI__builtin_sadd_overflow: - case Builtin::BI__builtin_saddl_overflow: - case Builtin::BI__builtin_saddll_overflow: - case Builtin::BI__builtin_ssub_overflow: - case Builtin::BI__builtin_ssubl_overflow: - case Builtin::BI__builtin_ssubll_overflow: - case Builtin::BI__builtin_smul_overflow: - case Builtin::BI__builtin_smull_overflow: - case Builtin::BI__builtin_smulll_overflow: { - - // We translate all of these builtins directly to the relevant llvm IR node. - - // Scalarize our inputs. - llvm::Value *X = EmitScalarExpr(E->getArg(0)); - llvm::Value *Y = EmitScalarExpr(E->getArg(1)); - Address SumOutPtr = EmitPointerWithAlignment(E->getArg(2)); - - // Decide which of the overflow intrinsics we are lowering to: - llvm::Intrinsic::ID IntrinsicId; - switch (BuiltinID) { - default: llvm_unreachable("Unknown overflow builtin id."); - case Builtin::BI__builtin_uadd_overflow: - case Builtin::BI__builtin_uaddl_overflow: - case Builtin::BI__builtin_uaddll_overflow: - IntrinsicId = llvm::Intrinsic::uadd_with_overflow; - break; - case Builtin::BI__builtin_usub_overflow: - case Builtin::BI__builtin_usubl_overflow: - case Builtin::BI__builtin_usubll_overflow: - IntrinsicId = llvm::Intrinsic::usub_with_overflow; - break; - case Builtin::BI__builtin_umul_overflow: - case Builtin::BI__builtin_umull_overflow: - case Builtin::BI__builtin_umulll_overflow: - IntrinsicId = llvm::Intrinsic::umul_with_overflow; - break; - case Builtin::BI__builtin_sadd_overflow: - case Builtin::BI__builtin_saddl_overflow: - case Builtin::BI__builtin_saddll_overflow: - IntrinsicId = llvm::Intrinsic::sadd_with_overflow; - break; - case Builtin::BI__builtin_ssub_overflow: - case Builtin::BI__builtin_ssubl_overflow: - case Builtin::BI__builtin_ssubll_overflow: - IntrinsicId = llvm::Intrinsic::ssub_with_overflow; - break; - case Builtin::BI__builtin_smul_overflow: - case Builtin::BI__builtin_smull_overflow: - case Builtin::BI__builtin_smulll_overflow: - IntrinsicId = llvm::Intrinsic::smul_with_overflow; - break; - } - - - llvm::Value *Carry; - llvm::Value *Sum = EmitOverflowIntrinsic(*this, IntrinsicId, X, Y, Carry); - Builder.CreateStore(Sum, SumOutPtr); - - return RValue::get(Carry); - } - case Builtin::BI__builtin_addressof: - return RValue::get(EmitLValue(E->getArg(0)).getPointer()); - case Builtin::BI__builtin_operator_new: - return EmitBuiltinNewDeleteCall( - E->getCallee()->getType()->castAs<FunctionProtoType>(), E, false); - case Builtin::BI__builtin_operator_delete: - return EmitBuiltinNewDeleteCall( - E->getCallee()->getType()->castAs<FunctionProtoType>(), E, true); - - case Builtin::BI__noop: - // __noop always evaluates to an integer literal zero. - return RValue::get(ConstantInt::get(IntTy, 0)); - case Builtin::BI__builtin_call_with_static_chain: { - const CallExpr *Call = cast<CallExpr>(E->getArg(0)); - const Expr *Chain = E->getArg(1); - return EmitCall(Call->getCallee()->getType(), - EmitCallee(Call->getCallee()), Call, ReturnValue, - EmitScalarExpr(Chain)); - } - case Builtin::BI_InterlockedExchange8: - case Builtin::BI_InterlockedExchange16: - case Builtin::BI_InterlockedExchange: - case Builtin::BI_InterlockedExchangePointer: - return RValue::get( - EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange, E)); - case Builtin::BI_InterlockedCompareExchangePointer: - case Builtin::BI_InterlockedCompareExchangePointer_nf: { - llvm::Type *RTy; - llvm::IntegerType *IntType = - IntegerType::get(getLLVMContext(), - getContext().getTypeSize(E->getType())); - llvm::Type *IntPtrType = IntType->getPointerTo(); - - llvm::Value *Destination = - Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)), IntPtrType); - - llvm::Value *Exchange = EmitScalarExpr(E->getArg(1)); - RTy = Exchange->getType(); - Exchange = Builder.CreatePtrToInt(Exchange, IntType); - - llvm::Value *Comparand = - Builder.CreatePtrToInt(EmitScalarExpr(E->getArg(2)), IntType); - - auto Ordering = - BuiltinID == Builtin::BI_InterlockedCompareExchangePointer_nf ? - AtomicOrdering::Monotonic : AtomicOrdering::SequentiallyConsistent; - - auto Result = Builder.CreateAtomicCmpXchg(Destination, Comparand, Exchange, - Ordering, Ordering); - Result->setVolatile(true); - - return RValue::get(Builder.CreateIntToPtr(Builder.CreateExtractValue(Result, - 0), - RTy)); - } - case Builtin::BI_InterlockedCompareExchange8: - case Builtin::BI_InterlockedCompareExchange16: - case Builtin::BI_InterlockedCompareExchange: - case Builtin::BI_InterlockedCompareExchange64: - return RValue::get(EmitAtomicCmpXchgForMSIntrin(*this, E)); - case Builtin::BI_InterlockedIncrement16: - case Builtin::BI_InterlockedIncrement: - return RValue::get( - EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement, E)); - case Builtin::BI_InterlockedDecrement16: - case Builtin::BI_InterlockedDecrement: - return RValue::get( - EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement, E)); - case Builtin::BI_InterlockedAnd8: - case Builtin::BI_InterlockedAnd16: - case Builtin::BI_InterlockedAnd: - return RValue::get(EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd, E)); - case Builtin::BI_InterlockedExchangeAdd8: - case Builtin::BI_InterlockedExchangeAdd16: - case Builtin::BI_InterlockedExchangeAdd: - return RValue::get( - EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd, E)); - case Builtin::BI_InterlockedExchangeSub8: - case Builtin::BI_InterlockedExchangeSub16: - case Builtin::BI_InterlockedExchangeSub: - return RValue::get( - EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeSub, E)); - case Builtin::BI_InterlockedOr8: - case Builtin::BI_InterlockedOr16: - case Builtin::BI_InterlockedOr: - return RValue::get(EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr, E)); - case Builtin::BI_InterlockedXor8: - case Builtin::BI_InterlockedXor16: - case Builtin::BI_InterlockedXor: - return RValue::get(EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor, E)); - - case Builtin::BI_bittest64: - case Builtin::BI_bittest: - case Builtin::BI_bittestandcomplement64: - case Builtin::BI_bittestandcomplement: - case Builtin::BI_bittestandreset64: - case Builtin::BI_bittestandreset: - case Builtin::BI_bittestandset64: - case Builtin::BI_bittestandset: - case Builtin::BI_interlockedbittestandreset: - case Builtin::BI_interlockedbittestandreset64: - case Builtin::BI_interlockedbittestandset64: - case Builtin::BI_interlockedbittestandset: - case Builtin::BI_interlockedbittestandset_acq: - case Builtin::BI_interlockedbittestandset_rel: - case Builtin::BI_interlockedbittestandset_nf: - case Builtin::BI_interlockedbittestandreset_acq: - case Builtin::BI_interlockedbittestandreset_rel: - case Builtin::BI_interlockedbittestandreset_nf: - return RValue::get(EmitBitTestIntrinsic(*this, BuiltinID, E)); - - case Builtin::BI__exception_code: - case Builtin::BI_exception_code: - return RValue::get(EmitSEHExceptionCode()); - case Builtin::BI__exception_info: - case Builtin::BI_exception_info: - return RValue::get(EmitSEHExceptionInfo()); - case Builtin::BI__abnormal_termination: - case Builtin::BI_abnormal_termination: - return RValue::get(EmitSEHAbnormalTermination()); - case Builtin::BI_setjmpex: - if (getTarget().getTriple().isOSMSVCRT()) - return EmitMSVCRTSetJmp(*this, MSVCSetJmpKind::_setjmpex, E); - break; - case Builtin::BI_setjmp: - if (getTarget().getTriple().isOSMSVCRT()) { - if (getTarget().getTriple().getArch() == llvm::Triple::x86) - return EmitMSVCRTSetJmp(*this, MSVCSetJmpKind::_setjmp3, E); - else if (getTarget().getTriple().getArch() == llvm::Triple::aarch64) - return EmitMSVCRTSetJmp(*this, MSVCSetJmpKind::_setjmpex, E); - return EmitMSVCRTSetJmp(*this, MSVCSetJmpKind::_setjmp, E); - } - break; - - case Builtin::BI__GetExceptionInfo: { - if (llvm::GlobalVariable *GV = - CGM.getCXXABI().getThrowInfo(FD->getParamDecl(0)->getType())) - return RValue::get(llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy)); - break; - } - - case Builtin::BI__fastfail: - return RValue::get(EmitMSVCBuiltinExpr(MSVCIntrin::__fastfail, E)); - - case Builtin::BI__builtin_coro_size: { - auto & Context = getContext(); - auto SizeTy = Context.getSizeType(); - auto T = Builder.getIntNTy(Context.getTypeSize(SizeTy)); - Value *F = CGM.getIntrinsic(Intrinsic::coro_size, T); - return RValue::get(Builder.CreateCall(F)); - } - - case Builtin::BI__builtin_coro_id: - return EmitCoroutineIntrinsic(E, Intrinsic::coro_id); - case Builtin::BI__builtin_coro_promise: - return EmitCoroutineIntrinsic(E, Intrinsic::coro_promise); - case Builtin::BI__builtin_coro_resume: - return EmitCoroutineIntrinsic(E, Intrinsic::coro_resume); - case Builtin::BI__builtin_coro_frame: - return EmitCoroutineIntrinsic(E, Intrinsic::coro_frame); - case Builtin::BI__builtin_coro_noop: - return EmitCoroutineIntrinsic(E, Intrinsic::coro_noop); - case Builtin::BI__builtin_coro_free: - return EmitCoroutineIntrinsic(E, Intrinsic::coro_free); - case Builtin::BI__builtin_coro_destroy: - return EmitCoroutineIntrinsic(E, Intrinsic::coro_destroy); - case Builtin::BI__builtin_coro_done: - return EmitCoroutineIntrinsic(E, Intrinsic::coro_done); - case Builtin::BI__builtin_coro_alloc: - return EmitCoroutineIntrinsic(E, Intrinsic::coro_alloc); - case Builtin::BI__builtin_coro_begin: - return EmitCoroutineIntrinsic(E, Intrinsic::coro_begin); - case Builtin::BI__builtin_coro_end: - return EmitCoroutineIntrinsic(E, Intrinsic::coro_end); - case Builtin::BI__builtin_coro_suspend: - return EmitCoroutineIntrinsic(E, Intrinsic::coro_suspend); - case Builtin::BI__builtin_coro_param: - return EmitCoroutineIntrinsic(E, Intrinsic::coro_param); - - // OpenCL v2.0 s6.13.16.2, Built-in pipe read and write functions - case Builtin::BIread_pipe: - case Builtin::BIwrite_pipe: { - Value *Arg0 = EmitScalarExpr(E->getArg(0)), - *Arg1 = EmitScalarExpr(E->getArg(1)); - CGOpenCLRuntime OpenCLRT(CGM); - Value *PacketSize = OpenCLRT.getPipeElemSize(E->getArg(0)); - Value *PacketAlign = OpenCLRT.getPipeElemAlign(E->getArg(0)); - - // Type of the generic packet parameter. - unsigned GenericAS = - getContext().getTargetAddressSpace(LangAS::opencl_generic); - llvm::Type *I8PTy = llvm::PointerType::get( - llvm::Type::getInt8Ty(getLLVMContext()), GenericAS); - - // Testing which overloaded version we should generate the call for. - if (2U == E->getNumArgs()) { - const char *Name = (BuiltinID == Builtin::BIread_pipe) ? "__read_pipe_2" - : "__write_pipe_2"; - // Creating a generic function type to be able to call with any builtin or - // user defined type. - llvm::Type *ArgTys[] = {Arg0->getType(), I8PTy, Int32Ty, Int32Ty}; - llvm::FunctionType *FTy = llvm::FunctionType::get( - Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false); - Value *BCast = Builder.CreatePointerCast(Arg1, I8PTy); - return RValue::get( - Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), - {Arg0, BCast, PacketSize, PacketAlign})); - } else { - assert(4 == E->getNumArgs() && - "Illegal number of parameters to pipe function"); - const char *Name = (BuiltinID == Builtin::BIread_pipe) ? "__read_pipe_4" - : "__write_pipe_4"; - - llvm::Type *ArgTys[] = {Arg0->getType(), Arg1->getType(), Int32Ty, I8PTy, - Int32Ty, Int32Ty}; - Value *Arg2 = EmitScalarExpr(E->getArg(2)), - *Arg3 = EmitScalarExpr(E->getArg(3)); - llvm::FunctionType *FTy = llvm::FunctionType::get( - Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false); - Value *BCast = Builder.CreatePointerCast(Arg3, I8PTy); - // We know the third argument is an integer type, but we may need to cast - // it to i32. - if (Arg2->getType() != Int32Ty) - Arg2 = Builder.CreateZExtOrTrunc(Arg2, Int32Ty); - return RValue::get(Builder.CreateCall( - CGM.CreateRuntimeFunction(FTy, Name), - {Arg0, Arg1, Arg2, BCast, PacketSize, PacketAlign})); - } - } - // OpenCL v2.0 s6.13.16 ,s9.17.3.5 - Built-in pipe reserve read and write - // functions - case Builtin::BIreserve_read_pipe: - case Builtin::BIreserve_write_pipe: - case Builtin::BIwork_group_reserve_read_pipe: - case Builtin::BIwork_group_reserve_write_pipe: - case Builtin::BIsub_group_reserve_read_pipe: - case Builtin::BIsub_group_reserve_write_pipe: { - // Composing the mangled name for the function. - const char *Name; - if (BuiltinID == Builtin::BIreserve_read_pipe) - Name = "__reserve_read_pipe"; - else if (BuiltinID == Builtin::BIreserve_write_pipe) - Name = "__reserve_write_pipe"; - else if (BuiltinID == Builtin::BIwork_group_reserve_read_pipe) - Name = "__work_group_reserve_read_pipe"; - else if (BuiltinID == Builtin::BIwork_group_reserve_write_pipe) - Name = "__work_group_reserve_write_pipe"; - else if (BuiltinID == Builtin::BIsub_group_reserve_read_pipe) - Name = "__sub_group_reserve_read_pipe"; - else - Name = "__sub_group_reserve_write_pipe"; - - Value *Arg0 = EmitScalarExpr(E->getArg(0)), - *Arg1 = EmitScalarExpr(E->getArg(1)); - llvm::Type *ReservedIDTy = ConvertType(getContext().OCLReserveIDTy); - CGOpenCLRuntime OpenCLRT(CGM); - Value *PacketSize = OpenCLRT.getPipeElemSize(E->getArg(0)); - Value *PacketAlign = OpenCLRT.getPipeElemAlign(E->getArg(0)); - - // Building the generic function prototype. - llvm::Type *ArgTys[] = {Arg0->getType(), Int32Ty, Int32Ty, Int32Ty}; - llvm::FunctionType *FTy = llvm::FunctionType::get( - ReservedIDTy, llvm::ArrayRef<llvm::Type *>(ArgTys), false); - // We know the second argument is an integer type, but we may need to cast - // it to i32. - if (Arg1->getType() != Int32Ty) - Arg1 = Builder.CreateZExtOrTrunc(Arg1, Int32Ty); - return RValue::get( - Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), - {Arg0, Arg1, PacketSize, PacketAlign})); - } - // OpenCL v2.0 s6.13.16, s9.17.3.5 - Built-in pipe commit read and write - // functions - case Builtin::BIcommit_read_pipe: - case Builtin::BIcommit_write_pipe: - case Builtin::BIwork_group_commit_read_pipe: - case Builtin::BIwork_group_commit_write_pipe: - case Builtin::BIsub_group_commit_read_pipe: - case Builtin::BIsub_group_commit_write_pipe: { - const char *Name; - if (BuiltinID == Builtin::BIcommit_read_pipe) - Name = "__commit_read_pipe"; - else if (BuiltinID == Builtin::BIcommit_write_pipe) - Name = "__commit_write_pipe"; - else if (BuiltinID == Builtin::BIwork_group_commit_read_pipe) - Name = "__work_group_commit_read_pipe"; - else if (BuiltinID == Builtin::BIwork_group_commit_write_pipe) - Name = "__work_group_commit_write_pipe"; - else if (BuiltinID == Builtin::BIsub_group_commit_read_pipe) - Name = "__sub_group_commit_read_pipe"; - else - Name = "__sub_group_commit_write_pipe"; - - Value *Arg0 = EmitScalarExpr(E->getArg(0)), - *Arg1 = EmitScalarExpr(E->getArg(1)); - CGOpenCLRuntime OpenCLRT(CGM); - Value *PacketSize = OpenCLRT.getPipeElemSize(E->getArg(0)); - Value *PacketAlign = OpenCLRT.getPipeElemAlign(E->getArg(0)); - - // Building the generic function prototype. - llvm::Type *ArgTys[] = {Arg0->getType(), Arg1->getType(), Int32Ty, Int32Ty}; - llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()), - llvm::ArrayRef<llvm::Type *>(ArgTys), false); - - return RValue::get( - Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), - {Arg0, Arg1, PacketSize, PacketAlign})); - } - // OpenCL v2.0 s6.13.16.4 Built-in pipe query functions - case Builtin::BIget_pipe_num_packets: - case Builtin::BIget_pipe_max_packets: { - const char *BaseName; - const PipeType *PipeTy = E->getArg(0)->getType()->getAs<PipeType>(); - if (BuiltinID == Builtin::BIget_pipe_num_packets) - BaseName = "__get_pipe_num_packets"; - else - BaseName = "__get_pipe_max_packets"; - auto Name = std::string(BaseName) + - std::string(PipeTy->isReadOnly() ? "_ro" : "_wo"); - - // Building the generic function prototype. - Value *Arg0 = EmitScalarExpr(E->getArg(0)); - CGOpenCLRuntime OpenCLRT(CGM); - Value *PacketSize = OpenCLRT.getPipeElemSize(E->getArg(0)); - Value *PacketAlign = OpenCLRT.getPipeElemAlign(E->getArg(0)); - llvm::Type *ArgTys[] = {Arg0->getType(), Int32Ty, Int32Ty}; - llvm::FunctionType *FTy = llvm::FunctionType::get( - Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false); - - return RValue::get(Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), - {Arg0, PacketSize, PacketAlign})); - } - - // OpenCL v2.0 s6.13.9 - Address space qualifier functions. - case Builtin::BIto_global: - case Builtin::BIto_local: - case Builtin::BIto_private: { - auto Arg0 = EmitScalarExpr(E->getArg(0)); - auto NewArgT = llvm::PointerType::get(Int8Ty, - CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic)); - auto NewRetT = llvm::PointerType::get(Int8Ty, - CGM.getContext().getTargetAddressSpace( - E->getType()->getPointeeType().getAddressSpace())); - auto FTy = llvm::FunctionType::get(NewRetT, {NewArgT}, false); - llvm::Value *NewArg; - if (Arg0->getType()->getPointerAddressSpace() != - NewArgT->getPointerAddressSpace()) - NewArg = Builder.CreateAddrSpaceCast(Arg0, NewArgT); - else - NewArg = Builder.CreateBitOrPointerCast(Arg0, NewArgT); - auto NewName = std::string("__") + E->getDirectCallee()->getName().str(); - auto NewCall = - Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, NewName), {NewArg}); - return RValue::get(Builder.CreateBitOrPointerCast(NewCall, - ConvertType(E->getType()))); - } - - // OpenCL v2.0, s6.13.17 - Enqueue kernel function. - // It contains four different overload formats specified in Table 6.13.17.1. - case Builtin::BIenqueue_kernel: { - StringRef Name; // Generated function call name - unsigned NumArgs = E->getNumArgs(); - - llvm::Type *QueueTy = ConvertType(getContext().OCLQueueTy); - llvm::Type *GenericVoidPtrTy = Builder.getInt8PtrTy( - getContext().getTargetAddressSpace(LangAS::opencl_generic)); - - llvm::Value *Queue = EmitScalarExpr(E->getArg(0)); - llvm::Value *Flags = EmitScalarExpr(E->getArg(1)); - LValue NDRangeL = EmitAggExprToLValue(E->getArg(2)); - llvm::Value *Range = NDRangeL.getAddress().getPointer(); - llvm::Type *RangeTy = NDRangeL.getAddress().getType(); - - if (NumArgs == 4) { - // The most basic form of the call with parameters: - // queue_t, kernel_enqueue_flags_t, ndrange_t, block(void) - Name = "__enqueue_kernel_basic"; - llvm::Type *ArgTys[] = {QueueTy, Int32Ty, RangeTy, GenericVoidPtrTy, - GenericVoidPtrTy}; - llvm::FunctionType *FTy = llvm::FunctionType::get( - Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false); - - auto Info = - CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(3)); - llvm::Value *Kernel = - Builder.CreatePointerCast(Info.Kernel, GenericVoidPtrTy); - llvm::Value *Block = - Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy); - - AttrBuilder B; - B.addAttribute(Attribute::ByVal); - llvm::AttributeList ByValAttrSet = - llvm::AttributeList::get(CGM.getModule().getContext(), 3U, B); - - auto RTCall = - Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name, ByValAttrSet), - {Queue, Flags, Range, Kernel, Block}); - RTCall->setAttributes(ByValAttrSet); - return RValue::get(RTCall); - } - assert(NumArgs >= 5 && "Invalid enqueue_kernel signature"); - - // Create a temporary array to hold the sizes of local pointer arguments - // for the block. \p First is the position of the first size argument. - auto CreateArrayForSizeVar = [=](unsigned First) - -> std::tuple<llvm::Value *, llvm::Value *, llvm::Value *> { - llvm::APInt ArraySize(32, NumArgs - First); - QualType SizeArrayTy = getContext().getConstantArrayType( - getContext().getSizeType(), ArraySize, ArrayType::Normal, - /*IndexTypeQuals=*/0); - auto Tmp = CreateMemTemp(SizeArrayTy, "block_sizes"); - llvm::Value *TmpPtr = Tmp.getPointer(); - llvm::Value *TmpSize = EmitLifetimeStart( - CGM.getDataLayout().getTypeAllocSize(Tmp.getElementType()), TmpPtr); - llvm::Value *ElemPtr; - // Each of the following arguments specifies the size of the corresponding - // argument passed to the enqueued block. - auto *Zero = llvm::ConstantInt::get(IntTy, 0); - for (unsigned I = First; I < NumArgs; ++I) { - auto *Index = llvm::ConstantInt::get(IntTy, I - First); - auto *GEP = Builder.CreateGEP(TmpPtr, {Zero, Index}); - if (I == First) - ElemPtr = GEP; - auto *V = - Builder.CreateZExtOrTrunc(EmitScalarExpr(E->getArg(I)), SizeTy); - Builder.CreateAlignedStore( - V, GEP, CGM.getDataLayout().getPrefTypeAlignment(SizeTy)); - } - return std::tie(ElemPtr, TmpSize, TmpPtr); - }; - - // Could have events and/or varargs. - if (E->getArg(3)->getType()->isBlockPointerType()) { - // No events passed, but has variadic arguments. - Name = "__enqueue_kernel_varargs"; - auto Info = - CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(3)); - llvm::Value *Kernel = - Builder.CreatePointerCast(Info.Kernel, GenericVoidPtrTy); - auto *Block = Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy); - llvm::Value *ElemPtr, *TmpSize, *TmpPtr; - std::tie(ElemPtr, TmpSize, TmpPtr) = CreateArrayForSizeVar(4); - - // Create a vector of the arguments, as well as a constant value to - // express to the runtime the number of variadic arguments. - std::vector<llvm::Value *> Args = { - Queue, Flags, Range, - Kernel, Block, ConstantInt::get(IntTy, NumArgs - 4), - ElemPtr}; - std::vector<llvm::Type *> ArgTys = { - QueueTy, IntTy, RangeTy, GenericVoidPtrTy, - GenericVoidPtrTy, IntTy, ElemPtr->getType()}; - - llvm::FunctionType *FTy = llvm::FunctionType::get( - Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false); - auto Call = - RValue::get(Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), - llvm::ArrayRef<llvm::Value *>(Args))); - if (TmpSize) - EmitLifetimeEnd(TmpSize, TmpPtr); - return Call; - } - // Any calls now have event arguments passed. - if (NumArgs >= 7) { - llvm::Type *EventTy = ConvertType(getContext().OCLClkEventTy); - llvm::Type *EventPtrTy = EventTy->getPointerTo( - CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic)); - - llvm::Value *NumEvents = - Builder.CreateZExtOrTrunc(EmitScalarExpr(E->getArg(3)), Int32Ty); - llvm::Value *EventList = - E->getArg(4)->getType()->isArrayType() - ? EmitArrayToPointerDecay(E->getArg(4)).getPointer() - : EmitScalarExpr(E->getArg(4)); - llvm::Value *ClkEvent = EmitScalarExpr(E->getArg(5)); - // Convert to generic address space. - EventList = Builder.CreatePointerCast(EventList, EventPtrTy); - ClkEvent = ClkEvent->getType()->isIntegerTy() - ? Builder.CreateBitOrPointerCast(ClkEvent, EventPtrTy) - : Builder.CreatePointerCast(ClkEvent, EventPtrTy); - auto Info = - CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(6)); - llvm::Value *Kernel = - Builder.CreatePointerCast(Info.Kernel, GenericVoidPtrTy); - llvm::Value *Block = - Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy); - - std::vector<llvm::Type *> ArgTys = { - QueueTy, Int32Ty, RangeTy, Int32Ty, - EventPtrTy, EventPtrTy, GenericVoidPtrTy, GenericVoidPtrTy}; - - std::vector<llvm::Value *> Args = {Queue, Flags, Range, NumEvents, - EventList, ClkEvent, Kernel, Block}; - - if (NumArgs == 7) { - // Has events but no variadics. - Name = "__enqueue_kernel_basic_events"; - llvm::FunctionType *FTy = llvm::FunctionType::get( - Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false); - return RValue::get( - Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), - llvm::ArrayRef<llvm::Value *>(Args))); - } - // Has event info and variadics - // Pass the number of variadics to the runtime function too. - Args.push_back(ConstantInt::get(Int32Ty, NumArgs - 7)); - ArgTys.push_back(Int32Ty); - Name = "__enqueue_kernel_events_varargs"; - - llvm::Value *ElemPtr, *TmpSize, *TmpPtr; - std::tie(ElemPtr, TmpSize, TmpPtr) = CreateArrayForSizeVar(7); - Args.push_back(ElemPtr); - ArgTys.push_back(ElemPtr->getType()); - - llvm::FunctionType *FTy = llvm::FunctionType::get( - Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false); - auto Call = - RValue::get(Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), - llvm::ArrayRef<llvm::Value *>(Args))); - if (TmpSize) - EmitLifetimeEnd(TmpSize, TmpPtr); - return Call; - } - LLVM_FALLTHROUGH; - } - // OpenCL v2.0 s6.13.17.6 - Kernel query functions need bitcast of block - // parameter. - case Builtin::BIget_kernel_work_group_size: { - llvm::Type *GenericVoidPtrTy = Builder.getInt8PtrTy( - getContext().getTargetAddressSpace(LangAS::opencl_generic)); - auto Info = - CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(0)); - Value *Kernel = Builder.CreatePointerCast(Info.Kernel, GenericVoidPtrTy); - Value *Arg = Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy); - return RValue::get(Builder.CreateCall( - CGM.CreateRuntimeFunction( - llvm::FunctionType::get(IntTy, {GenericVoidPtrTy, GenericVoidPtrTy}, - false), - "__get_kernel_work_group_size_impl"), - {Kernel, Arg})); - } - case Builtin::BIget_kernel_preferred_work_group_size_multiple: { - llvm::Type *GenericVoidPtrTy = Builder.getInt8PtrTy( - getContext().getTargetAddressSpace(LangAS::opencl_generic)); - auto Info = - CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(0)); - Value *Kernel = Builder.CreatePointerCast(Info.Kernel, GenericVoidPtrTy); - Value *Arg = Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy); - return RValue::get(Builder.CreateCall( - CGM.CreateRuntimeFunction( - llvm::FunctionType::get(IntTy, {GenericVoidPtrTy, GenericVoidPtrTy}, - false), - "__get_kernel_preferred_work_group_size_multiple_impl"), - {Kernel, Arg})); - } - case Builtin::BIget_kernel_max_sub_group_size_for_ndrange: - case Builtin::BIget_kernel_sub_group_count_for_ndrange: { - llvm::Type *GenericVoidPtrTy = Builder.getInt8PtrTy( - getContext().getTargetAddressSpace(LangAS::opencl_generic)); - LValue NDRangeL = EmitAggExprToLValue(E->getArg(0)); - llvm::Value *NDRange = NDRangeL.getAddress().getPointer(); - auto Info = - CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(1)); - Value *Kernel = Builder.CreatePointerCast(Info.Kernel, GenericVoidPtrTy); - Value *Block = Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy); - const char *Name = - BuiltinID == Builtin::BIget_kernel_max_sub_group_size_for_ndrange - ? "__get_kernel_max_sub_group_size_for_ndrange_impl" - : "__get_kernel_sub_group_count_for_ndrange_impl"; - return RValue::get(Builder.CreateCall( - CGM.CreateRuntimeFunction( - llvm::FunctionType::get( - IntTy, {NDRange->getType(), GenericVoidPtrTy, GenericVoidPtrTy}, - false), - Name), - {NDRange, Kernel, Block})); - } - - case Builtin::BI__builtin_store_half: - case Builtin::BI__builtin_store_halff: { - Value *Val = EmitScalarExpr(E->getArg(0)); - Address Address = EmitPointerWithAlignment(E->getArg(1)); - Value *HalfVal = Builder.CreateFPTrunc(Val, Builder.getHalfTy()); - return RValue::get(Builder.CreateStore(HalfVal, Address)); - } - case Builtin::BI__builtin_load_half: { - Address Address = EmitPointerWithAlignment(E->getArg(0)); - Value *HalfVal = Builder.CreateLoad(Address); - return RValue::get(Builder.CreateFPExt(HalfVal, Builder.getDoubleTy())); - } - case Builtin::BI__builtin_load_halff: { - Address Address = EmitPointerWithAlignment(E->getArg(0)); - Value *HalfVal = Builder.CreateLoad(Address); - return RValue::get(Builder.CreateFPExt(HalfVal, Builder.getFloatTy())); - } - case Builtin::BIprintf: - if (getTarget().getTriple().isNVPTX()) - return EmitNVPTXDevicePrintfCallExpr(E, ReturnValue); - break; - case Builtin::BI__builtin_canonicalize: - case Builtin::BI__builtin_canonicalizef: - case Builtin::BI__builtin_canonicalizel: - return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::canonicalize)); - - case Builtin::BI__builtin_thread_pointer: { - if (!getContext().getTargetInfo().isTLSSupported()) - CGM.ErrorUnsupported(E, "__builtin_thread_pointer"); - // Fall through - it's already mapped to the intrinsic by GCCBuiltin. - break; - } - case Builtin::BI__builtin_os_log_format: - return emitBuiltinOSLogFormat(*E); - - case Builtin::BI__xray_customevent: { - if (!ShouldXRayInstrumentFunction()) - return RValue::getIgnored(); - - if (!CGM.getCodeGenOpts().XRayInstrumentationBundle.has( - XRayInstrKind::Custom)) - return RValue::getIgnored(); - - if (const auto *XRayAttr = CurFuncDecl->getAttr<XRayInstrumentAttr>()) - if (XRayAttr->neverXRayInstrument() && !AlwaysEmitXRayCustomEvents()) - return RValue::getIgnored(); - - Function *F = CGM.getIntrinsic(Intrinsic::xray_customevent); - auto FTy = F->getFunctionType(); - auto Arg0 = E->getArg(0); - auto Arg0Val = EmitScalarExpr(Arg0); - auto Arg0Ty = Arg0->getType(); - auto PTy0 = FTy->getParamType(0); - if (PTy0 != Arg0Val->getType()) { - if (Arg0Ty->isArrayType()) - Arg0Val = EmitArrayToPointerDecay(Arg0).getPointer(); - else - Arg0Val = Builder.CreatePointerCast(Arg0Val, PTy0); - } - auto Arg1 = EmitScalarExpr(E->getArg(1)); - auto PTy1 = FTy->getParamType(1); - if (PTy1 != Arg1->getType()) - Arg1 = Builder.CreateTruncOrBitCast(Arg1, PTy1); - return RValue::get(Builder.CreateCall(F, {Arg0Val, Arg1})); - } - - case Builtin::BI__xray_typedevent: { - // TODO: There should be a way to always emit events even if the current - // function is not instrumented. Losing events in a stream can cripple - // a trace. - if (!ShouldXRayInstrumentFunction()) - return RValue::getIgnored(); - - if (!CGM.getCodeGenOpts().XRayInstrumentationBundle.has( - XRayInstrKind::Typed)) - return RValue::getIgnored(); - - if (const auto *XRayAttr = CurFuncDecl->getAttr<XRayInstrumentAttr>()) - if (XRayAttr->neverXRayInstrument() && !AlwaysEmitXRayTypedEvents()) - return RValue::getIgnored(); - - Function *F = CGM.getIntrinsic(Intrinsic::xray_typedevent); - auto FTy = F->getFunctionType(); - auto Arg0 = EmitScalarExpr(E->getArg(0)); - auto PTy0 = FTy->getParamType(0); - if (PTy0 != Arg0->getType()) - Arg0 = Builder.CreateTruncOrBitCast(Arg0, PTy0); - auto Arg1 = E->getArg(1); - auto Arg1Val = EmitScalarExpr(Arg1); - auto Arg1Ty = Arg1->getType(); - auto PTy1 = FTy->getParamType(1); - if (PTy1 != Arg1Val->getType()) { - if (Arg1Ty->isArrayType()) - Arg1Val = EmitArrayToPointerDecay(Arg1).getPointer(); - else - Arg1Val = Builder.CreatePointerCast(Arg1Val, PTy1); - } - auto Arg2 = EmitScalarExpr(E->getArg(2)); - auto PTy2 = FTy->getParamType(2); - if (PTy2 != Arg2->getType()) - Arg2 = Builder.CreateTruncOrBitCast(Arg2, PTy2); - return RValue::get(Builder.CreateCall(F, {Arg0, Arg1Val, Arg2})); - } - - case Builtin::BI__builtin_ms_va_start: - case Builtin::BI__builtin_ms_va_end: - return RValue::get( - EmitVAStartEnd(EmitMSVAListRef(E->getArg(0)).getPointer(), - BuiltinID == Builtin::BI__builtin_ms_va_start)); - - case Builtin::BI__builtin_ms_va_copy: { - // Lower this manually. We can't reliably determine whether or not any - // given va_copy() is for a Win64 va_list from the calling convention - // alone, because it's legal to do this from a System V ABI function. - // With opaque pointer types, we won't have enough information in LLVM - // IR to determine this from the argument types, either. Best to do it - // now, while we have enough information. - Address DestAddr = EmitMSVAListRef(E->getArg(0)); - Address SrcAddr = EmitMSVAListRef(E->getArg(1)); - - llvm::Type *BPP = Int8PtrPtrTy; - - DestAddr = Address(Builder.CreateBitCast(DestAddr.getPointer(), BPP, "cp"), - DestAddr.getAlignment()); - SrcAddr = Address(Builder.CreateBitCast(SrcAddr.getPointer(), BPP, "ap"), - SrcAddr.getAlignment()); - - Value *ArgPtr = Builder.CreateLoad(SrcAddr, "ap.val"); - return RValue::get(Builder.CreateStore(ArgPtr, DestAddr)); - } - } - - // If this is an alias for a lib function (e.g. __builtin_sin), emit - // the call using the normal call path, but using the unmangled - // version of the function name. - if (getContext().BuiltinInfo.isLibFunction(BuiltinID)) - return emitLibraryCall(*this, FD, E, - CGM.getBuiltinLibFunction(FD, BuiltinID)); - - // If this is a predefined lib function (e.g. malloc), emit the call - // using exactly the normal call path. - if (getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID)) - return emitLibraryCall(*this, FD, E, - cast<llvm::Constant>(EmitScalarExpr(E->getCallee()))); - - // Check that a call to a target specific builtin has the correct target - // features. - // This is down here to avoid non-target specific builtins, however, if - // generic builtins start to require generic target features then we - // can move this up to the beginning of the function. - checkTargetFeatures(E, FD); - - if (unsigned VectorWidth = getContext().BuiltinInfo.getRequiredVectorWidth(BuiltinID)) - LargestVectorWidth = std::max(LargestVectorWidth, VectorWidth); - - // See if we have a target specific intrinsic. - const char *Name = getContext().BuiltinInfo.getName(BuiltinID); - Intrinsic::ID IntrinsicID = Intrinsic::not_intrinsic; - StringRef Prefix = - llvm::Triple::getArchTypePrefix(getTarget().getTriple().getArch()); - if (!Prefix.empty()) { - IntrinsicID = Intrinsic::getIntrinsicForGCCBuiltin(Prefix.data(), Name); - // NOTE we don't need to perform a compatibility flag check here since the - // intrinsics are declared in Builtins*.def via LANGBUILTIN which filter the - // MS builtins via ALL_MS_LANGUAGES and are filtered earlier. - if (IntrinsicID == Intrinsic::not_intrinsic) - IntrinsicID = Intrinsic::getIntrinsicForMSBuiltin(Prefix.data(), Name); - } - - if (IntrinsicID != Intrinsic::not_intrinsic) { - SmallVector<Value*, 16> Args; - - // Find out if any arguments are required to be integer constant - // expressions. - unsigned ICEArguments = 0; - ASTContext::GetBuiltinTypeError Error; - getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments); - assert(Error == ASTContext::GE_None && "Should not codegen an error"); - - Function *F = CGM.getIntrinsic(IntrinsicID); - llvm::FunctionType *FTy = F->getFunctionType(); - - for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) { - Value *ArgValue; - // If this is a normal argument, just emit it as a scalar. - if ((ICEArguments & (1 << i)) == 0) { - ArgValue = EmitScalarExpr(E->getArg(i)); - } else { - // If this is required to be a constant, constant fold it so that we - // know that the generated intrinsic gets a ConstantInt. - llvm::APSInt Result; - bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result,getContext()); - assert(IsConst && "Constant arg isn't actually constant?"); - (void)IsConst; - ArgValue = llvm::ConstantInt::get(getLLVMContext(), Result); - } - - // If the intrinsic arg type is different from the builtin arg type - // we need to do a bit cast. - llvm::Type *PTy = FTy->getParamType(i); - if (PTy != ArgValue->getType()) { - // XXX - vector of pointers? - if (auto *PtrTy = dyn_cast<llvm::PointerType>(PTy)) { - if (PtrTy->getAddressSpace() != - ArgValue->getType()->getPointerAddressSpace()) { - ArgValue = Builder.CreateAddrSpaceCast( - ArgValue, - ArgValue->getType()->getPointerTo(PtrTy->getAddressSpace())); - } - } - - assert(PTy->canLosslesslyBitCastTo(FTy->getParamType(i)) && - "Must be able to losslessly bit cast to param"); - ArgValue = Builder.CreateBitCast(ArgValue, PTy); - } - - Args.push_back(ArgValue); - } - - Value *V = Builder.CreateCall(F, Args); - QualType BuiltinRetType = E->getType(); - - llvm::Type *RetTy = VoidTy; - if (!BuiltinRetType->isVoidType()) - RetTy = ConvertType(BuiltinRetType); - - if (RetTy != V->getType()) { - // XXX - vector of pointers? - if (auto *PtrTy = dyn_cast<llvm::PointerType>(RetTy)) { - if (PtrTy->getAddressSpace() != V->getType()->getPointerAddressSpace()) { - V = Builder.CreateAddrSpaceCast( - V, V->getType()->getPointerTo(PtrTy->getAddressSpace())); - } - } - - assert(V->getType()->canLosslesslyBitCastTo(RetTy) && - "Must be able to losslessly bit cast result type"); - V = Builder.CreateBitCast(V, RetTy); - } - - return RValue::get(V); - } - - // See if we have a target specific builtin that needs to be lowered. - if (Value *V = EmitTargetBuiltinExpr(BuiltinID, E)) - return RValue::get(V); - - ErrorUnsupported(E, "builtin function"); - - // Unknown builtin, for now just dump it out and return undef. - return GetUndefRValue(E->getType()); -} - -static Value *EmitTargetArchBuiltinExpr(CodeGenFunction *CGF, - unsigned BuiltinID, const CallExpr *E, - llvm::Triple::ArchType Arch) { - switch (Arch) { - case llvm::Triple::arm: - case llvm::Triple::armeb: - case llvm::Triple::thumb: - case llvm::Triple::thumbeb: - return CGF->EmitARMBuiltinExpr(BuiltinID, E, Arch); - case llvm::Triple::aarch64: - case llvm::Triple::aarch64_be: - return CGF->EmitAArch64BuiltinExpr(BuiltinID, E, Arch); - case llvm::Triple::x86: - case llvm::Triple::x86_64: - return CGF->EmitX86BuiltinExpr(BuiltinID, E); - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - case llvm::Triple::ppc64le: - return CGF->EmitPPCBuiltinExpr(BuiltinID, E); - case llvm::Triple::r600: - case llvm::Triple::amdgcn: - return CGF->EmitAMDGPUBuiltinExpr(BuiltinID, E); - case llvm::Triple::systemz: - return CGF->EmitSystemZBuiltinExpr(BuiltinID, E); - case llvm::Triple::nvptx: - case llvm::Triple::nvptx64: - return CGF->EmitNVPTXBuiltinExpr(BuiltinID, E); - case llvm::Triple::wasm32: - case llvm::Triple::wasm64: - return CGF->EmitWebAssemblyBuiltinExpr(BuiltinID, E); - case llvm::Triple::hexagon: - return CGF->EmitHexagonBuiltinExpr(BuiltinID, E); - default: - return nullptr; - } -} - -Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID, - const CallExpr *E) { - if (getContext().BuiltinInfo.isAuxBuiltinID(BuiltinID)) { - assert(getContext().getAuxTargetInfo() && "Missing aux target info"); - return EmitTargetArchBuiltinExpr( - this, getContext().BuiltinInfo.getAuxBuiltinID(BuiltinID), E, - getContext().getAuxTargetInfo()->getTriple().getArch()); - } - - return EmitTargetArchBuiltinExpr(this, BuiltinID, E, - getTarget().getTriple().getArch()); -} - -static llvm::VectorType *GetNeonType(CodeGenFunction *CGF, - NeonTypeFlags TypeFlags, - bool HasLegalHalfType=true, - bool V1Ty=false) { - int IsQuad = TypeFlags.isQuad(); - switch (TypeFlags.getEltType()) { - case NeonTypeFlags::Int8: - case NeonTypeFlags::Poly8: - return llvm::VectorType::get(CGF->Int8Ty, V1Ty ? 1 : (8 << IsQuad)); - case NeonTypeFlags::Int16: - case NeonTypeFlags::Poly16: - return llvm::VectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad)); - case NeonTypeFlags::Float16: - if (HasLegalHalfType) - return llvm::VectorType::get(CGF->HalfTy, V1Ty ? 1 : (4 << IsQuad)); - else - return llvm::VectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad)); - case NeonTypeFlags::Int32: - return llvm::VectorType::get(CGF->Int32Ty, V1Ty ? 1 : (2 << IsQuad)); - case NeonTypeFlags::Int64: - case NeonTypeFlags::Poly64: - return llvm::VectorType::get(CGF->Int64Ty, V1Ty ? 1 : (1 << IsQuad)); - case NeonTypeFlags::Poly128: - // FIXME: i128 and f128 doesn't get fully support in Clang and llvm. - // There is a lot of i128 and f128 API missing. - // so we use v16i8 to represent poly128 and get pattern matched. - return llvm::VectorType::get(CGF->Int8Ty, 16); - case NeonTypeFlags::Float32: - return llvm::VectorType::get(CGF->FloatTy, V1Ty ? 1 : (2 << IsQuad)); - case NeonTypeFlags::Float64: - return llvm::VectorType::get(CGF->DoubleTy, V1Ty ? 1 : (1 << IsQuad)); - } - llvm_unreachable("Unknown vector element type!"); -} - -static llvm::VectorType *GetFloatNeonType(CodeGenFunction *CGF, - NeonTypeFlags IntTypeFlags) { - int IsQuad = IntTypeFlags.isQuad(); - switch (IntTypeFlags.getEltType()) { - case NeonTypeFlags::Int16: - return llvm::VectorType::get(CGF->HalfTy, (4 << IsQuad)); - case NeonTypeFlags::Int32: - return llvm::VectorType::get(CGF->FloatTy, (2 << IsQuad)); - case NeonTypeFlags::Int64: - return llvm::VectorType::get(CGF->DoubleTy, (1 << IsQuad)); - default: - llvm_unreachable("Type can't be converted to floating-point!"); - } -} - -Value *CodeGenFunction::EmitNeonSplat(Value *V, Constant *C) { - unsigned nElts = V->getType()->getVectorNumElements(); - Value* SV = llvm::ConstantVector::getSplat(nElts, C); - return Builder.CreateShuffleVector(V, V, SV, "lane"); -} - -Value *CodeGenFunction::EmitNeonCall(Function *F, SmallVectorImpl<Value*> &Ops, - const char *name, - unsigned shift, bool rightshift) { - unsigned j = 0; - for (Function::const_arg_iterator ai = F->arg_begin(), ae = F->arg_end(); - ai != ae; ++ai, ++j) - if (shift > 0 && shift == j) - Ops[j] = EmitNeonShiftVector(Ops[j], ai->getType(), rightshift); - else - Ops[j] = Builder.CreateBitCast(Ops[j], ai->getType(), name); - - return Builder.CreateCall(F, Ops, name); -} - -Value *CodeGenFunction::EmitNeonShiftVector(Value *V, llvm::Type *Ty, - bool neg) { - int SV = cast<ConstantInt>(V)->getSExtValue(); - return ConstantInt::get(Ty, neg ? -SV : SV); -} - -// Right-shift a vector by a constant. -Value *CodeGenFunction::EmitNeonRShiftImm(Value *Vec, Value *Shift, - llvm::Type *Ty, bool usgn, - const char *name) { - llvm::VectorType *VTy = cast<llvm::VectorType>(Ty); - - int ShiftAmt = cast<ConstantInt>(Shift)->getSExtValue(); - int EltSize = VTy->getScalarSizeInBits(); - - Vec = Builder.CreateBitCast(Vec, Ty); - - // lshr/ashr are undefined when the shift amount is equal to the vector - // element size. - if (ShiftAmt == EltSize) { - if (usgn) { - // Right-shifting an unsigned value by its size yields 0. - return llvm::ConstantAggregateZero::get(VTy); - } else { - // Right-shifting a signed value by its size is equivalent - // to a shift of size-1. - --ShiftAmt; - Shift = ConstantInt::get(VTy->getElementType(), ShiftAmt); - } - } - - Shift = EmitNeonShiftVector(Shift, Ty, false); - if (usgn) - return Builder.CreateLShr(Vec, Shift, name); - else - return Builder.CreateAShr(Vec, Shift, name); -} - -enum { - AddRetType = (1 << 0), - Add1ArgType = (1 << 1), - Add2ArgTypes = (1 << 2), - - VectorizeRetType = (1 << 3), - VectorizeArgTypes = (1 << 4), - - InventFloatType = (1 << 5), - UnsignedAlts = (1 << 6), - - Use64BitVectors = (1 << 7), - Use128BitVectors = (1 << 8), - - Vectorize1ArgType = Add1ArgType | VectorizeArgTypes, - VectorRet = AddRetType | VectorizeRetType, - VectorRetGetArgs01 = - AddRetType | Add2ArgTypes | VectorizeRetType | VectorizeArgTypes, - FpCmpzModifiers = - AddRetType | VectorizeRetType | Add1ArgType | InventFloatType -}; - -namespace { -struct NeonIntrinsicInfo { - const char *NameHint; - unsigned BuiltinID; - unsigned LLVMIntrinsic; - unsigned AltLLVMIntrinsic; - unsigned TypeModifier; - - bool operator<(unsigned RHSBuiltinID) const { - return BuiltinID < RHSBuiltinID; - } - bool operator<(const NeonIntrinsicInfo &TE) const { - return BuiltinID < TE.BuiltinID; - } -}; -} // end anonymous namespace - -#define NEONMAP0(NameBase) \ - { #NameBase, NEON::BI__builtin_neon_ ## NameBase, 0, 0, 0 } - -#define NEONMAP1(NameBase, LLVMIntrinsic, TypeModifier) \ - { #NameBase, NEON:: BI__builtin_neon_ ## NameBase, \ - Intrinsic::LLVMIntrinsic, 0, TypeModifier } - -#define NEONMAP2(NameBase, LLVMIntrinsic, AltLLVMIntrinsic, TypeModifier) \ - { #NameBase, NEON:: BI__builtin_neon_ ## NameBase, \ - Intrinsic::LLVMIntrinsic, Intrinsic::AltLLVMIntrinsic, \ - TypeModifier } - -static const NeonIntrinsicInfo ARMSIMDIntrinsicMap [] = { - NEONMAP2(vabd_v, arm_neon_vabdu, arm_neon_vabds, Add1ArgType | UnsignedAlts), - NEONMAP2(vabdq_v, arm_neon_vabdu, arm_neon_vabds, Add1ArgType | UnsignedAlts), - NEONMAP1(vabs_v, arm_neon_vabs, 0), - NEONMAP1(vabsq_v, arm_neon_vabs, 0), - NEONMAP0(vaddhn_v), - NEONMAP1(vaesdq_v, arm_neon_aesd, 0), - NEONMAP1(vaeseq_v, arm_neon_aese, 0), - NEONMAP1(vaesimcq_v, arm_neon_aesimc, 0), - NEONMAP1(vaesmcq_v, arm_neon_aesmc, 0), - NEONMAP1(vbsl_v, arm_neon_vbsl, AddRetType), - NEONMAP1(vbslq_v, arm_neon_vbsl, AddRetType), - NEONMAP1(vcage_v, arm_neon_vacge, 0), - NEONMAP1(vcageq_v, arm_neon_vacge, 0), - NEONMAP1(vcagt_v, arm_neon_vacgt, 0), - NEONMAP1(vcagtq_v, arm_neon_vacgt, 0), - NEONMAP1(vcale_v, arm_neon_vacge, 0), - NEONMAP1(vcaleq_v, arm_neon_vacge, 0), - NEONMAP1(vcalt_v, arm_neon_vacgt, 0), - NEONMAP1(vcaltq_v, arm_neon_vacgt, 0), - NEONMAP0(vceqz_v), - NEONMAP0(vceqzq_v), - NEONMAP0(vcgez_v), - NEONMAP0(vcgezq_v), - NEONMAP0(vcgtz_v), - NEONMAP0(vcgtzq_v), - NEONMAP0(vclez_v), - NEONMAP0(vclezq_v), - NEONMAP1(vcls_v, arm_neon_vcls, Add1ArgType), - NEONMAP1(vclsq_v, arm_neon_vcls, Add1ArgType), - NEONMAP0(vcltz_v), - NEONMAP0(vcltzq_v), - NEONMAP1(vclz_v, ctlz, Add1ArgType), - NEONMAP1(vclzq_v, ctlz, Add1ArgType), - NEONMAP1(vcnt_v, ctpop, Add1ArgType), - NEONMAP1(vcntq_v, ctpop, Add1ArgType), - NEONMAP1(vcvt_f16_f32, arm_neon_vcvtfp2hf, 0), - NEONMAP0(vcvt_f16_v), - NEONMAP1(vcvt_f32_f16, arm_neon_vcvthf2fp, 0), - NEONMAP0(vcvt_f32_v), - NEONMAP2(vcvt_n_f16_v, arm_neon_vcvtfxu2fp, arm_neon_vcvtfxs2fp, 0), - NEONMAP2(vcvt_n_f32_v, arm_neon_vcvtfxu2fp, arm_neon_vcvtfxs2fp, 0), - NEONMAP1(vcvt_n_s16_v, arm_neon_vcvtfp2fxs, 0), - NEONMAP1(vcvt_n_s32_v, arm_neon_vcvtfp2fxs, 0), - NEONMAP1(vcvt_n_s64_v, arm_neon_vcvtfp2fxs, 0), - NEONMAP1(vcvt_n_u16_v, arm_neon_vcvtfp2fxu, 0), - NEONMAP1(vcvt_n_u32_v, arm_neon_vcvtfp2fxu, 0), - NEONMAP1(vcvt_n_u64_v, arm_neon_vcvtfp2fxu, 0), - NEONMAP0(vcvt_s16_v), - NEONMAP0(vcvt_s32_v), - NEONMAP0(vcvt_s64_v), - NEONMAP0(vcvt_u16_v), - NEONMAP0(vcvt_u32_v), - NEONMAP0(vcvt_u64_v), - NEONMAP1(vcvta_s16_v, arm_neon_vcvtas, 0), - NEONMAP1(vcvta_s32_v, arm_neon_vcvtas, 0), - NEONMAP1(vcvta_s64_v, arm_neon_vcvtas, 0), - NEONMAP1(vcvta_u16_v, arm_neon_vcvtau, 0), - NEONMAP1(vcvta_u32_v, arm_neon_vcvtau, 0), - NEONMAP1(vcvta_u64_v, arm_neon_vcvtau, 0), - NEONMAP1(vcvtaq_s16_v, arm_neon_vcvtas, 0), - NEONMAP1(vcvtaq_s32_v, arm_neon_vcvtas, 0), - NEONMAP1(vcvtaq_s64_v, arm_neon_vcvtas, 0), - NEONMAP1(vcvtaq_u16_v, arm_neon_vcvtau, 0), - NEONMAP1(vcvtaq_u32_v, arm_neon_vcvtau, 0), - NEONMAP1(vcvtaq_u64_v, arm_neon_vcvtau, 0), - NEONMAP1(vcvtm_s16_v, arm_neon_vcvtms, 0), - NEONMAP1(vcvtm_s32_v, arm_neon_vcvtms, 0), - NEONMAP1(vcvtm_s64_v, arm_neon_vcvtms, 0), - NEONMAP1(vcvtm_u16_v, arm_neon_vcvtmu, 0), - NEONMAP1(vcvtm_u32_v, arm_neon_vcvtmu, 0), - NEONMAP1(vcvtm_u64_v, arm_neon_vcvtmu, 0), - NEONMAP1(vcvtmq_s16_v, arm_neon_vcvtms, 0), - NEONMAP1(vcvtmq_s32_v, arm_neon_vcvtms, 0), - NEONMAP1(vcvtmq_s64_v, arm_neon_vcvtms, 0), - NEONMAP1(vcvtmq_u16_v, arm_neon_vcvtmu, 0), - NEONMAP1(vcvtmq_u32_v, arm_neon_vcvtmu, 0), - NEONMAP1(vcvtmq_u64_v, arm_neon_vcvtmu, 0), - NEONMAP1(vcvtn_s16_v, arm_neon_vcvtns, 0), - NEONMAP1(vcvtn_s32_v, arm_neon_vcvtns, 0), - NEONMAP1(vcvtn_s64_v, arm_neon_vcvtns, 0), - NEONMAP1(vcvtn_u16_v, arm_neon_vcvtnu, 0), - NEONMAP1(vcvtn_u32_v, arm_neon_vcvtnu, 0), - NEONMAP1(vcvtn_u64_v, arm_neon_vcvtnu, 0), - NEONMAP1(vcvtnq_s16_v, arm_neon_vcvtns, 0), - NEONMAP1(vcvtnq_s32_v, arm_neon_vcvtns, 0), - NEONMAP1(vcvtnq_s64_v, arm_neon_vcvtns, 0), - NEONMAP1(vcvtnq_u16_v, arm_neon_vcvtnu, 0), - NEONMAP1(vcvtnq_u32_v, arm_neon_vcvtnu, 0), - NEONMAP1(vcvtnq_u64_v, arm_neon_vcvtnu, 0), - NEONMAP1(vcvtp_s16_v, arm_neon_vcvtps, 0), - NEONMAP1(vcvtp_s32_v, arm_neon_vcvtps, 0), - NEONMAP1(vcvtp_s64_v, arm_neon_vcvtps, 0), - NEONMAP1(vcvtp_u16_v, arm_neon_vcvtpu, 0), - NEONMAP1(vcvtp_u32_v, arm_neon_vcvtpu, 0), - NEONMAP1(vcvtp_u64_v, arm_neon_vcvtpu, 0), - NEONMAP1(vcvtpq_s16_v, arm_neon_vcvtps, 0), - NEONMAP1(vcvtpq_s32_v, arm_neon_vcvtps, 0), - NEONMAP1(vcvtpq_s64_v, arm_neon_vcvtps, 0), - NEONMAP1(vcvtpq_u16_v, arm_neon_vcvtpu, 0), - NEONMAP1(vcvtpq_u32_v, arm_neon_vcvtpu, 0), - NEONMAP1(vcvtpq_u64_v, arm_neon_vcvtpu, 0), - NEONMAP0(vcvtq_f16_v), - NEONMAP0(vcvtq_f32_v), - NEONMAP2(vcvtq_n_f16_v, arm_neon_vcvtfxu2fp, arm_neon_vcvtfxs2fp, 0), - NEONMAP2(vcvtq_n_f32_v, arm_neon_vcvtfxu2fp, arm_neon_vcvtfxs2fp, 0), - NEONMAP1(vcvtq_n_s16_v, arm_neon_vcvtfp2fxs, 0), - NEONMAP1(vcvtq_n_s32_v, arm_neon_vcvtfp2fxs, 0), - NEONMAP1(vcvtq_n_s64_v, arm_neon_vcvtfp2fxs, 0), - NEONMAP1(vcvtq_n_u16_v, arm_neon_vcvtfp2fxu, 0), - NEONMAP1(vcvtq_n_u32_v, arm_neon_vcvtfp2fxu, 0), - NEONMAP1(vcvtq_n_u64_v, arm_neon_vcvtfp2fxu, 0), - NEONMAP0(vcvtq_s16_v), - NEONMAP0(vcvtq_s32_v), - NEONMAP0(vcvtq_s64_v), - NEONMAP0(vcvtq_u16_v), - NEONMAP0(vcvtq_u32_v), - NEONMAP0(vcvtq_u64_v), - NEONMAP2(vdot_v, arm_neon_udot, arm_neon_sdot, 0), - NEONMAP2(vdotq_v, arm_neon_udot, arm_neon_sdot, 0), - NEONMAP0(vext_v), - NEONMAP0(vextq_v), - NEONMAP0(vfma_v), - NEONMAP0(vfmaq_v), - NEONMAP2(vhadd_v, arm_neon_vhaddu, arm_neon_vhadds, Add1ArgType | UnsignedAlts), - NEONMAP2(vhaddq_v, arm_neon_vhaddu, arm_neon_vhadds, Add1ArgType | UnsignedAlts), - NEONMAP2(vhsub_v, arm_neon_vhsubu, arm_neon_vhsubs, Add1ArgType | UnsignedAlts), - NEONMAP2(vhsubq_v, arm_neon_vhsubu, arm_neon_vhsubs, Add1ArgType | UnsignedAlts), - NEONMAP0(vld1_dup_v), - NEONMAP1(vld1_v, arm_neon_vld1, 0), - NEONMAP1(vld1_x2_v, arm_neon_vld1x2, 0), - NEONMAP1(vld1_x3_v, arm_neon_vld1x3, 0), - NEONMAP1(vld1_x4_v, arm_neon_vld1x4, 0), - NEONMAP0(vld1q_dup_v), - NEONMAP1(vld1q_v, arm_neon_vld1, 0), - NEONMAP1(vld1q_x2_v, arm_neon_vld1x2, 0), - NEONMAP1(vld1q_x3_v, arm_neon_vld1x3, 0), - NEONMAP1(vld1q_x4_v, arm_neon_vld1x4, 0), - NEONMAP1(vld2_dup_v, arm_neon_vld2dup, 0), - NEONMAP1(vld2_lane_v, arm_neon_vld2lane, 0), - NEONMAP1(vld2_v, arm_neon_vld2, 0), - NEONMAP1(vld2q_dup_v, arm_neon_vld2dup, 0), - NEONMAP1(vld2q_lane_v, arm_neon_vld2lane, 0), - NEONMAP1(vld2q_v, arm_neon_vld2, 0), - NEONMAP1(vld3_dup_v, arm_neon_vld3dup, 0), - NEONMAP1(vld3_lane_v, arm_neon_vld3lane, 0), - NEONMAP1(vld3_v, arm_neon_vld3, 0), - NEONMAP1(vld3q_dup_v, arm_neon_vld3dup, 0), - NEONMAP1(vld3q_lane_v, arm_neon_vld3lane, 0), - NEONMAP1(vld3q_v, arm_neon_vld3, 0), - NEONMAP1(vld4_dup_v, arm_neon_vld4dup, 0), - NEONMAP1(vld4_lane_v, arm_neon_vld4lane, 0), - NEONMAP1(vld4_v, arm_neon_vld4, 0), - NEONMAP1(vld4q_dup_v, arm_neon_vld4dup, 0), - NEONMAP1(vld4q_lane_v, arm_neon_vld4lane, 0), - NEONMAP1(vld4q_v, arm_neon_vld4, 0), - NEONMAP2(vmax_v, arm_neon_vmaxu, arm_neon_vmaxs, Add1ArgType | UnsignedAlts), - NEONMAP1(vmaxnm_v, arm_neon_vmaxnm, Add1ArgType), - NEONMAP1(vmaxnmq_v, arm_neon_vmaxnm, Add1ArgType), - NEONMAP2(vmaxq_v, arm_neon_vmaxu, arm_neon_vmaxs, Add1ArgType | UnsignedAlts), - NEONMAP2(vmin_v, arm_neon_vminu, arm_neon_vmins, Add1ArgType | UnsignedAlts), - NEONMAP1(vminnm_v, arm_neon_vminnm, Add1ArgType), - NEONMAP1(vminnmq_v, arm_neon_vminnm, Add1ArgType), - NEONMAP2(vminq_v, arm_neon_vminu, arm_neon_vmins, Add1ArgType | UnsignedAlts), - NEONMAP0(vmovl_v), - NEONMAP0(vmovn_v), - NEONMAP1(vmul_v, arm_neon_vmulp, Add1ArgType), - NEONMAP0(vmull_v), - NEONMAP1(vmulq_v, arm_neon_vmulp, Add1ArgType), - NEONMAP2(vpadal_v, arm_neon_vpadalu, arm_neon_vpadals, UnsignedAlts), - NEONMAP2(vpadalq_v, arm_neon_vpadalu, arm_neon_vpadals, UnsignedAlts), - NEONMAP1(vpadd_v, arm_neon_vpadd, Add1ArgType), - NEONMAP2(vpaddl_v, arm_neon_vpaddlu, arm_neon_vpaddls, UnsignedAlts), - NEONMAP2(vpaddlq_v, arm_neon_vpaddlu, arm_neon_vpaddls, UnsignedAlts), - NEONMAP1(vpaddq_v, arm_neon_vpadd, Add1ArgType), - NEONMAP2(vpmax_v, arm_neon_vpmaxu, arm_neon_vpmaxs, Add1ArgType | UnsignedAlts), - NEONMAP2(vpmin_v, arm_neon_vpminu, arm_neon_vpmins, Add1ArgType | UnsignedAlts), - NEONMAP1(vqabs_v, arm_neon_vqabs, Add1ArgType), - NEONMAP1(vqabsq_v, arm_neon_vqabs, Add1ArgType), - NEONMAP2(vqadd_v, arm_neon_vqaddu, arm_neon_vqadds, Add1ArgType | UnsignedAlts), - NEONMAP2(vqaddq_v, arm_neon_vqaddu, arm_neon_vqadds, Add1ArgType | UnsignedAlts), - NEONMAP2(vqdmlal_v, arm_neon_vqdmull, arm_neon_vqadds, 0), - NEONMAP2(vqdmlsl_v, arm_neon_vqdmull, arm_neon_vqsubs, 0), - NEONMAP1(vqdmulh_v, arm_neon_vqdmulh, Add1ArgType), - NEONMAP1(vqdmulhq_v, arm_neon_vqdmulh, Add1ArgType), - NEONMAP1(vqdmull_v, arm_neon_vqdmull, Add1ArgType), - NEONMAP2(vqmovn_v, arm_neon_vqmovnu, arm_neon_vqmovns, Add1ArgType | UnsignedAlts), - NEONMAP1(vqmovun_v, arm_neon_vqmovnsu, Add1ArgType), - NEONMAP1(vqneg_v, arm_neon_vqneg, Add1ArgType), - NEONMAP1(vqnegq_v, arm_neon_vqneg, Add1ArgType), - NEONMAP1(vqrdmulh_v, arm_neon_vqrdmulh, Add1ArgType), - NEONMAP1(vqrdmulhq_v, arm_neon_vqrdmulh, Add1ArgType), - NEONMAP2(vqrshl_v, arm_neon_vqrshiftu, arm_neon_vqrshifts, Add1ArgType | UnsignedAlts), - NEONMAP2(vqrshlq_v, arm_neon_vqrshiftu, arm_neon_vqrshifts, Add1ArgType | UnsignedAlts), - NEONMAP2(vqshl_n_v, arm_neon_vqshiftu, arm_neon_vqshifts, UnsignedAlts), - NEONMAP2(vqshl_v, arm_neon_vqshiftu, arm_neon_vqshifts, Add1ArgType | UnsignedAlts), - NEONMAP2(vqshlq_n_v, arm_neon_vqshiftu, arm_neon_vqshifts, UnsignedAlts), - NEONMAP2(vqshlq_v, arm_neon_vqshiftu, arm_neon_vqshifts, Add1ArgType | UnsignedAlts), - NEONMAP1(vqshlu_n_v, arm_neon_vqshiftsu, 0), - NEONMAP1(vqshluq_n_v, arm_neon_vqshiftsu, 0), - NEONMAP2(vqsub_v, arm_neon_vqsubu, arm_neon_vqsubs, Add1ArgType | UnsignedAlts), - NEONMAP2(vqsubq_v, arm_neon_vqsubu, arm_neon_vqsubs, Add1ArgType | UnsignedAlts), - NEONMAP1(vraddhn_v, arm_neon_vraddhn, Add1ArgType), - NEONMAP2(vrecpe_v, arm_neon_vrecpe, arm_neon_vrecpe, 0), - NEONMAP2(vrecpeq_v, arm_neon_vrecpe, arm_neon_vrecpe, 0), - NEONMAP1(vrecps_v, arm_neon_vrecps, Add1ArgType), - NEONMAP1(vrecpsq_v, arm_neon_vrecps, Add1ArgType), - NEONMAP2(vrhadd_v, arm_neon_vrhaddu, arm_neon_vrhadds, Add1ArgType | UnsignedAlts), - NEONMAP2(vrhaddq_v, arm_neon_vrhaddu, arm_neon_vrhadds, Add1ArgType | UnsignedAlts), - NEONMAP1(vrnd_v, arm_neon_vrintz, Add1ArgType), - NEONMAP1(vrnda_v, arm_neon_vrinta, Add1ArgType), - NEONMAP1(vrndaq_v, arm_neon_vrinta, Add1ArgType), - NEONMAP0(vrndi_v), - NEONMAP0(vrndiq_v), - NEONMAP1(vrndm_v, arm_neon_vrintm, Add1ArgType), - NEONMAP1(vrndmq_v, arm_neon_vrintm, Add1ArgType), - NEONMAP1(vrndn_v, arm_neon_vrintn, Add1ArgType), - NEONMAP1(vrndnq_v, arm_neon_vrintn, Add1ArgType), - NEONMAP1(vrndp_v, arm_neon_vrintp, Add1ArgType), - NEONMAP1(vrndpq_v, arm_neon_vrintp, Add1ArgType), - NEONMAP1(vrndq_v, arm_neon_vrintz, Add1ArgType), - NEONMAP1(vrndx_v, arm_neon_vrintx, Add1ArgType), - NEONMAP1(vrndxq_v, arm_neon_vrintx, Add1ArgType), - NEONMAP2(vrshl_v, arm_neon_vrshiftu, arm_neon_vrshifts, Add1ArgType | UnsignedAlts), - NEONMAP2(vrshlq_v, arm_neon_vrshiftu, arm_neon_vrshifts, Add1ArgType | UnsignedAlts), - NEONMAP2(vrshr_n_v, arm_neon_vrshiftu, arm_neon_vrshifts, UnsignedAlts), - NEONMAP2(vrshrq_n_v, arm_neon_vrshiftu, arm_neon_vrshifts, UnsignedAlts), - NEONMAP2(vrsqrte_v, arm_neon_vrsqrte, arm_neon_vrsqrte, 0), - NEONMAP2(vrsqrteq_v, arm_neon_vrsqrte, arm_neon_vrsqrte, 0), - NEONMAP1(vrsqrts_v, arm_neon_vrsqrts, Add1ArgType), - NEONMAP1(vrsqrtsq_v, arm_neon_vrsqrts, Add1ArgType), - NEONMAP1(vrsubhn_v, arm_neon_vrsubhn, Add1ArgType), - NEONMAP1(vsha1su0q_v, arm_neon_sha1su0, 0), - NEONMAP1(vsha1su1q_v, arm_neon_sha1su1, 0), - NEONMAP1(vsha256h2q_v, arm_neon_sha256h2, 0), - NEONMAP1(vsha256hq_v, arm_neon_sha256h, 0), - NEONMAP1(vsha256su0q_v, arm_neon_sha256su0, 0), - NEONMAP1(vsha256su1q_v, arm_neon_sha256su1, 0), - NEONMAP0(vshl_n_v), - NEONMAP2(vshl_v, arm_neon_vshiftu, arm_neon_vshifts, Add1ArgType | UnsignedAlts), - NEONMAP0(vshll_n_v), - NEONMAP0(vshlq_n_v), - NEONMAP2(vshlq_v, arm_neon_vshiftu, arm_neon_vshifts, Add1ArgType | UnsignedAlts), - NEONMAP0(vshr_n_v), - NEONMAP0(vshrn_n_v), - NEONMAP0(vshrq_n_v), - NEONMAP1(vst1_v, arm_neon_vst1, 0), - NEONMAP1(vst1_x2_v, arm_neon_vst1x2, 0), - NEONMAP1(vst1_x3_v, arm_neon_vst1x3, 0), - NEONMAP1(vst1_x4_v, arm_neon_vst1x4, 0), - NEONMAP1(vst1q_v, arm_neon_vst1, 0), - NEONMAP1(vst1q_x2_v, arm_neon_vst1x2, 0), - NEONMAP1(vst1q_x3_v, arm_neon_vst1x3, 0), - NEONMAP1(vst1q_x4_v, arm_neon_vst1x4, 0), - NEONMAP1(vst2_lane_v, arm_neon_vst2lane, 0), - NEONMAP1(vst2_v, arm_neon_vst2, 0), - NEONMAP1(vst2q_lane_v, arm_neon_vst2lane, 0), - NEONMAP1(vst2q_v, arm_neon_vst2, 0), - NEONMAP1(vst3_lane_v, arm_neon_vst3lane, 0), - NEONMAP1(vst3_v, arm_neon_vst3, 0), - NEONMAP1(vst3q_lane_v, arm_neon_vst3lane, 0), - NEONMAP1(vst3q_v, arm_neon_vst3, 0), - NEONMAP1(vst4_lane_v, arm_neon_vst4lane, 0), - NEONMAP1(vst4_v, arm_neon_vst4, 0), - NEONMAP1(vst4q_lane_v, arm_neon_vst4lane, 0), - NEONMAP1(vst4q_v, arm_neon_vst4, 0), - NEONMAP0(vsubhn_v), - NEONMAP0(vtrn_v), - NEONMAP0(vtrnq_v), - NEONMAP0(vtst_v), - NEONMAP0(vtstq_v), - NEONMAP0(vuzp_v), - NEONMAP0(vuzpq_v), - NEONMAP0(vzip_v), - NEONMAP0(vzipq_v) -}; - -static const NeonIntrinsicInfo AArch64SIMDIntrinsicMap[] = { - NEONMAP1(vabs_v, aarch64_neon_abs, 0), - NEONMAP1(vabsq_v, aarch64_neon_abs, 0), - NEONMAP0(vaddhn_v), - NEONMAP1(vaesdq_v, aarch64_crypto_aesd, 0), - NEONMAP1(vaeseq_v, aarch64_crypto_aese, 0), - NEONMAP1(vaesimcq_v, aarch64_crypto_aesimc, 0), - NEONMAP1(vaesmcq_v, aarch64_crypto_aesmc, 0), - NEONMAP1(vcage_v, aarch64_neon_facge, 0), - NEONMAP1(vcageq_v, aarch64_neon_facge, 0), - NEONMAP1(vcagt_v, aarch64_neon_facgt, 0), - NEONMAP1(vcagtq_v, aarch64_neon_facgt, 0), - NEONMAP1(vcale_v, aarch64_neon_facge, 0), - NEONMAP1(vcaleq_v, aarch64_neon_facge, 0), - NEONMAP1(vcalt_v, aarch64_neon_facgt, 0), - NEONMAP1(vcaltq_v, aarch64_neon_facgt, 0), - NEONMAP0(vceqz_v), - NEONMAP0(vceqzq_v), - NEONMAP0(vcgez_v), - NEONMAP0(vcgezq_v), - NEONMAP0(vcgtz_v), - NEONMAP0(vcgtzq_v), - NEONMAP0(vclez_v), - NEONMAP0(vclezq_v), - NEONMAP1(vcls_v, aarch64_neon_cls, Add1ArgType), - NEONMAP1(vclsq_v, aarch64_neon_cls, Add1ArgType), - NEONMAP0(vcltz_v), - NEONMAP0(vcltzq_v), - NEONMAP1(vclz_v, ctlz, Add1ArgType), - NEONMAP1(vclzq_v, ctlz, Add1ArgType), - NEONMAP1(vcnt_v, ctpop, Add1ArgType), - NEONMAP1(vcntq_v, ctpop, Add1ArgType), - NEONMAP1(vcvt_f16_f32, aarch64_neon_vcvtfp2hf, 0), - NEONMAP0(vcvt_f16_v), - NEONMAP1(vcvt_f32_f16, aarch64_neon_vcvthf2fp, 0), - NEONMAP0(vcvt_f32_v), - NEONMAP2(vcvt_n_f16_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0), - NEONMAP2(vcvt_n_f32_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0), - NEONMAP2(vcvt_n_f64_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0), - NEONMAP1(vcvt_n_s16_v, aarch64_neon_vcvtfp2fxs, 0), - NEONMAP1(vcvt_n_s32_v, aarch64_neon_vcvtfp2fxs, 0), - NEONMAP1(vcvt_n_s64_v, aarch64_neon_vcvtfp2fxs, 0), - NEONMAP1(vcvt_n_u16_v, aarch64_neon_vcvtfp2fxu, 0), - NEONMAP1(vcvt_n_u32_v, aarch64_neon_vcvtfp2fxu, 0), - NEONMAP1(vcvt_n_u64_v, aarch64_neon_vcvtfp2fxu, 0), - NEONMAP0(vcvtq_f16_v), - NEONMAP0(vcvtq_f32_v), - NEONMAP2(vcvtq_n_f16_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0), - NEONMAP2(vcvtq_n_f32_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0), - NEONMAP2(vcvtq_n_f64_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0), - NEONMAP1(vcvtq_n_s16_v, aarch64_neon_vcvtfp2fxs, 0), - NEONMAP1(vcvtq_n_s32_v, aarch64_neon_vcvtfp2fxs, 0), - NEONMAP1(vcvtq_n_s64_v, aarch64_neon_vcvtfp2fxs, 0), - NEONMAP1(vcvtq_n_u16_v, aarch64_neon_vcvtfp2fxu, 0), - NEONMAP1(vcvtq_n_u32_v, aarch64_neon_vcvtfp2fxu, 0), - NEONMAP1(vcvtq_n_u64_v, aarch64_neon_vcvtfp2fxu, 0), - NEONMAP1(vcvtx_f32_v, aarch64_neon_fcvtxn, AddRetType | Add1ArgType), - NEONMAP2(vdot_v, aarch64_neon_udot, aarch64_neon_sdot, 0), - NEONMAP2(vdotq_v, aarch64_neon_udot, aarch64_neon_sdot, 0), - NEONMAP0(vext_v), - NEONMAP0(vextq_v), - NEONMAP0(vfma_v), - NEONMAP0(vfmaq_v), - NEONMAP1(vfmlal_high_v, aarch64_neon_fmlal2, 0), - NEONMAP1(vfmlal_low_v, aarch64_neon_fmlal, 0), - NEONMAP1(vfmlalq_high_v, aarch64_neon_fmlal2, 0), - NEONMAP1(vfmlalq_low_v, aarch64_neon_fmlal, 0), - NEONMAP1(vfmlsl_high_v, aarch64_neon_fmlsl2, 0), - NEONMAP1(vfmlsl_low_v, aarch64_neon_fmlsl, 0), - NEONMAP1(vfmlslq_high_v, aarch64_neon_fmlsl2, 0), - NEONMAP1(vfmlslq_low_v, aarch64_neon_fmlsl, 0), - NEONMAP2(vhadd_v, aarch64_neon_uhadd, aarch64_neon_shadd, Add1ArgType | UnsignedAlts), - NEONMAP2(vhaddq_v, aarch64_neon_uhadd, aarch64_neon_shadd, Add1ArgType | UnsignedAlts), - NEONMAP2(vhsub_v, aarch64_neon_uhsub, aarch64_neon_shsub, Add1ArgType | UnsignedAlts), - NEONMAP2(vhsubq_v, aarch64_neon_uhsub, aarch64_neon_shsub, Add1ArgType | UnsignedAlts), - NEONMAP1(vld1_x2_v, aarch64_neon_ld1x2, 0), - NEONMAP1(vld1_x3_v, aarch64_neon_ld1x3, 0), - NEONMAP1(vld1_x4_v, aarch64_neon_ld1x4, 0), - NEONMAP1(vld1q_x2_v, aarch64_neon_ld1x2, 0), - NEONMAP1(vld1q_x3_v, aarch64_neon_ld1x3, 0), - NEONMAP1(vld1q_x4_v, aarch64_neon_ld1x4, 0), - NEONMAP0(vmovl_v), - NEONMAP0(vmovn_v), - NEONMAP1(vmul_v, aarch64_neon_pmul, Add1ArgType), - NEONMAP1(vmulq_v, aarch64_neon_pmul, Add1ArgType), - NEONMAP1(vpadd_v, aarch64_neon_addp, Add1ArgType), - NEONMAP2(vpaddl_v, aarch64_neon_uaddlp, aarch64_neon_saddlp, UnsignedAlts), - NEONMAP2(vpaddlq_v, aarch64_neon_uaddlp, aarch64_neon_saddlp, UnsignedAlts), - NEONMAP1(vpaddq_v, aarch64_neon_addp, Add1ArgType), - NEONMAP1(vqabs_v, aarch64_neon_sqabs, Add1ArgType), - NEONMAP1(vqabsq_v, aarch64_neon_sqabs, Add1ArgType), - NEONMAP2(vqadd_v, aarch64_neon_uqadd, aarch64_neon_sqadd, Add1ArgType | UnsignedAlts), - NEONMAP2(vqaddq_v, aarch64_neon_uqadd, aarch64_neon_sqadd, Add1ArgType | UnsignedAlts), - NEONMAP2(vqdmlal_v, aarch64_neon_sqdmull, aarch64_neon_sqadd, 0), - NEONMAP2(vqdmlsl_v, aarch64_neon_sqdmull, aarch64_neon_sqsub, 0), - NEONMAP1(vqdmulh_v, aarch64_neon_sqdmulh, Add1ArgType), - NEONMAP1(vqdmulhq_v, aarch64_neon_sqdmulh, Add1ArgType), - NEONMAP1(vqdmull_v, aarch64_neon_sqdmull, Add1ArgType), - NEONMAP2(vqmovn_v, aarch64_neon_uqxtn, aarch64_neon_sqxtn, Add1ArgType | UnsignedAlts), - NEONMAP1(vqmovun_v, aarch64_neon_sqxtun, Add1ArgType), - NEONMAP1(vqneg_v, aarch64_neon_sqneg, Add1ArgType), - NEONMAP1(vqnegq_v, aarch64_neon_sqneg, Add1ArgType), - NEONMAP1(vqrdmulh_v, aarch64_neon_sqrdmulh, Add1ArgType), - NEONMAP1(vqrdmulhq_v, aarch64_neon_sqrdmulh, Add1ArgType), - NEONMAP2(vqrshl_v, aarch64_neon_uqrshl, aarch64_neon_sqrshl, Add1ArgType | UnsignedAlts), - NEONMAP2(vqrshlq_v, aarch64_neon_uqrshl, aarch64_neon_sqrshl, Add1ArgType | UnsignedAlts), - NEONMAP2(vqshl_n_v, aarch64_neon_uqshl, aarch64_neon_sqshl, UnsignedAlts), - NEONMAP2(vqshl_v, aarch64_neon_uqshl, aarch64_neon_sqshl, Add1ArgType | UnsignedAlts), - NEONMAP2(vqshlq_n_v, aarch64_neon_uqshl, aarch64_neon_sqshl,UnsignedAlts), - NEONMAP2(vqshlq_v, aarch64_neon_uqshl, aarch64_neon_sqshl, Add1ArgType | UnsignedAlts), - NEONMAP1(vqshlu_n_v, aarch64_neon_sqshlu, 0), - NEONMAP1(vqshluq_n_v, aarch64_neon_sqshlu, 0), - NEONMAP2(vqsub_v, aarch64_neon_uqsub, aarch64_neon_sqsub, Add1ArgType | UnsignedAlts), - NEONMAP2(vqsubq_v, aarch64_neon_uqsub, aarch64_neon_sqsub, Add1ArgType | UnsignedAlts), - NEONMAP1(vraddhn_v, aarch64_neon_raddhn, Add1ArgType), - NEONMAP2(vrecpe_v, aarch64_neon_frecpe, aarch64_neon_urecpe, 0), - NEONMAP2(vrecpeq_v, aarch64_neon_frecpe, aarch64_neon_urecpe, 0), - NEONMAP1(vrecps_v, aarch64_neon_frecps, Add1ArgType), - NEONMAP1(vrecpsq_v, aarch64_neon_frecps, Add1ArgType), - NEONMAP2(vrhadd_v, aarch64_neon_urhadd, aarch64_neon_srhadd, Add1ArgType | UnsignedAlts), - NEONMAP2(vrhaddq_v, aarch64_neon_urhadd, aarch64_neon_srhadd, Add1ArgType | UnsignedAlts), - NEONMAP0(vrndi_v), - NEONMAP0(vrndiq_v), - NEONMAP2(vrshl_v, aarch64_neon_urshl, aarch64_neon_srshl, Add1ArgType | UnsignedAlts), - NEONMAP2(vrshlq_v, aarch64_neon_urshl, aarch64_neon_srshl, Add1ArgType | UnsignedAlts), - NEONMAP2(vrshr_n_v, aarch64_neon_urshl, aarch64_neon_srshl, UnsignedAlts), - NEONMAP2(vrshrq_n_v, aarch64_neon_urshl, aarch64_neon_srshl, UnsignedAlts), - NEONMAP2(vrsqrte_v, aarch64_neon_frsqrte, aarch64_neon_ursqrte, 0), - NEONMAP2(vrsqrteq_v, aarch64_neon_frsqrte, aarch64_neon_ursqrte, 0), - NEONMAP1(vrsqrts_v, aarch64_neon_frsqrts, Add1ArgType), - NEONMAP1(vrsqrtsq_v, aarch64_neon_frsqrts, Add1ArgType), - NEONMAP1(vrsubhn_v, aarch64_neon_rsubhn, Add1ArgType), - NEONMAP1(vsha1su0q_v, aarch64_crypto_sha1su0, 0), - NEONMAP1(vsha1su1q_v, aarch64_crypto_sha1su1, 0), - NEONMAP1(vsha256h2q_v, aarch64_crypto_sha256h2, 0), - NEONMAP1(vsha256hq_v, aarch64_crypto_sha256h, 0), - NEONMAP1(vsha256su0q_v, aarch64_crypto_sha256su0, 0), - NEONMAP1(vsha256su1q_v, aarch64_crypto_sha256su1, 0), - NEONMAP0(vshl_n_v), - NEONMAP2(vshl_v, aarch64_neon_ushl, aarch64_neon_sshl, Add1ArgType | UnsignedAlts), - NEONMAP0(vshll_n_v), - NEONMAP0(vshlq_n_v), - NEONMAP2(vshlq_v, aarch64_neon_ushl, aarch64_neon_sshl, Add1ArgType | UnsignedAlts), - NEONMAP0(vshr_n_v), - NEONMAP0(vshrn_n_v), - NEONMAP0(vshrq_n_v), - NEONMAP1(vst1_x2_v, aarch64_neon_st1x2, 0), - NEONMAP1(vst1_x3_v, aarch64_neon_st1x3, 0), - NEONMAP1(vst1_x4_v, aarch64_neon_st1x4, 0), - NEONMAP1(vst1q_x2_v, aarch64_neon_st1x2, 0), - NEONMAP1(vst1q_x3_v, aarch64_neon_st1x3, 0), - NEONMAP1(vst1q_x4_v, aarch64_neon_st1x4, 0), - NEONMAP0(vsubhn_v), - NEONMAP0(vtst_v), - NEONMAP0(vtstq_v), -}; - -static const NeonIntrinsicInfo AArch64SISDIntrinsicMap[] = { - NEONMAP1(vabdd_f64, aarch64_sisd_fabd, Add1ArgType), - NEONMAP1(vabds_f32, aarch64_sisd_fabd, Add1ArgType), - NEONMAP1(vabsd_s64, aarch64_neon_abs, Add1ArgType), - NEONMAP1(vaddlv_s32, aarch64_neon_saddlv, AddRetType | Add1ArgType), - NEONMAP1(vaddlv_u32, aarch64_neon_uaddlv, AddRetType | Add1ArgType), - NEONMAP1(vaddlvq_s32, aarch64_neon_saddlv, AddRetType | Add1ArgType), - NEONMAP1(vaddlvq_u32, aarch64_neon_uaddlv, AddRetType | Add1ArgType), - NEONMAP1(vaddv_f32, aarch64_neon_faddv, AddRetType | Add1ArgType), - NEONMAP1(vaddv_s32, aarch64_neon_saddv, AddRetType | Add1ArgType), - NEONMAP1(vaddv_u32, aarch64_neon_uaddv, AddRetType | Add1ArgType), - NEONMAP1(vaddvq_f32, aarch64_neon_faddv, AddRetType | Add1ArgType), - NEONMAP1(vaddvq_f64, aarch64_neon_faddv, AddRetType | Add1ArgType), - NEONMAP1(vaddvq_s32, aarch64_neon_saddv, AddRetType | Add1ArgType), - NEONMAP1(vaddvq_s64, aarch64_neon_saddv, AddRetType | Add1ArgType), - NEONMAP1(vaddvq_u32, aarch64_neon_uaddv, AddRetType | Add1ArgType), - NEONMAP1(vaddvq_u64, aarch64_neon_uaddv, AddRetType | Add1ArgType), - NEONMAP1(vcaged_f64, aarch64_neon_facge, AddRetType | Add1ArgType), - NEONMAP1(vcages_f32, aarch64_neon_facge, AddRetType | Add1ArgType), - NEONMAP1(vcagtd_f64, aarch64_neon_facgt, AddRetType | Add1ArgType), - NEONMAP1(vcagts_f32, aarch64_neon_facgt, AddRetType | Add1ArgType), - NEONMAP1(vcaled_f64, aarch64_neon_facge, AddRetType | Add1ArgType), - NEONMAP1(vcales_f32, aarch64_neon_facge, AddRetType | Add1ArgType), - NEONMAP1(vcaltd_f64, aarch64_neon_facgt, AddRetType | Add1ArgType), - NEONMAP1(vcalts_f32, aarch64_neon_facgt, AddRetType | Add1ArgType), - NEONMAP1(vcvtad_s64_f64, aarch64_neon_fcvtas, AddRetType | Add1ArgType), - NEONMAP1(vcvtad_u64_f64, aarch64_neon_fcvtau, AddRetType | Add1ArgType), - NEONMAP1(vcvtas_s32_f32, aarch64_neon_fcvtas, AddRetType | Add1ArgType), - NEONMAP1(vcvtas_u32_f32, aarch64_neon_fcvtau, AddRetType | Add1ArgType), - NEONMAP1(vcvtd_n_f64_s64, aarch64_neon_vcvtfxs2fp, AddRetType | Add1ArgType), - NEONMAP1(vcvtd_n_f64_u64, aarch64_neon_vcvtfxu2fp, AddRetType | Add1ArgType), - NEONMAP1(vcvtd_n_s64_f64, aarch64_neon_vcvtfp2fxs, AddRetType | Add1ArgType), - NEONMAP1(vcvtd_n_u64_f64, aarch64_neon_vcvtfp2fxu, AddRetType | Add1ArgType), - NEONMAP1(vcvtmd_s64_f64, aarch64_neon_fcvtms, AddRetType | Add1ArgType), - NEONMAP1(vcvtmd_u64_f64, aarch64_neon_fcvtmu, AddRetType | Add1ArgType), - NEONMAP1(vcvtms_s32_f32, aarch64_neon_fcvtms, AddRetType | Add1ArgType), - NEONMAP1(vcvtms_u32_f32, aarch64_neon_fcvtmu, AddRetType | Add1ArgType), - NEONMAP1(vcvtnd_s64_f64, aarch64_neon_fcvtns, AddRetType | Add1ArgType), - NEONMAP1(vcvtnd_u64_f64, aarch64_neon_fcvtnu, AddRetType | Add1ArgType), - NEONMAP1(vcvtns_s32_f32, aarch64_neon_fcvtns, AddRetType | Add1ArgType), - NEONMAP1(vcvtns_u32_f32, aarch64_neon_fcvtnu, AddRetType | Add1ArgType), - NEONMAP1(vcvtpd_s64_f64, aarch64_neon_fcvtps, AddRetType | Add1ArgType), - NEONMAP1(vcvtpd_u64_f64, aarch64_neon_fcvtpu, AddRetType | Add1ArgType), - NEONMAP1(vcvtps_s32_f32, aarch64_neon_fcvtps, AddRetType | Add1ArgType), - NEONMAP1(vcvtps_u32_f32, aarch64_neon_fcvtpu, AddRetType | Add1ArgType), - NEONMAP1(vcvts_n_f32_s32, aarch64_neon_vcvtfxs2fp, AddRetType | Add1ArgType), - NEONMAP1(vcvts_n_f32_u32, aarch64_neon_vcvtfxu2fp, AddRetType | Add1ArgType), - NEONMAP1(vcvts_n_s32_f32, aarch64_neon_vcvtfp2fxs, AddRetType | Add1ArgType), - NEONMAP1(vcvts_n_u32_f32, aarch64_neon_vcvtfp2fxu, AddRetType | Add1ArgType), - NEONMAP1(vcvtxd_f32_f64, aarch64_sisd_fcvtxn, 0), - NEONMAP1(vmaxnmv_f32, aarch64_neon_fmaxnmv, AddRetType | Add1ArgType), - NEONMAP1(vmaxnmvq_f32, aarch64_neon_fmaxnmv, AddRetType | Add1ArgType), - NEONMAP1(vmaxnmvq_f64, aarch64_neon_fmaxnmv, AddRetType | Add1ArgType), - NEONMAP1(vmaxv_f32, aarch64_neon_fmaxv, AddRetType | Add1ArgType), - NEONMAP1(vmaxv_s32, aarch64_neon_smaxv, AddRetType | Add1ArgType), - NEONMAP1(vmaxv_u32, aarch64_neon_umaxv, AddRetType | Add1ArgType), - NEONMAP1(vmaxvq_f32, aarch64_neon_fmaxv, AddRetType | Add1ArgType), - NEONMAP1(vmaxvq_f64, aarch64_neon_fmaxv, AddRetType | Add1ArgType), - NEONMAP1(vmaxvq_s32, aarch64_neon_smaxv, AddRetType | Add1ArgType), - NEONMAP1(vmaxvq_u32, aarch64_neon_umaxv, AddRetType | Add1ArgType), - NEONMAP1(vminnmv_f32, aarch64_neon_fminnmv, AddRetType | Add1ArgType), - NEONMAP1(vminnmvq_f32, aarch64_neon_fminnmv, AddRetType | Add1ArgType), - NEONMAP1(vminnmvq_f64, aarch64_neon_fminnmv, AddRetType | Add1ArgType), - NEONMAP1(vminv_f32, aarch64_neon_fminv, AddRetType | Add1ArgType), - NEONMAP1(vminv_s32, aarch64_neon_sminv, AddRetType | Add1ArgType), - NEONMAP1(vminv_u32, aarch64_neon_uminv, AddRetType | Add1ArgType), - NEONMAP1(vminvq_f32, aarch64_neon_fminv, AddRetType | Add1ArgType), - NEONMAP1(vminvq_f64, aarch64_neon_fminv, AddRetType | Add1ArgType), - NEONMAP1(vminvq_s32, aarch64_neon_sminv, AddRetType | Add1ArgType), - NEONMAP1(vminvq_u32, aarch64_neon_uminv, AddRetType | Add1ArgType), - NEONMAP1(vmull_p64, aarch64_neon_pmull64, 0), - NEONMAP1(vmulxd_f64, aarch64_neon_fmulx, Add1ArgType), - NEONMAP1(vmulxs_f32, aarch64_neon_fmulx, Add1ArgType), - NEONMAP1(vpaddd_s64, aarch64_neon_uaddv, AddRetType | Add1ArgType), - NEONMAP1(vpaddd_u64, aarch64_neon_uaddv, AddRetType | Add1ArgType), - NEONMAP1(vpmaxnmqd_f64, aarch64_neon_fmaxnmv, AddRetType | Add1ArgType), - NEONMAP1(vpmaxnms_f32, aarch64_neon_fmaxnmv, AddRetType | Add1ArgType), - NEONMAP1(vpmaxqd_f64, aarch64_neon_fmaxv, AddRetType | Add1ArgType), - NEONMAP1(vpmaxs_f32, aarch64_neon_fmaxv, AddRetType | Add1ArgType), - NEONMAP1(vpminnmqd_f64, aarch64_neon_fminnmv, AddRetType | Add1ArgType), - NEONMAP1(vpminnms_f32, aarch64_neon_fminnmv, AddRetType | Add1ArgType), - NEONMAP1(vpminqd_f64, aarch64_neon_fminv, AddRetType | Add1ArgType), - NEONMAP1(vpmins_f32, aarch64_neon_fminv, AddRetType | Add1ArgType), - NEONMAP1(vqabsb_s8, aarch64_neon_sqabs, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqabsd_s64, aarch64_neon_sqabs, Add1ArgType), - NEONMAP1(vqabsh_s16, aarch64_neon_sqabs, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqabss_s32, aarch64_neon_sqabs, Add1ArgType), - NEONMAP1(vqaddb_s8, aarch64_neon_sqadd, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqaddb_u8, aarch64_neon_uqadd, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqaddd_s64, aarch64_neon_sqadd, Add1ArgType), - NEONMAP1(vqaddd_u64, aarch64_neon_uqadd, Add1ArgType), - NEONMAP1(vqaddh_s16, aarch64_neon_sqadd, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqaddh_u16, aarch64_neon_uqadd, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqadds_s32, aarch64_neon_sqadd, Add1ArgType), - NEONMAP1(vqadds_u32, aarch64_neon_uqadd, Add1ArgType), - NEONMAP1(vqdmulhh_s16, aarch64_neon_sqdmulh, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqdmulhs_s32, aarch64_neon_sqdmulh, Add1ArgType), - NEONMAP1(vqdmullh_s16, aarch64_neon_sqdmull, VectorRet | Use128BitVectors), - NEONMAP1(vqdmulls_s32, aarch64_neon_sqdmulls_scalar, 0), - NEONMAP1(vqmovnd_s64, aarch64_neon_scalar_sqxtn, AddRetType | Add1ArgType), - NEONMAP1(vqmovnd_u64, aarch64_neon_scalar_uqxtn, AddRetType | Add1ArgType), - NEONMAP1(vqmovnh_s16, aarch64_neon_sqxtn, VectorRet | Use64BitVectors), - NEONMAP1(vqmovnh_u16, aarch64_neon_uqxtn, VectorRet | Use64BitVectors), - NEONMAP1(vqmovns_s32, aarch64_neon_sqxtn, VectorRet | Use64BitVectors), - NEONMAP1(vqmovns_u32, aarch64_neon_uqxtn, VectorRet | Use64BitVectors), - NEONMAP1(vqmovund_s64, aarch64_neon_scalar_sqxtun, AddRetType | Add1ArgType), - NEONMAP1(vqmovunh_s16, aarch64_neon_sqxtun, VectorRet | Use64BitVectors), - NEONMAP1(vqmovuns_s32, aarch64_neon_sqxtun, VectorRet | Use64BitVectors), - NEONMAP1(vqnegb_s8, aarch64_neon_sqneg, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqnegd_s64, aarch64_neon_sqneg, Add1ArgType), - NEONMAP1(vqnegh_s16, aarch64_neon_sqneg, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqnegs_s32, aarch64_neon_sqneg, Add1ArgType), - NEONMAP1(vqrdmulhh_s16, aarch64_neon_sqrdmulh, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqrdmulhs_s32, aarch64_neon_sqrdmulh, Add1ArgType), - NEONMAP1(vqrshlb_s8, aarch64_neon_sqrshl, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqrshlb_u8, aarch64_neon_uqrshl, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqrshld_s64, aarch64_neon_sqrshl, Add1ArgType), - NEONMAP1(vqrshld_u64, aarch64_neon_uqrshl, Add1ArgType), - NEONMAP1(vqrshlh_s16, aarch64_neon_sqrshl, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqrshlh_u16, aarch64_neon_uqrshl, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqrshls_s32, aarch64_neon_sqrshl, Add1ArgType), - NEONMAP1(vqrshls_u32, aarch64_neon_uqrshl, Add1ArgType), - NEONMAP1(vqrshrnd_n_s64, aarch64_neon_sqrshrn, AddRetType), - NEONMAP1(vqrshrnd_n_u64, aarch64_neon_uqrshrn, AddRetType), - NEONMAP1(vqrshrnh_n_s16, aarch64_neon_sqrshrn, VectorRet | Use64BitVectors), - NEONMAP1(vqrshrnh_n_u16, aarch64_neon_uqrshrn, VectorRet | Use64BitVectors), - NEONMAP1(vqrshrns_n_s32, aarch64_neon_sqrshrn, VectorRet | Use64BitVectors), - NEONMAP1(vqrshrns_n_u32, aarch64_neon_uqrshrn, VectorRet | Use64BitVectors), - NEONMAP1(vqrshrund_n_s64, aarch64_neon_sqrshrun, AddRetType), - NEONMAP1(vqrshrunh_n_s16, aarch64_neon_sqrshrun, VectorRet | Use64BitVectors), - NEONMAP1(vqrshruns_n_s32, aarch64_neon_sqrshrun, VectorRet | Use64BitVectors), - NEONMAP1(vqshlb_n_s8, aarch64_neon_sqshl, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqshlb_n_u8, aarch64_neon_uqshl, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqshlb_s8, aarch64_neon_sqshl, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqshlb_u8, aarch64_neon_uqshl, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqshld_s64, aarch64_neon_sqshl, Add1ArgType), - NEONMAP1(vqshld_u64, aarch64_neon_uqshl, Add1ArgType), - NEONMAP1(vqshlh_n_s16, aarch64_neon_sqshl, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqshlh_n_u16, aarch64_neon_uqshl, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqshlh_s16, aarch64_neon_sqshl, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqshlh_u16, aarch64_neon_uqshl, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqshls_n_s32, aarch64_neon_sqshl, Add1ArgType), - NEONMAP1(vqshls_n_u32, aarch64_neon_uqshl, Add1ArgType), - NEONMAP1(vqshls_s32, aarch64_neon_sqshl, Add1ArgType), - NEONMAP1(vqshls_u32, aarch64_neon_uqshl, Add1ArgType), - NEONMAP1(vqshlub_n_s8, aarch64_neon_sqshlu, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqshluh_n_s16, aarch64_neon_sqshlu, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqshlus_n_s32, aarch64_neon_sqshlu, Add1ArgType), - NEONMAP1(vqshrnd_n_s64, aarch64_neon_sqshrn, AddRetType), - NEONMAP1(vqshrnd_n_u64, aarch64_neon_uqshrn, AddRetType), - NEONMAP1(vqshrnh_n_s16, aarch64_neon_sqshrn, VectorRet | Use64BitVectors), - NEONMAP1(vqshrnh_n_u16, aarch64_neon_uqshrn, VectorRet | Use64BitVectors), - NEONMAP1(vqshrns_n_s32, aarch64_neon_sqshrn, VectorRet | Use64BitVectors), - NEONMAP1(vqshrns_n_u32, aarch64_neon_uqshrn, VectorRet | Use64BitVectors), - NEONMAP1(vqshrund_n_s64, aarch64_neon_sqshrun, AddRetType), - NEONMAP1(vqshrunh_n_s16, aarch64_neon_sqshrun, VectorRet | Use64BitVectors), - NEONMAP1(vqshruns_n_s32, aarch64_neon_sqshrun, VectorRet | Use64BitVectors), - NEONMAP1(vqsubb_s8, aarch64_neon_sqsub, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqsubb_u8, aarch64_neon_uqsub, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqsubd_s64, aarch64_neon_sqsub, Add1ArgType), - NEONMAP1(vqsubd_u64, aarch64_neon_uqsub, Add1ArgType), - NEONMAP1(vqsubh_s16, aarch64_neon_sqsub, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqsubh_u16, aarch64_neon_uqsub, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vqsubs_s32, aarch64_neon_sqsub, Add1ArgType), - NEONMAP1(vqsubs_u32, aarch64_neon_uqsub, Add1ArgType), - NEONMAP1(vrecped_f64, aarch64_neon_frecpe, Add1ArgType), - NEONMAP1(vrecpes_f32, aarch64_neon_frecpe, Add1ArgType), - NEONMAP1(vrecpxd_f64, aarch64_neon_frecpx, Add1ArgType), - NEONMAP1(vrecpxs_f32, aarch64_neon_frecpx, Add1ArgType), - NEONMAP1(vrshld_s64, aarch64_neon_srshl, Add1ArgType), - NEONMAP1(vrshld_u64, aarch64_neon_urshl, Add1ArgType), - NEONMAP1(vrsqrted_f64, aarch64_neon_frsqrte, Add1ArgType), - NEONMAP1(vrsqrtes_f32, aarch64_neon_frsqrte, Add1ArgType), - NEONMAP1(vrsqrtsd_f64, aarch64_neon_frsqrts, Add1ArgType), - NEONMAP1(vrsqrtss_f32, aarch64_neon_frsqrts, Add1ArgType), - NEONMAP1(vsha1cq_u32, aarch64_crypto_sha1c, 0), - NEONMAP1(vsha1h_u32, aarch64_crypto_sha1h, 0), - NEONMAP1(vsha1mq_u32, aarch64_crypto_sha1m, 0), - NEONMAP1(vsha1pq_u32, aarch64_crypto_sha1p, 0), - NEONMAP1(vshld_s64, aarch64_neon_sshl, Add1ArgType), - NEONMAP1(vshld_u64, aarch64_neon_ushl, Add1ArgType), - NEONMAP1(vslid_n_s64, aarch64_neon_vsli, Vectorize1ArgType), - NEONMAP1(vslid_n_u64, aarch64_neon_vsli, Vectorize1ArgType), - NEONMAP1(vsqaddb_u8, aarch64_neon_usqadd, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vsqaddd_u64, aarch64_neon_usqadd, Add1ArgType), - NEONMAP1(vsqaddh_u16, aarch64_neon_usqadd, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vsqadds_u32, aarch64_neon_usqadd, Add1ArgType), - NEONMAP1(vsrid_n_s64, aarch64_neon_vsri, Vectorize1ArgType), - NEONMAP1(vsrid_n_u64, aarch64_neon_vsri, Vectorize1ArgType), - NEONMAP1(vuqaddb_s8, aarch64_neon_suqadd, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vuqaddd_s64, aarch64_neon_suqadd, Add1ArgType), - NEONMAP1(vuqaddh_s16, aarch64_neon_suqadd, Vectorize1ArgType | Use64BitVectors), - NEONMAP1(vuqadds_s32, aarch64_neon_suqadd, Add1ArgType), - // FP16 scalar intrinisics go here. - NEONMAP1(vabdh_f16, aarch64_sisd_fabd, Add1ArgType), - NEONMAP1(vcvtah_s32_f16, aarch64_neon_fcvtas, AddRetType | Add1ArgType), - NEONMAP1(vcvtah_s64_f16, aarch64_neon_fcvtas, AddRetType | Add1ArgType), - NEONMAP1(vcvtah_u32_f16, aarch64_neon_fcvtau, AddRetType | Add1ArgType), - NEONMAP1(vcvtah_u64_f16, aarch64_neon_fcvtau, AddRetType | Add1ArgType), - NEONMAP1(vcvth_n_f16_s32, aarch64_neon_vcvtfxs2fp, AddRetType | Add1ArgType), - NEONMAP1(vcvth_n_f16_s64, aarch64_neon_vcvtfxs2fp, AddRetType | Add1ArgType), - NEONMAP1(vcvth_n_f16_u32, aarch64_neon_vcvtfxu2fp, AddRetType | Add1ArgType), - NEONMAP1(vcvth_n_f16_u64, aarch64_neon_vcvtfxu2fp, AddRetType | Add1ArgType), - NEONMAP1(vcvth_n_s32_f16, aarch64_neon_vcvtfp2fxs, AddRetType | Add1ArgType), - NEONMAP1(vcvth_n_s64_f16, aarch64_neon_vcvtfp2fxs, AddRetType | Add1ArgType), - NEONMAP1(vcvth_n_u32_f16, aarch64_neon_vcvtfp2fxu, AddRetType | Add1ArgType), - NEONMAP1(vcvth_n_u64_f16, aarch64_neon_vcvtfp2fxu, AddRetType | Add1ArgType), - NEONMAP1(vcvtmh_s32_f16, aarch64_neon_fcvtms, AddRetType | Add1ArgType), - NEONMAP1(vcvtmh_s64_f16, aarch64_neon_fcvtms, AddRetType | Add1ArgType), - NEONMAP1(vcvtmh_u32_f16, aarch64_neon_fcvtmu, AddRetType | Add1ArgType), - NEONMAP1(vcvtmh_u64_f16, aarch64_neon_fcvtmu, AddRetType | Add1ArgType), - NEONMAP1(vcvtnh_s32_f16, aarch64_neon_fcvtns, AddRetType | Add1ArgType), - NEONMAP1(vcvtnh_s64_f16, aarch64_neon_fcvtns, AddRetType | Add1ArgType), - NEONMAP1(vcvtnh_u32_f16, aarch64_neon_fcvtnu, AddRetType | Add1ArgType), - NEONMAP1(vcvtnh_u64_f16, aarch64_neon_fcvtnu, AddRetType | Add1ArgType), - NEONMAP1(vcvtph_s32_f16, aarch64_neon_fcvtps, AddRetType | Add1ArgType), - NEONMAP1(vcvtph_s64_f16, aarch64_neon_fcvtps, AddRetType | Add1ArgType), - NEONMAP1(vcvtph_u32_f16, aarch64_neon_fcvtpu, AddRetType | Add1ArgType), - NEONMAP1(vcvtph_u64_f16, aarch64_neon_fcvtpu, AddRetType | Add1ArgType), - NEONMAP1(vmulxh_f16, aarch64_neon_fmulx, Add1ArgType), - NEONMAP1(vrecpeh_f16, aarch64_neon_frecpe, Add1ArgType), - NEONMAP1(vrecpxh_f16, aarch64_neon_frecpx, Add1ArgType), - NEONMAP1(vrsqrteh_f16, aarch64_neon_frsqrte, Add1ArgType), - NEONMAP1(vrsqrtsh_f16, aarch64_neon_frsqrts, Add1ArgType), -}; - -#undef NEONMAP0 -#undef NEONMAP1 -#undef NEONMAP2 - -static bool NEONSIMDIntrinsicsProvenSorted = false; - -static bool AArch64SIMDIntrinsicsProvenSorted = false; -static bool AArch64SISDIntrinsicsProvenSorted = false; - - -static const NeonIntrinsicInfo * -findNeonIntrinsicInMap(ArrayRef<NeonIntrinsicInfo> IntrinsicMap, - unsigned BuiltinID, bool &MapProvenSorted) { - -#ifndef NDEBUG - if (!MapProvenSorted) { - assert(std::is_sorted(std::begin(IntrinsicMap), std::end(IntrinsicMap))); - MapProvenSorted = true; - } -#endif - - const NeonIntrinsicInfo *Builtin = - std::lower_bound(IntrinsicMap.begin(), IntrinsicMap.end(), BuiltinID); - - if (Builtin != IntrinsicMap.end() && Builtin->BuiltinID == BuiltinID) - return Builtin; - - return nullptr; -} - -Function *CodeGenFunction::LookupNeonLLVMIntrinsic(unsigned IntrinsicID, - unsigned Modifier, - llvm::Type *ArgType, - const CallExpr *E) { - int VectorSize = 0; - if (Modifier & Use64BitVectors) - VectorSize = 64; - else if (Modifier & Use128BitVectors) - VectorSize = 128; - - // Return type. - SmallVector<llvm::Type *, 3> Tys; - if (Modifier & AddRetType) { - llvm::Type *Ty = ConvertType(E->getCallReturnType(getContext())); - if (Modifier & VectorizeRetType) - Ty = llvm::VectorType::get( - Ty, VectorSize ? VectorSize / Ty->getPrimitiveSizeInBits() : 1); - - Tys.push_back(Ty); - } - - // Arguments. - if (Modifier & VectorizeArgTypes) { - int Elts = VectorSize ? VectorSize / ArgType->getPrimitiveSizeInBits() : 1; - ArgType = llvm::VectorType::get(ArgType, Elts); - } - - if (Modifier & (Add1ArgType | Add2ArgTypes)) - Tys.push_back(ArgType); - - if (Modifier & Add2ArgTypes) - Tys.push_back(ArgType); - - if (Modifier & InventFloatType) - Tys.push_back(FloatTy); - - return CGM.getIntrinsic(IntrinsicID, Tys); -} - -static Value *EmitCommonNeonSISDBuiltinExpr(CodeGenFunction &CGF, - const NeonIntrinsicInfo &SISDInfo, - SmallVectorImpl<Value *> &Ops, - const CallExpr *E) { - unsigned BuiltinID = SISDInfo.BuiltinID; - unsigned int Int = SISDInfo.LLVMIntrinsic; - unsigned Modifier = SISDInfo.TypeModifier; - const char *s = SISDInfo.NameHint; - - switch (BuiltinID) { - case NEON::BI__builtin_neon_vcled_s64: - case NEON::BI__builtin_neon_vcled_u64: - case NEON::BI__builtin_neon_vcles_f32: - case NEON::BI__builtin_neon_vcled_f64: - case NEON::BI__builtin_neon_vcltd_s64: - case NEON::BI__builtin_neon_vcltd_u64: - case NEON::BI__builtin_neon_vclts_f32: - case NEON::BI__builtin_neon_vcltd_f64: - case NEON::BI__builtin_neon_vcales_f32: - case NEON::BI__builtin_neon_vcaled_f64: - case NEON::BI__builtin_neon_vcalts_f32: - case NEON::BI__builtin_neon_vcaltd_f64: - // Only one direction of comparisons actually exist, cmle is actually a cmge - // with swapped operands. The table gives us the right intrinsic but we - // still need to do the swap. - std::swap(Ops[0], Ops[1]); - break; - } - - assert(Int && "Generic code assumes a valid intrinsic"); - - // Determine the type(s) of this overloaded AArch64 intrinsic. - const Expr *Arg = E->getArg(0); - llvm::Type *ArgTy = CGF.ConvertType(Arg->getType()); - Function *F = CGF.LookupNeonLLVMIntrinsic(Int, Modifier, ArgTy, E); - - int j = 0; - ConstantInt *C0 = ConstantInt::get(CGF.SizeTy, 0); - for (Function::const_arg_iterator ai = F->arg_begin(), ae = F->arg_end(); - ai != ae; ++ai, ++j) { - llvm::Type *ArgTy = ai->getType(); - if (Ops[j]->getType()->getPrimitiveSizeInBits() == - ArgTy->getPrimitiveSizeInBits()) - continue; - - assert(ArgTy->isVectorTy() && !Ops[j]->getType()->isVectorTy()); - // The constant argument to an _n_ intrinsic always has Int32Ty, so truncate - // it before inserting. - Ops[j] = - CGF.Builder.CreateTruncOrBitCast(Ops[j], ArgTy->getVectorElementType()); - Ops[j] = - CGF.Builder.CreateInsertElement(UndefValue::get(ArgTy), Ops[j], C0); - } - - Value *Result = CGF.EmitNeonCall(F, Ops, s); - llvm::Type *ResultType = CGF.ConvertType(E->getType()); - if (ResultType->getPrimitiveSizeInBits() < - Result->getType()->getPrimitiveSizeInBits()) - return CGF.Builder.CreateExtractElement(Result, C0); - - return CGF.Builder.CreateBitCast(Result, ResultType, s); -} - -Value *CodeGenFunction::EmitCommonNeonBuiltinExpr( - unsigned BuiltinID, unsigned LLVMIntrinsic, unsigned AltLLVMIntrinsic, - const char *NameHint, unsigned Modifier, const CallExpr *E, - SmallVectorImpl<llvm::Value *> &Ops, Address PtrOp0, Address PtrOp1, - llvm::Triple::ArchType Arch) { - // Get the last argument, which specifies the vector type. - llvm::APSInt NeonTypeConst; - const Expr *Arg = E->getArg(E->getNumArgs() - 1); - if (!Arg->isIntegerConstantExpr(NeonTypeConst, getContext())) - return nullptr; - - // Determine the type of this overloaded NEON intrinsic. - NeonTypeFlags Type(NeonTypeConst.getZExtValue()); - bool Usgn = Type.isUnsigned(); - bool Quad = Type.isQuad(); - const bool HasLegalHalfType = getTarget().hasLegalHalfType(); - - llvm::VectorType *VTy = GetNeonType(this, Type, HasLegalHalfType); - llvm::Type *Ty = VTy; - if (!Ty) - return nullptr; - - auto getAlignmentValue32 = [&](Address addr) -> Value* { - return Builder.getInt32(addr.getAlignment().getQuantity()); - }; - - unsigned Int = LLVMIntrinsic; - if ((Modifier & UnsignedAlts) && !Usgn) - Int = AltLLVMIntrinsic; - - switch (BuiltinID) { - default: break; - case NEON::BI__builtin_neon_vabs_v: - case NEON::BI__builtin_neon_vabsq_v: - if (VTy->getElementType()->isFloatingPointTy()) - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::fabs, Ty), Ops, "vabs"); - return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Ty), Ops, "vabs"); - case NEON::BI__builtin_neon_vaddhn_v: { - llvm::VectorType *SrcTy = - llvm::VectorType::getExtendedElementVectorType(VTy); - - // %sum = add <4 x i32> %lhs, %rhs - Ops[0] = Builder.CreateBitCast(Ops[0], SrcTy); - Ops[1] = Builder.CreateBitCast(Ops[1], SrcTy); - Ops[0] = Builder.CreateAdd(Ops[0], Ops[1], "vaddhn"); - - // %high = lshr <4 x i32> %sum, <i32 16, i32 16, i32 16, i32 16> - Constant *ShiftAmt = - ConstantInt::get(SrcTy, SrcTy->getScalarSizeInBits() / 2); - Ops[0] = Builder.CreateLShr(Ops[0], ShiftAmt, "vaddhn"); - - // %res = trunc <4 x i32> %high to <4 x i16> - return Builder.CreateTrunc(Ops[0], VTy, "vaddhn"); - } - case NEON::BI__builtin_neon_vcale_v: - case NEON::BI__builtin_neon_vcaleq_v: - case NEON::BI__builtin_neon_vcalt_v: - case NEON::BI__builtin_neon_vcaltq_v: - std::swap(Ops[0], Ops[1]); - LLVM_FALLTHROUGH; - case NEON::BI__builtin_neon_vcage_v: - case NEON::BI__builtin_neon_vcageq_v: - case NEON::BI__builtin_neon_vcagt_v: - case NEON::BI__builtin_neon_vcagtq_v: { - llvm::Type *Ty; - switch (VTy->getScalarSizeInBits()) { - default: llvm_unreachable("unexpected type"); - case 32: - Ty = FloatTy; - break; - case 64: - Ty = DoubleTy; - break; - case 16: - Ty = HalfTy; - break; - } - llvm::Type *VecFlt = llvm::VectorType::get(Ty, VTy->getNumElements()); - llvm::Type *Tys[] = { VTy, VecFlt }; - Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys); - return EmitNeonCall(F, Ops, NameHint); - } - case NEON::BI__builtin_neon_vceqz_v: - case NEON::BI__builtin_neon_vceqzq_v: - return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OEQ, - ICmpInst::ICMP_EQ, "vceqz"); - case NEON::BI__builtin_neon_vcgez_v: - case NEON::BI__builtin_neon_vcgezq_v: - return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OGE, - ICmpInst::ICMP_SGE, "vcgez"); - case NEON::BI__builtin_neon_vclez_v: - case NEON::BI__builtin_neon_vclezq_v: - return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OLE, - ICmpInst::ICMP_SLE, "vclez"); - case NEON::BI__builtin_neon_vcgtz_v: - case NEON::BI__builtin_neon_vcgtzq_v: - return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OGT, - ICmpInst::ICMP_SGT, "vcgtz"); - case NEON::BI__builtin_neon_vcltz_v: - case NEON::BI__builtin_neon_vcltzq_v: - return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OLT, - ICmpInst::ICMP_SLT, "vcltz"); - case NEON::BI__builtin_neon_vclz_v: - case NEON::BI__builtin_neon_vclzq_v: - // We generate target-independent intrinsic, which needs a second argument - // for whether or not clz of zero is undefined; on ARM it isn't. - Ops.push_back(Builder.getInt1(getTarget().isCLZForZeroUndef())); - break; - case NEON::BI__builtin_neon_vcvt_f32_v: - case NEON::BI__builtin_neon_vcvtq_f32_v: - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, Quad), - HasLegalHalfType); - return Usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt") - : Builder.CreateSIToFP(Ops[0], Ty, "vcvt"); - case NEON::BI__builtin_neon_vcvt_f16_v: - case NEON::BI__builtin_neon_vcvtq_f16_v: - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float16, false, Quad), - HasLegalHalfType); - return Usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt") - : Builder.CreateSIToFP(Ops[0], Ty, "vcvt"); - case NEON::BI__builtin_neon_vcvt_n_f16_v: - case NEON::BI__builtin_neon_vcvt_n_f32_v: - case NEON::BI__builtin_neon_vcvt_n_f64_v: - case NEON::BI__builtin_neon_vcvtq_n_f16_v: - case NEON::BI__builtin_neon_vcvtq_n_f32_v: - case NEON::BI__builtin_neon_vcvtq_n_f64_v: { - llvm::Type *Tys[2] = { GetFloatNeonType(this, Type), Ty }; - Int = Usgn ? LLVMIntrinsic : AltLLVMIntrinsic; - Function *F = CGM.getIntrinsic(Int, Tys); - return EmitNeonCall(F, Ops, "vcvt_n"); - } - case NEON::BI__builtin_neon_vcvt_n_s16_v: - case NEON::BI__builtin_neon_vcvt_n_s32_v: - case NEON::BI__builtin_neon_vcvt_n_u16_v: - case NEON::BI__builtin_neon_vcvt_n_u32_v: - case NEON::BI__builtin_neon_vcvt_n_s64_v: - case NEON::BI__builtin_neon_vcvt_n_u64_v: - case NEON::BI__builtin_neon_vcvtq_n_s16_v: - case NEON::BI__builtin_neon_vcvtq_n_s32_v: - case NEON::BI__builtin_neon_vcvtq_n_u16_v: - case NEON::BI__builtin_neon_vcvtq_n_u32_v: - case NEON::BI__builtin_neon_vcvtq_n_s64_v: - case NEON::BI__builtin_neon_vcvtq_n_u64_v: { - llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) }; - Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys); - return EmitNeonCall(F, Ops, "vcvt_n"); - } - case NEON::BI__builtin_neon_vcvt_s32_v: - case NEON::BI__builtin_neon_vcvt_u32_v: - case NEON::BI__builtin_neon_vcvt_s64_v: - case NEON::BI__builtin_neon_vcvt_u64_v: - case NEON::BI__builtin_neon_vcvt_s16_v: - case NEON::BI__builtin_neon_vcvt_u16_v: - case NEON::BI__builtin_neon_vcvtq_s32_v: - case NEON::BI__builtin_neon_vcvtq_u32_v: - case NEON::BI__builtin_neon_vcvtq_s64_v: - case NEON::BI__builtin_neon_vcvtq_u64_v: - case NEON::BI__builtin_neon_vcvtq_s16_v: - case NEON::BI__builtin_neon_vcvtq_u16_v: { - Ops[0] = Builder.CreateBitCast(Ops[0], GetFloatNeonType(this, Type)); - return Usgn ? Builder.CreateFPToUI(Ops[0], Ty, "vcvt") - : Builder.CreateFPToSI(Ops[0], Ty, "vcvt"); - } - case NEON::BI__builtin_neon_vcvta_s16_v: - case NEON::BI__builtin_neon_vcvta_s32_v: - case NEON::BI__builtin_neon_vcvta_s64_v: - case NEON::BI__builtin_neon_vcvta_u16_v: - case NEON::BI__builtin_neon_vcvta_u32_v: - case NEON::BI__builtin_neon_vcvta_u64_v: - case NEON::BI__builtin_neon_vcvtaq_s16_v: - case NEON::BI__builtin_neon_vcvtaq_s32_v: - case NEON::BI__builtin_neon_vcvtaq_s64_v: - case NEON::BI__builtin_neon_vcvtaq_u16_v: - case NEON::BI__builtin_neon_vcvtaq_u32_v: - case NEON::BI__builtin_neon_vcvtaq_u64_v: - case NEON::BI__builtin_neon_vcvtn_s16_v: - case NEON::BI__builtin_neon_vcvtn_s32_v: - case NEON::BI__builtin_neon_vcvtn_s64_v: - case NEON::BI__builtin_neon_vcvtn_u16_v: - case NEON::BI__builtin_neon_vcvtn_u32_v: - case NEON::BI__builtin_neon_vcvtn_u64_v: - case NEON::BI__builtin_neon_vcvtnq_s16_v: - case NEON::BI__builtin_neon_vcvtnq_s32_v: - case NEON::BI__builtin_neon_vcvtnq_s64_v: - case NEON::BI__builtin_neon_vcvtnq_u16_v: - case NEON::BI__builtin_neon_vcvtnq_u32_v: - case NEON::BI__builtin_neon_vcvtnq_u64_v: - case NEON::BI__builtin_neon_vcvtp_s16_v: - case NEON::BI__builtin_neon_vcvtp_s32_v: - case NEON::BI__builtin_neon_vcvtp_s64_v: - case NEON::BI__builtin_neon_vcvtp_u16_v: - case NEON::BI__builtin_neon_vcvtp_u32_v: - case NEON::BI__builtin_neon_vcvtp_u64_v: - case NEON::BI__builtin_neon_vcvtpq_s16_v: - case NEON::BI__builtin_neon_vcvtpq_s32_v: - case NEON::BI__builtin_neon_vcvtpq_s64_v: - case NEON::BI__builtin_neon_vcvtpq_u16_v: - case NEON::BI__builtin_neon_vcvtpq_u32_v: - case NEON::BI__builtin_neon_vcvtpq_u64_v: - case NEON::BI__builtin_neon_vcvtm_s16_v: - case NEON::BI__builtin_neon_vcvtm_s32_v: - case NEON::BI__builtin_neon_vcvtm_s64_v: - case NEON::BI__builtin_neon_vcvtm_u16_v: - case NEON::BI__builtin_neon_vcvtm_u32_v: - case NEON::BI__builtin_neon_vcvtm_u64_v: - case NEON::BI__builtin_neon_vcvtmq_s16_v: - case NEON::BI__builtin_neon_vcvtmq_s32_v: - case NEON::BI__builtin_neon_vcvtmq_s64_v: - case NEON::BI__builtin_neon_vcvtmq_u16_v: - case NEON::BI__builtin_neon_vcvtmq_u32_v: - case NEON::BI__builtin_neon_vcvtmq_u64_v: { - llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) }; - return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Tys), Ops, NameHint); - } - case NEON::BI__builtin_neon_vext_v: - case NEON::BI__builtin_neon_vextq_v: { - int CV = cast<ConstantInt>(Ops[2])->getSExtValue(); - SmallVector<uint32_t, 16> Indices; - for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) - Indices.push_back(i+CV); - - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - return Builder.CreateShuffleVector(Ops[0], Ops[1], Indices, "vext"); - } - case NEON::BI__builtin_neon_vfma_v: - case NEON::BI__builtin_neon_vfmaq_v: { - Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty); - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - Ops[2] = Builder.CreateBitCast(Ops[2], Ty); - - // NEON intrinsic puts accumulator first, unlike the LLVM fma. - return Builder.CreateCall(F, {Ops[1], Ops[2], Ops[0]}); - } - case NEON::BI__builtin_neon_vld1_v: - case NEON::BI__builtin_neon_vld1q_v: { - llvm::Type *Tys[] = {Ty, Int8PtrTy}; - Ops.push_back(getAlignmentValue32(PtrOp0)); - return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Tys), Ops, "vld1"); - } - case NEON::BI__builtin_neon_vld1_x2_v: - case NEON::BI__builtin_neon_vld1q_x2_v: - case NEON::BI__builtin_neon_vld1_x3_v: - case NEON::BI__builtin_neon_vld1q_x3_v: - case NEON::BI__builtin_neon_vld1_x4_v: - case NEON::BI__builtin_neon_vld1q_x4_v: { - llvm::Type *PTy = llvm::PointerType::getUnqual(VTy->getVectorElementType()); - Ops[1] = Builder.CreateBitCast(Ops[1], PTy); - llvm::Type *Tys[2] = { VTy, PTy }; - Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys); - Ops[1] = Builder.CreateCall(F, Ops[1], "vld1xN"); - Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]); - } - case NEON::BI__builtin_neon_vld2_v: - case NEON::BI__builtin_neon_vld2q_v: - case NEON::BI__builtin_neon_vld3_v: - case NEON::BI__builtin_neon_vld3q_v: - case NEON::BI__builtin_neon_vld4_v: - case NEON::BI__builtin_neon_vld4q_v: - case NEON::BI__builtin_neon_vld2_dup_v: - case NEON::BI__builtin_neon_vld2q_dup_v: - case NEON::BI__builtin_neon_vld3_dup_v: - case NEON::BI__builtin_neon_vld3q_dup_v: - case NEON::BI__builtin_neon_vld4_dup_v: - case NEON::BI__builtin_neon_vld4q_dup_v: { - llvm::Type *Tys[] = {Ty, Int8PtrTy}; - Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys); - Value *Align = getAlignmentValue32(PtrOp1); - Ops[1] = Builder.CreateCall(F, {Ops[1], Align}, NameHint); - Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]); - } - case NEON::BI__builtin_neon_vld1_dup_v: - case NEON::BI__builtin_neon_vld1q_dup_v: { - Value *V = UndefValue::get(Ty); - Ty = llvm::PointerType::getUnqual(VTy->getElementType()); - PtrOp0 = Builder.CreateBitCast(PtrOp0, Ty); - LoadInst *Ld = Builder.CreateLoad(PtrOp0); - llvm::Constant *CI = ConstantInt::get(SizeTy, 0); - Ops[0] = Builder.CreateInsertElement(V, Ld, CI); - return EmitNeonSplat(Ops[0], CI); - } - case NEON::BI__builtin_neon_vld2_lane_v: - case NEON::BI__builtin_neon_vld2q_lane_v: - case NEON::BI__builtin_neon_vld3_lane_v: - case NEON::BI__builtin_neon_vld3q_lane_v: - case NEON::BI__builtin_neon_vld4_lane_v: - case NEON::BI__builtin_neon_vld4q_lane_v: { - llvm::Type *Tys[] = {Ty, Int8PtrTy}; - Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys); - for (unsigned I = 2; I < Ops.size() - 1; ++I) - Ops[I] = Builder.CreateBitCast(Ops[I], Ty); - Ops.push_back(getAlignmentValue32(PtrOp1)); - Ops[1] = Builder.CreateCall(F, makeArrayRef(Ops).slice(1), NameHint); - Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]); - } - case NEON::BI__builtin_neon_vmovl_v: { - llvm::Type *DTy =llvm::VectorType::getTruncatedElementVectorType(VTy); - Ops[0] = Builder.CreateBitCast(Ops[0], DTy); - if (Usgn) - return Builder.CreateZExt(Ops[0], Ty, "vmovl"); - return Builder.CreateSExt(Ops[0], Ty, "vmovl"); - } - case NEON::BI__builtin_neon_vmovn_v: { - llvm::Type *QTy = llvm::VectorType::getExtendedElementVectorType(VTy); - Ops[0] = Builder.CreateBitCast(Ops[0], QTy); - return Builder.CreateTrunc(Ops[0], Ty, "vmovn"); - } - case NEON::BI__builtin_neon_vmull_v: - // FIXME: the integer vmull operations could be emitted in terms of pure - // LLVM IR (2 exts followed by a mul). Unfortunately LLVM has a habit of - // hoisting the exts outside loops. Until global ISel comes along that can - // see through such movement this leads to bad CodeGen. So we need an - // intrinsic for now. - Int = Usgn ? Intrinsic::arm_neon_vmullu : Intrinsic::arm_neon_vmulls; - Int = Type.isPoly() ? (unsigned)Intrinsic::arm_neon_vmullp : Int; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmull"); - case NEON::BI__builtin_neon_vpadal_v: - case NEON::BI__builtin_neon_vpadalq_v: { - // The source operand type has twice as many elements of half the size. - unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); - llvm::Type *EltTy = - llvm::IntegerType::get(getLLVMContext(), EltBits / 2); - llvm::Type *NarrowTy = - llvm::VectorType::get(EltTy, VTy->getNumElements() * 2); - llvm::Type *Tys[2] = { Ty, NarrowTy }; - return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, NameHint); - } - case NEON::BI__builtin_neon_vpaddl_v: - case NEON::BI__builtin_neon_vpaddlq_v: { - // The source operand type has twice as many elements of half the size. - unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); - llvm::Type *EltTy = llvm::IntegerType::get(getLLVMContext(), EltBits / 2); - llvm::Type *NarrowTy = - llvm::VectorType::get(EltTy, VTy->getNumElements() * 2); - llvm::Type *Tys[2] = { Ty, NarrowTy }; - return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vpaddl"); - } - case NEON::BI__builtin_neon_vqdmlal_v: - case NEON::BI__builtin_neon_vqdmlsl_v: { - SmallVector<Value *, 2> MulOps(Ops.begin() + 1, Ops.end()); - Ops[1] = - EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Ty), MulOps, "vqdmlal"); - Ops.resize(2); - return EmitNeonCall(CGM.getIntrinsic(AltLLVMIntrinsic, Ty), Ops, NameHint); - } - case NEON::BI__builtin_neon_vqshl_n_v: - case NEON::BI__builtin_neon_vqshlq_n_v: - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshl_n", - 1, false); - case NEON::BI__builtin_neon_vqshlu_n_v: - case NEON::BI__builtin_neon_vqshluq_n_v: - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshlu_n", - 1, false); - case NEON::BI__builtin_neon_vrecpe_v: - case NEON::BI__builtin_neon_vrecpeq_v: - case NEON::BI__builtin_neon_vrsqrte_v: - case NEON::BI__builtin_neon_vrsqrteq_v: - Int = Ty->isFPOrFPVectorTy() ? LLVMIntrinsic : AltLLVMIntrinsic; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, NameHint); - case NEON::BI__builtin_neon_vrndi_v: - case NEON::BI__builtin_neon_vrndiq_v: - Int = Intrinsic::nearbyint; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, NameHint); - case NEON::BI__builtin_neon_vrshr_n_v: - case NEON::BI__builtin_neon_vrshrq_n_v: - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrshr_n", - 1, true); - case NEON::BI__builtin_neon_vshl_n_v: - case NEON::BI__builtin_neon_vshlq_n_v: - Ops[1] = EmitNeonShiftVector(Ops[1], Ty, false); - return Builder.CreateShl(Builder.CreateBitCast(Ops[0],Ty), Ops[1], - "vshl_n"); - case NEON::BI__builtin_neon_vshll_n_v: { - llvm::Type *SrcTy = llvm::VectorType::getTruncatedElementVectorType(VTy); - Ops[0] = Builder.CreateBitCast(Ops[0], SrcTy); - if (Usgn) - Ops[0] = Builder.CreateZExt(Ops[0], VTy); - else - Ops[0] = Builder.CreateSExt(Ops[0], VTy); - Ops[1] = EmitNeonShiftVector(Ops[1], VTy, false); - return Builder.CreateShl(Ops[0], Ops[1], "vshll_n"); - } - case NEON::BI__builtin_neon_vshrn_n_v: { - llvm::Type *SrcTy = llvm::VectorType::getExtendedElementVectorType(VTy); - Ops[0] = Builder.CreateBitCast(Ops[0], SrcTy); - Ops[1] = EmitNeonShiftVector(Ops[1], SrcTy, false); - if (Usgn) - Ops[0] = Builder.CreateLShr(Ops[0], Ops[1]); - else - Ops[0] = Builder.CreateAShr(Ops[0], Ops[1]); - return Builder.CreateTrunc(Ops[0], Ty, "vshrn_n"); - } - case NEON::BI__builtin_neon_vshr_n_v: - case NEON::BI__builtin_neon_vshrq_n_v: - return EmitNeonRShiftImm(Ops[0], Ops[1], Ty, Usgn, "vshr_n"); - case NEON::BI__builtin_neon_vst1_v: - case NEON::BI__builtin_neon_vst1q_v: - case NEON::BI__builtin_neon_vst2_v: - case NEON::BI__builtin_neon_vst2q_v: - case NEON::BI__builtin_neon_vst3_v: - case NEON::BI__builtin_neon_vst3q_v: - case NEON::BI__builtin_neon_vst4_v: - case NEON::BI__builtin_neon_vst4q_v: - case NEON::BI__builtin_neon_vst2_lane_v: - case NEON::BI__builtin_neon_vst2q_lane_v: - case NEON::BI__builtin_neon_vst3_lane_v: - case NEON::BI__builtin_neon_vst3q_lane_v: - case NEON::BI__builtin_neon_vst4_lane_v: - case NEON::BI__builtin_neon_vst4q_lane_v: { - llvm::Type *Tys[] = {Int8PtrTy, Ty}; - Ops.push_back(getAlignmentValue32(PtrOp0)); - return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, ""); - } - case NEON::BI__builtin_neon_vst1_x2_v: - case NEON::BI__builtin_neon_vst1q_x2_v: - case NEON::BI__builtin_neon_vst1_x3_v: - case NEON::BI__builtin_neon_vst1q_x3_v: - case NEON::BI__builtin_neon_vst1_x4_v: - case NEON::BI__builtin_neon_vst1q_x4_v: { - llvm::Type *PTy = llvm::PointerType::getUnqual(VTy->getVectorElementType()); - // TODO: Currently in AArch32 mode the pointer operand comes first, whereas - // in AArch64 it comes last. We may want to stick to one or another. - if (Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be) { - llvm::Type *Tys[2] = { VTy, PTy }; - std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end()); - return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Tys), Ops, ""); - } - llvm::Type *Tys[2] = { PTy, VTy }; - return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Tys), Ops, ""); - } - case NEON::BI__builtin_neon_vsubhn_v: { - llvm::VectorType *SrcTy = - llvm::VectorType::getExtendedElementVectorType(VTy); - - // %sum = add <4 x i32> %lhs, %rhs - Ops[0] = Builder.CreateBitCast(Ops[0], SrcTy); - Ops[1] = Builder.CreateBitCast(Ops[1], SrcTy); - Ops[0] = Builder.CreateSub(Ops[0], Ops[1], "vsubhn"); - - // %high = lshr <4 x i32> %sum, <i32 16, i32 16, i32 16, i32 16> - Constant *ShiftAmt = - ConstantInt::get(SrcTy, SrcTy->getScalarSizeInBits() / 2); - Ops[0] = Builder.CreateLShr(Ops[0], ShiftAmt, "vsubhn"); - - // %res = trunc <4 x i32> %high to <4 x i16> - return Builder.CreateTrunc(Ops[0], VTy, "vsubhn"); - } - case NEON::BI__builtin_neon_vtrn_v: - case NEON::BI__builtin_neon_vtrnq_v: { - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty)); - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - Ops[2] = Builder.CreateBitCast(Ops[2], Ty); - Value *SV = nullptr; - - for (unsigned vi = 0; vi != 2; ++vi) { - SmallVector<uint32_t, 16> Indices; - for (unsigned i = 0, e = VTy->getNumElements(); i != e; i += 2) { - Indices.push_back(i+vi); - Indices.push_back(i+e+vi); - } - Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi); - SV = Builder.CreateShuffleVector(Ops[1], Ops[2], Indices, "vtrn"); - SV = Builder.CreateDefaultAlignedStore(SV, Addr); - } - return SV; - } - case NEON::BI__builtin_neon_vtst_v: - case NEON::BI__builtin_neon_vtstq_v: { - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - Ops[0] = Builder.CreateAnd(Ops[0], Ops[1]); - Ops[0] = Builder.CreateICmp(ICmpInst::ICMP_NE, Ops[0], - ConstantAggregateZero::get(Ty)); - return Builder.CreateSExt(Ops[0], Ty, "vtst"); - } - case NEON::BI__builtin_neon_vuzp_v: - case NEON::BI__builtin_neon_vuzpq_v: { - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty)); - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - Ops[2] = Builder.CreateBitCast(Ops[2], Ty); - Value *SV = nullptr; - - for (unsigned vi = 0; vi != 2; ++vi) { - SmallVector<uint32_t, 16> Indices; - for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) - Indices.push_back(2*i+vi); - - Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi); - SV = Builder.CreateShuffleVector(Ops[1], Ops[2], Indices, "vuzp"); - SV = Builder.CreateDefaultAlignedStore(SV, Addr); - } - return SV; - } - case NEON::BI__builtin_neon_vzip_v: - case NEON::BI__builtin_neon_vzipq_v: { - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty)); - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - Ops[2] = Builder.CreateBitCast(Ops[2], Ty); - Value *SV = nullptr; - - for (unsigned vi = 0; vi != 2; ++vi) { - SmallVector<uint32_t, 16> Indices; - for (unsigned i = 0, e = VTy->getNumElements(); i != e; i += 2) { - Indices.push_back((i + vi*e) >> 1); - Indices.push_back(((i + vi*e) >> 1)+e); - } - Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi); - SV = Builder.CreateShuffleVector(Ops[1], Ops[2], Indices, "vzip"); - SV = Builder.CreateDefaultAlignedStore(SV, Addr); - } - return SV; - } - case NEON::BI__builtin_neon_vdot_v: - case NEON::BI__builtin_neon_vdotq_v: { - llvm::Type *InputTy = - llvm::VectorType::get(Int8Ty, Ty->getPrimitiveSizeInBits() / 8); - llvm::Type *Tys[2] = { Ty, InputTy }; - Int = Usgn ? LLVMIntrinsic : AltLLVMIntrinsic; - return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vdot"); - } - case NEON::BI__builtin_neon_vfmlal_low_v: - case NEON::BI__builtin_neon_vfmlalq_low_v: { - llvm::Type *InputTy = - llvm::VectorType::get(HalfTy, Ty->getPrimitiveSizeInBits() / 16); - llvm::Type *Tys[2] = { Ty, InputTy }; - return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vfmlal_low"); - } - case NEON::BI__builtin_neon_vfmlsl_low_v: - case NEON::BI__builtin_neon_vfmlslq_low_v: { - llvm::Type *InputTy = - llvm::VectorType::get(HalfTy, Ty->getPrimitiveSizeInBits() / 16); - llvm::Type *Tys[2] = { Ty, InputTy }; - return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vfmlsl_low"); - } - case NEON::BI__builtin_neon_vfmlal_high_v: - case NEON::BI__builtin_neon_vfmlalq_high_v: { - llvm::Type *InputTy = - llvm::VectorType::get(HalfTy, Ty->getPrimitiveSizeInBits() / 16); - llvm::Type *Tys[2] = { Ty, InputTy }; - return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vfmlal_high"); - } - case NEON::BI__builtin_neon_vfmlsl_high_v: - case NEON::BI__builtin_neon_vfmlslq_high_v: { - llvm::Type *InputTy = - llvm::VectorType::get(HalfTy, Ty->getPrimitiveSizeInBits() / 16); - llvm::Type *Tys[2] = { Ty, InputTy }; - return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vfmlsl_high"); - } - } - - assert(Int && "Expected valid intrinsic number"); - - // Determine the type(s) of this overloaded AArch64 intrinsic. - Function *F = LookupNeonLLVMIntrinsic(Int, Modifier, Ty, E); - - Value *Result = EmitNeonCall(F, Ops, NameHint); - llvm::Type *ResultType = ConvertType(E->getType()); - // AArch64 intrinsic one-element vector type cast to - // scalar type expected by the builtin - return Builder.CreateBitCast(Result, ResultType, NameHint); -} - -Value *CodeGenFunction::EmitAArch64CompareBuiltinExpr( - Value *Op, llvm::Type *Ty, const CmpInst::Predicate Fp, - const CmpInst::Predicate Ip, const Twine &Name) { - llvm::Type *OTy = Op->getType(); - - // FIXME: this is utterly horrific. We should not be looking at previous - // codegen context to find out what needs doing. Unfortunately TableGen - // currently gives us exactly the same calls for vceqz_f32 and vceqz_s32 - // (etc). - if (BitCastInst *BI = dyn_cast<BitCastInst>(Op)) - OTy = BI->getOperand(0)->getType(); - - Op = Builder.CreateBitCast(Op, OTy); - if (OTy->getScalarType()->isFloatingPointTy()) { - Op = Builder.CreateFCmp(Fp, Op, Constant::getNullValue(OTy)); - } else { - Op = Builder.CreateICmp(Ip, Op, Constant::getNullValue(OTy)); - } - return Builder.CreateSExt(Op, Ty, Name); -} - -static Value *packTBLDVectorList(CodeGenFunction &CGF, ArrayRef<Value *> Ops, - Value *ExtOp, Value *IndexOp, - llvm::Type *ResTy, unsigned IntID, - const char *Name) { - SmallVector<Value *, 2> TblOps; - if (ExtOp) - TblOps.push_back(ExtOp); - - // Build a vector containing sequential number like (0, 1, 2, ..., 15) - SmallVector<uint32_t, 16> Indices; - llvm::VectorType *TblTy = cast<llvm::VectorType>(Ops[0]->getType()); - for (unsigned i = 0, e = TblTy->getNumElements(); i != e; ++i) { - Indices.push_back(2*i); - Indices.push_back(2*i+1); - } - - int PairPos = 0, End = Ops.size() - 1; - while (PairPos < End) { - TblOps.push_back(CGF.Builder.CreateShuffleVector(Ops[PairPos], - Ops[PairPos+1], Indices, - Name)); - PairPos += 2; - } - - // If there's an odd number of 64-bit lookup table, fill the high 64-bit - // of the 128-bit lookup table with zero. - if (PairPos == End) { - Value *ZeroTbl = ConstantAggregateZero::get(TblTy); - TblOps.push_back(CGF.Builder.CreateShuffleVector(Ops[PairPos], - ZeroTbl, Indices, Name)); - } - - Function *TblF; - TblOps.push_back(IndexOp); - TblF = CGF.CGM.getIntrinsic(IntID, ResTy); - - return CGF.EmitNeonCall(TblF, TblOps, Name); -} - -Value *CodeGenFunction::GetValueForARMHint(unsigned BuiltinID) { - unsigned Value; - switch (BuiltinID) { - default: - return nullptr; - case ARM::BI__builtin_arm_nop: - Value = 0; - break; - case ARM::BI__builtin_arm_yield: - case ARM::BI__yield: - Value = 1; - break; - case ARM::BI__builtin_arm_wfe: - case ARM::BI__wfe: - Value = 2; - break; - case ARM::BI__builtin_arm_wfi: - case ARM::BI__wfi: - Value = 3; - break; - case ARM::BI__builtin_arm_sev: - case ARM::BI__sev: - Value = 4; - break; - case ARM::BI__builtin_arm_sevl: - case ARM::BI__sevl: - Value = 5; - break; - } - - return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_hint), - llvm::ConstantInt::get(Int32Ty, Value)); -} - -// Generates the IR for the read/write special register builtin, -// ValueType is the type of the value that is to be written or read, -// RegisterType is the type of the register being written to or read from. -static Value *EmitSpecialRegisterBuiltin(CodeGenFunction &CGF, - const CallExpr *E, - llvm::Type *RegisterType, - llvm::Type *ValueType, - bool IsRead, - StringRef SysReg = "") { - // write and register intrinsics only support 32 and 64 bit operations. - assert((RegisterType->isIntegerTy(32) || RegisterType->isIntegerTy(64)) - && "Unsupported size for register."); - - CodeGen::CGBuilderTy &Builder = CGF.Builder; - CodeGen::CodeGenModule &CGM = CGF.CGM; - LLVMContext &Context = CGM.getLLVMContext(); - - if (SysReg.empty()) { - const Expr *SysRegStrExpr = E->getArg(0)->IgnoreParenCasts(); - SysReg = cast<clang::StringLiteral>(SysRegStrExpr)->getString(); - } - - llvm::Metadata *Ops[] = { llvm::MDString::get(Context, SysReg) }; - llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops); - llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName); - - llvm::Type *Types[] = { RegisterType }; - - bool MixedTypes = RegisterType->isIntegerTy(64) && ValueType->isIntegerTy(32); - assert(!(RegisterType->isIntegerTy(32) && ValueType->isIntegerTy(64)) - && "Can't fit 64-bit value in 32-bit register"); - - if (IsRead) { - llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::read_register, Types); - llvm::Value *Call = Builder.CreateCall(F, Metadata); - - if (MixedTypes) - // Read into 64 bit register and then truncate result to 32 bit. - return Builder.CreateTrunc(Call, ValueType); - - if (ValueType->isPointerTy()) - // Have i32/i64 result (Call) but want to return a VoidPtrTy (i8*). - return Builder.CreateIntToPtr(Call, ValueType); - - return Call; - } - - llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::write_register, Types); - llvm::Value *ArgValue = CGF.EmitScalarExpr(E->getArg(1)); - if (MixedTypes) { - // Extend 32 bit write value to 64 bit to pass to write. - ArgValue = Builder.CreateZExt(ArgValue, RegisterType); - return Builder.CreateCall(F, { Metadata, ArgValue }); - } - - if (ValueType->isPointerTy()) { - // Have VoidPtrTy ArgValue but want to return an i32/i64. - ArgValue = Builder.CreatePtrToInt(ArgValue, RegisterType); - return Builder.CreateCall(F, { Metadata, ArgValue }); - } - - return Builder.CreateCall(F, { Metadata, ArgValue }); -} - -/// Return true if BuiltinID is an overloaded Neon intrinsic with an extra -/// argument that specifies the vector type. -static bool HasExtraNeonArgument(unsigned BuiltinID) { - switch (BuiltinID) { - default: break; - case NEON::BI__builtin_neon_vget_lane_i8: - case NEON::BI__builtin_neon_vget_lane_i16: - case NEON::BI__builtin_neon_vget_lane_i32: - case NEON::BI__builtin_neon_vget_lane_i64: - case NEON::BI__builtin_neon_vget_lane_f32: - case NEON::BI__builtin_neon_vgetq_lane_i8: - case NEON::BI__builtin_neon_vgetq_lane_i16: - case NEON::BI__builtin_neon_vgetq_lane_i32: - case NEON::BI__builtin_neon_vgetq_lane_i64: - case NEON::BI__builtin_neon_vgetq_lane_f32: - case NEON::BI__builtin_neon_vset_lane_i8: - case NEON::BI__builtin_neon_vset_lane_i16: - case NEON::BI__builtin_neon_vset_lane_i32: - case NEON::BI__builtin_neon_vset_lane_i64: - case NEON::BI__builtin_neon_vset_lane_f32: - case NEON::BI__builtin_neon_vsetq_lane_i8: - case NEON::BI__builtin_neon_vsetq_lane_i16: - case NEON::BI__builtin_neon_vsetq_lane_i32: - case NEON::BI__builtin_neon_vsetq_lane_i64: - case NEON::BI__builtin_neon_vsetq_lane_f32: - case NEON::BI__builtin_neon_vsha1h_u32: - case NEON::BI__builtin_neon_vsha1cq_u32: - case NEON::BI__builtin_neon_vsha1pq_u32: - case NEON::BI__builtin_neon_vsha1mq_u32: - case clang::ARM::BI_MoveToCoprocessor: - case clang::ARM::BI_MoveToCoprocessor2: - return false; - } - return true; -} - -Value *CodeGenFunction::EmitISOVolatileLoad(const CallExpr *E) { - Value *Ptr = EmitScalarExpr(E->getArg(0)); - QualType ElTy = E->getArg(0)->getType()->getPointeeType(); - CharUnits LoadSize = getContext().getTypeSizeInChars(ElTy); - llvm::Type *ITy = llvm::IntegerType::get(getLLVMContext(), - LoadSize.getQuantity() * 8); - Ptr = Builder.CreateBitCast(Ptr, ITy->getPointerTo()); - llvm::LoadInst *Load = - Builder.CreateAlignedLoad(Ptr, LoadSize); - Load->setVolatile(true); - return Load; -} - -Value *CodeGenFunction::EmitISOVolatileStore(const CallExpr *E) { - Value *Ptr = EmitScalarExpr(E->getArg(0)); - Value *Value = EmitScalarExpr(E->getArg(1)); - QualType ElTy = E->getArg(0)->getType()->getPointeeType(); - CharUnits StoreSize = getContext().getTypeSizeInChars(ElTy); - llvm::Type *ITy = llvm::IntegerType::get(getLLVMContext(), - StoreSize.getQuantity() * 8); - Ptr = Builder.CreateBitCast(Ptr, ITy->getPointerTo()); - llvm::StoreInst *Store = - Builder.CreateAlignedStore(Value, Ptr, - StoreSize); - Store->setVolatile(true); - return Store; -} - -Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, - const CallExpr *E, - llvm::Triple::ArchType Arch) { - if (auto Hint = GetValueForARMHint(BuiltinID)) - return Hint; - - if (BuiltinID == ARM::BI__emit) { - bool IsThumb = getTarget().getTriple().getArch() == llvm::Triple::thumb; - llvm::FunctionType *FTy = - llvm::FunctionType::get(VoidTy, /*Variadic=*/false); - - Expr::EvalResult Result; - if (!E->getArg(0)->EvaluateAsInt(Result, CGM.getContext())) - llvm_unreachable("Sema will ensure that the parameter is constant"); - - llvm::APSInt Value = Result.Val.getInt(); - uint64_t ZExtValue = Value.zextOrTrunc(IsThumb ? 16 : 32).getZExtValue(); - - llvm::InlineAsm *Emit = - IsThumb ? InlineAsm::get(FTy, ".inst.n 0x" + utohexstr(ZExtValue), "", - /*SideEffects=*/true) - : InlineAsm::get(FTy, ".inst 0x" + utohexstr(ZExtValue), "", - /*SideEffects=*/true); - - return Builder.CreateCall(Emit); - } - - if (BuiltinID == ARM::BI__builtin_arm_dbg) { - Value *Option = EmitScalarExpr(E->getArg(0)); - return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_dbg), Option); - } - - if (BuiltinID == ARM::BI__builtin_arm_prefetch) { - Value *Address = EmitScalarExpr(E->getArg(0)); - Value *RW = EmitScalarExpr(E->getArg(1)); - Value *IsData = EmitScalarExpr(E->getArg(2)); - - // Locality is not supported on ARM target - Value *Locality = llvm::ConstantInt::get(Int32Ty, 3); - - Value *F = CGM.getIntrinsic(Intrinsic::prefetch); - return Builder.CreateCall(F, {Address, RW, Locality, IsData}); - } - - if (BuiltinID == ARM::BI__builtin_arm_rbit) { - llvm::Value *Arg = EmitScalarExpr(E->getArg(0)); - return Builder.CreateCall( - CGM.getIntrinsic(Intrinsic::bitreverse, Arg->getType()), Arg, "rbit"); - } - - if (BuiltinID == ARM::BI__clear_cache) { - assert(E->getNumArgs() == 2 && "__clear_cache takes 2 arguments"); - const FunctionDecl *FD = E->getDirectCallee(); - Value *Ops[2]; - for (unsigned i = 0; i < 2; i++) - Ops[i] = EmitScalarExpr(E->getArg(i)); - llvm::Type *Ty = CGM.getTypes().ConvertType(FD->getType()); - llvm::FunctionType *FTy = cast<llvm::FunctionType>(Ty); - StringRef Name = FD->getName(); - return EmitNounwindRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Ops); - } - - if (BuiltinID == ARM::BI__builtin_arm_mcrr || - BuiltinID == ARM::BI__builtin_arm_mcrr2) { - Function *F; - - switch (BuiltinID) { - default: llvm_unreachable("unexpected builtin"); - case ARM::BI__builtin_arm_mcrr: - F = CGM.getIntrinsic(Intrinsic::arm_mcrr); - break; - case ARM::BI__builtin_arm_mcrr2: - F = CGM.getIntrinsic(Intrinsic::arm_mcrr2); - break; - } - - // MCRR{2} instruction has 5 operands but - // the intrinsic has 4 because Rt and Rt2 - // are represented as a single unsigned 64 - // bit integer in the intrinsic definition - // but internally it's represented as 2 32 - // bit integers. - - Value *Coproc = EmitScalarExpr(E->getArg(0)); - Value *Opc1 = EmitScalarExpr(E->getArg(1)); - Value *RtAndRt2 = EmitScalarExpr(E->getArg(2)); - Value *CRm = EmitScalarExpr(E->getArg(3)); - - Value *C1 = llvm::ConstantInt::get(Int64Ty, 32); - Value *Rt = Builder.CreateTruncOrBitCast(RtAndRt2, Int32Ty); - Value *Rt2 = Builder.CreateLShr(RtAndRt2, C1); - Rt2 = Builder.CreateTruncOrBitCast(Rt2, Int32Ty); - - return Builder.CreateCall(F, {Coproc, Opc1, Rt, Rt2, CRm}); - } - - if (BuiltinID == ARM::BI__builtin_arm_mrrc || - BuiltinID == ARM::BI__builtin_arm_mrrc2) { - Function *F; - - switch (BuiltinID) { - default: llvm_unreachable("unexpected builtin"); - case ARM::BI__builtin_arm_mrrc: - F = CGM.getIntrinsic(Intrinsic::arm_mrrc); - break; - case ARM::BI__builtin_arm_mrrc2: - F = CGM.getIntrinsic(Intrinsic::arm_mrrc2); - break; - } - - Value *Coproc = EmitScalarExpr(E->getArg(0)); - Value *Opc1 = EmitScalarExpr(E->getArg(1)); - Value *CRm = EmitScalarExpr(E->getArg(2)); - Value *RtAndRt2 = Builder.CreateCall(F, {Coproc, Opc1, CRm}); - - // Returns an unsigned 64 bit integer, represented - // as two 32 bit integers. - - Value *Rt = Builder.CreateExtractValue(RtAndRt2, 1); - Value *Rt1 = Builder.CreateExtractValue(RtAndRt2, 0); - Rt = Builder.CreateZExt(Rt, Int64Ty); - Rt1 = Builder.CreateZExt(Rt1, Int64Ty); - - Value *ShiftCast = llvm::ConstantInt::get(Int64Ty, 32); - RtAndRt2 = Builder.CreateShl(Rt, ShiftCast, "shl", true); - RtAndRt2 = Builder.CreateOr(RtAndRt2, Rt1); - - return Builder.CreateBitCast(RtAndRt2, ConvertType(E->getType())); - } - - if (BuiltinID == ARM::BI__builtin_arm_ldrexd || - ((BuiltinID == ARM::BI__builtin_arm_ldrex || - BuiltinID == ARM::BI__builtin_arm_ldaex) && - getContext().getTypeSize(E->getType()) == 64) || - BuiltinID == ARM::BI__ldrexd) { - Function *F; - - switch (BuiltinID) { - default: llvm_unreachable("unexpected builtin"); - case ARM::BI__builtin_arm_ldaex: - F = CGM.getIntrinsic(Intrinsic::arm_ldaexd); - break; - case ARM::BI__builtin_arm_ldrexd: - case ARM::BI__builtin_arm_ldrex: - case ARM::BI__ldrexd: - F = CGM.getIntrinsic(Intrinsic::arm_ldrexd); - break; - } - - Value *LdPtr = EmitScalarExpr(E->getArg(0)); - Value *Val = Builder.CreateCall(F, Builder.CreateBitCast(LdPtr, Int8PtrTy), - "ldrexd"); - - Value *Val0 = Builder.CreateExtractValue(Val, 1); - Value *Val1 = Builder.CreateExtractValue(Val, 0); - Val0 = Builder.CreateZExt(Val0, Int64Ty); - Val1 = Builder.CreateZExt(Val1, Int64Ty); - - Value *ShiftCst = llvm::ConstantInt::get(Int64Ty, 32); - Val = Builder.CreateShl(Val0, ShiftCst, "shl", true /* nuw */); - Val = Builder.CreateOr(Val, Val1); - return Builder.CreateBitCast(Val, ConvertType(E->getType())); - } - - if (BuiltinID == ARM::BI__builtin_arm_ldrex || - BuiltinID == ARM::BI__builtin_arm_ldaex) { - Value *LoadAddr = EmitScalarExpr(E->getArg(0)); - - QualType Ty = E->getType(); - llvm::Type *RealResTy = ConvertType(Ty); - llvm::Type *PtrTy = llvm::IntegerType::get( - getLLVMContext(), getContext().getTypeSize(Ty))->getPointerTo(); - LoadAddr = Builder.CreateBitCast(LoadAddr, PtrTy); - - Function *F = CGM.getIntrinsic(BuiltinID == ARM::BI__builtin_arm_ldaex - ? Intrinsic::arm_ldaex - : Intrinsic::arm_ldrex, - PtrTy); - Value *Val = Builder.CreateCall(F, LoadAddr, "ldrex"); - - if (RealResTy->isPointerTy()) - return Builder.CreateIntToPtr(Val, RealResTy); - else { - llvm::Type *IntResTy = llvm::IntegerType::get( - getLLVMContext(), CGM.getDataLayout().getTypeSizeInBits(RealResTy)); - Val = Builder.CreateTruncOrBitCast(Val, IntResTy); - return Builder.CreateBitCast(Val, RealResTy); - } - } - - if (BuiltinID == ARM::BI__builtin_arm_strexd || - ((BuiltinID == ARM::BI__builtin_arm_stlex || - BuiltinID == ARM::BI__builtin_arm_strex) && - getContext().getTypeSize(E->getArg(0)->getType()) == 64)) { - Function *F = CGM.getIntrinsic(BuiltinID == ARM::BI__builtin_arm_stlex - ? Intrinsic::arm_stlexd - : Intrinsic::arm_strexd); - llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty); - - Address Tmp = CreateMemTemp(E->getArg(0)->getType()); - Value *Val = EmitScalarExpr(E->getArg(0)); - Builder.CreateStore(Val, Tmp); - - Address LdPtr = Builder.CreateBitCast(Tmp,llvm::PointerType::getUnqual(STy)); - Val = Builder.CreateLoad(LdPtr); - - Value *Arg0 = Builder.CreateExtractValue(Val, 0); - Value *Arg1 = Builder.CreateExtractValue(Val, 1); - Value *StPtr = Builder.CreateBitCast(EmitScalarExpr(E->getArg(1)), Int8PtrTy); - return Builder.CreateCall(F, {Arg0, Arg1, StPtr}, "strexd"); - } - - if (BuiltinID == ARM::BI__builtin_arm_strex || - BuiltinID == ARM::BI__builtin_arm_stlex) { - Value *StoreVal = EmitScalarExpr(E->getArg(0)); - Value *StoreAddr = EmitScalarExpr(E->getArg(1)); - - QualType Ty = E->getArg(0)->getType(); - llvm::Type *StoreTy = llvm::IntegerType::get(getLLVMContext(), - getContext().getTypeSize(Ty)); - StoreAddr = Builder.CreateBitCast(StoreAddr, StoreTy->getPointerTo()); - - if (StoreVal->getType()->isPointerTy()) - StoreVal = Builder.CreatePtrToInt(StoreVal, Int32Ty); - else { - llvm::Type *IntTy = llvm::IntegerType::get( - getLLVMContext(), - CGM.getDataLayout().getTypeSizeInBits(StoreVal->getType())); - StoreVal = Builder.CreateBitCast(StoreVal, IntTy); - StoreVal = Builder.CreateZExtOrBitCast(StoreVal, Int32Ty); - } - - Function *F = CGM.getIntrinsic(BuiltinID == ARM::BI__builtin_arm_stlex - ? Intrinsic::arm_stlex - : Intrinsic::arm_strex, - StoreAddr->getType()); - return Builder.CreateCall(F, {StoreVal, StoreAddr}, "strex"); - } - - switch (BuiltinID) { - case ARM::BI__iso_volatile_load8: - case ARM::BI__iso_volatile_load16: - case ARM::BI__iso_volatile_load32: - case ARM::BI__iso_volatile_load64: - return EmitISOVolatileLoad(E); - case ARM::BI__iso_volatile_store8: - case ARM::BI__iso_volatile_store16: - case ARM::BI__iso_volatile_store32: - case ARM::BI__iso_volatile_store64: - return EmitISOVolatileStore(E); - } - - if (BuiltinID == ARM::BI__builtin_arm_clrex) { - Function *F = CGM.getIntrinsic(Intrinsic::arm_clrex); - return Builder.CreateCall(F); - } - - // CRC32 - Intrinsic::ID CRCIntrinsicID = Intrinsic::not_intrinsic; - switch (BuiltinID) { - case ARM::BI__builtin_arm_crc32b: - CRCIntrinsicID = Intrinsic::arm_crc32b; break; - case ARM::BI__builtin_arm_crc32cb: - CRCIntrinsicID = Intrinsic::arm_crc32cb; break; - case ARM::BI__builtin_arm_crc32h: - CRCIntrinsicID = Intrinsic::arm_crc32h; break; - case ARM::BI__builtin_arm_crc32ch: - CRCIntrinsicID = Intrinsic::arm_crc32ch; break; - case ARM::BI__builtin_arm_crc32w: - case ARM::BI__builtin_arm_crc32d: - CRCIntrinsicID = Intrinsic::arm_crc32w; break; - case ARM::BI__builtin_arm_crc32cw: - case ARM::BI__builtin_arm_crc32cd: - CRCIntrinsicID = Intrinsic::arm_crc32cw; break; - } - - if (CRCIntrinsicID != Intrinsic::not_intrinsic) { - Value *Arg0 = EmitScalarExpr(E->getArg(0)); - Value *Arg1 = EmitScalarExpr(E->getArg(1)); - - // crc32{c,}d intrinsics are implemnted as two calls to crc32{c,}w - // intrinsics, hence we need different codegen for these cases. - if (BuiltinID == ARM::BI__builtin_arm_crc32d || - BuiltinID == ARM::BI__builtin_arm_crc32cd) { - Value *C1 = llvm::ConstantInt::get(Int64Ty, 32); - Value *Arg1a = Builder.CreateTruncOrBitCast(Arg1, Int32Ty); - Value *Arg1b = Builder.CreateLShr(Arg1, C1); - Arg1b = Builder.CreateTruncOrBitCast(Arg1b, Int32Ty); - - Function *F = CGM.getIntrinsic(CRCIntrinsicID); - Value *Res = Builder.CreateCall(F, {Arg0, Arg1a}); - return Builder.CreateCall(F, {Res, Arg1b}); - } else { - Arg1 = Builder.CreateZExtOrBitCast(Arg1, Int32Ty); - - Function *F = CGM.getIntrinsic(CRCIntrinsicID); - return Builder.CreateCall(F, {Arg0, Arg1}); - } - } - - if (BuiltinID == ARM::BI__builtin_arm_rsr || - BuiltinID == ARM::BI__builtin_arm_rsr64 || - BuiltinID == ARM::BI__builtin_arm_rsrp || - BuiltinID == ARM::BI__builtin_arm_wsr || - BuiltinID == ARM::BI__builtin_arm_wsr64 || - BuiltinID == ARM::BI__builtin_arm_wsrp) { - - bool IsRead = BuiltinID == ARM::BI__builtin_arm_rsr || - BuiltinID == ARM::BI__builtin_arm_rsr64 || - BuiltinID == ARM::BI__builtin_arm_rsrp; - - bool IsPointerBuiltin = BuiltinID == ARM::BI__builtin_arm_rsrp || - BuiltinID == ARM::BI__builtin_arm_wsrp; - - bool Is64Bit = BuiltinID == ARM::BI__builtin_arm_rsr64 || - BuiltinID == ARM::BI__builtin_arm_wsr64; - - llvm::Type *ValueType; - llvm::Type *RegisterType; - if (IsPointerBuiltin) { - ValueType = VoidPtrTy; - RegisterType = Int32Ty; - } else if (Is64Bit) { - ValueType = RegisterType = Int64Ty; - } else { - ValueType = RegisterType = Int32Ty; - } - - return EmitSpecialRegisterBuiltin(*this, E, RegisterType, ValueType, IsRead); - } - - // Find out if any arguments are required to be integer constant - // expressions. - unsigned ICEArguments = 0; - ASTContext::GetBuiltinTypeError Error; - getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments); - assert(Error == ASTContext::GE_None && "Should not codegen an error"); - - auto getAlignmentValue32 = [&](Address addr) -> Value* { - return Builder.getInt32(addr.getAlignment().getQuantity()); - }; - - Address PtrOp0 = Address::invalid(); - Address PtrOp1 = Address::invalid(); - SmallVector<Value*, 4> Ops; - bool HasExtraArg = HasExtraNeonArgument(BuiltinID); - unsigned NumArgs = E->getNumArgs() - (HasExtraArg ? 1 : 0); - for (unsigned i = 0, e = NumArgs; i != e; i++) { - if (i == 0) { - switch (BuiltinID) { - case NEON::BI__builtin_neon_vld1_v: - case NEON::BI__builtin_neon_vld1q_v: - case NEON::BI__builtin_neon_vld1q_lane_v: - case NEON::BI__builtin_neon_vld1_lane_v: - case NEON::BI__builtin_neon_vld1_dup_v: - case NEON::BI__builtin_neon_vld1q_dup_v: - case NEON::BI__builtin_neon_vst1_v: - case NEON::BI__builtin_neon_vst1q_v: - case NEON::BI__builtin_neon_vst1q_lane_v: - case NEON::BI__builtin_neon_vst1_lane_v: - case NEON::BI__builtin_neon_vst2_v: - case NEON::BI__builtin_neon_vst2q_v: - case NEON::BI__builtin_neon_vst2_lane_v: - case NEON::BI__builtin_neon_vst2q_lane_v: - case NEON::BI__builtin_neon_vst3_v: - case NEON::BI__builtin_neon_vst3q_v: - case NEON::BI__builtin_neon_vst3_lane_v: - case NEON::BI__builtin_neon_vst3q_lane_v: - case NEON::BI__builtin_neon_vst4_v: - case NEON::BI__builtin_neon_vst4q_v: - case NEON::BI__builtin_neon_vst4_lane_v: - case NEON::BI__builtin_neon_vst4q_lane_v: - // Get the alignment for the argument in addition to the value; - // we'll use it later. - PtrOp0 = EmitPointerWithAlignment(E->getArg(0)); - Ops.push_back(PtrOp0.getPointer()); - continue; - } - } - if (i == 1) { - switch (BuiltinID) { - case NEON::BI__builtin_neon_vld2_v: - case NEON::BI__builtin_neon_vld2q_v: - case NEON::BI__builtin_neon_vld3_v: - case NEON::BI__builtin_neon_vld3q_v: - case NEON::BI__builtin_neon_vld4_v: - case NEON::BI__builtin_neon_vld4q_v: - case NEON::BI__builtin_neon_vld2_lane_v: - case NEON::BI__builtin_neon_vld2q_lane_v: - case NEON::BI__builtin_neon_vld3_lane_v: - case NEON::BI__builtin_neon_vld3q_lane_v: - case NEON::BI__builtin_neon_vld4_lane_v: - case NEON::BI__builtin_neon_vld4q_lane_v: - case NEON::BI__builtin_neon_vld2_dup_v: - case NEON::BI__builtin_neon_vld2q_dup_v: - case NEON::BI__builtin_neon_vld3_dup_v: - case NEON::BI__builtin_neon_vld3q_dup_v: - case NEON::BI__builtin_neon_vld4_dup_v: - case NEON::BI__builtin_neon_vld4q_dup_v: - // Get the alignment for the argument in addition to the value; - // we'll use it later. - PtrOp1 = EmitPointerWithAlignment(E->getArg(1)); - Ops.push_back(PtrOp1.getPointer()); - continue; - } - } - - if ((ICEArguments & (1 << i)) == 0) { - Ops.push_back(EmitScalarExpr(E->getArg(i))); - } else { - // If this is required to be a constant, constant fold it so that we know - // that the generated intrinsic gets a ConstantInt. - llvm::APSInt Result; - bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result, getContext()); - assert(IsConst && "Constant arg isn't actually constant?"); (void)IsConst; - Ops.push_back(llvm::ConstantInt::get(getLLVMContext(), Result)); - } - } - - switch (BuiltinID) { - default: break; - - case NEON::BI__builtin_neon_vget_lane_i8: - case NEON::BI__builtin_neon_vget_lane_i16: - case NEON::BI__builtin_neon_vget_lane_i32: - case NEON::BI__builtin_neon_vget_lane_i64: - case NEON::BI__builtin_neon_vget_lane_f32: - case NEON::BI__builtin_neon_vgetq_lane_i8: - case NEON::BI__builtin_neon_vgetq_lane_i16: - case NEON::BI__builtin_neon_vgetq_lane_i32: - case NEON::BI__builtin_neon_vgetq_lane_i64: - case NEON::BI__builtin_neon_vgetq_lane_f32: - return Builder.CreateExtractElement(Ops[0], Ops[1], "vget_lane"); - - case NEON::BI__builtin_neon_vrndns_f32: { - Value *Arg = EmitScalarExpr(E->getArg(0)); - llvm::Type *Tys[] = {Arg->getType()}; - Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vrintn, Tys); - return Builder.CreateCall(F, {Arg}, "vrndn"); } - - case NEON::BI__builtin_neon_vset_lane_i8: - case NEON::BI__builtin_neon_vset_lane_i16: - case NEON::BI__builtin_neon_vset_lane_i32: - case NEON::BI__builtin_neon_vset_lane_i64: - case NEON::BI__builtin_neon_vset_lane_f32: - case NEON::BI__builtin_neon_vsetq_lane_i8: - case NEON::BI__builtin_neon_vsetq_lane_i16: - case NEON::BI__builtin_neon_vsetq_lane_i32: - case NEON::BI__builtin_neon_vsetq_lane_i64: - case NEON::BI__builtin_neon_vsetq_lane_f32: - return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vset_lane"); - - case NEON::BI__builtin_neon_vsha1h_u32: - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1h), Ops, - "vsha1h"); - case NEON::BI__builtin_neon_vsha1cq_u32: - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1c), Ops, - "vsha1h"); - case NEON::BI__builtin_neon_vsha1pq_u32: - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1p), Ops, - "vsha1h"); - case NEON::BI__builtin_neon_vsha1mq_u32: - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1m), Ops, - "vsha1h"); - - // The ARM _MoveToCoprocessor builtins put the input register value as - // the first argument, but the LLVM intrinsic expects it as the third one. - case ARM::BI_MoveToCoprocessor: - case ARM::BI_MoveToCoprocessor2: { - Function *F = CGM.getIntrinsic(BuiltinID == ARM::BI_MoveToCoprocessor ? - Intrinsic::arm_mcr : Intrinsic::arm_mcr2); - return Builder.CreateCall(F, {Ops[1], Ops[2], Ops[0], - Ops[3], Ops[4], Ops[5]}); - } - case ARM::BI_BitScanForward: - case ARM::BI_BitScanForward64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_BitScanForward, E); - case ARM::BI_BitScanReverse: - case ARM::BI_BitScanReverse64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_BitScanReverse, E); - - case ARM::BI_InterlockedAnd64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd, E); - case ARM::BI_InterlockedExchange64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange, E); - case ARM::BI_InterlockedExchangeAdd64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd, E); - case ARM::BI_InterlockedExchangeSub64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeSub, E); - case ARM::BI_InterlockedOr64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr, E); - case ARM::BI_InterlockedXor64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor, E); - case ARM::BI_InterlockedDecrement64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement, E); - case ARM::BI_InterlockedIncrement64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement, E); - case ARM::BI_InterlockedExchangeAdd8_acq: - case ARM::BI_InterlockedExchangeAdd16_acq: - case ARM::BI_InterlockedExchangeAdd_acq: - case ARM::BI_InterlockedExchangeAdd64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd_acq, E); - case ARM::BI_InterlockedExchangeAdd8_rel: - case ARM::BI_InterlockedExchangeAdd16_rel: - case ARM::BI_InterlockedExchangeAdd_rel: - case ARM::BI_InterlockedExchangeAdd64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd_rel, E); - case ARM::BI_InterlockedExchangeAdd8_nf: - case ARM::BI_InterlockedExchangeAdd16_nf: - case ARM::BI_InterlockedExchangeAdd_nf: - case ARM::BI_InterlockedExchangeAdd64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd_nf, E); - case ARM::BI_InterlockedExchange8_acq: - case ARM::BI_InterlockedExchange16_acq: - case ARM::BI_InterlockedExchange_acq: - case ARM::BI_InterlockedExchange64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange_acq, E); - case ARM::BI_InterlockedExchange8_rel: - case ARM::BI_InterlockedExchange16_rel: - case ARM::BI_InterlockedExchange_rel: - case ARM::BI_InterlockedExchange64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange_rel, E); - case ARM::BI_InterlockedExchange8_nf: - case ARM::BI_InterlockedExchange16_nf: - case ARM::BI_InterlockedExchange_nf: - case ARM::BI_InterlockedExchange64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange_nf, E); - case ARM::BI_InterlockedCompareExchange8_acq: - case ARM::BI_InterlockedCompareExchange16_acq: - case ARM::BI_InterlockedCompareExchange_acq: - case ARM::BI_InterlockedCompareExchange64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange_acq, E); - case ARM::BI_InterlockedCompareExchange8_rel: - case ARM::BI_InterlockedCompareExchange16_rel: - case ARM::BI_InterlockedCompareExchange_rel: - case ARM::BI_InterlockedCompareExchange64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange_rel, E); - case ARM::BI_InterlockedCompareExchange8_nf: - case ARM::BI_InterlockedCompareExchange16_nf: - case ARM::BI_InterlockedCompareExchange_nf: - case ARM::BI_InterlockedCompareExchange64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange_nf, E); - case ARM::BI_InterlockedOr8_acq: - case ARM::BI_InterlockedOr16_acq: - case ARM::BI_InterlockedOr_acq: - case ARM::BI_InterlockedOr64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr_acq, E); - case ARM::BI_InterlockedOr8_rel: - case ARM::BI_InterlockedOr16_rel: - case ARM::BI_InterlockedOr_rel: - case ARM::BI_InterlockedOr64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr_rel, E); - case ARM::BI_InterlockedOr8_nf: - case ARM::BI_InterlockedOr16_nf: - case ARM::BI_InterlockedOr_nf: - case ARM::BI_InterlockedOr64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr_nf, E); - case ARM::BI_InterlockedXor8_acq: - case ARM::BI_InterlockedXor16_acq: - case ARM::BI_InterlockedXor_acq: - case ARM::BI_InterlockedXor64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor_acq, E); - case ARM::BI_InterlockedXor8_rel: - case ARM::BI_InterlockedXor16_rel: - case ARM::BI_InterlockedXor_rel: - case ARM::BI_InterlockedXor64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor_rel, E); - case ARM::BI_InterlockedXor8_nf: - case ARM::BI_InterlockedXor16_nf: - case ARM::BI_InterlockedXor_nf: - case ARM::BI_InterlockedXor64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor_nf, E); - case ARM::BI_InterlockedAnd8_acq: - case ARM::BI_InterlockedAnd16_acq: - case ARM::BI_InterlockedAnd_acq: - case ARM::BI_InterlockedAnd64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd_acq, E); - case ARM::BI_InterlockedAnd8_rel: - case ARM::BI_InterlockedAnd16_rel: - case ARM::BI_InterlockedAnd_rel: - case ARM::BI_InterlockedAnd64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd_rel, E); - case ARM::BI_InterlockedAnd8_nf: - case ARM::BI_InterlockedAnd16_nf: - case ARM::BI_InterlockedAnd_nf: - case ARM::BI_InterlockedAnd64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd_nf, E); - case ARM::BI_InterlockedIncrement16_acq: - case ARM::BI_InterlockedIncrement_acq: - case ARM::BI_InterlockedIncrement64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement_acq, E); - case ARM::BI_InterlockedIncrement16_rel: - case ARM::BI_InterlockedIncrement_rel: - case ARM::BI_InterlockedIncrement64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement_rel, E); - case ARM::BI_InterlockedIncrement16_nf: - case ARM::BI_InterlockedIncrement_nf: - case ARM::BI_InterlockedIncrement64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement_nf, E); - case ARM::BI_InterlockedDecrement16_acq: - case ARM::BI_InterlockedDecrement_acq: - case ARM::BI_InterlockedDecrement64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement_acq, E); - case ARM::BI_InterlockedDecrement16_rel: - case ARM::BI_InterlockedDecrement_rel: - case ARM::BI_InterlockedDecrement64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement_rel, E); - case ARM::BI_InterlockedDecrement16_nf: - case ARM::BI_InterlockedDecrement_nf: - case ARM::BI_InterlockedDecrement64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement_nf, E); - } - - // Get the last argument, which specifies the vector type. - assert(HasExtraArg); - llvm::APSInt Result; - const Expr *Arg = E->getArg(E->getNumArgs()-1); - if (!Arg->isIntegerConstantExpr(Result, getContext())) - return nullptr; - - if (BuiltinID == ARM::BI__builtin_arm_vcvtr_f || - BuiltinID == ARM::BI__builtin_arm_vcvtr_d) { - // Determine the overloaded type of this builtin. - llvm::Type *Ty; - if (BuiltinID == ARM::BI__builtin_arm_vcvtr_f) - Ty = FloatTy; - else - Ty = DoubleTy; - - // Determine whether this is an unsigned conversion or not. - bool usgn = Result.getZExtValue() == 1; - unsigned Int = usgn ? Intrinsic::arm_vcvtru : Intrinsic::arm_vcvtr; - - // Call the appropriate intrinsic. - Function *F = CGM.getIntrinsic(Int, Ty); - return Builder.CreateCall(F, Ops, "vcvtr"); - } - - // Determine the type of this overloaded NEON intrinsic. - NeonTypeFlags Type(Result.getZExtValue()); - bool usgn = Type.isUnsigned(); - bool rightShift = false; - - llvm::VectorType *VTy = GetNeonType(this, Type, - getTarget().hasLegalHalfType()); - llvm::Type *Ty = VTy; - if (!Ty) - return nullptr; - - // Many NEON builtins have identical semantics and uses in ARM and - // AArch64. Emit these in a single function. - auto IntrinsicMap = makeArrayRef(ARMSIMDIntrinsicMap); - const NeonIntrinsicInfo *Builtin = findNeonIntrinsicInMap( - IntrinsicMap, BuiltinID, NEONSIMDIntrinsicsProvenSorted); - if (Builtin) - return EmitCommonNeonBuiltinExpr( - Builtin->BuiltinID, Builtin->LLVMIntrinsic, Builtin->AltLLVMIntrinsic, - Builtin->NameHint, Builtin->TypeModifier, E, Ops, PtrOp0, PtrOp1, Arch); - - unsigned Int; - switch (BuiltinID) { - default: return nullptr; - case NEON::BI__builtin_neon_vld1q_lane_v: - // Handle 64-bit integer elements as a special case. Use shuffles of - // one-element vectors to avoid poor code for i64 in the backend. - if (VTy->getElementType()->isIntegerTy(64)) { - // Extract the other lane. - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - uint32_t Lane = cast<ConstantInt>(Ops[2])->getZExtValue(); - Value *SV = llvm::ConstantVector::get(ConstantInt::get(Int32Ty, 1-Lane)); - Ops[1] = Builder.CreateShuffleVector(Ops[1], Ops[1], SV); - // Load the value as a one-element vector. - Ty = llvm::VectorType::get(VTy->getElementType(), 1); - llvm::Type *Tys[] = {Ty, Int8PtrTy}; - Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld1, Tys); - Value *Align = getAlignmentValue32(PtrOp0); - Value *Ld = Builder.CreateCall(F, {Ops[0], Align}); - // Combine them. - uint32_t Indices[] = {1 - Lane, Lane}; - SV = llvm::ConstantDataVector::get(getLLVMContext(), Indices); - return Builder.CreateShuffleVector(Ops[1], Ld, SV, "vld1q_lane"); - } - LLVM_FALLTHROUGH; - case NEON::BI__builtin_neon_vld1_lane_v: { - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - PtrOp0 = Builder.CreateElementBitCast(PtrOp0, VTy->getElementType()); - Value *Ld = Builder.CreateLoad(PtrOp0); - return Builder.CreateInsertElement(Ops[1], Ld, Ops[2], "vld1_lane"); - } - case NEON::BI__builtin_neon_vqrshrn_n_v: - Int = - usgn ? Intrinsic::arm_neon_vqrshiftnu : Intrinsic::arm_neon_vqrshiftns; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqrshrn_n", - 1, true); - case NEON::BI__builtin_neon_vqrshrun_n_v: - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqrshiftnsu, Ty), - Ops, "vqrshrun_n", 1, true); - case NEON::BI__builtin_neon_vqshrn_n_v: - Int = usgn ? Intrinsic::arm_neon_vqshiftnu : Intrinsic::arm_neon_vqshiftns; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshrn_n", - 1, true); - case NEON::BI__builtin_neon_vqshrun_n_v: - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqshiftnsu, Ty), - Ops, "vqshrun_n", 1, true); - case NEON::BI__builtin_neon_vrecpe_v: - case NEON::BI__builtin_neon_vrecpeq_v: - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vrecpe, Ty), - Ops, "vrecpe"); - case NEON::BI__builtin_neon_vrshrn_n_v: - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vrshiftn, Ty), - Ops, "vrshrn_n", 1, true); - case NEON::BI__builtin_neon_vrsra_n_v: - case NEON::BI__builtin_neon_vrsraq_n_v: - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - Ops[2] = EmitNeonShiftVector(Ops[2], Ty, true); - Int = usgn ? Intrinsic::arm_neon_vrshiftu : Intrinsic::arm_neon_vrshifts; - Ops[1] = Builder.CreateCall(CGM.getIntrinsic(Int, Ty), {Ops[1], Ops[2]}); - return Builder.CreateAdd(Ops[0], Ops[1], "vrsra_n"); - case NEON::BI__builtin_neon_vsri_n_v: - case NEON::BI__builtin_neon_vsriq_n_v: - rightShift = true; - LLVM_FALLTHROUGH; - case NEON::BI__builtin_neon_vsli_n_v: - case NEON::BI__builtin_neon_vsliq_n_v: - Ops[2] = EmitNeonShiftVector(Ops[2], Ty, rightShift); - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vshiftins, Ty), - Ops, "vsli_n"); - case NEON::BI__builtin_neon_vsra_n_v: - case NEON::BI__builtin_neon_vsraq_n_v: - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - Ops[1] = EmitNeonRShiftImm(Ops[1], Ops[2], Ty, usgn, "vsra_n"); - return Builder.CreateAdd(Ops[0], Ops[1]); - case NEON::BI__builtin_neon_vst1q_lane_v: - // Handle 64-bit integer elements as a special case. Use a shuffle to get - // a one-element vector and avoid poor code for i64 in the backend. - if (VTy->getElementType()->isIntegerTy(64)) { - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - Value *SV = llvm::ConstantVector::get(cast<llvm::Constant>(Ops[2])); - Ops[1] = Builder.CreateShuffleVector(Ops[1], Ops[1], SV); - Ops[2] = getAlignmentValue32(PtrOp0); - llvm::Type *Tys[] = {Int8PtrTy, Ops[1]->getType()}; - return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst1, - Tys), Ops); - } - LLVM_FALLTHROUGH; - case NEON::BI__builtin_neon_vst1_lane_v: { - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2]); - Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); - auto St = Builder.CreateStore(Ops[1], Builder.CreateBitCast(PtrOp0, Ty)); - return St; - } - case NEON::BI__builtin_neon_vtbl1_v: - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl1), - Ops, "vtbl1"); - case NEON::BI__builtin_neon_vtbl2_v: - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl2), - Ops, "vtbl2"); - case NEON::BI__builtin_neon_vtbl3_v: - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl3), - Ops, "vtbl3"); - case NEON::BI__builtin_neon_vtbl4_v: - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl4), - Ops, "vtbl4"); - case NEON::BI__builtin_neon_vtbx1_v: - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx1), - Ops, "vtbx1"); - case NEON::BI__builtin_neon_vtbx2_v: - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx2), - Ops, "vtbx2"); - case NEON::BI__builtin_neon_vtbx3_v: - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx3), - Ops, "vtbx3"); - case NEON::BI__builtin_neon_vtbx4_v: - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx4), - Ops, "vtbx4"); - } -} - -static Value *EmitAArch64TblBuiltinExpr(CodeGenFunction &CGF, unsigned BuiltinID, - const CallExpr *E, - SmallVectorImpl<Value *> &Ops, - llvm::Triple::ArchType Arch) { - unsigned int Int = 0; - const char *s = nullptr; - - switch (BuiltinID) { - default: - return nullptr; - case NEON::BI__builtin_neon_vtbl1_v: - case NEON::BI__builtin_neon_vqtbl1_v: - case NEON::BI__builtin_neon_vqtbl1q_v: - case NEON::BI__builtin_neon_vtbl2_v: - case NEON::BI__builtin_neon_vqtbl2_v: - case NEON::BI__builtin_neon_vqtbl2q_v: - case NEON::BI__builtin_neon_vtbl3_v: - case NEON::BI__builtin_neon_vqtbl3_v: - case NEON::BI__builtin_neon_vqtbl3q_v: - case NEON::BI__builtin_neon_vtbl4_v: - case NEON::BI__builtin_neon_vqtbl4_v: - case NEON::BI__builtin_neon_vqtbl4q_v: - break; - case NEON::BI__builtin_neon_vtbx1_v: - case NEON::BI__builtin_neon_vqtbx1_v: - case NEON::BI__builtin_neon_vqtbx1q_v: - case NEON::BI__builtin_neon_vtbx2_v: - case NEON::BI__builtin_neon_vqtbx2_v: - case NEON::BI__builtin_neon_vqtbx2q_v: - case NEON::BI__builtin_neon_vtbx3_v: - case NEON::BI__builtin_neon_vqtbx3_v: - case NEON::BI__builtin_neon_vqtbx3q_v: - case NEON::BI__builtin_neon_vtbx4_v: - case NEON::BI__builtin_neon_vqtbx4_v: - case NEON::BI__builtin_neon_vqtbx4q_v: - break; - } - - assert(E->getNumArgs() >= 3); - - // Get the last argument, which specifies the vector type. - llvm::APSInt Result; - const Expr *Arg = E->getArg(E->getNumArgs() - 1); - if (!Arg->isIntegerConstantExpr(Result, CGF.getContext())) - return nullptr; - - // Determine the type of this overloaded NEON intrinsic. - NeonTypeFlags Type(Result.getZExtValue()); - llvm::VectorType *Ty = GetNeonType(&CGF, Type); - if (!Ty) - return nullptr; - - CodeGen::CGBuilderTy &Builder = CGF.Builder; - - // AArch64 scalar builtins are not overloaded, they do not have an extra - // argument that specifies the vector type, need to handle each case. - switch (BuiltinID) { - case NEON::BI__builtin_neon_vtbl1_v: { - return packTBLDVectorList(CGF, makeArrayRef(Ops).slice(0, 1), nullptr, - Ops[1], Ty, Intrinsic::aarch64_neon_tbl1, - "vtbl1"); - } - case NEON::BI__builtin_neon_vtbl2_v: { - return packTBLDVectorList(CGF, makeArrayRef(Ops).slice(0, 2), nullptr, - Ops[2], Ty, Intrinsic::aarch64_neon_tbl1, - "vtbl1"); - } - case NEON::BI__builtin_neon_vtbl3_v: { - return packTBLDVectorList(CGF, makeArrayRef(Ops).slice(0, 3), nullptr, - Ops[3], Ty, Intrinsic::aarch64_neon_tbl2, - "vtbl2"); - } - case NEON::BI__builtin_neon_vtbl4_v: { - return packTBLDVectorList(CGF, makeArrayRef(Ops).slice(0, 4), nullptr, - Ops[4], Ty, Intrinsic::aarch64_neon_tbl2, - "vtbl2"); - } - case NEON::BI__builtin_neon_vtbx1_v: { - Value *TblRes = - packTBLDVectorList(CGF, makeArrayRef(Ops).slice(1, 1), nullptr, Ops[2], - Ty, Intrinsic::aarch64_neon_tbl1, "vtbl1"); - - llvm::Constant *EightV = ConstantInt::get(Ty, 8); - Value *CmpRes = Builder.CreateICmp(ICmpInst::ICMP_UGE, Ops[2], EightV); - CmpRes = Builder.CreateSExt(CmpRes, Ty); - - Value *EltsFromInput = Builder.CreateAnd(CmpRes, Ops[0]); - Value *EltsFromTbl = Builder.CreateAnd(Builder.CreateNot(CmpRes), TblRes); - return Builder.CreateOr(EltsFromInput, EltsFromTbl, "vtbx"); - } - case NEON::BI__builtin_neon_vtbx2_v: { - return packTBLDVectorList(CGF, makeArrayRef(Ops).slice(1, 2), Ops[0], - Ops[3], Ty, Intrinsic::aarch64_neon_tbx1, - "vtbx1"); - } - case NEON::BI__builtin_neon_vtbx3_v: { - Value *TblRes = - packTBLDVectorList(CGF, makeArrayRef(Ops).slice(1, 3), nullptr, Ops[4], - Ty, Intrinsic::aarch64_neon_tbl2, "vtbl2"); - - llvm::Constant *TwentyFourV = ConstantInt::get(Ty, 24); - Value *CmpRes = Builder.CreateICmp(ICmpInst::ICMP_UGE, Ops[4], - TwentyFourV); - CmpRes = Builder.CreateSExt(CmpRes, Ty); - - Value *EltsFromInput = Builder.CreateAnd(CmpRes, Ops[0]); - Value *EltsFromTbl = Builder.CreateAnd(Builder.CreateNot(CmpRes), TblRes); - return Builder.CreateOr(EltsFromInput, EltsFromTbl, "vtbx"); - } - case NEON::BI__builtin_neon_vtbx4_v: { - return packTBLDVectorList(CGF, makeArrayRef(Ops).slice(1, 4), Ops[0], - Ops[5], Ty, Intrinsic::aarch64_neon_tbx2, - "vtbx2"); - } - case NEON::BI__builtin_neon_vqtbl1_v: - case NEON::BI__builtin_neon_vqtbl1q_v: - Int = Intrinsic::aarch64_neon_tbl1; s = "vtbl1"; break; - case NEON::BI__builtin_neon_vqtbl2_v: - case NEON::BI__builtin_neon_vqtbl2q_v: { - Int = Intrinsic::aarch64_neon_tbl2; s = "vtbl2"; break; - case NEON::BI__builtin_neon_vqtbl3_v: - case NEON::BI__builtin_neon_vqtbl3q_v: - Int = Intrinsic::aarch64_neon_tbl3; s = "vtbl3"; break; - case NEON::BI__builtin_neon_vqtbl4_v: - case NEON::BI__builtin_neon_vqtbl4q_v: - Int = Intrinsic::aarch64_neon_tbl4; s = "vtbl4"; break; - case NEON::BI__builtin_neon_vqtbx1_v: - case NEON::BI__builtin_neon_vqtbx1q_v: - Int = Intrinsic::aarch64_neon_tbx1; s = "vtbx1"; break; - case NEON::BI__builtin_neon_vqtbx2_v: - case NEON::BI__builtin_neon_vqtbx2q_v: - Int = Intrinsic::aarch64_neon_tbx2; s = "vtbx2"; break; - case NEON::BI__builtin_neon_vqtbx3_v: - case NEON::BI__builtin_neon_vqtbx3q_v: - Int = Intrinsic::aarch64_neon_tbx3; s = "vtbx3"; break; - case NEON::BI__builtin_neon_vqtbx4_v: - case NEON::BI__builtin_neon_vqtbx4q_v: - Int = Intrinsic::aarch64_neon_tbx4; s = "vtbx4"; break; - } - } - - if (!Int) - return nullptr; - - Function *F = CGF.CGM.getIntrinsic(Int, Ty); - return CGF.EmitNeonCall(F, Ops, s); -} - -Value *CodeGenFunction::vectorWrapScalar16(Value *Op) { - llvm::Type *VTy = llvm::VectorType::get(Int16Ty, 4); - Op = Builder.CreateBitCast(Op, Int16Ty); - Value *V = UndefValue::get(VTy); - llvm::Constant *CI = ConstantInt::get(SizeTy, 0); - Op = Builder.CreateInsertElement(V, Op, CI); - return Op; -} - -Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, - const CallExpr *E, - llvm::Triple::ArchType Arch) { - unsigned HintID = static_cast<unsigned>(-1); - switch (BuiltinID) { - default: break; - case AArch64::BI__builtin_arm_nop: - HintID = 0; - break; - case AArch64::BI__builtin_arm_yield: - case AArch64::BI__yield: - HintID = 1; - break; - case AArch64::BI__builtin_arm_wfe: - case AArch64::BI__wfe: - HintID = 2; - break; - case AArch64::BI__builtin_arm_wfi: - case AArch64::BI__wfi: - HintID = 3; - break; - case AArch64::BI__builtin_arm_sev: - case AArch64::BI__sev: - HintID = 4; - break; - case AArch64::BI__builtin_arm_sevl: - case AArch64::BI__sevl: - HintID = 5; - break; - } - - if (HintID != static_cast<unsigned>(-1)) { - Function *F = CGM.getIntrinsic(Intrinsic::aarch64_hint); - return Builder.CreateCall(F, llvm::ConstantInt::get(Int32Ty, HintID)); - } - - if (BuiltinID == AArch64::BI__builtin_arm_prefetch) { - Value *Address = EmitScalarExpr(E->getArg(0)); - Value *RW = EmitScalarExpr(E->getArg(1)); - Value *CacheLevel = EmitScalarExpr(E->getArg(2)); - Value *RetentionPolicy = EmitScalarExpr(E->getArg(3)); - Value *IsData = EmitScalarExpr(E->getArg(4)); - - Value *Locality = nullptr; - if (cast<llvm::ConstantInt>(RetentionPolicy)->isZero()) { - // Temporal fetch, needs to convert cache level to locality. - Locality = llvm::ConstantInt::get(Int32Ty, - -cast<llvm::ConstantInt>(CacheLevel)->getValue() + 3); - } else { - // Streaming fetch. - Locality = llvm::ConstantInt::get(Int32Ty, 0); - } - - // FIXME: We need AArch64 specific LLVM intrinsic if we want to specify - // PLDL3STRM or PLDL2STRM. - Value *F = CGM.getIntrinsic(Intrinsic::prefetch); - return Builder.CreateCall(F, {Address, RW, Locality, IsData}); - } - - if (BuiltinID == AArch64::BI__builtin_arm_rbit) { - assert((getContext().getTypeSize(E->getType()) == 32) && - "rbit of unusual size!"); - llvm::Value *Arg = EmitScalarExpr(E->getArg(0)); - return Builder.CreateCall( - CGM.getIntrinsic(Intrinsic::bitreverse, Arg->getType()), Arg, "rbit"); - } - if (BuiltinID == AArch64::BI__builtin_arm_rbit64) { - assert((getContext().getTypeSize(E->getType()) == 64) && - "rbit of unusual size!"); - llvm::Value *Arg = EmitScalarExpr(E->getArg(0)); - return Builder.CreateCall( - CGM.getIntrinsic(Intrinsic::bitreverse, Arg->getType()), Arg, "rbit"); - } - - if (BuiltinID == AArch64::BI__clear_cache) { - assert(E->getNumArgs() == 2 && "__clear_cache takes 2 arguments"); - const FunctionDecl *FD = E->getDirectCallee(); - Value *Ops[2]; - for (unsigned i = 0; i < 2; i++) - Ops[i] = EmitScalarExpr(E->getArg(i)); - llvm::Type *Ty = CGM.getTypes().ConvertType(FD->getType()); - llvm::FunctionType *FTy = cast<llvm::FunctionType>(Ty); - StringRef Name = FD->getName(); - return EmitNounwindRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Ops); - } - - if ((BuiltinID == AArch64::BI__builtin_arm_ldrex || - BuiltinID == AArch64::BI__builtin_arm_ldaex) && - getContext().getTypeSize(E->getType()) == 128) { - Function *F = CGM.getIntrinsic(BuiltinID == AArch64::BI__builtin_arm_ldaex - ? Intrinsic::aarch64_ldaxp - : Intrinsic::aarch64_ldxp); - - Value *LdPtr = EmitScalarExpr(E->getArg(0)); - Value *Val = Builder.CreateCall(F, Builder.CreateBitCast(LdPtr, Int8PtrTy), - "ldxp"); - - Value *Val0 = Builder.CreateExtractValue(Val, 1); - Value *Val1 = Builder.CreateExtractValue(Val, 0); - llvm::Type *Int128Ty = llvm::IntegerType::get(getLLVMContext(), 128); - Val0 = Builder.CreateZExt(Val0, Int128Ty); - Val1 = Builder.CreateZExt(Val1, Int128Ty); - - Value *ShiftCst = llvm::ConstantInt::get(Int128Ty, 64); - Val = Builder.CreateShl(Val0, ShiftCst, "shl", true /* nuw */); - Val = Builder.CreateOr(Val, Val1); - return Builder.CreateBitCast(Val, ConvertType(E->getType())); - } else if (BuiltinID == AArch64::BI__builtin_arm_ldrex || - BuiltinID == AArch64::BI__builtin_arm_ldaex) { - Value *LoadAddr = EmitScalarExpr(E->getArg(0)); - - QualType Ty = E->getType(); - llvm::Type *RealResTy = ConvertType(Ty); - llvm::Type *PtrTy = llvm::IntegerType::get( - getLLVMContext(), getContext().getTypeSize(Ty))->getPointerTo(); - LoadAddr = Builder.CreateBitCast(LoadAddr, PtrTy); - - Function *F = CGM.getIntrinsic(BuiltinID == AArch64::BI__builtin_arm_ldaex - ? Intrinsic::aarch64_ldaxr - : Intrinsic::aarch64_ldxr, - PtrTy); - Value *Val = Builder.CreateCall(F, LoadAddr, "ldxr"); - - if (RealResTy->isPointerTy()) - return Builder.CreateIntToPtr(Val, RealResTy); - - llvm::Type *IntResTy = llvm::IntegerType::get( - getLLVMContext(), CGM.getDataLayout().getTypeSizeInBits(RealResTy)); - Val = Builder.CreateTruncOrBitCast(Val, IntResTy); - return Builder.CreateBitCast(Val, RealResTy); - } - - if ((BuiltinID == AArch64::BI__builtin_arm_strex || - BuiltinID == AArch64::BI__builtin_arm_stlex) && - getContext().getTypeSize(E->getArg(0)->getType()) == 128) { - Function *F = CGM.getIntrinsic(BuiltinID == AArch64::BI__builtin_arm_stlex - ? Intrinsic::aarch64_stlxp - : Intrinsic::aarch64_stxp); - llvm::Type *STy = llvm::StructType::get(Int64Ty, Int64Ty); - - Address Tmp = CreateMemTemp(E->getArg(0)->getType()); - EmitAnyExprToMem(E->getArg(0), Tmp, Qualifiers(), /*init*/ true); - - Tmp = Builder.CreateBitCast(Tmp, llvm::PointerType::getUnqual(STy)); - llvm::Value *Val = Builder.CreateLoad(Tmp); - - Value *Arg0 = Builder.CreateExtractValue(Val, 0); - Value *Arg1 = Builder.CreateExtractValue(Val, 1); - Value *StPtr = Builder.CreateBitCast(EmitScalarExpr(E->getArg(1)), - Int8PtrTy); - return Builder.CreateCall(F, {Arg0, Arg1, StPtr}, "stxp"); - } - - if (BuiltinID == AArch64::BI__builtin_arm_strex || - BuiltinID == AArch64::BI__builtin_arm_stlex) { - Value *StoreVal = EmitScalarExpr(E->getArg(0)); - Value *StoreAddr = EmitScalarExpr(E->getArg(1)); - - QualType Ty = E->getArg(0)->getType(); - llvm::Type *StoreTy = llvm::IntegerType::get(getLLVMContext(), - getContext().getTypeSize(Ty)); - StoreAddr = Builder.CreateBitCast(StoreAddr, StoreTy->getPointerTo()); - - if (StoreVal->getType()->isPointerTy()) - StoreVal = Builder.CreatePtrToInt(StoreVal, Int64Ty); - else { - llvm::Type *IntTy = llvm::IntegerType::get( - getLLVMContext(), - CGM.getDataLayout().getTypeSizeInBits(StoreVal->getType())); - StoreVal = Builder.CreateBitCast(StoreVal, IntTy); - StoreVal = Builder.CreateZExtOrBitCast(StoreVal, Int64Ty); - } - - Function *F = CGM.getIntrinsic(BuiltinID == AArch64::BI__builtin_arm_stlex - ? Intrinsic::aarch64_stlxr - : Intrinsic::aarch64_stxr, - StoreAddr->getType()); - return Builder.CreateCall(F, {StoreVal, StoreAddr}, "stxr"); - } - - if (BuiltinID == AArch64::BI__getReg) { - Expr::EvalResult Result; - if (!E->getArg(0)->EvaluateAsInt(Result, CGM.getContext())) - llvm_unreachable("Sema will ensure that the parameter is constant"); - - llvm::APSInt Value = Result.Val.getInt(); - LLVMContext &Context = CGM.getLLVMContext(); - std::string Reg = Value == 31 ? "sp" : "x" + Value.toString(10); - - llvm::Metadata *Ops[] = {llvm::MDString::get(Context, Reg)}; - llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops); - llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName); - - llvm::Value *F = - CGM.getIntrinsic(llvm::Intrinsic::read_register, {Int64Ty}); - return Builder.CreateCall(F, Metadata); - } - - if (BuiltinID == AArch64::BI__builtin_arm_clrex) { - Function *F = CGM.getIntrinsic(Intrinsic::aarch64_clrex); - return Builder.CreateCall(F); - } - - if (BuiltinID == AArch64::BI_ReadWriteBarrier) - return Builder.CreateFence(llvm::AtomicOrdering::SequentiallyConsistent, - llvm::SyncScope::SingleThread); - - // CRC32 - Intrinsic::ID CRCIntrinsicID = Intrinsic::not_intrinsic; - switch (BuiltinID) { - case AArch64::BI__builtin_arm_crc32b: - CRCIntrinsicID = Intrinsic::aarch64_crc32b; break; - case AArch64::BI__builtin_arm_crc32cb: - CRCIntrinsicID = Intrinsic::aarch64_crc32cb; break; - case AArch64::BI__builtin_arm_crc32h: - CRCIntrinsicID = Intrinsic::aarch64_crc32h; break; - case AArch64::BI__builtin_arm_crc32ch: - CRCIntrinsicID = Intrinsic::aarch64_crc32ch; break; - case AArch64::BI__builtin_arm_crc32w: - CRCIntrinsicID = Intrinsic::aarch64_crc32w; break; - case AArch64::BI__builtin_arm_crc32cw: - CRCIntrinsicID = Intrinsic::aarch64_crc32cw; break; - case AArch64::BI__builtin_arm_crc32d: - CRCIntrinsicID = Intrinsic::aarch64_crc32x; break; - case AArch64::BI__builtin_arm_crc32cd: - CRCIntrinsicID = Intrinsic::aarch64_crc32cx; break; - } - - if (CRCIntrinsicID != Intrinsic::not_intrinsic) { - Value *Arg0 = EmitScalarExpr(E->getArg(0)); - Value *Arg1 = EmitScalarExpr(E->getArg(1)); - Function *F = CGM.getIntrinsic(CRCIntrinsicID); - - llvm::Type *DataTy = F->getFunctionType()->getParamType(1); - Arg1 = Builder.CreateZExtOrBitCast(Arg1, DataTy); - - return Builder.CreateCall(F, {Arg0, Arg1}); - } - - if (BuiltinID == AArch64::BI__builtin_arm_rsr || - BuiltinID == AArch64::BI__builtin_arm_rsr64 || - BuiltinID == AArch64::BI__builtin_arm_rsrp || - BuiltinID == AArch64::BI__builtin_arm_wsr || - BuiltinID == AArch64::BI__builtin_arm_wsr64 || - BuiltinID == AArch64::BI__builtin_arm_wsrp) { - - bool IsRead = BuiltinID == AArch64::BI__builtin_arm_rsr || - BuiltinID == AArch64::BI__builtin_arm_rsr64 || - BuiltinID == AArch64::BI__builtin_arm_rsrp; - - bool IsPointerBuiltin = BuiltinID == AArch64::BI__builtin_arm_rsrp || - BuiltinID == AArch64::BI__builtin_arm_wsrp; - - bool Is64Bit = BuiltinID != AArch64::BI__builtin_arm_rsr && - BuiltinID != AArch64::BI__builtin_arm_wsr; - - llvm::Type *ValueType; - llvm::Type *RegisterType = Int64Ty; - if (IsPointerBuiltin) { - ValueType = VoidPtrTy; - } else if (Is64Bit) { - ValueType = Int64Ty; - } else { - ValueType = Int32Ty; - } - - return EmitSpecialRegisterBuiltin(*this, E, RegisterType, ValueType, IsRead); - } - - if (BuiltinID == AArch64::BI_ReadStatusReg || - BuiltinID == AArch64::BI_WriteStatusReg) { - LLVMContext &Context = CGM.getLLVMContext(); - - unsigned SysReg = - E->getArg(0)->EvaluateKnownConstInt(getContext()).getZExtValue(); - - std::string SysRegStr; - llvm::raw_string_ostream(SysRegStr) << - ((1 << 1) | ((SysReg >> 14) & 1)) << ":" << - ((SysReg >> 11) & 7) << ":" << - ((SysReg >> 7) & 15) << ":" << - ((SysReg >> 3) & 15) << ":" << - ( SysReg & 7); - - llvm::Metadata *Ops[] = { llvm::MDString::get(Context, SysRegStr) }; - llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops); - llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName); - - llvm::Type *RegisterType = Int64Ty; - llvm::Type *Types[] = { RegisterType }; - - if (BuiltinID == AArch64::BI_ReadStatusReg) { - llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::read_register, Types); - - return Builder.CreateCall(F, Metadata); - } - - llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::write_register, Types); - llvm::Value *ArgValue = EmitScalarExpr(E->getArg(1)); - - return Builder.CreateCall(F, { Metadata, ArgValue }); - } - - if (BuiltinID == AArch64::BI_AddressOfReturnAddress) { - llvm::Value *F = CGM.getIntrinsic(Intrinsic::addressofreturnaddress); - return Builder.CreateCall(F); - } - - // Find out if any arguments are required to be integer constant - // expressions. - unsigned ICEArguments = 0; - ASTContext::GetBuiltinTypeError Error; - getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments); - assert(Error == ASTContext::GE_None && "Should not codegen an error"); - - llvm::SmallVector<Value*, 4> Ops; - for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++) { - if ((ICEArguments & (1 << i)) == 0) { - Ops.push_back(EmitScalarExpr(E->getArg(i))); - } else { - // If this is required to be a constant, constant fold it so that we know - // that the generated intrinsic gets a ConstantInt. - llvm::APSInt Result; - bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result, getContext()); - assert(IsConst && "Constant arg isn't actually constant?"); - (void)IsConst; - Ops.push_back(llvm::ConstantInt::get(getLLVMContext(), Result)); - } - } - - auto SISDMap = makeArrayRef(AArch64SISDIntrinsicMap); - const NeonIntrinsicInfo *Builtin = findNeonIntrinsicInMap( - SISDMap, BuiltinID, AArch64SISDIntrinsicsProvenSorted); - - if (Builtin) { - Ops.push_back(EmitScalarExpr(E->getArg(E->getNumArgs() - 1))); - Value *Result = EmitCommonNeonSISDBuiltinExpr(*this, *Builtin, Ops, E); - assert(Result && "SISD intrinsic should have been handled"); - return Result; - } - - llvm::APSInt Result; - const Expr *Arg = E->getArg(E->getNumArgs()-1); - NeonTypeFlags Type(0); - if (Arg->isIntegerConstantExpr(Result, getContext())) - // Determine the type of this overloaded NEON intrinsic. - Type = NeonTypeFlags(Result.getZExtValue()); - - bool usgn = Type.isUnsigned(); - bool quad = Type.isQuad(); - - // Handle non-overloaded intrinsics first. - switch (BuiltinID) { - default: break; - case NEON::BI__builtin_neon_vabsh_f16: - Ops.push_back(EmitScalarExpr(E->getArg(0))); - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::fabs, HalfTy), Ops, "vabs"); - case NEON::BI__builtin_neon_vldrq_p128: { - llvm::Type *Int128Ty = llvm::Type::getIntNTy(getLLVMContext(), 128); - llvm::Type *Int128PTy = llvm::PointerType::get(Int128Ty, 0); - Value *Ptr = Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)), Int128PTy); - return Builder.CreateAlignedLoad(Int128Ty, Ptr, - CharUnits::fromQuantity(16)); - } - case NEON::BI__builtin_neon_vstrq_p128: { - llvm::Type *Int128PTy = llvm::Type::getIntNPtrTy(getLLVMContext(), 128); - Value *Ptr = Builder.CreateBitCast(Ops[0], Int128PTy); - return Builder.CreateDefaultAlignedStore(EmitScalarExpr(E->getArg(1)), Ptr); - } - case NEON::BI__builtin_neon_vcvts_u32_f32: - case NEON::BI__builtin_neon_vcvtd_u64_f64: - usgn = true; - LLVM_FALLTHROUGH; - case NEON::BI__builtin_neon_vcvts_s32_f32: - case NEON::BI__builtin_neon_vcvtd_s64_f64: { - Ops.push_back(EmitScalarExpr(E->getArg(0))); - bool Is64 = Ops[0]->getType()->getPrimitiveSizeInBits() == 64; - llvm::Type *InTy = Is64 ? Int64Ty : Int32Ty; - llvm::Type *FTy = Is64 ? DoubleTy : FloatTy; - Ops[0] = Builder.CreateBitCast(Ops[0], FTy); - if (usgn) - return Builder.CreateFPToUI(Ops[0], InTy); - return Builder.CreateFPToSI(Ops[0], InTy); - } - case NEON::BI__builtin_neon_vcvts_f32_u32: - case NEON::BI__builtin_neon_vcvtd_f64_u64: - usgn = true; - LLVM_FALLTHROUGH; - case NEON::BI__builtin_neon_vcvts_f32_s32: - case NEON::BI__builtin_neon_vcvtd_f64_s64: { - Ops.push_back(EmitScalarExpr(E->getArg(0))); - bool Is64 = Ops[0]->getType()->getPrimitiveSizeInBits() == 64; - llvm::Type *InTy = Is64 ? Int64Ty : Int32Ty; - llvm::Type *FTy = Is64 ? DoubleTy : FloatTy; - Ops[0] = Builder.CreateBitCast(Ops[0], InTy); - if (usgn) - return Builder.CreateUIToFP(Ops[0], FTy); - return Builder.CreateSIToFP(Ops[0], FTy); - } - case NEON::BI__builtin_neon_vcvth_f16_u16: - case NEON::BI__builtin_neon_vcvth_f16_u32: - case NEON::BI__builtin_neon_vcvth_f16_u64: - usgn = true; - LLVM_FALLTHROUGH; - case NEON::BI__builtin_neon_vcvth_f16_s16: - case NEON::BI__builtin_neon_vcvth_f16_s32: - case NEON::BI__builtin_neon_vcvth_f16_s64: { - Ops.push_back(EmitScalarExpr(E->getArg(0))); - llvm::Type *FTy = HalfTy; - llvm::Type *InTy; - if (Ops[0]->getType()->getPrimitiveSizeInBits() == 64) - InTy = Int64Ty; - else if (Ops[0]->getType()->getPrimitiveSizeInBits() == 32) - InTy = Int32Ty; - else - InTy = Int16Ty; - Ops[0] = Builder.CreateBitCast(Ops[0], InTy); - if (usgn) - return Builder.CreateUIToFP(Ops[0], FTy); - return Builder.CreateSIToFP(Ops[0], FTy); - } - case NEON::BI__builtin_neon_vcvth_u16_f16: - usgn = true; - LLVM_FALLTHROUGH; - case NEON::BI__builtin_neon_vcvth_s16_f16: { - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = Builder.CreateBitCast(Ops[0], HalfTy); - if (usgn) - return Builder.CreateFPToUI(Ops[0], Int16Ty); - return Builder.CreateFPToSI(Ops[0], Int16Ty); - } - case NEON::BI__builtin_neon_vcvth_u32_f16: - usgn = true; - LLVM_FALLTHROUGH; - case NEON::BI__builtin_neon_vcvth_s32_f16: { - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = Builder.CreateBitCast(Ops[0], HalfTy); - if (usgn) - return Builder.CreateFPToUI(Ops[0], Int32Ty); - return Builder.CreateFPToSI(Ops[0], Int32Ty); - } - case NEON::BI__builtin_neon_vcvth_u64_f16: - usgn = true; - LLVM_FALLTHROUGH; - case NEON::BI__builtin_neon_vcvth_s64_f16: { - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = Builder.CreateBitCast(Ops[0], HalfTy); - if (usgn) - return Builder.CreateFPToUI(Ops[0], Int64Ty); - return Builder.CreateFPToSI(Ops[0], Int64Ty); - } - case NEON::BI__builtin_neon_vcvtah_u16_f16: - case NEON::BI__builtin_neon_vcvtmh_u16_f16: - case NEON::BI__builtin_neon_vcvtnh_u16_f16: - case NEON::BI__builtin_neon_vcvtph_u16_f16: - case NEON::BI__builtin_neon_vcvtah_s16_f16: - case NEON::BI__builtin_neon_vcvtmh_s16_f16: - case NEON::BI__builtin_neon_vcvtnh_s16_f16: - case NEON::BI__builtin_neon_vcvtph_s16_f16: { - unsigned Int; - llvm::Type* InTy = Int32Ty; - llvm::Type* FTy = HalfTy; - llvm::Type *Tys[2] = {InTy, FTy}; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - switch (BuiltinID) { - default: llvm_unreachable("missing builtin ID in switch!"); - case NEON::BI__builtin_neon_vcvtah_u16_f16: - Int = Intrinsic::aarch64_neon_fcvtau; break; - case NEON::BI__builtin_neon_vcvtmh_u16_f16: - Int = Intrinsic::aarch64_neon_fcvtmu; break; - case NEON::BI__builtin_neon_vcvtnh_u16_f16: - Int = Intrinsic::aarch64_neon_fcvtnu; break; - case NEON::BI__builtin_neon_vcvtph_u16_f16: - Int = Intrinsic::aarch64_neon_fcvtpu; break; - case NEON::BI__builtin_neon_vcvtah_s16_f16: - Int = Intrinsic::aarch64_neon_fcvtas; break; - case NEON::BI__builtin_neon_vcvtmh_s16_f16: - Int = Intrinsic::aarch64_neon_fcvtms; break; - case NEON::BI__builtin_neon_vcvtnh_s16_f16: - Int = Intrinsic::aarch64_neon_fcvtns; break; - case NEON::BI__builtin_neon_vcvtph_s16_f16: - Int = Intrinsic::aarch64_neon_fcvtps; break; - } - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "fcvt"); - return Builder.CreateTrunc(Ops[0], Int16Ty); - } - case NEON::BI__builtin_neon_vcaleh_f16: - case NEON::BI__builtin_neon_vcalth_f16: - case NEON::BI__builtin_neon_vcageh_f16: - case NEON::BI__builtin_neon_vcagth_f16: { - unsigned Int; - llvm::Type* InTy = Int32Ty; - llvm::Type* FTy = HalfTy; - llvm::Type *Tys[2] = {InTy, FTy}; - Ops.push_back(EmitScalarExpr(E->getArg(1))); - switch (BuiltinID) { - default: llvm_unreachable("missing builtin ID in switch!"); - case NEON::BI__builtin_neon_vcageh_f16: - Int = Intrinsic::aarch64_neon_facge; break; - case NEON::BI__builtin_neon_vcagth_f16: - Int = Intrinsic::aarch64_neon_facgt; break; - case NEON::BI__builtin_neon_vcaleh_f16: - Int = Intrinsic::aarch64_neon_facge; std::swap(Ops[0], Ops[1]); break; - case NEON::BI__builtin_neon_vcalth_f16: - Int = Intrinsic::aarch64_neon_facgt; std::swap(Ops[0], Ops[1]); break; - } - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "facg"); - return Builder.CreateTrunc(Ops[0], Int16Ty); - } - case NEON::BI__builtin_neon_vcvth_n_s16_f16: - case NEON::BI__builtin_neon_vcvth_n_u16_f16: { - unsigned Int; - llvm::Type* InTy = Int32Ty; - llvm::Type* FTy = HalfTy; - llvm::Type *Tys[2] = {InTy, FTy}; - Ops.push_back(EmitScalarExpr(E->getArg(1))); - switch (BuiltinID) { - default: llvm_unreachable("missing builtin ID in switch!"); - case NEON::BI__builtin_neon_vcvth_n_s16_f16: - Int = Intrinsic::aarch64_neon_vcvtfp2fxs; break; - case NEON::BI__builtin_neon_vcvth_n_u16_f16: - Int = Intrinsic::aarch64_neon_vcvtfp2fxu; break; - } - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "fcvth_n"); - return Builder.CreateTrunc(Ops[0], Int16Ty); - } - case NEON::BI__builtin_neon_vcvth_n_f16_s16: - case NEON::BI__builtin_neon_vcvth_n_f16_u16: { - unsigned Int; - llvm::Type* FTy = HalfTy; - llvm::Type* InTy = Int32Ty; - llvm::Type *Tys[2] = {FTy, InTy}; - Ops.push_back(EmitScalarExpr(E->getArg(1))); - switch (BuiltinID) { - default: llvm_unreachable("missing builtin ID in switch!"); - case NEON::BI__builtin_neon_vcvth_n_f16_s16: - Int = Intrinsic::aarch64_neon_vcvtfxs2fp; - Ops[0] = Builder.CreateSExt(Ops[0], InTy, "sext"); - break; - case NEON::BI__builtin_neon_vcvth_n_f16_u16: - Int = Intrinsic::aarch64_neon_vcvtfxu2fp; - Ops[0] = Builder.CreateZExt(Ops[0], InTy); - break; - } - return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "fcvth_n"); - } - case NEON::BI__builtin_neon_vpaddd_s64: { - llvm::Type *Ty = llvm::VectorType::get(Int64Ty, 2); - Value *Vec = EmitScalarExpr(E->getArg(0)); - // The vector is v2f64, so make sure it's bitcast to that. - Vec = Builder.CreateBitCast(Vec, Ty, "v2i64"); - llvm::Value *Idx0 = llvm::ConstantInt::get(SizeTy, 0); - llvm::Value *Idx1 = llvm::ConstantInt::get(SizeTy, 1); - Value *Op0 = Builder.CreateExtractElement(Vec, Idx0, "lane0"); - Value *Op1 = Builder.CreateExtractElement(Vec, Idx1, "lane1"); - // Pairwise addition of a v2f64 into a scalar f64. - return Builder.CreateAdd(Op0, Op1, "vpaddd"); - } - case NEON::BI__builtin_neon_vpaddd_f64: { - llvm::Type *Ty = - llvm::VectorType::get(DoubleTy, 2); - Value *Vec = EmitScalarExpr(E->getArg(0)); - // The vector is v2f64, so make sure it's bitcast to that. - Vec = Builder.CreateBitCast(Vec, Ty, "v2f64"); - llvm::Value *Idx0 = llvm::ConstantInt::get(SizeTy, 0); - llvm::Value *Idx1 = llvm::ConstantInt::get(SizeTy, 1); - Value *Op0 = Builder.CreateExtractElement(Vec, Idx0, "lane0"); - Value *Op1 = Builder.CreateExtractElement(Vec, Idx1, "lane1"); - // Pairwise addition of a v2f64 into a scalar f64. - return Builder.CreateFAdd(Op0, Op1, "vpaddd"); - } - case NEON::BI__builtin_neon_vpadds_f32: { - llvm::Type *Ty = - llvm::VectorType::get(FloatTy, 2); - Value *Vec = EmitScalarExpr(E->getArg(0)); - // The vector is v2f32, so make sure it's bitcast to that. - Vec = Builder.CreateBitCast(Vec, Ty, "v2f32"); - llvm::Value *Idx0 = llvm::ConstantInt::get(SizeTy, 0); - llvm::Value *Idx1 = llvm::ConstantInt::get(SizeTy, 1); - Value *Op0 = Builder.CreateExtractElement(Vec, Idx0, "lane0"); - Value *Op1 = Builder.CreateExtractElement(Vec, Idx1, "lane1"); - // Pairwise addition of a v2f32 into a scalar f32. - return Builder.CreateFAdd(Op0, Op1, "vpaddd"); - } - case NEON::BI__builtin_neon_vceqzd_s64: - case NEON::BI__builtin_neon_vceqzd_f64: - case NEON::BI__builtin_neon_vceqzs_f32: - case NEON::BI__builtin_neon_vceqzh_f16: - Ops.push_back(EmitScalarExpr(E->getArg(0))); - return EmitAArch64CompareBuiltinExpr( - Ops[0], ConvertType(E->getCallReturnType(getContext())), - ICmpInst::FCMP_OEQ, ICmpInst::ICMP_EQ, "vceqz"); - case NEON::BI__builtin_neon_vcgezd_s64: - case NEON::BI__builtin_neon_vcgezd_f64: - case NEON::BI__builtin_neon_vcgezs_f32: - case NEON::BI__builtin_neon_vcgezh_f16: - Ops.push_back(EmitScalarExpr(E->getArg(0))); - return EmitAArch64CompareBuiltinExpr( - Ops[0], ConvertType(E->getCallReturnType(getContext())), - ICmpInst::FCMP_OGE, ICmpInst::ICMP_SGE, "vcgez"); - case NEON::BI__builtin_neon_vclezd_s64: - case NEON::BI__builtin_neon_vclezd_f64: - case NEON::BI__builtin_neon_vclezs_f32: - case NEON::BI__builtin_neon_vclezh_f16: - Ops.push_back(EmitScalarExpr(E->getArg(0))); - return EmitAArch64CompareBuiltinExpr( - Ops[0], ConvertType(E->getCallReturnType(getContext())), - ICmpInst::FCMP_OLE, ICmpInst::ICMP_SLE, "vclez"); - case NEON::BI__builtin_neon_vcgtzd_s64: - case NEON::BI__builtin_neon_vcgtzd_f64: - case NEON::BI__builtin_neon_vcgtzs_f32: - case NEON::BI__builtin_neon_vcgtzh_f16: - Ops.push_back(EmitScalarExpr(E->getArg(0))); - return EmitAArch64CompareBuiltinExpr( - Ops[0], ConvertType(E->getCallReturnType(getContext())), - ICmpInst::FCMP_OGT, ICmpInst::ICMP_SGT, "vcgtz"); - case NEON::BI__builtin_neon_vcltzd_s64: - case NEON::BI__builtin_neon_vcltzd_f64: - case NEON::BI__builtin_neon_vcltzs_f32: - case NEON::BI__builtin_neon_vcltzh_f16: - Ops.push_back(EmitScalarExpr(E->getArg(0))); - return EmitAArch64CompareBuiltinExpr( - Ops[0], ConvertType(E->getCallReturnType(getContext())), - ICmpInst::FCMP_OLT, ICmpInst::ICMP_SLT, "vcltz"); - - case NEON::BI__builtin_neon_vceqzd_u64: { - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = Builder.CreateBitCast(Ops[0], Int64Ty); - Ops[0] = - Builder.CreateICmpEQ(Ops[0], llvm::Constant::getNullValue(Int64Ty)); - return Builder.CreateSExt(Ops[0], Int64Ty, "vceqzd"); - } - case NEON::BI__builtin_neon_vceqd_f64: - case NEON::BI__builtin_neon_vcled_f64: - case NEON::BI__builtin_neon_vcltd_f64: - case NEON::BI__builtin_neon_vcged_f64: - case NEON::BI__builtin_neon_vcgtd_f64: { - llvm::CmpInst::Predicate P; - switch (BuiltinID) { - default: llvm_unreachable("missing builtin ID in switch!"); - case NEON::BI__builtin_neon_vceqd_f64: P = llvm::FCmpInst::FCMP_OEQ; break; - case NEON::BI__builtin_neon_vcled_f64: P = llvm::FCmpInst::FCMP_OLE; break; - case NEON::BI__builtin_neon_vcltd_f64: P = llvm::FCmpInst::FCMP_OLT; break; - case NEON::BI__builtin_neon_vcged_f64: P = llvm::FCmpInst::FCMP_OGE; break; - case NEON::BI__builtin_neon_vcgtd_f64: P = llvm::FCmpInst::FCMP_OGT; break; - } - Ops.push_back(EmitScalarExpr(E->getArg(1))); - Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy); - Ops[1] = Builder.CreateBitCast(Ops[1], DoubleTy); - Ops[0] = Builder.CreateFCmp(P, Ops[0], Ops[1]); - return Builder.CreateSExt(Ops[0], Int64Ty, "vcmpd"); - } - case NEON::BI__builtin_neon_vceqs_f32: - case NEON::BI__builtin_neon_vcles_f32: - case NEON::BI__builtin_neon_vclts_f32: - case NEON::BI__builtin_neon_vcges_f32: - case NEON::BI__builtin_neon_vcgts_f32: { - llvm::CmpInst::Predicate P; - switch (BuiltinID) { - default: llvm_unreachable("missing builtin ID in switch!"); - case NEON::BI__builtin_neon_vceqs_f32: P = llvm::FCmpInst::FCMP_OEQ; break; - case NEON::BI__builtin_neon_vcles_f32: P = llvm::FCmpInst::FCMP_OLE; break; - case NEON::BI__builtin_neon_vclts_f32: P = llvm::FCmpInst::FCMP_OLT; break; - case NEON::BI__builtin_neon_vcges_f32: P = llvm::FCmpInst::FCMP_OGE; break; - case NEON::BI__builtin_neon_vcgts_f32: P = llvm::FCmpInst::FCMP_OGT; break; - } - Ops.push_back(EmitScalarExpr(E->getArg(1))); - Ops[0] = Builder.CreateBitCast(Ops[0], FloatTy); - Ops[1] = Builder.CreateBitCast(Ops[1], FloatTy); - Ops[0] = Builder.CreateFCmp(P, Ops[0], Ops[1]); - return Builder.CreateSExt(Ops[0], Int32Ty, "vcmpd"); - } - case NEON::BI__builtin_neon_vceqh_f16: - case NEON::BI__builtin_neon_vcleh_f16: - case NEON::BI__builtin_neon_vclth_f16: - case NEON::BI__builtin_neon_vcgeh_f16: - case NEON::BI__builtin_neon_vcgth_f16: { - llvm::CmpInst::Predicate P; - switch (BuiltinID) { - default: llvm_unreachable("missing builtin ID in switch!"); - case NEON::BI__builtin_neon_vceqh_f16: P = llvm::FCmpInst::FCMP_OEQ; break; - case NEON::BI__builtin_neon_vcleh_f16: P = llvm::FCmpInst::FCMP_OLE; break; - case NEON::BI__builtin_neon_vclth_f16: P = llvm::FCmpInst::FCMP_OLT; break; - case NEON::BI__builtin_neon_vcgeh_f16: P = llvm::FCmpInst::FCMP_OGE; break; - case NEON::BI__builtin_neon_vcgth_f16: P = llvm::FCmpInst::FCMP_OGT; break; - } - Ops.push_back(EmitScalarExpr(E->getArg(1))); - Ops[0] = Builder.CreateBitCast(Ops[0], HalfTy); - Ops[1] = Builder.CreateBitCast(Ops[1], HalfTy); - Ops[0] = Builder.CreateFCmp(P, Ops[0], Ops[1]); - return Builder.CreateSExt(Ops[0], Int16Ty, "vcmpd"); - } - case NEON::BI__builtin_neon_vceqd_s64: - case NEON::BI__builtin_neon_vceqd_u64: - case NEON::BI__builtin_neon_vcgtd_s64: - case NEON::BI__builtin_neon_vcgtd_u64: - case NEON::BI__builtin_neon_vcltd_s64: - case NEON::BI__builtin_neon_vcltd_u64: - case NEON::BI__builtin_neon_vcged_u64: - case NEON::BI__builtin_neon_vcged_s64: - case NEON::BI__builtin_neon_vcled_u64: - case NEON::BI__builtin_neon_vcled_s64: { - llvm::CmpInst::Predicate P; - switch (BuiltinID) { - default: llvm_unreachable("missing builtin ID in switch!"); - case NEON::BI__builtin_neon_vceqd_s64: - case NEON::BI__builtin_neon_vceqd_u64:P = llvm::ICmpInst::ICMP_EQ;break; - case NEON::BI__builtin_neon_vcgtd_s64:P = llvm::ICmpInst::ICMP_SGT;break; - case NEON::BI__builtin_neon_vcgtd_u64:P = llvm::ICmpInst::ICMP_UGT;break; - case NEON::BI__builtin_neon_vcltd_s64:P = llvm::ICmpInst::ICMP_SLT;break; - case NEON::BI__builtin_neon_vcltd_u64:P = llvm::ICmpInst::ICMP_ULT;break; - case NEON::BI__builtin_neon_vcged_u64:P = llvm::ICmpInst::ICMP_UGE;break; - case NEON::BI__builtin_neon_vcged_s64:P = llvm::ICmpInst::ICMP_SGE;break; - case NEON::BI__builtin_neon_vcled_u64:P = llvm::ICmpInst::ICMP_ULE;break; - case NEON::BI__builtin_neon_vcled_s64:P = llvm::ICmpInst::ICMP_SLE;break; - } - Ops.push_back(EmitScalarExpr(E->getArg(1))); - Ops[0] = Builder.CreateBitCast(Ops[0], Int64Ty); - Ops[1] = Builder.CreateBitCast(Ops[1], Int64Ty); - Ops[0] = Builder.CreateICmp(P, Ops[0], Ops[1]); - return Builder.CreateSExt(Ops[0], Int64Ty, "vceqd"); - } - case NEON::BI__builtin_neon_vtstd_s64: - case NEON::BI__builtin_neon_vtstd_u64: { - Ops.push_back(EmitScalarExpr(E->getArg(1))); - Ops[0] = Builder.CreateBitCast(Ops[0], Int64Ty); - Ops[1] = Builder.CreateBitCast(Ops[1], Int64Ty); - Ops[0] = Builder.CreateAnd(Ops[0], Ops[1]); - Ops[0] = Builder.CreateICmp(ICmpInst::ICMP_NE, Ops[0], - llvm::Constant::getNullValue(Int64Ty)); - return Builder.CreateSExt(Ops[0], Int64Ty, "vtstd"); - } - case NEON::BI__builtin_neon_vset_lane_i8: - case NEON::BI__builtin_neon_vset_lane_i16: - case NEON::BI__builtin_neon_vset_lane_i32: - case NEON::BI__builtin_neon_vset_lane_i64: - case NEON::BI__builtin_neon_vset_lane_f32: - case NEON::BI__builtin_neon_vsetq_lane_i8: - case NEON::BI__builtin_neon_vsetq_lane_i16: - case NEON::BI__builtin_neon_vsetq_lane_i32: - case NEON::BI__builtin_neon_vsetq_lane_i64: - case NEON::BI__builtin_neon_vsetq_lane_f32: - Ops.push_back(EmitScalarExpr(E->getArg(2))); - return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vset_lane"); - case NEON::BI__builtin_neon_vset_lane_f64: - // The vector type needs a cast for the v1f64 variant. - Ops[1] = Builder.CreateBitCast(Ops[1], - llvm::VectorType::get(DoubleTy, 1)); - Ops.push_back(EmitScalarExpr(E->getArg(2))); - return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vset_lane"); - case NEON::BI__builtin_neon_vsetq_lane_f64: - // The vector type needs a cast for the v2f64 variant. - Ops[1] = Builder.CreateBitCast(Ops[1], - llvm::VectorType::get(DoubleTy, 2)); - Ops.push_back(EmitScalarExpr(E->getArg(2))); - return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vset_lane"); - - case NEON::BI__builtin_neon_vget_lane_i8: - case NEON::BI__builtin_neon_vdupb_lane_i8: - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int8Ty, 8)); - return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)), - "vget_lane"); - case NEON::BI__builtin_neon_vgetq_lane_i8: - case NEON::BI__builtin_neon_vdupb_laneq_i8: - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int8Ty, 16)); - return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)), - "vgetq_lane"); - case NEON::BI__builtin_neon_vget_lane_i16: - case NEON::BI__builtin_neon_vduph_lane_i16: - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int16Ty, 4)); - return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)), - "vget_lane"); - case NEON::BI__builtin_neon_vgetq_lane_i16: - case NEON::BI__builtin_neon_vduph_laneq_i16: - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int16Ty, 8)); - return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)), - "vgetq_lane"); - case NEON::BI__builtin_neon_vget_lane_i32: - case NEON::BI__builtin_neon_vdups_lane_i32: - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int32Ty, 2)); - return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)), - "vget_lane"); - case NEON::BI__builtin_neon_vdups_lane_f32: - Ops[0] = Builder.CreateBitCast(Ops[0], - llvm::VectorType::get(FloatTy, 2)); - return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)), - "vdups_lane"); - case NEON::BI__builtin_neon_vgetq_lane_i32: - case NEON::BI__builtin_neon_vdups_laneq_i32: - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int32Ty, 4)); - return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)), - "vgetq_lane"); - case NEON::BI__builtin_neon_vget_lane_i64: - case NEON::BI__builtin_neon_vdupd_lane_i64: - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int64Ty, 1)); - return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)), - "vget_lane"); - case NEON::BI__builtin_neon_vdupd_lane_f64: - Ops[0] = Builder.CreateBitCast(Ops[0], - llvm::VectorType::get(DoubleTy, 1)); - return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)), - "vdupd_lane"); - case NEON::BI__builtin_neon_vgetq_lane_i64: - case NEON::BI__builtin_neon_vdupd_laneq_i64: - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int64Ty, 2)); - return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)), - "vgetq_lane"); - case NEON::BI__builtin_neon_vget_lane_f32: - Ops[0] = Builder.CreateBitCast(Ops[0], - llvm::VectorType::get(FloatTy, 2)); - return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)), - "vget_lane"); - case NEON::BI__builtin_neon_vget_lane_f64: - Ops[0] = Builder.CreateBitCast(Ops[0], - llvm::VectorType::get(DoubleTy, 1)); - return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)), - "vget_lane"); - case NEON::BI__builtin_neon_vgetq_lane_f32: - case NEON::BI__builtin_neon_vdups_laneq_f32: - Ops[0] = Builder.CreateBitCast(Ops[0], - llvm::VectorType::get(FloatTy, 4)); - return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)), - "vgetq_lane"); - case NEON::BI__builtin_neon_vgetq_lane_f64: - case NEON::BI__builtin_neon_vdupd_laneq_f64: - Ops[0] = Builder.CreateBitCast(Ops[0], - llvm::VectorType::get(DoubleTy, 2)); - return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)), - "vgetq_lane"); - case NEON::BI__builtin_neon_vaddh_f16: - Ops.push_back(EmitScalarExpr(E->getArg(1))); - return Builder.CreateFAdd(Ops[0], Ops[1], "vaddh"); - case NEON::BI__builtin_neon_vsubh_f16: - Ops.push_back(EmitScalarExpr(E->getArg(1))); - return Builder.CreateFSub(Ops[0], Ops[1], "vsubh"); - case NEON::BI__builtin_neon_vmulh_f16: - Ops.push_back(EmitScalarExpr(E->getArg(1))); - return Builder.CreateFMul(Ops[0], Ops[1], "vmulh"); - case NEON::BI__builtin_neon_vdivh_f16: - Ops.push_back(EmitScalarExpr(E->getArg(1))); - return Builder.CreateFDiv(Ops[0], Ops[1], "vdivh"); - case NEON::BI__builtin_neon_vfmah_f16: { - Value *F = CGM.getIntrinsic(Intrinsic::fma, HalfTy); - // NEON intrinsic puts accumulator first, unlike the LLVM fma. - return Builder.CreateCall(F, - {EmitScalarExpr(E->getArg(1)), EmitScalarExpr(E->getArg(2)), Ops[0]}); - } - case NEON::BI__builtin_neon_vfmsh_f16: { - Value *F = CGM.getIntrinsic(Intrinsic::fma, HalfTy); - Value *Zero = llvm::ConstantFP::getZeroValueForNegation(HalfTy); - Value* Sub = Builder.CreateFSub(Zero, EmitScalarExpr(E->getArg(1)), "vsubh"); - // NEON intrinsic puts accumulator first, unlike the LLVM fma. - return Builder.CreateCall(F, {Sub, EmitScalarExpr(E->getArg(2)), Ops[0]}); - } - case NEON::BI__builtin_neon_vaddd_s64: - case NEON::BI__builtin_neon_vaddd_u64: - return Builder.CreateAdd(Ops[0], EmitScalarExpr(E->getArg(1)), "vaddd"); - case NEON::BI__builtin_neon_vsubd_s64: - case NEON::BI__builtin_neon_vsubd_u64: - return Builder.CreateSub(Ops[0], EmitScalarExpr(E->getArg(1)), "vsubd"); - case NEON::BI__builtin_neon_vqdmlalh_s16: - case NEON::BI__builtin_neon_vqdmlslh_s16: { - SmallVector<Value *, 2> ProductOps; - ProductOps.push_back(vectorWrapScalar16(Ops[1])); - ProductOps.push_back(vectorWrapScalar16(EmitScalarExpr(E->getArg(2)))); - llvm::Type *VTy = llvm::VectorType::get(Int32Ty, 4); - Ops[1] = EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_sqdmull, VTy), - ProductOps, "vqdmlXl"); - Constant *CI = ConstantInt::get(SizeTy, 0); - Ops[1] = Builder.CreateExtractElement(Ops[1], CI, "lane0"); - - unsigned AccumInt = BuiltinID == NEON::BI__builtin_neon_vqdmlalh_s16 - ? Intrinsic::aarch64_neon_sqadd - : Intrinsic::aarch64_neon_sqsub; - return EmitNeonCall(CGM.getIntrinsic(AccumInt, Int32Ty), Ops, "vqdmlXl"); - } - case NEON::BI__builtin_neon_vqshlud_n_s64: { - Ops.push_back(EmitScalarExpr(E->getArg(1))); - Ops[1] = Builder.CreateZExt(Ops[1], Int64Ty); - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_sqshlu, Int64Ty), - Ops, "vqshlu_n"); - } - case NEON::BI__builtin_neon_vqshld_n_u64: - case NEON::BI__builtin_neon_vqshld_n_s64: { - unsigned Int = BuiltinID == NEON::BI__builtin_neon_vqshld_n_u64 - ? Intrinsic::aarch64_neon_uqshl - : Intrinsic::aarch64_neon_sqshl; - Ops.push_back(EmitScalarExpr(E->getArg(1))); - Ops[1] = Builder.CreateZExt(Ops[1], Int64Ty); - return EmitNeonCall(CGM.getIntrinsic(Int, Int64Ty), Ops, "vqshl_n"); - } - case NEON::BI__builtin_neon_vrshrd_n_u64: - case NEON::BI__builtin_neon_vrshrd_n_s64: { - unsigned Int = BuiltinID == NEON::BI__builtin_neon_vrshrd_n_u64 - ? Intrinsic::aarch64_neon_urshl - : Intrinsic::aarch64_neon_srshl; - Ops.push_back(EmitScalarExpr(E->getArg(1))); - int SV = cast<ConstantInt>(Ops[1])->getSExtValue(); - Ops[1] = ConstantInt::get(Int64Ty, -SV); - return EmitNeonCall(CGM.getIntrinsic(Int, Int64Ty), Ops, "vrshr_n"); - } - case NEON::BI__builtin_neon_vrsrad_n_u64: - case NEON::BI__builtin_neon_vrsrad_n_s64: { - unsigned Int = BuiltinID == NEON::BI__builtin_neon_vrsrad_n_u64 - ? Intrinsic::aarch64_neon_urshl - : Intrinsic::aarch64_neon_srshl; - Ops[1] = Builder.CreateBitCast(Ops[1], Int64Ty); - Ops.push_back(Builder.CreateNeg(EmitScalarExpr(E->getArg(2)))); - Ops[1] = Builder.CreateCall(CGM.getIntrinsic(Int, Int64Ty), - {Ops[1], Builder.CreateSExt(Ops[2], Int64Ty)}); - return Builder.CreateAdd(Ops[0], Builder.CreateBitCast(Ops[1], Int64Ty)); - } - case NEON::BI__builtin_neon_vshld_n_s64: - case NEON::BI__builtin_neon_vshld_n_u64: { - llvm::ConstantInt *Amt = cast<ConstantInt>(EmitScalarExpr(E->getArg(1))); - return Builder.CreateShl( - Ops[0], ConstantInt::get(Int64Ty, Amt->getZExtValue()), "shld_n"); - } - case NEON::BI__builtin_neon_vshrd_n_s64: { - llvm::ConstantInt *Amt = cast<ConstantInt>(EmitScalarExpr(E->getArg(1))); - return Builder.CreateAShr( - Ops[0], ConstantInt::get(Int64Ty, std::min(static_cast<uint64_t>(63), - Amt->getZExtValue())), - "shrd_n"); - } - case NEON::BI__builtin_neon_vshrd_n_u64: { - llvm::ConstantInt *Amt = cast<ConstantInt>(EmitScalarExpr(E->getArg(1))); - uint64_t ShiftAmt = Amt->getZExtValue(); - // Right-shifting an unsigned value by its size yields 0. - if (ShiftAmt == 64) - return ConstantInt::get(Int64Ty, 0); - return Builder.CreateLShr(Ops[0], ConstantInt::get(Int64Ty, ShiftAmt), - "shrd_n"); - } - case NEON::BI__builtin_neon_vsrad_n_s64: { - llvm::ConstantInt *Amt = cast<ConstantInt>(EmitScalarExpr(E->getArg(2))); - Ops[1] = Builder.CreateAShr( - Ops[1], ConstantInt::get(Int64Ty, std::min(static_cast<uint64_t>(63), - Amt->getZExtValue())), - "shrd_n"); - return Builder.CreateAdd(Ops[0], Ops[1]); - } - case NEON::BI__builtin_neon_vsrad_n_u64: { - llvm::ConstantInt *Amt = cast<ConstantInt>(EmitScalarExpr(E->getArg(2))); - uint64_t ShiftAmt = Amt->getZExtValue(); - // Right-shifting an unsigned value by its size yields 0. - // As Op + 0 = Op, return Ops[0] directly. - if (ShiftAmt == 64) - return Ops[0]; - Ops[1] = Builder.CreateLShr(Ops[1], ConstantInt::get(Int64Ty, ShiftAmt), - "shrd_n"); - return Builder.CreateAdd(Ops[0], Ops[1]); - } - case NEON::BI__builtin_neon_vqdmlalh_lane_s16: - case NEON::BI__builtin_neon_vqdmlalh_laneq_s16: - case NEON::BI__builtin_neon_vqdmlslh_lane_s16: - case NEON::BI__builtin_neon_vqdmlslh_laneq_s16: { - Ops[2] = Builder.CreateExtractElement(Ops[2], EmitScalarExpr(E->getArg(3)), - "lane"); - SmallVector<Value *, 2> ProductOps; - ProductOps.push_back(vectorWrapScalar16(Ops[1])); - ProductOps.push_back(vectorWrapScalar16(Ops[2])); - llvm::Type *VTy = llvm::VectorType::get(Int32Ty, 4); - Ops[1] = EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_sqdmull, VTy), - ProductOps, "vqdmlXl"); - Constant *CI = ConstantInt::get(SizeTy, 0); - Ops[1] = Builder.CreateExtractElement(Ops[1], CI, "lane0"); - Ops.pop_back(); - - unsigned AccInt = (BuiltinID == NEON::BI__builtin_neon_vqdmlalh_lane_s16 || - BuiltinID == NEON::BI__builtin_neon_vqdmlalh_laneq_s16) - ? Intrinsic::aarch64_neon_sqadd - : Intrinsic::aarch64_neon_sqsub; - return EmitNeonCall(CGM.getIntrinsic(AccInt, Int32Ty), Ops, "vqdmlXl"); - } - case NEON::BI__builtin_neon_vqdmlals_s32: - case NEON::BI__builtin_neon_vqdmlsls_s32: { - SmallVector<Value *, 2> ProductOps; - ProductOps.push_back(Ops[1]); - ProductOps.push_back(EmitScalarExpr(E->getArg(2))); - Ops[1] = - EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_sqdmulls_scalar), - ProductOps, "vqdmlXl"); - - unsigned AccumInt = BuiltinID == NEON::BI__builtin_neon_vqdmlals_s32 - ? Intrinsic::aarch64_neon_sqadd - : Intrinsic::aarch64_neon_sqsub; - return EmitNeonCall(CGM.getIntrinsic(AccumInt, Int64Ty), Ops, "vqdmlXl"); - } - case NEON::BI__builtin_neon_vqdmlals_lane_s32: - case NEON::BI__builtin_neon_vqdmlals_laneq_s32: - case NEON::BI__builtin_neon_vqdmlsls_lane_s32: - case NEON::BI__builtin_neon_vqdmlsls_laneq_s32: { - Ops[2] = Builder.CreateExtractElement(Ops[2], EmitScalarExpr(E->getArg(3)), - "lane"); - SmallVector<Value *, 2> ProductOps; - ProductOps.push_back(Ops[1]); - ProductOps.push_back(Ops[2]); - Ops[1] = - EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_sqdmulls_scalar), - ProductOps, "vqdmlXl"); - Ops.pop_back(); - - unsigned AccInt = (BuiltinID == NEON::BI__builtin_neon_vqdmlals_lane_s32 || - BuiltinID == NEON::BI__builtin_neon_vqdmlals_laneq_s32) - ? Intrinsic::aarch64_neon_sqadd - : Intrinsic::aarch64_neon_sqsub; - return EmitNeonCall(CGM.getIntrinsic(AccInt, Int64Ty), Ops, "vqdmlXl"); - } - } - - llvm::VectorType *VTy = GetNeonType(this, Type); - llvm::Type *Ty = VTy; - if (!Ty) - return nullptr; - - // Not all intrinsics handled by the common case work for AArch64 yet, so only - // defer to common code if it's been added to our special map. - Builtin = findNeonIntrinsicInMap(AArch64SIMDIntrinsicMap, BuiltinID, - AArch64SIMDIntrinsicsProvenSorted); - - if (Builtin) - return EmitCommonNeonBuiltinExpr( - Builtin->BuiltinID, Builtin->LLVMIntrinsic, Builtin->AltLLVMIntrinsic, - Builtin->NameHint, Builtin->TypeModifier, E, Ops, - /*never use addresses*/ Address::invalid(), Address::invalid(), Arch); - - if (Value *V = EmitAArch64TblBuiltinExpr(*this, BuiltinID, E, Ops, Arch)) - return V; - - unsigned Int; - switch (BuiltinID) { - default: return nullptr; - case NEON::BI__builtin_neon_vbsl_v: - case NEON::BI__builtin_neon_vbslq_v: { - llvm::Type *BitTy = llvm::VectorType::getInteger(VTy); - Ops[0] = Builder.CreateBitCast(Ops[0], BitTy, "vbsl"); - Ops[1] = Builder.CreateBitCast(Ops[1], BitTy, "vbsl"); - Ops[2] = Builder.CreateBitCast(Ops[2], BitTy, "vbsl"); - - Ops[1] = Builder.CreateAnd(Ops[0], Ops[1], "vbsl"); - Ops[2] = Builder.CreateAnd(Builder.CreateNot(Ops[0]), Ops[2], "vbsl"); - Ops[0] = Builder.CreateOr(Ops[1], Ops[2], "vbsl"); - return Builder.CreateBitCast(Ops[0], Ty); - } - case NEON::BI__builtin_neon_vfma_lane_v: - case NEON::BI__builtin_neon_vfmaq_lane_v: { // Only used for FP types - // The ARM builtins (and instructions) have the addend as the first - // operand, but the 'fma' intrinsics have it last. Swap it around here. - Value *Addend = Ops[0]; - Value *Multiplicand = Ops[1]; - Value *LaneSource = Ops[2]; - Ops[0] = Multiplicand; - Ops[1] = LaneSource; - Ops[2] = Addend; - - // Now adjust things to handle the lane access. - llvm::Type *SourceTy = BuiltinID == NEON::BI__builtin_neon_vfmaq_lane_v ? - llvm::VectorType::get(VTy->getElementType(), VTy->getNumElements() / 2) : - VTy; - llvm::Constant *cst = cast<Constant>(Ops[3]); - Value *SV = llvm::ConstantVector::getSplat(VTy->getNumElements(), cst); - Ops[1] = Builder.CreateBitCast(Ops[1], SourceTy); - Ops[1] = Builder.CreateShuffleVector(Ops[1], Ops[1], SV, "lane"); - - Ops.pop_back(); - Int = Intrinsic::fma; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "fmla"); - } - case NEON::BI__builtin_neon_vfma_laneq_v: { - llvm::VectorType *VTy = cast<llvm::VectorType>(Ty); - // v1f64 fma should be mapped to Neon scalar f64 fma - if (VTy && VTy->getElementType() == DoubleTy) { - Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy); - Ops[1] = Builder.CreateBitCast(Ops[1], DoubleTy); - llvm::Type *VTy = GetNeonType(this, - NeonTypeFlags(NeonTypeFlags::Float64, false, true)); - Ops[2] = Builder.CreateBitCast(Ops[2], VTy); - Ops[2] = Builder.CreateExtractElement(Ops[2], Ops[3], "extract"); - Value *F = CGM.getIntrinsic(Intrinsic::fma, DoubleTy); - Value *Result = Builder.CreateCall(F, {Ops[1], Ops[2], Ops[0]}); - return Builder.CreateBitCast(Result, Ty); - } - Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty); - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - - llvm::Type *STy = llvm::VectorType::get(VTy->getElementType(), - VTy->getNumElements() * 2); - Ops[2] = Builder.CreateBitCast(Ops[2], STy); - Value* SV = llvm::ConstantVector::getSplat(VTy->getNumElements(), - cast<ConstantInt>(Ops[3])); - Ops[2] = Builder.CreateShuffleVector(Ops[2], Ops[2], SV, "lane"); - - return Builder.CreateCall(F, {Ops[2], Ops[1], Ops[0]}); - } - case NEON::BI__builtin_neon_vfmaq_laneq_v: { - Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty); - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - - Ops[2] = Builder.CreateBitCast(Ops[2], Ty); - Ops[2] = EmitNeonSplat(Ops[2], cast<ConstantInt>(Ops[3])); - return Builder.CreateCall(F, {Ops[2], Ops[1], Ops[0]}); - } - case NEON::BI__builtin_neon_vfmah_lane_f16: - case NEON::BI__builtin_neon_vfmas_lane_f32: - case NEON::BI__builtin_neon_vfmah_laneq_f16: - case NEON::BI__builtin_neon_vfmas_laneq_f32: - case NEON::BI__builtin_neon_vfmad_lane_f64: - case NEON::BI__builtin_neon_vfmad_laneq_f64: { - Ops.push_back(EmitScalarExpr(E->getArg(3))); - llvm::Type *Ty = ConvertType(E->getCallReturnType(getContext())); - Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty); - Ops[2] = Builder.CreateExtractElement(Ops[2], Ops[3], "extract"); - return Builder.CreateCall(F, {Ops[1], Ops[2], Ops[0]}); - } - case NEON::BI__builtin_neon_vmull_v: - // FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics. - Int = usgn ? Intrinsic::aarch64_neon_umull : Intrinsic::aarch64_neon_smull; - if (Type.isPoly()) Int = Intrinsic::aarch64_neon_pmull; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmull"); - case NEON::BI__builtin_neon_vmax_v: - case NEON::BI__builtin_neon_vmaxq_v: - // FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics. - Int = usgn ? Intrinsic::aarch64_neon_umax : Intrinsic::aarch64_neon_smax; - if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::aarch64_neon_fmax; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmax"); - case NEON::BI__builtin_neon_vmaxh_f16: { - Ops.push_back(EmitScalarExpr(E->getArg(1))); - Int = Intrinsic::aarch64_neon_fmax; - return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vmax"); - } - case NEON::BI__builtin_neon_vmin_v: - case NEON::BI__builtin_neon_vminq_v: - // FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics. - Int = usgn ? Intrinsic::aarch64_neon_umin : Intrinsic::aarch64_neon_smin; - if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::aarch64_neon_fmin; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmin"); - case NEON::BI__builtin_neon_vminh_f16: { - Ops.push_back(EmitScalarExpr(E->getArg(1))); - Int = Intrinsic::aarch64_neon_fmin; - return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vmin"); - } - case NEON::BI__builtin_neon_vabd_v: - case NEON::BI__builtin_neon_vabdq_v: - // FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics. - Int = usgn ? Intrinsic::aarch64_neon_uabd : Intrinsic::aarch64_neon_sabd; - if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::aarch64_neon_fabd; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vabd"); - case NEON::BI__builtin_neon_vpadal_v: - case NEON::BI__builtin_neon_vpadalq_v: { - unsigned ArgElts = VTy->getNumElements(); - llvm::IntegerType *EltTy = cast<IntegerType>(VTy->getElementType()); - unsigned BitWidth = EltTy->getBitWidth(); - llvm::Type *ArgTy = llvm::VectorType::get( - llvm::IntegerType::get(getLLVMContext(), BitWidth/2), 2*ArgElts); - llvm::Type* Tys[2] = { VTy, ArgTy }; - Int = usgn ? Intrinsic::aarch64_neon_uaddlp : Intrinsic::aarch64_neon_saddlp; - SmallVector<llvm::Value*, 1> TmpOps; - TmpOps.push_back(Ops[1]); - Function *F = CGM.getIntrinsic(Int, Tys); - llvm::Value *tmp = EmitNeonCall(F, TmpOps, "vpadal"); - llvm::Value *addend = Builder.CreateBitCast(Ops[0], tmp->getType()); - return Builder.CreateAdd(tmp, addend); - } - case NEON::BI__builtin_neon_vpmin_v: - case NEON::BI__builtin_neon_vpminq_v: - // FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics. - Int = usgn ? Intrinsic::aarch64_neon_uminp : Intrinsic::aarch64_neon_sminp; - if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::aarch64_neon_fminp; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmin"); - case NEON::BI__builtin_neon_vpmax_v: - case NEON::BI__builtin_neon_vpmaxq_v: - // FIXME: improve sharing scheme to cope with 3 alternative LLVM intrinsics. - Int = usgn ? Intrinsic::aarch64_neon_umaxp : Intrinsic::aarch64_neon_smaxp; - if (Ty->isFPOrFPVectorTy()) Int = Intrinsic::aarch64_neon_fmaxp; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmax"); - case NEON::BI__builtin_neon_vminnm_v: - case NEON::BI__builtin_neon_vminnmq_v: - Int = Intrinsic::aarch64_neon_fminnm; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vminnm"); - case NEON::BI__builtin_neon_vminnmh_f16: - Ops.push_back(EmitScalarExpr(E->getArg(1))); - Int = Intrinsic::aarch64_neon_fminnm; - return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vminnm"); - case NEON::BI__builtin_neon_vmaxnm_v: - case NEON::BI__builtin_neon_vmaxnmq_v: - Int = Intrinsic::aarch64_neon_fmaxnm; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmaxnm"); - case NEON::BI__builtin_neon_vmaxnmh_f16: - Ops.push_back(EmitScalarExpr(E->getArg(1))); - Int = Intrinsic::aarch64_neon_fmaxnm; - return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vmaxnm"); - case NEON::BI__builtin_neon_vrecpss_f32: { - Ops.push_back(EmitScalarExpr(E->getArg(1))); - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_frecps, FloatTy), - Ops, "vrecps"); - } - case NEON::BI__builtin_neon_vrecpsd_f64: - Ops.push_back(EmitScalarExpr(E->getArg(1))); - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_frecps, DoubleTy), - Ops, "vrecps"); - case NEON::BI__builtin_neon_vrecpsh_f16: - Ops.push_back(EmitScalarExpr(E->getArg(1))); - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_frecps, HalfTy), - Ops, "vrecps"); - case NEON::BI__builtin_neon_vqshrun_n_v: - Int = Intrinsic::aarch64_neon_sqshrun; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshrun_n"); - case NEON::BI__builtin_neon_vqrshrun_n_v: - Int = Intrinsic::aarch64_neon_sqrshrun; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqrshrun_n"); - case NEON::BI__builtin_neon_vqshrn_n_v: - Int = usgn ? Intrinsic::aarch64_neon_uqshrn : Intrinsic::aarch64_neon_sqshrn; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshrn_n"); - case NEON::BI__builtin_neon_vrshrn_n_v: - Int = Intrinsic::aarch64_neon_rshrn; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrshrn_n"); - case NEON::BI__builtin_neon_vqrshrn_n_v: - Int = usgn ? Intrinsic::aarch64_neon_uqrshrn : Intrinsic::aarch64_neon_sqrshrn; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqrshrn_n"); - case NEON::BI__builtin_neon_vrndah_f16: { - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Int = Intrinsic::round; - return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrnda"); - } - case NEON::BI__builtin_neon_vrnda_v: - case NEON::BI__builtin_neon_vrndaq_v: { - Int = Intrinsic::round; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrnda"); - } - case NEON::BI__builtin_neon_vrndih_f16: { - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Int = Intrinsic::nearbyint; - return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndi"); - } - case NEON::BI__builtin_neon_vrndmh_f16: { - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Int = Intrinsic::floor; - return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndm"); - } - case NEON::BI__builtin_neon_vrndm_v: - case NEON::BI__builtin_neon_vrndmq_v: { - Int = Intrinsic::floor; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndm"); - } - case NEON::BI__builtin_neon_vrndnh_f16: { - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Int = Intrinsic::aarch64_neon_frintn; - return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndn"); - } - case NEON::BI__builtin_neon_vrndn_v: - case NEON::BI__builtin_neon_vrndnq_v: { - Int = Intrinsic::aarch64_neon_frintn; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndn"); - } - case NEON::BI__builtin_neon_vrndns_f32: { - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Int = Intrinsic::aarch64_neon_frintn; - return EmitNeonCall(CGM.getIntrinsic(Int, FloatTy), Ops, "vrndn"); - } - case NEON::BI__builtin_neon_vrndph_f16: { - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Int = Intrinsic::ceil; - return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndp"); - } - case NEON::BI__builtin_neon_vrndp_v: - case NEON::BI__builtin_neon_vrndpq_v: { - Int = Intrinsic::ceil; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndp"); - } - case NEON::BI__builtin_neon_vrndxh_f16: { - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Int = Intrinsic::rint; - return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndx"); - } - case NEON::BI__builtin_neon_vrndx_v: - case NEON::BI__builtin_neon_vrndxq_v: { - Int = Intrinsic::rint; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndx"); - } - case NEON::BI__builtin_neon_vrndh_f16: { - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Int = Intrinsic::trunc; - return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndz"); - } - case NEON::BI__builtin_neon_vrnd_v: - case NEON::BI__builtin_neon_vrndq_v: { - Int = Intrinsic::trunc; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndz"); - } - case NEON::BI__builtin_neon_vcvt_f64_v: - case NEON::BI__builtin_neon_vcvtq_f64_v: - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float64, false, quad)); - return usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt") - : Builder.CreateSIToFP(Ops[0], Ty, "vcvt"); - case NEON::BI__builtin_neon_vcvt_f64_f32: { - assert(Type.getEltType() == NeonTypeFlags::Float64 && quad && - "unexpected vcvt_f64_f32 builtin"); - NeonTypeFlags SrcFlag = NeonTypeFlags(NeonTypeFlags::Float32, false, false); - Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(this, SrcFlag)); - - return Builder.CreateFPExt(Ops[0], Ty, "vcvt"); - } - case NEON::BI__builtin_neon_vcvt_f32_f64: { - assert(Type.getEltType() == NeonTypeFlags::Float32 && - "unexpected vcvt_f32_f64 builtin"); - NeonTypeFlags SrcFlag = NeonTypeFlags(NeonTypeFlags::Float64, false, true); - Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(this, SrcFlag)); - - return Builder.CreateFPTrunc(Ops[0], Ty, "vcvt"); - } - case NEON::BI__builtin_neon_vcvt_s32_v: - case NEON::BI__builtin_neon_vcvt_u32_v: - case NEON::BI__builtin_neon_vcvt_s64_v: - case NEON::BI__builtin_neon_vcvt_u64_v: - case NEON::BI__builtin_neon_vcvt_s16_v: - case NEON::BI__builtin_neon_vcvt_u16_v: - case NEON::BI__builtin_neon_vcvtq_s32_v: - case NEON::BI__builtin_neon_vcvtq_u32_v: - case NEON::BI__builtin_neon_vcvtq_s64_v: - case NEON::BI__builtin_neon_vcvtq_u64_v: - case NEON::BI__builtin_neon_vcvtq_s16_v: - case NEON::BI__builtin_neon_vcvtq_u16_v: { - Ops[0] = Builder.CreateBitCast(Ops[0], GetFloatNeonType(this, Type)); - if (usgn) - return Builder.CreateFPToUI(Ops[0], Ty); - return Builder.CreateFPToSI(Ops[0], Ty); - } - case NEON::BI__builtin_neon_vcvta_s16_v: - case NEON::BI__builtin_neon_vcvta_u16_v: - case NEON::BI__builtin_neon_vcvta_s32_v: - case NEON::BI__builtin_neon_vcvtaq_s16_v: - case NEON::BI__builtin_neon_vcvtaq_s32_v: - case NEON::BI__builtin_neon_vcvta_u32_v: - case NEON::BI__builtin_neon_vcvtaq_u16_v: - case NEON::BI__builtin_neon_vcvtaq_u32_v: - case NEON::BI__builtin_neon_vcvta_s64_v: - case NEON::BI__builtin_neon_vcvtaq_s64_v: - case NEON::BI__builtin_neon_vcvta_u64_v: - case NEON::BI__builtin_neon_vcvtaq_u64_v: { - Int = usgn ? Intrinsic::aarch64_neon_fcvtau : Intrinsic::aarch64_neon_fcvtas; - llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) }; - return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvta"); - } - case NEON::BI__builtin_neon_vcvtm_s16_v: - case NEON::BI__builtin_neon_vcvtm_s32_v: - case NEON::BI__builtin_neon_vcvtmq_s16_v: - case NEON::BI__builtin_neon_vcvtmq_s32_v: - case NEON::BI__builtin_neon_vcvtm_u16_v: - case NEON::BI__builtin_neon_vcvtm_u32_v: - case NEON::BI__builtin_neon_vcvtmq_u16_v: - case NEON::BI__builtin_neon_vcvtmq_u32_v: - case NEON::BI__builtin_neon_vcvtm_s64_v: - case NEON::BI__builtin_neon_vcvtmq_s64_v: - case NEON::BI__builtin_neon_vcvtm_u64_v: - case NEON::BI__builtin_neon_vcvtmq_u64_v: { - Int = usgn ? Intrinsic::aarch64_neon_fcvtmu : Intrinsic::aarch64_neon_fcvtms; - llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) }; - return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtm"); - } - case NEON::BI__builtin_neon_vcvtn_s16_v: - case NEON::BI__builtin_neon_vcvtn_s32_v: - case NEON::BI__builtin_neon_vcvtnq_s16_v: - case NEON::BI__builtin_neon_vcvtnq_s32_v: - case NEON::BI__builtin_neon_vcvtn_u16_v: - case NEON::BI__builtin_neon_vcvtn_u32_v: - case NEON::BI__builtin_neon_vcvtnq_u16_v: - case NEON::BI__builtin_neon_vcvtnq_u32_v: - case NEON::BI__builtin_neon_vcvtn_s64_v: - case NEON::BI__builtin_neon_vcvtnq_s64_v: - case NEON::BI__builtin_neon_vcvtn_u64_v: - case NEON::BI__builtin_neon_vcvtnq_u64_v: { - Int = usgn ? Intrinsic::aarch64_neon_fcvtnu : Intrinsic::aarch64_neon_fcvtns; - llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) }; - return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtn"); - } - case NEON::BI__builtin_neon_vcvtp_s16_v: - case NEON::BI__builtin_neon_vcvtp_s32_v: - case NEON::BI__builtin_neon_vcvtpq_s16_v: - case NEON::BI__builtin_neon_vcvtpq_s32_v: - case NEON::BI__builtin_neon_vcvtp_u16_v: - case NEON::BI__builtin_neon_vcvtp_u32_v: - case NEON::BI__builtin_neon_vcvtpq_u16_v: - case NEON::BI__builtin_neon_vcvtpq_u32_v: - case NEON::BI__builtin_neon_vcvtp_s64_v: - case NEON::BI__builtin_neon_vcvtpq_s64_v: - case NEON::BI__builtin_neon_vcvtp_u64_v: - case NEON::BI__builtin_neon_vcvtpq_u64_v: { - Int = usgn ? Intrinsic::aarch64_neon_fcvtpu : Intrinsic::aarch64_neon_fcvtps; - llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) }; - return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtp"); - } - case NEON::BI__builtin_neon_vmulx_v: - case NEON::BI__builtin_neon_vmulxq_v: { - Int = Intrinsic::aarch64_neon_fmulx; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmulx"); - } - case NEON::BI__builtin_neon_vmulxh_lane_f16: - case NEON::BI__builtin_neon_vmulxh_laneq_f16: { - // vmulx_lane should be mapped to Neon scalar mulx after - // extracting the scalar element - Ops.push_back(EmitScalarExpr(E->getArg(2))); - Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2], "extract"); - Ops.pop_back(); - Int = Intrinsic::aarch64_neon_fmulx; - return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vmulx"); - } - case NEON::BI__builtin_neon_vmul_lane_v: - case NEON::BI__builtin_neon_vmul_laneq_v: { - // v1f64 vmul_lane should be mapped to Neon scalar mul lane - bool Quad = false; - if (BuiltinID == NEON::BI__builtin_neon_vmul_laneq_v) - Quad = true; - Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy); - llvm::Type *VTy = GetNeonType(this, - NeonTypeFlags(NeonTypeFlags::Float64, false, Quad)); - Ops[1] = Builder.CreateBitCast(Ops[1], VTy); - Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2], "extract"); - Value *Result = Builder.CreateFMul(Ops[0], Ops[1]); - return Builder.CreateBitCast(Result, Ty); - } - case NEON::BI__builtin_neon_vnegd_s64: - return Builder.CreateNeg(EmitScalarExpr(E->getArg(0)), "vnegd"); - case NEON::BI__builtin_neon_vnegh_f16: - return Builder.CreateFNeg(EmitScalarExpr(E->getArg(0)), "vnegh"); - case NEON::BI__builtin_neon_vpmaxnm_v: - case NEON::BI__builtin_neon_vpmaxnmq_v: { - Int = Intrinsic::aarch64_neon_fmaxnmp; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmaxnm"); - } - case NEON::BI__builtin_neon_vpminnm_v: - case NEON::BI__builtin_neon_vpminnmq_v: { - Int = Intrinsic::aarch64_neon_fminnmp; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpminnm"); - } - case NEON::BI__builtin_neon_vsqrth_f16: { - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Int = Intrinsic::sqrt; - return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vsqrt"); - } - case NEON::BI__builtin_neon_vsqrt_v: - case NEON::BI__builtin_neon_vsqrtq_v: { - Int = Intrinsic::sqrt; - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vsqrt"); - } - case NEON::BI__builtin_neon_vrbit_v: - case NEON::BI__builtin_neon_vrbitq_v: { - Int = Intrinsic::aarch64_neon_rbit; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrbit"); - } - case NEON::BI__builtin_neon_vaddv_u8: - // FIXME: These are handled by the AArch64 scalar code. - usgn = true; - LLVM_FALLTHROUGH; - case NEON::BI__builtin_neon_vaddv_s8: { - Int = usgn ? Intrinsic::aarch64_neon_uaddv : Intrinsic::aarch64_neon_saddv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int8Ty, 8); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddv"); - return Builder.CreateTrunc(Ops[0], Int8Ty); - } - case NEON::BI__builtin_neon_vaddv_u16: - usgn = true; - LLVM_FALLTHROUGH; - case NEON::BI__builtin_neon_vaddv_s16: { - Int = usgn ? Intrinsic::aarch64_neon_uaddv : Intrinsic::aarch64_neon_saddv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int16Ty, 4); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddv"); - return Builder.CreateTrunc(Ops[0], Int16Ty); - } - case NEON::BI__builtin_neon_vaddvq_u8: - usgn = true; - LLVM_FALLTHROUGH; - case NEON::BI__builtin_neon_vaddvq_s8: { - Int = usgn ? Intrinsic::aarch64_neon_uaddv : Intrinsic::aarch64_neon_saddv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int8Ty, 16); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddv"); - return Builder.CreateTrunc(Ops[0], Int8Ty); - } - case NEON::BI__builtin_neon_vaddvq_u16: - usgn = true; - LLVM_FALLTHROUGH; - case NEON::BI__builtin_neon_vaddvq_s16: { - Int = usgn ? Intrinsic::aarch64_neon_uaddv : Intrinsic::aarch64_neon_saddv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int16Ty, 8); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddv"); - return Builder.CreateTrunc(Ops[0], Int16Ty); - } - case NEON::BI__builtin_neon_vmaxv_u8: { - Int = Intrinsic::aarch64_neon_umaxv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int8Ty, 8); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv"); - return Builder.CreateTrunc(Ops[0], Int8Ty); - } - case NEON::BI__builtin_neon_vmaxv_u16: { - Int = Intrinsic::aarch64_neon_umaxv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int16Ty, 4); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv"); - return Builder.CreateTrunc(Ops[0], Int16Ty); - } - case NEON::BI__builtin_neon_vmaxvq_u8: { - Int = Intrinsic::aarch64_neon_umaxv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int8Ty, 16); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv"); - return Builder.CreateTrunc(Ops[0], Int8Ty); - } - case NEON::BI__builtin_neon_vmaxvq_u16: { - Int = Intrinsic::aarch64_neon_umaxv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int16Ty, 8); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv"); - return Builder.CreateTrunc(Ops[0], Int16Ty); - } - case NEON::BI__builtin_neon_vmaxv_s8: { - Int = Intrinsic::aarch64_neon_smaxv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int8Ty, 8); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv"); - return Builder.CreateTrunc(Ops[0], Int8Ty); - } - case NEON::BI__builtin_neon_vmaxv_s16: { - Int = Intrinsic::aarch64_neon_smaxv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int16Ty, 4); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv"); - return Builder.CreateTrunc(Ops[0], Int16Ty); - } - case NEON::BI__builtin_neon_vmaxvq_s8: { - Int = Intrinsic::aarch64_neon_smaxv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int8Ty, 16); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv"); - return Builder.CreateTrunc(Ops[0], Int8Ty); - } - case NEON::BI__builtin_neon_vmaxvq_s16: { - Int = Intrinsic::aarch64_neon_smaxv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int16Ty, 8); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv"); - return Builder.CreateTrunc(Ops[0], Int16Ty); - } - case NEON::BI__builtin_neon_vmaxv_f16: { - Int = Intrinsic::aarch64_neon_fmaxv; - Ty = HalfTy; - VTy = llvm::VectorType::get(HalfTy, 4); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv"); - return Builder.CreateTrunc(Ops[0], HalfTy); - } - case NEON::BI__builtin_neon_vmaxvq_f16: { - Int = Intrinsic::aarch64_neon_fmaxv; - Ty = HalfTy; - VTy = llvm::VectorType::get(HalfTy, 8); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv"); - return Builder.CreateTrunc(Ops[0], HalfTy); - } - case NEON::BI__builtin_neon_vminv_u8: { - Int = Intrinsic::aarch64_neon_uminv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int8Ty, 8); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv"); - return Builder.CreateTrunc(Ops[0], Int8Ty); - } - case NEON::BI__builtin_neon_vminv_u16: { - Int = Intrinsic::aarch64_neon_uminv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int16Ty, 4); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv"); - return Builder.CreateTrunc(Ops[0], Int16Ty); - } - case NEON::BI__builtin_neon_vminvq_u8: { - Int = Intrinsic::aarch64_neon_uminv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int8Ty, 16); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv"); - return Builder.CreateTrunc(Ops[0], Int8Ty); - } - case NEON::BI__builtin_neon_vminvq_u16: { - Int = Intrinsic::aarch64_neon_uminv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int16Ty, 8); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv"); - return Builder.CreateTrunc(Ops[0], Int16Ty); - } - case NEON::BI__builtin_neon_vminv_s8: { - Int = Intrinsic::aarch64_neon_sminv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int8Ty, 8); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv"); - return Builder.CreateTrunc(Ops[0], Int8Ty); - } - case NEON::BI__builtin_neon_vminv_s16: { - Int = Intrinsic::aarch64_neon_sminv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int16Ty, 4); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv"); - return Builder.CreateTrunc(Ops[0], Int16Ty); - } - case NEON::BI__builtin_neon_vminvq_s8: { - Int = Intrinsic::aarch64_neon_sminv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int8Ty, 16); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv"); - return Builder.CreateTrunc(Ops[0], Int8Ty); - } - case NEON::BI__builtin_neon_vminvq_s16: { - Int = Intrinsic::aarch64_neon_sminv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int16Ty, 8); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv"); - return Builder.CreateTrunc(Ops[0], Int16Ty); - } - case NEON::BI__builtin_neon_vminv_f16: { - Int = Intrinsic::aarch64_neon_fminv; - Ty = HalfTy; - VTy = llvm::VectorType::get(HalfTy, 4); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv"); - return Builder.CreateTrunc(Ops[0], HalfTy); - } - case NEON::BI__builtin_neon_vminvq_f16: { - Int = Intrinsic::aarch64_neon_fminv; - Ty = HalfTy; - VTy = llvm::VectorType::get(HalfTy, 8); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv"); - return Builder.CreateTrunc(Ops[0], HalfTy); - } - case NEON::BI__builtin_neon_vmaxnmv_f16: { - Int = Intrinsic::aarch64_neon_fmaxnmv; - Ty = HalfTy; - VTy = llvm::VectorType::get(HalfTy, 4); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxnmv"); - return Builder.CreateTrunc(Ops[0], HalfTy); - } - case NEON::BI__builtin_neon_vmaxnmvq_f16: { - Int = Intrinsic::aarch64_neon_fmaxnmv; - Ty = HalfTy; - VTy = llvm::VectorType::get(HalfTy, 8); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxnmv"); - return Builder.CreateTrunc(Ops[0], HalfTy); - } - case NEON::BI__builtin_neon_vminnmv_f16: { - Int = Intrinsic::aarch64_neon_fminnmv; - Ty = HalfTy; - VTy = llvm::VectorType::get(HalfTy, 4); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminnmv"); - return Builder.CreateTrunc(Ops[0], HalfTy); - } - case NEON::BI__builtin_neon_vminnmvq_f16: { - Int = Intrinsic::aarch64_neon_fminnmv; - Ty = HalfTy; - VTy = llvm::VectorType::get(HalfTy, 8); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminnmv"); - return Builder.CreateTrunc(Ops[0], HalfTy); - } - case NEON::BI__builtin_neon_vmul_n_f64: { - Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy); - Value *RHS = Builder.CreateBitCast(EmitScalarExpr(E->getArg(1)), DoubleTy); - return Builder.CreateFMul(Ops[0], RHS); - } - case NEON::BI__builtin_neon_vaddlv_u8: { - Int = Intrinsic::aarch64_neon_uaddlv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int8Ty, 8); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv"); - return Builder.CreateTrunc(Ops[0], Int16Ty); - } - case NEON::BI__builtin_neon_vaddlv_u16: { - Int = Intrinsic::aarch64_neon_uaddlv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int16Ty, 4); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv"); - } - case NEON::BI__builtin_neon_vaddlvq_u8: { - Int = Intrinsic::aarch64_neon_uaddlv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int8Ty, 16); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv"); - return Builder.CreateTrunc(Ops[0], Int16Ty); - } - case NEON::BI__builtin_neon_vaddlvq_u16: { - Int = Intrinsic::aarch64_neon_uaddlv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int16Ty, 8); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv"); - } - case NEON::BI__builtin_neon_vaddlv_s8: { - Int = Intrinsic::aarch64_neon_saddlv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int8Ty, 8); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv"); - return Builder.CreateTrunc(Ops[0], Int16Ty); - } - case NEON::BI__builtin_neon_vaddlv_s16: { - Int = Intrinsic::aarch64_neon_saddlv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int16Ty, 4); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv"); - } - case NEON::BI__builtin_neon_vaddlvq_s8: { - Int = Intrinsic::aarch64_neon_saddlv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int8Ty, 16); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv"); - return Builder.CreateTrunc(Ops[0], Int16Ty); - } - case NEON::BI__builtin_neon_vaddlvq_s16: { - Int = Intrinsic::aarch64_neon_saddlv; - Ty = Int32Ty; - VTy = llvm::VectorType::get(Int16Ty, 8); - llvm::Type *Tys[2] = { Ty, VTy }; - Ops.push_back(EmitScalarExpr(E->getArg(0))); - return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv"); - } - case NEON::BI__builtin_neon_vsri_n_v: - case NEON::BI__builtin_neon_vsriq_n_v: { - Int = Intrinsic::aarch64_neon_vsri; - llvm::Function *Intrin = CGM.getIntrinsic(Int, Ty); - return EmitNeonCall(Intrin, Ops, "vsri_n"); - } - case NEON::BI__builtin_neon_vsli_n_v: - case NEON::BI__builtin_neon_vsliq_n_v: { - Int = Intrinsic::aarch64_neon_vsli; - llvm::Function *Intrin = CGM.getIntrinsic(Int, Ty); - return EmitNeonCall(Intrin, Ops, "vsli_n"); - } - case NEON::BI__builtin_neon_vsra_n_v: - case NEON::BI__builtin_neon_vsraq_n_v: - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - Ops[1] = EmitNeonRShiftImm(Ops[1], Ops[2], Ty, usgn, "vsra_n"); - return Builder.CreateAdd(Ops[0], Ops[1]); - case NEON::BI__builtin_neon_vrsra_n_v: - case NEON::BI__builtin_neon_vrsraq_n_v: { - Int = usgn ? Intrinsic::aarch64_neon_urshl : Intrinsic::aarch64_neon_srshl; - SmallVector<llvm::Value*,2> TmpOps; - TmpOps.push_back(Ops[1]); - TmpOps.push_back(Ops[2]); - Function* F = CGM.getIntrinsic(Int, Ty); - llvm::Value *tmp = EmitNeonCall(F, TmpOps, "vrshr_n", 1, true); - Ops[0] = Builder.CreateBitCast(Ops[0], VTy); - return Builder.CreateAdd(Ops[0], tmp); - } - case NEON::BI__builtin_neon_vld1_v: - case NEON::BI__builtin_neon_vld1q_v: { - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(VTy)); - auto Alignment = CharUnits::fromQuantity( - BuiltinID == NEON::BI__builtin_neon_vld1_v ? 8 : 16); - return Builder.CreateAlignedLoad(VTy, Ops[0], Alignment); - } - case NEON::BI__builtin_neon_vst1_v: - case NEON::BI__builtin_neon_vst1q_v: - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(VTy)); - Ops[1] = Builder.CreateBitCast(Ops[1], VTy); - return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]); - case NEON::BI__builtin_neon_vld1_lane_v: - case NEON::BI__builtin_neon_vld1q_lane_v: { - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - Ty = llvm::PointerType::getUnqual(VTy->getElementType()); - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - auto Alignment = CharUnits::fromQuantity( - BuiltinID == NEON::BI__builtin_neon_vld1_lane_v ? 8 : 16); - Ops[0] = - Builder.CreateAlignedLoad(VTy->getElementType(), Ops[0], Alignment); - return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vld1_lane"); - } - case NEON::BI__builtin_neon_vld1_dup_v: - case NEON::BI__builtin_neon_vld1q_dup_v: { - Value *V = UndefValue::get(Ty); - Ty = llvm::PointerType::getUnqual(VTy->getElementType()); - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - auto Alignment = CharUnits::fromQuantity( - BuiltinID == NEON::BI__builtin_neon_vld1_dup_v ? 8 : 16); - Ops[0] = - Builder.CreateAlignedLoad(VTy->getElementType(), Ops[0], Alignment); - llvm::Constant *CI = ConstantInt::get(Int32Ty, 0); - Ops[0] = Builder.CreateInsertElement(V, Ops[0], CI); - return EmitNeonSplat(Ops[0], CI); - } - case NEON::BI__builtin_neon_vst1_lane_v: - case NEON::BI__builtin_neon_vst1q_lane_v: - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2]); - Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); - return Builder.CreateDefaultAlignedStore(Ops[1], - Builder.CreateBitCast(Ops[0], Ty)); - case NEON::BI__builtin_neon_vld2_v: - case NEON::BI__builtin_neon_vld2q_v: { - llvm::Type *PTy = llvm::PointerType::getUnqual(VTy); - Ops[1] = Builder.CreateBitCast(Ops[1], PTy); - llvm::Type *Tys[2] = { VTy, PTy }; - Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld2, Tys); - Ops[1] = Builder.CreateCall(F, Ops[1], "vld2"); - Ops[0] = Builder.CreateBitCast(Ops[0], - llvm::PointerType::getUnqual(Ops[1]->getType())); - return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]); - } - case NEON::BI__builtin_neon_vld3_v: - case NEON::BI__builtin_neon_vld3q_v: { - llvm::Type *PTy = llvm::PointerType::getUnqual(VTy); - Ops[1] = Builder.CreateBitCast(Ops[1], PTy); - llvm::Type *Tys[2] = { VTy, PTy }; - Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld3, Tys); - Ops[1] = Builder.CreateCall(F, Ops[1], "vld3"); - Ops[0] = Builder.CreateBitCast(Ops[0], - llvm::PointerType::getUnqual(Ops[1]->getType())); - return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]); - } - case NEON::BI__builtin_neon_vld4_v: - case NEON::BI__builtin_neon_vld4q_v: { - llvm::Type *PTy = llvm::PointerType::getUnqual(VTy); - Ops[1] = Builder.CreateBitCast(Ops[1], PTy); - llvm::Type *Tys[2] = { VTy, PTy }; - Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld4, Tys); - Ops[1] = Builder.CreateCall(F, Ops[1], "vld4"); - Ops[0] = Builder.CreateBitCast(Ops[0], - llvm::PointerType::getUnqual(Ops[1]->getType())); - return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]); - } - case NEON::BI__builtin_neon_vld2_dup_v: - case NEON::BI__builtin_neon_vld2q_dup_v: { - llvm::Type *PTy = - llvm::PointerType::getUnqual(VTy->getElementType()); - Ops[1] = Builder.CreateBitCast(Ops[1], PTy); - llvm::Type *Tys[2] = { VTy, PTy }; - Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld2r, Tys); - Ops[1] = Builder.CreateCall(F, Ops[1], "vld2"); - Ops[0] = Builder.CreateBitCast(Ops[0], - llvm::PointerType::getUnqual(Ops[1]->getType())); - return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]); - } - case NEON::BI__builtin_neon_vld3_dup_v: - case NEON::BI__builtin_neon_vld3q_dup_v: { - llvm::Type *PTy = - llvm::PointerType::getUnqual(VTy->getElementType()); - Ops[1] = Builder.CreateBitCast(Ops[1], PTy); - llvm::Type *Tys[2] = { VTy, PTy }; - Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld3r, Tys); - Ops[1] = Builder.CreateCall(F, Ops[1], "vld3"); - Ops[0] = Builder.CreateBitCast(Ops[0], - llvm::PointerType::getUnqual(Ops[1]->getType())); - return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]); - } - case NEON::BI__builtin_neon_vld4_dup_v: - case NEON::BI__builtin_neon_vld4q_dup_v: { - llvm::Type *PTy = - llvm::PointerType::getUnqual(VTy->getElementType()); - Ops[1] = Builder.CreateBitCast(Ops[1], PTy); - llvm::Type *Tys[2] = { VTy, PTy }; - Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld4r, Tys); - Ops[1] = Builder.CreateCall(F, Ops[1], "vld4"); - Ops[0] = Builder.CreateBitCast(Ops[0], - llvm::PointerType::getUnqual(Ops[1]->getType())); - return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]); - } - case NEON::BI__builtin_neon_vld2_lane_v: - case NEON::BI__builtin_neon_vld2q_lane_v: { - llvm::Type *Tys[2] = { VTy, Ops[1]->getType() }; - Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld2lane, Tys); - Ops.push_back(Ops[1]); - Ops.erase(Ops.begin()+1); - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - Ops[2] = Builder.CreateBitCast(Ops[2], Ty); - Ops[3] = Builder.CreateZExt(Ops[3], Int64Ty); - Ops[1] = Builder.CreateCall(F, makeArrayRef(Ops).slice(1), "vld2_lane"); - Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]); - } - case NEON::BI__builtin_neon_vld3_lane_v: - case NEON::BI__builtin_neon_vld3q_lane_v: { - llvm::Type *Tys[2] = { VTy, Ops[1]->getType() }; - Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld3lane, Tys); - Ops.push_back(Ops[1]); - Ops.erase(Ops.begin()+1); - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - Ops[2] = Builder.CreateBitCast(Ops[2], Ty); - Ops[3] = Builder.CreateBitCast(Ops[3], Ty); - Ops[4] = Builder.CreateZExt(Ops[4], Int64Ty); - Ops[1] = Builder.CreateCall(F, makeArrayRef(Ops).slice(1), "vld3_lane"); - Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]); - } - case NEON::BI__builtin_neon_vld4_lane_v: - case NEON::BI__builtin_neon_vld4q_lane_v: { - llvm::Type *Tys[2] = { VTy, Ops[1]->getType() }; - Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_ld4lane, Tys); - Ops.push_back(Ops[1]); - Ops.erase(Ops.begin()+1); - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - Ops[2] = Builder.CreateBitCast(Ops[2], Ty); - Ops[3] = Builder.CreateBitCast(Ops[3], Ty); - Ops[4] = Builder.CreateBitCast(Ops[4], Ty); - Ops[5] = Builder.CreateZExt(Ops[5], Int64Ty); - Ops[1] = Builder.CreateCall(F, makeArrayRef(Ops).slice(1), "vld4_lane"); - Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]); - } - case NEON::BI__builtin_neon_vst2_v: - case NEON::BI__builtin_neon_vst2q_v: { - Ops.push_back(Ops[0]); - Ops.erase(Ops.begin()); - llvm::Type *Tys[2] = { VTy, Ops[2]->getType() }; - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st2, Tys), - Ops, ""); - } - case NEON::BI__builtin_neon_vst2_lane_v: - case NEON::BI__builtin_neon_vst2q_lane_v: { - Ops.push_back(Ops[0]); - Ops.erase(Ops.begin()); - Ops[2] = Builder.CreateZExt(Ops[2], Int64Ty); - llvm::Type *Tys[2] = { VTy, Ops[3]->getType() }; - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st2lane, Tys), - Ops, ""); - } - case NEON::BI__builtin_neon_vst3_v: - case NEON::BI__builtin_neon_vst3q_v: { - Ops.push_back(Ops[0]); - Ops.erase(Ops.begin()); - llvm::Type *Tys[2] = { VTy, Ops[3]->getType() }; - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st3, Tys), - Ops, ""); - } - case NEON::BI__builtin_neon_vst3_lane_v: - case NEON::BI__builtin_neon_vst3q_lane_v: { - Ops.push_back(Ops[0]); - Ops.erase(Ops.begin()); - Ops[3] = Builder.CreateZExt(Ops[3], Int64Ty); - llvm::Type *Tys[2] = { VTy, Ops[4]->getType() }; - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st3lane, Tys), - Ops, ""); - } - case NEON::BI__builtin_neon_vst4_v: - case NEON::BI__builtin_neon_vst4q_v: { - Ops.push_back(Ops[0]); - Ops.erase(Ops.begin()); - llvm::Type *Tys[2] = { VTy, Ops[4]->getType() }; - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st4, Tys), - Ops, ""); - } - case NEON::BI__builtin_neon_vst4_lane_v: - case NEON::BI__builtin_neon_vst4q_lane_v: { - Ops.push_back(Ops[0]); - Ops.erase(Ops.begin()); - Ops[4] = Builder.CreateZExt(Ops[4], Int64Ty); - llvm::Type *Tys[2] = { VTy, Ops[5]->getType() }; - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st4lane, Tys), - Ops, ""); - } - case NEON::BI__builtin_neon_vtrn_v: - case NEON::BI__builtin_neon_vtrnq_v: { - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty)); - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - Ops[2] = Builder.CreateBitCast(Ops[2], Ty); - Value *SV = nullptr; - - for (unsigned vi = 0; vi != 2; ++vi) { - SmallVector<uint32_t, 16> Indices; - for (unsigned i = 0, e = VTy->getNumElements(); i != e; i += 2) { - Indices.push_back(i+vi); - Indices.push_back(i+e+vi); - } - Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi); - SV = Builder.CreateShuffleVector(Ops[1], Ops[2], Indices, "vtrn"); - SV = Builder.CreateDefaultAlignedStore(SV, Addr); - } - return SV; - } - case NEON::BI__builtin_neon_vuzp_v: - case NEON::BI__builtin_neon_vuzpq_v: { - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty)); - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - Ops[2] = Builder.CreateBitCast(Ops[2], Ty); - Value *SV = nullptr; - - for (unsigned vi = 0; vi != 2; ++vi) { - SmallVector<uint32_t, 16> Indices; - for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) - Indices.push_back(2*i+vi); - - Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi); - SV = Builder.CreateShuffleVector(Ops[1], Ops[2], Indices, "vuzp"); - SV = Builder.CreateDefaultAlignedStore(SV, Addr); - } - return SV; - } - case NEON::BI__builtin_neon_vzip_v: - case NEON::BI__builtin_neon_vzipq_v: { - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty)); - Ops[1] = Builder.CreateBitCast(Ops[1], Ty); - Ops[2] = Builder.CreateBitCast(Ops[2], Ty); - Value *SV = nullptr; - - for (unsigned vi = 0; vi != 2; ++vi) { - SmallVector<uint32_t, 16> Indices; - for (unsigned i = 0, e = VTy->getNumElements(); i != e; i += 2) { - Indices.push_back((i + vi*e) >> 1); - Indices.push_back(((i + vi*e) >> 1)+e); - } - Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi); - SV = Builder.CreateShuffleVector(Ops[1], Ops[2], Indices, "vzip"); - SV = Builder.CreateDefaultAlignedStore(SV, Addr); - } - return SV; - } - case NEON::BI__builtin_neon_vqtbl1q_v: { - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbl1, Ty), - Ops, "vtbl1"); - } - case NEON::BI__builtin_neon_vqtbl2q_v: { - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbl2, Ty), - Ops, "vtbl2"); - } - case NEON::BI__builtin_neon_vqtbl3q_v: { - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbl3, Ty), - Ops, "vtbl3"); - } - case NEON::BI__builtin_neon_vqtbl4q_v: { - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbl4, Ty), - Ops, "vtbl4"); - } - case NEON::BI__builtin_neon_vqtbx1q_v: { - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbx1, Ty), - Ops, "vtbx1"); - } - case NEON::BI__builtin_neon_vqtbx2q_v: { - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbx2, Ty), - Ops, "vtbx2"); - } - case NEON::BI__builtin_neon_vqtbx3q_v: { - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbx3, Ty), - Ops, "vtbx3"); - } - case NEON::BI__builtin_neon_vqtbx4q_v: { - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_tbx4, Ty), - Ops, "vtbx4"); - } - case NEON::BI__builtin_neon_vsqadd_v: - case NEON::BI__builtin_neon_vsqaddq_v: { - Int = Intrinsic::aarch64_neon_usqadd; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vsqadd"); - } - case NEON::BI__builtin_neon_vuqadd_v: - case NEON::BI__builtin_neon_vuqaddq_v: { - Int = Intrinsic::aarch64_neon_suqadd; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vuqadd"); - } - case AArch64::BI__iso_volatile_load8: - case AArch64::BI__iso_volatile_load16: - case AArch64::BI__iso_volatile_load32: - case AArch64::BI__iso_volatile_load64: - return EmitISOVolatileLoad(E); - case AArch64::BI__iso_volatile_store8: - case AArch64::BI__iso_volatile_store16: - case AArch64::BI__iso_volatile_store32: - case AArch64::BI__iso_volatile_store64: - return EmitISOVolatileStore(E); - case AArch64::BI_BitScanForward: - case AArch64::BI_BitScanForward64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_BitScanForward, E); - case AArch64::BI_BitScanReverse: - case AArch64::BI_BitScanReverse64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_BitScanReverse, E); - case AArch64::BI_InterlockedAnd64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd, E); - case AArch64::BI_InterlockedExchange64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange, E); - case AArch64::BI_InterlockedExchangeAdd64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd, E); - case AArch64::BI_InterlockedExchangeSub64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeSub, E); - case AArch64::BI_InterlockedOr64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr, E); - case AArch64::BI_InterlockedXor64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor, E); - case AArch64::BI_InterlockedDecrement64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement, E); - case AArch64::BI_InterlockedIncrement64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement, E); - case AArch64::BI_InterlockedExchangeAdd8_acq: - case AArch64::BI_InterlockedExchangeAdd16_acq: - case AArch64::BI_InterlockedExchangeAdd_acq: - case AArch64::BI_InterlockedExchangeAdd64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd_acq, E); - case AArch64::BI_InterlockedExchangeAdd8_rel: - case AArch64::BI_InterlockedExchangeAdd16_rel: - case AArch64::BI_InterlockedExchangeAdd_rel: - case AArch64::BI_InterlockedExchangeAdd64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd_rel, E); - case AArch64::BI_InterlockedExchangeAdd8_nf: - case AArch64::BI_InterlockedExchangeAdd16_nf: - case AArch64::BI_InterlockedExchangeAdd_nf: - case AArch64::BI_InterlockedExchangeAdd64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd_nf, E); - case AArch64::BI_InterlockedExchange8_acq: - case AArch64::BI_InterlockedExchange16_acq: - case AArch64::BI_InterlockedExchange_acq: - case AArch64::BI_InterlockedExchange64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange_acq, E); - case AArch64::BI_InterlockedExchange8_rel: - case AArch64::BI_InterlockedExchange16_rel: - case AArch64::BI_InterlockedExchange_rel: - case AArch64::BI_InterlockedExchange64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange_rel, E); - case AArch64::BI_InterlockedExchange8_nf: - case AArch64::BI_InterlockedExchange16_nf: - case AArch64::BI_InterlockedExchange_nf: - case AArch64::BI_InterlockedExchange64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange_nf, E); - case AArch64::BI_InterlockedCompareExchange8_acq: - case AArch64::BI_InterlockedCompareExchange16_acq: - case AArch64::BI_InterlockedCompareExchange_acq: - case AArch64::BI_InterlockedCompareExchange64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange_acq, E); - case AArch64::BI_InterlockedCompareExchange8_rel: - case AArch64::BI_InterlockedCompareExchange16_rel: - case AArch64::BI_InterlockedCompareExchange_rel: - case AArch64::BI_InterlockedCompareExchange64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange_rel, E); - case AArch64::BI_InterlockedCompareExchange8_nf: - case AArch64::BI_InterlockedCompareExchange16_nf: - case AArch64::BI_InterlockedCompareExchange_nf: - case AArch64::BI_InterlockedCompareExchange64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange_nf, E); - case AArch64::BI_InterlockedOr8_acq: - case AArch64::BI_InterlockedOr16_acq: - case AArch64::BI_InterlockedOr_acq: - case AArch64::BI_InterlockedOr64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr_acq, E); - case AArch64::BI_InterlockedOr8_rel: - case AArch64::BI_InterlockedOr16_rel: - case AArch64::BI_InterlockedOr_rel: - case AArch64::BI_InterlockedOr64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr_rel, E); - case AArch64::BI_InterlockedOr8_nf: - case AArch64::BI_InterlockedOr16_nf: - case AArch64::BI_InterlockedOr_nf: - case AArch64::BI_InterlockedOr64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr_nf, E); - case AArch64::BI_InterlockedXor8_acq: - case AArch64::BI_InterlockedXor16_acq: - case AArch64::BI_InterlockedXor_acq: - case AArch64::BI_InterlockedXor64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor_acq, E); - case AArch64::BI_InterlockedXor8_rel: - case AArch64::BI_InterlockedXor16_rel: - case AArch64::BI_InterlockedXor_rel: - case AArch64::BI_InterlockedXor64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor_rel, E); - case AArch64::BI_InterlockedXor8_nf: - case AArch64::BI_InterlockedXor16_nf: - case AArch64::BI_InterlockedXor_nf: - case AArch64::BI_InterlockedXor64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor_nf, E); - case AArch64::BI_InterlockedAnd8_acq: - case AArch64::BI_InterlockedAnd16_acq: - case AArch64::BI_InterlockedAnd_acq: - case AArch64::BI_InterlockedAnd64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd_acq, E); - case AArch64::BI_InterlockedAnd8_rel: - case AArch64::BI_InterlockedAnd16_rel: - case AArch64::BI_InterlockedAnd_rel: - case AArch64::BI_InterlockedAnd64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd_rel, E); - case AArch64::BI_InterlockedAnd8_nf: - case AArch64::BI_InterlockedAnd16_nf: - case AArch64::BI_InterlockedAnd_nf: - case AArch64::BI_InterlockedAnd64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd_nf, E); - case AArch64::BI_InterlockedIncrement16_acq: - case AArch64::BI_InterlockedIncrement_acq: - case AArch64::BI_InterlockedIncrement64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement_acq, E); - case AArch64::BI_InterlockedIncrement16_rel: - case AArch64::BI_InterlockedIncrement_rel: - case AArch64::BI_InterlockedIncrement64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement_rel, E); - case AArch64::BI_InterlockedIncrement16_nf: - case AArch64::BI_InterlockedIncrement_nf: - case AArch64::BI_InterlockedIncrement64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement_nf, E); - case AArch64::BI_InterlockedDecrement16_acq: - case AArch64::BI_InterlockedDecrement_acq: - case AArch64::BI_InterlockedDecrement64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement_acq, E); - case AArch64::BI_InterlockedDecrement16_rel: - case AArch64::BI_InterlockedDecrement_rel: - case AArch64::BI_InterlockedDecrement64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement_rel, E); - case AArch64::BI_InterlockedDecrement16_nf: - case AArch64::BI_InterlockedDecrement_nf: - case AArch64::BI_InterlockedDecrement64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement_nf, E); - - case AArch64::BI_InterlockedAdd: { - Value *Arg0 = EmitScalarExpr(E->getArg(0)); - Value *Arg1 = EmitScalarExpr(E->getArg(1)); - AtomicRMWInst *RMWI = Builder.CreateAtomicRMW( - AtomicRMWInst::Add, Arg0, Arg1, - llvm::AtomicOrdering::SequentiallyConsistent); - return Builder.CreateAdd(RMWI, Arg1); - } - } -} - -llvm::Value *CodeGenFunction:: -BuildVector(ArrayRef<llvm::Value*> Ops) { - assert((Ops.size() & (Ops.size() - 1)) == 0 && - "Not a power-of-two sized vector!"); - bool AllConstants = true; - for (unsigned i = 0, e = Ops.size(); i != e && AllConstants; ++i) - AllConstants &= isa<Constant>(Ops[i]); - - // If this is a constant vector, create a ConstantVector. - if (AllConstants) { - SmallVector<llvm::Constant*, 16> CstOps; - for (unsigned i = 0, e = Ops.size(); i != e; ++i) - CstOps.push_back(cast<Constant>(Ops[i])); - return llvm::ConstantVector::get(CstOps); - } - - // Otherwise, insertelement the values to build the vector. - Value *Result = - llvm::UndefValue::get(llvm::VectorType::get(Ops[0]->getType(), Ops.size())); - - for (unsigned i = 0, e = Ops.size(); i != e; ++i) - Result = Builder.CreateInsertElement(Result, Ops[i], Builder.getInt32(i)); - - return Result; -} - -// Convert the mask from an integer type to a vector of i1. -static Value *getMaskVecValue(CodeGenFunction &CGF, Value *Mask, - unsigned NumElts) { - - llvm::VectorType *MaskTy = llvm::VectorType::get(CGF.Builder.getInt1Ty(), - cast<IntegerType>(Mask->getType())->getBitWidth()); - Value *MaskVec = CGF.Builder.CreateBitCast(Mask, MaskTy); - - // If we have less than 8 elements, then the starting mask was an i8 and - // we need to extract down to the right number of elements. - if (NumElts < 8) { - uint32_t Indices[4]; - for (unsigned i = 0; i != NumElts; ++i) - Indices[i] = i; - MaskVec = CGF.Builder.CreateShuffleVector(MaskVec, MaskVec, - makeArrayRef(Indices, NumElts), - "extract"); - } - return MaskVec; -} - -static Value *EmitX86MaskedStore(CodeGenFunction &CGF, - ArrayRef<Value *> Ops, - unsigned Align) { - // Cast the pointer to right type. - Value *Ptr = CGF.Builder.CreateBitCast(Ops[0], - llvm::PointerType::getUnqual(Ops[1]->getType())); - - Value *MaskVec = getMaskVecValue(CGF, Ops[2], - Ops[1]->getType()->getVectorNumElements()); - - return CGF.Builder.CreateMaskedStore(Ops[1], Ptr, Align, MaskVec); -} - -static Value *EmitX86MaskedLoad(CodeGenFunction &CGF, - ArrayRef<Value *> Ops, unsigned Align) { - // Cast the pointer to right type. - Value *Ptr = CGF.Builder.CreateBitCast(Ops[0], - llvm::PointerType::getUnqual(Ops[1]->getType())); - - Value *MaskVec = getMaskVecValue(CGF, Ops[2], - Ops[1]->getType()->getVectorNumElements()); - - return CGF.Builder.CreateMaskedLoad(Ptr, Align, MaskVec, Ops[1]); -} - -static Value *EmitX86ExpandLoad(CodeGenFunction &CGF, - ArrayRef<Value *> Ops) { - llvm::Type *ResultTy = Ops[1]->getType(); - llvm::Type *PtrTy = ResultTy->getVectorElementType(); - - // Cast the pointer to element type. - Value *Ptr = CGF.Builder.CreateBitCast(Ops[0], - llvm::PointerType::getUnqual(PtrTy)); - - Value *MaskVec = getMaskVecValue(CGF, Ops[2], - ResultTy->getVectorNumElements()); - - llvm::Function *F = CGF.CGM.getIntrinsic(Intrinsic::masked_expandload, - ResultTy); - return CGF.Builder.CreateCall(F, { Ptr, MaskVec, Ops[1] }); -} - -static Value *EmitX86CompressStore(CodeGenFunction &CGF, - ArrayRef<Value *> Ops) { - llvm::Type *ResultTy = Ops[1]->getType(); - llvm::Type *PtrTy = ResultTy->getVectorElementType(); - - // Cast the pointer to element type. - Value *Ptr = CGF.Builder.CreateBitCast(Ops[0], - llvm::PointerType::getUnqual(PtrTy)); - - Value *MaskVec = getMaskVecValue(CGF, Ops[2], - ResultTy->getVectorNumElements()); - - llvm::Function *F = CGF.CGM.getIntrinsic(Intrinsic::masked_compressstore, - ResultTy); - return CGF.Builder.CreateCall(F, { Ops[1], Ptr, MaskVec }); -} - -static Value *EmitX86MaskLogic(CodeGenFunction &CGF, Instruction::BinaryOps Opc, - ArrayRef<Value *> Ops, - bool InvertLHS = false) { - unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth(); - Value *LHS = getMaskVecValue(CGF, Ops[0], NumElts); - Value *RHS = getMaskVecValue(CGF, Ops[1], NumElts); - - if (InvertLHS) - LHS = CGF.Builder.CreateNot(LHS); - - return CGF.Builder.CreateBitCast(CGF.Builder.CreateBinOp(Opc, LHS, RHS), - Ops[0]->getType()); -} - -static Value *EmitX86FunnelShift(CodeGenFunction &CGF, Value *Op0, Value *Op1, - Value *Amt, bool IsRight) { - llvm::Type *Ty = Op0->getType(); - - // Amount may be scalar immediate, in which case create a splat vector. - // Funnel shifts amounts are treated as modulo and types are all power-of-2 so - // we only care about the lowest log2 bits anyway. - if (Amt->getType() != Ty) { - unsigned NumElts = Ty->getVectorNumElements(); - Amt = CGF.Builder.CreateIntCast(Amt, Ty->getScalarType(), false); - Amt = CGF.Builder.CreateVectorSplat(NumElts, Amt); - } - - unsigned IID = IsRight ? Intrinsic::fshr : Intrinsic::fshl; - Value *F = CGF.CGM.getIntrinsic(IID, Ty); - return CGF.Builder.CreateCall(F, {Op0, Op1, Amt}); -} - -static Value *EmitX86Select(CodeGenFunction &CGF, - Value *Mask, Value *Op0, Value *Op1) { - - // If the mask is all ones just return first argument. - if (const auto *C = dyn_cast<Constant>(Mask)) - if (C->isAllOnesValue()) - return Op0; - - Mask = getMaskVecValue(CGF, Mask, Op0->getType()->getVectorNumElements()); - - return CGF.Builder.CreateSelect(Mask, Op0, Op1); -} - -static Value *EmitX86ScalarSelect(CodeGenFunction &CGF, - Value *Mask, Value *Op0, Value *Op1) { - // If the mask is all ones just return first argument. - if (const auto *C = dyn_cast<Constant>(Mask)) - if (C->isAllOnesValue()) - return Op0; - - llvm::VectorType *MaskTy = - llvm::VectorType::get(CGF.Builder.getInt1Ty(), - Mask->getType()->getIntegerBitWidth()); - Mask = CGF.Builder.CreateBitCast(Mask, MaskTy); - Mask = CGF.Builder.CreateExtractElement(Mask, (uint64_t)0); - return CGF.Builder.CreateSelect(Mask, Op0, Op1); -} - -static Value *EmitX86MaskedCompareResult(CodeGenFunction &CGF, Value *Cmp, - unsigned NumElts, Value *MaskIn) { - if (MaskIn) { - const auto *C = dyn_cast<Constant>(MaskIn); - if (!C || !C->isAllOnesValue()) - Cmp = CGF.Builder.CreateAnd(Cmp, getMaskVecValue(CGF, MaskIn, NumElts)); - } - - if (NumElts < 8) { - uint32_t Indices[8]; - for (unsigned i = 0; i != NumElts; ++i) - Indices[i] = i; - for (unsigned i = NumElts; i != 8; ++i) - Indices[i] = i % NumElts + NumElts; - Cmp = CGF.Builder.CreateShuffleVector( - Cmp, llvm::Constant::getNullValue(Cmp->getType()), Indices); - } - - return CGF.Builder.CreateBitCast(Cmp, - IntegerType::get(CGF.getLLVMContext(), - std::max(NumElts, 8U))); -} - -static Value *EmitX86MaskedCompare(CodeGenFunction &CGF, unsigned CC, - bool Signed, ArrayRef<Value *> Ops) { - assert((Ops.size() == 2 || Ops.size() == 4) && - "Unexpected number of arguments"); - unsigned NumElts = Ops[0]->getType()->getVectorNumElements(); - Value *Cmp; - - if (CC == 3) { - Cmp = Constant::getNullValue( - llvm::VectorType::get(CGF.Builder.getInt1Ty(), NumElts)); - } else if (CC == 7) { - Cmp = Constant::getAllOnesValue( - llvm::VectorType::get(CGF.Builder.getInt1Ty(), NumElts)); - } else { - ICmpInst::Predicate Pred; - switch (CC) { - default: llvm_unreachable("Unknown condition code"); - case 0: Pred = ICmpInst::ICMP_EQ; break; - case 1: Pred = Signed ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT; break; - case 2: Pred = Signed ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE; break; - case 4: Pred = ICmpInst::ICMP_NE; break; - case 5: Pred = Signed ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE; break; - case 6: Pred = Signed ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT; break; - } - Cmp = CGF.Builder.CreateICmp(Pred, Ops[0], Ops[1]); - } - - Value *MaskIn = nullptr; - if (Ops.size() == 4) - MaskIn = Ops[3]; - - return EmitX86MaskedCompareResult(CGF, Cmp, NumElts, MaskIn); -} - -static Value *EmitX86ConvertToMask(CodeGenFunction &CGF, Value *In) { - Value *Zero = Constant::getNullValue(In->getType()); - return EmitX86MaskedCompare(CGF, 1, true, { In, Zero }); -} - -static Value *EmitX86Abs(CodeGenFunction &CGF, ArrayRef<Value *> Ops) { - - llvm::Type *Ty = Ops[0]->getType(); - Value *Zero = llvm::Constant::getNullValue(Ty); - Value *Sub = CGF.Builder.CreateSub(Zero, Ops[0]); - Value *Cmp = CGF.Builder.CreateICmp(ICmpInst::ICMP_SGT, Ops[0], Zero); - Value *Res = CGF.Builder.CreateSelect(Cmp, Ops[0], Sub); - return Res; -} - -static Value *EmitX86MinMax(CodeGenFunction &CGF, ICmpInst::Predicate Pred, - ArrayRef<Value *> Ops) { - Value *Cmp = CGF.Builder.CreateICmp(Pred, Ops[0], Ops[1]); - Value *Res = CGF.Builder.CreateSelect(Cmp, Ops[0], Ops[1]); - - assert(Ops.size() == 2); - return Res; -} - -// Lowers X86 FMA intrinsics to IR. -static Value *EmitX86FMAExpr(CodeGenFunction &CGF, ArrayRef<Value *> Ops, - unsigned BuiltinID, bool IsAddSub) { - - bool Subtract = false; - Intrinsic::ID IID = Intrinsic::not_intrinsic; - switch (BuiltinID) { - default: break; - case clang::X86::BI__builtin_ia32_vfmsubps512_mask3: - Subtract = true; - LLVM_FALLTHROUGH; - case clang::X86::BI__builtin_ia32_vfmaddps512_mask: - case clang::X86::BI__builtin_ia32_vfmaddps512_maskz: - case clang::X86::BI__builtin_ia32_vfmaddps512_mask3: - IID = llvm::Intrinsic::x86_avx512_vfmadd_ps_512; break; - case clang::X86::BI__builtin_ia32_vfmsubpd512_mask3: - Subtract = true; - LLVM_FALLTHROUGH; - case clang::X86::BI__builtin_ia32_vfmaddpd512_mask: - case clang::X86::BI__builtin_ia32_vfmaddpd512_maskz: - case clang::X86::BI__builtin_ia32_vfmaddpd512_mask3: - IID = llvm::Intrinsic::x86_avx512_vfmadd_pd_512; break; - case clang::X86::BI__builtin_ia32_vfmsubaddps512_mask3: - Subtract = true; - LLVM_FALLTHROUGH; - case clang::X86::BI__builtin_ia32_vfmaddsubps512_mask: - case clang::X86::BI__builtin_ia32_vfmaddsubps512_maskz: - case clang::X86::BI__builtin_ia32_vfmaddsubps512_mask3: - IID = llvm::Intrinsic::x86_avx512_vfmaddsub_ps_512; - break; - case clang::X86::BI__builtin_ia32_vfmsubaddpd512_mask3: - Subtract = true; - LLVM_FALLTHROUGH; - case clang::X86::BI__builtin_ia32_vfmaddsubpd512_mask: - case clang::X86::BI__builtin_ia32_vfmaddsubpd512_maskz: - case clang::X86::BI__builtin_ia32_vfmaddsubpd512_mask3: - IID = llvm::Intrinsic::x86_avx512_vfmaddsub_pd_512; - break; - } - - Value *A = Ops[0]; - Value *B = Ops[1]; - Value *C = Ops[2]; - - if (Subtract) - C = CGF.Builder.CreateFNeg(C); - - Value *Res; - - // Only handle in case of _MM_FROUND_CUR_DIRECTION/4 (no rounding). - if (IID != Intrinsic::not_intrinsic && - cast<llvm::ConstantInt>(Ops.back())->getZExtValue() != (uint64_t)4) { - Function *Intr = CGF.CGM.getIntrinsic(IID); - Res = CGF.Builder.CreateCall(Intr, {A, B, C, Ops.back() }); - } else { - llvm::Type *Ty = A->getType(); - Function *FMA = CGF.CGM.getIntrinsic(Intrinsic::fma, Ty); - Res = CGF.Builder.CreateCall(FMA, {A, B, C} ); - - if (IsAddSub) { - // Negate even elts in C using a mask. - unsigned NumElts = Ty->getVectorNumElements(); - SmallVector<uint32_t, 16> Indices(NumElts); - for (unsigned i = 0; i != NumElts; ++i) - Indices[i] = i + (i % 2) * NumElts; - - Value *NegC = CGF.Builder.CreateFNeg(C); - Value *FMSub = CGF.Builder.CreateCall(FMA, {A, B, NegC} ); - Res = CGF.Builder.CreateShuffleVector(FMSub, Res, Indices); - } - } - - // Handle any required masking. - Value *MaskFalseVal = nullptr; - switch (BuiltinID) { - case clang::X86::BI__builtin_ia32_vfmaddps512_mask: - case clang::X86::BI__builtin_ia32_vfmaddpd512_mask: - case clang::X86::BI__builtin_ia32_vfmaddsubps512_mask: - case clang::X86::BI__builtin_ia32_vfmaddsubpd512_mask: - MaskFalseVal = Ops[0]; - break; - case clang::X86::BI__builtin_ia32_vfmaddps512_maskz: - case clang::X86::BI__builtin_ia32_vfmaddpd512_maskz: - case clang::X86::BI__builtin_ia32_vfmaddsubps512_maskz: - case clang::X86::BI__builtin_ia32_vfmaddsubpd512_maskz: - MaskFalseVal = Constant::getNullValue(Ops[0]->getType()); - break; - case clang::X86::BI__builtin_ia32_vfmsubps512_mask3: - case clang::X86::BI__builtin_ia32_vfmaddps512_mask3: - case clang::X86::BI__builtin_ia32_vfmsubpd512_mask3: - case clang::X86::BI__builtin_ia32_vfmaddpd512_mask3: - case clang::X86::BI__builtin_ia32_vfmsubaddps512_mask3: - case clang::X86::BI__builtin_ia32_vfmaddsubps512_mask3: - case clang::X86::BI__builtin_ia32_vfmsubaddpd512_mask3: - case clang::X86::BI__builtin_ia32_vfmaddsubpd512_mask3: - MaskFalseVal = Ops[2]; - break; - } - - if (MaskFalseVal) - return EmitX86Select(CGF, Ops[3], Res, MaskFalseVal); - - return Res; -} - -static Value * -EmitScalarFMAExpr(CodeGenFunction &CGF, MutableArrayRef<Value *> Ops, - Value *Upper, bool ZeroMask = false, unsigned PTIdx = 0, - bool NegAcc = false) { - unsigned Rnd = 4; - if (Ops.size() > 4) - Rnd = cast<llvm::ConstantInt>(Ops[4])->getZExtValue(); - - if (NegAcc) - Ops[2] = CGF.Builder.CreateFNeg(Ops[2]); - - Ops[0] = CGF.Builder.CreateExtractElement(Ops[0], (uint64_t)0); - Ops[1] = CGF.Builder.CreateExtractElement(Ops[1], (uint64_t)0); - Ops[2] = CGF.Builder.CreateExtractElement(Ops[2], (uint64_t)0); - Value *Res; - if (Rnd != 4) { - Intrinsic::ID IID = Ops[0]->getType()->getPrimitiveSizeInBits() == 32 ? - Intrinsic::x86_avx512_vfmadd_f32 : - Intrinsic::x86_avx512_vfmadd_f64; - Res = CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(IID), - {Ops[0], Ops[1], Ops[2], Ops[4]}); - } else { - Function *FMA = CGF.CGM.getIntrinsic(Intrinsic::fma, Ops[0]->getType()); - Res = CGF.Builder.CreateCall(FMA, Ops.slice(0, 3)); - } - // If we have more than 3 arguments, we need to do masking. - if (Ops.size() > 3) { - Value *PassThru = ZeroMask ? Constant::getNullValue(Res->getType()) - : Ops[PTIdx]; - - // If we negated the accumulator and the its the PassThru value we need to - // bypass the negate. Conveniently Upper should be the same thing in this - // case. - if (NegAcc && PTIdx == 2) - PassThru = CGF.Builder.CreateExtractElement(Upper, (uint64_t)0); - - Res = EmitX86ScalarSelect(CGF, Ops[3], Res, PassThru); - } - return CGF.Builder.CreateInsertElement(Upper, Res, (uint64_t)0); -} - -static Value *EmitX86Muldq(CodeGenFunction &CGF, bool IsSigned, - ArrayRef<Value *> Ops) { - llvm::Type *Ty = Ops[0]->getType(); - // Arguments have a vXi32 type so cast to vXi64. - Ty = llvm::VectorType::get(CGF.Int64Ty, - Ty->getPrimitiveSizeInBits() / 64); - Value *LHS = CGF.Builder.CreateBitCast(Ops[0], Ty); - Value *RHS = CGF.Builder.CreateBitCast(Ops[1], Ty); - - if (IsSigned) { - // Shift left then arithmetic shift right. - Constant *ShiftAmt = ConstantInt::get(Ty, 32); - LHS = CGF.Builder.CreateShl(LHS, ShiftAmt); - LHS = CGF.Builder.CreateAShr(LHS, ShiftAmt); - RHS = CGF.Builder.CreateShl(RHS, ShiftAmt); - RHS = CGF.Builder.CreateAShr(RHS, ShiftAmt); - } else { - // Clear the upper bits. - Constant *Mask = ConstantInt::get(Ty, 0xffffffff); - LHS = CGF.Builder.CreateAnd(LHS, Mask); - RHS = CGF.Builder.CreateAnd(RHS, Mask); - } - - return CGF.Builder.CreateMul(LHS, RHS); -} - -// Emit a masked pternlog intrinsic. This only exists because the header has to -// use a macro and we aren't able to pass the input argument to a pternlog -// builtin and a select builtin without evaluating it twice. -static Value *EmitX86Ternlog(CodeGenFunction &CGF, bool ZeroMask, - ArrayRef<Value *> Ops) { - llvm::Type *Ty = Ops[0]->getType(); - - unsigned VecWidth = Ty->getPrimitiveSizeInBits(); - unsigned EltWidth = Ty->getScalarSizeInBits(); - Intrinsic::ID IID; - if (VecWidth == 128 && EltWidth == 32) - IID = Intrinsic::x86_avx512_pternlog_d_128; - else if (VecWidth == 256 && EltWidth == 32) - IID = Intrinsic::x86_avx512_pternlog_d_256; - else if (VecWidth == 512 && EltWidth == 32) - IID = Intrinsic::x86_avx512_pternlog_d_512; - else if (VecWidth == 128 && EltWidth == 64) - IID = Intrinsic::x86_avx512_pternlog_q_128; - else if (VecWidth == 256 && EltWidth == 64) - IID = Intrinsic::x86_avx512_pternlog_q_256; - else if (VecWidth == 512 && EltWidth == 64) - IID = Intrinsic::x86_avx512_pternlog_q_512; - else - llvm_unreachable("Unexpected intrinsic"); - - Value *Ternlog = CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(IID), - Ops.drop_back()); - Value *PassThru = ZeroMask ? ConstantAggregateZero::get(Ty) : Ops[0]; - return EmitX86Select(CGF, Ops[4], Ternlog, PassThru); -} - -static Value *EmitX86SExtMask(CodeGenFunction &CGF, Value *Op, - llvm::Type *DstTy) { - unsigned NumberOfElements = DstTy->getVectorNumElements(); - Value *Mask = getMaskVecValue(CGF, Op, NumberOfElements); - return CGF.Builder.CreateSExt(Mask, DstTy, "vpmovm2"); -} - -// Emit addition or subtraction with signed/unsigned saturation. -static Value *EmitX86AddSubSatExpr(CodeGenFunction &CGF, - ArrayRef<Value *> Ops, bool IsSigned, - bool IsAddition) { - Intrinsic::ID IID = - IsSigned ? (IsAddition ? Intrinsic::sadd_sat : Intrinsic::ssub_sat) - : (IsAddition ? Intrinsic::uadd_sat : Intrinsic::usub_sat); - llvm::Function *F = CGF.CGM.getIntrinsic(IID, Ops[0]->getType()); - return CGF.Builder.CreateCall(F, {Ops[0], Ops[1]}); -} - -Value *CodeGenFunction::EmitX86CpuIs(const CallExpr *E) { - const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts(); - StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString(); - return EmitX86CpuIs(CPUStr); -} - -Value *CodeGenFunction::EmitX86CpuIs(StringRef CPUStr) { - - llvm::Type *Int32Ty = Builder.getInt32Ty(); - - // Matching the struct layout from the compiler-rt/libgcc structure that is - // filled in: - // unsigned int __cpu_vendor; - // unsigned int __cpu_type; - // unsigned int __cpu_subtype; - // unsigned int __cpu_features[1]; - llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty, Int32Ty, - llvm::ArrayType::get(Int32Ty, 1)); - - // Grab the global __cpu_model. - llvm::Constant *CpuModel = CGM.CreateRuntimeVariable(STy, "__cpu_model"); - cast<llvm::GlobalValue>(CpuModel)->setDSOLocal(true); - - // Calculate the index needed to access the correct field based on the - // range. Also adjust the expected value. - unsigned Index; - unsigned Value; - std::tie(Index, Value) = StringSwitch<std::pair<unsigned, unsigned>>(CPUStr) -#define X86_VENDOR(ENUM, STRING) \ - .Case(STRING, {0u, static_cast<unsigned>(llvm::X86::ENUM)}) -#define X86_CPU_TYPE_COMPAT_WITH_ALIAS(ARCHNAME, ENUM, STR, ALIAS) \ - .Cases(STR, ALIAS, {1u, static_cast<unsigned>(llvm::X86::ENUM)}) -#define X86_CPU_TYPE_COMPAT(ARCHNAME, ENUM, STR) \ - .Case(STR, {1u, static_cast<unsigned>(llvm::X86::ENUM)}) -#define X86_CPU_SUBTYPE_COMPAT(ARCHNAME, ENUM, STR) \ - .Case(STR, {2u, static_cast<unsigned>(llvm::X86::ENUM)}) -#include "llvm/Support/X86TargetParser.def" - .Default({0, 0}); - assert(Value != 0 && "Invalid CPUStr passed to CpuIs"); - - // Grab the appropriate field from __cpu_model. - llvm::Value *Idxs[] = {ConstantInt::get(Int32Ty, 0), - ConstantInt::get(Int32Ty, Index)}; - llvm::Value *CpuValue = Builder.CreateGEP(STy, CpuModel, Idxs); - CpuValue = Builder.CreateAlignedLoad(CpuValue, CharUnits::fromQuantity(4)); - - // Check the value of the field against the requested value. - return Builder.CreateICmpEQ(CpuValue, - llvm::ConstantInt::get(Int32Ty, Value)); -} - -Value *CodeGenFunction::EmitX86CpuSupports(const CallExpr *E) { - const Expr *FeatureExpr = E->getArg(0)->IgnoreParenCasts(); - StringRef FeatureStr = cast<StringLiteral>(FeatureExpr)->getString(); - return EmitX86CpuSupports(FeatureStr); -} - -uint64_t -CodeGenFunction::GetX86CpuSupportsMask(ArrayRef<StringRef> FeatureStrs) { - // Processor features and mapping to processor feature value. - uint64_t FeaturesMask = 0; - for (const StringRef &FeatureStr : FeatureStrs) { - unsigned Feature = - StringSwitch<unsigned>(FeatureStr) -#define X86_FEATURE_COMPAT(VAL, ENUM, STR) .Case(STR, VAL) -#include "llvm/Support/X86TargetParser.def" - ; - FeaturesMask |= (1ULL << Feature); - } - return FeaturesMask; -} - -Value *CodeGenFunction::EmitX86CpuSupports(ArrayRef<StringRef> FeatureStrs) { - return EmitX86CpuSupports(GetX86CpuSupportsMask(FeatureStrs)); -} - -llvm::Value *CodeGenFunction::EmitX86CpuSupports(uint64_t FeaturesMask) { - uint32_t Features1 = Lo_32(FeaturesMask); - uint32_t Features2 = Hi_32(FeaturesMask); - - Value *Result = Builder.getTrue(); - - if (Features1 != 0) { - // Matching the struct layout from the compiler-rt/libgcc structure that is - // filled in: - // unsigned int __cpu_vendor; - // unsigned int __cpu_type; - // unsigned int __cpu_subtype; - // unsigned int __cpu_features[1]; - llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty, Int32Ty, - llvm::ArrayType::get(Int32Ty, 1)); - - // Grab the global __cpu_model. - llvm::Constant *CpuModel = CGM.CreateRuntimeVariable(STy, "__cpu_model"); - cast<llvm::GlobalValue>(CpuModel)->setDSOLocal(true); - - // Grab the first (0th) element from the field __cpu_features off of the - // global in the struct STy. - Value *Idxs[] = {Builder.getInt32(0), Builder.getInt32(3), - Builder.getInt32(0)}; - Value *CpuFeatures = Builder.CreateGEP(STy, CpuModel, Idxs); - Value *Features = - Builder.CreateAlignedLoad(CpuFeatures, CharUnits::fromQuantity(4)); - - // Check the value of the bit corresponding to the feature requested. - Value *Mask = Builder.getInt32(Features1); - Value *Bitset = Builder.CreateAnd(Features, Mask); - Value *Cmp = Builder.CreateICmpEQ(Bitset, Mask); - Result = Builder.CreateAnd(Result, Cmp); - } - - if (Features2 != 0) { - llvm::Constant *CpuFeatures2 = CGM.CreateRuntimeVariable(Int32Ty, - "__cpu_features2"); - cast<llvm::GlobalValue>(CpuFeatures2)->setDSOLocal(true); - - Value *Features = - Builder.CreateAlignedLoad(CpuFeatures2, CharUnits::fromQuantity(4)); - - // Check the value of the bit corresponding to the feature requested. - Value *Mask = Builder.getInt32(Features2); - Value *Bitset = Builder.CreateAnd(Features, Mask); - Value *Cmp = Builder.CreateICmpEQ(Bitset, Mask); - Result = Builder.CreateAnd(Result, Cmp); - } - - return Result; -} - -Value *CodeGenFunction::EmitX86CpuInit() { - llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, - /*Variadic*/ false); - llvm::Constant *Func = CGM.CreateRuntimeFunction(FTy, "__cpu_indicator_init"); - cast<llvm::GlobalValue>(Func)->setDSOLocal(true); - cast<llvm::GlobalValue>(Func)->setDLLStorageClass( - llvm::GlobalValue::DefaultStorageClass); - return Builder.CreateCall(Func); -} - -Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, - const CallExpr *E) { - if (BuiltinID == X86::BI__builtin_cpu_is) - return EmitX86CpuIs(E); - if (BuiltinID == X86::BI__builtin_cpu_supports) - return EmitX86CpuSupports(E); - if (BuiltinID == X86::BI__builtin_cpu_init) - return EmitX86CpuInit(); - - SmallVector<Value*, 4> Ops; - - // Find out if any arguments are required to be integer constant expressions. - unsigned ICEArguments = 0; - ASTContext::GetBuiltinTypeError Error; - getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments); - assert(Error == ASTContext::GE_None && "Should not codegen an error"); - - for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) { - // If this is a normal argument, just emit it as a scalar. - if ((ICEArguments & (1 << i)) == 0) { - Ops.push_back(EmitScalarExpr(E->getArg(i))); - continue; - } - - // If this is required to be a constant, constant fold it so that we know - // that the generated intrinsic gets a ConstantInt. - llvm::APSInt Result; - bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result, getContext()); - assert(IsConst && "Constant arg isn't actually constant?"); (void)IsConst; - Ops.push_back(llvm::ConstantInt::get(getLLVMContext(), Result)); - } - - // These exist so that the builtin that takes an immediate can be bounds - // checked by clang to avoid passing bad immediates to the backend. Since - // AVX has a larger immediate than SSE we would need separate builtins to - // do the different bounds checking. Rather than create a clang specific - // SSE only builtin, this implements eight separate builtins to match gcc - // implementation. - auto getCmpIntrinsicCall = [this, &Ops](Intrinsic::ID ID, unsigned Imm) { - Ops.push_back(llvm::ConstantInt::get(Int8Ty, Imm)); - llvm::Function *F = CGM.getIntrinsic(ID); - return Builder.CreateCall(F, Ops); - }; - - // For the vector forms of FP comparisons, translate the builtins directly to - // IR. - // TODO: The builtins could be removed if the SSE header files used vector - // extension comparisons directly (vector ordered/unordered may need - // additional support via __builtin_isnan()). - auto getVectorFCmpIR = [this, &Ops](CmpInst::Predicate Pred) { - Value *Cmp = Builder.CreateFCmp(Pred, Ops[0], Ops[1]); - llvm::VectorType *FPVecTy = cast<llvm::VectorType>(Ops[0]->getType()); - llvm::VectorType *IntVecTy = llvm::VectorType::getInteger(FPVecTy); - Value *Sext = Builder.CreateSExt(Cmp, IntVecTy); - return Builder.CreateBitCast(Sext, FPVecTy); - }; - - switch (BuiltinID) { - default: return nullptr; - case X86::BI_mm_prefetch: { - Value *Address = Ops[0]; - ConstantInt *C = cast<ConstantInt>(Ops[1]); - Value *RW = ConstantInt::get(Int32Ty, (C->getZExtValue() >> 2) & 0x1); - Value *Locality = ConstantInt::get(Int32Ty, C->getZExtValue() & 0x3); - Value *Data = ConstantInt::get(Int32Ty, 1); - Value *F = CGM.getIntrinsic(Intrinsic::prefetch); - return Builder.CreateCall(F, {Address, RW, Locality, Data}); - } - case X86::BI_mm_clflush: { - return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse2_clflush), - Ops[0]); - } - case X86::BI_mm_lfence: { - return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse2_lfence)); - } - case X86::BI_mm_mfence: { - return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse2_mfence)); - } - case X86::BI_mm_sfence: { - return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_sfence)); - } - case X86::BI_mm_pause: { - return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse2_pause)); - } - case X86::BI__rdtsc: { - return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_rdtsc)); - } - case X86::BI__builtin_ia32_rdtscp: { - Value *Call = Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_rdtscp)); - Builder.CreateDefaultAlignedStore(Builder.CreateExtractValue(Call, 1), - Ops[0]); - return Builder.CreateExtractValue(Call, 0); - } - case X86::BI__builtin_ia32_lzcnt_u16: - case X86::BI__builtin_ia32_lzcnt_u32: - case X86::BI__builtin_ia32_lzcnt_u64: { - Value *F = CGM.getIntrinsic(Intrinsic::ctlz, Ops[0]->getType()); - return Builder.CreateCall(F, {Ops[0], Builder.getInt1(false)}); - } - case X86::BI__builtin_ia32_tzcnt_u16: - case X86::BI__builtin_ia32_tzcnt_u32: - case X86::BI__builtin_ia32_tzcnt_u64: { - Value *F = CGM.getIntrinsic(Intrinsic::cttz, Ops[0]->getType()); - return Builder.CreateCall(F, {Ops[0], Builder.getInt1(false)}); - } - case X86::BI__builtin_ia32_undef128: - case X86::BI__builtin_ia32_undef256: - case X86::BI__builtin_ia32_undef512: - // The x86 definition of "undef" is not the same as the LLVM definition - // (PR32176). We leave optimizing away an unnecessary zero constant to the - // IR optimizer and backend. - // TODO: If we had a "freeze" IR instruction to generate a fixed undef - // value, we should use that here instead of a zero. - return llvm::Constant::getNullValue(ConvertType(E->getType())); - case X86::BI__builtin_ia32_vec_init_v8qi: - case X86::BI__builtin_ia32_vec_init_v4hi: - case X86::BI__builtin_ia32_vec_init_v2si: - return Builder.CreateBitCast(BuildVector(Ops), - llvm::Type::getX86_MMXTy(getLLVMContext())); - case X86::BI__builtin_ia32_vec_ext_v2si: - case X86::BI__builtin_ia32_vec_ext_v16qi: - case X86::BI__builtin_ia32_vec_ext_v8hi: - case X86::BI__builtin_ia32_vec_ext_v4si: - case X86::BI__builtin_ia32_vec_ext_v4sf: - case X86::BI__builtin_ia32_vec_ext_v2di: - case X86::BI__builtin_ia32_vec_ext_v32qi: - case X86::BI__builtin_ia32_vec_ext_v16hi: - case X86::BI__builtin_ia32_vec_ext_v8si: - case X86::BI__builtin_ia32_vec_ext_v4di: { - unsigned NumElts = Ops[0]->getType()->getVectorNumElements(); - uint64_t Index = cast<ConstantInt>(Ops[1])->getZExtValue(); - Index &= NumElts - 1; - // These builtins exist so we can ensure the index is an ICE and in range. - // Otherwise we could just do this in the header file. - return Builder.CreateExtractElement(Ops[0], Index); - } - case X86::BI__builtin_ia32_vec_set_v16qi: - case X86::BI__builtin_ia32_vec_set_v8hi: - case X86::BI__builtin_ia32_vec_set_v4si: - case X86::BI__builtin_ia32_vec_set_v2di: - case X86::BI__builtin_ia32_vec_set_v32qi: - case X86::BI__builtin_ia32_vec_set_v16hi: - case X86::BI__builtin_ia32_vec_set_v8si: - case X86::BI__builtin_ia32_vec_set_v4di: { - unsigned NumElts = Ops[0]->getType()->getVectorNumElements(); - unsigned Index = cast<ConstantInt>(Ops[2])->getZExtValue(); - Index &= NumElts - 1; - // These builtins exist so we can ensure the index is an ICE and in range. - // Otherwise we could just do this in the header file. - return Builder.CreateInsertElement(Ops[0], Ops[1], Index); - } - case X86::BI_mm_setcsr: - case X86::BI__builtin_ia32_ldmxcsr: { - Address Tmp = CreateMemTemp(E->getArg(0)->getType()); - Builder.CreateStore(Ops[0], Tmp); - return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_ldmxcsr), - Builder.CreateBitCast(Tmp.getPointer(), Int8PtrTy)); - } - case X86::BI_mm_getcsr: - case X86::BI__builtin_ia32_stmxcsr: { - Address Tmp = CreateMemTemp(E->getType()); - Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_stmxcsr), - Builder.CreateBitCast(Tmp.getPointer(), Int8PtrTy)); - return Builder.CreateLoad(Tmp, "stmxcsr"); - } - case X86::BI__builtin_ia32_xsave: - case X86::BI__builtin_ia32_xsave64: - case X86::BI__builtin_ia32_xrstor: - case X86::BI__builtin_ia32_xrstor64: - case X86::BI__builtin_ia32_xsaveopt: - case X86::BI__builtin_ia32_xsaveopt64: - case X86::BI__builtin_ia32_xrstors: - case X86::BI__builtin_ia32_xrstors64: - case X86::BI__builtin_ia32_xsavec: - case X86::BI__builtin_ia32_xsavec64: - case X86::BI__builtin_ia32_xsaves: - case X86::BI__builtin_ia32_xsaves64: { - Intrinsic::ID ID; -#define INTRINSIC_X86_XSAVE_ID(NAME) \ - case X86::BI__builtin_ia32_##NAME: \ - ID = Intrinsic::x86_##NAME; \ - break - switch (BuiltinID) { - default: llvm_unreachable("Unsupported intrinsic!"); - INTRINSIC_X86_XSAVE_ID(xsave); - INTRINSIC_X86_XSAVE_ID(xsave64); - INTRINSIC_X86_XSAVE_ID(xrstor); - INTRINSIC_X86_XSAVE_ID(xrstor64); - INTRINSIC_X86_XSAVE_ID(xsaveopt); - INTRINSIC_X86_XSAVE_ID(xsaveopt64); - INTRINSIC_X86_XSAVE_ID(xrstors); - INTRINSIC_X86_XSAVE_ID(xrstors64); - INTRINSIC_X86_XSAVE_ID(xsavec); - INTRINSIC_X86_XSAVE_ID(xsavec64); - INTRINSIC_X86_XSAVE_ID(xsaves); - INTRINSIC_X86_XSAVE_ID(xsaves64); - } -#undef INTRINSIC_X86_XSAVE_ID - Value *Mhi = Builder.CreateTrunc( - Builder.CreateLShr(Ops[1], ConstantInt::get(Int64Ty, 32)), Int32Ty); - Value *Mlo = Builder.CreateTrunc(Ops[1], Int32Ty); - Ops[1] = Mhi; - Ops.push_back(Mlo); - return Builder.CreateCall(CGM.getIntrinsic(ID), Ops); - } - case X86::BI__builtin_ia32_storedqudi128_mask: - case X86::BI__builtin_ia32_storedqusi128_mask: - case X86::BI__builtin_ia32_storedquhi128_mask: - case X86::BI__builtin_ia32_storedquqi128_mask: - case X86::BI__builtin_ia32_storeupd128_mask: - case X86::BI__builtin_ia32_storeups128_mask: - case X86::BI__builtin_ia32_storedqudi256_mask: - case X86::BI__builtin_ia32_storedqusi256_mask: - case X86::BI__builtin_ia32_storedquhi256_mask: - case X86::BI__builtin_ia32_storedquqi256_mask: - case X86::BI__builtin_ia32_storeupd256_mask: - case X86::BI__builtin_ia32_storeups256_mask: - case X86::BI__builtin_ia32_storedqudi512_mask: - case X86::BI__builtin_ia32_storedqusi512_mask: - case X86::BI__builtin_ia32_storedquhi512_mask: - case X86::BI__builtin_ia32_storedquqi512_mask: - case X86::BI__builtin_ia32_storeupd512_mask: - case X86::BI__builtin_ia32_storeups512_mask: - return EmitX86MaskedStore(*this, Ops, 1); - - case X86::BI__builtin_ia32_storess128_mask: - case X86::BI__builtin_ia32_storesd128_mask: { - return EmitX86MaskedStore(*this, Ops, 1); - } - case X86::BI__builtin_ia32_vpopcntb_128: - case X86::BI__builtin_ia32_vpopcntd_128: - case X86::BI__builtin_ia32_vpopcntq_128: - case X86::BI__builtin_ia32_vpopcntw_128: - case X86::BI__builtin_ia32_vpopcntb_256: - case X86::BI__builtin_ia32_vpopcntd_256: - case X86::BI__builtin_ia32_vpopcntq_256: - case X86::BI__builtin_ia32_vpopcntw_256: - case X86::BI__builtin_ia32_vpopcntb_512: - case X86::BI__builtin_ia32_vpopcntd_512: - case X86::BI__builtin_ia32_vpopcntq_512: - case X86::BI__builtin_ia32_vpopcntw_512: { - llvm::Type *ResultType = ConvertType(E->getType()); - llvm::Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ResultType); - return Builder.CreateCall(F, Ops); - } - case X86::BI__builtin_ia32_cvtmask2b128: - case X86::BI__builtin_ia32_cvtmask2b256: - case X86::BI__builtin_ia32_cvtmask2b512: - case X86::BI__builtin_ia32_cvtmask2w128: - case X86::BI__builtin_ia32_cvtmask2w256: - case X86::BI__builtin_ia32_cvtmask2w512: - case X86::BI__builtin_ia32_cvtmask2d128: - case X86::BI__builtin_ia32_cvtmask2d256: - case X86::BI__builtin_ia32_cvtmask2d512: - case X86::BI__builtin_ia32_cvtmask2q128: - case X86::BI__builtin_ia32_cvtmask2q256: - case X86::BI__builtin_ia32_cvtmask2q512: - return EmitX86SExtMask(*this, Ops[0], ConvertType(E->getType())); - - case X86::BI__builtin_ia32_cvtb2mask128: - case X86::BI__builtin_ia32_cvtb2mask256: - case X86::BI__builtin_ia32_cvtb2mask512: - case X86::BI__builtin_ia32_cvtw2mask128: - case X86::BI__builtin_ia32_cvtw2mask256: - case X86::BI__builtin_ia32_cvtw2mask512: - case X86::BI__builtin_ia32_cvtd2mask128: - case X86::BI__builtin_ia32_cvtd2mask256: - case X86::BI__builtin_ia32_cvtd2mask512: - case X86::BI__builtin_ia32_cvtq2mask128: - case X86::BI__builtin_ia32_cvtq2mask256: - case X86::BI__builtin_ia32_cvtq2mask512: - return EmitX86ConvertToMask(*this, Ops[0]); - - case X86::BI__builtin_ia32_vfmaddss3: - case X86::BI__builtin_ia32_vfmaddsd3: - case X86::BI__builtin_ia32_vfmaddss3_mask: - case X86::BI__builtin_ia32_vfmaddsd3_mask: - return EmitScalarFMAExpr(*this, Ops, Ops[0]); - case X86::BI__builtin_ia32_vfmaddss: - case X86::BI__builtin_ia32_vfmaddsd: - return EmitScalarFMAExpr(*this, Ops, - Constant::getNullValue(Ops[0]->getType())); - case X86::BI__builtin_ia32_vfmaddss3_maskz: - case X86::BI__builtin_ia32_vfmaddsd3_maskz: - return EmitScalarFMAExpr(*this, Ops, Ops[0], /*ZeroMask*/true); - case X86::BI__builtin_ia32_vfmaddss3_mask3: - case X86::BI__builtin_ia32_vfmaddsd3_mask3: - return EmitScalarFMAExpr(*this, Ops, Ops[2], /*ZeroMask*/false, 2); - case X86::BI__builtin_ia32_vfmsubss3_mask3: - case X86::BI__builtin_ia32_vfmsubsd3_mask3: - return EmitScalarFMAExpr(*this, Ops, Ops[2], /*ZeroMask*/false, 2, - /*NegAcc*/true); - case X86::BI__builtin_ia32_vfmaddps: - case X86::BI__builtin_ia32_vfmaddpd: - case X86::BI__builtin_ia32_vfmaddps256: - case X86::BI__builtin_ia32_vfmaddpd256: - case X86::BI__builtin_ia32_vfmaddps512_mask: - case X86::BI__builtin_ia32_vfmaddps512_maskz: - case X86::BI__builtin_ia32_vfmaddps512_mask3: - case X86::BI__builtin_ia32_vfmsubps512_mask3: - case X86::BI__builtin_ia32_vfmaddpd512_mask: - case X86::BI__builtin_ia32_vfmaddpd512_maskz: - case X86::BI__builtin_ia32_vfmaddpd512_mask3: - case X86::BI__builtin_ia32_vfmsubpd512_mask3: - return EmitX86FMAExpr(*this, Ops, BuiltinID, /*IsAddSub*/false); - case X86::BI__builtin_ia32_vfmaddsubps: - case X86::BI__builtin_ia32_vfmaddsubpd: - case X86::BI__builtin_ia32_vfmaddsubps256: - case X86::BI__builtin_ia32_vfmaddsubpd256: - case X86::BI__builtin_ia32_vfmaddsubps512_mask: - case X86::BI__builtin_ia32_vfmaddsubps512_maskz: - case X86::BI__builtin_ia32_vfmaddsubps512_mask3: - case X86::BI__builtin_ia32_vfmsubaddps512_mask3: - case X86::BI__builtin_ia32_vfmaddsubpd512_mask: - case X86::BI__builtin_ia32_vfmaddsubpd512_maskz: - case X86::BI__builtin_ia32_vfmaddsubpd512_mask3: - case X86::BI__builtin_ia32_vfmsubaddpd512_mask3: - return EmitX86FMAExpr(*this, Ops, BuiltinID, /*IsAddSub*/true); - - case X86::BI__builtin_ia32_movdqa32store128_mask: - case X86::BI__builtin_ia32_movdqa64store128_mask: - case X86::BI__builtin_ia32_storeaps128_mask: - case X86::BI__builtin_ia32_storeapd128_mask: - case X86::BI__builtin_ia32_movdqa32store256_mask: - case X86::BI__builtin_ia32_movdqa64store256_mask: - case X86::BI__builtin_ia32_storeaps256_mask: - case X86::BI__builtin_ia32_storeapd256_mask: - case X86::BI__builtin_ia32_movdqa32store512_mask: - case X86::BI__builtin_ia32_movdqa64store512_mask: - case X86::BI__builtin_ia32_storeaps512_mask: - case X86::BI__builtin_ia32_storeapd512_mask: { - unsigned Align = - getContext().getTypeAlignInChars(E->getArg(1)->getType()).getQuantity(); - return EmitX86MaskedStore(*this, Ops, Align); - } - case X86::BI__builtin_ia32_loadups128_mask: - case X86::BI__builtin_ia32_loadups256_mask: - case X86::BI__builtin_ia32_loadups512_mask: - case X86::BI__builtin_ia32_loadupd128_mask: - case X86::BI__builtin_ia32_loadupd256_mask: - case X86::BI__builtin_ia32_loadupd512_mask: - case X86::BI__builtin_ia32_loaddquqi128_mask: - case X86::BI__builtin_ia32_loaddquqi256_mask: - case X86::BI__builtin_ia32_loaddquqi512_mask: - case X86::BI__builtin_ia32_loaddquhi128_mask: - case X86::BI__builtin_ia32_loaddquhi256_mask: - case X86::BI__builtin_ia32_loaddquhi512_mask: - case X86::BI__builtin_ia32_loaddqusi128_mask: - case X86::BI__builtin_ia32_loaddqusi256_mask: - case X86::BI__builtin_ia32_loaddqusi512_mask: - case X86::BI__builtin_ia32_loaddqudi128_mask: - case X86::BI__builtin_ia32_loaddqudi256_mask: - case X86::BI__builtin_ia32_loaddqudi512_mask: - return EmitX86MaskedLoad(*this, Ops, 1); - - case X86::BI__builtin_ia32_loadss128_mask: - case X86::BI__builtin_ia32_loadsd128_mask: - return EmitX86MaskedLoad(*this, Ops, 1); - - case X86::BI__builtin_ia32_loadaps128_mask: - case X86::BI__builtin_ia32_loadaps256_mask: - case X86::BI__builtin_ia32_loadaps512_mask: - case X86::BI__builtin_ia32_loadapd128_mask: - case X86::BI__builtin_ia32_loadapd256_mask: - case X86::BI__builtin_ia32_loadapd512_mask: - case X86::BI__builtin_ia32_movdqa32load128_mask: - case X86::BI__builtin_ia32_movdqa32load256_mask: - case X86::BI__builtin_ia32_movdqa32load512_mask: - case X86::BI__builtin_ia32_movdqa64load128_mask: - case X86::BI__builtin_ia32_movdqa64load256_mask: - case X86::BI__builtin_ia32_movdqa64load512_mask: { - unsigned Align = - getContext().getTypeAlignInChars(E->getArg(1)->getType()).getQuantity(); - return EmitX86MaskedLoad(*this, Ops, Align); - } - - case X86::BI__builtin_ia32_expandloaddf128_mask: - case X86::BI__builtin_ia32_expandloaddf256_mask: - case X86::BI__builtin_ia32_expandloaddf512_mask: - case X86::BI__builtin_ia32_expandloadsf128_mask: - case X86::BI__builtin_ia32_expandloadsf256_mask: - case X86::BI__builtin_ia32_expandloadsf512_mask: - case X86::BI__builtin_ia32_expandloaddi128_mask: - case X86::BI__builtin_ia32_expandloaddi256_mask: - case X86::BI__builtin_ia32_expandloaddi512_mask: - case X86::BI__builtin_ia32_expandloadsi128_mask: - case X86::BI__builtin_ia32_expandloadsi256_mask: - case X86::BI__builtin_ia32_expandloadsi512_mask: - case X86::BI__builtin_ia32_expandloadhi128_mask: - case X86::BI__builtin_ia32_expandloadhi256_mask: - case X86::BI__builtin_ia32_expandloadhi512_mask: - case X86::BI__builtin_ia32_expandloadqi128_mask: - case X86::BI__builtin_ia32_expandloadqi256_mask: - case X86::BI__builtin_ia32_expandloadqi512_mask: - return EmitX86ExpandLoad(*this, Ops); - - case X86::BI__builtin_ia32_compressstoredf128_mask: - case X86::BI__builtin_ia32_compressstoredf256_mask: - case X86::BI__builtin_ia32_compressstoredf512_mask: - case X86::BI__builtin_ia32_compressstoresf128_mask: - case X86::BI__builtin_ia32_compressstoresf256_mask: - case X86::BI__builtin_ia32_compressstoresf512_mask: - case X86::BI__builtin_ia32_compressstoredi128_mask: - case X86::BI__builtin_ia32_compressstoredi256_mask: - case X86::BI__builtin_ia32_compressstoredi512_mask: - case X86::BI__builtin_ia32_compressstoresi128_mask: - case X86::BI__builtin_ia32_compressstoresi256_mask: - case X86::BI__builtin_ia32_compressstoresi512_mask: - case X86::BI__builtin_ia32_compressstorehi128_mask: - case X86::BI__builtin_ia32_compressstorehi256_mask: - case X86::BI__builtin_ia32_compressstorehi512_mask: - case X86::BI__builtin_ia32_compressstoreqi128_mask: - case X86::BI__builtin_ia32_compressstoreqi256_mask: - case X86::BI__builtin_ia32_compressstoreqi512_mask: - return EmitX86CompressStore(*this, Ops); - - case X86::BI__builtin_ia32_storehps: - case X86::BI__builtin_ia32_storelps: { - llvm::Type *PtrTy = llvm::PointerType::getUnqual(Int64Ty); - llvm::Type *VecTy = llvm::VectorType::get(Int64Ty, 2); - - // cast val v2i64 - Ops[1] = Builder.CreateBitCast(Ops[1], VecTy, "cast"); - - // extract (0, 1) - unsigned Index = BuiltinID == X86::BI__builtin_ia32_storelps ? 0 : 1; - Ops[1] = Builder.CreateExtractElement(Ops[1], Index, "extract"); - - // cast pointer to i64 & store - Ops[0] = Builder.CreateBitCast(Ops[0], PtrTy); - return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]); - } - case X86::BI__builtin_ia32_vextractf128_pd256: - case X86::BI__builtin_ia32_vextractf128_ps256: - case X86::BI__builtin_ia32_vextractf128_si256: - case X86::BI__builtin_ia32_extract128i256: - case X86::BI__builtin_ia32_extractf64x4_mask: - case X86::BI__builtin_ia32_extractf32x4_mask: - case X86::BI__builtin_ia32_extracti64x4_mask: - case X86::BI__builtin_ia32_extracti32x4_mask: - case X86::BI__builtin_ia32_extractf32x8_mask: - case X86::BI__builtin_ia32_extracti32x8_mask: - case X86::BI__builtin_ia32_extractf32x4_256_mask: - case X86::BI__builtin_ia32_extracti32x4_256_mask: - case X86::BI__builtin_ia32_extractf64x2_256_mask: - case X86::BI__builtin_ia32_extracti64x2_256_mask: - case X86::BI__builtin_ia32_extractf64x2_512_mask: - case X86::BI__builtin_ia32_extracti64x2_512_mask: { - llvm::Type *DstTy = ConvertType(E->getType()); - unsigned NumElts = DstTy->getVectorNumElements(); - unsigned SrcNumElts = Ops[0]->getType()->getVectorNumElements(); - unsigned SubVectors = SrcNumElts / NumElts; - unsigned Index = cast<ConstantInt>(Ops[1])->getZExtValue(); - assert(llvm::isPowerOf2_32(SubVectors) && "Expected power of 2 subvectors"); - Index &= SubVectors - 1; // Remove any extra bits. - Index *= NumElts; - - uint32_t Indices[16]; - for (unsigned i = 0; i != NumElts; ++i) - Indices[i] = i + Index; - - Value *Res = Builder.CreateShuffleVector(Ops[0], - UndefValue::get(Ops[0]->getType()), - makeArrayRef(Indices, NumElts), - "extract"); - - if (Ops.size() == 4) - Res = EmitX86Select(*this, Ops[3], Res, Ops[2]); - - return Res; - } - case X86::BI__builtin_ia32_vinsertf128_pd256: - case X86::BI__builtin_ia32_vinsertf128_ps256: - case X86::BI__builtin_ia32_vinsertf128_si256: - case X86::BI__builtin_ia32_insert128i256: - case X86::BI__builtin_ia32_insertf64x4: - case X86::BI__builtin_ia32_insertf32x4: - case X86::BI__builtin_ia32_inserti64x4: - case X86::BI__builtin_ia32_inserti32x4: - case X86::BI__builtin_ia32_insertf32x8: - case X86::BI__builtin_ia32_inserti32x8: - case X86::BI__builtin_ia32_insertf32x4_256: - case X86::BI__builtin_ia32_inserti32x4_256: - case X86::BI__builtin_ia32_insertf64x2_256: - case X86::BI__builtin_ia32_inserti64x2_256: - case X86::BI__builtin_ia32_insertf64x2_512: - case X86::BI__builtin_ia32_inserti64x2_512: { - unsigned DstNumElts = Ops[0]->getType()->getVectorNumElements(); - unsigned SrcNumElts = Ops[1]->getType()->getVectorNumElements(); - unsigned SubVectors = DstNumElts / SrcNumElts; - unsigned Index = cast<ConstantInt>(Ops[2])->getZExtValue(); - assert(llvm::isPowerOf2_32(SubVectors) && "Expected power of 2 subvectors"); - Index &= SubVectors - 1; // Remove any extra bits. - Index *= SrcNumElts; - - uint32_t Indices[16]; - for (unsigned i = 0; i != DstNumElts; ++i) - Indices[i] = (i >= SrcNumElts) ? SrcNumElts + (i % SrcNumElts) : i; - - Value *Op1 = Builder.CreateShuffleVector(Ops[1], - UndefValue::get(Ops[1]->getType()), - makeArrayRef(Indices, DstNumElts), - "widen"); - - for (unsigned i = 0; i != DstNumElts; ++i) { - if (i >= Index && i < (Index + SrcNumElts)) - Indices[i] = (i - Index) + DstNumElts; - else - Indices[i] = i; - } - - return Builder.CreateShuffleVector(Ops[0], Op1, - makeArrayRef(Indices, DstNumElts), - "insert"); - } - case X86::BI__builtin_ia32_pmovqd512_mask: - case X86::BI__builtin_ia32_pmovwb512_mask: { - Value *Res = Builder.CreateTrunc(Ops[0], Ops[1]->getType()); - return EmitX86Select(*this, Ops[2], Res, Ops[1]); - } - case X86::BI__builtin_ia32_pmovdb512_mask: - case X86::BI__builtin_ia32_pmovdw512_mask: - case X86::BI__builtin_ia32_pmovqw512_mask: { - if (const auto *C = dyn_cast<Constant>(Ops[2])) - if (C->isAllOnesValue()) - return Builder.CreateTrunc(Ops[0], Ops[1]->getType()); - - Intrinsic::ID IID; - switch (BuiltinID) { - default: llvm_unreachable("Unsupported intrinsic!"); - case X86::BI__builtin_ia32_pmovdb512_mask: - IID = Intrinsic::x86_avx512_mask_pmov_db_512; - break; - case X86::BI__builtin_ia32_pmovdw512_mask: - IID = Intrinsic::x86_avx512_mask_pmov_dw_512; - break; - case X86::BI__builtin_ia32_pmovqw512_mask: - IID = Intrinsic::x86_avx512_mask_pmov_qw_512; - break; - } - - Function *Intr = CGM.getIntrinsic(IID); - return Builder.CreateCall(Intr, Ops); - } - case X86::BI__builtin_ia32_pblendw128: - case X86::BI__builtin_ia32_blendpd: - case X86::BI__builtin_ia32_blendps: - case X86::BI__builtin_ia32_blendpd256: - case X86::BI__builtin_ia32_blendps256: - case X86::BI__builtin_ia32_pblendw256: - case X86::BI__builtin_ia32_pblendd128: - case X86::BI__builtin_ia32_pblendd256: { - unsigned NumElts = Ops[0]->getType()->getVectorNumElements(); - unsigned Imm = cast<llvm::ConstantInt>(Ops[2])->getZExtValue(); - - uint32_t Indices[16]; - // If there are more than 8 elements, the immediate is used twice so make - // sure we handle that. - for (unsigned i = 0; i != NumElts; ++i) - Indices[i] = ((Imm >> (i % 8)) & 0x1) ? NumElts + i : i; - - return Builder.CreateShuffleVector(Ops[0], Ops[1], - makeArrayRef(Indices, NumElts), - "blend"); - } - case X86::BI__builtin_ia32_pshuflw: - case X86::BI__builtin_ia32_pshuflw256: - case X86::BI__builtin_ia32_pshuflw512: { - uint32_t Imm = cast<llvm::ConstantInt>(Ops[1])->getZExtValue(); - llvm::Type *Ty = Ops[0]->getType(); - unsigned NumElts = Ty->getVectorNumElements(); - - // Splat the 8-bits of immediate 4 times to help the loop wrap around. - Imm = (Imm & 0xff) * 0x01010101; - - uint32_t Indices[32]; - for (unsigned l = 0; l != NumElts; l += 8) { - for (unsigned i = 0; i != 4; ++i) { - Indices[l + i] = l + (Imm & 3); - Imm >>= 2; - } - for (unsigned i = 4; i != 8; ++i) - Indices[l + i] = l + i; - } - - return Builder.CreateShuffleVector(Ops[0], UndefValue::get(Ty), - makeArrayRef(Indices, NumElts), - "pshuflw"); - } - case X86::BI__builtin_ia32_pshufhw: - case X86::BI__builtin_ia32_pshufhw256: - case X86::BI__builtin_ia32_pshufhw512: { - uint32_t Imm = cast<llvm::ConstantInt>(Ops[1])->getZExtValue(); - llvm::Type *Ty = Ops[0]->getType(); - unsigned NumElts = Ty->getVectorNumElements(); - - // Splat the 8-bits of immediate 4 times to help the loop wrap around. - Imm = (Imm & 0xff) * 0x01010101; - - uint32_t Indices[32]; - for (unsigned l = 0; l != NumElts; l += 8) { - for (unsigned i = 0; i != 4; ++i) - Indices[l + i] = l + i; - for (unsigned i = 4; i != 8; ++i) { - Indices[l + i] = l + 4 + (Imm & 3); - Imm >>= 2; - } - } - - return Builder.CreateShuffleVector(Ops[0], UndefValue::get(Ty), - makeArrayRef(Indices, NumElts), - "pshufhw"); - } - case X86::BI__builtin_ia32_pshufd: - case X86::BI__builtin_ia32_pshufd256: - case X86::BI__builtin_ia32_pshufd512: - case X86::BI__builtin_ia32_vpermilpd: - case X86::BI__builtin_ia32_vpermilps: - case X86::BI__builtin_ia32_vpermilpd256: - case X86::BI__builtin_ia32_vpermilps256: - case X86::BI__builtin_ia32_vpermilpd512: - case X86::BI__builtin_ia32_vpermilps512: { - uint32_t Imm = cast<llvm::ConstantInt>(Ops[1])->getZExtValue(); - llvm::Type *Ty = Ops[0]->getType(); - unsigned NumElts = Ty->getVectorNumElements(); - unsigned NumLanes = Ty->getPrimitiveSizeInBits() / 128; - unsigned NumLaneElts = NumElts / NumLanes; - - // Splat the 8-bits of immediate 4 times to help the loop wrap around. - Imm = (Imm & 0xff) * 0x01010101; - - uint32_t Indices[16]; - for (unsigned l = 0; l != NumElts; l += NumLaneElts) { - for (unsigned i = 0; i != NumLaneElts; ++i) { - Indices[i + l] = (Imm % NumLaneElts) + l; - Imm /= NumLaneElts; - } - } - - return Builder.CreateShuffleVector(Ops[0], UndefValue::get(Ty), - makeArrayRef(Indices, NumElts), - "permil"); - } - case X86::BI__builtin_ia32_shufpd: - case X86::BI__builtin_ia32_shufpd256: - case X86::BI__builtin_ia32_shufpd512: - case X86::BI__builtin_ia32_shufps: - case X86::BI__builtin_ia32_shufps256: - case X86::BI__builtin_ia32_shufps512: { - uint32_t Imm = cast<llvm::ConstantInt>(Ops[2])->getZExtValue(); - llvm::Type *Ty = Ops[0]->getType(); - unsigned NumElts = Ty->getVectorNumElements(); - unsigned NumLanes = Ty->getPrimitiveSizeInBits() / 128; - unsigned NumLaneElts = NumElts / NumLanes; - - // Splat the 8-bits of immediate 4 times to help the loop wrap around. - Imm = (Imm & 0xff) * 0x01010101; - - uint32_t Indices[16]; - for (unsigned l = 0; l != NumElts; l += NumLaneElts) { - for (unsigned i = 0; i != NumLaneElts; ++i) { - unsigned Index = Imm % NumLaneElts; - Imm /= NumLaneElts; - if (i >= (NumLaneElts / 2)) - Index += NumElts; - Indices[l + i] = l + Index; - } - } - - return Builder.CreateShuffleVector(Ops[0], Ops[1], - makeArrayRef(Indices, NumElts), - "shufp"); - } - case X86::BI__builtin_ia32_permdi256: - case X86::BI__builtin_ia32_permdf256: - case X86::BI__builtin_ia32_permdi512: - case X86::BI__builtin_ia32_permdf512: { - unsigned Imm = cast<llvm::ConstantInt>(Ops[1])->getZExtValue(); - llvm::Type *Ty = Ops[0]->getType(); - unsigned NumElts = Ty->getVectorNumElements(); - - // These intrinsics operate on 256-bit lanes of four 64-bit elements. - uint32_t Indices[8]; - for (unsigned l = 0; l != NumElts; l += 4) - for (unsigned i = 0; i != 4; ++i) - Indices[l + i] = l + ((Imm >> (2 * i)) & 0x3); - - return Builder.CreateShuffleVector(Ops[0], UndefValue::get(Ty), - makeArrayRef(Indices, NumElts), - "perm"); - } - case X86::BI__builtin_ia32_palignr128: - case X86::BI__builtin_ia32_palignr256: - case X86::BI__builtin_ia32_palignr512: { - unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue() & 0xff; - - unsigned NumElts = Ops[0]->getType()->getVectorNumElements(); - assert(NumElts % 16 == 0); - - // If palignr is shifting the pair of vectors more than the size of two - // lanes, emit zero. - if (ShiftVal >= 32) - return llvm::Constant::getNullValue(ConvertType(E->getType())); - - // If palignr is shifting the pair of input vectors more than one lane, - // but less than two lanes, convert to shifting in zeroes. - if (ShiftVal > 16) { - ShiftVal -= 16; - Ops[1] = Ops[0]; - Ops[0] = llvm::Constant::getNullValue(Ops[0]->getType()); - } - - uint32_t Indices[64]; - // 256-bit palignr operates on 128-bit lanes so we need to handle that - for (unsigned l = 0; l != NumElts; l += 16) { - for (unsigned i = 0; i != 16; ++i) { - unsigned Idx = ShiftVal + i; - if (Idx >= 16) - Idx += NumElts - 16; // End of lane, switch operand. - Indices[l + i] = Idx + l; - } - } - - return Builder.CreateShuffleVector(Ops[1], Ops[0], - makeArrayRef(Indices, NumElts), - "palignr"); - } - case X86::BI__builtin_ia32_alignd128: - case X86::BI__builtin_ia32_alignd256: - case X86::BI__builtin_ia32_alignd512: - case X86::BI__builtin_ia32_alignq128: - case X86::BI__builtin_ia32_alignq256: - case X86::BI__builtin_ia32_alignq512: { - unsigned NumElts = Ops[0]->getType()->getVectorNumElements(); - unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue() & 0xff; - - // Mask the shift amount to width of two vectors. - ShiftVal &= (2 * NumElts) - 1; - - uint32_t Indices[16]; - for (unsigned i = 0; i != NumElts; ++i) - Indices[i] = i + ShiftVal; - - return Builder.CreateShuffleVector(Ops[1], Ops[0], - makeArrayRef(Indices, NumElts), - "valign"); - } - case X86::BI__builtin_ia32_shuf_f32x4_256: - case X86::BI__builtin_ia32_shuf_f64x2_256: - case X86::BI__builtin_ia32_shuf_i32x4_256: - case X86::BI__builtin_ia32_shuf_i64x2_256: - case X86::BI__builtin_ia32_shuf_f32x4: - case X86::BI__builtin_ia32_shuf_f64x2: - case X86::BI__builtin_ia32_shuf_i32x4: - case X86::BI__builtin_ia32_shuf_i64x2: { - unsigned Imm = cast<llvm::ConstantInt>(Ops[2])->getZExtValue(); - llvm::Type *Ty = Ops[0]->getType(); - unsigned NumElts = Ty->getVectorNumElements(); - unsigned NumLanes = Ty->getPrimitiveSizeInBits() == 512 ? 4 : 2; - unsigned NumLaneElts = NumElts / NumLanes; - - uint32_t Indices[16]; - for (unsigned l = 0; l != NumElts; l += NumLaneElts) { - unsigned Index = (Imm % NumLanes) * NumLaneElts; - Imm /= NumLanes; // Discard the bits we just used. - if (l >= (NumElts / 2)) - Index += NumElts; // Switch to other source. - for (unsigned i = 0; i != NumLaneElts; ++i) { - Indices[l + i] = Index + i; - } - } - - return Builder.CreateShuffleVector(Ops[0], Ops[1], - makeArrayRef(Indices, NumElts), - "shuf"); - } - - case X86::BI__builtin_ia32_vperm2f128_pd256: - case X86::BI__builtin_ia32_vperm2f128_ps256: - case X86::BI__builtin_ia32_vperm2f128_si256: - case X86::BI__builtin_ia32_permti256: { - unsigned Imm = cast<llvm::ConstantInt>(Ops[2])->getZExtValue(); - unsigned NumElts = Ops[0]->getType()->getVectorNumElements(); - - // This takes a very simple approach since there are two lanes and a - // shuffle can have 2 inputs. So we reserve the first input for the first - // lane and the second input for the second lane. This may result in - // duplicate sources, but this can be dealt with in the backend. - - Value *OutOps[2]; - uint32_t Indices[8]; - for (unsigned l = 0; l != 2; ++l) { - // Determine the source for this lane. - if (Imm & (1 << ((l * 4) + 3))) - OutOps[l] = llvm::ConstantAggregateZero::get(Ops[0]->getType()); - else if (Imm & (1 << ((l * 4) + 1))) - OutOps[l] = Ops[1]; - else - OutOps[l] = Ops[0]; - - for (unsigned i = 0; i != NumElts/2; ++i) { - // Start with ith element of the source for this lane. - unsigned Idx = (l * NumElts) + i; - // If bit 0 of the immediate half is set, switch to the high half of - // the source. - if (Imm & (1 << (l * 4))) - Idx += NumElts/2; - Indices[(l * (NumElts/2)) + i] = Idx; - } - } - - return Builder.CreateShuffleVector(OutOps[0], OutOps[1], - makeArrayRef(Indices, NumElts), - "vperm"); - } - - case X86::BI__builtin_ia32_pslldqi128_byteshift: - case X86::BI__builtin_ia32_pslldqi256_byteshift: - case X86::BI__builtin_ia32_pslldqi512_byteshift: { - unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[1])->getZExtValue() & 0xff; - llvm::Type *ResultType = Ops[0]->getType(); - // Builtin type is vXi64 so multiply by 8 to get bytes. - unsigned NumElts = ResultType->getVectorNumElements() * 8; - - // If pslldq is shifting the vector more than 15 bytes, emit zero. - if (ShiftVal >= 16) - return llvm::Constant::getNullValue(ResultType); - - uint32_t Indices[64]; - // 256/512-bit pslldq operates on 128-bit lanes so we need to handle that - for (unsigned l = 0; l != NumElts; l += 16) { - for (unsigned i = 0; i != 16; ++i) { - unsigned Idx = NumElts + i - ShiftVal; - if (Idx < NumElts) Idx -= NumElts - 16; // end of lane, switch operand. - Indices[l + i] = Idx + l; - } - } - - llvm::Type *VecTy = llvm::VectorType::get(Int8Ty, NumElts); - Value *Cast = Builder.CreateBitCast(Ops[0], VecTy, "cast"); - Value *Zero = llvm::Constant::getNullValue(VecTy); - Value *SV = Builder.CreateShuffleVector(Zero, Cast, - makeArrayRef(Indices, NumElts), - "pslldq"); - return Builder.CreateBitCast(SV, Ops[0]->getType(), "cast"); - } - case X86::BI__builtin_ia32_psrldqi128_byteshift: - case X86::BI__builtin_ia32_psrldqi256_byteshift: - case X86::BI__builtin_ia32_psrldqi512_byteshift: { - unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[1])->getZExtValue() & 0xff; - llvm::Type *ResultType = Ops[0]->getType(); - // Builtin type is vXi64 so multiply by 8 to get bytes. - unsigned NumElts = ResultType->getVectorNumElements() * 8; - - // If psrldq is shifting the vector more than 15 bytes, emit zero. - if (ShiftVal >= 16) - return llvm::Constant::getNullValue(ResultType); - - uint32_t Indices[64]; - // 256/512-bit psrldq operates on 128-bit lanes so we need to handle that - for (unsigned l = 0; l != NumElts; l += 16) { - for (unsigned i = 0; i != 16; ++i) { - unsigned Idx = i + ShiftVal; - if (Idx >= 16) Idx += NumElts - 16; // end of lane, switch operand. - Indices[l + i] = Idx + l; - } - } - - llvm::Type *VecTy = llvm::VectorType::get(Int8Ty, NumElts); - Value *Cast = Builder.CreateBitCast(Ops[0], VecTy, "cast"); - Value *Zero = llvm::Constant::getNullValue(VecTy); - Value *SV = Builder.CreateShuffleVector(Cast, Zero, - makeArrayRef(Indices, NumElts), - "psrldq"); - return Builder.CreateBitCast(SV, ResultType, "cast"); - } - case X86::BI__builtin_ia32_kshiftliqi: - case X86::BI__builtin_ia32_kshiftlihi: - case X86::BI__builtin_ia32_kshiftlisi: - case X86::BI__builtin_ia32_kshiftlidi: { - unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[1])->getZExtValue() & 0xff; - unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth(); - - if (ShiftVal >= NumElts) - return llvm::Constant::getNullValue(Ops[0]->getType()); - - Value *In = getMaskVecValue(*this, Ops[0], NumElts); - - uint32_t Indices[64]; - for (unsigned i = 0; i != NumElts; ++i) - Indices[i] = NumElts + i - ShiftVal; - - Value *Zero = llvm::Constant::getNullValue(In->getType()); - Value *SV = Builder.CreateShuffleVector(Zero, In, - makeArrayRef(Indices, NumElts), - "kshiftl"); - return Builder.CreateBitCast(SV, Ops[0]->getType()); - } - case X86::BI__builtin_ia32_kshiftriqi: - case X86::BI__builtin_ia32_kshiftrihi: - case X86::BI__builtin_ia32_kshiftrisi: - case X86::BI__builtin_ia32_kshiftridi: { - unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[1])->getZExtValue() & 0xff; - unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth(); - - if (ShiftVal >= NumElts) - return llvm::Constant::getNullValue(Ops[0]->getType()); - - Value *In = getMaskVecValue(*this, Ops[0], NumElts); - - uint32_t Indices[64]; - for (unsigned i = 0; i != NumElts; ++i) - Indices[i] = i + ShiftVal; - - Value *Zero = llvm::Constant::getNullValue(In->getType()); - Value *SV = Builder.CreateShuffleVector(In, Zero, - makeArrayRef(Indices, NumElts), - "kshiftr"); - return Builder.CreateBitCast(SV, Ops[0]->getType()); - } - case X86::BI__builtin_ia32_movnti: - case X86::BI__builtin_ia32_movnti64: - case X86::BI__builtin_ia32_movntsd: - case X86::BI__builtin_ia32_movntss: { - llvm::MDNode *Node = llvm::MDNode::get( - getLLVMContext(), llvm::ConstantAsMetadata::get(Builder.getInt32(1))); - - Value *Ptr = Ops[0]; - Value *Src = Ops[1]; - - // Extract the 0'th element of the source vector. - if (BuiltinID == X86::BI__builtin_ia32_movntsd || - BuiltinID == X86::BI__builtin_ia32_movntss) - Src = Builder.CreateExtractElement(Src, (uint64_t)0, "extract"); - - // Convert the type of the pointer to a pointer to the stored type. - Value *BC = Builder.CreateBitCast( - Ptr, llvm::PointerType::getUnqual(Src->getType()), "cast"); - - // Unaligned nontemporal store of the scalar value. - StoreInst *SI = Builder.CreateDefaultAlignedStore(Src, BC); - SI->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node); - SI->setAlignment(1); - return SI; - } - // Rotate is a special case of funnel shift - 1st 2 args are the same. - case X86::BI__builtin_ia32_vprotb: - case X86::BI__builtin_ia32_vprotw: - case X86::BI__builtin_ia32_vprotd: - case X86::BI__builtin_ia32_vprotq: - case X86::BI__builtin_ia32_vprotbi: - case X86::BI__builtin_ia32_vprotwi: - case X86::BI__builtin_ia32_vprotdi: - case X86::BI__builtin_ia32_vprotqi: - case X86::BI__builtin_ia32_prold128: - case X86::BI__builtin_ia32_prold256: - case X86::BI__builtin_ia32_prold512: - case X86::BI__builtin_ia32_prolq128: - case X86::BI__builtin_ia32_prolq256: - case X86::BI__builtin_ia32_prolq512: - case X86::BI__builtin_ia32_prolvd128: - case X86::BI__builtin_ia32_prolvd256: - case X86::BI__builtin_ia32_prolvd512: - case X86::BI__builtin_ia32_prolvq128: - case X86::BI__builtin_ia32_prolvq256: - case X86::BI__builtin_ia32_prolvq512: - return EmitX86FunnelShift(*this, Ops[0], Ops[0], Ops[1], false); - case X86::BI__builtin_ia32_prord128: - case X86::BI__builtin_ia32_prord256: - case X86::BI__builtin_ia32_prord512: - case X86::BI__builtin_ia32_prorq128: - case X86::BI__builtin_ia32_prorq256: - case X86::BI__builtin_ia32_prorq512: - case X86::BI__builtin_ia32_prorvd128: - case X86::BI__builtin_ia32_prorvd256: - case X86::BI__builtin_ia32_prorvd512: - case X86::BI__builtin_ia32_prorvq128: - case X86::BI__builtin_ia32_prorvq256: - case X86::BI__builtin_ia32_prorvq512: - return EmitX86FunnelShift(*this, Ops[0], Ops[0], Ops[1], true); - case X86::BI__builtin_ia32_selectb_128: - case X86::BI__builtin_ia32_selectb_256: - case X86::BI__builtin_ia32_selectb_512: - case X86::BI__builtin_ia32_selectw_128: - case X86::BI__builtin_ia32_selectw_256: - case X86::BI__builtin_ia32_selectw_512: - case X86::BI__builtin_ia32_selectd_128: - case X86::BI__builtin_ia32_selectd_256: - case X86::BI__builtin_ia32_selectd_512: - case X86::BI__builtin_ia32_selectq_128: - case X86::BI__builtin_ia32_selectq_256: - case X86::BI__builtin_ia32_selectq_512: - case X86::BI__builtin_ia32_selectps_128: - case X86::BI__builtin_ia32_selectps_256: - case X86::BI__builtin_ia32_selectps_512: - case X86::BI__builtin_ia32_selectpd_128: - case X86::BI__builtin_ia32_selectpd_256: - case X86::BI__builtin_ia32_selectpd_512: - return EmitX86Select(*this, Ops[0], Ops[1], Ops[2]); - case X86::BI__builtin_ia32_selectss_128: - case X86::BI__builtin_ia32_selectsd_128: { - Value *A = Builder.CreateExtractElement(Ops[1], (uint64_t)0); - Value *B = Builder.CreateExtractElement(Ops[2], (uint64_t)0); - A = EmitX86ScalarSelect(*this, Ops[0], A, B); - return Builder.CreateInsertElement(Ops[1], A, (uint64_t)0); - } - case X86::BI__builtin_ia32_cmpb128_mask: - case X86::BI__builtin_ia32_cmpb256_mask: - case X86::BI__builtin_ia32_cmpb512_mask: - case X86::BI__builtin_ia32_cmpw128_mask: - case X86::BI__builtin_ia32_cmpw256_mask: - case X86::BI__builtin_ia32_cmpw512_mask: - case X86::BI__builtin_ia32_cmpd128_mask: - case X86::BI__builtin_ia32_cmpd256_mask: - case X86::BI__builtin_ia32_cmpd512_mask: - case X86::BI__builtin_ia32_cmpq128_mask: - case X86::BI__builtin_ia32_cmpq256_mask: - case X86::BI__builtin_ia32_cmpq512_mask: { - unsigned CC = cast<llvm::ConstantInt>(Ops[2])->getZExtValue() & 0x7; - return EmitX86MaskedCompare(*this, CC, true, Ops); - } - case X86::BI__builtin_ia32_ucmpb128_mask: - case X86::BI__builtin_ia32_ucmpb256_mask: - case X86::BI__builtin_ia32_ucmpb512_mask: - case X86::BI__builtin_ia32_ucmpw128_mask: - case X86::BI__builtin_ia32_ucmpw256_mask: - case X86::BI__builtin_ia32_ucmpw512_mask: - case X86::BI__builtin_ia32_ucmpd128_mask: - case X86::BI__builtin_ia32_ucmpd256_mask: - case X86::BI__builtin_ia32_ucmpd512_mask: - case X86::BI__builtin_ia32_ucmpq128_mask: - case X86::BI__builtin_ia32_ucmpq256_mask: - case X86::BI__builtin_ia32_ucmpq512_mask: { - unsigned CC = cast<llvm::ConstantInt>(Ops[2])->getZExtValue() & 0x7; - return EmitX86MaskedCompare(*this, CC, false, Ops); - } - - case X86::BI__builtin_ia32_kortestcqi: - case X86::BI__builtin_ia32_kortestchi: - case X86::BI__builtin_ia32_kortestcsi: - case X86::BI__builtin_ia32_kortestcdi: { - Value *Or = EmitX86MaskLogic(*this, Instruction::Or, Ops); - Value *C = llvm::Constant::getAllOnesValue(Ops[0]->getType()); - Value *Cmp = Builder.CreateICmpEQ(Or, C); - return Builder.CreateZExt(Cmp, ConvertType(E->getType())); - } - case X86::BI__builtin_ia32_kortestzqi: - case X86::BI__builtin_ia32_kortestzhi: - case X86::BI__builtin_ia32_kortestzsi: - case X86::BI__builtin_ia32_kortestzdi: { - Value *Or = EmitX86MaskLogic(*this, Instruction::Or, Ops); - Value *C = llvm::Constant::getNullValue(Ops[0]->getType()); - Value *Cmp = Builder.CreateICmpEQ(Or, C); - return Builder.CreateZExt(Cmp, ConvertType(E->getType())); - } - - case X86::BI__builtin_ia32_ktestcqi: - case X86::BI__builtin_ia32_ktestzqi: - case X86::BI__builtin_ia32_ktestchi: - case X86::BI__builtin_ia32_ktestzhi: - case X86::BI__builtin_ia32_ktestcsi: - case X86::BI__builtin_ia32_ktestzsi: - case X86::BI__builtin_ia32_ktestcdi: - case X86::BI__builtin_ia32_ktestzdi: { - Intrinsic::ID IID; - switch (BuiltinID) { - default: llvm_unreachable("Unsupported intrinsic!"); - case X86::BI__builtin_ia32_ktestcqi: - IID = Intrinsic::x86_avx512_ktestc_b; - break; - case X86::BI__builtin_ia32_ktestzqi: - IID = Intrinsic::x86_avx512_ktestz_b; - break; - case X86::BI__builtin_ia32_ktestchi: - IID = Intrinsic::x86_avx512_ktestc_w; - break; - case X86::BI__builtin_ia32_ktestzhi: - IID = Intrinsic::x86_avx512_ktestz_w; - break; - case X86::BI__builtin_ia32_ktestcsi: - IID = Intrinsic::x86_avx512_ktestc_d; - break; - case X86::BI__builtin_ia32_ktestzsi: - IID = Intrinsic::x86_avx512_ktestz_d; - break; - case X86::BI__builtin_ia32_ktestcdi: - IID = Intrinsic::x86_avx512_ktestc_q; - break; - case X86::BI__builtin_ia32_ktestzdi: - IID = Intrinsic::x86_avx512_ktestz_q; - break; - } - - unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth(); - Value *LHS = getMaskVecValue(*this, Ops[0], NumElts); - Value *RHS = getMaskVecValue(*this, Ops[1], NumElts); - Function *Intr = CGM.getIntrinsic(IID); - return Builder.CreateCall(Intr, {LHS, RHS}); - } - - case X86::BI__builtin_ia32_kaddqi: - case X86::BI__builtin_ia32_kaddhi: - case X86::BI__builtin_ia32_kaddsi: - case X86::BI__builtin_ia32_kadddi: { - Intrinsic::ID IID; - switch (BuiltinID) { - default: llvm_unreachable("Unsupported intrinsic!"); - case X86::BI__builtin_ia32_kaddqi: - IID = Intrinsic::x86_avx512_kadd_b; - break; - case X86::BI__builtin_ia32_kaddhi: - IID = Intrinsic::x86_avx512_kadd_w; - break; - case X86::BI__builtin_ia32_kaddsi: - IID = Intrinsic::x86_avx512_kadd_d; - break; - case X86::BI__builtin_ia32_kadddi: - IID = Intrinsic::x86_avx512_kadd_q; - break; - } - - unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth(); - Value *LHS = getMaskVecValue(*this, Ops[0], NumElts); - Value *RHS = getMaskVecValue(*this, Ops[1], NumElts); - Function *Intr = CGM.getIntrinsic(IID); - Value *Res = Builder.CreateCall(Intr, {LHS, RHS}); - return Builder.CreateBitCast(Res, Ops[0]->getType()); - } - case X86::BI__builtin_ia32_kandqi: - case X86::BI__builtin_ia32_kandhi: - case X86::BI__builtin_ia32_kandsi: - case X86::BI__builtin_ia32_kanddi: - return EmitX86MaskLogic(*this, Instruction::And, Ops); - case X86::BI__builtin_ia32_kandnqi: - case X86::BI__builtin_ia32_kandnhi: - case X86::BI__builtin_ia32_kandnsi: - case X86::BI__builtin_ia32_kandndi: - return EmitX86MaskLogic(*this, Instruction::And, Ops, true); - case X86::BI__builtin_ia32_korqi: - case X86::BI__builtin_ia32_korhi: - case X86::BI__builtin_ia32_korsi: - case X86::BI__builtin_ia32_kordi: - return EmitX86MaskLogic(*this, Instruction::Or, Ops); - case X86::BI__builtin_ia32_kxnorqi: - case X86::BI__builtin_ia32_kxnorhi: - case X86::BI__builtin_ia32_kxnorsi: - case X86::BI__builtin_ia32_kxnordi: - return EmitX86MaskLogic(*this, Instruction::Xor, Ops, true); - case X86::BI__builtin_ia32_kxorqi: - case X86::BI__builtin_ia32_kxorhi: - case X86::BI__builtin_ia32_kxorsi: - case X86::BI__builtin_ia32_kxordi: - return EmitX86MaskLogic(*this, Instruction::Xor, Ops); - case X86::BI__builtin_ia32_knotqi: - case X86::BI__builtin_ia32_knothi: - case X86::BI__builtin_ia32_knotsi: - case X86::BI__builtin_ia32_knotdi: { - unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth(); - Value *Res = getMaskVecValue(*this, Ops[0], NumElts); - return Builder.CreateBitCast(Builder.CreateNot(Res), - Ops[0]->getType()); - } - case X86::BI__builtin_ia32_kmovb: - case X86::BI__builtin_ia32_kmovw: - case X86::BI__builtin_ia32_kmovd: - case X86::BI__builtin_ia32_kmovq: { - // Bitcast to vXi1 type and then back to integer. This gets the mask - // register type into the IR, but might be optimized out depending on - // what's around it. - unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth(); - Value *Res = getMaskVecValue(*this, Ops[0], NumElts); - return Builder.CreateBitCast(Res, Ops[0]->getType()); - } - - case X86::BI__builtin_ia32_kunpckdi: - case X86::BI__builtin_ia32_kunpcksi: - case X86::BI__builtin_ia32_kunpckhi: { - unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth(); - Value *LHS = getMaskVecValue(*this, Ops[0], NumElts); - Value *RHS = getMaskVecValue(*this, Ops[1], NumElts); - uint32_t Indices[64]; - for (unsigned i = 0; i != NumElts; ++i) - Indices[i] = i; - - // First extract half of each vector. This gives better codegen than - // doing it in a single shuffle. - LHS = Builder.CreateShuffleVector(LHS, LHS, - makeArrayRef(Indices, NumElts / 2)); - RHS = Builder.CreateShuffleVector(RHS, RHS, - makeArrayRef(Indices, NumElts / 2)); - // Concat the vectors. - // NOTE: Operands are swapped to match the intrinsic definition. - Value *Res = Builder.CreateShuffleVector(RHS, LHS, - makeArrayRef(Indices, NumElts)); - return Builder.CreateBitCast(Res, Ops[0]->getType()); - } - - case X86::BI__builtin_ia32_vplzcntd_128: - case X86::BI__builtin_ia32_vplzcntd_256: - case X86::BI__builtin_ia32_vplzcntd_512: - case X86::BI__builtin_ia32_vplzcntq_128: - case X86::BI__builtin_ia32_vplzcntq_256: - case X86::BI__builtin_ia32_vplzcntq_512: { - Function *F = CGM.getIntrinsic(Intrinsic::ctlz, Ops[0]->getType()); - return Builder.CreateCall(F, {Ops[0],Builder.getInt1(false)}); - } - case X86::BI__builtin_ia32_sqrtss: - case X86::BI__builtin_ia32_sqrtsd: { - Value *A = Builder.CreateExtractElement(Ops[0], (uint64_t)0); - Function *F = CGM.getIntrinsic(Intrinsic::sqrt, A->getType()); - A = Builder.CreateCall(F, {A}); - return Builder.CreateInsertElement(Ops[0], A, (uint64_t)0); - } - case X86::BI__builtin_ia32_sqrtsd_round_mask: - case X86::BI__builtin_ia32_sqrtss_round_mask: { - unsigned CC = cast<llvm::ConstantInt>(Ops[4])->getZExtValue(); - // Support only if the rounding mode is 4 (AKA CUR_DIRECTION), - // otherwise keep the intrinsic. - if (CC != 4) { - Intrinsic::ID IID = BuiltinID == X86::BI__builtin_ia32_sqrtsd_round_mask ? - Intrinsic::x86_avx512_mask_sqrt_sd : - Intrinsic::x86_avx512_mask_sqrt_ss; - return Builder.CreateCall(CGM.getIntrinsic(IID), Ops); - } - Value *A = Builder.CreateExtractElement(Ops[1], (uint64_t)0); - Function *F = CGM.getIntrinsic(Intrinsic::sqrt, A->getType()); - A = Builder.CreateCall(F, A); - Value *Src = Builder.CreateExtractElement(Ops[2], (uint64_t)0); - A = EmitX86ScalarSelect(*this, Ops[3], A, Src); - return Builder.CreateInsertElement(Ops[0], A, (uint64_t)0); - } - case X86::BI__builtin_ia32_sqrtpd256: - case X86::BI__builtin_ia32_sqrtpd: - case X86::BI__builtin_ia32_sqrtps256: - case X86::BI__builtin_ia32_sqrtps: - case X86::BI__builtin_ia32_sqrtps512: - case X86::BI__builtin_ia32_sqrtpd512: { - if (Ops.size() == 2) { - unsigned CC = cast<llvm::ConstantInt>(Ops[1])->getZExtValue(); - // Support only if the rounding mode is 4 (AKA CUR_DIRECTION), - // otherwise keep the intrinsic. - if (CC != 4) { - Intrinsic::ID IID = BuiltinID == X86::BI__builtin_ia32_sqrtps512 ? - Intrinsic::x86_avx512_sqrt_ps_512 : - Intrinsic::x86_avx512_sqrt_pd_512; - return Builder.CreateCall(CGM.getIntrinsic(IID), Ops); - } - } - Function *F = CGM.getIntrinsic(Intrinsic::sqrt, Ops[0]->getType()); - return Builder.CreateCall(F, Ops[0]); - } - case X86::BI__builtin_ia32_pabsb128: - case X86::BI__builtin_ia32_pabsw128: - case X86::BI__builtin_ia32_pabsd128: - case X86::BI__builtin_ia32_pabsb256: - case X86::BI__builtin_ia32_pabsw256: - case X86::BI__builtin_ia32_pabsd256: - case X86::BI__builtin_ia32_pabsq128: - case X86::BI__builtin_ia32_pabsq256: - case X86::BI__builtin_ia32_pabsb512: - case X86::BI__builtin_ia32_pabsw512: - case X86::BI__builtin_ia32_pabsd512: - case X86::BI__builtin_ia32_pabsq512: - return EmitX86Abs(*this, Ops); - - case X86::BI__builtin_ia32_pmaxsb128: - case X86::BI__builtin_ia32_pmaxsw128: - case X86::BI__builtin_ia32_pmaxsd128: - case X86::BI__builtin_ia32_pmaxsq128: - case X86::BI__builtin_ia32_pmaxsb256: - case X86::BI__builtin_ia32_pmaxsw256: - case X86::BI__builtin_ia32_pmaxsd256: - case X86::BI__builtin_ia32_pmaxsq256: - case X86::BI__builtin_ia32_pmaxsb512: - case X86::BI__builtin_ia32_pmaxsw512: - case X86::BI__builtin_ia32_pmaxsd512: - case X86::BI__builtin_ia32_pmaxsq512: - return EmitX86MinMax(*this, ICmpInst::ICMP_SGT, Ops); - case X86::BI__builtin_ia32_pmaxub128: - case X86::BI__builtin_ia32_pmaxuw128: - case X86::BI__builtin_ia32_pmaxud128: - case X86::BI__builtin_ia32_pmaxuq128: - case X86::BI__builtin_ia32_pmaxub256: - case X86::BI__builtin_ia32_pmaxuw256: - case X86::BI__builtin_ia32_pmaxud256: - case X86::BI__builtin_ia32_pmaxuq256: - case X86::BI__builtin_ia32_pmaxub512: - case X86::BI__builtin_ia32_pmaxuw512: - case X86::BI__builtin_ia32_pmaxud512: - case X86::BI__builtin_ia32_pmaxuq512: - return EmitX86MinMax(*this, ICmpInst::ICMP_UGT, Ops); - case X86::BI__builtin_ia32_pminsb128: - case X86::BI__builtin_ia32_pminsw128: - case X86::BI__builtin_ia32_pminsd128: - case X86::BI__builtin_ia32_pminsq128: - case X86::BI__builtin_ia32_pminsb256: - case X86::BI__builtin_ia32_pminsw256: - case X86::BI__builtin_ia32_pminsd256: - case X86::BI__builtin_ia32_pminsq256: - case X86::BI__builtin_ia32_pminsb512: - case X86::BI__builtin_ia32_pminsw512: - case X86::BI__builtin_ia32_pminsd512: - case X86::BI__builtin_ia32_pminsq512: - return EmitX86MinMax(*this, ICmpInst::ICMP_SLT, Ops); - case X86::BI__builtin_ia32_pminub128: - case X86::BI__builtin_ia32_pminuw128: - case X86::BI__builtin_ia32_pminud128: - case X86::BI__builtin_ia32_pminuq128: - case X86::BI__builtin_ia32_pminub256: - case X86::BI__builtin_ia32_pminuw256: - case X86::BI__builtin_ia32_pminud256: - case X86::BI__builtin_ia32_pminuq256: - case X86::BI__builtin_ia32_pminub512: - case X86::BI__builtin_ia32_pminuw512: - case X86::BI__builtin_ia32_pminud512: - case X86::BI__builtin_ia32_pminuq512: - return EmitX86MinMax(*this, ICmpInst::ICMP_ULT, Ops); - - case X86::BI__builtin_ia32_pmuludq128: - case X86::BI__builtin_ia32_pmuludq256: - case X86::BI__builtin_ia32_pmuludq512: - return EmitX86Muldq(*this, /*IsSigned*/false, Ops); - - case X86::BI__builtin_ia32_pmuldq128: - case X86::BI__builtin_ia32_pmuldq256: - case X86::BI__builtin_ia32_pmuldq512: - return EmitX86Muldq(*this, /*IsSigned*/true, Ops); - - case X86::BI__builtin_ia32_pternlogd512_mask: - case X86::BI__builtin_ia32_pternlogq512_mask: - case X86::BI__builtin_ia32_pternlogd128_mask: - case X86::BI__builtin_ia32_pternlogd256_mask: - case X86::BI__builtin_ia32_pternlogq128_mask: - case X86::BI__builtin_ia32_pternlogq256_mask: - return EmitX86Ternlog(*this, /*ZeroMask*/false, Ops); - - case X86::BI__builtin_ia32_pternlogd512_maskz: - case X86::BI__builtin_ia32_pternlogq512_maskz: - case X86::BI__builtin_ia32_pternlogd128_maskz: - case X86::BI__builtin_ia32_pternlogd256_maskz: - case X86::BI__builtin_ia32_pternlogq128_maskz: - case X86::BI__builtin_ia32_pternlogq256_maskz: - return EmitX86Ternlog(*this, /*ZeroMask*/true, Ops); - - case X86::BI__builtin_ia32_vpshldd128: - case X86::BI__builtin_ia32_vpshldd256: - case X86::BI__builtin_ia32_vpshldd512: - case X86::BI__builtin_ia32_vpshldq128: - case X86::BI__builtin_ia32_vpshldq256: - case X86::BI__builtin_ia32_vpshldq512: - case X86::BI__builtin_ia32_vpshldw128: - case X86::BI__builtin_ia32_vpshldw256: - case X86::BI__builtin_ia32_vpshldw512: - return EmitX86FunnelShift(*this, Ops[0], Ops[1], Ops[2], false); - - case X86::BI__builtin_ia32_vpshrdd128: - case X86::BI__builtin_ia32_vpshrdd256: - case X86::BI__builtin_ia32_vpshrdd512: - case X86::BI__builtin_ia32_vpshrdq128: - case X86::BI__builtin_ia32_vpshrdq256: - case X86::BI__builtin_ia32_vpshrdq512: - case X86::BI__builtin_ia32_vpshrdw128: - case X86::BI__builtin_ia32_vpshrdw256: - case X86::BI__builtin_ia32_vpshrdw512: - // Ops 0 and 1 are swapped. - return EmitX86FunnelShift(*this, Ops[1], Ops[0], Ops[2], true); - - case X86::BI__builtin_ia32_vpshldvd128: - case X86::BI__builtin_ia32_vpshldvd256: - case X86::BI__builtin_ia32_vpshldvd512: - case X86::BI__builtin_ia32_vpshldvq128: - case X86::BI__builtin_ia32_vpshldvq256: - case X86::BI__builtin_ia32_vpshldvq512: - case X86::BI__builtin_ia32_vpshldvw128: - case X86::BI__builtin_ia32_vpshldvw256: - case X86::BI__builtin_ia32_vpshldvw512: - return EmitX86FunnelShift(*this, Ops[0], Ops[1], Ops[2], false); - - case X86::BI__builtin_ia32_vpshrdvd128: - case X86::BI__builtin_ia32_vpshrdvd256: - case X86::BI__builtin_ia32_vpshrdvd512: - case X86::BI__builtin_ia32_vpshrdvq128: - case X86::BI__builtin_ia32_vpshrdvq256: - case X86::BI__builtin_ia32_vpshrdvq512: - case X86::BI__builtin_ia32_vpshrdvw128: - case X86::BI__builtin_ia32_vpshrdvw256: - case X86::BI__builtin_ia32_vpshrdvw512: - // Ops 0 and 1 are swapped. - return EmitX86FunnelShift(*this, Ops[1], Ops[0], Ops[2], true); - - // 3DNow! - case X86::BI__builtin_ia32_pswapdsf: - case X86::BI__builtin_ia32_pswapdsi: { - llvm::Type *MMXTy = llvm::Type::getX86_MMXTy(getLLVMContext()); - Ops[0] = Builder.CreateBitCast(Ops[0], MMXTy, "cast"); - llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_3dnowa_pswapd); - return Builder.CreateCall(F, Ops, "pswapd"); - } - case X86::BI__builtin_ia32_rdrand16_step: - case X86::BI__builtin_ia32_rdrand32_step: - case X86::BI__builtin_ia32_rdrand64_step: - case X86::BI__builtin_ia32_rdseed16_step: - case X86::BI__builtin_ia32_rdseed32_step: - case X86::BI__builtin_ia32_rdseed64_step: { - Intrinsic::ID ID; - switch (BuiltinID) { - default: llvm_unreachable("Unsupported intrinsic!"); - case X86::BI__builtin_ia32_rdrand16_step: - ID = Intrinsic::x86_rdrand_16; - break; - case X86::BI__builtin_ia32_rdrand32_step: - ID = Intrinsic::x86_rdrand_32; - break; - case X86::BI__builtin_ia32_rdrand64_step: - ID = Intrinsic::x86_rdrand_64; - break; - case X86::BI__builtin_ia32_rdseed16_step: - ID = Intrinsic::x86_rdseed_16; - break; - case X86::BI__builtin_ia32_rdseed32_step: - ID = Intrinsic::x86_rdseed_32; - break; - case X86::BI__builtin_ia32_rdseed64_step: - ID = Intrinsic::x86_rdseed_64; - break; - } - - Value *Call = Builder.CreateCall(CGM.getIntrinsic(ID)); - Builder.CreateDefaultAlignedStore(Builder.CreateExtractValue(Call, 0), - Ops[0]); - return Builder.CreateExtractValue(Call, 1); - } - case X86::BI__builtin_ia32_addcarryx_u32: - case X86::BI__builtin_ia32_addcarryx_u64: - case X86::BI__builtin_ia32_subborrow_u32: - case X86::BI__builtin_ia32_subborrow_u64: { - Intrinsic::ID IID; - switch (BuiltinID) { - default: llvm_unreachable("Unsupported intrinsic!"); - case X86::BI__builtin_ia32_addcarryx_u32: - IID = Intrinsic::x86_addcarry_32; - break; - case X86::BI__builtin_ia32_addcarryx_u64: - IID = Intrinsic::x86_addcarry_64; - break; - case X86::BI__builtin_ia32_subborrow_u32: - IID = Intrinsic::x86_subborrow_32; - break; - case X86::BI__builtin_ia32_subborrow_u64: - IID = Intrinsic::x86_subborrow_64; - break; - } - - Value *Call = Builder.CreateCall(CGM.getIntrinsic(IID), - { Ops[0], Ops[1], Ops[2] }); - Builder.CreateDefaultAlignedStore(Builder.CreateExtractValue(Call, 1), - Ops[3]); - return Builder.CreateExtractValue(Call, 0); - } - - case X86::BI__builtin_ia32_fpclassps128_mask: - case X86::BI__builtin_ia32_fpclassps256_mask: - case X86::BI__builtin_ia32_fpclassps512_mask: - case X86::BI__builtin_ia32_fpclasspd128_mask: - case X86::BI__builtin_ia32_fpclasspd256_mask: - case X86::BI__builtin_ia32_fpclasspd512_mask: { - unsigned NumElts = Ops[0]->getType()->getVectorNumElements(); - Value *MaskIn = Ops[2]; - Ops.erase(&Ops[2]); - - Intrinsic::ID ID; - switch (BuiltinID) { - default: llvm_unreachable("Unsupported intrinsic!"); - case X86::BI__builtin_ia32_fpclassps128_mask: - ID = Intrinsic::x86_avx512_fpclass_ps_128; - break; - case X86::BI__builtin_ia32_fpclassps256_mask: - ID = Intrinsic::x86_avx512_fpclass_ps_256; - break; - case X86::BI__builtin_ia32_fpclassps512_mask: - ID = Intrinsic::x86_avx512_fpclass_ps_512; - break; - case X86::BI__builtin_ia32_fpclasspd128_mask: - ID = Intrinsic::x86_avx512_fpclass_pd_128; - break; - case X86::BI__builtin_ia32_fpclasspd256_mask: - ID = Intrinsic::x86_avx512_fpclass_pd_256; - break; - case X86::BI__builtin_ia32_fpclasspd512_mask: - ID = Intrinsic::x86_avx512_fpclass_pd_512; - break; - } - - Value *Fpclass = Builder.CreateCall(CGM.getIntrinsic(ID), Ops); - return EmitX86MaskedCompareResult(*this, Fpclass, NumElts, MaskIn); - } - - case X86::BI__builtin_ia32_vpmultishiftqb128: - case X86::BI__builtin_ia32_vpmultishiftqb256: - case X86::BI__builtin_ia32_vpmultishiftqb512: { - Intrinsic::ID ID; - switch (BuiltinID) { - default: llvm_unreachable("Unsupported intrinsic!"); - case X86::BI__builtin_ia32_vpmultishiftqb128: - ID = Intrinsic::x86_avx512_pmultishift_qb_128; - break; - case X86::BI__builtin_ia32_vpmultishiftqb256: - ID = Intrinsic::x86_avx512_pmultishift_qb_256; - break; - case X86::BI__builtin_ia32_vpmultishiftqb512: - ID = Intrinsic::x86_avx512_pmultishift_qb_512; - break; - } - - return Builder.CreateCall(CGM.getIntrinsic(ID), Ops); - } - - case X86::BI__builtin_ia32_vpshufbitqmb128_mask: - case X86::BI__builtin_ia32_vpshufbitqmb256_mask: - case X86::BI__builtin_ia32_vpshufbitqmb512_mask: { - unsigned NumElts = Ops[0]->getType()->getVectorNumElements(); - Value *MaskIn = Ops[2]; - Ops.erase(&Ops[2]); - - Intrinsic::ID ID; - switch (BuiltinID) { - default: llvm_unreachable("Unsupported intrinsic!"); - case X86::BI__builtin_ia32_vpshufbitqmb128_mask: - ID = Intrinsic::x86_avx512_vpshufbitqmb_128; - break; - case X86::BI__builtin_ia32_vpshufbitqmb256_mask: - ID = Intrinsic::x86_avx512_vpshufbitqmb_256; - break; - case X86::BI__builtin_ia32_vpshufbitqmb512_mask: - ID = Intrinsic::x86_avx512_vpshufbitqmb_512; - break; - } - - Value *Shufbit = Builder.CreateCall(CGM.getIntrinsic(ID), Ops); - return EmitX86MaskedCompareResult(*this, Shufbit, NumElts, MaskIn); - } - - // packed comparison intrinsics - case X86::BI__builtin_ia32_cmpeqps: - case X86::BI__builtin_ia32_cmpeqpd: - return getVectorFCmpIR(CmpInst::FCMP_OEQ); - case X86::BI__builtin_ia32_cmpltps: - case X86::BI__builtin_ia32_cmpltpd: - return getVectorFCmpIR(CmpInst::FCMP_OLT); - case X86::BI__builtin_ia32_cmpleps: - case X86::BI__builtin_ia32_cmplepd: - return getVectorFCmpIR(CmpInst::FCMP_OLE); - case X86::BI__builtin_ia32_cmpunordps: - case X86::BI__builtin_ia32_cmpunordpd: - return getVectorFCmpIR(CmpInst::FCMP_UNO); - case X86::BI__builtin_ia32_cmpneqps: - case X86::BI__builtin_ia32_cmpneqpd: - return getVectorFCmpIR(CmpInst::FCMP_UNE); - case X86::BI__builtin_ia32_cmpnltps: - case X86::BI__builtin_ia32_cmpnltpd: - return getVectorFCmpIR(CmpInst::FCMP_UGE); - case X86::BI__builtin_ia32_cmpnleps: - case X86::BI__builtin_ia32_cmpnlepd: - return getVectorFCmpIR(CmpInst::FCMP_UGT); - case X86::BI__builtin_ia32_cmpordps: - case X86::BI__builtin_ia32_cmpordpd: - return getVectorFCmpIR(CmpInst::FCMP_ORD); - case X86::BI__builtin_ia32_cmpps: - case X86::BI__builtin_ia32_cmpps256: - case X86::BI__builtin_ia32_cmppd: - case X86::BI__builtin_ia32_cmppd256: - case X86::BI__builtin_ia32_cmpps128_mask: - case X86::BI__builtin_ia32_cmpps256_mask: - case X86::BI__builtin_ia32_cmpps512_mask: - case X86::BI__builtin_ia32_cmppd128_mask: - case X86::BI__builtin_ia32_cmppd256_mask: - case X86::BI__builtin_ia32_cmppd512_mask: { - // Lowering vector comparisons to fcmp instructions, while - // ignoring signalling behaviour requested - // ignoring rounding mode requested - // This is is only possible as long as FENV_ACCESS is not implemented. - // See also: https://reviews.llvm.org/D45616 - - // The third argument is the comparison condition, and integer in the - // range [0, 31] - unsigned CC = cast<llvm::ConstantInt>(Ops[2])->getZExtValue() & 0x1f; - - // Lowering to IR fcmp instruction. - // Ignoring requested signaling behaviour, - // e.g. both _CMP_GT_OS & _CMP_GT_OQ are translated to FCMP_OGT. - FCmpInst::Predicate Pred; - switch (CC) { - case 0x00: Pred = FCmpInst::FCMP_OEQ; break; - case 0x01: Pred = FCmpInst::FCMP_OLT; break; - case 0x02: Pred = FCmpInst::FCMP_OLE; break; - case 0x03: Pred = FCmpInst::FCMP_UNO; break; - case 0x04: Pred = FCmpInst::FCMP_UNE; break; - case 0x05: Pred = FCmpInst::FCMP_UGE; break; - case 0x06: Pred = FCmpInst::FCMP_UGT; break; - case 0x07: Pred = FCmpInst::FCMP_ORD; break; - case 0x08: Pred = FCmpInst::FCMP_UEQ; break; - case 0x09: Pred = FCmpInst::FCMP_ULT; break; - case 0x0a: Pred = FCmpInst::FCMP_ULE; break; - case 0x0b: Pred = FCmpInst::FCMP_FALSE; break; - case 0x0c: Pred = FCmpInst::FCMP_ONE; break; - case 0x0d: Pred = FCmpInst::FCMP_OGE; break; - case 0x0e: Pred = FCmpInst::FCMP_OGT; break; - case 0x0f: Pred = FCmpInst::FCMP_TRUE; break; - case 0x10: Pred = FCmpInst::FCMP_OEQ; break; - case 0x11: Pred = FCmpInst::FCMP_OLT; break; - case 0x12: Pred = FCmpInst::FCMP_OLE; break; - case 0x13: Pred = FCmpInst::FCMP_UNO; break; - case 0x14: Pred = FCmpInst::FCMP_UNE; break; - case 0x15: Pred = FCmpInst::FCMP_UGE; break; - case 0x16: Pred = FCmpInst::FCMP_UGT; break; - case 0x17: Pred = FCmpInst::FCMP_ORD; break; - case 0x18: Pred = FCmpInst::FCMP_UEQ; break; - case 0x19: Pred = FCmpInst::FCMP_ULT; break; - case 0x1a: Pred = FCmpInst::FCMP_ULE; break; - case 0x1b: Pred = FCmpInst::FCMP_FALSE; break; - case 0x1c: Pred = FCmpInst::FCMP_ONE; break; - case 0x1d: Pred = FCmpInst::FCMP_OGE; break; - case 0x1e: Pred = FCmpInst::FCMP_OGT; break; - case 0x1f: Pred = FCmpInst::FCMP_TRUE; break; - default: llvm_unreachable("Unhandled CC"); - } - - // Builtins without the _mask suffix return a vector of integers - // of the same width as the input vectors - switch (BuiltinID) { - case X86::BI__builtin_ia32_cmpps512_mask: - case X86::BI__builtin_ia32_cmppd512_mask: - case X86::BI__builtin_ia32_cmpps128_mask: - case X86::BI__builtin_ia32_cmpps256_mask: - case X86::BI__builtin_ia32_cmppd128_mask: - case X86::BI__builtin_ia32_cmppd256_mask: { - unsigned NumElts = Ops[0]->getType()->getVectorNumElements(); - Value *Cmp = Builder.CreateFCmp(Pred, Ops[0], Ops[1]); - return EmitX86MaskedCompareResult(*this, Cmp, NumElts, Ops[3]); - } - default: - return getVectorFCmpIR(Pred); - } - } - - // SSE scalar comparison intrinsics - case X86::BI__builtin_ia32_cmpeqss: - return getCmpIntrinsicCall(Intrinsic::x86_sse_cmp_ss, 0); - case X86::BI__builtin_ia32_cmpltss: - return getCmpIntrinsicCall(Intrinsic::x86_sse_cmp_ss, 1); - case X86::BI__builtin_ia32_cmpless: - return getCmpIntrinsicCall(Intrinsic::x86_sse_cmp_ss, 2); - case X86::BI__builtin_ia32_cmpunordss: - return getCmpIntrinsicCall(Intrinsic::x86_sse_cmp_ss, 3); - case X86::BI__builtin_ia32_cmpneqss: - return getCmpIntrinsicCall(Intrinsic::x86_sse_cmp_ss, 4); - case X86::BI__builtin_ia32_cmpnltss: - return getCmpIntrinsicCall(Intrinsic::x86_sse_cmp_ss, 5); - case X86::BI__builtin_ia32_cmpnless: - return getCmpIntrinsicCall(Intrinsic::x86_sse_cmp_ss, 6); - case X86::BI__builtin_ia32_cmpordss: - return getCmpIntrinsicCall(Intrinsic::x86_sse_cmp_ss, 7); - case X86::BI__builtin_ia32_cmpeqsd: - return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 0); - case X86::BI__builtin_ia32_cmpltsd: - return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 1); - case X86::BI__builtin_ia32_cmplesd: - return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 2); - case X86::BI__builtin_ia32_cmpunordsd: - return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 3); - case X86::BI__builtin_ia32_cmpneqsd: - return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 4); - case X86::BI__builtin_ia32_cmpnltsd: - return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 5); - case X86::BI__builtin_ia32_cmpnlesd: - return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 6); - case X86::BI__builtin_ia32_cmpordsd: - return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 7); - - case X86::BI__emul: - case X86::BI__emulu: { - llvm::Type *Int64Ty = llvm::IntegerType::get(getLLVMContext(), 64); - bool isSigned = (BuiltinID == X86::BI__emul); - Value *LHS = Builder.CreateIntCast(Ops[0], Int64Ty, isSigned); - Value *RHS = Builder.CreateIntCast(Ops[1], Int64Ty, isSigned); - return Builder.CreateMul(LHS, RHS, "", !isSigned, isSigned); - } - case X86::BI__mulh: - case X86::BI__umulh: - case X86::BI_mul128: - case X86::BI_umul128: { - llvm::Type *ResType = ConvertType(E->getType()); - llvm::Type *Int128Ty = llvm::IntegerType::get(getLLVMContext(), 128); - - bool IsSigned = (BuiltinID == X86::BI__mulh || BuiltinID == X86::BI_mul128); - Value *LHS = Builder.CreateIntCast(Ops[0], Int128Ty, IsSigned); - Value *RHS = Builder.CreateIntCast(Ops[1], Int128Ty, IsSigned); - - Value *MulResult, *HigherBits; - if (IsSigned) { - MulResult = Builder.CreateNSWMul(LHS, RHS); - HigherBits = Builder.CreateAShr(MulResult, 64); - } else { - MulResult = Builder.CreateNUWMul(LHS, RHS); - HigherBits = Builder.CreateLShr(MulResult, 64); - } - HigherBits = Builder.CreateIntCast(HigherBits, ResType, IsSigned); - - if (BuiltinID == X86::BI__mulh || BuiltinID == X86::BI__umulh) - return HigherBits; - - Address HighBitsAddress = EmitPointerWithAlignment(E->getArg(2)); - Builder.CreateStore(HigherBits, HighBitsAddress); - return Builder.CreateIntCast(MulResult, ResType, IsSigned); - } - - case X86::BI__faststorefence: { - return Builder.CreateFence(llvm::AtomicOrdering::SequentiallyConsistent, - llvm::SyncScope::System); - } - case X86::BI__shiftleft128: - case X86::BI__shiftright128: { - // FIXME: Once fshl/fshr no longer add an unneeded and and cmov, do this: - // llvm::Function *F = CGM.getIntrinsic( - // BuiltinID == X86::BI__shiftleft128 ? Intrinsic::fshl : Intrinsic::fshr, - // Int64Ty); - // Ops[2] = Builder.CreateZExt(Ops[2], Int64Ty); - // return Builder.CreateCall(F, Ops); - llvm::Type *Int128Ty = Builder.getInt128Ty(); - Value *Val = Builder.CreateOr( - Builder.CreateShl(Builder.CreateZExt(Ops[1], Int128Ty), 64), - Builder.CreateZExt(Ops[0], Int128Ty)); - Value *Amt = Builder.CreateAnd(Builder.CreateZExt(Ops[2], Int128Ty), - llvm::ConstantInt::get(Int128Ty, 0x3f)); - Value *Res; - if (BuiltinID == X86::BI__shiftleft128) - Res = Builder.CreateLShr(Builder.CreateShl(Val, Amt), 64); - else - Res = Builder.CreateLShr(Val, Amt); - return Builder.CreateTrunc(Res, Int64Ty); - } - case X86::BI_ReadWriteBarrier: - case X86::BI_ReadBarrier: - case X86::BI_WriteBarrier: { - return Builder.CreateFence(llvm::AtomicOrdering::SequentiallyConsistent, - llvm::SyncScope::SingleThread); - } - case X86::BI_BitScanForward: - case X86::BI_BitScanForward64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_BitScanForward, E); - case X86::BI_BitScanReverse: - case X86::BI_BitScanReverse64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_BitScanReverse, E); - - case X86::BI_InterlockedAnd64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd, E); - case X86::BI_InterlockedExchange64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange, E); - case X86::BI_InterlockedExchangeAdd64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd, E); - case X86::BI_InterlockedExchangeSub64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeSub, E); - case X86::BI_InterlockedOr64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr, E); - case X86::BI_InterlockedXor64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor, E); - case X86::BI_InterlockedDecrement64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement, E); - case X86::BI_InterlockedIncrement64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement, E); - case X86::BI_InterlockedCompareExchange128: { - // InterlockedCompareExchange128 doesn't directly refer to 128bit ints, - // instead it takes pointers to 64bit ints for Destination and - // ComparandResult, and exchange is taken as two 64bit ints (high & low). - // The previous value is written to ComparandResult, and success is - // returned. - - llvm::Type *Int128Ty = Builder.getInt128Ty(); - llvm::Type *Int128PtrTy = Int128Ty->getPointerTo(); - - Value *Destination = - Builder.CreateBitCast(Ops[0], Int128PtrTy); - Value *ExchangeHigh128 = Builder.CreateZExt(Ops[1], Int128Ty); - Value *ExchangeLow128 = Builder.CreateZExt(Ops[2], Int128Ty); - Address ComparandResult(Builder.CreateBitCast(Ops[3], Int128PtrTy), - getContext().toCharUnitsFromBits(128)); - - Value *Exchange = Builder.CreateOr( - Builder.CreateShl(ExchangeHigh128, 64, "", false, false), - ExchangeLow128); - - Value *Comparand = Builder.CreateLoad(ComparandResult); - - AtomicCmpXchgInst *CXI = - Builder.CreateAtomicCmpXchg(Destination, Comparand, Exchange, - AtomicOrdering::SequentiallyConsistent, - AtomicOrdering::SequentiallyConsistent); - CXI->setVolatile(true); - - // Write the result back to the inout pointer. - Builder.CreateStore(Builder.CreateExtractValue(CXI, 0), ComparandResult); - - // Get the success boolean and zero extend it to i8. - Value *Success = Builder.CreateExtractValue(CXI, 1); - return Builder.CreateZExt(Success, ConvertType(E->getType())); - } - - case X86::BI_AddressOfReturnAddress: { - Value *F = CGM.getIntrinsic(Intrinsic::addressofreturnaddress); - return Builder.CreateCall(F); - } - case X86::BI__stosb: { - // We treat __stosb as a volatile memset - it may not generate "rep stosb" - // instruction, but it will create a memset that won't be optimized away. - return Builder.CreateMemSet(Ops[0], Ops[1], Ops[2], 1, true); - } - case X86::BI__ud2: - // llvm.trap makes a ud2a instruction on x86. - return EmitTrapCall(Intrinsic::trap); - case X86::BI__int2c: { - // This syscall signals a driver assertion failure in x86 NT kernels. - llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); - llvm::InlineAsm *IA = - llvm::InlineAsm::get(FTy, "int $$0x2c", "", /*SideEffects=*/true); - llvm::AttributeList NoReturnAttr = llvm::AttributeList::get( - getLLVMContext(), llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoReturn); - CallSite CS = Builder.CreateCall(IA); - CS.setAttributes(NoReturnAttr); - return CS.getInstruction(); - } - case X86::BI__readfsbyte: - case X86::BI__readfsword: - case X86::BI__readfsdword: - case X86::BI__readfsqword: { - llvm::Type *IntTy = ConvertType(E->getType()); - Value *Ptr = - Builder.CreateIntToPtr(Ops[0], llvm::PointerType::get(IntTy, 257)); - LoadInst *Load = Builder.CreateAlignedLoad( - IntTy, Ptr, getContext().getTypeAlignInChars(E->getType())); - Load->setVolatile(true); - return Load; - } - case X86::BI__readgsbyte: - case X86::BI__readgsword: - case X86::BI__readgsdword: - case X86::BI__readgsqword: { - llvm::Type *IntTy = ConvertType(E->getType()); - Value *Ptr = - Builder.CreateIntToPtr(Ops[0], llvm::PointerType::get(IntTy, 256)); - LoadInst *Load = Builder.CreateAlignedLoad( - IntTy, Ptr, getContext().getTypeAlignInChars(E->getType())); - Load->setVolatile(true); - return Load; - } - case X86::BI__builtin_ia32_paddsb512: - case X86::BI__builtin_ia32_paddsw512: - case X86::BI__builtin_ia32_paddsb256: - case X86::BI__builtin_ia32_paddsw256: - case X86::BI__builtin_ia32_paddsb128: - case X86::BI__builtin_ia32_paddsw128: - return EmitX86AddSubSatExpr(*this, Ops, true, true); - case X86::BI__builtin_ia32_paddusb512: - case X86::BI__builtin_ia32_paddusw512: - case X86::BI__builtin_ia32_paddusb256: - case X86::BI__builtin_ia32_paddusw256: - case X86::BI__builtin_ia32_paddusb128: - case X86::BI__builtin_ia32_paddusw128: - return EmitX86AddSubSatExpr(*this, Ops, false, true); - case X86::BI__builtin_ia32_psubsb512: - case X86::BI__builtin_ia32_psubsw512: - case X86::BI__builtin_ia32_psubsb256: - case X86::BI__builtin_ia32_psubsw256: - case X86::BI__builtin_ia32_psubsb128: - case X86::BI__builtin_ia32_psubsw128: - return EmitX86AddSubSatExpr(*this, Ops, true, false); - case X86::BI__builtin_ia32_psubusb512: - case X86::BI__builtin_ia32_psubusw512: - case X86::BI__builtin_ia32_psubusb256: - case X86::BI__builtin_ia32_psubusw256: - case X86::BI__builtin_ia32_psubusb128: - case X86::BI__builtin_ia32_psubusw128: - return EmitX86AddSubSatExpr(*this, Ops, false, false); - } -} - -Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, - const CallExpr *E) { - SmallVector<Value*, 4> Ops; - - for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) - Ops.push_back(EmitScalarExpr(E->getArg(i))); - - Intrinsic::ID ID = Intrinsic::not_intrinsic; - - switch (BuiltinID) { - default: return nullptr; - - // __builtin_ppc_get_timebase is GCC 4.8+'s PowerPC-specific name for what we - // call __builtin_readcyclecounter. - case PPC::BI__builtin_ppc_get_timebase: - return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::readcyclecounter)); - - // vec_ld, vec_xl_be, vec_lvsl, vec_lvsr - case PPC::BI__builtin_altivec_lvx: - case PPC::BI__builtin_altivec_lvxl: - case PPC::BI__builtin_altivec_lvebx: - case PPC::BI__builtin_altivec_lvehx: - case PPC::BI__builtin_altivec_lvewx: - case PPC::BI__builtin_altivec_lvsl: - case PPC::BI__builtin_altivec_lvsr: - case PPC::BI__builtin_vsx_lxvd2x: - case PPC::BI__builtin_vsx_lxvw4x: - case PPC::BI__builtin_vsx_lxvd2x_be: - case PPC::BI__builtin_vsx_lxvw4x_be: - case PPC::BI__builtin_vsx_lxvl: - case PPC::BI__builtin_vsx_lxvll: - { - if(BuiltinID == PPC::BI__builtin_vsx_lxvl || - BuiltinID == PPC::BI__builtin_vsx_lxvll){ - Ops[0] = Builder.CreateBitCast(Ops[0], Int8PtrTy); - }else { - Ops[1] = Builder.CreateBitCast(Ops[1], Int8PtrTy); - Ops[0] = Builder.CreateGEP(Ops[1], Ops[0]); - Ops.pop_back(); - } - - switch (BuiltinID) { - default: llvm_unreachable("Unsupported ld/lvsl/lvsr intrinsic!"); - case PPC::BI__builtin_altivec_lvx: - ID = Intrinsic::ppc_altivec_lvx; - break; - case PPC::BI__builtin_altivec_lvxl: - ID = Intrinsic::ppc_altivec_lvxl; - break; - case PPC::BI__builtin_altivec_lvebx: - ID = Intrinsic::ppc_altivec_lvebx; - break; - case PPC::BI__builtin_altivec_lvehx: - ID = Intrinsic::ppc_altivec_lvehx; - break; - case PPC::BI__builtin_altivec_lvewx: - ID = Intrinsic::ppc_altivec_lvewx; - break; - case PPC::BI__builtin_altivec_lvsl: - ID = Intrinsic::ppc_altivec_lvsl; - break; - case PPC::BI__builtin_altivec_lvsr: - ID = Intrinsic::ppc_altivec_lvsr; - break; - case PPC::BI__builtin_vsx_lxvd2x: - ID = Intrinsic::ppc_vsx_lxvd2x; - break; - case PPC::BI__builtin_vsx_lxvw4x: - ID = Intrinsic::ppc_vsx_lxvw4x; - break; - case PPC::BI__builtin_vsx_lxvd2x_be: - ID = Intrinsic::ppc_vsx_lxvd2x_be; - break; - case PPC::BI__builtin_vsx_lxvw4x_be: - ID = Intrinsic::ppc_vsx_lxvw4x_be; - break; - case PPC::BI__builtin_vsx_lxvl: - ID = Intrinsic::ppc_vsx_lxvl; - break; - case PPC::BI__builtin_vsx_lxvll: - ID = Intrinsic::ppc_vsx_lxvll; - break; - } - llvm::Function *F = CGM.getIntrinsic(ID); - return Builder.CreateCall(F, Ops, ""); - } - - // vec_st, vec_xst_be - case PPC::BI__builtin_altivec_stvx: - case PPC::BI__builtin_altivec_stvxl: - case PPC::BI__builtin_altivec_stvebx: - case PPC::BI__builtin_altivec_stvehx: - case PPC::BI__builtin_altivec_stvewx: - case PPC::BI__builtin_vsx_stxvd2x: - case PPC::BI__builtin_vsx_stxvw4x: - case PPC::BI__builtin_vsx_stxvd2x_be: - case PPC::BI__builtin_vsx_stxvw4x_be: - case PPC::BI__builtin_vsx_stxvl: - case PPC::BI__builtin_vsx_stxvll: - { - if(BuiltinID == PPC::BI__builtin_vsx_stxvl || - BuiltinID == PPC::BI__builtin_vsx_stxvll ){ - Ops[1] = Builder.CreateBitCast(Ops[1], Int8PtrTy); - }else { - Ops[2] = Builder.CreateBitCast(Ops[2], Int8PtrTy); - Ops[1] = Builder.CreateGEP(Ops[2], Ops[1]); - Ops.pop_back(); - } - - switch (BuiltinID) { - default: llvm_unreachable("Unsupported st intrinsic!"); - case PPC::BI__builtin_altivec_stvx: - ID = Intrinsic::ppc_altivec_stvx; - break; - case PPC::BI__builtin_altivec_stvxl: - ID = Intrinsic::ppc_altivec_stvxl; - break; - case PPC::BI__builtin_altivec_stvebx: - ID = Intrinsic::ppc_altivec_stvebx; - break; - case PPC::BI__builtin_altivec_stvehx: - ID = Intrinsic::ppc_altivec_stvehx; - break; - case PPC::BI__builtin_altivec_stvewx: - ID = Intrinsic::ppc_altivec_stvewx; - break; - case PPC::BI__builtin_vsx_stxvd2x: - ID = Intrinsic::ppc_vsx_stxvd2x; - break; - case PPC::BI__builtin_vsx_stxvw4x: - ID = Intrinsic::ppc_vsx_stxvw4x; - break; - case PPC::BI__builtin_vsx_stxvd2x_be: - ID = Intrinsic::ppc_vsx_stxvd2x_be; - break; - case PPC::BI__builtin_vsx_stxvw4x_be: - ID = Intrinsic::ppc_vsx_stxvw4x_be; - break; - case PPC::BI__builtin_vsx_stxvl: - ID = Intrinsic::ppc_vsx_stxvl; - break; - case PPC::BI__builtin_vsx_stxvll: - ID = Intrinsic::ppc_vsx_stxvll; - break; - } - llvm::Function *F = CGM.getIntrinsic(ID); - return Builder.CreateCall(F, Ops, ""); - } - // Square root - case PPC::BI__builtin_vsx_xvsqrtsp: - case PPC::BI__builtin_vsx_xvsqrtdp: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - ID = Intrinsic::sqrt; - llvm::Function *F = CGM.getIntrinsic(ID, ResultType); - return Builder.CreateCall(F, X); - } - // Count leading zeros - case PPC::BI__builtin_altivec_vclzb: - case PPC::BI__builtin_altivec_vclzh: - case PPC::BI__builtin_altivec_vclzw: - case PPC::BI__builtin_altivec_vclzd: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - Value *Undef = ConstantInt::get(Builder.getInt1Ty(), false); - Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ResultType); - return Builder.CreateCall(F, {X, Undef}); - } - case PPC::BI__builtin_altivec_vctzb: - case PPC::BI__builtin_altivec_vctzh: - case PPC::BI__builtin_altivec_vctzw: - case PPC::BI__builtin_altivec_vctzd: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - Value *Undef = ConstantInt::get(Builder.getInt1Ty(), false); - Function *F = CGM.getIntrinsic(Intrinsic::cttz, ResultType); - return Builder.CreateCall(F, {X, Undef}); - } - case PPC::BI__builtin_altivec_vpopcntb: - case PPC::BI__builtin_altivec_vpopcnth: - case PPC::BI__builtin_altivec_vpopcntw: - case PPC::BI__builtin_altivec_vpopcntd: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - llvm::Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ResultType); - return Builder.CreateCall(F, X); - } - // Copy sign - case PPC::BI__builtin_vsx_xvcpsgnsp: - case PPC::BI__builtin_vsx_xvcpsgndp: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - Value *Y = EmitScalarExpr(E->getArg(1)); - ID = Intrinsic::copysign; - llvm::Function *F = CGM.getIntrinsic(ID, ResultType); - return Builder.CreateCall(F, {X, Y}); - } - // Rounding/truncation - case PPC::BI__builtin_vsx_xvrspip: - case PPC::BI__builtin_vsx_xvrdpip: - case PPC::BI__builtin_vsx_xvrdpim: - case PPC::BI__builtin_vsx_xvrspim: - case PPC::BI__builtin_vsx_xvrdpi: - case PPC::BI__builtin_vsx_xvrspi: - case PPC::BI__builtin_vsx_xvrdpic: - case PPC::BI__builtin_vsx_xvrspic: - case PPC::BI__builtin_vsx_xvrdpiz: - case PPC::BI__builtin_vsx_xvrspiz: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - if (BuiltinID == PPC::BI__builtin_vsx_xvrdpim || - BuiltinID == PPC::BI__builtin_vsx_xvrspim) - ID = Intrinsic::floor; - else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpi || - BuiltinID == PPC::BI__builtin_vsx_xvrspi) - ID = Intrinsic::round; - else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpic || - BuiltinID == PPC::BI__builtin_vsx_xvrspic) - ID = Intrinsic::nearbyint; - else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpip || - BuiltinID == PPC::BI__builtin_vsx_xvrspip) - ID = Intrinsic::ceil; - else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpiz || - BuiltinID == PPC::BI__builtin_vsx_xvrspiz) - ID = Intrinsic::trunc; - llvm::Function *F = CGM.getIntrinsic(ID, ResultType); - return Builder.CreateCall(F, X); - } - - // Absolute value - case PPC::BI__builtin_vsx_xvabsdp: - case PPC::BI__builtin_vsx_xvabssp: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - llvm::Function *F = CGM.getIntrinsic(Intrinsic::fabs, ResultType); - return Builder.CreateCall(F, X); - } - - // FMA variations - case PPC::BI__builtin_vsx_xvmaddadp: - case PPC::BI__builtin_vsx_xvmaddasp: - case PPC::BI__builtin_vsx_xvnmaddadp: - case PPC::BI__builtin_vsx_xvnmaddasp: - case PPC::BI__builtin_vsx_xvmsubadp: - case PPC::BI__builtin_vsx_xvmsubasp: - case PPC::BI__builtin_vsx_xvnmsubadp: - case PPC::BI__builtin_vsx_xvnmsubasp: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - Value *Y = EmitScalarExpr(E->getArg(1)); - Value *Z = EmitScalarExpr(E->getArg(2)); - Value *Zero = llvm::ConstantFP::getZeroValueForNegation(ResultType); - llvm::Function *F = CGM.getIntrinsic(Intrinsic::fma, ResultType); - switch (BuiltinID) { - case PPC::BI__builtin_vsx_xvmaddadp: - case PPC::BI__builtin_vsx_xvmaddasp: - return Builder.CreateCall(F, {X, Y, Z}); - case PPC::BI__builtin_vsx_xvnmaddadp: - case PPC::BI__builtin_vsx_xvnmaddasp: - return Builder.CreateFSub(Zero, - Builder.CreateCall(F, {X, Y, Z}), "sub"); - case PPC::BI__builtin_vsx_xvmsubadp: - case PPC::BI__builtin_vsx_xvmsubasp: - return Builder.CreateCall(F, - {X, Y, Builder.CreateFSub(Zero, Z, "sub")}); - case PPC::BI__builtin_vsx_xvnmsubadp: - case PPC::BI__builtin_vsx_xvnmsubasp: - Value *FsubRes = - Builder.CreateCall(F, {X, Y, Builder.CreateFSub(Zero, Z, "sub")}); - return Builder.CreateFSub(Zero, FsubRes, "sub"); - } - llvm_unreachable("Unknown FMA operation"); - return nullptr; // Suppress no-return warning - } - - case PPC::BI__builtin_vsx_insertword: { - llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_vsx_xxinsertw); - - // Third argument is a compile time constant int. It must be clamped to - // to the range [0, 12]. - ConstantInt *ArgCI = dyn_cast<ConstantInt>(Ops[2]); - assert(ArgCI && - "Third arg to xxinsertw intrinsic must be constant integer"); - const int64_t MaxIndex = 12; - int64_t Index = clamp(ArgCI->getSExtValue(), 0, MaxIndex); - - // The builtin semantics don't exactly match the xxinsertw instructions - // semantics (which ppc_vsx_xxinsertw follows). The builtin extracts the - // word from the first argument, and inserts it in the second argument. The - // instruction extracts the word from its second input register and inserts - // it into its first input register, so swap the first and second arguments. - std::swap(Ops[0], Ops[1]); - - // Need to cast the second argument from a vector of unsigned int to a - // vector of long long. - Ops[1] = Builder.CreateBitCast(Ops[1], llvm::VectorType::get(Int64Ty, 2)); - - if (getTarget().isLittleEndian()) { - // Create a shuffle mask of (1, 0) - Constant *ShuffleElts[2] = { ConstantInt::get(Int32Ty, 1), - ConstantInt::get(Int32Ty, 0) - }; - Constant *ShuffleMask = llvm::ConstantVector::get(ShuffleElts); - - // Reverse the double words in the vector we will extract from. - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int64Ty, 2)); - Ops[0] = Builder.CreateShuffleVector(Ops[0], Ops[0], ShuffleMask); - - // Reverse the index. - Index = MaxIndex - Index; - } - - // Intrinsic expects the first arg to be a vector of int. - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int32Ty, 4)); - Ops[2] = ConstantInt::getSigned(Int32Ty, Index); - return Builder.CreateCall(F, Ops); - } - - case PPC::BI__builtin_vsx_extractuword: { - llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_vsx_xxextractuw); - - // Intrinsic expects the first argument to be a vector of doublewords. - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int64Ty, 2)); - - // The second argument is a compile time constant int that needs to - // be clamped to the range [0, 12]. - ConstantInt *ArgCI = dyn_cast<ConstantInt>(Ops[1]); - assert(ArgCI && - "Second Arg to xxextractuw intrinsic must be a constant integer!"); - const int64_t MaxIndex = 12; - int64_t Index = clamp(ArgCI->getSExtValue(), 0, MaxIndex); - - if (getTarget().isLittleEndian()) { - // Reverse the index. - Index = MaxIndex - Index; - Ops[1] = ConstantInt::getSigned(Int32Ty, Index); - - // Emit the call, then reverse the double words of the results vector. - Value *Call = Builder.CreateCall(F, Ops); - - // Create a shuffle mask of (1, 0) - Constant *ShuffleElts[2] = { ConstantInt::get(Int32Ty, 1), - ConstantInt::get(Int32Ty, 0) - }; - Constant *ShuffleMask = llvm::ConstantVector::get(ShuffleElts); - - Value *ShuffleCall = Builder.CreateShuffleVector(Call, Call, ShuffleMask); - return ShuffleCall; - } else { - Ops[1] = ConstantInt::getSigned(Int32Ty, Index); - return Builder.CreateCall(F, Ops); - } - } - - case PPC::BI__builtin_vsx_xxpermdi: { - ConstantInt *ArgCI = dyn_cast<ConstantInt>(Ops[2]); - assert(ArgCI && "Third arg must be constant integer!"); - - unsigned Index = ArgCI->getZExtValue(); - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int64Ty, 2)); - Ops[1] = Builder.CreateBitCast(Ops[1], llvm::VectorType::get(Int64Ty, 2)); - - // Account for endianness by treating this as just a shuffle. So we use the - // same indices for both LE and BE in order to produce expected results in - // both cases. - unsigned ElemIdx0 = (Index & 2) >> 1; - unsigned ElemIdx1 = 2 + (Index & 1); - - Constant *ShuffleElts[2] = {ConstantInt::get(Int32Ty, ElemIdx0), - ConstantInt::get(Int32Ty, ElemIdx1)}; - Constant *ShuffleMask = llvm::ConstantVector::get(ShuffleElts); - - Value *ShuffleCall = - Builder.CreateShuffleVector(Ops[0], Ops[1], ShuffleMask); - QualType BIRetType = E->getType(); - auto RetTy = ConvertType(BIRetType); - return Builder.CreateBitCast(ShuffleCall, RetTy); - } - - case PPC::BI__builtin_vsx_xxsldwi: { - ConstantInt *ArgCI = dyn_cast<ConstantInt>(Ops[2]); - assert(ArgCI && "Third argument must be a compile time constant"); - unsigned Index = ArgCI->getZExtValue() & 0x3; - Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int32Ty, 4)); - Ops[1] = Builder.CreateBitCast(Ops[1], llvm::VectorType::get(Int32Ty, 4)); - - // Create a shuffle mask - unsigned ElemIdx0; - unsigned ElemIdx1; - unsigned ElemIdx2; - unsigned ElemIdx3; - if (getTarget().isLittleEndian()) { - // Little endian element N comes from element 8+N-Index of the - // concatenated wide vector (of course, using modulo arithmetic on - // the total number of elements). - ElemIdx0 = (8 - Index) % 8; - ElemIdx1 = (9 - Index) % 8; - ElemIdx2 = (10 - Index) % 8; - ElemIdx3 = (11 - Index) % 8; - } else { - // Big endian ElemIdx<N> = Index + N - ElemIdx0 = Index; - ElemIdx1 = Index + 1; - ElemIdx2 = Index + 2; - ElemIdx3 = Index + 3; - } - - Constant *ShuffleElts[4] = {ConstantInt::get(Int32Ty, ElemIdx0), - ConstantInt::get(Int32Ty, ElemIdx1), - ConstantInt::get(Int32Ty, ElemIdx2), - ConstantInt::get(Int32Ty, ElemIdx3)}; - - Constant *ShuffleMask = llvm::ConstantVector::get(ShuffleElts); - Value *ShuffleCall = - Builder.CreateShuffleVector(Ops[0], Ops[1], ShuffleMask); - QualType BIRetType = E->getType(); - auto RetTy = ConvertType(BIRetType); - return Builder.CreateBitCast(ShuffleCall, RetTy); - } - - case PPC::BI__builtin_pack_vector_int128: { - bool isLittleEndian = getTarget().isLittleEndian(); - Value *UndefValue = - llvm::UndefValue::get(llvm::VectorType::get(Ops[0]->getType(), 2)); - Value *Res = Builder.CreateInsertElement( - UndefValue, Ops[0], (uint64_t)(isLittleEndian ? 1 : 0)); - Res = Builder.CreateInsertElement(Res, Ops[1], - (uint64_t)(isLittleEndian ? 0 : 1)); - return Builder.CreateBitCast(Res, ConvertType(E->getType())); - } - - case PPC::BI__builtin_unpack_vector_int128: { - ConstantInt *Index = cast<ConstantInt>(Ops[1]); - Value *Unpacked = Builder.CreateBitCast( - Ops[0], llvm::VectorType::get(ConvertType(E->getType()), 2)); - - if (getTarget().isLittleEndian()) - Index = ConstantInt::get(Index->getType(), 1 - Index->getZExtValue()); - - return Builder.CreateExtractElement(Unpacked, Index); - } - } -} - -Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, - const CallExpr *E) { - switch (BuiltinID) { - case AMDGPU::BI__builtin_amdgcn_div_scale: - case AMDGPU::BI__builtin_amdgcn_div_scalef: { - // Translate from the intrinsics's struct return to the builtin's out - // argument. - - Address FlagOutPtr = EmitPointerWithAlignment(E->getArg(3)); - - llvm::Value *X = EmitScalarExpr(E->getArg(0)); - llvm::Value *Y = EmitScalarExpr(E->getArg(1)); - llvm::Value *Z = EmitScalarExpr(E->getArg(2)); - - llvm::Value *Callee = CGM.getIntrinsic(Intrinsic::amdgcn_div_scale, - X->getType()); - - llvm::Value *Tmp = Builder.CreateCall(Callee, {X, Y, Z}); - - llvm::Value *Result = Builder.CreateExtractValue(Tmp, 0); - llvm::Value *Flag = Builder.CreateExtractValue(Tmp, 1); - - llvm::Type *RealFlagType - = FlagOutPtr.getPointer()->getType()->getPointerElementType(); - - llvm::Value *FlagExt = Builder.CreateZExt(Flag, RealFlagType); - Builder.CreateStore(FlagExt, FlagOutPtr); - return Result; - } - case AMDGPU::BI__builtin_amdgcn_div_fmas: - case AMDGPU::BI__builtin_amdgcn_div_fmasf: { - llvm::Value *Src0 = EmitScalarExpr(E->getArg(0)); - llvm::Value *Src1 = EmitScalarExpr(E->getArg(1)); - llvm::Value *Src2 = EmitScalarExpr(E->getArg(2)); - llvm::Value *Src3 = EmitScalarExpr(E->getArg(3)); - - llvm::Value *F = CGM.getIntrinsic(Intrinsic::amdgcn_div_fmas, - Src0->getType()); - llvm::Value *Src3ToBool = Builder.CreateIsNotNull(Src3); - return Builder.CreateCall(F, {Src0, Src1, Src2, Src3ToBool}); - } - - case AMDGPU::BI__builtin_amdgcn_ds_swizzle: - return emitBinaryBuiltin(*this, E, Intrinsic::amdgcn_ds_swizzle); - case AMDGPU::BI__builtin_amdgcn_mov_dpp: - case AMDGPU::BI__builtin_amdgcn_update_dpp: { - llvm::SmallVector<llvm::Value *, 6> Args; - for (unsigned I = 0; I != E->getNumArgs(); ++I) - Args.push_back(EmitScalarExpr(E->getArg(I))); - assert(Args.size() == 5 || Args.size() == 6); - if (Args.size() == 5) - Args.insert(Args.begin(), llvm::UndefValue::get(Args[0]->getType())); - Value *F = - CGM.getIntrinsic(Intrinsic::amdgcn_update_dpp, Args[0]->getType()); - return Builder.CreateCall(F, Args); - } - case AMDGPU::BI__builtin_amdgcn_div_fixup: - case AMDGPU::BI__builtin_amdgcn_div_fixupf: - case AMDGPU::BI__builtin_amdgcn_div_fixuph: - return emitTernaryBuiltin(*this, E, Intrinsic::amdgcn_div_fixup); - case AMDGPU::BI__builtin_amdgcn_trig_preop: - case AMDGPU::BI__builtin_amdgcn_trig_preopf: - return emitFPIntBuiltin(*this, E, Intrinsic::amdgcn_trig_preop); - case AMDGPU::BI__builtin_amdgcn_rcp: - case AMDGPU::BI__builtin_amdgcn_rcpf: - case AMDGPU::BI__builtin_amdgcn_rcph: - return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_rcp); - case AMDGPU::BI__builtin_amdgcn_rsq: - case AMDGPU::BI__builtin_amdgcn_rsqf: - case AMDGPU::BI__builtin_amdgcn_rsqh: - return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_rsq); - case AMDGPU::BI__builtin_amdgcn_rsq_clamp: - case AMDGPU::BI__builtin_amdgcn_rsq_clampf: - return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_rsq_clamp); - case AMDGPU::BI__builtin_amdgcn_sinf: - case AMDGPU::BI__builtin_amdgcn_sinh: - return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_sin); - case AMDGPU::BI__builtin_amdgcn_cosf: - case AMDGPU::BI__builtin_amdgcn_cosh: - return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_cos); - case AMDGPU::BI__builtin_amdgcn_log_clampf: - return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_log_clamp); - case AMDGPU::BI__builtin_amdgcn_ldexp: - case AMDGPU::BI__builtin_amdgcn_ldexpf: - case AMDGPU::BI__builtin_amdgcn_ldexph: - return emitFPIntBuiltin(*this, E, Intrinsic::amdgcn_ldexp); - case AMDGPU::BI__builtin_amdgcn_frexp_mant: - case AMDGPU::BI__builtin_amdgcn_frexp_mantf: - case AMDGPU::BI__builtin_amdgcn_frexp_manth: - return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_frexp_mant); - case AMDGPU::BI__builtin_amdgcn_frexp_exp: - case AMDGPU::BI__builtin_amdgcn_frexp_expf: { - Value *Src0 = EmitScalarExpr(E->getArg(0)); - Value *F = CGM.getIntrinsic(Intrinsic::amdgcn_frexp_exp, - { Builder.getInt32Ty(), Src0->getType() }); - return Builder.CreateCall(F, Src0); - } - case AMDGPU::BI__builtin_amdgcn_frexp_exph: { - Value *Src0 = EmitScalarExpr(E->getArg(0)); - Value *F = CGM.getIntrinsic(Intrinsic::amdgcn_frexp_exp, - { Builder.getInt16Ty(), Src0->getType() }); - return Builder.CreateCall(F, Src0); - } - case AMDGPU::BI__builtin_amdgcn_fract: - case AMDGPU::BI__builtin_amdgcn_fractf: - case AMDGPU::BI__builtin_amdgcn_fracth: - return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_fract); - case AMDGPU::BI__builtin_amdgcn_lerp: - return emitTernaryBuiltin(*this, E, Intrinsic::amdgcn_lerp); - case AMDGPU::BI__builtin_amdgcn_uicmp: - case AMDGPU::BI__builtin_amdgcn_uicmpl: - case AMDGPU::BI__builtin_amdgcn_sicmp: - case AMDGPU::BI__builtin_amdgcn_sicmpl: - return emitTernaryBuiltin(*this, E, Intrinsic::amdgcn_icmp); - case AMDGPU::BI__builtin_amdgcn_fcmp: - case AMDGPU::BI__builtin_amdgcn_fcmpf: - return emitTernaryBuiltin(*this, E, Intrinsic::amdgcn_fcmp); - case AMDGPU::BI__builtin_amdgcn_class: - case AMDGPU::BI__builtin_amdgcn_classf: - case AMDGPU::BI__builtin_amdgcn_classh: - return emitFPIntBuiltin(*this, E, Intrinsic::amdgcn_class); - case AMDGPU::BI__builtin_amdgcn_fmed3f: - case AMDGPU::BI__builtin_amdgcn_fmed3h: - return emitTernaryBuiltin(*this, E, Intrinsic::amdgcn_fmed3); - case AMDGPU::BI__builtin_amdgcn_read_exec: { - CallInst *CI = cast<CallInst>( - EmitSpecialRegisterBuiltin(*this, E, Int64Ty, Int64Ty, true, "exec")); - CI->setConvergent(); - return CI; - } - case AMDGPU::BI__builtin_amdgcn_read_exec_lo: - case AMDGPU::BI__builtin_amdgcn_read_exec_hi: { - StringRef RegName = BuiltinID == AMDGPU::BI__builtin_amdgcn_read_exec_lo ? - "exec_lo" : "exec_hi"; - CallInst *CI = cast<CallInst>( - EmitSpecialRegisterBuiltin(*this, E, Int32Ty, Int32Ty, true, RegName)); - CI->setConvergent(); - return CI; - } - // amdgcn workitem - case AMDGPU::BI__builtin_amdgcn_workitem_id_x: - return emitRangedBuiltin(*this, Intrinsic::amdgcn_workitem_id_x, 0, 1024); - case AMDGPU::BI__builtin_amdgcn_workitem_id_y: - return emitRangedBuiltin(*this, Intrinsic::amdgcn_workitem_id_y, 0, 1024); - case AMDGPU::BI__builtin_amdgcn_workitem_id_z: - return emitRangedBuiltin(*this, Intrinsic::amdgcn_workitem_id_z, 0, 1024); - - // r600 intrinsics - case AMDGPU::BI__builtin_r600_recipsqrt_ieee: - case AMDGPU::BI__builtin_r600_recipsqrt_ieeef: - return emitUnaryBuiltin(*this, E, Intrinsic::r600_recipsqrt_ieee); - case AMDGPU::BI__builtin_r600_read_tidig_x: - return emitRangedBuiltin(*this, Intrinsic::r600_read_tidig_x, 0, 1024); - case AMDGPU::BI__builtin_r600_read_tidig_y: - return emitRangedBuiltin(*this, Intrinsic::r600_read_tidig_y, 0, 1024); - case AMDGPU::BI__builtin_r600_read_tidig_z: - return emitRangedBuiltin(*this, Intrinsic::r600_read_tidig_z, 0, 1024); - default: - return nullptr; - } -} - -/// Handle a SystemZ function in which the final argument is a pointer -/// to an int that receives the post-instruction CC value. At the LLVM level -/// this is represented as a function that returns a {result, cc} pair. -static Value *EmitSystemZIntrinsicWithCC(CodeGenFunction &CGF, - unsigned IntrinsicID, - const CallExpr *E) { - unsigned NumArgs = E->getNumArgs() - 1; - SmallVector<Value *, 8> Args(NumArgs); - for (unsigned I = 0; I < NumArgs; ++I) - Args[I] = CGF.EmitScalarExpr(E->getArg(I)); - Address CCPtr = CGF.EmitPointerWithAlignment(E->getArg(NumArgs)); - Value *F = CGF.CGM.getIntrinsic(IntrinsicID); - Value *Call = CGF.Builder.CreateCall(F, Args); - Value *CC = CGF.Builder.CreateExtractValue(Call, 1); - CGF.Builder.CreateStore(CC, CCPtr); - return CGF.Builder.CreateExtractValue(Call, 0); -} - -Value *CodeGenFunction::EmitSystemZBuiltinExpr(unsigned BuiltinID, - const CallExpr *E) { - switch (BuiltinID) { - case SystemZ::BI__builtin_tbegin: { - Value *TDB = EmitScalarExpr(E->getArg(0)); - Value *Control = llvm::ConstantInt::get(Int32Ty, 0xff0c); - Value *F = CGM.getIntrinsic(Intrinsic::s390_tbegin); - return Builder.CreateCall(F, {TDB, Control}); - } - case SystemZ::BI__builtin_tbegin_nofloat: { - Value *TDB = EmitScalarExpr(E->getArg(0)); - Value *Control = llvm::ConstantInt::get(Int32Ty, 0xff0c); - Value *F = CGM.getIntrinsic(Intrinsic::s390_tbegin_nofloat); - return Builder.CreateCall(F, {TDB, Control}); - } - case SystemZ::BI__builtin_tbeginc: { - Value *TDB = llvm::ConstantPointerNull::get(Int8PtrTy); - Value *Control = llvm::ConstantInt::get(Int32Ty, 0xff08); - Value *F = CGM.getIntrinsic(Intrinsic::s390_tbeginc); - return Builder.CreateCall(F, {TDB, Control}); - } - case SystemZ::BI__builtin_tabort: { - Value *Data = EmitScalarExpr(E->getArg(0)); - Value *F = CGM.getIntrinsic(Intrinsic::s390_tabort); - return Builder.CreateCall(F, Builder.CreateSExt(Data, Int64Ty, "tabort")); - } - case SystemZ::BI__builtin_non_tx_store: { - Value *Address = EmitScalarExpr(E->getArg(0)); - Value *Data = EmitScalarExpr(E->getArg(1)); - Value *F = CGM.getIntrinsic(Intrinsic::s390_ntstg); - return Builder.CreateCall(F, {Data, Address}); - } - - // Vector builtins. Note that most vector builtins are mapped automatically - // to target-specific LLVM intrinsics. The ones handled specially here can - // be represented via standard LLVM IR, which is preferable to enable common - // LLVM optimizations. - - case SystemZ::BI__builtin_s390_vpopctb: - case SystemZ::BI__builtin_s390_vpopcth: - case SystemZ::BI__builtin_s390_vpopctf: - case SystemZ::BI__builtin_s390_vpopctg: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ResultType); - return Builder.CreateCall(F, X); - } - - case SystemZ::BI__builtin_s390_vclzb: - case SystemZ::BI__builtin_s390_vclzh: - case SystemZ::BI__builtin_s390_vclzf: - case SystemZ::BI__builtin_s390_vclzg: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - Value *Undef = ConstantInt::get(Builder.getInt1Ty(), false); - Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ResultType); - return Builder.CreateCall(F, {X, Undef}); - } - - case SystemZ::BI__builtin_s390_vctzb: - case SystemZ::BI__builtin_s390_vctzh: - case SystemZ::BI__builtin_s390_vctzf: - case SystemZ::BI__builtin_s390_vctzg: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - Value *Undef = ConstantInt::get(Builder.getInt1Ty(), false); - Function *F = CGM.getIntrinsic(Intrinsic::cttz, ResultType); - return Builder.CreateCall(F, {X, Undef}); - } - - case SystemZ::BI__builtin_s390_vfsqsb: - case SystemZ::BI__builtin_s390_vfsqdb: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - Function *F = CGM.getIntrinsic(Intrinsic::sqrt, ResultType); - return Builder.CreateCall(F, X); - } - case SystemZ::BI__builtin_s390_vfmasb: - case SystemZ::BI__builtin_s390_vfmadb: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - Value *Y = EmitScalarExpr(E->getArg(1)); - Value *Z = EmitScalarExpr(E->getArg(2)); - Function *F = CGM.getIntrinsic(Intrinsic::fma, ResultType); - return Builder.CreateCall(F, {X, Y, Z}); - } - case SystemZ::BI__builtin_s390_vfmssb: - case SystemZ::BI__builtin_s390_vfmsdb: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - Value *Y = EmitScalarExpr(E->getArg(1)); - Value *Z = EmitScalarExpr(E->getArg(2)); - Value *Zero = llvm::ConstantFP::getZeroValueForNegation(ResultType); - Function *F = CGM.getIntrinsic(Intrinsic::fma, ResultType); - return Builder.CreateCall(F, {X, Y, Builder.CreateFSub(Zero, Z, "sub")}); - } - case SystemZ::BI__builtin_s390_vfnmasb: - case SystemZ::BI__builtin_s390_vfnmadb: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - Value *Y = EmitScalarExpr(E->getArg(1)); - Value *Z = EmitScalarExpr(E->getArg(2)); - Value *Zero = llvm::ConstantFP::getZeroValueForNegation(ResultType); - Function *F = CGM.getIntrinsic(Intrinsic::fma, ResultType); - return Builder.CreateFSub(Zero, Builder.CreateCall(F, {X, Y, Z}), "sub"); - } - case SystemZ::BI__builtin_s390_vfnmssb: - case SystemZ::BI__builtin_s390_vfnmsdb: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - Value *Y = EmitScalarExpr(E->getArg(1)); - Value *Z = EmitScalarExpr(E->getArg(2)); - Value *Zero = llvm::ConstantFP::getZeroValueForNegation(ResultType); - Function *F = CGM.getIntrinsic(Intrinsic::fma, ResultType); - Value *NegZ = Builder.CreateFSub(Zero, Z, "sub"); - return Builder.CreateFSub(Zero, Builder.CreateCall(F, {X, Y, NegZ})); - } - case SystemZ::BI__builtin_s390_vflpsb: - case SystemZ::BI__builtin_s390_vflpdb: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - Function *F = CGM.getIntrinsic(Intrinsic::fabs, ResultType); - return Builder.CreateCall(F, X); - } - case SystemZ::BI__builtin_s390_vflnsb: - case SystemZ::BI__builtin_s390_vflndb: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - Value *Zero = llvm::ConstantFP::getZeroValueForNegation(ResultType); - Function *F = CGM.getIntrinsic(Intrinsic::fabs, ResultType); - return Builder.CreateFSub(Zero, Builder.CreateCall(F, X), "sub"); - } - case SystemZ::BI__builtin_s390_vfisb: - case SystemZ::BI__builtin_s390_vfidb: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - // Constant-fold the M4 and M5 mask arguments. - llvm::APSInt M4, M5; - bool IsConstM4 = E->getArg(1)->isIntegerConstantExpr(M4, getContext()); - bool IsConstM5 = E->getArg(2)->isIntegerConstantExpr(M5, getContext()); - assert(IsConstM4 && IsConstM5 && "Constant arg isn't actually constant?"); - (void)IsConstM4; (void)IsConstM5; - // Check whether this instance can be represented via a LLVM standard - // intrinsic. We only support some combinations of M4 and M5. - Intrinsic::ID ID = Intrinsic::not_intrinsic; - switch (M4.getZExtValue()) { - default: break; - case 0: // IEEE-inexact exception allowed - switch (M5.getZExtValue()) { - default: break; - case 0: ID = Intrinsic::rint; break; - } - break; - case 4: // IEEE-inexact exception suppressed - switch (M5.getZExtValue()) { - default: break; - case 0: ID = Intrinsic::nearbyint; break; - case 1: ID = Intrinsic::round; break; - case 5: ID = Intrinsic::trunc; break; - case 6: ID = Intrinsic::ceil; break; - case 7: ID = Intrinsic::floor; break; - } - break; - } - if (ID != Intrinsic::not_intrinsic) { - Function *F = CGM.getIntrinsic(ID, ResultType); - return Builder.CreateCall(F, X); - } - switch (BuiltinID) { - case SystemZ::BI__builtin_s390_vfisb: ID = Intrinsic::s390_vfisb; break; - case SystemZ::BI__builtin_s390_vfidb: ID = Intrinsic::s390_vfidb; break; - default: llvm_unreachable("Unknown BuiltinID"); - } - Function *F = CGM.getIntrinsic(ID); - Value *M4Value = llvm::ConstantInt::get(getLLVMContext(), M4); - Value *M5Value = llvm::ConstantInt::get(getLLVMContext(), M5); - return Builder.CreateCall(F, {X, M4Value, M5Value}); - } - case SystemZ::BI__builtin_s390_vfmaxsb: - case SystemZ::BI__builtin_s390_vfmaxdb: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - Value *Y = EmitScalarExpr(E->getArg(1)); - // Constant-fold the M4 mask argument. - llvm::APSInt M4; - bool IsConstM4 = E->getArg(2)->isIntegerConstantExpr(M4, getContext()); - assert(IsConstM4 && "Constant arg isn't actually constant?"); - (void)IsConstM4; - // Check whether this instance can be represented via a LLVM standard - // intrinsic. We only support some values of M4. - Intrinsic::ID ID = Intrinsic::not_intrinsic; - switch (M4.getZExtValue()) { - default: break; - case 4: ID = Intrinsic::maxnum; break; - } - if (ID != Intrinsic::not_intrinsic) { - Function *F = CGM.getIntrinsic(ID, ResultType); - return Builder.CreateCall(F, {X, Y}); - } - switch (BuiltinID) { - case SystemZ::BI__builtin_s390_vfmaxsb: ID = Intrinsic::s390_vfmaxsb; break; - case SystemZ::BI__builtin_s390_vfmaxdb: ID = Intrinsic::s390_vfmaxdb; break; - default: llvm_unreachable("Unknown BuiltinID"); - } - Function *F = CGM.getIntrinsic(ID); - Value *M4Value = llvm::ConstantInt::get(getLLVMContext(), M4); - return Builder.CreateCall(F, {X, Y, M4Value}); - } - case SystemZ::BI__builtin_s390_vfminsb: - case SystemZ::BI__builtin_s390_vfmindb: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *X = EmitScalarExpr(E->getArg(0)); - Value *Y = EmitScalarExpr(E->getArg(1)); - // Constant-fold the M4 mask argument. - llvm::APSInt M4; - bool IsConstM4 = E->getArg(2)->isIntegerConstantExpr(M4, getContext()); - assert(IsConstM4 && "Constant arg isn't actually constant?"); - (void)IsConstM4; - // Check whether this instance can be represented via a LLVM standard - // intrinsic. We only support some values of M4. - Intrinsic::ID ID = Intrinsic::not_intrinsic; - switch (M4.getZExtValue()) { - default: break; - case 4: ID = Intrinsic::minnum; break; - } - if (ID != Intrinsic::not_intrinsic) { - Function *F = CGM.getIntrinsic(ID, ResultType); - return Builder.CreateCall(F, {X, Y}); - } - switch (BuiltinID) { - case SystemZ::BI__builtin_s390_vfminsb: ID = Intrinsic::s390_vfminsb; break; - case SystemZ::BI__builtin_s390_vfmindb: ID = Intrinsic::s390_vfmindb; break; - default: llvm_unreachable("Unknown BuiltinID"); - } - Function *F = CGM.getIntrinsic(ID); - Value *M4Value = llvm::ConstantInt::get(getLLVMContext(), M4); - return Builder.CreateCall(F, {X, Y, M4Value}); - } - - // Vector intrinsics that output the post-instruction CC value. - -#define INTRINSIC_WITH_CC(NAME) \ - case SystemZ::BI__builtin_##NAME: \ - return EmitSystemZIntrinsicWithCC(*this, Intrinsic::NAME, E) - - INTRINSIC_WITH_CC(s390_vpkshs); - INTRINSIC_WITH_CC(s390_vpksfs); - INTRINSIC_WITH_CC(s390_vpksgs); - - INTRINSIC_WITH_CC(s390_vpklshs); - INTRINSIC_WITH_CC(s390_vpklsfs); - INTRINSIC_WITH_CC(s390_vpklsgs); - - INTRINSIC_WITH_CC(s390_vceqbs); - INTRINSIC_WITH_CC(s390_vceqhs); - INTRINSIC_WITH_CC(s390_vceqfs); - INTRINSIC_WITH_CC(s390_vceqgs); - - INTRINSIC_WITH_CC(s390_vchbs); - INTRINSIC_WITH_CC(s390_vchhs); - INTRINSIC_WITH_CC(s390_vchfs); - INTRINSIC_WITH_CC(s390_vchgs); - - INTRINSIC_WITH_CC(s390_vchlbs); - INTRINSIC_WITH_CC(s390_vchlhs); - INTRINSIC_WITH_CC(s390_vchlfs); - INTRINSIC_WITH_CC(s390_vchlgs); - - INTRINSIC_WITH_CC(s390_vfaebs); - INTRINSIC_WITH_CC(s390_vfaehs); - INTRINSIC_WITH_CC(s390_vfaefs); - - INTRINSIC_WITH_CC(s390_vfaezbs); - INTRINSIC_WITH_CC(s390_vfaezhs); - INTRINSIC_WITH_CC(s390_vfaezfs); - - INTRINSIC_WITH_CC(s390_vfeebs); - INTRINSIC_WITH_CC(s390_vfeehs); - INTRINSIC_WITH_CC(s390_vfeefs); - - INTRINSIC_WITH_CC(s390_vfeezbs); - INTRINSIC_WITH_CC(s390_vfeezhs); - INTRINSIC_WITH_CC(s390_vfeezfs); - - INTRINSIC_WITH_CC(s390_vfenebs); - INTRINSIC_WITH_CC(s390_vfenehs); - INTRINSIC_WITH_CC(s390_vfenefs); - - INTRINSIC_WITH_CC(s390_vfenezbs); - INTRINSIC_WITH_CC(s390_vfenezhs); - INTRINSIC_WITH_CC(s390_vfenezfs); - - INTRINSIC_WITH_CC(s390_vistrbs); - INTRINSIC_WITH_CC(s390_vistrhs); - INTRINSIC_WITH_CC(s390_vistrfs); - - INTRINSIC_WITH_CC(s390_vstrcbs); - INTRINSIC_WITH_CC(s390_vstrchs); - INTRINSIC_WITH_CC(s390_vstrcfs); - - INTRINSIC_WITH_CC(s390_vstrczbs); - INTRINSIC_WITH_CC(s390_vstrczhs); - INTRINSIC_WITH_CC(s390_vstrczfs); - - INTRINSIC_WITH_CC(s390_vfcesbs); - INTRINSIC_WITH_CC(s390_vfcedbs); - INTRINSIC_WITH_CC(s390_vfchsbs); - INTRINSIC_WITH_CC(s390_vfchdbs); - INTRINSIC_WITH_CC(s390_vfchesbs); - INTRINSIC_WITH_CC(s390_vfchedbs); - - INTRINSIC_WITH_CC(s390_vftcisb); - INTRINSIC_WITH_CC(s390_vftcidb); - -#undef INTRINSIC_WITH_CC - - default: - return nullptr; - } -} - -Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, - const CallExpr *E) { - auto MakeLdg = [&](unsigned IntrinsicID) { - Value *Ptr = EmitScalarExpr(E->getArg(0)); - clang::CharUnits Align = - getNaturalPointeeTypeAlignment(E->getArg(0)->getType()); - return Builder.CreateCall( - CGM.getIntrinsic(IntrinsicID, {Ptr->getType()->getPointerElementType(), - Ptr->getType()}), - {Ptr, ConstantInt::get(Builder.getInt32Ty(), Align.getQuantity())}); - }; - auto MakeScopedAtomic = [&](unsigned IntrinsicID) { - Value *Ptr = EmitScalarExpr(E->getArg(0)); - return Builder.CreateCall( - CGM.getIntrinsic(IntrinsicID, {Ptr->getType()->getPointerElementType(), - Ptr->getType()}), - {Ptr, EmitScalarExpr(E->getArg(1))}); - }; - switch (BuiltinID) { - case NVPTX::BI__nvvm_atom_add_gen_i: - case NVPTX::BI__nvvm_atom_add_gen_l: - case NVPTX::BI__nvvm_atom_add_gen_ll: - return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Add, E); - - case NVPTX::BI__nvvm_atom_sub_gen_i: - case NVPTX::BI__nvvm_atom_sub_gen_l: - case NVPTX::BI__nvvm_atom_sub_gen_ll: - return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Sub, E); - - case NVPTX::BI__nvvm_atom_and_gen_i: - case NVPTX::BI__nvvm_atom_and_gen_l: - case NVPTX::BI__nvvm_atom_and_gen_ll: - return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::And, E); - - case NVPTX::BI__nvvm_atom_or_gen_i: - case NVPTX::BI__nvvm_atom_or_gen_l: - case NVPTX::BI__nvvm_atom_or_gen_ll: - return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Or, E); - - case NVPTX::BI__nvvm_atom_xor_gen_i: - case NVPTX::BI__nvvm_atom_xor_gen_l: - case NVPTX::BI__nvvm_atom_xor_gen_ll: - return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Xor, E); - - case NVPTX::BI__nvvm_atom_xchg_gen_i: - case NVPTX::BI__nvvm_atom_xchg_gen_l: - case NVPTX::BI__nvvm_atom_xchg_gen_ll: - return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Xchg, E); - - case NVPTX::BI__nvvm_atom_max_gen_i: - case NVPTX::BI__nvvm_atom_max_gen_l: - case NVPTX::BI__nvvm_atom_max_gen_ll: - return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Max, E); - - case NVPTX::BI__nvvm_atom_max_gen_ui: - case NVPTX::BI__nvvm_atom_max_gen_ul: - case NVPTX::BI__nvvm_atom_max_gen_ull: - return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::UMax, E); - - case NVPTX::BI__nvvm_atom_min_gen_i: - case NVPTX::BI__nvvm_atom_min_gen_l: - case NVPTX::BI__nvvm_atom_min_gen_ll: - return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Min, E); - - case NVPTX::BI__nvvm_atom_min_gen_ui: - case NVPTX::BI__nvvm_atom_min_gen_ul: - case NVPTX::BI__nvvm_atom_min_gen_ull: - return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::UMin, E); - - case NVPTX::BI__nvvm_atom_cas_gen_i: - case NVPTX::BI__nvvm_atom_cas_gen_l: - case NVPTX::BI__nvvm_atom_cas_gen_ll: - // __nvvm_atom_cas_gen_* should return the old value rather than the - // success flag. - return MakeAtomicCmpXchgValue(*this, E, /*ReturnBool=*/false); - - case NVPTX::BI__nvvm_atom_add_gen_f: { - Value *Ptr = EmitScalarExpr(E->getArg(0)); - Value *Val = EmitScalarExpr(E->getArg(1)); - // atomicrmw only deals with integer arguments so we need to use - // LLVM's nvvm_atomic_load_add_f32 intrinsic for that. - Value *FnALAF32 = - CGM.getIntrinsic(Intrinsic::nvvm_atomic_load_add_f32, Ptr->getType()); - return Builder.CreateCall(FnALAF32, {Ptr, Val}); - } - - case NVPTX::BI__nvvm_atom_add_gen_d: { - Value *Ptr = EmitScalarExpr(E->getArg(0)); - Value *Val = EmitScalarExpr(E->getArg(1)); - // atomicrmw only deals with integer arguments, so we need to use - // LLVM's nvvm_atomic_load_add_f64 intrinsic. - Value *FnALAF64 = - CGM.getIntrinsic(Intrinsic::nvvm_atomic_load_add_f64, Ptr->getType()); - return Builder.CreateCall(FnALAF64, {Ptr, Val}); - } - - case NVPTX::BI__nvvm_atom_inc_gen_ui: { - Value *Ptr = EmitScalarExpr(E->getArg(0)); - Value *Val = EmitScalarExpr(E->getArg(1)); - Value *FnALI32 = - CGM.getIntrinsic(Intrinsic::nvvm_atomic_load_inc_32, Ptr->getType()); - return Builder.CreateCall(FnALI32, {Ptr, Val}); - } - - case NVPTX::BI__nvvm_atom_dec_gen_ui: { - Value *Ptr = EmitScalarExpr(E->getArg(0)); - Value *Val = EmitScalarExpr(E->getArg(1)); - Value *FnALD32 = - CGM.getIntrinsic(Intrinsic::nvvm_atomic_load_dec_32, Ptr->getType()); - return Builder.CreateCall(FnALD32, {Ptr, Val}); - } - - case NVPTX::BI__nvvm_ldg_c: - case NVPTX::BI__nvvm_ldg_c2: - case NVPTX::BI__nvvm_ldg_c4: - case NVPTX::BI__nvvm_ldg_s: - case NVPTX::BI__nvvm_ldg_s2: - case NVPTX::BI__nvvm_ldg_s4: - case NVPTX::BI__nvvm_ldg_i: - case NVPTX::BI__nvvm_ldg_i2: - case NVPTX::BI__nvvm_ldg_i4: - case NVPTX::BI__nvvm_ldg_l: - case NVPTX::BI__nvvm_ldg_ll: - case NVPTX::BI__nvvm_ldg_ll2: - case NVPTX::BI__nvvm_ldg_uc: - case NVPTX::BI__nvvm_ldg_uc2: - case NVPTX::BI__nvvm_ldg_uc4: - case NVPTX::BI__nvvm_ldg_us: - case NVPTX::BI__nvvm_ldg_us2: - case NVPTX::BI__nvvm_ldg_us4: - case NVPTX::BI__nvvm_ldg_ui: - case NVPTX::BI__nvvm_ldg_ui2: - case NVPTX::BI__nvvm_ldg_ui4: - case NVPTX::BI__nvvm_ldg_ul: - case NVPTX::BI__nvvm_ldg_ull: - case NVPTX::BI__nvvm_ldg_ull2: - // PTX Interoperability section 2.2: "For a vector with an even number of - // elements, its alignment is set to number of elements times the alignment - // of its member: n*alignof(t)." - return MakeLdg(Intrinsic::nvvm_ldg_global_i); - case NVPTX::BI__nvvm_ldg_f: - case NVPTX::BI__nvvm_ldg_f2: - case NVPTX::BI__nvvm_ldg_f4: - case NVPTX::BI__nvvm_ldg_d: - case NVPTX::BI__nvvm_ldg_d2: - return MakeLdg(Intrinsic::nvvm_ldg_global_f); - - case NVPTX::BI__nvvm_atom_cta_add_gen_i: - case NVPTX::BI__nvvm_atom_cta_add_gen_l: - case NVPTX::BI__nvvm_atom_cta_add_gen_ll: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_add_gen_i_cta); - case NVPTX::BI__nvvm_atom_sys_add_gen_i: - case NVPTX::BI__nvvm_atom_sys_add_gen_l: - case NVPTX::BI__nvvm_atom_sys_add_gen_ll: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_add_gen_i_sys); - case NVPTX::BI__nvvm_atom_cta_add_gen_f: - case NVPTX::BI__nvvm_atom_cta_add_gen_d: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_add_gen_f_cta); - case NVPTX::BI__nvvm_atom_sys_add_gen_f: - case NVPTX::BI__nvvm_atom_sys_add_gen_d: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_add_gen_f_sys); - case NVPTX::BI__nvvm_atom_cta_xchg_gen_i: - case NVPTX::BI__nvvm_atom_cta_xchg_gen_l: - case NVPTX::BI__nvvm_atom_cta_xchg_gen_ll: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_exch_gen_i_cta); - case NVPTX::BI__nvvm_atom_sys_xchg_gen_i: - case NVPTX::BI__nvvm_atom_sys_xchg_gen_l: - case NVPTX::BI__nvvm_atom_sys_xchg_gen_ll: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_exch_gen_i_sys); - case NVPTX::BI__nvvm_atom_cta_max_gen_i: - case NVPTX::BI__nvvm_atom_cta_max_gen_ui: - case NVPTX::BI__nvvm_atom_cta_max_gen_l: - case NVPTX::BI__nvvm_atom_cta_max_gen_ul: - case NVPTX::BI__nvvm_atom_cta_max_gen_ll: - case NVPTX::BI__nvvm_atom_cta_max_gen_ull: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_max_gen_i_cta); - case NVPTX::BI__nvvm_atom_sys_max_gen_i: - case NVPTX::BI__nvvm_atom_sys_max_gen_ui: - case NVPTX::BI__nvvm_atom_sys_max_gen_l: - case NVPTX::BI__nvvm_atom_sys_max_gen_ul: - case NVPTX::BI__nvvm_atom_sys_max_gen_ll: - case NVPTX::BI__nvvm_atom_sys_max_gen_ull: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_max_gen_i_sys); - case NVPTX::BI__nvvm_atom_cta_min_gen_i: - case NVPTX::BI__nvvm_atom_cta_min_gen_ui: - case NVPTX::BI__nvvm_atom_cta_min_gen_l: - case NVPTX::BI__nvvm_atom_cta_min_gen_ul: - case NVPTX::BI__nvvm_atom_cta_min_gen_ll: - case NVPTX::BI__nvvm_atom_cta_min_gen_ull: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_min_gen_i_cta); - case NVPTX::BI__nvvm_atom_sys_min_gen_i: - case NVPTX::BI__nvvm_atom_sys_min_gen_ui: - case NVPTX::BI__nvvm_atom_sys_min_gen_l: - case NVPTX::BI__nvvm_atom_sys_min_gen_ul: - case NVPTX::BI__nvvm_atom_sys_min_gen_ll: - case NVPTX::BI__nvvm_atom_sys_min_gen_ull: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_min_gen_i_sys); - case NVPTX::BI__nvvm_atom_cta_inc_gen_ui: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_inc_gen_i_cta); - case NVPTX::BI__nvvm_atom_cta_dec_gen_ui: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_dec_gen_i_cta); - case NVPTX::BI__nvvm_atom_sys_inc_gen_ui: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_inc_gen_i_sys); - case NVPTX::BI__nvvm_atom_sys_dec_gen_ui: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_dec_gen_i_sys); - case NVPTX::BI__nvvm_atom_cta_and_gen_i: - case NVPTX::BI__nvvm_atom_cta_and_gen_l: - case NVPTX::BI__nvvm_atom_cta_and_gen_ll: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_and_gen_i_cta); - case NVPTX::BI__nvvm_atom_sys_and_gen_i: - case NVPTX::BI__nvvm_atom_sys_and_gen_l: - case NVPTX::BI__nvvm_atom_sys_and_gen_ll: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_and_gen_i_sys); - case NVPTX::BI__nvvm_atom_cta_or_gen_i: - case NVPTX::BI__nvvm_atom_cta_or_gen_l: - case NVPTX::BI__nvvm_atom_cta_or_gen_ll: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_or_gen_i_cta); - case NVPTX::BI__nvvm_atom_sys_or_gen_i: - case NVPTX::BI__nvvm_atom_sys_or_gen_l: - case NVPTX::BI__nvvm_atom_sys_or_gen_ll: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_or_gen_i_sys); - case NVPTX::BI__nvvm_atom_cta_xor_gen_i: - case NVPTX::BI__nvvm_atom_cta_xor_gen_l: - case NVPTX::BI__nvvm_atom_cta_xor_gen_ll: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_xor_gen_i_cta); - case NVPTX::BI__nvvm_atom_sys_xor_gen_i: - case NVPTX::BI__nvvm_atom_sys_xor_gen_l: - case NVPTX::BI__nvvm_atom_sys_xor_gen_ll: - return MakeScopedAtomic(Intrinsic::nvvm_atomic_xor_gen_i_sys); - case NVPTX::BI__nvvm_atom_cta_cas_gen_i: - case NVPTX::BI__nvvm_atom_cta_cas_gen_l: - case NVPTX::BI__nvvm_atom_cta_cas_gen_ll: { - Value *Ptr = EmitScalarExpr(E->getArg(0)); - return Builder.CreateCall( - CGM.getIntrinsic( - Intrinsic::nvvm_atomic_cas_gen_i_cta, - {Ptr->getType()->getPointerElementType(), Ptr->getType()}), - {Ptr, EmitScalarExpr(E->getArg(1)), EmitScalarExpr(E->getArg(2))}); - } - case NVPTX::BI__nvvm_atom_sys_cas_gen_i: - case NVPTX::BI__nvvm_atom_sys_cas_gen_l: - case NVPTX::BI__nvvm_atom_sys_cas_gen_ll: { - Value *Ptr = EmitScalarExpr(E->getArg(0)); - return Builder.CreateCall( - CGM.getIntrinsic( - Intrinsic::nvvm_atomic_cas_gen_i_sys, - {Ptr->getType()->getPointerElementType(), Ptr->getType()}), - {Ptr, EmitScalarExpr(E->getArg(1)), EmitScalarExpr(E->getArg(2))}); - } - case NVPTX::BI__nvvm_match_all_sync_i32p: - case NVPTX::BI__nvvm_match_all_sync_i64p: { - Value *Mask = EmitScalarExpr(E->getArg(0)); - Value *Val = EmitScalarExpr(E->getArg(1)); - Address PredOutPtr = EmitPointerWithAlignment(E->getArg(2)); - Value *ResultPair = Builder.CreateCall( - CGM.getIntrinsic(BuiltinID == NVPTX::BI__nvvm_match_all_sync_i32p - ? Intrinsic::nvvm_match_all_sync_i32p - : Intrinsic::nvvm_match_all_sync_i64p), - {Mask, Val}); - Value *Pred = Builder.CreateZExt(Builder.CreateExtractValue(ResultPair, 1), - PredOutPtr.getElementType()); - Builder.CreateStore(Pred, PredOutPtr); - return Builder.CreateExtractValue(ResultPair, 0); - } - case NVPTX::BI__hmma_m16n16k16_ld_a: - case NVPTX::BI__hmma_m16n16k16_ld_b: - case NVPTX::BI__hmma_m16n16k16_ld_c_f16: - case NVPTX::BI__hmma_m16n16k16_ld_c_f32: - case NVPTX::BI__hmma_m32n8k16_ld_a: - case NVPTX::BI__hmma_m32n8k16_ld_b: - case NVPTX::BI__hmma_m32n8k16_ld_c_f16: - case NVPTX::BI__hmma_m32n8k16_ld_c_f32: - case NVPTX::BI__hmma_m8n32k16_ld_a: - case NVPTX::BI__hmma_m8n32k16_ld_b: - case NVPTX::BI__hmma_m8n32k16_ld_c_f16: - case NVPTX::BI__hmma_m8n32k16_ld_c_f32: { - Address Dst = EmitPointerWithAlignment(E->getArg(0)); - Value *Src = EmitScalarExpr(E->getArg(1)); - Value *Ldm = EmitScalarExpr(E->getArg(2)); - llvm::APSInt isColMajorArg; - if (!E->getArg(3)->isIntegerConstantExpr(isColMajorArg, getContext())) - return nullptr; - bool isColMajor = isColMajorArg.getSExtValue(); - unsigned IID; - unsigned NumResults; - switch (BuiltinID) { - case NVPTX::BI__hmma_m16n16k16_ld_a: - IID = isColMajor ? Intrinsic::nvvm_wmma_m16n16k16_load_a_f16_col_stride - : Intrinsic::nvvm_wmma_m16n16k16_load_a_f16_row_stride; - NumResults = 8; - break; - case NVPTX::BI__hmma_m16n16k16_ld_b: - IID = isColMajor ? Intrinsic::nvvm_wmma_m16n16k16_load_b_f16_col_stride - : Intrinsic::nvvm_wmma_m16n16k16_load_b_f16_row_stride; - NumResults = 8; - break; - case NVPTX::BI__hmma_m16n16k16_ld_c_f16: - IID = isColMajor ? Intrinsic::nvvm_wmma_m16n16k16_load_c_f16_col_stride - : Intrinsic::nvvm_wmma_m16n16k16_load_c_f16_row_stride; - NumResults = 4; - break; - case NVPTX::BI__hmma_m16n16k16_ld_c_f32: - IID = isColMajor ? Intrinsic::nvvm_wmma_m16n16k16_load_c_f32_col_stride - : Intrinsic::nvvm_wmma_m16n16k16_load_c_f32_row_stride; - NumResults = 8; - break; - case NVPTX::BI__hmma_m32n8k16_ld_a: - IID = isColMajor ? Intrinsic::nvvm_wmma_m32n8k16_load_a_f16_col_stride - : Intrinsic::nvvm_wmma_m32n8k16_load_a_f16_row_stride; - NumResults = 8; - break; - case NVPTX::BI__hmma_m32n8k16_ld_b: - IID = isColMajor ? Intrinsic::nvvm_wmma_m32n8k16_load_b_f16_col_stride - : Intrinsic::nvvm_wmma_m32n8k16_load_b_f16_row_stride; - NumResults = 8; - break; - case NVPTX::BI__hmma_m32n8k16_ld_c_f16: - IID = isColMajor ? Intrinsic::nvvm_wmma_m32n8k16_load_c_f16_col_stride - : Intrinsic::nvvm_wmma_m32n8k16_load_c_f16_row_stride; - NumResults = 4; - break; - case NVPTX::BI__hmma_m32n8k16_ld_c_f32: - IID = isColMajor ? Intrinsic::nvvm_wmma_m32n8k16_load_c_f32_col_stride - : Intrinsic::nvvm_wmma_m32n8k16_load_c_f32_row_stride; - NumResults = 8; - break; - case NVPTX::BI__hmma_m8n32k16_ld_a: - IID = isColMajor ? Intrinsic::nvvm_wmma_m8n32k16_load_a_f16_col_stride - : Intrinsic::nvvm_wmma_m8n32k16_load_a_f16_row_stride; - NumResults = 8; - break; - case NVPTX::BI__hmma_m8n32k16_ld_b: - IID = isColMajor ? Intrinsic::nvvm_wmma_m8n32k16_load_b_f16_col_stride - : Intrinsic::nvvm_wmma_m8n32k16_load_b_f16_row_stride; - NumResults = 8; - break; - case NVPTX::BI__hmma_m8n32k16_ld_c_f16: - IID = isColMajor ? Intrinsic::nvvm_wmma_m8n32k16_load_c_f16_col_stride - : Intrinsic::nvvm_wmma_m8n32k16_load_c_f16_row_stride; - NumResults = 4; - break; - case NVPTX::BI__hmma_m8n32k16_ld_c_f32: - IID = isColMajor ? Intrinsic::nvvm_wmma_m8n32k16_load_c_f32_col_stride - : Intrinsic::nvvm_wmma_m8n32k16_load_c_f32_row_stride; - NumResults = 8; - break; - default: - llvm_unreachable("Unexpected builtin ID."); - } - Value *Result = - Builder.CreateCall(CGM.getIntrinsic(IID, Src->getType()), {Src, Ldm}); - - // Save returned values. - for (unsigned i = 0; i < NumResults; ++i) { - Builder.CreateAlignedStore( - Builder.CreateBitCast(Builder.CreateExtractValue(Result, i), - Dst.getElementType()), - Builder.CreateGEP(Dst.getPointer(), llvm::ConstantInt::get(IntTy, i)), - CharUnits::fromQuantity(4)); - } - return Result; - } - - case NVPTX::BI__hmma_m16n16k16_st_c_f16: - case NVPTX::BI__hmma_m16n16k16_st_c_f32: - case NVPTX::BI__hmma_m32n8k16_st_c_f16: - case NVPTX::BI__hmma_m32n8k16_st_c_f32: - case NVPTX::BI__hmma_m8n32k16_st_c_f16: - case NVPTX::BI__hmma_m8n32k16_st_c_f32: { - Value *Dst = EmitScalarExpr(E->getArg(0)); - Address Src = EmitPointerWithAlignment(E->getArg(1)); - Value *Ldm = EmitScalarExpr(E->getArg(2)); - llvm::APSInt isColMajorArg; - if (!E->getArg(3)->isIntegerConstantExpr(isColMajorArg, getContext())) - return nullptr; - bool isColMajor = isColMajorArg.getSExtValue(); - unsigned IID; - unsigned NumResults = 8; - // PTX Instructions (and LLVM intrinsics) are defined for slice _d_, yet - // for some reason nvcc builtins use _c_. - switch (BuiltinID) { - case NVPTX::BI__hmma_m16n16k16_st_c_f16: - IID = isColMajor ? Intrinsic::nvvm_wmma_m16n16k16_store_d_f16_col_stride - : Intrinsic::nvvm_wmma_m16n16k16_store_d_f16_row_stride; - NumResults = 4; - break; - case NVPTX::BI__hmma_m16n16k16_st_c_f32: - IID = isColMajor ? Intrinsic::nvvm_wmma_m16n16k16_store_d_f32_col_stride - : Intrinsic::nvvm_wmma_m16n16k16_store_d_f32_row_stride; - break; - case NVPTX::BI__hmma_m32n8k16_st_c_f16: - IID = isColMajor ? Intrinsic::nvvm_wmma_m32n8k16_store_d_f16_col_stride - : Intrinsic::nvvm_wmma_m32n8k16_store_d_f16_row_stride; - NumResults = 4; - break; - case NVPTX::BI__hmma_m32n8k16_st_c_f32: - IID = isColMajor ? Intrinsic::nvvm_wmma_m32n8k16_store_d_f32_col_stride - : Intrinsic::nvvm_wmma_m32n8k16_store_d_f32_row_stride; - break; - case NVPTX::BI__hmma_m8n32k16_st_c_f16: - IID = isColMajor ? Intrinsic::nvvm_wmma_m8n32k16_store_d_f16_col_stride - : Intrinsic::nvvm_wmma_m8n32k16_store_d_f16_row_stride; - NumResults = 4; - break; - case NVPTX::BI__hmma_m8n32k16_st_c_f32: - IID = isColMajor ? Intrinsic::nvvm_wmma_m8n32k16_store_d_f32_col_stride - : Intrinsic::nvvm_wmma_m8n32k16_store_d_f32_row_stride; - break; - default: - llvm_unreachable("Unexpected builtin ID."); - } - Function *Intrinsic = CGM.getIntrinsic(IID, Dst->getType()); - llvm::Type *ParamType = Intrinsic->getFunctionType()->getParamType(1); - SmallVector<Value *, 10> Values = {Dst}; - for (unsigned i = 0; i < NumResults; ++i) { - Value *V = Builder.CreateAlignedLoad( - Builder.CreateGEP(Src.getPointer(), llvm::ConstantInt::get(IntTy, i)), - CharUnits::fromQuantity(4)); - Values.push_back(Builder.CreateBitCast(V, ParamType)); - } - Values.push_back(Ldm); - Value *Result = Builder.CreateCall(Intrinsic, Values); - return Result; - } - - // BI__hmma_m16n16k16_mma_<Dtype><CType>(d, a, b, c, layout, satf) --> - // Intrinsic::nvvm_wmma_m16n16k16_mma_sync<layout A,B><DType><CType><Satf> - case NVPTX::BI__hmma_m16n16k16_mma_f16f16: - case NVPTX::BI__hmma_m16n16k16_mma_f32f16: - case NVPTX::BI__hmma_m16n16k16_mma_f32f32: - case NVPTX::BI__hmma_m16n16k16_mma_f16f32: - case NVPTX::BI__hmma_m32n8k16_mma_f16f16: - case NVPTX::BI__hmma_m32n8k16_mma_f32f16: - case NVPTX::BI__hmma_m32n8k16_mma_f32f32: - case NVPTX::BI__hmma_m32n8k16_mma_f16f32: - case NVPTX::BI__hmma_m8n32k16_mma_f16f16: - case NVPTX::BI__hmma_m8n32k16_mma_f32f16: - case NVPTX::BI__hmma_m8n32k16_mma_f32f32: - case NVPTX::BI__hmma_m8n32k16_mma_f16f32: { - Address Dst = EmitPointerWithAlignment(E->getArg(0)); - Address SrcA = EmitPointerWithAlignment(E->getArg(1)); - Address SrcB = EmitPointerWithAlignment(E->getArg(2)); - Address SrcC = EmitPointerWithAlignment(E->getArg(3)); - llvm::APSInt LayoutArg; - if (!E->getArg(4)->isIntegerConstantExpr(LayoutArg, getContext())) - return nullptr; - int Layout = LayoutArg.getSExtValue(); - if (Layout < 0 || Layout > 3) - return nullptr; - llvm::APSInt SatfArg; - if (!E->getArg(5)->isIntegerConstantExpr(SatfArg, getContext())) - return nullptr; - bool Satf = SatfArg.getSExtValue(); - - // clang-format off -#define MMA_VARIANTS(geom, type) {{ \ - Intrinsic::nvvm_wmma_##geom##_mma_row_row_##type, \ - Intrinsic::nvvm_wmma_##geom##_mma_row_row_##type##_satfinite, \ - Intrinsic::nvvm_wmma_##geom##_mma_row_col_##type, \ - Intrinsic::nvvm_wmma_##geom##_mma_row_col_##type##_satfinite, \ - Intrinsic::nvvm_wmma_##geom##_mma_col_row_##type, \ - Intrinsic::nvvm_wmma_##geom##_mma_col_row_##type##_satfinite, \ - Intrinsic::nvvm_wmma_##geom##_mma_col_col_##type, \ - Intrinsic::nvvm_wmma_##geom##_mma_col_col_##type##_satfinite \ - }} - // clang-format on - - auto getMMAIntrinsic = [Layout, Satf](std::array<unsigned, 8> Variants) { - unsigned Index = Layout * 2 + Satf; - assert(Index < 8); - return Variants[Index]; - }; - unsigned IID; - unsigned NumEltsC; - unsigned NumEltsD; - switch (BuiltinID) { - case NVPTX::BI__hmma_m16n16k16_mma_f16f16: - IID = getMMAIntrinsic(MMA_VARIANTS(m16n16k16, f16_f16)); - NumEltsC = 4; - NumEltsD = 4; - break; - case NVPTX::BI__hmma_m16n16k16_mma_f32f16: - IID = getMMAIntrinsic(MMA_VARIANTS(m16n16k16, f32_f16)); - NumEltsC = 4; - NumEltsD = 8; - break; - case NVPTX::BI__hmma_m16n16k16_mma_f16f32: - IID = getMMAIntrinsic(MMA_VARIANTS(m16n16k16, f16_f32)); - NumEltsC = 8; - NumEltsD = 4; - break; - case NVPTX::BI__hmma_m16n16k16_mma_f32f32: - IID = getMMAIntrinsic(MMA_VARIANTS(m16n16k16, f32_f32)); - NumEltsC = 8; - NumEltsD = 8; - break; - case NVPTX::BI__hmma_m32n8k16_mma_f16f16: - IID = getMMAIntrinsic(MMA_VARIANTS(m32n8k16, f16_f16)); - NumEltsC = 4; - NumEltsD = 4; - break; - case NVPTX::BI__hmma_m32n8k16_mma_f32f16: - IID = getMMAIntrinsic(MMA_VARIANTS(m32n8k16, f32_f16)); - NumEltsC = 4; - NumEltsD = 8; - break; - case NVPTX::BI__hmma_m32n8k16_mma_f16f32: - IID = getMMAIntrinsic(MMA_VARIANTS(m32n8k16, f16_f32)); - NumEltsC = 8; - NumEltsD = 4; - break; - case NVPTX::BI__hmma_m32n8k16_mma_f32f32: - IID = getMMAIntrinsic(MMA_VARIANTS(m32n8k16, f32_f32)); - NumEltsC = 8; - NumEltsD = 8; - break; - case NVPTX::BI__hmma_m8n32k16_mma_f16f16: - IID = getMMAIntrinsic(MMA_VARIANTS(m8n32k16, f16_f16)); - NumEltsC = 4; - NumEltsD = 4; - break; - case NVPTX::BI__hmma_m8n32k16_mma_f32f16: - IID = getMMAIntrinsic(MMA_VARIANTS(m8n32k16, f32_f16)); - NumEltsC = 4; - NumEltsD = 8; - break; - case NVPTX::BI__hmma_m8n32k16_mma_f16f32: - IID = getMMAIntrinsic(MMA_VARIANTS(m8n32k16, f16_f32)); - NumEltsC = 8; - NumEltsD = 4; - break; - case NVPTX::BI__hmma_m8n32k16_mma_f32f32: - IID = getMMAIntrinsic(MMA_VARIANTS(m8n32k16, f32_f32)); - NumEltsC = 8; - NumEltsD = 8; - break; - default: - llvm_unreachable("Unexpected builtin ID."); - } -#undef MMA_VARIANTS - - SmallVector<Value *, 24> Values; - Function *Intrinsic = CGM.getIntrinsic(IID); - llvm::Type *ABType = Intrinsic->getFunctionType()->getParamType(0); - // Load A - for (unsigned i = 0; i < 8; ++i) { - Value *V = Builder.CreateAlignedLoad( - Builder.CreateGEP(SrcA.getPointer(), - llvm::ConstantInt::get(IntTy, i)), - CharUnits::fromQuantity(4)); - Values.push_back(Builder.CreateBitCast(V, ABType)); - } - // Load B - for (unsigned i = 0; i < 8; ++i) { - Value *V = Builder.CreateAlignedLoad( - Builder.CreateGEP(SrcB.getPointer(), - llvm::ConstantInt::get(IntTy, i)), - CharUnits::fromQuantity(4)); - Values.push_back(Builder.CreateBitCast(V, ABType)); - } - // Load C - llvm::Type *CType = Intrinsic->getFunctionType()->getParamType(16); - for (unsigned i = 0; i < NumEltsC; ++i) { - Value *V = Builder.CreateAlignedLoad( - Builder.CreateGEP(SrcC.getPointer(), - llvm::ConstantInt::get(IntTy, i)), - CharUnits::fromQuantity(4)); - Values.push_back(Builder.CreateBitCast(V, CType)); - } - Value *Result = Builder.CreateCall(Intrinsic, Values); - llvm::Type *DType = Dst.getElementType(); - for (unsigned i = 0; i < NumEltsD; ++i) - Builder.CreateAlignedStore( - Builder.CreateBitCast(Builder.CreateExtractValue(Result, i), DType), - Builder.CreateGEP(Dst.getPointer(), llvm::ConstantInt::get(IntTy, i)), - CharUnits::fromQuantity(4)); - return Result; - } - default: - return nullptr; - } -} - -Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, - const CallExpr *E) { - switch (BuiltinID) { - case WebAssembly::BI__builtin_wasm_memory_size: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *I = EmitScalarExpr(E->getArg(0)); - Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_memory_size, ResultType); - return Builder.CreateCall(Callee, I); - } - case WebAssembly::BI__builtin_wasm_memory_grow: { - llvm::Type *ResultType = ConvertType(E->getType()); - Value *Args[] = { - EmitScalarExpr(E->getArg(0)), - EmitScalarExpr(E->getArg(1)) - }; - Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_memory_grow, ResultType); - return Builder.CreateCall(Callee, Args); - } - case WebAssembly::BI__builtin_wasm_throw: { - Value *Tag = EmitScalarExpr(E->getArg(0)); - Value *Obj = EmitScalarExpr(E->getArg(1)); - Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_throw); - return Builder.CreateCall(Callee, {Tag, Obj}); - } - case WebAssembly::BI__builtin_wasm_rethrow: { - Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_rethrow); - return Builder.CreateCall(Callee); - } - case WebAssembly::BI__builtin_wasm_atomic_wait_i32: { - Value *Addr = EmitScalarExpr(E->getArg(0)); - Value *Expected = EmitScalarExpr(E->getArg(1)); - Value *Timeout = EmitScalarExpr(E->getArg(2)); - Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_atomic_wait_i32); - return Builder.CreateCall(Callee, {Addr, Expected, Timeout}); - } - case WebAssembly::BI__builtin_wasm_atomic_wait_i64: { - Value *Addr = EmitScalarExpr(E->getArg(0)); - Value *Expected = EmitScalarExpr(E->getArg(1)); - Value *Timeout = EmitScalarExpr(E->getArg(2)); - Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_atomic_wait_i64); - return Builder.CreateCall(Callee, {Addr, Expected, Timeout}); - } - case WebAssembly::BI__builtin_wasm_atomic_notify: { - Value *Addr = EmitScalarExpr(E->getArg(0)); - Value *Count = EmitScalarExpr(E->getArg(1)); - Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_atomic_notify); - return Builder.CreateCall(Callee, {Addr, Count}); - } - case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i32_f32: - case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i32_f64: - case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i64_f32: - case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i64_f64: - case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i32x4_f32x4: - case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i64x2_f64x2: { - Value *Src = EmitScalarExpr(E->getArg(0)); - llvm::Type *ResT = ConvertType(E->getType()); - Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_trunc_saturate_signed, - {ResT, Src->getType()}); - return Builder.CreateCall(Callee, {Src}); - } - case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i32_f32: - case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i32_f64: - case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i64_f32: - case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i64_f64: - case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i32x4_f32x4: - case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i64x2_f64x2: { - Value *Src = EmitScalarExpr(E->getArg(0)); - llvm::Type *ResT = ConvertType(E->getType()); - Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_trunc_saturate_unsigned, - {ResT, Src->getType()}); - return Builder.CreateCall(Callee, {Src}); - } - case WebAssembly::BI__builtin_wasm_min_f32: - case WebAssembly::BI__builtin_wasm_min_f64: - case WebAssembly::BI__builtin_wasm_min_f32x4: - case WebAssembly::BI__builtin_wasm_min_f64x2: { - Value *LHS = EmitScalarExpr(E->getArg(0)); - Value *RHS = EmitScalarExpr(E->getArg(1)); - Value *Callee = CGM.getIntrinsic(Intrinsic::minimum, - ConvertType(E->getType())); - return Builder.CreateCall(Callee, {LHS, RHS}); - } - case WebAssembly::BI__builtin_wasm_max_f32: - case WebAssembly::BI__builtin_wasm_max_f64: - case WebAssembly::BI__builtin_wasm_max_f32x4: - case WebAssembly::BI__builtin_wasm_max_f64x2: { - Value *LHS = EmitScalarExpr(E->getArg(0)); - Value *RHS = EmitScalarExpr(E->getArg(1)); - Value *Callee = CGM.getIntrinsic(Intrinsic::maximum, - ConvertType(E->getType())); - return Builder.CreateCall(Callee, {LHS, RHS}); - } - case WebAssembly::BI__builtin_wasm_extract_lane_s_i8x16: - case WebAssembly::BI__builtin_wasm_extract_lane_u_i8x16: - case WebAssembly::BI__builtin_wasm_extract_lane_s_i16x8: - case WebAssembly::BI__builtin_wasm_extract_lane_u_i16x8: - case WebAssembly::BI__builtin_wasm_extract_lane_i32x4: - case WebAssembly::BI__builtin_wasm_extract_lane_i64x2: - case WebAssembly::BI__builtin_wasm_extract_lane_f32x4: - case WebAssembly::BI__builtin_wasm_extract_lane_f64x2: { - llvm::APSInt LaneConst; - if (!E->getArg(1)->isIntegerConstantExpr(LaneConst, getContext())) - llvm_unreachable("Constant arg isn't actually constant?"); - Value *Vec = EmitScalarExpr(E->getArg(0)); - Value *Lane = llvm::ConstantInt::get(getLLVMContext(), LaneConst); - Value *Extract = Builder.CreateExtractElement(Vec, Lane); - switch (BuiltinID) { - case WebAssembly::BI__builtin_wasm_extract_lane_s_i8x16: - case WebAssembly::BI__builtin_wasm_extract_lane_s_i16x8: - return Builder.CreateSExt(Extract, ConvertType(E->getType())); - case WebAssembly::BI__builtin_wasm_extract_lane_u_i8x16: - case WebAssembly::BI__builtin_wasm_extract_lane_u_i16x8: - return Builder.CreateZExt(Extract, ConvertType(E->getType())); - case WebAssembly::BI__builtin_wasm_extract_lane_i32x4: - case WebAssembly::BI__builtin_wasm_extract_lane_i64x2: - case WebAssembly::BI__builtin_wasm_extract_lane_f32x4: - case WebAssembly::BI__builtin_wasm_extract_lane_f64x2: - return Extract; - default: - llvm_unreachable("unexpected builtin ID"); - } - } - case WebAssembly::BI__builtin_wasm_replace_lane_i8x16: - case WebAssembly::BI__builtin_wasm_replace_lane_i16x8: - case WebAssembly::BI__builtin_wasm_replace_lane_i32x4: - case WebAssembly::BI__builtin_wasm_replace_lane_i64x2: - case WebAssembly::BI__builtin_wasm_replace_lane_f32x4: - case WebAssembly::BI__builtin_wasm_replace_lane_f64x2: { - llvm::APSInt LaneConst; - if (!E->getArg(1)->isIntegerConstantExpr(LaneConst, getContext())) - llvm_unreachable("Constant arg isn't actually constant?"); - Value *Vec = EmitScalarExpr(E->getArg(0)); - Value *Lane = llvm::ConstantInt::get(getLLVMContext(), LaneConst); - Value *Val = EmitScalarExpr(E->getArg(2)); - switch (BuiltinID) { - case WebAssembly::BI__builtin_wasm_replace_lane_i8x16: - case WebAssembly::BI__builtin_wasm_replace_lane_i16x8: { - llvm::Type *ElemType = ConvertType(E->getType())->getVectorElementType(); - Value *Trunc = Builder.CreateTrunc(Val, ElemType); - return Builder.CreateInsertElement(Vec, Trunc, Lane); - } - case WebAssembly::BI__builtin_wasm_replace_lane_i32x4: - case WebAssembly::BI__builtin_wasm_replace_lane_i64x2: - case WebAssembly::BI__builtin_wasm_replace_lane_f32x4: - case WebAssembly::BI__builtin_wasm_replace_lane_f64x2: - return Builder.CreateInsertElement(Vec, Val, Lane); - default: - llvm_unreachable("unexpected builtin ID"); - } - } - case WebAssembly::BI__builtin_wasm_add_saturate_s_i8x16: - case WebAssembly::BI__builtin_wasm_add_saturate_u_i8x16: - case WebAssembly::BI__builtin_wasm_add_saturate_s_i16x8: - case WebAssembly::BI__builtin_wasm_add_saturate_u_i16x8: - case WebAssembly::BI__builtin_wasm_sub_saturate_s_i8x16: - case WebAssembly::BI__builtin_wasm_sub_saturate_u_i8x16: - case WebAssembly::BI__builtin_wasm_sub_saturate_s_i16x8: - case WebAssembly::BI__builtin_wasm_sub_saturate_u_i16x8: { - unsigned IntNo; - switch (BuiltinID) { - case WebAssembly::BI__builtin_wasm_add_saturate_s_i8x16: - case WebAssembly::BI__builtin_wasm_add_saturate_s_i16x8: - IntNo = Intrinsic::sadd_sat; - break; - case WebAssembly::BI__builtin_wasm_add_saturate_u_i8x16: - case WebAssembly::BI__builtin_wasm_add_saturate_u_i16x8: - IntNo = Intrinsic::uadd_sat; - break; - case WebAssembly::BI__builtin_wasm_sub_saturate_s_i8x16: - case WebAssembly::BI__builtin_wasm_sub_saturate_s_i16x8: - IntNo = Intrinsic::wasm_sub_saturate_signed; - break; - case WebAssembly::BI__builtin_wasm_sub_saturate_u_i8x16: - case WebAssembly::BI__builtin_wasm_sub_saturate_u_i16x8: - IntNo = Intrinsic::wasm_sub_saturate_unsigned; - break; - default: - llvm_unreachable("unexpected builtin ID"); - } - Value *LHS = EmitScalarExpr(E->getArg(0)); - Value *RHS = EmitScalarExpr(E->getArg(1)); - Value *Callee = CGM.getIntrinsic(IntNo, ConvertType(E->getType())); - return Builder.CreateCall(Callee, {LHS, RHS}); - } - case WebAssembly::BI__builtin_wasm_bitselect: { - Value *V1 = EmitScalarExpr(E->getArg(0)); - Value *V2 = EmitScalarExpr(E->getArg(1)); - Value *C = EmitScalarExpr(E->getArg(2)); - Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_bitselect, - ConvertType(E->getType())); - return Builder.CreateCall(Callee, {V1, V2, C}); - } - case WebAssembly::BI__builtin_wasm_any_true_i8x16: - case WebAssembly::BI__builtin_wasm_any_true_i16x8: - case WebAssembly::BI__builtin_wasm_any_true_i32x4: - case WebAssembly::BI__builtin_wasm_any_true_i64x2: - case WebAssembly::BI__builtin_wasm_all_true_i8x16: - case WebAssembly::BI__builtin_wasm_all_true_i16x8: - case WebAssembly::BI__builtin_wasm_all_true_i32x4: - case WebAssembly::BI__builtin_wasm_all_true_i64x2: { - unsigned IntNo; - switch (BuiltinID) { - case WebAssembly::BI__builtin_wasm_any_true_i8x16: - case WebAssembly::BI__builtin_wasm_any_true_i16x8: - case WebAssembly::BI__builtin_wasm_any_true_i32x4: - case WebAssembly::BI__builtin_wasm_any_true_i64x2: - IntNo = Intrinsic::wasm_anytrue; - break; - case WebAssembly::BI__builtin_wasm_all_true_i8x16: - case WebAssembly::BI__builtin_wasm_all_true_i16x8: - case WebAssembly::BI__builtin_wasm_all_true_i32x4: - case WebAssembly::BI__builtin_wasm_all_true_i64x2: - IntNo = Intrinsic::wasm_alltrue; - break; - default: - llvm_unreachable("unexpected builtin ID"); - } - Value *Vec = EmitScalarExpr(E->getArg(0)); - Value *Callee = CGM.getIntrinsic(IntNo, Vec->getType()); - return Builder.CreateCall(Callee, {Vec}); - } - case WebAssembly::BI__builtin_wasm_abs_f32x4: - case WebAssembly::BI__builtin_wasm_abs_f64x2: { - Value *Vec = EmitScalarExpr(E->getArg(0)); - Value *Callee = CGM.getIntrinsic(Intrinsic::fabs, Vec->getType()); - return Builder.CreateCall(Callee, {Vec}); - } - case WebAssembly::BI__builtin_wasm_sqrt_f32x4: - case WebAssembly::BI__builtin_wasm_sqrt_f64x2: { - Value *Vec = EmitScalarExpr(E->getArg(0)); - Value *Callee = CGM.getIntrinsic(Intrinsic::sqrt, Vec->getType()); - return Builder.CreateCall(Callee, {Vec}); - } - - default: - return nullptr; - } -} - -Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, - const CallExpr *E) { - SmallVector<llvm::Value *, 4> Ops; - Intrinsic::ID ID = Intrinsic::not_intrinsic; - - auto MakeCircLd = [&](unsigned IntID, bool HasImm) { - // The base pointer is passed by address, so it needs to be loaded. - Address BP = EmitPointerWithAlignment(E->getArg(0)); - BP = Address(Builder.CreateBitCast(BP.getPointer(), Int8PtrPtrTy), - BP.getAlignment()); - llvm::Value *Base = Builder.CreateLoad(BP); - // Operands are Base, Increment, Modifier, Start. - if (HasImm) - Ops = { Base, EmitScalarExpr(E->getArg(1)), EmitScalarExpr(E->getArg(2)), - EmitScalarExpr(E->getArg(3)) }; - else - Ops = { Base, EmitScalarExpr(E->getArg(1)), - EmitScalarExpr(E->getArg(2)) }; - - llvm::Value *Result = Builder.CreateCall(CGM.getIntrinsic(IntID), Ops); - llvm::Value *NewBase = Builder.CreateExtractValue(Result, 1); - llvm::Value *LV = Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)), - NewBase->getType()->getPointerTo()); - Address Dest = EmitPointerWithAlignment(E->getArg(0)); - // The intrinsic generates two results. The new value for the base pointer - // needs to be stored. - Builder.CreateAlignedStore(NewBase, LV, Dest.getAlignment()); - return Builder.CreateExtractValue(Result, 0); - }; - - auto MakeCircSt = [&](unsigned IntID, bool HasImm) { - // The base pointer is passed by address, so it needs to be loaded. - Address BP = EmitPointerWithAlignment(E->getArg(0)); - BP = Address(Builder.CreateBitCast(BP.getPointer(), Int8PtrPtrTy), - BP.getAlignment()); - llvm::Value *Base = Builder.CreateLoad(BP); - // Operands are Base, Increment, Modifier, Value, Start. - if (HasImm) - Ops = { Base, EmitScalarExpr(E->getArg(1)), EmitScalarExpr(E->getArg(2)), - EmitScalarExpr(E->getArg(3)), EmitScalarExpr(E->getArg(4)) }; - else - Ops = { Base, EmitScalarExpr(E->getArg(1)), - EmitScalarExpr(E->getArg(2)), EmitScalarExpr(E->getArg(3)) }; - - llvm::Value *NewBase = Builder.CreateCall(CGM.getIntrinsic(IntID), Ops); - llvm::Value *LV = Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)), - NewBase->getType()->getPointerTo()); - Address Dest = EmitPointerWithAlignment(E->getArg(0)); - // The intrinsic generates one result, which is the new value for the base - // pointer. It needs to be stored. - return Builder.CreateAlignedStore(NewBase, LV, Dest.getAlignment()); - }; - - // Handle the conversion of bit-reverse load intrinsics to bit code. - // The intrinsic call after this function only reads from memory and the - // write to memory is dealt by the store instruction. - auto MakeBrevLd = [&](unsigned IntID, llvm::Type *DestTy) { - // The intrinsic generates one result, which is the new value for the base - // pointer. It needs to be returned. The result of the load instruction is - // passed to intrinsic by address, so the value needs to be stored. - llvm::Value *BaseAddress = - Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)), Int8PtrTy); - - // Expressions like &(*pt++) will be incremented per evaluation. - // EmitPointerWithAlignment and EmitScalarExpr evaluates the expression - // per call. - Address DestAddr = EmitPointerWithAlignment(E->getArg(1)); - DestAddr = Address(Builder.CreateBitCast(DestAddr.getPointer(), Int8PtrTy), - DestAddr.getAlignment()); - llvm::Value *DestAddress = DestAddr.getPointer(); - - // Operands are Base, Dest, Modifier. - // The intrinsic format in LLVM IR is defined as - // { ValueType, i8* } (i8*, i32). - Ops = {BaseAddress, EmitScalarExpr(E->getArg(2))}; - - llvm::Value *Result = Builder.CreateCall(CGM.getIntrinsic(IntID), Ops); - // The value needs to be stored as the variable is passed by reference. - llvm::Value *DestVal = Builder.CreateExtractValue(Result, 0); - - // The store needs to be truncated to fit the destination type. - // While i32 and i64 are natively supported on Hexagon, i8 and i16 needs - // to be handled with stores of respective destination type. - DestVal = Builder.CreateTrunc(DestVal, DestTy); - - llvm::Value *DestForStore = - Builder.CreateBitCast(DestAddress, DestVal->getType()->getPointerTo()); - Builder.CreateAlignedStore(DestVal, DestForStore, DestAddr.getAlignment()); - // The updated value of the base pointer is returned. - return Builder.CreateExtractValue(Result, 1); - }; - - switch (BuiltinID) { - case Hexagon::BI__builtin_HEXAGON_V6_vaddcarry: - case Hexagon::BI__builtin_HEXAGON_V6_vaddcarry_128B: { - Address Dest = EmitPointerWithAlignment(E->getArg(2)); - unsigned Size; - if (BuiltinID == Hexagon::BI__builtin_HEXAGON_V6_vaddcarry) { - Size = 512; - ID = Intrinsic::hexagon_V6_vaddcarry; - } else { - Size = 1024; - ID = Intrinsic::hexagon_V6_vaddcarry_128B; - } - Dest = Builder.CreateBitCast(Dest, - llvm::VectorType::get(Builder.getInt1Ty(), Size)->getPointerTo(0)); - LoadInst *QLd = Builder.CreateLoad(Dest); - Ops = { EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1)), QLd }; - llvm::Value *Result = Builder.CreateCall(CGM.getIntrinsic(ID), Ops); - llvm::Value *Vprd = Builder.CreateExtractValue(Result, 1); - llvm::Value *Base = Builder.CreateBitCast(EmitScalarExpr(E->getArg(2)), - Vprd->getType()->getPointerTo(0)); - Builder.CreateAlignedStore(Vprd, Base, Dest.getAlignment()); - return Builder.CreateExtractValue(Result, 0); - } - case Hexagon::BI__builtin_HEXAGON_V6_vsubcarry: - case Hexagon::BI__builtin_HEXAGON_V6_vsubcarry_128B: { - Address Dest = EmitPointerWithAlignment(E->getArg(2)); - unsigned Size; - if (BuiltinID == Hexagon::BI__builtin_HEXAGON_V6_vsubcarry) { - Size = 512; - ID = Intrinsic::hexagon_V6_vsubcarry; - } else { - Size = 1024; - ID = Intrinsic::hexagon_V6_vsubcarry_128B; - } - Dest = Builder.CreateBitCast(Dest, - llvm::VectorType::get(Builder.getInt1Ty(), Size)->getPointerTo(0)); - LoadInst *QLd = Builder.CreateLoad(Dest); - Ops = { EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1)), QLd }; - llvm::Value *Result = Builder.CreateCall(CGM.getIntrinsic(ID), Ops); - llvm::Value *Vprd = Builder.CreateExtractValue(Result, 1); - llvm::Value *Base = Builder.CreateBitCast(EmitScalarExpr(E->getArg(2)), - Vprd->getType()->getPointerTo(0)); - Builder.CreateAlignedStore(Vprd, Base, Dest.getAlignment()); - return Builder.CreateExtractValue(Result, 0); - } - case Hexagon::BI__builtin_HEXAGON_L2_loadrub_pci: - return MakeCircLd(Intrinsic::hexagon_L2_loadrub_pci, /*HasImm*/true); - case Hexagon::BI__builtin_HEXAGON_L2_loadrb_pci: - return MakeCircLd(Intrinsic::hexagon_L2_loadrb_pci, /*HasImm*/true); - case Hexagon::BI__builtin_HEXAGON_L2_loadruh_pci: - return MakeCircLd(Intrinsic::hexagon_L2_loadruh_pci, /*HasImm*/true); - case Hexagon::BI__builtin_HEXAGON_L2_loadrh_pci: - return MakeCircLd(Intrinsic::hexagon_L2_loadrh_pci, /*HasImm*/true); - case Hexagon::BI__builtin_HEXAGON_L2_loadri_pci: - return MakeCircLd(Intrinsic::hexagon_L2_loadri_pci, /*HasImm*/true); - case Hexagon::BI__builtin_HEXAGON_L2_loadrd_pci: - return MakeCircLd(Intrinsic::hexagon_L2_loadrd_pci, /*HasImm*/true); - case Hexagon::BI__builtin_HEXAGON_L2_loadrub_pcr: - return MakeCircLd(Intrinsic::hexagon_L2_loadrub_pcr, /*HasImm*/false); - case Hexagon::BI__builtin_HEXAGON_L2_loadrb_pcr: - return MakeCircLd(Intrinsic::hexagon_L2_loadrb_pcr, /*HasImm*/false); - case Hexagon::BI__builtin_HEXAGON_L2_loadruh_pcr: - return MakeCircLd(Intrinsic::hexagon_L2_loadruh_pcr, /*HasImm*/false); - case Hexagon::BI__builtin_HEXAGON_L2_loadrh_pcr: - return MakeCircLd(Intrinsic::hexagon_L2_loadrh_pcr, /*HasImm*/false); - case Hexagon::BI__builtin_HEXAGON_L2_loadri_pcr: - return MakeCircLd(Intrinsic::hexagon_L2_loadri_pcr, /*HasImm*/false); - case Hexagon::BI__builtin_HEXAGON_L2_loadrd_pcr: - return MakeCircLd(Intrinsic::hexagon_L2_loadrd_pcr, /*HasImm*/false); - case Hexagon::BI__builtin_HEXAGON_S2_storerb_pci: - return MakeCircSt(Intrinsic::hexagon_S2_storerb_pci, /*HasImm*/true); - case Hexagon::BI__builtin_HEXAGON_S2_storerh_pci: - return MakeCircSt(Intrinsic::hexagon_S2_storerh_pci, /*HasImm*/true); - case Hexagon::BI__builtin_HEXAGON_S2_storerf_pci: - return MakeCircSt(Intrinsic::hexagon_S2_storerf_pci, /*HasImm*/true); - case Hexagon::BI__builtin_HEXAGON_S2_storeri_pci: - return MakeCircSt(Intrinsic::hexagon_S2_storeri_pci, /*HasImm*/true); - case Hexagon::BI__builtin_HEXAGON_S2_storerd_pci: - return MakeCircSt(Intrinsic::hexagon_S2_storerd_pci, /*HasImm*/true); - case Hexagon::BI__builtin_HEXAGON_S2_storerb_pcr: - return MakeCircSt(Intrinsic::hexagon_S2_storerb_pcr, /*HasImm*/false); - case Hexagon::BI__builtin_HEXAGON_S2_storerh_pcr: - return MakeCircSt(Intrinsic::hexagon_S2_storerh_pcr, /*HasImm*/false); - case Hexagon::BI__builtin_HEXAGON_S2_storerf_pcr: - return MakeCircSt(Intrinsic::hexagon_S2_storerf_pcr, /*HasImm*/false); - case Hexagon::BI__builtin_HEXAGON_S2_storeri_pcr: - return MakeCircSt(Intrinsic::hexagon_S2_storeri_pcr, /*HasImm*/false); - case Hexagon::BI__builtin_HEXAGON_S2_storerd_pcr: - return MakeCircSt(Intrinsic::hexagon_S2_storerd_pcr, /*HasImm*/false); - case Hexagon::BI__builtin_brev_ldub: - return MakeBrevLd(Intrinsic::hexagon_L2_loadrub_pbr, Int8Ty); - case Hexagon::BI__builtin_brev_ldb: - return MakeBrevLd(Intrinsic::hexagon_L2_loadrb_pbr, Int8Ty); - case Hexagon::BI__builtin_brev_lduh: - return MakeBrevLd(Intrinsic::hexagon_L2_loadruh_pbr, Int16Ty); - case Hexagon::BI__builtin_brev_ldh: - return MakeBrevLd(Intrinsic::hexagon_L2_loadrh_pbr, Int16Ty); - case Hexagon::BI__builtin_brev_ldw: - return MakeBrevLd(Intrinsic::hexagon_L2_loadri_pbr, Int32Ty); - case Hexagon::BI__builtin_brev_ldd: - return MakeBrevLd(Intrinsic::hexagon_L2_loadrd_pbr, Int64Ty); - default: - break; - } // switch - - return nullptr; -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp deleted file mode 100644 index 1c578bd151b..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp +++ /dev/null @@ -1,632 +0,0 @@ -//===----- CGCUDANV.cpp - Interface to NVIDIA CUDA Runtime ----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This provides a class for CUDA code generation targeting the NVIDIA CUDA -// runtime library. -// -//===----------------------------------------------------------------------===// - -#include "CGCUDARuntime.h" -#include "CodeGenFunction.h" -#include "CodeGenModule.h" -#include "clang/AST/Decl.h" -#include "clang/CodeGen/ConstantInitBuilder.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/Support/Format.h" - -using namespace clang; -using namespace CodeGen; - -namespace { -constexpr unsigned CudaFatMagic = 0x466243b1; -constexpr unsigned HIPFatMagic = 0x48495046; // "HIPF" - -class CGNVCUDARuntime : public CGCUDARuntime { - -private: - llvm::IntegerType *IntTy, *SizeTy; - llvm::Type *VoidTy; - llvm::PointerType *CharPtrTy, *VoidPtrTy, *VoidPtrPtrTy; - - /// Convenience reference to LLVM Context - llvm::LLVMContext &Context; - /// Convenience reference to the current module - llvm::Module &TheModule; - /// Keeps track of kernel launch stubs emitted in this module - llvm::SmallVector<llvm::Function *, 16> EmittedKernels; - llvm::SmallVector<std::pair<llvm::GlobalVariable *, unsigned>, 16> DeviceVars; - /// Keeps track of variable containing handle of GPU binary. Populated by - /// ModuleCtorFunction() and used to create corresponding cleanup calls in - /// ModuleDtorFunction() - llvm::GlobalVariable *GpuBinaryHandle = nullptr; - /// Whether we generate relocatable device code. - bool RelocatableDeviceCode; - - llvm::Constant *getSetupArgumentFn() const; - llvm::Constant *getLaunchFn() const; - - llvm::FunctionType *getRegisterGlobalsFnTy() const; - llvm::FunctionType *getCallbackFnTy() const; - llvm::FunctionType *getRegisterLinkedBinaryFnTy() const; - std::string addPrefixToName(StringRef FuncName) const; - std::string addUnderscoredPrefixToName(StringRef FuncName) const; - - /// Creates a function to register all kernel stubs generated in this module. - llvm::Function *makeRegisterGlobalsFn(); - - /// Helper function that generates a constant string and returns a pointer to - /// the start of the string. The result of this function can be used anywhere - /// where the C code specifies const char*. - llvm::Constant *makeConstantString(const std::string &Str, - const std::string &Name = "", - const std::string &SectionName = "", - unsigned Alignment = 0) { - llvm::Constant *Zeros[] = {llvm::ConstantInt::get(SizeTy, 0), - llvm::ConstantInt::get(SizeTy, 0)}; - auto ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str()); - llvm::GlobalVariable *GV = - cast<llvm::GlobalVariable>(ConstStr.getPointer()); - if (!SectionName.empty()) { - GV->setSection(SectionName); - // Mark the address as used which make sure that this section isn't - // merged and we will really have it in the object file. - GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None); - } - if (Alignment) - GV->setAlignment(Alignment); - - return llvm::ConstantExpr::getGetElementPtr(ConstStr.getElementType(), - ConstStr.getPointer(), Zeros); - } - - /// Helper function that generates an empty dummy function returning void. - llvm::Function *makeDummyFunction(llvm::FunctionType *FnTy) { - assert(FnTy->getReturnType()->isVoidTy() && - "Can only generate dummy functions returning void!"); - llvm::Function *DummyFunc = llvm::Function::Create( - FnTy, llvm::GlobalValue::InternalLinkage, "dummy", &TheModule); - - llvm::BasicBlock *DummyBlock = - llvm::BasicBlock::Create(Context, "", DummyFunc); - CGBuilderTy FuncBuilder(CGM, Context); - FuncBuilder.SetInsertPoint(DummyBlock); - FuncBuilder.CreateRetVoid(); - - return DummyFunc; - } - - void emitDeviceStubBody(CodeGenFunction &CGF, FunctionArgList &Args); - -public: - CGNVCUDARuntime(CodeGenModule &CGM); - - void emitDeviceStub(CodeGenFunction &CGF, FunctionArgList &Args) override; - void registerDeviceVar(llvm::GlobalVariable &Var, unsigned Flags) override { - DeviceVars.push_back(std::make_pair(&Var, Flags)); - } - - /// Creates module constructor function - llvm::Function *makeModuleCtorFunction() override; - /// Creates module destructor function - llvm::Function *makeModuleDtorFunction() override; -}; - -} - -std::string CGNVCUDARuntime::addPrefixToName(StringRef FuncName) const { - if (CGM.getLangOpts().HIP) - return ((Twine("hip") + Twine(FuncName)).str()); - return ((Twine("cuda") + Twine(FuncName)).str()); -} -std::string -CGNVCUDARuntime::addUnderscoredPrefixToName(StringRef FuncName) const { - if (CGM.getLangOpts().HIP) - return ((Twine("__hip") + Twine(FuncName)).str()); - return ((Twine("__cuda") + Twine(FuncName)).str()); -} - -CGNVCUDARuntime::CGNVCUDARuntime(CodeGenModule &CGM) - : CGCUDARuntime(CGM), Context(CGM.getLLVMContext()), - TheModule(CGM.getModule()), - RelocatableDeviceCode(CGM.getLangOpts().GPURelocatableDeviceCode) { - CodeGen::CodeGenTypes &Types = CGM.getTypes(); - ASTContext &Ctx = CGM.getContext(); - - IntTy = CGM.IntTy; - SizeTy = CGM.SizeTy; - VoidTy = CGM.VoidTy; - - CharPtrTy = llvm::PointerType::getUnqual(Types.ConvertType(Ctx.CharTy)); - VoidPtrTy = cast<llvm::PointerType>(Types.ConvertType(Ctx.VoidPtrTy)); - VoidPtrPtrTy = VoidPtrTy->getPointerTo(); -} - -llvm::Constant *CGNVCUDARuntime::getSetupArgumentFn() const { - // cudaError_t cudaSetupArgument(void *, size_t, size_t) - llvm::Type *Params[] = {VoidPtrTy, SizeTy, SizeTy}; - return CGM.CreateRuntimeFunction( - llvm::FunctionType::get(IntTy, Params, false), - addPrefixToName("SetupArgument")); -} - -llvm::Constant *CGNVCUDARuntime::getLaunchFn() const { - if (CGM.getLangOpts().HIP) { - // hipError_t hipLaunchByPtr(char *); - return CGM.CreateRuntimeFunction( - llvm::FunctionType::get(IntTy, CharPtrTy, false), "hipLaunchByPtr"); - } else { - // cudaError_t cudaLaunch(char *); - return CGM.CreateRuntimeFunction( - llvm::FunctionType::get(IntTy, CharPtrTy, false), "cudaLaunch"); - } -} - -llvm::FunctionType *CGNVCUDARuntime::getRegisterGlobalsFnTy() const { - return llvm::FunctionType::get(VoidTy, VoidPtrPtrTy, false); -} - -llvm::FunctionType *CGNVCUDARuntime::getCallbackFnTy() const { - return llvm::FunctionType::get(VoidTy, VoidPtrTy, false); -} - -llvm::FunctionType *CGNVCUDARuntime::getRegisterLinkedBinaryFnTy() const { - auto CallbackFnTy = getCallbackFnTy(); - auto RegisterGlobalsFnTy = getRegisterGlobalsFnTy(); - llvm::Type *Params[] = {RegisterGlobalsFnTy->getPointerTo(), VoidPtrTy, - VoidPtrTy, CallbackFnTy->getPointerTo()}; - return llvm::FunctionType::get(VoidTy, Params, false); -} - -void CGNVCUDARuntime::emitDeviceStub(CodeGenFunction &CGF, - FunctionArgList &Args) { - EmittedKernels.push_back(CGF.CurFn); - emitDeviceStubBody(CGF, Args); -} - -void CGNVCUDARuntime::emitDeviceStubBody(CodeGenFunction &CGF, - FunctionArgList &Args) { - // Emit a call to cudaSetupArgument for each arg in Args. - llvm::Constant *cudaSetupArgFn = getSetupArgumentFn(); - llvm::BasicBlock *EndBlock = CGF.createBasicBlock("setup.end"); - CharUnits Offset = CharUnits::Zero(); - for (const VarDecl *A : Args) { - CharUnits TyWidth, TyAlign; - std::tie(TyWidth, TyAlign) = - CGM.getContext().getTypeInfoInChars(A->getType()); - Offset = Offset.alignTo(TyAlign); - llvm::Value *Args[] = { - CGF.Builder.CreatePointerCast(CGF.GetAddrOfLocalVar(A).getPointer(), - VoidPtrTy), - llvm::ConstantInt::get(SizeTy, TyWidth.getQuantity()), - llvm::ConstantInt::get(SizeTy, Offset.getQuantity()), - }; - llvm::CallSite CS = CGF.EmitRuntimeCallOrInvoke(cudaSetupArgFn, Args); - llvm::Constant *Zero = llvm::ConstantInt::get(IntTy, 0); - llvm::Value *CSZero = CGF.Builder.CreateICmpEQ(CS.getInstruction(), Zero); - llvm::BasicBlock *NextBlock = CGF.createBasicBlock("setup.next"); - CGF.Builder.CreateCondBr(CSZero, NextBlock, EndBlock); - CGF.EmitBlock(NextBlock); - Offset += TyWidth; - } - - // Emit the call to cudaLaunch - llvm::Constant *cudaLaunchFn = getLaunchFn(); - llvm::Value *Arg = CGF.Builder.CreatePointerCast(CGF.CurFn, CharPtrTy); - CGF.EmitRuntimeCallOrInvoke(cudaLaunchFn, Arg); - CGF.EmitBranch(EndBlock); - - CGF.EmitBlock(EndBlock); -} - -/// Creates a function that sets up state on the host side for CUDA objects that -/// have a presence on both the host and device sides. Specifically, registers -/// the host side of kernel functions and device global variables with the CUDA -/// runtime. -/// \code -/// void __cuda_register_globals(void** GpuBinaryHandle) { -/// __cudaRegisterFunction(GpuBinaryHandle,Kernel0,...); -/// ... -/// __cudaRegisterFunction(GpuBinaryHandle,KernelM,...); -/// __cudaRegisterVar(GpuBinaryHandle, GlobalVar0, ...); -/// ... -/// __cudaRegisterVar(GpuBinaryHandle, GlobalVarN, ...); -/// } -/// \endcode -llvm::Function *CGNVCUDARuntime::makeRegisterGlobalsFn() { - // No need to register anything - if (EmittedKernels.empty() && DeviceVars.empty()) - return nullptr; - - llvm::Function *RegisterKernelsFunc = llvm::Function::Create( - getRegisterGlobalsFnTy(), llvm::GlobalValue::InternalLinkage, - addUnderscoredPrefixToName("_register_globals"), &TheModule); - llvm::BasicBlock *EntryBB = - llvm::BasicBlock::Create(Context, "entry", RegisterKernelsFunc); - CGBuilderTy Builder(CGM, Context); - Builder.SetInsertPoint(EntryBB); - - // void __cudaRegisterFunction(void **, const char *, char *, const char *, - // int, uint3*, uint3*, dim3*, dim3*, int*) - llvm::Type *RegisterFuncParams[] = { - VoidPtrPtrTy, CharPtrTy, CharPtrTy, CharPtrTy, IntTy, - VoidPtrTy, VoidPtrTy, VoidPtrTy, VoidPtrTy, IntTy->getPointerTo()}; - llvm::Constant *RegisterFunc = CGM.CreateRuntimeFunction( - llvm::FunctionType::get(IntTy, RegisterFuncParams, false), - addUnderscoredPrefixToName("RegisterFunction")); - - // Extract GpuBinaryHandle passed as the first argument passed to - // __cuda_register_globals() and generate __cudaRegisterFunction() call for - // each emitted kernel. - llvm::Argument &GpuBinaryHandlePtr = *RegisterKernelsFunc->arg_begin(); - for (llvm::Function *Kernel : EmittedKernels) { - llvm::Constant *KernelName = makeConstantString(Kernel->getName()); - llvm::Constant *NullPtr = llvm::ConstantPointerNull::get(VoidPtrTy); - llvm::Value *Args[] = { - &GpuBinaryHandlePtr, Builder.CreateBitCast(Kernel, VoidPtrTy), - KernelName, KernelName, llvm::ConstantInt::get(IntTy, -1), NullPtr, - NullPtr, NullPtr, NullPtr, - llvm::ConstantPointerNull::get(IntTy->getPointerTo())}; - Builder.CreateCall(RegisterFunc, Args); - } - - // void __cudaRegisterVar(void **, char *, char *, const char *, - // int, int, int, int) - llvm::Type *RegisterVarParams[] = {VoidPtrPtrTy, CharPtrTy, CharPtrTy, - CharPtrTy, IntTy, IntTy, - IntTy, IntTy}; - llvm::Constant *RegisterVar = CGM.CreateRuntimeFunction( - llvm::FunctionType::get(IntTy, RegisterVarParams, false), - addUnderscoredPrefixToName("RegisterVar")); - for (auto &Pair : DeviceVars) { - llvm::GlobalVariable *Var = Pair.first; - unsigned Flags = Pair.second; - llvm::Constant *VarName = makeConstantString(Var->getName()); - uint64_t VarSize = - CGM.getDataLayout().getTypeAllocSize(Var->getValueType()); - llvm::Value *Args[] = { - &GpuBinaryHandlePtr, - Builder.CreateBitCast(Var, VoidPtrTy), - VarName, - VarName, - llvm::ConstantInt::get(IntTy, (Flags & ExternDeviceVar) ? 1 : 0), - llvm::ConstantInt::get(IntTy, VarSize), - llvm::ConstantInt::get(IntTy, (Flags & ConstantDeviceVar) ? 1 : 0), - llvm::ConstantInt::get(IntTy, 0)}; - Builder.CreateCall(RegisterVar, Args); - } - - Builder.CreateRetVoid(); - return RegisterKernelsFunc; -} - -/// Creates a global constructor function for the module: -/// -/// For CUDA: -/// \code -/// void __cuda_module_ctor(void*) { -/// Handle = __cudaRegisterFatBinary(GpuBinaryBlob); -/// __cuda_register_globals(Handle); -/// } -/// \endcode -/// -/// For HIP: -/// \code -/// void __hip_module_ctor(void*) { -/// if (__hip_gpubin_handle == 0) { -/// __hip_gpubin_handle = __hipRegisterFatBinary(GpuBinaryBlob); -/// __hip_register_globals(__hip_gpubin_handle); -/// } -/// } -/// \endcode -llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() { - bool IsHIP = CGM.getLangOpts().HIP; - // No need to generate ctors/dtors if there is no GPU binary. - StringRef CudaGpuBinaryFileName = CGM.getCodeGenOpts().CudaGpuBinaryFileName; - if (CudaGpuBinaryFileName.empty() && !IsHIP) - return nullptr; - - // void __{cuda|hip}_register_globals(void* handle); - llvm::Function *RegisterGlobalsFunc = makeRegisterGlobalsFn(); - // We always need a function to pass in as callback. Create a dummy - // implementation if we don't need to register anything. - if (RelocatableDeviceCode && !RegisterGlobalsFunc) - RegisterGlobalsFunc = makeDummyFunction(getRegisterGlobalsFnTy()); - - // void ** __{cuda|hip}RegisterFatBinary(void *); - llvm::Constant *RegisterFatbinFunc = CGM.CreateRuntimeFunction( - llvm::FunctionType::get(VoidPtrPtrTy, VoidPtrTy, false), - addUnderscoredPrefixToName("RegisterFatBinary")); - // struct { int magic, int version, void * gpu_binary, void * dont_care }; - llvm::StructType *FatbinWrapperTy = - llvm::StructType::get(IntTy, IntTy, VoidPtrTy, VoidPtrTy); - - // Register GPU binary with the CUDA runtime, store returned handle in a - // global variable and save a reference in GpuBinaryHandle to be cleaned up - // in destructor on exit. Then associate all known kernels with the GPU binary - // handle so CUDA runtime can figure out what to call on the GPU side. - std::unique_ptr<llvm::MemoryBuffer> CudaGpuBinary = nullptr; - if (!CudaGpuBinaryFileName.empty()) { - llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> CudaGpuBinaryOrErr = - llvm::MemoryBuffer::getFileOrSTDIN(CudaGpuBinaryFileName); - if (std::error_code EC = CudaGpuBinaryOrErr.getError()) { - CGM.getDiags().Report(diag::err_cannot_open_file) - << CudaGpuBinaryFileName << EC.message(); - return nullptr; - } - CudaGpuBinary = std::move(CudaGpuBinaryOrErr.get()); - } - - llvm::Function *ModuleCtorFunc = llvm::Function::Create( - llvm::FunctionType::get(VoidTy, VoidPtrTy, false), - llvm::GlobalValue::InternalLinkage, - addUnderscoredPrefixToName("_module_ctor"), &TheModule); - llvm::BasicBlock *CtorEntryBB = - llvm::BasicBlock::Create(Context, "entry", ModuleCtorFunc); - CGBuilderTy CtorBuilder(CGM, Context); - - CtorBuilder.SetInsertPoint(CtorEntryBB); - - const char *FatbinConstantName; - const char *FatbinSectionName; - const char *ModuleIDSectionName; - StringRef ModuleIDPrefix; - llvm::Constant *FatBinStr; - unsigned FatMagic; - if (IsHIP) { - FatbinConstantName = ".hip_fatbin"; - FatbinSectionName = ".hipFatBinSegment"; - - ModuleIDSectionName = "__hip_module_id"; - ModuleIDPrefix = "__hip_"; - - if (CudaGpuBinary) { - // If fatbin is available from early finalization, create a string - // literal containing the fat binary loaded from the given file. - FatBinStr = makeConstantString(CudaGpuBinary->getBuffer(), "", - FatbinConstantName, 8); - } else { - // If fatbin is not available, create an external symbol - // __hip_fatbin in section .hip_fatbin. The external symbol is supposed - // to contain the fat binary but will be populated somewhere else, - // e.g. by lld through link script. - FatBinStr = new llvm::GlobalVariable( - CGM.getModule(), CGM.Int8Ty, - /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage, nullptr, - "__hip_fatbin", nullptr, - llvm::GlobalVariable::NotThreadLocal); - cast<llvm::GlobalVariable>(FatBinStr)->setSection(FatbinConstantName); - } - - FatMagic = HIPFatMagic; - } else { - if (RelocatableDeviceCode) - FatbinConstantName = CGM.getTriple().isMacOSX() - ? "__NV_CUDA,__nv_relfatbin" - : "__nv_relfatbin"; - else - FatbinConstantName = - CGM.getTriple().isMacOSX() ? "__NV_CUDA,__nv_fatbin" : ".nv_fatbin"; - // NVIDIA's cuobjdump looks for fatbins in this section. - FatbinSectionName = - CGM.getTriple().isMacOSX() ? "__NV_CUDA,__fatbin" : ".nvFatBinSegment"; - - ModuleIDSectionName = CGM.getTriple().isMacOSX() - ? "__NV_CUDA,__nv_module_id" - : "__nv_module_id"; - ModuleIDPrefix = "__nv_"; - - // For CUDA, create a string literal containing the fat binary loaded from - // the given file. - FatBinStr = makeConstantString(CudaGpuBinary->getBuffer(), "", - FatbinConstantName, 8); - FatMagic = CudaFatMagic; - } - - // Create initialized wrapper structure that points to the loaded GPU binary - ConstantInitBuilder Builder(CGM); - auto Values = Builder.beginStruct(FatbinWrapperTy); - // Fatbin wrapper magic. - Values.addInt(IntTy, FatMagic); - // Fatbin version. - Values.addInt(IntTy, 1); - // Data. - Values.add(FatBinStr); - // Unused in fatbin v1. - Values.add(llvm::ConstantPointerNull::get(VoidPtrTy)); - llvm::GlobalVariable *FatbinWrapper = Values.finishAndCreateGlobal( - addUnderscoredPrefixToName("_fatbin_wrapper"), CGM.getPointerAlign(), - /*constant*/ true); - FatbinWrapper->setSection(FatbinSectionName); - - // There is only one HIP fat binary per linked module, however there are - // multiple constructor functions. Make sure the fat binary is registered - // only once. The constructor functions are executed by the dynamic loader - // before the program gains control. The dynamic loader cannot execute the - // constructor functions concurrently since doing that would not guarantee - // thread safety of the loaded program. Therefore we can assume sequential - // execution of constructor functions here. - if (IsHIP) { - auto Linkage = CudaGpuBinary ? llvm::GlobalValue::InternalLinkage : - llvm::GlobalValue::LinkOnceAnyLinkage; - llvm::BasicBlock *IfBlock = - llvm::BasicBlock::Create(Context, "if", ModuleCtorFunc); - llvm::BasicBlock *ExitBlock = - llvm::BasicBlock::Create(Context, "exit", ModuleCtorFunc); - // The name, size, and initialization pattern of this variable is part - // of HIP ABI. - GpuBinaryHandle = new llvm::GlobalVariable( - TheModule, VoidPtrPtrTy, /*isConstant=*/false, - Linkage, - /*Initializer=*/llvm::ConstantPointerNull::get(VoidPtrPtrTy), - "__hip_gpubin_handle"); - GpuBinaryHandle->setAlignment(CGM.getPointerAlign().getQuantity()); - // Prevent the weak symbol in different shared libraries being merged. - if (Linkage != llvm::GlobalValue::InternalLinkage) - GpuBinaryHandle->setVisibility(llvm::GlobalValue::HiddenVisibility); - Address GpuBinaryAddr( - GpuBinaryHandle, - CharUnits::fromQuantity(GpuBinaryHandle->getAlignment())); - { - auto HandleValue = CtorBuilder.CreateLoad(GpuBinaryAddr); - llvm::Constant *Zero = - llvm::Constant::getNullValue(HandleValue->getType()); - llvm::Value *EQZero = CtorBuilder.CreateICmpEQ(HandleValue, Zero); - CtorBuilder.CreateCondBr(EQZero, IfBlock, ExitBlock); - } - { - CtorBuilder.SetInsertPoint(IfBlock); - // GpuBinaryHandle = __hipRegisterFatBinary(&FatbinWrapper); - llvm::CallInst *RegisterFatbinCall = CtorBuilder.CreateCall( - RegisterFatbinFunc, - CtorBuilder.CreateBitCast(FatbinWrapper, VoidPtrTy)); - CtorBuilder.CreateStore(RegisterFatbinCall, GpuBinaryAddr); - CtorBuilder.CreateBr(ExitBlock); - } - { - CtorBuilder.SetInsertPoint(ExitBlock); - // Call __hip_register_globals(GpuBinaryHandle); - if (RegisterGlobalsFunc) { - auto HandleValue = CtorBuilder.CreateLoad(GpuBinaryAddr); - CtorBuilder.CreateCall(RegisterGlobalsFunc, HandleValue); - } - } - } else if (!RelocatableDeviceCode) { - // Register binary with CUDA runtime. This is substantially different in - // default mode vs. separate compilation! - // GpuBinaryHandle = __cudaRegisterFatBinary(&FatbinWrapper); - llvm::CallInst *RegisterFatbinCall = CtorBuilder.CreateCall( - RegisterFatbinFunc, - CtorBuilder.CreateBitCast(FatbinWrapper, VoidPtrTy)); - GpuBinaryHandle = new llvm::GlobalVariable( - TheModule, VoidPtrPtrTy, false, llvm::GlobalValue::InternalLinkage, - llvm::ConstantPointerNull::get(VoidPtrPtrTy), "__cuda_gpubin_handle"); - GpuBinaryHandle->setAlignment(CGM.getPointerAlign().getQuantity()); - CtorBuilder.CreateAlignedStore(RegisterFatbinCall, GpuBinaryHandle, - CGM.getPointerAlign()); - - // Call __cuda_register_globals(GpuBinaryHandle); - if (RegisterGlobalsFunc) - CtorBuilder.CreateCall(RegisterGlobalsFunc, RegisterFatbinCall); - } else { - // Generate a unique module ID. - SmallString<64> ModuleID; - llvm::raw_svector_ostream OS(ModuleID); - OS << ModuleIDPrefix << llvm::format("%" PRIx64, FatbinWrapper->getGUID()); - llvm::Constant *ModuleIDConstant = - makeConstantString(ModuleID.str(), "", ModuleIDSectionName, 32); - - // Create an alias for the FatbinWrapper that nvcc will look for. - llvm::GlobalAlias::create(llvm::GlobalValue::ExternalLinkage, - Twine("__fatbinwrap") + ModuleID, FatbinWrapper); - - // void __cudaRegisterLinkedBinary%ModuleID%(void (*)(void *), void *, - // void *, void (*)(void **)) - SmallString<128> RegisterLinkedBinaryName("__cudaRegisterLinkedBinary"); - RegisterLinkedBinaryName += ModuleID; - llvm::Constant *RegisterLinkedBinaryFunc = CGM.CreateRuntimeFunction( - getRegisterLinkedBinaryFnTy(), RegisterLinkedBinaryName); - - assert(RegisterGlobalsFunc && "Expecting at least dummy function!"); - llvm::Value *Args[] = {RegisterGlobalsFunc, - CtorBuilder.CreateBitCast(FatbinWrapper, VoidPtrTy), - ModuleIDConstant, - makeDummyFunction(getCallbackFnTy())}; - CtorBuilder.CreateCall(RegisterLinkedBinaryFunc, Args); - } - - // Create destructor and register it with atexit() the way NVCC does it. Doing - // it during regular destructor phase worked in CUDA before 9.2 but results in - // double-free in 9.2. - if (llvm::Function *CleanupFn = makeModuleDtorFunction()) { - // extern "C" int atexit(void (*f)(void)); - llvm::FunctionType *AtExitTy = - llvm::FunctionType::get(IntTy, CleanupFn->getType(), false); - llvm::Constant *AtExitFunc = - CGM.CreateRuntimeFunction(AtExitTy, "atexit", llvm::AttributeList(), - /*Local=*/true); - CtorBuilder.CreateCall(AtExitFunc, CleanupFn); - } - - CtorBuilder.CreateRetVoid(); - return ModuleCtorFunc; -} - -/// Creates a global destructor function that unregisters the GPU code blob -/// registered by constructor. -/// -/// For CUDA: -/// \code -/// void __cuda_module_dtor(void*) { -/// __cudaUnregisterFatBinary(Handle); -/// } -/// \endcode -/// -/// For HIP: -/// \code -/// void __hip_module_dtor(void*) { -/// if (__hip_gpubin_handle) { -/// __hipUnregisterFatBinary(__hip_gpubin_handle); -/// __hip_gpubin_handle = 0; -/// } -/// } -/// \endcode -llvm::Function *CGNVCUDARuntime::makeModuleDtorFunction() { - // No need for destructor if we don't have a handle to unregister. - if (!GpuBinaryHandle) - return nullptr; - - // void __cudaUnregisterFatBinary(void ** handle); - llvm::Constant *UnregisterFatbinFunc = CGM.CreateRuntimeFunction( - llvm::FunctionType::get(VoidTy, VoidPtrPtrTy, false), - addUnderscoredPrefixToName("UnregisterFatBinary")); - - llvm::Function *ModuleDtorFunc = llvm::Function::Create( - llvm::FunctionType::get(VoidTy, VoidPtrTy, false), - llvm::GlobalValue::InternalLinkage, - addUnderscoredPrefixToName("_module_dtor"), &TheModule); - - llvm::BasicBlock *DtorEntryBB = - llvm::BasicBlock::Create(Context, "entry", ModuleDtorFunc); - CGBuilderTy DtorBuilder(CGM, Context); - DtorBuilder.SetInsertPoint(DtorEntryBB); - - Address GpuBinaryAddr(GpuBinaryHandle, CharUnits::fromQuantity( - GpuBinaryHandle->getAlignment())); - auto HandleValue = DtorBuilder.CreateLoad(GpuBinaryAddr); - // There is only one HIP fat binary per linked module, however there are - // multiple destructor functions. Make sure the fat binary is unregistered - // only once. - if (CGM.getLangOpts().HIP) { - llvm::BasicBlock *IfBlock = - llvm::BasicBlock::Create(Context, "if", ModuleDtorFunc); - llvm::BasicBlock *ExitBlock = - llvm::BasicBlock::Create(Context, "exit", ModuleDtorFunc); - llvm::Constant *Zero = llvm::Constant::getNullValue(HandleValue->getType()); - llvm::Value *NEZero = DtorBuilder.CreateICmpNE(HandleValue, Zero); - DtorBuilder.CreateCondBr(NEZero, IfBlock, ExitBlock); - - DtorBuilder.SetInsertPoint(IfBlock); - DtorBuilder.CreateCall(UnregisterFatbinFunc, HandleValue); - DtorBuilder.CreateStore(Zero, GpuBinaryAddr); - DtorBuilder.CreateBr(ExitBlock); - - DtorBuilder.SetInsertPoint(ExitBlock); - } else { - DtorBuilder.CreateCall(UnregisterFatbinFunc, HandleValue); - } - DtorBuilder.CreateRetVoid(); - return ModuleDtorFunc; -} - -CGCUDARuntime *CodeGen::CreateNVCUDARuntime(CodeGenModule &CGM) { - return new CGNVCUDARuntime(CGM); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGCUDARuntime.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGCUDARuntime.cpp deleted file mode 100644 index 1936f9f1369..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGCUDARuntime.cpp +++ /dev/null @@ -1,46 +0,0 @@ -//===----- CGCUDARuntime.cpp - Interface to CUDA Runtimes -----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This provides an abstract class for CUDA code generation. Concrete -// subclasses of this implement code generation for specific CUDA -// runtime libraries. -// -//===----------------------------------------------------------------------===// - -#include "CGCUDARuntime.h" -#include "CGCall.h" -#include "CodeGenFunction.h" -#include "clang/AST/Decl.h" -#include "clang/AST/ExprCXX.h" - -using namespace clang; -using namespace CodeGen; - -CGCUDARuntime::~CGCUDARuntime() {} - -RValue CGCUDARuntime::EmitCUDAKernelCallExpr(CodeGenFunction &CGF, - const CUDAKernelCallExpr *E, - ReturnValueSlot ReturnValue) { - llvm::BasicBlock *ConfigOKBlock = CGF.createBasicBlock("kcall.configok"); - llvm::BasicBlock *ContBlock = CGF.createBasicBlock("kcall.end"); - - CodeGenFunction::ConditionalEvaluation eval(CGF); - CGF.EmitBranchOnBoolExpr(E->getConfig(), ContBlock, ConfigOKBlock, - /*TrueCount=*/0); - - eval.begin(CGF); - CGF.EmitBlock(ConfigOKBlock); - CGF.EmitSimpleCallExpr(E, ReturnValue); - CGF.EmitBranch(ContBlock); - - CGF.EmitBlock(ContBlock); - eval.end(CGF); - - return RValue::get(nullptr); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGCUDARuntime.h b/gnu/llvm/tools/clang/lib/CodeGen/CGCUDARuntime.h deleted file mode 100644 index 0168f4f9e94..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGCUDARuntime.h +++ /dev/null @@ -1,73 +0,0 @@ -//===----- CGCUDARuntime.h - Interface to CUDA Runtimes ---------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This provides an abstract class for CUDA code generation. Concrete -// subclasses of this implement code generation for specific CUDA -// runtime libraries. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CGCUDARUNTIME_H -#define LLVM_CLANG_LIB_CODEGEN_CGCUDARUNTIME_H - -namespace llvm { -class Function; -class GlobalVariable; -} - -namespace clang { - -class CUDAKernelCallExpr; - -namespace CodeGen { - -class CodeGenFunction; -class CodeGenModule; -class FunctionArgList; -class ReturnValueSlot; -class RValue; - -class CGCUDARuntime { -protected: - CodeGenModule &CGM; - -public: - // Global variable properties that must be passed to CUDA runtime. - enum DeviceVarFlags { - ExternDeviceVar = 0x01, // extern - ConstantDeviceVar = 0x02, // __constant__ - }; - - CGCUDARuntime(CodeGenModule &CGM) : CGM(CGM) {} - virtual ~CGCUDARuntime(); - - virtual RValue EmitCUDAKernelCallExpr(CodeGenFunction &CGF, - const CUDAKernelCallExpr *E, - ReturnValueSlot ReturnValue); - - /// Emits a kernel launch stub. - virtual void emitDeviceStub(CodeGenFunction &CGF, FunctionArgList &Args) = 0; - virtual void registerDeviceVar(llvm::GlobalVariable &Var, unsigned Flags) = 0; - - /// Constructs and returns a module initialization function or nullptr if it's - /// not needed. Must be called after all kernels have been emitted. - virtual llvm::Function *makeModuleCtorFunction() = 0; - - /// Returns a module cleanup function or nullptr if it's not needed. - /// Must be called after ModuleCtorFunction - virtual llvm::Function *makeModuleDtorFunction() = 0; -}; - -/// Creates an instance of a CUDA runtime class. -CGCUDARuntime *CreateNVCUDARuntime(CodeGenModule &CGM); - -} -} - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGCXX.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGCXX.cpp deleted file mode 100644 index 8b0733fbec3..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGCXX.cpp +++ /dev/null @@ -1,318 +0,0 @@ -//===--- CGCXX.cpp - Emit LLVM Code for declarations ----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code dealing with C++ code generation. -// -//===----------------------------------------------------------------------===// - -// We might split this into multiple files if it gets too unwieldy - -#include "CodeGenModule.h" -#include "CGCXXABI.h" -#include "CodeGenFunction.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/Mangle.h" -#include "clang/AST/RecordLayout.h" -#include "clang/AST/StmtCXX.h" -#include "clang/Basic/CodeGenOptions.h" -#include "llvm/ADT/StringExtras.h" -using namespace clang; -using namespace CodeGen; - - -/// Try to emit a base destructor as an alias to its primary -/// base-class destructor. -bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) { - if (!getCodeGenOpts().CXXCtorDtorAliases) - return true; - - // Producing an alias to a base class ctor/dtor can degrade debug quality - // as the debugger cannot tell them apart. - if (getCodeGenOpts().OptimizationLevel == 0) - return true; - - // If sanitizing memory to check for use-after-dtor, do not emit as - // an alias, unless this class owns no members. - if (getCodeGenOpts().SanitizeMemoryUseAfterDtor && - !D->getParent()->field_empty()) - return true; - - // If the destructor doesn't have a trivial body, we have to emit it - // separately. - if (!D->hasTrivialBody()) - return true; - - const CXXRecordDecl *Class = D->getParent(); - - // We are going to instrument this destructor, so give up even if it is - // currently empty. - if (Class->mayInsertExtraPadding()) - return true; - - // If we need to manipulate a VTT parameter, give up. - if (Class->getNumVBases()) { - // Extra Credit: passing extra parameters is perfectly safe - // in many calling conventions, so only bail out if the ctor's - // calling convention is nonstandard. - return true; - } - - // If any field has a non-trivial destructor, we have to emit the - // destructor separately. - for (const auto *I : Class->fields()) - if (I->getType().isDestructedType()) - return true; - - // Try to find a unique base class with a non-trivial destructor. - const CXXRecordDecl *UniqueBase = nullptr; - for (const auto &I : Class->bases()) { - - // We're in the base destructor, so skip virtual bases. - if (I.isVirtual()) continue; - - // Skip base classes with trivial destructors. - const auto *Base = - cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl()); - if (Base->hasTrivialDestructor()) continue; - - // If we've already found a base class with a non-trivial - // destructor, give up. - if (UniqueBase) return true; - UniqueBase = Base; - } - - // If we didn't find any bases with a non-trivial destructor, then - // the base destructor is actually effectively trivial, which can - // happen if it was needlessly user-defined or if there are virtual - // bases with non-trivial destructors. - if (!UniqueBase) - return true; - - // If the base is at a non-zero offset, give up. - const ASTRecordLayout &ClassLayout = Context.getASTRecordLayout(Class); - if (!ClassLayout.getBaseClassOffset(UniqueBase).isZero()) - return true; - - // Give up if the calling conventions don't match. We could update the call, - // but it is probably not worth it. - const CXXDestructorDecl *BaseD = UniqueBase->getDestructor(); - if (BaseD->getType()->getAs<FunctionType>()->getCallConv() != - D->getType()->getAs<FunctionType>()->getCallConv()) - return true; - - GlobalDecl AliasDecl(D, Dtor_Base); - GlobalDecl TargetDecl(BaseD, Dtor_Base); - - // The alias will use the linkage of the referent. If we can't - // support aliases with that linkage, fail. - llvm::GlobalValue::LinkageTypes Linkage = getFunctionLinkage(AliasDecl); - - // We can't use an alias if the linkage is not valid for one. - if (!llvm::GlobalAlias::isValidLinkage(Linkage)) - return true; - - llvm::GlobalValue::LinkageTypes TargetLinkage = - getFunctionLinkage(TargetDecl); - - // Check if we have it already. - StringRef MangledName = getMangledName(AliasDecl); - llvm::GlobalValue *Entry = GetGlobalValue(MangledName); - if (Entry && !Entry->isDeclaration()) - return false; - if (Replacements.count(MangledName)) - return false; - - // Derive the type for the alias. - llvm::Type *AliasValueType = getTypes().GetFunctionType(AliasDecl); - llvm::PointerType *AliasType = AliasValueType->getPointerTo(); - - // Find the referent. Some aliases might require a bitcast, in - // which case the caller is responsible for ensuring the soundness - // of these semantics. - auto *Ref = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl)); - llvm::Constant *Aliasee = Ref; - if (Ref->getType() != AliasType) - Aliasee = llvm::ConstantExpr::getBitCast(Ref, AliasType); - - // Instead of creating as alias to a linkonce_odr, replace all of the uses - // of the aliasee. - if (llvm::GlobalValue::isDiscardableIfUnused(Linkage) && - !(TargetLinkage == llvm::GlobalValue::AvailableExternallyLinkage && - TargetDecl.getDecl()->hasAttr<AlwaysInlineAttr>())) { - // FIXME: An extern template instantiation will create functions with - // linkage "AvailableExternally". In libc++, some classes also define - // members with attribute "AlwaysInline" and expect no reference to - // be generated. It is desirable to reenable this optimisation after - // corresponding LLVM changes. - addReplacement(MangledName, Aliasee); - return false; - } - - // If we have a weak, non-discardable alias (weak, weak_odr), like an extern - // template instantiation or a dllexported class, avoid forming it on COFF. - // A COFF weak external alias cannot satisfy a normal undefined symbol - // reference from another TU. The other TU must also mark the referenced - // symbol as weak, which we cannot rely on. - if (llvm::GlobalValue::isWeakForLinker(Linkage) && - getTriple().isOSBinFormatCOFF()) { - return true; - } - - // If we don't have a definition for the destructor yet or the definition is - // avaialable_externally, don't emit an alias. We can't emit aliases to - // declarations; that's just not how aliases work. - if (Ref->isDeclarationForLinker()) - return true; - - // Don't create an alias to a linker weak symbol. This avoids producing - // different COMDATs in different TUs. Another option would be to - // output the alias both for weak_odr and linkonce_odr, but that - // requires explicit comdat support in the IL. - if (llvm::GlobalValue::isWeakForLinker(TargetLinkage)) - return true; - - // Create the alias with no name. - auto *Alias = llvm::GlobalAlias::create(AliasValueType, 0, Linkage, "", - Aliasee, &getModule()); - - // Destructors are always unnamed_addr. - Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - - // Switch any previous uses to the alias. - if (Entry) { - assert(Entry->getType() == AliasType && - "declaration exists with different type"); - Alias->takeName(Entry); - Entry->replaceAllUsesWith(Alias); - Entry->eraseFromParent(); - } else { - Alias->setName(MangledName); - } - - // Finally, set up the alias with its proper name and attributes. - SetCommonAttributes(AliasDecl, Alias); - - return false; -} - -llvm::Function *CodeGenModule::codegenCXXStructor(const CXXMethodDecl *MD, - StructorType Type) { - const CGFunctionInfo &FnInfo = - getTypes().arrangeCXXStructorDeclaration(MD, Type); - auto *Fn = cast<llvm::Function>( - getAddrOfCXXStructor(MD, Type, &FnInfo, /*FnType=*/nullptr, - /*DontDefer=*/true, ForDefinition)); - - GlobalDecl GD; - if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) { - GD = GlobalDecl(DD, toCXXDtorType(Type)); - } else { - const auto *CD = cast<CXXConstructorDecl>(MD); - GD = GlobalDecl(CD, toCXXCtorType(Type)); - } - - setFunctionLinkage(GD, Fn); - - CodeGenFunction(*this).GenerateCode(GD, Fn, FnInfo); - setNonAliasAttributes(GD, Fn); - SetLLVMFunctionAttributesForDefinition(MD, Fn); - return Fn; -} - -llvm::Constant *CodeGenModule::getAddrOfCXXStructor( - const CXXMethodDecl *MD, StructorType Type, const CGFunctionInfo *FnInfo, - llvm::FunctionType *FnType, bool DontDefer, - ForDefinition_t IsForDefinition) { - GlobalDecl GD; - if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) { - GD = GlobalDecl(CD, toCXXCtorType(Type)); - } else { - // Always alias equivalent complete destructors to base destructors in the - // MS ABI. - if (getTarget().getCXXABI().isMicrosoft() && - Type == StructorType::Complete && MD->getParent()->getNumVBases() == 0) - Type = StructorType::Base; - GD = GlobalDecl(cast<CXXDestructorDecl>(MD), toCXXDtorType(Type)); - } - - if (!FnType) { - if (!FnInfo) - FnInfo = &getTypes().arrangeCXXStructorDeclaration(MD, Type); - FnType = getTypes().GetFunctionType(*FnInfo); - } - - return GetOrCreateLLVMFunction( - getMangledName(GD), FnType, GD, /*ForVTable=*/false, DontDefer, - /*isThunk=*/false, /*ExtraAttrs=*/llvm::AttributeList(), IsForDefinition); -} - -static CGCallee BuildAppleKextVirtualCall(CodeGenFunction &CGF, - GlobalDecl GD, - llvm::Type *Ty, - const CXXRecordDecl *RD) { - assert(!CGF.CGM.getTarget().getCXXABI().isMicrosoft() && - "No kext in Microsoft ABI"); - CodeGenModule &CGM = CGF.CGM; - llvm::Value *VTable = CGM.getCXXABI().getAddrOfVTable(RD, CharUnits()); - Ty = Ty->getPointerTo()->getPointerTo(); - VTable = CGF.Builder.CreateBitCast(VTable, Ty); - assert(VTable && "BuildVirtualCall = kext vtbl pointer is null"); - uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD); - const VTableLayout &VTLayout = CGM.getItaniumVTableContext().getVTableLayout(RD); - VTableLayout::AddressPointLocation AddressPoint = - VTLayout.getAddressPoint(BaseSubobject(RD, CharUnits::Zero())); - VTableIndex += VTLayout.getVTableOffset(AddressPoint.VTableIndex) + - AddressPoint.AddressPointIndex; - llvm::Value *VFuncPtr = - CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt"); - llvm::Value *VFunc = - CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.PointerAlignInBytes); - CGCallee Callee(GD, VFunc); - return Callee; -} - -/// BuildAppleKextVirtualCall - This routine is to support gcc's kext ABI making -/// indirect call to virtual functions. It makes the call through indexing -/// into the vtable. -CGCallee -CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD, - NestedNameSpecifier *Qual, - llvm::Type *Ty) { - assert((Qual->getKind() == NestedNameSpecifier::TypeSpec) && - "BuildAppleKextVirtualCall - bad Qual kind"); - - const Type *QTy = Qual->getAsType(); - QualType T = QualType(QTy, 0); - const RecordType *RT = T->getAs<RecordType>(); - assert(RT && "BuildAppleKextVirtualCall - Qual type must be record"); - const auto *RD = cast<CXXRecordDecl>(RT->getDecl()); - - if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) - return BuildAppleKextVirtualDestructorCall(DD, Dtor_Complete, RD); - - return ::BuildAppleKextVirtualCall(*this, MD, Ty, RD); -} - -/// BuildVirtualCall - This routine makes indirect vtable call for -/// call to virtual destructors. It returns 0 if it could not do it. -CGCallee -CodeGenFunction::BuildAppleKextVirtualDestructorCall( - const CXXDestructorDecl *DD, - CXXDtorType Type, - const CXXRecordDecl *RD) { - assert(DD->isVirtual() && Type != Dtor_Base); - // Compute the function type we're calling. - const CGFunctionInfo &FInfo = CGM.getTypes().arrangeCXXStructorDeclaration( - DD, StructorType::Complete); - llvm::Type *Ty = CGM.getTypes().GetFunctionType(FInfo); - return ::BuildAppleKextVirtualCall(*this, GlobalDecl(DD, Type), Ty, RD); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp deleted file mode 100644 index ed168b1ce72..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp +++ /dev/null @@ -1,321 +0,0 @@ -//===----- CGCXXABI.cpp - Interface to C++ ABIs ---------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This provides an abstract class for C++ code generation. Concrete subclasses -// of this implement code generation for specific C++ ABIs. -// -//===----------------------------------------------------------------------===// - -#include "CGCXXABI.h" -#include "CGCleanup.h" - -using namespace clang; -using namespace CodeGen; - -CGCXXABI::~CGCXXABI() { } - -void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) { - DiagnosticsEngine &Diags = CGF.CGM.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot yet compile %0 in this ABI"); - Diags.Report(CGF.getContext().getFullLoc(CGF.CurCodeDecl->getLocation()), - DiagID) - << S; -} - -bool CGCXXABI::canCopyArgument(const CXXRecordDecl *RD) const { - // We can only copy the argument if there exists at least one trivial, - // non-deleted copy or move constructor. - return RD->canPassInRegisters(); -} - -llvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) { - return llvm::Constant::getNullValue(CGM.getTypes().ConvertType(T)); -} - -llvm::Type * -CGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) { - return CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType()); -} - -CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer( - CodeGenFunction &CGF, const Expr *E, Address This, - llvm::Value *&ThisPtrForCall, - llvm::Value *MemPtr, const MemberPointerType *MPT) { - ErrorUnsupportedABI(CGF, "calls through member pointers"); - - ThisPtrForCall = This.getPointer(); - const FunctionProtoType *FPT = - MPT->getPointeeType()->getAs<FunctionProtoType>(); - const CXXRecordDecl *RD = - cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl()); - llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType( - CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr)); - llvm::Constant *FnPtr = llvm::Constant::getNullValue(FTy->getPointerTo()); - return CGCallee::forDirect(FnPtr, FPT); -} - -llvm::Value * -CGCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E, - Address Base, llvm::Value *MemPtr, - const MemberPointerType *MPT) { - ErrorUnsupportedABI(CGF, "loads of member pointers"); - llvm::Type *Ty = CGF.ConvertType(MPT->getPointeeType()) - ->getPointerTo(Base.getAddressSpace()); - return llvm::Constant::getNullValue(Ty); -} - -llvm::Value *CGCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, - const CastExpr *E, - llvm::Value *Src) { - ErrorUnsupportedABI(CGF, "member function pointer conversions"); - return GetBogusMemberPointer(E->getType()); -} - -llvm::Constant *CGCXXABI::EmitMemberPointerConversion(const CastExpr *E, - llvm::Constant *Src) { - return GetBogusMemberPointer(E->getType()); -} - -llvm::Value * -CGCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF, - llvm::Value *L, - llvm::Value *R, - const MemberPointerType *MPT, - bool Inequality) { - ErrorUnsupportedABI(CGF, "member function pointer comparison"); - return CGF.Builder.getFalse(); -} - -llvm::Value * -CGCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF, - llvm::Value *MemPtr, - const MemberPointerType *MPT) { - ErrorUnsupportedABI(CGF, "member function pointer null testing"); - return CGF.Builder.getFalse(); -} - -llvm::Constant * -CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { - return GetBogusMemberPointer(QualType(MPT, 0)); -} - -llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { - return GetBogusMemberPointer(CGM.getContext().getMemberPointerType( - MD->getType(), MD->getParent()->getTypeForDecl())); -} - -llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, - CharUnits offset) { - return GetBogusMemberPointer(QualType(MPT, 0)); -} - -llvm::Constant *CGCXXABI::EmitMemberPointer(const APValue &MP, QualType MPT) { - return GetBogusMemberPointer(MPT); -} - -bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) { - // Fake answer. - return true; -} - -void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList ¶ms) { - const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); - - // FIXME: I'm not entirely sure I like using a fake decl just for code - // generation. Maybe we can come up with a better way? - auto *ThisDecl = ImplicitParamDecl::Create( - CGM.getContext(), nullptr, MD->getLocation(), - &CGM.getContext().Idents.get("this"), MD->getThisType(), - ImplicitParamDecl::CXXThis); - params.push_back(ThisDecl); - CGF.CXXABIThisDecl = ThisDecl; - - // Compute the presumed alignment of 'this', which basically comes - // down to whether we know it's a complete object or not. - auto &Layout = CGF.getContext().getASTRecordLayout(MD->getParent()); - if (MD->getParent()->getNumVBases() == 0 || // avoid vcall in common case - MD->getParent()->hasAttr<FinalAttr>() || - !isThisCompleteObject(CGF.CurGD)) { - CGF.CXXABIThisAlignment = Layout.getAlignment(); - } else { - CGF.CXXABIThisAlignment = Layout.getNonVirtualAlignment(); - } -} - -llvm::Value *CGCXXABI::loadIncomingCXXThis(CodeGenFunction &CGF) { - return CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)), - "this"); -} - -void CGCXXABI::setCXXABIThisValue(CodeGenFunction &CGF, llvm::Value *ThisPtr) { - /// Initialize the 'this' slot. - assert(getThisDecl(CGF) && "no 'this' variable for function"); - CGF.CXXABIThisValue = ThisPtr; -} - -void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, - RValue RV, QualType ResultType) { - CGF.EmitReturnOfRValue(RV, ResultType); -} - -CharUnits CGCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { - if (!requiresArrayCookie(expr)) - return CharUnits::Zero(); - return getArrayCookieSizeImpl(expr->getAllocatedType()); -} - -CharUnits CGCXXABI::getArrayCookieSizeImpl(QualType elementType) { - // BOGUS - return CharUnits::Zero(); -} - -Address CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, - Address NewPtr, - llvm::Value *NumElements, - const CXXNewExpr *expr, - QualType ElementType) { - // Should never be called. - ErrorUnsupportedABI(CGF, "array cookie initialization"); - return Address::invalid(); -} - -bool CGCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr, - QualType elementType) { - // If the class's usual deallocation function takes two arguments, - // it needs a cookie. - if (expr->doesUsualArrayDeleteWantSize()) - return true; - - return elementType.isDestructedType(); -} - -bool CGCXXABI::requiresArrayCookie(const CXXNewExpr *expr) { - // If the class's usual deallocation function takes two arguments, - // it needs a cookie. - if (expr->doesUsualArrayDeleteWantSize()) - return true; - - return expr->getAllocatedType().isDestructedType(); -} - -void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr, - const CXXDeleteExpr *expr, QualType eltTy, - llvm::Value *&numElements, - llvm::Value *&allocPtr, CharUnits &cookieSize) { - // Derive a char* in the same address space as the pointer. - ptr = CGF.Builder.CreateElementBitCast(ptr, CGF.Int8Ty); - - // If we don't need an array cookie, bail out early. - if (!requiresArrayCookie(expr, eltTy)) { - allocPtr = ptr.getPointer(); - numElements = nullptr; - cookieSize = CharUnits::Zero(); - return; - } - - cookieSize = getArrayCookieSizeImpl(eltTy); - Address allocAddr = - CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize); - allocPtr = allocAddr.getPointer(); - numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize); -} - -llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, - Address ptr, - CharUnits cookieSize) { - ErrorUnsupportedABI(CGF, "reading a new[] cookie"); - return llvm::ConstantInt::get(CGF.SizeTy, 0); -} - -/// Returns the adjustment, in bytes, required for the given -/// member-pointer operation. Returns null if no adjustment is -/// required. -llvm::Constant *CGCXXABI::getMemberPointerAdjustment(const CastExpr *E) { - assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || - E->getCastKind() == CK_BaseToDerivedMemberPointer); - - QualType derivedType; - if (E->getCastKind() == CK_DerivedToBaseMemberPointer) - derivedType = E->getSubExpr()->getType(); - else - derivedType = E->getType(); - - const CXXRecordDecl *derivedClass = - derivedType->castAs<MemberPointerType>()->getClass()->getAsCXXRecordDecl(); - - return CGM.GetNonVirtualBaseClassOffset(derivedClass, - E->path_begin(), - E->path_end()); -} - -CharUnits CGCXXABI::getMemberPointerPathAdjustment(const APValue &MP) { - // TODO: Store base specifiers in APValue member pointer paths so we can - // easily reuse CGM.GetNonVirtualBaseClassOffset(). - const ValueDecl *MPD = MP.getMemberPointerDecl(); - CharUnits ThisAdjustment = CharUnits::Zero(); - ArrayRef<const CXXRecordDecl*> Path = MP.getMemberPointerPath(); - bool DerivedMember = MP.isMemberPointerToDerivedMember(); - const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPD->getDeclContext()); - for (unsigned I = 0, N = Path.size(); I != N; ++I) { - const CXXRecordDecl *Base = RD; - const CXXRecordDecl *Derived = Path[I]; - if (DerivedMember) - std::swap(Base, Derived); - ThisAdjustment += - getContext().getASTRecordLayout(Derived).getBaseClassOffset(Base); - RD = Path[I]; - } - if (DerivedMember) - ThisAdjustment = -ThisAdjustment; - return ThisAdjustment; -} - -llvm::BasicBlock * -CGCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, - const CXXRecordDecl *RD) { - if (CGM.getTarget().getCXXABI().hasConstructorVariants()) - llvm_unreachable("shouldn't be called in this ABI"); - - ErrorUnsupportedABI(CGF, "complete object detection in ctor"); - return nullptr; -} - -void CGCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV, - const CXXDestructorDecl *Dtor, - CXXDtorType DT) const { - // Assume the base C++ ABI has no special rules for destructor variants. - CGM.setDLLImportDLLExport(GV, Dtor); -} - -llvm::GlobalValue::LinkageTypes CGCXXABI::getCXXDestructorLinkage( - GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const { - // Delegate back to CGM by default. - return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage, - /*isConstantVariable=*/false); -} - -bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) { - return false; -} - -llvm::CallInst * -CGCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF, - llvm::Value *Exn) { - // Just call std::terminate and ignore the violating exception. - return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn()); -} - -CatchTypeInfo CGCXXABI::getCatchAllTypeInfo() { - return CatchTypeInfo{nullptr, 0}; -} - -std::vector<CharUnits> CGCXXABI::getVBPtrOffsets(const CXXRecordDecl *RD) { - return std::vector<CharUnits>(); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGCXXABI.h b/gnu/llvm/tools/clang/lib/CodeGen/CGCXXABI.h deleted file mode 100644 index 65b50e14f43..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGCXXABI.h +++ /dev/null @@ -1,624 +0,0 @@ -//===----- CGCXXABI.h - Interface to C++ ABIs -------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This provides an abstract class for C++ code generation. Concrete subclasses -// of this implement code generation for specific C++ ABIs. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CGCXXABI_H -#define LLVM_CLANG_LIB_CODEGEN_CGCXXABI_H - -#include "CodeGenFunction.h" -#include "clang/Basic/LLVM.h" - -namespace llvm { -class Constant; -class Type; -class Value; -class CallInst; -} - -namespace clang { -class CastExpr; -class CXXConstructorDecl; -class CXXDestructorDecl; -class CXXMethodDecl; -class CXXRecordDecl; -class FieldDecl; -class MangleContext; - -namespace CodeGen { -class CGCallee; -class CodeGenFunction; -class CodeGenModule; -struct CatchTypeInfo; - -/// Implements C++ ABI-specific code generation functions. -class CGCXXABI { -protected: - CodeGenModule &CGM; - std::unique_ptr<MangleContext> MangleCtx; - - CGCXXABI(CodeGenModule &CGM) - : CGM(CGM), MangleCtx(CGM.getContext().createMangleContext()) {} - -protected: - ImplicitParamDecl *getThisDecl(CodeGenFunction &CGF) { - return CGF.CXXABIThisDecl; - } - llvm::Value *getThisValue(CodeGenFunction &CGF) { - return CGF.CXXABIThisValue; - } - Address getThisAddress(CodeGenFunction &CGF) { - return Address(CGF.CXXABIThisValue, CGF.CXXABIThisAlignment); - } - - /// Issue a diagnostic about unsupported features in the ABI. - void ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S); - - /// Get a null value for unsupported member pointers. - llvm::Constant *GetBogusMemberPointer(QualType T); - - ImplicitParamDecl *&getStructorImplicitParamDecl(CodeGenFunction &CGF) { - return CGF.CXXStructorImplicitParamDecl; - } - llvm::Value *&getStructorImplicitParamValue(CodeGenFunction &CGF) { - return CGF.CXXStructorImplicitParamValue; - } - - /// Loads the incoming C++ this pointer as it was passed by the caller. - llvm::Value *loadIncomingCXXThis(CodeGenFunction &CGF); - - void setCXXABIThisValue(CodeGenFunction &CGF, llvm::Value *ThisPtr); - - ASTContext &getContext() const { return CGM.getContext(); } - - virtual bool requiresArrayCookie(const CXXDeleteExpr *E, QualType eltType); - virtual bool requiresArrayCookie(const CXXNewExpr *E); - - /// Determine whether there's something special about the rules of - /// the ABI tell us that 'this' is a complete object within the - /// given function. Obvious common logic like being defined on a - /// final class will have been taken care of by the caller. - virtual bool isThisCompleteObject(GlobalDecl GD) const = 0; - -public: - - virtual ~CGCXXABI(); - - /// Gets the mangle context. - MangleContext &getMangleContext() { - return *MangleCtx; - } - - /// Returns true if the given constructor or destructor is one of the - /// kinds that the ABI says returns 'this' (only applies when called - /// non-virtually for destructors). - /// - /// There currently is no way to indicate if a destructor returns 'this' - /// when called virtually, and code generation does not support the case. - virtual bool HasThisReturn(GlobalDecl GD) const { return false; } - - virtual bool hasMostDerivedReturn(GlobalDecl GD) const { return false; } - - /// Returns true if the target allows calling a function through a pointer - /// with a different signature than the actual function (or equivalently, - /// bitcasting a function or function pointer to a different function type). - /// In principle in the most general case this could depend on the target, the - /// calling convention, and the actual types of the arguments and return - /// value. Here it just means whether the signature mismatch could *ever* be - /// allowed; in other words, does the target do strict checking of signatures - /// for all calls. - virtual bool canCallMismatchedFunctionType() const { return true; } - - /// If the C++ ABI requires the given type be returned in a particular way, - /// this method sets RetAI and returns true. - virtual bool classifyReturnType(CGFunctionInfo &FI) const = 0; - - /// Specify how one should pass an argument of a record type. - enum RecordArgABI { - /// Pass it using the normal C aggregate rules for the ABI, potentially - /// introducing extra copies and passing some or all of it in registers. - RAA_Default = 0, - - /// Pass it on the stack using its defined layout. The argument must be - /// evaluated directly into the correct stack position in the arguments area, - /// and the call machinery must not move it or introduce extra copies. - RAA_DirectInMemory, - - /// Pass it as a pointer to temporary memory. - RAA_Indirect - }; - - /// Returns true if C++ allows us to copy the memory of an object of type RD - /// when it is passed as an argument. - bool canCopyArgument(const CXXRecordDecl *RD) const; - - /// Returns how an argument of the given record type should be passed. - virtual RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const = 0; - - /// Returns true if the implicit 'sret' parameter comes after the implicit - /// 'this' parameter of C++ instance methods. - virtual bool isSRetParameterAfterThis() const { return false; } - - /// Find the LLVM type used to represent the given member pointer - /// type. - virtual llvm::Type * - ConvertMemberPointerType(const MemberPointerType *MPT); - - /// Load a member function from an object and a member function - /// pointer. Apply the this-adjustment and set 'This' to the - /// adjusted value. - virtual CGCallee EmitLoadOfMemberFunctionPointer( - CodeGenFunction &CGF, const Expr *E, Address This, - llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr, - const MemberPointerType *MPT); - - /// Calculate an l-value from an object and a data member pointer. - virtual llvm::Value * - EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E, - Address Base, llvm::Value *MemPtr, - const MemberPointerType *MPT); - - /// Perform a derived-to-base, base-to-derived, or bitcast member - /// pointer conversion. - virtual llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF, - const CastExpr *E, - llvm::Value *Src); - - /// Perform a derived-to-base, base-to-derived, or bitcast member - /// pointer conversion on a constant value. - virtual llvm::Constant *EmitMemberPointerConversion(const CastExpr *E, - llvm::Constant *Src); - - /// Return true if the given member pointer can be zero-initialized - /// (in the C++ sense) with an LLVM zeroinitializer. - virtual bool isZeroInitializable(const MemberPointerType *MPT); - - /// Return whether or not a member pointers type is convertible to an IR type. - virtual bool isMemberPointerConvertible(const MemberPointerType *MPT) const { - return true; - } - - /// Create a null member pointer of the given type. - virtual llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT); - - /// Create a member pointer for the given method. - virtual llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD); - - /// Create a member pointer for the given field. - virtual llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT, - CharUnits offset); - - /// Create a member pointer for the given member pointer constant. - virtual llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT); - - /// Emit a comparison between two member pointers. Returns an i1. - virtual llvm::Value * - EmitMemberPointerComparison(CodeGenFunction &CGF, - llvm::Value *L, - llvm::Value *R, - const MemberPointerType *MPT, - bool Inequality); - - /// Determine if a member pointer is non-null. Returns an i1. - virtual llvm::Value * - EmitMemberPointerIsNotNull(CodeGenFunction &CGF, - llvm::Value *MemPtr, - const MemberPointerType *MPT); - -protected: - /// A utility method for computing the offset required for the given - /// base-to-derived or derived-to-base member-pointer conversion. - /// Does not handle virtual conversions (in case we ever fully - /// support an ABI that allows this). Returns null if no adjustment - /// is required. - llvm::Constant *getMemberPointerAdjustment(const CastExpr *E); - - /// Computes the non-virtual adjustment needed for a member pointer - /// conversion along an inheritance path stored in an APValue. Unlike - /// getMemberPointerAdjustment(), the adjustment can be negative if the path - /// is from a derived type to a base type. - CharUnits getMemberPointerPathAdjustment(const APValue &MP); - -public: - virtual void emitVirtualObjectDelete(CodeGenFunction &CGF, - const CXXDeleteExpr *DE, - Address Ptr, QualType ElementType, - const CXXDestructorDecl *Dtor) = 0; - virtual void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) = 0; - virtual void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) = 0; - virtual llvm::GlobalVariable *getThrowInfo(QualType T) { return nullptr; } - - /// Determine whether it's possible to emit a vtable for \p RD, even - /// though we do not know that the vtable has been marked as used by semantic - /// analysis. - virtual bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const = 0; - - virtual void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) = 0; - - virtual llvm::CallInst * - emitTerminateForUnexpectedException(CodeGenFunction &CGF, - llvm::Value *Exn); - - virtual llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) = 0; - virtual CatchTypeInfo - getAddrOfCXXCatchHandlerType(QualType Ty, QualType CatchHandlerType) = 0; - virtual CatchTypeInfo getCatchAllTypeInfo(); - - virtual bool shouldTypeidBeNullChecked(bool IsDeref, - QualType SrcRecordTy) = 0; - virtual void EmitBadTypeidCall(CodeGenFunction &CGF) = 0; - virtual llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy, - Address ThisPtr, - llvm::Type *StdTypeInfoPtrTy) = 0; - - virtual bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr, - QualType SrcRecordTy) = 0; - - virtual llvm::Value * - EmitDynamicCastCall(CodeGenFunction &CGF, Address Value, - QualType SrcRecordTy, QualType DestTy, - QualType DestRecordTy, llvm::BasicBlock *CastEnd) = 0; - - virtual llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF, - Address Value, - QualType SrcRecordTy, - QualType DestTy) = 0; - - virtual bool EmitBadCastCall(CodeGenFunction &CGF) = 0; - - virtual llvm::Value *GetVirtualBaseClassOffset(CodeGenFunction &CGF, - Address This, - const CXXRecordDecl *ClassDecl, - const CXXRecordDecl *BaseClassDecl) = 0; - - virtual llvm::BasicBlock *EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, - const CXXRecordDecl *RD); - - /// Emit the code to initialize hidden members required - /// to handle virtual inheritance, if needed by the ABI. - virtual void - initializeHiddenVirtualInheritanceMembers(CodeGenFunction &CGF, - const CXXRecordDecl *RD) {} - - /// Emit constructor variants required by this ABI. - virtual void EmitCXXConstructors(const CXXConstructorDecl *D) = 0; - - /// Notes how many arguments were added to the beginning (Prefix) and ending - /// (Suffix) of an arg list. - /// - /// Note that Prefix actually refers to the number of args *after* the first - /// one: `this` arguments always come first. - struct AddedStructorArgs { - unsigned Prefix = 0; - unsigned Suffix = 0; - AddedStructorArgs() = default; - AddedStructorArgs(unsigned P, unsigned S) : Prefix(P), Suffix(S) {} - static AddedStructorArgs prefix(unsigned N) { return {N, 0}; } - static AddedStructorArgs suffix(unsigned N) { return {0, N}; } - }; - - /// Build the signature of the given constructor or destructor variant by - /// adding any required parameters. For convenience, ArgTys has been - /// initialized with the type of 'this'. - virtual AddedStructorArgs - buildStructorSignature(const CXXMethodDecl *MD, StructorType T, - SmallVectorImpl<CanQualType> &ArgTys) = 0; - - /// Returns true if the given destructor type should be emitted as a linkonce - /// delegating thunk, regardless of whether the dtor is defined in this TU or - /// not. - virtual bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor, - CXXDtorType DT) const = 0; - - virtual void setCXXDestructorDLLStorage(llvm::GlobalValue *GV, - const CXXDestructorDecl *Dtor, - CXXDtorType DT) const; - - virtual llvm::GlobalValue::LinkageTypes - getCXXDestructorLinkage(GVALinkage Linkage, const CXXDestructorDecl *Dtor, - CXXDtorType DT) const; - - /// Emit destructor variants required by this ABI. - virtual void EmitCXXDestructors(const CXXDestructorDecl *D) = 0; - - /// Get the type of the implicit "this" parameter used by a method. May return - /// zero if no specific type is applicable, e.g. if the ABI expects the "this" - /// parameter to point to some artificial offset in a complete object due to - /// vbases being reordered. - virtual const CXXRecordDecl * - getThisArgumentTypeForMethod(const CXXMethodDecl *MD) { - return MD->getParent(); - } - - /// Perform ABI-specific "this" argument adjustment required prior to - /// a call of a virtual function. - /// The "VirtualCall" argument is true iff the call itself is virtual. - virtual Address - adjustThisArgumentForVirtualFunctionCall(CodeGenFunction &CGF, GlobalDecl GD, - Address This, bool VirtualCall) { - return This; - } - - /// Build a parameter variable suitable for 'this'. - void buildThisParam(CodeGenFunction &CGF, FunctionArgList &Params); - - /// Insert any ABI-specific implicit parameters into the parameter list for a - /// function. This generally involves extra data for constructors and - /// destructors. - /// - /// ABIs may also choose to override the return type, which has been - /// initialized with the type of 'this' if HasThisReturn(CGF.CurGD) is true or - /// the formal return type of the function otherwise. - virtual void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy, - FunctionArgList &Params) = 0; - - /// Get the ABI-specific "this" parameter adjustment to apply in the prologue - /// of a virtual function. - virtual CharUnits getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD) { - return CharUnits::Zero(); - } - - /// Emit the ABI-specific prolog for the function. - virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF) = 0; - - /// Add any ABI-specific implicit arguments needed to call a constructor. - /// - /// \return The number of arguments added at the beginning and end of the - /// call, which is typically zero or one. - virtual AddedStructorArgs - addImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D, - CXXCtorType Type, bool ForVirtualBase, - bool Delegating, CallArgList &Args) = 0; - - /// Emit the destructor call. - virtual void EmitDestructorCall(CodeGenFunction &CGF, - const CXXDestructorDecl *DD, CXXDtorType Type, - bool ForVirtualBase, bool Delegating, - Address This) = 0; - - /// Emits the VTable definitions required for the given record type. - virtual void emitVTableDefinitions(CodeGenVTables &CGVT, - const CXXRecordDecl *RD) = 0; - - /// Checks if ABI requires extra virtual offset for vtable field. - virtual bool - isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF, - CodeGenFunction::VPtr Vptr) = 0; - - /// Checks if ABI requires to initialize vptrs for given dynamic class. - virtual bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass) = 0; - - /// Get the address point of the vtable for the given base subobject. - virtual llvm::Constant * - getVTableAddressPoint(BaseSubobject Base, - const CXXRecordDecl *VTableClass) = 0; - - /// Get the address point of the vtable for the given base subobject while - /// building a constructor or a destructor. - virtual llvm::Value * - getVTableAddressPointInStructor(CodeGenFunction &CGF, const CXXRecordDecl *RD, - 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, - CharUnits VPtrOffset) = 0; - - /// Build a virtual function pointer in the ABI-specific way. - virtual CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, - GlobalDecl GD, Address This, - llvm::Type *Ty, - SourceLocation Loc) = 0; - - /// Emit the ABI-specific virtual destructor call. - virtual llvm::Value * - EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, - CXXDtorType DtorType, Address This, - const CXXMemberCallExpr *CE) = 0; - - virtual void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, - GlobalDecl GD, - CallArgList &CallArgs) {} - - /// Emit any tables needed to implement virtual inheritance. For Itanium, - /// this emits virtual table tables. For the MSVC++ ABI, this emits virtual - /// base tables. - virtual void emitVirtualInheritanceTables(const CXXRecordDecl *RD) = 0; - - virtual bool exportThunk() = 0; - virtual void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, - GlobalDecl GD, bool ReturnAdjustment) = 0; - - virtual llvm::Value *performThisAdjustment(CodeGenFunction &CGF, - Address This, - const ThisAdjustment &TA) = 0; - - virtual llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, - Address Ret, - const ReturnAdjustment &RA) = 0; - - virtual void EmitReturnFromThunk(CodeGenFunction &CGF, - RValue RV, QualType ResultType); - - virtual size_t getSrcArgforCopyCtor(const CXXConstructorDecl *, - FunctionArgList &Args) const = 0; - - /// Gets the offsets of all the virtual base pointers in a given class. - virtual std::vector<CharUnits> getVBPtrOffsets(const CXXRecordDecl *RD); - - /// Gets the pure virtual member call function. - virtual StringRef GetPureVirtualCallName() = 0; - - /// Gets the deleted virtual member call name. - virtual StringRef GetDeletedVirtualCallName() = 0; - - /**************************** Array cookies ******************************/ - - /// Returns the extra size required in order to store the array - /// cookie for the given new-expression. May return 0 to indicate that no - /// array cookie is required. - /// - /// Several cases are filtered out before this method is called: - /// - non-array allocations never need a cookie - /// - calls to \::operator new(size_t, void*) never need a cookie - /// - /// \param expr - the new-expression being allocated. - virtual CharUnits GetArrayCookieSize(const CXXNewExpr *expr); - - /// Initialize the array cookie for the given allocation. - /// - /// \param NewPtr - a char* which is the presumed-non-null - /// return value of the allocation function - /// \param NumElements - the computed number of elements, - /// potentially collapsed from the multidimensional array case; - /// always a size_t - /// \param ElementType - the base element allocated type, - /// i.e. the allocated type after stripping all array types - virtual Address InitializeArrayCookie(CodeGenFunction &CGF, - Address NewPtr, - llvm::Value *NumElements, - const CXXNewExpr *expr, - QualType ElementType); - - /// Reads the array cookie associated with the given pointer, - /// if it has one. - /// - /// \param Ptr - a pointer to the first element in the array - /// \param ElementType - the base element type of elements of the array - /// \param NumElements - an out parameter which will be initialized - /// with the number of elements allocated, or zero if there is no - /// cookie - /// \param AllocPtr - an out parameter which will be initialized - /// with a char* pointing to the address returned by the allocation - /// function - /// \param CookieSize - an out parameter which will be initialized - /// with the size of the cookie, or zero if there is no cookie - virtual void ReadArrayCookie(CodeGenFunction &CGF, Address Ptr, - const CXXDeleteExpr *expr, - QualType ElementType, llvm::Value *&NumElements, - llvm::Value *&AllocPtr, CharUnits &CookieSize); - - /// Return whether the given global decl needs a VTT parameter. - virtual bool NeedsVTTParameter(GlobalDecl GD); - -protected: - /// Returns the extra size required in order to store the array - /// cookie for the given type. Assumes that an array cookie is - /// required. - virtual CharUnits getArrayCookieSizeImpl(QualType elementType); - - /// Reads the array cookie for an allocation which is known to have one. - /// This is called by the standard implementation of ReadArrayCookie. - /// - /// \param ptr - a pointer to the allocation made for an array, as a char* - /// \param cookieSize - the computed cookie size of an array - /// - /// Other parameters are as above. - /// - /// \return a size_t - virtual llvm::Value *readArrayCookieImpl(CodeGenFunction &IGF, Address ptr, - CharUnits cookieSize); - -public: - - /*************************** Static local guards ****************************/ - - /// Emits the guarded initializer and destructor setup for the given - /// variable, given that it couldn't be emitted as a constant. - /// If \p PerformInit is false, the initialization has been folded to a - /// constant and should not be performed. - /// - /// The variable may be: - /// - a static local variable - /// - a static data member of a class template instantiation - virtual void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, - llvm::GlobalVariable *DeclPtr, - bool PerformInit) = 0; - - /// Emit code to force the execution of a destructor during global - /// teardown. The default implementation of this uses atexit. - /// - /// \param Dtor - a function taking a single pointer argument - /// \param Addr - a pointer to pass to the destructor function. - virtual void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, - llvm::Constant *Dtor, - llvm::Constant *Addr) = 0; - - /*************************** thread_local initialization ********************/ - - /// Emits ABI-required functions necessary to initialize thread_local - /// variables in this translation unit. - /// - /// \param CXXThreadLocals - The thread_local declarations in this translation - /// unit. - /// \param CXXThreadLocalInits - If this translation unit contains any - /// non-constant initialization or non-trivial destruction for - /// thread_local variables, a list of functions to perform the - /// initialization. - virtual void EmitThreadLocalInitFuncs( - CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals, - ArrayRef<llvm::Function *> CXXThreadLocalInits, - ArrayRef<const VarDecl *> CXXThreadLocalInitVars) = 0; - - // Determine if references to thread_local global variables can be made - // directly or require access through a thread wrapper function. - virtual bool usesThreadWrapperFunction() const = 0; - - /// Emit a reference to a non-local thread_local variable (including - /// triggering the initialization of all thread_local variables in its - /// translation unit). - virtual LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, - const VarDecl *VD, - QualType LValType) = 0; - - /// Emit a single constructor/destructor with the given type from a C++ - /// constructor Decl. - virtual void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) = 0; - - /// Load a vtable from This, an object of polymorphic type RD, or from one of - /// its virtual bases if it does not have its own vtable. Returns the vtable - /// and the class from which the vtable was loaded. - virtual std::pair<llvm::Value *, const CXXRecordDecl *> - LoadVTablePtr(CodeGenFunction &CGF, Address This, - const CXXRecordDecl *RD) = 0; -}; - -// Create an instance of a C++ ABI class: - -/// Creates an Itanium-family ABI. -CGCXXABI *CreateItaniumCXXABI(CodeGenModule &CGM); - -/// Creates a Microsoft-family ABI. -CGCXXABI *CreateMicrosoftCXXABI(CodeGenModule &CGM); - -struct CatchRetScope final : EHScopeStack::Cleanup { - llvm::CatchPadInst *CPI; - - CatchRetScope(llvm::CatchPadInst *CPI) : CPI(CPI) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - llvm::BasicBlock *BB = CGF.createBasicBlock("catchret.dest"); - CGF.Builder.CreateCatchRet(CPI, BB); - CGF.EmitBlock(BB); - } -}; -} -} - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGCall.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGCall.cpp deleted file mode 100644 index 8a3ae7511cf..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGCall.cpp +++ /dev/null @@ -1,4579 +0,0 @@ -//===--- CGCall.cpp - Encapsulate calling convention details --------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// These classes wrap the information about a call or function -// definition used to handle ABI compliancy. -// -//===----------------------------------------------------------------------===// - -#include "CGCall.h" -#include "ABIInfo.h" -#include "CGBlocks.h" -#include "CGCXXABI.h" -#include "CGCleanup.h" -#include "CodeGenFunction.h" -#include "CodeGenModule.h" -#include "TargetInfo.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" -#include "clang/Basic/CodeGenOptions.h" -#include "clang/Basic/TargetBuiltins.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/CodeGen/CGFunctionInfo.h" -#include "clang/CodeGen/SwiftCallingConv.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Transforms/Utils/Local.h" -#include "llvm/Analysis/ValueTracking.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/Intrinsics.h" -using namespace clang; -using namespace CodeGen; - -/***/ - -unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) { - switch (CC) { - default: return llvm::CallingConv::C; - case CC_X86StdCall: return llvm::CallingConv::X86_StdCall; - case CC_X86FastCall: return llvm::CallingConv::X86_FastCall; - case CC_X86RegCall: return llvm::CallingConv::X86_RegCall; - case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall; - case CC_Win64: return llvm::CallingConv::Win64; - case CC_X86_64SysV: return llvm::CallingConv::X86_64_SysV; - case CC_AAPCS: return llvm::CallingConv::ARM_AAPCS; - case CC_AAPCS_VFP: return llvm::CallingConv::ARM_AAPCS_VFP; - case CC_IntelOclBicc: return llvm::CallingConv::Intel_OCL_BI; - // TODO: Add support for __pascal to LLVM. - case CC_X86Pascal: return llvm::CallingConv::C; - // TODO: Add support for __vectorcall to LLVM. - case CC_X86VectorCall: return llvm::CallingConv::X86_VectorCall; - case CC_AArch64VectorCall: return llvm::CallingConv::AArch64_VectorCall; - case CC_SpirFunction: return llvm::CallingConv::SPIR_FUNC; - case CC_OpenCLKernel: return CGM.getTargetCodeGenInfo().getOpenCLKernelCallingConv(); - case CC_PreserveMost: return llvm::CallingConv::PreserveMost; - case CC_PreserveAll: return llvm::CallingConv::PreserveAll; - case CC_Swift: return llvm::CallingConv::Swift; - } -} - -/// Derives the 'this' type for codegen purposes, i.e. ignoring method CVR -/// qualification. -static CanQualType GetThisType(ASTContext &Context, const CXXRecordDecl *RD, - const CXXMethodDecl *MD) { - QualType RecTy = Context.getTagDeclType(RD)->getCanonicalTypeInternal(); - if (MD) - RecTy = Context.getAddrSpaceQualType(RecTy, MD->getTypeQualifiers().getAddressSpace()); - return Context.getPointerType(CanQualType::CreateUnsafe(RecTy)); -} - -/// Returns the canonical formal type of the given C++ method. -static CanQual<FunctionProtoType> GetFormalType(const CXXMethodDecl *MD) { - return MD->getType()->getCanonicalTypeUnqualified() - .getAs<FunctionProtoType>(); -} - -/// Returns the "extra-canonicalized" return type, which discards -/// qualifiers on the return type. Codegen doesn't care about them, -/// and it makes ABI code a little easier to be able to assume that -/// all parameter and return types are top-level unqualified. -static CanQualType GetReturnType(QualType RetTy) { - return RetTy->getCanonicalTypeUnqualified().getUnqualifiedType(); -} - -/// Arrange the argument and result information for a value of the given -/// unprototyped freestanding function type. -const CGFunctionInfo & -CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> FTNP) { - // When translating an unprototyped function type, always use a - // variadic type. - return arrangeLLVMFunctionInfo(FTNP->getReturnType().getUnqualifiedType(), - /*instanceMethod=*/false, - /*chainCall=*/false, None, - FTNP->getExtInfo(), {}, RequiredArgs(0)); -} - -static void addExtParameterInfosForCall( - llvm::SmallVectorImpl<FunctionProtoType::ExtParameterInfo> ¶mInfos, - const FunctionProtoType *proto, - unsigned prefixArgs, - unsigned totalArgs) { - assert(proto->hasExtParameterInfos()); - assert(paramInfos.size() <= prefixArgs); - assert(proto->getNumParams() + prefixArgs <= totalArgs); - - paramInfos.reserve(totalArgs); - - // Add default infos for any prefix args that don't already have infos. - paramInfos.resize(prefixArgs); - - // Add infos for the prototype. - for (const auto &ParamInfo : proto->getExtParameterInfos()) { - paramInfos.push_back(ParamInfo); - // pass_object_size params have no parameter info. - if (ParamInfo.hasPassObjectSize()) - paramInfos.emplace_back(); - } - - assert(paramInfos.size() <= totalArgs && - "Did we forget to insert pass_object_size args?"); - // Add default infos for the variadic and/or suffix arguments. - paramInfos.resize(totalArgs); -} - -/// Adds the formal parameters in FPT to the given prefix. If any parameter in -/// FPT has pass_object_size attrs, then we'll add parameters for those, too. -static void appendParameterTypes(const CodeGenTypes &CGT, - SmallVectorImpl<CanQualType> &prefix, - SmallVectorImpl<FunctionProtoType::ExtParameterInfo> ¶mInfos, - CanQual<FunctionProtoType> FPT) { - // Fast path: don't touch param info if we don't need to. - if (!FPT->hasExtParameterInfos()) { - assert(paramInfos.empty() && - "We have paramInfos, but the prototype doesn't?"); - prefix.append(FPT->param_type_begin(), FPT->param_type_end()); - return; - } - - unsigned PrefixSize = prefix.size(); - // In the vast majority of cases, we'll have precisely FPT->getNumParams() - // parameters; the only thing that can change this is the presence of - // pass_object_size. So, we preallocate for the common case. - prefix.reserve(prefix.size() + FPT->getNumParams()); - - auto ExtInfos = FPT->getExtParameterInfos(); - assert(ExtInfos.size() == FPT->getNumParams()); - for (unsigned I = 0, E = FPT->getNumParams(); I != E; ++I) { - prefix.push_back(FPT->getParamType(I)); - if (ExtInfos[I].hasPassObjectSize()) - prefix.push_back(CGT.getContext().getSizeType()); - } - - addExtParameterInfosForCall(paramInfos, FPT.getTypePtr(), PrefixSize, - prefix.size()); -} - -/// Arrange the LLVM function layout for a value of the given function -/// type, on top of any implicit parameters already stored. -static const CGFunctionInfo & -arrangeLLVMFunctionInfo(CodeGenTypes &CGT, bool instanceMethod, - SmallVectorImpl<CanQualType> &prefix, - CanQual<FunctionProtoType> FTP, - const FunctionDecl *FD) { - SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos; - RequiredArgs Required = - RequiredArgs::forPrototypePlus(FTP, prefix.size(), FD); - // FIXME: Kill copy. - appendParameterTypes(CGT, prefix, paramInfos, FTP); - CanQualType resultType = FTP->getReturnType().getUnqualifiedType(); - - return CGT.arrangeLLVMFunctionInfo(resultType, instanceMethod, - /*chainCall=*/false, prefix, - FTP->getExtInfo(), paramInfos, - Required); -} - -/// Arrange the argument and result information for a value of the -/// given freestanding function type. -const CGFunctionInfo & -CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> FTP, - const FunctionDecl *FD) { - SmallVector<CanQualType, 16> argTypes; - return ::arrangeLLVMFunctionInfo(*this, /*instanceMethod=*/false, argTypes, - FTP, FD); -} - -static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) { - // Set the appropriate calling convention for the Function. - if (D->hasAttr<StdCallAttr>()) - return CC_X86StdCall; - - if (D->hasAttr<FastCallAttr>()) - return CC_X86FastCall; - - if (D->hasAttr<RegCallAttr>()) - return CC_X86RegCall; - - if (D->hasAttr<ThisCallAttr>()) - return CC_X86ThisCall; - - if (D->hasAttr<VectorCallAttr>()) - return CC_X86VectorCall; - - if (D->hasAttr<PascalAttr>()) - return CC_X86Pascal; - - if (PcsAttr *PCS = D->getAttr<PcsAttr>()) - return (PCS->getPCS() == PcsAttr::AAPCS ? CC_AAPCS : CC_AAPCS_VFP); - - if (D->hasAttr<AArch64VectorPcsAttr>()) - return CC_AArch64VectorCall; - - if (D->hasAttr<IntelOclBiccAttr>()) - return CC_IntelOclBicc; - - if (D->hasAttr<MSABIAttr>()) - return IsWindows ? CC_C : CC_Win64; - - if (D->hasAttr<SysVABIAttr>()) - return IsWindows ? CC_X86_64SysV : CC_C; - - if (D->hasAttr<PreserveMostAttr>()) - return CC_PreserveMost; - - if (D->hasAttr<PreserveAllAttr>()) - return CC_PreserveAll; - - return CC_C; -} - -/// Arrange the argument and result information for a call to an -/// unknown C++ non-static member function of the given abstract type. -/// (Zero value of RD means we don't have any meaningful "this" argument type, -/// so fall back to a generic pointer type). -/// The member function must be an ordinary function, i.e. not a -/// constructor or destructor. -const CGFunctionInfo & -CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD, - const FunctionProtoType *FTP, - const CXXMethodDecl *MD) { - SmallVector<CanQualType, 16> argTypes; - - // Add the 'this' pointer. - if (RD) - argTypes.push_back(GetThisType(Context, RD, MD)); - else - argTypes.push_back(Context.VoidPtrTy); - - return ::arrangeLLVMFunctionInfo( - *this, true, argTypes, - FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>(), MD); -} - -/// Set calling convention for CUDA/HIP kernel. -static void setCUDAKernelCallingConvention(CanQualType &FTy, CodeGenModule &CGM, - const FunctionDecl *FD) { - if (FD->hasAttr<CUDAGlobalAttr>()) { - const FunctionType *FT = FTy->getAs<FunctionType>(); - CGM.getTargetCodeGenInfo().setCUDAKernelCallingConvention(FT); - FTy = FT->getCanonicalTypeUnqualified(); - } -} - -/// Arrange the argument and result information for a declaration or -/// definition of the given C++ non-static member function. The -/// member function must be an ordinary function, i.e. not a -/// constructor or destructor. -const CGFunctionInfo & -CodeGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *MD) { - assert(!isa<CXXConstructorDecl>(MD) && "wrong method for constructors!"); - assert(!isa<CXXDestructorDecl>(MD) && "wrong method for destructors!"); - - CanQualType FT = GetFormalType(MD).getAs<Type>(); - setCUDAKernelCallingConvention(FT, CGM, MD); - auto prototype = FT.getAs<FunctionProtoType>(); - - if (MD->isInstance()) { - // The abstract case is perfectly fine. - const CXXRecordDecl *ThisType = TheCXXABI.getThisArgumentTypeForMethod(MD); - return arrangeCXXMethodType(ThisType, prototype.getTypePtr(), MD); - } - - return arrangeFreeFunctionType(prototype, MD); -} - -bool CodeGenTypes::inheritingCtorHasParams( - const InheritedConstructor &Inherited, CXXCtorType Type) { - // Parameters are unnecessary if we're constructing a base class subobject - // and the inherited constructor lives in a virtual base. - return Type == Ctor_Complete || - !Inherited.getShadowDecl()->constructsVirtualBase() || - !Target.getCXXABI().hasConstructorVariants(); - } - -const CGFunctionInfo & -CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD, - StructorType Type) { - - SmallVector<CanQualType, 16> argTypes; - SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos; - argTypes.push_back(GetThisType(Context, MD->getParent(), MD)); - - bool PassParams = true; - - GlobalDecl GD; - if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) { - GD = GlobalDecl(CD, toCXXCtorType(Type)); - - // A base class inheriting constructor doesn't get forwarded arguments - // needed to construct a virtual base (or base class thereof). - if (auto Inherited = CD->getInheritedConstructor()) - PassParams = inheritingCtorHasParams(Inherited, toCXXCtorType(Type)); - } else { - auto *DD = dyn_cast<CXXDestructorDecl>(MD); - GD = GlobalDecl(DD, toCXXDtorType(Type)); - } - - CanQual<FunctionProtoType> FTP = GetFormalType(MD); - - // Add the formal parameters. - if (PassParams) - appendParameterTypes(*this, argTypes, paramInfos, FTP); - - CGCXXABI::AddedStructorArgs AddedArgs = - TheCXXABI.buildStructorSignature(MD, Type, argTypes); - if (!paramInfos.empty()) { - // Note: prefix implies after the first param. - if (AddedArgs.Prefix) - paramInfos.insert(paramInfos.begin() + 1, AddedArgs.Prefix, - FunctionProtoType::ExtParameterInfo{}); - if (AddedArgs.Suffix) - paramInfos.append(AddedArgs.Suffix, - FunctionProtoType::ExtParameterInfo{}); - } - - RequiredArgs required = - (PassParams && MD->isVariadic() ? RequiredArgs(argTypes.size()) - : RequiredArgs::All); - - FunctionType::ExtInfo extInfo = FTP->getExtInfo(); - CanQualType resultType = TheCXXABI.HasThisReturn(GD) - ? argTypes.front() - : TheCXXABI.hasMostDerivedReturn(GD) - ? CGM.getContext().VoidPtrTy - : Context.VoidTy; - return arrangeLLVMFunctionInfo(resultType, /*instanceMethod=*/true, - /*chainCall=*/false, argTypes, extInfo, - paramInfos, required); -} - -static SmallVector<CanQualType, 16> -getArgTypesForCall(ASTContext &ctx, const CallArgList &args) { - SmallVector<CanQualType, 16> argTypes; - for (auto &arg : args) - argTypes.push_back(ctx.getCanonicalParamType(arg.Ty)); - return argTypes; -} - -static SmallVector<CanQualType, 16> -getArgTypesForDeclaration(ASTContext &ctx, const FunctionArgList &args) { - SmallVector<CanQualType, 16> argTypes; - for (auto &arg : args) - argTypes.push_back(ctx.getCanonicalParamType(arg->getType())); - return argTypes; -} - -static llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16> -getExtParameterInfosForCall(const FunctionProtoType *proto, - unsigned prefixArgs, unsigned totalArgs) { - llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16> result; - if (proto->hasExtParameterInfos()) { - addExtParameterInfosForCall(result, proto, prefixArgs, totalArgs); - } - return result; -} - -/// Arrange a call to a C++ method, passing the given arguments. -/// -/// ExtraPrefixArgs is the number of ABI-specific args passed after the `this` -/// parameter. -/// ExtraSuffixArgs is the number of ABI-specific args passed at the end of -/// args. -/// PassProtoArgs indicates whether `args` has args for the parameters in the -/// given CXXConstructorDecl. -const CGFunctionInfo & -CodeGenTypes::arrangeCXXConstructorCall(const CallArgList &args, - const CXXConstructorDecl *D, - CXXCtorType CtorKind, - unsigned ExtraPrefixArgs, - unsigned ExtraSuffixArgs, - bool PassProtoArgs) { - // FIXME: Kill copy. - SmallVector<CanQualType, 16> ArgTypes; - for (const auto &Arg : args) - ArgTypes.push_back(Context.getCanonicalParamType(Arg.Ty)); - - // +1 for implicit this, which should always be args[0]. - unsigned TotalPrefixArgs = 1 + ExtraPrefixArgs; - - CanQual<FunctionProtoType> FPT = GetFormalType(D); - RequiredArgs Required = - RequiredArgs::forPrototypePlus(FPT, TotalPrefixArgs + ExtraSuffixArgs, D); - GlobalDecl GD(D, CtorKind); - CanQualType ResultType = TheCXXABI.HasThisReturn(GD) - ? ArgTypes.front() - : TheCXXABI.hasMostDerivedReturn(GD) - ? CGM.getContext().VoidPtrTy - : Context.VoidTy; - - FunctionType::ExtInfo Info = FPT->getExtInfo(); - llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16> ParamInfos; - // If the prototype args are elided, we should only have ABI-specific args, - // which never have param info. - if (PassProtoArgs && FPT->hasExtParameterInfos()) { - // ABI-specific suffix arguments are treated the same as variadic arguments. - addExtParameterInfosForCall(ParamInfos, FPT.getTypePtr(), TotalPrefixArgs, - ArgTypes.size()); - } - return arrangeLLVMFunctionInfo(ResultType, /*instanceMethod=*/true, - /*chainCall=*/false, ArgTypes, Info, - ParamInfos, Required); -} - -/// Arrange the argument and result information for the declaration or -/// definition of the given function. -const CGFunctionInfo & -CodeGenTypes::arrangeFunctionDeclaration(const FunctionDecl *FD) { - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) - if (MD->isInstance()) - return arrangeCXXMethodDeclaration(MD); - - CanQualType FTy = FD->getType()->getCanonicalTypeUnqualified(); - - assert(isa<FunctionType>(FTy)); - setCUDAKernelCallingConvention(FTy, CGM, FD); - - // When declaring a function without a prototype, always use a - // non-variadic type. - if (CanQual<FunctionNoProtoType> noProto = FTy.getAs<FunctionNoProtoType>()) { - return arrangeLLVMFunctionInfo( - noProto->getReturnType(), /*instanceMethod=*/false, - /*chainCall=*/false, None, noProto->getExtInfo(), {},RequiredArgs::All); - } - - return arrangeFreeFunctionType(FTy.castAs<FunctionProtoType>(), FD); -} - -/// Arrange the argument and result information for the declaration or -/// definition of an Objective-C method. -const CGFunctionInfo & -CodeGenTypes::arrangeObjCMethodDeclaration(const ObjCMethodDecl *MD) { - // It happens that this is the same as a call with no optional - // arguments, except also using the formal 'self' type. - return arrangeObjCMessageSendSignature(MD, MD->getSelfDecl()->getType()); -} - -/// Arrange the argument and result information for the function type -/// through which to perform a send to the given Objective-C method, -/// using the given receiver type. The receiver type is not always -/// the 'self' type of the method or even an Objective-C pointer type. -/// This is *not* the right method for actually performing such a -/// message send, due to the possibility of optional arguments. -const CGFunctionInfo & -CodeGenTypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD, - QualType receiverType) { - SmallVector<CanQualType, 16> argTys; - SmallVector<FunctionProtoType::ExtParameterInfo, 4> extParamInfos(2); - argTys.push_back(Context.getCanonicalParamType(receiverType)); - argTys.push_back(Context.getCanonicalParamType(Context.getObjCSelType())); - // FIXME: Kill copy? - for (const auto *I : MD->parameters()) { - argTys.push_back(Context.getCanonicalParamType(I->getType())); - auto extParamInfo = FunctionProtoType::ExtParameterInfo().withIsNoEscape( - I->hasAttr<NoEscapeAttr>()); - extParamInfos.push_back(extParamInfo); - } - - FunctionType::ExtInfo einfo; - bool IsWindows = getContext().getTargetInfo().getTriple().isOSWindows(); - einfo = einfo.withCallingConv(getCallingConventionForDecl(MD, IsWindows)); - - if (getContext().getLangOpts().ObjCAutoRefCount && - MD->hasAttr<NSReturnsRetainedAttr>()) - einfo = einfo.withProducesResult(true); - - RequiredArgs required = - (MD->isVariadic() ? RequiredArgs(argTys.size()) : RequiredArgs::All); - - return arrangeLLVMFunctionInfo( - GetReturnType(MD->getReturnType()), /*instanceMethod=*/false, - /*chainCall=*/false, argTys, einfo, extParamInfos, required); -} - -const CGFunctionInfo & -CodeGenTypes::arrangeUnprototypedObjCMessageSend(QualType returnType, - const CallArgList &args) { - auto argTypes = getArgTypesForCall(Context, args); - FunctionType::ExtInfo einfo; - - return arrangeLLVMFunctionInfo( - GetReturnType(returnType), /*instanceMethod=*/false, - /*chainCall=*/false, argTypes, einfo, {}, RequiredArgs::All); -} - -const CGFunctionInfo & -CodeGenTypes::arrangeGlobalDeclaration(GlobalDecl GD) { - // FIXME: Do we need to handle ObjCMethodDecl? - const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); - - if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) - return arrangeCXXStructorDeclaration(CD, getFromCtorType(GD.getCtorType())); - - if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) - return arrangeCXXStructorDeclaration(DD, getFromDtorType(GD.getDtorType())); - - return arrangeFunctionDeclaration(FD); -} - -/// Arrange a thunk that takes 'this' as the first parameter followed by -/// varargs. Return a void pointer, regardless of the actual return type. -/// The body of the thunk will end in a musttail call to a function of the -/// correct type, and the caller will bitcast the function to the correct -/// prototype. -const CGFunctionInfo & -CodeGenTypes::arrangeUnprototypedMustTailThunk(const CXXMethodDecl *MD) { - assert(MD->isVirtual() && "only methods have thunks"); - CanQual<FunctionProtoType> FTP = GetFormalType(MD); - CanQualType ArgTys[] = { GetThisType(Context, MD->getParent(), MD) }; - return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/false, - /*chainCall=*/false, ArgTys, - FTP->getExtInfo(), {}, RequiredArgs(1)); -} - -const CGFunctionInfo & -CodeGenTypes::arrangeMSCtorClosure(const CXXConstructorDecl *CD, - CXXCtorType CT) { - assert(CT == Ctor_CopyingClosure || CT == Ctor_DefaultClosure); - - CanQual<FunctionProtoType> FTP = GetFormalType(CD); - SmallVector<CanQualType, 2> ArgTys; - const CXXRecordDecl *RD = CD->getParent(); - ArgTys.push_back(GetThisType(Context, RD, CD)); - if (CT == Ctor_CopyingClosure) - ArgTys.push_back(*FTP->param_type_begin()); - if (RD->getNumVBases() > 0) - ArgTys.push_back(Context.IntTy); - CallingConv CC = Context.getDefaultCallingConvention( - /*IsVariadic=*/false, /*IsCXXMethod=*/true); - return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/true, - /*chainCall=*/false, ArgTys, - FunctionType::ExtInfo(CC), {}, - RequiredArgs::All); -} - -/// Arrange a call as unto a free function, except possibly with an -/// additional number of formal parameters considered required. -static const CGFunctionInfo & -arrangeFreeFunctionLikeCall(CodeGenTypes &CGT, - CodeGenModule &CGM, - const CallArgList &args, - const FunctionType *fnType, - unsigned numExtraRequiredArgs, - bool chainCall) { - assert(args.size() >= numExtraRequiredArgs); - - llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos; - - // In most cases, there are no optional arguments. - RequiredArgs required = RequiredArgs::All; - - // If we have a variadic prototype, the required arguments are the - // extra prefix plus the arguments in the prototype. - if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fnType)) { - if (proto->isVariadic()) - required = RequiredArgs(proto->getNumParams() + numExtraRequiredArgs); - - if (proto->hasExtParameterInfos()) - addExtParameterInfosForCall(paramInfos, proto, numExtraRequiredArgs, - args.size()); - - // If we don't have a prototype at all, but we're supposed to - // explicitly use the variadic convention for unprototyped calls, - // treat all of the arguments as required but preserve the nominal - // possibility of variadics. - } else if (CGM.getTargetCodeGenInfo() - .isNoProtoCallVariadic(args, - cast<FunctionNoProtoType>(fnType))) { - required = RequiredArgs(args.size()); - } - - // FIXME: Kill copy. - SmallVector<CanQualType, 16> argTypes; - for (const auto &arg : args) - argTypes.push_back(CGT.getContext().getCanonicalParamType(arg.Ty)); - return CGT.arrangeLLVMFunctionInfo(GetReturnType(fnType->getReturnType()), - /*instanceMethod=*/false, chainCall, - argTypes, fnType->getExtInfo(), paramInfos, - required); -} - -/// Figure out the rules for calling a function with the given formal -/// type using the given arguments. The arguments are necessary -/// because the function might be unprototyped, in which case it's -/// target-dependent in crazy ways. -const CGFunctionInfo & -CodeGenTypes::arrangeFreeFunctionCall(const CallArgList &args, - const FunctionType *fnType, - bool chainCall) { - return arrangeFreeFunctionLikeCall(*this, CGM, args, fnType, - chainCall ? 1 : 0, chainCall); -} - -/// A block function is essentially a free function with an -/// extra implicit argument. -const CGFunctionInfo & -CodeGenTypes::arrangeBlockFunctionCall(const CallArgList &args, - const FunctionType *fnType) { - return arrangeFreeFunctionLikeCall(*this, CGM, args, fnType, 1, - /*chainCall=*/false); -} - -const CGFunctionInfo & -CodeGenTypes::arrangeBlockFunctionDeclaration(const FunctionProtoType *proto, - const FunctionArgList ¶ms) { - auto paramInfos = getExtParameterInfosForCall(proto, 1, params.size()); - auto argTypes = getArgTypesForDeclaration(Context, params); - - return arrangeLLVMFunctionInfo( - GetReturnType(proto->getReturnType()), - /*instanceMethod*/ false, /*chainCall*/ false, argTypes, - proto->getExtInfo(), paramInfos, - RequiredArgs::forPrototypePlus(proto, 1, nullptr)); -} - -const CGFunctionInfo & -CodeGenTypes::arrangeBuiltinFunctionCall(QualType resultType, - const CallArgList &args) { - // FIXME: Kill copy. - SmallVector<CanQualType, 16> argTypes; - for (const auto &Arg : args) - argTypes.push_back(Context.getCanonicalParamType(Arg.Ty)); - return arrangeLLVMFunctionInfo( - GetReturnType(resultType), /*instanceMethod=*/false, - /*chainCall=*/false, argTypes, FunctionType::ExtInfo(), - /*paramInfos=*/ {}, RequiredArgs::All); -} - -const CGFunctionInfo & -CodeGenTypes::arrangeBuiltinFunctionDeclaration(QualType resultType, - const FunctionArgList &args) { - auto argTypes = getArgTypesForDeclaration(Context, args); - - return arrangeLLVMFunctionInfo( - GetReturnType(resultType), /*instanceMethod=*/false, /*chainCall=*/false, - argTypes, FunctionType::ExtInfo(), {}, RequiredArgs::All); -} - -const CGFunctionInfo & -CodeGenTypes::arrangeBuiltinFunctionDeclaration(CanQualType resultType, - ArrayRef<CanQualType> argTypes) { - return arrangeLLVMFunctionInfo( - resultType, /*instanceMethod=*/false, /*chainCall=*/false, - argTypes, FunctionType::ExtInfo(), {}, RequiredArgs::All); -} - -/// Arrange a call to a C++ method, passing the given arguments. -/// -/// numPrefixArgs is the number of ABI-specific prefix arguments we have. It -/// does not count `this`. -const CGFunctionInfo & -CodeGenTypes::arrangeCXXMethodCall(const CallArgList &args, - const FunctionProtoType *proto, - RequiredArgs required, - unsigned numPrefixArgs) { - assert(numPrefixArgs + 1 <= args.size() && - "Emitting a call with less args than the required prefix?"); - // Add one to account for `this`. It's a bit awkward here, but we don't count - // `this` in similar places elsewhere. - auto paramInfos = - getExtParameterInfosForCall(proto, numPrefixArgs + 1, args.size()); - - // FIXME: Kill copy. - auto argTypes = getArgTypesForCall(Context, args); - - FunctionType::ExtInfo info = proto->getExtInfo(); - return arrangeLLVMFunctionInfo( - GetReturnType(proto->getReturnType()), /*instanceMethod=*/true, - /*chainCall=*/false, argTypes, info, paramInfos, required); -} - -const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() { - return arrangeLLVMFunctionInfo( - getContext().VoidTy, /*instanceMethod=*/false, /*chainCall=*/false, - None, FunctionType::ExtInfo(), {}, RequiredArgs::All); -} - -const CGFunctionInfo & -CodeGenTypes::arrangeCall(const CGFunctionInfo &signature, - const CallArgList &args) { - assert(signature.arg_size() <= args.size()); - if (signature.arg_size() == args.size()) - return signature; - - SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos; - auto sigParamInfos = signature.getExtParameterInfos(); - if (!sigParamInfos.empty()) { - paramInfos.append(sigParamInfos.begin(), sigParamInfos.end()); - paramInfos.resize(args.size()); - } - - auto argTypes = getArgTypesForCall(Context, args); - - assert(signature.getRequiredArgs().allowsOptionalArgs()); - return arrangeLLVMFunctionInfo(signature.getReturnType(), - signature.isInstanceMethod(), - signature.isChainCall(), - argTypes, - signature.getExtInfo(), - paramInfos, - signature.getRequiredArgs()); -} - -namespace clang { -namespace CodeGen { -void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI); -} -} - -/// Arrange the argument and result information for an abstract value -/// of a given function type. This is the method which all of the -/// above functions ultimately defer to. -const CGFunctionInfo & -CodeGenTypes::arrangeLLVMFunctionInfo(CanQualType resultType, - bool instanceMethod, - bool chainCall, - ArrayRef<CanQualType> argTypes, - FunctionType::ExtInfo info, - ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, - RequiredArgs required) { - assert(llvm::all_of(argTypes, - [](CanQualType T) { return T.isCanonicalAsParam(); })); - - // Lookup or create unique function info. - llvm::FoldingSetNodeID ID; - CGFunctionInfo::Profile(ID, instanceMethod, chainCall, info, paramInfos, - required, resultType, argTypes); - - void *insertPos = nullptr; - CGFunctionInfo *FI = FunctionInfos.FindNodeOrInsertPos(ID, insertPos); - if (FI) - return *FI; - - unsigned CC = ClangCallConvToLLVMCallConv(info.getCC()); - - // Construct the function info. We co-allocate the ArgInfos. - FI = CGFunctionInfo::create(CC, instanceMethod, chainCall, info, - paramInfos, resultType, argTypes, required); - FunctionInfos.InsertNode(FI, insertPos); - - bool inserted = FunctionsBeingProcessed.insert(FI).second; - (void)inserted; - assert(inserted && "Recursively being processed?"); - - // Compute ABI information. - if (CC == llvm::CallingConv::SPIR_KERNEL) { - // Force target independent argument handling for the host visible - // kernel functions. - computeSPIRKernelABIInfo(CGM, *FI); - } else if (info.getCC() == CC_Swift) { - swiftcall::computeABIInfo(CGM, *FI); - } else { - getABIInfo().computeInfo(*FI); - } - - // Loop over all of the computed argument and return value info. If any of - // them are direct or extend without a specified coerce type, specify the - // default now. - ABIArgInfo &retInfo = FI->getReturnInfo(); - if (retInfo.canHaveCoerceToType() && retInfo.getCoerceToType() == nullptr) - retInfo.setCoerceToType(ConvertType(FI->getReturnType())); - - for (auto &I : FI->arguments()) - if (I.info.canHaveCoerceToType() && I.info.getCoerceToType() == nullptr) - I.info.setCoerceToType(ConvertType(I.type)); - - bool erased = FunctionsBeingProcessed.erase(FI); (void)erased; - assert(erased && "Not in set?"); - - return *FI; -} - -CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC, - bool instanceMethod, - bool chainCall, - const FunctionType::ExtInfo &info, - ArrayRef<ExtParameterInfo> paramInfos, - CanQualType resultType, - ArrayRef<CanQualType> argTypes, - RequiredArgs required) { - assert(paramInfos.empty() || paramInfos.size() == argTypes.size()); - - void *buffer = - operator new(totalSizeToAlloc<ArgInfo, ExtParameterInfo>( - argTypes.size() + 1, paramInfos.size())); - - CGFunctionInfo *FI = new(buffer) CGFunctionInfo(); - FI->CallingConvention = llvmCC; - FI->EffectiveCallingConvention = llvmCC; - FI->ASTCallingConvention = info.getCC(); - FI->InstanceMethod = instanceMethod; - FI->ChainCall = chainCall; - FI->NoReturn = info.getNoReturn(); - FI->ReturnsRetained = info.getProducesResult(); - FI->NoCallerSavedRegs = info.getNoCallerSavedRegs(); - FI->NoCfCheck = info.getNoCfCheck(); - FI->Required = required; - FI->HasRegParm = info.getHasRegParm(); - FI->RegParm = info.getRegParm(); - FI->ArgStruct = nullptr; - FI->ArgStructAlign = 0; - FI->NumArgs = argTypes.size(); - FI->HasExtParameterInfos = !paramInfos.empty(); - FI->getArgsBuffer()[0].type = resultType; - for (unsigned i = 0, e = argTypes.size(); i != e; ++i) - FI->getArgsBuffer()[i + 1].type = argTypes[i]; - for (unsigned i = 0, e = paramInfos.size(); i != e; ++i) - FI->getExtParameterInfosBuffer()[i] = paramInfos[i]; - return FI; -} - -/***/ - -namespace { -// ABIArgInfo::Expand implementation. - -// Specifies the way QualType passed as ABIArgInfo::Expand is expanded. -struct TypeExpansion { - enum TypeExpansionKind { - // Elements of constant arrays are expanded recursively. - TEK_ConstantArray, - // Record fields are expanded recursively (but if record is a union, only - // the field with the largest size is expanded). - TEK_Record, - // For complex types, real and imaginary parts are expanded recursively. - TEK_Complex, - // All other types are not expandable. - TEK_None - }; - - const TypeExpansionKind Kind; - - TypeExpansion(TypeExpansionKind K) : Kind(K) {} - virtual ~TypeExpansion() {} -}; - -struct ConstantArrayExpansion : TypeExpansion { - QualType EltTy; - uint64_t NumElts; - - ConstantArrayExpansion(QualType EltTy, uint64_t NumElts) - : TypeExpansion(TEK_ConstantArray), EltTy(EltTy), NumElts(NumElts) {} - static bool classof(const TypeExpansion *TE) { - return TE->Kind == TEK_ConstantArray; - } -}; - -struct RecordExpansion : TypeExpansion { - SmallVector<const CXXBaseSpecifier *, 1> Bases; - - SmallVector<const FieldDecl *, 1> Fields; - - RecordExpansion(SmallVector<const CXXBaseSpecifier *, 1> &&Bases, - SmallVector<const FieldDecl *, 1> &&Fields) - : TypeExpansion(TEK_Record), Bases(std::move(Bases)), - Fields(std::move(Fields)) {} - static bool classof(const TypeExpansion *TE) { - return TE->Kind == TEK_Record; - } -}; - -struct ComplexExpansion : TypeExpansion { - QualType EltTy; - - ComplexExpansion(QualType EltTy) : TypeExpansion(TEK_Complex), EltTy(EltTy) {} - static bool classof(const TypeExpansion *TE) { - return TE->Kind == TEK_Complex; - } -}; - -struct NoExpansion : TypeExpansion { - NoExpansion() : TypeExpansion(TEK_None) {} - static bool classof(const TypeExpansion *TE) { - return TE->Kind == TEK_None; - } -}; -} // namespace - -static std::unique_ptr<TypeExpansion> -getTypeExpansion(QualType Ty, const ASTContext &Context) { - if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) { - return llvm::make_unique<ConstantArrayExpansion>( - AT->getElementType(), AT->getSize().getZExtValue()); - } - if (const RecordType *RT = Ty->getAs<RecordType>()) { - SmallVector<const CXXBaseSpecifier *, 1> Bases; - SmallVector<const FieldDecl *, 1> Fields; - const RecordDecl *RD = RT->getDecl(); - assert(!RD->hasFlexibleArrayMember() && - "Cannot expand structure with flexible array."); - if (RD->isUnion()) { - // Unions can be here only in degenerative cases - all the fields are same - // after flattening. Thus we have to use the "largest" field. - const FieldDecl *LargestFD = nullptr; - CharUnits UnionSize = CharUnits::Zero(); - - for (const auto *FD : RD->fields()) { - if (FD->isZeroLengthBitField(Context)) - continue; - assert(!FD->isBitField() && - "Cannot expand structure with bit-field members."); - CharUnits FieldSize = Context.getTypeSizeInChars(FD->getType()); - if (UnionSize < FieldSize) { - UnionSize = FieldSize; - LargestFD = FD; - } - } - if (LargestFD) - Fields.push_back(LargestFD); - } else { - if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) { - assert(!CXXRD->isDynamicClass() && - "cannot expand vtable pointers in dynamic classes"); - for (const CXXBaseSpecifier &BS : CXXRD->bases()) - Bases.push_back(&BS); - } - - for (const auto *FD : RD->fields()) { - if (FD->isZeroLengthBitField(Context)) - continue; - assert(!FD->isBitField() && - "Cannot expand structure with bit-field members."); - Fields.push_back(FD); - } - } - return llvm::make_unique<RecordExpansion>(std::move(Bases), - std::move(Fields)); - } - if (const ComplexType *CT = Ty->getAs<ComplexType>()) { - return llvm::make_unique<ComplexExpansion>(CT->getElementType()); - } - return llvm::make_unique<NoExpansion>(); -} - -static int getExpansionSize(QualType Ty, const ASTContext &Context) { - auto Exp = getTypeExpansion(Ty, Context); - if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) { - return CAExp->NumElts * getExpansionSize(CAExp->EltTy, Context); - } - if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) { - int Res = 0; - for (auto BS : RExp->Bases) - Res += getExpansionSize(BS->getType(), Context); - for (auto FD : RExp->Fields) - Res += getExpansionSize(FD->getType(), Context); - return Res; - } - if (isa<ComplexExpansion>(Exp.get())) - return 2; - assert(isa<NoExpansion>(Exp.get())); - return 1; -} - -void -CodeGenTypes::getExpandedTypes(QualType Ty, - SmallVectorImpl<llvm::Type *>::iterator &TI) { - auto Exp = getTypeExpansion(Ty, Context); - if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) { - for (int i = 0, n = CAExp->NumElts; i < n; i++) { - getExpandedTypes(CAExp->EltTy, TI); - } - } else if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) { - for (auto BS : RExp->Bases) - getExpandedTypes(BS->getType(), TI); - for (auto FD : RExp->Fields) - getExpandedTypes(FD->getType(), TI); - } else if (auto CExp = dyn_cast<ComplexExpansion>(Exp.get())) { - llvm::Type *EltTy = ConvertType(CExp->EltTy); - *TI++ = EltTy; - *TI++ = EltTy; - } else { - assert(isa<NoExpansion>(Exp.get())); - *TI++ = ConvertType(Ty); - } -} - -static void forConstantArrayExpansion(CodeGenFunction &CGF, - ConstantArrayExpansion *CAE, - Address BaseAddr, - llvm::function_ref<void(Address)> Fn) { - CharUnits EltSize = CGF.getContext().getTypeSizeInChars(CAE->EltTy); - CharUnits EltAlign = - BaseAddr.getAlignment().alignmentOfArrayElement(EltSize); - - for (int i = 0, n = CAE->NumElts; i < n; i++) { - llvm::Value *EltAddr = - CGF.Builder.CreateConstGEP2_32(nullptr, BaseAddr.getPointer(), 0, i); - Fn(Address(EltAddr, EltAlign)); - } -} - -void CodeGenFunction::ExpandTypeFromArgs( - QualType Ty, LValue LV, SmallVectorImpl<llvm::Value *>::iterator &AI) { - assert(LV.isSimple() && - "Unexpected non-simple lvalue during struct expansion."); - - auto Exp = getTypeExpansion(Ty, getContext()); - if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) { - forConstantArrayExpansion(*this, CAExp, LV.getAddress(), - [&](Address EltAddr) { - LValue LV = MakeAddrLValue(EltAddr, CAExp->EltTy); - ExpandTypeFromArgs(CAExp->EltTy, LV, AI); - }); - } else if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) { - Address This = LV.getAddress(); - for (const CXXBaseSpecifier *BS : RExp->Bases) { - // Perform a single step derived-to-base conversion. - Address Base = - GetAddressOfBaseClass(This, Ty->getAsCXXRecordDecl(), &BS, &BS + 1, - /*NullCheckValue=*/false, SourceLocation()); - LValue SubLV = MakeAddrLValue(Base, BS->getType()); - - // Recurse onto bases. - ExpandTypeFromArgs(BS->getType(), SubLV, AI); - } - for (auto FD : RExp->Fields) { - // FIXME: What are the right qualifiers here? - LValue SubLV = EmitLValueForFieldInitialization(LV, FD); - ExpandTypeFromArgs(FD->getType(), SubLV, AI); - } - } else if (isa<ComplexExpansion>(Exp.get())) { - auto realValue = *AI++; - auto imagValue = *AI++; - EmitStoreOfComplex(ComplexPairTy(realValue, imagValue), LV, /*init*/ true); - } else { - assert(isa<NoExpansion>(Exp.get())); - EmitStoreThroughLValue(RValue::get(*AI++), LV); - } -} - -void CodeGenFunction::ExpandTypeToArgs( - QualType Ty, CallArg Arg, llvm::FunctionType *IRFuncTy, - SmallVectorImpl<llvm::Value *> &IRCallArgs, unsigned &IRCallArgPos) { - auto Exp = getTypeExpansion(Ty, getContext()); - if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) { - Address Addr = Arg.hasLValue() ? Arg.getKnownLValue().getAddress() - : Arg.getKnownRValue().getAggregateAddress(); - forConstantArrayExpansion( - *this, CAExp, Addr, [&](Address EltAddr) { - CallArg EltArg = CallArg( - convertTempToRValue(EltAddr, CAExp->EltTy, SourceLocation()), - CAExp->EltTy); - ExpandTypeToArgs(CAExp->EltTy, EltArg, IRFuncTy, IRCallArgs, - IRCallArgPos); - }); - } else if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) { - Address This = Arg.hasLValue() ? Arg.getKnownLValue().getAddress() - : Arg.getKnownRValue().getAggregateAddress(); - for (const CXXBaseSpecifier *BS : RExp->Bases) { - // Perform a single step derived-to-base conversion. - Address Base = - GetAddressOfBaseClass(This, Ty->getAsCXXRecordDecl(), &BS, &BS + 1, - /*NullCheckValue=*/false, SourceLocation()); - CallArg BaseArg = CallArg(RValue::getAggregate(Base), BS->getType()); - - // Recurse onto bases. - ExpandTypeToArgs(BS->getType(), BaseArg, IRFuncTy, IRCallArgs, - IRCallArgPos); - } - - LValue LV = MakeAddrLValue(This, Ty); - for (auto FD : RExp->Fields) { - CallArg FldArg = - CallArg(EmitRValueForField(LV, FD, SourceLocation()), FD->getType()); - ExpandTypeToArgs(FD->getType(), FldArg, IRFuncTy, IRCallArgs, - IRCallArgPos); - } - } else if (isa<ComplexExpansion>(Exp.get())) { - ComplexPairTy CV = Arg.getKnownRValue().getComplexVal(); - IRCallArgs[IRCallArgPos++] = CV.first; - IRCallArgs[IRCallArgPos++] = CV.second; - } else { - assert(isa<NoExpansion>(Exp.get())); - auto RV = Arg.getKnownRValue(); - assert(RV.isScalar() && - "Unexpected non-scalar rvalue during struct expansion."); - - // Insert a bitcast as needed. - llvm::Value *V = RV.getScalarVal(); - if (IRCallArgPos < IRFuncTy->getNumParams() && - V->getType() != IRFuncTy->getParamType(IRCallArgPos)) - V = Builder.CreateBitCast(V, IRFuncTy->getParamType(IRCallArgPos)); - - IRCallArgs[IRCallArgPos++] = V; - } -} - -/// Create a temporary allocation for the purposes of coercion. -static Address CreateTempAllocaForCoercion(CodeGenFunction &CGF, llvm::Type *Ty, - CharUnits MinAlign) { - // Don't use an alignment that's worse than what LLVM would prefer. - auto PrefAlign = CGF.CGM.getDataLayout().getPrefTypeAlignment(Ty); - CharUnits Align = std::max(MinAlign, CharUnits::fromQuantity(PrefAlign)); - - return CGF.CreateTempAlloca(Ty, Align); -} - -/// EnterStructPointerForCoercedAccess - Given a struct pointer that we are -/// accessing some number of bytes out of it, try to gep into the struct to get -/// at its inner goodness. Dive as deep as possible without entering an element -/// with an in-memory size smaller than DstSize. -static Address -EnterStructPointerForCoercedAccess(Address SrcPtr, - llvm::StructType *SrcSTy, - uint64_t DstSize, CodeGenFunction &CGF) { - // We can't dive into a zero-element struct. - if (SrcSTy->getNumElements() == 0) return SrcPtr; - - llvm::Type *FirstElt = SrcSTy->getElementType(0); - - // If the first elt is at least as large as what we're looking for, or if the - // first element is the same size as the whole struct, we can enter it. The - // comparison must be made on the store size and not the alloca size. Using - // the alloca size may overstate the size of the load. - uint64_t FirstEltSize = - CGF.CGM.getDataLayout().getTypeStoreSize(FirstElt); - if (FirstEltSize < DstSize && - FirstEltSize < CGF.CGM.getDataLayout().getTypeStoreSize(SrcSTy)) - return SrcPtr; - - // GEP into the first element. - SrcPtr = CGF.Builder.CreateStructGEP(SrcPtr, 0, CharUnits(), "coerce.dive"); - - // If the first element is a struct, recurse. - llvm::Type *SrcTy = SrcPtr.getElementType(); - if (llvm::StructType *SrcSTy = dyn_cast<llvm::StructType>(SrcTy)) - return EnterStructPointerForCoercedAccess(SrcPtr, SrcSTy, DstSize, CGF); - - return SrcPtr; -} - -/// CoerceIntOrPtrToIntOrPtr - Convert a value Val to the specific Ty where both -/// are either integers or pointers. This does a truncation of the value if it -/// is too large or a zero extension if it is too small. -/// -/// This behaves as if the value were coerced through memory, so on big-endian -/// targets the high bits are preserved in a truncation, while little-endian -/// targets preserve the low bits. -static llvm::Value *CoerceIntOrPtrToIntOrPtr(llvm::Value *Val, - llvm::Type *Ty, - CodeGenFunction &CGF) { - if (Val->getType() == Ty) - return Val; - - if (isa<llvm::PointerType>(Val->getType())) { - // If this is Pointer->Pointer avoid conversion to and from int. - if (isa<llvm::PointerType>(Ty)) - return CGF.Builder.CreateBitCast(Val, Ty, "coerce.val"); - - // Convert the pointer to an integer so we can play with its width. - Val = CGF.Builder.CreatePtrToInt(Val, CGF.IntPtrTy, "coerce.val.pi"); - } - - llvm::Type *DestIntTy = Ty; - if (isa<llvm::PointerType>(DestIntTy)) - DestIntTy = CGF.IntPtrTy; - - if (Val->getType() != DestIntTy) { - const llvm::DataLayout &DL = CGF.CGM.getDataLayout(); - if (DL.isBigEndian()) { - // Preserve the high bits on big-endian targets. - // That is what memory coercion does. - uint64_t SrcSize = DL.getTypeSizeInBits(Val->getType()); - uint64_t DstSize = DL.getTypeSizeInBits(DestIntTy); - - if (SrcSize > DstSize) { - Val = CGF.Builder.CreateLShr(Val, SrcSize - DstSize, "coerce.highbits"); - Val = CGF.Builder.CreateTrunc(Val, DestIntTy, "coerce.val.ii"); - } else { - Val = CGF.Builder.CreateZExt(Val, DestIntTy, "coerce.val.ii"); - Val = CGF.Builder.CreateShl(Val, DstSize - SrcSize, "coerce.highbits"); - } - } else { - // Little-endian targets preserve the low bits. No shifts required. - Val = CGF.Builder.CreateIntCast(Val, DestIntTy, false, "coerce.val.ii"); - } - } - - if (isa<llvm::PointerType>(Ty)) - Val = CGF.Builder.CreateIntToPtr(Val, Ty, "coerce.val.ip"); - return Val; -} - - - -/// CreateCoercedLoad - Create a load from \arg SrcPtr interpreted as -/// a pointer to an object of type \arg Ty, known to be aligned to -/// \arg SrcAlign bytes. -/// -/// This safely handles the case when the src type is smaller than the -/// destination type; in this situation the values of bits which not -/// present in the src are undefined. -static llvm::Value *CreateCoercedLoad(Address Src, llvm::Type *Ty, - CodeGenFunction &CGF) { - llvm::Type *SrcTy = Src.getElementType(); - - // If SrcTy and Ty are the same, just do a load. - if (SrcTy == Ty) - return CGF.Builder.CreateLoad(Src); - - uint64_t DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(Ty); - - if (llvm::StructType *SrcSTy = dyn_cast<llvm::StructType>(SrcTy)) { - Src = EnterStructPointerForCoercedAccess(Src, SrcSTy, DstSize, CGF); - SrcTy = Src.getType()->getElementType(); - } - - uint64_t SrcSize = CGF.CGM.getDataLayout().getTypeAllocSize(SrcTy); - - // If the source and destination are integer or pointer types, just do an - // extension or truncation to the desired type. - if ((isa<llvm::IntegerType>(Ty) || isa<llvm::PointerType>(Ty)) && - (isa<llvm::IntegerType>(SrcTy) || isa<llvm::PointerType>(SrcTy))) { - llvm::Value *Load = CGF.Builder.CreateLoad(Src); - return CoerceIntOrPtrToIntOrPtr(Load, Ty, CGF); - } - - // If load is legal, just bitcast the src pointer. - if (SrcSize >= DstSize) { - // Generally SrcSize is never greater than DstSize, since this means we are - // losing bits. However, this can happen in cases where the structure has - // additional padding, for example due to a user specified alignment. - // - // FIXME: Assert that we aren't truncating non-padding bits when have access - // to that information. - Src = CGF.Builder.CreateBitCast(Src, - Ty->getPointerTo(Src.getAddressSpace())); - return CGF.Builder.CreateLoad(Src); - } - - // Otherwise do coercion through memory. This is stupid, but simple. - Address Tmp = CreateTempAllocaForCoercion(CGF, Ty, Src.getAlignment()); - Address Casted = CGF.Builder.CreateElementBitCast(Tmp,CGF.Int8Ty); - Address SrcCasted = CGF.Builder.CreateElementBitCast(Src,CGF.Int8Ty); - CGF.Builder.CreateMemCpy(Casted, SrcCasted, - llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize), - false); - return CGF.Builder.CreateLoad(Tmp); -} - -// Function to store a first-class aggregate into memory. We prefer to -// store the elements rather than the aggregate to be more friendly to -// fast-isel. -// FIXME: Do we need to recurse here? -static void BuildAggStore(CodeGenFunction &CGF, llvm::Value *Val, - Address Dest, bool DestIsVolatile) { - // Prefer scalar stores to first-class aggregate stores. - if (llvm::StructType *STy = - dyn_cast<llvm::StructType>(Val->getType())) { - const llvm::StructLayout *Layout = - CGF.CGM.getDataLayout().getStructLayout(STy); - - for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { - auto EltOffset = CharUnits::fromQuantity(Layout->getElementOffset(i)); - Address EltPtr = CGF.Builder.CreateStructGEP(Dest, i, EltOffset); - llvm::Value *Elt = CGF.Builder.CreateExtractValue(Val, i); - CGF.Builder.CreateStore(Elt, EltPtr, DestIsVolatile); - } - } else { - CGF.Builder.CreateStore(Val, Dest, DestIsVolatile); - } -} - -/// CreateCoercedStore - Create a store to \arg DstPtr from \arg Src, -/// where the source and destination may have different types. The -/// destination is known to be aligned to \arg DstAlign bytes. -/// -/// This safely handles the case when the src type is larger than the -/// destination type; the upper bits of the src will be lost. -static void CreateCoercedStore(llvm::Value *Src, - Address Dst, - bool DstIsVolatile, - CodeGenFunction &CGF) { - llvm::Type *SrcTy = Src->getType(); - llvm::Type *DstTy = Dst.getType()->getElementType(); - if (SrcTy == DstTy) { - CGF.Builder.CreateStore(Src, Dst, DstIsVolatile); - return; - } - - uint64_t SrcSize = CGF.CGM.getDataLayout().getTypeAllocSize(SrcTy); - - if (llvm::StructType *DstSTy = dyn_cast<llvm::StructType>(DstTy)) { - Dst = EnterStructPointerForCoercedAccess(Dst, DstSTy, SrcSize, CGF); - DstTy = Dst.getType()->getElementType(); - } - - // If the source and destination are integer or pointer types, just do an - // extension or truncation to the desired type. - if ((isa<llvm::IntegerType>(SrcTy) || isa<llvm::PointerType>(SrcTy)) && - (isa<llvm::IntegerType>(DstTy) || isa<llvm::PointerType>(DstTy))) { - Src = CoerceIntOrPtrToIntOrPtr(Src, DstTy, CGF); - CGF.Builder.CreateStore(Src, Dst, DstIsVolatile); - return; - } - - uint64_t DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(DstTy); - - // If store is legal, just bitcast the src pointer. - if (SrcSize <= DstSize) { - Dst = CGF.Builder.CreateElementBitCast(Dst, SrcTy); - BuildAggStore(CGF, Src, Dst, DstIsVolatile); - } else { - // Otherwise do coercion through memory. This is stupid, but - // simple. - - // Generally SrcSize is never greater than DstSize, since this means we are - // losing bits. However, this can happen in cases where the structure has - // additional padding, for example due to a user specified alignment. - // - // FIXME: Assert that we aren't truncating non-padding bits when have access - // to that information. - Address Tmp = CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment()); - CGF.Builder.CreateStore(Src, Tmp); - Address Casted = CGF.Builder.CreateElementBitCast(Tmp,CGF.Int8Ty); - Address DstCasted = CGF.Builder.CreateElementBitCast(Dst,CGF.Int8Ty); - CGF.Builder.CreateMemCpy(DstCasted, Casted, - llvm::ConstantInt::get(CGF.IntPtrTy, DstSize), - false); - } -} - -static Address emitAddressAtOffset(CodeGenFunction &CGF, Address addr, - const ABIArgInfo &info) { - if (unsigned offset = info.getDirectOffset()) { - addr = CGF.Builder.CreateElementBitCast(addr, CGF.Int8Ty); - addr = CGF.Builder.CreateConstInBoundsByteGEP(addr, - CharUnits::fromQuantity(offset)); - addr = CGF.Builder.CreateElementBitCast(addr, info.getCoerceToType()); - } - return addr; -} - -namespace { - -/// Encapsulates information about the way function arguments from -/// CGFunctionInfo should be passed to actual LLVM IR function. -class ClangToLLVMArgMapping { - static const unsigned InvalidIndex = ~0U; - unsigned InallocaArgNo; - unsigned SRetArgNo; - unsigned TotalIRArgs; - - /// Arguments of LLVM IR function corresponding to single Clang argument. - struct IRArgs { - unsigned PaddingArgIndex; - // Argument is expanded to IR arguments at positions - // [FirstArgIndex, FirstArgIndex + NumberOfArgs). - unsigned FirstArgIndex; - unsigned NumberOfArgs; - - IRArgs() - : PaddingArgIndex(InvalidIndex), FirstArgIndex(InvalidIndex), - NumberOfArgs(0) {} - }; - - SmallVector<IRArgs, 8> ArgInfo; - -public: - ClangToLLVMArgMapping(const ASTContext &Context, const CGFunctionInfo &FI, - bool OnlyRequiredArgs = false) - : InallocaArgNo(InvalidIndex), SRetArgNo(InvalidIndex), TotalIRArgs(0), - ArgInfo(OnlyRequiredArgs ? FI.getNumRequiredArgs() : FI.arg_size()) { - construct(Context, FI, OnlyRequiredArgs); - } - - bool hasInallocaArg() const { return InallocaArgNo != InvalidIndex; } - unsigned getInallocaArgNo() const { - assert(hasInallocaArg()); - return InallocaArgNo; - } - - bool hasSRetArg() const { return SRetArgNo != InvalidIndex; } - unsigned getSRetArgNo() const { - assert(hasSRetArg()); - return SRetArgNo; - } - - unsigned totalIRArgs() const { return TotalIRArgs; } - - bool hasPaddingArg(unsigned ArgNo) const { - assert(ArgNo < ArgInfo.size()); - return ArgInfo[ArgNo].PaddingArgIndex != InvalidIndex; - } - unsigned getPaddingArgNo(unsigned ArgNo) const { - assert(hasPaddingArg(ArgNo)); - return ArgInfo[ArgNo].PaddingArgIndex; - } - - /// Returns index of first IR argument corresponding to ArgNo, and their - /// quantity. - std::pair<unsigned, unsigned> getIRArgs(unsigned ArgNo) const { - assert(ArgNo < ArgInfo.size()); - return std::make_pair(ArgInfo[ArgNo].FirstArgIndex, - ArgInfo[ArgNo].NumberOfArgs); - } - -private: - void construct(const ASTContext &Context, const CGFunctionInfo &FI, - bool OnlyRequiredArgs); -}; - -void ClangToLLVMArgMapping::construct(const ASTContext &Context, - const CGFunctionInfo &FI, - bool OnlyRequiredArgs) { - unsigned IRArgNo = 0; - bool SwapThisWithSRet = false; - const ABIArgInfo &RetAI = FI.getReturnInfo(); - - if (RetAI.getKind() == ABIArgInfo::Indirect) { - SwapThisWithSRet = RetAI.isSRetAfterThis(); - SRetArgNo = SwapThisWithSRet ? 1 : IRArgNo++; - } - - unsigned ArgNo = 0; - unsigned NumArgs = OnlyRequiredArgs ? FI.getNumRequiredArgs() : FI.arg_size(); - for (CGFunctionInfo::const_arg_iterator I = FI.arg_begin(); ArgNo < NumArgs; - ++I, ++ArgNo) { - assert(I != FI.arg_end()); - QualType ArgType = I->type; - const ABIArgInfo &AI = I->info; - // Collect data about IR arguments corresponding to Clang argument ArgNo. - auto &IRArgs = ArgInfo[ArgNo]; - - if (AI.getPaddingType()) - IRArgs.PaddingArgIndex = IRArgNo++; - - switch (AI.getKind()) { - case ABIArgInfo::Extend: - case ABIArgInfo::Direct: { - // FIXME: handle sseregparm someday... - llvm::StructType *STy = dyn_cast<llvm::StructType>(AI.getCoerceToType()); - if (AI.isDirect() && AI.getCanBeFlattened() && STy) { - IRArgs.NumberOfArgs = STy->getNumElements(); - } else { - IRArgs.NumberOfArgs = 1; - } - break; - } - case ABIArgInfo::Indirect: - IRArgs.NumberOfArgs = 1; - break; - case ABIArgInfo::Ignore: - case ABIArgInfo::InAlloca: - // ignore and inalloca doesn't have matching LLVM parameters. - IRArgs.NumberOfArgs = 0; - break; - case ABIArgInfo::CoerceAndExpand: - IRArgs.NumberOfArgs = AI.getCoerceAndExpandTypeSequence().size(); - break; - case ABIArgInfo::Expand: - IRArgs.NumberOfArgs = getExpansionSize(ArgType, Context); - break; - } - - if (IRArgs.NumberOfArgs > 0) { - IRArgs.FirstArgIndex = IRArgNo; - IRArgNo += IRArgs.NumberOfArgs; - } - - // Skip over the sret parameter when it comes second. We already handled it - // above. - if (IRArgNo == 1 && SwapThisWithSRet) - IRArgNo++; - } - assert(ArgNo == ArgInfo.size()); - - if (FI.usesInAlloca()) - InallocaArgNo = IRArgNo++; - - TotalIRArgs = IRArgNo; -} -} // namespace - -/***/ - -bool CodeGenModule::ReturnTypeUsesSRet(const CGFunctionInfo &FI) { - const auto &RI = FI.getReturnInfo(); - return RI.isIndirect() || (RI.isInAlloca() && RI.getInAllocaSRet()); -} - -bool CodeGenModule::ReturnSlotInterferesWithArgs(const CGFunctionInfo &FI) { - return ReturnTypeUsesSRet(FI) && - getTargetCodeGenInfo().doesReturnSlotInterfereWithArgs(); -} - -bool CodeGenModule::ReturnTypeUsesFPRet(QualType ResultType) { - if (const BuiltinType *BT = ResultType->getAs<BuiltinType>()) { - switch (BT->getKind()) { - default: - return false; - case BuiltinType::Float: - return getTarget().useObjCFPRetForRealType(TargetInfo::Float); - case BuiltinType::Double: - return getTarget().useObjCFPRetForRealType(TargetInfo::Double); - case BuiltinType::LongDouble: - return getTarget().useObjCFPRetForRealType(TargetInfo::LongDouble); - } - } - - return false; -} - -bool CodeGenModule::ReturnTypeUsesFP2Ret(QualType ResultType) { - if (const ComplexType *CT = ResultType->getAs<ComplexType>()) { - if (const BuiltinType *BT = CT->getElementType()->getAs<BuiltinType>()) { - if (BT->getKind() == BuiltinType::LongDouble) - return getTarget().useObjCFP2RetForComplexLongDouble(); - } - } - - return false; -} - -llvm::FunctionType *CodeGenTypes::GetFunctionType(GlobalDecl GD) { - const CGFunctionInfo &FI = arrangeGlobalDeclaration(GD); - return GetFunctionType(FI); -} - -llvm::FunctionType * -CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) { - - bool Inserted = FunctionsBeingProcessed.insert(&FI).second; - (void)Inserted; - assert(Inserted && "Recursively being processed?"); - - llvm::Type *resultType = nullptr; - const ABIArgInfo &retAI = FI.getReturnInfo(); - switch (retAI.getKind()) { - case ABIArgInfo::Expand: - llvm_unreachable("Invalid ABI kind for return argument"); - - case ABIArgInfo::Extend: - case ABIArgInfo::Direct: - resultType = retAI.getCoerceToType(); - break; - - case ABIArgInfo::InAlloca: - if (retAI.getInAllocaSRet()) { - // sret things on win32 aren't void, they return the sret pointer. - QualType ret = FI.getReturnType(); - llvm::Type *ty = ConvertType(ret); - unsigned addressSpace = Context.getTargetAddressSpace(ret); - resultType = llvm::PointerType::get(ty, addressSpace); - } else { - resultType = llvm::Type::getVoidTy(getLLVMContext()); - } - break; - - case ABIArgInfo::Indirect: - case ABIArgInfo::Ignore: - resultType = llvm::Type::getVoidTy(getLLVMContext()); - break; - - case ABIArgInfo::CoerceAndExpand: - resultType = retAI.getUnpaddedCoerceAndExpandType(); - break; - } - - ClangToLLVMArgMapping IRFunctionArgs(getContext(), FI, true); - SmallVector<llvm::Type*, 8> ArgTypes(IRFunctionArgs.totalIRArgs()); - - // Add type for sret argument. - if (IRFunctionArgs.hasSRetArg()) { - QualType Ret = FI.getReturnType(); - llvm::Type *Ty = ConvertType(Ret); - unsigned AddressSpace = Context.getTargetAddressSpace(Ret); - ArgTypes[IRFunctionArgs.getSRetArgNo()] = - llvm::PointerType::get(Ty, AddressSpace); - } - - // Add type for inalloca argument. - if (IRFunctionArgs.hasInallocaArg()) { - auto ArgStruct = FI.getArgStruct(); - assert(ArgStruct); - ArgTypes[IRFunctionArgs.getInallocaArgNo()] = ArgStruct->getPointerTo(); - } - - // Add in all of the required arguments. - unsigned ArgNo = 0; - CGFunctionInfo::const_arg_iterator it = FI.arg_begin(), - ie = it + FI.getNumRequiredArgs(); - for (; it != ie; ++it, ++ArgNo) { - const ABIArgInfo &ArgInfo = it->info; - - // Insert a padding type to ensure proper alignment. - if (IRFunctionArgs.hasPaddingArg(ArgNo)) - ArgTypes[IRFunctionArgs.getPaddingArgNo(ArgNo)] = - ArgInfo.getPaddingType(); - - unsigned FirstIRArg, NumIRArgs; - std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo); - - switch (ArgInfo.getKind()) { - case ABIArgInfo::Ignore: - case ABIArgInfo::InAlloca: - assert(NumIRArgs == 0); - break; - - case ABIArgInfo::Indirect: { - assert(NumIRArgs == 1); - // indirect arguments are always on the stack, which is alloca addr space. - llvm::Type *LTy = ConvertTypeForMem(it->type); - ArgTypes[FirstIRArg] = LTy->getPointerTo( - CGM.getDataLayout().getAllocaAddrSpace()); - break; - } - - case ABIArgInfo::Extend: - case ABIArgInfo::Direct: { - // Fast-isel and the optimizer generally like scalar values better than - // FCAs, so we flatten them if this is safe to do for this argument. - llvm::Type *argType = ArgInfo.getCoerceToType(); - llvm::StructType *st = dyn_cast<llvm::StructType>(argType); - if (st && ArgInfo.isDirect() && ArgInfo.getCanBeFlattened()) { - assert(NumIRArgs == st->getNumElements()); - for (unsigned i = 0, e = st->getNumElements(); i != e; ++i) - ArgTypes[FirstIRArg + i] = st->getElementType(i); - } else { - assert(NumIRArgs == 1); - ArgTypes[FirstIRArg] = argType; - } - break; - } - - case ABIArgInfo::CoerceAndExpand: { - auto ArgTypesIter = ArgTypes.begin() + FirstIRArg; - for (auto EltTy : ArgInfo.getCoerceAndExpandTypeSequence()) { - *ArgTypesIter++ = EltTy; - } - assert(ArgTypesIter == ArgTypes.begin() + FirstIRArg + NumIRArgs); - break; - } - - case ABIArgInfo::Expand: - auto ArgTypesIter = ArgTypes.begin() + FirstIRArg; - getExpandedTypes(it->type, ArgTypesIter); - assert(ArgTypesIter == ArgTypes.begin() + FirstIRArg + NumIRArgs); - break; - } - } - - bool Erased = FunctionsBeingProcessed.erase(&FI); (void)Erased; - assert(Erased && "Not in set?"); - - return llvm::FunctionType::get(resultType, ArgTypes, FI.isVariadic()); -} - -llvm::Type *CodeGenTypes::GetFunctionTypeForVTable(GlobalDecl GD) { - const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); - const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); - - if (!isFuncTypeConvertible(FPT)) - return llvm::StructType::get(getLLVMContext()); - - const CGFunctionInfo *Info; - if (isa<CXXDestructorDecl>(MD)) - Info = - &arrangeCXXStructorDeclaration(MD, getFromDtorType(GD.getDtorType())); - else - Info = &arrangeCXXMethodDeclaration(MD); - return GetFunctionType(*Info); -} - -static void AddAttributesFromFunctionProtoType(ASTContext &Ctx, - llvm::AttrBuilder &FuncAttrs, - const FunctionProtoType *FPT) { - if (!FPT) - return; - - if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) && - FPT->isNothrow()) - FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); -} - -void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone, - bool AttrOnCallSite, - llvm::AttrBuilder &FuncAttrs) { - // OptimizeNoneAttr takes precedence over -Os or -Oz. No warning needed. - if (!HasOptnone) { - if (CodeGenOpts.OptimizeSize) - FuncAttrs.addAttribute(llvm::Attribute::OptimizeForSize); - if (CodeGenOpts.OptimizeSize == 2) - FuncAttrs.addAttribute(llvm::Attribute::MinSize); - } - - if (CodeGenOpts.DisableRedZone) - FuncAttrs.addAttribute(llvm::Attribute::NoRedZone); - if (CodeGenOpts.IndirectTlsSegRefs) - FuncAttrs.addAttribute("indirect-tls-seg-refs"); - if (CodeGenOpts.NoImplicitFloat) - FuncAttrs.addAttribute(llvm::Attribute::NoImplicitFloat); - - if (AttrOnCallSite) { - // Attributes that should go on the call site only. - if (!CodeGenOpts.SimplifyLibCalls || - CodeGenOpts.isNoBuiltinFunc(Name.data())) - FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin); - if (!CodeGenOpts.TrapFuncName.empty()) - FuncAttrs.addAttribute("trap-func-name", CodeGenOpts.TrapFuncName); - } else { - // Attributes that should go on the function, but not the call site. - if (!CodeGenOpts.DisableFPElim) { - FuncAttrs.addAttribute("no-frame-pointer-elim", "false"); - } else if (CodeGenOpts.OmitLeafFramePointer) { - FuncAttrs.addAttribute("no-frame-pointer-elim", "false"); - FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf"); - } else { - FuncAttrs.addAttribute("no-frame-pointer-elim", "true"); - FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf"); - } - - FuncAttrs.addAttribute("less-precise-fpmad", - llvm::toStringRef(CodeGenOpts.LessPreciseFPMAD)); - - if (CodeGenOpts.NullPointerIsValid) - FuncAttrs.addAttribute("null-pointer-is-valid", "true"); - if (!CodeGenOpts.FPDenormalMode.empty()) - FuncAttrs.addAttribute("denormal-fp-math", CodeGenOpts.FPDenormalMode); - - FuncAttrs.addAttribute("no-trapping-math", - llvm::toStringRef(CodeGenOpts.NoTrappingMath)); - - // Strict (compliant) code is the default, so only add this attribute to - // indicate that we are trying to workaround a problem case. - if (!CodeGenOpts.StrictFloatCastOverflow) - FuncAttrs.addAttribute("strict-float-cast-overflow", "false"); - - // TODO: Are these all needed? - // unsafe/inf/nan/nsz are handled by instruction-level FastMathFlags. - FuncAttrs.addAttribute("no-infs-fp-math", - llvm::toStringRef(CodeGenOpts.NoInfsFPMath)); - FuncAttrs.addAttribute("no-nans-fp-math", - llvm::toStringRef(CodeGenOpts.NoNaNsFPMath)); - FuncAttrs.addAttribute("unsafe-fp-math", - llvm::toStringRef(CodeGenOpts.UnsafeFPMath)); - FuncAttrs.addAttribute("use-soft-float", - llvm::toStringRef(CodeGenOpts.SoftFloat)); - FuncAttrs.addAttribute("stack-protector-buffer-size", - llvm::utostr(CodeGenOpts.SSPBufferSize)); - FuncAttrs.addAttribute("no-signed-zeros-fp-math", - llvm::toStringRef(CodeGenOpts.NoSignedZeros)); - FuncAttrs.addAttribute( - "correctly-rounded-divide-sqrt-fp-math", - llvm::toStringRef(CodeGenOpts.CorrectlyRoundedDivSqrt)); - - if (getLangOpts().OpenCL) - FuncAttrs.addAttribute("denorms-are-zero", - llvm::toStringRef(CodeGenOpts.FlushDenorm)); - - // TODO: Reciprocal estimate codegen options should apply to instructions? - const std::vector<std::string> &Recips = CodeGenOpts.Reciprocals; - if (!Recips.empty()) - FuncAttrs.addAttribute("reciprocal-estimates", - llvm::join(Recips, ",")); - - if (!CodeGenOpts.PreferVectorWidth.empty() && - CodeGenOpts.PreferVectorWidth != "none") - FuncAttrs.addAttribute("prefer-vector-width", - CodeGenOpts.PreferVectorWidth); - - if (CodeGenOpts.StackRealignment) - FuncAttrs.addAttribute("stackrealign"); - if (CodeGenOpts.Backchain) - FuncAttrs.addAttribute("backchain"); - - // FIXME: The interaction of this attribute with the SLH command line flag - // has not been determined. - if (CodeGenOpts.SpeculativeLoadHardening) - FuncAttrs.addAttribute(llvm::Attribute::SpeculativeLoadHardening); - } - - if (getLangOpts().assumeFunctionsAreConvergent()) { - // Conservatively, mark all functions and calls in CUDA and OpenCL as - // convergent (meaning, they may call an intrinsically convergent op, such - // as __syncthreads() / barrier(), and so can't have certain optimizations - // applied around them). LLVM will remove this attribute where it safely - // can. - FuncAttrs.addAttribute(llvm::Attribute::Convergent); - } - - if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) { - // Exceptions aren't supported in CUDA device code. - FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); - - // Respect -fcuda-flush-denormals-to-zero. - if (CodeGenOpts.FlushDenorm) - FuncAttrs.addAttribute("nvptx-f32ftz", "true"); - } - - for (StringRef Attr : CodeGenOpts.DefaultFunctionAttrs) { - StringRef Var, Value; - std::tie(Var, Value) = Attr.split('='); - FuncAttrs.addAttribute(Var, Value); - } -} - -void CodeGenModule::AddDefaultFnAttrs(llvm::Function &F) { - llvm::AttrBuilder FuncAttrs; - ConstructDefaultFnAttrList(F.getName(), - F.hasFnAttribute(llvm::Attribute::OptimizeNone), - /* AttrOnCallsite = */ false, FuncAttrs); - F.addAttributes(llvm::AttributeList::FunctionIndex, FuncAttrs); -} - -void CodeGenModule::ConstructAttributeList( - StringRef Name, const CGFunctionInfo &FI, CGCalleeInfo CalleeInfo, - llvm::AttributeList &AttrList, unsigned &CallingConv, bool AttrOnCallSite) { - llvm::AttrBuilder FuncAttrs; - llvm::AttrBuilder RetAttrs; - - CallingConv = FI.getEffectiveCallingConvention(); - if (FI.isNoReturn()) - FuncAttrs.addAttribute(llvm::Attribute::NoReturn); - - // If we have information about the function prototype, we can learn - // attributes from there. - AddAttributesFromFunctionProtoType(getContext(), FuncAttrs, - CalleeInfo.getCalleeFunctionProtoType()); - - const Decl *TargetDecl = CalleeInfo.getCalleeDecl().getDecl(); - - bool HasOptnone = false; - // FIXME: handle sseregparm someday... - if (TargetDecl) { - if (TargetDecl->hasAttr<ReturnsTwiceAttr>()) - FuncAttrs.addAttribute(llvm::Attribute::ReturnsTwice); - if (TargetDecl->hasAttr<NoThrowAttr>()) - FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); - if (TargetDecl->hasAttr<NoReturnAttr>()) - FuncAttrs.addAttribute(llvm::Attribute::NoReturn); - if (TargetDecl->hasAttr<ColdAttr>()) - FuncAttrs.addAttribute(llvm::Attribute::Cold); - if (TargetDecl->hasAttr<NoDuplicateAttr>()) - FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate); - if (TargetDecl->hasAttr<ConvergentAttr>()) - FuncAttrs.addAttribute(llvm::Attribute::Convergent); - if (TargetDecl->hasAttr<SpeculativeLoadHardeningAttr>()) - FuncAttrs.addAttribute(llvm::Attribute::SpeculativeLoadHardening); - - if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) { - AddAttributesFromFunctionProtoType( - getContext(), FuncAttrs, Fn->getType()->getAs<FunctionProtoType>()); - // Don't use [[noreturn]] or _Noreturn for a call to a virtual function. - // These attributes are not inherited by overloads. - const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn); - if (Fn->isNoReturn() && !(AttrOnCallSite && MD && MD->isVirtual())) - FuncAttrs.addAttribute(llvm::Attribute::NoReturn); - } - - // 'const', 'pure' and 'noalias' attributed functions are also nounwind. - if (TargetDecl->hasAttr<ConstAttr>()) { - FuncAttrs.addAttribute(llvm::Attribute::ReadNone); - FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); - } else if (TargetDecl->hasAttr<PureAttr>()) { - FuncAttrs.addAttribute(llvm::Attribute::ReadOnly); - FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); - } else if (TargetDecl->hasAttr<NoAliasAttr>()) { - FuncAttrs.addAttribute(llvm::Attribute::ArgMemOnly); - FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); - } - if (TargetDecl->hasAttr<RestrictAttr>()) - RetAttrs.addAttribute(llvm::Attribute::NoAlias); - if (TargetDecl->hasAttr<ReturnsNonNullAttr>() && - !CodeGenOpts.NullPointerIsValid) - RetAttrs.addAttribute(llvm::Attribute::NonNull); - if (TargetDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>()) - FuncAttrs.addAttribute("no_caller_saved_registers"); - if (TargetDecl->hasAttr<AnyX86NoCfCheckAttr>()) - FuncAttrs.addAttribute(llvm::Attribute::NoCfCheck); - - HasOptnone = TargetDecl->hasAttr<OptimizeNoneAttr>(); - if (auto *AllocSize = TargetDecl->getAttr<AllocSizeAttr>()) { - Optional<unsigned> NumElemsParam; - if (AllocSize->getNumElemsParam().isValid()) - NumElemsParam = AllocSize->getNumElemsParam().getLLVMIndex(); - FuncAttrs.addAllocSizeAttr(AllocSize->getElemSizeParam().getLLVMIndex(), - NumElemsParam); - } - } - - ConstructDefaultFnAttrList(Name, HasOptnone, AttrOnCallSite, FuncAttrs); - - if (CodeGenOpts.EnableSegmentedStacks && - !(TargetDecl && TargetDecl->hasAttr<NoSplitStackAttr>())) - FuncAttrs.addAttribute("split-stack"); - - // Add NonLazyBind attribute to function declarations when -fno-plt - // is used. - if (TargetDecl && CodeGenOpts.NoPLT) { - if (auto *Fn = dyn_cast<FunctionDecl>(TargetDecl)) { - if (!Fn->isDefined() && !AttrOnCallSite) { - FuncAttrs.addAttribute(llvm::Attribute::NonLazyBind); - } - } - } - - if (TargetDecl && TargetDecl->hasAttr<OpenCLKernelAttr>()) { - if (getLangOpts().OpenCLVersion <= 120) { - // OpenCL v1.2 Work groups are always uniform - FuncAttrs.addAttribute("uniform-work-group-size", "true"); - } else { - // OpenCL v2.0 Work groups may be whether uniform or not. - // '-cl-uniform-work-group-size' compile option gets a hint - // to the compiler that the global work-size be a multiple of - // the work-group size specified to clEnqueueNDRangeKernel - // (i.e. work groups are uniform). - FuncAttrs.addAttribute("uniform-work-group-size", - llvm::toStringRef(CodeGenOpts.UniformWGSize)); - } - } - - if (!AttrOnCallSite) { - bool DisableTailCalls = false; - - if (CodeGenOpts.DisableTailCalls) - DisableTailCalls = true; - else if (TargetDecl) { - if (TargetDecl->hasAttr<DisableTailCallsAttr>() || - TargetDecl->hasAttr<AnyX86InterruptAttr>()) - DisableTailCalls = true; - else if (CodeGenOpts.NoEscapingBlockTailCalls) { - if (const auto *BD = dyn_cast<BlockDecl>(TargetDecl)) - if (!BD->doesNotEscape()) - DisableTailCalls = true; - } - } - - FuncAttrs.addAttribute("disable-tail-calls", - llvm::toStringRef(DisableTailCalls)); - GetCPUAndFeaturesAttributes(CalleeInfo.getCalleeDecl(), FuncAttrs); - - if (CodeGenOpts.ReturnProtector) - FuncAttrs.addAttribute("ret-protector"); - } - - ClangToLLVMArgMapping IRFunctionArgs(getContext(), FI); - - QualType RetTy = FI.getReturnType(); - const ABIArgInfo &RetAI = FI.getReturnInfo(); - switch (RetAI.getKind()) { - case ABIArgInfo::Extend: - if (RetAI.isSignExt()) - RetAttrs.addAttribute(llvm::Attribute::SExt); - else - RetAttrs.addAttribute(llvm::Attribute::ZExt); - LLVM_FALLTHROUGH; - case ABIArgInfo::Direct: - if (RetAI.getInReg()) - RetAttrs.addAttribute(llvm::Attribute::InReg); - break; - case ABIArgInfo::Ignore: - break; - - case ABIArgInfo::InAlloca: - case ABIArgInfo::Indirect: { - // inalloca and sret disable readnone and readonly - FuncAttrs.removeAttribute(llvm::Attribute::ReadOnly) - .removeAttribute(llvm::Attribute::ReadNone); - break; - } - - case ABIArgInfo::CoerceAndExpand: - break; - - case ABIArgInfo::Expand: - llvm_unreachable("Invalid ABI kind for return argument"); - } - - if (const auto *RefTy = RetTy->getAs<ReferenceType>()) { - QualType PTy = RefTy->getPointeeType(); - if (!PTy->isIncompleteType() && PTy->isConstantSizeType()) - RetAttrs.addDereferenceableAttr(getContext().getTypeSizeInChars(PTy) - .getQuantity()); - else if (getContext().getTargetAddressSpace(PTy) == 0 && - !CodeGenOpts.NullPointerIsValid) - RetAttrs.addAttribute(llvm::Attribute::NonNull); - } - - bool hasUsedSRet = false; - SmallVector<llvm::AttributeSet, 4> ArgAttrs(IRFunctionArgs.totalIRArgs()); - - // Attach attributes to sret. - if (IRFunctionArgs.hasSRetArg()) { - llvm::AttrBuilder SRETAttrs; - if (!RetAI.getSuppressSRet()) - SRETAttrs.addAttribute(llvm::Attribute::StructRet); - hasUsedSRet = true; - if (RetAI.getInReg()) - SRETAttrs.addAttribute(llvm::Attribute::InReg); - ArgAttrs[IRFunctionArgs.getSRetArgNo()] = - llvm::AttributeSet::get(getLLVMContext(), SRETAttrs); - } - - // Attach attributes to inalloca argument. - if (IRFunctionArgs.hasInallocaArg()) { - llvm::AttrBuilder Attrs; - Attrs.addAttribute(llvm::Attribute::InAlloca); - ArgAttrs[IRFunctionArgs.getInallocaArgNo()] = - llvm::AttributeSet::get(getLLVMContext(), Attrs); - } - - unsigned ArgNo = 0; - for (CGFunctionInfo::const_arg_iterator I = FI.arg_begin(), - E = FI.arg_end(); - I != E; ++I, ++ArgNo) { - QualType ParamType = I->type; - const ABIArgInfo &AI = I->info; - llvm::AttrBuilder Attrs; - - // Add attribute for padding argument, if necessary. - if (IRFunctionArgs.hasPaddingArg(ArgNo)) { - if (AI.getPaddingInReg()) { - ArgAttrs[IRFunctionArgs.getPaddingArgNo(ArgNo)] = - llvm::AttributeSet::get( - getLLVMContext(), - llvm::AttrBuilder().addAttribute(llvm::Attribute::InReg)); - } - } - - // 'restrict' -> 'noalias' is done in EmitFunctionProlog when we - // have the corresponding parameter variable. It doesn't make - // sense to do it here because parameters are so messed up. - switch (AI.getKind()) { - case ABIArgInfo::Extend: - if (AI.isSignExt()) - Attrs.addAttribute(llvm::Attribute::SExt); - else - Attrs.addAttribute(llvm::Attribute::ZExt); - LLVM_FALLTHROUGH; - case ABIArgInfo::Direct: - if (ArgNo == 0 && FI.isChainCall()) - Attrs.addAttribute(llvm::Attribute::Nest); - else if (AI.getInReg()) - Attrs.addAttribute(llvm::Attribute::InReg); - break; - - case ABIArgInfo::Indirect: { - if (AI.getInReg()) - Attrs.addAttribute(llvm::Attribute::InReg); - - if (AI.getIndirectByVal()) - Attrs.addAttribute(llvm::Attribute::ByVal); - - CharUnits Align = AI.getIndirectAlign(); - - // In a byval argument, it is important that the required - // alignment of the type is honored, as LLVM might be creating a - // *new* stack object, and needs to know what alignment to give - // it. (Sometimes it can deduce a sensible alignment on its own, - // but not if clang decides it must emit a packed struct, or the - // user specifies increased alignment requirements.) - // - // This is different from indirect *not* byval, where the object - // exists already, and the align attribute is purely - // informative. - assert(!Align.isZero()); - - // For now, only add this when we have a byval argument. - // TODO: be less lazy about updating test cases. - if (AI.getIndirectByVal()) - Attrs.addAlignmentAttr(Align.getQuantity()); - - // byval disables readnone and readonly. - FuncAttrs.removeAttribute(llvm::Attribute::ReadOnly) - .removeAttribute(llvm::Attribute::ReadNone); - break; - } - case ABIArgInfo::Ignore: - case ABIArgInfo::Expand: - case ABIArgInfo::CoerceAndExpand: - break; - - case ABIArgInfo::InAlloca: - // inalloca disables readnone and readonly. - FuncAttrs.removeAttribute(llvm::Attribute::ReadOnly) - .removeAttribute(llvm::Attribute::ReadNone); - continue; - } - - if (const auto *RefTy = ParamType->getAs<ReferenceType>()) { - QualType PTy = RefTy->getPointeeType(); - if (!PTy->isIncompleteType() && PTy->isConstantSizeType()) - Attrs.addDereferenceableAttr(getContext().getTypeSizeInChars(PTy) - .getQuantity()); - else if (getContext().getTargetAddressSpace(PTy) == 0 && - !CodeGenOpts.NullPointerIsValid) - Attrs.addAttribute(llvm::Attribute::NonNull); - } - - switch (FI.getExtParameterInfo(ArgNo).getABI()) { - case ParameterABI::Ordinary: - break; - - case ParameterABI::SwiftIndirectResult: { - // Add 'sret' if we haven't already used it for something, but - // only if the result is void. - if (!hasUsedSRet && RetTy->isVoidType()) { - Attrs.addAttribute(llvm::Attribute::StructRet); - hasUsedSRet = true; - } - - // Add 'noalias' in either case. - Attrs.addAttribute(llvm::Attribute::NoAlias); - - // Add 'dereferenceable' and 'alignment'. - auto PTy = ParamType->getPointeeType(); - if (!PTy->isIncompleteType() && PTy->isConstantSizeType()) { - auto info = getContext().getTypeInfoInChars(PTy); - Attrs.addDereferenceableAttr(info.first.getQuantity()); - Attrs.addAttribute(llvm::Attribute::getWithAlignment(getLLVMContext(), - info.second.getQuantity())); - } - break; - } - - case ParameterABI::SwiftErrorResult: - Attrs.addAttribute(llvm::Attribute::SwiftError); - break; - - case ParameterABI::SwiftContext: - Attrs.addAttribute(llvm::Attribute::SwiftSelf); - break; - } - - if (FI.getExtParameterInfo(ArgNo).isNoEscape()) - Attrs.addAttribute(llvm::Attribute::NoCapture); - - if (Attrs.hasAttributes()) { - unsigned FirstIRArg, NumIRArgs; - std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo); - for (unsigned i = 0; i < NumIRArgs; i++) - ArgAttrs[FirstIRArg + i] = - llvm::AttributeSet::get(getLLVMContext(), Attrs); - } - } - assert(ArgNo == FI.arg_size()); - - AttrList = llvm::AttributeList::get( - getLLVMContext(), llvm::AttributeSet::get(getLLVMContext(), FuncAttrs), - llvm::AttributeSet::get(getLLVMContext(), RetAttrs), ArgAttrs); -} - -/// An argument came in as a promoted argument; demote it back to its -/// declared type. -static llvm::Value *emitArgumentDemotion(CodeGenFunction &CGF, - const VarDecl *var, - llvm::Value *value) { - llvm::Type *varType = CGF.ConvertType(var->getType()); - - // This can happen with promotions that actually don't change the - // underlying type, like the enum promotions. - if (value->getType() == varType) return value; - - assert((varType->isIntegerTy() || varType->isFloatingPointTy()) - && "unexpected promotion type"); - - if (isa<llvm::IntegerType>(varType)) - return CGF.Builder.CreateTrunc(value, varType, "arg.unpromote"); - - return CGF.Builder.CreateFPCast(value, varType, "arg.unpromote"); -} - -/// Returns the attribute (either parameter attribute, or function -/// attribute), which declares argument ArgNo to be non-null. -static const NonNullAttr *getNonNullAttr(const Decl *FD, const ParmVarDecl *PVD, - QualType ArgType, unsigned ArgNo) { - // FIXME: __attribute__((nonnull)) can also be applied to: - // - references to pointers, where the pointee is known to be - // nonnull (apparently a Clang extension) - // - transparent unions containing pointers - // In the former case, LLVM IR cannot represent the constraint. In - // the latter case, we have no guarantee that the transparent union - // is in fact passed as a pointer. - if (!ArgType->isAnyPointerType() && !ArgType->isBlockPointerType()) - return nullptr; - // First, check attribute on parameter itself. - if (PVD) { - if (auto ParmNNAttr = PVD->getAttr<NonNullAttr>()) - return ParmNNAttr; - } - // Check function attributes. - if (!FD) - return nullptr; - for (const auto *NNAttr : FD->specific_attrs<NonNullAttr>()) { - if (NNAttr->isNonNull(ArgNo)) - return NNAttr; - } - return nullptr; -} - -namespace { - struct CopyBackSwiftError final : EHScopeStack::Cleanup { - Address Temp; - Address Arg; - CopyBackSwiftError(Address temp, Address arg) : Temp(temp), Arg(arg) {} - void Emit(CodeGenFunction &CGF, Flags flags) override { - llvm::Value *errorValue = CGF.Builder.CreateLoad(Temp); - CGF.Builder.CreateStore(errorValue, Arg); - } - }; -} - -void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, - llvm::Function *Fn, - const FunctionArgList &Args) { - if (CurCodeDecl && CurCodeDecl->hasAttr<NakedAttr>()) - // Naked functions don't have prologues. - return; - - // If this is an implicit-return-zero function, go ahead and - // initialize the return value. TODO: it might be nice to have - // a more general mechanism for this that didn't require synthesized - // return statements. - if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurCodeDecl)) { - if (FD->hasImplicitReturnZero()) { - QualType RetTy = FD->getReturnType().getUnqualifiedType(); - llvm::Type* LLVMTy = CGM.getTypes().ConvertType(RetTy); - llvm::Constant* Zero = llvm::Constant::getNullValue(LLVMTy); - Builder.CreateStore(Zero, ReturnValue); - } - } - - // FIXME: We no longer need the types from FunctionArgList; lift up and - // simplify. - - ClangToLLVMArgMapping IRFunctionArgs(CGM.getContext(), FI); - // Flattened function arguments. - SmallVector<llvm::Value *, 16> FnArgs; - FnArgs.reserve(IRFunctionArgs.totalIRArgs()); - for (auto &Arg : Fn->args()) { - FnArgs.push_back(&Arg); - } - assert(FnArgs.size() == IRFunctionArgs.totalIRArgs()); - - // If we're using inalloca, all the memory arguments are GEPs off of the last - // parameter, which is a pointer to the complete memory area. - Address ArgStruct = Address::invalid(); - const llvm::StructLayout *ArgStructLayout = nullptr; - if (IRFunctionArgs.hasInallocaArg()) { - ArgStructLayout = CGM.getDataLayout().getStructLayout(FI.getArgStruct()); - ArgStruct = Address(FnArgs[IRFunctionArgs.getInallocaArgNo()], - FI.getArgStructAlignment()); - - assert(ArgStruct.getType() == FI.getArgStruct()->getPointerTo()); - } - - // Name the struct return parameter. - if (IRFunctionArgs.hasSRetArg()) { - auto AI = cast<llvm::Argument>(FnArgs[IRFunctionArgs.getSRetArgNo()]); - AI->setName("agg.result"); - AI->addAttr(llvm::Attribute::NoAlias); - } - - // Track if we received the parameter as a pointer (indirect, byval, or - // inalloca). If already have a pointer, EmitParmDecl doesn't need to copy it - // into a local alloca for us. - SmallVector<ParamValue, 16> ArgVals; - ArgVals.reserve(Args.size()); - - // Create a pointer value for every parameter declaration. This usually - // entails copying one or more LLVM IR arguments into an alloca. Don't push - // any cleanups or do anything that might unwind. We do that separately, so - // we can push the cleanups in the correct order for the ABI. - assert(FI.arg_size() == Args.size() && - "Mismatch between function signature & arguments."); - unsigned ArgNo = 0; - CGFunctionInfo::const_arg_iterator info_it = FI.arg_begin(); - for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); - i != e; ++i, ++info_it, ++ArgNo) { - const VarDecl *Arg = *i; - const ABIArgInfo &ArgI = info_it->info; - - bool isPromoted = - isa<ParmVarDecl>(Arg) && cast<ParmVarDecl>(Arg)->isKNRPromoted(); - // We are converting from ABIArgInfo type to VarDecl type directly, unless - // the parameter is promoted. In this case we convert to - // CGFunctionInfo::ArgInfo type with subsequent argument demotion. - QualType Ty = isPromoted ? info_it->type : Arg->getType(); - assert(hasScalarEvaluationKind(Ty) == - hasScalarEvaluationKind(Arg->getType())); - - unsigned FirstIRArg, NumIRArgs; - std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo); - - switch (ArgI.getKind()) { - case ABIArgInfo::InAlloca: { - assert(NumIRArgs == 0); - auto FieldIndex = ArgI.getInAllocaFieldIndex(); - CharUnits FieldOffset = - CharUnits::fromQuantity(ArgStructLayout->getElementOffset(FieldIndex)); - Address V = Builder.CreateStructGEP(ArgStruct, FieldIndex, FieldOffset, - Arg->getName()); - ArgVals.push_back(ParamValue::forIndirect(V)); - break; - } - - case ABIArgInfo::Indirect: { - assert(NumIRArgs == 1); - Address ParamAddr = Address(FnArgs[FirstIRArg], ArgI.getIndirectAlign()); - - if (!hasScalarEvaluationKind(Ty)) { - // Aggregates and complex variables are accessed by reference. All we - // need to do is realign the value, if requested. - Address V = ParamAddr; - if (ArgI.getIndirectRealign()) { - Address AlignedTemp = CreateMemTemp(Ty, "coerce"); - - // Copy from the incoming argument pointer to the temporary with the - // appropriate alignment. - // - // FIXME: We should have a common utility for generating an aggregate - // copy. - CharUnits Size = getContext().getTypeSizeInChars(Ty); - auto SizeVal = llvm::ConstantInt::get(IntPtrTy, Size.getQuantity()); - Address Dst = Builder.CreateBitCast(AlignedTemp, Int8PtrTy); - Address Src = Builder.CreateBitCast(ParamAddr, Int8PtrTy); - Builder.CreateMemCpy(Dst, Src, SizeVal, false); - V = AlignedTemp; - } - ArgVals.push_back(ParamValue::forIndirect(V)); - } else { - // Load scalar value from indirect argument. - llvm::Value *V = - EmitLoadOfScalar(ParamAddr, false, Ty, Arg->getBeginLoc()); - - if (isPromoted) - V = emitArgumentDemotion(*this, Arg, V); - ArgVals.push_back(ParamValue::forDirect(V)); - } - break; - } - - case ABIArgInfo::Extend: - case ABIArgInfo::Direct: { - - // If we have the trivial case, handle it with no muss and fuss. - if (!isa<llvm::StructType>(ArgI.getCoerceToType()) && - ArgI.getCoerceToType() == ConvertType(Ty) && - ArgI.getDirectOffset() == 0) { - assert(NumIRArgs == 1); - llvm::Value *V = FnArgs[FirstIRArg]; - auto AI = cast<llvm::Argument>(V); - - if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(Arg)) { - if (getNonNullAttr(CurCodeDecl, PVD, PVD->getType(), - PVD->getFunctionScopeIndex()) && - !CGM.getCodeGenOpts().NullPointerIsValid) - AI->addAttr(llvm::Attribute::NonNull); - - QualType OTy = PVD->getOriginalType(); - if (const auto *ArrTy = - getContext().getAsConstantArrayType(OTy)) { - // A C99 array parameter declaration with the static keyword also - // indicates dereferenceability, and if the size is constant we can - // use the dereferenceable attribute (which requires the size in - // bytes). - if (ArrTy->getSizeModifier() == ArrayType::Static) { - QualType ETy = ArrTy->getElementType(); - uint64_t ArrSize = ArrTy->getSize().getZExtValue(); - if (!ETy->isIncompleteType() && ETy->isConstantSizeType() && - ArrSize) { - llvm::AttrBuilder Attrs; - Attrs.addDereferenceableAttr( - getContext().getTypeSizeInChars(ETy).getQuantity()*ArrSize); - AI->addAttrs(Attrs); - } else if (getContext().getTargetAddressSpace(ETy) == 0 && - !CGM.getCodeGenOpts().NullPointerIsValid) { - AI->addAttr(llvm::Attribute::NonNull); - } - } - } else if (const auto *ArrTy = - getContext().getAsVariableArrayType(OTy)) { - // For C99 VLAs with the static keyword, we don't know the size so - // we can't use the dereferenceable attribute, but in addrspace(0) - // we know that it must be nonnull. - if (ArrTy->getSizeModifier() == VariableArrayType::Static && - !getContext().getTargetAddressSpace(ArrTy->getElementType()) && - !CGM.getCodeGenOpts().NullPointerIsValid) - AI->addAttr(llvm::Attribute::NonNull); - } - - const auto *AVAttr = PVD->getAttr<AlignValueAttr>(); - if (!AVAttr) - if (const auto *TOTy = dyn_cast<TypedefType>(OTy)) - AVAttr = TOTy->getDecl()->getAttr<AlignValueAttr>(); - if (AVAttr && !SanOpts.has(SanitizerKind::Alignment)) { - // If alignment-assumption sanitizer is enabled, we do *not* add - // alignment attribute here, but emit normal alignment assumption, - // so the UBSAN check could function. - llvm::Value *AlignmentValue = - EmitScalarExpr(AVAttr->getAlignment()); - llvm::ConstantInt *AlignmentCI = - cast<llvm::ConstantInt>(AlignmentValue); - unsigned Alignment = std::min((unsigned)AlignmentCI->getZExtValue(), - +llvm::Value::MaximumAlignment); - AI->addAttrs(llvm::AttrBuilder().addAlignmentAttr(Alignment)); - } - } - - if (Arg->getType().isRestrictQualified()) - AI->addAttr(llvm::Attribute::NoAlias); - - // LLVM expects swifterror parameters to be used in very restricted - // ways. Copy the value into a less-restricted temporary. - if (FI.getExtParameterInfo(ArgNo).getABI() - == ParameterABI::SwiftErrorResult) { - QualType pointeeTy = Ty->getPointeeType(); - assert(pointeeTy->isPointerType()); - Address temp = - CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); - Address arg = Address(V, getContext().getTypeAlignInChars(pointeeTy)); - llvm::Value *incomingErrorValue = Builder.CreateLoad(arg); - Builder.CreateStore(incomingErrorValue, temp); - V = temp.getPointer(); - - // Push a cleanup to copy the value back at the end of the function. - // The convention does not guarantee that the value will be written - // back if the function exits with an unwind exception. - EHStack.pushCleanup<CopyBackSwiftError>(NormalCleanup, temp, arg); - } - - // Ensure the argument is the correct type. - if (V->getType() != ArgI.getCoerceToType()) - V = Builder.CreateBitCast(V, ArgI.getCoerceToType()); - - if (isPromoted) - V = emitArgumentDemotion(*this, Arg, V); - - // Because of merging of function types from multiple decls it is - // possible for the type of an argument to not match the corresponding - // type in the function type. Since we are codegening the callee - // in here, add a cast to the argument type. - llvm::Type *LTy = ConvertType(Arg->getType()); - if (V->getType() != LTy) - V = Builder.CreateBitCast(V, LTy); - - ArgVals.push_back(ParamValue::forDirect(V)); - break; - } - - Address Alloca = CreateMemTemp(Ty, getContext().getDeclAlign(Arg), - Arg->getName()); - - // Pointer to store into. - Address Ptr = emitAddressAtOffset(*this, Alloca, ArgI); - - // Fast-isel and the optimizer generally like scalar values better than - // FCAs, so we flatten them if this is safe to do for this argument. - llvm::StructType *STy = dyn_cast<llvm::StructType>(ArgI.getCoerceToType()); - if (ArgI.isDirect() && ArgI.getCanBeFlattened() && STy && - STy->getNumElements() > 1) { - auto SrcLayout = CGM.getDataLayout().getStructLayout(STy); - uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(STy); - llvm::Type *DstTy = Ptr.getElementType(); - uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(DstTy); - - Address AddrToStoreInto = Address::invalid(); - if (SrcSize <= DstSize) { - AddrToStoreInto = Builder.CreateElementBitCast(Ptr, STy); - } else { - AddrToStoreInto = - CreateTempAlloca(STy, Alloca.getAlignment(), "coerce"); - } - - assert(STy->getNumElements() == NumIRArgs); - for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { - auto AI = FnArgs[FirstIRArg + i]; - AI->setName(Arg->getName() + ".coerce" + Twine(i)); - auto Offset = CharUnits::fromQuantity(SrcLayout->getElementOffset(i)); - Address EltPtr = - Builder.CreateStructGEP(AddrToStoreInto, i, Offset); - Builder.CreateStore(AI, EltPtr); - } - - if (SrcSize > DstSize) { - Builder.CreateMemCpy(Ptr, AddrToStoreInto, DstSize); - } - - } else { - // Simple case, just do a coerced store of the argument into the alloca. - assert(NumIRArgs == 1); - auto AI = FnArgs[FirstIRArg]; - AI->setName(Arg->getName() + ".coerce"); - CreateCoercedStore(AI, Ptr, /*DestIsVolatile=*/false, *this); - } - - // Match to what EmitParmDecl is expecting for this type. - if (CodeGenFunction::hasScalarEvaluationKind(Ty)) { - llvm::Value *V = - EmitLoadOfScalar(Alloca, false, Ty, Arg->getBeginLoc()); - if (isPromoted) - V = emitArgumentDemotion(*this, Arg, V); - ArgVals.push_back(ParamValue::forDirect(V)); - } else { - ArgVals.push_back(ParamValue::forIndirect(Alloca)); - } - break; - } - - case ABIArgInfo::CoerceAndExpand: { - // Reconstruct into a temporary. - Address alloca = CreateMemTemp(Ty, getContext().getDeclAlign(Arg)); - ArgVals.push_back(ParamValue::forIndirect(alloca)); - - auto coercionType = ArgI.getCoerceAndExpandType(); - alloca = Builder.CreateElementBitCast(alloca, coercionType); - auto layout = CGM.getDataLayout().getStructLayout(coercionType); - - unsigned argIndex = FirstIRArg; - for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { - llvm::Type *eltType = coercionType->getElementType(i); - if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) - continue; - - auto eltAddr = Builder.CreateStructGEP(alloca, i, layout); - auto elt = FnArgs[argIndex++]; - Builder.CreateStore(elt, eltAddr); - } - assert(argIndex == FirstIRArg + NumIRArgs); - break; - } - - case ABIArgInfo::Expand: { - // If this structure was expanded into multiple arguments then - // we need to create a temporary and reconstruct it from the - // arguments. - Address Alloca = CreateMemTemp(Ty, getContext().getDeclAlign(Arg)); - LValue LV = MakeAddrLValue(Alloca, Ty); - ArgVals.push_back(ParamValue::forIndirect(Alloca)); - - auto FnArgIter = FnArgs.begin() + FirstIRArg; - ExpandTypeFromArgs(Ty, LV, FnArgIter); - assert(FnArgIter == FnArgs.begin() + FirstIRArg + NumIRArgs); - for (unsigned i = 0, e = NumIRArgs; i != e; ++i) { - auto AI = FnArgs[FirstIRArg + i]; - AI->setName(Arg->getName() + "." + Twine(i)); - } - break; - } - - case ABIArgInfo::Ignore: - assert(NumIRArgs == 0); - // Initialize the local variable appropriately. - if (!hasScalarEvaluationKind(Ty)) { - ArgVals.push_back(ParamValue::forIndirect(CreateMemTemp(Ty))); - } else { - llvm::Value *U = llvm::UndefValue::get(ConvertType(Arg->getType())); - ArgVals.push_back(ParamValue::forDirect(U)); - } - break; - } - } - - if (getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) { - for (int I = Args.size() - 1; I >= 0; --I) - EmitParmDecl(*Args[I], ArgVals[I], I + 1); - } else { - for (unsigned I = 0, E = Args.size(); I != E; ++I) - EmitParmDecl(*Args[I], ArgVals[I], I + 1); - } -} - -static void eraseUnusedBitCasts(llvm::Instruction *insn) { - while (insn->use_empty()) { - llvm::BitCastInst *bitcast = dyn_cast<llvm::BitCastInst>(insn); - if (!bitcast) return; - - // This is "safe" because we would have used a ConstantExpr otherwise. - insn = cast<llvm::Instruction>(bitcast->getOperand(0)); - bitcast->eraseFromParent(); - } -} - -/// Try to emit a fused autorelease of a return result. -static llvm::Value *tryEmitFusedAutoreleaseOfResult(CodeGenFunction &CGF, - llvm::Value *result) { - // We must be immediately followed the cast. - llvm::BasicBlock *BB = CGF.Builder.GetInsertBlock(); - if (BB->empty()) return nullptr; - if (&BB->back() != result) return nullptr; - - llvm::Type *resultType = result->getType(); - - // result is in a BasicBlock and is therefore an Instruction. - llvm::Instruction *generator = cast<llvm::Instruction>(result); - - SmallVector<llvm::Instruction *, 4> InstsToKill; - - // Look for: - // %generator = bitcast %type1* %generator2 to %type2* - while (llvm::BitCastInst *bitcast = dyn_cast<llvm::BitCastInst>(generator)) { - // We would have emitted this as a constant if the operand weren't - // an Instruction. - generator = cast<llvm::Instruction>(bitcast->getOperand(0)); - - // Require the generator to be immediately followed by the cast. - if (generator->getNextNode() != bitcast) - return nullptr; - - InstsToKill.push_back(bitcast); - } - - // Look for: - // %generator = call i8* @objc_retain(i8* %originalResult) - // or - // %generator = call i8* @objc_retainAutoreleasedReturnValue(i8* %originalResult) - llvm::CallInst *call = dyn_cast<llvm::CallInst>(generator); - if (!call) return nullptr; - - bool doRetainAutorelease; - - if (call->getCalledValue() == CGF.CGM.getObjCEntrypoints().objc_retain) { - doRetainAutorelease = true; - } else if (call->getCalledValue() == CGF.CGM.getObjCEntrypoints() - .objc_retainAutoreleasedReturnValue) { - doRetainAutorelease = false; - - // If we emitted an assembly marker for this call (and the - // ARCEntrypoints field should have been set if so), go looking - // for that call. If we can't find it, we can't do this - // optimization. But it should always be the immediately previous - // instruction, unless we needed bitcasts around the call. - if (CGF.CGM.getObjCEntrypoints().retainAutoreleasedReturnValueMarker) { - llvm::Instruction *prev = call->getPrevNode(); - assert(prev); - if (isa<llvm::BitCastInst>(prev)) { - prev = prev->getPrevNode(); - assert(prev); - } - assert(isa<llvm::CallInst>(prev)); - assert(cast<llvm::CallInst>(prev)->getCalledValue() == - CGF.CGM.getObjCEntrypoints().retainAutoreleasedReturnValueMarker); - InstsToKill.push_back(prev); - } - } else { - return nullptr; - } - - result = call->getArgOperand(0); - InstsToKill.push_back(call); - - // Keep killing bitcasts, for sanity. Note that we no longer care - // about precise ordering as long as there's exactly one use. - while (llvm::BitCastInst *bitcast = dyn_cast<llvm::BitCastInst>(result)) { - if (!bitcast->hasOneUse()) break; - InstsToKill.push_back(bitcast); - result = bitcast->getOperand(0); - } - - // Delete all the unnecessary instructions, from latest to earliest. - for (auto *I : InstsToKill) - I->eraseFromParent(); - - // Do the fused retain/autorelease if we were asked to. - if (doRetainAutorelease) - result = CGF.EmitARCRetainAutoreleaseReturnValue(result); - - // Cast back to the result type. - return CGF.Builder.CreateBitCast(result, resultType); -} - -/// If this is a +1 of the value of an immutable 'self', remove it. -static llvm::Value *tryRemoveRetainOfSelf(CodeGenFunction &CGF, - llvm::Value *result) { - // This is only applicable to a method with an immutable 'self'. - const ObjCMethodDecl *method = - dyn_cast_or_null<ObjCMethodDecl>(CGF.CurCodeDecl); - if (!method) return nullptr; - const VarDecl *self = method->getSelfDecl(); - if (!self->getType().isConstQualified()) return nullptr; - - // Look for a retain call. - llvm::CallInst *retainCall = - dyn_cast<llvm::CallInst>(result->stripPointerCasts()); - if (!retainCall || - retainCall->getCalledValue() != CGF.CGM.getObjCEntrypoints().objc_retain) - return nullptr; - - // Look for an ordinary load of 'self'. - llvm::Value *retainedValue = retainCall->getArgOperand(0); - llvm::LoadInst *load = - dyn_cast<llvm::LoadInst>(retainedValue->stripPointerCasts()); - if (!load || load->isAtomic() || load->isVolatile() || - load->getPointerOperand() != CGF.GetAddrOfLocalVar(self).getPointer()) - return nullptr; - - // Okay! Burn it all down. This relies for correctness on the - // assumption that the retain is emitted as part of the return and - // that thereafter everything is used "linearly". - llvm::Type *resultType = result->getType(); - eraseUnusedBitCasts(cast<llvm::Instruction>(result)); - assert(retainCall->use_empty()); - retainCall->eraseFromParent(); - eraseUnusedBitCasts(cast<llvm::Instruction>(retainedValue)); - - return CGF.Builder.CreateBitCast(load, resultType); -} - -/// Emit an ARC autorelease of the result of a function. -/// -/// \return the value to actually return from the function -static llvm::Value *emitAutoreleaseOfResult(CodeGenFunction &CGF, - llvm::Value *result) { - // If we're returning 'self', kill the initial retain. This is a - // heuristic attempt to "encourage correctness" in the really unfortunate - // case where we have a return of self during a dealloc and we desperately - // need to avoid the possible autorelease. - if (llvm::Value *self = tryRemoveRetainOfSelf(CGF, result)) - return self; - - // At -O0, try to emit a fused retain/autorelease. - if (CGF.shouldUseFusedARCCalls()) - if (llvm::Value *fused = tryEmitFusedAutoreleaseOfResult(CGF, result)) - return fused; - - return CGF.EmitARCAutoreleaseReturnValue(result); -} - -/// Heuristically search for a dominating store to the return-value slot. -static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { - // Check if a User is a store which pointerOperand is the ReturnValue. - // We are looking for stores to the ReturnValue, not for stores of the - // ReturnValue to some other location. - auto GetStoreIfValid = [&CGF](llvm::User *U) -> llvm::StoreInst * { - auto *SI = dyn_cast<llvm::StoreInst>(U); - if (!SI || SI->getPointerOperand() != CGF.ReturnValue.getPointer()) - return nullptr; - // These aren't actually possible for non-coerced returns, and we - // only care about non-coerced returns on this code path. - assert(!SI->isAtomic() && !SI->isVolatile()); - return SI; - }; - // If there are multiple uses of the return-value slot, just check - // for something immediately preceding the IP. Sometimes this can - // happen with how we generate implicit-returns; it can also happen - // with noreturn cleanups. - if (!CGF.ReturnValue.getPointer()->hasOneUse()) { - llvm::BasicBlock *IP = CGF.Builder.GetInsertBlock(); - if (IP->empty()) return nullptr; - llvm::Instruction *I = &IP->back(); - - // Skip lifetime markers - for (llvm::BasicBlock::reverse_iterator II = IP->rbegin(), - IE = IP->rend(); - II != IE; ++II) { - if (llvm::IntrinsicInst *Intrinsic = - dyn_cast<llvm::IntrinsicInst>(&*II)) { - if (Intrinsic->getIntrinsicID() == llvm::Intrinsic::lifetime_end) { - const llvm::Value *CastAddr = Intrinsic->getArgOperand(1); - ++II; - if (II == IE) - break; - if (isa<llvm::BitCastInst>(&*II) && (CastAddr == &*II)) - continue; - } - } - I = &*II; - break; - } - - return GetStoreIfValid(I); - } - - llvm::StoreInst *store = - GetStoreIfValid(CGF.ReturnValue.getPointer()->user_back()); - if (!store) return nullptr; - - // Now do a first-and-dirty dominance check: just walk up the - // single-predecessors chain from the current insertion point. - llvm::BasicBlock *StoreBB = store->getParent(); - llvm::BasicBlock *IP = CGF.Builder.GetInsertBlock(); - while (IP != StoreBB) { - if (!(IP = IP->getSinglePredecessor())) - return nullptr; - } - - // Okay, the store's basic block dominates the insertion point; we - // can do our thing. - return store; -} - -void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, - bool EmitRetDbgLoc, - SourceLocation EndLoc) { - if (FI.isNoReturn()) { - // Noreturn functions don't return. - EmitUnreachable(EndLoc); - return; - } - - if (CurCodeDecl && CurCodeDecl->hasAttr<NakedAttr>()) { - // Naked functions don't have epilogues. - Builder.CreateUnreachable(); - return; - } - - // Functions with no result always return void. - if (!ReturnValue.isValid()) { - Builder.CreateRetVoid(); - return; - } - - llvm::DebugLoc RetDbgLoc; - llvm::Value *RV = nullptr; - QualType RetTy = FI.getReturnType(); - const ABIArgInfo &RetAI = FI.getReturnInfo(); - - switch (RetAI.getKind()) { - case ABIArgInfo::InAlloca: - // Aggregrates get evaluated directly into the destination. Sometimes we - // need to return the sret value in a register, though. - assert(hasAggregateEvaluationKind(RetTy)); - if (RetAI.getInAllocaSRet()) { - llvm::Function::arg_iterator EI = CurFn->arg_end(); - --EI; - llvm::Value *ArgStruct = &*EI; - llvm::Value *SRet = Builder.CreateStructGEP( - nullptr, ArgStruct, RetAI.getInAllocaFieldIndex()); - RV = Builder.CreateAlignedLoad(SRet, getPointerAlign(), "sret"); - } - break; - - case ABIArgInfo::Indirect: { - auto AI = CurFn->arg_begin(); - if (RetAI.isSRetAfterThis()) - ++AI; - switch (getEvaluationKind(RetTy)) { - case TEK_Complex: { - ComplexPairTy RT = - EmitLoadOfComplex(MakeAddrLValue(ReturnValue, RetTy), EndLoc); - EmitStoreOfComplex(RT, MakeNaturalAlignAddrLValue(&*AI, RetTy), - /*isInit*/ true); - break; - } - case TEK_Aggregate: - // Do nothing; aggregrates get evaluated directly into the destination. - break; - case TEK_Scalar: - EmitStoreOfScalar(Builder.CreateLoad(ReturnValue), - MakeNaturalAlignAddrLValue(&*AI, RetTy), - /*isInit*/ true); - break; - } - break; - } - - case ABIArgInfo::Extend: - case ABIArgInfo::Direct: - if (RetAI.getCoerceToType() == ConvertType(RetTy) && - RetAI.getDirectOffset() == 0) { - // The internal return value temp always will have pointer-to-return-type - // type, just do a load. - - // If there is a dominating store to ReturnValue, we can elide - // the load, zap the store, and usually zap the alloca. - if (llvm::StoreInst *SI = - findDominatingStoreToReturnValue(*this)) { - // Reuse the debug location from the store unless there is - // cleanup code to be emitted between the store and return - // instruction. - if (EmitRetDbgLoc && !AutoreleaseResult) - RetDbgLoc = SI->getDebugLoc(); - // Get the stored value and nuke the now-dead store. - RV = SI->getValueOperand(); - SI->eraseFromParent(); - - // If that was the only use of the return value, nuke it as well now. - auto returnValueInst = ReturnValue.getPointer(); - if (returnValueInst->use_empty()) { - if (auto alloca = dyn_cast<llvm::AllocaInst>(returnValueInst)) { - alloca->eraseFromParent(); - ReturnValue = Address::invalid(); - } - } - - // Otherwise, we have to do a simple load. - } else { - RV = Builder.CreateLoad(ReturnValue); - } - } else { - // If the value is offset in memory, apply the offset now. - Address V = emitAddressAtOffset(*this, ReturnValue, RetAI); - - RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), *this); - } - - // In ARC, end functions that return a retainable type with a call - // to objc_autoreleaseReturnValue. - if (AutoreleaseResult) { -#ifndef NDEBUG - // Type::isObjCRetainabletype has to be called on a QualType that hasn't - // been stripped of the typedefs, so we cannot use RetTy here. Get the - // original return type of FunctionDecl, CurCodeDecl, and BlockDecl from - // CurCodeDecl or BlockInfo. - QualType RT; - - if (auto *FD = dyn_cast<FunctionDecl>(CurCodeDecl)) - RT = FD->getReturnType(); - else if (auto *MD = dyn_cast<ObjCMethodDecl>(CurCodeDecl)) - RT = MD->getReturnType(); - else if (isa<BlockDecl>(CurCodeDecl)) - RT = BlockInfo->BlockExpression->getFunctionType()->getReturnType(); - else - llvm_unreachable("Unexpected function/method type"); - - assert(getLangOpts().ObjCAutoRefCount && - !FI.isReturnsRetained() && - RT->isObjCRetainableType()); -#endif - RV = emitAutoreleaseOfResult(*this, RV); - } - - break; - - case ABIArgInfo::Ignore: - break; - - case ABIArgInfo::CoerceAndExpand: { - auto coercionType = RetAI.getCoerceAndExpandType(); - auto layout = CGM.getDataLayout().getStructLayout(coercionType); - - // Load all of the coerced elements out into results. - llvm::SmallVector<llvm::Value*, 4> results; - Address addr = Builder.CreateElementBitCast(ReturnValue, coercionType); - for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { - auto coercedEltType = coercionType->getElementType(i); - if (ABIArgInfo::isPaddingForCoerceAndExpand(coercedEltType)) - continue; - - auto eltAddr = Builder.CreateStructGEP(addr, i, layout); - auto elt = Builder.CreateLoad(eltAddr); - results.push_back(elt); - } - - // If we have one result, it's the single direct result type. - if (results.size() == 1) { - RV = results[0]; - - // Otherwise, we need to make a first-class aggregate. - } else { - // Construct a return type that lacks padding elements. - llvm::Type *returnType = RetAI.getUnpaddedCoerceAndExpandType(); - - RV = llvm::UndefValue::get(returnType); - for (unsigned i = 0, e = results.size(); i != e; ++i) { - RV = Builder.CreateInsertValue(RV, results[i], i); - } - } - break; - } - - case ABIArgInfo::Expand: - llvm_unreachable("Invalid ABI kind for return argument"); - } - - llvm::Instruction *Ret; - if (RV) { - EmitReturnValueCheck(RV); - Ret = Builder.CreateRet(RV); - } else { - Ret = Builder.CreateRetVoid(); - } - - if (RetDbgLoc) - Ret->setDebugLoc(std::move(RetDbgLoc)); -} - -void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV) { - // A current decl may not be available when emitting vtable thunks. - if (!CurCodeDecl) - return; - - ReturnsNonNullAttr *RetNNAttr = nullptr; - if (SanOpts.has(SanitizerKind::ReturnsNonnullAttribute)) - RetNNAttr = CurCodeDecl->getAttr<ReturnsNonNullAttr>(); - - if (!RetNNAttr && !requiresReturnValueNullabilityCheck()) - return; - - // Prefer the returns_nonnull attribute if it's present. - SourceLocation AttrLoc; - SanitizerMask CheckKind; - SanitizerHandler Handler; - if (RetNNAttr) { - assert(!requiresReturnValueNullabilityCheck() && - "Cannot check nullability and the nonnull attribute"); - AttrLoc = RetNNAttr->getLocation(); - CheckKind = SanitizerKind::ReturnsNonnullAttribute; - Handler = SanitizerHandler::NonnullReturn; - } else { - if (auto *DD = dyn_cast<DeclaratorDecl>(CurCodeDecl)) - if (auto *TSI = DD->getTypeSourceInfo()) - if (auto FTL = TSI->getTypeLoc().castAs<FunctionTypeLoc>()) - AttrLoc = FTL.getReturnLoc().findNullabilityLoc(); - CheckKind = SanitizerKind::NullabilityReturn; - Handler = SanitizerHandler::NullabilityReturn; - } - - SanitizerScope SanScope(this); - - // Make sure the "return" source location is valid. If we're checking a - // nullability annotation, make sure the preconditions for the check are met. - llvm::BasicBlock *Check = createBasicBlock("nullcheck"); - llvm::BasicBlock *NoCheck = createBasicBlock("no.nullcheck"); - llvm::Value *SLocPtr = Builder.CreateLoad(ReturnLocation, "return.sloc.load"); - llvm::Value *CanNullCheck = Builder.CreateIsNotNull(SLocPtr); - if (requiresReturnValueNullabilityCheck()) - CanNullCheck = - Builder.CreateAnd(CanNullCheck, RetValNullabilityPrecondition); - Builder.CreateCondBr(CanNullCheck, Check, NoCheck); - EmitBlock(Check); - - // Now do the null check. - llvm::Value *Cond = Builder.CreateIsNotNull(RV); - llvm::Constant *StaticData[] = {EmitCheckSourceLocation(AttrLoc)}; - llvm::Value *DynamicData[] = {SLocPtr}; - EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, DynamicData); - - EmitBlock(NoCheck); - -#ifndef NDEBUG - // The return location should not be used after the check has been emitted. - ReturnLocation = Address::invalid(); -#endif -} - -static bool isInAllocaArgument(CGCXXABI &ABI, QualType type) { - const CXXRecordDecl *RD = type->getAsCXXRecordDecl(); - return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory; -} - -static AggValueSlot createPlaceholderSlot(CodeGenFunction &CGF, - QualType Ty) { - // FIXME: Generate IR in one pass, rather than going back and fixing up these - // placeholders. - llvm::Type *IRTy = CGF.ConvertTypeForMem(Ty); - llvm::Type *IRPtrTy = IRTy->getPointerTo(); - llvm::Value *Placeholder = llvm::UndefValue::get(IRPtrTy->getPointerTo()); - - // FIXME: When we generate this IR in one pass, we shouldn't need - // this win32-specific alignment hack. - CharUnits Align = CharUnits::fromQuantity(4); - Placeholder = CGF.Builder.CreateAlignedLoad(IRPtrTy, Placeholder, Align); - - return AggValueSlot::forAddr(Address(Placeholder, Align), - Ty.getQualifiers(), - AggValueSlot::IsNotDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - AggValueSlot::DoesNotOverlap); -} - -void CodeGenFunction::EmitDelegateCallArg(CallArgList &args, - const VarDecl *param, - SourceLocation loc) { - // StartFunction converted the ABI-lowered parameter(s) into a - // local alloca. We need to turn that into an r-value suitable - // for EmitCall. - Address local = GetAddrOfLocalVar(param); - - QualType type = param->getType(); - - if (isInAllocaArgument(CGM.getCXXABI(), type)) { - CGM.ErrorUnsupported(param, "forwarded non-trivially copyable parameter"); - } - - // GetAddrOfLocalVar returns a pointer-to-pointer for references, - // but the argument needs to be the original pointer. - if (type->isReferenceType()) { - args.add(RValue::get(Builder.CreateLoad(local)), type); - - // In ARC, move out of consumed arguments so that the release cleanup - // entered by StartFunction doesn't cause an over-release. This isn't - // optimal -O0 code generation, but it should get cleaned up when - // optimization is enabled. This also assumes that delegate calls are - // performed exactly once for a set of arguments, but that should be safe. - } else if (getLangOpts().ObjCAutoRefCount && - param->hasAttr<NSConsumedAttr>() && - type->isObjCRetainableType()) { - llvm::Value *ptr = Builder.CreateLoad(local); - auto null = - llvm::ConstantPointerNull::get(cast<llvm::PointerType>(ptr->getType())); - Builder.CreateStore(null, local); - args.add(RValue::get(ptr), type); - - // For the most part, we just need to load the alloca, except that - // aggregate r-values are actually pointers to temporaries. - } else { - args.add(convertTempToRValue(local, type, loc), type); - } - - // Deactivate the cleanup for the callee-destructed param that was pushed. - if (hasAggregateEvaluationKind(type) && !CurFuncIsThunk && - type->getAs<RecordType>()->getDecl()->isParamDestroyedInCallee() && - type.isDestructedType()) { - EHScopeStack::stable_iterator cleanup = - CalleeDestructedParamCleanups.lookup(cast<ParmVarDecl>(param)); - assert(cleanup.isValid() && - "cleanup for callee-destructed param not recorded"); - // This unreachable is a temporary marker which will be removed later. - llvm::Instruction *isActive = Builder.CreateUnreachable(); - args.addArgCleanupDeactivation(cleanup, isActive); - } -} - -static bool isProvablyNull(llvm::Value *addr) { - return isa<llvm::ConstantPointerNull>(addr); -} - -/// Emit the actual writing-back of a writeback. -static void emitWriteback(CodeGenFunction &CGF, - const CallArgList::Writeback &writeback) { - const LValue &srcLV = writeback.Source; - Address srcAddr = srcLV.getAddress(); - assert(!isProvablyNull(srcAddr.getPointer()) && - "shouldn't have writeback for provably null argument"); - - llvm::BasicBlock *contBB = nullptr; - - // If the argument wasn't provably non-null, we need to null check - // before doing the store. - bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(), - CGF.CGM.getDataLayout()); - if (!provablyNonNull) { - llvm::BasicBlock *writebackBB = CGF.createBasicBlock("icr.writeback"); - contBB = CGF.createBasicBlock("icr.done"); - - llvm::Value *isNull = - CGF.Builder.CreateIsNull(srcAddr.getPointer(), "icr.isnull"); - CGF.Builder.CreateCondBr(isNull, contBB, writebackBB); - CGF.EmitBlock(writebackBB); - } - - // Load the value to writeback. - llvm::Value *value = CGF.Builder.CreateLoad(writeback.Temporary); - - // Cast it back, in case we're writing an id to a Foo* or something. - value = CGF.Builder.CreateBitCast(value, srcAddr.getElementType(), - "icr.writeback-cast"); - - // Perform the writeback. - - // If we have a "to use" value, it's something we need to emit a use - // of. This has to be carefully threaded in: if it's done after the - // release it's potentially undefined behavior (and the optimizer - // will ignore it), and if it happens before the retain then the - // optimizer could move the release there. - if (writeback.ToUse) { - assert(srcLV.getObjCLifetime() == Qualifiers::OCL_Strong); - - // Retain the new value. No need to block-copy here: the block's - // being passed up the stack. - value = CGF.EmitARCRetainNonBlock(value); - - // Emit the intrinsic use here. - CGF.EmitARCIntrinsicUse(writeback.ToUse); - - // Load the old value (primitively). - llvm::Value *oldValue = CGF.EmitLoadOfScalar(srcLV, SourceLocation()); - - // Put the new value in place (primitively). - CGF.EmitStoreOfScalar(value, srcLV, /*init*/ false); - - // Release the old value. - CGF.EmitARCRelease(oldValue, srcLV.isARCPreciseLifetime()); - - // Otherwise, we can just do a normal lvalue store. - } else { - CGF.EmitStoreThroughLValue(RValue::get(value), srcLV); - } - - // Jump to the continuation block. - if (!provablyNonNull) - CGF.EmitBlock(contBB); -} - -static void emitWritebacks(CodeGenFunction &CGF, - const CallArgList &args) { - for (const auto &I : args.writebacks()) - emitWriteback(CGF, I); -} - -static void deactivateArgCleanupsBeforeCall(CodeGenFunction &CGF, - const CallArgList &CallArgs) { - ArrayRef<CallArgList::CallArgCleanup> Cleanups = - CallArgs.getCleanupsToDeactivate(); - // Iterate in reverse to increase the likelihood of popping the cleanup. - for (const auto &I : llvm::reverse(Cleanups)) { - CGF.DeactivateCleanupBlock(I.Cleanup, I.IsActiveIP); - I.IsActiveIP->eraseFromParent(); - } -} - -static const Expr *maybeGetUnaryAddrOfOperand(const Expr *E) { - if (const UnaryOperator *uop = dyn_cast<UnaryOperator>(E->IgnoreParens())) - if (uop->getOpcode() == UO_AddrOf) - return uop->getSubExpr(); - return nullptr; -} - -/// Emit an argument that's being passed call-by-writeback. That is, -/// we are passing the address of an __autoreleased temporary; it -/// might be copy-initialized with the current value of the given -/// address, but it will definitely be copied out of after the call. -static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args, - const ObjCIndirectCopyRestoreExpr *CRE) { - LValue srcLV; - - // Make an optimistic effort to emit the address as an l-value. - // This can fail if the argument expression is more complicated. - if (const Expr *lvExpr = maybeGetUnaryAddrOfOperand(CRE->getSubExpr())) { - srcLV = CGF.EmitLValue(lvExpr); - - // Otherwise, just emit it as a scalar. - } else { - Address srcAddr = CGF.EmitPointerWithAlignment(CRE->getSubExpr()); - - QualType srcAddrType = - CRE->getSubExpr()->getType()->castAs<PointerType>()->getPointeeType(); - srcLV = CGF.MakeAddrLValue(srcAddr, srcAddrType); - } - Address srcAddr = srcLV.getAddress(); - - // The dest and src types don't necessarily match in LLVM terms - // because of the crazy ObjC compatibility rules. - - llvm::PointerType *destType = - cast<llvm::PointerType>(CGF.ConvertType(CRE->getType())); - - // If the address is a constant null, just pass the appropriate null. - if (isProvablyNull(srcAddr.getPointer())) { - args.add(RValue::get(llvm::ConstantPointerNull::get(destType)), - CRE->getType()); - return; - } - - // Create the temporary. - Address temp = CGF.CreateTempAlloca(destType->getElementType(), - CGF.getPointerAlign(), - "icr.temp"); - // Loading an l-value can introduce a cleanup if the l-value is __weak, - // and that cleanup will be conditional if we can't prove that the l-value - // isn't null, so we need to register a dominating point so that the cleanups - // system will make valid IR. - CodeGenFunction::ConditionalEvaluation condEval(CGF); - - // Zero-initialize it if we're not doing a copy-initialization. - bool shouldCopy = CRE->shouldCopy(); - if (!shouldCopy) { - llvm::Value *null = - llvm::ConstantPointerNull::get( - cast<llvm::PointerType>(destType->getElementType())); - CGF.Builder.CreateStore(null, temp); - } - - llvm::BasicBlock *contBB = nullptr; - llvm::BasicBlock *originBB = nullptr; - - // If the address is *not* known to be non-null, we need to switch. - llvm::Value *finalArgument; - - bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(), - CGF.CGM.getDataLayout()); - if (provablyNonNull) { - finalArgument = temp.getPointer(); - } else { - llvm::Value *isNull = - CGF.Builder.CreateIsNull(srcAddr.getPointer(), "icr.isnull"); - - finalArgument = CGF.Builder.CreateSelect(isNull, - llvm::ConstantPointerNull::get(destType), - temp.getPointer(), "icr.argument"); - - // If we need to copy, then the load has to be conditional, which - // means we need control flow. - if (shouldCopy) { - originBB = CGF.Builder.GetInsertBlock(); - contBB = CGF.createBasicBlock("icr.cont"); - llvm::BasicBlock *copyBB = CGF.createBasicBlock("icr.copy"); - CGF.Builder.CreateCondBr(isNull, contBB, copyBB); - CGF.EmitBlock(copyBB); - condEval.begin(CGF); - } - } - - llvm::Value *valueToUse = nullptr; - - // Perform a copy if necessary. - if (shouldCopy) { - RValue srcRV = CGF.EmitLoadOfLValue(srcLV, SourceLocation()); - assert(srcRV.isScalar()); - - llvm::Value *src = srcRV.getScalarVal(); - src = CGF.Builder.CreateBitCast(src, destType->getElementType(), - "icr.cast"); - - // Use an ordinary store, not a store-to-lvalue. - CGF.Builder.CreateStore(src, temp); - - // If optimization is enabled, and the value was held in a - // __strong variable, we need to tell the optimizer that this - // value has to stay alive until we're doing the store back. - // This is because the temporary is effectively unretained, - // and so otherwise we can violate the high-level semantics. - if (CGF.CGM.getCodeGenOpts().OptimizationLevel != 0 && - srcLV.getObjCLifetime() == Qualifiers::OCL_Strong) { - valueToUse = src; - } - } - - // Finish the control flow if we needed it. - if (shouldCopy && !provablyNonNull) { - llvm::BasicBlock *copyBB = CGF.Builder.GetInsertBlock(); - CGF.EmitBlock(contBB); - - // Make a phi for the value to intrinsically use. - if (valueToUse) { - llvm::PHINode *phiToUse = CGF.Builder.CreatePHI(valueToUse->getType(), 2, - "icr.to-use"); - phiToUse->addIncoming(valueToUse, copyBB); - phiToUse->addIncoming(llvm::UndefValue::get(valueToUse->getType()), - originBB); - valueToUse = phiToUse; - } - - condEval.end(CGF); - } - - args.addWriteback(srcLV, temp, valueToUse); - args.add(RValue::get(finalArgument), CRE->getType()); -} - -void CallArgList::allocateArgumentMemory(CodeGenFunction &CGF) { - assert(!StackBase); - - // Save the stack. - llvm::Function *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::stacksave); - StackBase = CGF.Builder.CreateCall(F, {}, "inalloca.save"); -} - -void CallArgList::freeArgumentMemory(CodeGenFunction &CGF) const { - if (StackBase) { - // Restore the stack after the call. - llvm::Value *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::stackrestore); - CGF.Builder.CreateCall(F, StackBase); - } -} - -void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType, - SourceLocation ArgLoc, - AbstractCallee AC, - unsigned ParmNum) { - if (!AC.getDecl() || !(SanOpts.has(SanitizerKind::NonnullAttribute) || - SanOpts.has(SanitizerKind::NullabilityArg))) - return; - - // The param decl may be missing in a variadic function. - auto PVD = ParmNum < AC.getNumParams() ? AC.getParamDecl(ParmNum) : nullptr; - unsigned ArgNo = PVD ? PVD->getFunctionScopeIndex() : ParmNum; - - // Prefer the nonnull attribute if it's present. - const NonNullAttr *NNAttr = nullptr; - if (SanOpts.has(SanitizerKind::NonnullAttribute)) - NNAttr = getNonNullAttr(AC.getDecl(), PVD, ArgType, ArgNo); - - bool CanCheckNullability = false; - if (SanOpts.has(SanitizerKind::NullabilityArg) && !NNAttr && PVD) { - auto Nullability = PVD->getType()->getNullability(getContext()); - CanCheckNullability = Nullability && - *Nullability == NullabilityKind::NonNull && - PVD->getTypeSourceInfo(); - } - - if (!NNAttr && !CanCheckNullability) - return; - - SourceLocation AttrLoc; - SanitizerMask CheckKind; - SanitizerHandler Handler; - if (NNAttr) { - AttrLoc = NNAttr->getLocation(); - CheckKind = SanitizerKind::NonnullAttribute; - Handler = SanitizerHandler::NonnullArg; - } else { - AttrLoc = PVD->getTypeSourceInfo()->getTypeLoc().findNullabilityLoc(); - CheckKind = SanitizerKind::NullabilityArg; - Handler = SanitizerHandler::NullabilityArg; - } - - SanitizerScope SanScope(this); - assert(RV.isScalar()); - llvm::Value *V = RV.getScalarVal(); - llvm::Value *Cond = - Builder.CreateICmpNE(V, llvm::Constant::getNullValue(V->getType())); - llvm::Constant *StaticData[] = { - EmitCheckSourceLocation(ArgLoc), EmitCheckSourceLocation(AttrLoc), - llvm::ConstantInt::get(Int32Ty, ArgNo + 1), - }; - EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, None); -} - -void CodeGenFunction::EmitCallArgs( - CallArgList &Args, ArrayRef<QualType> ArgTypes, - llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange, - AbstractCallee AC, unsigned ParamsToSkip, EvaluationOrder Order) { - assert((int)ArgTypes.size() == (ArgRange.end() - ArgRange.begin())); - - // We *have* to evaluate arguments from right to left in the MS C++ ABI, - // because arguments are destroyed left to right in the callee. As a special - // case, there are certain language constructs that require left-to-right - // evaluation, and in those cases we consider the evaluation order requirement - // to trump the "destruction order is reverse construction order" guarantee. - bool LeftToRight = - CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee() - ? Order == EvaluationOrder::ForceLeftToRight - : Order != EvaluationOrder::ForceRightToLeft; - - auto MaybeEmitImplicitObjectSize = [&](unsigned I, const Expr *Arg, - RValue EmittedArg) { - if (!AC.hasFunctionDecl() || I >= AC.getNumParams()) - return; - auto *PS = AC.getParamDecl(I)->getAttr<PassObjectSizeAttr>(); - if (PS == nullptr) - return; - - const auto &Context = getContext(); - auto SizeTy = Context.getSizeType(); - auto T = Builder.getIntNTy(Context.getTypeSize(SizeTy)); - assert(EmittedArg.getScalarVal() && "We emitted nothing for the arg?"); - llvm::Value *V = evaluateOrEmitBuiltinObjectSize(Arg, PS->getType(), T, - EmittedArg.getScalarVal()); - Args.add(RValue::get(V), SizeTy); - // If we're emitting args in reverse, be sure to do so with - // pass_object_size, as well. - if (!LeftToRight) - std::swap(Args.back(), *(&Args.back() - 1)); - }; - - // Insert a stack save if we're going to need any inalloca args. - bool HasInAllocaArgs = false; - if (CGM.getTarget().getCXXABI().isMicrosoft()) { - for (ArrayRef<QualType>::iterator I = ArgTypes.begin(), E = ArgTypes.end(); - I != E && !HasInAllocaArgs; ++I) - HasInAllocaArgs = isInAllocaArgument(CGM.getCXXABI(), *I); - if (HasInAllocaArgs) { - assert(getTarget().getTriple().getArch() == llvm::Triple::x86); - Args.allocateArgumentMemory(*this); - } - } - - // Evaluate each argument in the appropriate order. - size_t CallArgsStart = Args.size(); - for (unsigned I = 0, E = ArgTypes.size(); I != E; ++I) { - unsigned Idx = LeftToRight ? I : E - I - 1; - CallExpr::const_arg_iterator Arg = ArgRange.begin() + Idx; - unsigned InitialArgSize = Args.size(); - // If *Arg is an ObjCIndirectCopyRestoreExpr, check that either the types of - // the argument and parameter match or the objc method is parameterized. - assert((!isa<ObjCIndirectCopyRestoreExpr>(*Arg) || - getContext().hasSameUnqualifiedType((*Arg)->getType(), - ArgTypes[Idx]) || - (isa<ObjCMethodDecl>(AC.getDecl()) && - isObjCMethodWithTypeParams(cast<ObjCMethodDecl>(AC.getDecl())))) && - "Argument and parameter types don't match"); - EmitCallArg(Args, *Arg, ArgTypes[Idx]); - // In particular, we depend on it being the last arg in Args, and the - // objectsize bits depend on there only being one arg if !LeftToRight. - assert(InitialArgSize + 1 == Args.size() && - "The code below depends on only adding one arg per EmitCallArg"); - (void)InitialArgSize; - // Since pointer argument are never emitted as LValue, it is safe to emit - // non-null argument check for r-value only. - if (!Args.back().hasLValue()) { - RValue RVArg = Args.back().getKnownRValue(); - EmitNonNullArgCheck(RVArg, ArgTypes[Idx], (*Arg)->getExprLoc(), AC, - ParamsToSkip + Idx); - // @llvm.objectsize should never have side-effects and shouldn't need - // destruction/cleanups, so we can safely "emit" it after its arg, - // regardless of right-to-leftness - MaybeEmitImplicitObjectSize(Idx, *Arg, RVArg); - } - } - - if (!LeftToRight) { - // Un-reverse the arguments we just evaluated so they match up with the LLVM - // IR function. - std::reverse(Args.begin() + CallArgsStart, Args.end()); - } -} - -namespace { - -struct DestroyUnpassedArg final : EHScopeStack::Cleanup { - DestroyUnpassedArg(Address Addr, QualType Ty) - : Addr(Addr), Ty(Ty) {} - - Address Addr; - QualType Ty; - - void Emit(CodeGenFunction &CGF, Flags flags) override { - QualType::DestructionKind DtorKind = Ty.isDestructedType(); - if (DtorKind == QualType::DK_cxx_destructor) { - const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor(); - assert(!Dtor->isTrivial()); - CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*for vbase*/ false, - /*Delegating=*/false, Addr); - } else { - CGF.callCStructDestructor(CGF.MakeAddrLValue(Addr, Ty)); - } - } -}; - -struct DisableDebugLocationUpdates { - CodeGenFunction &CGF; - bool disabledDebugInfo; - DisableDebugLocationUpdates(CodeGenFunction &CGF, const Expr *E) : CGF(CGF) { - if ((disabledDebugInfo = isa<CXXDefaultArgExpr>(E) && CGF.getDebugInfo())) - CGF.disableDebugInfo(); - } - ~DisableDebugLocationUpdates() { - if (disabledDebugInfo) - CGF.enableDebugInfo(); - } -}; - -} // end anonymous namespace - -RValue CallArg::getRValue(CodeGenFunction &CGF) const { - if (!HasLV) - return RV; - LValue Copy = CGF.MakeAddrLValue(CGF.CreateMemTemp(Ty), Ty); - CGF.EmitAggregateCopy(Copy, LV, Ty, AggValueSlot::DoesNotOverlap, - LV.isVolatile()); - IsUsed = true; - return RValue::getAggregate(Copy.getAddress()); -} - -void CallArg::copyInto(CodeGenFunction &CGF, Address Addr) const { - LValue Dst = CGF.MakeAddrLValue(Addr, Ty); - if (!HasLV && RV.isScalar()) - CGF.EmitStoreOfScalar(RV.getScalarVal(), Dst, /*init=*/true); - else if (!HasLV && RV.isComplex()) - CGF.EmitStoreOfComplex(RV.getComplexVal(), Dst, /*init=*/true); - else { - auto Addr = HasLV ? LV.getAddress() : RV.getAggregateAddress(); - LValue SrcLV = CGF.MakeAddrLValue(Addr, Ty); - // We assume that call args are never copied into subobjects. - CGF.EmitAggregateCopy(Dst, SrcLV, Ty, AggValueSlot::DoesNotOverlap, - HasLV ? LV.isVolatileQualified() - : RV.isVolatileQualified()); - } - IsUsed = true; -} - -void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, - QualType type) { - DisableDebugLocationUpdates Dis(*this, E); - if (const ObjCIndirectCopyRestoreExpr *CRE - = dyn_cast<ObjCIndirectCopyRestoreExpr>(E)) { - assert(getLangOpts().ObjCAutoRefCount); - return emitWritebackArg(*this, args, CRE); - } - - assert(type->isReferenceType() == E->isGLValue() && - "reference binding to unmaterialized r-value!"); - - if (E->isGLValue()) { - assert(E->getObjectKind() == OK_Ordinary); - return args.add(EmitReferenceBindingToExpr(E), type); - } - - bool HasAggregateEvalKind = hasAggregateEvaluationKind(type); - - // In the Microsoft C++ ABI, aggregate arguments are destructed by the callee. - // However, we still have to push an EH-only cleanup in case we unwind before - // we make it to the call. - if (HasAggregateEvalKind && - type->getAs<RecordType>()->getDecl()->isParamDestroyedInCallee()) { - // If we're using inalloca, use the argument memory. Otherwise, use a - // temporary. - AggValueSlot Slot; - if (args.isUsingInAlloca()) - Slot = createPlaceholderSlot(*this, type); - else - Slot = CreateAggTemp(type, "agg.tmp"); - - bool DestroyedInCallee = true, NeedsEHCleanup = true; - if (const auto *RD = type->getAsCXXRecordDecl()) - DestroyedInCallee = RD->hasNonTrivialDestructor(); - else - NeedsEHCleanup = needsEHCleanup(type.isDestructedType()); - - if (DestroyedInCallee) - Slot.setExternallyDestructed(); - - EmitAggExpr(E, Slot); - RValue RV = Slot.asRValue(); - args.add(RV, type); - - if (DestroyedInCallee && NeedsEHCleanup) { - // Create a no-op GEP between the placeholder and the cleanup so we can - // RAUW it successfully. It also serves as a marker of the first - // instruction where the cleanup is active. - pushFullExprCleanup<DestroyUnpassedArg>(EHCleanup, Slot.getAddress(), - type); - // This unreachable is a temporary marker which will be removed later. - llvm::Instruction *IsActive = Builder.CreateUnreachable(); - args.addArgCleanupDeactivation(EHStack.getInnermostEHScope(), IsActive); - } - return; - } - - if (HasAggregateEvalKind && isa<ImplicitCastExpr>(E) && - cast<CastExpr>(E)->getCastKind() == CK_LValueToRValue) { - LValue L = EmitLValue(cast<CastExpr>(E)->getSubExpr()); - assert(L.isSimple()); - args.addUncopiedAggregate(L, type); - return; - } - - args.add(EmitAnyExprToTemp(E), type); -} - -QualType CodeGenFunction::getVarArgType(const Expr *Arg) { - // System headers on Windows define NULL to 0 instead of 0LL on Win64. MSVC - // implicitly widens null pointer constants that are arguments to varargs - // functions to pointer-sized ints. - if (!getTarget().getTriple().isOSWindows()) - return Arg->getType(); - - if (Arg->getType()->isIntegerType() && - getContext().getTypeSize(Arg->getType()) < - getContext().getTargetInfo().getPointerWidth(0) && - Arg->isNullPointerConstant(getContext(), - Expr::NPC_ValueDependentIsNotNull)) { - return getContext().getIntPtrType(); - } - - return Arg->getType(); -} - -// In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC -// optimizer it can aggressively ignore unwind edges. -void -CodeGenFunction::AddObjCARCExceptionMetadata(llvm::Instruction *Inst) { - if (CGM.getCodeGenOpts().OptimizationLevel != 0 && - !CGM.getCodeGenOpts().ObjCAutoRefCountExceptions) - Inst->setMetadata("clang.arc.no_objc_arc_exceptions", - CGM.getNoObjCARCExceptionsMetadata()); -} - -/// Emits a call to the given no-arguments nounwind runtime function. -llvm::CallInst * -CodeGenFunction::EmitNounwindRuntimeCall(llvm::Value *callee, - const llvm::Twine &name) { - return EmitNounwindRuntimeCall(callee, None, name); -} - -/// Emits a call to the given nounwind runtime function. -llvm::CallInst * -CodeGenFunction::EmitNounwindRuntimeCall(llvm::Value *callee, - ArrayRef<llvm::Value*> args, - const llvm::Twine &name) { - llvm::CallInst *call = EmitRuntimeCall(callee, args, name); - call->setDoesNotThrow(); - return call; -} - -/// Emits a simple call (never an invoke) to the given no-arguments -/// runtime function. -llvm::CallInst * -CodeGenFunction::EmitRuntimeCall(llvm::Value *callee, - const llvm::Twine &name) { - return EmitRuntimeCall(callee, None, name); -} - -// Calls which may throw must have operand bundles indicating which funclet -// they are nested within. -SmallVector<llvm::OperandBundleDef, 1> -CodeGenFunction::getBundlesForFunclet(llvm::Value *Callee) { - SmallVector<llvm::OperandBundleDef, 1> BundleList; - // There is no need for a funclet operand bundle if we aren't inside a - // funclet. - if (!CurrentFuncletPad) - return BundleList; - - // Skip intrinsics which cannot throw. - auto *CalleeFn = dyn_cast<llvm::Function>(Callee->stripPointerCasts()); - if (CalleeFn && CalleeFn->isIntrinsic() && CalleeFn->doesNotThrow()) - return BundleList; - - BundleList.emplace_back("funclet", CurrentFuncletPad); - return BundleList; -} - -/// Emits a simple call (never an invoke) to the given runtime function. -llvm::CallInst * -CodeGenFunction::EmitRuntimeCall(llvm::Value *callee, - ArrayRef<llvm::Value*> args, - const llvm::Twine &name) { - llvm::CallInst *call = - Builder.CreateCall(callee, args, getBundlesForFunclet(callee), name); - call->setCallingConv(getRuntimeCC()); - return call; -} - -/// Emits a call or invoke to the given noreturn runtime function. -void CodeGenFunction::EmitNoreturnRuntimeCallOrInvoke(llvm::Value *callee, - ArrayRef<llvm::Value*> args) { - SmallVector<llvm::OperandBundleDef, 1> BundleList = - getBundlesForFunclet(callee); - - if (getInvokeDest()) { - llvm::InvokeInst *invoke = - Builder.CreateInvoke(callee, - getUnreachableBlock(), - getInvokeDest(), - args, - BundleList); - invoke->setDoesNotReturn(); - invoke->setCallingConv(getRuntimeCC()); - } else { - llvm::CallInst *call = Builder.CreateCall(callee, args, BundleList); - call->setDoesNotReturn(); - call->setCallingConv(getRuntimeCC()); - Builder.CreateUnreachable(); - } -} - -/// Emits a call or invoke instruction to the given nullary runtime function. -llvm::CallSite -CodeGenFunction::EmitRuntimeCallOrInvoke(llvm::Value *callee, - const Twine &name) { - return EmitRuntimeCallOrInvoke(callee, None, name); -} - -/// Emits a call or invoke instruction to the given runtime function. -llvm::CallSite -CodeGenFunction::EmitRuntimeCallOrInvoke(llvm::Value *callee, - ArrayRef<llvm::Value*> args, - const Twine &name) { - llvm::CallSite callSite = EmitCallOrInvoke(callee, args, name); - callSite.setCallingConv(getRuntimeCC()); - return callSite; -} - -/// Emits a call or invoke instruction to the given function, depending -/// on the current state of the EH stack. -llvm::CallSite -CodeGenFunction::EmitCallOrInvoke(llvm::Value *Callee, - ArrayRef<llvm::Value *> Args, - const Twine &Name) { - llvm::BasicBlock *InvokeDest = getInvokeDest(); - SmallVector<llvm::OperandBundleDef, 1> BundleList = - getBundlesForFunclet(Callee); - - llvm::Instruction *Inst; - if (!InvokeDest) - Inst = Builder.CreateCall(Callee, Args, BundleList, Name); - else { - llvm::BasicBlock *ContBB = createBasicBlock("invoke.cont"); - Inst = Builder.CreateInvoke(Callee, ContBB, InvokeDest, Args, BundleList, - Name); - EmitBlock(ContBB); - } - - // In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC - // optimizer it can aggressively ignore unwind edges. - if (CGM.getLangOpts().ObjCAutoRefCount) - AddObjCARCExceptionMetadata(Inst); - - return llvm::CallSite(Inst); -} - -void CodeGenFunction::deferPlaceholderReplacement(llvm::Instruction *Old, - llvm::Value *New) { - DeferredReplacements.push_back(std::make_pair(Old, New)); -} - -RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, - const CGCallee &Callee, - ReturnValueSlot ReturnValue, - const CallArgList &CallArgs, - llvm::Instruction **callOrInvoke, - SourceLocation Loc) { - // FIXME: We no longer need the types from CallArgs; lift up and simplify. - - assert(Callee.isOrdinary() || Callee.isVirtual()); - - // Handle struct-return functions by passing a pointer to the - // location that we would like to return into. - QualType RetTy = CallInfo.getReturnType(); - const ABIArgInfo &RetAI = CallInfo.getReturnInfo(); - - llvm::FunctionType *IRFuncTy = Callee.getFunctionType(); - - // 1. Set up the arguments. - - // If we're using inalloca, insert the allocation after the stack save. - // FIXME: Do this earlier rather than hacking it in here! - Address ArgMemory = Address::invalid(); - const llvm::StructLayout *ArgMemoryLayout = nullptr; - if (llvm::StructType *ArgStruct = CallInfo.getArgStruct()) { - const llvm::DataLayout &DL = CGM.getDataLayout(); - ArgMemoryLayout = DL.getStructLayout(ArgStruct); - llvm::Instruction *IP = CallArgs.getStackBase(); - llvm::AllocaInst *AI; - if (IP) { - IP = IP->getNextNode(); - AI = new llvm::AllocaInst(ArgStruct, DL.getAllocaAddrSpace(), - "argmem", IP); - } else { - AI = CreateTempAlloca(ArgStruct, "argmem"); - } - auto Align = CallInfo.getArgStructAlignment(); - AI->setAlignment(Align.getQuantity()); - AI->setUsedWithInAlloca(true); - assert(AI->isUsedWithInAlloca() && !AI->isStaticAlloca()); - ArgMemory = Address(AI, Align); - } - - // Helper function to drill into the inalloca allocation. - auto createInAllocaStructGEP = [&](unsigned FieldIndex) -> Address { - auto FieldOffset = - CharUnits::fromQuantity(ArgMemoryLayout->getElementOffset(FieldIndex)); - return Builder.CreateStructGEP(ArgMemory, FieldIndex, FieldOffset); - }; - - ClangToLLVMArgMapping IRFunctionArgs(CGM.getContext(), CallInfo); - SmallVector<llvm::Value *, 16> IRCallArgs(IRFunctionArgs.totalIRArgs()); - - // If the call returns a temporary with struct return, create a temporary - // alloca to hold the result, unless one is given to us. - Address SRetPtr = Address::invalid(); - Address SRetAlloca = Address::invalid(); - llvm::Value *UnusedReturnSizePtr = nullptr; - if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) { - if (!ReturnValue.isNull()) { - SRetPtr = ReturnValue.getValue(); - } else { - SRetPtr = CreateMemTemp(RetTy, "tmp", &SRetAlloca); - if (HaveInsertPoint() && ReturnValue.isUnused()) { - uint64_t size = - CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(RetTy)); - UnusedReturnSizePtr = EmitLifetimeStart(size, SRetAlloca.getPointer()); - } - } - if (IRFunctionArgs.hasSRetArg()) { - IRCallArgs[IRFunctionArgs.getSRetArgNo()] = SRetPtr.getPointer(); - } else if (RetAI.isInAlloca()) { - Address Addr = createInAllocaStructGEP(RetAI.getInAllocaFieldIndex()); - Builder.CreateStore(SRetPtr.getPointer(), Addr); - } - } - - Address swiftErrorTemp = Address::invalid(); - Address swiftErrorArg = Address::invalid(); - - // Translate all of the arguments as necessary to match the IR lowering. - assert(CallInfo.arg_size() == CallArgs.size() && - "Mismatch between function signature & arguments."); - unsigned ArgNo = 0; - CGFunctionInfo::const_arg_iterator info_it = CallInfo.arg_begin(); - for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end(); - I != E; ++I, ++info_it, ++ArgNo) { - const ABIArgInfo &ArgInfo = info_it->info; - - // Insert a padding argument to ensure proper alignment. - if (IRFunctionArgs.hasPaddingArg(ArgNo)) - IRCallArgs[IRFunctionArgs.getPaddingArgNo(ArgNo)] = - llvm::UndefValue::get(ArgInfo.getPaddingType()); - - unsigned FirstIRArg, NumIRArgs; - std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo); - - switch (ArgInfo.getKind()) { - case ABIArgInfo::InAlloca: { - assert(NumIRArgs == 0); - assert(getTarget().getTriple().getArch() == llvm::Triple::x86); - if (I->isAggregate()) { - // Replace the placeholder with the appropriate argument slot GEP. - Address Addr = I->hasLValue() - ? I->getKnownLValue().getAddress() - : I->getKnownRValue().getAggregateAddress(); - llvm::Instruction *Placeholder = - cast<llvm::Instruction>(Addr.getPointer()); - CGBuilderTy::InsertPoint IP = Builder.saveIP(); - Builder.SetInsertPoint(Placeholder); - Addr = createInAllocaStructGEP(ArgInfo.getInAllocaFieldIndex()); - Builder.restoreIP(IP); - deferPlaceholderReplacement(Placeholder, Addr.getPointer()); - } else { - // Store the RValue into the argument struct. - Address Addr = createInAllocaStructGEP(ArgInfo.getInAllocaFieldIndex()); - unsigned AS = Addr.getType()->getPointerAddressSpace(); - llvm::Type *MemType = ConvertTypeForMem(I->Ty)->getPointerTo(AS); - // There are some cases where a trivial bitcast is not avoidable. The - // definition of a type later in a translation unit may change it's type - // from {}* to (%struct.foo*)*. - if (Addr.getType() != MemType) - Addr = Builder.CreateBitCast(Addr, MemType); - I->copyInto(*this, Addr); - } - break; - } - - case ABIArgInfo::Indirect: { - assert(NumIRArgs == 1); - if (!I->isAggregate()) { - // Make a temporary alloca to pass the argument. - Address Addr = CreateMemTempWithoutCast( - I->Ty, ArgInfo.getIndirectAlign(), "indirect-arg-temp"); - IRCallArgs[FirstIRArg] = Addr.getPointer(); - - I->copyInto(*this, Addr); - } else { - // We want to avoid creating an unnecessary temporary+copy here; - // however, we need one in three cases: - // 1. If the argument is not byval, and we are required to copy the - // source. (This case doesn't occur on any common architecture.) - // 2. If the argument is byval, RV is not sufficiently aligned, and - // we cannot force it to be sufficiently aligned. - // 3. If the argument is byval, but RV is not located in default - // or alloca address space. - Address Addr = I->hasLValue() - ? I->getKnownLValue().getAddress() - : I->getKnownRValue().getAggregateAddress(); - llvm::Value *V = Addr.getPointer(); - CharUnits Align = ArgInfo.getIndirectAlign(); - const llvm::DataLayout *TD = &CGM.getDataLayout(); - - assert((FirstIRArg >= IRFuncTy->getNumParams() || - IRFuncTy->getParamType(FirstIRArg)->getPointerAddressSpace() == - TD->getAllocaAddrSpace()) && - "indirect argument must be in alloca address space"); - - bool NeedCopy = false; - - if (Addr.getAlignment() < Align && - llvm::getOrEnforceKnownAlignment(V, Align.getQuantity(), *TD) < - Align.getQuantity()) { - NeedCopy = true; - } else if (I->hasLValue()) { - auto LV = I->getKnownLValue(); - auto AS = LV.getAddressSpace(); - - if ((!ArgInfo.getIndirectByVal() && - (LV.getAlignment() >= - getContext().getTypeAlignInChars(I->Ty)))) { - NeedCopy = true; - } - if (!getLangOpts().OpenCL) { - if ((ArgInfo.getIndirectByVal() && - (AS != LangAS::Default && - AS != CGM.getASTAllocaAddressSpace()))) { - NeedCopy = true; - } - } - // For OpenCL even if RV is located in default or alloca address space - // we don't want to perform address space cast for it. - else if ((ArgInfo.getIndirectByVal() && - Addr.getType()->getAddressSpace() != IRFuncTy-> - getParamType(FirstIRArg)->getPointerAddressSpace())) { - NeedCopy = true; - } - } - - if (NeedCopy) { - // Create an aligned temporary, and copy to it. - Address AI = CreateMemTempWithoutCast( - I->Ty, ArgInfo.getIndirectAlign(), "byval-temp"); - IRCallArgs[FirstIRArg] = AI.getPointer(); - I->copyInto(*this, AI); - } else { - // Skip the extra memcpy call. - auto *T = V->getType()->getPointerElementType()->getPointerTo( - CGM.getDataLayout().getAllocaAddrSpace()); - IRCallArgs[FirstIRArg] = getTargetHooks().performAddrSpaceCast( - *this, V, LangAS::Default, CGM.getASTAllocaAddressSpace(), T, - true); - } - } - break; - } - - case ABIArgInfo::Ignore: - assert(NumIRArgs == 0); - break; - - case ABIArgInfo::Extend: - case ABIArgInfo::Direct: { - if (!isa<llvm::StructType>(ArgInfo.getCoerceToType()) && - ArgInfo.getCoerceToType() == ConvertType(info_it->type) && - ArgInfo.getDirectOffset() == 0) { - assert(NumIRArgs == 1); - llvm::Value *V; - if (!I->isAggregate()) - V = I->getKnownRValue().getScalarVal(); - else - V = Builder.CreateLoad( - I->hasLValue() ? I->getKnownLValue().getAddress() - : I->getKnownRValue().getAggregateAddress()); - - // Implement swifterror by copying into a new swifterror argument. - // We'll write back in the normal path out of the call. - if (CallInfo.getExtParameterInfo(ArgNo).getABI() - == ParameterABI::SwiftErrorResult) { - assert(!swiftErrorTemp.isValid() && "multiple swifterror args"); - - QualType pointeeTy = I->Ty->getPointeeType(); - swiftErrorArg = - Address(V, getContext().getTypeAlignInChars(pointeeTy)); - - swiftErrorTemp = - CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); - V = swiftErrorTemp.getPointer(); - cast<llvm::AllocaInst>(V)->setSwiftError(true); - - llvm::Value *errorValue = Builder.CreateLoad(swiftErrorArg); - Builder.CreateStore(errorValue, swiftErrorTemp); - } - - // We might have to widen integers, but we should never truncate. - if (ArgInfo.getCoerceToType() != V->getType() && - V->getType()->isIntegerTy()) - V = Builder.CreateZExt(V, ArgInfo.getCoerceToType()); - - // If the argument doesn't match, perform a bitcast to coerce it. This - // can happen due to trivial type mismatches. - if (FirstIRArg < IRFuncTy->getNumParams() && - V->getType() != IRFuncTy->getParamType(FirstIRArg)) - V = Builder.CreateBitCast(V, IRFuncTy->getParamType(FirstIRArg)); - - IRCallArgs[FirstIRArg] = V; - break; - } - - // FIXME: Avoid the conversion through memory if possible. - Address Src = Address::invalid(); - if (!I->isAggregate()) { - Src = CreateMemTemp(I->Ty, "coerce"); - I->copyInto(*this, Src); - } else { - Src = I->hasLValue() ? I->getKnownLValue().getAddress() - : I->getKnownRValue().getAggregateAddress(); - } - - // If the value is offset in memory, apply the offset now. - Src = emitAddressAtOffset(*this, Src, ArgInfo); - - // Fast-isel and the optimizer generally like scalar values better than - // FCAs, so we flatten them if this is safe to do for this argument. - llvm::StructType *STy = - dyn_cast<llvm::StructType>(ArgInfo.getCoerceToType()); - if (STy && ArgInfo.isDirect() && ArgInfo.getCanBeFlattened()) { - llvm::Type *SrcTy = Src.getType()->getElementType(); - uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy); - uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy); - - // If the source type is smaller than the destination type of the - // coerce-to logic, copy the source value into a temp alloca the size - // of the destination type to allow loading all of it. The bits past - // the source value are left undef. - if (SrcSize < DstSize) { - Address TempAlloca - = CreateTempAlloca(STy, Src.getAlignment(), - Src.getName() + ".coerce"); - Builder.CreateMemCpy(TempAlloca, Src, SrcSize); - Src = TempAlloca; - } else { - Src = Builder.CreateBitCast(Src, - STy->getPointerTo(Src.getAddressSpace())); - } - - auto SrcLayout = CGM.getDataLayout().getStructLayout(STy); - assert(NumIRArgs == STy->getNumElements()); - for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { - auto Offset = CharUnits::fromQuantity(SrcLayout->getElementOffset(i)); - Address EltPtr = Builder.CreateStructGEP(Src, i, Offset); - llvm::Value *LI = Builder.CreateLoad(EltPtr); - IRCallArgs[FirstIRArg + i] = LI; - } - } else { - // In the simple case, just pass the coerced loaded value. - assert(NumIRArgs == 1); - IRCallArgs[FirstIRArg] = - CreateCoercedLoad(Src, ArgInfo.getCoerceToType(), *this); - } - - break; - } - - case ABIArgInfo::CoerceAndExpand: { - auto coercionType = ArgInfo.getCoerceAndExpandType(); - auto layout = CGM.getDataLayout().getStructLayout(coercionType); - - llvm::Value *tempSize = nullptr; - Address addr = Address::invalid(); - Address AllocaAddr = Address::invalid(); - if (I->isAggregate()) { - addr = I->hasLValue() ? I->getKnownLValue().getAddress() - : I->getKnownRValue().getAggregateAddress(); - - } else { - RValue RV = I->getKnownRValue(); - assert(RV.isScalar()); // complex should always just be direct - - llvm::Type *scalarType = RV.getScalarVal()->getType(); - auto scalarSize = CGM.getDataLayout().getTypeAllocSize(scalarType); - auto scalarAlign = CGM.getDataLayout().getPrefTypeAlignment(scalarType); - - // Materialize to a temporary. - addr = CreateTempAlloca(RV.getScalarVal()->getType(), - CharUnits::fromQuantity(std::max( - layout->getAlignment(), scalarAlign)), - "tmp", - /*ArraySize=*/nullptr, &AllocaAddr); - tempSize = EmitLifetimeStart(scalarSize, AllocaAddr.getPointer()); - - Builder.CreateStore(RV.getScalarVal(), addr); - } - - addr = Builder.CreateElementBitCast(addr, coercionType); - - unsigned IRArgPos = FirstIRArg; - for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { - llvm::Type *eltType = coercionType->getElementType(i); - if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) continue; - Address eltAddr = Builder.CreateStructGEP(addr, i, layout); - llvm::Value *elt = Builder.CreateLoad(eltAddr); - IRCallArgs[IRArgPos++] = elt; - } - assert(IRArgPos == FirstIRArg + NumIRArgs); - - if (tempSize) { - EmitLifetimeEnd(tempSize, AllocaAddr.getPointer()); - } - - break; - } - - case ABIArgInfo::Expand: - unsigned IRArgPos = FirstIRArg; - ExpandTypeToArgs(I->Ty, *I, IRFuncTy, IRCallArgs, IRArgPos); - assert(IRArgPos == FirstIRArg + NumIRArgs); - break; - } - } - - const CGCallee &ConcreteCallee = Callee.prepareConcreteCallee(*this); - llvm::Value *CalleePtr = ConcreteCallee.getFunctionPointer(); - - // If we're using inalloca, set up that argument. - if (ArgMemory.isValid()) { - llvm::Value *Arg = ArgMemory.getPointer(); - if (CallInfo.isVariadic()) { - // When passing non-POD arguments by value to variadic functions, we will - // end up with a variadic prototype and an inalloca call site. In such - // cases, we can't do any parameter mismatch checks. Give up and bitcast - // the callee. - unsigned CalleeAS = CalleePtr->getType()->getPointerAddressSpace(); - auto FnTy = getTypes().GetFunctionType(CallInfo)->getPointerTo(CalleeAS); - CalleePtr = Builder.CreateBitCast(CalleePtr, FnTy); - } else { - llvm::Type *LastParamTy = - IRFuncTy->getParamType(IRFuncTy->getNumParams() - 1); - if (Arg->getType() != LastParamTy) { -#ifndef NDEBUG - // Assert that these structs have equivalent element types. - llvm::StructType *FullTy = CallInfo.getArgStruct(); - llvm::StructType *DeclaredTy = cast<llvm::StructType>( - cast<llvm::PointerType>(LastParamTy)->getElementType()); - assert(DeclaredTy->getNumElements() == FullTy->getNumElements()); - for (llvm::StructType::element_iterator DI = DeclaredTy->element_begin(), - DE = DeclaredTy->element_end(), - FI = FullTy->element_begin(); - DI != DE; ++DI, ++FI) - assert(*DI == *FI); -#endif - Arg = Builder.CreateBitCast(Arg, LastParamTy); - } - } - assert(IRFunctionArgs.hasInallocaArg()); - IRCallArgs[IRFunctionArgs.getInallocaArgNo()] = Arg; - } - - // 2. Prepare the function pointer. - - // If the callee is a bitcast of a non-variadic function to have a - // variadic function pointer type, check to see if we can remove the - // bitcast. This comes up with unprototyped functions. - // - // This makes the IR nicer, but more importantly it ensures that we - // can inline the function at -O0 if it is marked always_inline. - auto simplifyVariadicCallee = [](llvm::Value *Ptr) -> llvm::Value* { - llvm::FunctionType *CalleeFT = - cast<llvm::FunctionType>(Ptr->getType()->getPointerElementType()); - if (!CalleeFT->isVarArg()) - return Ptr; - - llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Ptr); - if (!CE || CE->getOpcode() != llvm::Instruction::BitCast) - return Ptr; - - llvm::Function *OrigFn = dyn_cast<llvm::Function>(CE->getOperand(0)); - if (!OrigFn) - return Ptr; - - llvm::FunctionType *OrigFT = OrigFn->getFunctionType(); - - // If the original type is variadic, or if any of the component types - // disagree, we cannot remove the cast. - if (OrigFT->isVarArg() || - OrigFT->getNumParams() != CalleeFT->getNumParams() || - OrigFT->getReturnType() != CalleeFT->getReturnType()) - return Ptr; - - for (unsigned i = 0, e = OrigFT->getNumParams(); i != e; ++i) - if (OrigFT->getParamType(i) != CalleeFT->getParamType(i)) - return Ptr; - - return OrigFn; - }; - CalleePtr = simplifyVariadicCallee(CalleePtr); - - // 3. Perform the actual call. - - // Deactivate any cleanups that we're supposed to do immediately before - // the call. - if (!CallArgs.getCleanupsToDeactivate().empty()) - deactivateArgCleanupsBeforeCall(*this, CallArgs); - - // Assert that the arguments we computed match up. The IR verifier - // will catch this, but this is a common enough source of problems - // during IRGen changes that it's way better for debugging to catch - // it ourselves here. -#ifndef NDEBUG - assert(IRCallArgs.size() == IRFuncTy->getNumParams() || IRFuncTy->isVarArg()); - for (unsigned i = 0; i < IRCallArgs.size(); ++i) { - // Inalloca argument can have different type. - if (IRFunctionArgs.hasInallocaArg() && - i == IRFunctionArgs.getInallocaArgNo()) - continue; - if (i < IRFuncTy->getNumParams()) - assert(IRCallArgs[i]->getType() == IRFuncTy->getParamType(i)); - } -#endif - - // Update the largest vector width if any arguments have vector types. - for (unsigned i = 0; i < IRCallArgs.size(); ++i) { - if (auto *VT = dyn_cast<llvm::VectorType>(IRCallArgs[i]->getType())) - LargestVectorWidth = std::max(LargestVectorWidth, - VT->getPrimitiveSizeInBits()); - } - - // Compute the calling convention and attributes. - unsigned CallingConv; - llvm::AttributeList Attrs; - CGM.ConstructAttributeList(CalleePtr->getName(), CallInfo, - Callee.getAbstractInfo(), Attrs, CallingConv, - /*AttrOnCallSite=*/true); - - // Apply some call-site-specific attributes. - // TODO: work this into building the attribute set. - - // Apply always_inline to all calls within flatten functions. - // FIXME: should this really take priority over __try, below? - if (CurCodeDecl && CurCodeDecl->hasAttr<FlattenAttr>() && - !(Callee.getAbstractInfo().getCalleeDecl().getDecl() && - Callee.getAbstractInfo() - .getCalleeDecl() - .getDecl() - ->hasAttr<NoInlineAttr>())) { - Attrs = - Attrs.addAttribute(getLLVMContext(), llvm::AttributeList::FunctionIndex, - llvm::Attribute::AlwaysInline); - } - - // Disable inlining inside SEH __try blocks. - if (isSEHTryScope()) { - Attrs = - Attrs.addAttribute(getLLVMContext(), llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoInline); - } - - // Decide whether to use a call or an invoke. - bool CannotThrow; - if (currentFunctionUsesSEHTry()) { - // SEH cares about asynchronous exceptions, so everything can "throw." - CannotThrow = false; - } else if (isCleanupPadScope() && - EHPersonality::get(*this).isMSVCXXPersonality()) { - // The MSVC++ personality will implicitly terminate the program if an - // exception is thrown during a cleanup outside of a try/catch. - // We don't need to model anything in IR to get this behavior. - CannotThrow = true; - } else { - // Otherwise, nounwind call sites will never throw. - CannotThrow = Attrs.hasAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind); - } - - // If we made a temporary, be sure to clean up after ourselves. Note that we - // can't depend on being inside of an ExprWithCleanups, so we need to manually - // pop this cleanup later on. Being eager about this is OK, since this - // temporary is 'invisible' outside of the callee. - if (UnusedReturnSizePtr) - pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetAlloca, - UnusedReturnSizePtr); - - llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest(); - - SmallVector<llvm::OperandBundleDef, 1> BundleList = - getBundlesForFunclet(CalleePtr); - - // Emit the actual call/invoke instruction. - llvm::CallSite CS; - if (!InvokeDest) { - CS = Builder.CreateCall(CalleePtr, IRCallArgs, BundleList); - } else { - llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); - CS = Builder.CreateInvoke(CalleePtr, Cont, InvokeDest, IRCallArgs, - BundleList); - EmitBlock(Cont); - } - llvm::Instruction *CI = CS.getInstruction(); - if (callOrInvoke) - *callOrInvoke = CI; - - // Apply the attributes and calling convention. - CS.setAttributes(Attrs); - CS.setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv)); - - // Apply various metadata. - - if (!CI->getType()->isVoidTy()) - CI->setName("call"); - - // Update largest vector width from the return type. - if (auto *VT = dyn_cast<llvm::VectorType>(CI->getType())) - LargestVectorWidth = std::max(LargestVectorWidth, - VT->getPrimitiveSizeInBits()); - - // Insert instrumentation or attach profile metadata at indirect call sites. - // For more details, see the comment before the definition of - // IPVK_IndirectCallTarget in InstrProfData.inc. - if (!CS.getCalledFunction()) - PGO.valueProfile(Builder, llvm::IPVK_IndirectCallTarget, - CI, CalleePtr); - - // In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC - // optimizer it can aggressively ignore unwind edges. - if (CGM.getLangOpts().ObjCAutoRefCount) - AddObjCARCExceptionMetadata(CI); - - // Suppress tail calls if requested. - if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) { - const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl().getDecl(); - if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>()) - Call->setTailCallKind(llvm::CallInst::TCK_NoTail); - } - - // 4. Finish the call. - - // If the call doesn't return, finish the basic block and clear the - // insertion point; this allows the rest of IRGen to discard - // unreachable code. - if (CS.doesNotReturn()) { - if (UnusedReturnSizePtr) - PopCleanupBlock(); - - // Strip away the noreturn attribute to better diagnose unreachable UB. - if (SanOpts.has(SanitizerKind::Unreachable)) { - if (auto *F = CS.getCalledFunction()) - F->removeFnAttr(llvm::Attribute::NoReturn); - CS.removeAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoReturn); - } - - EmitUnreachable(Loc); - Builder.ClearInsertionPoint(); - - // FIXME: For now, emit a dummy basic block because expr emitters in - // generally are not ready to handle emitting expressions at unreachable - // points. - EnsureInsertPoint(); - - // Return a reasonable RValue. - return GetUndefRValue(RetTy); - } - - // Perform the swifterror writeback. - if (swiftErrorTemp.isValid()) { - llvm::Value *errorResult = Builder.CreateLoad(swiftErrorTemp); - Builder.CreateStore(errorResult, swiftErrorArg); - } - - // Emit any call-associated writebacks immediately. Arguably this - // should happen after any return-value munging. - if (CallArgs.hasWritebacks()) - emitWritebacks(*this, CallArgs); - - // The stack cleanup for inalloca arguments has to run out of the normal - // lexical order, so deactivate it and run it manually here. - CallArgs.freeArgumentMemory(*this); - - // Extract the return value. - RValue Ret = [&] { - switch (RetAI.getKind()) { - case ABIArgInfo::CoerceAndExpand: { - auto coercionType = RetAI.getCoerceAndExpandType(); - auto layout = CGM.getDataLayout().getStructLayout(coercionType); - - Address addr = SRetPtr; - addr = Builder.CreateElementBitCast(addr, coercionType); - - assert(CI->getType() == RetAI.getUnpaddedCoerceAndExpandType()); - bool requiresExtract = isa<llvm::StructType>(CI->getType()); - - unsigned unpaddedIndex = 0; - for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { - llvm::Type *eltType = coercionType->getElementType(i); - if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) continue; - Address eltAddr = Builder.CreateStructGEP(addr, i, layout); - llvm::Value *elt = CI; - if (requiresExtract) - elt = Builder.CreateExtractValue(elt, unpaddedIndex++); - else - assert(unpaddedIndex == 0); - Builder.CreateStore(elt, eltAddr); - } - // FALLTHROUGH - LLVM_FALLTHROUGH; - } - - case ABIArgInfo::InAlloca: - case ABIArgInfo::Indirect: { - RValue ret = convertTempToRValue(SRetPtr, RetTy, SourceLocation()); - if (UnusedReturnSizePtr) - PopCleanupBlock(); - return ret; - } - - case ABIArgInfo::Ignore: - // If we are ignoring an argument that had a result, make sure to - // construct the appropriate return value for our caller. - return GetUndefRValue(RetTy); - - case ABIArgInfo::Extend: - case ABIArgInfo::Direct: { - llvm::Type *RetIRTy = ConvertType(RetTy); - if (RetAI.getCoerceToType() == RetIRTy && RetAI.getDirectOffset() == 0) { - switch (getEvaluationKind(RetTy)) { - case TEK_Complex: { - llvm::Value *Real = Builder.CreateExtractValue(CI, 0); - llvm::Value *Imag = Builder.CreateExtractValue(CI, 1); - return RValue::getComplex(std::make_pair(Real, Imag)); - } - case TEK_Aggregate: { - Address DestPtr = ReturnValue.getValue(); - bool DestIsVolatile = ReturnValue.isVolatile(); - - if (!DestPtr.isValid()) { - DestPtr = CreateMemTemp(RetTy, "agg.tmp"); - DestIsVolatile = false; - } - BuildAggStore(*this, CI, DestPtr, DestIsVolatile); - return RValue::getAggregate(DestPtr); - } - case TEK_Scalar: { - // If the argument doesn't match, perform a bitcast to coerce it. This - // can happen due to trivial type mismatches. - llvm::Value *V = CI; - if (V->getType() != RetIRTy) - V = Builder.CreateBitCast(V, RetIRTy); - return RValue::get(V); - } - } - llvm_unreachable("bad evaluation kind"); - } - - Address DestPtr = ReturnValue.getValue(); - bool DestIsVolatile = ReturnValue.isVolatile(); - - if (!DestPtr.isValid()) { - DestPtr = CreateMemTemp(RetTy, "coerce"); - DestIsVolatile = false; - } - - // If the value is offset in memory, apply the offset now. - Address StorePtr = emitAddressAtOffset(*this, DestPtr, RetAI); - CreateCoercedStore(CI, StorePtr, DestIsVolatile, *this); - - return convertTempToRValue(DestPtr, RetTy, SourceLocation()); - } - - case ABIArgInfo::Expand: - llvm_unreachable("Invalid ABI kind for return argument"); - } - - llvm_unreachable("Unhandled ABIArgInfo::Kind"); - } (); - - // Emit the assume_aligned check on the return value. - const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl().getDecl(); - if (Ret.isScalar() && TargetDecl) { - if (const auto *AA = TargetDecl->getAttr<AssumeAlignedAttr>()) { - llvm::Value *OffsetValue = nullptr; - if (const auto *Offset = AA->getOffset()) - OffsetValue = EmitScalarExpr(Offset); - - llvm::Value *Alignment = EmitScalarExpr(AA->getAlignment()); - llvm::ConstantInt *AlignmentCI = cast<llvm::ConstantInt>(Alignment); - EmitAlignmentAssumption(Ret.getScalarVal(), RetTy, Loc, AA->getLocation(), - AlignmentCI->getZExtValue(), OffsetValue); - } else if (const auto *AA = TargetDecl->getAttr<AllocAlignAttr>()) { - llvm::Value *AlignmentVal = CallArgs[AA->getParamIndex().getLLVMIndex()] - .getRValue(*this) - .getScalarVal(); - EmitAlignmentAssumption(Ret.getScalarVal(), RetTy, Loc, AA->getLocation(), - AlignmentVal); - } - } - - return Ret; -} - -CGCallee CGCallee::prepareConcreteCallee(CodeGenFunction &CGF) const { - if (isVirtual()) { - const CallExpr *CE = getVirtualCallExpr(); - return CGF.CGM.getCXXABI().getVirtualFunctionPointer( - CGF, getVirtualMethodDecl(), getThisAddress(), getFunctionType(), - CE ? CE->getBeginLoc() : SourceLocation()); - } - - return *this; -} - -/* VarArg handling */ - -Address CodeGenFunction::EmitVAArg(VAArgExpr *VE, Address &VAListAddr) { - VAListAddr = VE->isMicrosoftABI() - ? EmitMSVAListRef(VE->getSubExpr()) - : EmitVAListRef(VE->getSubExpr()); - QualType Ty = VE->getType(); - if (VE->isMicrosoftABI()) - return CGM.getTypes().getABIInfo().EmitMSVAArg(*this, VAListAddr, Ty); - return CGM.getTypes().getABIInfo().EmitVAArg(*this, VAListAddr, Ty); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGCall.h b/gnu/llvm/tools/clang/lib/CodeGen/CGCall.h deleted file mode 100644 index c300808bea2..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGCall.h +++ /dev/null @@ -1,388 +0,0 @@ -//===----- CGCall.h - Encapsulate calling convention details ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// These classes wrap the information about a call or function -// definition used to handle ABI compliancy. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CGCALL_H -#define LLVM_CLANG_LIB_CODEGEN_CGCALL_H - -#include "CGValue.h" -#include "EHScopeStack.h" -#include "clang/AST/CanonicalType.h" -#include "clang/AST/GlobalDecl.h" -#include "clang/AST/Type.h" -#include "llvm/IR/Value.h" - -// FIXME: Restructure so we don't have to expose so much stuff. -#include "ABIInfo.h" - -namespace llvm { -class AttributeList; -class Function; -class Type; -class Value; -} - -namespace clang { - class ASTContext; - class Decl; - class FunctionDecl; - class ObjCMethodDecl; - class VarDecl; - -namespace CodeGen { - -/// Abstract information about a function or function prototype. -class CGCalleeInfo { - /// The function prototype of the callee. - const FunctionProtoType *CalleeProtoTy; - /// The function declaration of the callee. - GlobalDecl CalleeDecl; - -public: - explicit CGCalleeInfo() : CalleeProtoTy(nullptr), CalleeDecl() {} - CGCalleeInfo(const FunctionProtoType *calleeProtoTy, GlobalDecl calleeDecl) - : CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {} - CGCalleeInfo(const FunctionProtoType *calleeProtoTy) - : CalleeProtoTy(calleeProtoTy), CalleeDecl() {} - CGCalleeInfo(GlobalDecl calleeDecl) - : CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {} - - const FunctionProtoType *getCalleeFunctionProtoType() const { - return CalleeProtoTy; - } - const GlobalDecl getCalleeDecl() const { return CalleeDecl; } - }; - - /// All available information about a concrete callee. - class CGCallee { - enum class SpecialKind : uintptr_t { - Invalid, - Builtin, - PseudoDestructor, - Virtual, - - Last = Virtual - }; - - struct BuiltinInfoStorage { - const FunctionDecl *Decl; - unsigned ID; - }; - struct PseudoDestructorInfoStorage { - const CXXPseudoDestructorExpr *Expr; - }; - struct VirtualInfoStorage { - const CallExpr *CE; - GlobalDecl MD; - Address Addr; - llvm::FunctionType *FTy; - }; - - SpecialKind KindOrFunctionPointer; - union { - CGCalleeInfo AbstractInfo; - BuiltinInfoStorage BuiltinInfo; - PseudoDestructorInfoStorage PseudoDestructorInfo; - VirtualInfoStorage VirtualInfo; - }; - - explicit CGCallee(SpecialKind kind) : KindOrFunctionPointer(kind) {} - - CGCallee(const FunctionDecl *builtinDecl, unsigned builtinID) - : KindOrFunctionPointer(SpecialKind::Builtin) { - BuiltinInfo.Decl = builtinDecl; - BuiltinInfo.ID = builtinID; - } - - public: - CGCallee() : KindOrFunctionPointer(SpecialKind::Invalid) {} - - /// Construct a callee. Call this constructor directly when this - /// isn't a direct call. - CGCallee(const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr) - : KindOrFunctionPointer(SpecialKind(uintptr_t(functionPtr))) { - AbstractInfo = abstractInfo; - assert(functionPtr && "configuring callee without function pointer"); - assert(functionPtr->getType()->isPointerTy()); - assert(functionPtr->getType()->getPointerElementType()->isFunctionTy()); - } - - static CGCallee forBuiltin(unsigned builtinID, - const FunctionDecl *builtinDecl) { - CGCallee result(SpecialKind::Builtin); - result.BuiltinInfo.Decl = builtinDecl; - result.BuiltinInfo.ID = builtinID; - return result; - } - - static CGCallee forPseudoDestructor(const CXXPseudoDestructorExpr *E) { - CGCallee result(SpecialKind::PseudoDestructor); - result.PseudoDestructorInfo.Expr = E; - return result; - } - - static CGCallee forDirect(llvm::Constant *functionPtr, - const CGCalleeInfo &abstractInfo = CGCalleeInfo()) { - return CGCallee(abstractInfo, functionPtr); - } - - static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr, - llvm::FunctionType *FTy) { - CGCallee result(SpecialKind::Virtual); - result.VirtualInfo.CE = CE; - result.VirtualInfo.MD = MD; - result.VirtualInfo.Addr = Addr; - result.VirtualInfo.FTy = FTy; - return result; - } - - bool isBuiltin() const { - return KindOrFunctionPointer == SpecialKind::Builtin; - } - const FunctionDecl *getBuiltinDecl() const { - assert(isBuiltin()); - return BuiltinInfo.Decl; - } - unsigned getBuiltinID() const { - assert(isBuiltin()); - return BuiltinInfo.ID; - } - - bool isPseudoDestructor() const { - return KindOrFunctionPointer == SpecialKind::PseudoDestructor; - } - const CXXPseudoDestructorExpr *getPseudoDestructorExpr() const { - assert(isPseudoDestructor()); - return PseudoDestructorInfo.Expr; - } - - bool isOrdinary() const { - return uintptr_t(KindOrFunctionPointer) > uintptr_t(SpecialKind::Last); - } - CGCalleeInfo getAbstractInfo() const { - if (isVirtual()) - return VirtualInfo.MD; - assert(isOrdinary()); - return AbstractInfo; - } - llvm::Value *getFunctionPointer() const { - assert(isOrdinary()); - return reinterpret_cast<llvm::Value*>(uintptr_t(KindOrFunctionPointer)); - } - void setFunctionPointer(llvm::Value *functionPtr) { - assert(isOrdinary()); - KindOrFunctionPointer = SpecialKind(uintptr_t(functionPtr)); - } - - bool isVirtual() const { - return KindOrFunctionPointer == SpecialKind::Virtual; - } - const CallExpr *getVirtualCallExpr() const { - assert(isVirtual()); - return VirtualInfo.CE; - } - GlobalDecl getVirtualMethodDecl() const { - assert(isVirtual()); - return VirtualInfo.MD; - } - Address getThisAddress() const { - assert(isVirtual()); - return VirtualInfo.Addr; - } - - llvm::FunctionType *getFunctionType() const { - if (isVirtual()) - return VirtualInfo.FTy; - return cast<llvm::FunctionType>( - getFunctionPointer()->getType()->getPointerElementType()); - } - - /// If this is a delayed callee computation of some sort, prepare - /// a concrete callee. - CGCallee prepareConcreteCallee(CodeGenFunction &CGF) const; - }; - - struct CallArg { - private: - union { - RValue RV; - LValue LV; /// The argument is semantically a load from this l-value. - }; - bool HasLV; - - /// A data-flow flag to make sure getRValue and/or copyInto are not - /// called twice for duplicated IR emission. - mutable bool IsUsed; - - public: - QualType Ty; - CallArg(RValue rv, QualType ty) - : RV(rv), HasLV(false), IsUsed(false), Ty(ty) {} - CallArg(LValue lv, QualType ty) - : LV(lv), HasLV(true), IsUsed(false), Ty(ty) {} - bool hasLValue() const { return HasLV; } - QualType getType() const { return Ty; } - - /// \returns an independent RValue. If the CallArg contains an LValue, - /// a temporary copy is returned. - RValue getRValue(CodeGenFunction &CGF) const; - - LValue getKnownLValue() const { - assert(HasLV && !IsUsed); - return LV; - } - RValue getKnownRValue() const { - assert(!HasLV && !IsUsed); - return RV; - } - void setRValue(RValue _RV) { - assert(!HasLV); - RV = _RV; - } - - bool isAggregate() const { return HasLV || RV.isAggregate(); } - - void copyInto(CodeGenFunction &CGF, Address A) const; - }; - - /// CallArgList - Type for representing both the value and type of - /// arguments in a call. - class CallArgList : - public SmallVector<CallArg, 8> { - public: - CallArgList() : StackBase(nullptr) {} - - struct Writeback { - /// The original argument. Note that the argument l-value - /// is potentially null. - LValue Source; - - /// The temporary alloca. - Address Temporary; - - /// A value to "use" after the writeback, or null. - llvm::Value *ToUse; - }; - - struct CallArgCleanup { - EHScopeStack::stable_iterator Cleanup; - - /// The "is active" insertion point. This instruction is temporary and - /// will be removed after insertion. - llvm::Instruction *IsActiveIP; - }; - - void add(RValue rvalue, QualType type) { push_back(CallArg(rvalue, type)); } - - void addUncopiedAggregate(LValue LV, QualType type) { - push_back(CallArg(LV, type)); - } - - /// Add all the arguments from another CallArgList to this one. After doing - /// this, the old CallArgList retains its list of arguments, but must not - /// be used to emit a call. - void addFrom(const CallArgList &other) { - insert(end(), other.begin(), other.end()); - Writebacks.insert(Writebacks.end(), - other.Writebacks.begin(), other.Writebacks.end()); - CleanupsToDeactivate.insert(CleanupsToDeactivate.end(), - other.CleanupsToDeactivate.begin(), - other.CleanupsToDeactivate.end()); - assert(!(StackBase && other.StackBase) && "can't merge stackbases"); - if (!StackBase) - StackBase = other.StackBase; - } - - void addWriteback(LValue srcLV, Address temporary, - llvm::Value *toUse) { - Writeback writeback = { srcLV, temporary, toUse }; - Writebacks.push_back(writeback); - } - - bool hasWritebacks() const { return !Writebacks.empty(); } - - typedef llvm::iterator_range<SmallVectorImpl<Writeback>::const_iterator> - writeback_const_range; - - writeback_const_range writebacks() const { - return writeback_const_range(Writebacks.begin(), Writebacks.end()); - } - - void addArgCleanupDeactivation(EHScopeStack::stable_iterator Cleanup, - llvm::Instruction *IsActiveIP) { - CallArgCleanup ArgCleanup; - ArgCleanup.Cleanup = Cleanup; - ArgCleanup.IsActiveIP = IsActiveIP; - CleanupsToDeactivate.push_back(ArgCleanup); - } - - ArrayRef<CallArgCleanup> getCleanupsToDeactivate() const { - return CleanupsToDeactivate; - } - - void allocateArgumentMemory(CodeGenFunction &CGF); - llvm::Instruction *getStackBase() const { return StackBase; } - void freeArgumentMemory(CodeGenFunction &CGF) const; - - /// Returns if we're using an inalloca struct to pass arguments in - /// memory. - bool isUsingInAlloca() const { return StackBase; } - - private: - SmallVector<Writeback, 1> Writebacks; - - /// Deactivate these cleanups immediately before making the call. This - /// is used to cleanup objects that are owned by the callee once the call - /// occurs. - SmallVector<CallArgCleanup, 1> CleanupsToDeactivate; - - /// The stacksave call. It dominates all of the argument evaluation. - llvm::CallInst *StackBase; - }; - - /// FunctionArgList - Type for representing both the decl and type - /// of parameters to a function. The decl must be either a - /// ParmVarDecl or ImplicitParamDecl. - class FunctionArgList : public SmallVector<const VarDecl*, 16> { - }; - - /// ReturnValueSlot - Contains the address where the return value of a - /// function can be stored, and whether the address is volatile or not. - class ReturnValueSlot { - llvm::PointerIntPair<llvm::Value *, 2, unsigned int> Value; - CharUnits Alignment; - - // Return value slot flags - enum Flags { - IS_VOLATILE = 0x1, - IS_UNUSED = 0x2, - }; - - public: - ReturnValueSlot() {} - ReturnValueSlot(Address Addr, bool IsVolatile, bool IsUnused = false) - : Value(Addr.isValid() ? Addr.getPointer() : nullptr, - (IsVolatile ? IS_VOLATILE : 0) | (IsUnused ? IS_UNUSED : 0)), - Alignment(Addr.isValid() ? Addr.getAlignment() : CharUnits::Zero()) {} - - bool isNull() const { return !getValue().isValid(); } - - bool isVolatile() const { return Value.getInt() & IS_VOLATILE; } - Address getValue() const { return Address(Value.getPointer(), Alignment); } - bool isUnused() const { return Value.getInt() & IS_UNUSED; } - }; - -} // end namespace CodeGen -} // end namespace clang - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGClass.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGClass.cpp deleted file mode 100644 index ee150a792b7..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGClass.cpp +++ /dev/null @@ -1,2906 +0,0 @@ -//===--- CGClass.cpp - Emit LLVM Code for C++ classes -----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code dealing with C++ code generation of classes -// -//===----------------------------------------------------------------------===// - -#include "CGBlocks.h" -#include "CGCXXABI.h" -#include "CGDebugInfo.h" -#include "CGRecordLayout.h" -#include "CodeGenFunction.h" -#include "TargetInfo.h" -#include "clang/AST/CXXInheritance.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/EvaluatedExprVisitor.h" -#include "clang/AST/RecordLayout.h" -#include "clang/AST/StmtCXX.h" -#include "clang/Basic/CodeGenOptions.h" -#include "clang/Basic/TargetBuiltins.h" -#include "clang/CodeGen/CGFunctionInfo.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Metadata.h" -#include "llvm/Transforms/Utils/SanitizerStats.h" - -using namespace clang; -using namespace CodeGen; - -/// Return the best known alignment for an unknown pointer to a -/// particular class. -CharUnits CodeGenModule::getClassPointerAlignment(const CXXRecordDecl *RD) { - if (!RD->isCompleteDefinition()) - return CharUnits::One(); // Hopefully won't be used anywhere. - - auto &layout = getContext().getASTRecordLayout(RD); - - // If the class is final, then we know that the pointer points to an - // object of that type and can use the full alignment. - if (RD->hasAttr<FinalAttr>()) { - return layout.getAlignment(); - - // Otherwise, we have to assume it could be a subclass. - } else { - return layout.getNonVirtualAlignment(); - } -} - -/// Return the best known alignment for a pointer to a virtual base, -/// given the alignment of a pointer to the derived class. -CharUnits CodeGenModule::getVBaseAlignment(CharUnits actualDerivedAlign, - const CXXRecordDecl *derivedClass, - const CXXRecordDecl *vbaseClass) { - // The basic idea here is that an underaligned derived pointer might - // indicate an underaligned base pointer. - - assert(vbaseClass->isCompleteDefinition()); - auto &baseLayout = getContext().getASTRecordLayout(vbaseClass); - CharUnits expectedVBaseAlign = baseLayout.getNonVirtualAlignment(); - - return getDynamicOffsetAlignment(actualDerivedAlign, derivedClass, - expectedVBaseAlign); -} - -CharUnits -CodeGenModule::getDynamicOffsetAlignment(CharUnits actualBaseAlign, - const CXXRecordDecl *baseDecl, - CharUnits expectedTargetAlign) { - // If the base is an incomplete type (which is, alas, possible with - // member pointers), be pessimistic. - if (!baseDecl->isCompleteDefinition()) - return std::min(actualBaseAlign, expectedTargetAlign); - - auto &baseLayout = getContext().getASTRecordLayout(baseDecl); - CharUnits expectedBaseAlign = baseLayout.getNonVirtualAlignment(); - - // If the class is properly aligned, assume the target offset is, too. - // - // This actually isn't necessarily the right thing to do --- if the - // class is a complete object, but it's only properly aligned for a - // base subobject, then the alignments of things relative to it are - // probably off as well. (Note that this requires the alignment of - // the target to be greater than the NV alignment of the derived - // class.) - // - // However, our approach to this kind of under-alignment can only - // ever be best effort; after all, we're never going to propagate - // alignments through variables or parameters. Note, in particular, - // that constructing a polymorphic type in an address that's less - // than pointer-aligned will generally trap in the constructor, - // unless we someday add some sort of attribute to change the - // assumed alignment of 'this'. So our goal here is pretty much - // just to allow the user to explicitly say that a pointer is - // under-aligned and then safely access its fields and vtables. - if (actualBaseAlign >= expectedBaseAlign) { - return expectedTargetAlign; - } - - // Otherwise, we might be offset by an arbitrary multiple of the - // actual alignment. The correct adjustment is to take the min of - // the two alignments. - return std::min(actualBaseAlign, expectedTargetAlign); -} - -Address CodeGenFunction::LoadCXXThisAddress() { - assert(CurFuncDecl && "loading 'this' without a func declaration?"); - assert(isa<CXXMethodDecl>(CurFuncDecl)); - - // Lazily compute CXXThisAlignment. - if (CXXThisAlignment.isZero()) { - // Just use the best known alignment for the parent. - // TODO: if we're currently emitting a complete-object ctor/dtor, - // we can always use the complete-object alignment. - auto RD = cast<CXXMethodDecl>(CurFuncDecl)->getParent(); - CXXThisAlignment = CGM.getClassPointerAlignment(RD); - } - - return Address(LoadCXXThis(), CXXThisAlignment); -} - -/// Emit the address of a field using a member data pointer. -/// -/// \param E Only used for emergency diagnostics -Address -CodeGenFunction::EmitCXXMemberDataPointerAddress(const Expr *E, Address base, - llvm::Value *memberPtr, - const MemberPointerType *memberPtrType, - LValueBaseInfo *BaseInfo, - TBAAAccessInfo *TBAAInfo) { - // Ask the ABI to compute the actual address. - llvm::Value *ptr = - CGM.getCXXABI().EmitMemberDataPointerAddress(*this, E, base, - memberPtr, memberPtrType); - - QualType memberType = memberPtrType->getPointeeType(); - CharUnits memberAlign = getNaturalTypeAlignment(memberType, BaseInfo, - TBAAInfo); - memberAlign = - CGM.getDynamicOffsetAlignment(base.getAlignment(), - memberPtrType->getClass()->getAsCXXRecordDecl(), - memberAlign); - return Address(ptr, memberAlign); -} - -CharUnits CodeGenModule::computeNonVirtualBaseClassOffset( - const CXXRecordDecl *DerivedClass, CastExpr::path_const_iterator Start, - CastExpr::path_const_iterator End) { - CharUnits Offset = CharUnits::Zero(); - - const ASTContext &Context = getContext(); - const CXXRecordDecl *RD = DerivedClass; - - for (CastExpr::path_const_iterator I = Start; I != End; ++I) { - const CXXBaseSpecifier *Base = *I; - assert(!Base->isVirtual() && "Should not see virtual bases here!"); - - // Get the layout. - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - - // Add the offset. - Offset += Layout.getBaseClassOffset(BaseDecl); - - RD = BaseDecl; - } - - return Offset; -} - -llvm::Constant * -CodeGenModule::GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl, - CastExpr::path_const_iterator PathBegin, - CastExpr::path_const_iterator PathEnd) { - assert(PathBegin != PathEnd && "Base path should not be empty!"); - - CharUnits Offset = - computeNonVirtualBaseClassOffset(ClassDecl, PathBegin, PathEnd); - if (Offset.isZero()) - return nullptr; - - llvm::Type *PtrDiffTy = - Types.ConvertType(getContext().getPointerDiffType()); - - return llvm::ConstantInt::get(PtrDiffTy, Offset.getQuantity()); -} - -/// Gets the address of a direct base class within a complete object. -/// This should only be used for (1) non-virtual bases or (2) virtual bases -/// when the type is known to be complete (e.g. in complete destructors). -/// -/// The object pointed to by 'This' is assumed to be non-null. -Address -CodeGenFunction::GetAddressOfDirectBaseInCompleteClass(Address This, - const CXXRecordDecl *Derived, - const CXXRecordDecl *Base, - bool BaseIsVirtual) { - // 'this' must be a pointer (in some address space) to Derived. - assert(This.getElementType() == ConvertType(Derived)); - - // Compute the offset of the virtual base. - CharUnits Offset; - const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Derived); - if (BaseIsVirtual) - Offset = Layout.getVBaseClassOffset(Base); - else - Offset = Layout.getBaseClassOffset(Base); - - // Shift and cast down to the base type. - // TODO: for complete types, this should be possible with a GEP. - Address V = This; - if (!Offset.isZero()) { - V = Builder.CreateElementBitCast(V, Int8Ty); - V = Builder.CreateConstInBoundsByteGEP(V, Offset); - } - V = Builder.CreateElementBitCast(V, ConvertType(Base)); - - return V; -} - -static Address -ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, Address addr, - CharUnits nonVirtualOffset, - llvm::Value *virtualOffset, - const CXXRecordDecl *derivedClass, - const CXXRecordDecl *nearestVBase) { - // Assert that we have something to do. - assert(!nonVirtualOffset.isZero() || virtualOffset != nullptr); - - // Compute the offset from the static and dynamic components. - llvm::Value *baseOffset; - if (!nonVirtualOffset.isZero()) { - baseOffset = llvm::ConstantInt::get(CGF.PtrDiffTy, - nonVirtualOffset.getQuantity()); - if (virtualOffset) { - baseOffset = CGF.Builder.CreateAdd(virtualOffset, baseOffset); - } - } else { - baseOffset = virtualOffset; - } - - // Apply the base offset. - llvm::Value *ptr = addr.getPointer(); - ptr = CGF.Builder.CreateBitCast(ptr, CGF.Int8PtrTy); - ptr = CGF.Builder.CreateInBoundsGEP(ptr, baseOffset, "add.ptr"); - - // If we have a virtual component, the alignment of the result will - // be relative only to the known alignment of that vbase. - CharUnits alignment; - if (virtualOffset) { - assert(nearestVBase && "virtual offset without vbase?"); - alignment = CGF.CGM.getVBaseAlignment(addr.getAlignment(), - derivedClass, nearestVBase); - } else { - alignment = addr.getAlignment(); - } - alignment = alignment.alignmentAtOffset(nonVirtualOffset); - - return Address(ptr, alignment); -} - -Address CodeGenFunction::GetAddressOfBaseClass( - Address Value, const CXXRecordDecl *Derived, - CastExpr::path_const_iterator PathBegin, - CastExpr::path_const_iterator PathEnd, bool NullCheckValue, - SourceLocation Loc) { - assert(PathBegin != PathEnd && "Base path should not be empty!"); - - CastExpr::path_const_iterator Start = PathBegin; - const CXXRecordDecl *VBase = nullptr; - - // Sema has done some convenient canonicalization here: if the - // access path involved any virtual steps, the conversion path will - // *start* with a step down to the correct virtual base subobject, - // and hence will not require any further steps. - if ((*Start)->isVirtual()) { - VBase = - cast<CXXRecordDecl>((*Start)->getType()->getAs<RecordType>()->getDecl()); - ++Start; - } - - // Compute the static offset of the ultimate destination within its - // allocating subobject (the virtual base, if there is one, or else - // the "complete" object that we see). - CharUnits NonVirtualOffset = CGM.computeNonVirtualBaseClassOffset( - VBase ? VBase : Derived, Start, PathEnd); - - // If there's a virtual step, we can sometimes "devirtualize" it. - // For now, that's limited to when the derived type is final. - // TODO: "devirtualize" this for accesses to known-complete objects. - if (VBase && Derived->hasAttr<FinalAttr>()) { - const ASTRecordLayout &layout = getContext().getASTRecordLayout(Derived); - CharUnits vBaseOffset = layout.getVBaseClassOffset(VBase); - NonVirtualOffset += vBaseOffset; - VBase = nullptr; // we no longer have a virtual step - } - - // Get the base pointer type. - llvm::Type *BasePtrTy = - ConvertType((PathEnd[-1])->getType())->getPointerTo(); - - QualType DerivedTy = getContext().getRecordType(Derived); - CharUnits DerivedAlign = CGM.getClassPointerAlignment(Derived); - - // If the static offset is zero and we don't have a virtual step, - // just do a bitcast; null checks are unnecessary. - if (NonVirtualOffset.isZero() && !VBase) { - if (sanitizePerformTypeCheck()) { - SanitizerSet SkippedChecks; - SkippedChecks.set(SanitizerKind::Null, !NullCheckValue); - EmitTypeCheck(TCK_Upcast, Loc, Value.getPointer(), - DerivedTy, DerivedAlign, SkippedChecks); - } - return Builder.CreateBitCast(Value, BasePtrTy); - } - - llvm::BasicBlock *origBB = nullptr; - llvm::BasicBlock *endBB = nullptr; - - // Skip over the offset (and the vtable load) if we're supposed to - // null-check the pointer. - if (NullCheckValue) { - origBB = Builder.GetInsertBlock(); - llvm::BasicBlock *notNullBB = createBasicBlock("cast.notnull"); - endBB = createBasicBlock("cast.end"); - - llvm::Value *isNull = Builder.CreateIsNull(Value.getPointer()); - Builder.CreateCondBr(isNull, endBB, notNullBB); - EmitBlock(notNullBB); - } - - if (sanitizePerformTypeCheck()) { - SanitizerSet SkippedChecks; - SkippedChecks.set(SanitizerKind::Null, true); - EmitTypeCheck(VBase ? TCK_UpcastToVirtualBase : TCK_Upcast, Loc, - Value.getPointer(), DerivedTy, DerivedAlign, SkippedChecks); - } - - // Compute the virtual offset. - llvm::Value *VirtualOffset = nullptr; - if (VBase) { - VirtualOffset = - CGM.getCXXABI().GetVirtualBaseClassOffset(*this, Value, Derived, VBase); - } - - // Apply both offsets. - Value = ApplyNonVirtualAndVirtualOffset(*this, Value, NonVirtualOffset, - VirtualOffset, Derived, VBase); - - // Cast to the destination type. - Value = Builder.CreateBitCast(Value, BasePtrTy); - - // Build a phi if we needed a null check. - if (NullCheckValue) { - llvm::BasicBlock *notNullBB = Builder.GetInsertBlock(); - Builder.CreateBr(endBB); - EmitBlock(endBB); - - llvm::PHINode *PHI = Builder.CreatePHI(BasePtrTy, 2, "cast.result"); - PHI->addIncoming(Value.getPointer(), notNullBB); - PHI->addIncoming(llvm::Constant::getNullValue(BasePtrTy), origBB); - Value = Address(PHI, Value.getAlignment()); - } - - return Value; -} - -Address -CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr, - const CXXRecordDecl *Derived, - CastExpr::path_const_iterator PathBegin, - CastExpr::path_const_iterator PathEnd, - bool NullCheckValue) { - assert(PathBegin != PathEnd && "Base path should not be empty!"); - - QualType DerivedTy = - getContext().getCanonicalType(getContext().getTagDeclType(Derived)); - llvm::Type *DerivedPtrTy = ConvertType(DerivedTy)->getPointerTo(); - - llvm::Value *NonVirtualOffset = - CGM.GetNonVirtualBaseClassOffset(Derived, PathBegin, PathEnd); - - if (!NonVirtualOffset) { - // No offset, we can just cast back. - return Builder.CreateBitCast(BaseAddr, DerivedPtrTy); - } - - llvm::BasicBlock *CastNull = nullptr; - llvm::BasicBlock *CastNotNull = nullptr; - llvm::BasicBlock *CastEnd = nullptr; - - if (NullCheckValue) { - CastNull = createBasicBlock("cast.null"); - CastNotNull = createBasicBlock("cast.notnull"); - CastEnd = createBasicBlock("cast.end"); - - llvm::Value *IsNull = Builder.CreateIsNull(BaseAddr.getPointer()); - Builder.CreateCondBr(IsNull, CastNull, CastNotNull); - EmitBlock(CastNotNull); - } - - // Apply the offset. - llvm::Value *Value = Builder.CreateBitCast(BaseAddr.getPointer(), Int8PtrTy); - Value = Builder.CreateInBoundsGEP(Value, Builder.CreateNeg(NonVirtualOffset), - "sub.ptr"); - - // Just cast. - Value = Builder.CreateBitCast(Value, DerivedPtrTy); - - // Produce a PHI if we had a null-check. - if (NullCheckValue) { - Builder.CreateBr(CastEnd); - EmitBlock(CastNull); - Builder.CreateBr(CastEnd); - EmitBlock(CastEnd); - - llvm::PHINode *PHI = Builder.CreatePHI(Value->getType(), 2); - PHI->addIncoming(Value, CastNotNull); - PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), CastNull); - Value = PHI; - } - - return Address(Value, CGM.getClassPointerAlignment(Derived)); -} - -llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD, - bool ForVirtualBase, - bool Delegating) { - if (!CGM.getCXXABI().NeedsVTTParameter(GD)) { - // This constructor/destructor does not need a VTT parameter. - return nullptr; - } - - const CXXRecordDecl *RD = cast<CXXMethodDecl>(CurCodeDecl)->getParent(); - const CXXRecordDecl *Base = cast<CXXMethodDecl>(GD.getDecl())->getParent(); - - llvm::Value *VTT; - - uint64_t SubVTTIndex; - - if (Delegating) { - // If this is a delegating constructor call, just load the VTT. - return LoadCXXVTT(); - } else if (RD == Base) { - // If the record matches the base, this is the complete ctor/dtor - // variant calling the base variant in a class with virtual bases. - assert(!CGM.getCXXABI().NeedsVTTParameter(CurGD) && - "doing no-op VTT offset in base dtor/ctor?"); - assert(!ForVirtualBase && "Can't have same class as virtual base!"); - SubVTTIndex = 0; - } else { - const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); - CharUnits BaseOffset = ForVirtualBase ? - Layout.getVBaseClassOffset(Base) : - Layout.getBaseClassOffset(Base); - - SubVTTIndex = - CGM.getVTables().getSubVTTIndex(RD, BaseSubobject(Base, BaseOffset)); - assert(SubVTTIndex != 0 && "Sub-VTT index must be greater than zero!"); - } - - if (CGM.getCXXABI().NeedsVTTParameter(CurGD)) { - // A VTT parameter was passed to the constructor, use it. - VTT = LoadCXXVTT(); - VTT = Builder.CreateConstInBoundsGEP1_64(VTT, SubVTTIndex); - } else { - // We're the complete constructor, so get the VTT by name. - VTT = CGM.getVTables().GetAddrOfVTT(RD); - VTT = Builder.CreateConstInBoundsGEP2_64(VTT, 0, SubVTTIndex); - } - - return VTT; -} - -namespace { - /// Call the destructor for a direct base class. - struct CallBaseDtor final : EHScopeStack::Cleanup { - const CXXRecordDecl *BaseClass; - bool BaseIsVirtual; - CallBaseDtor(const CXXRecordDecl *Base, bool BaseIsVirtual) - : BaseClass(Base), BaseIsVirtual(BaseIsVirtual) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - const CXXRecordDecl *DerivedClass = - cast<CXXMethodDecl>(CGF.CurCodeDecl)->getParent(); - - const CXXDestructorDecl *D = BaseClass->getDestructor(); - Address Addr = - CGF.GetAddressOfDirectBaseInCompleteClass(CGF.LoadCXXThisAddress(), - DerivedClass, BaseClass, - BaseIsVirtual); - CGF.EmitCXXDestructorCall(D, Dtor_Base, BaseIsVirtual, - /*Delegating=*/false, Addr); - } - }; - - /// A visitor which checks whether an initializer uses 'this' in a - /// way which requires the vtable to be properly set. - struct DynamicThisUseChecker : ConstEvaluatedExprVisitor<DynamicThisUseChecker> { - typedef ConstEvaluatedExprVisitor<DynamicThisUseChecker> super; - - bool UsesThis; - - DynamicThisUseChecker(const ASTContext &C) : super(C), UsesThis(false) {} - - // Black-list all explicit and implicit references to 'this'. - // - // Do we need to worry about external references to 'this' derived - // from arbitrary code? If so, then anything which runs arbitrary - // external code might potentially access the vtable. - void VisitCXXThisExpr(const CXXThisExpr *E) { UsesThis = true; } - }; -} // end anonymous namespace - -static bool BaseInitializerUsesThis(ASTContext &C, const Expr *Init) { - DynamicThisUseChecker Checker(C); - Checker.Visit(Init); - return Checker.UsesThis; -} - -static void EmitBaseInitializer(CodeGenFunction &CGF, - const CXXRecordDecl *ClassDecl, - CXXCtorInitializer *BaseInit, - CXXCtorType CtorType) { - assert(BaseInit->isBaseInitializer() && - "Must have base initializer!"); - - Address ThisPtr = CGF.LoadCXXThisAddress(); - - const Type *BaseType = BaseInit->getBaseClass(); - CXXRecordDecl *BaseClassDecl = - cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl()); - - bool isBaseVirtual = BaseInit->isBaseVirtual(); - - // The base constructor doesn't construct virtual bases. - if (CtorType == Ctor_Base && isBaseVirtual) - return; - - // If the initializer for the base (other than the constructor - // itself) accesses 'this' in any way, we need to initialize the - // vtables. - if (BaseInitializerUsesThis(CGF.getContext(), BaseInit->getInit())) - CGF.InitializeVTablePointers(ClassDecl); - - // We can pretend to be a complete class because it only matters for - // virtual bases, and we only do virtual bases for complete ctors. - Address V = - CGF.GetAddressOfDirectBaseInCompleteClass(ThisPtr, ClassDecl, - BaseClassDecl, - isBaseVirtual); - AggValueSlot AggSlot = - AggValueSlot::forAddr( - V, Qualifiers(), - AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - CGF.overlapForBaseInit(ClassDecl, BaseClassDecl, isBaseVirtual)); - - CGF.EmitAggExpr(BaseInit->getInit(), AggSlot); - - if (CGF.CGM.getLangOpts().Exceptions && - !BaseClassDecl->hasTrivialDestructor()) - CGF.EHStack.pushCleanup<CallBaseDtor>(EHCleanup, BaseClassDecl, - isBaseVirtual); -} - -static bool isMemcpyEquivalentSpecialMember(const CXXMethodDecl *D) { - auto *CD = dyn_cast<CXXConstructorDecl>(D); - if (!(CD && CD->isCopyOrMoveConstructor()) && - !D->isCopyAssignmentOperator() && !D->isMoveAssignmentOperator()) - return false; - - // We can emit a memcpy for a trivial copy or move constructor/assignment. - if (D->isTrivial() && !D->getParent()->mayInsertExtraPadding()) - return true; - - // We *must* emit a memcpy for a defaulted union copy or move op. - if (D->getParent()->isUnion() && D->isDefaulted()) - return true; - - return false; -} - -static void EmitLValueForAnyFieldInitialization(CodeGenFunction &CGF, - CXXCtorInitializer *MemberInit, - LValue &LHS) { - FieldDecl *Field = MemberInit->getAnyMember(); - if (MemberInit->isIndirectMemberInitializer()) { - // If we are initializing an anonymous union field, drill down to the field. - IndirectFieldDecl *IndirectField = MemberInit->getIndirectMember(); - for (const auto *I : IndirectField->chain()) - LHS = CGF.EmitLValueForFieldInitialization(LHS, cast<FieldDecl>(I)); - } else { - LHS = CGF.EmitLValueForFieldInitialization(LHS, Field); - } -} - -static void EmitMemberInitializer(CodeGenFunction &CGF, - const CXXRecordDecl *ClassDecl, - CXXCtorInitializer *MemberInit, - const CXXConstructorDecl *Constructor, - FunctionArgList &Args) { - ApplyDebugLocation Loc(CGF, MemberInit->getSourceLocation()); - assert(MemberInit->isAnyMemberInitializer() && - "Must have member initializer!"); - assert(MemberInit->getInit() && "Must have initializer!"); - - // non-static data member initializers. - FieldDecl *Field = MemberInit->getAnyMember(); - QualType FieldType = Field->getType(); - - llvm::Value *ThisPtr = CGF.LoadCXXThis(); - QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl); - LValue LHS; - - // If a base constructor is being emitted, create an LValue that has the - // non-virtual alignment. - if (CGF.CurGD.getCtorType() == Ctor_Base) - LHS = CGF.MakeNaturalAlignPointeeAddrLValue(ThisPtr, RecordTy); - else - LHS = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy); - - EmitLValueForAnyFieldInitialization(CGF, MemberInit, LHS); - - // Special case: if we are in a copy or move constructor, and we are copying - // an array of PODs or classes with trivial copy constructors, ignore the - // AST and perform the copy we know is equivalent. - // FIXME: This is hacky at best... if we had a bit more explicit information - // in the AST, we could generalize it more easily. - const ConstantArrayType *Array - = CGF.getContext().getAsConstantArrayType(FieldType); - if (Array && Constructor->isDefaulted() && - Constructor->isCopyOrMoveConstructor()) { - QualType BaseElementTy = CGF.getContext().getBaseElementType(Array); - CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(MemberInit->getInit()); - if (BaseElementTy.isPODType(CGF.getContext()) || - (CE && isMemcpyEquivalentSpecialMember(CE->getConstructor()))) { - unsigned SrcArgIndex = - CGF.CGM.getCXXABI().getSrcArgforCopyCtor(Constructor, Args); - llvm::Value *SrcPtr - = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(Args[SrcArgIndex])); - LValue ThisRHSLV = CGF.MakeNaturalAlignAddrLValue(SrcPtr, RecordTy); - LValue Src = CGF.EmitLValueForFieldInitialization(ThisRHSLV, Field); - - // Copy the aggregate. - CGF.EmitAggregateCopy(LHS, Src, FieldType, CGF.overlapForFieldInit(Field), - LHS.isVolatileQualified()); - // Ensure that we destroy the objects if an exception is thrown later in - // the constructor. - QualType::DestructionKind dtorKind = FieldType.isDestructedType(); - if (CGF.needsEHCleanup(dtorKind)) - CGF.pushEHDestroy(dtorKind, LHS.getAddress(), FieldType); - return; - } - } - - CGF.EmitInitializerForField(Field, LHS, MemberInit->getInit()); -} - -void CodeGenFunction::EmitInitializerForField(FieldDecl *Field, LValue LHS, - Expr *Init) { - QualType FieldType = Field->getType(); - switch (getEvaluationKind(FieldType)) { - case TEK_Scalar: - if (LHS.isSimple()) { - EmitExprAsInit(Init, Field, LHS, false); - } else { - RValue RHS = RValue::get(EmitScalarExpr(Init)); - EmitStoreThroughLValue(RHS, LHS); - } - break; - case TEK_Complex: - EmitComplexExprIntoLValue(Init, LHS, /*isInit*/ true); - break; - case TEK_Aggregate: { - AggValueSlot Slot = - AggValueSlot::forLValue( - LHS, - AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - overlapForFieldInit(Field), - AggValueSlot::IsNotZeroed, - // Checks are made by the code that calls constructor. - AggValueSlot::IsSanitizerChecked); - EmitAggExpr(Init, Slot); - break; - } - } - - // Ensure that we destroy this object if an exception is thrown - // later in the constructor. - QualType::DestructionKind dtorKind = FieldType.isDestructedType(); - if (needsEHCleanup(dtorKind)) - pushEHDestroy(dtorKind, LHS.getAddress(), FieldType); -} - -/// Checks whether the given constructor is a valid subject for the -/// complete-to-base constructor delegation optimization, i.e. -/// emitting the complete constructor as a simple call to the base -/// constructor. -bool CodeGenFunction::IsConstructorDelegationValid( - const CXXConstructorDecl *Ctor) { - - // Currently we disable the optimization for classes with virtual - // bases because (1) the addresses of parameter variables need to be - // consistent across all initializers but (2) the delegate function - // call necessarily creates a second copy of the parameter variable. - // - // The limiting example (purely theoretical AFAIK): - // struct A { A(int &c) { c++; } }; - // struct B : virtual A { - // B(int count) : A(count) { printf("%d\n", count); } - // }; - // ...although even this example could in principle be emitted as a - // delegation since the address of the parameter doesn't escape. - if (Ctor->getParent()->getNumVBases()) { - // TODO: white-list trivial vbase initializers. This case wouldn't - // be subject to the restrictions below. - - // TODO: white-list cases where: - // - there are no non-reference parameters to the constructor - // - the initializers don't access any non-reference parameters - // - the initializers don't take the address of non-reference - // parameters - // - etc. - // If we ever add any of the above cases, remember that: - // - function-try-blocks will always blacklist this optimization - // - we need to perform the constructor prologue and cleanup in - // EmitConstructorBody. - - return false; - } - - // We also disable the optimization for variadic functions because - // it's impossible to "re-pass" varargs. - if (Ctor->getType()->getAs<FunctionProtoType>()->isVariadic()) - return false; - - // FIXME: Decide if we can do a delegation of a delegating constructor. - if (Ctor->isDelegatingConstructor()) - return false; - - return true; -} - -// Emit code in ctor (Prologue==true) or dtor (Prologue==false) -// to poison the extra field paddings inserted under -// -fsanitize-address-field-padding=1|2. -void CodeGenFunction::EmitAsanPrologueOrEpilogue(bool Prologue) { - ASTContext &Context = getContext(); - const CXXRecordDecl *ClassDecl = - Prologue ? cast<CXXConstructorDecl>(CurGD.getDecl())->getParent() - : cast<CXXDestructorDecl>(CurGD.getDecl())->getParent(); - if (!ClassDecl->mayInsertExtraPadding()) return; - - struct SizeAndOffset { - uint64_t Size; - uint64_t Offset; - }; - - unsigned PtrSize = CGM.getDataLayout().getPointerSizeInBits(); - const ASTRecordLayout &Info = Context.getASTRecordLayout(ClassDecl); - - // Populate sizes and offsets of fields. - SmallVector<SizeAndOffset, 16> SSV(Info.getFieldCount()); - for (unsigned i = 0, e = Info.getFieldCount(); i != e; ++i) - SSV[i].Offset = - Context.toCharUnitsFromBits(Info.getFieldOffset(i)).getQuantity(); - - size_t NumFields = 0; - for (const auto *Field : ClassDecl->fields()) { - const FieldDecl *D = Field; - std::pair<CharUnits, CharUnits> FieldInfo = - Context.getTypeInfoInChars(D->getType()); - CharUnits FieldSize = FieldInfo.first; - assert(NumFields < SSV.size()); - SSV[NumFields].Size = D->isBitField() ? 0 : FieldSize.getQuantity(); - NumFields++; - } - assert(NumFields == SSV.size()); - if (SSV.size() <= 1) return; - - // We will insert calls to __asan_* run-time functions. - // LLVM AddressSanitizer pass may decide to inline them later. - llvm::Type *Args[2] = {IntPtrTy, IntPtrTy}; - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, Args, false); - llvm::Constant *F = CGM.CreateRuntimeFunction( - FTy, Prologue ? "__asan_poison_intra_object_redzone" - : "__asan_unpoison_intra_object_redzone"); - - llvm::Value *ThisPtr = LoadCXXThis(); - ThisPtr = Builder.CreatePtrToInt(ThisPtr, IntPtrTy); - uint64_t TypeSize = Info.getNonVirtualSize().getQuantity(); - // For each field check if it has sufficient padding, - // if so (un)poison it with a call. - for (size_t i = 0; i < SSV.size(); i++) { - uint64_t AsanAlignment = 8; - uint64_t NextField = i == SSV.size() - 1 ? TypeSize : SSV[i + 1].Offset; - uint64_t PoisonSize = NextField - SSV[i].Offset - SSV[i].Size; - uint64_t EndOffset = SSV[i].Offset + SSV[i].Size; - if (PoisonSize < AsanAlignment || !SSV[i].Size || - (NextField % AsanAlignment) != 0) - continue; - Builder.CreateCall( - F, {Builder.CreateAdd(ThisPtr, Builder.getIntN(PtrSize, EndOffset)), - Builder.getIntN(PtrSize, PoisonSize)}); - } -} - -/// EmitConstructorBody - Emits the body of the current constructor. -void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) { - EmitAsanPrologueOrEpilogue(true); - const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(CurGD.getDecl()); - CXXCtorType CtorType = CurGD.getCtorType(); - - assert((CGM.getTarget().getCXXABI().hasConstructorVariants() || - CtorType == Ctor_Complete) && - "can only generate complete ctor for this ABI"); - - // Before we go any further, try the complete->base constructor - // delegation optimization. - if (CtorType == Ctor_Complete && IsConstructorDelegationValid(Ctor) && - CGM.getTarget().getCXXABI().hasConstructorVariants()) { - EmitDelegateCXXConstructorCall(Ctor, Ctor_Base, Args, Ctor->getEndLoc()); - return; - } - - const FunctionDecl *Definition = nullptr; - Stmt *Body = Ctor->getBody(Definition); - assert(Definition == Ctor && "emitting wrong constructor body"); - - // Enter the function-try-block before the constructor prologue if - // applicable. - bool IsTryBody = (Body && isa<CXXTryStmt>(Body)); - if (IsTryBody) - EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true); - - incrementProfileCounter(Body); - - RunCleanupsScope RunCleanups(*this); - - // TODO: in restricted cases, we can emit the vbase initializers of - // a complete ctor and then delegate to the base ctor. - - // Emit the constructor prologue, i.e. the base and member - // initializers. - EmitCtorPrologue(Ctor, CtorType, Args); - - // Emit the body of the statement. - if (IsTryBody) - EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock()); - else if (Body) - EmitStmt(Body); - - // Emit any cleanup blocks associated with the member or base - // initializers, which includes (along the exceptional path) the - // destructors for those members and bases that were fully - // constructed. - RunCleanups.ForceCleanup(); - - if (IsTryBody) - ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true); -} - -namespace { - /// RAII object to indicate that codegen is copying the value representation - /// instead of the object representation. Useful when copying a struct or - /// class which has uninitialized members and we're only performing - /// lvalue-to-rvalue conversion on the object but not its members. - class CopyingValueRepresentation { - public: - explicit CopyingValueRepresentation(CodeGenFunction &CGF) - : CGF(CGF), OldSanOpts(CGF.SanOpts) { - CGF.SanOpts.set(SanitizerKind::Bool, false); - CGF.SanOpts.set(SanitizerKind::Enum, false); - } - ~CopyingValueRepresentation() { - CGF.SanOpts = OldSanOpts; - } - private: - CodeGenFunction &CGF; - SanitizerSet OldSanOpts; - }; -} // end anonymous namespace - -namespace { - class FieldMemcpyizer { - public: - FieldMemcpyizer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl, - const VarDecl *SrcRec) - : CGF(CGF), ClassDecl(ClassDecl), SrcRec(SrcRec), - RecLayout(CGF.getContext().getASTRecordLayout(ClassDecl)), - FirstField(nullptr), LastField(nullptr), FirstFieldOffset(0), - LastFieldOffset(0), LastAddedFieldIndex(0) {} - - bool isMemcpyableField(FieldDecl *F) const { - // Never memcpy fields when we are adding poisoned paddings. - if (CGF.getContext().getLangOpts().SanitizeAddressFieldPadding) - return false; - Qualifiers Qual = F->getType().getQualifiers(); - if (Qual.hasVolatile() || Qual.hasObjCLifetime()) - return false; - return true; - } - - void addMemcpyableField(FieldDecl *F) { - if (!FirstField) - addInitialField(F); - else - addNextField(F); - } - - CharUnits getMemcpySize(uint64_t FirstByteOffset) const { - ASTContext &Ctx = CGF.getContext(); - unsigned LastFieldSize = - LastField->isBitField() - ? LastField->getBitWidthValue(Ctx) - : Ctx.toBits( - Ctx.getTypeInfoDataSizeInChars(LastField->getType()).first); - uint64_t MemcpySizeBits = LastFieldOffset + LastFieldSize - - FirstByteOffset + Ctx.getCharWidth() - 1; - CharUnits MemcpySize = Ctx.toCharUnitsFromBits(MemcpySizeBits); - return MemcpySize; - } - - void emitMemcpy() { - // Give the subclass a chance to bail out if it feels the memcpy isn't - // worth it (e.g. Hasn't aggregated enough data). - if (!FirstField) { - return; - } - - uint64_t FirstByteOffset; - if (FirstField->isBitField()) { - const CGRecordLayout &RL = - CGF.getTypes().getCGRecordLayout(FirstField->getParent()); - const CGBitFieldInfo &BFInfo = RL.getBitFieldInfo(FirstField); - // FirstFieldOffset is not appropriate for bitfields, - // we need to use the storage offset instead. - FirstByteOffset = CGF.getContext().toBits(BFInfo.StorageOffset); - } else { - FirstByteOffset = FirstFieldOffset; - } - - CharUnits MemcpySize = getMemcpySize(FirstByteOffset); - QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl); - Address ThisPtr = CGF.LoadCXXThisAddress(); - LValue DestLV = CGF.MakeAddrLValue(ThisPtr, RecordTy); - LValue Dest = CGF.EmitLValueForFieldInitialization(DestLV, FirstField); - llvm::Value *SrcPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(SrcRec)); - LValue SrcLV = CGF.MakeNaturalAlignAddrLValue(SrcPtr, RecordTy); - LValue Src = CGF.EmitLValueForFieldInitialization(SrcLV, FirstField); - - emitMemcpyIR(Dest.isBitField() ? Dest.getBitFieldAddress() : Dest.getAddress(), - Src.isBitField() ? Src.getBitFieldAddress() : Src.getAddress(), - MemcpySize); - reset(); - } - - void reset() { - FirstField = nullptr; - } - - protected: - CodeGenFunction &CGF; - const CXXRecordDecl *ClassDecl; - - private: - void emitMemcpyIR(Address DestPtr, Address SrcPtr, CharUnits Size) { - llvm::PointerType *DPT = DestPtr.getType(); - llvm::Type *DBP = - llvm::Type::getInt8PtrTy(CGF.getLLVMContext(), DPT->getAddressSpace()); - DestPtr = CGF.Builder.CreateBitCast(DestPtr, DBP); - - llvm::PointerType *SPT = SrcPtr.getType(); - llvm::Type *SBP = - llvm::Type::getInt8PtrTy(CGF.getLLVMContext(), SPT->getAddressSpace()); - SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, SBP); - - CGF.Builder.CreateMemCpy(DestPtr, SrcPtr, Size.getQuantity()); - } - - void addInitialField(FieldDecl *F) { - FirstField = F; - LastField = F; - FirstFieldOffset = RecLayout.getFieldOffset(F->getFieldIndex()); - LastFieldOffset = FirstFieldOffset; - LastAddedFieldIndex = F->getFieldIndex(); - } - - void addNextField(FieldDecl *F) { - // For the most part, the following invariant will hold: - // F->getFieldIndex() == LastAddedFieldIndex + 1 - // The one exception is that Sema won't add a copy-initializer for an - // unnamed bitfield, which will show up here as a gap in the sequence. - assert(F->getFieldIndex() >= LastAddedFieldIndex + 1 && - "Cannot aggregate fields out of order."); - LastAddedFieldIndex = F->getFieldIndex(); - - // The 'first' and 'last' fields are chosen by offset, rather than field - // index. This allows the code to support bitfields, as well as regular - // fields. - uint64_t FOffset = RecLayout.getFieldOffset(F->getFieldIndex()); - if (FOffset < FirstFieldOffset) { - FirstField = F; - FirstFieldOffset = FOffset; - } else if (FOffset > LastFieldOffset) { - LastField = F; - LastFieldOffset = FOffset; - } - } - - const VarDecl *SrcRec; - const ASTRecordLayout &RecLayout; - FieldDecl *FirstField; - FieldDecl *LastField; - uint64_t FirstFieldOffset, LastFieldOffset; - unsigned LastAddedFieldIndex; - }; - - class ConstructorMemcpyizer : public FieldMemcpyizer { - private: - /// Get source argument for copy constructor. Returns null if not a copy - /// constructor. - static const VarDecl *getTrivialCopySource(CodeGenFunction &CGF, - const CXXConstructorDecl *CD, - FunctionArgList &Args) { - if (CD->isCopyOrMoveConstructor() && CD->isDefaulted()) - return Args[CGF.CGM.getCXXABI().getSrcArgforCopyCtor(CD, Args)]; - return nullptr; - } - - // Returns true if a CXXCtorInitializer represents a member initialization - // that can be rolled into a memcpy. - bool isMemberInitMemcpyable(CXXCtorInitializer *MemberInit) const { - if (!MemcpyableCtor) - return false; - FieldDecl *Field = MemberInit->getMember(); - assert(Field && "No field for member init."); - QualType FieldType = Field->getType(); - CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(MemberInit->getInit()); - - // Bail out on non-memcpyable, not-trivially-copyable members. - if (!(CE && isMemcpyEquivalentSpecialMember(CE->getConstructor())) && - !(FieldType.isTriviallyCopyableType(CGF.getContext()) || - FieldType->isReferenceType())) - return false; - - // Bail out on volatile fields. - if (!isMemcpyableField(Field)) - return false; - - // Otherwise we're good. - return true; - } - - public: - ConstructorMemcpyizer(CodeGenFunction &CGF, const CXXConstructorDecl *CD, - FunctionArgList &Args) - : FieldMemcpyizer(CGF, CD->getParent(), getTrivialCopySource(CGF, CD, Args)), - ConstructorDecl(CD), - MemcpyableCtor(CD->isDefaulted() && - CD->isCopyOrMoveConstructor() && - CGF.getLangOpts().getGC() == LangOptions::NonGC), - Args(Args) { } - - void addMemberInitializer(CXXCtorInitializer *MemberInit) { - if (isMemberInitMemcpyable(MemberInit)) { - AggregatedInits.push_back(MemberInit); - addMemcpyableField(MemberInit->getMember()); - } else { - emitAggregatedInits(); - EmitMemberInitializer(CGF, ConstructorDecl->getParent(), MemberInit, - ConstructorDecl, Args); - } - } - - void emitAggregatedInits() { - if (AggregatedInits.size() <= 1) { - // This memcpy is too small to be worthwhile. Fall back on default - // codegen. - if (!AggregatedInits.empty()) { - CopyingValueRepresentation CVR(CGF); - EmitMemberInitializer(CGF, ConstructorDecl->getParent(), - AggregatedInits[0], ConstructorDecl, Args); - AggregatedInits.clear(); - } - reset(); - return; - } - - pushEHDestructors(); - emitMemcpy(); - AggregatedInits.clear(); - } - - void pushEHDestructors() { - Address ThisPtr = CGF.LoadCXXThisAddress(); - QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl); - LValue LHS = CGF.MakeAddrLValue(ThisPtr, RecordTy); - - for (unsigned i = 0; i < AggregatedInits.size(); ++i) { - CXXCtorInitializer *MemberInit = AggregatedInits[i]; - QualType FieldType = MemberInit->getAnyMember()->getType(); - QualType::DestructionKind dtorKind = FieldType.isDestructedType(); - if (!CGF.needsEHCleanup(dtorKind)) - continue; - LValue FieldLHS = LHS; - EmitLValueForAnyFieldInitialization(CGF, MemberInit, FieldLHS); - CGF.pushEHDestroy(dtorKind, FieldLHS.getAddress(), FieldType); - } - } - - void finish() { - emitAggregatedInits(); - } - - private: - const CXXConstructorDecl *ConstructorDecl; - bool MemcpyableCtor; - FunctionArgList &Args; - SmallVector<CXXCtorInitializer*, 16> AggregatedInits; - }; - - class AssignmentMemcpyizer : public FieldMemcpyizer { - private: - // Returns the memcpyable field copied by the given statement, if one - // exists. Otherwise returns null. - FieldDecl *getMemcpyableField(Stmt *S) { - if (!AssignmentsMemcpyable) - return nullptr; - if (BinaryOperator *BO = dyn_cast<BinaryOperator>(S)) { - // Recognise trivial assignments. - if (BO->getOpcode() != BO_Assign) - return nullptr; - MemberExpr *ME = dyn_cast<MemberExpr>(BO->getLHS()); - if (!ME) - return nullptr; - FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl()); - if (!Field || !isMemcpyableField(Field)) - return nullptr; - Stmt *RHS = BO->getRHS(); - if (ImplicitCastExpr *EC = dyn_cast<ImplicitCastExpr>(RHS)) - RHS = EC->getSubExpr(); - if (!RHS) - return nullptr; - if (MemberExpr *ME2 = dyn_cast<MemberExpr>(RHS)) { - if (ME2->getMemberDecl() == Field) - return Field; - } - return nullptr; - } else if (CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(S)) { - CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MCE->getCalleeDecl()); - if (!(MD && isMemcpyEquivalentSpecialMember(MD))) - return nullptr; - MemberExpr *IOA = dyn_cast<MemberExpr>(MCE->getImplicitObjectArgument()); - if (!IOA) - return nullptr; - FieldDecl *Field = dyn_cast<FieldDecl>(IOA->getMemberDecl()); - if (!Field || !isMemcpyableField(Field)) - return nullptr; - MemberExpr *Arg0 = dyn_cast<MemberExpr>(MCE->getArg(0)); - if (!Arg0 || Field != dyn_cast<FieldDecl>(Arg0->getMemberDecl())) - return nullptr; - return Field; - } else if (CallExpr *CE = dyn_cast<CallExpr>(S)) { - FunctionDecl *FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl()); - if (!FD || FD->getBuiltinID() != Builtin::BI__builtin_memcpy) - return nullptr; - Expr *DstPtr = CE->getArg(0); - if (ImplicitCastExpr *DC = dyn_cast<ImplicitCastExpr>(DstPtr)) - DstPtr = DC->getSubExpr(); - UnaryOperator *DUO = dyn_cast<UnaryOperator>(DstPtr); - if (!DUO || DUO->getOpcode() != UO_AddrOf) - return nullptr; - MemberExpr *ME = dyn_cast<MemberExpr>(DUO->getSubExpr()); - if (!ME) - return nullptr; - FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl()); - if (!Field || !isMemcpyableField(Field)) - return nullptr; - Expr *SrcPtr = CE->getArg(1); - if (ImplicitCastExpr *SC = dyn_cast<ImplicitCastExpr>(SrcPtr)) - SrcPtr = SC->getSubExpr(); - UnaryOperator *SUO = dyn_cast<UnaryOperator>(SrcPtr); - if (!SUO || SUO->getOpcode() != UO_AddrOf) - return nullptr; - MemberExpr *ME2 = dyn_cast<MemberExpr>(SUO->getSubExpr()); - if (!ME2 || Field != dyn_cast<FieldDecl>(ME2->getMemberDecl())) - return nullptr; - return Field; - } - - return nullptr; - } - - bool AssignmentsMemcpyable; - SmallVector<Stmt*, 16> AggregatedStmts; - - public: - AssignmentMemcpyizer(CodeGenFunction &CGF, const CXXMethodDecl *AD, - FunctionArgList &Args) - : FieldMemcpyizer(CGF, AD->getParent(), Args[Args.size() - 1]), - AssignmentsMemcpyable(CGF.getLangOpts().getGC() == LangOptions::NonGC) { - assert(Args.size() == 2); - } - - void emitAssignment(Stmt *S) { - FieldDecl *F = getMemcpyableField(S); - if (F) { - addMemcpyableField(F); - AggregatedStmts.push_back(S); - } else { - emitAggregatedStmts(); - CGF.EmitStmt(S); - } - } - - void emitAggregatedStmts() { - if (AggregatedStmts.size() <= 1) { - if (!AggregatedStmts.empty()) { - CopyingValueRepresentation CVR(CGF); - CGF.EmitStmt(AggregatedStmts[0]); - } - reset(); - } - - emitMemcpy(); - AggregatedStmts.clear(); - } - - void finish() { - emitAggregatedStmts(); - } - }; -} // end anonymous namespace - -static bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit) { - const Type *BaseType = BaseInit->getBaseClass(); - const auto *BaseClassDecl = - cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl()); - return BaseClassDecl->isDynamicClass(); -} - -/// EmitCtorPrologue - This routine generates necessary code to initialize -/// base classes and non-static data members belonging to this constructor. -void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, - CXXCtorType CtorType, - FunctionArgList &Args) { - if (CD->isDelegatingConstructor()) - return EmitDelegatingCXXConstructorCall(CD, Args); - - const CXXRecordDecl *ClassDecl = CD->getParent(); - - CXXConstructorDecl::init_const_iterator B = CD->init_begin(), - E = CD->init_end(); - - llvm::BasicBlock *BaseCtorContinueBB = nullptr; - if (ClassDecl->getNumVBases() && - !CGM.getTarget().getCXXABI().hasConstructorVariants()) { - // The ABIs that don't have constructor variants need to put a branch - // before the virtual base initialization code. - BaseCtorContinueBB = - CGM.getCXXABI().EmitCtorCompleteObjectHandler(*this, ClassDecl); - assert(BaseCtorContinueBB); - } - - llvm::Value *const OldThis = CXXThisValue; - // Virtual base initializers first. - for (; B != E && (*B)->isBaseInitializer() && (*B)->isBaseVirtual(); B++) { - if (CGM.getCodeGenOpts().StrictVTablePointers && - CGM.getCodeGenOpts().OptimizationLevel > 0 && - isInitializerOfDynamicClass(*B)) - CXXThisValue = Builder.CreateLaunderInvariantGroup(LoadCXXThis()); - EmitBaseInitializer(*this, ClassDecl, *B, CtorType); - } - - if (BaseCtorContinueBB) { - // Complete object handler should continue to the remaining initializers. - Builder.CreateBr(BaseCtorContinueBB); - EmitBlock(BaseCtorContinueBB); - } - - // Then, non-virtual base initializers. - for (; B != E && (*B)->isBaseInitializer(); B++) { - assert(!(*B)->isBaseVirtual()); - - if (CGM.getCodeGenOpts().StrictVTablePointers && - CGM.getCodeGenOpts().OptimizationLevel > 0 && - isInitializerOfDynamicClass(*B)) - CXXThisValue = Builder.CreateLaunderInvariantGroup(LoadCXXThis()); - EmitBaseInitializer(*this, ClassDecl, *B, CtorType); - } - - CXXThisValue = OldThis; - - InitializeVTablePointers(ClassDecl); - - // And finally, initialize class members. - FieldConstructionScope FCS(*this, LoadCXXThisAddress()); - ConstructorMemcpyizer CM(*this, CD, Args); - for (; B != E; B++) { - CXXCtorInitializer *Member = (*B); - assert(!Member->isBaseInitializer()); - assert(Member->isAnyMemberInitializer() && - "Delegating initializer on non-delegating constructor"); - CM.addMemberInitializer(Member); - } - CM.finish(); -} - -static bool -FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); - -static bool -HasTrivialDestructorBody(ASTContext &Context, - const CXXRecordDecl *BaseClassDecl, - const CXXRecordDecl *MostDerivedClassDecl) -{ - // If the destructor is trivial we don't have to check anything else. - if (BaseClassDecl->hasTrivialDestructor()) - return true; - - if (!BaseClassDecl->getDestructor()->hasTrivialBody()) - return false; - - // Check fields. - for (const auto *Field : BaseClassDecl->fields()) - if (!FieldHasTrivialDestructorBody(Context, Field)) - return false; - - // Check non-virtual bases. - for (const auto &I : BaseClassDecl->bases()) { - if (I.isVirtual()) - continue; - - const CXXRecordDecl *NonVirtualBase = - cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl()); - if (!HasTrivialDestructorBody(Context, NonVirtualBase, - MostDerivedClassDecl)) - return false; - } - - if (BaseClassDecl == MostDerivedClassDecl) { - // Check virtual bases. - for (const auto &I : BaseClassDecl->vbases()) { - const CXXRecordDecl *VirtualBase = - cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl()); - if (!HasTrivialDestructorBody(Context, VirtualBase, - MostDerivedClassDecl)) - return false; - } - } - - return true; -} - -static bool -FieldHasTrivialDestructorBody(ASTContext &Context, - const FieldDecl *Field) -{ - QualType FieldBaseElementType = Context.getBaseElementType(Field->getType()); - - const RecordType *RT = FieldBaseElementType->getAs<RecordType>(); - if (!RT) - return true; - - CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); - - // The destructor for an implicit anonymous union member is never invoked. - if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion()) - return false; - - return HasTrivialDestructorBody(Context, FieldClassDecl, FieldClassDecl); -} - -/// CanSkipVTablePointerInitialization - Check whether we need to initialize -/// any vtable pointers before calling this destructor. -static bool CanSkipVTablePointerInitialization(CodeGenFunction &CGF, - const CXXDestructorDecl *Dtor) { - const CXXRecordDecl *ClassDecl = Dtor->getParent(); - if (!ClassDecl->isDynamicClass()) - return true; - - if (!Dtor->hasTrivialBody()) - return false; - - // Check the fields. - for (const auto *Field : ClassDecl->fields()) - if (!FieldHasTrivialDestructorBody(CGF.getContext(), Field)) - return false; - - return true; -} - -/// EmitDestructorBody - Emits the body of the current destructor. -void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { - const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CurGD.getDecl()); - CXXDtorType DtorType = CurGD.getDtorType(); - - // For an abstract class, non-base destructors are never used (and can't - // be emitted in general, because vbase dtors may not have been validated - // by Sema), but the Itanium ABI doesn't make them optional and Clang may - // in fact emit references to them from other compilations, so emit them - // as functions containing a trap instruction. - if (DtorType != Dtor_Base && Dtor->getParent()->isAbstract()) { - llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap); - TrapCall->setDoesNotReturn(); - TrapCall->setDoesNotThrow(); - Builder.CreateUnreachable(); - Builder.ClearInsertionPoint(); - return; - } - - Stmt *Body = Dtor->getBody(); - if (Body) - incrementProfileCounter(Body); - - // The call to operator delete in a deleting destructor happens - // outside of the function-try-block, which means it's always - // possible to delegate the destructor body to the complete - // destructor. Do so. - if (DtorType == Dtor_Deleting) { - RunCleanupsScope DtorEpilogue(*this); - EnterDtorCleanups(Dtor, Dtor_Deleting); - if (HaveInsertPoint()) - EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, - /*Delegating=*/false, LoadCXXThisAddress()); - return; - } - - // If the body is a function-try-block, enter the try before - // anything else. - bool isTryBody = (Body && isa<CXXTryStmt>(Body)); - if (isTryBody) - EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true); - EmitAsanPrologueOrEpilogue(false); - - // Enter the epilogue cleanups. - RunCleanupsScope DtorEpilogue(*this); - - // If this is the complete variant, just invoke the base variant; - // the epilogue will destruct the virtual bases. But we can't do - // this optimization if the body is a function-try-block, because - // we'd introduce *two* handler blocks. In the Microsoft ABI, we - // always delegate because we might not have a definition in this TU. - switch (DtorType) { - case Dtor_Comdat: llvm_unreachable("not expecting a COMDAT"); - case Dtor_Deleting: llvm_unreachable("already handled deleting case"); - - case Dtor_Complete: - assert((Body || getTarget().getCXXABI().isMicrosoft()) && - "can't emit a dtor without a body for non-Microsoft ABIs"); - - // Enter the cleanup scopes for virtual bases. - EnterDtorCleanups(Dtor, Dtor_Complete); - - if (!isTryBody) { - EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false, - /*Delegating=*/false, LoadCXXThisAddress()); - break; - } - - // Fallthrough: act like we're in the base variant. - LLVM_FALLTHROUGH; - - case Dtor_Base: - assert(Body); - - // Enter the cleanup scopes for fields and non-virtual bases. - EnterDtorCleanups(Dtor, Dtor_Base); - - // Initialize the vtable pointers before entering the body. - if (!CanSkipVTablePointerInitialization(*this, Dtor)) { - // Insert the llvm.launder.invariant.group intrinsic before initializing - // the vptrs to cancel any previous assumptions we might have made. - if (CGM.getCodeGenOpts().StrictVTablePointers && - CGM.getCodeGenOpts().OptimizationLevel > 0) - CXXThisValue = Builder.CreateLaunderInvariantGroup(LoadCXXThis()); - InitializeVTablePointers(Dtor->getParent()); - } - - if (isTryBody) - EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock()); - else if (Body) - EmitStmt(Body); - else { - assert(Dtor->isImplicit() && "bodyless dtor not implicit"); - // nothing to do besides what's in the epilogue - } - // -fapple-kext must inline any call to this dtor into - // the caller's body. - if (getLangOpts().AppleKext) - CurFn->addFnAttr(llvm::Attribute::AlwaysInline); - - break; - } - - // Jump out through the epilogue cleanups. - DtorEpilogue.ForceCleanup(); - - // Exit the try if applicable. - if (isTryBody) - ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true); -} - -void CodeGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &Args) { - const CXXMethodDecl *AssignOp = cast<CXXMethodDecl>(CurGD.getDecl()); - const Stmt *RootS = AssignOp->getBody(); - assert(isa<CompoundStmt>(RootS) && - "Body of an implicit assignment operator should be compound stmt."); - const CompoundStmt *RootCS = cast<CompoundStmt>(RootS); - - LexicalScope Scope(*this, RootCS->getSourceRange()); - - incrementProfileCounter(RootCS); - AssignmentMemcpyizer AM(*this, AssignOp, Args); - for (auto *I : RootCS->body()) - AM.emitAssignment(I); - AM.finish(); -} - -namespace { - llvm::Value *LoadThisForDtorDelete(CodeGenFunction &CGF, - const CXXDestructorDecl *DD) { - if (Expr *ThisArg = DD->getOperatorDeleteThisArg()) - return CGF.EmitScalarExpr(ThisArg); - return CGF.LoadCXXThis(); - } - - /// Call the operator delete associated with the current destructor. - struct CallDtorDelete final : EHScopeStack::Cleanup { - CallDtorDelete() {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl); - const CXXRecordDecl *ClassDecl = Dtor->getParent(); - CGF.EmitDeleteCall(Dtor->getOperatorDelete(), - LoadThisForDtorDelete(CGF, Dtor), - CGF.getContext().getTagDeclType(ClassDecl)); - } - }; - - void EmitConditionalDtorDeleteCall(CodeGenFunction &CGF, - llvm::Value *ShouldDeleteCondition, - bool ReturnAfterDelete) { - llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete"); - llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue"); - llvm::Value *ShouldCallDelete - = CGF.Builder.CreateIsNull(ShouldDeleteCondition); - CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB); - - CGF.EmitBlock(callDeleteBB); - const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl); - const CXXRecordDecl *ClassDecl = Dtor->getParent(); - CGF.EmitDeleteCall(Dtor->getOperatorDelete(), - LoadThisForDtorDelete(CGF, Dtor), - CGF.getContext().getTagDeclType(ClassDecl)); - assert(Dtor->getOperatorDelete()->isDestroyingOperatorDelete() == - ReturnAfterDelete && - "unexpected value for ReturnAfterDelete"); - if (ReturnAfterDelete) - CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); - else - CGF.Builder.CreateBr(continueBB); - - CGF.EmitBlock(continueBB); - } - - struct CallDtorDeleteConditional final : EHScopeStack::Cleanup { - llvm::Value *ShouldDeleteCondition; - - public: - CallDtorDeleteConditional(llvm::Value *ShouldDeleteCondition) - : ShouldDeleteCondition(ShouldDeleteCondition) { - assert(ShouldDeleteCondition != nullptr); - } - - void Emit(CodeGenFunction &CGF, Flags flags) override { - EmitConditionalDtorDeleteCall(CGF, ShouldDeleteCondition, - /*ReturnAfterDelete*/false); - } - }; - - class DestroyField final : public EHScopeStack::Cleanup { - const FieldDecl *field; - CodeGenFunction::Destroyer *destroyer; - bool useEHCleanupForArray; - - public: - DestroyField(const FieldDecl *field, CodeGenFunction::Destroyer *destroyer, - bool useEHCleanupForArray) - : field(field), destroyer(destroyer), - useEHCleanupForArray(useEHCleanupForArray) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - // Find the address of the field. - Address thisValue = CGF.LoadCXXThisAddress(); - QualType RecordTy = CGF.getContext().getTagDeclType(field->getParent()); - LValue ThisLV = CGF.MakeAddrLValue(thisValue, RecordTy); - LValue LV = CGF.EmitLValueForField(ThisLV, field); - assert(LV.isSimple()); - - CGF.emitDestroy(LV.getAddress(), field->getType(), destroyer, - flags.isForNormalCleanup() && useEHCleanupForArray); - } - }; - - static void EmitSanitizerDtorCallback(CodeGenFunction &CGF, llvm::Value *Ptr, - CharUnits::QuantityType PoisonSize) { - CodeGenFunction::SanitizerScope SanScope(&CGF); - // Pass in void pointer and size of region as arguments to runtime - // function - llvm::Value *Args[] = {CGF.Builder.CreateBitCast(Ptr, CGF.VoidPtrTy), - llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)}; - - llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy}; - - llvm::FunctionType *FnType = - llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false); - llvm::Value *Fn = - CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback"); - CGF.EmitNounwindRuntimeCall(Fn, Args); - } - - class SanitizeDtorMembers final : public EHScopeStack::Cleanup { - const CXXDestructorDecl *Dtor; - - public: - SanitizeDtorMembers(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {} - - // Generate function call for handling object poisoning. - // Disables tail call elimination, to prevent the current stack frame - // from disappearing from the stack trace. - void Emit(CodeGenFunction &CGF, Flags flags) override { - const ASTRecordLayout &Layout = - CGF.getContext().getASTRecordLayout(Dtor->getParent()); - - // Nothing to poison. - if (Layout.getFieldCount() == 0) - return; - - // Prevent the current stack frame from disappearing from the stack trace. - CGF.CurFn->addFnAttr("disable-tail-calls", "true"); - - // Construct pointer to region to begin poisoning, and calculate poison - // size, so that only members declared in this class are poisoned. - ASTContext &Context = CGF.getContext(); - unsigned fieldIndex = 0; - int startIndex = -1; - // RecordDecl::field_iterator Field; - for (const FieldDecl *Field : Dtor->getParent()->fields()) { - // Poison field if it is trivial - if (FieldHasTrivialDestructorBody(Context, Field)) { - // Start sanitizing at this field - if (startIndex < 0) - startIndex = fieldIndex; - - // Currently on the last field, and it must be poisoned with the - // current block. - if (fieldIndex == Layout.getFieldCount() - 1) { - PoisonMembers(CGF, startIndex, Layout.getFieldCount()); - } - } else if (startIndex >= 0) { - // No longer within a block of memory to poison, so poison the block - PoisonMembers(CGF, startIndex, fieldIndex); - // Re-set the start index - startIndex = -1; - } - fieldIndex += 1; - } - } - - private: - /// \param layoutStartOffset index of the ASTRecordLayout field to - /// start poisoning (inclusive) - /// \param layoutEndOffset index of the ASTRecordLayout field to - /// end poisoning (exclusive) - void PoisonMembers(CodeGenFunction &CGF, unsigned layoutStartOffset, - unsigned layoutEndOffset) { - ASTContext &Context = CGF.getContext(); - const ASTRecordLayout &Layout = - Context.getASTRecordLayout(Dtor->getParent()); - - llvm::ConstantInt *OffsetSizePtr = llvm::ConstantInt::get( - CGF.SizeTy, - Context.toCharUnitsFromBits(Layout.getFieldOffset(layoutStartOffset)) - .getQuantity()); - - llvm::Value *OffsetPtr = CGF.Builder.CreateGEP( - CGF.Builder.CreateBitCast(CGF.LoadCXXThis(), CGF.Int8PtrTy), - OffsetSizePtr); - - CharUnits::QuantityType PoisonSize; - if (layoutEndOffset >= Layout.getFieldCount()) { - PoisonSize = Layout.getNonVirtualSize().getQuantity() - - Context.toCharUnitsFromBits( - Layout.getFieldOffset(layoutStartOffset)) - .getQuantity(); - } else { - PoisonSize = Context.toCharUnitsFromBits( - Layout.getFieldOffset(layoutEndOffset) - - Layout.getFieldOffset(layoutStartOffset)) - .getQuantity(); - } - - if (PoisonSize == 0) - return; - - EmitSanitizerDtorCallback(CGF, OffsetPtr, PoisonSize); - } - }; - - class SanitizeDtorVTable final : public EHScopeStack::Cleanup { - const CXXDestructorDecl *Dtor; - - public: - SanitizeDtorVTable(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {} - - // Generate function call for handling vtable pointer poisoning. - void Emit(CodeGenFunction &CGF, Flags flags) override { - assert(Dtor->getParent()->isDynamicClass()); - (void)Dtor; - ASTContext &Context = CGF.getContext(); - // Poison vtable and vtable ptr if they exist for this class. - llvm::Value *VTablePtr = CGF.LoadCXXThis(); - - CharUnits::QuantityType PoisonSize = - Context.toCharUnitsFromBits(CGF.PointerWidthInBits).getQuantity(); - // Pass in void pointer and size of region as arguments to runtime - // function - EmitSanitizerDtorCallback(CGF, VTablePtr, PoisonSize); - } - }; -} // end anonymous namespace - -/// Emit all code that comes at the end of class's -/// destructor. This is to call destructors on members and base classes -/// in reverse order of their construction. -/// -/// For a deleting destructor, this also handles the case where a destroying -/// operator delete completely overrides the definition. -void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD, - CXXDtorType DtorType) { - assert((!DD->isTrivial() || DD->hasAttr<DLLExportAttr>()) && - "Should not emit dtor epilogue for non-exported trivial dtor!"); - - // The deleting-destructor phase just needs to call the appropriate - // operator delete that Sema picked up. - if (DtorType == Dtor_Deleting) { - assert(DD->getOperatorDelete() && - "operator delete missing - EnterDtorCleanups"); - if (CXXStructorImplicitParamValue) { - // If there is an implicit param to the deleting dtor, it's a boolean - // telling whether this is a deleting destructor. - if (DD->getOperatorDelete()->isDestroyingOperatorDelete()) - EmitConditionalDtorDeleteCall(*this, CXXStructorImplicitParamValue, - /*ReturnAfterDelete*/true); - else - EHStack.pushCleanup<CallDtorDeleteConditional>( - NormalAndEHCleanup, CXXStructorImplicitParamValue); - } else { - if (DD->getOperatorDelete()->isDestroyingOperatorDelete()) { - const CXXRecordDecl *ClassDecl = DD->getParent(); - EmitDeleteCall(DD->getOperatorDelete(), - LoadThisForDtorDelete(*this, DD), - getContext().getTagDeclType(ClassDecl)); - EmitBranchThroughCleanup(ReturnBlock); - } else { - EHStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup); - } - } - return; - } - - const CXXRecordDecl *ClassDecl = DD->getParent(); - - // Unions have no bases and do not call field destructors. - if (ClassDecl->isUnion()) - return; - - // The complete-destructor phase just destructs all the virtual bases. - if (DtorType == Dtor_Complete) { - // Poison the vtable pointer such that access after the base - // and member destructors are invoked is invalid. - if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor && - SanOpts.has(SanitizerKind::Memory) && ClassDecl->getNumVBases() && - ClassDecl->isPolymorphic()) - EHStack.pushCleanup<SanitizeDtorVTable>(NormalAndEHCleanup, DD); - - // We push them in the forward order so that they'll be popped in - // the reverse order. - for (const auto &Base : ClassDecl->vbases()) { - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl()); - - // Ignore trivial destructors. - if (BaseClassDecl->hasTrivialDestructor()) - continue; - - EHStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, - BaseClassDecl, - /*BaseIsVirtual*/ true); - } - - return; - } - - assert(DtorType == Dtor_Base); - // Poison the vtable pointer if it has no virtual bases, but inherits - // virtual functions. - if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor && - SanOpts.has(SanitizerKind::Memory) && !ClassDecl->getNumVBases() && - ClassDecl->isPolymorphic()) - EHStack.pushCleanup<SanitizeDtorVTable>(NormalAndEHCleanup, DD); - - // Destroy non-virtual bases. - for (const auto &Base : ClassDecl->bases()) { - // Ignore virtual bases. - if (Base.isVirtual()) - continue; - - CXXRecordDecl *BaseClassDecl = Base.getType()->getAsCXXRecordDecl(); - - // Ignore trivial destructors. - if (BaseClassDecl->hasTrivialDestructor()) - continue; - - EHStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, - BaseClassDecl, - /*BaseIsVirtual*/ false); - } - - // Poison fields such that access after their destructors are - // invoked, and before the base class destructor runs, is invalid. - if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor && - SanOpts.has(SanitizerKind::Memory)) - EHStack.pushCleanup<SanitizeDtorMembers>(NormalAndEHCleanup, DD); - - // Destroy direct fields. - for (const auto *Field : ClassDecl->fields()) { - QualType type = Field->getType(); - QualType::DestructionKind dtorKind = type.isDestructedType(); - if (!dtorKind) continue; - - // Anonymous union members do not have their destructors called. - const RecordType *RT = type->getAsUnionType(); - if (RT && RT->getDecl()->isAnonymousStructOrUnion()) continue; - - CleanupKind cleanupKind = getCleanupKind(dtorKind); - EHStack.pushCleanup<DestroyField>(cleanupKind, Field, - getDestroyer(dtorKind), - cleanupKind & EHCleanup); - } -} - -/// EmitCXXAggrConstructorCall - Emit a loop to call a particular -/// constructor for each of several members of an array. -/// -/// \param ctor the constructor to call for each element -/// \param arrayType the type of the array to initialize -/// \param arrayBegin an arrayType* -/// \param zeroInitialize true if each element should be -/// zero-initialized before it is constructed -void CodeGenFunction::EmitCXXAggrConstructorCall( - const CXXConstructorDecl *ctor, const ArrayType *arrayType, - Address arrayBegin, const CXXConstructExpr *E, bool NewPointerIsChecked, - bool zeroInitialize) { - QualType elementType; - llvm::Value *numElements = - emitArrayLength(arrayType, elementType, arrayBegin); - - EmitCXXAggrConstructorCall(ctor, numElements, arrayBegin, E, - NewPointerIsChecked, zeroInitialize); -} - -/// EmitCXXAggrConstructorCall - Emit a loop to call a particular -/// constructor for each of several members of an array. -/// -/// \param ctor the constructor to call for each element -/// \param numElements the number of elements in the array; -/// may be zero -/// \param arrayBase a T*, where T is the type constructed by ctor -/// \param zeroInitialize true if each element should be -/// zero-initialized before it is constructed -void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor, - llvm::Value *numElements, - Address arrayBase, - const CXXConstructExpr *E, - bool NewPointerIsChecked, - bool zeroInitialize) { - // It's legal for numElements to be zero. This can happen both - // dynamically, because x can be zero in 'new A[x]', and statically, - // because of GCC extensions that permit zero-length arrays. There - // are probably legitimate places where we could assume that this - // doesn't happen, but it's not clear that it's worth it. - llvm::BranchInst *zeroCheckBranch = nullptr; - - // Optimize for a constant count. - llvm::ConstantInt *constantCount - = dyn_cast<llvm::ConstantInt>(numElements); - if (constantCount) { - // Just skip out if the constant count is zero. - if (constantCount->isZero()) return; - - // Otherwise, emit the check. - } else { - llvm::BasicBlock *loopBB = createBasicBlock("new.ctorloop"); - llvm::Value *iszero = Builder.CreateIsNull(numElements, "isempty"); - zeroCheckBranch = Builder.CreateCondBr(iszero, loopBB, loopBB); - EmitBlock(loopBB); - } - - // Find the end of the array. - llvm::Value *arrayBegin = arrayBase.getPointer(); - llvm::Value *arrayEnd = Builder.CreateInBoundsGEP(arrayBegin, numElements, - "arrayctor.end"); - - // Enter the loop, setting up a phi for the current location to initialize. - llvm::BasicBlock *entryBB = Builder.GetInsertBlock(); - llvm::BasicBlock *loopBB = createBasicBlock("arrayctor.loop"); - EmitBlock(loopBB); - llvm::PHINode *cur = Builder.CreatePHI(arrayBegin->getType(), 2, - "arrayctor.cur"); - cur->addIncoming(arrayBegin, entryBB); - - // Inside the loop body, emit the constructor call on the array element. - - // The alignment of the base, adjusted by the size of a single element, - // provides a conservative estimate of the alignment of every element. - // (This assumes we never start tracking offsetted alignments.) - // - // Note that these are complete objects and so we don't need to - // use the non-virtual size or alignment. - QualType type = getContext().getTypeDeclType(ctor->getParent()); - CharUnits eltAlignment = - arrayBase.getAlignment() - .alignmentOfArrayElement(getContext().getTypeSizeInChars(type)); - Address curAddr = Address(cur, eltAlignment); - - // Zero initialize the storage, if requested. - if (zeroInitialize) - EmitNullInitialization(curAddr, type); - - // C++ [class.temporary]p4: - // There are two contexts in which temporaries are destroyed at a different - // point than the end of the full-expression. The first context is when a - // default constructor is called to initialize an element of an array. - // If the constructor has one or more default arguments, the destruction of - // every temporary created in a default argument expression is sequenced - // before the construction of the next array element, if any. - - { - RunCleanupsScope Scope(*this); - - // Evaluate the constructor and its arguments in a regular - // partial-destroy cleanup. - if (getLangOpts().Exceptions && - !ctor->getParent()->hasTrivialDestructor()) { - Destroyer *destroyer = destroyCXXObject; - pushRegularPartialArrayCleanup(arrayBegin, cur, type, eltAlignment, - *destroyer); - } - - EmitCXXConstructorCall(ctor, Ctor_Complete, /*ForVirtualBase=*/false, - /*Delegating=*/false, curAddr, E, - AggValueSlot::DoesNotOverlap, NewPointerIsChecked); - } - - // Go to the next element. - llvm::Value *next = - Builder.CreateInBoundsGEP(cur, llvm::ConstantInt::get(SizeTy, 1), - "arrayctor.next"); - cur->addIncoming(next, Builder.GetInsertBlock()); - - // Check whether that's the end of the loop. - llvm::Value *done = Builder.CreateICmpEQ(next, arrayEnd, "arrayctor.done"); - llvm::BasicBlock *contBB = createBasicBlock("arrayctor.cont"); - Builder.CreateCondBr(done, contBB, loopBB); - - // Patch the earlier check to skip over the loop. - if (zeroCheckBranch) zeroCheckBranch->setSuccessor(0, contBB); - - EmitBlock(contBB); -} - -void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF, - Address addr, - QualType type) { - const RecordType *rtype = type->castAs<RecordType>(); - const CXXRecordDecl *record = cast<CXXRecordDecl>(rtype->getDecl()); - const CXXDestructorDecl *dtor = record->getDestructor(); - assert(!dtor->isTrivial()); - CGF.EmitCXXDestructorCall(dtor, Dtor_Complete, /*for vbase*/ false, - /*Delegating=*/false, addr); -} - -void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, - CXXCtorType Type, - bool ForVirtualBase, - bool Delegating, Address This, - const CXXConstructExpr *E, - AggValueSlot::Overlap_t Overlap, - bool NewPointerIsChecked) { - CallArgList Args; - - LangAS SlotAS = E->getType().getAddressSpace(); - QualType ThisType = D->getThisType(); - LangAS ThisAS = ThisType.getTypePtr()->getPointeeType().getAddressSpace(); - llvm::Value *ThisPtr = This.getPointer(); - if (SlotAS != ThisAS) { - unsigned TargetThisAS = getContext().getTargetAddressSpace(ThisAS); - llvm::Type *NewType = - ThisPtr->getType()->getPointerElementType()->getPointerTo(TargetThisAS); - ThisPtr = getTargetHooks().performAddrSpaceCast(*this, This.getPointer(), - ThisAS, SlotAS, NewType); - } - // Push the this ptr. - Args.add(RValue::get(ThisPtr), D->getThisType()); - - // If this is a trivial constructor, emit a memcpy now before we lose - // the alignment information on the argument. - // FIXME: It would be better to preserve alignment information into CallArg. - if (isMemcpyEquivalentSpecialMember(D)) { - assert(E->getNumArgs() == 1 && "unexpected argcount for trivial ctor"); - - const Expr *Arg = E->getArg(0); - LValue Src = EmitLValue(Arg); - QualType DestTy = getContext().getTypeDeclType(D->getParent()); - LValue Dest = MakeAddrLValue(This, DestTy); - EmitAggregateCopyCtor(Dest, Src, Overlap); - return; - } - - // Add the rest of the user-supplied arguments. - const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>(); - EvaluationOrder Order = E->isListInitialization() - ? EvaluationOrder::ForceLeftToRight - : EvaluationOrder::Default; - EmitCallArgs(Args, FPT, E->arguments(), E->getConstructor(), - /*ParamsToSkip*/ 0, Order); - - EmitCXXConstructorCall(D, Type, ForVirtualBase, Delegating, This, Args, - Overlap, E->getExprLoc(), NewPointerIsChecked); -} - -static bool canEmitDelegateCallArgs(CodeGenFunction &CGF, - const CXXConstructorDecl *Ctor, - CXXCtorType Type, CallArgList &Args) { - // We can't forward a variadic call. - if (Ctor->isVariadic()) - return false; - - if (CGF.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) { - // If the parameters are callee-cleanup, it's not safe to forward. - for (auto *P : Ctor->parameters()) - if (P->getType().isDestructedType()) - return false; - - // Likewise if they're inalloca. - const CGFunctionInfo &Info = - CGF.CGM.getTypes().arrangeCXXConstructorCall(Args, Ctor, Type, 0, 0); - if (Info.usesInAlloca()) - return false; - } - - // Anything else should be OK. - return true; -} - -void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, - CXXCtorType Type, - bool ForVirtualBase, - bool Delegating, - Address This, - CallArgList &Args, - AggValueSlot::Overlap_t Overlap, - SourceLocation Loc, - bool NewPointerIsChecked) { - const CXXRecordDecl *ClassDecl = D->getParent(); - - if (!NewPointerIsChecked) - EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This.getPointer(), - getContext().getRecordType(ClassDecl), CharUnits::Zero()); - - if (D->isTrivial() && D->isDefaultConstructor()) { - assert(Args.size() == 1 && "trivial default ctor with args"); - return; - } - - // If this is a trivial constructor, just emit what's needed. If this is a - // union copy constructor, we must emit a memcpy, because the AST does not - // model that copy. - if (isMemcpyEquivalentSpecialMember(D)) { - assert(Args.size() == 2 && "unexpected argcount for trivial ctor"); - - QualType SrcTy = D->getParamDecl(0)->getType().getNonReferenceType(); - Address Src(Args[1].getRValue(*this).getScalarVal(), - getNaturalTypeAlignment(SrcTy)); - LValue SrcLVal = MakeAddrLValue(Src, SrcTy); - QualType DestTy = getContext().getTypeDeclType(ClassDecl); - LValue DestLVal = MakeAddrLValue(This, DestTy); - EmitAggregateCopyCtor(DestLVal, SrcLVal, Overlap); - return; - } - - bool PassPrototypeArgs = true; - // Check whether we can actually emit the constructor before trying to do so. - if (auto Inherited = D->getInheritedConstructor()) { - PassPrototypeArgs = getTypes().inheritingCtorHasParams(Inherited, Type); - if (PassPrototypeArgs && !canEmitDelegateCallArgs(*this, D, Type, Args)) { - EmitInlinedInheritingCXXConstructorCall(D, Type, ForVirtualBase, - Delegating, Args); - return; - } - } - - // Insert any ABI-specific implicit constructor arguments. - CGCXXABI::AddedStructorArgs ExtraArgs = - CGM.getCXXABI().addImplicitConstructorArgs(*this, D, Type, ForVirtualBase, - Delegating, Args); - - // Emit the call. - llvm::Constant *CalleePtr = - CGM.getAddrOfCXXStructor(D, getFromCtorType(Type)); - const CGFunctionInfo &Info = CGM.getTypes().arrangeCXXConstructorCall( - Args, D, Type, ExtraArgs.Prefix, ExtraArgs.Suffix, PassPrototypeArgs); - CGCallee Callee = CGCallee::forDirect(CalleePtr, GlobalDecl(D, Type)); - EmitCall(Info, Callee, ReturnValueSlot(), Args); - - // Generate vtable assumptions if we're constructing a complete object - // with a vtable. We don't do this for base subobjects for two reasons: - // first, it's incorrect for classes with virtual bases, and second, we're - // about to overwrite the vptrs anyway. - // We also have to make sure if we can refer to vtable: - // - Otherwise we can refer to vtable if it's safe to speculatively emit. - // FIXME: If vtable is used by ctor/dtor, or if vtable is external and we are - // sure that definition of vtable is not hidden, - // then we are always safe to refer to it. - // FIXME: It looks like InstCombine is very inefficient on dealing with - // assumes. Make assumption loads require -fstrict-vtable-pointers temporarily. - if (CGM.getCodeGenOpts().OptimizationLevel > 0 && - ClassDecl->isDynamicClass() && Type != Ctor_Base && - CGM.getCXXABI().canSpeculativelyEmitVTable(ClassDecl) && - CGM.getCodeGenOpts().StrictVTablePointers) - EmitVTableAssumptionLoads(ClassDecl, This); -} - -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()); - - // Forward the parameters. - if (InheritedFromVBase && - CGM.getTarget().getCXXABI().hasConstructorVariants()) { - // Nothing to do; this construction is not responsible for constructing - // the base class containing the inherited constructor. - // FIXME: Can we just pass undef's for the remaining arguments if we don't - // have constructor variants? - Args.push_back(ThisArg); - } else if (!CXXInheritedCtorInitExprArgs.empty()) { - // The inheriting constructor was inlined; just inject its arguments. - assert(CXXInheritedCtorInitExprArgs.size() >= D->getNumParams() && - "wrong number of parameters for inherited constructor call"); - Args = CXXInheritedCtorInitExprArgs; - Args[0] = ThisArg; - } else { - // The inheriting constructor was not inlined. Emit delegating arguments. - Args.push_back(ThisArg); - const auto *OuterCtor = cast<CXXConstructorDecl>(CurCodeDecl); - assert(OuterCtor->getNumParams() == D->getNumParams()); - assert(!OuterCtor->isVariadic() && "should have been inlined"); - - for (const auto *Param : OuterCtor->parameters()) { - assert(getContext().hasSameUnqualifiedType( - OuterCtor->getParamDecl(Param->getFunctionScopeIndex())->getType(), - Param->getType())); - EmitDelegateCallArg(Args, Param, E->getLocation()); - - // Forward __attribute__(pass_object_size). - if (Param->hasAttr<PassObjectSizeAttr>()) { - auto *POSParam = SizeArguments[Param]; - assert(POSParam && "missing pass_object_size value for forwarding"); - EmitDelegateCallArg(Args, POSParam, E->getLocation()); - } - } - } - - EmitCXXConstructorCall(D, Ctor_Base, ForVirtualBase, /*Delegating*/false, - This, Args, AggValueSlot::MayOverlap, - E->getLocation(), /*NewPointerIsChecked*/true); -} - -void CodeGenFunction::EmitInlinedInheritingCXXConstructorCall( - const CXXConstructorDecl *Ctor, CXXCtorType CtorType, bool ForVirtualBase, - bool Delegating, CallArgList &Args) { - GlobalDecl GD(Ctor, CtorType); - InlinedInheritingConstructorScope Scope(*this, GD); - ApplyInlineDebugLocation DebugScope(*this, GD); - RunCleanupsScope RunCleanups(*this); - - // Save the arguments to be passed to the inherited constructor. - CXXInheritedCtorInitExprArgs = Args; - - FunctionArgList Params; - QualType RetType = BuildFunctionArgList(CurGD, Params); - FnRetTy = RetType; - - // Insert any ABI-specific implicit constructor arguments. - CGM.getCXXABI().addImplicitConstructorArgs(*this, Ctor, CtorType, - ForVirtualBase, Delegating, Args); - - // Emit a simplified prolog. We only need to emit the implicit params. - assert(Args.size() >= Params.size() && "too few arguments for call"); - for (unsigned I = 0, N = Args.size(); I != N; ++I) { - if (I < Params.size() && isa<ImplicitParamDecl>(Params[I])) { - const RValue &RV = Args[I].getRValue(*this); - assert(!RV.isComplex() && "complex indirect params not supported"); - ParamValue Val = RV.isScalar() - ? ParamValue::forDirect(RV.getScalarVal()) - : ParamValue::forIndirect(RV.getAggregateAddress()); - EmitParmDecl(*Params[I], Val, I + 1); - } - } - - // Create a return value slot if the ABI implementation wants one. - // FIXME: This is dumb, we should ask the ABI not to try to set the return - // value instead. - if (!RetType->isVoidType()) - ReturnValue = CreateIRTemp(RetType, "retval.inhctor"); - - CGM.getCXXABI().EmitInstanceFunctionProlog(*this); - CXXThisValue = CXXABIThisValue; - - // Directly emit the constructor initializers. - EmitCtorPrologue(Ctor, CtorType, Params); -} - -void CodeGenFunction::EmitVTableAssumptionLoad(const VPtr &Vptr, Address This) { - llvm::Value *VTableGlobal = - CGM.getCXXABI().getVTableAddressPoint(Vptr.Base, Vptr.VTableClass); - if (!VTableGlobal) - return; - - // We can just use the base offset in the complete class. - CharUnits NonVirtualOffset = Vptr.Base.getBaseOffset(); - - if (!NonVirtualOffset.isZero()) - This = - ApplyNonVirtualAndVirtualOffset(*this, This, NonVirtualOffset, nullptr, - Vptr.VTableClass, Vptr.NearestVBase); - - llvm::Value *VPtrValue = - GetVTablePtr(This, VTableGlobal->getType(), Vptr.VTableClass); - llvm::Value *Cmp = - Builder.CreateICmpEQ(VPtrValue, VTableGlobal, "cmp.vtables"); - Builder.CreateAssumption(Cmp); -} - -void CodeGenFunction::EmitVTableAssumptionLoads(const CXXRecordDecl *ClassDecl, - Address This) { - if (CGM.getCXXABI().doStructorsInitializeVPtrs(ClassDecl)) - for (const VPtr &Vptr : getVTablePointers(ClassDecl)) - EmitVTableAssumptionLoad(Vptr, This); -} - -void -CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, - Address This, Address Src, - const CXXConstructExpr *E) { - const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>(); - - CallArgList Args; - - // Push the this ptr. - Args.add(RValue::get(This.getPointer()), D->getThisType()); - - // Push the src ptr. - QualType QT = *(FPT->param_type_begin()); - llvm::Type *t = CGM.getTypes().ConvertType(QT); - Src = Builder.CreateBitCast(Src, t); - Args.add(RValue::get(Src.getPointer()), QT); - - // Skip over first argument (Src). - EmitCallArgs(Args, FPT, drop_begin(E->arguments(), 1), E->getConstructor(), - /*ParamsToSkip*/ 1); - - EmitCXXConstructorCall(D, Ctor_Complete, /*ForVirtualBase*/false, - /*Delegating*/false, This, Args, - AggValueSlot::MayOverlap, E->getExprLoc(), - /*NewPointerIsChecked*/false); -} - -void -CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, - CXXCtorType CtorType, - const FunctionArgList &Args, - SourceLocation Loc) { - CallArgList DelegateArgs; - - FunctionArgList::const_iterator I = Args.begin(), E = Args.end(); - assert(I != E && "no parameters to constructor"); - - // this - Address This = LoadCXXThisAddress(); - DelegateArgs.add(RValue::get(This.getPointer()), (*I)->getType()); - ++I; - - // FIXME: The location of the VTT parameter in the parameter list is - // specific to the Itanium ABI and shouldn't be hardcoded here. - if (CGM.getCXXABI().NeedsVTTParameter(CurGD)) { - assert(I != E && "cannot skip vtt parameter, already done with args"); - assert((*I)->getType()->isPointerType() && - "skipping parameter not of vtt type"); - ++I; - } - - // Explicit arguments. - for (; I != E; ++I) { - const VarDecl *param = *I; - // FIXME: per-argument source location - EmitDelegateCallArg(DelegateArgs, param, Loc); - } - - EmitCXXConstructorCall(Ctor, CtorType, /*ForVirtualBase=*/false, - /*Delegating=*/true, This, DelegateArgs, - AggValueSlot::MayOverlap, Loc, - /*NewPointerIsChecked=*/true); -} - -namespace { - struct CallDelegatingCtorDtor final : EHScopeStack::Cleanup { - const CXXDestructorDecl *Dtor; - Address Addr; - CXXDtorType Type; - - CallDelegatingCtorDtor(const CXXDestructorDecl *D, Address Addr, - CXXDtorType Type) - : Dtor(D), Addr(Addr), Type(Type) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - CGF.EmitCXXDestructorCall(Dtor, Type, /*ForVirtualBase=*/false, - /*Delegating=*/true, Addr); - } - }; -} // end anonymous namespace - -void -CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor, - const FunctionArgList &Args) { - assert(Ctor->isDelegatingConstructor()); - - Address ThisPtr = LoadCXXThisAddress(); - - AggValueSlot AggSlot = - AggValueSlot::forAddr(ThisPtr, Qualifiers(), - AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - AggValueSlot::MayOverlap, - AggValueSlot::IsNotZeroed, - // Checks are made by the code that calls constructor. - AggValueSlot::IsSanitizerChecked); - - EmitAggExpr(Ctor->init_begin()[0]->getInit(), AggSlot); - - const CXXRecordDecl *ClassDecl = Ctor->getParent(); - if (CGM.getLangOpts().Exceptions && !ClassDecl->hasTrivialDestructor()) { - CXXDtorType Type = - CurGD.getCtorType() == Ctor_Complete ? Dtor_Complete : Dtor_Base; - - EHStack.pushCleanup<CallDelegatingCtorDtor>(EHCleanup, - ClassDecl->getDestructor(), - ThisPtr, Type); - } -} - -void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD, - CXXDtorType Type, - bool ForVirtualBase, - bool Delegating, - Address This) { - CGM.getCXXABI().EmitDestructorCall(*this, DD, Type, ForVirtualBase, - Delegating, This); -} - -namespace { - struct CallLocalDtor final : EHScopeStack::Cleanup { - const CXXDestructorDecl *Dtor; - Address Addr; - - CallLocalDtor(const CXXDestructorDecl *D, Address Addr) - : Dtor(D), Addr(Addr) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, - /*ForVirtualBase=*/false, - /*Delegating=*/false, Addr); - } - }; -} // end anonymous namespace - -void CodeGenFunction::PushDestructorCleanup(const CXXDestructorDecl *D, - Address Addr) { - EHStack.pushCleanup<CallLocalDtor>(NormalAndEHCleanup, D, Addr); -} - -void CodeGenFunction::PushDestructorCleanup(QualType T, Address Addr) { - CXXRecordDecl *ClassDecl = T->getAsCXXRecordDecl(); - if (!ClassDecl) return; - if (ClassDecl->hasTrivialDestructor()) return; - - const CXXDestructorDecl *D = ClassDecl->getDestructor(); - assert(D && D->isUsed() && "destructor not marked as used!"); - PushDestructorCleanup(D, Addr); -} - -void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) { - // Compute the address point. - llvm::Value *VTableAddressPoint = - CGM.getCXXABI().getVTableAddressPointInStructor( - *this, Vptr.VTableClass, Vptr.Base, Vptr.NearestVBase); - - if (!VTableAddressPoint) - return; - - // Compute where to store the address point. - llvm::Value *VirtualOffset = nullptr; - CharUnits NonVirtualOffset = CharUnits::Zero(); - - if (CGM.getCXXABI().isVirtualOffsetNeededForVTableField(*this, Vptr)) { - // We need to use the virtual base offset offset because the virtual base - // might have a different offset in the most derived class. - - VirtualOffset = CGM.getCXXABI().GetVirtualBaseClassOffset( - *this, LoadCXXThisAddress(), Vptr.VTableClass, Vptr.NearestVBase); - NonVirtualOffset = Vptr.OffsetFromNearestVBase; - } else { - // We can just use the base offset in the complete class. - NonVirtualOffset = Vptr.Base.getBaseOffset(); - } - - // Apply the offsets. - Address VTableField = LoadCXXThisAddress(); - - if (!NonVirtualOffset.isZero() || VirtualOffset) - VTableField = ApplyNonVirtualAndVirtualOffset( - *this, VTableField, NonVirtualOffset, VirtualOffset, Vptr.VTableClass, - Vptr.NearestVBase); - - // Finally, store the address point. Use the same LLVM types as the field to - // support optimization. - llvm::Type *VTablePtrTy = - llvm::FunctionType::get(CGM.Int32Ty, /*isVarArg=*/true) - ->getPointerTo() - ->getPointerTo(); - VTableField = Builder.CreateBitCast(VTableField, VTablePtrTy->getPointerTo()); - VTableAddressPoint = Builder.CreateBitCast(VTableAddressPoint, VTablePtrTy); - - llvm::StoreInst *Store = Builder.CreateStore(VTableAddressPoint, VTableField); - TBAAAccessInfo TBAAInfo = CGM.getTBAAVTablePtrAccessInfo(VTablePtrTy); - CGM.DecorateInstructionWithTBAA(Store, TBAAInfo); - if (CGM.getCodeGenOpts().OptimizationLevel > 0 && - CGM.getCodeGenOpts().StrictVTablePointers) - CGM.DecorateInstructionWithInvariantGroup(Store, Vptr.VTableClass); -} - -CodeGenFunction::VPtrsVector -CodeGenFunction::getVTablePointers(const CXXRecordDecl *VTableClass) { - CodeGenFunction::VPtrsVector VPtrsResult; - VisitedVirtualBasesSetTy VBases; - getVTablePointers(BaseSubobject(VTableClass, CharUnits::Zero()), - /*NearestVBase=*/nullptr, - /*OffsetFromNearestVBase=*/CharUnits::Zero(), - /*BaseIsNonVirtualPrimaryBase=*/false, VTableClass, VBases, - VPtrsResult); - return VPtrsResult; -} - -void CodeGenFunction::getVTablePointers(BaseSubobject Base, - const CXXRecordDecl *NearestVBase, - CharUnits OffsetFromNearestVBase, - bool BaseIsNonVirtualPrimaryBase, - const CXXRecordDecl *VTableClass, - VisitedVirtualBasesSetTy &VBases, - VPtrsVector &Vptrs) { - // If this base is a non-virtual primary base the address point has already - // been set. - if (!BaseIsNonVirtualPrimaryBase) { - // Initialize the vtable pointer for this base. - VPtr Vptr = {Base, NearestVBase, OffsetFromNearestVBase, VTableClass}; - Vptrs.push_back(Vptr); - } - - const CXXRecordDecl *RD = Base.getBase(); - - // Traverse bases. - for (const auto &I : RD->bases()) { - CXXRecordDecl *BaseDecl - = cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl()); - - // Ignore classes without a vtable. - if (!BaseDecl->isDynamicClass()) - continue; - - CharUnits BaseOffset; - CharUnits BaseOffsetFromNearestVBase; - bool BaseDeclIsNonVirtualPrimaryBase; - - if (I.isVirtual()) { - // Check if we've visited this virtual base before. - if (!VBases.insert(BaseDecl).second) - continue; - - const ASTRecordLayout &Layout = - getContext().getASTRecordLayout(VTableClass); - - BaseOffset = Layout.getVBaseClassOffset(BaseDecl); - BaseOffsetFromNearestVBase = CharUnits::Zero(); - BaseDeclIsNonVirtualPrimaryBase = false; - } else { - const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); - - BaseOffset = Base.getBaseOffset() + Layout.getBaseClassOffset(BaseDecl); - BaseOffsetFromNearestVBase = - OffsetFromNearestVBase + Layout.getBaseClassOffset(BaseDecl); - BaseDeclIsNonVirtualPrimaryBase = Layout.getPrimaryBase() == BaseDecl; - } - - getVTablePointers( - BaseSubobject(BaseDecl, BaseOffset), - I.isVirtual() ? BaseDecl : NearestVBase, BaseOffsetFromNearestVBase, - BaseDeclIsNonVirtualPrimaryBase, VTableClass, VBases, Vptrs); - } -} - -void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) { - // Ignore classes without a vtable. - if (!RD->isDynamicClass()) - return; - - // Initialize the vtable pointers for this class and all of its bases. - if (CGM.getCXXABI().doStructorsInitializeVPtrs(RD)) - for (const VPtr &Vptr : getVTablePointers(RD)) - InitializeVTablePointer(Vptr); - - if (RD->getNumVBases()) - CGM.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, RD); -} - -llvm::Value *CodeGenFunction::GetVTablePtr(Address This, - llvm::Type *VTableTy, - const CXXRecordDecl *RD) { - Address VTablePtrSrc = Builder.CreateElementBitCast(This, VTableTy); - llvm::Instruction *VTable = Builder.CreateLoad(VTablePtrSrc, "vtable"); - TBAAAccessInfo TBAAInfo = CGM.getTBAAVTablePtrAccessInfo(VTableTy); - CGM.DecorateInstructionWithTBAA(VTable, TBAAInfo); - - if (CGM.getCodeGenOpts().OptimizationLevel > 0 && - CGM.getCodeGenOpts().StrictVTablePointers) - CGM.DecorateInstructionWithInvariantGroup(VTable, RD); - - return VTable; -} - -// If a class has a single non-virtual base and does not introduce or override -// virtual member functions or fields, it will have the same layout as its base. -// This function returns the least derived such class. -// -// Casting an instance of a base class to such a derived class is technically -// undefined behavior, but it is a relatively common hack for introducing member -// functions on class instances with specific properties (e.g. llvm::Operator) -// that works under most compilers and should not have security implications, so -// we allow it by default. It can be disabled with -fsanitize=cfi-cast-strict. -static const CXXRecordDecl * -LeastDerivedClassWithSameLayout(const CXXRecordDecl *RD) { - if (!RD->field_empty()) - return RD; - - if (RD->getNumVBases() != 0) - return RD; - - if (RD->getNumBases() != 1) - return RD; - - for (const CXXMethodDecl *MD : RD->methods()) { - if (MD->isVirtual()) { - // Virtual member functions are only ok if they are implicit destructors - // because the implicit destructor will have the same semantics as the - // base class's destructor if no fields are added. - if (isa<CXXDestructorDecl>(MD) && MD->isImplicit()) - continue; - return RD; - } - } - - return LeastDerivedClassWithSameLayout( - RD->bases_begin()->getType()->getAsCXXRecordDecl()); -} - -void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD, - llvm::Value *VTable, - SourceLocation Loc) { - if (SanOpts.has(SanitizerKind::CFIVCall)) - EmitVTablePtrCheckForCall(RD, VTable, CodeGenFunction::CFITCK_VCall, Loc); - else if (CGM.getCodeGenOpts().WholeProgramVTables && - CGM.HasHiddenLTOVisibility(RD)) { - llvm::Metadata *MD = - CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0)); - llvm::Value *TypeId = - llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD); - - llvm::Value *CastedVTable = Builder.CreateBitCast(VTable, Int8PtrTy); - llvm::Value *TypeTest = - Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test), - {CastedVTable, TypeId}); - Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::assume), TypeTest); - } -} - -void CodeGenFunction::EmitVTablePtrCheckForCall(const CXXRecordDecl *RD, - llvm::Value *VTable, - CFITypeCheckKind TCK, - SourceLocation Loc) { - if (!SanOpts.has(SanitizerKind::CFICastStrict)) - RD = LeastDerivedClassWithSameLayout(RD); - - EmitVTablePtrCheck(RD, VTable, TCK, Loc); -} - -void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, - llvm::Value *Derived, - bool MayBeNull, - CFITypeCheckKind TCK, - SourceLocation Loc) { - if (!getLangOpts().CPlusPlus) - return; - - auto *ClassTy = T->getAs<RecordType>(); - if (!ClassTy) - return; - - const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassTy->getDecl()); - - if (!ClassDecl->isCompleteDefinition() || !ClassDecl->isDynamicClass()) - return; - - if (!SanOpts.has(SanitizerKind::CFICastStrict)) - ClassDecl = LeastDerivedClassWithSameLayout(ClassDecl); - - llvm::BasicBlock *ContBlock = nullptr; - - if (MayBeNull) { - llvm::Value *DerivedNotNull = - Builder.CreateIsNotNull(Derived, "cast.nonnull"); - - llvm::BasicBlock *CheckBlock = createBasicBlock("cast.check"); - ContBlock = createBasicBlock("cast.cont"); - - Builder.CreateCondBr(DerivedNotNull, CheckBlock, ContBlock); - - EmitBlock(CheckBlock); - } - - llvm::Value *VTable; - std::tie(VTable, ClassDecl) = CGM.getCXXABI().LoadVTablePtr( - *this, Address(Derived, getPointerAlign()), ClassDecl); - - EmitVTablePtrCheck(ClassDecl, VTable, TCK, Loc); - - if (MayBeNull) { - Builder.CreateBr(ContBlock); - EmitBlock(ContBlock); - } -} - -void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD, - llvm::Value *VTable, - CFITypeCheckKind TCK, - SourceLocation Loc) { - if (!CGM.getCodeGenOpts().SanitizeCfiCrossDso && - !CGM.HasHiddenLTOVisibility(RD)) - return; - - SanitizerMask M; - llvm::SanitizerStatKind SSK; - switch (TCK) { - case CFITCK_VCall: - M = SanitizerKind::CFIVCall; - SSK = llvm::SanStat_CFI_VCall; - break; - case CFITCK_NVCall: - M = SanitizerKind::CFINVCall; - SSK = llvm::SanStat_CFI_NVCall; - break; - case CFITCK_DerivedCast: - M = SanitizerKind::CFIDerivedCast; - SSK = llvm::SanStat_CFI_DerivedCast; - break; - case CFITCK_UnrelatedCast: - M = SanitizerKind::CFIUnrelatedCast; - SSK = llvm::SanStat_CFI_UnrelatedCast; - break; - case CFITCK_ICall: - case CFITCK_NVMFCall: - case CFITCK_VMFCall: - llvm_unreachable("unexpected sanitizer kind"); - } - - std::string TypeName = RD->getQualifiedNameAsString(); - if (getContext().getSanitizerBlacklist().isBlacklistedType(M, TypeName)) - return; - - SanitizerScope SanScope(this); - EmitSanitizerStatReport(SSK); - - llvm::Metadata *MD = - CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0)); - llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD); - - llvm::Value *CastedVTable = Builder.CreateBitCast(VTable, Int8PtrTy); - llvm::Value *TypeTest = Builder.CreateCall( - CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedVTable, TypeId}); - - llvm::Constant *StaticData[] = { - llvm::ConstantInt::get(Int8Ty, TCK), - EmitCheckSourceLocation(Loc), - EmitCheckTypeDescriptor(QualType(RD->getTypeForDecl(), 0)), - }; - - auto CrossDsoTypeId = CGM.CreateCrossDsoCfiTypeId(MD); - if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && CrossDsoTypeId) { - EmitCfiSlowPathCheck(M, TypeTest, CrossDsoTypeId, CastedVTable, StaticData); - return; - } - - if (CGM.getCodeGenOpts().SanitizeTrap.has(M)) { - EmitTrapCheck(TypeTest); - return; - } - - llvm::Value *AllVtables = llvm::MetadataAsValue::get( - CGM.getLLVMContext(), - llvm::MDString::get(CGM.getLLVMContext(), "all-vtables")); - llvm::Value *ValidVtable = Builder.CreateCall( - CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedVTable, AllVtables}); - EmitCheck(std::make_pair(TypeTest, M), SanitizerHandler::CFICheckFail, - StaticData, {CastedVTable, ValidVtable}); -} - -bool CodeGenFunction::ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD) { - if (!CGM.getCodeGenOpts().WholeProgramVTables || - !SanOpts.has(SanitizerKind::CFIVCall) || - !CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIVCall) || - !CGM.HasHiddenLTOVisibility(RD)) - return false; - - std::string TypeName = RD->getQualifiedNameAsString(); - return !getContext().getSanitizerBlacklist().isBlacklistedType( - SanitizerKind::CFIVCall, TypeName); -} - -llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad( - const CXXRecordDecl *RD, llvm::Value *VTable, uint64_t VTableByteOffset) { - SanitizerScope SanScope(this); - - EmitSanitizerStatReport(llvm::SanStat_CFI_VCall); - - llvm::Metadata *MD = - CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0)); - llvm::Value *TypeId = llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD); - - llvm::Value *CastedVTable = Builder.CreateBitCast(VTable, Int8PtrTy); - llvm::Value *CheckedLoad = Builder.CreateCall( - CGM.getIntrinsic(llvm::Intrinsic::type_checked_load), - {CastedVTable, llvm::ConstantInt::get(Int32Ty, VTableByteOffset), - TypeId}); - llvm::Value *CheckResult = Builder.CreateExtractValue(CheckedLoad, 1); - - EmitCheck(std::make_pair(CheckResult, SanitizerKind::CFIVCall), - SanitizerHandler::CFICheckFail, nullptr, nullptr); - - return Builder.CreateBitCast( - Builder.CreateExtractValue(CheckedLoad, 0), - cast<llvm::PointerType>(VTable->getType())->getElementType()); -} - -void CodeGenFunction::EmitForwardingCallToLambda( - const CXXMethodDecl *callOperator, - CallArgList &callArgs) { - // Get the address of the call operator. - const CGFunctionInfo &calleeFnInfo = - CGM.getTypes().arrangeCXXMethodDeclaration(callOperator); - llvm::Constant *calleePtr = - CGM.GetAddrOfFunction(GlobalDecl(callOperator), - CGM.getTypes().GetFunctionType(calleeFnInfo)); - - // Prepare the return slot. - const FunctionProtoType *FPT = - callOperator->getType()->castAs<FunctionProtoType>(); - QualType resultType = FPT->getReturnType(); - ReturnValueSlot returnSlot; - if (!resultType->isVoidType() && - calleeFnInfo.getReturnInfo().getKind() == ABIArgInfo::Indirect && - !hasScalarEvaluationKind(calleeFnInfo.getReturnType())) - returnSlot = ReturnValueSlot(ReturnValue, resultType.isVolatileQualified()); - - // We don't need to separately arrange the call arguments because - // the call can't be variadic anyway --- it's impossible to forward - // variadic arguments. - - // Now emit our call. - auto callee = CGCallee::forDirect(calleePtr, GlobalDecl(callOperator)); - RValue RV = EmitCall(calleeFnInfo, callee, returnSlot, callArgs); - - // If necessary, copy the returned value into the slot. - if (!resultType->isVoidType() && returnSlot.isNull()) { - if (getLangOpts().ObjCAutoRefCount && resultType->isObjCRetainableType()) { - RV = RValue::get(EmitARCRetainAutoreleasedReturnValue(RV.getScalarVal())); - } - EmitReturnOfRValue(RV, resultType); - } else - EmitBranchThroughCleanup(ReturnBlock); -} - -void CodeGenFunction::EmitLambdaBlockInvokeBody() { - const BlockDecl *BD = BlockInfo->getBlockDecl(); - const VarDecl *variable = BD->capture_begin()->getVariable(); - const CXXRecordDecl *Lambda = variable->getType()->getAsCXXRecordDecl(); - const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator(); - - if (CallOp->isVariadic()) { - // FIXME: Making this work correctly is nasty because it requires either - // cloning the body of the call operator or making the call operator - // forward. - CGM.ErrorUnsupported(CurCodeDecl, "lambda conversion to variadic function"); - return; - } - - // Start building arguments for forwarding call - CallArgList CallArgs; - - QualType ThisType = getContext().getPointerType(getContext().getRecordType(Lambda)); - Address ThisPtr = GetAddrOfBlockDecl(variable); - CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType); - - // Add the rest of the parameters. - for (auto param : BD->parameters()) - EmitDelegateCallArg(CallArgs, param, param->getBeginLoc()); - - assert(!Lambda->isGenericLambda() && - "generic lambda interconversion to block not implemented"); - EmitForwardingCallToLambda(CallOp, CallArgs); -} - -void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) { - const CXXRecordDecl *Lambda = MD->getParent(); - - // Start building arguments for forwarding call - CallArgList CallArgs; - - QualType ThisType = getContext().getPointerType(getContext().getRecordType(Lambda)); - llvm::Value *ThisPtr = llvm::UndefValue::get(getTypes().ConvertType(ThisType)); - CallArgs.add(RValue::get(ThisPtr), ThisType); - - // Add the rest of the parameters. - for (auto Param : MD->parameters()) - EmitDelegateCallArg(CallArgs, Param, Param->getBeginLoc()); - - const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator(); - // For a generic lambda, find the corresponding call operator specialization - // to which the call to the static-invoker shall be forwarded. - if (Lambda->isGenericLambda()) { - assert(MD->isFunctionTemplateSpecialization()); - const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs(); - FunctionTemplateDecl *CallOpTemplate = CallOp->getDescribedFunctionTemplate(); - void *InsertPos = nullptr; - FunctionDecl *CorrespondingCallOpSpecialization = - CallOpTemplate->findSpecialization(TAL->asArray(), InsertPos); - assert(CorrespondingCallOpSpecialization); - CallOp = cast<CXXMethodDecl>(CorrespondingCallOpSpecialization); - } - EmitForwardingCallToLambda(CallOp, CallArgs); -} - -void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) { - if (MD->isVariadic()) { - // FIXME: Making this work correctly is nasty because it requires either - // cloning the body of the call operator or making the call operator forward. - CGM.ErrorUnsupported(MD, "lambda conversion to variadic function"); - return; - } - - EmitLambdaDelegatingInvokeBody(MD); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp deleted file mode 100644 index 3743d24f11f..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp +++ /dev/null @@ -1,1283 +0,0 @@ -//===--- CGCleanup.cpp - Bookkeeping and code emission for cleanups -------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains code dealing with the IR generation for cleanups -// and related information. -// -// A "cleanup" is a piece of code which needs to be executed whenever -// control transfers out of a particular scope. This can be -// conditionalized to occur only on exceptional control flow, only on -// normal control flow, or both. -// -//===----------------------------------------------------------------------===// - -#include "CGCleanup.h" -#include "CodeGenFunction.h" -#include "llvm/Support/SaveAndRestore.h" - -using namespace clang; -using namespace CodeGen; - -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 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, ScalarLiteral); - - // Everything else needs an alloca. - Address addr = - CGF.CreateDefaultAlignTempAlloca(V->getType(), "saved-rvalue"); - CGF.Builder.CreateStore(V, addr); - return saved_type(addr.getPointer(), ScalarAddress); - } - - 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, CharUnits())); - CharUnits offset = CharUnits::fromQuantity( - CGF.CGM.getDataLayout().getTypeAllocSize(V.first->getType())); - CGF.Builder.CreateStore(V.second, - CGF.Builder.CreateStructGEP(addr, 1, offset)); - return saved_type(addr.getPointer(), ComplexAddress); - } - - assert(rv.isAggregate()); - Address V = rv.getAggregateAddress(); // TODO: volatile? - if (!DominatingLLVMValue::needsSaving(V.getPointer())) - return saved_type(V.getPointer(), 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(), AggregateAddress, - V.getAlignment().getQuantity()); -} - -/// 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 alignment = cast<llvm::AllocaInst>(value)->getAlignment(); - return Address(value, CharUnits::fromQuantity(alignment)); - }; - switch (K) { - case ScalarLiteral: - return RValue::get(Value); - case ScalarAddress: - return RValue::get(CGF.Builder.CreateLoad(getSavingAddress(Value))); - case AggregateLiteral: - return RValue::getAggregate(Address(Value, CharUnits::fromQuantity(Align))); - case AggregateAddress: { - auto addr = CGF.Builder.CreateLoad(getSavingAddress(Value)); - return RValue::getAggregate(Address(addr, CharUnits::fromQuantity(Align))); - } - case ComplexAddress: { - Address address = getSavingAddress(Value); - llvm::Value *real = CGF.Builder.CreateLoad( - CGF.Builder.CreateStructGEP(address, 0, CharUnits())); - CharUnits offset = CharUnits::fromQuantity( - CGF.CGM.getDataLayout().getTypeAllocSize(real->getType())); - llvm::Value *imag = CGF.Builder.CreateLoad( - CGF.Builder.CreateStructGEP(address, 1, offset)); - return RValue::getComplex(real, imag); - } - } - - llvm_unreachable("bad saved r-value kind"); -} - -/// Push an entry of the given size onto this protected-scope stack. -char *EHScopeStack::allocate(size_t Size) { - Size = llvm::alignTo(Size, ScopeStackAlignment); - if (!StartOfBuffer) { - unsigned Capacity = 1024; - while (Capacity < Size) Capacity *= 2; - StartOfBuffer = new char[Capacity]; - StartOfData = EndOfBuffer = StartOfBuffer + Capacity; - } else if (static_cast<size_t>(StartOfData - StartOfBuffer) < Size) { - unsigned CurrentCapacity = EndOfBuffer - StartOfBuffer; - unsigned UsedCapacity = CurrentCapacity - (StartOfData - StartOfBuffer); - - unsigned NewCapacity = CurrentCapacity; - do { - NewCapacity *= 2; - } while (NewCapacity < UsedCapacity + Size); - - char *NewStartOfBuffer = new char[NewCapacity]; - char *NewEndOfBuffer = NewStartOfBuffer + NewCapacity; - char *NewStartOfData = NewEndOfBuffer - UsedCapacity; - memcpy(NewStartOfData, StartOfData, UsedCapacity); - delete [] StartOfBuffer; - StartOfBuffer = NewStartOfBuffer; - EndOfBuffer = NewEndOfBuffer; - StartOfData = NewStartOfData; - } - - assert(StartOfBuffer + Size <= StartOfData); - StartOfData -= Size; - return StartOfData; -} - -void EHScopeStack::deallocate(size_t Size) { - StartOfData += llvm::alignTo(Size, ScopeStackAlignment); -} - -bool EHScopeStack::containsOnlyLifetimeMarkers( - EHScopeStack::stable_iterator Old) const { - for (EHScopeStack::iterator it = begin(); stabilize(it) != Old; it++) { - EHCleanupScope *cleanup = dyn_cast<EHCleanupScope>(&*it); - if (!cleanup || !cleanup->isLifetimeMarker()) - return false; - } - - return true; -} - -bool EHScopeStack::requiresLandingPad() const { - for (stable_iterator si = getInnermostEHScope(); si != stable_end(); ) { - // Skip lifetime markers. - if (auto *cleanup = dyn_cast<EHCleanupScope>(&*find(si))) - if (cleanup->isLifetimeMarker()) { - si = cleanup->getEnclosingEHScope(); - continue; - } - return true; - } - - return false; -} - -EHScopeStack::stable_iterator -EHScopeStack::getInnermostActiveNormalCleanup() const { - for (stable_iterator si = getInnermostNormalCleanup(), se = stable_end(); - si != se; ) { - EHCleanupScope &cleanup = cast<EHCleanupScope>(*find(si)); - if (cleanup.isActive()) return si; - si = cleanup.getEnclosingNormalCleanup(); - } - return stable_end(); -} - - -void *EHScopeStack::pushCleanup(CleanupKind Kind, size_t Size) { - char *Buffer = allocate(EHCleanupScope::getSizeForCleanupSize(Size)); - bool IsNormalCleanup = Kind & NormalCleanup; - bool IsEHCleanup = Kind & EHCleanup; - bool IsActive = !(Kind & InactiveCleanup); - bool IsLifetimeMarker = Kind & LifetimeMarker; - EHCleanupScope *Scope = - new (Buffer) EHCleanupScope(IsNormalCleanup, - IsEHCleanup, - IsActive, - Size, - BranchFixups.size(), - InnermostNormalCleanup, - InnermostEHScope); - if (IsNormalCleanup) - InnermostNormalCleanup = stable_begin(); - if (IsEHCleanup) - InnermostEHScope = stable_begin(); - if (IsLifetimeMarker) - Scope->setLifetimeMarker(); - - return Scope->getCleanupBuffer(); -} - -void EHScopeStack::popCleanup() { - assert(!empty() && "popping exception stack when not empty"); - - assert(isa<EHCleanupScope>(*begin())); - EHCleanupScope &Cleanup = cast<EHCleanupScope>(*begin()); - InnermostNormalCleanup = Cleanup.getEnclosingNormalCleanup(); - InnermostEHScope = Cleanup.getEnclosingEHScope(); - deallocate(Cleanup.getAllocatedSize()); - - // Destroy the cleanup. - Cleanup.Destroy(); - - // Check whether we can shrink the branch-fixups stack. - if (!BranchFixups.empty()) { - // If we no longer have any normal cleanups, all the fixups are - // complete. - if (!hasNormalCleanups()) - BranchFixups.clear(); - - // Otherwise we can still trim out unnecessary nulls. - else - popNullFixups(); - } -} - -EHFilterScope *EHScopeStack::pushFilter(unsigned numFilters) { - assert(getInnermostEHScope() == stable_end()); - char *buffer = allocate(EHFilterScope::getSizeForNumFilters(numFilters)); - EHFilterScope *filter = new (buffer) EHFilterScope(numFilters); - InnermostEHScope = stable_begin(); - return filter; -} - -void EHScopeStack::popFilter() { - assert(!empty() && "popping exception stack when not empty"); - - EHFilterScope &filter = cast<EHFilterScope>(*begin()); - deallocate(EHFilterScope::getSizeForNumFilters(filter.getNumFilters())); - - InnermostEHScope = filter.getEnclosingEHScope(); -} - -EHCatchScope *EHScopeStack::pushCatch(unsigned numHandlers) { - char *buffer = allocate(EHCatchScope::getSizeForNumHandlers(numHandlers)); - EHCatchScope *scope = - new (buffer) EHCatchScope(numHandlers, InnermostEHScope); - InnermostEHScope = stable_begin(); - return scope; -} - -void EHScopeStack::pushTerminate() { - char *Buffer = allocate(EHTerminateScope::getSize()); - new (Buffer) EHTerminateScope(InnermostEHScope); - InnermostEHScope = stable_begin(); -} - -/// Remove any 'null' fixups on the stack. However, we can't pop more -/// fixups than the fixup depth on the innermost normal cleanup, or -/// else fixups that we try to add to that cleanup will end up in the -/// wrong place. We *could* try to shrink fixup depths, but that's -/// actually a lot of work for little benefit. -void EHScopeStack::popNullFixups() { - // We expect this to only be called when there's still an innermost - // normal cleanup; otherwise there really shouldn't be any fixups. - assert(hasNormalCleanups()); - - EHScopeStack::iterator it = find(InnermostNormalCleanup); - unsigned MinSize = cast<EHCleanupScope>(*it).getFixupDepth(); - assert(BranchFixups.size() >= MinSize && "fixup stack out of order"); - - while (BranchFixups.size() > MinSize && - BranchFixups.back().Destination == nullptr) - BranchFixups.pop_back(); -} - -Address CodeGenFunction::createCleanupActiveFlag() { - // Create a variable to decide whether the cleanup needs to be run. - Address 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); - - // Initialize it to true at the current location. - Builder.CreateStore(Builder.getTrue(), active); - - return active; -} - -void CodeGenFunction::initFullExprCleanupWithFlag(Address ActiveFlag) { - // Set that as the active flag in the cleanup. - EHCleanupScope &cleanup = cast<EHCleanupScope>(*EHStack.begin()); - assert(!cleanup.hasActiveFlag() && "cleanup already has active flag?"); - cleanup.setActiveFlag(ActiveFlag); - - if (cleanup.isNormalCleanup()) cleanup.setTestFlagInNormalCleanup(); - if (cleanup.isEHCleanup()) cleanup.setTestFlagInEHCleanup(); -} - -void EHScopeStack::Cleanup::anchor() {} - -static void createStoreInstBefore(llvm::Value *value, Address addr, - llvm::Instruction *beforeInst) { - auto store = new llvm::StoreInst(value, addr.getPointer(), beforeInst); - store->setAlignment(addr.getAlignment().getQuantity()); -} - -static llvm::LoadInst *createLoadInstBefore(Address addr, const Twine &name, - llvm::Instruction *beforeInst) { - auto load = new llvm::LoadInst(addr.getPointer(), name, beforeInst); - load->setAlignment(addr.getAlignment().getQuantity()); - return load; -} - -/// All the branch fixups on the EH stack have propagated out past the -/// outermost normal cleanup; resolve them all by adding cases to the -/// given switch instruction. -static void ResolveAllBranchFixups(CodeGenFunction &CGF, - llvm::SwitchInst *Switch, - llvm::BasicBlock *CleanupEntry) { - llvm::SmallPtrSet<llvm::BasicBlock*, 4> CasesAdded; - - for (unsigned I = 0, E = CGF.EHStack.getNumBranchFixups(); I != E; ++I) { - // Skip this fixup if its destination isn't set. - BranchFixup &Fixup = CGF.EHStack.getBranchFixup(I); - if (Fixup.Destination == nullptr) continue; - - // If there isn't an OptimisticBranchBlock, then InitialBranch is - // still pointing directly to its destination; forward it to the - // appropriate cleanup entry. This is required in the specific - // case of - // { std::string s; goto lbl; } - // lbl: - // i.e. where there's an unresolved fixup inside a single cleanup - // entry which we're currently popping. - if (Fixup.OptimisticBranchBlock == nullptr) { - createStoreInstBefore(CGF.Builder.getInt32(Fixup.DestinationIndex), - CGF.getNormalCleanupDestSlot(), - Fixup.InitialBranch); - Fixup.InitialBranch->setSuccessor(0, CleanupEntry); - } - - // Don't add this case to the switch statement twice. - if (!CasesAdded.insert(Fixup.Destination).second) - continue; - - Switch->addCase(CGF.Builder.getInt32(Fixup.DestinationIndex), - Fixup.Destination); - } - - CGF.EHStack.clearFixups(); -} - -/// Transitions the terminator of the given exit-block of a cleanup to -/// be a cleanup switch. -static llvm::SwitchInst *TransitionToCleanupSwitch(CodeGenFunction &CGF, - llvm::BasicBlock *Block) { - // If it's a branch, turn it into a switch whose default - // destination is its original target. - llvm::Instruction *Term = Block->getTerminator(); - assert(Term && "can't transition block without terminator"); - - if (llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Term)) { - assert(Br->isUnconditional()); - auto Load = createLoadInstBefore(CGF.getNormalCleanupDestSlot(), - "cleanup.dest", Term); - llvm::SwitchInst *Switch = - llvm::SwitchInst::Create(Load, Br->getSuccessor(0), 4, Block); - Br->eraseFromParent(); - return Switch; - } else { - return cast<llvm::SwitchInst>(Term); - } -} - -void CodeGenFunction::ResolveBranchFixups(llvm::BasicBlock *Block) { - assert(Block && "resolving a null target block"); - if (!EHStack.getNumBranchFixups()) return; - - assert(EHStack.hasNormalCleanups() && - "branch fixups exist with no normal cleanups on stack"); - - llvm::SmallPtrSet<llvm::BasicBlock*, 4> ModifiedOptimisticBlocks; - bool ResolvedAny = false; - - for (unsigned I = 0, E = EHStack.getNumBranchFixups(); I != E; ++I) { - // Skip this fixup if its destination doesn't match. - BranchFixup &Fixup = EHStack.getBranchFixup(I); - if (Fixup.Destination != Block) continue; - - Fixup.Destination = nullptr; - ResolvedAny = true; - - // If it doesn't have an optimistic branch block, LatestBranch is - // already pointing to the right place. - llvm::BasicBlock *BranchBB = Fixup.OptimisticBranchBlock; - if (!BranchBB) - continue; - - // Don't process the same optimistic branch block twice. - if (!ModifiedOptimisticBlocks.insert(BranchBB).second) - continue; - - llvm::SwitchInst *Switch = TransitionToCleanupSwitch(*this, BranchBB); - - // Add a case to the switch. - Switch->addCase(Builder.getInt32(Fixup.DestinationIndex), Block); - } - - if (ResolvedAny) - EHStack.popNullFixups(); -} - -/// Pops cleanup blocks until the given savepoint is reached. -void CodeGenFunction::PopCleanupBlocks( - EHScopeStack::stable_iterator Old, - std::initializer_list<llvm::Value **> ValuesToReload) { - assert(Old.isValid()); - - bool HadBranches = false; - while (EHStack.stable_begin() != Old) { - EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.begin()); - HadBranches |= Scope.hasBranches(); - - // As long as Old strictly encloses the scope's enclosing normal - // cleanup, we're going to emit another normal cleanup which - // fallthrough can propagate through. - bool FallThroughIsBranchThrough = - Old.strictlyEncloses(Scope.getEnclosingNormalCleanup()); - - PopCleanupBlock(FallThroughIsBranchThrough); - } - - // If we didn't have any branches, the insertion point before cleanups must - // dominate the current insertion point and we don't need to reload any - // values. - if (!HadBranches) - return; - - // Spill and reload all values that the caller wants to be live at the current - // insertion point. - for (llvm::Value **ReloadedValue : ValuesToReload) { - auto *Inst = dyn_cast_or_null<llvm::Instruction>(*ReloadedValue); - if (!Inst) - continue; - - // Don't spill static allocas, they dominate all cleanups. These are created - // by binding a reference to a local variable or temporary. - auto *AI = dyn_cast<llvm::AllocaInst>(Inst); - if (AI && AI->isStaticAlloca()) - continue; - - Address Tmp = - CreateDefaultAlignTempAlloca(Inst->getType(), "tmp.exprcleanup"); - - // Find an insertion point after Inst and spill it to the temporary. - llvm::BasicBlock::iterator InsertBefore; - if (auto *Invoke = dyn_cast<llvm::InvokeInst>(Inst)) - InsertBefore = Invoke->getNormalDest()->getFirstInsertionPt(); - else - InsertBefore = std::next(Inst->getIterator()); - CGBuilderTy(CGM, &*InsertBefore).CreateStore(Inst, Tmp); - - // Reload the value at the current insertion point. - *ReloadedValue = Builder.CreateLoad(Tmp); - } -} - -/// Pops cleanup blocks until the given savepoint is reached, then add the -/// cleanups from the given savepoint in the lifetime-extended cleanups stack. -void CodeGenFunction::PopCleanupBlocks( - EHScopeStack::stable_iterator Old, size_t OldLifetimeExtendedSize, - std::initializer_list<llvm::Value **> ValuesToReload) { - PopCleanupBlocks(Old, ValuesToReload); - - // Move our deferred cleanups onto the EH stack. - for (size_t I = OldLifetimeExtendedSize, - E = LifetimeExtendedCleanupStack.size(); I != E; /**/) { - // Alignment should be guaranteed by the vptrs in the individual cleanups. - assert((I % alignof(LifetimeExtendedCleanupHeader) == 0) && - "misaligned cleanup stack entry"); - - LifetimeExtendedCleanupHeader &Header = - reinterpret_cast<LifetimeExtendedCleanupHeader&>( - LifetimeExtendedCleanupStack[I]); - I += sizeof(Header); - - EHStack.pushCopyOfCleanup(Header.getKind(), - &LifetimeExtendedCleanupStack[I], - Header.getSize()); - I += Header.getSize(); - - if (Header.isConditional()) { - Address ActiveFlag = - reinterpret_cast<Address &>(LifetimeExtendedCleanupStack[I]); - initFullExprCleanupWithFlag(ActiveFlag); - I += sizeof(ActiveFlag); - } - } - LifetimeExtendedCleanupStack.resize(OldLifetimeExtendedSize); -} - -static llvm::BasicBlock *CreateNormalEntry(CodeGenFunction &CGF, - EHCleanupScope &Scope) { - assert(Scope.isNormalCleanup()); - llvm::BasicBlock *Entry = Scope.getNormalBlock(); - if (!Entry) { - Entry = CGF.createBasicBlock("cleanup"); - Scope.setNormalBlock(Entry); - } - return Entry; -} - -/// Attempts to reduce a cleanup's entry block to a fallthrough. This -/// is basically llvm::MergeBlockIntoPredecessor, except -/// simplified/optimized for the tighter constraints on cleanup blocks. -/// -/// Returns the new block, whatever it is. -static llvm::BasicBlock *SimplifyCleanupEntry(CodeGenFunction &CGF, - llvm::BasicBlock *Entry) { - llvm::BasicBlock *Pred = Entry->getSinglePredecessor(); - if (!Pred) return Entry; - - llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Pred->getTerminator()); - if (!Br || Br->isConditional()) return Entry; - assert(Br->getSuccessor(0) == Entry); - - // If we were previously inserting at the end of the cleanup entry - // block, we'll need to continue inserting at the end of the - // predecessor. - bool WasInsertBlock = CGF.Builder.GetInsertBlock() == Entry; - assert(!WasInsertBlock || CGF.Builder.GetInsertPoint() == Entry->end()); - - // Kill the branch. - Br->eraseFromParent(); - - // Replace all uses of the entry with the predecessor, in case there - // are phis in the cleanup. - Entry->replaceAllUsesWith(Pred); - - // Merge the blocks. - Pred->getInstList().splice(Pred->end(), Entry->getInstList()); - - // Kill the entry block. - Entry->eraseFromParent(); - - if (WasInsertBlock) - CGF.Builder.SetInsertPoint(Pred); - - return Pred; -} - -static void EmitCleanup(CodeGenFunction &CGF, - EHScopeStack::Cleanup *Fn, - EHScopeStack::Cleanup::Flags flags, - Address ActiveFlag) { - // If there's an active flag, load it and skip the cleanup if it's - // false. - llvm::BasicBlock *ContBB = nullptr; - if (ActiveFlag.isValid()) { - ContBB = CGF.createBasicBlock("cleanup.done"); - llvm::BasicBlock *CleanupBB = CGF.createBasicBlock("cleanup.action"); - llvm::Value *IsActive - = CGF.Builder.CreateLoad(ActiveFlag, "cleanup.is_active"); - CGF.Builder.CreateCondBr(IsActive, CleanupBB, ContBB); - CGF.EmitBlock(CleanupBB); - } - - // Ask the cleanup to emit itself. - Fn->Emit(CGF, flags); - assert(CGF.HaveInsertPoint() && "cleanup ended with no insertion point?"); - - // Emit the continuation block if there was an active flag. - if (ActiveFlag.isValid()) - CGF.EmitBlock(ContBB); -} - -static void ForwardPrebranchedFallthrough(llvm::BasicBlock *Exit, - llvm::BasicBlock *From, - llvm::BasicBlock *To) { - // Exit is the exit block of a cleanup, so it always terminates in - // an unconditional branch or a switch. - llvm::Instruction *Term = Exit->getTerminator(); - - if (llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Term)) { - assert(Br->isUnconditional() && Br->getSuccessor(0) == From); - Br->setSuccessor(0, To); - } else { - llvm::SwitchInst *Switch = cast<llvm::SwitchInst>(Term); - for (unsigned I = 0, E = Switch->getNumSuccessors(); I != E; ++I) - if (Switch->getSuccessor(I) == From) - Switch->setSuccessor(I, To); - } -} - -/// We don't need a normal entry block for the given cleanup. -/// Optimistic fixup branches can cause these blocks to come into -/// existence anyway; if so, destroy it. -/// -/// The validity of this transformation is very much specific to the -/// exact ways in which we form branches to cleanup entries. -static void destroyOptimisticNormalEntry(CodeGenFunction &CGF, - EHCleanupScope &scope) { - llvm::BasicBlock *entry = scope.getNormalBlock(); - if (!entry) return; - - // Replace all the uses with unreachable. - llvm::BasicBlock *unreachableBB = CGF.getUnreachableBlock(); - for (llvm::BasicBlock::use_iterator - i = entry->use_begin(), e = entry->use_end(); i != e; ) { - llvm::Use &use = *i; - ++i; - - use.set(unreachableBB); - - // The only uses should be fixup switches. - llvm::SwitchInst *si = cast<llvm::SwitchInst>(use.getUser()); - if (si->getNumCases() == 1 && si->getDefaultDest() == unreachableBB) { - // Replace the switch with a branch. - llvm::BranchInst::Create(si->case_begin()->getCaseSuccessor(), si); - - // The switch operand is a load from the cleanup-dest alloca. - llvm::LoadInst *condition = cast<llvm::LoadInst>(si->getCondition()); - - // Destroy the switch. - si->eraseFromParent(); - - // Destroy the load. - assert(condition->getOperand(0) == CGF.NormalCleanupDest.getPointer()); - assert(condition->use_empty()); - condition->eraseFromParent(); - } - } - - assert(entry->use_empty()); - delete entry; -} - -/// Pops a cleanup block. If the block includes a normal cleanup, the -/// current insertion point is threaded through the cleanup, as are -/// any branch fixups on the cleanup. -void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { - assert(!EHStack.empty() && "cleanup stack is empty!"); - assert(isa<EHCleanupScope>(*EHStack.begin()) && "top not a cleanup!"); - EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.begin()); - assert(Scope.getFixupDepth() <= EHStack.getNumBranchFixups()); - - // Remember activation information. - bool IsActive = Scope.isActive(); - Address NormalActiveFlag = - Scope.shouldTestFlagInNormalCleanup() ? Scope.getActiveFlag() - : Address::invalid(); - Address EHActiveFlag = - Scope.shouldTestFlagInEHCleanup() ? Scope.getActiveFlag() - : Address::invalid(); - - // Check whether we need an EH cleanup. This is only true if we've - // generated a lazy EH cleanup block. - llvm::BasicBlock *EHEntry = Scope.getCachedEHDispatchBlock(); - assert(Scope.hasEHBranches() == (EHEntry != nullptr)); - bool RequiresEHCleanup = (EHEntry != nullptr); - EHScopeStack::stable_iterator EHParent = Scope.getEnclosingEHScope(); - - // Check the three conditions which might require a normal cleanup: - - // - whether there are branch fix-ups through this cleanup - unsigned FixupDepth = Scope.getFixupDepth(); - bool HasFixups = EHStack.getNumBranchFixups() != FixupDepth; - - // - whether there are branch-throughs or branch-afters - bool HasExistingBranches = Scope.hasBranches(); - - // - whether there's a fallthrough - llvm::BasicBlock *FallthroughSource = Builder.GetInsertBlock(); - bool HasFallthrough = (FallthroughSource != nullptr && IsActive); - - // Branch-through fall-throughs leave the insertion point set to the - // end of the last cleanup, which points to the current scope. The - // rest of IR gen doesn't need to worry about this; it only happens - // during the execution of PopCleanupBlocks(). - bool HasPrebranchedFallthrough = - (FallthroughSource && FallthroughSource->getTerminator()); - - // If this is a normal cleanup, then having a prebranched - // fallthrough implies that the fallthrough source unconditionally - // jumps here. - assert(!Scope.isNormalCleanup() || !HasPrebranchedFallthrough || - (Scope.getNormalBlock() && - FallthroughSource->getTerminator()->getSuccessor(0) - == Scope.getNormalBlock())); - - bool RequiresNormalCleanup = false; - if (Scope.isNormalCleanup() && - (HasFixups || HasExistingBranches || HasFallthrough)) { - RequiresNormalCleanup = true; - } - - // If we have a prebranched fallthrough into an inactive normal - // cleanup, rewrite it so that it leads to the appropriate place. - if (Scope.isNormalCleanup() && HasPrebranchedFallthrough && !IsActive) { - llvm::BasicBlock *prebranchDest; - - // If the prebranch is semantically branching through the next - // cleanup, just forward it to the next block, leaving the - // insertion point in the prebranched block. - if (FallthroughIsBranchThrough) { - EHScope &enclosing = *EHStack.find(Scope.getEnclosingNormalCleanup()); - prebranchDest = CreateNormalEntry(*this, cast<EHCleanupScope>(enclosing)); - - // Otherwise, we need to make a new block. If the normal cleanup - // isn't being used at all, we could actually reuse the normal - // entry block, but this is simpler, and it avoids conflicts with - // dead optimistic fixup branches. - } else { - prebranchDest = createBasicBlock("forwarded-prebranch"); - EmitBlock(prebranchDest); - } - - llvm::BasicBlock *normalEntry = Scope.getNormalBlock(); - assert(normalEntry && !normalEntry->use_empty()); - - ForwardPrebranchedFallthrough(FallthroughSource, - normalEntry, prebranchDest); - } - - // If we don't need the cleanup at all, we're done. - if (!RequiresNormalCleanup && !RequiresEHCleanup) { - destroyOptimisticNormalEntry(*this, Scope); - EHStack.popCleanup(); // safe because there are no fixups - assert(EHStack.getNumBranchFixups() == 0 || - EHStack.hasNormalCleanups()); - return; - } - - // Copy the cleanup emission data out. This uses either a stack - // array or malloc'd memory, depending on the size, which is - // behavior that SmallVector would provide, if we could use it - // here. Unfortunately, if you ask for a SmallVector<char>, the - // alignment isn't sufficient. - auto *CleanupSource = reinterpret_cast<char *>(Scope.getCleanupBuffer()); - llvm::AlignedCharArray<EHScopeStack::ScopeStackAlignment, 8 * sizeof(void *)> CleanupBufferStack; - std::unique_ptr<char[]> CleanupBufferHeap; - size_t CleanupSize = Scope.getCleanupSize(); - EHScopeStack::Cleanup *Fn; - - if (CleanupSize <= sizeof(CleanupBufferStack)) { - memcpy(CleanupBufferStack.buffer, CleanupSource, CleanupSize); - Fn = reinterpret_cast<EHScopeStack::Cleanup *>(CleanupBufferStack.buffer); - } else { - CleanupBufferHeap.reset(new char[CleanupSize]); - memcpy(CleanupBufferHeap.get(), CleanupSource, CleanupSize); - Fn = reinterpret_cast<EHScopeStack::Cleanup *>(CleanupBufferHeap.get()); - } - - EHScopeStack::Cleanup::Flags cleanupFlags; - if (Scope.isNormalCleanup()) - cleanupFlags.setIsNormalCleanupKind(); - if (Scope.isEHCleanup()) - cleanupFlags.setIsEHCleanupKind(); - - if (!RequiresNormalCleanup) { - destroyOptimisticNormalEntry(*this, Scope); - EHStack.popCleanup(); - } else { - // If we have a fallthrough and no other need for the cleanup, - // emit it directly. - if (HasFallthrough && !HasPrebranchedFallthrough && - !HasFixups && !HasExistingBranches) { - - destroyOptimisticNormalEntry(*this, Scope); - EHStack.popCleanup(); - - EmitCleanup(*this, Fn, cleanupFlags, NormalActiveFlag); - - // Otherwise, the best approach is to thread everything through - // the cleanup block and then try to clean up after ourselves. - } else { - // Force the entry block to exist. - llvm::BasicBlock *NormalEntry = CreateNormalEntry(*this, Scope); - - // I. Set up the fallthrough edge in. - - CGBuilderTy::InsertPoint savedInactiveFallthroughIP; - - // If there's a fallthrough, we need to store the cleanup - // destination index. For fall-throughs this is always zero. - if (HasFallthrough) { - if (!HasPrebranchedFallthrough) - Builder.CreateStore(Builder.getInt32(0), getNormalCleanupDestSlot()); - - // Otherwise, save and clear the IP if we don't have fallthrough - // because the cleanup is inactive. - } else if (FallthroughSource) { - assert(!IsActive && "source without fallthrough for active cleanup"); - savedInactiveFallthroughIP = Builder.saveAndClearIP(); - } - - // II. Emit the entry block. This implicitly branches to it if - // we have fallthrough. All the fixups and existing branches - // should already be branched to it. - EmitBlock(NormalEntry); - - // III. Figure out where we're going and build the cleanup - // epilogue. - - bool HasEnclosingCleanups = - (Scope.getEnclosingNormalCleanup() != EHStack.stable_end()); - - // Compute the branch-through dest if we need it: - // - if there are branch-throughs threaded through the scope - // - if fall-through is a branch-through - // - if there are fixups that will be optimistically forwarded - // to the enclosing cleanup - llvm::BasicBlock *BranchThroughDest = nullptr; - if (Scope.hasBranchThroughs() || - (FallthroughSource && FallthroughIsBranchThrough) || - (HasFixups && HasEnclosingCleanups)) { - assert(HasEnclosingCleanups); - EHScope &S = *EHStack.find(Scope.getEnclosingNormalCleanup()); - BranchThroughDest = CreateNormalEntry(*this, cast<EHCleanupScope>(S)); - } - - llvm::BasicBlock *FallthroughDest = nullptr; - SmallVector<llvm::Instruction*, 2> InstsToAppend; - - // If there's exactly one branch-after and no other threads, - // we can route it without a switch. - if (!Scope.hasBranchThroughs() && !HasFixups && !HasFallthrough && - Scope.getNumBranchAfters() == 1) { - assert(!BranchThroughDest || !IsActive); - - // Clean up the possibly dead store to the cleanup dest slot. - llvm::Instruction *NormalCleanupDestSlot = - cast<llvm::Instruction>(getNormalCleanupDestSlot().getPointer()); - if (NormalCleanupDestSlot->hasOneUse()) { - NormalCleanupDestSlot->user_back()->eraseFromParent(); - NormalCleanupDestSlot->eraseFromParent(); - NormalCleanupDest = Address::invalid(); - } - - llvm::BasicBlock *BranchAfter = Scope.getBranchAfterBlock(0); - InstsToAppend.push_back(llvm::BranchInst::Create(BranchAfter)); - - // Build a switch-out if we need it: - // - if there are branch-afters threaded through the scope - // - if fall-through is a branch-after - // - if there are fixups that have nowhere left to go and - // so must be immediately resolved - } else if (Scope.getNumBranchAfters() || - (HasFallthrough && !FallthroughIsBranchThrough) || - (HasFixups && !HasEnclosingCleanups)) { - - llvm::BasicBlock *Default = - (BranchThroughDest ? BranchThroughDest : getUnreachableBlock()); - - // TODO: base this on the number of branch-afters and fixups - const unsigned SwitchCapacity = 10; - - llvm::LoadInst *Load = - createLoadInstBefore(getNormalCleanupDestSlot(), "cleanup.dest", - nullptr); - llvm::SwitchInst *Switch = - llvm::SwitchInst::Create(Load, Default, SwitchCapacity); - - InstsToAppend.push_back(Load); - InstsToAppend.push_back(Switch); - - // Branch-after fallthrough. - if (FallthroughSource && !FallthroughIsBranchThrough) { - FallthroughDest = createBasicBlock("cleanup.cont"); - if (HasFallthrough) - Switch->addCase(Builder.getInt32(0), FallthroughDest); - } - - for (unsigned I = 0, E = Scope.getNumBranchAfters(); I != E; ++I) { - Switch->addCase(Scope.getBranchAfterIndex(I), - Scope.getBranchAfterBlock(I)); - } - - // If there aren't any enclosing cleanups, we can resolve all - // the fixups now. - if (HasFixups && !HasEnclosingCleanups) - ResolveAllBranchFixups(*this, Switch, NormalEntry); - } else { - // We should always have a branch-through destination in this case. - assert(BranchThroughDest); - InstsToAppend.push_back(llvm::BranchInst::Create(BranchThroughDest)); - } - - // IV. Pop the cleanup and emit it. - EHStack.popCleanup(); - assert(EHStack.hasNormalCleanups() == HasEnclosingCleanups); - - EmitCleanup(*this, Fn, cleanupFlags, NormalActiveFlag); - - // Append the prepared cleanup prologue from above. - llvm::BasicBlock *NormalExit = Builder.GetInsertBlock(); - for (unsigned I = 0, E = InstsToAppend.size(); I != E; ++I) - NormalExit->getInstList().push_back(InstsToAppend[I]); - - // Optimistically hope that any fixups will continue falling through. - for (unsigned I = FixupDepth, E = EHStack.getNumBranchFixups(); - I < E; ++I) { - BranchFixup &Fixup = EHStack.getBranchFixup(I); - if (!Fixup.Destination) continue; - if (!Fixup.OptimisticBranchBlock) { - createStoreInstBefore(Builder.getInt32(Fixup.DestinationIndex), - getNormalCleanupDestSlot(), - Fixup.InitialBranch); - Fixup.InitialBranch->setSuccessor(0, NormalEntry); - } - Fixup.OptimisticBranchBlock = NormalExit; - } - - // V. Set up the fallthrough edge out. - - // Case 1: a fallthrough source exists but doesn't branch to the - // cleanup because the cleanup is inactive. - if (!HasFallthrough && FallthroughSource) { - // Prebranched fallthrough was forwarded earlier. - // Non-prebranched fallthrough doesn't need to be forwarded. - // Either way, all we need to do is restore the IP we cleared before. - assert(!IsActive); - Builder.restoreIP(savedInactiveFallthroughIP); - - // Case 2: a fallthrough source exists and should branch to the - // cleanup, but we're not supposed to branch through to the next - // cleanup. - } else if (HasFallthrough && FallthroughDest) { - assert(!FallthroughIsBranchThrough); - EmitBlock(FallthroughDest); - - // Case 3: a fallthrough source exists and should branch to the - // cleanup and then through to the next. - } else if (HasFallthrough) { - // Everything is already set up for this. - - // Case 4: no fallthrough source exists. - } else { - Builder.ClearInsertionPoint(); - } - - // VI. Assorted cleaning. - - // Check whether we can merge NormalEntry into a single predecessor. - // This might invalidate (non-IR) pointers to NormalEntry. - llvm::BasicBlock *NewNormalEntry = - SimplifyCleanupEntry(*this, NormalEntry); - - // If it did invalidate those pointers, and NormalEntry was the same - // as NormalExit, go back and patch up the fixups. - if (NewNormalEntry != NormalEntry && NormalEntry == NormalExit) - for (unsigned I = FixupDepth, E = EHStack.getNumBranchFixups(); - I < E; ++I) - EHStack.getBranchFixup(I).OptimisticBranchBlock = NewNormalEntry; - } - } - - assert(EHStack.hasNormalCleanups() || EHStack.getNumBranchFixups() == 0); - - // Emit the EH cleanup if required. - if (RequiresEHCleanup) { - CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); - - EmitBlock(EHEntry); - - llvm::BasicBlock *NextAction = getEHDispatchBlock(EHParent); - - // Push a terminate scope or cleanupendpad scope around the potentially - // throwing cleanups. For funclet EH personalities, the cleanupendpad models - // program termination when cleanups throw. - bool PushedTerminate = false; - SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad( - CurrentFuncletPad); - llvm::CleanupPadInst *CPI = nullptr; - - const EHPersonality &Personality = EHPersonality::get(*this); - if (Personality.usesFuncletPads()) { - llvm::Value *ParentPad = CurrentFuncletPad; - if (!ParentPad) - ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext()); - CurrentFuncletPad = CPI = Builder.CreateCleanupPad(ParentPad); - } - - // Non-MSVC personalities need to terminate when an EH cleanup throws. - if (!Personality.isMSVCPersonality()) { - EHStack.pushTerminate(); - PushedTerminate = true; - } - - // We only actually emit the cleanup code if the cleanup is either - // active or was used before it was deactivated. - if (EHActiveFlag.isValid() || IsActive) { - cleanupFlags.setIsForEHCleanup(); - EmitCleanup(*this, Fn, cleanupFlags, EHActiveFlag); - } - - if (CPI) - Builder.CreateCleanupRet(CPI, NextAction); - else - Builder.CreateBr(NextAction); - - // Leave the terminate scope. - if (PushedTerminate) - EHStack.popTerminate(); - - Builder.restoreIP(SavedIP); - - SimplifyCleanupEntry(*this, EHEntry); - } -} - -/// isObviouslyBranchWithoutCleanups - Return true if a branch to the -/// specified destination obviously has no cleanups to run. 'false' is always -/// a conservatively correct answer for this method. -bool CodeGenFunction::isObviouslyBranchWithoutCleanups(JumpDest Dest) const { - assert(Dest.getScopeDepth().encloses(EHStack.stable_begin()) - && "stale jump destination"); - - // Calculate the innermost active normal cleanup. - EHScopeStack::stable_iterator TopCleanup = - EHStack.getInnermostActiveNormalCleanup(); - - // If we're not in an active normal cleanup scope, or if the - // destination scope is within the innermost active normal cleanup - // scope, we don't need to worry about fixups. - if (TopCleanup == EHStack.stable_end() || - TopCleanup.encloses(Dest.getScopeDepth())) // works for invalid - return true; - - // Otherwise, we might need some cleanups. - return false; -} - - -/// Terminate the current block by emitting a branch which might leave -/// the current cleanup-protected scope. The target scope may not yet -/// be known, in which case this will require a fixup. -/// -/// As a side-effect, this method clears the insertion point. -void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) { - assert(Dest.getScopeDepth().encloses(EHStack.stable_begin()) - && "stale jump destination"); - - if (!HaveInsertPoint()) - return; - - // Create the branch. - llvm::BranchInst *BI = Builder.CreateBr(Dest.getBlock()); - - // Calculate the innermost active normal cleanup. - EHScopeStack::stable_iterator - TopCleanup = EHStack.getInnermostActiveNormalCleanup(); - - // If we're not in an active normal cleanup scope, or if the - // destination scope is within the innermost active normal cleanup - // scope, we don't need to worry about fixups. - if (TopCleanup == EHStack.stable_end() || - TopCleanup.encloses(Dest.getScopeDepth())) { // works for invalid - Builder.ClearInsertionPoint(); - return; - } - - // If we can't resolve the destination cleanup scope, just add this - // to the current cleanup scope as a branch fixup. - if (!Dest.getScopeDepth().isValid()) { - BranchFixup &Fixup = EHStack.addBranchFixup(); - Fixup.Destination = Dest.getBlock(); - Fixup.DestinationIndex = Dest.getDestIndex(); - Fixup.InitialBranch = BI; - Fixup.OptimisticBranchBlock = nullptr; - - Builder.ClearInsertionPoint(); - return; - } - - // Otherwise, thread through all the normal cleanups in scope. - - // Store the index at the start. - llvm::ConstantInt *Index = Builder.getInt32(Dest.getDestIndex()); - createStoreInstBefore(Index, getNormalCleanupDestSlot(), BI); - - // Adjust BI to point to the first cleanup block. - { - EHCleanupScope &Scope = - cast<EHCleanupScope>(*EHStack.find(TopCleanup)); - BI->setSuccessor(0, CreateNormalEntry(*this, Scope)); - } - - // Add this destination to all the scopes involved. - EHScopeStack::stable_iterator I = TopCleanup; - EHScopeStack::stable_iterator E = Dest.getScopeDepth(); - if (E.strictlyEncloses(I)) { - while (true) { - EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(I)); - assert(Scope.isNormalCleanup()); - I = Scope.getEnclosingNormalCleanup(); - - // If this is the last cleanup we're propagating through, tell it - // that there's a resolved jump moving through it. - if (!E.strictlyEncloses(I)) { - Scope.addBranchAfter(Index, Dest.getBlock()); - break; - } - - // Otherwise, tell the scope that there's a jump propagating - // through it. If this isn't new information, all the rest of - // the work has been done before. - if (!Scope.addBranchThrough(Dest.getBlock())) - break; - } - } - - Builder.ClearInsertionPoint(); -} - -static bool IsUsedAsNormalCleanup(EHScopeStack &EHStack, - EHScopeStack::stable_iterator C) { - // If we needed a normal block for any reason, that counts. - if (cast<EHCleanupScope>(*EHStack.find(C)).getNormalBlock()) - return true; - - // Check whether any enclosed cleanups were needed. - for (EHScopeStack::stable_iterator - I = EHStack.getInnermostNormalCleanup(); - I != C; ) { - assert(C.strictlyEncloses(I)); - EHCleanupScope &S = cast<EHCleanupScope>(*EHStack.find(I)); - if (S.getNormalBlock()) return true; - I = S.getEnclosingNormalCleanup(); - } - - return false; -} - -static bool IsUsedAsEHCleanup(EHScopeStack &EHStack, - EHScopeStack::stable_iterator cleanup) { - // If we needed an EH block for any reason, that counts. - if (EHStack.find(cleanup)->hasEHBranches()) - return true; - - // Check whether any enclosed cleanups were needed. - for (EHScopeStack::stable_iterator - i = EHStack.getInnermostEHScope(); i != cleanup; ) { - assert(cleanup.strictlyEncloses(i)); - - EHScope &scope = *EHStack.find(i); - if (scope.hasEHBranches()) - return true; - - i = scope.getEnclosingEHScope(); - } - - return false; -} - -enum ForActivation_t { - ForActivation, - ForDeactivation -}; - -/// The given cleanup block is changing activation state. Configure a -/// cleanup variable if necessary. -/// -/// It would be good if we had some way of determining if there were -/// extra uses *after* the change-over point. -static void SetupCleanupBlockActivation(CodeGenFunction &CGF, - EHScopeStack::stable_iterator C, - ForActivation_t kind, - llvm::Instruction *dominatingIP) { - EHCleanupScope &Scope = cast<EHCleanupScope>(*CGF.EHStack.find(C)); - - // We always need the flag if we're activating the cleanup in a - // conditional context, because we have to assume that the current - // location doesn't necessarily dominate the cleanup's code. - bool isActivatedInConditional = - (kind == ForActivation && CGF.isInConditionalBranch()); - - bool needFlag = false; - - // Calculate whether the cleanup was used: - - // - as a normal cleanup - if (Scope.isNormalCleanup() && - (isActivatedInConditional || IsUsedAsNormalCleanup(CGF.EHStack, C))) { - Scope.setTestFlagInNormalCleanup(); - needFlag = true; - } - - // - as an EH cleanup - if (Scope.isEHCleanup() && - (isActivatedInConditional || IsUsedAsEHCleanup(CGF.EHStack, C))) { - Scope.setTestFlagInEHCleanup(); - needFlag = true; - } - - // If it hasn't yet been used as either, we're done. - if (!needFlag) return; - - Address var = Scope.getActiveFlag(); - if (!var.isValid()) { - var = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), CharUnits::One(), - "cleanup.isactive"); - Scope.setActiveFlag(var); - - assert(dominatingIP && "no existing variable and no dominating IP!"); - - // Initialize to true or false depending on whether it was - // active up to this point. - llvm::Constant *value = CGF.Builder.getInt1(kind == ForDeactivation); - - // If we're in a conditional block, ignore the dominating IP and - // use the outermost conditional branch. - if (CGF.isInConditionalBranch()) { - CGF.setBeforeOutermostConditional(value, var); - } else { - createStoreInstBefore(value, var, dominatingIP); - } - } - - CGF.Builder.CreateStore(CGF.Builder.getInt1(kind == ForActivation), var); -} - -/// Activate a cleanup that was created in an inactivated state. -void CodeGenFunction::ActivateCleanupBlock(EHScopeStack::stable_iterator C, - llvm::Instruction *dominatingIP) { - assert(C != EHStack.stable_end() && "activating bottom of stack?"); - EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(C)); - assert(!Scope.isActive() && "double activation"); - - SetupCleanupBlockActivation(*this, C, ForActivation, dominatingIP); - - Scope.setActive(true); -} - -/// Deactive a cleanup that was created in an active state. -void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C, - llvm::Instruction *dominatingIP) { - assert(C != EHStack.stable_end() && "deactivating bottom of stack?"); - EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(C)); - assert(Scope.isActive() && "double deactivation"); - - // If it's the top of the stack, just pop it, but do so only if it belongs - // to the current RunCleanupsScope. - if (C == EHStack.stable_begin() && - CurrentCleanupScopeDepth.strictlyEncloses(C)) { - // If it's a normal cleanup, we need to pretend that the - // fallthrough is unreachable. - CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); - PopCleanupBlock(); - Builder.restoreIP(SavedIP); - return; - } - - // Otherwise, follow the general case. - SetupCleanupBlockActivation(*this, C, ForDeactivation, dominatingIP); - - Scope.setActive(false); -} - -Address CodeGenFunction::getNormalCleanupDestSlot() { - if (!NormalCleanupDest.isValid()) - NormalCleanupDest = - CreateDefaultAlignTempAlloca(Builder.getInt32Ty(), "cleanup.dest.slot"); - return NormalCleanupDest; -} - -/// Emits all the code to cause the given temporary to be cleaned up. -void CodeGenFunction::EmitCXXTemporary(const CXXTemporary *Temporary, - QualType TempType, - Address Ptr) { - pushDestroy(NormalAndEHCleanup, Ptr, TempType, destroyCXXObject, - /*useEHCleanup*/ true); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGCleanup.h b/gnu/llvm/tools/clang/lib/CodeGen/CGCleanup.h deleted file mode 100644 index 15d6f46dcb5..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGCleanup.h +++ /dev/null @@ -1,650 +0,0 @@ -//===-- CGCleanup.h - Classes for cleanups IR generation --------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// These classes support the generation of LLVM IR for cleanups. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CGCLEANUP_H -#define LLVM_CLANG_LIB_CODEGEN_CGCLEANUP_H - -#include "EHScopeStack.h" - -#include "Address.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" - -namespace llvm { -class BasicBlock; -class Value; -class ConstantInt; -class AllocaInst; -} - -namespace clang { -class FunctionDecl; -namespace CodeGen { -class CodeGenModule; -class CodeGenFunction; - -/// The MS C++ ABI needs a pointer to RTTI data plus some flags to describe the -/// type of a catch handler, so we use this wrapper. -struct CatchTypeInfo { - llvm::Constant *RTTI; - unsigned Flags; -}; - -/// A protected scope for zero-cost EH handling. -class EHScope { - llvm::BasicBlock *CachedLandingPad; - llvm::BasicBlock *CachedEHDispatchBlock; - - EHScopeStack::stable_iterator EnclosingEHScope; - - class CommonBitFields { - friend class EHScope; - unsigned Kind : 3; - }; - enum { NumCommonBits = 3 }; - -protected: - class CatchBitFields { - friend class EHCatchScope; - unsigned : NumCommonBits; - - unsigned NumHandlers : 32 - NumCommonBits; - }; - - class CleanupBitFields { - friend class EHCleanupScope; - unsigned : NumCommonBits; - - /// Whether this cleanup needs to be run along normal edges. - unsigned IsNormalCleanup : 1; - - /// Whether this cleanup needs to be run along exception edges. - unsigned IsEHCleanup : 1; - - /// Whether this cleanup is currently active. - unsigned IsActive : 1; - - /// Whether this cleanup is a lifetime marker - unsigned IsLifetimeMarker : 1; - - /// Whether the normal cleanup should test the activation flag. - unsigned TestFlagInNormalCleanup : 1; - - /// Whether the EH cleanup should test the activation flag. - unsigned TestFlagInEHCleanup : 1; - - /// The amount of extra storage needed by the Cleanup. - /// Always a multiple of the scope-stack alignment. - unsigned CleanupSize : 12; - }; - - class FilterBitFields { - friend class EHFilterScope; - unsigned : NumCommonBits; - - unsigned NumFilters : 32 - NumCommonBits; - }; - - union { - CommonBitFields CommonBits; - CatchBitFields CatchBits; - CleanupBitFields CleanupBits; - FilterBitFields FilterBits; - }; - -public: - enum Kind { Cleanup, Catch, Terminate, Filter, PadEnd }; - - EHScope(Kind kind, EHScopeStack::stable_iterator enclosingEHScope) - : CachedLandingPad(nullptr), CachedEHDispatchBlock(nullptr), - EnclosingEHScope(enclosingEHScope) { - CommonBits.Kind = kind; - } - - Kind getKind() const { return static_cast<Kind>(CommonBits.Kind); } - - llvm::BasicBlock *getCachedLandingPad() const { - return CachedLandingPad; - } - - void setCachedLandingPad(llvm::BasicBlock *block) { - CachedLandingPad = block; - } - - llvm::BasicBlock *getCachedEHDispatchBlock() const { - return CachedEHDispatchBlock; - } - - void setCachedEHDispatchBlock(llvm::BasicBlock *block) { - CachedEHDispatchBlock = block; - } - - bool hasEHBranches() const { - if (llvm::BasicBlock *block = getCachedEHDispatchBlock()) - return !block->use_empty(); - return false; - } - - EHScopeStack::stable_iterator getEnclosingEHScope() const { - return EnclosingEHScope; - } -}; - -/// A scope which attempts to handle some, possibly all, types of -/// exceptions. -/// -/// Objective C \@finally blocks are represented using a cleanup scope -/// after the catch scope. -class EHCatchScope : public EHScope { - // In effect, we have a flexible array member - // Handler Handlers[0]; - // But that's only standard in C99, not C++, so we have to do - // annoying pointer arithmetic instead. - -public: - struct Handler { - /// A type info value, or null (C++ null, not an LLVM null pointer) - /// for a catch-all. - CatchTypeInfo Type; - - /// The catch handler for this type. - llvm::BasicBlock *Block; - - bool isCatchAll() const { return Type.RTTI == nullptr; } - }; - -private: - friend class EHScopeStack; - - Handler *getHandlers() { - return reinterpret_cast<Handler*>(this+1); - } - - const Handler *getHandlers() const { - return reinterpret_cast<const Handler*>(this+1); - } - -public: - static size_t getSizeForNumHandlers(unsigned N) { - return sizeof(EHCatchScope) + N * sizeof(Handler); - } - - EHCatchScope(unsigned numHandlers, - EHScopeStack::stable_iterator enclosingEHScope) - : EHScope(Catch, enclosingEHScope) { - CatchBits.NumHandlers = numHandlers; - assert(CatchBits.NumHandlers == numHandlers && "NumHandlers overflow?"); - } - - unsigned getNumHandlers() const { - return CatchBits.NumHandlers; - } - - void setCatchAllHandler(unsigned I, llvm::BasicBlock *Block) { - setHandler(I, CatchTypeInfo{nullptr, 0}, Block); - } - - void setHandler(unsigned I, llvm::Constant *Type, llvm::BasicBlock *Block) { - assert(I < getNumHandlers()); - getHandlers()[I].Type = CatchTypeInfo{Type, 0}; - getHandlers()[I].Block = Block; - } - - void setHandler(unsigned I, CatchTypeInfo Type, llvm::BasicBlock *Block) { - assert(I < getNumHandlers()); - getHandlers()[I].Type = Type; - getHandlers()[I].Block = Block; - } - - const Handler &getHandler(unsigned I) const { - assert(I < getNumHandlers()); - return getHandlers()[I]; - } - - // Clear all handler blocks. - // FIXME: it's better to always call clearHandlerBlocks in DTOR and have a - // 'takeHandler' or some such function which removes ownership from the - // EHCatchScope object if the handlers should live longer than EHCatchScope. - void clearHandlerBlocks() { - for (unsigned I = 0, N = getNumHandlers(); I != N; ++I) - delete getHandler(I).Block; - } - - typedef const Handler *iterator; - iterator begin() const { return getHandlers(); } - iterator end() const { return getHandlers() + getNumHandlers(); } - - static bool classof(const EHScope *Scope) { - return Scope->getKind() == Catch; - } -}; - -/// A cleanup scope which generates the cleanup blocks lazily. -class alignas(8) EHCleanupScope : public EHScope { - /// The nearest normal cleanup scope enclosing this one. - EHScopeStack::stable_iterator EnclosingNormal; - - /// The nearest EH scope enclosing this one. - EHScopeStack::stable_iterator EnclosingEH; - - /// The dual entry/exit block along the normal edge. This is lazily - /// created if needed before the cleanup is popped. - llvm::BasicBlock *NormalBlock; - - /// An optional i1 variable indicating whether this cleanup has been - /// activated yet. - llvm::AllocaInst *ActiveFlag; - - /// Extra information required for cleanups that have resolved - /// branches through them. This has to be allocated on the side - /// because everything on the cleanup stack has be trivially - /// movable. - struct ExtInfo { - /// The destinations of normal branch-afters and branch-throughs. - llvm::SmallPtrSet<llvm::BasicBlock*, 4> Branches; - - /// Normal branch-afters. - SmallVector<std::pair<llvm::BasicBlock*,llvm::ConstantInt*>, 4> - BranchAfters; - }; - mutable struct ExtInfo *ExtInfo; - - /// The number of fixups required by enclosing scopes (not including - /// this one). If this is the top cleanup scope, all the fixups - /// from this index onwards belong to this scope. - unsigned FixupDepth; - - struct ExtInfo &getExtInfo() { - if (!ExtInfo) ExtInfo = new struct ExtInfo(); - return *ExtInfo; - } - - const struct ExtInfo &getExtInfo() const { - if (!ExtInfo) ExtInfo = new struct ExtInfo(); - return *ExtInfo; - } - -public: - /// Gets the size required for a lazy cleanup scope with the given - /// cleanup-data requirements. - static size_t getSizeForCleanupSize(size_t Size) { - return sizeof(EHCleanupScope) + Size; - } - - size_t getAllocatedSize() const { - return sizeof(EHCleanupScope) + CleanupBits.CleanupSize; - } - - EHCleanupScope(bool isNormal, bool isEH, bool isActive, - unsigned cleanupSize, unsigned fixupDepth, - EHScopeStack::stable_iterator enclosingNormal, - EHScopeStack::stable_iterator enclosingEH) - : EHScope(EHScope::Cleanup, enclosingEH), - EnclosingNormal(enclosingNormal), NormalBlock(nullptr), - ActiveFlag(nullptr), ExtInfo(nullptr), FixupDepth(fixupDepth) { - CleanupBits.IsNormalCleanup = isNormal; - CleanupBits.IsEHCleanup = isEH; - CleanupBits.IsActive = isActive; - CleanupBits.IsLifetimeMarker = false; - CleanupBits.TestFlagInNormalCleanup = false; - CleanupBits.TestFlagInEHCleanup = false; - CleanupBits.CleanupSize = cleanupSize; - - assert(CleanupBits.CleanupSize == cleanupSize && "cleanup size overflow"); - } - - void Destroy() { - delete ExtInfo; - } - // Objects of EHCleanupScope are not destructed. Use Destroy(). - ~EHCleanupScope() = delete; - - bool isNormalCleanup() const { return CleanupBits.IsNormalCleanup; } - llvm::BasicBlock *getNormalBlock() const { return NormalBlock; } - void setNormalBlock(llvm::BasicBlock *BB) { NormalBlock = BB; } - - bool isEHCleanup() const { return CleanupBits.IsEHCleanup; } - - bool isActive() const { return CleanupBits.IsActive; } - void setActive(bool A) { CleanupBits.IsActive = A; } - - bool isLifetimeMarker() const { return CleanupBits.IsLifetimeMarker; } - void setLifetimeMarker() { CleanupBits.IsLifetimeMarker = true; } - - bool hasActiveFlag() const { return ActiveFlag != nullptr; } - Address getActiveFlag() const { - return Address(ActiveFlag, CharUnits::One()); - } - void setActiveFlag(Address Var) { - assert(Var.getAlignment().isOne()); - ActiveFlag = cast<llvm::AllocaInst>(Var.getPointer()); - } - - void setTestFlagInNormalCleanup() { - CleanupBits.TestFlagInNormalCleanup = true; - } - bool shouldTestFlagInNormalCleanup() const { - return CleanupBits.TestFlagInNormalCleanup; - } - - void setTestFlagInEHCleanup() { - CleanupBits.TestFlagInEHCleanup = true; - } - bool shouldTestFlagInEHCleanup() const { - return CleanupBits.TestFlagInEHCleanup; - } - - unsigned getFixupDepth() const { return FixupDepth; } - EHScopeStack::stable_iterator getEnclosingNormalCleanup() const { - return EnclosingNormal; - } - - size_t getCleanupSize() const { return CleanupBits.CleanupSize; } - void *getCleanupBuffer() { return this + 1; } - - EHScopeStack::Cleanup *getCleanup() { - return reinterpret_cast<EHScopeStack::Cleanup*>(getCleanupBuffer()); - } - - /// True if this cleanup scope has any branch-afters or branch-throughs. - bool hasBranches() const { return ExtInfo && !ExtInfo->Branches.empty(); } - - /// Add a branch-after to this cleanup scope. A branch-after is a - /// branch from a point protected by this (normal) cleanup to a - /// point in the normal cleanup scope immediately containing it. - /// For example, - /// for (;;) { A a; break; } - /// contains a branch-after. - /// - /// Branch-afters each have their own destination out of the - /// cleanup, guaranteed distinct from anything else threaded through - /// it. Therefore branch-afters usually force a switch after the - /// cleanup. - void addBranchAfter(llvm::ConstantInt *Index, - llvm::BasicBlock *Block) { - struct ExtInfo &ExtInfo = getExtInfo(); - if (ExtInfo.Branches.insert(Block).second) - ExtInfo.BranchAfters.push_back(std::make_pair(Block, Index)); - } - - /// Return the number of unique branch-afters on this scope. - unsigned getNumBranchAfters() const { - return ExtInfo ? ExtInfo->BranchAfters.size() : 0; - } - - llvm::BasicBlock *getBranchAfterBlock(unsigned I) const { - assert(I < getNumBranchAfters()); - return ExtInfo->BranchAfters[I].first; - } - - llvm::ConstantInt *getBranchAfterIndex(unsigned I) const { - assert(I < getNumBranchAfters()); - return ExtInfo->BranchAfters[I].second; - } - - /// Add a branch-through to this cleanup scope. A branch-through is - /// a branch from a scope protected by this (normal) cleanup to an - /// enclosing scope other than the immediately-enclosing normal - /// cleanup scope. - /// - /// In the following example, the branch through B's scope is a - /// branch-through, while the branch through A's scope is a - /// branch-after: - /// for (;;) { A a; B b; break; } - /// - /// All branch-throughs have a common destination out of the - /// cleanup, one possibly shared with the fall-through. Therefore - /// branch-throughs usually don't force a switch after the cleanup. - /// - /// \return true if the branch-through was new to this scope - bool addBranchThrough(llvm::BasicBlock *Block) { - return getExtInfo().Branches.insert(Block).second; - } - - /// Determines if this cleanup scope has any branch throughs. - bool hasBranchThroughs() const { - if (!ExtInfo) return false; - return (ExtInfo->BranchAfters.size() != ExtInfo->Branches.size()); - } - - static bool classof(const EHScope *Scope) { - return (Scope->getKind() == Cleanup); - } -}; -// NOTE: there's a bunch of different data classes tacked on after an -// EHCleanupScope. It is asserted (in EHScopeStack::pushCleanup*) that -// they don't require greater alignment than ScopeStackAlignment. So, -// EHCleanupScope ought to have alignment equal to that -- not more -// (would be misaligned by the stack allocator), and not less (would -// break the appended classes). -static_assert(alignof(EHCleanupScope) == EHScopeStack::ScopeStackAlignment, - "EHCleanupScope expected alignment"); - -/// An exceptions scope which filters exceptions thrown through it. -/// Only exceptions matching the filter types will be permitted to be -/// thrown. -/// -/// This is used to implement C++ exception specifications. -class EHFilterScope : public EHScope { - // Essentially ends in a flexible array member: - // llvm::Value *FilterTypes[0]; - - llvm::Value **getFilters() { - return reinterpret_cast<llvm::Value**>(this+1); - } - - llvm::Value * const *getFilters() const { - return reinterpret_cast<llvm::Value* const *>(this+1); - } - -public: - EHFilterScope(unsigned numFilters) - : EHScope(Filter, EHScopeStack::stable_end()) { - FilterBits.NumFilters = numFilters; - assert(FilterBits.NumFilters == numFilters && "NumFilters overflow"); - } - - static size_t getSizeForNumFilters(unsigned numFilters) { - return sizeof(EHFilterScope) + numFilters * sizeof(llvm::Value*); - } - - unsigned getNumFilters() const { return FilterBits.NumFilters; } - - void setFilter(unsigned i, llvm::Value *filterValue) { - assert(i < getNumFilters()); - getFilters()[i] = filterValue; - } - - llvm::Value *getFilter(unsigned i) const { - assert(i < getNumFilters()); - return getFilters()[i]; - } - - static bool classof(const EHScope *scope) { - return scope->getKind() == Filter; - } -}; - -/// An exceptions scope which calls std::terminate if any exception -/// reaches it. -class EHTerminateScope : public EHScope { -public: - EHTerminateScope(EHScopeStack::stable_iterator enclosingEHScope) - : EHScope(Terminate, enclosingEHScope) {} - static size_t getSize() { return sizeof(EHTerminateScope); } - - static bool classof(const EHScope *scope) { - return scope->getKind() == Terminate; - } -}; - -class EHPadEndScope : public EHScope { -public: - EHPadEndScope(EHScopeStack::stable_iterator enclosingEHScope) - : EHScope(PadEnd, enclosingEHScope) {} - static size_t getSize() { return sizeof(EHPadEndScope); } - - static bool classof(const EHScope *scope) { - return scope->getKind() == PadEnd; - } -}; - -/// A non-stable pointer into the scope stack. -class EHScopeStack::iterator { - char *Ptr; - - friend class EHScopeStack; - explicit iterator(char *Ptr) : Ptr(Ptr) {} - -public: - iterator() : Ptr(nullptr) {} - - EHScope *get() const { - return reinterpret_cast<EHScope*>(Ptr); - } - - EHScope *operator->() const { return get(); } - EHScope &operator*() const { return *get(); } - - iterator &operator++() { - size_t Size; - switch (get()->getKind()) { - case EHScope::Catch: - Size = EHCatchScope::getSizeForNumHandlers( - static_cast<const EHCatchScope *>(get())->getNumHandlers()); - break; - - case EHScope::Filter: - Size = EHFilterScope::getSizeForNumFilters( - static_cast<const EHFilterScope *>(get())->getNumFilters()); - break; - - case EHScope::Cleanup: - Size = static_cast<const EHCleanupScope *>(get())->getAllocatedSize(); - break; - - case EHScope::Terminate: - Size = EHTerminateScope::getSize(); - break; - - case EHScope::PadEnd: - Size = EHPadEndScope::getSize(); - break; - } - Ptr += llvm::alignTo(Size, ScopeStackAlignment); - return *this; - } - - iterator next() { - iterator copy = *this; - ++copy; - return copy; - } - - iterator operator++(int) { - iterator copy = *this; - operator++(); - return copy; - } - - bool encloses(iterator other) const { return Ptr >= other.Ptr; } - bool strictlyEncloses(iterator other) const { return Ptr > other.Ptr; } - - bool operator==(iterator other) const { return Ptr == other.Ptr; } - bool operator!=(iterator other) const { return Ptr != other.Ptr; } -}; - -inline EHScopeStack::iterator EHScopeStack::begin() const { - return iterator(StartOfData); -} - -inline EHScopeStack::iterator EHScopeStack::end() const { - return iterator(EndOfBuffer); -} - -inline void EHScopeStack::popCatch() { - assert(!empty() && "popping exception stack when not empty"); - - EHCatchScope &scope = cast<EHCatchScope>(*begin()); - InnermostEHScope = scope.getEnclosingEHScope(); - deallocate(EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers())); -} - -inline void EHScopeStack::popTerminate() { - assert(!empty() && "popping exception stack when not empty"); - - EHTerminateScope &scope = cast<EHTerminateScope>(*begin()); - InnermostEHScope = scope.getEnclosingEHScope(); - deallocate(EHTerminateScope::getSize()); -} - -inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const { - assert(sp.isValid() && "finding invalid savepoint"); - assert(sp.Size <= stable_begin().Size && "finding savepoint after pop"); - return iterator(EndOfBuffer - sp.Size); -} - -inline EHScopeStack::stable_iterator -EHScopeStack::stabilize(iterator ir) const { - assert(StartOfData <= ir.Ptr && ir.Ptr <= EndOfBuffer); - return stable_iterator(EndOfBuffer - ir.Ptr); -} - -/// The exceptions personality for a function. -struct EHPersonality { - const char *PersonalityFn; - - // If this is non-null, this personality requires a non-standard - // function for rethrowing an exception after a catchall cleanup. - // This function must have prototype void(void*). - const char *CatchallRethrowFn; - - static const EHPersonality &get(CodeGenModule &CGM, const FunctionDecl *FD); - static const EHPersonality &get(CodeGenFunction &CGF); - - static const EHPersonality GNU_C; - static const EHPersonality GNU_C_SJLJ; - static const EHPersonality GNU_C_SEH; - static const EHPersonality GNU_ObjC; - static const EHPersonality GNU_ObjC_SJLJ; - static const EHPersonality GNU_ObjC_SEH; - static const EHPersonality GNUstep_ObjC; - static const EHPersonality GNU_ObjCXX; - static const EHPersonality NeXT_ObjC; - static const EHPersonality GNU_CPlusPlus; - static const EHPersonality GNU_CPlusPlus_SJLJ; - static const EHPersonality GNU_CPlusPlus_SEH; - static const EHPersonality MSVC_except_handler; - static const EHPersonality MSVC_C_specific_handler; - static const EHPersonality MSVC_CxxFrameHandler3; - static const EHPersonality GNU_Wasm_CPlusPlus; - - /// Does this personality use landingpads or the family of pad instructions - /// designed to form funclets? - bool usesFuncletPads() const { - return isMSVCPersonality() || isWasmPersonality(); - } - - bool isMSVCPersonality() const { - return this == &MSVC_except_handler || this == &MSVC_C_specific_handler || - this == &MSVC_CxxFrameHandler3; - } - - bool isWasmPersonality() const { return this == &GNU_Wasm_CPlusPlus; } - - bool isMSVCXXPersonality() const { return this == &MSVC_CxxFrameHandler3; } -}; -} -} - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp deleted file mode 100644 index 80fa7c87363..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp +++ /dev/null @@ -1,760 +0,0 @@ -//===----- CGCoroutine.cpp - Emit LLVM Code for C++ coroutines ------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code dealing with C++ code generation of coroutines. -// -//===----------------------------------------------------------------------===// - -#include "CGCleanup.h" -#include "CodeGenFunction.h" -#include "llvm/ADT/ScopeExit.h" -#include "clang/AST/StmtCXX.h" -#include "clang/AST/StmtVisitor.h" - -using namespace clang; -using namespace CodeGen; - -using llvm::Value; -using llvm::BasicBlock; - -namespace { -enum class AwaitKind { Init, Normal, Yield, Final }; -static constexpr llvm::StringLiteral AwaitKindStr[] = {"init", "await", "yield", - "final"}; -} - -struct clang::CodeGen::CGCoroData { - // What is the current await expression kind and how many - // await/yield expressions were encountered so far. - // These are used to generate pretty labels for await expressions in LLVM IR. - AwaitKind CurrentAwaitKind = AwaitKind::Init; - unsigned AwaitNum = 0; - unsigned YieldNum = 0; - - // How many co_return statements are in the coroutine. Used to decide whether - // we need to add co_return; equivalent at the end of the user authored body. - unsigned CoreturnCount = 0; - - // A branch to this block is emitted when coroutine needs to suspend. - llvm::BasicBlock *SuspendBB = nullptr; - - // The promise type's 'unhandled_exception' handler, if it defines one. - Stmt *ExceptionHandler = nullptr; - - // A temporary i1 alloca that stores whether 'await_resume' threw an - // exception. If it did, 'true' is stored in this variable, and the coroutine - // body must be skipped. If the promise type does not define an exception - // handler, this is null. - llvm::Value *ResumeEHVar = nullptr; - - // Stores the jump destination just before the coroutine memory is freed. - // This is the destination that every suspend point jumps to for the cleanup - // branch. - CodeGenFunction::JumpDest CleanupJD; - - // Stores the jump destination just before the final suspend. The co_return - // statements jumps to this point after calling return_xxx promise member. - CodeGenFunction::JumpDest FinalJD; - - // Stores the llvm.coro.id emitted in the function so that we can supply it - // as the first argument to coro.begin, coro.alloc and coro.free intrinsics. - // Note: llvm.coro.id returns a token that cannot be directly expressed in a - // builtin. - llvm::CallInst *CoroId = nullptr; - - // Stores the llvm.coro.begin emitted in the function so that we can replace - // all coro.frame intrinsics with direct SSA value of coro.begin that returns - // the address of the coroutine frame of the current coroutine. - llvm::CallInst *CoroBegin = nullptr; - - // Stores the last emitted coro.free for the deallocate expressions, we use it - // to wrap dealloc code with if(auto mem = coro.free) dealloc(mem). - llvm::CallInst *LastCoroFree = nullptr; - - // If coro.id came from the builtin, remember the expression to give better - // diagnostic. If CoroIdExpr is nullptr, the coro.id was created by - // EmitCoroutineBody. - CallExpr const *CoroIdExpr = nullptr; -}; - -// Defining these here allows to keep CGCoroData private to this file. -clang::CodeGen::CodeGenFunction::CGCoroInfo::CGCoroInfo() {} -CodeGenFunction::CGCoroInfo::~CGCoroInfo() {} - -static void createCoroData(CodeGenFunction &CGF, - CodeGenFunction::CGCoroInfo &CurCoro, - llvm::CallInst *CoroId, - CallExpr const *CoroIdExpr = nullptr) { - if (CurCoro.Data) { - if (CurCoro.Data->CoroIdExpr) - CGF.CGM.Error(CoroIdExpr->getBeginLoc(), - "only one __builtin_coro_id can be used in a function"); - else if (CoroIdExpr) - CGF.CGM.Error(CoroIdExpr->getBeginLoc(), - "__builtin_coro_id shall not be used in a C++ coroutine"); - else - llvm_unreachable("EmitCoroutineBodyStatement called twice?"); - - return; - } - - CurCoro.Data = std::unique_ptr<CGCoroData>(new CGCoroData); - CurCoro.Data->CoroId = CoroId; - CurCoro.Data->CoroIdExpr = CoroIdExpr; -} - -// Synthesize a pretty name for a suspend point. -static SmallString<32> buildSuspendPrefixStr(CGCoroData &Coro, AwaitKind Kind) { - unsigned No = 0; - switch (Kind) { - case AwaitKind::Init: - case AwaitKind::Final: - break; - case AwaitKind::Normal: - No = ++Coro.AwaitNum; - break; - case AwaitKind::Yield: - No = ++Coro.YieldNum; - break; - } - SmallString<32> Prefix(AwaitKindStr[static_cast<unsigned>(Kind)]); - if (No > 1) { - Twine(No).toVector(Prefix); - } - return Prefix; -} - -static bool memberCallExpressionCanThrow(const Expr *E) { - if (const auto *CE = dyn_cast<CXXMemberCallExpr>(E)) - if (const auto *Proto = - CE->getMethodDecl()->getType()->getAs<FunctionProtoType>()) - if (isNoexceptExceptionSpec(Proto->getExceptionSpecType()) && - Proto->canThrow() == CT_Cannot) - return false; - return true; -} - -// Emit suspend expression which roughly looks like: -// -// auto && x = CommonExpr(); -// if (!x.await_ready()) { -// llvm_coro_save(); -// x.await_suspend(...); (*) -// llvm_coro_suspend(); (**) -// } -// x.await_resume(); -// -// where the result of the entire expression is the result of x.await_resume() -// -// (*) If x.await_suspend return type is bool, it allows to veto a suspend: -// if (x.await_suspend(...)) -// llvm_coro_suspend(); -// -// (**) llvm_coro_suspend() encodes three possible continuations as -// a switch instruction: -// -// %where-to = call i8 @llvm.coro.suspend(...) -// switch i8 %where-to, label %coro.ret [ ; jump to epilogue to suspend -// i8 0, label %yield.ready ; go here when resumed -// i8 1, label %yield.cleanup ; go here when destroyed -// ] -// -// See llvm's docs/Coroutines.rst for more details. -// -namespace { - struct LValueOrRValue { - LValue LV; - RValue RV; - }; -} -static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Coro, - CoroutineSuspendExpr const &S, - AwaitKind Kind, AggValueSlot aggSlot, - bool ignoreResult, bool forLValue) { - auto *E = S.getCommonExpr(); - - auto Binder = - CodeGenFunction::OpaqueValueMappingData::bind(CGF, S.getOpaqueValue(), E); - auto UnbindOnExit = llvm::make_scope_exit([&] { Binder.unbind(CGF); }); - - auto Prefix = buildSuspendPrefixStr(Coro, Kind); - BasicBlock *ReadyBlock = CGF.createBasicBlock(Prefix + Twine(".ready")); - BasicBlock *SuspendBlock = CGF.createBasicBlock(Prefix + Twine(".suspend")); - BasicBlock *CleanupBlock = CGF.createBasicBlock(Prefix + Twine(".cleanup")); - - // If expression is ready, no need to suspend. - CGF.EmitBranchOnBoolExpr(S.getReadyExpr(), ReadyBlock, SuspendBlock, 0); - - // Otherwise, emit suspend logic. - CGF.EmitBlock(SuspendBlock); - - auto &Builder = CGF.Builder; - llvm::Function *CoroSave = CGF.CGM.getIntrinsic(llvm::Intrinsic::coro_save); - auto *NullPtr = llvm::ConstantPointerNull::get(CGF.CGM.Int8PtrTy); - auto *SaveCall = Builder.CreateCall(CoroSave, {NullPtr}); - - auto *SuspendRet = CGF.EmitScalarExpr(S.getSuspendExpr()); - if (SuspendRet != nullptr && SuspendRet->getType()->isIntegerTy(1)) { - // Veto suspension if requested by bool returning await_suspend. - BasicBlock *RealSuspendBlock = - CGF.createBasicBlock(Prefix + Twine(".suspend.bool")); - CGF.Builder.CreateCondBr(SuspendRet, RealSuspendBlock, ReadyBlock); - SuspendBlock = RealSuspendBlock; - CGF.EmitBlock(RealSuspendBlock); - } - - // Emit the suspend point. - const bool IsFinalSuspend = (Kind == AwaitKind::Final); - llvm::Function *CoroSuspend = - CGF.CGM.getIntrinsic(llvm::Intrinsic::coro_suspend); - auto *SuspendResult = Builder.CreateCall( - CoroSuspend, {SaveCall, Builder.getInt1(IsFinalSuspend)}); - - // Create a switch capturing three possible continuations. - auto *Switch = Builder.CreateSwitch(SuspendResult, Coro.SuspendBB, 2); - Switch->addCase(Builder.getInt8(0), ReadyBlock); - Switch->addCase(Builder.getInt8(1), CleanupBlock); - - // Emit cleanup for this suspend point. - CGF.EmitBlock(CleanupBlock); - CGF.EmitBranchThroughCleanup(Coro.CleanupJD); - - // Emit await_resume expression. - CGF.EmitBlock(ReadyBlock); - - // Exception handling requires additional IR. If the 'await_resume' function - // is marked as 'noexcept', we avoid generating this additional IR. - CXXTryStmt *TryStmt = nullptr; - if (Coro.ExceptionHandler && Kind == AwaitKind::Init && - memberCallExpressionCanThrow(S.getResumeExpr())) { - Coro.ResumeEHVar = - CGF.CreateTempAlloca(Builder.getInt1Ty(), Prefix + Twine("resume.eh")); - Builder.CreateFlagStore(true, Coro.ResumeEHVar); - - auto Loc = S.getResumeExpr()->getExprLoc(); - auto *Catch = new (CGF.getContext()) - CXXCatchStmt(Loc, /*exDecl=*/nullptr, Coro.ExceptionHandler); - auto *TryBody = - CompoundStmt::Create(CGF.getContext(), S.getResumeExpr(), Loc, Loc); - TryStmt = CXXTryStmt::Create(CGF.getContext(), Loc, TryBody, Catch); - CGF.EnterCXXTryStmt(*TryStmt); - } - - LValueOrRValue Res; - if (forLValue) - Res.LV = CGF.EmitLValue(S.getResumeExpr()); - else - Res.RV = CGF.EmitAnyExpr(S.getResumeExpr(), aggSlot, ignoreResult); - - if (TryStmt) { - Builder.CreateFlagStore(false, Coro.ResumeEHVar); - CGF.ExitCXXTryStmt(*TryStmt); - } - - return Res; -} - -RValue CodeGenFunction::EmitCoawaitExpr(const CoawaitExpr &E, - AggValueSlot aggSlot, - bool ignoreResult) { - return emitSuspendExpression(*this, *CurCoro.Data, E, - CurCoro.Data->CurrentAwaitKind, aggSlot, - ignoreResult, /*forLValue*/false).RV; -} -RValue CodeGenFunction::EmitCoyieldExpr(const CoyieldExpr &E, - AggValueSlot aggSlot, - bool ignoreResult) { - return emitSuspendExpression(*this, *CurCoro.Data, E, AwaitKind::Yield, - aggSlot, ignoreResult, /*forLValue*/false).RV; -} - -void CodeGenFunction::EmitCoreturnStmt(CoreturnStmt const &S) { - ++CurCoro.Data->CoreturnCount; - const Expr *RV = S.getOperand(); - if (RV && RV->getType()->isVoidType()) { - // Make sure to evaluate the expression of a co_return with a void - // expression for side effects. - RunCleanupsScope cleanupScope(*this); - EmitIgnoredExpr(RV); - } - EmitStmt(S.getPromiseCall()); - EmitBranchThroughCleanup(CurCoro.Data->FinalJD); -} - - -#ifndef NDEBUG -static QualType getCoroutineSuspendExprReturnType(const ASTContext &Ctx, - const CoroutineSuspendExpr *E) { - const auto *RE = E->getResumeExpr(); - // Is it possible for RE to be a CXXBindTemporaryExpr wrapping - // a MemberCallExpr? - assert(isa<CallExpr>(RE) && "unexpected suspend expression type"); - return cast<CallExpr>(RE)->getCallReturnType(Ctx); -} -#endif - -LValue -CodeGenFunction::EmitCoawaitLValue(const CoawaitExpr *E) { - assert(getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType() && - "Can't have a scalar return unless the return type is a " - "reference type!"); - return emitSuspendExpression(*this, *CurCoro.Data, *E, - CurCoro.Data->CurrentAwaitKind, AggValueSlot::ignored(), - /*ignoreResult*/false, /*forLValue*/true).LV; -} - -LValue -CodeGenFunction::EmitCoyieldLValue(const CoyieldExpr *E) { - assert(getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType() && - "Can't have a scalar return unless the return type is a " - "reference type!"); - return emitSuspendExpression(*this, *CurCoro.Data, *E, - AwaitKind::Yield, AggValueSlot::ignored(), - /*ignoreResult*/false, /*forLValue*/true).LV; -} - -// Hunts for the parameter reference in the parameter copy/move declaration. -namespace { -struct GetParamRef : public StmtVisitor<GetParamRef> { -public: - DeclRefExpr *Expr = nullptr; - GetParamRef() {} - void VisitDeclRefExpr(DeclRefExpr *E) { - assert(Expr == nullptr && "multilple declref in param move"); - Expr = E; - } - void VisitStmt(Stmt *S) { - for (auto *C : S->children()) { - if (C) - Visit(C); - } - } -}; -} - -// This class replaces references to parameters to their copies by changing -// the addresses in CGF.LocalDeclMap and restoring back the original values in -// its destructor. - -namespace { - struct ParamReferenceReplacerRAII { - CodeGenFunction::DeclMapTy SavedLocals; - CodeGenFunction::DeclMapTy& LocalDeclMap; - - ParamReferenceReplacerRAII(CodeGenFunction::DeclMapTy &LocalDeclMap) - : LocalDeclMap(LocalDeclMap) {} - - void addCopy(DeclStmt const *PM) { - // Figure out what param it refers to. - - assert(PM->isSingleDecl()); - VarDecl const*VD = static_cast<VarDecl const*>(PM->getSingleDecl()); - Expr const *InitExpr = VD->getInit(); - GetParamRef Visitor; - Visitor.Visit(const_cast<Expr*>(InitExpr)); - assert(Visitor.Expr); - DeclRefExpr *DREOrig = Visitor.Expr; - auto *PD = DREOrig->getDecl(); - - auto it = LocalDeclMap.find(PD); - assert(it != LocalDeclMap.end() && "parameter is not found"); - SavedLocals.insert({ PD, it->second }); - - auto copyIt = LocalDeclMap.find(VD); - assert(copyIt != LocalDeclMap.end() && "parameter copy is not found"); - it->second = copyIt->getSecond(); - } - - ~ParamReferenceReplacerRAII() { - for (auto&& SavedLocal : SavedLocals) { - LocalDeclMap.insert({SavedLocal.first, SavedLocal.second}); - } - } - }; -} - -// For WinEH exception representation backend needs to know what funclet coro.end -// belongs to. That information is passed in a funclet bundle. -static SmallVector<llvm::OperandBundleDef, 1> -getBundlesForCoroEnd(CodeGenFunction &CGF) { - SmallVector<llvm::OperandBundleDef, 1> BundleList; - - if (llvm::Instruction *EHPad = CGF.CurrentFuncletPad) - BundleList.emplace_back("funclet", EHPad); - - return BundleList; -} - -namespace { -// We will insert coro.end to cut any of the destructors for objects that -// do not need to be destroyed once the coroutine is resumed. -// See llvm/docs/Coroutines.rst for more details about coro.end. -struct CallCoroEnd final : public EHScopeStack::Cleanup { - void Emit(CodeGenFunction &CGF, Flags flags) override { - auto &CGM = CGF.CGM; - auto *NullPtr = llvm::ConstantPointerNull::get(CGF.Int8PtrTy); - llvm::Function *CoroEndFn = CGM.getIntrinsic(llvm::Intrinsic::coro_end); - // See if we have a funclet bundle to associate coro.end with. (WinEH) - auto Bundles = getBundlesForCoroEnd(CGF); - auto *CoroEnd = CGF.Builder.CreateCall( - CoroEndFn, {NullPtr, CGF.Builder.getTrue()}, Bundles); - if (Bundles.empty()) { - // Otherwise, (landingpad model), create a conditional branch that leads - // either to a cleanup block or a block with EH resume instruction. - auto *ResumeBB = CGF.getEHResumeBlock(/*cleanup=*/true); - auto *CleanupContBB = CGF.createBasicBlock("cleanup.cont"); - CGF.Builder.CreateCondBr(CoroEnd, ResumeBB, CleanupContBB); - CGF.EmitBlock(CleanupContBB); - } - } -}; -} - -namespace { -// Make sure to call coro.delete on scope exit. -struct CallCoroDelete final : public EHScopeStack::Cleanup { - Stmt *Deallocate; - - // Emit "if (coro.free(CoroId, CoroBegin)) Deallocate;" - - // Note: That deallocation will be emitted twice: once for a normal exit and - // once for exceptional exit. This usage is safe because Deallocate does not - // contain any declarations. The SubStmtBuilder::makeNewAndDeleteExpr() - // builds a single call to a deallocation function which is safe to emit - // multiple times. - void Emit(CodeGenFunction &CGF, Flags) override { - // Remember the current point, as we are going to emit deallocation code - // first to get to coro.free instruction that is an argument to a delete - // call. - BasicBlock *SaveInsertBlock = CGF.Builder.GetInsertBlock(); - - auto *FreeBB = CGF.createBasicBlock("coro.free"); - CGF.EmitBlock(FreeBB); - CGF.EmitStmt(Deallocate); - - auto *AfterFreeBB = CGF.createBasicBlock("after.coro.free"); - CGF.EmitBlock(AfterFreeBB); - - // We should have captured coro.free from the emission of deallocate. - auto *CoroFree = CGF.CurCoro.Data->LastCoroFree; - if (!CoroFree) { - CGF.CGM.Error(Deallocate->getBeginLoc(), - "Deallocation expressoin does not refer to coro.free"); - return; - } - - // Get back to the block we were originally and move coro.free there. - auto *InsertPt = SaveInsertBlock->getTerminator(); - CoroFree->moveBefore(InsertPt); - CGF.Builder.SetInsertPoint(InsertPt); - - // Add if (auto *mem = coro.free) Deallocate; - auto *NullPtr = llvm::ConstantPointerNull::get(CGF.Int8PtrTy); - auto *Cond = CGF.Builder.CreateICmpNE(CoroFree, NullPtr); - CGF.Builder.CreateCondBr(Cond, FreeBB, AfterFreeBB); - - // No longer need old terminator. - InsertPt->eraseFromParent(); - CGF.Builder.SetInsertPoint(AfterFreeBB); - } - explicit CallCoroDelete(Stmt *DeallocStmt) : Deallocate(DeallocStmt) {} -}; -} - -namespace { -struct GetReturnObjectManager { - CodeGenFunction &CGF; - CGBuilderTy &Builder; - const CoroutineBodyStmt &S; - - Address GroActiveFlag; - CodeGenFunction::AutoVarEmission GroEmission; - - GetReturnObjectManager(CodeGenFunction &CGF, const CoroutineBodyStmt &S) - : CGF(CGF), Builder(CGF.Builder), S(S), GroActiveFlag(Address::invalid()), - GroEmission(CodeGenFunction::AutoVarEmission::invalid()) {} - - // The gro variable has to outlive coroutine frame and coroutine promise, but, - // it can only be initialized after coroutine promise was created, thus, we - // split its emission in two parts. EmitGroAlloca emits an alloca and sets up - // cleanups. Later when coroutine promise is available we initialize the gro - // and sets the flag that the cleanup is now active. - - void EmitGroAlloca() { - auto *GroDeclStmt = dyn_cast<DeclStmt>(S.getResultDecl()); - if (!GroDeclStmt) { - // If get_return_object returns void, no need to do an alloca. - return; - } - - auto *GroVarDecl = cast<VarDecl>(GroDeclStmt->getSingleDecl()); - - // Set GRO flag that it is not initialized yet - GroActiveFlag = - CGF.CreateTempAlloca(Builder.getInt1Ty(), CharUnits::One(), "gro.active"); - Builder.CreateStore(Builder.getFalse(), GroActiveFlag); - - GroEmission = CGF.EmitAutoVarAlloca(*GroVarDecl); - - // Remember the top of EHStack before emitting the cleanup. - auto old_top = CGF.EHStack.stable_begin(); - CGF.EmitAutoVarCleanups(GroEmission); - auto top = CGF.EHStack.stable_begin(); - - // Make the cleanup conditional on gro.active - for (auto b = CGF.EHStack.find(top), e = CGF.EHStack.find(old_top); - b != e; b++) { - if (auto *Cleanup = dyn_cast<EHCleanupScope>(&*b)) { - assert(!Cleanup->hasActiveFlag() && "cleanup already has active flag?"); - Cleanup->setActiveFlag(GroActiveFlag); - Cleanup->setTestFlagInEHCleanup(); - Cleanup->setTestFlagInNormalCleanup(); - } - } - } - - void EmitGroInit() { - if (!GroActiveFlag.isValid()) { - // No Gro variable was allocated. Simply emit the call to - // get_return_object. - CGF.EmitStmt(S.getResultDecl()); - return; - } - - CGF.EmitAutoVarInit(GroEmission); - Builder.CreateStore(Builder.getTrue(), GroActiveFlag); - } -}; -} - -static void emitBodyAndFallthrough(CodeGenFunction &CGF, - const CoroutineBodyStmt &S, Stmt *Body) { - CGF.EmitStmt(Body); - const bool CanFallthrough = CGF.Builder.GetInsertBlock(); - if (CanFallthrough) - if (Stmt *OnFallthrough = S.getFallthroughHandler()) - CGF.EmitStmt(OnFallthrough); -} - -void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) { - auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy()); - auto &TI = CGM.getContext().getTargetInfo(); - unsigned NewAlign = TI.getNewAlign() / TI.getCharWidth(); - - auto *EntryBB = Builder.GetInsertBlock(); - auto *AllocBB = createBasicBlock("coro.alloc"); - auto *InitBB = createBasicBlock("coro.init"); - auto *FinalBB = createBasicBlock("coro.final"); - auto *RetBB = createBasicBlock("coro.ret"); - - auto *CoroId = Builder.CreateCall( - CGM.getIntrinsic(llvm::Intrinsic::coro_id), - {Builder.getInt32(NewAlign), NullPtr, NullPtr, NullPtr}); - createCoroData(*this, CurCoro, CoroId); - CurCoro.Data->SuspendBB = RetBB; - - // Backend is allowed to elide memory allocations, to help it, emit - // auto mem = coro.alloc() ? 0 : ... allocation code ...; - auto *CoroAlloc = Builder.CreateCall( - CGM.getIntrinsic(llvm::Intrinsic::coro_alloc), {CoroId}); - - Builder.CreateCondBr(CoroAlloc, AllocBB, InitBB); - - EmitBlock(AllocBB); - auto *AllocateCall = EmitScalarExpr(S.getAllocate()); - auto *AllocOrInvokeContBB = Builder.GetInsertBlock(); - - // Handle allocation failure if 'ReturnStmtOnAllocFailure' was provided. - if (auto *RetOnAllocFailure = S.getReturnStmtOnAllocFailure()) { - auto *RetOnFailureBB = createBasicBlock("coro.ret.on.failure"); - - // See if allocation was successful. - auto *NullPtr = llvm::ConstantPointerNull::get(Int8PtrTy); - auto *Cond = Builder.CreateICmpNE(AllocateCall, NullPtr); - Builder.CreateCondBr(Cond, InitBB, RetOnFailureBB); - - // If not, return OnAllocFailure object. - EmitBlock(RetOnFailureBB); - EmitStmt(RetOnAllocFailure); - } - else { - Builder.CreateBr(InitBB); - } - - EmitBlock(InitBB); - - // Pass the result of the allocation to coro.begin. - auto *Phi = Builder.CreatePHI(VoidPtrTy, 2); - Phi->addIncoming(NullPtr, EntryBB); - Phi->addIncoming(AllocateCall, AllocOrInvokeContBB); - auto *CoroBegin = Builder.CreateCall( - CGM.getIntrinsic(llvm::Intrinsic::coro_begin), {CoroId, Phi}); - CurCoro.Data->CoroBegin = CoroBegin; - - GetReturnObjectManager GroManager(*this, S); - GroManager.EmitGroAlloca(); - - CurCoro.Data->CleanupJD = getJumpDestInCurrentScope(RetBB); - { - ParamReferenceReplacerRAII ParamReplacer(LocalDeclMap); - CodeGenFunction::RunCleanupsScope ResumeScope(*this); - EHStack.pushCleanup<CallCoroDelete>(NormalAndEHCleanup, S.getDeallocate()); - - // Create parameter copies. We do it before creating a promise, since an - // evolution of coroutine TS may allow promise constructor to observe - // parameter copies. - for (auto *PM : S.getParamMoves()) { - EmitStmt(PM); - ParamReplacer.addCopy(cast<DeclStmt>(PM)); - // TODO: if(CoroParam(...)) need to surround ctor and dtor - // for the copy, so that llvm can elide it if the copy is - // not needed. - } - - EmitStmt(S.getPromiseDeclStmt()); - - Address PromiseAddr = GetAddrOfLocalVar(S.getPromiseDecl()); - auto *PromiseAddrVoidPtr = - new llvm::BitCastInst(PromiseAddr.getPointer(), 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); - - // Now we have the promise, initialize the GRO - GroManager.EmitGroInit(); - - EHStack.pushCleanup<CallCoroEnd>(EHCleanup); - - CurCoro.Data->CurrentAwaitKind = AwaitKind::Init; - CurCoro.Data->ExceptionHandler = S.getExceptionHandler(); - EmitStmt(S.getInitSuspendStmt()); - CurCoro.Data->FinalJD = getJumpDestInCurrentScope(FinalBB); - - CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal; - - if (CurCoro.Data->ExceptionHandler) { - // If we generated IR to record whether an exception was thrown from - // 'await_resume', then use that IR to determine whether the coroutine - // body should be skipped. - // If we didn't generate the IR (perhaps because 'await_resume' was marked - // as 'noexcept'), then we skip this check. - BasicBlock *ContBB = nullptr; - if (CurCoro.Data->ResumeEHVar) { - BasicBlock *BodyBB = createBasicBlock("coro.resumed.body"); - ContBB = createBasicBlock("coro.resumed.cont"); - Value *SkipBody = Builder.CreateFlagLoad(CurCoro.Data->ResumeEHVar, - "coro.resumed.eh"); - Builder.CreateCondBr(SkipBody, ContBB, BodyBB); - EmitBlock(BodyBB); - } - - auto Loc = S.getBeginLoc(); - CXXCatchStmt Catch(Loc, /*exDecl=*/nullptr, - CurCoro.Data->ExceptionHandler); - auto *TryStmt = - CXXTryStmt::Create(getContext(), Loc, S.getBody(), &Catch); - - EnterCXXTryStmt(*TryStmt); - emitBodyAndFallthrough(*this, S, TryStmt->getTryBlock()); - ExitCXXTryStmt(*TryStmt); - - if (ContBB) - EmitBlock(ContBB); - } - else { - emitBodyAndFallthrough(*this, S, S.getBody()); - } - - // See if we need to generate final suspend. - const bool CanFallthrough = Builder.GetInsertBlock(); - const bool HasCoreturns = CurCoro.Data->CoreturnCount > 0; - if (CanFallthrough || HasCoreturns) { - EmitBlock(FinalBB); - CurCoro.Data->CurrentAwaitKind = AwaitKind::Final; - EmitStmt(S.getFinalSuspendStmt()); - } else { - // We don't need FinalBB. Emit it to make sure the block is deleted. - EmitBlock(FinalBB, /*IsFinished=*/true); - } - } - - EmitBlock(RetBB); - // Emit coro.end before getReturnStmt (and parameter destructors), since - // resume and destroy parts of the coroutine should not include them. - llvm::Function *CoroEnd = CGM.getIntrinsic(llvm::Intrinsic::coro_end); - Builder.CreateCall(CoroEnd, {NullPtr, Builder.getFalse()}); - - if (Stmt *Ret = S.getReturnStmt()) - EmitStmt(Ret); -} - -// Emit coroutine intrinsic and patch up arguments of the token type. -RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E, - unsigned int IID) { - SmallVector<llvm::Value *, 8> Args; - switch (IID) { - default: - break; - // The coro.frame builtin is replaced with an SSA value of the coro.begin - // intrinsic. - case llvm::Intrinsic::coro_frame: { - if (CurCoro.Data && CurCoro.Data->CoroBegin) { - return RValue::get(CurCoro.Data->CoroBegin); - } - CGM.Error(E->getBeginLoc(), "this builtin expect that __builtin_coro_begin " - "has been used earlier in this function"); - auto NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy()); - return RValue::get(NullPtr); - } - // The following three intrinsics take a token parameter referring to a token - // returned by earlier call to @llvm.coro.id. Since we cannot represent it in - // builtins, we patch it up here. - case llvm::Intrinsic::coro_alloc: - case llvm::Intrinsic::coro_begin: - case llvm::Intrinsic::coro_free: { - if (CurCoro.Data && CurCoro.Data->CoroId) { - Args.push_back(CurCoro.Data->CoroId); - break; - } - CGM.Error(E->getBeginLoc(), "this builtin expect that __builtin_coro_id has" - " been used earlier in this function"); - // Fallthrough to the next case to add TokenNone as the first argument. - LLVM_FALLTHROUGH; - } - // @llvm.coro.suspend takes a token parameter. Add token 'none' as the first - // argument. - case llvm::Intrinsic::coro_suspend: - Args.push_back(llvm::ConstantTokenNone::get(getLLVMContext())); - break; - } - for (auto &Arg : E->arguments()) - Args.push_back(EmitScalarExpr(Arg)); - - llvm::Value *F = CGM.getIntrinsic(IID); - llvm::CallInst *Call = Builder.CreateCall(F, Args); - - // Note: The following code is to enable to emit coro.id and coro.begin by - // hand to experiment with coroutines in C. - // If we see @llvm.coro.id remember it in the CoroData. We will update - // coro.alloc, coro.begin and coro.free intrinsics to refer to it. - if (IID == llvm::Intrinsic::coro_id) { - createCoroData(*this, CurCoro, Call, E); - } - else if (IID == llvm::Intrinsic::coro_begin) { - if (CurCoro.Data) - CurCoro.Data->CoroBegin = Call; - } - else if (IID == llvm::Intrinsic::coro_free) { - // Remember the last coro_free as we need it to build the conditional - // deletion of the coroutine frame. - if (CurCoro.Data) - CurCoro.Data->LastCoroFree = Call; - } - return RValue::get(Call); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp deleted file mode 100644 index ad1a9157a12..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp +++ /dev/null @@ -1,4497 +0,0 @@ -//===--- CGDebugInfo.cpp - Emit Debug Information for a Module ------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This coordinates the debug information generation while generating code. -// -//===----------------------------------------------------------------------===// - -#include "CGDebugInfo.h" -#include "CGBlocks.h" -#include "CGCXXABI.h" -#include "CGObjCRuntime.h" -#include "CGRecordLayout.h" -#include "CodeGenFunction.h" -#include "CodeGenModule.h" -#include "ConstantEmitter.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclFriend.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/Expr.h" -#include "clang/AST/RecordLayout.h" -#include "clang/Basic/CodeGenOptions.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/Version.h" -#include "clang/Frontend/FrontendOptions.h" -#include "clang/Lex/HeaderSearchOptions.h" -#include "clang/Lex/ModuleMap.h" -#include "clang/Lex/PreprocessorOptions.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Metadata.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/MD5.h" -#include "llvm/Support/Path.h" -using namespace clang; -using namespace clang::CodeGen; - -static uint32_t getTypeAlignIfRequired(const Type *Ty, const ASTContext &Ctx) { - auto TI = Ctx.getTypeInfo(Ty); - return TI.AlignIsRequired ? TI.Align : 0; -} - -static uint32_t getTypeAlignIfRequired(QualType Ty, const ASTContext &Ctx) { - return getTypeAlignIfRequired(Ty.getTypePtr(), Ctx); -} - -static uint32_t getDeclAlignIfRequired(const Decl *D, const ASTContext &Ctx) { - return D->hasAttr<AlignedAttr>() ? D->getMaxAlignment() : 0; -} - -CGDebugInfo::CGDebugInfo(CodeGenModule &CGM) - : CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()), - DebugTypeExtRefs(CGM.getCodeGenOpts().DebugTypeExtRefs), - DBuilder(CGM.getModule()) { - for (const auto &KV : CGM.getCodeGenOpts().DebugPrefixMap) - DebugPrefixMap[KV.first] = KV.second; - CreateCompileUnit(); -} - -CGDebugInfo::~CGDebugInfo() { - assert(LexicalBlockStack.empty() && - "Region stack mismatch, stack not empty!"); -} - -ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF, - SourceLocation TemporaryLocation) - : CGF(&CGF) { - init(TemporaryLocation); -} - -ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF, - bool DefaultToEmpty, - SourceLocation TemporaryLocation) - : CGF(&CGF) { - init(TemporaryLocation, DefaultToEmpty); -} - -void ApplyDebugLocation::init(SourceLocation TemporaryLocation, - bool DefaultToEmpty) { - auto *DI = CGF->getDebugInfo(); - if (!DI) { - CGF = nullptr; - return; - } - - OriginalLocation = CGF->Builder.getCurrentDebugLocation(); - - if (OriginalLocation && !DI->CGM.getExpressionLocationsEnabled()) - return; - - if (TemporaryLocation.isValid()) { - DI->EmitLocation(CGF->Builder, TemporaryLocation); - return; - } - - if (DefaultToEmpty) { - CGF->Builder.SetCurrentDebugLocation(llvm::DebugLoc()); - return; - } - - // Construct a location that has a valid scope, but no line info. - assert(!DI->LexicalBlockStack.empty()); - CGF->Builder.SetCurrentDebugLocation(llvm::DebugLoc::get( - 0, 0, DI->LexicalBlockStack.back(), DI->getInlinedAt())); -} - -ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF, const Expr *E) - : CGF(&CGF) { - init(E->getExprLoc()); -} - -ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF, llvm::DebugLoc Loc) - : CGF(&CGF) { - if (!CGF.getDebugInfo()) { - this->CGF = nullptr; - return; - } - OriginalLocation = CGF.Builder.getCurrentDebugLocation(); - if (Loc) - CGF.Builder.SetCurrentDebugLocation(std::move(Loc)); -} - -ApplyDebugLocation::~ApplyDebugLocation() { - // Query CGF so the location isn't overwritten when location updates are - // temporarily disabled (for C++ default function arguments) - if (CGF) - CGF->Builder.SetCurrentDebugLocation(std::move(OriginalLocation)); -} - -ApplyInlineDebugLocation::ApplyInlineDebugLocation(CodeGenFunction &CGF, - GlobalDecl InlinedFn) - : CGF(&CGF) { - if (!CGF.getDebugInfo()) { - this->CGF = nullptr; - return; - } - auto &DI = *CGF.getDebugInfo(); - SavedLocation = DI.getLocation(); - assert((DI.getInlinedAt() == - CGF.Builder.getCurrentDebugLocation()->getInlinedAt()) && - "CGDebugInfo and IRBuilder are out of sync"); - - DI.EmitInlineFunctionStart(CGF.Builder, InlinedFn); -} - -ApplyInlineDebugLocation::~ApplyInlineDebugLocation() { - if (!CGF) - return; - auto &DI = *CGF->getDebugInfo(); - DI.EmitInlineFunctionEnd(CGF->Builder); - DI.EmitLocation(CGF->Builder, SavedLocation); -} - -void CGDebugInfo::setLocation(SourceLocation Loc) { - // If the new location isn't valid return. - if (Loc.isInvalid()) - return; - - CurLoc = CGM.getContext().getSourceManager().getExpansionLoc(Loc); - - // If we've changed files in the middle of a lexical scope go ahead - // and create a new lexical scope with file node if it's different - // from the one in the scope. - if (LexicalBlockStack.empty()) - return; - - SourceManager &SM = CGM.getContext().getSourceManager(); - auto *Scope = cast<llvm::DIScope>(LexicalBlockStack.back()); - PresumedLoc PCLoc = SM.getPresumedLoc(CurLoc); - if (PCLoc.isInvalid() || Scope->getFile() == getOrCreateFile(CurLoc)) - return; - - if (auto *LBF = dyn_cast<llvm::DILexicalBlockFile>(Scope)) { - LexicalBlockStack.pop_back(); - LexicalBlockStack.emplace_back(DBuilder.createLexicalBlockFile( - LBF->getScope(), getOrCreateFile(CurLoc))); - } else if (isa<llvm::DILexicalBlock>(Scope) || - isa<llvm::DISubprogram>(Scope)) { - LexicalBlockStack.pop_back(); - LexicalBlockStack.emplace_back( - DBuilder.createLexicalBlockFile(Scope, getOrCreateFile(CurLoc))); - } -} - -llvm::DIScope *CGDebugInfo::getDeclContextDescriptor(const Decl *D) { - llvm::DIScope *Mod = getParentModuleOrNull(D); - return getContextDescriptor(cast<Decl>(D->getDeclContext()), - Mod ? Mod : TheCU); -} - -llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context, - llvm::DIScope *Default) { - if (!Context) - return Default; - - auto I = RegionMap.find(Context); - if (I != RegionMap.end()) { - llvm::Metadata *V = I->second; - return dyn_cast_or_null<llvm::DIScope>(V); - } - - // Check namespace. - if (const auto *NSDecl = dyn_cast<NamespaceDecl>(Context)) - return getOrCreateNamespace(NSDecl); - - if (const auto *RDecl = dyn_cast<RecordDecl>(Context)) - if (!RDecl->isDependentType()) - return getOrCreateType(CGM.getContext().getTypeDeclType(RDecl), - TheCU->getFile()); - return Default; -} - -PrintingPolicy CGDebugInfo::getPrintingPolicy() const { - PrintingPolicy PP = CGM.getContext().getPrintingPolicy(); - - // If we're emitting codeview, it's important to try to match MSVC's naming so - // that visualizers written for MSVC will trigger for our class names. In - // particular, we can't have spaces between arguments of standard templates - // like basic_string and vector. - if (CGM.getCodeGenOpts().EmitCodeView) - PP.MSVCFormatting = true; - - // Apply -fdebug-prefix-map. - PP.RemapFilePaths = true; - PP.remapPath = [this](StringRef Path) { return remapDIPath(Path); }; - return PP; -} - -StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) { - assert(FD && "Invalid FunctionDecl!"); - IdentifierInfo *FII = FD->getIdentifier(); - FunctionTemplateSpecializationInfo *Info = - FD->getTemplateSpecializationInfo(); - - // Emit the unqualified name in normal operation. LLVM and the debugger can - // compute the fully qualified name from the scope chain. If we're only - // emitting line table info, there won't be any scope chains, so emit the - // fully qualified name here so that stack traces are more accurate. - // FIXME: Do this when emitting DWARF as well as when emitting CodeView after - // evaluating the size impact. - bool UseQualifiedName = DebugKind == codegenoptions::DebugLineTablesOnly && - CGM.getCodeGenOpts().EmitCodeView; - - if (!Info && FII && !UseQualifiedName) - return FII->getName(); - - SmallString<128> NS; - llvm::raw_svector_ostream OS(NS); - if (!UseQualifiedName) - FD->printName(OS); - else - FD->printQualifiedName(OS, getPrintingPolicy()); - - // Add any template specialization args. - if (Info) { - const TemplateArgumentList *TArgs = Info->TemplateArguments; - printTemplateArgumentList(OS, TArgs->asArray(), getPrintingPolicy()); - } - - // Copy this name on the side and use its reference. - return internString(OS.str()); -} - -StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) { - SmallString<256> MethodName; - llvm::raw_svector_ostream OS(MethodName); - OS << (OMD->isInstanceMethod() ? '-' : '+') << '['; - const DeclContext *DC = OMD->getDeclContext(); - if (const auto *OID = dyn_cast<ObjCImplementationDecl>(DC)) { - OS << OID->getName(); - } else if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) { - OS << OID->getName(); - } else if (const auto *OC = dyn_cast<ObjCCategoryDecl>(DC)) { - if (OC->IsClassExtension()) { - OS << OC->getClassInterface()->getName(); - } else { - OS << OC->getIdentifier()->getNameStart() << '(' - << OC->getIdentifier()->getNameStart() << ')'; - } - } else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) { - OS << OCD->getClassInterface()->getName() << '(' << OCD->getName() << ')'; - } else if (isa<ObjCProtocolDecl>(DC)) { - // We can extract the type of the class from the self pointer. - if (ImplicitParamDecl *SelfDecl = OMD->getSelfDecl()) { - QualType ClassTy = - cast<ObjCObjectPointerType>(SelfDecl->getType())->getPointeeType(); - ClassTy.print(OS, PrintingPolicy(LangOptions())); - } - } - OS << ' ' << OMD->getSelector().getAsString() << ']'; - - return internString(OS.str()); -} - -StringRef CGDebugInfo::getSelectorName(Selector S) { - return internString(S.getAsString()); -} - -StringRef CGDebugInfo::getClassName(const RecordDecl *RD) { - if (isa<ClassTemplateSpecializationDecl>(RD)) { - SmallString<128> Name; - llvm::raw_svector_ostream OS(Name); - RD->getNameForDiagnostic(OS, getPrintingPolicy(), - /*Qualified*/ false); - - // Copy this name on the side and use its reference. - return internString(Name); - } - - // quick optimization to avoid having to intern strings that are already - // stored reliably elsewhere - if (const IdentifierInfo *II = RD->getIdentifier()) - return II->getName(); - - // The CodeView printer in LLVM wants to see the names of unnamed types: it is - // used to reconstruct the fully qualified type names. - if (CGM.getCodeGenOpts().EmitCodeView) { - if (const TypedefNameDecl *D = RD->getTypedefNameForAnonDecl()) { - assert(RD->getDeclContext() == D->getDeclContext() && - "Typedef should not be in another decl context!"); - assert(D->getDeclName().getAsIdentifierInfo() && - "Typedef was not named!"); - return D->getDeclName().getAsIdentifierInfo()->getName(); - } - - if (CGM.getLangOpts().CPlusPlus) { - StringRef Name; - - ASTContext &Context = CGM.getContext(); - if (const DeclaratorDecl *DD = Context.getDeclaratorForUnnamedTagDecl(RD)) - // Anonymous types without a name for linkage purposes have their - // declarator mangled in if they have one. - Name = DD->getName(); - else if (const TypedefNameDecl *TND = - Context.getTypedefNameForUnnamedTagDecl(RD)) - // Anonymous types without a name for linkage purposes have their - // associate typedef mangled in if they have one. - Name = TND->getName(); - - if (!Name.empty()) { - SmallString<256> UnnamedType("<unnamed-type-"); - UnnamedType += Name; - UnnamedType += '>'; - return internString(UnnamedType); - } - } - } - - return StringRef(); -} - -Optional<llvm::DIFile::ChecksumKind> -CGDebugInfo::computeChecksum(FileID FID, SmallString<32> &Checksum) const { - Checksum.clear(); - - if (!CGM.getCodeGenOpts().EmitCodeView && - CGM.getCodeGenOpts().DwarfVersion < 5) - return None; - - SourceManager &SM = CGM.getContext().getSourceManager(); - bool Invalid; - llvm::MemoryBuffer *MemBuffer = SM.getBuffer(FID, &Invalid); - if (Invalid) - return None; - - llvm::MD5 Hash; - llvm::MD5::MD5Result Result; - - Hash.update(MemBuffer->getBuffer()); - Hash.final(Result); - - Hash.stringifyResult(Result, Checksum); - return llvm::DIFile::CSK_MD5; -} - -Optional<StringRef> CGDebugInfo::getSource(const SourceManager &SM, - FileID FID) { - if (!CGM.getCodeGenOpts().EmbedSource) - return None; - - bool SourceInvalid = false; - StringRef Source = SM.getBufferData(FID, &SourceInvalid); - - if (SourceInvalid) - return None; - - return Source; -} - -llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) { - if (!Loc.isValid()) - // If Location is not valid then use main input file. - return TheCU->getFile(); - - SourceManager &SM = CGM.getContext().getSourceManager(); - PresumedLoc PLoc = SM.getPresumedLoc(Loc); - - StringRef FileName = PLoc.getFilename(); - if (PLoc.isInvalid() || FileName.empty()) - // If the location is not valid then use main input file. - return TheCU->getFile(); - - // Cache the results. - auto It = DIFileCache.find(FileName.data()); - if (It != DIFileCache.end()) { - // Verify that the information still exists. - if (llvm::Metadata *V = It->second) - return cast<llvm::DIFile>(V); - } - - SmallString<32> Checksum; - Optional<llvm::DIFile::ChecksumKind> CSKind = - computeChecksum(SM.getFileID(Loc), Checksum); - Optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo; - if (CSKind) - CSInfo.emplace(*CSKind, Checksum); - return createFile(FileName, CSInfo, getSource(SM, SM.getFileID(Loc))); -} - -llvm::DIFile * -CGDebugInfo::createFile(StringRef FileName, - Optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo, - Optional<StringRef> Source) { - StringRef Dir; - StringRef File; - std::string RemappedFile = remapDIPath(FileName); - std::string CurDir = remapDIPath(getCurrentDirname()); - SmallString<128> DirBuf; - SmallString<128> FileBuf; - if (llvm::sys::path::is_absolute(RemappedFile)) { - // Strip the common prefix (if it is more than just "/") from current - // directory and FileName for a more space-efficient encoding. - auto FileIt = llvm::sys::path::begin(RemappedFile); - auto FileE = llvm::sys::path::end(RemappedFile); - auto CurDirIt = llvm::sys::path::begin(CurDir); - auto CurDirE = llvm::sys::path::end(CurDir); - for (; CurDirIt != CurDirE && *CurDirIt == *FileIt; ++CurDirIt, ++FileIt) - llvm::sys::path::append(DirBuf, *CurDirIt); - if (std::distance(llvm::sys::path::begin(CurDir), CurDirIt) == 1) { - // The common prefix only the root; stripping it would cause - // LLVM diagnostic locations to be more confusing. - Dir = {}; - File = RemappedFile; - } else { - for (; FileIt != FileE; ++FileIt) - llvm::sys::path::append(FileBuf, *FileIt); - Dir = DirBuf; - File = FileBuf; - } - } else { - Dir = CurDir; - File = RemappedFile; - } - llvm::DIFile *F = DBuilder.createFile(File, Dir, CSInfo, Source); - DIFileCache[FileName.data()].reset(F); - return F; -} - -std::string CGDebugInfo::remapDIPath(StringRef Path) const { - for (const auto &Entry : DebugPrefixMap) - if (Path.startswith(Entry.first)) - return (Twine(Entry.second) + Path.substr(Entry.first.size())).str(); - return Path.str(); -} - -unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) { - if (Loc.isInvalid() && CurLoc.isInvalid()) - return 0; - SourceManager &SM = CGM.getContext().getSourceManager(); - PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc); - return PLoc.isValid() ? PLoc.getLine() : 0; -} - -unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc, bool Force) { - // We may not want column information at all. - if (!Force && !CGM.getCodeGenOpts().DebugColumnInfo) - return 0; - - // If the location is invalid then use the current column. - if (Loc.isInvalid() && CurLoc.isInvalid()) - return 0; - SourceManager &SM = CGM.getContext().getSourceManager(); - PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc); - return PLoc.isValid() ? PLoc.getColumn() : 0; -} - -StringRef CGDebugInfo::getCurrentDirname() { - if (!CGM.getCodeGenOpts().DebugCompilationDir.empty()) - return CGM.getCodeGenOpts().DebugCompilationDir; - - if (!CWDName.empty()) - return CWDName; - SmallString<256> CWD; - llvm::sys::fs::current_path(CWD); - return CWDName = internString(CWD); -} - -void CGDebugInfo::CreateCompileUnit() { - SmallString<32> Checksum; - Optional<llvm::DIFile::ChecksumKind> CSKind; - Optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo; - - // Should we be asking the SourceManager for the main file name, instead of - // accepting it as an argument? This just causes the main file name to - // mismatch with source locations and create extra lexical scopes or - // mismatched debug info (a CU with a DW_AT_file of "-", because that's what - // the driver passed, but functions/other things have DW_AT_file of "<stdin>" - // because that's what the SourceManager says) - - // Get absolute path name. - SourceManager &SM = CGM.getContext().getSourceManager(); - std::string MainFileName = CGM.getCodeGenOpts().MainFileName; - if (MainFileName.empty()) - MainFileName = "<stdin>"; - - // The main file name provided via the "-main-file-name" option contains just - // the file name itself with no path information. This file name may have had - // a relative path, so we look into the actual file entry for the main - // file to determine the real absolute path for the file. - std::string MainFileDir; - if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) { - MainFileDir = remapDIPath(MainFile->getDir()->getName()); - if (MainFileDir != ".") { - llvm::SmallString<1024> MainFileDirSS(MainFileDir); - llvm::sys::path::append(MainFileDirSS, MainFileName); - MainFileName = MainFileDirSS.str(); - } - // If the main file name provided is identical to the input file name, and - // if the input file is a preprocessed source, use the module name for - // debug info. The module name comes from the name specified in the first - // linemarker if the input is a preprocessed source. - if (MainFile->getName() == MainFileName && - FrontendOptions::getInputKindForExtension( - MainFile->getName().rsplit('.').second) - .isPreprocessed()) - MainFileName = CGM.getModule().getName().str(); - - CSKind = computeChecksum(SM.getMainFileID(), Checksum); - } - - llvm::dwarf::SourceLanguage LangTag; - const LangOptions &LO = CGM.getLangOpts(); - if (LO.CPlusPlus) { - if (LO.ObjC) - LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus; - else - LangTag = llvm::dwarf::DW_LANG_C_plus_plus; - } else if (LO.ObjC) { - LangTag = llvm::dwarf::DW_LANG_ObjC; - } else if (LO.RenderScript) { - LangTag = llvm::dwarf::DW_LANG_GOOGLE_RenderScript; - } else if (LO.C99) { - LangTag = llvm::dwarf::DW_LANG_C99; - } else { - LangTag = llvm::dwarf::DW_LANG_C89; - } - - std::string Producer = getClangFullVersion(); - - // Figure out which version of the ObjC runtime we have. - unsigned RuntimeVers = 0; - if (LO.ObjC) - RuntimeVers = LO.ObjCRuntime.isNonFragile() ? 2 : 1; - - llvm::DICompileUnit::DebugEmissionKind EmissionKind; - switch (DebugKind) { - case codegenoptions::NoDebugInfo: - case codegenoptions::LocTrackingOnly: - EmissionKind = llvm::DICompileUnit::NoDebug; - break; - case codegenoptions::DebugLineTablesOnly: - EmissionKind = llvm::DICompileUnit::LineTablesOnly; - break; - case codegenoptions::DebugDirectivesOnly: - EmissionKind = llvm::DICompileUnit::DebugDirectivesOnly; - break; - case codegenoptions::LimitedDebugInfo: - case codegenoptions::FullDebugInfo: - EmissionKind = llvm::DICompileUnit::FullDebug; - break; - } - - uint64_t DwoId = 0; - auto &CGOpts = CGM.getCodeGenOpts(); - // The DIFile used by the CU is distinct from the main source - // file. Its directory part specifies what becomes the - // DW_AT_comp_dir (the compilation directory), even if the source - // file was specified with an absolute path. - if (CSKind) - CSInfo.emplace(*CSKind, Checksum); - llvm::DIFile *CUFile = DBuilder.createFile( - remapDIPath(MainFileName), remapDIPath(getCurrentDirname()), CSInfo, - getSource(SM, SM.getMainFileID())); - - // Create new compile unit. - TheCU = DBuilder.createCompileUnit( - LangTag, CUFile, CGOpts.EmitVersionIdentMetadata ? Producer : "", - LO.Optimize || CGOpts.PrepareForLTO || CGOpts.PrepareForThinLTO, - CGOpts.DwarfDebugFlags, RuntimeVers, - (CGOpts.getSplitDwarfMode() != CodeGenOptions::NoFission) - ? "" - : CGOpts.SplitDwarfFile, - EmissionKind, DwoId, CGOpts.SplitDwarfInlining, - CGOpts.DebugInfoForProfiling, - CGM.getTarget().getTriple().isNVPTX() - ? llvm::DICompileUnit::DebugNameTableKind::None - : static_cast<llvm::DICompileUnit::DebugNameTableKind>( - CGOpts.DebugNameTable), - CGOpts.DebugRangesBaseAddress); -} - -llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) { - llvm::dwarf::TypeKind Encoding; - StringRef BTName; - switch (BT->getKind()) { -#define BUILTIN_TYPE(Id, SingletonId) -#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id: -#include "clang/AST/BuiltinTypes.def" - case BuiltinType::Dependent: - llvm_unreachable("Unexpected builtin type"); - case BuiltinType::NullPtr: - return DBuilder.createNullPtrType(); - case BuiltinType::Void: - return nullptr; - case BuiltinType::ObjCClass: - if (!ClassTy) - ClassTy = - DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, - "objc_class", TheCU, TheCU->getFile(), 0); - return ClassTy; - case BuiltinType::ObjCId: { - // typedef struct objc_class *Class; - // typedef struct objc_object { - // Class isa; - // } *id; - - if (ObjTy) - return ObjTy; - - if (!ClassTy) - ClassTy = - DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, - "objc_class", TheCU, TheCU->getFile(), 0); - - unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); - - auto *ISATy = DBuilder.createPointerType(ClassTy, Size); - - ObjTy = DBuilder.createStructType(TheCU, "objc_object", TheCU->getFile(), 0, - 0, 0, llvm::DINode::FlagZero, nullptr, - llvm::DINodeArray()); - - DBuilder.replaceArrays( - ObjTy, DBuilder.getOrCreateArray(&*DBuilder.createMemberType( - ObjTy, "isa", TheCU->getFile(), 0, Size, 0, 0, - llvm::DINode::FlagZero, ISATy))); - return ObjTy; - } - case BuiltinType::ObjCSel: { - if (!SelTy) - SelTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, - "objc_selector", TheCU, - TheCU->getFile(), 0); - return SelTy; - } - -#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ - case BuiltinType::Id: \ - return getOrCreateStructPtrType("opencl_" #ImgType "_" #Suffix "_t", \ - SingletonId); -#include "clang/Basic/OpenCLImageTypes.def" - case BuiltinType::OCLSampler: - return getOrCreateStructPtrType("opencl_sampler_t", OCLSamplerDITy); - case BuiltinType::OCLEvent: - return getOrCreateStructPtrType("opencl_event_t", OCLEventDITy); - case BuiltinType::OCLClkEvent: - return getOrCreateStructPtrType("opencl_clk_event_t", OCLClkEventDITy); - case BuiltinType::OCLQueue: - return getOrCreateStructPtrType("opencl_queue_t", OCLQueueDITy); - case BuiltinType::OCLReserveID: - return getOrCreateStructPtrType("opencl_reserve_id_t", OCLReserveIDDITy); -#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ - case BuiltinType::Id: \ - return getOrCreateStructPtrType("opencl_" #ExtType, Id##Ty); -#include "clang/Basic/OpenCLExtensionTypes.def" - - case BuiltinType::UChar: - case BuiltinType::Char_U: - Encoding = llvm::dwarf::DW_ATE_unsigned_char; - break; - case BuiltinType::Char_S: - case BuiltinType::SChar: - Encoding = llvm::dwarf::DW_ATE_signed_char; - break; - case BuiltinType::Char8: - case BuiltinType::Char16: - case BuiltinType::Char32: - Encoding = llvm::dwarf::DW_ATE_UTF; - break; - case BuiltinType::UShort: - case BuiltinType::UInt: - case BuiltinType::UInt128: - case BuiltinType::ULong: - case BuiltinType::WChar_U: - case BuiltinType::ULongLong: - Encoding = llvm::dwarf::DW_ATE_unsigned; - break; - case BuiltinType::Short: - case BuiltinType::Int: - case BuiltinType::Int128: - case BuiltinType::Long: - case BuiltinType::WChar_S: - case BuiltinType::LongLong: - Encoding = llvm::dwarf::DW_ATE_signed; - break; - case BuiltinType::Bool: - Encoding = llvm::dwarf::DW_ATE_boolean; - break; - case BuiltinType::Half: - case BuiltinType::Float: - case BuiltinType::LongDouble: - case BuiltinType::Float16: - case BuiltinType::Float128: - case BuiltinType::Double: - // FIXME: For targets where long double and __float128 have the same size, - // they are currently indistinguishable in the debugger without some - // special treatment. However, there is currently no consensus on encoding - // and this should be updated once a DWARF encoding exists for distinct - // floating point types of the same size. - Encoding = llvm::dwarf::DW_ATE_float; - break; - case BuiltinType::ShortAccum: - case BuiltinType::Accum: - case BuiltinType::LongAccum: - case BuiltinType::ShortFract: - case BuiltinType::Fract: - case BuiltinType::LongFract: - case BuiltinType::SatShortFract: - case BuiltinType::SatFract: - case BuiltinType::SatLongFract: - case BuiltinType::SatShortAccum: - case BuiltinType::SatAccum: - case BuiltinType::SatLongAccum: - Encoding = llvm::dwarf::DW_ATE_signed_fixed; - break; - case BuiltinType::UShortAccum: - case BuiltinType::UAccum: - case BuiltinType::ULongAccum: - case BuiltinType::UShortFract: - case BuiltinType::UFract: - case BuiltinType::ULongFract: - case BuiltinType::SatUShortAccum: - case BuiltinType::SatUAccum: - case BuiltinType::SatULongAccum: - case BuiltinType::SatUShortFract: - case BuiltinType::SatUFract: - case BuiltinType::SatULongFract: - Encoding = llvm::dwarf::DW_ATE_unsigned_fixed; - break; - } - - switch (BT->getKind()) { - case BuiltinType::Long: - BTName = "long int"; - break; - case BuiltinType::LongLong: - BTName = "long long int"; - break; - case BuiltinType::ULong: - BTName = "long unsigned int"; - break; - case BuiltinType::ULongLong: - BTName = "long long unsigned int"; - break; - default: - BTName = BT->getName(CGM.getLangOpts()); - break; - } - // Bit size and offset of the type. - uint64_t Size = CGM.getContext().getTypeSize(BT); - return DBuilder.createBasicType(BTName, Size, Encoding); -} - -llvm::DIType *CGDebugInfo::CreateType(const ComplexType *Ty) { - // Bit size and offset of the type. - llvm::dwarf::TypeKind Encoding = llvm::dwarf::DW_ATE_complex_float; - if (Ty->isComplexIntegerType()) - Encoding = llvm::dwarf::DW_ATE_lo_user; - - uint64_t Size = CGM.getContext().getTypeSize(Ty); - return DBuilder.createBasicType("complex", Size, Encoding); -} - -llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty, - llvm::DIFile *Unit) { - QualifierCollector Qc; - const Type *T = Qc.strip(Ty); - - // Ignore these qualifiers for now. - Qc.removeObjCGCAttr(); - Qc.removeAddressSpace(); - Qc.removeObjCLifetime(); - - // We will create one Derived type for one qualifier and recurse to handle any - // additional ones. - llvm::dwarf::Tag Tag; - if (Qc.hasConst()) { - Tag = llvm::dwarf::DW_TAG_const_type; - Qc.removeConst(); - } else if (Qc.hasVolatile()) { - Tag = llvm::dwarf::DW_TAG_volatile_type; - Qc.removeVolatile(); - } else if (Qc.hasRestrict()) { - Tag = llvm::dwarf::DW_TAG_restrict_type; - Qc.removeRestrict(); - } else { - assert(Qc.empty() && "Unknown type qualifier for debug info"); - return getOrCreateType(QualType(T, 0), Unit); - } - - auto *FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit); - - // No need to fill in the Name, Line, Size, Alignment, Offset in case of - // CVR derived types. - return DBuilder.createQualifiedType(Tag, FromTy); -} - -llvm::DIType *CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty, - llvm::DIFile *Unit) { - - // The frontend treats 'id' as a typedef to an ObjCObjectType, - // whereas 'id<protocol>' is treated as an ObjCPointerType. For the - // debug info, we want to emit 'id' in both cases. - if (Ty->isObjCQualifiedIdType()) - return getOrCreateType(CGM.getContext().getObjCIdType(), Unit); - - return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty, - Ty->getPointeeType(), Unit); -} - -llvm::DIType *CGDebugInfo::CreateType(const PointerType *Ty, - llvm::DIFile *Unit) { - return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty, - Ty->getPointeeType(), Unit); -} - -/// \return whether a C++ mangling exists for the type defined by TD. -static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) { - switch (TheCU->getSourceLanguage()) { - case llvm::dwarf::DW_LANG_C_plus_plus: - return true; - case llvm::dwarf::DW_LANG_ObjC_plus_plus: - return isa<CXXRecordDecl>(TD) || isa<EnumDecl>(TD); - default: - return false; - } -} - -// Determines if the debug info for this tag declaration needs a type -// identifier. The purpose of the unique identifier is to deduplicate type -// information for identical types across TUs. Because of the C++ one definition -// rule (ODR), it is valid to assume that the type is defined the same way in -// every TU and its debug info is equivalent. -// -// C does not have the ODR, and it is common for codebases to contain multiple -// different definitions of a struct with the same name in different TUs. -// Therefore, if the type doesn't have a C++ mangling, don't give it an -// identifer. Type information in C is smaller and simpler than C++ type -// information, so the increase in debug info size is negligible. -// -// If the type is not externally visible, it should be unique to the current TU, -// and should not need an identifier to participate in type deduplication. -// However, when emitting CodeView, the format internally uses these -// unique type name identifers for references between debug info. For example, -// the method of a class in an anonymous namespace uses the identifer to refer -// to its parent class. The Microsoft C++ ABI attempts to provide unique names -// for such types, so when emitting CodeView, always use identifiers for C++ -// types. This may create problems when attempting to emit CodeView when the MS -// C++ ABI is not in use. -static bool needsTypeIdentifier(const TagDecl *TD, CodeGenModule &CGM, - llvm::DICompileUnit *TheCU) { - // We only add a type identifier for types with C++ name mangling. - if (!hasCXXMangling(TD, TheCU)) - return false; - - // Externally visible types with C++ mangling need a type identifier. - if (TD->isExternallyVisible()) - return true; - - // CodeView types with C++ mangling need a type identifier. - if (CGM.getCodeGenOpts().EmitCodeView) - return true; - - return false; -} - -// Returns a unique type identifier string if one exists, or an empty string. -static SmallString<256> getTypeIdentifier(const TagType *Ty, CodeGenModule &CGM, - llvm::DICompileUnit *TheCU) { - SmallString<256> Identifier; - const TagDecl *TD = Ty->getDecl(); - - if (!needsTypeIdentifier(TD, CGM, TheCU)) - return Identifier; - - // TODO: This is using the RTTI name. Is there a better way to get - // a unique string for a type? - llvm::raw_svector_ostream Out(Identifier); - CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(QualType(Ty, 0), Out); - return Identifier; -} - -/// \return the appropriate DWARF tag for a composite type. -static llvm::dwarf::Tag getTagForRecord(const RecordDecl *RD) { - llvm::dwarf::Tag Tag; - if (RD->isStruct() || RD->isInterface()) - Tag = llvm::dwarf::DW_TAG_structure_type; - else if (RD->isUnion()) - Tag = llvm::dwarf::DW_TAG_union_type; - else { - // FIXME: This could be a struct type giving a default visibility different - // than C++ class type, but needs llvm metadata changes first. - assert(RD->isClass()); - Tag = llvm::dwarf::DW_TAG_class_type; - } - return Tag; -} - -llvm::DICompositeType * -CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty, - llvm::DIScope *Ctx) { - const RecordDecl *RD = Ty->getDecl(); - if (llvm::DIType *T = getTypeOrNull(CGM.getContext().getRecordType(RD))) - return cast<llvm::DICompositeType>(T); - llvm::DIFile *DefUnit = getOrCreateFile(RD->getLocation()); - unsigned Line = getLineNumber(RD->getLocation()); - StringRef RDName = getClassName(RD); - - uint64_t Size = 0; - uint32_t Align = 0; - - // Create the type. - SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU); - llvm::DICompositeType *RetTy = DBuilder.createReplaceableCompositeType( - getTagForRecord(RD), RDName, Ctx, DefUnit, Line, 0, Size, Align, - llvm::DINode::FlagFwdDecl, Identifier); - if (CGM.getCodeGenOpts().DebugFwdTemplateParams) - if (auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD)) - DBuilder.replaceArrays(RetTy, llvm::DINodeArray(), - CollectCXXTemplateParams(TSpecial, DefUnit)); - ReplaceMap.emplace_back( - std::piecewise_construct, std::make_tuple(Ty), - std::make_tuple(static_cast<llvm::Metadata *>(RetTy))); - return RetTy; -} - -llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag, - const Type *Ty, - QualType PointeeTy, - llvm::DIFile *Unit) { - // Bit size, align and offset of the type. - // Size is always the size of a pointer. We can't use getTypeSize here - // because that does not return the correct value for references. - unsigned AddressSpace = CGM.getContext().getTargetAddressSpace(PointeeTy); - uint64_t Size = CGM.getTarget().getPointerWidth(AddressSpace); - auto Align = getTypeAlignIfRequired(Ty, CGM.getContext()); - Optional<unsigned> DWARFAddressSpace = - CGM.getTarget().getDWARFAddressSpace(AddressSpace); - - if (Tag == llvm::dwarf::DW_TAG_reference_type || - Tag == llvm::dwarf::DW_TAG_rvalue_reference_type) - return DBuilder.createReferenceType(Tag, getOrCreateType(PointeeTy, Unit), - Size, Align, DWARFAddressSpace); - else - return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size, - Align, DWARFAddressSpace); -} - -llvm::DIType *CGDebugInfo::getOrCreateStructPtrType(StringRef Name, - llvm::DIType *&Cache) { - if (Cache) - return Cache; - Cache = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, Name, - TheCU, TheCU->getFile(), 0); - unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); - Cache = DBuilder.createPointerType(Cache, Size); - return Cache; -} - -uint64_t CGDebugInfo::collectDefaultElementTypesForBlockPointer( - const BlockPointerType *Ty, llvm::DIFile *Unit, llvm::DIDerivedType *DescTy, - unsigned LineNo, SmallVectorImpl<llvm::Metadata *> &EltTys) { - QualType FType; - - // Advanced by calls to CreateMemberType in increments of FType, then - // returned as the overall size of the default elements. - uint64_t FieldOffset = 0; - - // Blocks in OpenCL have unique constraints which make the standard fields - // redundant while requiring size and align fields for enqueue_kernel. See - // initializeForBlockHeader in CGBlocks.cpp - if (CGM.getLangOpts().OpenCL) { - FType = CGM.getContext().IntTy; - EltTys.push_back(CreateMemberType(Unit, FType, "__size", &FieldOffset)); - EltTys.push_back(CreateMemberType(Unit, FType, "__align", &FieldOffset)); - } else { - FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); - EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset)); - FType = CGM.getContext().IntTy; - EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset)); - EltTys.push_back(CreateMemberType(Unit, FType, "__reserved", &FieldOffset)); - FType = CGM.getContext().getPointerType(Ty->getPointeeType()); - EltTys.push_back(CreateMemberType(Unit, FType, "__FuncPtr", &FieldOffset)); - FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); - uint64_t FieldSize = CGM.getContext().getTypeSize(Ty); - uint32_t FieldAlign = CGM.getContext().getTypeAlign(Ty); - EltTys.push_back(DBuilder.createMemberType( - Unit, "__descriptor", nullptr, LineNo, FieldSize, FieldAlign, - FieldOffset, llvm::DINode::FlagZero, DescTy)); - FieldOffset += FieldSize; - } - - return FieldOffset; -} - -llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty, - llvm::DIFile *Unit) { - SmallVector<llvm::Metadata *, 8> EltTys; - QualType FType; - uint64_t FieldOffset; - llvm::DINodeArray Elements; - - FieldOffset = 0; - FType = CGM.getContext().UnsignedLongTy; - EltTys.push_back(CreateMemberType(Unit, FType, "reserved", &FieldOffset)); - EltTys.push_back(CreateMemberType(Unit, FType, "Size", &FieldOffset)); - - Elements = DBuilder.getOrCreateArray(EltTys); - EltTys.clear(); - - llvm::DINode::DIFlags Flags = llvm::DINode::FlagAppleBlock; - - auto *EltTy = - DBuilder.createStructType(Unit, "__block_descriptor", nullptr, 0, - FieldOffset, 0, Flags, nullptr, Elements); - - // Bit size, align and offset of the type. - uint64_t Size = CGM.getContext().getTypeSize(Ty); - - auto *DescTy = DBuilder.createPointerType(EltTy, Size); - - FieldOffset = collectDefaultElementTypesForBlockPointer(Ty, Unit, DescTy, - 0, EltTys); - - Elements = DBuilder.getOrCreateArray(EltTys); - - // The __block_literal_generic structs are marked with a special - // DW_AT_APPLE_BLOCK attribute and are an implementation detail only - // the debugger needs to know about. To allow type uniquing, emit - // them without a name or a location. - EltTy = DBuilder.createStructType(Unit, "", nullptr, 0, FieldOffset, 0, - Flags, nullptr, Elements); - - return DBuilder.createPointerType(EltTy, Size); -} - -llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty, - llvm::DIFile *Unit) { - assert(Ty->isTypeAlias()); - llvm::DIType *Src = getOrCreateType(Ty->getAliasedType(), Unit); - - SmallString<128> NS; - llvm::raw_svector_ostream OS(NS); - Ty->getTemplateName().print(OS, getPrintingPolicy(), /*qualified*/ false); - printTemplateArgumentList(OS, Ty->template_arguments(), getPrintingPolicy()); - - auto *AliasDecl = - cast<TypeAliasTemplateDecl>(Ty->getTemplateName().getAsTemplateDecl()) - ->getTemplatedDecl(); - - SourceLocation Loc = AliasDecl->getLocation(); - return DBuilder.createTypedef(Src, OS.str(), getOrCreateFile(Loc), - getLineNumber(Loc), - getDeclContextDescriptor(AliasDecl)); -} - -llvm::DIType *CGDebugInfo::CreateType(const TypedefType *Ty, - llvm::DIFile *Unit) { - // We don't set size information, but do specify where the typedef was - // declared. - SourceLocation Loc = Ty->getDecl()->getLocation(); - - // Typedefs are derived from some other type. - return DBuilder.createTypedef( - getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit), - Ty->getDecl()->getName(), getOrCreateFile(Loc), getLineNumber(Loc), - getDeclContextDescriptor(Ty->getDecl())); -} - -static unsigned getDwarfCC(CallingConv CC) { - switch (CC) { - case CC_C: - // Avoid emitting DW_AT_calling_convention if the C convention was used. - return 0; - - case CC_X86StdCall: - return llvm::dwarf::DW_CC_BORLAND_stdcall; - case CC_X86FastCall: - return llvm::dwarf::DW_CC_BORLAND_msfastcall; - case CC_X86ThisCall: - return llvm::dwarf::DW_CC_BORLAND_thiscall; - case CC_X86VectorCall: - return llvm::dwarf::DW_CC_LLVM_vectorcall; - case CC_X86Pascal: - return llvm::dwarf::DW_CC_BORLAND_pascal; - case CC_Win64: - return llvm::dwarf::DW_CC_LLVM_Win64; - case CC_X86_64SysV: - return llvm::dwarf::DW_CC_LLVM_X86_64SysV; - case CC_AAPCS: - case CC_AArch64VectorCall: - return llvm::dwarf::DW_CC_LLVM_AAPCS; - case CC_AAPCS_VFP: - return llvm::dwarf::DW_CC_LLVM_AAPCS_VFP; - case CC_IntelOclBicc: - return llvm::dwarf::DW_CC_LLVM_IntelOclBicc; - case CC_SpirFunction: - return llvm::dwarf::DW_CC_LLVM_SpirFunction; - case CC_OpenCLKernel: - return llvm::dwarf::DW_CC_LLVM_OpenCLKernel; - case CC_Swift: - return llvm::dwarf::DW_CC_LLVM_Swift; - case CC_PreserveMost: - return llvm::dwarf::DW_CC_LLVM_PreserveMost; - case CC_PreserveAll: - return llvm::dwarf::DW_CC_LLVM_PreserveAll; - case CC_X86RegCall: - return llvm::dwarf::DW_CC_LLVM_X86RegCall; - } - return 0; -} - -llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty, - llvm::DIFile *Unit) { - SmallVector<llvm::Metadata *, 16> EltTys; - - // Add the result type at least. - EltTys.push_back(getOrCreateType(Ty->getReturnType(), Unit)); - - // Set up remainder of arguments if there is a prototype. - // otherwise emit it as a variadic function. - if (isa<FunctionNoProtoType>(Ty)) - EltTys.push_back(DBuilder.createUnspecifiedParameter()); - else if (const auto *FPT = dyn_cast<FunctionProtoType>(Ty)) { - for (const QualType &ParamType : FPT->param_types()) - EltTys.push_back(getOrCreateType(ParamType, Unit)); - if (FPT->isVariadic()) - EltTys.push_back(DBuilder.createUnspecifiedParameter()); - } - - llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(EltTys); - return DBuilder.createSubroutineType(EltTypeArray, llvm::DINode::FlagZero, - getDwarfCC(Ty->getCallConv())); -} - -/// Convert an AccessSpecifier into the corresponding DINode flag. -/// As an optimization, return 0 if the access specifier equals the -/// default for the containing type. -static llvm::DINode::DIFlags getAccessFlag(AccessSpecifier Access, - const RecordDecl *RD) { - AccessSpecifier Default = clang::AS_none; - if (RD && RD->isClass()) - Default = clang::AS_private; - else if (RD && (RD->isStruct() || RD->isUnion())) - Default = clang::AS_public; - - if (Access == Default) - return llvm::DINode::FlagZero; - - switch (Access) { - case clang::AS_private: - return llvm::DINode::FlagPrivate; - case clang::AS_protected: - return llvm::DINode::FlagProtected; - case clang::AS_public: - return llvm::DINode::FlagPublic; - case clang::AS_none: - return llvm::DINode::FlagZero; - } - llvm_unreachable("unexpected access enumerator"); -} - -llvm::DIType *CGDebugInfo::createBitFieldType(const FieldDecl *BitFieldDecl, - llvm::DIScope *RecordTy, - const RecordDecl *RD) { - StringRef Name = BitFieldDecl->getName(); - QualType Ty = BitFieldDecl->getType(); - SourceLocation Loc = BitFieldDecl->getLocation(); - llvm::DIFile *VUnit = getOrCreateFile(Loc); - llvm::DIType *DebugType = getOrCreateType(Ty, VUnit); - - // Get the location for the field. - llvm::DIFile *File = getOrCreateFile(Loc); - unsigned Line = getLineNumber(Loc); - - const CGBitFieldInfo &BitFieldInfo = - CGM.getTypes().getCGRecordLayout(RD).getBitFieldInfo(BitFieldDecl); - uint64_t SizeInBits = BitFieldInfo.Size; - assert(SizeInBits > 0 && "found named 0-width bitfield"); - uint64_t StorageOffsetInBits = - CGM.getContext().toBits(BitFieldInfo.StorageOffset); - uint64_t Offset = BitFieldInfo.Offset; - // The bit offsets for big endian machines are reversed for big - // endian target, compensate for that as the DIDerivedType requires - // un-reversed offsets. - if (CGM.getDataLayout().isBigEndian()) - Offset = BitFieldInfo.StorageSize - BitFieldInfo.Size - Offset; - uint64_t OffsetInBits = StorageOffsetInBits + Offset; - llvm::DINode::DIFlags Flags = getAccessFlag(BitFieldDecl->getAccess(), RD); - return DBuilder.createBitFieldMemberType( - RecordTy, Name, File, Line, SizeInBits, OffsetInBits, StorageOffsetInBits, - Flags, DebugType); -} - -llvm::DIType * -CGDebugInfo::createFieldType(StringRef name, QualType type, SourceLocation loc, - AccessSpecifier AS, uint64_t offsetInBits, - uint32_t AlignInBits, llvm::DIFile *tunit, - llvm::DIScope *scope, const RecordDecl *RD) { - llvm::DIType *debugType = getOrCreateType(type, tunit); - - // Get the location for the field. - llvm::DIFile *file = getOrCreateFile(loc); - unsigned line = getLineNumber(loc); - - uint64_t SizeInBits = 0; - auto Align = AlignInBits; - if (!type->isIncompleteArrayType()) { - TypeInfo TI = CGM.getContext().getTypeInfo(type); - SizeInBits = TI.Width; - if (!Align) - Align = getTypeAlignIfRequired(type, CGM.getContext()); - } - - llvm::DINode::DIFlags flags = getAccessFlag(AS, RD); - return DBuilder.createMemberType(scope, name, file, line, SizeInBits, Align, - offsetInBits, flags, debugType); -} - -void CGDebugInfo::CollectRecordLambdaFields( - const CXXRecordDecl *CXXDecl, SmallVectorImpl<llvm::Metadata *> &elements, - llvm::DIType *RecordTy) { - // For C++11 Lambdas a Field will be the same as a Capture, but the Capture - // has the name and the location of the variable so we should iterate over - // both concurrently. - const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(CXXDecl); - RecordDecl::field_iterator Field = CXXDecl->field_begin(); - unsigned fieldno = 0; - for (CXXRecordDecl::capture_const_iterator I = CXXDecl->captures_begin(), - E = CXXDecl->captures_end(); - I != E; ++I, ++Field, ++fieldno) { - const LambdaCapture &C = *I; - if (C.capturesVariable()) { - SourceLocation Loc = C.getLocation(); - assert(!Field->isBitField() && "lambdas don't have bitfield members!"); - VarDecl *V = C.getCapturedVar(); - StringRef VName = V->getName(); - llvm::DIFile *VUnit = getOrCreateFile(Loc); - auto Align = getDeclAlignIfRequired(V, CGM.getContext()); - llvm::DIType *FieldType = createFieldType( - VName, Field->getType(), Loc, Field->getAccess(), - layout.getFieldOffset(fieldno), Align, VUnit, RecordTy, CXXDecl); - elements.push_back(FieldType); - } else if (C.capturesThis()) { - // TODO: Need to handle 'this' in some way by probably renaming the - // this of the lambda class and having a field member of 'this' or - // by using AT_object_pointer for the function and having that be - // used as 'this' for semantic references. - FieldDecl *f = *Field; - llvm::DIFile *VUnit = getOrCreateFile(f->getLocation()); - QualType type = f->getType(); - llvm::DIType *fieldType = createFieldType( - "this", type, f->getLocation(), f->getAccess(), - layout.getFieldOffset(fieldno), VUnit, RecordTy, CXXDecl); - - elements.push_back(fieldType); - } - } -} - -llvm::DIDerivedType * -CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy, - const RecordDecl *RD) { - // Create the descriptor for the static variable, with or without - // constant initializers. - Var = Var->getCanonicalDecl(); - llvm::DIFile *VUnit = getOrCreateFile(Var->getLocation()); - llvm::DIType *VTy = getOrCreateType(Var->getType(), VUnit); - - unsigned LineNumber = getLineNumber(Var->getLocation()); - StringRef VName = Var->getName(); - llvm::Constant *C = nullptr; - if (Var->getInit()) { - const APValue *Value = Var->evaluateValue(); - if (Value) { - if (Value->isInt()) - C = llvm::ConstantInt::get(CGM.getLLVMContext(), Value->getInt()); - if (Value->isFloat()) - C = llvm::ConstantFP::get(CGM.getLLVMContext(), Value->getFloat()); - } - } - - llvm::DINode::DIFlags Flags = getAccessFlag(Var->getAccess(), RD); - auto Align = getDeclAlignIfRequired(Var, CGM.getContext()); - llvm::DIDerivedType *GV = DBuilder.createStaticMemberType( - RecordTy, VName, VUnit, LineNumber, VTy, Flags, C, Align); - StaticDataMemberCache[Var->getCanonicalDecl()].reset(GV); - return GV; -} - -void CGDebugInfo::CollectRecordNormalField( - const FieldDecl *field, uint64_t OffsetInBits, llvm::DIFile *tunit, - SmallVectorImpl<llvm::Metadata *> &elements, llvm::DIType *RecordTy, - const RecordDecl *RD) { - StringRef name = field->getName(); - QualType type = field->getType(); - - // Ignore unnamed fields unless they're anonymous structs/unions. - if (name.empty() && !type->isRecordType()) - return; - - llvm::DIType *FieldType; - if (field->isBitField()) { - FieldType = createBitFieldType(field, RecordTy, RD); - } else { - auto Align = getDeclAlignIfRequired(field, CGM.getContext()); - FieldType = - createFieldType(name, type, field->getLocation(), field->getAccess(), - OffsetInBits, Align, tunit, RecordTy, RD); - } - - elements.push_back(FieldType); -} - -void CGDebugInfo::CollectRecordNestedType( - const TypeDecl *TD, SmallVectorImpl<llvm::Metadata *> &elements) { - QualType Ty = CGM.getContext().getTypeDeclType(TD); - // Injected class names are not considered nested records. - if (isa<InjectedClassNameType>(Ty)) - return; - SourceLocation Loc = TD->getLocation(); - llvm::DIType *nestedType = getOrCreateType(Ty, getOrCreateFile(Loc)); - elements.push_back(nestedType); -} - -void CGDebugInfo::CollectRecordFields( - const RecordDecl *record, llvm::DIFile *tunit, - SmallVectorImpl<llvm::Metadata *> &elements, - llvm::DICompositeType *RecordTy) { - const auto *CXXDecl = dyn_cast<CXXRecordDecl>(record); - - if (CXXDecl && CXXDecl->isLambda()) - CollectRecordLambdaFields(CXXDecl, elements, RecordTy); - else { - const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record); - - // Field number for non-static fields. - unsigned fieldNo = 0; - - // Static and non-static members should appear in the same order as - // the corresponding declarations in the source program. - for (const auto *I : record->decls()) - if (const auto *V = dyn_cast<VarDecl>(I)) { - if (V->hasAttr<NoDebugAttr>()) - continue; - - // Skip variable template specializations when emitting CodeView. MSVC - // doesn't emit them. - if (CGM.getCodeGenOpts().EmitCodeView && - isa<VarTemplateSpecializationDecl>(V)) - continue; - - // Reuse the existing static member declaration if one exists - auto MI = StaticDataMemberCache.find(V->getCanonicalDecl()); - if (MI != StaticDataMemberCache.end()) { - assert(MI->second && - "Static data member declaration should still exist"); - elements.push_back(MI->second); - } else { - auto Field = CreateRecordStaticField(V, RecordTy, record); - elements.push_back(Field); - } - } else if (const auto *field = dyn_cast<FieldDecl>(I)) { - CollectRecordNormalField(field, layout.getFieldOffset(fieldNo), tunit, - elements, RecordTy, record); - - // Bump field number for next field. - ++fieldNo; - } else if (CGM.getCodeGenOpts().EmitCodeView) { - // Debug info for nested types is included in the member list only for - // CodeView. - if (const auto *nestedType = dyn_cast<TypeDecl>(I)) - if (!nestedType->isImplicit() && - nestedType->getDeclContext() == record) - CollectRecordNestedType(nestedType, elements); - } - } -} - -llvm::DISubroutineType * -CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, - llvm::DIFile *Unit) { - const FunctionProtoType *Func = Method->getType()->getAs<FunctionProtoType>(); - if (Method->isStatic()) - return cast_or_null<llvm::DISubroutineType>( - getOrCreateType(QualType(Func, 0), Unit)); - return getOrCreateInstanceMethodType(Method->getThisType(), Func, Unit); -} - -llvm::DISubroutineType *CGDebugInfo::getOrCreateInstanceMethodType( - QualType ThisPtr, const FunctionProtoType *Func, llvm::DIFile *Unit) { - // Add "this" pointer. - llvm::DITypeRefArray Args( - cast<llvm::DISubroutineType>(getOrCreateType(QualType(Func, 0), Unit)) - ->getTypeArray()); - assert(Args.size() && "Invalid number of arguments!"); - - SmallVector<llvm::Metadata *, 16> Elts; - - // First element is always return type. For 'void' functions it is NULL. - Elts.push_back(Args[0]); - - // "this" pointer is always first argument. - const CXXRecordDecl *RD = ThisPtr->getPointeeCXXRecordDecl(); - if (isa<ClassTemplateSpecializationDecl>(RD)) { - // Create pointer type directly in this case. - const PointerType *ThisPtrTy = cast<PointerType>(ThisPtr); - QualType PointeeTy = ThisPtrTy->getPointeeType(); - unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy); - uint64_t Size = CGM.getTarget().getPointerWidth(AS); - auto Align = getTypeAlignIfRequired(ThisPtrTy, CGM.getContext()); - llvm::DIType *PointeeType = getOrCreateType(PointeeTy, Unit); - llvm::DIType *ThisPtrType = - DBuilder.createPointerType(PointeeType, Size, Align); - TypeCache[ThisPtr.getAsOpaquePtr()].reset(ThisPtrType); - // TODO: This and the artificial type below are misleading, the - // types aren't artificial the argument is, but the current - // metadata doesn't represent that. - ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType); - Elts.push_back(ThisPtrType); - } else { - llvm::DIType *ThisPtrType = getOrCreateType(ThisPtr, Unit); - TypeCache[ThisPtr.getAsOpaquePtr()].reset(ThisPtrType); - ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType); - Elts.push_back(ThisPtrType); - } - - // Copy rest of the arguments. - for (unsigned i = 1, e = Args.size(); i != e; ++i) - Elts.push_back(Args[i]); - - llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); - - llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; - if (Func->getExtProtoInfo().RefQualifier == RQ_LValue) - Flags |= llvm::DINode::FlagLValueReference; - if (Func->getExtProtoInfo().RefQualifier == RQ_RValue) - Flags |= llvm::DINode::FlagRValueReference; - - return DBuilder.createSubroutineType(EltTypeArray, Flags, - getDwarfCC(Func->getCallConv())); -} - -/// isFunctionLocalClass - Return true if CXXRecordDecl is defined -/// inside a function. -static bool isFunctionLocalClass(const CXXRecordDecl *RD) { - if (const auto *NRD = dyn_cast<CXXRecordDecl>(RD->getDeclContext())) - return isFunctionLocalClass(NRD); - if (isa<FunctionDecl>(RD->getDeclContext())) - return true; - return false; -} - -llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction( - const CXXMethodDecl *Method, llvm::DIFile *Unit, llvm::DIType *RecordTy) { - bool IsCtorOrDtor = - isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method); - - StringRef MethodName = getFunctionName(Method); - llvm::DISubroutineType *MethodTy = getOrCreateMethodType(Method, Unit); - - // Since a single ctor/dtor corresponds to multiple functions, it doesn't - // make sense to give a single ctor/dtor a linkage name. - StringRef MethodLinkageName; - // FIXME: 'isFunctionLocalClass' seems like an arbitrary/unintentional - // property to use here. It may've been intended to model "is non-external - // type" but misses cases of non-function-local but non-external classes such - // as those in anonymous namespaces as well as the reverse - external types - // that are function local, such as those in (non-local) inline functions. - if (!IsCtorOrDtor && !isFunctionLocalClass(Method->getParent())) - MethodLinkageName = CGM.getMangledName(Method); - - // Get the location for the method. - llvm::DIFile *MethodDefUnit = nullptr; - unsigned MethodLine = 0; - if (!Method->isImplicit()) { - MethodDefUnit = getOrCreateFile(Method->getLocation()); - MethodLine = getLineNumber(Method->getLocation()); - } - - // Collect virtual method info. - llvm::DIType *ContainingType = nullptr; - unsigned VIndex = 0; - llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; - llvm::DISubprogram::DISPFlags SPFlags = llvm::DISubprogram::SPFlagZero; - int ThisAdjustment = 0; - - if (Method->isVirtual()) { - if (Method->isPure()) - SPFlags |= llvm::DISubprogram::SPFlagPureVirtual; - else - SPFlags |= llvm::DISubprogram::SPFlagVirtual; - - if (CGM.getTarget().getCXXABI().isItaniumFamily()) { - // It doesn't make sense to give a virtual destructor a vtable index, - // since a single destructor has two entries in the vtable. - if (!isa<CXXDestructorDecl>(Method)) - VIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(Method); - } else { - // Emit MS ABI vftable information. There is only one entry for the - // deleting dtor. - const auto *DD = dyn_cast<CXXDestructorDecl>(Method); - GlobalDecl GD = DD ? GlobalDecl(DD, Dtor_Deleting) : GlobalDecl(Method); - MethodVFTableLocation ML = - CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD); - VIndex = ML.Index; - - // CodeView only records the vftable offset in the class that introduces - // the virtual method. This is possible because, unlike Itanium, the MS - // C++ ABI does not include all virtual methods from non-primary bases in - // the vtable for the most derived class. For example, if C inherits from - // A and B, C's primary vftable will not include B's virtual methods. - if (Method->size_overridden_methods() == 0) - Flags |= llvm::DINode::FlagIntroducedVirtual; - - // The 'this' adjustment accounts for both the virtual and non-virtual - // portions of the adjustment. Presumably the debugger only uses it when - // it knows the dynamic type of an object. - ThisAdjustment = CGM.getCXXABI() - .getVirtualFunctionPrologueThisAdjustment(GD) - .getQuantity(); - } - ContainingType = RecordTy; - } - - if (Method->isStatic()) - Flags |= llvm::DINode::FlagStaticMember; - if (Method->isImplicit()) - Flags |= llvm::DINode::FlagArtificial; - Flags |= getAccessFlag(Method->getAccess(), Method->getParent()); - if (const auto *CXXC = dyn_cast<CXXConstructorDecl>(Method)) { - if (CXXC->isExplicit()) - Flags |= llvm::DINode::FlagExplicit; - } else if (const auto *CXXC = dyn_cast<CXXConversionDecl>(Method)) { - if (CXXC->isExplicit()) - Flags |= llvm::DINode::FlagExplicit; - } - if (Method->hasPrototype()) - Flags |= llvm::DINode::FlagPrototyped; - if (Method->getRefQualifier() == RQ_LValue) - Flags |= llvm::DINode::FlagLValueReference; - if (Method->getRefQualifier() == RQ_RValue) - Flags |= llvm::DINode::FlagRValueReference; - if (CGM.getLangOpts().Optimize) - SPFlags |= llvm::DISubprogram::SPFlagOptimized; - - llvm::DINodeArray TParamsArray = CollectFunctionTemplateParams(Method, Unit); - llvm::DISubprogram *SP = DBuilder.createMethod( - RecordTy, MethodName, MethodLinkageName, MethodDefUnit, MethodLine, - MethodTy, VIndex, ThisAdjustment, ContainingType, Flags, SPFlags, - TParamsArray.get()); - - SPCache[Method->getCanonicalDecl()].reset(SP); - - return SP; -} - -void CGDebugInfo::CollectCXXMemberFunctions( - const CXXRecordDecl *RD, llvm::DIFile *Unit, - SmallVectorImpl<llvm::Metadata *> &EltTys, llvm::DIType *RecordTy) { - - // Since we want more than just the individual member decls if we - // have templated functions iterate over every declaration to gather - // the functions. - for (const auto *I : RD->decls()) { - const auto *Method = dyn_cast<CXXMethodDecl>(I); - // If the member is implicit, don't add it to the member list. This avoids - // the member being added to type units by LLVM, while still allowing it - // to be emitted into the type declaration/reference inside the compile - // unit. - // Ditto 'nodebug' methods, for consistency with CodeGenFunction.cpp. - // FIXME: Handle Using(Shadow?)Decls here to create - // DW_TAG_imported_declarations inside the class for base decls brought into - // derived classes. GDB doesn't seem to notice/leverage these when I tried - // it, so I'm not rushing to fix this. (GCC seems to produce them, if - // referenced) - if (!Method || Method->isImplicit() || Method->hasAttr<NoDebugAttr>()) - continue; - - if (Method->getType()->getAs<FunctionProtoType>()->getContainedAutoType()) - continue; - - // Reuse the existing member function declaration if it exists. - // It may be associated with the declaration of the type & should be - // reused as we're building the definition. - // - // This situation can arise in the vtable-based debug info reduction where - // implicit members are emitted in a non-vtable TU. - auto MI = SPCache.find(Method->getCanonicalDecl()); - EltTys.push_back(MI == SPCache.end() - ? CreateCXXMemberFunction(Method, Unit, RecordTy) - : static_cast<llvm::Metadata *>(MI->second)); - } -} - -void CGDebugInfo::CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile *Unit, - SmallVectorImpl<llvm::Metadata *> &EltTys, - llvm::DIType *RecordTy) { - llvm::DenseSet<CanonicalDeclPtr<const CXXRecordDecl>> SeenTypes; - CollectCXXBasesAux(RD, Unit, EltTys, RecordTy, RD->bases(), SeenTypes, - llvm::DINode::FlagZero); - - // If we are generating CodeView debug info, we also need to emit records for - // indirect virtual base classes. - if (CGM.getCodeGenOpts().EmitCodeView) { - CollectCXXBasesAux(RD, Unit, EltTys, RecordTy, RD->vbases(), SeenTypes, - llvm::DINode::FlagIndirectVirtualBase); - } -} - -void CGDebugInfo::CollectCXXBasesAux( - const CXXRecordDecl *RD, llvm::DIFile *Unit, - SmallVectorImpl<llvm::Metadata *> &EltTys, llvm::DIType *RecordTy, - const CXXRecordDecl::base_class_const_range &Bases, - llvm::DenseSet<CanonicalDeclPtr<const CXXRecordDecl>> &SeenTypes, - llvm::DINode::DIFlags StartingFlags) { - const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); - for (const auto &BI : Bases) { - const auto *Base = - cast<CXXRecordDecl>(BI.getType()->getAs<RecordType>()->getDecl()); - if (!SeenTypes.insert(Base).second) - continue; - auto *BaseTy = getOrCreateType(BI.getType(), Unit); - llvm::DINode::DIFlags BFlags = StartingFlags; - uint64_t BaseOffset; - uint32_t VBPtrOffset = 0; - - if (BI.isVirtual()) { - if (CGM.getTarget().getCXXABI().isItaniumFamily()) { - // virtual base offset offset is -ve. The code generator emits dwarf - // expression where it expects +ve number. - BaseOffset = 0 - CGM.getItaniumVTableContext() - .getVirtualBaseOffsetOffset(RD, Base) - .getQuantity(); - } else { - // In the MS ABI, store the vbtable offset, which is analogous to the - // vbase offset offset in Itanium. - BaseOffset = - 4 * CGM.getMicrosoftVTableContext().getVBTableIndex(RD, Base); - VBPtrOffset = CGM.getContext() - .getASTRecordLayout(RD) - .getVBPtrOffset() - .getQuantity(); - } - BFlags |= llvm::DINode::FlagVirtual; - } else - BaseOffset = CGM.getContext().toBits(RL.getBaseClassOffset(Base)); - // FIXME: Inconsistent units for BaseOffset. It is in bytes when - // BI->isVirtual() and bits when not. - - BFlags |= getAccessFlag(BI.getAccessSpecifier(), RD); - llvm::DIType *DTy = DBuilder.createInheritance(RecordTy, BaseTy, BaseOffset, - VBPtrOffset, BFlags); - EltTys.push_back(DTy); - } -} - -llvm::DINodeArray -CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList, - ArrayRef<TemplateArgument> TAList, - llvm::DIFile *Unit) { - SmallVector<llvm::Metadata *, 16> TemplateParams; - for (unsigned i = 0, e = TAList.size(); i != e; ++i) { - const TemplateArgument &TA = TAList[i]; - StringRef Name; - if (TPList) - Name = TPList->getParam(i)->getName(); - switch (TA.getKind()) { - case TemplateArgument::Type: { - llvm::DIType *TTy = getOrCreateType(TA.getAsType(), Unit); - TemplateParams.push_back( - DBuilder.createTemplateTypeParameter(TheCU, Name, TTy)); - } break; - case TemplateArgument::Integral: { - llvm::DIType *TTy = getOrCreateType(TA.getIntegralType(), Unit); - TemplateParams.push_back(DBuilder.createTemplateValueParameter( - TheCU, Name, TTy, - llvm::ConstantInt::get(CGM.getLLVMContext(), TA.getAsIntegral()))); - } break; - case TemplateArgument::Declaration: { - const ValueDecl *D = TA.getAsDecl(); - QualType T = TA.getParamTypeForDecl().getDesugaredType(CGM.getContext()); - llvm::DIType *TTy = getOrCreateType(T, Unit); - llvm::Constant *V = nullptr; - const CXXMethodDecl *MD; - // Variable pointer template parameters have a value that is the address - // of the variable. - if (const auto *VD = dyn_cast<VarDecl>(D)) - V = CGM.GetAddrOfGlobalVar(VD); - // Member function pointers have special support for building them, though - // this is currently unsupported in LLVM CodeGen. - else if ((MD = dyn_cast<CXXMethodDecl>(D)) && MD->isInstance()) - V = CGM.getCXXABI().EmitMemberFunctionPointer(MD); - else if (const auto *FD = dyn_cast<FunctionDecl>(D)) - V = CGM.GetAddrOfFunction(FD); - // Member data pointers have special handling too to compute the fixed - // offset within the object. - else if (const auto *MPT = dyn_cast<MemberPointerType>(T.getTypePtr())) { - // These five lines (& possibly the above member function pointer - // handling) might be able to be refactored to use similar code in - // CodeGenModule::getMemberPointerConstant - uint64_t fieldOffset = CGM.getContext().getFieldOffset(D); - CharUnits chars = - CGM.getContext().toCharUnitsFromBits((int64_t)fieldOffset); - V = CGM.getCXXABI().EmitMemberDataPointer(MPT, chars); - } - TemplateParams.push_back(DBuilder.createTemplateValueParameter( - TheCU, Name, TTy, - cast_or_null<llvm::Constant>(V->stripPointerCasts()))); - } break; - case TemplateArgument::NullPtr: { - QualType T = TA.getNullPtrType(); - llvm::DIType *TTy = getOrCreateType(T, Unit); - llvm::Constant *V = nullptr; - // Special case member data pointer null values since they're actually -1 - // instead of zero. - if (const auto *MPT = dyn_cast<MemberPointerType>(T.getTypePtr())) - // But treat member function pointers as simple zero integers because - // it's easier than having a special case in LLVM's CodeGen. If LLVM - // CodeGen grows handling for values of non-null member function - // pointers then perhaps we could remove this special case and rely on - // EmitNullMemberPointer for member function pointers. - if (MPT->isMemberDataPointer()) - V = CGM.getCXXABI().EmitNullMemberPointer(MPT); - if (!V) - V = llvm::ConstantInt::get(CGM.Int8Ty, 0); - TemplateParams.push_back( - DBuilder.createTemplateValueParameter(TheCU, Name, TTy, V)); - } break; - case TemplateArgument::Template: - TemplateParams.push_back(DBuilder.createTemplateTemplateParameter( - TheCU, Name, nullptr, - TA.getAsTemplate().getAsTemplateDecl()->getQualifiedNameAsString())); - break; - case TemplateArgument::Pack: - TemplateParams.push_back(DBuilder.createTemplateParameterPack( - TheCU, Name, nullptr, - CollectTemplateParams(nullptr, TA.getPackAsArray(), Unit))); - break; - case TemplateArgument::Expression: { - const Expr *E = TA.getAsExpr(); - QualType T = E->getType(); - if (E->isGLValue()) - T = CGM.getContext().getLValueReferenceType(T); - llvm::Constant *V = ConstantEmitter(CGM).emitAbstract(E, T); - assert(V && "Expression in template argument isn't constant"); - llvm::DIType *TTy = getOrCreateType(T, Unit); - TemplateParams.push_back(DBuilder.createTemplateValueParameter( - TheCU, Name, TTy, V->stripPointerCasts())); - } break; - // And the following should never occur: - case TemplateArgument::TemplateExpansion: - case TemplateArgument::Null: - llvm_unreachable( - "These argument types shouldn't exist in concrete types"); - } - } - return DBuilder.getOrCreateArray(TemplateParams); -} - -llvm::DINodeArray -CGDebugInfo::CollectFunctionTemplateParams(const FunctionDecl *FD, - llvm::DIFile *Unit) { - if (FD->getTemplatedKind() == - FunctionDecl::TK_FunctionTemplateSpecialization) { - const TemplateParameterList *TList = FD->getTemplateSpecializationInfo() - ->getTemplate() - ->getTemplateParameters(); - return CollectTemplateParams( - TList, FD->getTemplateSpecializationArgs()->asArray(), Unit); - } - return llvm::DINodeArray(); -} - -llvm::DINodeArray CGDebugInfo::CollectVarTemplateParams(const VarDecl *VL, - llvm::DIFile *Unit) { - // Always get the full list of parameters, not just the ones from the - // specialization. A partial specialization may have fewer parameters than - // there are arguments. - auto *TS = dyn_cast<VarTemplateSpecializationDecl>(VL); - if (!TS) - return llvm::DINodeArray(); - VarTemplateDecl *T = TS->getSpecializedTemplate(); - const TemplateParameterList *TList = T->getTemplateParameters(); - auto TA = TS->getTemplateArgs().asArray(); - return CollectTemplateParams(TList, TA, Unit); -} - -llvm::DINodeArray CGDebugInfo::CollectCXXTemplateParams( - const ClassTemplateSpecializationDecl *TSpecial, llvm::DIFile *Unit) { - // Always get the full list of parameters, not just the ones from the - // specialization. A partial specialization may have fewer parameters than - // there are arguments. - TemplateParameterList *TPList = - TSpecial->getSpecializedTemplate()->getTemplateParameters(); - const TemplateArgumentList &TAList = TSpecial->getTemplateArgs(); - return CollectTemplateParams(TPList, TAList.asArray(), Unit); -} - -llvm::DIType *CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile *Unit) { - if (VTablePtrType) - return VTablePtrType; - - ASTContext &Context = CGM.getContext(); - - /* Function type */ - llvm::Metadata *STy = getOrCreateType(Context.IntTy, Unit); - llvm::DITypeRefArray SElements = DBuilder.getOrCreateTypeArray(STy); - llvm::DIType *SubTy = DBuilder.createSubroutineType(SElements); - unsigned Size = Context.getTypeSize(Context.VoidPtrTy); - unsigned VtblPtrAddressSpace = CGM.getTarget().getVtblPtrAddressSpace(); - Optional<unsigned> DWARFAddressSpace = - CGM.getTarget().getDWARFAddressSpace(VtblPtrAddressSpace); - - llvm::DIType *vtbl_ptr_type = DBuilder.createPointerType( - SubTy, Size, 0, DWARFAddressSpace, "__vtbl_ptr_type"); - VTablePtrType = DBuilder.createPointerType(vtbl_ptr_type, Size); - return VTablePtrType; -} - -StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) { - // Copy the gdb compatible name on the side and use its reference. - return internString("_vptr$", RD->getNameAsString()); -} - -void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile *Unit, - SmallVectorImpl<llvm::Metadata *> &EltTys, - llvm::DICompositeType *RecordTy) { - // If this class is not dynamic then there is not any vtable info to collect. - if (!RD->isDynamicClass()) - return; - - // Don't emit any vtable shape or vptr info if this class doesn't have an - // extendable vfptr. This can happen if the class doesn't have virtual - // methods, or in the MS ABI if those virtual methods only come from virtually - // inherited bases. - const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); - if (!RL.hasExtendableVFPtr()) - return; - - // CodeView needs to know how large the vtable of every dynamic class is, so - // emit a special named pointer type into the element list. The vptr type - // points to this type as well. - llvm::DIType *VPtrTy = nullptr; - bool NeedVTableShape = CGM.getCodeGenOpts().EmitCodeView && - CGM.getTarget().getCXXABI().isMicrosoft(); - if (NeedVTableShape) { - uint64_t PtrWidth = - CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); - const VTableLayout &VFTLayout = - CGM.getMicrosoftVTableContext().getVFTableLayout(RD, CharUnits::Zero()); - unsigned VSlotCount = - VFTLayout.vtable_components().size() - CGM.getLangOpts().RTTIData; - unsigned VTableWidth = PtrWidth * VSlotCount; - unsigned VtblPtrAddressSpace = CGM.getTarget().getVtblPtrAddressSpace(); - Optional<unsigned> DWARFAddressSpace = - CGM.getTarget().getDWARFAddressSpace(VtblPtrAddressSpace); - - // Create a very wide void* type and insert it directly in the element list. - llvm::DIType *VTableType = DBuilder.createPointerType( - nullptr, VTableWidth, 0, DWARFAddressSpace, "__vtbl_ptr_type"); - EltTys.push_back(VTableType); - - // The vptr is a pointer to this special vtable type. - VPtrTy = DBuilder.createPointerType(VTableType, PtrWidth); - } - - // If there is a primary base then the artificial vptr member lives there. - if (RL.getPrimaryBase()) - return; - - if (!VPtrTy) - VPtrTy = getOrCreateVTablePtrType(Unit); - - unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); - llvm::DIType *VPtrMember = - DBuilder.createMemberType(Unit, getVTableName(RD), Unit, 0, Size, 0, 0, - llvm::DINode::FlagArtificial, VPtrTy); - EltTys.push_back(VPtrMember); -} - -llvm::DIType *CGDebugInfo::getOrCreateRecordType(QualType RTy, - SourceLocation Loc) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); - llvm::DIType *T = getOrCreateType(RTy, getOrCreateFile(Loc)); - return T; -} - -llvm::DIType *CGDebugInfo::getOrCreateInterfaceType(QualType D, - SourceLocation Loc) { - return getOrCreateStandaloneType(D, Loc); -} - -llvm::DIType *CGDebugInfo::getOrCreateStandaloneType(QualType D, - SourceLocation Loc) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); - assert(!D.isNull() && "null type"); - llvm::DIType *T = getOrCreateType(D, getOrCreateFile(Loc)); - assert(T && "could not create debug info for type"); - - RetainedTypes.push_back(D.getAsOpaquePtr()); - return T; -} - -void CGDebugInfo::completeType(const EnumDecl *ED) { - if (DebugKind <= codegenoptions::DebugLineTablesOnly) - return; - QualType Ty = CGM.getContext().getEnumType(ED); - void *TyPtr = Ty.getAsOpaquePtr(); - auto I = TypeCache.find(TyPtr); - if (I == TypeCache.end() || !cast<llvm::DIType>(I->second)->isForwardDecl()) - return; - llvm::DIType *Res = CreateTypeDefinition(Ty->castAs<EnumType>()); - assert(!Res->isForwardDecl()); - TypeCache[TyPtr].reset(Res); -} - -void CGDebugInfo::completeType(const RecordDecl *RD) { - if (DebugKind > codegenoptions::LimitedDebugInfo || - !CGM.getLangOpts().CPlusPlus) - completeRequiredType(RD); -} - -/// Return true if the class or any of its methods are marked dllimport. -static bool isClassOrMethodDLLImport(const CXXRecordDecl *RD) { - if (RD->hasAttr<DLLImportAttr>()) - return true; - for (const CXXMethodDecl *MD : RD->methods()) - if (MD->hasAttr<DLLImportAttr>()) - return true; - return false; -} - -/// Does a type definition exist in an imported clang module? -static bool isDefinedInClangModule(const RecordDecl *RD) { - // Only definitions that where imported from an AST file come from a module. - if (!RD || !RD->isFromASTFile()) - return false; - // Anonymous entities cannot be addressed. Treat them as not from module. - if (!RD->isExternallyVisible() && RD->getName().empty()) - return false; - if (auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD)) { - if (!CXXDecl->isCompleteDefinition()) - return false; - // Check wether RD is a template. - auto TemplateKind = CXXDecl->getTemplateSpecializationKind(); - if (TemplateKind != TSK_Undeclared) { - // Unfortunately getOwningModule() isn't accurate enough to find the - // owning module of a ClassTemplateSpecializationDecl that is inside a - // namespace spanning multiple modules. - bool Explicit = false; - if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(CXXDecl)) - Explicit = TD->isExplicitInstantiationOrSpecialization(); - if (!Explicit && CXXDecl->getEnclosingNamespaceContext()) - return false; - // This is a template, check the origin of the first member. - if (CXXDecl->field_begin() == CXXDecl->field_end()) - return TemplateKind == TSK_ExplicitInstantiationDeclaration; - if (!CXXDecl->field_begin()->isFromASTFile()) - return false; - } - } - return true; -} - -void CGDebugInfo::completeClassData(const RecordDecl *RD) { - if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) - if (CXXRD->isDynamicClass() && - CGM.getVTableLinkage(CXXRD) == - llvm::GlobalValue::AvailableExternallyLinkage && - !isClassOrMethodDLLImport(CXXRD)) - return; - - if (DebugTypeExtRefs && isDefinedInClangModule(RD->getDefinition())) - return; - - completeClass(RD); -} - -void CGDebugInfo::completeClass(const RecordDecl *RD) { - if (DebugKind <= codegenoptions::DebugLineTablesOnly) - return; - QualType Ty = CGM.getContext().getRecordType(RD); - void *TyPtr = Ty.getAsOpaquePtr(); - auto I = TypeCache.find(TyPtr); - if (I != TypeCache.end() && !cast<llvm::DIType>(I->second)->isForwardDecl()) - return; - llvm::DIType *Res = CreateTypeDefinition(Ty->castAs<RecordType>()); - assert(!Res->isForwardDecl()); - TypeCache[TyPtr].reset(Res); -} - -static bool hasExplicitMemberDefinition(CXXRecordDecl::method_iterator I, - CXXRecordDecl::method_iterator End) { - for (CXXMethodDecl *MD : llvm::make_range(I, End)) - if (FunctionDecl *Tmpl = MD->getInstantiatedFromMemberFunction()) - if (!Tmpl->isImplicit() && Tmpl->isThisDeclarationADefinition() && - !MD->getMemberSpecializationInfo()->isExplicitSpecialization()) - return true; - return false; -} - -static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind, - bool DebugTypeExtRefs, const RecordDecl *RD, - const LangOptions &LangOpts) { - if (DebugTypeExtRefs && isDefinedInClangModule(RD->getDefinition())) - return true; - - if (auto *ES = RD->getASTContext().getExternalSource()) - if (ES->hasExternalDefinitions(RD) == ExternalASTSource::EK_Always) - return true; - - if (DebugKind > codegenoptions::LimitedDebugInfo) - return false; - - if (!LangOpts.CPlusPlus) - return false; - - if (!RD->isCompleteDefinitionRequired()) - return true; - - const auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD); - - if (!CXXDecl) - return false; - - // Only emit complete debug info for a dynamic class when its vtable is - // emitted. However, Microsoft debuggers don't resolve type information - // across DLL boundaries, so skip this optimization if the class or any of its - // methods are marked dllimport. This isn't a complete solution, since objects - // without any dllimport methods can be used in one DLL and constructed in - // another, but it is the current behavior of LimitedDebugInfo. - if (CXXDecl->hasDefinition() && CXXDecl->isDynamicClass() && - !isClassOrMethodDLLImport(CXXDecl)) - return true; - - TemplateSpecializationKind Spec = TSK_Undeclared; - if (const auto *SD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) - Spec = SD->getSpecializationKind(); - - if (Spec == TSK_ExplicitInstantiationDeclaration && - hasExplicitMemberDefinition(CXXDecl->method_begin(), - CXXDecl->method_end())) - return true; - - return false; -} - -void CGDebugInfo::completeRequiredType(const RecordDecl *RD) { - if (shouldOmitDefinition(DebugKind, DebugTypeExtRefs, RD, CGM.getLangOpts())) - return; - - QualType Ty = CGM.getContext().getRecordType(RD); - llvm::DIType *T = getTypeOrNull(Ty); - if (T && T->isForwardDecl()) - completeClassData(RD); -} - -llvm::DIType *CGDebugInfo::CreateType(const RecordType *Ty) { - RecordDecl *RD = Ty->getDecl(); - llvm::DIType *T = cast_or_null<llvm::DIType>(getTypeOrNull(QualType(Ty, 0))); - if (T || shouldOmitDefinition(DebugKind, DebugTypeExtRefs, RD, - CGM.getLangOpts())) { - if (!T) - T = getOrCreateRecordFwdDecl(Ty, getDeclContextDescriptor(RD)); - return T; - } - - return CreateTypeDefinition(Ty); -} - -llvm::DIType *CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { - RecordDecl *RD = Ty->getDecl(); - - // Get overall information about the record type for the debug info. - llvm::DIFile *DefUnit = getOrCreateFile(RD->getLocation()); - - // Records and classes and unions can all be recursive. To handle them, we - // first generate a debug descriptor for the struct as a forward declaration. - // Then (if it is a definition) we go through and get debug info for all of - // its members. Finally, we create a descriptor for the complete type (which - // may refer to the forward decl if the struct is recursive) and replace all - // uses of the forward declaration with the final definition. - llvm::DICompositeType *FwdDecl = getOrCreateLimitedType(Ty, DefUnit); - - const RecordDecl *D = RD->getDefinition(); - if (!D || !D->isCompleteDefinition()) - return FwdDecl; - - if (const auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD)) - CollectContainingType(CXXDecl, FwdDecl); - - // Push the struct on region stack. - LexicalBlockStack.emplace_back(&*FwdDecl); - RegionMap[Ty->getDecl()].reset(FwdDecl); - - // Convert all the elements. - SmallVector<llvm::Metadata *, 16> EltTys; - // what about nested types? - - // Note: The split of CXXDecl information here is intentional, the - // gdb tests will depend on a certain ordering at printout. The debug - // information offsets are still correct if we merge them all together - // though. - const auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD); - if (CXXDecl) { - CollectCXXBases(CXXDecl, DefUnit, EltTys, FwdDecl); - CollectVTableInfo(CXXDecl, DefUnit, EltTys, FwdDecl); - } - - // Collect data fields (including static variables and any initializers). - CollectRecordFields(RD, DefUnit, EltTys, FwdDecl); - if (CXXDecl) - CollectCXXMemberFunctions(CXXDecl, DefUnit, EltTys, FwdDecl); - - LexicalBlockStack.pop_back(); - RegionMap.erase(Ty->getDecl()); - - llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys); - DBuilder.replaceArrays(FwdDecl, Elements); - - if (FwdDecl->isTemporary()) - FwdDecl = - llvm::MDNode::replaceWithPermanent(llvm::TempDICompositeType(FwdDecl)); - - RegionMap[Ty->getDecl()].reset(FwdDecl); - return FwdDecl; -} - -llvm::DIType *CGDebugInfo::CreateType(const ObjCObjectType *Ty, - llvm::DIFile *Unit) { - // Ignore protocols. - return getOrCreateType(Ty->getBaseType(), Unit); -} - -llvm::DIType *CGDebugInfo::CreateType(const ObjCTypeParamType *Ty, - llvm::DIFile *Unit) { - // Ignore protocols. - SourceLocation Loc = Ty->getDecl()->getLocation(); - - // Use Typedefs to represent ObjCTypeParamType. - return DBuilder.createTypedef( - getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit), - Ty->getDecl()->getName(), getOrCreateFile(Loc), getLineNumber(Loc), - getDeclContextDescriptor(Ty->getDecl())); -} - -/// \return true if Getter has the default name for the property PD. -static bool hasDefaultGetterName(const ObjCPropertyDecl *PD, - const ObjCMethodDecl *Getter) { - assert(PD); - if (!Getter) - return true; - - assert(Getter->getDeclName().isObjCZeroArgSelector()); - return PD->getName() == - Getter->getDeclName().getObjCSelector().getNameForSlot(0); -} - -/// \return true if Setter has the default name for the property PD. -static bool hasDefaultSetterName(const ObjCPropertyDecl *PD, - const ObjCMethodDecl *Setter) { - assert(PD); - if (!Setter) - return true; - - assert(Setter->getDeclName().isObjCOneArgSelector()); - return SelectorTable::constructSetterName(PD->getName()) == - Setter->getDeclName().getObjCSelector().getNameForSlot(0); -} - -llvm::DIType *CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, - llvm::DIFile *Unit) { - ObjCInterfaceDecl *ID = Ty->getDecl(); - if (!ID) - return nullptr; - - // Return a forward declaration if this type was imported from a clang module, - // and this is not the compile unit with the implementation of the type (which - // may contain hidden ivars). - if (DebugTypeExtRefs && ID->isFromASTFile() && ID->getDefinition() && - !ID->getImplementation()) - return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, - ID->getName(), - getDeclContextDescriptor(ID), Unit, 0); - - // Get overall information about the record type for the debug info. - llvm::DIFile *DefUnit = getOrCreateFile(ID->getLocation()); - unsigned Line = getLineNumber(ID->getLocation()); - auto RuntimeLang = - static_cast<llvm::dwarf::SourceLanguage>(TheCU->getSourceLanguage()); - - // If this is just a forward declaration return a special forward-declaration - // debug type since we won't be able to lay out the entire type. - ObjCInterfaceDecl *Def = ID->getDefinition(); - if (!Def || !Def->getImplementation()) { - llvm::DIScope *Mod = getParentModuleOrNull(ID); - llvm::DIType *FwdDecl = DBuilder.createReplaceableCompositeType( - llvm::dwarf::DW_TAG_structure_type, ID->getName(), Mod ? Mod : TheCU, - DefUnit, Line, RuntimeLang); - ObjCInterfaceCache.push_back(ObjCInterfaceCacheEntry(Ty, FwdDecl, Unit)); - return FwdDecl; - } - - return CreateTypeDefinition(Ty, Unit); -} - -llvm::DIModule * -CGDebugInfo::getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod, - bool CreateSkeletonCU) { - // Use the Module pointer as the key into the cache. This is a - // nullptr if the "Module" is a PCH, which is safe because we don't - // support chained PCH debug info, so there can only be a single PCH. - const Module *M = Mod.getModuleOrNull(); - auto ModRef = ModuleCache.find(M); - if (ModRef != ModuleCache.end()) - return cast<llvm::DIModule>(ModRef->second); - - // Macro definitions that were defined with "-D" on the command line. - SmallString<128> ConfigMacros; - { - llvm::raw_svector_ostream OS(ConfigMacros); - const auto &PPOpts = CGM.getPreprocessorOpts(); - unsigned I = 0; - // Translate the macro definitions back into a command line. - for (auto &M : PPOpts.Macros) { - if (++I > 1) - OS << " "; - const std::string &Macro = M.first; - bool Undef = M.second; - OS << "\"-" << (Undef ? 'U' : 'D'); - for (char c : Macro) - switch (c) { - case '\\': - OS << "\\\\"; - break; - case '"': - OS << "\\\""; - break; - default: - OS << c; - } - OS << '\"'; - } - } - - bool IsRootModule = M ? !M->Parent : true; - if (CreateSkeletonCU && IsRootModule) { - // PCH files don't have a signature field in the control block, - // but LLVM detects skeleton CUs by looking for a non-zero DWO id. - // We use the lower 64 bits for debug info. - uint64_t Signature = - Mod.getSignature() - ? (uint64_t)Mod.getSignature()[1] << 32 | Mod.getSignature()[0] - : ~1ULL; - llvm::DIBuilder DIB(CGM.getModule()); - DIB.createCompileUnit(TheCU->getSourceLanguage(), - // TODO: Support "Source" from external AST providers? - DIB.createFile(Mod.getModuleName(), Mod.getPath()), - TheCU->getProducer(), true, StringRef(), 0, - Mod.getASTFile(), llvm::DICompileUnit::FullDebug, - Signature); - DIB.finalize(); - } - llvm::DIModule *Parent = - IsRootModule ? nullptr - : getOrCreateModuleRef( - ExternalASTSource::ASTSourceDescriptor(*M->Parent), - CreateSkeletonCU); - llvm::DIModule *DIMod = - DBuilder.createModule(Parent, Mod.getModuleName(), ConfigMacros, - Mod.getPath(), CGM.getHeaderSearchOpts().Sysroot); - ModuleCache[M].reset(DIMod); - return DIMod; -} - -llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty, - llvm::DIFile *Unit) { - ObjCInterfaceDecl *ID = Ty->getDecl(); - llvm::DIFile *DefUnit = getOrCreateFile(ID->getLocation()); - unsigned Line = getLineNumber(ID->getLocation()); - unsigned RuntimeLang = TheCU->getSourceLanguage(); - - // Bit size, align and offset of the type. - uint64_t Size = CGM.getContext().getTypeSize(Ty); - auto Align = getTypeAlignIfRequired(Ty, CGM.getContext()); - - llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; - if (ID->getImplementation()) - Flags |= llvm::DINode::FlagObjcClassComplete; - - llvm::DIScope *Mod = getParentModuleOrNull(ID); - llvm::DICompositeType *RealDecl = DBuilder.createStructType( - Mod ? Mod : Unit, ID->getName(), DefUnit, Line, Size, Align, Flags, - nullptr, llvm::DINodeArray(), RuntimeLang); - - QualType QTy(Ty, 0); - TypeCache[QTy.getAsOpaquePtr()].reset(RealDecl); - - // Push the struct on region stack. - LexicalBlockStack.emplace_back(RealDecl); - RegionMap[Ty->getDecl()].reset(RealDecl); - - // Convert all the elements. - SmallVector<llvm::Metadata *, 16> EltTys; - - ObjCInterfaceDecl *SClass = ID->getSuperClass(); - if (SClass) { - llvm::DIType *SClassTy = - getOrCreateType(CGM.getContext().getObjCInterfaceType(SClass), Unit); - if (!SClassTy) - return nullptr; - - llvm::DIType *InhTag = DBuilder.createInheritance(RealDecl, SClassTy, 0, 0, - llvm::DINode::FlagZero); - EltTys.push_back(InhTag); - } - - // Create entries for all of the properties. - auto AddProperty = [&](const ObjCPropertyDecl *PD) { - SourceLocation Loc = PD->getLocation(); - llvm::DIFile *PUnit = getOrCreateFile(Loc); - unsigned PLine = getLineNumber(Loc); - ObjCMethodDecl *Getter = PD->getGetterMethodDecl(); - ObjCMethodDecl *Setter = PD->getSetterMethodDecl(); - llvm::MDNode *PropertyNode = DBuilder.createObjCProperty( - PD->getName(), PUnit, PLine, - hasDefaultGetterName(PD, Getter) ? "" - : getSelectorName(PD->getGetterName()), - hasDefaultSetterName(PD, Setter) ? "" - : getSelectorName(PD->getSetterName()), - PD->getPropertyAttributes(), getOrCreateType(PD->getType(), PUnit)); - EltTys.push_back(PropertyNode); - }; - { - llvm::SmallPtrSet<const IdentifierInfo *, 16> PropertySet; - for (const ObjCCategoryDecl *ClassExt : ID->known_extensions()) - for (auto *PD : ClassExt->properties()) { - PropertySet.insert(PD->getIdentifier()); - AddProperty(PD); - } - for (const auto *PD : ID->properties()) { - // Don't emit duplicate metadata for properties that were already in a - // class extension. - if (!PropertySet.insert(PD->getIdentifier()).second) - continue; - AddProperty(PD); - } - } - - const ASTRecordLayout &RL = CGM.getContext().getASTObjCInterfaceLayout(ID); - unsigned FieldNo = 0; - for (ObjCIvarDecl *Field = ID->all_declared_ivar_begin(); Field; - Field = Field->getNextIvar(), ++FieldNo) { - llvm::DIType *FieldTy = getOrCreateType(Field->getType(), Unit); - if (!FieldTy) - return nullptr; - - StringRef FieldName = Field->getName(); - - // Ignore unnamed fields. - if (FieldName.empty()) - continue; - - // Get the location for the field. - llvm::DIFile *FieldDefUnit = getOrCreateFile(Field->getLocation()); - unsigned FieldLine = getLineNumber(Field->getLocation()); - QualType FType = Field->getType(); - uint64_t FieldSize = 0; - uint32_t FieldAlign = 0; - - if (!FType->isIncompleteArrayType()) { - - // Bit size, align and offset of the type. - FieldSize = Field->isBitField() - ? Field->getBitWidthValue(CGM.getContext()) - : CGM.getContext().getTypeSize(FType); - FieldAlign = getTypeAlignIfRequired(FType, CGM.getContext()); - } - - uint64_t FieldOffset; - if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) { - // We don't know the runtime offset of an ivar if we're using the - // non-fragile ABI. For bitfields, use the bit offset into the first - // byte of storage of the bitfield. For other fields, use zero. - if (Field->isBitField()) { - FieldOffset = - CGM.getObjCRuntime().ComputeBitfieldBitOffset(CGM, ID, Field); - FieldOffset %= CGM.getContext().getCharWidth(); - } else { - FieldOffset = 0; - } - } else { - FieldOffset = RL.getFieldOffset(FieldNo); - } - - llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; - if (Field->getAccessControl() == ObjCIvarDecl::Protected) - Flags = llvm::DINode::FlagProtected; - else if (Field->getAccessControl() == ObjCIvarDecl::Private) - Flags = llvm::DINode::FlagPrivate; - else if (Field->getAccessControl() == ObjCIvarDecl::Public) - Flags = llvm::DINode::FlagPublic; - - llvm::MDNode *PropertyNode = nullptr; - if (ObjCImplementationDecl *ImpD = ID->getImplementation()) { - if (ObjCPropertyImplDecl *PImpD = - ImpD->FindPropertyImplIvarDecl(Field->getIdentifier())) { - if (ObjCPropertyDecl *PD = PImpD->getPropertyDecl()) { - SourceLocation Loc = PD->getLocation(); - llvm::DIFile *PUnit = getOrCreateFile(Loc); - unsigned PLine = getLineNumber(Loc); - ObjCMethodDecl *Getter = PD->getGetterMethodDecl(); - ObjCMethodDecl *Setter = PD->getSetterMethodDecl(); - PropertyNode = DBuilder.createObjCProperty( - PD->getName(), PUnit, PLine, - hasDefaultGetterName(PD, Getter) - ? "" - : getSelectorName(PD->getGetterName()), - hasDefaultSetterName(PD, Setter) - ? "" - : getSelectorName(PD->getSetterName()), - PD->getPropertyAttributes(), - getOrCreateType(PD->getType(), PUnit)); - } - } - } - FieldTy = DBuilder.createObjCIVar(FieldName, FieldDefUnit, FieldLine, - FieldSize, FieldAlign, FieldOffset, Flags, - FieldTy, PropertyNode); - EltTys.push_back(FieldTy); - } - - llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys); - DBuilder.replaceArrays(RealDecl, Elements); - - LexicalBlockStack.pop_back(); - return RealDecl; -} - -llvm::DIType *CGDebugInfo::CreateType(const VectorType *Ty, - llvm::DIFile *Unit) { - llvm::DIType *ElementTy = getOrCreateType(Ty->getElementType(), Unit); - int64_t Count = Ty->getNumElements(); - - llvm::Metadata *Subscript; - QualType QTy(Ty, 0); - auto SizeExpr = SizeExprCache.find(QTy); - if (SizeExpr != SizeExprCache.end()) - Subscript = DBuilder.getOrCreateSubrange(0, SizeExpr->getSecond()); - else - Subscript = DBuilder.getOrCreateSubrange(0, Count ? Count : -1); - llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscript); - - uint64_t Size = CGM.getContext().getTypeSize(Ty); - auto Align = getTypeAlignIfRequired(Ty, CGM.getContext()); - - return DBuilder.createVectorType(Size, Align, ElementTy, SubscriptArray); -} - -llvm::DIType *CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile *Unit) { - uint64_t Size; - uint32_t Align; - - // FIXME: make getTypeAlign() aware of VLAs and incomplete array types - if (const auto *VAT = dyn_cast<VariableArrayType>(Ty)) { - Size = 0; - Align = getTypeAlignIfRequired(CGM.getContext().getBaseElementType(VAT), - CGM.getContext()); - } else if (Ty->isIncompleteArrayType()) { - Size = 0; - if (Ty->getElementType()->isIncompleteType()) - Align = 0; - else - Align = getTypeAlignIfRequired(Ty->getElementType(), CGM.getContext()); - } else if (Ty->isIncompleteType()) { - Size = 0; - Align = 0; - } else { - // Size and align of the whole array, not the element type. - Size = CGM.getContext().getTypeSize(Ty); - Align = getTypeAlignIfRequired(Ty, CGM.getContext()); - } - - // Add the dimensions of the array. FIXME: This loses CV qualifiers from - // interior arrays, do we care? Why aren't nested arrays represented the - // obvious/recursive way? - SmallVector<llvm::Metadata *, 8> Subscripts; - QualType EltTy(Ty, 0); - while ((Ty = dyn_cast<ArrayType>(EltTy))) { - // If the number of elements is known, then count is that number. Otherwise, - // it's -1. This allows us to represent a subrange with an array of 0 - // elements, like this: - // - // struct foo { - // int x[0]; - // }; - int64_t Count = -1; // Count == -1 is an unbounded array. - if (const auto *CAT = dyn_cast<ConstantArrayType>(Ty)) - Count = CAT->getSize().getZExtValue(); - else if (const auto *VAT = dyn_cast<VariableArrayType>(Ty)) { - if (Expr *Size = VAT->getSizeExpr()) { - Expr::EvalResult Result; - if (Size->EvaluateAsInt(Result, CGM.getContext())) - Count = Result.Val.getInt().getExtValue(); - } - } - - auto SizeNode = SizeExprCache.find(EltTy); - if (SizeNode != SizeExprCache.end()) - Subscripts.push_back( - DBuilder.getOrCreateSubrange(0, SizeNode->getSecond())); - else - Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count)); - EltTy = Ty->getElementType(); - } - - llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscripts); - - return DBuilder.createArrayType(Size, Align, getOrCreateType(EltTy, Unit), - SubscriptArray); -} - -llvm::DIType *CGDebugInfo::CreateType(const LValueReferenceType *Ty, - llvm::DIFile *Unit) { - return CreatePointerLikeType(llvm::dwarf::DW_TAG_reference_type, Ty, - Ty->getPointeeType(), Unit); -} - -llvm::DIType *CGDebugInfo::CreateType(const RValueReferenceType *Ty, - llvm::DIFile *Unit) { - return CreatePointerLikeType(llvm::dwarf::DW_TAG_rvalue_reference_type, Ty, - Ty->getPointeeType(), Unit); -} - -llvm::DIType *CGDebugInfo::CreateType(const MemberPointerType *Ty, - llvm::DIFile *U) { - llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; - uint64_t Size = 0; - - if (!Ty->isIncompleteType()) { - Size = CGM.getContext().getTypeSize(Ty); - - // Set the MS inheritance model. There is no flag for the unspecified model. - if (CGM.getTarget().getCXXABI().isMicrosoft()) { - switch (Ty->getMostRecentCXXRecordDecl()->getMSInheritanceModel()) { - case MSInheritanceAttr::Keyword_single_inheritance: - Flags |= llvm::DINode::FlagSingleInheritance; - break; - case MSInheritanceAttr::Keyword_multiple_inheritance: - Flags |= llvm::DINode::FlagMultipleInheritance; - break; - case MSInheritanceAttr::Keyword_virtual_inheritance: - Flags |= llvm::DINode::FlagVirtualInheritance; - break; - case MSInheritanceAttr::Keyword_unspecified_inheritance: - break; - } - } - } - - llvm::DIType *ClassType = getOrCreateType(QualType(Ty->getClass(), 0), U); - if (Ty->isMemberDataPointerType()) - return DBuilder.createMemberPointerType( - getOrCreateType(Ty->getPointeeType(), U), ClassType, Size, /*Align=*/0, - Flags); - - const FunctionProtoType *FPT = - Ty->getPointeeType()->getAs<FunctionProtoType>(); - return DBuilder.createMemberPointerType( - getOrCreateInstanceMethodType( - CXXMethodDecl::getThisType(FPT, Ty->getMostRecentCXXRecordDecl()), - FPT, U), - ClassType, Size, /*Align=*/0, Flags); -} - -llvm::DIType *CGDebugInfo::CreateType(const AtomicType *Ty, llvm::DIFile *U) { - auto *FromTy = getOrCreateType(Ty->getValueType(), U); - return DBuilder.createQualifiedType(llvm::dwarf::DW_TAG_atomic_type, FromTy); -} - -llvm::DIType *CGDebugInfo::CreateType(const PipeType *Ty, llvm::DIFile *U) { - return getOrCreateType(Ty->getElementType(), U); -} - -llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) { - const EnumDecl *ED = Ty->getDecl(); - - uint64_t Size = 0; - uint32_t Align = 0; - if (!ED->getTypeForDecl()->isIncompleteType()) { - Size = CGM.getContext().getTypeSize(ED->getTypeForDecl()); - Align = getDeclAlignIfRequired(ED, CGM.getContext()); - } - - SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU); - - bool isImportedFromModule = - DebugTypeExtRefs && ED->isFromASTFile() && ED->getDefinition(); - - // If this is just a forward declaration, construct an appropriately - // marked node and just return it. - if (isImportedFromModule || !ED->getDefinition()) { - // Note that it is possible for enums to be created as part of - // their own declcontext. In this case a FwdDecl will be created - // twice. This doesn't cause a problem because both FwdDecls are - // entered into the ReplaceMap: finalize() will replace the first - // FwdDecl with the second and then replace the second with - // complete type. - llvm::DIScope *EDContext = getDeclContextDescriptor(ED); - llvm::DIFile *DefUnit = getOrCreateFile(ED->getLocation()); - llvm::TempDIScope TmpContext(DBuilder.createReplaceableCompositeType( - llvm::dwarf::DW_TAG_enumeration_type, "", TheCU, DefUnit, 0)); - - unsigned Line = getLineNumber(ED->getLocation()); - StringRef EDName = ED->getName(); - llvm::DIType *RetTy = DBuilder.createReplaceableCompositeType( - llvm::dwarf::DW_TAG_enumeration_type, EDName, EDContext, DefUnit, Line, - 0, Size, Align, llvm::DINode::FlagFwdDecl, Identifier); - - ReplaceMap.emplace_back( - std::piecewise_construct, std::make_tuple(Ty), - std::make_tuple(static_cast<llvm::Metadata *>(RetTy))); - return RetTy; - } - - return CreateTypeDefinition(Ty); -} - -llvm::DIType *CGDebugInfo::CreateTypeDefinition(const EnumType *Ty) { - const EnumDecl *ED = Ty->getDecl(); - uint64_t Size = 0; - uint32_t Align = 0; - if (!ED->getTypeForDecl()->isIncompleteType()) { - Size = CGM.getContext().getTypeSize(ED->getTypeForDecl()); - Align = getDeclAlignIfRequired(ED, CGM.getContext()); - } - - SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU); - - // Create elements for each enumerator. - SmallVector<llvm::Metadata *, 16> Enumerators; - ED = ED->getDefinition(); - bool IsSigned = ED->getIntegerType()->isSignedIntegerType(); - for (const auto *Enum : ED->enumerators()) { - const auto &InitVal = Enum->getInitVal(); - auto Value = IsSigned ? InitVal.getSExtValue() : InitVal.getZExtValue(); - Enumerators.push_back( - DBuilder.createEnumerator(Enum->getName(), Value, !IsSigned)); - } - - // Return a CompositeType for the enum itself. - llvm::DINodeArray EltArray = DBuilder.getOrCreateArray(Enumerators); - - llvm::DIFile *DefUnit = getOrCreateFile(ED->getLocation()); - unsigned Line = getLineNumber(ED->getLocation()); - llvm::DIScope *EnumContext = getDeclContextDescriptor(ED); - llvm::DIType *ClassTy = getOrCreateType(ED->getIntegerType(), DefUnit); - return DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit, - Line, Size, Align, EltArray, ClassTy, - Identifier, ED->isScoped()); -} - -llvm::DIMacro *CGDebugInfo::CreateMacro(llvm::DIMacroFile *Parent, - unsigned MType, SourceLocation LineLoc, - StringRef Name, StringRef Value) { - unsigned Line = LineLoc.isInvalid() ? 0 : getLineNumber(LineLoc); - return DBuilder.createMacro(Parent, Line, MType, Name, Value); -} - -llvm::DIMacroFile *CGDebugInfo::CreateTempMacroFile(llvm::DIMacroFile *Parent, - SourceLocation LineLoc, - SourceLocation FileLoc) { - llvm::DIFile *FName = getOrCreateFile(FileLoc); - unsigned Line = LineLoc.isInvalid() ? 0 : getLineNumber(LineLoc); - return DBuilder.createTempMacroFile(Parent, Line, FName); -} - -static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) { - Qualifiers Quals; - do { - Qualifiers InnerQuals = T.getLocalQualifiers(); - // Qualifiers::operator+() doesn't like it if you add a Qualifier - // that is already there. - Quals += Qualifiers::removeCommonQualifiers(Quals, InnerQuals); - Quals += InnerQuals; - QualType LastT = T; - switch (T->getTypeClass()) { - default: - return C.getQualifiedType(T.getTypePtr(), Quals); - case Type::TemplateSpecialization: { - const auto *Spec = cast<TemplateSpecializationType>(T); - if (Spec->isTypeAlias()) - return C.getQualifiedType(T.getTypePtr(), Quals); - T = Spec->desugar(); - break; - } - case Type::TypeOfExpr: - T = cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType(); - break; - case Type::TypeOf: - T = cast<TypeOfType>(T)->getUnderlyingType(); - break; - case Type::Decltype: - T = cast<DecltypeType>(T)->getUnderlyingType(); - break; - case Type::UnaryTransform: - T = cast<UnaryTransformType>(T)->getUnderlyingType(); - break; - case Type::Attributed: - T = cast<AttributedType>(T)->getEquivalentType(); - break; - case Type::Elaborated: - T = cast<ElaboratedType>(T)->getNamedType(); - break; - case Type::Paren: - T = cast<ParenType>(T)->getInnerType(); - break; - case Type::SubstTemplateTypeParm: - T = cast<SubstTemplateTypeParmType>(T)->getReplacementType(); - break; - case Type::Auto: - case Type::DeducedTemplateSpecialization: { - QualType DT = cast<DeducedType>(T)->getDeducedType(); - assert(!DT.isNull() && "Undeduced types shouldn't reach here."); - T = DT; - break; - } - case Type::Adjusted: - case Type::Decayed: - // Decayed and adjusted types use the adjusted type in LLVM and DWARF. - T = cast<AdjustedType>(T)->getAdjustedType(); - break; - } - - assert(T != LastT && "Type unwrapping failed to unwrap!"); - (void)LastT; - } while (true); -} - -llvm::DIType *CGDebugInfo::getTypeOrNull(QualType Ty) { - - // Unwrap the type as needed for debug information. - Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext()); - - auto It = TypeCache.find(Ty.getAsOpaquePtr()); - if (It != TypeCache.end()) { - // Verify that the debug info still exists. - if (llvm::Metadata *V = It->second) - return cast<llvm::DIType>(V); - } - - return nullptr; -} - -void CGDebugInfo::completeTemplateDefinition( - const ClassTemplateSpecializationDecl &SD) { - if (DebugKind <= codegenoptions::DebugLineTablesOnly) - return; - completeUnusedClass(SD); -} - -void CGDebugInfo::completeUnusedClass(const CXXRecordDecl &D) { - if (DebugKind <= codegenoptions::DebugLineTablesOnly) - return; - - completeClassData(&D); - // In case this type has no member function definitions being emitted, ensure - // it is retained - RetainedTypes.push_back(CGM.getContext().getRecordType(&D).getAsOpaquePtr()); -} - -llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) { - if (Ty.isNull()) - return nullptr; - - // Unwrap the type as needed for debug information. - Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext()); - - if (auto *T = getTypeOrNull(Ty)) - return T; - - llvm::DIType *Res = CreateTypeNode(Ty, Unit); - void *TyPtr = Ty.getAsOpaquePtr(); - - // And update the type cache. - TypeCache[TyPtr].reset(Res); - - return Res; -} - -llvm::DIModule *CGDebugInfo::getParentModuleOrNull(const Decl *D) { - // A forward declaration inside a module header does not belong to the module. - if (isa<RecordDecl>(D) && !cast<RecordDecl>(D)->getDefinition()) - return nullptr; - if (DebugTypeExtRefs && D->isFromASTFile()) { - // Record a reference to an imported clang module or precompiled header. - auto *Reader = CGM.getContext().getExternalSource(); - auto Idx = D->getOwningModuleID(); - auto Info = Reader->getSourceDescriptor(Idx); - if (Info) - return getOrCreateModuleRef(*Info, /*SkeletonCU=*/true); - } else if (ClangModuleMap) { - // We are building a clang module or a precompiled header. - // - // TODO: When D is a CXXRecordDecl or a C++ Enum, the ODR applies - // and it wouldn't be necessary to specify the parent scope - // because the type is already unique by definition (it would look - // like the output of -fno-standalone-debug). On the other hand, - // the parent scope helps a consumer to quickly locate the object - // file where the type's definition is located, so it might be - // best to make this behavior a command line or debugger tuning - // option. - if (Module *M = D->getOwningModule()) { - // This is a (sub-)module. - auto Info = ExternalASTSource::ASTSourceDescriptor(*M); - return getOrCreateModuleRef(Info, /*SkeletonCU=*/false); - } else { - // This the precompiled header being built. - return getOrCreateModuleRef(PCHDescriptor, /*SkeletonCU=*/false); - } - } - - return nullptr; -} - -llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { - // Handle qualifiers, which recursively handles what they refer to. - if (Ty.hasLocalQualifiers()) - return CreateQualifiedType(Ty, Unit); - - // Work out details of type. - switch (Ty->getTypeClass()) { -#define TYPE(Class, Base) -#define ABSTRACT_TYPE(Class, Base) -#define NON_CANONICAL_TYPE(Class, Base) -#define DEPENDENT_TYPE(Class, Base) case Type::Class: -#include "clang/AST/TypeNodes.def" - llvm_unreachable("Dependent types cannot show up in debug information"); - - case Type::ExtVector: - case Type::Vector: - return CreateType(cast<VectorType>(Ty), Unit); - case Type::ObjCObjectPointer: - return CreateType(cast<ObjCObjectPointerType>(Ty), Unit); - case Type::ObjCObject: - return CreateType(cast<ObjCObjectType>(Ty), Unit); - case Type::ObjCTypeParam: - return CreateType(cast<ObjCTypeParamType>(Ty), Unit); - case Type::ObjCInterface: - return CreateType(cast<ObjCInterfaceType>(Ty), Unit); - case Type::Builtin: - return CreateType(cast<BuiltinType>(Ty)); - case Type::Complex: - return CreateType(cast<ComplexType>(Ty)); - case Type::Pointer: - return CreateType(cast<PointerType>(Ty), Unit); - case Type::BlockPointer: - return CreateType(cast<BlockPointerType>(Ty), Unit); - case Type::Typedef: - return CreateType(cast<TypedefType>(Ty), Unit); - case Type::Record: - return CreateType(cast<RecordType>(Ty)); - case Type::Enum: - return CreateEnumType(cast<EnumType>(Ty)); - case Type::FunctionProto: - case Type::FunctionNoProto: - return CreateType(cast<FunctionType>(Ty), Unit); - case Type::ConstantArray: - case Type::VariableArray: - case Type::IncompleteArray: - return CreateType(cast<ArrayType>(Ty), Unit); - - case Type::LValueReference: - return CreateType(cast<LValueReferenceType>(Ty), Unit); - case Type::RValueReference: - return CreateType(cast<RValueReferenceType>(Ty), Unit); - - case Type::MemberPointer: - return CreateType(cast<MemberPointerType>(Ty), Unit); - - case Type::Atomic: - return CreateType(cast<AtomicType>(Ty), Unit); - - case Type::Pipe: - return CreateType(cast<PipeType>(Ty), Unit); - - case Type::TemplateSpecialization: - return CreateType(cast<TemplateSpecializationType>(Ty), Unit); - - case Type::Auto: - case Type::Attributed: - case Type::Adjusted: - case Type::Decayed: - case Type::DeducedTemplateSpecialization: - case Type::Elaborated: - case Type::Paren: - case Type::SubstTemplateTypeParm: - case Type::TypeOfExpr: - case Type::TypeOf: - case Type::Decltype: - case Type::UnaryTransform: - case Type::PackExpansion: - break; - } - - llvm_unreachable("type should have been unwrapped!"); -} - -llvm::DICompositeType *CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty, - llvm::DIFile *Unit) { - QualType QTy(Ty, 0); - - auto *T = cast_or_null<llvm::DICompositeType>(getTypeOrNull(QTy)); - - // We may have cached a forward decl when we could have created - // a non-forward decl. Go ahead and create a non-forward decl - // now. - if (T && !T->isForwardDecl()) - return T; - - // Otherwise create the type. - llvm::DICompositeType *Res = CreateLimitedType(Ty); - - // Propagate members from the declaration to the definition - // CreateType(const RecordType*) will overwrite this with the members in the - // correct order if the full type is needed. - DBuilder.replaceArrays(Res, T ? T->getElements() : llvm::DINodeArray()); - - // And update the type cache. - TypeCache[QTy.getAsOpaquePtr()].reset(Res); - return Res; -} - -// TODO: Currently used for context chains when limiting debug info. -llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { - RecordDecl *RD = Ty->getDecl(); - - // Get overall information about the record type for the debug info. - llvm::DIFile *DefUnit = getOrCreateFile(RD->getLocation()); - unsigned Line = getLineNumber(RD->getLocation()); - StringRef RDName = getClassName(RD); - - llvm::DIScope *RDContext = getDeclContextDescriptor(RD); - - // If we ended up creating the type during the context chain construction, - // just return that. - auto *T = cast_or_null<llvm::DICompositeType>( - getTypeOrNull(CGM.getContext().getRecordType(RD))); - if (T && (!T->isForwardDecl() || !RD->getDefinition())) - return T; - - // If this is just a forward or incomplete declaration, construct an - // appropriately marked node and just return it. - const RecordDecl *D = RD->getDefinition(); - if (!D || !D->isCompleteDefinition()) - return getOrCreateRecordFwdDecl(Ty, RDContext); - - uint64_t Size = CGM.getContext().getTypeSize(Ty); - auto Align = getDeclAlignIfRequired(D, CGM.getContext()); - - SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU); - - // Explicitly record the calling convention for C++ records. - auto Flags = llvm::DINode::FlagZero; - if (auto CXXRD = dyn_cast<CXXRecordDecl>(RD)) { - if (CGM.getCXXABI().getRecordArgABI(CXXRD) == CGCXXABI::RAA_Indirect) - Flags |= llvm::DINode::FlagTypePassByReference; - else - Flags |= llvm::DINode::FlagTypePassByValue; - - // Record if a C++ record is trivial type. - if (CXXRD->isTrivial()) - Flags |= llvm::DINode::FlagTrivial; - } - - llvm::DICompositeType *RealDecl = DBuilder.createReplaceableCompositeType( - getTagForRecord(RD), RDName, RDContext, DefUnit, Line, 0, Size, Align, - Flags, Identifier); - - // Elements of composite types usually have back to the type, creating - // uniquing cycles. Distinct nodes are more efficient. - switch (RealDecl->getTag()) { - default: - llvm_unreachable("invalid composite type tag"); - - case llvm::dwarf::DW_TAG_array_type: - case llvm::dwarf::DW_TAG_enumeration_type: - // Array elements and most enumeration elements don't have back references, - // so they don't tend to be involved in uniquing cycles and there is some - // chance of merging them when linking together two modules. Only make - // them distinct if they are ODR-uniqued. - if (Identifier.empty()) - break; - LLVM_FALLTHROUGH; - - case llvm::dwarf::DW_TAG_structure_type: - case llvm::dwarf::DW_TAG_union_type: - case llvm::dwarf::DW_TAG_class_type: - // Immediately resolve to a distinct node. - RealDecl = - llvm::MDNode::replaceWithDistinct(llvm::TempDICompositeType(RealDecl)); - break; - } - - RegionMap[Ty->getDecl()].reset(RealDecl); - TypeCache[QualType(Ty, 0).getAsOpaquePtr()].reset(RealDecl); - - if (const auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD)) - DBuilder.replaceArrays(RealDecl, llvm::DINodeArray(), - CollectCXXTemplateParams(TSpecial, DefUnit)); - return RealDecl; -} - -void CGDebugInfo::CollectContainingType(const CXXRecordDecl *RD, - llvm::DICompositeType *RealDecl) { - // A class's primary base or the class itself contains the vtable. - llvm::DICompositeType *ContainingType = nullptr; - const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); - if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) { - // Seek non-virtual primary base root. - while (1) { - const ASTRecordLayout &BRL = CGM.getContext().getASTRecordLayout(PBase); - const CXXRecordDecl *PBT = BRL.getPrimaryBase(); - if (PBT && !BRL.isPrimaryBaseVirtual()) - PBase = PBT; - else - break; - } - ContainingType = cast<llvm::DICompositeType>( - getOrCreateType(QualType(PBase->getTypeForDecl(), 0), - getOrCreateFile(RD->getLocation()))); - } else if (RD->isDynamicClass()) - ContainingType = RealDecl; - - DBuilder.replaceVTableHolder(RealDecl, ContainingType); -} - -llvm::DIType *CGDebugInfo::CreateMemberType(llvm::DIFile *Unit, QualType FType, - StringRef Name, uint64_t *Offset) { - llvm::DIType *FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); - uint64_t FieldSize = CGM.getContext().getTypeSize(FType); - auto FieldAlign = getTypeAlignIfRequired(FType, CGM.getContext()); - llvm::DIType *Ty = - DBuilder.createMemberType(Unit, Name, Unit, 0, FieldSize, FieldAlign, - *Offset, llvm::DINode::FlagZero, FieldTy); - *Offset += FieldSize; - return Ty; -} - -void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit, - StringRef &Name, - StringRef &LinkageName, - llvm::DIScope *&FDContext, - llvm::DINodeArray &TParamsArray, - llvm::DINode::DIFlags &Flags) { - const auto *FD = cast<FunctionDecl>(GD.getDecl()); - Name = getFunctionName(FD); - // Use mangled name as linkage name for C/C++ functions. - if (FD->hasPrototype()) { - LinkageName = CGM.getMangledName(GD); - Flags |= llvm::DINode::FlagPrototyped; - } - // No need to replicate the linkage name if it isn't different from the - // subprogram name, no need to have it at all unless coverage is enabled or - // debug is set to more than just line tables or extra debug info is needed. - if (LinkageName == Name || (!CGM.getCodeGenOpts().EmitGcovArcs && - !CGM.getCodeGenOpts().EmitGcovNotes && - !CGM.getCodeGenOpts().DebugInfoForProfiling && - DebugKind <= codegenoptions::DebugLineTablesOnly)) - LinkageName = StringRef(); - - if (DebugKind >= codegenoptions::LimitedDebugInfo) { - if (const NamespaceDecl *NSDecl = - dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext())) - FDContext = getOrCreateNamespace(NSDecl); - else if (const RecordDecl *RDecl = - dyn_cast_or_null<RecordDecl>(FD->getDeclContext())) { - llvm::DIScope *Mod = getParentModuleOrNull(RDecl); - FDContext = getContextDescriptor(RDecl, Mod ? Mod : TheCU); - } - // Check if it is a noreturn-marked function - if (FD->isNoReturn()) - Flags |= llvm::DINode::FlagNoReturn; - // Collect template parameters. - TParamsArray = CollectFunctionTemplateParams(FD, Unit); - } -} - -void CGDebugInfo::collectVarDeclProps(const VarDecl *VD, llvm::DIFile *&Unit, - unsigned &LineNo, QualType &T, - StringRef &Name, StringRef &LinkageName, - llvm::MDTuple *&TemplateParameters, - llvm::DIScope *&VDContext) { - Unit = getOrCreateFile(VD->getLocation()); - LineNo = getLineNumber(VD->getLocation()); - - setLocation(VD->getLocation()); - - T = VD->getType(); - if (T->isIncompleteArrayType()) { - // CodeGen turns int[] into int[1] so we'll do the same here. - llvm::APInt ConstVal(32, 1); - QualType ET = CGM.getContext().getAsArrayType(T)->getElementType(); - - T = CGM.getContext().getConstantArrayType(ET, ConstVal, ArrayType::Normal, - 0); - } - - Name = VD->getName(); - if (VD->getDeclContext() && !isa<FunctionDecl>(VD->getDeclContext()) && - !isa<ObjCMethodDecl>(VD->getDeclContext())) - LinkageName = CGM.getMangledName(VD); - if (LinkageName == Name) - LinkageName = StringRef(); - - if (isa<VarTemplateSpecializationDecl>(VD)) { - llvm::DINodeArray parameterNodes = CollectVarTemplateParams(VD, &*Unit); - TemplateParameters = parameterNodes.get(); - } else { - TemplateParameters = nullptr; - } - - // Since we emit declarations (DW_AT_members) for static members, place the - // definition of those static members in the namespace they were declared in - // in the source code (the lexical decl context). - // FIXME: Generalize this for even non-member global variables where the - // declaration and definition may have different lexical decl contexts, once - // we have support for emitting declarations of (non-member) global variables. - const DeclContext *DC = VD->isStaticDataMember() ? VD->getLexicalDeclContext() - : VD->getDeclContext(); - // When a record type contains an in-line initialization of a static data - // member, and the record type is marked as __declspec(dllexport), an implicit - // definition of the member will be created in the record context. DWARF - // doesn't seem to have a nice way to describe this in a form that consumers - // are likely to understand, so fake the "normal" situation of a definition - // outside the class by putting it in the global scope. - if (DC->isRecord()) - DC = CGM.getContext().getTranslationUnitDecl(); - - llvm::DIScope *Mod = getParentModuleOrNull(VD); - VDContext = getContextDescriptor(cast<Decl>(DC), Mod ? Mod : TheCU); -} - -llvm::DISubprogram *CGDebugInfo::getFunctionFwdDeclOrStub(GlobalDecl GD, - bool Stub) { - llvm::DINodeArray TParamsArray; - StringRef Name, LinkageName; - llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; - llvm::DISubprogram::DISPFlags SPFlags = llvm::DISubprogram::SPFlagZero; - SourceLocation Loc = GD.getDecl()->getLocation(); - llvm::DIFile *Unit = getOrCreateFile(Loc); - llvm::DIScope *DContext = Unit; - unsigned Line = getLineNumber(Loc); - collectFunctionDeclProps(GD, Unit, Name, LinkageName, DContext, TParamsArray, - Flags); - auto *FD = dyn_cast<FunctionDecl>(GD.getDecl()); - - // Build function type. - SmallVector<QualType, 16> ArgTypes; - if (FD) - for (const ParmVarDecl *Parm : FD->parameters()) - ArgTypes.push_back(Parm->getType()); - CallingConv CC = FD->getType()->castAs<FunctionType>()->getCallConv(); - QualType FnType = CGM.getContext().getFunctionType( - FD->getReturnType(), ArgTypes, FunctionProtoType::ExtProtoInfo(CC)); - if (!FD->isExternallyVisible()) - SPFlags |= llvm::DISubprogram::SPFlagLocalToUnit; - if (CGM.getLangOpts().Optimize) - SPFlags |= llvm::DISubprogram::SPFlagOptimized; - - if (Stub) { - Flags |= getCallSiteRelatedAttrs(); - SPFlags |= llvm::DISubprogram::SPFlagDefinition; - return DBuilder.createFunction( - DContext, Name, LinkageName, Unit, Line, - getOrCreateFunctionType(GD.getDecl(), FnType, Unit), 0, Flags, SPFlags, - TParamsArray.get(), getFunctionDeclaration(FD)); - } - - llvm::DISubprogram *SP = DBuilder.createTempFunctionFwdDecl( - DContext, Name, LinkageName, Unit, Line, - getOrCreateFunctionType(GD.getDecl(), FnType, Unit), 0, Flags, SPFlags, - TParamsArray.get(), getFunctionDeclaration(FD)); - const FunctionDecl *CanonDecl = FD->getCanonicalDecl(); - FwdDeclReplaceMap.emplace_back(std::piecewise_construct, - std::make_tuple(CanonDecl), - std::make_tuple(SP)); - return SP; -} - -llvm::DISubprogram *CGDebugInfo::getFunctionForwardDeclaration(GlobalDecl GD) { - return getFunctionFwdDeclOrStub(GD, /* Stub = */ false); -} - -llvm::DISubprogram *CGDebugInfo::getFunctionStub(GlobalDecl GD) { - return getFunctionFwdDeclOrStub(GD, /* Stub = */ true); -} - -llvm::DIGlobalVariable * -CGDebugInfo::getGlobalVariableForwardDeclaration(const VarDecl *VD) { - QualType T; - StringRef Name, LinkageName; - SourceLocation Loc = VD->getLocation(); - llvm::DIFile *Unit = getOrCreateFile(Loc); - llvm::DIScope *DContext = Unit; - unsigned Line = getLineNumber(Loc); - llvm::MDTuple *TemplateParameters = nullptr; - - collectVarDeclProps(VD, Unit, Line, T, Name, LinkageName, TemplateParameters, - DContext); - auto Align = getDeclAlignIfRequired(VD, CGM.getContext()); - auto *GV = DBuilder.createTempGlobalVariableFwdDecl( - DContext, Name, LinkageName, Unit, Line, getOrCreateType(T, Unit), - !VD->isExternallyVisible(), nullptr, TemplateParameters, Align); - FwdDeclReplaceMap.emplace_back( - std::piecewise_construct, - std::make_tuple(cast<VarDecl>(VD->getCanonicalDecl())), - std::make_tuple(static_cast<llvm::Metadata *>(GV))); - return GV; -} - -llvm::DINode *CGDebugInfo::getDeclarationOrDefinition(const Decl *D) { - // We only need a declaration (not a definition) of the type - so use whatever - // we would otherwise do to get a type for a pointee. (forward declarations in - // limited debug info, full definitions (if the type definition is available) - // in unlimited debug info) - if (const auto *TD = dyn_cast<TypeDecl>(D)) - return getOrCreateType(CGM.getContext().getTypeDeclType(TD), - getOrCreateFile(TD->getLocation())); - auto I = DeclCache.find(D->getCanonicalDecl()); - - if (I != DeclCache.end()) { - auto N = I->second; - if (auto *GVE = dyn_cast_or_null<llvm::DIGlobalVariableExpression>(N)) - return GVE->getVariable(); - return dyn_cast_or_null<llvm::DINode>(N); - } - - // No definition for now. Emit a forward definition that might be - // merged with a potential upcoming definition. - if (const auto *FD = dyn_cast<FunctionDecl>(D)) - return getFunctionForwardDeclaration(FD); - else if (const auto *VD = dyn_cast<VarDecl>(D)) - return getGlobalVariableForwardDeclaration(VD); - - return nullptr; -} - -llvm::DISubprogram *CGDebugInfo::getFunctionDeclaration(const Decl *D) { - if (!D || DebugKind <= codegenoptions::DebugLineTablesOnly) - return nullptr; - - const auto *FD = dyn_cast<FunctionDecl>(D); - if (!FD) - return nullptr; - - // Setup context. - auto *S = getDeclContextDescriptor(D); - - auto MI = SPCache.find(FD->getCanonicalDecl()); - if (MI == SPCache.end()) { - if (const auto *MD = dyn_cast<CXXMethodDecl>(FD->getCanonicalDecl())) { - return CreateCXXMemberFunction(MD, getOrCreateFile(MD->getLocation()), - cast<llvm::DICompositeType>(S)); - } - } - if (MI != SPCache.end()) { - auto *SP = dyn_cast_or_null<llvm::DISubprogram>(MI->second); - if (SP && !SP->isDefinition()) - return SP; - } - - for (auto NextFD : FD->redecls()) { - auto MI = SPCache.find(NextFD->getCanonicalDecl()); - if (MI != SPCache.end()) { - auto *SP = dyn_cast_or_null<llvm::DISubprogram>(MI->second); - if (SP && !SP->isDefinition()) - return SP; - } - } - return nullptr; -} - -// getOrCreateFunctionType - Construct type. If it is a c++ method, include -// implicit parameter "this". -llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D, - QualType FnType, - llvm::DIFile *F) { - if (!D || DebugKind <= codegenoptions::DebugLineTablesOnly) - // Create fake but valid subroutine type. Otherwise -verify would fail, and - // subprogram DIE will miss DW_AT_decl_file and DW_AT_decl_line fields. - return DBuilder.createSubroutineType(DBuilder.getOrCreateTypeArray(None)); - - if (const auto *Method = dyn_cast<CXXMethodDecl>(D)) - return getOrCreateMethodType(Method, F); - - const auto *FTy = FnType->getAs<FunctionType>(); - CallingConv CC = FTy ? FTy->getCallConv() : CallingConv::CC_C; - - if (const auto *OMethod = dyn_cast<ObjCMethodDecl>(D)) { - // Add "self" and "_cmd" - SmallVector<llvm::Metadata *, 16> Elts; - - // First element is always return type. For 'void' functions it is NULL. - QualType ResultTy = OMethod->getReturnType(); - - // Replace the instancetype keyword with the actual type. - if (ResultTy == CGM.getContext().getObjCInstanceType()) - ResultTy = CGM.getContext().getPointerType( - QualType(OMethod->getClassInterface()->getTypeForDecl(), 0)); - - Elts.push_back(getOrCreateType(ResultTy, F)); - // "self" pointer is always first argument. - QualType SelfDeclTy; - if (auto *SelfDecl = OMethod->getSelfDecl()) - SelfDeclTy = SelfDecl->getType(); - else if (auto *FPT = dyn_cast<FunctionProtoType>(FnType)) - if (FPT->getNumParams() > 1) - SelfDeclTy = FPT->getParamType(0); - if (!SelfDeclTy.isNull()) - Elts.push_back( - CreateSelfType(SelfDeclTy, getOrCreateType(SelfDeclTy, F))); - // "_cmd" pointer is always second argument. - Elts.push_back(DBuilder.createArtificialType( - getOrCreateType(CGM.getContext().getObjCSelType(), F))); - // Get rest of the arguments. - for (const auto *PI : OMethod->parameters()) - Elts.push_back(getOrCreateType(PI->getType(), F)); - // Variadic methods need a special marker at the end of the type list. - if (OMethod->isVariadic()) - Elts.push_back(DBuilder.createUnspecifiedParameter()); - - llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); - return DBuilder.createSubroutineType(EltTypeArray, llvm::DINode::FlagZero, - getDwarfCC(CC)); - } - - // Handle variadic function types; they need an additional - // unspecified parameter. - if (const auto *FD = dyn_cast<FunctionDecl>(D)) - if (FD->isVariadic()) { - SmallVector<llvm::Metadata *, 16> EltTys; - EltTys.push_back(getOrCreateType(FD->getReturnType(), F)); - if (const auto *FPT = dyn_cast<FunctionProtoType>(FnType)) - for (QualType ParamType : FPT->param_types()) - EltTys.push_back(getOrCreateType(ParamType, F)); - EltTys.push_back(DBuilder.createUnspecifiedParameter()); - llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(EltTys); - return DBuilder.createSubroutineType(EltTypeArray, llvm::DINode::FlagZero, - getDwarfCC(CC)); - } - - return cast<llvm::DISubroutineType>(getOrCreateType(FnType, F)); -} - -void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc, - SourceLocation ScopeLoc, QualType FnType, - llvm::Function *Fn, bool CurFuncIsThunk, - CGBuilderTy &Builder) { - - StringRef Name; - StringRef LinkageName; - - FnBeginRegionCount.push_back(LexicalBlockStack.size()); - - const Decl *D = GD.getDecl(); - bool HasDecl = (D != nullptr); - - llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; - llvm::DISubprogram::DISPFlags SPFlags = llvm::DISubprogram::SPFlagZero; - llvm::DIFile *Unit = getOrCreateFile(Loc); - llvm::DIScope *FDContext = Unit; - llvm::DINodeArray TParamsArray; - if (!HasDecl) { - // Use llvm function name. - LinkageName = Fn->getName(); - } else if (const auto *FD = dyn_cast<FunctionDecl>(D)) { - // If there is a subprogram for this function available then use it. - auto FI = SPCache.find(FD->getCanonicalDecl()); - if (FI != SPCache.end()) { - auto *SP = dyn_cast_or_null<llvm::DISubprogram>(FI->second); - if (SP && SP->isDefinition()) { - LexicalBlockStack.emplace_back(SP); - RegionMap[D].reset(SP); - return; - } - } - collectFunctionDeclProps(GD, Unit, Name, LinkageName, FDContext, - TParamsArray, Flags); - } else if (const auto *OMD = dyn_cast<ObjCMethodDecl>(D)) { - Name = getObjCMethodName(OMD); - Flags |= llvm::DINode::FlagPrototyped; - } else { - // Use llvm function name. - Name = Fn->getName(); - Flags |= llvm::DINode::FlagPrototyped; - } - if (Name.startswith("\01")) - Name = Name.substr(1); - - if (!HasDecl || D->isImplicit() || D->hasAttr<ArtificialAttr>()) { - Flags |= llvm::DINode::FlagArtificial; - // Artificial functions should not silently reuse CurLoc. - CurLoc = SourceLocation(); - } - - if (CurFuncIsThunk) - Flags |= llvm::DINode::FlagThunk; - - if (Fn->hasLocalLinkage()) - SPFlags |= llvm::DISubprogram::SPFlagLocalToUnit; - if (CGM.getLangOpts().Optimize) - SPFlags |= llvm::DISubprogram::SPFlagOptimized; - - llvm::DINode::DIFlags FlagsForDef = Flags | getCallSiteRelatedAttrs(); - llvm::DISubprogram::DISPFlags SPFlagsForDef = - SPFlags | llvm::DISubprogram::SPFlagDefinition; - - unsigned LineNo = getLineNumber(Loc); - unsigned ScopeLine = getLineNumber(ScopeLoc); - - // FIXME: The function declaration we're constructing here is mostly reusing - // declarations from CXXMethodDecl and not constructing new ones for arbitrary - // FunctionDecls. When/if we fix this we can have FDContext be TheCU/null for - // all subprograms instead of the actual context since subprogram definitions - // are emitted as CU level entities by the backend. - llvm::DISubprogram *SP = DBuilder.createFunction( - FDContext, Name, LinkageName, Unit, LineNo, - getOrCreateFunctionType(D, FnType, Unit), ScopeLine, FlagsForDef, - SPFlagsForDef, TParamsArray.get(), getFunctionDeclaration(D)); - Fn->setSubprogram(SP); - // We might get here with a VarDecl in the case we're generating - // code for the initialization of globals. Do not record these decls - // as they will overwrite the actual VarDecl Decl in the cache. - if (HasDecl && isa<FunctionDecl>(D)) - DeclCache[D->getCanonicalDecl()].reset(SP); - - if (CGM.getCodeGenOpts().DwarfVersion >= 5) { - // Starting with DWARF V5 method declarations are emitted as children of - // the interface type. - if (const auto *OMD = dyn_cast_or_null<ObjCMethodDecl>(D)) { - const ObjCInterfaceDecl *ID = OMD->getClassInterface(); - QualType QTy(ID->getTypeForDecl(), 0); - auto It = TypeCache.find(QTy.getAsOpaquePtr()); - if (It != TypeCache.end()) { - llvm::DICompositeType *InterfaceDecl = - cast<llvm::DICompositeType>(It->second); - llvm::DISubprogram *FD = DBuilder.createFunction( - InterfaceDecl, Name, LinkageName, Unit, LineNo, - getOrCreateFunctionType(D, FnType, Unit), ScopeLine, Flags, SPFlags, - TParamsArray.get()); - DBuilder.finalizeSubprogram(FD); - ObjCMethodCache[ID].push_back(FD); - } - } - } - - // Push the function onto the lexical block stack. - LexicalBlockStack.emplace_back(SP); - - if (HasDecl) - RegionMap[D].reset(SP); -} - -void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, - QualType FnType) { - StringRef Name; - StringRef LinkageName; - - const Decl *D = GD.getDecl(); - if (!D) - return; - - llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; - llvm::DIFile *Unit = getOrCreateFile(Loc); - llvm::DIScope *FDContext = getDeclContextDescriptor(D); - llvm::DINodeArray TParamsArray; - if (isa<FunctionDecl>(D)) { - // If there is a DISubprogram for this function available then use it. - collectFunctionDeclProps(GD, Unit, Name, LinkageName, FDContext, - TParamsArray, Flags); - } else if (const auto *OMD = dyn_cast<ObjCMethodDecl>(D)) { - Name = getObjCMethodName(OMD); - Flags |= llvm::DINode::FlagPrototyped; - } else { - llvm_unreachable("not a function or ObjC method"); - } - if (!Name.empty() && Name[0] == '\01') - Name = Name.substr(1); - - if (D->isImplicit()) { - Flags |= llvm::DINode::FlagArtificial; - // Artificial functions without a location should not silently reuse CurLoc. - if (Loc.isInvalid()) - CurLoc = SourceLocation(); - } - unsigned LineNo = getLineNumber(Loc); - unsigned ScopeLine = 0; - llvm::DISubprogram::DISPFlags SPFlags = llvm::DISubprogram::SPFlagZero; - if (CGM.getLangOpts().Optimize) - SPFlags |= llvm::DISubprogram::SPFlagOptimized; - - DBuilder.retainType(DBuilder.createFunction( - FDContext, Name, LinkageName, Unit, LineNo, - getOrCreateFunctionType(D, FnType, Unit), ScopeLine, Flags, SPFlags, - TParamsArray.get(), getFunctionDeclaration(D))); -} - -void CGDebugInfo::EmitInlineFunctionStart(CGBuilderTy &Builder, GlobalDecl GD) { - const auto *FD = cast<FunctionDecl>(GD.getDecl()); - // If there is a subprogram for this function available then use it. - auto FI = SPCache.find(FD->getCanonicalDecl()); - llvm::DISubprogram *SP = nullptr; - if (FI != SPCache.end()) - SP = dyn_cast_or_null<llvm::DISubprogram>(FI->second); - if (!SP || !SP->isDefinition()) - SP = getFunctionStub(GD); - FnBeginRegionCount.push_back(LexicalBlockStack.size()); - LexicalBlockStack.emplace_back(SP); - setInlinedAt(Builder.getCurrentDebugLocation()); - EmitLocation(Builder, FD->getLocation()); -} - -void CGDebugInfo::EmitInlineFunctionEnd(CGBuilderTy &Builder) { - assert(CurInlinedAt && "unbalanced inline scope stack"); - EmitFunctionEnd(Builder, nullptr); - setInlinedAt(llvm::DebugLoc(CurInlinedAt).getInlinedAt()); -} - -void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) { - // Update our current location - setLocation(Loc); - - if (CurLoc.isInvalid() || CurLoc.isMacroID() || LexicalBlockStack.empty()) - return; - - llvm::MDNode *Scope = LexicalBlockStack.back(); - Builder.SetCurrentDebugLocation(llvm::DebugLoc::get( - getLineNumber(CurLoc), getColumnNumber(CurLoc), Scope, CurInlinedAt)); -} - -void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) { - llvm::MDNode *Back = nullptr; - if (!LexicalBlockStack.empty()) - Back = LexicalBlockStack.back().get(); - LexicalBlockStack.emplace_back(DBuilder.createLexicalBlock( - cast<llvm::DIScope>(Back), getOrCreateFile(CurLoc), getLineNumber(CurLoc), - getColumnNumber(CurLoc))); -} - -void CGDebugInfo::AppendAddressSpaceXDeref( - unsigned AddressSpace, SmallVectorImpl<int64_t> &Expr) const { - Optional<unsigned> DWARFAddressSpace = - CGM.getTarget().getDWARFAddressSpace(AddressSpace); - if (!DWARFAddressSpace) - return; - - Expr.push_back(llvm::dwarf::DW_OP_constu); - Expr.push_back(DWARFAddressSpace.getValue()); - Expr.push_back(llvm::dwarf::DW_OP_swap); - Expr.push_back(llvm::dwarf::DW_OP_xderef); -} - -void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder, - SourceLocation Loc) { - // Set our current location. - setLocation(Loc); - - // Emit a line table change for the current location inside the new scope. - Builder.SetCurrentDebugLocation( - llvm::DebugLoc::get(getLineNumber(Loc), getColumnNumber(Loc), - LexicalBlockStack.back(), CurInlinedAt)); - - if (DebugKind <= codegenoptions::DebugLineTablesOnly) - return; - - // Create a new lexical block and push it on the stack. - CreateLexicalBlock(Loc); -} - -void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder, - SourceLocation Loc) { - assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); - - // Provide an entry in the line table for the end of the block. - EmitLocation(Builder, Loc); - - if (DebugKind <= codegenoptions::DebugLineTablesOnly) - return; - - LexicalBlockStack.pop_back(); -} - -void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder, llvm::Function *Fn) { - assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); - unsigned RCount = FnBeginRegionCount.back(); - assert(RCount <= LexicalBlockStack.size() && "Region stack mismatch"); - - // Pop all regions for this function. - while (LexicalBlockStack.size() != RCount) { - // Provide an entry in the line table for the end of the block. - EmitLocation(Builder, CurLoc); - LexicalBlockStack.pop_back(); - } - FnBeginRegionCount.pop_back(); - - if (Fn && Fn->getSubprogram()) - DBuilder.finalizeSubprogram(Fn->getSubprogram()); -} - -CGDebugInfo::BlockByRefType -CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD, - uint64_t *XOffset) { - SmallVector<llvm::Metadata *, 5> EltTys; - QualType FType; - uint64_t FieldSize, FieldOffset; - uint32_t FieldAlign; - - llvm::DIFile *Unit = getOrCreateFile(VD->getLocation()); - QualType Type = VD->getType(); - - FieldOffset = 0; - FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); - EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset)); - EltTys.push_back(CreateMemberType(Unit, FType, "__forwarding", &FieldOffset)); - FType = CGM.getContext().IntTy; - EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset)); - EltTys.push_back(CreateMemberType(Unit, FType, "__size", &FieldOffset)); - - bool HasCopyAndDispose = CGM.getContext().BlockRequiresCopying(Type, VD); - if (HasCopyAndDispose) { - FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); - EltTys.push_back( - CreateMemberType(Unit, FType, "__copy_helper", &FieldOffset)); - EltTys.push_back( - CreateMemberType(Unit, FType, "__destroy_helper", &FieldOffset)); - } - bool HasByrefExtendedLayout; - Qualifiers::ObjCLifetime Lifetime; - if (CGM.getContext().getByrefLifetime(Type, Lifetime, - HasByrefExtendedLayout) && - HasByrefExtendedLayout) { - FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); - EltTys.push_back( - CreateMemberType(Unit, FType, "__byref_variable_layout", &FieldOffset)); - } - - CharUnits Align = CGM.getContext().getDeclAlign(VD); - if (Align > CGM.getContext().toCharUnitsFromBits( - CGM.getTarget().getPointerAlign(0))) { - CharUnits FieldOffsetInBytes = - CGM.getContext().toCharUnitsFromBits(FieldOffset); - CharUnits AlignedOffsetInBytes = FieldOffsetInBytes.alignTo(Align); - CharUnits NumPaddingBytes = AlignedOffsetInBytes - FieldOffsetInBytes; - - if (NumPaddingBytes.isPositive()) { - llvm::APInt pad(32, NumPaddingBytes.getQuantity()); - FType = CGM.getContext().getConstantArrayType(CGM.getContext().CharTy, - pad, ArrayType::Normal, 0); - EltTys.push_back(CreateMemberType(Unit, FType, "", &FieldOffset)); - } - } - - FType = Type; - llvm::DIType *WrappedTy = getOrCreateType(FType, Unit); - FieldSize = CGM.getContext().getTypeSize(FType); - FieldAlign = CGM.getContext().toBits(Align); - - *XOffset = FieldOffset; - llvm::DIType *FieldTy = DBuilder.createMemberType( - Unit, VD->getName(), Unit, 0, FieldSize, FieldAlign, FieldOffset, - llvm::DINode::FlagZero, WrappedTy); - EltTys.push_back(FieldTy); - FieldOffset += FieldSize; - - llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys); - return {DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, - llvm::DINode::FlagZero, nullptr, Elements), - WrappedTy}; -} - -llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD, - llvm::Value *Storage, - llvm::Optional<unsigned> ArgNo, - CGBuilderTy &Builder) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); - assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); - if (VD->hasAttr<NoDebugAttr>()) - return nullptr; - - bool Unwritten = - VD->isImplicit() || (isa<Decl>(VD->getDeclContext()) && - cast<Decl>(VD->getDeclContext())->isImplicit()); - llvm::DIFile *Unit = nullptr; - if (!Unwritten) - Unit = getOrCreateFile(VD->getLocation()); - llvm::DIType *Ty; - uint64_t XOffset = 0; - if (VD->hasAttr<BlocksAttr>()) - Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset).WrappedType; - else - Ty = getOrCreateType(VD->getType(), Unit); - - // If there is no debug info for this type then do not emit debug info - // for this variable. - if (!Ty) - return nullptr; - - // Get location information. - unsigned Line = 0; - unsigned Column = 0; - if (!Unwritten) { - Line = getLineNumber(VD->getLocation()); - Column = getColumnNumber(VD->getLocation()); - } - SmallVector<int64_t, 13> Expr; - llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; - if (VD->isImplicit()) - Flags |= llvm::DINode::FlagArtificial; - - auto Align = getDeclAlignIfRequired(VD, CGM.getContext()); - - unsigned AddressSpace = CGM.getContext().getTargetAddressSpace(VD->getType()); - AppendAddressSpaceXDeref(AddressSpace, Expr); - - // If this is implicit parameter of CXXThis or ObjCSelf kind, then give it an - // object pointer flag. - if (const auto *IPD = dyn_cast<ImplicitParamDecl>(VD)) { - if (IPD->getParameterKind() == ImplicitParamDecl::CXXThis || - IPD->getParameterKind() == ImplicitParamDecl::ObjCSelf) - Flags |= llvm::DINode::FlagObjectPointer; - } - - // Note: Older versions of clang used to emit byval references with an extra - // DW_OP_deref, because they referenced the IR arg directly instead of - // referencing an alloca. Newer versions of LLVM don't treat allocas - // differently from other function arguments when used in a dbg.declare. - auto *Scope = cast<llvm::DIScope>(LexicalBlockStack.back()); - StringRef Name = VD->getName(); - if (!Name.empty()) { - if (VD->hasAttr<BlocksAttr>()) { - // Here, we need an offset *into* the alloca. - CharUnits offset = CharUnits::fromQuantity(32); - Expr.push_back(llvm::dwarf::DW_OP_plus_uconst); - // offset of __forwarding field - offset = CGM.getContext().toCharUnitsFromBits( - CGM.getTarget().getPointerWidth(0)); - Expr.push_back(offset.getQuantity()); - Expr.push_back(llvm::dwarf::DW_OP_deref); - Expr.push_back(llvm::dwarf::DW_OP_plus_uconst); - // offset of x field - offset = CGM.getContext().toCharUnitsFromBits(XOffset); - Expr.push_back(offset.getQuantity()); - } - } else if (const auto *RT = dyn_cast<RecordType>(VD->getType())) { - // If VD is an anonymous union then Storage represents value for - // all union fields. - const RecordDecl *RD = RT->getDecl(); - if (RD->isUnion() && RD->isAnonymousStructOrUnion()) { - // GDB has trouble finding local variables in anonymous unions, so we emit - // artificial local variables for each of the members. - // - // FIXME: Remove this code as soon as GDB supports this. - // The debug info verifier in LLVM operates based on the assumption that a - // variable has the same size as its storage and we had to disable the - // check for artificial variables. - for (const auto *Field : RD->fields()) { - llvm::DIType *FieldTy = getOrCreateType(Field->getType(), Unit); - StringRef FieldName = Field->getName(); - - // Ignore unnamed fields. Do not ignore unnamed records. - if (FieldName.empty() && !isa<RecordType>(Field->getType())) - continue; - - // Use VarDecl's Tag, Scope and Line number. - auto FieldAlign = getDeclAlignIfRequired(Field, CGM.getContext()); - auto *D = DBuilder.createAutoVariable( - Scope, FieldName, Unit, Line, FieldTy, CGM.getLangOpts().Optimize, - Flags | llvm::DINode::FlagArtificial, FieldAlign); - - // Insert an llvm.dbg.declare into the current block. - DBuilder.insertDeclare( - Storage, D, DBuilder.createExpression(Expr), - llvm::DebugLoc::get(Line, Column, Scope, CurInlinedAt), - Builder.GetInsertBlock()); - } - } - } - - // Create the descriptor for the variable. - auto *D = ArgNo ? DBuilder.createParameterVariable( - Scope, Name, *ArgNo, Unit, Line, Ty, - CGM.getLangOpts().Optimize, Flags) - : DBuilder.createAutoVariable(Scope, Name, Unit, Line, Ty, - CGM.getLangOpts().Optimize, - Flags, Align); - - // Insert an llvm.dbg.declare into the current block. - DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr), - llvm::DebugLoc::get(Line, Column, Scope, CurInlinedAt), - Builder.GetInsertBlock()); - - return D; -} - -llvm::DILocalVariable * -CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, llvm::Value *Storage, - CGBuilderTy &Builder) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); - return EmitDeclare(VD, Storage, llvm::None, Builder); -} - -llvm::DIType *CGDebugInfo::CreateSelfType(const QualType &QualTy, - llvm::DIType *Ty) { - llvm::DIType *CachedTy = getTypeOrNull(QualTy); - if (CachedTy) - Ty = CachedTy; - return DBuilder.createObjectPointerType(Ty); -} - -void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable( - const VarDecl *VD, llvm::Value *Storage, CGBuilderTy &Builder, - const CGBlockInfo &blockInfo, llvm::Instruction *InsertPoint) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); - assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); - - if (Builder.GetInsertBlock() == nullptr) - return; - if (VD->hasAttr<NoDebugAttr>()) - return; - - bool isByRef = VD->hasAttr<BlocksAttr>(); - - uint64_t XOffset = 0; - llvm::DIFile *Unit = getOrCreateFile(VD->getLocation()); - llvm::DIType *Ty; - if (isByRef) - Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset).WrappedType; - else - Ty = getOrCreateType(VD->getType(), Unit); - - // Self is passed along as an implicit non-arg variable in a - // block. Mark it as the object pointer. - if (const auto *IPD = dyn_cast<ImplicitParamDecl>(VD)) - if (IPD->getParameterKind() == ImplicitParamDecl::ObjCSelf) - Ty = CreateSelfType(VD->getType(), Ty); - - // Get location information. - unsigned Line = getLineNumber(VD->getLocation()); - unsigned Column = getColumnNumber(VD->getLocation()); - - const llvm::DataLayout &target = CGM.getDataLayout(); - - CharUnits offset = CharUnits::fromQuantity( - target.getStructLayout(blockInfo.StructureType) - ->getElementOffset(blockInfo.getCapture(VD).getIndex())); - - SmallVector<int64_t, 9> addr; - addr.push_back(llvm::dwarf::DW_OP_deref); - addr.push_back(llvm::dwarf::DW_OP_plus_uconst); - addr.push_back(offset.getQuantity()); - if (isByRef) { - addr.push_back(llvm::dwarf::DW_OP_deref); - addr.push_back(llvm::dwarf::DW_OP_plus_uconst); - // offset of __forwarding field - offset = - CGM.getContext().toCharUnitsFromBits(target.getPointerSizeInBits(0)); - addr.push_back(offset.getQuantity()); - addr.push_back(llvm::dwarf::DW_OP_deref); - addr.push_back(llvm::dwarf::DW_OP_plus_uconst); - // offset of x field - offset = CGM.getContext().toCharUnitsFromBits(XOffset); - addr.push_back(offset.getQuantity()); - } - - // Create the descriptor for the variable. - auto Align = getDeclAlignIfRequired(VD, CGM.getContext()); - auto *D = DBuilder.createAutoVariable( - cast<llvm::DILocalScope>(LexicalBlockStack.back()), VD->getName(), Unit, - Line, Ty, false, llvm::DINode::FlagZero, Align); - - // Insert an llvm.dbg.declare into the current block. - auto DL = - llvm::DebugLoc::get(Line, Column, LexicalBlockStack.back(), CurInlinedAt); - auto *Expr = DBuilder.createExpression(addr); - if (InsertPoint) - DBuilder.insertDeclare(Storage, D, Expr, DL, InsertPoint); - else - DBuilder.insertDeclare(Storage, D, Expr, DL, Builder.GetInsertBlock()); -} - -void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI, - unsigned ArgNo, - CGBuilderTy &Builder) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); - EmitDeclare(VD, AI, ArgNo, Builder); -} - -namespace { -struct BlockLayoutChunk { - uint64_t OffsetInBits; - const BlockDecl::Capture *Capture; -}; -bool operator<(const BlockLayoutChunk &l, const BlockLayoutChunk &r) { - return l.OffsetInBits < r.OffsetInBits; -} -} // namespace - -void CGDebugInfo::collectDefaultFieldsForBlockLiteralDeclare( - const CGBlockInfo &Block, const ASTContext &Context, SourceLocation Loc, - const llvm::StructLayout &BlockLayout, llvm::DIFile *Unit, - SmallVectorImpl<llvm::Metadata *> &Fields) { - // Blocks in OpenCL have unique constraints which make the standard fields - // redundant while requiring size and align fields for enqueue_kernel. See - // initializeForBlockHeader in CGBlocks.cpp - if (CGM.getLangOpts().OpenCL) { - Fields.push_back(createFieldType("__size", Context.IntTy, Loc, AS_public, - BlockLayout.getElementOffsetInBits(0), - Unit, Unit)); - Fields.push_back(createFieldType("__align", Context.IntTy, Loc, AS_public, - BlockLayout.getElementOffsetInBits(1), - Unit, Unit)); - } else { - Fields.push_back(createFieldType("__isa", Context.VoidPtrTy, Loc, AS_public, - BlockLayout.getElementOffsetInBits(0), - Unit, Unit)); - Fields.push_back(createFieldType("__flags", Context.IntTy, Loc, AS_public, - BlockLayout.getElementOffsetInBits(1), - Unit, Unit)); - Fields.push_back( - createFieldType("__reserved", Context.IntTy, Loc, AS_public, - BlockLayout.getElementOffsetInBits(2), Unit, Unit)); - auto *FnTy = Block.getBlockExpr()->getFunctionType(); - auto FnPtrType = CGM.getContext().getPointerType(FnTy->desugar()); - Fields.push_back(createFieldType("__FuncPtr", FnPtrType, Loc, AS_public, - BlockLayout.getElementOffsetInBits(3), - Unit, Unit)); - Fields.push_back(createFieldType( - "__descriptor", - Context.getPointerType(Block.NeedsCopyDispose - ? Context.getBlockDescriptorExtendedType() - : Context.getBlockDescriptorType()), - Loc, AS_public, BlockLayout.getElementOffsetInBits(4), Unit, Unit)); - } -} - -void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, - StringRef Name, - unsigned ArgNo, - llvm::AllocaInst *Alloca, - CGBuilderTy &Builder) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); - ASTContext &C = CGM.getContext(); - const BlockDecl *blockDecl = block.getBlockDecl(); - - // Collect some general information about the block's location. - SourceLocation loc = blockDecl->getCaretLocation(); - llvm::DIFile *tunit = getOrCreateFile(loc); - unsigned line = getLineNumber(loc); - unsigned column = getColumnNumber(loc); - - // Build the debug-info type for the block literal. - getDeclContextDescriptor(blockDecl); - - const llvm::StructLayout *blockLayout = - CGM.getDataLayout().getStructLayout(block.StructureType); - - SmallVector<llvm::Metadata *, 16> fields; - collectDefaultFieldsForBlockLiteralDeclare(block, C, loc, *blockLayout, tunit, - fields); - - // We want to sort the captures by offset, not because DWARF - // requires this, but because we're paranoid about debuggers. - SmallVector<BlockLayoutChunk, 8> chunks; - - // 'this' capture. - if (blockDecl->capturesCXXThis()) { - BlockLayoutChunk chunk; - chunk.OffsetInBits = - blockLayout->getElementOffsetInBits(block.CXXThisIndex); - chunk.Capture = nullptr; - chunks.push_back(chunk); - } - - // Variable captures. - for (const auto &capture : blockDecl->captures()) { - const VarDecl *variable = capture.getVariable(); - const CGBlockInfo::Capture &captureInfo = block.getCapture(variable); - - // Ignore constant captures. - if (captureInfo.isConstant()) - continue; - - BlockLayoutChunk chunk; - chunk.OffsetInBits = - blockLayout->getElementOffsetInBits(captureInfo.getIndex()); - chunk.Capture = &capture; - chunks.push_back(chunk); - } - - // Sort by offset. - llvm::array_pod_sort(chunks.begin(), chunks.end()); - - for (const BlockLayoutChunk &Chunk : chunks) { - uint64_t offsetInBits = Chunk.OffsetInBits; - const BlockDecl::Capture *capture = Chunk.Capture; - - // If we have a null capture, this must be the C++ 'this' capture. - if (!capture) { - QualType type; - if (auto *Method = - cast_or_null<CXXMethodDecl>(blockDecl->getNonClosureContext())) - type = Method->getThisType(); - else if (auto *RDecl = dyn_cast<CXXRecordDecl>(blockDecl->getParent())) - type = QualType(RDecl->getTypeForDecl(), 0); - else - llvm_unreachable("unexpected block declcontext"); - - fields.push_back(createFieldType("this", type, loc, AS_public, - offsetInBits, tunit, tunit)); - continue; - } - - const VarDecl *variable = capture->getVariable(); - StringRef name = variable->getName(); - - llvm::DIType *fieldType; - if (capture->isByRef()) { - TypeInfo PtrInfo = C.getTypeInfo(C.VoidPtrTy); - auto Align = PtrInfo.AlignIsRequired ? PtrInfo.Align : 0; - // FIXME: This recomputes the layout of the BlockByRefWrapper. - uint64_t xoffset; - fieldType = - EmitTypeForVarWithBlocksAttr(variable, &xoffset).BlockByRefWrapper; - fieldType = DBuilder.createPointerType(fieldType, PtrInfo.Width); - fieldType = DBuilder.createMemberType(tunit, name, tunit, line, - PtrInfo.Width, Align, offsetInBits, - llvm::DINode::FlagZero, fieldType); - } else { - auto Align = getDeclAlignIfRequired(variable, CGM.getContext()); - fieldType = createFieldType(name, variable->getType(), loc, AS_public, - offsetInBits, Align, tunit, tunit); - } - fields.push_back(fieldType); - } - - SmallString<36> typeName; - llvm::raw_svector_ostream(typeName) - << "__block_literal_" << CGM.getUniqueBlockCount(); - - llvm::DINodeArray fieldsArray = DBuilder.getOrCreateArray(fields); - - llvm::DIType *type = - DBuilder.createStructType(tunit, typeName.str(), tunit, line, - CGM.getContext().toBits(block.BlockSize), 0, - llvm::DINode::FlagZero, nullptr, fieldsArray); - type = DBuilder.createPointerType(type, CGM.PointerWidthInBits); - - // Get overall information about the block. - llvm::DINode::DIFlags flags = llvm::DINode::FlagArtificial; - auto *scope = cast<llvm::DILocalScope>(LexicalBlockStack.back()); - - // Create the descriptor for the parameter. - auto *debugVar = DBuilder.createParameterVariable( - scope, Name, ArgNo, tunit, line, type, CGM.getLangOpts().Optimize, flags); - - // Insert an llvm.dbg.declare into the current block. - DBuilder.insertDeclare(Alloca, debugVar, DBuilder.createExpression(), - llvm::DebugLoc::get(line, column, scope, CurInlinedAt), - Builder.GetInsertBlock()); -} - -llvm::DIDerivedType * -CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) { - if (!D->isStaticDataMember()) - return nullptr; - - auto MI = StaticDataMemberCache.find(D->getCanonicalDecl()); - if (MI != StaticDataMemberCache.end()) { - assert(MI->second && "Static data member declaration should still exist"); - return MI->second; - } - - // If the member wasn't found in the cache, lazily construct and add it to the - // type (used when a limited form of the type is emitted). - auto DC = D->getDeclContext(); - auto *Ctxt = cast<llvm::DICompositeType>(getDeclContextDescriptor(D)); - return CreateRecordStaticField(D, Ctxt, cast<RecordDecl>(DC)); -} - -llvm::DIGlobalVariableExpression *CGDebugInfo::CollectAnonRecordDecls( - const RecordDecl *RD, llvm::DIFile *Unit, unsigned LineNo, - StringRef LinkageName, llvm::GlobalVariable *Var, llvm::DIScope *DContext) { - llvm::DIGlobalVariableExpression *GVE = nullptr; - - for (const auto *Field : RD->fields()) { - llvm::DIType *FieldTy = getOrCreateType(Field->getType(), Unit); - StringRef FieldName = Field->getName(); - - // Ignore unnamed fields, but recurse into anonymous records. - if (FieldName.empty()) { - if (const auto *RT = dyn_cast<RecordType>(Field->getType())) - GVE = CollectAnonRecordDecls(RT->getDecl(), Unit, LineNo, LinkageName, - Var, DContext); - continue; - } - // Use VarDecl's Tag, Scope and Line number. - GVE = DBuilder.createGlobalVariableExpression( - DContext, FieldName, LinkageName, Unit, LineNo, FieldTy, - Var->hasLocalLinkage()); - Var->addDebugInfo(GVE); - } - return GVE; -} - -void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, - const VarDecl *D) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); - if (D->hasAttr<NoDebugAttr>()) - return; - - // If we already created a DIGlobalVariable for this declaration, just attach - // it to the llvm::GlobalVariable. - auto Cached = DeclCache.find(D->getCanonicalDecl()); - if (Cached != DeclCache.end()) - return Var->addDebugInfo( - cast<llvm::DIGlobalVariableExpression>(Cached->second)); - - // Create global variable debug descriptor. - llvm::DIFile *Unit = nullptr; - llvm::DIScope *DContext = nullptr; - unsigned LineNo; - StringRef DeclName, LinkageName; - QualType T; - llvm::MDTuple *TemplateParameters = nullptr; - collectVarDeclProps(D, Unit, LineNo, T, DeclName, LinkageName, - TemplateParameters, DContext); - - // Attempt to store one global variable for the declaration - even if we - // emit a lot of fields. - llvm::DIGlobalVariableExpression *GVE = nullptr; - - // If this is an anonymous union then we'll want to emit a global - // variable for each member of the anonymous union so that it's possible - // to find the name of any field in the union. - if (T->isUnionType() && DeclName.empty()) { - const RecordDecl *RD = T->castAs<RecordType>()->getDecl(); - assert(RD->isAnonymousStructOrUnion() && - "unnamed non-anonymous struct or union?"); - GVE = CollectAnonRecordDecls(RD, Unit, LineNo, LinkageName, Var, DContext); - } else { - auto Align = getDeclAlignIfRequired(D, CGM.getContext()); - - SmallVector<int64_t, 4> Expr; - unsigned AddressSpace = - CGM.getContext().getTargetAddressSpace(D->getType()); - AppendAddressSpaceXDeref(AddressSpace, Expr); - - GVE = DBuilder.createGlobalVariableExpression( - DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit), - Var->hasLocalLinkage(), - Expr.empty() ? nullptr : DBuilder.createExpression(Expr), - getOrCreateStaticDataMemberDeclarationOrNull(D), TemplateParameters, - Align); - Var->addDebugInfo(GVE); - } - DeclCache[D->getCanonicalDecl()].reset(GVE); -} - -void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); - if (VD->hasAttr<NoDebugAttr>()) - return; - auto Align = getDeclAlignIfRequired(VD, CGM.getContext()); - // Create the descriptor for the variable. - llvm::DIFile *Unit = getOrCreateFile(VD->getLocation()); - StringRef Name = VD->getName(); - llvm::DIType *Ty = getOrCreateType(VD->getType(), Unit); - if (const auto *ECD = dyn_cast<EnumConstantDecl>(VD)) { - const auto *ED = cast<EnumDecl>(ECD->getDeclContext()); - assert(isa<EnumType>(ED->getTypeForDecl()) && "Enum without EnumType?"); - Ty = getOrCreateType(QualType(ED->getTypeForDecl(), 0), Unit); - } - // Do not use global variables for enums. - // - // FIXME: why not? - if (Ty->getTag() == llvm::dwarf::DW_TAG_enumeration_type) - return; - // Do not emit separate definitions for function local const/statics. - if (isa<FunctionDecl>(VD->getDeclContext())) - return; - VD = cast<ValueDecl>(VD->getCanonicalDecl()); - auto *VarD = cast<VarDecl>(VD); - if (VarD->isStaticDataMember()) { - auto *RD = cast<RecordDecl>(VarD->getDeclContext()); - getDeclContextDescriptor(VarD); - // Ensure that the type is retained even though it's otherwise unreferenced. - // - // FIXME: This is probably unnecessary, since Ty should reference RD - // through its scope. - RetainedTypes.push_back( - CGM.getContext().getRecordType(RD).getAsOpaquePtr()); - return; - } - - llvm::DIScope *DContext = getDeclContextDescriptor(VD); - - auto &GV = DeclCache[VD]; - if (GV) - return; - llvm::DIExpression *InitExpr = nullptr; - if (CGM.getContext().getTypeSize(VD->getType()) <= 64) { - // FIXME: Add a representation for integer constants wider than 64 bits. - if (Init.isInt()) - InitExpr = - DBuilder.createConstantValueExpression(Init.getInt().getExtValue()); - else if (Init.isFloat()) - InitExpr = DBuilder.createConstantValueExpression( - Init.getFloat().bitcastToAPInt().getZExtValue()); - } - - llvm::MDTuple *TemplateParameters = nullptr; - - if (isa<VarTemplateSpecializationDecl>(VD)) - if (VarD) { - llvm::DINodeArray parameterNodes = CollectVarTemplateParams(VarD, &*Unit); - TemplateParameters = parameterNodes.get(); - } - - GV.reset(DBuilder.createGlobalVariableExpression( - DContext, Name, StringRef(), Unit, getLineNumber(VD->getLocation()), Ty, - true, InitExpr, getOrCreateStaticDataMemberDeclarationOrNull(VarD), - TemplateParameters, Align)); -} - -llvm::DIScope *CGDebugInfo::getCurrentContextDescriptor(const Decl *D) { - if (!LexicalBlockStack.empty()) - return LexicalBlockStack.back(); - llvm::DIScope *Mod = getParentModuleOrNull(D); - return getContextDescriptor(D, Mod ? Mod : TheCU); -} - -void CGDebugInfo::EmitUsingDirective(const UsingDirectiveDecl &UD) { - if (CGM.getCodeGenOpts().getDebugInfo() < codegenoptions::LimitedDebugInfo) - return; - const NamespaceDecl *NSDecl = UD.getNominatedNamespace(); - if (!NSDecl->isAnonymousNamespace() || - CGM.getCodeGenOpts().DebugExplicitImport) { - auto Loc = UD.getLocation(); - DBuilder.createImportedModule( - getCurrentContextDescriptor(cast<Decl>(UD.getDeclContext())), - getOrCreateNamespace(NSDecl), getOrCreateFile(Loc), getLineNumber(Loc)); - } -} - -void CGDebugInfo::EmitUsingDecl(const UsingDecl &UD) { - if (CGM.getCodeGenOpts().getDebugInfo() < codegenoptions::LimitedDebugInfo) - return; - assert(UD.shadow_size() && - "We shouldn't be codegening an invalid UsingDecl containing no decls"); - // Emitting one decl is sufficient - debuggers can detect that this is an - // overloaded name & provide lookup for all the overloads. - const UsingShadowDecl &USD = **UD.shadow_begin(); - - // FIXME: Skip functions with undeduced auto return type for now since we - // don't currently have the plumbing for separate declarations & definitions - // of free functions and mismatched types (auto in the declaration, concrete - // return type in the definition) - if (const auto *FD = dyn_cast<FunctionDecl>(USD.getUnderlyingDecl())) - if (const auto *AT = - FD->getType()->getAs<FunctionProtoType>()->getContainedAutoType()) - if (AT->getDeducedType().isNull()) - return; - if (llvm::DINode *Target = - getDeclarationOrDefinition(USD.getUnderlyingDecl())) { - auto Loc = USD.getLocation(); - DBuilder.createImportedDeclaration( - getCurrentContextDescriptor(cast<Decl>(USD.getDeclContext())), Target, - getOrCreateFile(Loc), getLineNumber(Loc)); - } -} - -void CGDebugInfo::EmitImportDecl(const ImportDecl &ID) { - if (CGM.getCodeGenOpts().getDebuggerTuning() != llvm::DebuggerKind::LLDB) - return; - if (Module *M = ID.getImportedModule()) { - auto Info = ExternalASTSource::ASTSourceDescriptor(*M); - auto Loc = ID.getLocation(); - DBuilder.createImportedDeclaration( - getCurrentContextDescriptor(cast<Decl>(ID.getDeclContext())), - getOrCreateModuleRef(Info, DebugTypeExtRefs), getOrCreateFile(Loc), - getLineNumber(Loc)); - } -} - -llvm::DIImportedEntity * -CGDebugInfo::EmitNamespaceAlias(const NamespaceAliasDecl &NA) { - if (CGM.getCodeGenOpts().getDebugInfo() < codegenoptions::LimitedDebugInfo) - return nullptr; - auto &VH = NamespaceAliasCache[&NA]; - if (VH) - return cast<llvm::DIImportedEntity>(VH); - llvm::DIImportedEntity *R; - auto Loc = NA.getLocation(); - if (const auto *Underlying = - dyn_cast<NamespaceAliasDecl>(NA.getAliasedNamespace())) - // This could cache & dedup here rather than relying on metadata deduping. - R = DBuilder.createImportedDeclaration( - getCurrentContextDescriptor(cast<Decl>(NA.getDeclContext())), - EmitNamespaceAlias(*Underlying), getOrCreateFile(Loc), - getLineNumber(Loc), NA.getName()); - else - R = DBuilder.createImportedDeclaration( - getCurrentContextDescriptor(cast<Decl>(NA.getDeclContext())), - getOrCreateNamespace(cast<NamespaceDecl>(NA.getAliasedNamespace())), - getOrCreateFile(Loc), getLineNumber(Loc), NA.getName()); - VH.reset(R); - return R; -} - -llvm::DINamespace * -CGDebugInfo::getOrCreateNamespace(const NamespaceDecl *NSDecl) { - // Don't canonicalize the NamespaceDecl here: The DINamespace will be uniqued - // if necessary, and this way multiple declarations of the same namespace in - // different parent modules stay distinct. - auto I = NamespaceCache.find(NSDecl); - if (I != NamespaceCache.end()) - return cast<llvm::DINamespace>(I->second); - - llvm::DIScope *Context = getDeclContextDescriptor(NSDecl); - // Don't trust the context if it is a DIModule (see comment above). - llvm::DINamespace *NS = - DBuilder.createNameSpace(Context, NSDecl->getName(), NSDecl->isInline()); - NamespaceCache[NSDecl].reset(NS); - return NS; -} - -void CGDebugInfo::setDwoId(uint64_t Signature) { - assert(TheCU && "no main compile unit"); - TheCU->setDWOId(Signature); -} - -void CGDebugInfo::finalize() { - // Creating types might create further types - invalidating the current - // element and the size(), so don't cache/reference them. - for (size_t i = 0; i != ObjCInterfaceCache.size(); ++i) { - ObjCInterfaceCacheEntry E = ObjCInterfaceCache[i]; - llvm::DIType *Ty = E.Type->getDecl()->getDefinition() - ? CreateTypeDefinition(E.Type, E.Unit) - : E.Decl; - DBuilder.replaceTemporary(llvm::TempDIType(E.Decl), Ty); - } - - if (CGM.getCodeGenOpts().DwarfVersion >= 5) { - // Add methods to interface. - for (const auto &P : ObjCMethodCache) { - if (P.second.empty()) - continue; - - QualType QTy(P.first->getTypeForDecl(), 0); - auto It = TypeCache.find(QTy.getAsOpaquePtr()); - assert(It != TypeCache.end()); - - llvm::DICompositeType *InterfaceDecl = - cast<llvm::DICompositeType>(It->second); - - SmallVector<llvm::Metadata *, 16> EltTys; - auto CurrenetElts = InterfaceDecl->getElements(); - EltTys.append(CurrenetElts.begin(), CurrenetElts.end()); - for (auto &MD : P.second) - EltTys.push_back(MD); - llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys); - DBuilder.replaceArrays(InterfaceDecl, Elements); - } - } - - for (const auto &P : ReplaceMap) { - assert(P.second); - auto *Ty = cast<llvm::DIType>(P.second); - assert(Ty->isForwardDecl()); - - auto It = TypeCache.find(P.first); - assert(It != TypeCache.end()); - assert(It->second); - - DBuilder.replaceTemporary(llvm::TempDIType(Ty), - cast<llvm::DIType>(It->second)); - } - - for (const auto &P : FwdDeclReplaceMap) { - assert(P.second); - llvm::TempMDNode FwdDecl(cast<llvm::MDNode>(P.second)); - llvm::Metadata *Repl; - - auto It = DeclCache.find(P.first); - // If there has been no definition for the declaration, call RAUW - // with ourselves, that will destroy the temporary MDNode and - // replace it with a standard one, avoiding leaking memory. - if (It == DeclCache.end()) - Repl = P.second; - else - Repl = It->second; - - if (auto *GVE = dyn_cast_or_null<llvm::DIGlobalVariableExpression>(Repl)) - Repl = GVE->getVariable(); - DBuilder.replaceTemporary(std::move(FwdDecl), cast<llvm::MDNode>(Repl)); - } - - // We keep our own list of retained types, because we need to look - // up the final type in the type cache. - for (auto &RT : RetainedTypes) - if (auto MD = TypeCache[RT]) - DBuilder.retainType(cast<llvm::DIType>(MD)); - - DBuilder.finalize(); -} - -void CGDebugInfo::EmitExplicitCastType(QualType Ty) { - if (CGM.getCodeGenOpts().getDebugInfo() < codegenoptions::LimitedDebugInfo) - return; - - if (auto *DieTy = getOrCreateType(Ty, TheCU->getFile())) - // Don't ignore in case of explicit cast where it is referenced indirectly. - DBuilder.retainType(DieTy); -} - -llvm::DebugLoc CGDebugInfo::SourceLocToDebugLoc(SourceLocation Loc) { - if (LexicalBlockStack.empty()) - return llvm::DebugLoc(); - - llvm::MDNode *Scope = LexicalBlockStack.back(); - return llvm::DebugLoc::get(getLineNumber(Loc), getColumnNumber(Loc), Scope); -} - -llvm::DINode::DIFlags CGDebugInfo::getCallSiteRelatedAttrs() const { - // Call site-related attributes are only useful in optimized programs, and - // when there's a possibility of debugging backtraces. - if (!CGM.getLangOpts().Optimize || DebugKind == codegenoptions::NoDebugInfo || - DebugKind == codegenoptions::LocTrackingOnly) - return llvm::DINode::FlagZero; - - // Call site-related attributes are available in DWARF v5. Some debuggers, - // while not fully DWARF v5-compliant, may accept these attributes as if they - // were part of DWARF v4. - bool SupportsDWARFv4Ext = - CGM.getCodeGenOpts().DwarfVersion == 4 && - CGM.getCodeGenOpts().getDebuggerTuning() == llvm::DebuggerKind::LLDB; - if (!SupportsDWARFv4Ext && CGM.getCodeGenOpts().DwarfVersion < 5) - return llvm::DINode::FlagZero; - - return llvm::DINode::FlagAllCallsDescribed; -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h b/gnu/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h deleted file mode 100644 index 031e40b9dde..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h +++ /dev/null @@ -1,754 +0,0 @@ -//===--- CGDebugInfo.h - DebugInfo for LLVM CodeGen -------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This is the source-level debug info generator for llvm translation. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CGDEBUGINFO_H -#define LLVM_CLANG_LIB_CODEGEN_CGDEBUGINFO_H - -#include "CGBuilder.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExternalASTSource.h" -#include "clang/AST/Type.h" -#include "clang/AST/TypeOrdering.h" -#include "clang/Basic/CodeGenOptions.h" -#include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/Optional.h" -#include "llvm/IR/DIBuilder.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/ValueHandle.h" -#include "llvm/Support/Allocator.h" - -namespace llvm { -class MDNode; -} - -namespace clang { -class ClassTemplateSpecializationDecl; -class GlobalDecl; -class ModuleMap; -class ObjCInterfaceDecl; -class ObjCIvarDecl; -class UsingDecl; -class VarDecl; - -namespace CodeGen { -class CodeGenModule; -class CodeGenFunction; -class CGBlockInfo; - -/// This class gathers all debug information during compilation and is -/// responsible for emitting to llvm globals or pass directly to the -/// backend. -class CGDebugInfo { - friend class ApplyDebugLocation; - friend class SaveAndRestoreLocation; - CodeGenModule &CGM; - const codegenoptions::DebugInfoKind DebugKind; - bool DebugTypeExtRefs; - llvm::DIBuilder DBuilder; - llvm::DICompileUnit *TheCU = nullptr; - ModuleMap *ClangModuleMap = nullptr; - ExternalASTSource::ASTSourceDescriptor PCHDescriptor; - SourceLocation CurLoc; - llvm::MDNode *CurInlinedAt = nullptr; - llvm::DIType *VTablePtrType = nullptr; - llvm::DIType *ClassTy = nullptr; - llvm::DICompositeType *ObjTy = nullptr; - llvm::DIType *SelTy = nullptr; -#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ - llvm::DIType *SingletonId = nullptr; -#include "clang/Basic/OpenCLImageTypes.def" - llvm::DIType *OCLSamplerDITy = nullptr; - llvm::DIType *OCLEventDITy = nullptr; - llvm::DIType *OCLClkEventDITy = nullptr; - llvm::DIType *OCLQueueDITy = nullptr; - llvm::DIType *OCLNDRangeDITy = nullptr; - llvm::DIType *OCLReserveIDDITy = nullptr; -#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ - llvm::DIType *Id##Ty = nullptr; -#include "clang/Basic/OpenCLExtensionTypes.def" - - /// Cache of previously constructed Types. - llvm::DenseMap<const void *, llvm::TrackingMDRef> TypeCache; - - llvm::SmallDenseMap<llvm::StringRef, llvm::StringRef> DebugPrefixMap; - - /// Cache that maps VLA types to size expressions for that type, - /// represented by instantiated Metadata nodes. - llvm::SmallDenseMap<QualType, llvm::Metadata *> SizeExprCache; - - struct ObjCInterfaceCacheEntry { - const ObjCInterfaceType *Type; - llvm::DIType *Decl; - llvm::DIFile *Unit; - ObjCInterfaceCacheEntry(const ObjCInterfaceType *Type, llvm::DIType *Decl, - llvm::DIFile *Unit) - : Type(Type), Decl(Decl), Unit(Unit) {} - }; - - /// Cache of previously constructed interfaces which may change. - llvm::SmallVector<ObjCInterfaceCacheEntry, 32> ObjCInterfaceCache; - - /// Cache of forward declarations for methods belonging to the interface. - llvm::DenseMap<const ObjCInterfaceDecl *, std::vector<llvm::DISubprogram *>> - ObjCMethodCache; - - /// Cache of references to clang modules and precompiled headers. - llvm::DenseMap<const Module *, llvm::TrackingMDRef> ModuleCache; - - /// List of interfaces we want to keep even if orphaned. - std::vector<void *> RetainedTypes; - - /// Cache of forward declared types to RAUW at the end of compilation. - std::vector<std::pair<const TagType *, llvm::TrackingMDRef>> ReplaceMap; - - /// Cache of replaceable forward declarations (functions and - /// variables) to RAUW at the end of compilation. - std::vector<std::pair<const DeclaratorDecl *, llvm::TrackingMDRef>> - FwdDeclReplaceMap; - - /// Keep track of our current nested lexical block. - std::vector<llvm::TypedTrackingMDRef<llvm::DIScope>> LexicalBlockStack; - llvm::DenseMap<const Decl *, llvm::TrackingMDRef> RegionMap; - /// Keep track of LexicalBlockStack counter at the beginning of a - /// function. This is used to pop unbalanced regions at the end of a - /// function. - std::vector<unsigned> FnBeginRegionCount; - - /// This is a storage for names that are constructed on demand. For - /// example, C++ destructors, C++ operators etc.. - llvm::BumpPtrAllocator DebugInfoNames; - StringRef CWDName; - - llvm::DenseMap<const char *, llvm::TrackingMDRef> DIFileCache; - llvm::DenseMap<const FunctionDecl *, llvm::TrackingMDRef> SPCache; - /// Cache declarations relevant to DW_TAG_imported_declarations (C++ - /// using declarations) that aren't covered by other more specific caches. - llvm::DenseMap<const Decl *, llvm::TrackingMDRef> DeclCache; - llvm::DenseMap<const NamespaceDecl *, llvm::TrackingMDRef> NamespaceCache; - llvm::DenseMap<const NamespaceAliasDecl *, llvm::TrackingMDRef> - NamespaceAliasCache; - llvm::DenseMap<const Decl *, llvm::TypedTrackingMDRef<llvm::DIDerivedType>> - StaticDataMemberCache; - - /// Helper functions for getOrCreateType. - /// @{ - /// Currently the checksum of an interface includes the number of - /// ivars and property accessors. - llvm::DIType *CreateType(const BuiltinType *Ty); - llvm::DIType *CreateType(const ComplexType *Ty); - llvm::DIType *CreateQualifiedType(QualType Ty, llvm::DIFile *Fg); - llvm::DIType *CreateType(const TypedefType *Ty, llvm::DIFile *Fg); - llvm::DIType *CreateType(const TemplateSpecializationType *Ty, - llvm::DIFile *Fg); - llvm::DIType *CreateType(const ObjCObjectPointerType *Ty, llvm::DIFile *F); - llvm::DIType *CreateType(const PointerType *Ty, llvm::DIFile *F); - llvm::DIType *CreateType(const BlockPointerType *Ty, llvm::DIFile *F); - llvm::DIType *CreateType(const FunctionType *Ty, llvm::DIFile *F); - /// Get structure or union type. - llvm::DIType *CreateType(const RecordType *Tyg); - llvm::DIType *CreateTypeDefinition(const RecordType *Ty); - llvm::DICompositeType *CreateLimitedType(const RecordType *Ty); - void CollectContainingType(const CXXRecordDecl *RD, - llvm::DICompositeType *CT); - /// Get Objective-C interface type. - llvm::DIType *CreateType(const ObjCInterfaceType *Ty, llvm::DIFile *F); - llvm::DIType *CreateTypeDefinition(const ObjCInterfaceType *Ty, - llvm::DIFile *F); - /// Get Objective-C object type. - llvm::DIType *CreateType(const ObjCObjectType *Ty, llvm::DIFile *F); - llvm::DIType *CreateType(const ObjCTypeParamType *Ty, llvm::DIFile *Unit); - - llvm::DIType *CreateType(const VectorType *Ty, llvm::DIFile *F); - llvm::DIType *CreateType(const ArrayType *Ty, llvm::DIFile *F); - llvm::DIType *CreateType(const LValueReferenceType *Ty, llvm::DIFile *F); - llvm::DIType *CreateType(const RValueReferenceType *Ty, llvm::DIFile *Unit); - llvm::DIType *CreateType(const MemberPointerType *Ty, llvm::DIFile *F); - llvm::DIType *CreateType(const AtomicType *Ty, llvm::DIFile *F); - llvm::DIType *CreateType(const PipeType *Ty, llvm::DIFile *F); - /// Get enumeration type. - llvm::DIType *CreateEnumType(const EnumType *Ty); - llvm::DIType *CreateTypeDefinition(const EnumType *Ty); - /// Look up the completed type for a self pointer in the TypeCache and - /// create a copy of it with the ObjectPointer and Artificial flags - /// set. If the type is not cached, a new one is created. This should - /// never happen though, since creating a type for the implicit self - /// argument implies that we already parsed the interface definition - /// and the ivar declarations in the implementation. - llvm::DIType *CreateSelfType(const QualType &QualTy, llvm::DIType *Ty); - /// @} - - /// Get the type from the cache or return null type if it doesn't - /// exist. - llvm::DIType *getTypeOrNull(const QualType); - /// Return the debug type for a C++ method. - /// \arg CXXMethodDecl is of FunctionType. This function type is - /// not updated to include implicit \c this pointer. Use this routine - /// to get a method type which includes \c this pointer. - llvm::DISubroutineType *getOrCreateMethodType(const CXXMethodDecl *Method, - llvm::DIFile *F); - llvm::DISubroutineType * - getOrCreateInstanceMethodType(QualType ThisPtr, const FunctionProtoType *Func, - llvm::DIFile *Unit); - llvm::DISubroutineType * - getOrCreateFunctionType(const Decl *D, QualType FnType, llvm::DIFile *F); - /// \return debug info descriptor for vtable. - llvm::DIType *getOrCreateVTablePtrType(llvm::DIFile *F); - - /// \return namespace descriptor for the given namespace decl. - llvm::DINamespace *getOrCreateNamespace(const NamespaceDecl *N); - llvm::DIType *CreatePointerLikeType(llvm::dwarf::Tag Tag, const Type *Ty, - QualType PointeeTy, llvm::DIFile *F); - llvm::DIType *getOrCreateStructPtrType(StringRef Name, llvm::DIType *&Cache); - - /// A helper function to create a subprogram for a single member - /// function GlobalDecl. - llvm::DISubprogram *CreateCXXMemberFunction(const CXXMethodDecl *Method, - llvm::DIFile *F, - llvm::DIType *RecordTy); - - /// A helper function to collect debug info for C++ member - /// functions. This is used while creating debug info entry for a - /// Record. - void CollectCXXMemberFunctions(const CXXRecordDecl *Decl, llvm::DIFile *F, - SmallVectorImpl<llvm::Metadata *> &E, - llvm::DIType *T); - - /// A helper function to collect debug info for C++ base - /// classes. This is used while creating debug info entry for a - /// Record. - void CollectCXXBases(const CXXRecordDecl *Decl, llvm::DIFile *F, - SmallVectorImpl<llvm::Metadata *> &EltTys, - llvm::DIType *RecordTy); - - /// Helper function for CollectCXXBases. - /// Adds debug info entries for types in Bases that are not in SeenTypes. - void CollectCXXBasesAux( - const CXXRecordDecl *RD, llvm::DIFile *Unit, - SmallVectorImpl<llvm::Metadata *> &EltTys, llvm::DIType *RecordTy, - const CXXRecordDecl::base_class_const_range &Bases, - llvm::DenseSet<CanonicalDeclPtr<const CXXRecordDecl>> &SeenTypes, - llvm::DINode::DIFlags StartingFlags); - - /// A helper function to collect template parameters. - llvm::DINodeArray CollectTemplateParams(const TemplateParameterList *TPList, - ArrayRef<TemplateArgument> TAList, - llvm::DIFile *Unit); - /// A helper function to collect debug info for function template - /// parameters. - llvm::DINodeArray CollectFunctionTemplateParams(const FunctionDecl *FD, - llvm::DIFile *Unit); - - /// A helper function to collect debug info for function template - /// parameters. - llvm::DINodeArray CollectVarTemplateParams(const VarDecl *VD, - llvm::DIFile *Unit); - - /// A helper function to collect debug info for template - /// parameters. - llvm::DINodeArray - CollectCXXTemplateParams(const ClassTemplateSpecializationDecl *TS, - llvm::DIFile *F); - - llvm::DIType *createFieldType(StringRef name, QualType type, - SourceLocation loc, AccessSpecifier AS, - uint64_t offsetInBits, uint32_t AlignInBits, - llvm::DIFile *tunit, llvm::DIScope *scope, - const RecordDecl *RD = nullptr); - - llvm::DIType *createFieldType(StringRef name, QualType type, - SourceLocation loc, AccessSpecifier AS, - uint64_t offsetInBits, llvm::DIFile *tunit, - llvm::DIScope *scope, - const RecordDecl *RD = nullptr) { - return createFieldType(name, type, loc, AS, offsetInBits, 0, tunit, scope, - RD); - } - - /// Create new bit field member. - llvm::DIType *createBitFieldType(const FieldDecl *BitFieldDecl, - llvm::DIScope *RecordTy, - const RecordDecl *RD); - - /// Helpers for collecting fields of a record. - /// @{ - void CollectRecordLambdaFields(const CXXRecordDecl *CXXDecl, - SmallVectorImpl<llvm::Metadata *> &E, - llvm::DIType *RecordTy); - llvm::DIDerivedType *CreateRecordStaticField(const VarDecl *Var, - llvm::DIType *RecordTy, - const RecordDecl *RD); - void CollectRecordNormalField(const FieldDecl *Field, uint64_t OffsetInBits, - llvm::DIFile *F, - SmallVectorImpl<llvm::Metadata *> &E, - llvm::DIType *RecordTy, const RecordDecl *RD); - void CollectRecordNestedType(const TypeDecl *RD, - SmallVectorImpl<llvm::Metadata *> &E); - void CollectRecordFields(const RecordDecl *Decl, llvm::DIFile *F, - SmallVectorImpl<llvm::Metadata *> &E, - llvm::DICompositeType *RecordTy); - - /// If the C++ class has vtable info then insert appropriate debug - /// info entry in EltTys vector. - void CollectVTableInfo(const CXXRecordDecl *Decl, llvm::DIFile *F, - SmallVectorImpl<llvm::Metadata *> &EltTys, - llvm::DICompositeType *RecordTy); - /// @} - - /// Create a new lexical block node and push it on the stack. - void CreateLexicalBlock(SourceLocation Loc); - - /// If target-specific LLVM \p AddressSpace directly maps to target-specific - /// DWARF address space, appends extended dereferencing mechanism to complex - /// expression \p Expr. Otherwise, does nothing. - /// - /// Extended dereferencing mechanism is has the following format: - /// DW_OP_constu <DWARF Address Space> DW_OP_swap DW_OP_xderef - void AppendAddressSpaceXDeref(unsigned AddressSpace, - SmallVectorImpl<int64_t> &Expr) const; - - /// A helper function to collect debug info for the default elements of a - /// block. - /// - /// \returns The next available field offset after the default elements. - uint64_t collectDefaultElementTypesForBlockPointer( - const BlockPointerType *Ty, llvm::DIFile *Unit, - llvm::DIDerivedType *DescTy, unsigned LineNo, - SmallVectorImpl<llvm::Metadata *> &EltTys); - - /// A helper function to collect debug info for the default fields of a - /// block. - void collectDefaultFieldsForBlockLiteralDeclare( - const CGBlockInfo &Block, const ASTContext &Context, SourceLocation Loc, - const llvm::StructLayout &BlockLayout, llvm::DIFile *Unit, - SmallVectorImpl<llvm::Metadata *> &Fields); - -public: - CGDebugInfo(CodeGenModule &CGM); - ~CGDebugInfo(); - - void finalize(); - - /// Remap a given path with the current debug prefix map - std::string remapDIPath(StringRef) const; - - /// Register VLA size expression debug node with the qualified type. - void registerVLASizeExpression(QualType Ty, llvm::Metadata *SizeExpr) { - SizeExprCache[Ty] = SizeExpr; - } - - /// Module debugging: Support for building PCMs. - /// @{ - /// Set the main CU's DwoId field to \p Signature. - void setDwoId(uint64_t Signature); - - /// When generating debug information for a clang module or - /// precompiled header, this module map will be used to determine - /// the module of origin of each Decl. - void setModuleMap(ModuleMap &MMap) { ClangModuleMap = &MMap; } - - /// When generating debug information for a clang module or - /// precompiled header, this module map will be used to determine - /// the module of origin of each Decl. - void setPCHDescriptor(ExternalASTSource::ASTSourceDescriptor PCH) { - PCHDescriptor = PCH; - } - /// @} - - /// Update the current source location. If \arg loc is invalid it is - /// ignored. - void setLocation(SourceLocation Loc); - - /// Return the current source location. This does not necessarily correspond - /// to the IRBuilder's current DebugLoc. - SourceLocation getLocation() const { return CurLoc; } - - /// Update the current inline scope. All subsequent calls to \p EmitLocation - /// will create a location with this inlinedAt field. - void setInlinedAt(llvm::MDNode *InlinedAt) { CurInlinedAt = InlinedAt; } - - /// \return the current inline scope. - llvm::MDNode *getInlinedAt() const { return CurInlinedAt; } - - // Converts a SourceLocation to a DebugLoc - llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Loc); - - /// Emit metadata to indicate a change in line/column information in - /// the source file. If the location is invalid, the previous - /// location will be reused. - void EmitLocation(CGBuilderTy &Builder, SourceLocation Loc); - - /// Emit a call to llvm.dbg.function.start to indicate - /// start of a new function. - /// \param Loc The location of the function header. - /// \param ScopeLoc The location of the function body. - void EmitFunctionStart(GlobalDecl GD, SourceLocation Loc, - SourceLocation ScopeLoc, QualType FnType, - llvm::Function *Fn, bool CurFnIsThunk, - CGBuilderTy &Builder); - - /// Start a new scope for an inlined function. - void EmitInlineFunctionStart(CGBuilderTy &Builder, GlobalDecl GD); - /// End an inlined function scope. - void EmitInlineFunctionEnd(CGBuilderTy &Builder); - - /// Emit debug info for a function declaration. - void EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, QualType FnType); - - /// Constructs the debug code for exiting a function. - void EmitFunctionEnd(CGBuilderTy &Builder, llvm::Function *Fn); - - /// Emit metadata to indicate the beginning of a new lexical block - /// and push the block onto the stack. - void EmitLexicalBlockStart(CGBuilderTy &Builder, SourceLocation Loc); - - /// Emit metadata to indicate the end of a new lexical block and pop - /// the current block. - void EmitLexicalBlockEnd(CGBuilderTy &Builder, SourceLocation Loc); - - /// Emit call to \c llvm.dbg.declare for an automatic variable - /// declaration. - /// Returns a pointer to the DILocalVariable associated with the - /// llvm.dbg.declare, or nullptr otherwise. - llvm::DILocalVariable *EmitDeclareOfAutoVariable(const VarDecl *Decl, - llvm::Value *AI, - CGBuilderTy &Builder); - - /// Emit call to \c llvm.dbg.declare for an imported variable - /// declaration in a block. - void EmitDeclareOfBlockDeclRefVariable( - const VarDecl *variable, llvm::Value *storage, CGBuilderTy &Builder, - const CGBlockInfo &blockInfo, llvm::Instruction *InsertPoint = nullptr); - - /// Emit call to \c llvm.dbg.declare for an argument variable - /// declaration. - void EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI, - unsigned ArgNo, CGBuilderTy &Builder); - - /// Emit call to \c llvm.dbg.declare for the block-literal argument - /// to a block invocation function. - void EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, - StringRef Name, unsigned ArgNo, - llvm::AllocaInst *LocalAddr, - CGBuilderTy &Builder); - - /// Emit information about a global variable. - void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl); - - /// Emit a constant global variable's debug info. - void EmitGlobalVariable(const ValueDecl *VD, const APValue &Init); - - /// Emit C++ using directive. - void EmitUsingDirective(const UsingDirectiveDecl &UD); - - /// Emit the type explicitly casted to. - void EmitExplicitCastType(QualType Ty); - - /// Emit C++ using declaration. - void EmitUsingDecl(const UsingDecl &UD); - - /// Emit an @import declaration. - void EmitImportDecl(const ImportDecl &ID); - - /// Emit C++ namespace alias. - llvm::DIImportedEntity *EmitNamespaceAlias(const NamespaceAliasDecl &NA); - - /// Emit record type's standalone debug info. - llvm::DIType *getOrCreateRecordType(QualType Ty, SourceLocation L); - - /// Emit an Objective-C interface type standalone debug info. - llvm::DIType *getOrCreateInterfaceType(QualType Ty, SourceLocation Loc); - - /// Emit standalone debug info for a type. - llvm::DIType *getOrCreateStandaloneType(QualType Ty, SourceLocation Loc); - - void completeType(const EnumDecl *ED); - void completeType(const RecordDecl *RD); - void completeRequiredType(const RecordDecl *RD); - void completeClassData(const RecordDecl *RD); - void completeClass(const RecordDecl *RD); - - void completeTemplateDefinition(const ClassTemplateSpecializationDecl &SD); - void completeUnusedClass(const CXXRecordDecl &D); - - /// Create debug info for a macro defined by a #define directive or a macro - /// undefined by a #undef directive. - llvm::DIMacro *CreateMacro(llvm::DIMacroFile *Parent, unsigned MType, - SourceLocation LineLoc, StringRef Name, - StringRef Value); - - /// Create debug info for a file referenced by an #include directive. - llvm::DIMacroFile *CreateTempMacroFile(llvm::DIMacroFile *Parent, - SourceLocation LineLoc, - SourceLocation FileLoc); - -private: - /// Emit call to llvm.dbg.declare for a variable declaration. - /// Returns a pointer to the DILocalVariable associated with the - /// llvm.dbg.declare, or nullptr otherwise. - llvm::DILocalVariable *EmitDeclare(const VarDecl *decl, llvm::Value *AI, - llvm::Optional<unsigned> ArgNo, - CGBuilderTy &Builder); - - struct BlockByRefType { - /// The wrapper struct used inside the __block_literal struct. - llvm::DIType *BlockByRefWrapper; - /// The type as it appears in the source code. - llvm::DIType *WrappedType; - }; - - /// Build up structure info for the byref. See \a BuildByRefType. - BlockByRefType EmitTypeForVarWithBlocksAttr(const VarDecl *VD, - uint64_t *OffSet); - - /// Get context info for the DeclContext of \p Decl. - llvm::DIScope *getDeclContextDescriptor(const Decl *D); - /// Get context info for a given DeclContext \p Decl. - llvm::DIScope *getContextDescriptor(const Decl *Context, - llvm::DIScope *Default); - - llvm::DIScope *getCurrentContextDescriptor(const Decl *Decl); - - /// Create a forward decl for a RecordType in a given context. - llvm::DICompositeType *getOrCreateRecordFwdDecl(const RecordType *, - llvm::DIScope *); - - /// Return current directory name. - StringRef getCurrentDirname(); - - /// Create new compile unit. - void CreateCompileUnit(); - - /// Compute the file checksum debug info for input file ID. - Optional<llvm::DIFile::ChecksumKind> - computeChecksum(FileID FID, SmallString<32> &Checksum) const; - - /// Get the source of the given file ID. - Optional<StringRef> getSource(const SourceManager &SM, FileID FID); - - /// Convenience function to get the file debug info descriptor for the input - /// location. - llvm::DIFile *getOrCreateFile(SourceLocation Loc); - - /// Create a file debug info descriptor for a source file. - llvm::DIFile * - createFile(StringRef FileName, - Optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo, - Optional<StringRef> Source); - - /// Get the type from the cache or create a new type if necessary. - llvm::DIType *getOrCreateType(QualType Ty, llvm::DIFile *Fg); - - /// Get a reference to a clang module. If \p CreateSkeletonCU is true, - /// this also creates a split dwarf skeleton compile unit. - llvm::DIModule * - getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod, - bool CreateSkeletonCU); - - /// DebugTypeExtRefs: If \p D originated in a clang module, return it. - llvm::DIModule *getParentModuleOrNull(const Decl *D); - - /// Get the type from the cache or create a new partial type if - /// necessary. - llvm::DICompositeType *getOrCreateLimitedType(const RecordType *Ty, - llvm::DIFile *F); - - /// Create type metadata for a source language type. - llvm::DIType *CreateTypeNode(QualType Ty, llvm::DIFile *Fg); - - /// Create new member and increase Offset by FType's size. - llvm::DIType *CreateMemberType(llvm::DIFile *Unit, QualType FType, - StringRef Name, uint64_t *Offset); - - /// Retrieve the DIDescriptor, if any, for the canonical form of this - /// declaration. - llvm::DINode *getDeclarationOrDefinition(const Decl *D); - - /// \return debug info descriptor to describe method - /// declaration for the given method definition. - llvm::DISubprogram *getFunctionDeclaration(const Decl *D); - - /// \return debug info descriptor to describe in-class static data - /// member declaration for the given out-of-class definition. If D - /// is an out-of-class definition of a static data member of a - /// class, find its corresponding in-class declaration. - llvm::DIDerivedType * - getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D); - - /// Helper that either creates a forward declaration or a stub. - llvm::DISubprogram *getFunctionFwdDeclOrStub(GlobalDecl GD, bool Stub); - - /// Create a subprogram describing the forward declaration - /// represented in the given FunctionDecl wrapped in a GlobalDecl. - llvm::DISubprogram *getFunctionForwardDeclaration(GlobalDecl GD); - - /// Create a DISubprogram describing the function - /// represented in the given FunctionDecl wrapped in a GlobalDecl. - llvm::DISubprogram *getFunctionStub(GlobalDecl GD); - - /// Create a global variable describing the forward declaration - /// represented in the given VarDecl. - llvm::DIGlobalVariable * - getGlobalVariableForwardDeclaration(const VarDecl *VD); - - /// Return a global variable that represents one of the collection of global - /// variables created for an anonmyous union. - /// - /// Recursively collect all of the member fields of a global - /// anonymous decl and create static variables for them. The first - /// time this is called it needs to be on a union and then from - /// there we can have additional unnamed fields. - llvm::DIGlobalVariableExpression * - CollectAnonRecordDecls(const RecordDecl *RD, llvm::DIFile *Unit, - unsigned LineNo, StringRef LinkageName, - llvm::GlobalVariable *Var, llvm::DIScope *DContext); - - - /// Return flags which enable debug info emission for call sites, provided - /// that it is supported and enabled. - llvm::DINode::DIFlags getCallSiteRelatedAttrs() const; - - /// Get the printing policy for producing names for debug info. - PrintingPolicy getPrintingPolicy() const; - - /// Get function name for the given FunctionDecl. If the name is - /// constructed on demand (e.g., C++ destructor) then the name is - /// stored on the side. - StringRef getFunctionName(const FunctionDecl *FD); - - /// Returns the unmangled name of an Objective-C method. - /// This is the display name for the debugging info. - StringRef getObjCMethodName(const ObjCMethodDecl *FD); - - /// Return selector name. This is used for debugging - /// info. - StringRef getSelectorName(Selector S); - - /// Get class name including template argument list. - StringRef getClassName(const RecordDecl *RD); - - /// Get the vtable name for the given class. - StringRef getVTableName(const CXXRecordDecl *Decl); - - /// Get line number for the location. If location is invalid - /// then use current location. - unsigned getLineNumber(SourceLocation Loc); - - /// Get column number for the location. If location is - /// invalid then use current location. - /// \param Force Assume DebugColumnInfo option is true. - unsigned getColumnNumber(SourceLocation Loc, bool Force = false); - - /// Collect various properties of a FunctionDecl. - /// \param GD A GlobalDecl whose getDecl() must return a FunctionDecl. - void collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit, - StringRef &Name, StringRef &LinkageName, - llvm::DIScope *&FDContext, - llvm::DINodeArray &TParamsArray, - llvm::DINode::DIFlags &Flags); - - /// Collect various properties of a VarDecl. - void collectVarDeclProps(const VarDecl *VD, llvm::DIFile *&Unit, - unsigned &LineNo, QualType &T, StringRef &Name, - StringRef &LinkageName, - llvm::MDTuple *&TemplateParameters, - llvm::DIScope *&VDContext); - - /// Allocate a copy of \p A using the DebugInfoNames allocator - /// and return a reference to it. If multiple arguments are given the strings - /// are concatenated. - StringRef internString(StringRef A, StringRef B = StringRef()) { - char *Data = DebugInfoNames.Allocate<char>(A.size() + B.size()); - if (!A.empty()) - std::memcpy(Data, A.data(), A.size()); - if (!B.empty()) - std::memcpy(Data + A.size(), B.data(), B.size()); - return StringRef(Data, A.size() + B.size()); - } -}; - -/// A scoped helper to set the current debug location to the specified -/// location or preferred location of the specified Expr. -class ApplyDebugLocation { -private: - void init(SourceLocation TemporaryLocation, bool DefaultToEmpty = false); - ApplyDebugLocation(CodeGenFunction &CGF, bool DefaultToEmpty, - SourceLocation TemporaryLocation); - - llvm::DebugLoc OriginalLocation; - CodeGenFunction *CGF; - -public: - /// Set the location to the (valid) TemporaryLocation. - ApplyDebugLocation(CodeGenFunction &CGF, SourceLocation TemporaryLocation); - ApplyDebugLocation(CodeGenFunction &CGF, const Expr *E); - ApplyDebugLocation(CodeGenFunction &CGF, llvm::DebugLoc Loc); - ApplyDebugLocation(ApplyDebugLocation &&Other) : CGF(Other.CGF) { - Other.CGF = nullptr; - } - - ~ApplyDebugLocation(); - - /// Apply TemporaryLocation if it is valid. Otherwise switch - /// to an artificial debug location that has a valid scope, but no - /// line information. - /// - /// Artificial locations are useful when emitting compiler-generated - /// helper functions that have no source location associated with - /// them. The DWARF specification allows the compiler to use the - /// special line number 0 to indicate code that can not be - /// attributed to any source location. Note that passing an empty - /// SourceLocation to CGDebugInfo::setLocation() will result in the - /// last valid location being reused. - static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF) { - return ApplyDebugLocation(CGF, false, SourceLocation()); - } - /// Apply TemporaryLocation if it is valid. Otherwise switch - /// to an artificial debug location that has a valid scope, but no - /// line information. - static ApplyDebugLocation - CreateDefaultArtificial(CodeGenFunction &CGF, - SourceLocation TemporaryLocation) { - return ApplyDebugLocation(CGF, false, TemporaryLocation); - } - - /// Set the IRBuilder to not attach debug locations. Note that - /// passing an empty SourceLocation to \a CGDebugInfo::setLocation() - /// will result in the last valid location being reused. Note that - /// all instructions that do not have a location at the beginning of - /// a function are counted towards to function prologue. - static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF) { - return ApplyDebugLocation(CGF, true, SourceLocation()); - } -}; - -/// A scoped helper to set the current debug location to an inlined location. -class ApplyInlineDebugLocation { - SourceLocation SavedLocation; - CodeGenFunction *CGF; - -public: - /// Set up the CodeGenFunction's DebugInfo to produce inline locations for the - /// function \p InlinedFn. The current debug location becomes the inlined call - /// site of the inlined function. - ApplyInlineDebugLocation(CodeGenFunction &CGF, GlobalDecl InlinedFn); - /// Restore everything back to the original state. - ~ApplyInlineDebugLocation(); -}; - -} // namespace CodeGen -} // namespace clang - -#endif // LLVM_CLANG_LIB_CODEGEN_CGDEBUGINFO_H diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGDecl.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGDecl.cpp deleted file mode 100644 index 790a8df3d7e..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGDecl.cpp +++ /dev/null @@ -1,2426 +0,0 @@ -//===--- CGDecl.cpp - Emit LLVM Code for declarations ---------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code to emit Decl nodes as LLVM code. -// -//===----------------------------------------------------------------------===// - -#include "CGBlocks.h" -#include "CGCXXABI.h" -#include "CGCleanup.h" -#include "CGDebugInfo.h" -#include "CGOpenCLRuntime.h" -#include "CGOpenMPRuntime.h" -#include "CodeGenFunction.h" -#include "CodeGenModule.h" -#include "ConstantEmitter.h" -#include "TargetInfo.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/CharUnits.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclOpenMP.h" -#include "clang/Basic/CodeGenOptions.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/CodeGen/CGFunctionInfo.h" -#include "llvm/Analysis/ValueTracking.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Type.h" - -using namespace clang; -using namespace CodeGen; - -void CodeGenFunction::EmitDecl(const Decl &D) { - switch (D.getKind()) { - case Decl::BuiltinTemplate: - case Decl::TranslationUnit: - case Decl::ExternCContext: - case Decl::Namespace: - case Decl::UnresolvedUsingTypename: - case Decl::ClassTemplateSpecialization: - case Decl::ClassTemplatePartialSpecialization: - case Decl::VarTemplateSpecialization: - case Decl::VarTemplatePartialSpecialization: - case Decl::TemplateTypeParm: - case Decl::UnresolvedUsingValue: - case Decl::NonTypeTemplateParm: - case Decl::CXXDeductionGuide: - case Decl::CXXMethod: - case Decl::CXXConstructor: - case Decl::CXXDestructor: - case Decl::CXXConversion: - case Decl::Field: - case Decl::MSProperty: - case Decl::IndirectField: - case Decl::ObjCIvar: - case Decl::ObjCAtDefsField: - case Decl::ParmVar: - case Decl::ImplicitParam: - case Decl::ClassTemplate: - case Decl::VarTemplate: - case Decl::FunctionTemplate: - case Decl::TypeAliasTemplate: - case Decl::TemplateTemplateParm: - case Decl::ObjCMethod: - case Decl::ObjCCategory: - case Decl::ObjCProtocol: - case Decl::ObjCInterface: - case Decl::ObjCCategoryImpl: - case Decl::ObjCImplementation: - case Decl::ObjCProperty: - case Decl::ObjCCompatibleAlias: - case Decl::PragmaComment: - case Decl::PragmaDetectMismatch: - case Decl::AccessSpec: - case Decl::LinkageSpec: - case Decl::Export: - case Decl::ObjCPropertyImpl: - case Decl::FileScopeAsm: - case Decl::Friend: - case Decl::FriendTemplate: - case Decl::Block: - case Decl::Captured: - case Decl::ClassScopeFunctionSpecialization: - case Decl::UsingShadow: - case Decl::ConstructorUsingShadow: - case Decl::ObjCTypeParam: - case Decl::Binding: - llvm_unreachable("Declaration should not be in declstmts!"); - case Decl::Function: // void X(); - case Decl::Record: // struct/union/class X; - case Decl::Enum: // enum X; - case Decl::EnumConstant: // enum ? { X = ? } - case Decl::CXXRecord: // struct/union/class X; [C++] - case Decl::StaticAssert: // static_assert(X, ""); [C++0x] - case Decl::Label: // __label__ x; - case Decl::Import: - case Decl::OMPThreadPrivate: - case Decl::OMPCapturedExpr: - case Decl::OMPRequires: - case Decl::Empty: - // None of these decls require codegen support. - return; - - case Decl::NamespaceAlias: - if (CGDebugInfo *DI = getDebugInfo()) - DI->EmitNamespaceAlias(cast<NamespaceAliasDecl>(D)); - return; - case Decl::Using: // using X; [C++] - if (CGDebugInfo *DI = getDebugInfo()) - DI->EmitUsingDecl(cast<UsingDecl>(D)); - return; - case Decl::UsingPack: - for (auto *Using : cast<UsingPackDecl>(D).expansions()) - EmitDecl(*Using); - return; - case Decl::UsingDirective: // using namespace X; [C++] - if (CGDebugInfo *DI = getDebugInfo()) - DI->EmitUsingDirective(cast<UsingDirectiveDecl>(D)); - return; - case Decl::Var: - case Decl::Decomposition: { - const VarDecl &VD = cast<VarDecl>(D); - assert(VD.isLocalVarDecl() && - "Should not see file-scope variables inside a function!"); - EmitVarDecl(VD); - if (auto *DD = dyn_cast<DecompositionDecl>(&VD)) - for (auto *B : DD->bindings()) - if (auto *HD = B->getHoldingVar()) - EmitVarDecl(*HD); - return; - } - - case Decl::OMPDeclareReduction: - return CGM.EmitOMPDeclareReduction(cast<OMPDeclareReductionDecl>(&D), this); - - case Decl::Typedef: // typedef int X; - case Decl::TypeAlias: { // using X = int; [C++0x] - const TypedefNameDecl &TD = cast<TypedefNameDecl>(D); - QualType Ty = TD.getUnderlyingType(); - - if (Ty->isVariablyModifiedType()) - EmitVariablyModifiedType(Ty); - } - } -} - -/// EmitVarDecl - This method handles emission of any variable declaration -/// inside a function, including static vars etc. -void CodeGenFunction::EmitVarDecl(const VarDecl &D) { - if (D.hasExternalStorage()) - // Don't emit it now, allow it to be emitted lazily on its first use. - return; - - // Some function-scope variable does not have static storage but still - // needs to be emitted like a static variable, e.g. a function-scope - // variable in constant address space in OpenCL. - if (D.getStorageDuration() != SD_Automatic) { - // Static sampler variables translated to function calls. - if (D.getType()->isSamplerT()) - return; - - llvm::GlobalValue::LinkageTypes Linkage = - CGM.getLLVMLinkageVarDefinition(&D, /*isConstant=*/false); - - // FIXME: We need to force the emission/use of a guard variable for - // some variables even if we can constant-evaluate them because - // we can't guarantee every translation unit will constant-evaluate them. - - return EmitStaticVarDecl(D, Linkage); - } - - if (D.getType().getAddressSpace() == LangAS::opencl_local) - return CGM.getOpenCLRuntime().EmitWorkGroupLocalVarDecl(*this, D); - - assert(D.hasLocalStorage()); - return EmitAutoVarDecl(D); -} - -static std::string getStaticDeclName(CodeGenModule &CGM, const VarDecl &D) { - if (CGM.getLangOpts().CPlusPlus) - return CGM.getMangledName(&D).str(); - - // If this isn't C++, we don't need a mangled name, just a pretty one. - assert(!D.isExternallyVisible() && "name shouldn't matter"); - std::string ContextName; - const DeclContext *DC = D.getDeclContext(); - if (auto *CD = dyn_cast<CapturedDecl>(DC)) - DC = cast<DeclContext>(CD->getNonClosureContext()); - if (const auto *FD = dyn_cast<FunctionDecl>(DC)) - ContextName = CGM.getMangledName(FD); - else if (const auto *BD = dyn_cast<BlockDecl>(DC)) - ContextName = CGM.getBlockMangledName(GlobalDecl(), BD); - else if (const auto *OMD = dyn_cast<ObjCMethodDecl>(DC)) - ContextName = OMD->getSelector().getAsString(); - else - llvm_unreachable("Unknown context for static var decl"); - - ContextName += "." + D.getNameAsString(); - return ContextName; -} - -llvm::Constant *CodeGenModule::getOrCreateStaticVarDecl( - const VarDecl &D, llvm::GlobalValue::LinkageTypes Linkage) { - // In general, we don't always emit static var decls once before we reference - // them. It is possible to reference them before emitting the function that - // contains them, and it is possible to emit the containing function multiple - // times. - if (llvm::Constant *ExistingGV = StaticLocalDeclMap[&D]) - return ExistingGV; - - QualType Ty = D.getType(); - assert(Ty->isConstantSizeType() && "VLAs can't be static"); - - // Use the label if the variable is renamed with the asm-label extension. - std::string Name; - if (D.hasAttr<AsmLabelAttr>()) - Name = getMangledName(&D); - else - Name = getStaticDeclName(*this, D); - - llvm::Type *LTy = getTypes().ConvertTypeForMem(Ty); - LangAS AS = GetGlobalVarAddressSpace(&D); - unsigned TargetAS = getContext().getTargetAddressSpace(AS); - - // OpenCL variables in local address space and CUDA shared - // variables cannot have an initializer. - llvm::Constant *Init = nullptr; - if (Ty.getAddressSpace() == LangAS::opencl_local || - D.hasAttr<CUDASharedAttr>()) - Init = llvm::UndefValue::get(LTy); - else - Init = EmitNullConstant(Ty); - - llvm::GlobalVariable *GV = new llvm::GlobalVariable( - getModule(), LTy, Ty.isConstant(getContext()), Linkage, Init, Name, - nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS); - GV->setAlignment(getContext().getDeclAlign(&D).getQuantity()); - - if (supportsCOMDAT() && GV->isWeakForLinker()) - GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); - - if (D.getTLSKind()) - setTLSMode(GV, D); - - setGVProperties(GV, &D); - - // Make sure the result is of the correct type. - LangAS ExpectedAS = Ty.getAddressSpace(); - llvm::Constant *Addr = GV; - if (AS != ExpectedAS) { - Addr = getTargetCodeGenInfo().performAddrSpaceCast( - *this, GV, AS, ExpectedAS, - LTy->getPointerTo(getContext().getTargetAddressSpace(ExpectedAS))); - } - - setStaticLocalDeclAddress(&D, Addr); - - // Ensure that the static local gets initialized by making sure the parent - // function gets emitted eventually. - const Decl *DC = cast<Decl>(D.getDeclContext()); - - // We can't name blocks or captured statements directly, so try to emit their - // parents. - if (isa<BlockDecl>(DC) || isa<CapturedDecl>(DC)) { - DC = DC->getNonClosureContext(); - // FIXME: Ensure that global blocks get emitted. - if (!DC) - return Addr; - } - - GlobalDecl GD; - if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC)) - GD = GlobalDecl(CD, Ctor_Base); - else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC)) - GD = GlobalDecl(DD, Dtor_Base); - else if (const auto *FD = dyn_cast<FunctionDecl>(DC)) - GD = GlobalDecl(FD); - else { - // Don't do anything for Obj-C method decls or global closures. We should - // never defer them. - assert(isa<ObjCMethodDecl>(DC) && "unexpected parent code decl"); - } - if (GD.getDecl()) { - // Disable emission of the parent function for the OpenMP device codegen. - CGOpenMPRuntime::DisableAutoDeclareTargetRAII NoDeclTarget(*this); - (void)GetAddrOfGlobal(GD); - } - - return Addr; -} - -/// hasNontrivialDestruction - Determine whether a type's destruction is -/// non-trivial. If so, and the variable uses static initialization, we must -/// register its destructor to run on exit. -static bool hasNontrivialDestruction(QualType T) { - CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); - return RD && !RD->hasTrivialDestructor(); -} - -/// AddInitializerToStaticVarDecl - Add the initializer for 'D' to the -/// global variable that has already been created for it. If the initializer -/// has a different type than GV does, this may free GV and return a different -/// one. Otherwise it just returns GV. -llvm::GlobalVariable * -CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D, - llvm::GlobalVariable *GV) { - ConstantEmitter emitter(*this); - llvm::Constant *Init = emitter.tryEmitForInitializer(D); - - // If constant emission failed, then this should be a C++ static - // initializer. - if (!Init) { - if (!getLangOpts().CPlusPlus) - CGM.ErrorUnsupported(D.getInit(), "constant l-value expression"); - else if (HaveInsertPoint()) { - // Since we have a static initializer, this global variable can't - // be constant. - GV->setConstant(false); - - EmitCXXGuardedInit(D, GV, /*PerformInit*/true); - } - return GV; - } - - // The initializer may differ in type from the global. Rewrite - // the global to match the initializer. (We have to do this - // because some types, like unions, can't be completely represented - // in the LLVM type system.) - if (GV->getType()->getElementType() != Init->getType()) { - llvm::GlobalVariable *OldGV = GV; - - GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), - OldGV->isConstant(), - OldGV->getLinkage(), Init, "", - /*InsertBefore*/ OldGV, - OldGV->getThreadLocalMode(), - CGM.getContext().getTargetAddressSpace(D.getType())); - GV->setVisibility(OldGV->getVisibility()); - GV->setDSOLocal(OldGV->isDSOLocal()); - GV->setComdat(OldGV->getComdat()); - - // Steal the name of the old global - GV->takeName(OldGV); - - // Replace all uses of the old global with the new global - llvm::Constant *NewPtrForOldDecl = - llvm::ConstantExpr::getBitCast(GV, OldGV->getType()); - OldGV->replaceAllUsesWith(NewPtrForOldDecl); - - // Erase the old global, since it is no longer used. - OldGV->eraseFromParent(); - } - - GV->setConstant(CGM.isTypeConstant(D.getType(), true)); - GV->setInitializer(Init); - - emitter.finalize(GV); - - if (hasNontrivialDestruction(D.getType()) && HaveInsertPoint()) { - // We have a constant initializer, but a nontrivial destructor. We still - // need to perform a guarded "initialization" in order to register the - // destructor. - EmitCXXGuardedInit(D, GV, /*PerformInit*/false); - } - - return GV; -} - -void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D, - llvm::GlobalValue::LinkageTypes Linkage) { - // Check to see if we already have a global variable for this - // declaration. This can happen when double-emitting function - // bodies, e.g. with complete and base constructors. - llvm::Constant *addr = CGM.getOrCreateStaticVarDecl(D, Linkage); - CharUnits alignment = getContext().getDeclAlign(&D); - - // Store into LocalDeclMap before generating initializer to handle - // circular references. - setAddrOfLocalVar(&D, Address(addr, alignment)); - - // We can't have a VLA here, but we can have a pointer to a VLA, - // even though that doesn't really make any sense. - // Make sure to evaluate VLA bounds now so that we have them for later. - if (D.getType()->isVariablyModifiedType()) - EmitVariablyModifiedType(D.getType()); - - // Save the type in case adding the initializer forces a type change. - llvm::Type *expectedType = addr->getType(); - - llvm::GlobalVariable *var = - cast<llvm::GlobalVariable>(addr->stripPointerCasts()); - - // CUDA's local and local static __shared__ variables should not - // have any non-empty initializers. This is ensured by Sema. - // Whatever initializer such variable may have when it gets here is - // a no-op and should not be emitted. - bool isCudaSharedVar = getLangOpts().CUDA && getLangOpts().CUDAIsDevice && - D.hasAttr<CUDASharedAttr>(); - // If this value has an initializer, emit it. - if (D.getInit() && !isCudaSharedVar) - var = AddInitializerToStaticVarDecl(D, var); - - var->setAlignment(alignment.getQuantity()); - - if (D.hasAttr<AnnotateAttr>()) - CGM.AddGlobalAnnotations(&D, var); - - if (auto *SA = D.getAttr<PragmaClangBSSSectionAttr>()) - var->addAttribute("bss-section", SA->getName()); - if (auto *SA = D.getAttr<PragmaClangDataSectionAttr>()) - var->addAttribute("data-section", SA->getName()); - if (auto *SA = D.getAttr<PragmaClangRodataSectionAttr>()) - var->addAttribute("rodata-section", SA->getName()); - - if (const SectionAttr *SA = D.getAttr<SectionAttr>()) - var->setSection(SA->getName()); - - if (D.hasAttr<UsedAttr>()) - CGM.addUsedGlobal(var); - - // We may have to cast the constant because of the initializer - // mismatch above. - // - // FIXME: It is really dangerous to store this in the map; if anyone - // RAUW's the GV uses of this constant will be invalid. - llvm::Constant *castedAddr = - llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(var, expectedType); - if (var != castedAddr) - LocalDeclMap.find(&D)->second = Address(castedAddr, alignment); - CGM.setStaticLocalDeclAddress(&D, castedAddr); - - CGM.getSanitizerMetadata()->reportGlobalToASan(var, D); - - // Emit global variable debug descriptor for static vars. - CGDebugInfo *DI = getDebugInfo(); - if (DI && - CGM.getCodeGenOpts().getDebugInfo() >= codegenoptions::LimitedDebugInfo) { - DI->setLocation(D.getLocation()); - DI->EmitGlobalVariable(var, &D); - } -} - -namespace { - struct DestroyObject final : EHScopeStack::Cleanup { - DestroyObject(Address addr, QualType type, - CodeGenFunction::Destroyer *destroyer, - bool useEHCleanupForArray) - : addr(addr), type(type), destroyer(destroyer), - useEHCleanupForArray(useEHCleanupForArray) {} - - Address addr; - QualType type; - CodeGenFunction::Destroyer *destroyer; - bool useEHCleanupForArray; - - void Emit(CodeGenFunction &CGF, Flags flags) override { - // Don't use an EH cleanup recursively from an EH cleanup. - bool useEHCleanupForArray = - flags.isForNormalCleanup() && this->useEHCleanupForArray; - - CGF.emitDestroy(addr, type, destroyer, useEHCleanupForArray); - } - }; - - template <class Derived> - struct DestroyNRVOVariable : EHScopeStack::Cleanup { - DestroyNRVOVariable(Address addr, llvm::Value *NRVOFlag) - : NRVOFlag(NRVOFlag), Loc(addr) {} - - llvm::Value *NRVOFlag; - Address Loc; - - void Emit(CodeGenFunction &CGF, Flags flags) override { - // Along the exceptions path we always execute the dtor. - bool NRVO = flags.isForNormalCleanup() && NRVOFlag; - - llvm::BasicBlock *SkipDtorBB = nullptr; - if (NRVO) { - // If we exited via NRVO, we skip the destructor call. - llvm::BasicBlock *RunDtorBB = CGF.createBasicBlock("nrvo.unused"); - SkipDtorBB = CGF.createBasicBlock("nrvo.skipdtor"); - llvm::Value *DidNRVO = - CGF.Builder.CreateFlagLoad(NRVOFlag, "nrvo.val"); - CGF.Builder.CreateCondBr(DidNRVO, SkipDtorBB, RunDtorBB); - CGF.EmitBlock(RunDtorBB); - } - - static_cast<Derived *>(this)->emitDestructorCall(CGF); - - if (NRVO) CGF.EmitBlock(SkipDtorBB); - } - - virtual ~DestroyNRVOVariable() = default; - }; - - struct DestroyNRVOVariableCXX final - : DestroyNRVOVariable<DestroyNRVOVariableCXX> { - DestroyNRVOVariableCXX(Address addr, const CXXDestructorDecl *Dtor, - llvm::Value *NRVOFlag) - : DestroyNRVOVariable<DestroyNRVOVariableCXX>(addr, NRVOFlag), - Dtor(Dtor) {} - - const CXXDestructorDecl *Dtor; - - void emitDestructorCall(CodeGenFunction &CGF) { - CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, - /*ForVirtualBase=*/false, - /*Delegating=*/false, Loc); - } - }; - - struct DestroyNRVOVariableC final - : DestroyNRVOVariable<DestroyNRVOVariableC> { - DestroyNRVOVariableC(Address addr, llvm::Value *NRVOFlag, QualType Ty) - : DestroyNRVOVariable<DestroyNRVOVariableC>(addr, NRVOFlag), Ty(Ty) {} - - QualType Ty; - - void emitDestructorCall(CodeGenFunction &CGF) { - CGF.destroyNonTrivialCStruct(CGF, Loc, Ty); - } - }; - - struct CallStackRestore final : EHScopeStack::Cleanup { - Address Stack; - CallStackRestore(Address Stack) : Stack(Stack) {} - void Emit(CodeGenFunction &CGF, Flags flags) override { - llvm::Value *V = CGF.Builder.CreateLoad(Stack); - llvm::Value *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::stackrestore); - CGF.Builder.CreateCall(F, V); - } - }; - - struct ExtendGCLifetime final : EHScopeStack::Cleanup { - const VarDecl &Var; - ExtendGCLifetime(const VarDecl *var) : Var(*var) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - // Compute the address of the local variable, in case it's a - // byref or something. - DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(&Var), false, - Var.getType(), VK_LValue, SourceLocation()); - llvm::Value *value = CGF.EmitLoadOfScalar(CGF.EmitDeclRefLValue(&DRE), - SourceLocation()); - CGF.EmitExtendGCLifetime(value); - } - }; - - struct CallCleanupFunction final : EHScopeStack::Cleanup { - llvm::Constant *CleanupFn; - const CGFunctionInfo &FnInfo; - const VarDecl &Var; - - CallCleanupFunction(llvm::Constant *CleanupFn, const CGFunctionInfo *Info, - const VarDecl *Var) - : CleanupFn(CleanupFn), FnInfo(*Info), Var(*Var) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(&Var), false, - Var.getType(), VK_LValue, SourceLocation()); - // Compute the address of the local variable, in case it's a byref - // or something. - llvm::Value *Addr = CGF.EmitDeclRefLValue(&DRE).getPointer(); - - // In some cases, the type of the function argument will be different from - // the type of the pointer. An example of this is - // void f(void* arg); - // __attribute__((cleanup(f))) void *g; - // - // To fix this we insert a bitcast here. - QualType ArgTy = FnInfo.arg_begin()->type; - llvm::Value *Arg = - CGF.Builder.CreateBitCast(Addr, CGF.ConvertType(ArgTy)); - - CallArgList Args; - Args.add(RValue::get(Arg), - CGF.getContext().getPointerType(Var.getType())); - auto Callee = CGCallee::forDirect(CleanupFn); - CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args); - } - }; -} // end anonymous namespace - -/// EmitAutoVarWithLifetime - Does the setup required for an automatic -/// variable with lifetime. -static void EmitAutoVarWithLifetime(CodeGenFunction &CGF, const VarDecl &var, - Address addr, - Qualifiers::ObjCLifetime lifetime) { - switch (lifetime) { - case Qualifiers::OCL_None: - llvm_unreachable("present but none"); - - case Qualifiers::OCL_ExplicitNone: - // nothing to do - break; - - case Qualifiers::OCL_Strong: { - CodeGenFunction::Destroyer *destroyer = - (var.hasAttr<ObjCPreciseLifetimeAttr>() - ? CodeGenFunction::destroyARCStrongPrecise - : CodeGenFunction::destroyARCStrongImprecise); - - CleanupKind cleanupKind = CGF.getARCCleanupKind(); - CGF.pushDestroy(cleanupKind, addr, var.getType(), destroyer, - cleanupKind & EHCleanup); - break; - } - case Qualifiers::OCL_Autoreleasing: - // nothing to do - break; - - case Qualifiers::OCL_Weak: - // __weak objects always get EH cleanups; otherwise, exceptions - // could cause really nasty crashes instead of mere leaks. - CGF.pushDestroy(NormalAndEHCleanup, addr, var.getType(), - CodeGenFunction::destroyARCWeak, - /*useEHCleanup*/ true); - break; - } -} - -static bool isAccessedBy(const VarDecl &var, const Stmt *s) { - if (const Expr *e = dyn_cast<Expr>(s)) { - // Skip the most common kinds of expressions that make - // hierarchy-walking expensive. - s = e = e->IgnoreParenCasts(); - - if (const DeclRefExpr *ref = dyn_cast<DeclRefExpr>(e)) - return (ref->getDecl() == &var); - if (const BlockExpr *be = dyn_cast<BlockExpr>(e)) { - const BlockDecl *block = be->getBlockDecl(); - for (const auto &I : block->captures()) { - if (I.getVariable() == &var) - return true; - } - } - } - - for (const Stmt *SubStmt : s->children()) - // SubStmt might be null; as in missing decl or conditional of an if-stmt. - if (SubStmt && isAccessedBy(var, SubStmt)) - return true; - - return false; -} - -static bool isAccessedBy(const ValueDecl *decl, const Expr *e) { - if (!decl) return false; - if (!isa<VarDecl>(decl)) return false; - const VarDecl *var = cast<VarDecl>(decl); - return isAccessedBy(*var, e); -} - -static bool tryEmitARCCopyWeakInit(CodeGenFunction &CGF, - const LValue &destLV, const Expr *init) { - bool needsCast = false; - - while (auto castExpr = dyn_cast<CastExpr>(init->IgnoreParens())) { - switch (castExpr->getCastKind()) { - // Look through casts that don't require representation changes. - case CK_NoOp: - case CK_BitCast: - case CK_BlockPointerToObjCPointerCast: - needsCast = true; - break; - - // If we find an l-value to r-value cast from a __weak variable, - // emit this operation as a copy or move. - case CK_LValueToRValue: { - const Expr *srcExpr = castExpr->getSubExpr(); - if (srcExpr->getType().getObjCLifetime() != Qualifiers::OCL_Weak) - return false; - - // Emit the source l-value. - LValue srcLV = CGF.EmitLValue(srcExpr); - - // Handle a formal type change to avoid asserting. - auto srcAddr = srcLV.getAddress(); - if (needsCast) { - srcAddr = CGF.Builder.CreateElementBitCast(srcAddr, - destLV.getAddress().getElementType()); - } - - // If it was an l-value, use objc_copyWeak. - if (srcExpr->getValueKind() == VK_LValue) { - CGF.EmitARCCopyWeak(destLV.getAddress(), srcAddr); - } else { - assert(srcExpr->getValueKind() == VK_XValue); - CGF.EmitARCMoveWeak(destLV.getAddress(), srcAddr); - } - return true; - } - - // Stop at anything else. - default: - return false; - } - - init = castExpr->getSubExpr(); - } - return false; -} - -static void drillIntoBlockVariable(CodeGenFunction &CGF, - LValue &lvalue, - const VarDecl *var) { - lvalue.setAddress(CGF.emitBlockByrefAddress(lvalue.getAddress(), var)); -} - -void CodeGenFunction::EmitNullabilityCheck(LValue LHS, llvm::Value *RHS, - SourceLocation Loc) { - if (!SanOpts.has(SanitizerKind::NullabilityAssign)) - return; - - auto Nullability = LHS.getType()->getNullability(getContext()); - if (!Nullability || *Nullability != NullabilityKind::NonNull) - return; - - // Check if the right hand side of the assignment is nonnull, if the left - // hand side must be nonnull. - SanitizerScope SanScope(this); - llvm::Value *IsNotNull = Builder.CreateIsNotNull(RHS); - llvm::Constant *StaticData[] = { - EmitCheckSourceLocation(Loc), EmitCheckTypeDescriptor(LHS.getType()), - llvm::ConstantInt::get(Int8Ty, 0), // The LogAlignment info is unused. - llvm::ConstantInt::get(Int8Ty, TCK_NonnullAssign)}; - EmitCheck({{IsNotNull, SanitizerKind::NullabilityAssign}}, - SanitizerHandler::TypeMismatch, StaticData, RHS); -} - -void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D, - LValue lvalue, bool capturedByInit) { - Qualifiers::ObjCLifetime lifetime = lvalue.getObjCLifetime(); - if (!lifetime) { - llvm::Value *value = EmitScalarExpr(init); - if (capturedByInit) - drillIntoBlockVariable(*this, lvalue, cast<VarDecl>(D)); - EmitNullabilityCheck(lvalue, value, init->getExprLoc()); - EmitStoreThroughLValue(RValue::get(value), lvalue, true); - return; - } - - if (const CXXDefaultInitExpr *DIE = dyn_cast<CXXDefaultInitExpr>(init)) - init = DIE->getExpr(); - - // If we're emitting a value with lifetime, we have to do the - // initialization *before* we leave the cleanup scopes. - if (const FullExpr *fe = dyn_cast<FullExpr>(init)) { - enterFullExpression(fe); - init = fe->getSubExpr(); - } - CodeGenFunction::RunCleanupsScope Scope(*this); - - // We have to maintain the illusion that the variable is - // zero-initialized. If the variable might be accessed in its - // initializer, zero-initialize before running the initializer, then - // actually perform the initialization with an assign. - bool accessedByInit = false; - if (lifetime != Qualifiers::OCL_ExplicitNone) - accessedByInit = (capturedByInit || isAccessedBy(D, init)); - if (accessedByInit) { - LValue tempLV = lvalue; - // Drill down to the __block object if necessary. - if (capturedByInit) { - // We can use a simple GEP for this because it can't have been - // moved yet. - tempLV.setAddress(emitBlockByrefAddress(tempLV.getAddress(), - cast<VarDecl>(D), - /*follow*/ false)); - } - - auto ty = cast<llvm::PointerType>(tempLV.getAddress().getElementType()); - llvm::Value *zero = CGM.getNullPointer(ty, tempLV.getType()); - - // If __weak, we want to use a barrier under certain conditions. - if (lifetime == Qualifiers::OCL_Weak) - EmitARCInitWeak(tempLV.getAddress(), zero); - - // Otherwise just do a simple store. - else - EmitStoreOfScalar(zero, tempLV, /* isInitialization */ true); - } - - // Emit the initializer. - llvm::Value *value = nullptr; - - switch (lifetime) { - case Qualifiers::OCL_None: - llvm_unreachable("present but none"); - - case Qualifiers::OCL_Strong: { - if (!D || !isa<VarDecl>(D) || !cast<VarDecl>(D)->isARCPseudoStrong()) { - value = EmitARCRetainScalarExpr(init); - break; - } - // If D is pseudo-strong, treat it like __unsafe_unretained here. This means - // that we omit the retain, and causes non-autoreleased return values to be - // immediately released. - LLVM_FALLTHROUGH; - } - - case Qualifiers::OCL_ExplicitNone: - value = EmitARCUnsafeUnretainedScalarExpr(init); - break; - - case Qualifiers::OCL_Weak: { - // If it's not accessed by the initializer, try to emit the - // initialization with a copy or move. - if (!accessedByInit && tryEmitARCCopyWeakInit(*this, lvalue, init)) { - return; - } - - // No way to optimize a producing initializer into this. It's not - // worth optimizing for, because the value will immediately - // disappear in the common case. - value = EmitScalarExpr(init); - - if (capturedByInit) drillIntoBlockVariable(*this, lvalue, cast<VarDecl>(D)); - if (accessedByInit) - EmitARCStoreWeak(lvalue.getAddress(), value, /*ignored*/ true); - else - EmitARCInitWeak(lvalue.getAddress(), value); - return; - } - - case Qualifiers::OCL_Autoreleasing: - value = EmitARCRetainAutoreleaseScalarExpr(init); - break; - } - - if (capturedByInit) drillIntoBlockVariable(*this, lvalue, cast<VarDecl>(D)); - - EmitNullabilityCheck(lvalue, value, init->getExprLoc()); - - // If the variable might have been accessed by its initializer, we - // might have to initialize with a barrier. We have to do this for - // both __weak and __strong, but __weak got filtered out above. - if (accessedByInit && lifetime == Qualifiers::OCL_Strong) { - llvm::Value *oldValue = EmitLoadOfScalar(lvalue, init->getExprLoc()); - EmitStoreOfScalar(value, lvalue, /* isInitialization */ true); - EmitARCRelease(oldValue, ARCImpreciseLifetime); - return; - } - - EmitStoreOfScalar(value, lvalue, /* isInitialization */ true); -} - -/// Decide whether we can emit the non-zero parts of the specified initializer -/// with equal or fewer than NumStores scalar stores. -static bool canEmitInitWithFewStoresAfterBZero(llvm::Constant *Init, - unsigned &NumStores) { - // Zero and Undef never requires any extra stores. - if (isa<llvm::ConstantAggregateZero>(Init) || - isa<llvm::ConstantPointerNull>(Init) || - isa<llvm::UndefValue>(Init)) - return true; - if (isa<llvm::ConstantInt>(Init) || isa<llvm::ConstantFP>(Init) || - isa<llvm::ConstantVector>(Init) || isa<llvm::BlockAddress>(Init) || - isa<llvm::ConstantExpr>(Init)) - return Init->isNullValue() || NumStores--; - - // See if we can emit each element. - if (isa<llvm::ConstantArray>(Init) || isa<llvm::ConstantStruct>(Init)) { - for (unsigned i = 0, e = Init->getNumOperands(); i != e; ++i) { - llvm::Constant *Elt = cast<llvm::Constant>(Init->getOperand(i)); - if (!canEmitInitWithFewStoresAfterBZero(Elt, NumStores)) - return false; - } - return true; - } - - if (llvm::ConstantDataSequential *CDS = - dyn_cast<llvm::ConstantDataSequential>(Init)) { - for (unsigned i = 0, e = CDS->getNumElements(); i != e; ++i) { - llvm::Constant *Elt = CDS->getElementAsConstant(i); - if (!canEmitInitWithFewStoresAfterBZero(Elt, NumStores)) - return false; - } - return true; - } - - // Anything else is hard and scary. - return false; -} - -/// For inits that canEmitInitWithFewStoresAfterBZero returned true for, emit -/// the scalar stores that would be required. -static void emitStoresForInitAfterBZero(CodeGenModule &CGM, - llvm::Constant *Init, Address Loc, - bool isVolatile, CGBuilderTy &Builder) { - assert(!Init->isNullValue() && !isa<llvm::UndefValue>(Init) && - "called emitStoresForInitAfterBZero for zero or undef value."); - - if (isa<llvm::ConstantInt>(Init) || isa<llvm::ConstantFP>(Init) || - isa<llvm::ConstantVector>(Init) || isa<llvm::BlockAddress>(Init) || - isa<llvm::ConstantExpr>(Init)) { - Builder.CreateStore(Init, Loc, isVolatile); - return; - } - - if (llvm::ConstantDataSequential *CDS = - dyn_cast<llvm::ConstantDataSequential>(Init)) { - for (unsigned i = 0, e = CDS->getNumElements(); i != e; ++i) { - llvm::Constant *Elt = CDS->getElementAsConstant(i); - - // If necessary, get a pointer to the element and emit it. - if (!Elt->isNullValue() && !isa<llvm::UndefValue>(Elt)) - emitStoresForInitAfterBZero( - CGM, Elt, - Builder.CreateConstInBoundsGEP2_32(Loc, 0, i, CGM.getDataLayout()), - isVolatile, Builder); - } - return; - } - - assert((isa<llvm::ConstantStruct>(Init) || isa<llvm::ConstantArray>(Init)) && - "Unknown value type!"); - - for (unsigned i = 0, e = Init->getNumOperands(); i != e; ++i) { - llvm::Constant *Elt = cast<llvm::Constant>(Init->getOperand(i)); - - // If necessary, get a pointer to the element and emit it. - if (!Elt->isNullValue() && !isa<llvm::UndefValue>(Elt)) - emitStoresForInitAfterBZero( - CGM, Elt, - Builder.CreateConstInBoundsGEP2_32(Loc, 0, i, CGM.getDataLayout()), - isVolatile, Builder); - } -} - -/// Decide whether we should use bzero plus some stores to initialize a local -/// variable instead of using a memcpy from a constant global. It is beneficial -/// to use bzero if the global is all zeros, or mostly zeros and large. -static bool shouldUseBZeroPlusStoresToInitialize(llvm::Constant *Init, - uint64_t GlobalSize) { - // If a global is all zeros, always use a bzero. - if (isa<llvm::ConstantAggregateZero>(Init)) return true; - - // If a non-zero global is <= 32 bytes, always use a memcpy. If it is large, - // do it if it will require 6 or fewer scalar stores. - // TODO: Should budget depends on the size? Avoiding a large global warrants - // plopping in more stores. - unsigned StoreBudget = 6; - uint64_t SizeLimit = 32; - - return GlobalSize > SizeLimit && - canEmitInitWithFewStoresAfterBZero(Init, StoreBudget); -} - -/// Decide whether we should use memset to initialize a local variable instead -/// of using a memcpy from a constant global. Assumes we've already decided to -/// not user bzero. -/// FIXME We could be more clever, as we are for bzero above, and generate -/// memset followed by stores. It's unclear that's worth the effort. -static llvm::Value *shouldUseMemSetToInitialize(llvm::Constant *Init, - uint64_t GlobalSize) { - uint64_t SizeLimit = 32; - if (GlobalSize <= SizeLimit) - return nullptr; - return llvm::isBytewiseValue(Init); -} - -static llvm::Constant *patternFor(CodeGenModule &CGM, llvm::Type *Ty) { - // The following value is a guaranteed unmappable pointer value and has a - // repeated byte-pattern which makes it easier to synthesize. We use it for - // pointers as well as integers so that aggregates are likely to be - // initialized with this repeated value. - constexpr uint64_t LargeValue = 0xAAAAAAAAAAAAAAAAull; - // For 32-bit platforms it's a bit trickier because, across systems, only the - // zero page can reasonably be expected to be unmapped, and even then we need - // a very low address. We use a smaller value, and that value sadly doesn't - // have a repeated byte-pattern. We don't use it for integers. - constexpr uint32_t SmallValue = 0x000000AA; - // Floating-point values are initialized as NaNs because they propagate. Using - // a repeated byte pattern means that it will be easier to initialize - // all-floating-point aggregates and arrays with memset. Further, aggregates - // which mix integral and a few floats might also initialize with memset - // followed by a handful of stores for the floats. Using fairly unique NaNs - // also means they'll be easier to distinguish in a crash. - constexpr bool NegativeNaN = true; - constexpr uint64_t NaNPayload = 0xFFFFFFFFFFFFFFFFull; - if (Ty->isIntOrIntVectorTy()) { - unsigned BitWidth = cast<llvm::IntegerType>( - Ty->isVectorTy() ? Ty->getVectorElementType() : Ty) - ->getBitWidth(); - if (BitWidth <= 64) - return llvm::ConstantInt::get(Ty, LargeValue); - return llvm::ConstantInt::get( - Ty, llvm::APInt::getSplat(BitWidth, llvm::APInt(64, LargeValue))); - } - if (Ty->isPtrOrPtrVectorTy()) { - auto *PtrTy = cast<llvm::PointerType>( - Ty->isVectorTy() ? Ty->getVectorElementType() : Ty); - unsigned PtrWidth = CGM.getContext().getTargetInfo().getPointerWidth( - PtrTy->getAddressSpace()); - llvm::Type *IntTy = llvm::IntegerType::get(CGM.getLLVMContext(), PtrWidth); - uint64_t IntValue; - switch (PtrWidth) { - default: - llvm_unreachable("pattern initialization of unsupported pointer width"); - case 64: - IntValue = LargeValue; - break; - case 32: - IntValue = SmallValue; - break; - } - auto *Int = llvm::ConstantInt::get(IntTy, IntValue); - return llvm::ConstantExpr::getIntToPtr(Int, PtrTy); - } - if (Ty->isFPOrFPVectorTy()) { - unsigned BitWidth = llvm::APFloat::semanticsSizeInBits( - (Ty->isVectorTy() ? Ty->getVectorElementType() : Ty) - ->getFltSemantics()); - llvm::APInt Payload(64, NaNPayload); - if (BitWidth >= 64) - Payload = llvm::APInt::getSplat(BitWidth, Payload); - return llvm::ConstantFP::getQNaN(Ty, NegativeNaN, &Payload); - } - if (Ty->isArrayTy()) { - // Note: this doesn't touch tail padding (at the end of an object, before - // the next array object). It is instead handled by replaceUndef. - auto *ArrTy = cast<llvm::ArrayType>(Ty); - llvm::SmallVector<llvm::Constant *, 8> Element( - ArrTy->getNumElements(), patternFor(CGM, ArrTy->getElementType())); - return llvm::ConstantArray::get(ArrTy, Element); - } - - // Note: this doesn't touch struct padding. It will initialize as much union - // padding as is required for the largest type in the union. Padding is - // instead handled by replaceUndef. Stores to structs with volatile members - // don't have a volatile qualifier when initialized according to C++. This is - // fine because stack-based volatiles don't really have volatile semantics - // anyways, and the initialization shouldn't be observable. - auto *StructTy = cast<llvm::StructType>(Ty); - llvm::SmallVector<llvm::Constant *, 8> Struct(StructTy->getNumElements()); - for (unsigned El = 0; El != Struct.size(); ++El) - Struct[El] = patternFor(CGM, StructTy->getElementType(El)); - return llvm::ConstantStruct::get(StructTy, Struct); -} - -static Address createUnnamedGlobalFrom(CodeGenModule &CGM, const VarDecl &D, - CGBuilderTy &Builder, - llvm::Constant *Constant, - CharUnits Align) { - auto FunctionName = [&](const DeclContext *DC) -> std::string { - if (const auto *FD = dyn_cast<FunctionDecl>(DC)) { - if (const auto *CC = dyn_cast<CXXConstructorDecl>(FD)) - return CC->getNameAsString(); - if (const auto *CD = dyn_cast<CXXDestructorDecl>(FD)) - return CD->getNameAsString(); - return CGM.getMangledName(FD); - } else if (const auto *OM = dyn_cast<ObjCMethodDecl>(DC)) { - return OM->getNameAsString(); - } else if (isa<BlockDecl>(DC)) { - return "<block>"; - } else if (isa<CapturedDecl>(DC)) { - return "<captured>"; - } else { - llvm::llvm_unreachable_internal("expected a function or method"); - } - }; - - auto *Ty = Constant->getType(); - bool isConstant = true; - llvm::GlobalVariable *InsertBefore = nullptr; - unsigned AS = CGM.getContext().getTargetAddressSpace( - CGM.getStringLiteralAddressSpace()); - llvm::GlobalVariable *GV = new llvm::GlobalVariable( - CGM.getModule(), Ty, isConstant, llvm::GlobalValue::PrivateLinkage, - Constant, - "__const." + FunctionName(D.getParentFunctionOrMethod()) + "." + - D.getName(), - InsertBefore, llvm::GlobalValue::NotThreadLocal, AS); - GV->setAlignment(Align.getQuantity()); - GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - - Address SrcPtr = Address(GV, Align); - llvm::Type *BP = llvm::PointerType::getInt8PtrTy(CGM.getLLVMContext(), AS); - if (SrcPtr.getType() != BP) - SrcPtr = Builder.CreateBitCast(SrcPtr, BP); - return SrcPtr; -} - -static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D, - Address Loc, bool isVolatile, - CGBuilderTy &Builder, - llvm::Constant *constant) { - auto *Ty = constant->getType(); - bool isScalar = Ty->isIntOrIntVectorTy() || Ty->isPtrOrPtrVectorTy() || - Ty->isFPOrFPVectorTy(); - if (isScalar) { - Builder.CreateStore(constant, Loc, isVolatile); - return; - } - - auto *Int8Ty = llvm::IntegerType::getInt8Ty(CGM.getLLVMContext()); - auto *IntPtrTy = CGM.getDataLayout().getIntPtrType(CGM.getLLVMContext()); - - // If the initializer is all or mostly the same, codegen with bzero / memset - // then do a few stores afterward. - uint64_t ConstantSize = CGM.getDataLayout().getTypeAllocSize(Ty); - auto *SizeVal = llvm::ConstantInt::get(IntPtrTy, ConstantSize); - if (shouldUseBZeroPlusStoresToInitialize(constant, ConstantSize)) { - Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal, - isVolatile); - - bool valueAlreadyCorrect = - constant->isNullValue() || isa<llvm::UndefValue>(constant); - if (!valueAlreadyCorrect) { - Loc = Builder.CreateBitCast(Loc, Ty->getPointerTo(Loc.getAddressSpace())); - emitStoresForInitAfterBZero(CGM, constant, Loc, isVolatile, Builder); - } - return; - } - - llvm::Value *Pattern = shouldUseMemSetToInitialize(constant, ConstantSize); - if (Pattern) { - uint64_t Value = 0x00; - if (!isa<llvm::UndefValue>(Pattern)) { - const llvm::APInt &AP = cast<llvm::ConstantInt>(Pattern)->getValue(); - assert(AP.getBitWidth() <= 8); - Value = AP.getLimitedValue(); - } - Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, Value), SizeVal, - isVolatile); - return; - } - - Builder.CreateMemCpy( - Loc, - createUnnamedGlobalFrom(CGM, D, Builder, constant, Loc.getAlignment()), - SizeVal, isVolatile); -} - -static void emitStoresForZeroInit(CodeGenModule &CGM, const VarDecl &D, - Address Loc, bool isVolatile, - CGBuilderTy &Builder) { - llvm::Type *ElTy = Loc.getElementType(); - llvm::Constant *constant = llvm::Constant::getNullValue(ElTy); - emitStoresForConstant(CGM, D, Loc, isVolatile, Builder, constant); -} - -static void emitStoresForPatternInit(CodeGenModule &CGM, const VarDecl &D, - Address Loc, bool isVolatile, - CGBuilderTy &Builder) { - llvm::Type *ElTy = Loc.getElementType(); - llvm::Constant *constant = patternFor(CGM, ElTy); - assert(!isa<llvm::UndefValue>(constant)); - emitStoresForConstant(CGM, D, Loc, isVolatile, Builder, constant); -} - -static bool containsUndef(llvm::Constant *constant) { - auto *Ty = constant->getType(); - if (isa<llvm::UndefValue>(constant)) - return true; - if (Ty->isStructTy() || Ty->isArrayTy() || Ty->isVectorTy()) - for (llvm::Use &Op : constant->operands()) - if (containsUndef(cast<llvm::Constant>(Op))) - return true; - return false; -} - -static llvm::Constant *replaceUndef(llvm::Constant *constant) { - // FIXME: when doing pattern initialization, replace undef with 0xAA instead. - // FIXME: also replace padding between values by creating a new struct type - // which has no padding. - auto *Ty = constant->getType(); - if (isa<llvm::UndefValue>(constant)) - return llvm::Constant::getNullValue(Ty); - if (!(Ty->isStructTy() || Ty->isArrayTy() || Ty->isVectorTy())) - return constant; - if (!containsUndef(constant)) - return constant; - llvm::SmallVector<llvm::Constant *, 8> Values(constant->getNumOperands()); - for (unsigned Op = 0, NumOp = constant->getNumOperands(); Op != NumOp; ++Op) { - auto *OpValue = cast<llvm::Constant>(constant->getOperand(Op)); - Values[Op] = replaceUndef(OpValue); - } - if (Ty->isStructTy()) - return llvm::ConstantStruct::get(cast<llvm::StructType>(Ty), Values); - if (Ty->isArrayTy()) - return llvm::ConstantArray::get(cast<llvm::ArrayType>(Ty), Values); - assert(Ty->isVectorTy()); - return llvm::ConstantVector::get(Values); -} - -/// EmitAutoVarDecl - Emit code and set up an entry in LocalDeclMap for a -/// variable declaration with auto, register, or no storage class specifier. -/// These turn into simple stack objects, or GlobalValues depending on target. -void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D) { - AutoVarEmission emission = EmitAutoVarAlloca(D); - EmitAutoVarInit(emission); - EmitAutoVarCleanups(emission); -} - -/// Emit a lifetime.begin marker if some criteria are satisfied. -/// \return a pointer to the temporary size Value if a marker was emitted, null -/// otherwise -llvm::Value *CodeGenFunction::EmitLifetimeStart(uint64_t Size, - llvm::Value *Addr) { - if (!ShouldEmitLifetimeMarkers) - return nullptr; - - assert(Addr->getType()->getPointerAddressSpace() == - CGM.getDataLayout().getAllocaAddrSpace() && - "Pointer should be in alloca address space"); - llvm::Value *SizeV = llvm::ConstantInt::get(Int64Ty, Size); - Addr = Builder.CreateBitCast(Addr, AllocaInt8PtrTy); - llvm::CallInst *C = - Builder.CreateCall(CGM.getLLVMLifetimeStartFn(), {SizeV, Addr}); - C->setDoesNotThrow(); - return SizeV; -} - -void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) { - assert(Addr->getType()->getPointerAddressSpace() == - CGM.getDataLayout().getAllocaAddrSpace() && - "Pointer should be in alloca address space"); - Addr = Builder.CreateBitCast(Addr, AllocaInt8PtrTy); - llvm::CallInst *C = - Builder.CreateCall(CGM.getLLVMLifetimeEndFn(), {Size, Addr}); - C->setDoesNotThrow(); -} - -void CodeGenFunction::EmitAndRegisterVariableArrayDimensions( - CGDebugInfo *DI, const VarDecl &D, bool EmitDebugInfo) { - // For each dimension stores its QualType and corresponding - // size-expression Value. - SmallVector<CodeGenFunction::VlaSizePair, 4> Dimensions; - SmallVector<IdentifierInfo *, 4> VLAExprNames; - - // Break down the array into individual dimensions. - QualType Type1D = D.getType(); - while (getContext().getAsVariableArrayType(Type1D)) { - auto VlaSize = getVLAElements1D(Type1D); - if (auto *C = dyn_cast<llvm::ConstantInt>(VlaSize.NumElts)) - Dimensions.emplace_back(C, Type1D.getUnqualifiedType()); - else { - // Generate a locally unique name for the size expression. - Twine Name = Twine("__vla_expr") + Twine(VLAExprCounter++); - SmallString<12> Buffer; - StringRef NameRef = Name.toStringRef(Buffer); - auto &Ident = getContext().Idents.getOwn(NameRef); - VLAExprNames.push_back(&Ident); - auto SizeExprAddr = - CreateDefaultAlignTempAlloca(VlaSize.NumElts->getType(), NameRef); - Builder.CreateStore(VlaSize.NumElts, SizeExprAddr); - Dimensions.emplace_back(SizeExprAddr.getPointer(), - Type1D.getUnqualifiedType()); - } - Type1D = VlaSize.Type; - } - - if (!EmitDebugInfo) - return; - - // Register each dimension's size-expression with a DILocalVariable, - // so that it can be used by CGDebugInfo when instantiating a DISubrange - // to describe this array. - unsigned NameIdx = 0; - for (auto &VlaSize : Dimensions) { - llvm::Metadata *MD; - if (auto *C = dyn_cast<llvm::ConstantInt>(VlaSize.NumElts)) - MD = llvm::ConstantAsMetadata::get(C); - else { - // Create an artificial VarDecl to generate debug info for. - IdentifierInfo *NameIdent = VLAExprNames[NameIdx++]; - auto VlaExprTy = VlaSize.NumElts->getType()->getPointerElementType(); - auto QT = getContext().getIntTypeForBitwidth( - VlaExprTy->getScalarSizeInBits(), false); - auto *ArtificialDecl = VarDecl::Create( - getContext(), const_cast<DeclContext *>(D.getDeclContext()), - D.getLocation(), D.getLocation(), NameIdent, QT, - getContext().CreateTypeSourceInfo(QT), SC_Auto); - ArtificialDecl->setImplicit(); - - MD = DI->EmitDeclareOfAutoVariable(ArtificialDecl, VlaSize.NumElts, - Builder); - } - assert(MD && "No Size expression debug node created"); - DI->registerVLASizeExpression(VlaSize.Type, MD); - } -} - -/// EmitAutoVarAlloca - Emit the alloca and debug information for a -/// local variable. Does not emit initialization or destruction. -CodeGenFunction::AutoVarEmission -CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { - QualType Ty = D.getType(); - assert( - Ty.getAddressSpace() == LangAS::Default || - (Ty.getAddressSpace() == LangAS::opencl_private && getLangOpts().OpenCL)); - - AutoVarEmission emission(D); - - bool isEscapingByRef = D.isEscapingByref(); - emission.IsEscapingByRef = isEscapingByRef; - - CharUnits alignment = getContext().getDeclAlign(&D); - - // If the type is variably-modified, emit all the VLA sizes for it. - if (Ty->isVariablyModifiedType()) - EmitVariablyModifiedType(Ty); - - auto *DI = getDebugInfo(); - bool EmitDebugInfo = DI && CGM.getCodeGenOpts().getDebugInfo() >= - codegenoptions::LimitedDebugInfo; - - Address address = Address::invalid(); - Address AllocaAddr = Address::invalid(); - if (Ty->isConstantSizeType()) { - bool NRVO = getLangOpts().ElideConstructors && - D.isNRVOVariable(); - - // If this value is an array or struct with a statically determinable - // constant initializer, there are optimizations we can do. - // - // TODO: We should constant-evaluate the initializer of any variable, - // as long as it is initialized by a constant expression. Currently, - // isConstantInitializer produces wrong answers for structs with - // reference or bitfield members, and a few other cases, and checking - // for POD-ness protects us from some of these. - if (D.getInit() && (Ty->isArrayType() || Ty->isRecordType()) && - (D.isConstexpr() || - ((Ty.isPODType(getContext()) || - getContext().getBaseElementType(Ty)->isObjCObjectPointerType()) && - D.getInit()->isConstantInitializer(getContext(), false)))) { - - // If the variable's a const type, and it's neither an NRVO - // candidate nor a __block variable and has no mutable members, - // emit it as a global instead. - // Exception is if a variable is located in non-constant address space - // in OpenCL. - if ((!getLangOpts().OpenCL || - Ty.getAddressSpace() == LangAS::opencl_constant) && - (CGM.getCodeGenOpts().MergeAllConstants && !NRVO && - !isEscapingByRef && CGM.isTypeConstant(Ty, true))) { - EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage); - - // Signal this condition to later callbacks. - emission.Addr = Address::invalid(); - assert(emission.wasEmittedAsGlobal()); - return emission; - } - - // Otherwise, tell the initialization code that we're in this case. - emission.IsConstantAggregate = true; - } - - // A normal fixed sized variable becomes an alloca in the entry block, - // unless: - // - it's an NRVO variable. - // - we are compiling OpenMP and it's an OpenMP local variable. - - Address OpenMPLocalAddr = - getLangOpts().OpenMP - ? CGM.getOpenMPRuntime().getAddressOfLocalVariable(*this, &D) - : Address::invalid(); - if (getLangOpts().OpenMP && OpenMPLocalAddr.isValid()) { - address = OpenMPLocalAddr; - } else if (NRVO) { - // The named return value optimization: allocate this variable in the - // return slot, so that we can elide the copy when returning this - // variable (C++0x [class.copy]p34). - address = ReturnValue; - - if (const RecordType *RecordTy = Ty->getAs<RecordType>()) { - const auto *RD = RecordTy->getDecl(); - const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD); - if ((CXXRD && !CXXRD->hasTrivialDestructor()) || - RD->isNonTrivialToPrimitiveDestroy()) { - // Create a flag that is used to indicate when the NRVO was applied - // to this variable. Set it to zero to indicate that NRVO was not - // applied. - llvm::Value *Zero = Builder.getFalse(); - Address NRVOFlag = - CreateTempAlloca(Zero->getType(), CharUnits::One(), "nrvo"); - EnsureInsertPoint(); - Builder.CreateStore(Zero, NRVOFlag); - - // Record the NRVO flag for this variable. - NRVOFlags[&D] = NRVOFlag.getPointer(); - emission.NRVOFlag = NRVOFlag.getPointer(); - } - } - } else { - CharUnits allocaAlignment; - llvm::Type *allocaTy; - if (isEscapingByRef) { - auto &byrefInfo = getBlockByrefInfo(&D); - allocaTy = byrefInfo.Type; - allocaAlignment = byrefInfo.ByrefAlignment; - } else { - allocaTy = ConvertTypeForMem(Ty); - allocaAlignment = alignment; - } - - // Create the alloca. Note that we set the name separately from - // building the instruction so that it's there even in no-asserts - // builds. - address = CreateTempAlloca(allocaTy, allocaAlignment, D.getName(), - /*ArraySize=*/nullptr, &AllocaAddr); - - // Don't emit lifetime markers for MSVC catch parameters. The lifetime of - // the catch parameter starts in the catchpad instruction, and we can't - // insert code in those basic blocks. - bool IsMSCatchParam = - D.isExceptionVariable() && getTarget().getCXXABI().isMicrosoft(); - - // Emit a lifetime intrinsic if meaningful. There's no point in doing this - // if we don't have a valid insertion point (?). - if (HaveInsertPoint() && !IsMSCatchParam) { - // If there's a jump into the lifetime of this variable, its lifetime - // gets broken up into several regions in IR, which requires more work - // to handle correctly. For now, just omit the intrinsics; this is a - // rare case, and it's better to just be conservatively correct. - // PR28267. - // - // We have to do this in all language modes if there's a jump past the - // declaration. We also have to do it in C if there's a jump to an - // earlier point in the current block because non-VLA lifetimes begin as - // soon as the containing block is entered, not when its variables - // actually come into scope; suppressing the lifetime annotations - // completely in this case is unnecessarily pessimistic, but again, this - // is rare. - if (!Bypasses.IsBypassed(&D) && - !(!getLangOpts().CPlusPlus && hasLabelBeenSeenInCurrentScope())) { - uint64_t size = CGM.getDataLayout().getTypeAllocSize(allocaTy); - emission.SizeForLifetimeMarkers = - EmitLifetimeStart(size, AllocaAddr.getPointer()); - } - } else { - assert(!emission.useLifetimeMarkers()); - } - } - } else { - EnsureInsertPoint(); - - if (!DidCallStackSave) { - // Save the stack. - Address Stack = - CreateTempAlloca(Int8PtrTy, getPointerAlign(), "saved_stack"); - - llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stacksave); - llvm::Value *V = Builder.CreateCall(F); - Builder.CreateStore(V, Stack); - - DidCallStackSave = true; - - // Push a cleanup block and restore the stack there. - // FIXME: in general circumstances, this should be an EH cleanup. - pushStackRestore(NormalCleanup, Stack); - } - - auto VlaSize = getVLASize(Ty); - llvm::Type *llvmTy = ConvertTypeForMem(VlaSize.Type); - - // Allocate memory for the array. - address = CreateTempAlloca(llvmTy, alignment, "vla", VlaSize.NumElts, - &AllocaAddr); - - // If we have debug info enabled, properly describe the VLA dimensions for - // this type by registering the vla size expression for each of the - // dimensions. - EmitAndRegisterVariableArrayDimensions(DI, D, EmitDebugInfo); - } - - setAddrOfLocalVar(&D, address); - emission.Addr = address; - emission.AllocaAddr = AllocaAddr; - - // Emit debug info for local var declaration. - if (EmitDebugInfo && HaveInsertPoint()) { - DI->setLocation(D.getLocation()); - (void)DI->EmitDeclareOfAutoVariable(&D, address.getPointer(), Builder); - } - - if (D.hasAttr<AnnotateAttr>()) - EmitVarAnnotations(&D, address.getPointer()); - - // Make sure we call @llvm.lifetime.end. - if (emission.useLifetimeMarkers()) - EHStack.pushCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, - emission.getOriginalAllocatedAddress(), - emission.getSizeForLifetimeMarkers()); - - return emission; -} - -static bool isCapturedBy(const VarDecl &, const Expr *); - -/// Determines whether the given __block variable is potentially -/// captured by the given statement. -static bool isCapturedBy(const VarDecl &Var, const Stmt *S) { - if (const Expr *E = dyn_cast<Expr>(S)) - return isCapturedBy(Var, E); - for (const Stmt *SubStmt : S->children()) - if (isCapturedBy(Var, SubStmt)) - return true; - return false; -} - -/// Determines whether the given __block variable is potentially -/// captured by the given expression. -static bool isCapturedBy(const VarDecl &Var, const Expr *E) { - // Skip the most common kinds of expressions that make - // hierarchy-walking expensive. - E = E->IgnoreParenCasts(); - - if (const BlockExpr *BE = dyn_cast<BlockExpr>(E)) { - const BlockDecl *Block = BE->getBlockDecl(); - for (const auto &I : Block->captures()) { - if (I.getVariable() == &Var) - return true; - } - - // No need to walk into the subexpressions. - return false; - } - - if (const StmtExpr *SE = dyn_cast<StmtExpr>(E)) { - const CompoundStmt *CS = SE->getSubStmt(); - for (const auto *BI : CS->body()) - if (const auto *BIE = dyn_cast<Expr>(BI)) { - if (isCapturedBy(Var, BIE)) - return true; - } - else if (const auto *DS = dyn_cast<DeclStmt>(BI)) { - // special case declarations - for (const auto *I : DS->decls()) { - if (const auto *VD = dyn_cast<VarDecl>((I))) { - const Expr *Init = VD->getInit(); - if (Init && isCapturedBy(Var, Init)) - return true; - } - } - } - else - // FIXME. Make safe assumption assuming arbitrary statements cause capturing. - // Later, provide code to poke into statements for capture analysis. - return true; - return false; - } - - for (const Stmt *SubStmt : E->children()) - if (isCapturedBy(Var, SubStmt)) - return true; - - return false; -} - -/// Determine whether the given initializer is trivial in the sense -/// that it requires no code to be generated. -bool CodeGenFunction::isTrivialInitializer(const Expr *Init) { - if (!Init) - return true; - - if (const CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) - if (CXXConstructorDecl *Constructor = Construct->getConstructor()) - if (Constructor->isTrivial() && - Constructor->isDefaultConstructor() && - !Construct->requiresZeroInitialization()) - return true; - - return false; -} - -void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { - assert(emission.Variable && "emission was not valid!"); - - // If this was emitted as a global constant, we're done. - if (emission.wasEmittedAsGlobal()) return; - - const VarDecl &D = *emission.Variable; - auto DL = ApplyDebugLocation::CreateDefaultArtificial(*this, D.getLocation()); - QualType type = D.getType(); - - bool isVolatile = type.isVolatileQualified(); - - // If this local has an initializer, emit it now. - const Expr *Init = D.getInit(); - - // If we are at an unreachable point, we don't need to emit the initializer - // unless it contains a label. - if (!HaveInsertPoint()) { - if (!Init || !ContainsLabel(Init)) return; - EnsureInsertPoint(); - } - - // Initialize the structure of a __block variable. - if (emission.IsEscapingByRef) - emitByrefStructureInit(emission); - - // Initialize the variable here if it doesn't have a initializer and it is a - // C struct that is non-trivial to initialize or an array containing such a - // struct. - if (!Init && - type.isNonTrivialToPrimitiveDefaultInitialize() == - QualType::PDIK_Struct) { - LValue Dst = MakeAddrLValue(emission.getAllocatedAddress(), type); - if (emission.IsEscapingByRef) - drillIntoBlockVariable(*this, Dst, &D); - defaultInitNonTrivialCStructVar(Dst); - return; - } - - // Check whether this is a byref variable that's potentially - // captured and moved by its own initializer. If so, we'll need to - // emit the initializer first, then copy into the variable. - bool capturedByInit = - Init && emission.IsEscapingByRef && isCapturedBy(D, Init); - - bool locIsByrefHeader = !capturedByInit; - const Address Loc = - locIsByrefHeader ? emission.getObjectAddress(*this) : emission.Addr; - - // Note: constexpr already initializes everything correctly. - LangOptions::TrivialAutoVarInitKind trivialAutoVarInit = - (D.isConstexpr() - ? LangOptions::TrivialAutoVarInitKind::Uninitialized - : (D.getAttr<UninitializedAttr>() - ? LangOptions::TrivialAutoVarInitKind::Uninitialized - : getContext().getLangOpts().getTrivialAutoVarInit())); - - auto initializeWhatIsTechnicallyUninitialized = [&](Address Loc) { - if (trivialAutoVarInit == - LangOptions::TrivialAutoVarInitKind::Uninitialized) - return; - - // Only initialize a __block's storage: we always initialize the header. - if (emission.IsEscapingByRef && !locIsByrefHeader) - Loc = emitBlockByrefAddress(Loc, &D, /*follow=*/false); - - CharUnits Size = getContext().getTypeSizeInChars(type); - if (!Size.isZero()) { - switch (trivialAutoVarInit) { - case LangOptions::TrivialAutoVarInitKind::Uninitialized: - llvm_unreachable("Uninitialized handled above"); - case LangOptions::TrivialAutoVarInitKind::Zero: - emitStoresForZeroInit(CGM, D, Loc, isVolatile, Builder); - break; - case LangOptions::TrivialAutoVarInitKind::Pattern: - emitStoresForPatternInit(CGM, D, Loc, isVolatile, Builder); - break; - } - return; - } - - // VLAs look zero-sized to getTypeInfo. We can't emit constant stores to - // them, so emit a memcpy with the VLA size to initialize each element. - // Technically zero-sized or negative-sized VLAs are undefined, and UBSan - // will catch that code, but there exists code which generates zero-sized - // VLAs. Be nice and initialize whatever they requested. - const VariableArrayType *VlaType = - dyn_cast_or_null<VariableArrayType>(getContext().getAsArrayType(type)); - if (!VlaType) - return; - auto VlaSize = getVLASize(VlaType); - auto SizeVal = VlaSize.NumElts; - CharUnits EltSize = getContext().getTypeSizeInChars(VlaSize.Type); - switch (trivialAutoVarInit) { - case LangOptions::TrivialAutoVarInitKind::Uninitialized: - llvm_unreachable("Uninitialized handled above"); - - case LangOptions::TrivialAutoVarInitKind::Zero: - if (!EltSize.isOne()) - SizeVal = Builder.CreateNUWMul(SizeVal, CGM.getSize(EltSize)); - Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal, - isVolatile); - break; - - case LangOptions::TrivialAutoVarInitKind::Pattern: { - llvm::Type *ElTy = Loc.getElementType(); - llvm::Constant *Constant = patternFor(CGM, ElTy); - CharUnits ConstantAlign = getContext().getTypeAlignInChars(VlaSize.Type); - llvm::BasicBlock *SetupBB = createBasicBlock("vla-setup.loop"); - llvm::BasicBlock *LoopBB = createBasicBlock("vla-init.loop"); - llvm::BasicBlock *ContBB = createBasicBlock("vla-init.cont"); - llvm::Value *IsZeroSizedVLA = Builder.CreateICmpEQ( - SizeVal, llvm::ConstantInt::get(SizeVal->getType(), 0), - "vla.iszerosized"); - Builder.CreateCondBr(IsZeroSizedVLA, ContBB, SetupBB); - EmitBlock(SetupBB); - if (!EltSize.isOne()) - SizeVal = Builder.CreateNUWMul(SizeVal, CGM.getSize(EltSize)); - llvm::Value *BaseSizeInChars = - llvm::ConstantInt::get(IntPtrTy, EltSize.getQuantity()); - Address Begin = Builder.CreateElementBitCast(Loc, Int8Ty, "vla.begin"); - llvm::Value *End = - Builder.CreateInBoundsGEP(Begin.getPointer(), 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); - CharUnits CurAlign = Loc.getAlignment().alignmentOfArrayElement(EltSize); - Builder.CreateMemCpy( - Address(Cur, CurAlign), - createUnnamedGlobalFrom(CGM, D, Builder, Constant, ConstantAlign), - BaseSizeInChars, isVolatile); - llvm::Value *Next = - Builder.CreateInBoundsGEP(Int8Ty, Cur, BaseSizeInChars, "vla.next"); - llvm::Value *Done = Builder.CreateICmpEQ(Next, End, "vla-init.isdone"); - Builder.CreateCondBr(Done, ContBB, LoopBB); - Cur->addIncoming(Next, LoopBB); - EmitBlock(ContBB); - } break; - } - }; - - if (isTrivialInitializer(Init)) { - initializeWhatIsTechnicallyUninitialized(Loc); - return; - } - - llvm::Constant *constant = nullptr; - if (emission.IsConstantAggregate || D.isConstexpr()) { - assert(!capturedByInit && "constant init contains a capturing block?"); - constant = ConstantEmitter(*this).tryEmitAbstractForInitializer(D); - if (constant && trivialAutoVarInit != - LangOptions::TrivialAutoVarInitKind::Uninitialized) - constant = replaceUndef(constant); - } - - if (!constant) { - initializeWhatIsTechnicallyUninitialized(Loc); - LValue lv = MakeAddrLValue(Loc, type); - lv.setNonGC(true); - return EmitExprAsInit(Init, &D, lv, capturedByInit); - } - - if (!emission.IsConstantAggregate) { - // For simple scalar/complex initialization, store the value directly. - LValue lv = MakeAddrLValue(Loc, type); - lv.setNonGC(true); - return EmitStoreThroughLValue(RValue::get(constant), lv, true); - } - - llvm::Type *BP = CGM.Int8Ty->getPointerTo(Loc.getAddressSpace()); - emitStoresForConstant( - CGM, D, (Loc.getType() == BP) ? Loc : Builder.CreateBitCast(Loc, BP), - isVolatile, Builder, constant); -} - -/// Emit an expression as an initializer for an object (variable, field, etc.) -/// at the given location. The expression is not necessarily the normal -/// initializer for the object, and the address is not necessarily -/// its normal location. -/// -/// \param init the initializing expression -/// \param D the object to act as if we're initializing -/// \param loc the address to initialize; its type is a pointer -/// to the LLVM mapping of the object's type -/// \param alignment the alignment of the address -/// \param capturedByInit true if \p D is a __block variable -/// whose address is potentially changed by the initializer -void CodeGenFunction::EmitExprAsInit(const Expr *init, const ValueDecl *D, - LValue lvalue, bool capturedByInit) { - QualType type = D->getType(); - - if (type->isReferenceType()) { - RValue rvalue = EmitReferenceBindingToExpr(init); - if (capturedByInit) - drillIntoBlockVariable(*this, lvalue, cast<VarDecl>(D)); - EmitStoreThroughLValue(rvalue, lvalue, true); - return; - } - switch (getEvaluationKind(type)) { - case TEK_Scalar: - EmitScalarInit(init, D, lvalue, capturedByInit); - return; - case TEK_Complex: { - ComplexPairTy complex = EmitComplexExpr(init); - if (capturedByInit) - drillIntoBlockVariable(*this, lvalue, cast<VarDecl>(D)); - EmitStoreOfComplex(complex, lvalue, /*init*/ true); - return; - } - case TEK_Aggregate: - if (type->isAtomicType()) { - EmitAtomicInit(const_cast<Expr*>(init), lvalue); - } else { - AggValueSlot::Overlap_t Overlap = AggValueSlot::MayOverlap; - if (isa<VarDecl>(D)) - Overlap = AggValueSlot::DoesNotOverlap; - else if (auto *FD = dyn_cast<FieldDecl>(D)) - Overlap = overlapForFieldInit(FD); - // TODO: how can we delay here if D is captured by its initializer? - EmitAggExpr(init, AggValueSlot::forLValue(lvalue, - AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - Overlap)); - } - return; - } - llvm_unreachable("bad evaluation kind"); -} - -/// Enter a destroy cleanup for the given local variable. -void CodeGenFunction::emitAutoVarTypeCleanup( - const CodeGenFunction::AutoVarEmission &emission, - QualType::DestructionKind dtorKind) { - assert(dtorKind != QualType::DK_none); - - // Note that for __block variables, we want to destroy the - // original stack object, not the possibly forwarded object. - Address addr = emission.getObjectAddress(*this); - - const VarDecl *var = emission.Variable; - QualType type = var->getType(); - - CleanupKind cleanupKind = NormalAndEHCleanup; - CodeGenFunction::Destroyer *destroyer = nullptr; - - switch (dtorKind) { - case QualType::DK_none: - llvm_unreachable("no cleanup for trivially-destructible variable"); - - case QualType::DK_cxx_destructor: - // If there's an NRVO flag on the emission, we need a different - // cleanup. - if (emission.NRVOFlag) { - assert(!type->isArrayType()); - CXXDestructorDecl *dtor = type->getAsCXXRecordDecl()->getDestructor(); - EHStack.pushCleanup<DestroyNRVOVariableCXX>(cleanupKind, addr, dtor, - emission.NRVOFlag); - return; - } - break; - - case QualType::DK_objc_strong_lifetime: - // Suppress cleanups for pseudo-strong variables. - if (var->isARCPseudoStrong()) return; - - // Otherwise, consider whether to use an EH cleanup or not. - cleanupKind = getARCCleanupKind(); - - // Use the imprecise destroyer by default. - if (!var->hasAttr<ObjCPreciseLifetimeAttr>()) - destroyer = CodeGenFunction::destroyARCStrongImprecise; - break; - - case QualType::DK_objc_weak_lifetime: - break; - - case QualType::DK_nontrivial_c_struct: - destroyer = CodeGenFunction::destroyNonTrivialCStruct; - if (emission.NRVOFlag) { - assert(!type->isArrayType()); - EHStack.pushCleanup<DestroyNRVOVariableC>(cleanupKind, addr, - emission.NRVOFlag, type); - return; - } - break; - } - - // If we haven't chosen a more specific destroyer, use the default. - if (!destroyer) destroyer = getDestroyer(dtorKind); - - // Use an EH cleanup in array destructors iff the destructor itself - // is being pushed as an EH cleanup. - bool useEHCleanup = (cleanupKind & EHCleanup); - EHStack.pushCleanup<DestroyObject>(cleanupKind, addr, type, destroyer, - useEHCleanup); -} - -void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) { - assert(emission.Variable && "emission was not valid!"); - - // If this was emitted as a global constant, we're done. - if (emission.wasEmittedAsGlobal()) return; - - // If we don't have an insertion point, we're done. Sema prevents - // us from jumping into any of these scopes anyway. - if (!HaveInsertPoint()) return; - - const VarDecl &D = *emission.Variable; - - // Check the type for a cleanup. - if (QualType::DestructionKind dtorKind = D.getType().isDestructedType()) - emitAutoVarTypeCleanup(emission, dtorKind); - - // In GC mode, honor objc_precise_lifetime. - if (getLangOpts().getGC() != LangOptions::NonGC && - D.hasAttr<ObjCPreciseLifetimeAttr>()) { - EHStack.pushCleanup<ExtendGCLifetime>(NormalCleanup, &D); - } - - // Handle the cleanup attribute. - if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) { - const FunctionDecl *FD = CA->getFunctionDecl(); - - llvm::Constant *F = CGM.GetAddrOfFunction(FD); - assert(F && "Could not find function!"); - - const CGFunctionInfo &Info = CGM.getTypes().arrangeFunctionDeclaration(FD); - EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup, F, &Info, &D); - } - - // If this is a block variable, call _Block_object_destroy - // (on the unforwarded address). Don't enter this cleanup if we're in pure-GC - // mode. - if (emission.IsEscapingByRef && - CGM.getLangOpts().getGC() != LangOptions::GCOnly) { - BlockFieldFlags Flags = BLOCK_FIELD_IS_BYREF; - if (emission.Variable->getType().isObjCGCWeak()) - Flags |= BLOCK_FIELD_IS_WEAK; - enterByrefCleanup(NormalAndEHCleanup, emission.Addr, Flags, - /*LoadBlockVarAddr*/ false, - cxxDestructorCanThrow(emission.Variable->getType())); - } -} - -CodeGenFunction::Destroyer * -CodeGenFunction::getDestroyer(QualType::DestructionKind kind) { - switch (kind) { - case QualType::DK_none: llvm_unreachable("no destroyer for trivial dtor"); - case QualType::DK_cxx_destructor: - return destroyCXXObject; - case QualType::DK_objc_strong_lifetime: - return destroyARCStrongPrecise; - case QualType::DK_objc_weak_lifetime: - return destroyARCWeak; - case QualType::DK_nontrivial_c_struct: - return destroyNonTrivialCStruct; - } - llvm_unreachable("Unknown DestructionKind"); -} - -/// pushEHDestroy - Push the standard destructor for the given type as -/// an EH-only cleanup. -void CodeGenFunction::pushEHDestroy(QualType::DestructionKind dtorKind, - Address addr, QualType type) { - assert(dtorKind && "cannot push destructor for trivial type"); - assert(needsEHCleanup(dtorKind)); - - pushDestroy(EHCleanup, addr, type, getDestroyer(dtorKind), true); -} - -/// pushDestroy - Push the standard destructor for the given type as -/// at least a normal cleanup. -void CodeGenFunction::pushDestroy(QualType::DestructionKind dtorKind, - Address addr, QualType type) { - assert(dtorKind && "cannot push destructor for trivial type"); - - CleanupKind cleanupKind = getCleanupKind(dtorKind); - pushDestroy(cleanupKind, addr, type, getDestroyer(dtorKind), - cleanupKind & EHCleanup); -} - -void CodeGenFunction::pushDestroy(CleanupKind cleanupKind, Address addr, - QualType type, Destroyer *destroyer, - bool useEHCleanupForArray) { - pushFullExprCleanup<DestroyObject>(cleanupKind, addr, type, - destroyer, useEHCleanupForArray); -} - -void CodeGenFunction::pushStackRestore(CleanupKind Kind, Address SPMem) { - EHStack.pushCleanup<CallStackRestore>(Kind, SPMem); -} - -void CodeGenFunction::pushLifetimeExtendedDestroy( - CleanupKind cleanupKind, Address addr, QualType type, - Destroyer *destroyer, bool useEHCleanupForArray) { - // Push an EH-only cleanup for the object now. - // FIXME: When popping normal cleanups, we need to keep this EH cleanup - // around in case a temporary's destructor throws an exception. - if (cleanupKind & EHCleanup) - EHStack.pushCleanup<DestroyObject>( - static_cast<CleanupKind>(cleanupKind & ~NormalCleanup), addr, type, - destroyer, useEHCleanupForArray); - - // Remember that we need to push a full cleanup for the object at the - // end of the full-expression. - pushCleanupAfterFullExpr<DestroyObject>( - cleanupKind, addr, type, destroyer, useEHCleanupForArray); -} - -/// emitDestroy - Immediately perform the destruction of the given -/// object. -/// -/// \param addr - the address of the object; a type* -/// \param type - the type of the object; if an array type, all -/// objects are destroyed in reverse order -/// \param destroyer - the function to call to destroy individual -/// elements -/// \param useEHCleanupForArray - whether an EH cleanup should be -/// used when destroying array elements, in case one of the -/// destructions throws an exception -void CodeGenFunction::emitDestroy(Address addr, QualType type, - Destroyer *destroyer, - bool useEHCleanupForArray) { - const ArrayType *arrayType = getContext().getAsArrayType(type); - if (!arrayType) - return destroyer(*this, addr, type); - - llvm::Value *length = emitArrayLength(arrayType, type, addr); - - CharUnits elementAlign = - addr.getAlignment() - .alignmentOfArrayElement(getContext().getTypeSizeInChars(type)); - - // Normally we have to check whether the array is zero-length. - bool checkZeroLength = true; - - // But if the array length is constant, we can suppress that. - if (llvm::ConstantInt *constLength = dyn_cast<llvm::ConstantInt>(length)) { - // ...and if it's constant zero, we can just skip the entire thing. - if (constLength->isZero()) return; - checkZeroLength = false; - } - - llvm::Value *begin = addr.getPointer(); - llvm::Value *end = Builder.CreateInBoundsGEP(begin, length); - emitArrayDestroy(begin, end, type, elementAlign, destroyer, - checkZeroLength, useEHCleanupForArray); -} - -/// emitArrayDestroy - Destroys all the elements of the given array, -/// beginning from last to first. The array cannot be zero-length. -/// -/// \param begin - a type* denoting the first element of the array -/// \param end - a type* denoting one past the end of the array -/// \param elementType - the element type of the array -/// \param destroyer - the function to call to destroy elements -/// \param useEHCleanup - whether to push an EH cleanup to destroy -/// the remaining elements in case the destruction of a single -/// element throws -void CodeGenFunction::emitArrayDestroy(llvm::Value *begin, - llvm::Value *end, - QualType elementType, - CharUnits elementAlign, - Destroyer *destroyer, - bool checkZeroLength, - bool useEHCleanup) { - assert(!elementType->isArrayType()); - - // The basic structure here is a do-while loop, because we don't - // need to check for the zero-element case. - llvm::BasicBlock *bodyBB = createBasicBlock("arraydestroy.body"); - llvm::BasicBlock *doneBB = createBasicBlock("arraydestroy.done"); - - if (checkZeroLength) { - llvm::Value *isEmpty = Builder.CreateICmpEQ(begin, end, - "arraydestroy.isempty"); - Builder.CreateCondBr(isEmpty, doneBB, bodyBB); - } - - // Enter the loop body, making that address the current address. - llvm::BasicBlock *entryBB = Builder.GetInsertBlock(); - EmitBlock(bodyBB); - llvm::PHINode *elementPast = - Builder.CreatePHI(begin->getType(), 2, "arraydestroy.elementPast"); - elementPast->addIncoming(end, entryBB); - - // Shift the address back by one element. - llvm::Value *negativeOne = llvm::ConstantInt::get(SizeTy, -1, true); - llvm::Value *element = Builder.CreateInBoundsGEP(elementPast, negativeOne, - "arraydestroy.element"); - - if (useEHCleanup) - pushRegularPartialArrayCleanup(begin, element, elementType, elementAlign, - destroyer); - - // Perform the actual destruction there. - destroyer(*this, Address(element, elementAlign), elementType); - - if (useEHCleanup) - PopCleanupBlock(); - - // Check whether we've reached the end. - llvm::Value *done = Builder.CreateICmpEQ(element, begin, "arraydestroy.done"); - Builder.CreateCondBr(done, doneBB, bodyBB); - elementPast->addIncoming(element, Builder.GetInsertBlock()); - - // Done. - EmitBlock(doneBB); -} - -/// Perform partial array destruction as if in an EH cleanup. Unlike -/// emitArrayDestroy, the element type here may still be an array type. -static void emitPartialArrayDestroy(CodeGenFunction &CGF, - llvm::Value *begin, llvm::Value *end, - QualType type, CharUnits elementAlign, - CodeGenFunction::Destroyer *destroyer) { - // If the element type is itself an array, drill down. - unsigned arrayDepth = 0; - while (const ArrayType *arrayType = CGF.getContext().getAsArrayType(type)) { - // VLAs don't require a GEP index to walk into. - if (!isa<VariableArrayType>(arrayType)) - arrayDepth++; - type = arrayType->getElementType(); - } - - if (arrayDepth) { - llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); - - SmallVector<llvm::Value*,4> gepIndices(arrayDepth+1, zero); - begin = CGF.Builder.CreateInBoundsGEP(begin, gepIndices, "pad.arraybegin"); - end = CGF.Builder.CreateInBoundsGEP(end, gepIndices, "pad.arrayend"); - } - - // Destroy the array. We don't ever need an EH cleanup because we - // assume that we're in an EH cleanup ourselves, so a throwing - // destructor causes an immediate terminate. - CGF.emitArrayDestroy(begin, end, type, elementAlign, destroyer, - /*checkZeroLength*/ true, /*useEHCleanup*/ false); -} - -namespace { - /// RegularPartialArrayDestroy - a cleanup which performs a partial - /// array destroy where the end pointer is regularly determined and - /// does not need to be loaded from a local. - class RegularPartialArrayDestroy final : public EHScopeStack::Cleanup { - llvm::Value *ArrayBegin; - llvm::Value *ArrayEnd; - QualType ElementType; - CodeGenFunction::Destroyer *Destroyer; - CharUnits ElementAlign; - public: - RegularPartialArrayDestroy(llvm::Value *arrayBegin, llvm::Value *arrayEnd, - QualType elementType, CharUnits elementAlign, - CodeGenFunction::Destroyer *destroyer) - : ArrayBegin(arrayBegin), ArrayEnd(arrayEnd), - ElementType(elementType), Destroyer(destroyer), - ElementAlign(elementAlign) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - emitPartialArrayDestroy(CGF, ArrayBegin, ArrayEnd, - ElementType, ElementAlign, Destroyer); - } - }; - - /// IrregularPartialArrayDestroy - a cleanup which performs a - /// partial array destroy where the end pointer is irregularly - /// determined and must be loaded from a local. - class IrregularPartialArrayDestroy final : public EHScopeStack::Cleanup { - llvm::Value *ArrayBegin; - Address ArrayEndPointer; - QualType ElementType; - CodeGenFunction::Destroyer *Destroyer; - CharUnits ElementAlign; - public: - IrregularPartialArrayDestroy(llvm::Value *arrayBegin, - Address arrayEndPointer, - QualType elementType, - CharUnits elementAlign, - CodeGenFunction::Destroyer *destroyer) - : ArrayBegin(arrayBegin), ArrayEndPointer(arrayEndPointer), - ElementType(elementType), Destroyer(destroyer), - ElementAlign(elementAlign) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - llvm::Value *arrayEnd = CGF.Builder.CreateLoad(ArrayEndPointer); - emitPartialArrayDestroy(CGF, ArrayBegin, arrayEnd, - ElementType, ElementAlign, Destroyer); - } - }; -} // end anonymous namespace - -/// pushIrregularPartialArrayCleanup - Push an EH cleanup to destroy -/// already-constructed elements of the given array. The cleanup -/// may be popped with DeactivateCleanupBlock or PopCleanupBlock. -/// -/// \param elementType - the immediate element type of the array; -/// possibly still an array type -void CodeGenFunction::pushIrregularPartialArrayCleanup(llvm::Value *arrayBegin, - Address arrayEndPointer, - QualType elementType, - CharUnits elementAlign, - Destroyer *destroyer) { - pushFullExprCleanup<IrregularPartialArrayDestroy>(EHCleanup, - arrayBegin, arrayEndPointer, - elementType, elementAlign, - destroyer); -} - -/// pushRegularPartialArrayCleanup - Push an EH cleanup to destroy -/// already-constructed elements of the given array. The cleanup -/// may be popped with DeactivateCleanupBlock or PopCleanupBlock. -/// -/// \param elementType - the immediate element type of the array; -/// possibly still an array type -void CodeGenFunction::pushRegularPartialArrayCleanup(llvm::Value *arrayBegin, - llvm::Value *arrayEnd, - QualType elementType, - CharUnits elementAlign, - Destroyer *destroyer) { - pushFullExprCleanup<RegularPartialArrayDestroy>(EHCleanup, - arrayBegin, arrayEnd, - elementType, elementAlign, - destroyer); -} - -/// Lazily declare the @llvm.lifetime.start intrinsic. -llvm::Constant *CodeGenModule::getLLVMLifetimeStartFn() { - if (LifetimeStartFn) - return LifetimeStartFn; - LifetimeStartFn = llvm::Intrinsic::getDeclaration(&getModule(), - llvm::Intrinsic::lifetime_start, AllocaInt8PtrTy); - return LifetimeStartFn; -} - -/// Lazily declare the @llvm.lifetime.end intrinsic. -llvm::Constant *CodeGenModule::getLLVMLifetimeEndFn() { - if (LifetimeEndFn) - return LifetimeEndFn; - LifetimeEndFn = llvm::Intrinsic::getDeclaration(&getModule(), - llvm::Intrinsic::lifetime_end, AllocaInt8PtrTy); - return LifetimeEndFn; -} - -namespace { - /// A cleanup to perform a release of an object at the end of a - /// function. This is used to balance out the incoming +1 of a - /// ns_consumed argument when we can't reasonably do that just by - /// not doing the initial retain for a __block argument. - struct ConsumeARCParameter final : EHScopeStack::Cleanup { - ConsumeARCParameter(llvm::Value *param, - ARCPreciseLifetime_t precise) - : Param(param), Precise(precise) {} - - llvm::Value *Param; - ARCPreciseLifetime_t Precise; - - void Emit(CodeGenFunction &CGF, Flags flags) override { - CGF.EmitARCRelease(Param, Precise); - } - }; -} // end anonymous namespace - -/// Emit an alloca (or GlobalValue depending on target) -/// for the specified parameter and set up LocalDeclMap. -void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, - unsigned ArgNo) { - // FIXME: Why isn't ImplicitParamDecl a ParmVarDecl? - assert((isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) && - "Invalid argument to EmitParmDecl"); - - Arg.getAnyValue()->setName(D.getName()); - - QualType Ty = D.getType(); - - // Use better IR generation for certain implicit parameters. - if (auto IPD = dyn_cast<ImplicitParamDecl>(&D)) { - // The only implicit argument a block has is its literal. - // This may be passed as an inalloca'ed value on Windows x86. - if (BlockInfo) { - llvm::Value *V = Arg.isIndirect() - ? Builder.CreateLoad(Arg.getIndirectAddress()) - : Arg.getDirectValue(); - setBlockContextParameter(IPD, ArgNo, V); - return; - } - } - - Address DeclPtr = Address::invalid(); - bool DoStore = false; - bool IsScalar = hasScalarEvaluationKind(Ty); - // If we already have a pointer to the argument, reuse the input pointer. - if (Arg.isIndirect()) { - DeclPtr = Arg.getIndirectAddress(); - // If we have a prettier pointer type at this point, bitcast to that. - unsigned AS = DeclPtr.getType()->getAddressSpace(); - llvm::Type *IRTy = ConvertTypeForMem(Ty)->getPointerTo(AS); - if (DeclPtr.getType() != IRTy) - DeclPtr = Builder.CreateBitCast(DeclPtr, IRTy, D.getName()); - // Indirect argument is in alloca address space, which may be different - // from the default address space. - auto AllocaAS = CGM.getASTAllocaAddressSpace(); - auto *V = DeclPtr.getPointer(); - auto SrcLangAS = getLangOpts().OpenCL ? LangAS::opencl_private : AllocaAS; - auto DestLangAS = - getLangOpts().OpenCL ? LangAS::opencl_private : LangAS::Default; - if (SrcLangAS != DestLangAS) { - assert(getContext().getTargetAddressSpace(SrcLangAS) == - CGM.getDataLayout().getAllocaAddrSpace()); - auto DestAS = getContext().getTargetAddressSpace(DestLangAS); - auto *T = V->getType()->getPointerElementType()->getPointerTo(DestAS); - DeclPtr = Address(getTargetHooks().performAddrSpaceCast( - *this, V, SrcLangAS, DestLangAS, T, true), - DeclPtr.getAlignment()); - } - - // Push a destructor cleanup for this parameter if the ABI requires it. - // Don't push a cleanup in a thunk for a method that will also emit a - // cleanup. - if (hasAggregateEvaluationKind(Ty) && !CurFuncIsThunk && - Ty->getAs<RecordType>()->getDecl()->isParamDestroyedInCallee()) { - if (QualType::DestructionKind DtorKind = Ty.isDestructedType()) { - assert((DtorKind == QualType::DK_cxx_destructor || - DtorKind == QualType::DK_nontrivial_c_struct) && - "unexpected destructor type"); - pushDestroy(DtorKind, DeclPtr, Ty); - CalleeDestructedParamCleanups[cast<ParmVarDecl>(&D)] = - EHStack.stable_begin(); - } - } - } else { - // Check if the parameter address is controlled by OpenMP runtime. - Address OpenMPLocalAddr = - getLangOpts().OpenMP - ? CGM.getOpenMPRuntime().getAddressOfLocalVariable(*this, &D) - : Address::invalid(); - if (getLangOpts().OpenMP && OpenMPLocalAddr.isValid()) { - DeclPtr = OpenMPLocalAddr; - } else { - // Otherwise, create a temporary to hold the value. - DeclPtr = CreateMemTemp(Ty, getContext().getDeclAlign(&D), - D.getName() + ".addr"); - } - DoStore = true; - } - - llvm::Value *ArgVal = (DoStore ? Arg.getDirectValue() : nullptr); - - LValue lv = MakeAddrLValue(DeclPtr, Ty); - if (IsScalar) { - Qualifiers qs = Ty.getQualifiers(); - if (Qualifiers::ObjCLifetime lt = qs.getObjCLifetime()) { - // We honor __attribute__((ns_consumed)) for types with lifetime. - // For __strong, it's handled by just skipping the initial retain; - // otherwise we have to balance out the initial +1 with an extra - // cleanup to do the release at the end of the function. - bool isConsumed = D.hasAttr<NSConsumedAttr>(); - - // If a parameter is pseudo-strong then we can omit the implicit retain. - if (D.isARCPseudoStrong()) { - assert(lt == Qualifiers::OCL_Strong && - "pseudo-strong variable isn't strong?"); - assert(qs.hasConst() && "pseudo-strong variable should be const!"); - lt = Qualifiers::OCL_ExplicitNone; - } - - // Load objects passed indirectly. - if (Arg.isIndirect() && !ArgVal) - ArgVal = Builder.CreateLoad(DeclPtr); - - if (lt == Qualifiers::OCL_Strong) { - if (!isConsumed) { - if (CGM.getCodeGenOpts().OptimizationLevel == 0) { - // use objc_storeStrong(&dest, value) for retaining the - // object. But first, store a null into 'dest' because - // objc_storeStrong attempts to release its old value. - llvm::Value *Null = CGM.EmitNullConstant(D.getType()); - EmitStoreOfScalar(Null, lv, /* isInitialization */ true); - EmitARCStoreStrongCall(lv.getAddress(), ArgVal, true); - DoStore = false; - } - else - // Don't use objc_retainBlock for block pointers, because we - // don't want to Block_copy something just because we got it - // as a parameter. - ArgVal = EmitARCRetainNonBlock(ArgVal); - } - } else { - // Push the cleanup for a consumed parameter. - if (isConsumed) { - ARCPreciseLifetime_t precise = (D.hasAttr<ObjCPreciseLifetimeAttr>() - ? ARCPreciseLifetime : ARCImpreciseLifetime); - EHStack.pushCleanup<ConsumeARCParameter>(getARCCleanupKind(), ArgVal, - precise); - } - - if (lt == Qualifiers::OCL_Weak) { - EmitARCInitWeak(DeclPtr, ArgVal); - DoStore = false; // The weak init is a store, no need to do two. - } - } - - // Enter the cleanup scope. - EmitAutoVarWithLifetime(*this, D, DeclPtr, lt); - } - } - - // Store the initial value into the alloca. - if (DoStore) - EmitStoreOfScalar(ArgVal, lv, /* isInitialization */ true); - - setAddrOfLocalVar(&D, DeclPtr); - - // Emit debug info for param declaration. - if (CGDebugInfo *DI = getDebugInfo()) { - if (CGM.getCodeGenOpts().getDebugInfo() >= - codegenoptions::LimitedDebugInfo) { - DI->EmitDeclareOfArgVariable(&D, DeclPtr.getPointer(), ArgNo, Builder); - } - } - - if (D.hasAttr<AnnotateAttr>()) - EmitVarAnnotations(&D, DeclPtr.getPointer()); - - // We can only check return value nullability if all arguments to the - // function satisfy their nullability preconditions. This makes it necessary - // to emit null checks for args in the function body itself. - if (requiresReturnValueNullabilityCheck()) { - auto Nullability = Ty->getNullability(getContext()); - if (Nullability && *Nullability == NullabilityKind::NonNull) { - SanitizerScope SanScope(this); - RetValNullabilityPrecondition = - Builder.CreateAnd(RetValNullabilityPrecondition, - Builder.CreateIsNotNull(Arg.getAnyValue())); - } - } -} - -void CodeGenModule::EmitOMPDeclareReduction(const OMPDeclareReductionDecl *D, - CodeGenFunction *CGF) { - if (!LangOpts.OpenMP || (!LangOpts.EmitAllDecls && !D->isUsed())) - return; - getOpenMPRuntime().emitUserDefinedReduction(CGF, D); -} - -void CodeGenModule::EmitOMPRequiresDecl(const OMPRequiresDecl *D) { - getOpenMPRuntime().checkArchForUnifiedAddressing(*this, D); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp deleted file mode 100644 index 9aa31f181e9..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp +++ /dev/null @@ -1,734 +0,0 @@ -//===--- CGDeclCXX.cpp - Emit LLVM Code for C++ declarations --------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code dealing with code generation of C++ declarations -// -//===----------------------------------------------------------------------===// - -#include "CodeGenFunction.h" -#include "CGCXXABI.h" -#include "CGObjCRuntime.h" -#include "CGOpenMPRuntime.h" -#include "clang/Basic/CodeGenOptions.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/MDBuilder.h" -#include "llvm/Support/Path.h" - -using namespace clang; -using namespace CodeGen; - -static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D, - ConstantAddress DeclPtr) { - assert( - (D.hasGlobalStorage() || - (D.hasLocalStorage() && CGF.getContext().getLangOpts().OpenCLCPlusPlus)) && - "VarDecl must have global or local (in the case of OpenCL) storage!"); - assert(!D.getType()->isReferenceType() && - "Should not call EmitDeclInit on a reference!"); - - QualType type = D.getType(); - LValue lv = CGF.MakeAddrLValue(DeclPtr, type); - - const Expr *Init = D.getInit(); - switch (CGF.getEvaluationKind(type)) { - case TEK_Scalar: { - CodeGenModule &CGM = CGF.CGM; - if (lv.isObjCStrong()) - CGM.getObjCRuntime().EmitObjCGlobalAssign(CGF, CGF.EmitScalarExpr(Init), - DeclPtr, D.getTLSKind()); - else if (lv.isObjCWeak()) - CGM.getObjCRuntime().EmitObjCWeakAssign(CGF, CGF.EmitScalarExpr(Init), - DeclPtr); - else - CGF.EmitScalarInit(Init, &D, lv, false); - return; - } - case TEK_Complex: - CGF.EmitComplexExprIntoLValue(Init, lv, /*isInit*/ true); - return; - case TEK_Aggregate: - CGF.EmitAggExpr(Init, AggValueSlot::forLValue(lv,AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - AggValueSlot::DoesNotOverlap)); - return; - } - llvm_unreachable("bad evaluation kind"); -} - -/// Emit code to cause the destruction of the given variable with -/// static storage duration. -static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D, - ConstantAddress Addr) { - // Honor __attribute__((no_destroy)) and bail instead of attempting - // to emit a reference to a possibly nonexistent destructor, which - // in turn can cause a crash. This will result in a global constructor - // that isn't balanced out by a destructor call as intended by the - // attribute. This also checks for -fno-c++-static-destructors and - // bails even if the attribute is not present. - if (D.isNoDestroy(CGF.getContext())) - return; - - CodeGenModule &CGM = CGF.CGM; - - // FIXME: __attribute__((cleanup)) ? - - QualType Type = D.getType(); - QualType::DestructionKind DtorKind = Type.isDestructedType(); - - switch (DtorKind) { - case QualType::DK_none: - return; - - case QualType::DK_cxx_destructor: - break; - - case QualType::DK_objc_strong_lifetime: - case QualType::DK_objc_weak_lifetime: - case QualType::DK_nontrivial_c_struct: - // We don't care about releasing objects during process teardown. - assert(!D.getTLSKind() && "should have rejected this"); - return; - } - - llvm::Constant *Func; - llvm::Constant *Argument; - - // Special-case non-array C++ destructors, if they have the right signature. - // Under some ABIs, destructors return this instead of void, and cannot be - // passed directly to __cxa_atexit if the target does not allow this - // mismatch. - const CXXRecordDecl *Record = Type->getAsCXXRecordDecl(); - bool CanRegisterDestructor = - Record && (!CGM.getCXXABI().HasThisReturn( - GlobalDecl(Record->getDestructor(), Dtor_Complete)) || - CGM.getCXXABI().canCallMismatchedFunctionType()); - // If __cxa_atexit is disabled via a flag, a different helper function is - // generated elsewhere which uses atexit instead, and it takes the destructor - // directly. - bool UsingExternalHelper = !CGM.getCodeGenOpts().CXAAtExit; - if (Record && (CanRegisterDestructor || UsingExternalHelper)) { - assert(!Record->hasTrivialDestructor()); - CXXDestructorDecl *Dtor = Record->getDestructor(); - - Func = CGM.getAddrOfCXXStructor(Dtor, StructorType::Complete); - Argument = llvm::ConstantExpr::getBitCast( - Addr.getPointer(), CGF.getTypes().ConvertType(Type)->getPointerTo()); - - // Otherwise, the standard logic requires a helper function. - } else { - Func = CodeGenFunction(CGM) - .generateDestroyHelper(Addr, Type, CGF.getDestroyer(DtorKind), - CGF.needsEHCleanup(DtorKind), &D); - Argument = llvm::Constant::getNullValue(CGF.Int8PtrTy); - } - - CGM.getCXXABI().registerGlobalDtor(CGF, D, Func, Argument); -} - -/// Emit code to cause the variable at the given address to be considered as -/// constant from this point onwards. -static void EmitDeclInvariant(CodeGenFunction &CGF, const VarDecl &D, - llvm::Constant *Addr) { - return CGF.EmitInvariantStart( - Addr, CGF.getContext().getTypeSizeInChars(D.getType())); -} - -void CodeGenFunction::EmitInvariantStart(llvm::Constant *Addr, CharUnits Size) { - // Do not emit the intrinsic if we're not optimizing. - if (!CGM.getCodeGenOpts().OptimizationLevel) - return; - - // Grab the llvm.invariant.start intrinsic. - llvm::Intrinsic::ID InvStartID = llvm::Intrinsic::invariant_start; - // Overloaded address space type. - llvm::Type *ObjectPtr[1] = {Int8PtrTy}; - llvm::Constant *InvariantStart = CGM.getIntrinsic(InvStartID, ObjectPtr); - - // Emit a call with the size in bytes of the object. - uint64_t Width = Size.getQuantity(); - llvm::Value *Args[2] = { llvm::ConstantInt::getSigned(Int64Ty, Width), - llvm::ConstantExpr::getBitCast(Addr, Int8PtrTy)}; - Builder.CreateCall(InvariantStart, Args); -} - -void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, - llvm::Constant *DeclPtr, - bool PerformInit) { - - const Expr *Init = D.getInit(); - QualType T = D.getType(); - - // The address space of a static local variable (DeclPtr) may be different - // from the address space of the "this" argument of the constructor. In that - // case, we need an addrspacecast before calling the constructor. - // - // struct StructWithCtor { - // __device__ StructWithCtor() {...} - // }; - // __device__ void foo() { - // __shared__ StructWithCtor s; - // ... - // } - // - // For example, in the above CUDA code, the static local variable s has a - // "shared" address space qualifier, but the constructor of StructWithCtor - // expects "this" in the "generic" address space. - unsigned ExpectedAddrSpace = getContext().getTargetAddressSpace(T); - unsigned ActualAddrSpace = DeclPtr->getType()->getPointerAddressSpace(); - if (ActualAddrSpace != ExpectedAddrSpace) { - llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(T); - llvm::PointerType *PTy = llvm::PointerType::get(LTy, ExpectedAddrSpace); - DeclPtr = llvm::ConstantExpr::getAddrSpaceCast(DeclPtr, PTy); - } - - ConstantAddress DeclAddr(DeclPtr, getContext().getDeclAlign(&D)); - - if (!T->isReferenceType()) { - if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd && - D.hasAttr<OMPThreadPrivateDeclAttr>()) { - (void)CGM.getOpenMPRuntime().emitThreadPrivateVarDefinition( - &D, DeclAddr, D.getAttr<OMPThreadPrivateDeclAttr>()->getLocation(), - PerformInit, this); - } - if (PerformInit) - EmitDeclInit(*this, D, DeclAddr); - if (CGM.isTypeConstant(D.getType(), true)) - EmitDeclInvariant(*this, D, DeclPtr); - else - EmitDeclDestroy(*this, D, DeclAddr); - return; - } - - assert(PerformInit && "cannot have constant initializer which needs " - "destruction for reference"); - RValue RV = EmitReferenceBindingToExpr(Init); - EmitStoreOfScalar(RV.getScalarVal(), DeclAddr, false, T); -} - -/// Create a stub function, suitable for being passed to atexit, -/// which passes the given address to the given destructor function. -llvm::Constant *CodeGenFunction::createAtExitStub(const VarDecl &VD, - llvm::Constant *dtor, - llvm::Constant *addr) { - // Get the destructor function type, void(*)(void). - llvm::FunctionType *ty = llvm::FunctionType::get(CGM.VoidTy, false); - SmallString<256> FnName; - { - llvm::raw_svector_ostream Out(FnName); - CGM.getCXXABI().getMangleContext().mangleDynamicAtExitDestructor(&VD, Out); - } - - const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); - llvm::Function *fn = CGM.CreateGlobalInitOrDestructFunction(ty, FnName.str(), - FI, - VD.getLocation()); - - CodeGenFunction CGF(CGM); - - CGF.StartFunction(&VD, CGM.getContext().VoidTy, fn, FI, FunctionArgList()); - - llvm::CallInst *call = CGF.Builder.CreateCall(dtor, addr); - - // Make sure the call and the callee agree on calling convention. - if (llvm::Function *dtorFn = - dyn_cast<llvm::Function>(dtor->stripPointerCasts())) - call->setCallingConv(dtorFn->getCallingConv()); - - CGF.FinishFunction(); - - return fn; -} - -/// Register a global destructor using the C atexit runtime function. -void CodeGenFunction::registerGlobalDtorWithAtExit(const VarDecl &VD, - llvm::Constant *dtor, - llvm::Constant *addr) { - // Create a function which calls the destructor. - llvm::Constant *dtorStub = createAtExitStub(VD, dtor, addr); - registerGlobalDtorWithAtExit(dtorStub); -} - -void CodeGenFunction::registerGlobalDtorWithAtExit(llvm::Constant *dtorStub) { - // extern "C" int atexit(void (*f)(void)); - llvm::FunctionType *atexitTy = - llvm::FunctionType::get(IntTy, dtorStub->getType(), false); - - llvm::Constant *atexit = - CGM.CreateRuntimeFunction(atexitTy, "atexit", llvm::AttributeList(), - /*Local=*/true); - if (llvm::Function *atexitFn = dyn_cast<llvm::Function>(atexit)) - atexitFn->setDoesNotThrow(); - - EmitNounwindRuntimeCall(atexit, dtorStub); -} - -void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D, - llvm::GlobalVariable *DeclPtr, - bool PerformInit) { - // If we've been asked to forbid guard variables, emit an error now. - // This diagnostic is hard-coded for Darwin's use case; we can find - // better phrasing if someone else needs it. - if (CGM.getCodeGenOpts().ForbidGuardVariables) - CGM.Error(D.getLocation(), - "this initialization requires a guard variable, which " - "the kernel does not support"); - - CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr, PerformInit); -} - -void CodeGenFunction::EmitCXXGuardedInitBranch(llvm::Value *NeedsInit, - llvm::BasicBlock *InitBlock, - llvm::BasicBlock *NoInitBlock, - GuardKind Kind, - const VarDecl *D) { - assert((Kind == GuardKind::TlsGuard || D) && "no guarded variable"); - - // A guess at how many times we will enter the initialization of a - // variable, depending on the kind of variable. - static const uint64_t InitsPerTLSVar = 1024; - static const uint64_t InitsPerLocalVar = 1024 * 1024; - - llvm::MDNode *Weights; - if (Kind == GuardKind::VariableGuard && !D->isLocalVarDecl()) { - // For non-local variables, don't apply any weighting for now. Due to our - // use of COMDATs, we expect there to be at most one initialization of the - // variable per DSO, but we have no way to know how many DSOs will try to - // initialize the variable. - Weights = nullptr; - } else { - uint64_t NumInits; - // FIXME: For the TLS case, collect and use profiling information to - // determine a more accurate brach weight. - if (Kind == GuardKind::TlsGuard || D->getTLSKind()) - NumInits = InitsPerTLSVar; - else - NumInits = InitsPerLocalVar; - - // The probability of us entering the initializer is - // 1 / (total number of times we attempt to initialize the variable). - llvm::MDBuilder MDHelper(CGM.getLLVMContext()); - Weights = MDHelper.createBranchWeights(1, NumInits - 1); - } - - Builder.CreateCondBr(NeedsInit, InitBlock, NoInitBlock, Weights); -} - -llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction( - llvm::FunctionType *FTy, const Twine &Name, const CGFunctionInfo &FI, - SourceLocation Loc, bool TLS) { - llvm::Function *Fn = - llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, - Name, &getModule()); - if (!getLangOpts().AppleKext && !TLS) { - // Set the section if needed. - if (const char *Section = getTarget().getStaticInitSectionSpecifier()) - Fn->setSection(Section); - } - - SetInternalFunctionAttributes(GlobalDecl(), Fn, FI); - - Fn->setCallingConv(getRuntimeCC()); - - if (!getLangOpts().Exceptions) - Fn->setDoesNotThrow(); - - if (getLangOpts().Sanitize.has(SanitizerKind::Address) && - !isInSanitizerBlacklist(SanitizerKind::Address, Fn, Loc)) - Fn->addFnAttr(llvm::Attribute::SanitizeAddress); - - if (getLangOpts().Sanitize.has(SanitizerKind::KernelAddress) && - !isInSanitizerBlacklist(SanitizerKind::KernelAddress, Fn, Loc)) - Fn->addFnAttr(llvm::Attribute::SanitizeAddress); - - if (getLangOpts().Sanitize.has(SanitizerKind::HWAddress) && - !isInSanitizerBlacklist(SanitizerKind::HWAddress, Fn, Loc)) - Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress); - - if (getLangOpts().Sanitize.has(SanitizerKind::KernelHWAddress) && - !isInSanitizerBlacklist(SanitizerKind::KernelHWAddress, Fn, Loc)) - Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress); - - if (getLangOpts().Sanitize.has(SanitizerKind::Thread) && - !isInSanitizerBlacklist(SanitizerKind::Thread, Fn, Loc)) - Fn->addFnAttr(llvm::Attribute::SanitizeThread); - - if (getLangOpts().Sanitize.has(SanitizerKind::Memory) && - !isInSanitizerBlacklist(SanitizerKind::Memory, Fn, Loc)) - Fn->addFnAttr(llvm::Attribute::SanitizeMemory); - - if (getLangOpts().Sanitize.has(SanitizerKind::KernelMemory) && - !isInSanitizerBlacklist(SanitizerKind::KernelMemory, Fn, Loc)) - Fn->addFnAttr(llvm::Attribute::SanitizeMemory); - - if (getLangOpts().Sanitize.has(SanitizerKind::SafeStack) && - !isInSanitizerBlacklist(SanitizerKind::SafeStack, Fn, Loc)) - Fn->addFnAttr(llvm::Attribute::SafeStack); - - if (getLangOpts().Sanitize.has(SanitizerKind::ShadowCallStack) && - !isInSanitizerBlacklist(SanitizerKind::ShadowCallStack, Fn, Loc)) - Fn->addFnAttr(llvm::Attribute::ShadowCallStack); - - auto RASignKind = getCodeGenOpts().getSignReturnAddress(); - if (RASignKind != CodeGenOptions::SignReturnAddressScope::None) { - Fn->addFnAttr("sign-return-address", - RASignKind == CodeGenOptions::SignReturnAddressScope::All - ? "all" - : "non-leaf"); - auto RASignKey = getCodeGenOpts().getSignReturnAddressKey(); - Fn->addFnAttr("sign-return-address-key", - RASignKey == CodeGenOptions::SignReturnAddressKeyValue::AKey - ? "a_key" - : "b_key"); - } - - if (getCodeGenOpts().BranchTargetEnforcement) - Fn->addFnAttr("branch-target-enforcement"); - - return Fn; -} - -/// Create a global pointer to a function that will initialize a global -/// variable. The user has requested that this pointer be emitted in a specific -/// section. -void CodeGenModule::EmitPointerToInitFunc(const VarDecl *D, - llvm::GlobalVariable *GV, - llvm::Function *InitFunc, - InitSegAttr *ISA) { - llvm::GlobalVariable *PtrArray = new llvm::GlobalVariable( - TheModule, InitFunc->getType(), /*isConstant=*/true, - llvm::GlobalValue::PrivateLinkage, InitFunc, "__cxx_init_fn_ptr"); - PtrArray->setSection(ISA->getSection()); - addUsedGlobal(PtrArray); - - // If the GV is already in a comdat group, then we have to join it. - if (llvm::Comdat *C = GV->getComdat()) - PtrArray->setComdat(C); -} - -void -CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D, - llvm::GlobalVariable *Addr, - bool PerformInit) { - - // According to E.2.3.1 in CUDA-7.5 Programming guide: __device__, - // __constant__ and __shared__ variables defined in namespace scope, - // that are of class type, cannot have a non-empty constructor. All - // the checks have been done in Sema by now. Whatever initializers - // are allowed are empty and we just need to ignore them here. - if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice && - (D->hasAttr<CUDADeviceAttr>() || D->hasAttr<CUDAConstantAttr>() || - D->hasAttr<CUDASharedAttr>())) - return; - - if (getLangOpts().OpenMP && - getOpenMPRuntime().emitDeclareTargetVarDefinition(D, Addr, PerformInit)) - return; - - // Check if we've already initialized this decl. - auto I = DelayedCXXInitPosition.find(D); - if (I != DelayedCXXInitPosition.end() && I->second == ~0U) - return; - - llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); - SmallString<256> FnName; - { - llvm::raw_svector_ostream Out(FnName); - getCXXABI().getMangleContext().mangleDynamicInitializer(D, Out); - } - - // Create a variable initialization function. - llvm::Function *Fn = - CreateGlobalInitOrDestructFunction(FTy, FnName.str(), - getTypes().arrangeNullaryFunction(), - D->getLocation()); - - auto *ISA = D->getAttr<InitSegAttr>(); - CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr, - PerformInit); - - llvm::GlobalVariable *COMDATKey = - supportsCOMDAT() && D->isExternallyVisible() ? Addr : nullptr; - - if (D->getTLSKind()) { - // FIXME: Should we support init_priority for thread_local? - // FIXME: We only need to register one __cxa_thread_atexit function for the - // entire TU. - CXXThreadLocalInits.push_back(Fn); - CXXThreadLocalInitVars.push_back(D); - } else if (PerformInit && ISA) { - EmitPointerToInitFunc(D, Addr, Fn, ISA); - } else if (auto *IPA = D->getAttr<InitPriorityAttr>()) { - OrderGlobalInits Key(IPA->getPriority(), PrioritizedCXXGlobalInits.size()); - PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn)); - } else if (isTemplateInstantiation(D->getTemplateSpecializationKind())) { - // C++ [basic.start.init]p2: - // Definitions of explicitly specialized class template static data - // members have ordered initialization. Other class template static data - // members (i.e., implicitly or explicitly instantiated specializations) - // have unordered initialization. - // - // As a consequence, we can put them into their own llvm.global_ctors entry. - // - // If the global is externally visible, put the initializer into a COMDAT - // group with the global being initialized. On most platforms, this is a - // minor startup time optimization. In the MS C++ ABI, there are no guard - // variables, so this COMDAT key is required for correctness. - AddGlobalCtor(Fn, 65535, COMDATKey); - } else if (D->hasAttr<SelectAnyAttr>()) { - // SelectAny globals will be comdat-folded. Put the initializer into a - // COMDAT group associated with the global, so the initializers get folded - // too. - AddGlobalCtor(Fn, 65535, COMDATKey); - } else { - I = DelayedCXXInitPosition.find(D); // Re-do lookup in case of re-hash. - if (I == DelayedCXXInitPosition.end()) { - CXXGlobalInits.push_back(Fn); - } else if (I->second != ~0U) { - assert(I->second < CXXGlobalInits.size() && - CXXGlobalInits[I->second] == nullptr); - CXXGlobalInits[I->second] = Fn; - } - } - - // Remember that we already emitted the initializer for this global. - DelayedCXXInitPosition[D] = ~0U; -} - -void CodeGenModule::EmitCXXThreadLocalInitFunc() { - getCXXABI().EmitThreadLocalInitFuncs( - *this, CXXThreadLocals, CXXThreadLocalInits, CXXThreadLocalInitVars); - - CXXThreadLocalInits.clear(); - CXXThreadLocalInitVars.clear(); - CXXThreadLocals.clear(); -} - -void -CodeGenModule::EmitCXXGlobalInitFunc() { - while (!CXXGlobalInits.empty() && !CXXGlobalInits.back()) - CXXGlobalInits.pop_back(); - - if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty()) - return; - - llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); - const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction(); - - // Create our global initialization function. - if (!PrioritizedCXXGlobalInits.empty()) { - SmallVector<llvm::Function *, 8> LocalCXXGlobalInits; - llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(), - PrioritizedCXXGlobalInits.end()); - // Iterate over "chunks" of ctors with same priority and emit each chunk - // into separate function. Note - everything is sorted first by priority, - // second - by lex order, so we emit ctor functions in proper order. - for (SmallVectorImpl<GlobalInitData >::iterator - I = PrioritizedCXXGlobalInits.begin(), - E = PrioritizedCXXGlobalInits.end(); I != E; ) { - SmallVectorImpl<GlobalInitData >::iterator - PrioE = std::upper_bound(I + 1, E, *I, GlobalInitPriorityCmp()); - - LocalCXXGlobalInits.clear(); - unsigned Priority = I->first.priority; - // Compute the function suffix from priority. Prepend with zeroes to make - // sure the function names are also ordered as priorities. - std::string PrioritySuffix = llvm::utostr(Priority); - // Priority is always <= 65535 (enforced by sema). - PrioritySuffix = std::string(6-PrioritySuffix.size(), '0')+PrioritySuffix; - llvm::Function *Fn = CreateGlobalInitOrDestructFunction( - FTy, "_GLOBAL__I_" + PrioritySuffix, FI); - - for (; I < PrioE; ++I) - LocalCXXGlobalInits.push_back(I->second); - - CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, LocalCXXGlobalInits); - AddGlobalCtor(Fn, Priority); - } - PrioritizedCXXGlobalInits.clear(); - } - - // Include the filename in the symbol name. Including "sub_" matches gcc and - // makes sure these symbols appear lexicographically behind the symbols with - // priority emitted above. - SmallString<128> FileName = llvm::sys::path::filename(getModule().getName()); - if (FileName.empty()) - FileName = "<null>"; - - for (size_t i = 0; i < FileName.size(); ++i) { - // Replace everything that's not [a-zA-Z0-9._] with a _. This set happens - // to be the set of C preprocessing numbers. - if (!isPreprocessingNumberBody(FileName[i])) - FileName[i] = '_'; - } - - llvm::Function *Fn = CreateGlobalInitOrDestructFunction( - FTy, llvm::Twine("_GLOBAL__sub_I_", FileName), FI); - - CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, CXXGlobalInits); - AddGlobalCtor(Fn); - - CXXGlobalInits.clear(); -} - -void CodeGenModule::EmitCXXGlobalDtorFunc() { - if (CXXGlobalDtors.empty()) - return; - - llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); - - // Create our global destructor function. - const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction(); - llvm::Function *Fn = - CreateGlobalInitOrDestructFunction(FTy, "_GLOBAL__D_a", FI); - - CodeGenFunction(*this).GenerateCXXGlobalDtorsFunc(Fn, CXXGlobalDtors); - AddGlobalDtor(Fn); -} - -/// Emit the code necessary to initialize the given global variable. -void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, - const VarDecl *D, - llvm::GlobalVariable *Addr, - bool PerformInit) { - // Check if we need to emit debug info for variable initializer. - if (D->hasAttr<NoDebugAttr>()) - DebugInfo = nullptr; // disable debug info indefinitely for this function - - CurEHLocation = D->getBeginLoc(); - - StartFunction(GlobalDecl(D), getContext().VoidTy, Fn, - getTypes().arrangeNullaryFunction(), - FunctionArgList(), D->getLocation(), - D->getInit()->getExprLoc()); - - // Use guarded initialization if the global variable is weak. This - // occurs for, e.g., instantiated static data members and - // definitions explicitly marked weak. - if (Addr->hasWeakLinkage() || Addr->hasLinkOnceLinkage()) { - EmitCXXGuardedInit(*D, Addr, PerformInit); - } else { - EmitCXXGlobalVarDeclInit(*D, Addr, PerformInit); - } - - FinishFunction(); -} - -void -CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, - ArrayRef<llvm::Function *> Decls, - ConstantAddress Guard) { - { - auto NL = ApplyDebugLocation::CreateEmpty(*this); - StartFunction(GlobalDecl(), getContext().VoidTy, Fn, - getTypes().arrangeNullaryFunction(), FunctionArgList()); - // Emit an artificial location for this function. - auto AL = ApplyDebugLocation::CreateArtificial(*this); - - llvm::BasicBlock *ExitBlock = nullptr; - if (Guard.isValid()) { - // If we have a guard variable, check whether we've already performed - // these initializations. This happens for TLS initialization functions. - llvm::Value *GuardVal = Builder.CreateLoad(Guard); - llvm::Value *Uninit = Builder.CreateIsNull(GuardVal, - "guard.uninitialized"); - llvm::BasicBlock *InitBlock = createBasicBlock("init"); - ExitBlock = createBasicBlock("exit"); - EmitCXXGuardedInitBranch(Uninit, InitBlock, ExitBlock, - GuardKind::TlsGuard, nullptr); - EmitBlock(InitBlock); - // Mark as initialized before initializing anything else. If the - // initializers use previously-initialized thread_local vars, that's - // probably supposed to be OK, but the standard doesn't say. - Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(),1), Guard); - - // The guard variable can't ever change again. - EmitInvariantStart( - Guard.getPointer(), - CharUnits::fromQuantity( - CGM.getDataLayout().getTypeAllocSize(GuardVal->getType()))); - } - - RunCleanupsScope Scope(*this); - - // When building in Objective-C++ ARC mode, create an autorelease pool - // around the global initializers. - if (getLangOpts().ObjCAutoRefCount && getLangOpts().CPlusPlus) { - llvm::Value *token = EmitObjCAutoreleasePoolPush(); - EmitObjCAutoreleasePoolCleanup(token); - } - - for (unsigned i = 0, e = Decls.size(); i != e; ++i) - if (Decls[i]) - EmitRuntimeCall(Decls[i]); - - Scope.ForceCleanup(); - - if (ExitBlock) { - Builder.CreateBr(ExitBlock); - EmitBlock(ExitBlock); - } - } - - FinishFunction(); -} - -void CodeGenFunction::GenerateCXXGlobalDtorsFunc( - llvm::Function *Fn, - const std::vector<std::pair<llvm::WeakTrackingVH, llvm::Constant *>> - &DtorsAndObjects) { - { - auto NL = ApplyDebugLocation::CreateEmpty(*this); - StartFunction(GlobalDecl(), getContext().VoidTy, Fn, - getTypes().arrangeNullaryFunction(), FunctionArgList()); - // Emit an artificial location for this function. - auto AL = ApplyDebugLocation::CreateArtificial(*this); - - // Emit the dtors, in reverse order from construction. - for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) { - llvm::Value *Callee = DtorsAndObjects[e - i - 1].first; - llvm::CallInst *CI = Builder.CreateCall(Callee, - DtorsAndObjects[e - i - 1].second); - // Make sure the call and the callee agree on calling convention. - if (llvm::Function *F = dyn_cast<llvm::Function>(Callee)) - CI->setCallingConv(F->getCallingConv()); - } - } - - FinishFunction(); -} - -/// generateDestroyHelper - Generates a helper function which, when -/// invoked, destroys the given object. The address of the object -/// should be in global memory. -llvm::Function *CodeGenFunction::generateDestroyHelper( - Address addr, QualType type, Destroyer *destroyer, - bool useEHCleanupForArray, const VarDecl *VD) { - FunctionArgList args; - ImplicitParamDecl Dst(getContext(), getContext().VoidPtrTy, - ImplicitParamDecl::Other); - args.push_back(&Dst); - - const CGFunctionInfo &FI = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(getContext().VoidTy, args); - llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); - llvm::Function *fn = CGM.CreateGlobalInitOrDestructFunction( - FTy, "__cxx_global_array_dtor", FI, VD->getLocation()); - - CurEHLocation = VD->getBeginLoc(); - - StartFunction(VD, getContext().VoidTy, fn, FI, args); - - emitDestroy(addr, type, destroyer, useEHCleanupForArray); - - FinishFunction(); - - return fn; -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGException.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGException.cpp deleted file mode 100644 index 5756e13d262..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGException.cpp +++ /dev/null @@ -1,2114 +0,0 @@ -//===--- CGException.cpp - Emit LLVM Code for C++ exceptions ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code dealing with C++ exception related code generation. -// -//===----------------------------------------------------------------------===// - -#include "CodeGenFunction.h" -#include "CGCXXABI.h" -#include "CGCleanup.h" -#include "CGObjCRuntime.h" -#include "ConstantEmitter.h" -#include "TargetInfo.h" -#include "clang/AST/Mangle.h" -#include "clang/AST/StmtCXX.h" -#include "clang/AST/StmtObjC.h" -#include "clang/AST/StmtVisitor.h" -#include "clang/Basic/TargetBuiltins.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/Support/SaveAndRestore.h" - -using namespace clang; -using namespace CodeGen; - -static llvm::Constant *getFreeExceptionFn(CodeGenModule &CGM) { - // void __cxa_free_exception(void *thrown_exception); - - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false); - - return CGM.CreateRuntimeFunction(FTy, "__cxa_free_exception"); -} - -static llvm::Constant *getUnexpectedFn(CodeGenModule &CGM) { - // void __cxa_call_unexpected(void *thrown_exception); - - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false); - - return CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected"); -} - -llvm::Constant *CodeGenModule::getTerminateFn() { - // void __terminate(); - - llvm::FunctionType *FTy = - llvm::FunctionType::get(VoidTy, /*IsVarArgs=*/false); - - StringRef name; - - // In C++, use std::terminate(). - if (getLangOpts().CPlusPlus && - getTarget().getCXXABI().isItaniumFamily()) { - name = "_ZSt9terminatev"; - } else if (getLangOpts().CPlusPlus && - getTarget().getCXXABI().isMicrosoft()) { - if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015)) - name = "__std_terminate"; - else - name = "?terminate@@YAXXZ"; - } else if (getLangOpts().ObjC && - getLangOpts().ObjCRuntime.hasTerminate()) - name = "objc_terminate"; - else - name = "abort"; - return CreateRuntimeFunction(FTy, name); -} - -static llvm::Constant *getCatchallRethrowFn(CodeGenModule &CGM, - StringRef Name) { - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false); - - return CGM.CreateRuntimeFunction(FTy, Name); -} - -const EHPersonality EHPersonality::GNU_C = { "__gcc_personality_v0", nullptr }; -const EHPersonality -EHPersonality::GNU_C_SJLJ = { "__gcc_personality_sj0", nullptr }; -const EHPersonality -EHPersonality::GNU_C_SEH = { "__gcc_personality_seh0", nullptr }; -const EHPersonality -EHPersonality::NeXT_ObjC = { "__objc_personality_v0", nullptr }; -const EHPersonality -EHPersonality::GNU_CPlusPlus = { "__gxx_personality_v0", nullptr }; -const EHPersonality -EHPersonality::GNU_CPlusPlus_SJLJ = { "__gxx_personality_sj0", nullptr }; -const EHPersonality -EHPersonality::GNU_CPlusPlus_SEH = { "__gxx_personality_seh0", nullptr }; -const EHPersonality -EHPersonality::GNU_ObjC = {"__gnu_objc_personality_v0", "objc_exception_throw"}; -const EHPersonality -EHPersonality::GNU_ObjC_SJLJ = {"__gnu_objc_personality_sj0", "objc_exception_throw"}; -const EHPersonality -EHPersonality::GNU_ObjC_SEH = {"__gnu_objc_personality_seh0", "objc_exception_throw"}; -const EHPersonality -EHPersonality::GNU_ObjCXX = { "__gnustep_objcxx_personality_v0", nullptr }; -const EHPersonality -EHPersonality::GNUstep_ObjC = { "__gnustep_objc_personality_v0", nullptr }; -const EHPersonality -EHPersonality::MSVC_except_handler = { "_except_handler3", nullptr }; -const EHPersonality -EHPersonality::MSVC_C_specific_handler = { "__C_specific_handler", nullptr }; -const EHPersonality -EHPersonality::MSVC_CxxFrameHandler3 = { "__CxxFrameHandler3", nullptr }; -const EHPersonality -EHPersonality::GNU_Wasm_CPlusPlus = { "__gxx_wasm_personality_v0", nullptr }; - -static const EHPersonality &getCPersonality(const TargetInfo &Target, - const LangOptions &L) { - const llvm::Triple &T = Target.getTriple(); - if (T.isWindowsMSVCEnvironment()) - return EHPersonality::MSVC_CxxFrameHandler3; - if (L.SjLjExceptions) - return EHPersonality::GNU_C_SJLJ; - if (L.DWARFExceptions) - return EHPersonality::GNU_C; - if (L.SEHExceptions) - return EHPersonality::GNU_C_SEH; - return EHPersonality::GNU_C; -} - -static const EHPersonality &getObjCPersonality(const TargetInfo &Target, - const LangOptions &L) { - const llvm::Triple &T = Target.getTriple(); - if (T.isWindowsMSVCEnvironment()) - return EHPersonality::MSVC_CxxFrameHandler3; - - switch (L.ObjCRuntime.getKind()) { - case ObjCRuntime::FragileMacOSX: - return getCPersonality(Target, L); - case ObjCRuntime::MacOSX: - case ObjCRuntime::iOS: - case ObjCRuntime::WatchOS: - return EHPersonality::NeXT_ObjC; - case ObjCRuntime::GNUstep: - if (L.ObjCRuntime.getVersion() >= VersionTuple(1, 7)) - return EHPersonality::GNUstep_ObjC; - LLVM_FALLTHROUGH; - case ObjCRuntime::GCC: - case ObjCRuntime::ObjFW: - if (L.SjLjExceptions) - return EHPersonality::GNU_ObjC_SJLJ; - if (L.SEHExceptions) - return EHPersonality::GNU_ObjC_SEH; - return EHPersonality::GNU_ObjC; - } - llvm_unreachable("bad runtime kind"); -} - -static const EHPersonality &getCXXPersonality(const TargetInfo &Target, - const LangOptions &L) { - const llvm::Triple &T = Target.getTriple(); - if (T.isWindowsMSVCEnvironment()) - return EHPersonality::MSVC_CxxFrameHandler3; - if (L.SjLjExceptions) - return EHPersonality::GNU_CPlusPlus_SJLJ; - if (L.DWARFExceptions) - return EHPersonality::GNU_CPlusPlus; - if (L.SEHExceptions) - return EHPersonality::GNU_CPlusPlus_SEH; - // Wasm EH is a non-MVP feature for now. - if (Target.hasFeature("exception-handling") && - (T.getArch() == llvm::Triple::wasm32 || - T.getArch() == llvm::Triple::wasm64)) - return EHPersonality::GNU_Wasm_CPlusPlus; - return EHPersonality::GNU_CPlusPlus; -} - -/// Determines the personality function to use when both C++ -/// and Objective-C exceptions are being caught. -static const EHPersonality &getObjCXXPersonality(const TargetInfo &Target, - const LangOptions &L) { - if (Target.getTriple().isWindowsMSVCEnvironment()) - return EHPersonality::MSVC_CxxFrameHandler3; - - switch (L.ObjCRuntime.getKind()) { - // In the fragile ABI, just use C++ exception handling and hope - // they're not doing crazy exception mixing. - case ObjCRuntime::FragileMacOSX: - return getCXXPersonality(Target, L); - - // The ObjC personality defers to the C++ personality for non-ObjC - // handlers. Unlike the C++ case, we use the same personality - // function on targets using (backend-driven) SJLJ EH. - case ObjCRuntime::MacOSX: - case ObjCRuntime::iOS: - case ObjCRuntime::WatchOS: - return getObjCPersonality(Target, L); - - case ObjCRuntime::GNUstep: - return EHPersonality::GNU_ObjCXX; - - // The GCC runtime's personality function inherently doesn't support - // mixed EH. Use the ObjC personality just to avoid returning null. - case ObjCRuntime::GCC: - case ObjCRuntime::ObjFW: - return getObjCPersonality(Target, L); - } - llvm_unreachable("bad runtime kind"); -} - -static const EHPersonality &getSEHPersonalityMSVC(const llvm::Triple &T) { - if (T.getArch() == llvm::Triple::x86) - return EHPersonality::MSVC_except_handler; - return EHPersonality::MSVC_C_specific_handler; -} - -const EHPersonality &EHPersonality::get(CodeGenModule &CGM, - const FunctionDecl *FD) { - const llvm::Triple &T = CGM.getTarget().getTriple(); - const LangOptions &L = CGM.getLangOpts(); - const TargetInfo &Target = CGM.getTarget(); - - // Functions using SEH get an SEH personality. - if (FD && FD->usesSEHTry()) - return getSEHPersonalityMSVC(T); - - if (L.ObjC) - return L.CPlusPlus ? getObjCXXPersonality(Target, L) - : getObjCPersonality(Target, L); - return L.CPlusPlus ? getCXXPersonality(Target, L) - : getCPersonality(Target, L); -} - -const EHPersonality &EHPersonality::get(CodeGenFunction &CGF) { - const auto *FD = CGF.CurCodeDecl; - // For outlined finallys and filters, use the SEH personality in case they - // contain more SEH. This mostly only affects finallys. Filters could - // hypothetically use gnu statement expressions to sneak in nested SEH. - FD = FD ? FD : CGF.CurSEHParent; - return get(CGF.CGM, dyn_cast_or_null<FunctionDecl>(FD)); -} - -static llvm::Constant *getPersonalityFn(CodeGenModule &CGM, - const EHPersonality &Personality) { - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty, true), - Personality.PersonalityFn, - llvm::AttributeList(), /*Local=*/true); -} - -static llvm::Constant *getOpaquePersonalityFn(CodeGenModule &CGM, - const EHPersonality &Personality) { - llvm::Constant *Fn = getPersonalityFn(CGM, Personality); - llvm::PointerType* Int8PtrTy = llvm::PointerType::get( - llvm::Type::getInt8Ty(CGM.getLLVMContext()), - CGM.getDataLayout().getProgramAddressSpace()); - - return llvm::ConstantExpr::getBitCast(Fn, Int8PtrTy); -} - -/// Check whether a landingpad instruction only uses C++ features. -static bool LandingPadHasOnlyCXXUses(llvm::LandingPadInst *LPI) { - for (unsigned I = 0, E = LPI->getNumClauses(); I != E; ++I) { - // Look for something that would've been returned by the ObjC - // runtime's GetEHType() method. - llvm::Value *Val = LPI->getClause(I)->stripPointerCasts(); - if (LPI->isCatch(I)) { - // Check if the catch value has the ObjC prefix. - if (llvm::GlobalVariable *GV = dyn_cast<llvm::GlobalVariable>(Val)) - // ObjC EH selector entries are always global variables with - // names starting like this. - if (GV->getName().startswith("OBJC_EHTYPE")) - return false; - } else { - // Check if any of the filter values have the ObjC prefix. - llvm::Constant *CVal = cast<llvm::Constant>(Val); - for (llvm::User::op_iterator - II = CVal->op_begin(), IE = CVal->op_end(); II != IE; ++II) { - if (llvm::GlobalVariable *GV = - cast<llvm::GlobalVariable>((*II)->stripPointerCasts())) - // ObjC EH selector entries are always global variables with - // names starting like this. - if (GV->getName().startswith("OBJC_EHTYPE")) - return false; - } - } - } - return true; -} - -/// Check whether a personality function could reasonably be swapped -/// for a C++ personality function. -static bool PersonalityHasOnlyCXXUses(llvm::Constant *Fn) { - for (llvm::User *U : Fn->users()) { - // Conditionally white-list bitcasts. - if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(U)) { - if (CE->getOpcode() != llvm::Instruction::BitCast) return false; - if (!PersonalityHasOnlyCXXUses(CE)) - return false; - continue; - } - - // Otherwise it must be a function. - llvm::Function *F = dyn_cast<llvm::Function>(U); - if (!F) return false; - - for (auto BB = F->begin(), E = F->end(); BB != E; ++BB) { - if (BB->isLandingPad()) - if (!LandingPadHasOnlyCXXUses(BB->getLandingPadInst())) - return false; - } - } - - return true; -} - -/// Try to use the C++ personality function in ObjC++. Not doing this -/// can cause some incompatibilities with gcc, which is more -/// aggressive about only using the ObjC++ personality in a function -/// when it really needs it. -void CodeGenModule::SimplifyPersonality() { - // If we're not in ObjC++ -fexceptions, there's nothing to do. - if (!LangOpts.CPlusPlus || !LangOpts.ObjC || !LangOpts.Exceptions) - return; - - // Both the problem this endeavors to fix and the way the logic - // above works is specific to the NeXT runtime. - if (!LangOpts.ObjCRuntime.isNeXTFamily()) - return; - - const EHPersonality &ObjCXX = EHPersonality::get(*this, /*FD=*/nullptr); - const EHPersonality &CXX = getCXXPersonality(getTarget(), LangOpts); - if (&ObjCXX == &CXX) - return; - - assert(std::strcmp(ObjCXX.PersonalityFn, CXX.PersonalityFn) != 0 && - "Different EHPersonalities using the same personality function."); - - llvm::Function *Fn = getModule().getFunction(ObjCXX.PersonalityFn); - - // Nothing to do if it's unused. - if (!Fn || Fn->use_empty()) return; - - // Can't do the optimization if it has non-C++ uses. - if (!PersonalityHasOnlyCXXUses(Fn)) return; - - // Create the C++ personality function and kill off the old - // function. - llvm::Constant *CXXFn = getPersonalityFn(*this, CXX); - - // This can happen if the user is screwing with us. - if (Fn->getType() != CXXFn->getType()) return; - - Fn->replaceAllUsesWith(CXXFn); - Fn->eraseFromParent(); -} - -/// Returns the value to inject into a selector to indicate the -/// presence of a catch-all. -static llvm::Constant *getCatchAllValue(CodeGenFunction &CGF) { - // Possibly we should use @llvm.eh.catch.all.value here. - return llvm::ConstantPointerNull::get(CGF.Int8PtrTy); -} - -namespace { - /// A cleanup to free the exception object if its initialization - /// throws. - struct FreeException final : EHScopeStack::Cleanup { - llvm::Value *exn; - FreeException(llvm::Value *exn) : exn(exn) {} - void Emit(CodeGenFunction &CGF, Flags flags) override { - CGF.EmitNounwindRuntimeCall(getFreeExceptionFn(CGF.CGM), exn); - } - }; -} // end anonymous namespace - -// Emits an exception expression into the given location. This -// differs from EmitAnyExprToMem only in that, if a final copy-ctor -// call is required, an exception within that copy ctor causes -// std::terminate to be invoked. -void CodeGenFunction::EmitAnyExprToExn(const Expr *e, Address addr) { - // Make sure the exception object is cleaned up if there's an - // exception during initialization. - pushFullExprCleanup<FreeException>(EHCleanup, addr.getPointer()); - EHScopeStack::stable_iterator cleanup = EHStack.stable_begin(); - - // __cxa_allocate_exception returns a void*; we need to cast this - // to the appropriate type for the object. - llvm::Type *ty = ConvertTypeForMem(e->getType())->getPointerTo(); - Address typedAddr = Builder.CreateBitCast(addr, ty); - - // FIXME: this isn't quite right! If there's a final unelided call - // to a copy constructor, then according to [except.terminate]p1 we - // must call std::terminate() if that constructor throws, because - // technically that copy occurs after the exception expression is - // evaluated but before the exception is caught. But the best way - // to handle that is to teach EmitAggExpr to do the final copy - // differently if it can't be elided. - EmitAnyExprToMem(e, typedAddr, e->getType().getQualifiers(), - /*IsInit*/ true); - - // Deactivate the cleanup block. - DeactivateCleanupBlock(cleanup, - cast<llvm::Instruction>(typedAddr.getPointer())); -} - -Address CodeGenFunction::getExceptionSlot() { - if (!ExceptionSlot) - ExceptionSlot = CreateTempAlloca(Int8PtrTy, "exn.slot"); - return Address(ExceptionSlot, getPointerAlign()); -} - -Address CodeGenFunction::getEHSelectorSlot() { - if (!EHSelectorSlot) - EHSelectorSlot = CreateTempAlloca(Int32Ty, "ehselector.slot"); - return Address(EHSelectorSlot, CharUnits::fromQuantity(4)); -} - -llvm::Value *CodeGenFunction::getExceptionFromSlot() { - return Builder.CreateLoad(getExceptionSlot(), "exn"); -} - -llvm::Value *CodeGenFunction::getSelectorFromSlot() { - return Builder.CreateLoad(getEHSelectorSlot(), "sel"); -} - -void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E, - bool KeepInsertionPoint) { - if (const Expr *SubExpr = E->getSubExpr()) { - QualType ThrowType = SubExpr->getType(); - if (ThrowType->isObjCObjectPointerType()) { - const Stmt *ThrowStmt = E->getSubExpr(); - const ObjCAtThrowStmt S(E->getExprLoc(), const_cast<Stmt *>(ThrowStmt)); - CGM.getObjCRuntime().EmitThrowStmt(*this, S, false); - } else { - CGM.getCXXABI().emitThrow(*this, E); - } - } else { - CGM.getCXXABI().emitRethrow(*this, /*isNoReturn=*/true); - } - - // throw is an expression, and the expression emitters expect us - // to leave ourselves at a valid insertion point. - if (KeepInsertionPoint) - EmitBlock(createBasicBlock("throw.cont")); -} - -void CodeGenFunction::EmitStartEHSpec(const Decl *D) { - if (!CGM.getLangOpts().CXXExceptions) - return; - - const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D); - if (!FD) { - // Check if CapturedDecl is nothrow and create terminate scope for it. - if (const CapturedDecl* CD = dyn_cast_or_null<CapturedDecl>(D)) { - if (CD->isNothrow()) - EHStack.pushTerminate(); - } - return; - } - const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>(); - if (!Proto) - return; - - ExceptionSpecificationType EST = Proto->getExceptionSpecType(); - if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot) { - // noexcept functions are simple terminate scopes. - EHStack.pushTerminate(); - } else if (EST == EST_Dynamic || EST == EST_DynamicNone) { - // TODO: Revisit exception specifications for the MS ABI. There is a way to - // encode these in an object file but MSVC doesn't do anything with it. - if (getTarget().getCXXABI().isMicrosoft()) - return; - unsigned NumExceptions = Proto->getNumExceptions(); - EHFilterScope *Filter = EHStack.pushFilter(NumExceptions); - - for (unsigned I = 0; I != NumExceptions; ++I) { - QualType Ty = Proto->getExceptionType(I); - QualType ExceptType = Ty.getNonReferenceType().getUnqualifiedType(); - llvm::Value *EHType = CGM.GetAddrOfRTTIDescriptor(ExceptType, - /*ForEH=*/true); - Filter->setFilter(I, EHType); - } - } -} - -/// Emit the dispatch block for a filter scope if necessary. -static void emitFilterDispatchBlock(CodeGenFunction &CGF, - EHFilterScope &filterScope) { - llvm::BasicBlock *dispatchBlock = filterScope.getCachedEHDispatchBlock(); - if (!dispatchBlock) return; - if (dispatchBlock->use_empty()) { - delete dispatchBlock; - return; - } - - CGF.EmitBlockAfterUses(dispatchBlock); - - // If this isn't a catch-all filter, we need to check whether we got - // here because the filter triggered. - if (filterScope.getNumFilters()) { - // Load the selector value. - llvm::Value *selector = CGF.getSelectorFromSlot(); - llvm::BasicBlock *unexpectedBB = CGF.createBasicBlock("ehspec.unexpected"); - - llvm::Value *zero = CGF.Builder.getInt32(0); - llvm::Value *failsFilter = - CGF.Builder.CreateICmpSLT(selector, zero, "ehspec.fails"); - CGF.Builder.CreateCondBr(failsFilter, unexpectedBB, - CGF.getEHResumeBlock(false)); - - CGF.EmitBlock(unexpectedBB); - } - - // Call __cxa_call_unexpected. This doesn't need to be an invoke - // because __cxa_call_unexpected magically filters exceptions - // according to the last landing pad the exception was thrown - // into. Seriously. - llvm::Value *exn = CGF.getExceptionFromSlot(); - CGF.EmitRuntimeCall(getUnexpectedFn(CGF.CGM), exn) - ->setDoesNotReturn(); - CGF.Builder.CreateUnreachable(); -} - -void CodeGenFunction::EmitEndEHSpec(const Decl *D) { - if (!CGM.getLangOpts().CXXExceptions) - return; - - const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D); - if (!FD) { - // Check if CapturedDecl is nothrow and pop terminate scope for it. - if (const CapturedDecl* CD = dyn_cast_or_null<CapturedDecl>(D)) { - if (CD->isNothrow()) - EHStack.popTerminate(); - } - return; - } - const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>(); - if (!Proto) - return; - - ExceptionSpecificationType EST = Proto->getExceptionSpecType(); - if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot) { - EHStack.popTerminate(); - } else if (EST == EST_Dynamic || EST == EST_DynamicNone) { - // TODO: Revisit exception specifications for the MS ABI. There is a way to - // encode these in an object file but MSVC doesn't do anything with it. - if (getTarget().getCXXABI().isMicrosoft()) - return; - EHFilterScope &filterScope = cast<EHFilterScope>(*EHStack.begin()); - emitFilterDispatchBlock(*this, filterScope); - EHStack.popFilter(); - } -} - -void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { - EnterCXXTryStmt(S); - EmitStmt(S.getTryBlock()); - ExitCXXTryStmt(S); -} - -void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { - unsigned NumHandlers = S.getNumHandlers(); - EHCatchScope *CatchScope = EHStack.pushCatch(NumHandlers); - - for (unsigned I = 0; I != NumHandlers; ++I) { - const CXXCatchStmt *C = S.getHandler(I); - - llvm::BasicBlock *Handler = createBasicBlock("catch"); - if (C->getExceptionDecl()) { - // FIXME: Dropping the reference type on the type into makes it - // impossible to correctly implement catch-by-reference - // semantics for pointers. Unfortunately, this is what all - // existing compilers do, and it's not clear that the standard - // personality routine is capable of doing this right. See C++ DR 388: - // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#388 - Qualifiers CaughtTypeQuals; - QualType CaughtType = CGM.getContext().getUnqualifiedArrayType( - C->getCaughtType().getNonReferenceType(), CaughtTypeQuals); - - CatchTypeInfo TypeInfo{nullptr, 0}; - if (CaughtType->isObjCObjectPointerType()) - TypeInfo.RTTI = CGM.getObjCRuntime().GetEHType(CaughtType); - else - TypeInfo = CGM.getCXXABI().getAddrOfCXXCatchHandlerType( - CaughtType, C->getCaughtType()); - CatchScope->setHandler(I, TypeInfo, Handler); - } else { - // No exception decl indicates '...', a catch-all. - CatchScope->setHandler(I, CGM.getCXXABI().getCatchAllTypeInfo(), Handler); - } - } -} - -llvm::BasicBlock * -CodeGenFunction::getEHDispatchBlock(EHScopeStack::stable_iterator si) { - if (EHPersonality::get(*this).usesFuncletPads()) - return getFuncletEHDispatchBlock(si); - - // The dispatch block for the end of the scope chain is a block that - // just resumes unwinding. - if (si == EHStack.stable_end()) - return getEHResumeBlock(true); - - // Otherwise, we should look at the actual scope. - EHScope &scope = *EHStack.find(si); - - llvm::BasicBlock *dispatchBlock = scope.getCachedEHDispatchBlock(); - if (!dispatchBlock) { - switch (scope.getKind()) { - case EHScope::Catch: { - // Apply a special case to a single catch-all. - EHCatchScope &catchScope = cast<EHCatchScope>(scope); - if (catchScope.getNumHandlers() == 1 && - catchScope.getHandler(0).isCatchAll()) { - dispatchBlock = catchScope.getHandler(0).Block; - - // Otherwise, make a dispatch block. - } else { - dispatchBlock = createBasicBlock("catch.dispatch"); - } - break; - } - - case EHScope::Cleanup: - dispatchBlock = createBasicBlock("ehcleanup"); - break; - - case EHScope::Filter: - dispatchBlock = createBasicBlock("filter.dispatch"); - break; - - case EHScope::Terminate: - dispatchBlock = getTerminateHandler(); - break; - - case EHScope::PadEnd: - llvm_unreachable("PadEnd unnecessary for Itanium!"); - } - scope.setCachedEHDispatchBlock(dispatchBlock); - } - return dispatchBlock; -} - -llvm::BasicBlock * -CodeGenFunction::getFuncletEHDispatchBlock(EHScopeStack::stable_iterator SI) { - // Returning nullptr indicates that the previous dispatch block should unwind - // to caller. - if (SI == EHStack.stable_end()) - return nullptr; - - // Otherwise, we should look at the actual scope. - EHScope &EHS = *EHStack.find(SI); - - llvm::BasicBlock *DispatchBlock = EHS.getCachedEHDispatchBlock(); - if (DispatchBlock) - return DispatchBlock; - - if (EHS.getKind() == EHScope::Terminate) - DispatchBlock = getTerminateFunclet(); - else - DispatchBlock = createBasicBlock(); - CGBuilderTy Builder(*this, DispatchBlock); - - switch (EHS.getKind()) { - case EHScope::Catch: - DispatchBlock->setName("catch.dispatch"); - break; - - case EHScope::Cleanup: - DispatchBlock->setName("ehcleanup"); - break; - - case EHScope::Filter: - llvm_unreachable("exception specifications not handled yet!"); - - case EHScope::Terminate: - DispatchBlock->setName("terminate"); - break; - - case EHScope::PadEnd: - llvm_unreachable("PadEnd dispatch block missing!"); - } - EHS.setCachedEHDispatchBlock(DispatchBlock); - return DispatchBlock; -} - -/// Check whether this is a non-EH scope, i.e. a scope which doesn't -/// affect exception handling. Currently, the only non-EH scopes are -/// normal-only cleanup scopes. -static bool isNonEHScope(const EHScope &S) { - switch (S.getKind()) { - case EHScope::Cleanup: - return !cast<EHCleanupScope>(S).isEHCleanup(); - case EHScope::Filter: - case EHScope::Catch: - case EHScope::Terminate: - case EHScope::PadEnd: - return false; - } - - llvm_unreachable("Invalid EHScope Kind!"); -} - -llvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() { - assert(EHStack.requiresLandingPad()); - assert(!EHStack.empty()); - - // If exceptions are disabled and SEH is not in use, then there is no invoke - // destination. SEH "works" even if exceptions are off. In practice, this - // means that C++ destructors and other EH cleanups don't run, which is - // consistent with MSVC's behavior. - const LangOptions &LO = CGM.getLangOpts(); - if (!LO.Exceptions) { - if (!LO.Borland && !LO.MicrosoftExt) - return nullptr; - if (!currentFunctionUsesSEHTry()) - return nullptr; - } - - // CUDA device code doesn't have exceptions. - if (LO.CUDA && LO.CUDAIsDevice) - return nullptr; - - // Check the innermost scope for a cached landing pad. If this is - // a non-EH cleanup, we'll check enclosing scopes in EmitLandingPad. - llvm::BasicBlock *LP = EHStack.begin()->getCachedLandingPad(); - if (LP) return LP; - - const EHPersonality &Personality = EHPersonality::get(*this); - - if (!CurFn->hasPersonalityFn()) - CurFn->setPersonalityFn(getOpaquePersonalityFn(CGM, Personality)); - - if (Personality.usesFuncletPads()) { - // We don't need separate landing pads in the funclet model. - LP = getEHDispatchBlock(EHStack.getInnermostEHScope()); - } else { - // Build the landing pad for this scope. - LP = EmitLandingPad(); - } - - assert(LP); - - // Cache the landing pad on the innermost scope. If this is a - // non-EH scope, cache the landing pad on the enclosing scope, too. - for (EHScopeStack::iterator ir = EHStack.begin(); true; ++ir) { - ir->setCachedLandingPad(LP); - if (!isNonEHScope(*ir)) break; - } - - return LP; -} - -llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { - assert(EHStack.requiresLandingPad()); - - EHScope &innermostEHScope = *EHStack.find(EHStack.getInnermostEHScope()); - switch (innermostEHScope.getKind()) { - case EHScope::Terminate: - return getTerminateLandingPad(); - - case EHScope::PadEnd: - llvm_unreachable("PadEnd unnecessary for Itanium!"); - - case EHScope::Catch: - case EHScope::Cleanup: - case EHScope::Filter: - if (llvm::BasicBlock *lpad = innermostEHScope.getCachedLandingPad()) - return lpad; - } - - // Save the current IR generation state. - CGBuilderTy::InsertPoint savedIP = Builder.saveAndClearIP(); - auto DL = ApplyDebugLocation::CreateDefaultArtificial(*this, CurEHLocation); - - // Create and configure the landing pad. - llvm::BasicBlock *lpad = createBasicBlock("lpad"); - EmitBlock(lpad); - - llvm::LandingPadInst *LPadInst = - Builder.CreateLandingPad(llvm::StructType::get(Int8PtrTy, Int32Ty), 0); - - llvm::Value *LPadExn = Builder.CreateExtractValue(LPadInst, 0); - Builder.CreateStore(LPadExn, getExceptionSlot()); - llvm::Value *LPadSel = Builder.CreateExtractValue(LPadInst, 1); - Builder.CreateStore(LPadSel, getEHSelectorSlot()); - - // Save the exception pointer. It's safe to use a single exception - // pointer per function because EH cleanups can never have nested - // try/catches. - // Build the landingpad instruction. - - // Accumulate all the handlers in scope. - bool hasCatchAll = false; - bool hasCleanup = false; - bool hasFilter = false; - SmallVector<llvm::Value*, 4> filterTypes; - llvm::SmallPtrSet<llvm::Value*, 4> catchTypes; - for (EHScopeStack::iterator I = EHStack.begin(), E = EHStack.end(); I != E; - ++I) { - - switch (I->getKind()) { - case EHScope::Cleanup: - // If we have a cleanup, remember that. - hasCleanup = (hasCleanup || cast<EHCleanupScope>(*I).isEHCleanup()); - continue; - - case EHScope::Filter: { - assert(I.next() == EHStack.end() && "EH filter is not end of EH stack"); - assert(!hasCatchAll && "EH filter reached after catch-all"); - - // Filter scopes get added to the landingpad in weird ways. - EHFilterScope &filter = cast<EHFilterScope>(*I); - hasFilter = true; - - // Add all the filter values. - for (unsigned i = 0, e = filter.getNumFilters(); i != e; ++i) - filterTypes.push_back(filter.getFilter(i)); - goto done; - } - - case EHScope::Terminate: - // Terminate scopes are basically catch-alls. - assert(!hasCatchAll); - hasCatchAll = true; - goto done; - - case EHScope::Catch: - break; - - case EHScope::PadEnd: - llvm_unreachable("PadEnd unnecessary for Itanium!"); - } - - EHCatchScope &catchScope = cast<EHCatchScope>(*I); - for (unsigned hi = 0, he = catchScope.getNumHandlers(); hi != he; ++hi) { - EHCatchScope::Handler handler = catchScope.getHandler(hi); - assert(handler.Type.Flags == 0 && - "landingpads do not support catch handler flags"); - - // If this is a catch-all, register that and abort. - if (!handler.Type.RTTI) { - assert(!hasCatchAll); - hasCatchAll = true; - goto done; - } - - // Check whether we already have a handler for this type. - if (catchTypes.insert(handler.Type.RTTI).second) - // If not, add it directly to the landingpad. - LPadInst->addClause(handler.Type.RTTI); - } - } - - done: - // If we have a catch-all, add null to the landingpad. - assert(!(hasCatchAll && hasFilter)); - if (hasCatchAll) { - LPadInst->addClause(getCatchAllValue(*this)); - - // If we have an EH filter, we need to add those handlers in the - // right place in the landingpad, which is to say, at the end. - } else if (hasFilter) { - // Create a filter expression: a constant array indicating which filter - // types there are. The personality routine only lands here if the filter - // doesn't match. - SmallVector<llvm::Constant*, 8> Filters; - llvm::ArrayType *AType = - llvm::ArrayType::get(!filterTypes.empty() ? - filterTypes[0]->getType() : Int8PtrTy, - filterTypes.size()); - - for (unsigned i = 0, e = filterTypes.size(); i != e; ++i) - Filters.push_back(cast<llvm::Constant>(filterTypes[i])); - llvm::Constant *FilterArray = llvm::ConstantArray::get(AType, Filters); - LPadInst->addClause(FilterArray); - - // Also check whether we need a cleanup. - if (hasCleanup) - LPadInst->setCleanup(true); - - // Otherwise, signal that we at least have cleanups. - } else if (hasCleanup) { - LPadInst->setCleanup(true); - } - - assert((LPadInst->getNumClauses() > 0 || LPadInst->isCleanup()) && - "landingpad instruction has no clauses!"); - - // Tell the backend how to generate the landing pad. - Builder.CreateBr(getEHDispatchBlock(EHStack.getInnermostEHScope())); - - // Restore the old IR generation state. - Builder.restoreIP(savedIP); - - return lpad; -} - -static void emitCatchPadBlock(CodeGenFunction &CGF, EHCatchScope &CatchScope) { - llvm::BasicBlock *DispatchBlock = CatchScope.getCachedEHDispatchBlock(); - assert(DispatchBlock); - - CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveIP(); - CGF.EmitBlockAfterUses(DispatchBlock); - - llvm::Value *ParentPad = CGF.CurrentFuncletPad; - if (!ParentPad) - ParentPad = llvm::ConstantTokenNone::get(CGF.getLLVMContext()); - llvm::BasicBlock *UnwindBB = - CGF.getEHDispatchBlock(CatchScope.getEnclosingEHScope()); - - unsigned NumHandlers = CatchScope.getNumHandlers(); - llvm::CatchSwitchInst *CatchSwitch = - CGF.Builder.CreateCatchSwitch(ParentPad, UnwindBB, NumHandlers); - - // Test against each of the exception types we claim to catch. - for (unsigned I = 0; I < NumHandlers; ++I) { - const EHCatchScope::Handler &Handler = CatchScope.getHandler(I); - - CatchTypeInfo TypeInfo = Handler.Type; - if (!TypeInfo.RTTI) - TypeInfo.RTTI = llvm::Constant::getNullValue(CGF.VoidPtrTy); - - CGF.Builder.SetInsertPoint(Handler.Block); - - if (EHPersonality::get(CGF).isMSVCXXPersonality()) { - CGF.Builder.CreateCatchPad( - CatchSwitch, {TypeInfo.RTTI, CGF.Builder.getInt32(TypeInfo.Flags), - llvm::Constant::getNullValue(CGF.VoidPtrTy)}); - } else { - CGF.Builder.CreateCatchPad(CatchSwitch, {TypeInfo.RTTI}); - } - - CatchSwitch->addHandler(Handler.Block); - } - CGF.Builder.restoreIP(SavedIP); -} - -// Wasm uses Windows-style EH instructions, but it merges all catch clauses into -// one big catchpad, within which we use Itanium's landingpad-style selector -// comparison instructions. -static void emitWasmCatchPadBlock(CodeGenFunction &CGF, - EHCatchScope &CatchScope) { - llvm::BasicBlock *DispatchBlock = CatchScope.getCachedEHDispatchBlock(); - assert(DispatchBlock); - - CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveIP(); - CGF.EmitBlockAfterUses(DispatchBlock); - - llvm::Value *ParentPad = CGF.CurrentFuncletPad; - if (!ParentPad) - ParentPad = llvm::ConstantTokenNone::get(CGF.getLLVMContext()); - llvm::BasicBlock *UnwindBB = - CGF.getEHDispatchBlock(CatchScope.getEnclosingEHScope()); - - unsigned NumHandlers = CatchScope.getNumHandlers(); - llvm::CatchSwitchInst *CatchSwitch = - CGF.Builder.CreateCatchSwitch(ParentPad, UnwindBB, NumHandlers); - - // We don't use a landingpad instruction, so generate intrinsic calls to - // provide exception and selector values. - llvm::BasicBlock *WasmCatchStartBlock = CGF.createBasicBlock("catch.start"); - CatchSwitch->addHandler(WasmCatchStartBlock); - CGF.EmitBlockAfterUses(WasmCatchStartBlock); - - // Create a catchpad instruction. - SmallVector<llvm::Value *, 4> CatchTypes; - for (unsigned I = 0, E = NumHandlers; I < E; ++I) { - const EHCatchScope::Handler &Handler = CatchScope.getHandler(I); - CatchTypeInfo TypeInfo = Handler.Type; - if (!TypeInfo.RTTI) - TypeInfo.RTTI = llvm::Constant::getNullValue(CGF.VoidPtrTy); - CatchTypes.push_back(TypeInfo.RTTI); - } - auto *CPI = CGF.Builder.CreateCatchPad(CatchSwitch, CatchTypes); - - // Create calls to wasm.get.exception and wasm.get.ehselector intrinsics. - // Before they are lowered appropriately later, they provide values for the - // exception and selector. - llvm::Value *GetExnFn = - CGF.CGM.getIntrinsic(llvm::Intrinsic::wasm_get_exception); - llvm::Value *GetSelectorFn = - CGF.CGM.getIntrinsic(llvm::Intrinsic::wasm_get_ehselector); - llvm::CallInst *Exn = CGF.Builder.CreateCall(GetExnFn, CPI); - CGF.Builder.CreateStore(Exn, CGF.getExceptionSlot()); - llvm::CallInst *Selector = CGF.Builder.CreateCall(GetSelectorFn, CPI); - - llvm::Value *TypeIDFn = CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for); - - // If there's only a single catch-all, branch directly to its handler. - if (CatchScope.getNumHandlers() == 1 && - CatchScope.getHandler(0).isCatchAll()) { - CGF.Builder.CreateBr(CatchScope.getHandler(0).Block); - CGF.Builder.restoreIP(SavedIP); - return; - } - - // Test against each of the exception types we claim to catch. - for (unsigned I = 0, E = NumHandlers;; ++I) { - assert(I < E && "ran off end of handlers!"); - const EHCatchScope::Handler &Handler = CatchScope.getHandler(I); - CatchTypeInfo TypeInfo = Handler.Type; - if (!TypeInfo.RTTI) - TypeInfo.RTTI = llvm::Constant::getNullValue(CGF.VoidPtrTy); - - // Figure out the next block. - llvm::BasicBlock *NextBlock; - - bool EmitNextBlock = false, NextIsEnd = false; - - // If this is the last handler, we're at the end, and the next block is a - // block that contains a call to the rethrow function, so we can unwind to - // the enclosing EH scope. The call itself will be generated later. - if (I + 1 == E) { - NextBlock = CGF.createBasicBlock("rethrow"); - EmitNextBlock = true; - NextIsEnd = true; - - // If the next handler is a catch-all, we're at the end, and the - // next block is that handler. - } else if (CatchScope.getHandler(I + 1).isCatchAll()) { - NextBlock = CatchScope.getHandler(I + 1).Block; - NextIsEnd = true; - - // Otherwise, we're not at the end and we need a new block. - } else { - NextBlock = CGF.createBasicBlock("catch.fallthrough"); - EmitNextBlock = true; - } - - // Figure out the catch type's index in the LSDA's type table. - llvm::CallInst *TypeIndex = CGF.Builder.CreateCall(TypeIDFn, TypeInfo.RTTI); - TypeIndex->setDoesNotThrow(); - - llvm::Value *MatchesTypeIndex = - CGF.Builder.CreateICmpEQ(Selector, TypeIndex, "matches"); - CGF.Builder.CreateCondBr(MatchesTypeIndex, Handler.Block, NextBlock); - - if (EmitNextBlock) - CGF.EmitBlock(NextBlock); - if (NextIsEnd) - break; - } - - CGF.Builder.restoreIP(SavedIP); -} - -/// Emit the structure of the dispatch block for the given catch scope. -/// It is an invariant that the dispatch block already exists. -static void emitCatchDispatchBlock(CodeGenFunction &CGF, - EHCatchScope &catchScope) { - if (EHPersonality::get(CGF).isWasmPersonality()) - return emitWasmCatchPadBlock(CGF, catchScope); - if (EHPersonality::get(CGF).usesFuncletPads()) - return emitCatchPadBlock(CGF, catchScope); - - llvm::BasicBlock *dispatchBlock = catchScope.getCachedEHDispatchBlock(); - assert(dispatchBlock); - - // If there's only a single catch-all, getEHDispatchBlock returned - // that catch-all as the dispatch block. - if (catchScope.getNumHandlers() == 1 && - catchScope.getHandler(0).isCatchAll()) { - assert(dispatchBlock == catchScope.getHandler(0).Block); - return; - } - - CGBuilderTy::InsertPoint savedIP = CGF.Builder.saveIP(); - CGF.EmitBlockAfterUses(dispatchBlock); - - // Select the right handler. - llvm::Value *llvm_eh_typeid_for = - CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for); - - // Load the selector value. - llvm::Value *selector = CGF.getSelectorFromSlot(); - - // Test against each of the exception types we claim to catch. - for (unsigned i = 0, e = catchScope.getNumHandlers(); ; ++i) { - assert(i < e && "ran off end of handlers!"); - const EHCatchScope::Handler &handler = catchScope.getHandler(i); - - llvm::Value *typeValue = handler.Type.RTTI; - assert(handler.Type.Flags == 0 && - "landingpads do not support catch handler flags"); - assert(typeValue && "fell into catch-all case!"); - typeValue = CGF.Builder.CreateBitCast(typeValue, CGF.Int8PtrTy); - - // Figure out the next block. - bool nextIsEnd; - llvm::BasicBlock *nextBlock; - - // If this is the last handler, we're at the end, and the next - // block is the block for the enclosing EH scope. - if (i + 1 == e) { - nextBlock = CGF.getEHDispatchBlock(catchScope.getEnclosingEHScope()); - nextIsEnd = true; - - // If the next handler is a catch-all, we're at the end, and the - // next block is that handler. - } else if (catchScope.getHandler(i+1).isCatchAll()) { - nextBlock = catchScope.getHandler(i+1).Block; - nextIsEnd = true; - - // Otherwise, we're not at the end and we need a new block. - } else { - nextBlock = CGF.createBasicBlock("catch.fallthrough"); - nextIsEnd = false; - } - - // Figure out the catch type's index in the LSDA's type table. - llvm::CallInst *typeIndex = - CGF.Builder.CreateCall(llvm_eh_typeid_for, typeValue); - typeIndex->setDoesNotThrow(); - - llvm::Value *matchesTypeIndex = - CGF.Builder.CreateICmpEQ(selector, typeIndex, "matches"); - CGF.Builder.CreateCondBr(matchesTypeIndex, handler.Block, nextBlock); - - // If the next handler is a catch-all, we're completely done. - if (nextIsEnd) { - CGF.Builder.restoreIP(savedIP); - return; - } - // Otherwise we need to emit and continue at that block. - CGF.EmitBlock(nextBlock); - } -} - -void CodeGenFunction::popCatchScope() { - EHCatchScope &catchScope = cast<EHCatchScope>(*EHStack.begin()); - if (catchScope.hasEHBranches()) - emitCatchDispatchBlock(*this, catchScope); - EHStack.popCatch(); -} - -void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { - unsigned NumHandlers = S.getNumHandlers(); - EHCatchScope &CatchScope = cast<EHCatchScope>(*EHStack.begin()); - assert(CatchScope.getNumHandlers() == NumHandlers); - llvm::BasicBlock *DispatchBlock = CatchScope.getCachedEHDispatchBlock(); - - // If the catch was not required, bail out now. - if (!CatchScope.hasEHBranches()) { - CatchScope.clearHandlerBlocks(); - EHStack.popCatch(); - return; - } - - // Emit the structure of the EH dispatch for this catch. - emitCatchDispatchBlock(*this, CatchScope); - - // Copy the handler blocks off before we pop the EH stack. Emitting - // the handlers might scribble on this memory. - SmallVector<EHCatchScope::Handler, 8> Handlers( - CatchScope.begin(), CatchScope.begin() + NumHandlers); - - EHStack.popCatch(); - - // The fall-through block. - llvm::BasicBlock *ContBB = createBasicBlock("try.cont"); - - // We just emitted the body of the try; jump to the continue block. - if (HaveInsertPoint()) - Builder.CreateBr(ContBB); - - // Determine if we need an implicit rethrow for all these catch handlers; - // see the comment below. - bool doImplicitRethrow = false; - if (IsFnTryBlock) - doImplicitRethrow = isa<CXXDestructorDecl>(CurCodeDecl) || - isa<CXXConstructorDecl>(CurCodeDecl); - - // Wasm uses Windows-style EH instructions, but merges all catch clauses into - // one big catchpad. So we save the old funclet pad here before we traverse - // each catch handler. - SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad( - CurrentFuncletPad); - llvm::BasicBlock *WasmCatchStartBlock = nullptr; - if (EHPersonality::get(*this).isWasmPersonality()) { - auto *CatchSwitch = - cast<llvm::CatchSwitchInst>(DispatchBlock->getFirstNonPHI()); - WasmCatchStartBlock = CatchSwitch->hasUnwindDest() - ? CatchSwitch->getSuccessor(1) - : CatchSwitch->getSuccessor(0); - auto *CPI = cast<llvm::CatchPadInst>(WasmCatchStartBlock->getFirstNonPHI()); - CurrentFuncletPad = CPI; - } - - // Perversely, we emit the handlers backwards precisely because we - // want them to appear in source order. In all of these cases, the - // catch block will have exactly one predecessor, which will be a - // particular block in the catch dispatch. However, in the case of - // a catch-all, one of the dispatch blocks will branch to two - // different handlers, and EmitBlockAfterUses will cause the second - // handler to be moved before the first. - bool HasCatchAll = false; - for (unsigned I = NumHandlers; I != 0; --I) { - HasCatchAll |= Handlers[I - 1].isCatchAll(); - llvm::BasicBlock *CatchBlock = Handlers[I-1].Block; - EmitBlockAfterUses(CatchBlock); - - // Catch the exception if this isn't a catch-all. - const CXXCatchStmt *C = S.getHandler(I-1); - - // Enter a cleanup scope, including the catch variable and the - // end-catch. - RunCleanupsScope CatchScope(*this); - - // Initialize the catch variable and set up the cleanups. - SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad( - CurrentFuncletPad); - CGM.getCXXABI().emitBeginCatch(*this, C); - - // Emit the PGO counter increment. - incrementProfileCounter(C); - - // Perform the body of the catch. - EmitStmt(C->getHandlerBlock()); - - // [except.handle]p11: - // The currently handled exception is rethrown if control - // reaches the end of a handler of the function-try-block of a - // constructor or destructor. - - // It is important that we only do this on fallthrough and not on - // return. Note that it's illegal to put a return in a - // constructor function-try-block's catch handler (p14), so this - // really only applies to destructors. - if (doImplicitRethrow && HaveInsertPoint()) { - CGM.getCXXABI().emitRethrow(*this, /*isNoReturn*/false); - Builder.CreateUnreachable(); - Builder.ClearInsertionPoint(); - } - - // Fall out through the catch cleanups. - CatchScope.ForceCleanup(); - - // Branch out of the try. - if (HaveInsertPoint()) - Builder.CreateBr(ContBB); - } - - // Because in wasm we merge all catch clauses into one big catchpad, in case - // none of the types in catch handlers matches after we test against each of - // them, we should unwind to the next EH enclosing scope. We generate a call - // to rethrow function here to do that. - if (EHPersonality::get(*this).isWasmPersonality() && !HasCatchAll) { - assert(WasmCatchStartBlock); - // Navigate for the "rethrow" block we created in emitWasmCatchPadBlock(). - // Wasm uses landingpad-style conditional branches to compare selectors, so - // we follow the false destination for each of the cond branches to reach - // the rethrow block. - llvm::BasicBlock *RethrowBlock = WasmCatchStartBlock; - while (llvm::Instruction *TI = RethrowBlock->getTerminator()) { - auto *BI = cast<llvm::BranchInst>(TI); - assert(BI->isConditional()); - RethrowBlock = BI->getSuccessor(1); - } - assert(RethrowBlock != WasmCatchStartBlock && RethrowBlock->empty()); - Builder.SetInsertPoint(RethrowBlock); - CGM.getCXXABI().emitRethrow(*this, /*isNoReturn=*/true); - } - - EmitBlock(ContBB); - incrementProfileCounter(&S); -} - -namespace { - struct CallEndCatchForFinally final : EHScopeStack::Cleanup { - llvm::Value *ForEHVar; - llvm::Value *EndCatchFn; - CallEndCatchForFinally(llvm::Value *ForEHVar, llvm::Value *EndCatchFn) - : ForEHVar(ForEHVar), EndCatchFn(EndCatchFn) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - llvm::BasicBlock *EndCatchBB = CGF.createBasicBlock("finally.endcatch"); - llvm::BasicBlock *CleanupContBB = - CGF.createBasicBlock("finally.cleanup.cont"); - - llvm::Value *ShouldEndCatch = - CGF.Builder.CreateFlagLoad(ForEHVar, "finally.endcatch"); - CGF.Builder.CreateCondBr(ShouldEndCatch, EndCatchBB, CleanupContBB); - CGF.EmitBlock(EndCatchBB); - CGF.EmitRuntimeCallOrInvoke(EndCatchFn); // catch-all, so might throw - CGF.EmitBlock(CleanupContBB); - } - }; - - struct PerformFinally final : EHScopeStack::Cleanup { - const Stmt *Body; - llvm::Value *ForEHVar; - llvm::Value *EndCatchFn; - llvm::Value *RethrowFn; - llvm::Value *SavedExnVar; - - PerformFinally(const Stmt *Body, llvm::Value *ForEHVar, - llvm::Value *EndCatchFn, - llvm::Value *RethrowFn, llvm::Value *SavedExnVar) - : Body(Body), ForEHVar(ForEHVar), EndCatchFn(EndCatchFn), - RethrowFn(RethrowFn), SavedExnVar(SavedExnVar) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - // Enter a cleanup to call the end-catch function if one was provided. - if (EndCatchFn) - CGF.EHStack.pushCleanup<CallEndCatchForFinally>(NormalAndEHCleanup, - ForEHVar, EndCatchFn); - - // Save the current cleanup destination in case there are - // cleanups in the finally block. - llvm::Value *SavedCleanupDest = - CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot(), - "cleanup.dest.saved"); - - // Emit the finally block. - CGF.EmitStmt(Body); - - // If the end of the finally is reachable, check whether this was - // for EH. If so, rethrow. - if (CGF.HaveInsertPoint()) { - llvm::BasicBlock *RethrowBB = CGF.createBasicBlock("finally.rethrow"); - llvm::BasicBlock *ContBB = CGF.createBasicBlock("finally.cont"); - - llvm::Value *ShouldRethrow = - CGF.Builder.CreateFlagLoad(ForEHVar, "finally.shouldthrow"); - CGF.Builder.CreateCondBr(ShouldRethrow, RethrowBB, ContBB); - - CGF.EmitBlock(RethrowBB); - if (SavedExnVar) { - CGF.EmitRuntimeCallOrInvoke(RethrowFn, - CGF.Builder.CreateAlignedLoad(SavedExnVar, CGF.getPointerAlign())); - } else { - CGF.EmitRuntimeCallOrInvoke(RethrowFn); - } - CGF.Builder.CreateUnreachable(); - - CGF.EmitBlock(ContBB); - - // Restore the cleanup destination. - CGF.Builder.CreateStore(SavedCleanupDest, - CGF.getNormalCleanupDestSlot()); - } - - // Leave the end-catch cleanup. As an optimization, pretend that - // the fallthrough path was inaccessible; we've dynamically proven - // that we're not in the EH case along that path. - if (EndCatchFn) { - CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP(); - CGF.PopCleanupBlock(); - CGF.Builder.restoreIP(SavedIP); - } - - // Now make sure we actually have an insertion point or the - // cleanup gods will hate us. - CGF.EnsureInsertPoint(); - } - }; -} // end anonymous namespace - -/// Enters a finally block for an implementation using zero-cost -/// exceptions. This is mostly general, but hard-codes some -/// language/ABI-specific behavior in the catch-all sections. -void CodeGenFunction::FinallyInfo::enter(CodeGenFunction &CGF, - const Stmt *body, - llvm::Constant *beginCatchFn, - llvm::Constant *endCatchFn, - llvm::Constant *rethrowFn) { - assert((beginCatchFn != nullptr) == (endCatchFn != nullptr) && - "begin/end catch functions not paired"); - assert(rethrowFn && "rethrow function is required"); - - BeginCatchFn = beginCatchFn; - - // The rethrow function has one of the following two types: - // void (*)() - // void (*)(void*) - // In the latter case we need to pass it the exception object. - // But we can't use the exception slot because the @finally might - // have a landing pad (which would overwrite the exception slot). - llvm::FunctionType *rethrowFnTy = - cast<llvm::FunctionType>( - cast<llvm::PointerType>(rethrowFn->getType())->getElementType()); - SavedExnVar = nullptr; - if (rethrowFnTy->getNumParams()) - SavedExnVar = CGF.CreateTempAlloca(CGF.Int8PtrTy, "finally.exn"); - - // A finally block is a statement which must be executed on any edge - // out of a given scope. Unlike a cleanup, the finally block may - // contain arbitrary control flow leading out of itself. In - // addition, finally blocks should always be executed, even if there - // are no catch handlers higher on the stack. Therefore, we - // surround the protected scope with a combination of a normal - // cleanup (to catch attempts to break out of the block via normal - // control flow) and an EH catch-all (semantically "outside" any try - // statement to which the finally block might have been attached). - // The finally block itself is generated in the context of a cleanup - // which conditionally leaves the catch-all. - - // Jump destination for performing the finally block on an exception - // edge. We'll never actually reach this block, so unreachable is - // fine. - RethrowDest = CGF.getJumpDestInCurrentScope(CGF.getUnreachableBlock()); - - // Whether the finally block is being executed for EH purposes. - ForEHVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), "finally.for-eh"); - CGF.Builder.CreateFlagStore(false, ForEHVar); - - // Enter a normal cleanup which will perform the @finally block. - CGF.EHStack.pushCleanup<PerformFinally>(NormalCleanup, body, - ForEHVar, endCatchFn, - rethrowFn, SavedExnVar); - - // Enter a catch-all scope. - llvm::BasicBlock *catchBB = CGF.createBasicBlock("finally.catchall"); - EHCatchScope *catchScope = CGF.EHStack.pushCatch(1); - catchScope->setCatchAllHandler(0, catchBB); -} - -void CodeGenFunction::FinallyInfo::exit(CodeGenFunction &CGF) { - // Leave the finally catch-all. - EHCatchScope &catchScope = cast<EHCatchScope>(*CGF.EHStack.begin()); - llvm::BasicBlock *catchBB = catchScope.getHandler(0).Block; - - CGF.popCatchScope(); - - // If there are any references to the catch-all block, emit it. - if (catchBB->use_empty()) { - delete catchBB; - } else { - CGBuilderTy::InsertPoint savedIP = CGF.Builder.saveAndClearIP(); - CGF.EmitBlock(catchBB); - - llvm::Value *exn = nullptr; - - // If there's a begin-catch function, call it. - if (BeginCatchFn) { - exn = CGF.getExceptionFromSlot(); - CGF.EmitNounwindRuntimeCall(BeginCatchFn, exn); - } - - // If we need to remember the exception pointer to rethrow later, do so. - if (SavedExnVar) { - if (!exn) exn = CGF.getExceptionFromSlot(); - CGF.Builder.CreateAlignedStore(exn, SavedExnVar, CGF.getPointerAlign()); - } - - // Tell the cleanups in the finally block that we're do this for EH. - CGF.Builder.CreateFlagStore(true, ForEHVar); - - // Thread a jump through the finally cleanup. - CGF.EmitBranchThroughCleanup(RethrowDest); - - CGF.Builder.restoreIP(savedIP); - } - - // Finally, leave the @finally cleanup. - CGF.PopCleanupBlock(); -} - -llvm::BasicBlock *CodeGenFunction::getTerminateLandingPad() { - if (TerminateLandingPad) - return TerminateLandingPad; - - CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); - - // This will get inserted at the end of the function. - TerminateLandingPad = createBasicBlock("terminate.lpad"); - Builder.SetInsertPoint(TerminateLandingPad); - - // Tell the backend that this is a landing pad. - const EHPersonality &Personality = EHPersonality::get(*this); - - if (!CurFn->hasPersonalityFn()) - CurFn->setPersonalityFn(getOpaquePersonalityFn(CGM, Personality)); - - llvm::LandingPadInst *LPadInst = - Builder.CreateLandingPad(llvm::StructType::get(Int8PtrTy, Int32Ty), 0); - LPadInst->addClause(getCatchAllValue(*this)); - - llvm::Value *Exn = nullptr; - if (getLangOpts().CPlusPlus) - Exn = Builder.CreateExtractValue(LPadInst, 0); - llvm::CallInst *terminateCall = - CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn); - terminateCall->setDoesNotReturn(); - Builder.CreateUnreachable(); - - // Restore the saved insertion state. - Builder.restoreIP(SavedIP); - - return TerminateLandingPad; -} - -llvm::BasicBlock *CodeGenFunction::getTerminateHandler() { - if (TerminateHandler) - return TerminateHandler; - - // Set up the terminate handler. This block is inserted at the very - // end of the function by FinishFunction. - TerminateHandler = createBasicBlock("terminate.handler"); - CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); - Builder.SetInsertPoint(TerminateHandler); - - llvm::Value *Exn = nullptr; - if (getLangOpts().CPlusPlus) - Exn = getExceptionFromSlot(); - llvm::CallInst *terminateCall = - CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn); - terminateCall->setDoesNotReturn(); - Builder.CreateUnreachable(); - - // Restore the saved insertion state. - Builder.restoreIP(SavedIP); - - return TerminateHandler; -} - -llvm::BasicBlock *CodeGenFunction::getTerminateFunclet() { - assert(EHPersonality::get(*this).usesFuncletPads() && - "use getTerminateLandingPad for non-funclet EH"); - - llvm::BasicBlock *&TerminateFunclet = TerminateFunclets[CurrentFuncletPad]; - if (TerminateFunclet) - return TerminateFunclet; - - CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); - - // Set up the terminate handler. This block is inserted at the very - // end of the function by FinishFunction. - TerminateFunclet = createBasicBlock("terminate.handler"); - Builder.SetInsertPoint(TerminateFunclet); - - // Create the cleanuppad using the current parent pad as its token. Use 'none' - // if this is a top-level terminate scope, which is the common case. - SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad( - CurrentFuncletPad); - llvm::Value *ParentPad = CurrentFuncletPad; - if (!ParentPad) - ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext()); - CurrentFuncletPad = Builder.CreateCleanupPad(ParentPad); - - // Emit the __std_terminate call. - llvm::Value *Exn = nullptr; - // In case of wasm personality, we need to pass the exception value to - // __clang_call_terminate function. - if (getLangOpts().CPlusPlus && - EHPersonality::get(*this).isWasmPersonality()) { - llvm::Value *GetExnFn = - CGM.getIntrinsic(llvm::Intrinsic::wasm_get_exception); - Exn = Builder.CreateCall(GetExnFn, CurrentFuncletPad); - } - llvm::CallInst *terminateCall = - CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn); - terminateCall->setDoesNotReturn(); - Builder.CreateUnreachable(); - - // Restore the saved insertion state. - Builder.restoreIP(SavedIP); - - return TerminateFunclet; -} - -llvm::BasicBlock *CodeGenFunction::getEHResumeBlock(bool isCleanup) { - if (EHResumeBlock) return EHResumeBlock; - - CGBuilderTy::InsertPoint SavedIP = Builder.saveIP(); - - // We emit a jump to a notional label at the outermost unwind state. - EHResumeBlock = createBasicBlock("eh.resume"); - Builder.SetInsertPoint(EHResumeBlock); - - const EHPersonality &Personality = EHPersonality::get(*this); - - // This can always be a call because we necessarily didn't find - // anything on the EH stack which needs our help. - const char *RethrowName = Personality.CatchallRethrowFn; - if (RethrowName != nullptr && !isCleanup) { - EmitRuntimeCall(getCatchallRethrowFn(CGM, RethrowName), - getExceptionFromSlot())->setDoesNotReturn(); - Builder.CreateUnreachable(); - Builder.restoreIP(SavedIP); - return EHResumeBlock; - } - - // Recreate the landingpad's return value for the 'resume' instruction. - llvm::Value *Exn = getExceptionFromSlot(); - llvm::Value *Sel = getSelectorFromSlot(); - - llvm::Type *LPadType = llvm::StructType::get(Exn->getType(), Sel->getType()); - llvm::Value *LPadVal = llvm::UndefValue::get(LPadType); - LPadVal = Builder.CreateInsertValue(LPadVal, Exn, 0, "lpad.val"); - LPadVal = Builder.CreateInsertValue(LPadVal, Sel, 1, "lpad.val"); - - Builder.CreateResume(LPadVal); - Builder.restoreIP(SavedIP); - return EHResumeBlock; -} - -void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) { - EnterSEHTryStmt(S); - { - JumpDest TryExit = getJumpDestInCurrentScope("__try.__leave"); - - SEHTryEpilogueStack.push_back(&TryExit); - EmitStmt(S.getTryBlock()); - SEHTryEpilogueStack.pop_back(); - - if (!TryExit.getBlock()->use_empty()) - EmitBlock(TryExit.getBlock(), /*IsFinished=*/true); - else - delete TryExit.getBlock(); - } - ExitSEHTryStmt(S); -} - -namespace { -struct PerformSEHFinally final : EHScopeStack::Cleanup { - llvm::Function *OutlinedFinally; - PerformSEHFinally(llvm::Function *OutlinedFinally) - : OutlinedFinally(OutlinedFinally) {} - - void Emit(CodeGenFunction &CGF, Flags F) override { - ASTContext &Context = CGF.getContext(); - CodeGenModule &CGM = CGF.CGM; - - CallArgList Args; - - // Compute the two argument values. - QualType ArgTys[2] = {Context.UnsignedCharTy, Context.VoidPtrTy}; - llvm::Value *FP = nullptr; - // If CFG.IsOutlinedSEHHelper is true, then we are within a finally block. - if (CGF.IsOutlinedSEHHelper) { - FP = &CGF.CurFn->arg_begin()[1]; - } else { - llvm::Value *LocalAddrFn = - CGM.getIntrinsic(llvm::Intrinsic::localaddress); - FP = CGF.Builder.CreateCall(LocalAddrFn); - } - - llvm::Value *IsForEH = - llvm::ConstantInt::get(CGF.ConvertType(ArgTys[0]), F.isForEHCleanup()); - Args.add(RValue::get(IsForEH), ArgTys[0]); - Args.add(RValue::get(FP), ArgTys[1]); - - // Arrange a two-arg function info and type. - const CGFunctionInfo &FnInfo = - CGM.getTypes().arrangeBuiltinFunctionCall(Context.VoidTy, Args); - - auto Callee = CGCallee::forDirect(OutlinedFinally); - CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args); - } -}; -} // end anonymous namespace - -namespace { -/// Find all local variable captures in the statement. -struct CaptureFinder : ConstStmtVisitor<CaptureFinder> { - CodeGenFunction &ParentCGF; - const VarDecl *ParentThis; - llvm::SmallSetVector<const VarDecl *, 4> Captures; - Address SEHCodeSlot = Address::invalid(); - CaptureFinder(CodeGenFunction &ParentCGF, const VarDecl *ParentThis) - : ParentCGF(ParentCGF), ParentThis(ParentThis) {} - - // Return true if we need to do any capturing work. - bool foundCaptures() { - return !Captures.empty() || SEHCodeSlot.isValid(); - } - - void Visit(const Stmt *S) { - // See if this is a capture, then recurse. - ConstStmtVisitor<CaptureFinder>::Visit(S); - for (const Stmt *Child : S->children()) - if (Child) - Visit(Child); - } - - void VisitDeclRefExpr(const DeclRefExpr *E) { - // If this is already a capture, just make sure we capture 'this'. - if (E->refersToEnclosingVariableOrCapture()) { - Captures.insert(ParentThis); - return; - } - - const auto *D = dyn_cast<VarDecl>(E->getDecl()); - if (D && D->isLocalVarDeclOrParm() && D->hasLocalStorage()) - Captures.insert(D); - } - - void VisitCXXThisExpr(const CXXThisExpr *E) { - Captures.insert(ParentThis); - } - - void VisitCallExpr(const CallExpr *E) { - // We only need to add parent frame allocations for these builtins in x86. - if (ParentCGF.getTarget().getTriple().getArch() != llvm::Triple::x86) - return; - - unsigned ID = E->getBuiltinCallee(); - switch (ID) { - case Builtin::BI__exception_code: - case Builtin::BI_exception_code: - // This is the simple case where we are the outermost finally. All we - // have to do here is make sure we escape this and recover it in the - // outlined handler. - if (!SEHCodeSlot.isValid()) - SEHCodeSlot = ParentCGF.SEHCodeSlotStack.back(); - break; - } - } -}; -} // end anonymous namespace - -Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, - Address ParentVar, - llvm::Value *ParentFP) { - llvm::CallInst *RecoverCall = nullptr; - CGBuilderTy Builder(*this, AllocaInsertPt); - if (auto *ParentAlloca = dyn_cast<llvm::AllocaInst>(ParentVar.getPointer())) { - // Mark the variable escaped if nobody else referenced it and compute the - // localescape index. - auto InsertPair = ParentCGF.EscapedLocals.insert( - std::make_pair(ParentAlloca, ParentCGF.EscapedLocals.size())); - int FrameEscapeIdx = InsertPair.first->second; - // call i8* @llvm.localrecover(i8* bitcast(@parentFn), i8* %fp, i32 N) - llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration( - &CGM.getModule(), llvm::Intrinsic::localrecover); - llvm::Constant *ParentI8Fn = - llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy); - RecoverCall = Builder.CreateCall( - FrameRecoverFn, {ParentI8Fn, ParentFP, - llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx)}); - - } else { - // If the parent didn't have an alloca, we're doing some nested outlining. - // Just clone the existing localrecover call, but tweak the FP argument to - // use our FP value. All other arguments are constants. - auto *ParentRecover = - cast<llvm::IntrinsicInst>(ParentVar.getPointer()->stripPointerCasts()); - assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::localrecover && - "expected alloca or localrecover in parent LocalDeclMap"); - RecoverCall = cast<llvm::CallInst>(ParentRecover->clone()); - RecoverCall->setArgOperand(1, ParentFP); - RecoverCall->insertBefore(AllocaInsertPt); - } - - // Bitcast the variable, rename it, and insert it in the local decl map. - llvm::Value *ChildVar = - Builder.CreateBitCast(RecoverCall, ParentVar.getType()); - ChildVar->setName(ParentVar.getName()); - return Address(ChildVar, ParentVar.getAlignment()); -} - -void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, - const Stmt *OutlinedStmt, - bool IsFilter) { - // Find all captures in the Stmt. - CaptureFinder Finder(ParentCGF, ParentCGF.CXXABIThisDecl); - Finder.Visit(OutlinedStmt); - - // We can exit early on x86_64 when there are no captures. We just have to - // save the exception code in filters so that __exception_code() works. - if (!Finder.foundCaptures() && - CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) { - if (IsFilter) - EmitSEHExceptionCodeSave(ParentCGF, nullptr, nullptr); - return; - } - - llvm::Value *EntryFP = nullptr; - CGBuilderTy Builder(CGM, AllocaInsertPt); - if (IsFilter && CGM.getTarget().getTriple().getArch() == llvm::Triple::x86) { - // 32-bit SEH filters need to be careful about FP recovery. The end of the - // EH registration is passed in as the EBP physical register. We can - // recover that with llvm.frameaddress(1). - EntryFP = Builder.CreateCall( - CGM.getIntrinsic(llvm::Intrinsic::frameaddress), {Builder.getInt32(1)}); - } else { - // Otherwise, for x64 and 32-bit finally functions, the parent FP is the - // second parameter. - auto AI = CurFn->arg_begin(); - ++AI; - EntryFP = &*AI; - } - - llvm::Value *ParentFP = EntryFP; - if (IsFilter) { - // Given whatever FP the runtime provided us in EntryFP, recover the true - // frame pointer of the parent function. We only need to do this in filters, - // since finally funclets recover the parent FP for us. - llvm::Function *RecoverFPIntrin = - CGM.getIntrinsic(llvm::Intrinsic::eh_recoverfp); - llvm::Constant *ParentI8Fn = - llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy); - ParentFP = Builder.CreateCall(RecoverFPIntrin, {ParentI8Fn, EntryFP}); - } - - // Create llvm.localrecover calls for all captures. - for (const VarDecl *VD : Finder.Captures) { - if (isa<ImplicitParamDecl>(VD)) { - CGM.ErrorUnsupported(VD, "'this' captured by SEH"); - CXXThisValue = llvm::UndefValue::get(ConvertTypeForMem(VD->getType())); - continue; - } - if (VD->getType()->isVariablyModifiedType()) { - CGM.ErrorUnsupported(VD, "VLA captured by SEH"); - continue; - } - assert((isa<ImplicitParamDecl>(VD) || VD->isLocalVarDeclOrParm()) && - "captured non-local variable"); - - // If this decl hasn't been declared yet, it will be declared in the - // OutlinedStmt. - auto I = ParentCGF.LocalDeclMap.find(VD); - if (I == ParentCGF.LocalDeclMap.end()) - continue; - - Address ParentVar = I->second; - setAddrOfLocalVar( - VD, recoverAddrOfEscapedLocal(ParentCGF, ParentVar, ParentFP)); - } - - if (Finder.SEHCodeSlot.isValid()) { - SEHCodeSlotStack.push_back( - recoverAddrOfEscapedLocal(ParentCGF, Finder.SEHCodeSlot, ParentFP)); - } - - if (IsFilter) - EmitSEHExceptionCodeSave(ParentCGF, ParentFP, EntryFP); -} - -/// Arrange a function prototype that can be called by Windows exception -/// handling personalities. On Win64, the prototype looks like: -/// RetTy func(void *EHPtrs, void *ParentFP); -void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF, - bool IsFilter, - const Stmt *OutlinedStmt) { - SourceLocation StartLoc = OutlinedStmt->getBeginLoc(); - - // Get the mangled function name. - SmallString<128> Name; - { - llvm::raw_svector_ostream OS(Name); - const NamedDecl *ParentSEHFn = ParentCGF.CurSEHParent; - assert(ParentSEHFn && "No CurSEHParent!"); - MangleContext &Mangler = CGM.getCXXABI().getMangleContext(); - if (IsFilter) - Mangler.mangleSEHFilterExpression(ParentSEHFn, OS); - else - Mangler.mangleSEHFinallyBlock(ParentSEHFn, OS); - } - - FunctionArgList Args; - if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86 || !IsFilter) { - // All SEH finally functions take two parameters. Win64 filters take two - // parameters. Win32 filters take no parameters. - if (IsFilter) { - Args.push_back(ImplicitParamDecl::Create( - getContext(), /*DC=*/nullptr, StartLoc, - &getContext().Idents.get("exception_pointers"), - getContext().VoidPtrTy, ImplicitParamDecl::Other)); - } else { - Args.push_back(ImplicitParamDecl::Create( - getContext(), /*DC=*/nullptr, StartLoc, - &getContext().Idents.get("abnormal_termination"), - getContext().UnsignedCharTy, ImplicitParamDecl::Other)); - } - Args.push_back(ImplicitParamDecl::Create( - getContext(), /*DC=*/nullptr, StartLoc, - &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy, - ImplicitParamDecl::Other)); - } - - QualType RetTy = IsFilter ? getContext().LongTy : getContext().VoidTy; - - const CGFunctionInfo &FnInfo = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(RetTy, Args); - - llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); - llvm::Function *Fn = llvm::Function::Create( - FnTy, llvm::GlobalValue::InternalLinkage, Name.str(), &CGM.getModule()); - - IsOutlinedSEHHelper = true; - - StartFunction(GlobalDecl(), RetTy, Fn, FnInfo, Args, - OutlinedStmt->getBeginLoc(), OutlinedStmt->getBeginLoc()); - CurSEHParent = ParentCGF.CurSEHParent; - - CGM.SetLLVMFunctionAttributes(GlobalDecl(), FnInfo, CurFn); - EmitCapturedLocals(ParentCGF, OutlinedStmt, IsFilter); -} - -/// Create a stub filter function that will ultimately hold the code of the -/// filter expression. The EH preparation passes in LLVM will outline the code -/// from the main function body into this stub. -llvm::Function * -CodeGenFunction::GenerateSEHFilterFunction(CodeGenFunction &ParentCGF, - const SEHExceptStmt &Except) { - const Expr *FilterExpr = Except.getFilterExpr(); - startOutlinedSEHHelper(ParentCGF, true, FilterExpr); - - // Emit the original filter expression, convert to i32, and return. - llvm::Value *R = EmitScalarExpr(FilterExpr); - R = Builder.CreateIntCast(R, ConvertType(getContext().LongTy), - FilterExpr->getType()->isSignedIntegerType()); - Builder.CreateStore(R, ReturnValue); - - FinishFunction(FilterExpr->getEndLoc()); - - return CurFn; -} - -llvm::Function * -CodeGenFunction::GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF, - const SEHFinallyStmt &Finally) { - const Stmt *FinallyBlock = Finally.getBlock(); - startOutlinedSEHHelper(ParentCGF, false, FinallyBlock); - - // Emit the original filter expression, convert to i32, and return. - EmitStmt(FinallyBlock); - - FinishFunction(FinallyBlock->getEndLoc()); - - return CurFn; -} - -void CodeGenFunction::EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF, - llvm::Value *ParentFP, - llvm::Value *EntryFP) { - // Get the pointer to the EXCEPTION_POINTERS struct. This is returned by the - // __exception_info intrinsic. - if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) { - // On Win64, the info is passed as the first parameter to the filter. - SEHInfo = &*CurFn->arg_begin(); - SEHCodeSlotStack.push_back( - CreateMemTemp(getContext().IntTy, "__exception_code")); - } else { - // On Win32, the EBP on entry to the filter points to the end of an - // exception registration object. It contains 6 32-bit fields, and the info - // pointer is stored in the second field. So, GEP 20 bytes backwards and - // load the pointer. - SEHInfo = Builder.CreateConstInBoundsGEP1_32(Int8Ty, EntryFP, -20); - SEHInfo = Builder.CreateBitCast(SEHInfo, Int8PtrTy->getPointerTo()); - SEHInfo = Builder.CreateAlignedLoad(Int8PtrTy, SEHInfo, getPointerAlign()); - SEHCodeSlotStack.push_back(recoverAddrOfEscapedLocal( - ParentCGF, ParentCGF.SEHCodeSlotStack.back(), ParentFP)); - } - - // Save the exception code in the exception slot to unify exception access in - // the filter function and the landing pad. - // struct EXCEPTION_POINTERS { - // EXCEPTION_RECORD *ExceptionRecord; - // CONTEXT *ContextRecord; - // }; - // int exceptioncode = exception_pointers->ExceptionRecord->ExceptionCode; - llvm::Type *RecordTy = CGM.Int32Ty->getPointerTo(); - llvm::Type *PtrsTy = llvm::StructType::get(RecordTy, CGM.VoidPtrTy); - llvm::Value *Ptrs = Builder.CreateBitCast(SEHInfo, PtrsTy->getPointerTo()); - llvm::Value *Rec = Builder.CreateStructGEP(PtrsTy, Ptrs, 0); - Rec = Builder.CreateAlignedLoad(Rec, getPointerAlign()); - llvm::Value *Code = Builder.CreateAlignedLoad(Rec, getIntAlign()); - assert(!SEHCodeSlotStack.empty() && "emitting EH code outside of __except"); - Builder.CreateStore(Code, SEHCodeSlotStack.back()); -} - -llvm::Value *CodeGenFunction::EmitSEHExceptionInfo() { - // Sema should diagnose calling this builtin outside of a filter context, but - // don't crash if we screw up. - if (!SEHInfo) - return llvm::UndefValue::get(Int8PtrTy); - assert(SEHInfo->getType() == Int8PtrTy); - return SEHInfo; -} - -llvm::Value *CodeGenFunction::EmitSEHExceptionCode() { - assert(!SEHCodeSlotStack.empty() && "emitting EH code outside of __except"); - return Builder.CreateLoad(SEHCodeSlotStack.back()); -} - -llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() { - // Abnormal termination is just the first parameter to the outlined finally - // helper. - auto AI = CurFn->arg_begin(); - return Builder.CreateZExt(&*AI, Int32Ty); -} - -void CodeGenFunction::pushSEHCleanup(CleanupKind Kind, - llvm::Function *FinallyFunc) { - EHStack.pushCleanup<PerformSEHFinally>(Kind, FinallyFunc); -} - -void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) { - CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true); - if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) { - // Outline the finally block. - llvm::Function *FinallyFunc = - HelperCGF.GenerateSEHFinallyFunction(*this, *Finally); - - // Push a cleanup for __finally blocks. - EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, FinallyFunc); - return; - } - - // Otherwise, we must have an __except block. - const SEHExceptStmt *Except = S.getExceptHandler(); - assert(Except); - EHCatchScope *CatchScope = EHStack.pushCatch(1); - SEHCodeSlotStack.push_back( - CreateMemTemp(getContext().IntTy, "__exception_code")); - - // If the filter is known to evaluate to 1, then we can use the clause - // "catch i8* null". We can't do this on x86 because the filter has to save - // the exception code. - llvm::Constant *C = - ConstantEmitter(*this).tryEmitAbstract(Except->getFilterExpr(), - getContext().IntTy); - if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86 && C && - C->isOneValue()) { - CatchScope->setCatchAllHandler(0, createBasicBlock("__except")); - return; - } - - // In general, we have to emit an outlined filter function. Use the function - // in place of the RTTI typeinfo global that C++ EH uses. - llvm::Function *FilterFunc = - HelperCGF.GenerateSEHFilterFunction(*this, *Except); - llvm::Constant *OpaqueFunc = - llvm::ConstantExpr::getBitCast(FilterFunc, Int8PtrTy); - CatchScope->setHandler(0, OpaqueFunc, createBasicBlock("__except.ret")); -} - -void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) { - // Just pop the cleanup if it's a __finally block. - if (S.getFinallyHandler()) { - PopCleanupBlock(); - return; - } - - // Otherwise, we must have an __except block. - const SEHExceptStmt *Except = S.getExceptHandler(); - assert(Except && "__try must have __finally xor __except"); - EHCatchScope &CatchScope = cast<EHCatchScope>(*EHStack.begin()); - - // Don't emit the __except block if the __try block lacked invokes. - // TODO: Model unwind edges from instructions, either with iload / istore or - // a try body function. - if (!CatchScope.hasEHBranches()) { - CatchScope.clearHandlerBlocks(); - EHStack.popCatch(); - SEHCodeSlotStack.pop_back(); - return; - } - - // The fall-through block. - llvm::BasicBlock *ContBB = createBasicBlock("__try.cont"); - - // We just emitted the body of the __try; jump to the continue block. - if (HaveInsertPoint()) - Builder.CreateBr(ContBB); - - // Check if our filter function returned true. - emitCatchDispatchBlock(*this, CatchScope); - - // Grab the block before we pop the handler. - llvm::BasicBlock *CatchPadBB = CatchScope.getHandler(0).Block; - EHStack.popCatch(); - - EmitBlockAfterUses(CatchPadBB); - - // __except blocks don't get outlined into funclets, so immediately do a - // catchret. - llvm::CatchPadInst *CPI = - cast<llvm::CatchPadInst>(CatchPadBB->getFirstNonPHI()); - llvm::BasicBlock *ExceptBB = createBasicBlock("__except"); - Builder.CreateCatchRet(CPI, ExceptBB); - EmitBlock(ExceptBB); - - // On Win64, the exception code is returned in EAX. Copy it into the slot. - if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) { - llvm::Function *SEHCodeIntrin = - CGM.getIntrinsic(llvm::Intrinsic::eh_exceptioncode); - llvm::Value *Code = Builder.CreateCall(SEHCodeIntrin, {CPI}); - Builder.CreateStore(Code, SEHCodeSlotStack.back()); - } - - // Emit the __except body. - EmitStmt(Except->getBlock()); - - // End the lifetime of the exception code. - SEHCodeSlotStack.pop_back(); - - if (HaveInsertPoint()) - Builder.CreateBr(ContBB); - - EmitBlock(ContBB); -} - -void CodeGenFunction::EmitSEHLeaveStmt(const SEHLeaveStmt &S) { - // If this code is reachable then emit a stop point (if generating - // debug info). We have to do this ourselves because we are on the - // "simple" statement path. - if (HaveInsertPoint()) - EmitStopPoint(&S); - - // This must be a __leave from a __finally block, which we warn on and is UB. - // Just emit unreachable. - if (!isSEHTryScope()) { - Builder.CreateUnreachable(); - Builder.ClearInsertionPoint(); - return; - } - - EmitBranchThroughCleanup(*SEHTryEpilogueStack.back()); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGExpr.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGExpr.cpp deleted file mode 100644 index 34a921e2dc0..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGExpr.cpp +++ /dev/null @@ -1,4942 +0,0 @@ -//===--- CGExpr.cpp - Emit LLVM Code from Expressions ---------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code to emit Expr nodes as LLVM code. -// -//===----------------------------------------------------------------------===// - -#include "CGCXXABI.h" -#include "CGCall.h" -#include "CGCleanup.h" -#include "CGDebugInfo.h" -#include "CGObjCRuntime.h" -#include "CGOpenMPRuntime.h" -#include "CGRecordLayout.h" -#include "CodeGenFunction.h" -#include "CodeGenModule.h" -#include "ConstantEmitter.h" -#include "TargetInfo.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Attr.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/NSAPI.h" -#include "clang/Basic/CodeGenOptions.h" -#include "llvm/ADT/Hashing.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/MDBuilder.h" -#include "llvm/Support/ConvertUTF.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/Path.h" -#include "llvm/Transforms/Utils/SanitizerStats.h" - -#include <string> - -using namespace clang; -using namespace CodeGen; - -//===--------------------------------------------------------------------===// -// Miscellaneous Helper Methods -//===--------------------------------------------------------------------===// - -llvm::Value *CodeGenFunction::EmitCastToVoidPtr(llvm::Value *value) { - unsigned addressSpace = - cast<llvm::PointerType>(value->getType())->getAddressSpace(); - - llvm::PointerType *destType = Int8PtrTy; - if (addressSpace) - destType = llvm::Type::getInt8PtrTy(getLLVMContext(), addressSpace); - - if (value->getType() == destType) return value; - return Builder.CreateBitCast(value, destType); -} - -/// CreateTempAlloca - This creates a alloca and inserts it into the entry -/// block. -Address CodeGenFunction::CreateTempAllocaWithoutCast(llvm::Type *Ty, - CharUnits Align, - const Twine &Name, - llvm::Value *ArraySize) { - auto Alloca = CreateTempAlloca(Ty, Name, ArraySize); - Alloca->setAlignment(Align.getQuantity()); - return Address(Alloca, Align); -} - -/// CreateTempAlloca - This creates a alloca and inserts it into the entry -/// block. The alloca is casted to default address space if necessary. -Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align, - const Twine &Name, - llvm::Value *ArraySize, - Address *AllocaAddr) { - auto Alloca = CreateTempAllocaWithoutCast(Ty, Align, Name, ArraySize); - if (AllocaAddr) - *AllocaAddr = Alloca; - llvm::Value *V = Alloca.getPointer(); - // Alloca always returns a pointer in alloca address space, which may - // be different from the type defined by the language. For example, - // in C++ the auto variables are in the default address space. Therefore - // cast alloca to the default address space when necessary. - if (getASTAllocaAddressSpace() != LangAS::Default) { - auto DestAddrSpace = getContext().getTargetAddressSpace(LangAS::Default); - llvm::IRBuilderBase::InsertPointGuard IPG(Builder); - // When ArraySize is nullptr, alloca is inserted at AllocaInsertPt, - // otherwise alloca is inserted at the current insertion point of the - // builder. - if (!ArraySize) - Builder.SetInsertPoint(AllocaInsertPt); - V = getTargetHooks().performAddrSpaceCast( - *this, V, getASTAllocaAddressSpace(), LangAS::Default, - Ty->getPointerTo(DestAddrSpace), /*non-null*/ true); - } - - return Address(V, Align); -} - -/// CreateTempAlloca - This creates an alloca and inserts it into the entry -/// block if \p ArraySize is nullptr, otherwise inserts it at the current -/// insertion point of the builder. -llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, - const Twine &Name, - llvm::Value *ArraySize) { - if (ArraySize) - return Builder.CreateAlloca(Ty, ArraySize, Name); - return new llvm::AllocaInst(Ty, CGM.getDataLayout().getAllocaAddrSpace(), - ArraySize, Name, AllocaInsertPt); -} - -/// CreateDefaultAlignTempAlloca - This creates an alloca with the -/// default alignment of the corresponding LLVM type, which is *not* -/// guaranteed to be related in any way to the expected alignment of -/// an AST type that might have been lowered to Ty. -Address CodeGenFunction::CreateDefaultAlignTempAlloca(llvm::Type *Ty, - const Twine &Name) { - CharUnits Align = - CharUnits::fromQuantity(CGM.getDataLayout().getABITypeAlignment(Ty)); - return CreateTempAlloca(Ty, Align, Name); -} - -void CodeGenFunction::InitTempAlloca(Address Var, llvm::Value *Init) { - assert(isa<llvm::AllocaInst>(Var.getPointer())); - auto *Store = new llvm::StoreInst(Init, Var.getPointer()); - Store->setAlignment(Var.getAlignment().getQuantity()); - llvm::BasicBlock *Block = AllocaInsertPt->getParent(); - Block->getInstList().insertAfter(AllocaInsertPt->getIterator(), Store); -} - -Address CodeGenFunction::CreateIRTemp(QualType Ty, const Twine &Name) { - CharUnits Align = getContext().getTypeAlignInChars(Ty); - return CreateTempAlloca(ConvertType(Ty), Align, Name); -} - -Address CodeGenFunction::CreateMemTemp(QualType Ty, const Twine &Name, - Address *Alloca) { - // FIXME: Should we prefer the preferred type alignment here? - return CreateMemTemp(Ty, getContext().getTypeAlignInChars(Ty), Name, Alloca); -} - -Address CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align, - const Twine &Name, Address *Alloca) { - return CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name, - /*ArraySize=*/nullptr, Alloca); -} - -Address CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, CharUnits Align, - const Twine &Name) { - return CreateTempAllocaWithoutCast(ConvertTypeForMem(Ty), Align, Name); -} - -Address CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, - const Twine &Name) { - return CreateMemTempWithoutCast(Ty, getContext().getTypeAlignInChars(Ty), - Name); -} - -/// EvaluateExprAsBool - Perform the usual unary conversions on the specified -/// expression and compare the result against zero, returning an Int1Ty value. -llvm::Value *CodeGenFunction::EvaluateExprAsBool(const Expr *E) { - PGO.setCurrentStmt(E); - if (const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>()) { - llvm::Value *MemPtr = EmitScalarExpr(E); - return CGM.getCXXABI().EmitMemberPointerIsNotNull(*this, MemPtr, MPT); - } - - QualType BoolTy = getContext().BoolTy; - SourceLocation Loc = E->getExprLoc(); - if (!E->getType()->isAnyComplexType()) - return EmitScalarConversion(EmitScalarExpr(E), E->getType(), BoolTy, Loc); - - return EmitComplexToScalarConversion(EmitComplexExpr(E), E->getType(), BoolTy, - Loc); -} - -/// EmitIgnoredExpr - Emit code to compute the specified expression, -/// ignoring the result. -void CodeGenFunction::EmitIgnoredExpr(const Expr *E) { - if (E->isRValue()) - return (void) EmitAnyExpr(E, AggValueSlot::ignored(), true); - - // Just emit it as an l-value and drop the result. - EmitLValue(E); -} - -/// EmitAnyExpr - Emit code to compute the specified expression which -/// can have any type. The result is returned as an RValue struct. -/// If this is an aggregate expression, AggSlot indicates where the -/// result should be returned. -RValue CodeGenFunction::EmitAnyExpr(const Expr *E, - AggValueSlot aggSlot, - bool ignoreResult) { - switch (getEvaluationKind(E->getType())) { - case TEK_Scalar: - return RValue::get(EmitScalarExpr(E, ignoreResult)); - case TEK_Complex: - return RValue::getComplex(EmitComplexExpr(E, ignoreResult, ignoreResult)); - case TEK_Aggregate: - if (!ignoreResult && aggSlot.isIgnored()) - aggSlot = CreateAggTemp(E->getType(), "agg-temp"); - EmitAggExpr(E, aggSlot); - return aggSlot.asRValue(); - } - llvm_unreachable("bad evaluation kind"); -} - -/// EmitAnyExprToTemp - Similar to EmitAnyExpr(), however, the result will -/// always be accessible even if no aggregate location is provided. -RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E) { - AggValueSlot AggSlot = AggValueSlot::ignored(); - - if (hasAggregateEvaluationKind(E->getType())) - AggSlot = CreateAggTemp(E->getType(), "agg.tmp"); - return EmitAnyExpr(E, AggSlot); -} - -/// EmitAnyExprToMem - Evaluate an expression into a given memory -/// location. -void CodeGenFunction::EmitAnyExprToMem(const Expr *E, - Address Location, - Qualifiers Quals, - bool IsInit) { - // FIXME: This function should take an LValue as an argument. - switch (getEvaluationKind(E->getType())) { - case TEK_Complex: - EmitComplexExprIntoLValue(E, MakeAddrLValue(Location, E->getType()), - /*isInit*/ false); - return; - - case TEK_Aggregate: { - EmitAggExpr(E, AggValueSlot::forAddr(Location, Quals, - AggValueSlot::IsDestructed_t(IsInit), - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsAliased_t(!IsInit), - AggValueSlot::MayOverlap)); - return; - } - - case TEK_Scalar: { - RValue RV = RValue::get(EmitScalarExpr(E, /*Ignore*/ false)); - LValue LV = MakeAddrLValue(Location, E->getType()); - EmitStoreThroughLValue(RV, LV); - return; - } - } - llvm_unreachable("bad evaluation kind"); -} - -static void -pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, - const Expr *E, Address ReferenceTemporary) { - // Objective-C++ ARC: - // If we are binding a reference to a temporary that has ownership, we - // need to perform retain/release operations on the temporary. - // - // FIXME: This should be looking at E, not M. - if (auto Lifetime = M->getType().getObjCLifetime()) { - switch (Lifetime) { - case Qualifiers::OCL_None: - case Qualifiers::OCL_ExplicitNone: - // Carry on to normal cleanup handling. - break; - - case Qualifiers::OCL_Autoreleasing: - // Nothing to do; cleaned up by an autorelease pool. - return; - - case Qualifiers::OCL_Strong: - case Qualifiers::OCL_Weak: - switch (StorageDuration Duration = M->getStorageDuration()) { - case SD_Static: - // Note: we intentionally do not register a cleanup to release - // the object on program termination. - return; - - case SD_Thread: - // FIXME: We should probably register a cleanup in this case. - return; - - case SD_Automatic: - case SD_FullExpression: - CodeGenFunction::Destroyer *Destroy; - CleanupKind CleanupKind; - if (Lifetime == Qualifiers::OCL_Strong) { - const ValueDecl *VD = M->getExtendingDecl(); - bool Precise = - VD && isa<VarDecl>(VD) && VD->hasAttr<ObjCPreciseLifetimeAttr>(); - CleanupKind = CGF.getARCCleanupKind(); - Destroy = Precise ? &CodeGenFunction::destroyARCStrongPrecise - : &CodeGenFunction::destroyARCStrongImprecise; - } else { - // __weak objects always get EH cleanups; otherwise, exceptions - // could cause really nasty crashes instead of mere leaks. - CleanupKind = NormalAndEHCleanup; - Destroy = &CodeGenFunction::destroyARCWeak; - } - if (Duration == SD_FullExpression) - CGF.pushDestroy(CleanupKind, ReferenceTemporary, - M->getType(), *Destroy, - CleanupKind & EHCleanup); - else - CGF.pushLifetimeExtendedDestroy(CleanupKind, ReferenceTemporary, - M->getType(), - *Destroy, CleanupKind & EHCleanup); - return; - - case SD_Dynamic: - llvm_unreachable("temporary cannot have dynamic storage duration"); - } - llvm_unreachable("unknown storage duration"); - } - } - - CXXDestructorDecl *ReferenceTemporaryDtor = nullptr; - if (const RecordType *RT = - E->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()) { - // Get the destructor for the reference temporary. - auto *ClassDecl = cast<CXXRecordDecl>(RT->getDecl()); - if (!ClassDecl->hasTrivialDestructor()) - ReferenceTemporaryDtor = ClassDecl->getDestructor(); - } - - if (!ReferenceTemporaryDtor) - return; - - // Call the destructor for the temporary. - switch (M->getStorageDuration()) { - case SD_Static: - case SD_Thread: { - llvm::Constant *CleanupFn; - llvm::Constant *CleanupArg; - if (E->getType()->isArrayType()) { - CleanupFn = CodeGenFunction(CGF.CGM).generateDestroyHelper( - ReferenceTemporary, E->getType(), - CodeGenFunction::destroyCXXObject, CGF.getLangOpts().Exceptions, - dyn_cast_or_null<VarDecl>(M->getExtendingDecl())); - CleanupArg = llvm::Constant::getNullValue(CGF.Int8PtrTy); - } else { - CleanupFn = CGF.CGM.getAddrOfCXXStructor(ReferenceTemporaryDtor, - StructorType::Complete); - CleanupArg = cast<llvm::Constant>(ReferenceTemporary.getPointer()); - } - CGF.CGM.getCXXABI().registerGlobalDtor( - CGF, *cast<VarDecl>(M->getExtendingDecl()), CleanupFn, CleanupArg); - break; - } - - case SD_FullExpression: - CGF.pushDestroy(NormalAndEHCleanup, ReferenceTemporary, E->getType(), - CodeGenFunction::destroyCXXObject, - CGF.getLangOpts().Exceptions); - break; - - case SD_Automatic: - CGF.pushLifetimeExtendedDestroy(NormalAndEHCleanup, - ReferenceTemporary, E->getType(), - CodeGenFunction::destroyCXXObject, - CGF.getLangOpts().Exceptions); - break; - - case SD_Dynamic: - llvm_unreachable("temporary cannot have dynamic storage duration"); - } -} - -static Address createReferenceTemporary(CodeGenFunction &CGF, - const MaterializeTemporaryExpr *M, - const Expr *Inner, - Address *Alloca = nullptr) { - auto &TCG = CGF.getTargetHooks(); - switch (M->getStorageDuration()) { - case SD_FullExpression: - case SD_Automatic: { - // If we have a constant temporary array or record try to promote it into a - // constant global under the same rules a normal constant would've been - // promoted. This is easier on the optimizer and generally emits fewer - // instructions. - QualType Ty = Inner->getType(); - if (CGF.CGM.getCodeGenOpts().MergeAllConstants && - (Ty->isArrayType() || Ty->isRecordType()) && - CGF.CGM.isTypeConstant(Ty, true)) - if (auto Init = ConstantEmitter(CGF).tryEmitAbstract(Inner, Ty)) { - if (auto AddrSpace = CGF.getTarget().getConstantAddressSpace()) { - auto AS = AddrSpace.getValue(); - auto *GV = new llvm::GlobalVariable( - CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, - llvm::GlobalValue::PrivateLinkage, Init, ".ref.tmp", nullptr, - llvm::GlobalValue::NotThreadLocal, - CGF.getContext().getTargetAddressSpace(AS)); - CharUnits alignment = CGF.getContext().getTypeAlignInChars(Ty); - GV->setAlignment(alignment.getQuantity()); - llvm::Constant *C = GV; - if (AS != LangAS::Default) - C = TCG.performAddrSpaceCast( - CGF.CGM, GV, AS, LangAS::Default, - GV->getValueType()->getPointerTo( - CGF.getContext().getTargetAddressSpace(LangAS::Default))); - // FIXME: Should we put the new global into a COMDAT? - return Address(C, alignment); - } - } - return CGF.CreateMemTemp(Ty, "ref.tmp", Alloca); - } - case SD_Thread: - case SD_Static: - return CGF.CGM.GetAddrOfGlobalTemporary(M, Inner); - - case SD_Dynamic: - llvm_unreachable("temporary can't have dynamic storage duration"); - } - llvm_unreachable("unknown storage duration"); -} - -LValue CodeGenFunction:: -EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) { - const Expr *E = M->GetTemporaryExpr(); - - assert((!M->getExtendingDecl() || !isa<VarDecl>(M->getExtendingDecl()) || - !cast<VarDecl>(M->getExtendingDecl())->isARCPseudoStrong()) && - "Reference should never be pseudo-strong!"); - - // FIXME: ideally this would use EmitAnyExprToMem, however, we cannot do so - // as that will cause the lifetime adjustment to be lost for ARC - auto ownership = M->getType().getObjCLifetime(); - if (ownership != Qualifiers::OCL_None && - ownership != Qualifiers::OCL_ExplicitNone) { - Address Object = createReferenceTemporary(*this, M, E); - if (auto *Var = dyn_cast<llvm::GlobalVariable>(Object.getPointer())) { - Object = Address(llvm::ConstantExpr::getBitCast(Var, - ConvertTypeForMem(E->getType()) - ->getPointerTo(Object.getAddressSpace())), - Object.getAlignment()); - - // createReferenceTemporary will promote the temporary to a global with a - // constant initializer if it can. It can only do this to a value of - // ARC-manageable type if the value is global and therefore "immune" to - // ref-counting operations. Therefore we have no need to emit either a - // dynamic initialization or a cleanup and we can just return the address - // of the temporary. - if (Var->hasInitializer()) - return MakeAddrLValue(Object, M->getType(), AlignmentSource::Decl); - - Var->setInitializer(CGM.EmitNullConstant(E->getType())); - } - LValue RefTempDst = MakeAddrLValue(Object, M->getType(), - AlignmentSource::Decl); - - switch (getEvaluationKind(E->getType())) { - default: llvm_unreachable("expected scalar or aggregate expression"); - case TEK_Scalar: - EmitScalarInit(E, M->getExtendingDecl(), RefTempDst, false); - break; - case TEK_Aggregate: { - EmitAggExpr(E, AggValueSlot::forAddr(Object, - E->getType().getQualifiers(), - AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - AggValueSlot::DoesNotOverlap)); - break; - } - } - - pushTemporaryCleanup(*this, M, E, Object); - return RefTempDst; - } - - SmallVector<const Expr *, 2> CommaLHSs; - SmallVector<SubobjectAdjustment, 2> Adjustments; - E = E->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); - - for (const auto &Ignored : CommaLHSs) - EmitIgnoredExpr(Ignored); - - if (const auto *opaque = dyn_cast<OpaqueValueExpr>(E)) { - if (opaque->getType()->isRecordType()) { - assert(Adjustments.empty()); - return EmitOpaqueValueLValue(opaque); - } - } - - // Create and initialize the reference temporary. - Address Alloca = Address::invalid(); - Address Object = createReferenceTemporary(*this, M, E, &Alloca); - if (auto *Var = dyn_cast<llvm::GlobalVariable>( - Object.getPointer()->stripPointerCasts())) { - Object = Address(llvm::ConstantExpr::getBitCast( - cast<llvm::Constant>(Object.getPointer()), - ConvertTypeForMem(E->getType())->getPointerTo()), - Object.getAlignment()); - // If the temporary is a global and has a constant initializer or is a - // constant temporary that we promoted to a global, we may have already - // initialized it. - if (!Var->hasInitializer()) { - Var->setInitializer(CGM.EmitNullConstant(E->getType())); - EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true); - } - } else { - switch (M->getStorageDuration()) { - case SD_Automatic: - if (auto *Size = EmitLifetimeStart( - CGM.getDataLayout().getTypeAllocSize(Alloca.getElementType()), - Alloca.getPointer())) { - pushCleanupAfterFullExpr<CallLifetimeEnd>(NormalEHLifetimeMarker, - Alloca, Size); - } - break; - - case SD_FullExpression: { - if (!ShouldEmitLifetimeMarkers) - break; - - // Avoid creating a conditional cleanup just to hold an llvm.lifetime.end - // marker. Instead, start the lifetime of a conditional temporary earlier - // so that it's unconditional. Don't do this in ASan's use-after-scope - // mode so that it gets the more precise lifetime marks. If the type has - // a non-trivial destructor, we'll have a cleanup block for it anyway, - // so this typically doesn't help; skip it in that case. - ConditionalEvaluation *OldConditional = nullptr; - CGBuilderTy::InsertPoint OldIP; - if (isInConditionalBranch() && !E->getType().isDestructedType() && - !CGM.getCodeGenOpts().SanitizeAddressUseAfterScope) { - OldConditional = OutermostConditional; - OutermostConditional = nullptr; - - OldIP = Builder.saveIP(); - llvm::BasicBlock *Block = OldConditional->getStartingBlock(); - Builder.restoreIP(CGBuilderTy::InsertPoint( - Block, llvm::BasicBlock::iterator(Block->back()))); - } - - if (auto *Size = EmitLifetimeStart( - CGM.getDataLayout().getTypeAllocSize(Alloca.getElementType()), - Alloca.getPointer())) { - pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Alloca, - Size); - } - - if (OldConditional) { - OutermostConditional = OldConditional; - Builder.restoreIP(OldIP); - } - break; - } - - default: - break; - } - EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true); - } - pushTemporaryCleanup(*this, M, E, Object); - - // Perform derived-to-base casts and/or field accesses, to get from the - // temporary object we created (and, potentially, for which we extended - // the lifetime) to the subobject we're binding the reference to. - for (unsigned I = Adjustments.size(); I != 0; --I) { - SubobjectAdjustment &Adjustment = Adjustments[I-1]; - switch (Adjustment.Kind) { - case SubobjectAdjustment::DerivedToBaseAdjustment: - Object = - GetAddressOfBaseClass(Object, Adjustment.DerivedToBase.DerivedClass, - Adjustment.DerivedToBase.BasePath->path_begin(), - Adjustment.DerivedToBase.BasePath->path_end(), - /*NullCheckValue=*/ false, E->getExprLoc()); - break; - - case SubobjectAdjustment::FieldAdjustment: { - LValue LV = MakeAddrLValue(Object, E->getType(), AlignmentSource::Decl); - LV = EmitLValueForField(LV, Adjustment.Field); - assert(LV.isSimple() && - "materialized temporary field is not a simple lvalue"); - Object = LV.getAddress(); - break; - } - - case SubobjectAdjustment::MemberPointerAdjustment: { - llvm::Value *Ptr = EmitScalarExpr(Adjustment.Ptr.RHS); - Object = EmitCXXMemberDataPointerAddress(E, Object, Ptr, - Adjustment.Ptr.MPT); - break; - } - } - } - - return MakeAddrLValue(Object, M->getType(), AlignmentSource::Decl); -} - -RValue -CodeGenFunction::EmitReferenceBindingToExpr(const Expr *E) { - // Emit the expression as an lvalue. - LValue LV = EmitLValue(E); - assert(LV.isSimple()); - llvm::Value *Value = LV.getPointer(); - - if (sanitizePerformTypeCheck() && !E->getType()->isFunctionType()) { - // C++11 [dcl.ref]p5 (as amended by core issue 453): - // If a glvalue to which a reference is directly bound designates neither - // an existing object or function of an appropriate type nor a region of - // storage of suitable size and alignment to contain an object of the - // reference's type, the behavior is undefined. - QualType Ty = E->getType(); - EmitTypeCheck(TCK_ReferenceBinding, E->getExprLoc(), Value, Ty); - } - - return RValue::get(Value); -} - - -/// getAccessedFieldNo - Given an encoded value and a result number, return the -/// input field number being accessed. -unsigned CodeGenFunction::getAccessedFieldNo(unsigned Idx, - const llvm::Constant *Elts) { - return cast<llvm::ConstantInt>(Elts->getAggregateElement(Idx)) - ->getZExtValue(); -} - -/// Emit the hash_16_bytes function from include/llvm/ADT/Hashing.h. -static llvm::Value *emitHash16Bytes(CGBuilderTy &Builder, llvm::Value *Low, - llvm::Value *High) { - llvm::Value *KMul = Builder.getInt64(0x9ddfea08eb382d69ULL); - llvm::Value *K47 = Builder.getInt64(47); - llvm::Value *A0 = Builder.CreateMul(Builder.CreateXor(Low, High), KMul); - llvm::Value *A1 = Builder.CreateXor(Builder.CreateLShr(A0, K47), A0); - llvm::Value *B0 = Builder.CreateMul(Builder.CreateXor(High, A1), KMul); - llvm::Value *B1 = Builder.CreateXor(Builder.CreateLShr(B0, K47), B0); - return Builder.CreateMul(B1, KMul); -} - -bool CodeGenFunction::isNullPointerAllowed(TypeCheckKind TCK) { - return TCK == TCK_DowncastPointer || TCK == TCK_Upcast || - TCK == TCK_UpcastToVirtualBase || TCK == TCK_DynamicOperation; -} - -bool CodeGenFunction::isVptrCheckRequired(TypeCheckKind TCK, QualType Ty) { - CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); - return (RD && RD->hasDefinition() && RD->isDynamicClass()) && - (TCK == TCK_MemberAccess || TCK == TCK_MemberCall || - TCK == TCK_DowncastPointer || TCK == TCK_DowncastReference || - TCK == TCK_UpcastToVirtualBase || TCK == TCK_DynamicOperation); -} - -bool CodeGenFunction::sanitizePerformTypeCheck() const { - return SanOpts.has(SanitizerKind::Null) | - SanOpts.has(SanitizerKind::Alignment) | - SanOpts.has(SanitizerKind::ObjectSize) | - SanOpts.has(SanitizerKind::Vptr); -} - -void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, - llvm::Value *Ptr, QualType Ty, - CharUnits Alignment, - SanitizerSet SkippedChecks) { - if (!sanitizePerformTypeCheck()) - return; - - // Don't check pointers outside the default address space. The null check - // isn't correct, the object-size check isn't supported by LLVM, and we can't - // communicate the addresses to the runtime handler for the vptr check. - if (Ptr->getType()->getPointerAddressSpace()) - return; - - // Don't check pointers to volatile data. The behavior here is implementation- - // defined. - if (Ty.isVolatileQualified()) - return; - - SanitizerScope SanScope(this); - - SmallVector<std::pair<llvm::Value *, SanitizerMask>, 3> Checks; - llvm::BasicBlock *Done = nullptr; - - // Quickly determine whether we have a pointer to an alloca. It's possible - // to skip null checks, and some alignment checks, for these pointers. This - // can reduce compile-time significantly. - auto PtrToAlloca = - dyn_cast<llvm::AllocaInst>(Ptr->stripPointerCastsNoFollowAliases()); - - llvm::Value *True = llvm::ConstantInt::getTrue(getLLVMContext()); - llvm::Value *IsNonNull = nullptr; - bool IsGuaranteedNonNull = - SkippedChecks.has(SanitizerKind::Null) || PtrToAlloca; - bool AllowNullPointers = isNullPointerAllowed(TCK); - if ((SanOpts.has(SanitizerKind::Null) || AllowNullPointers) && - !IsGuaranteedNonNull) { - // The glvalue must not be an empty glvalue. - IsNonNull = Builder.CreateIsNotNull(Ptr); - - // The IR builder can constant-fold the null check if the pointer points to - // a constant. - IsGuaranteedNonNull = IsNonNull == True; - - // Skip the null check if the pointer is known to be non-null. - if (!IsGuaranteedNonNull) { - if (AllowNullPointers) { - // When performing pointer casts, it's OK if the value is null. - // Skip the remaining checks in that case. - Done = createBasicBlock("null"); - llvm::BasicBlock *Rest = createBasicBlock("not.null"); - Builder.CreateCondBr(IsNonNull, Rest, Done); - EmitBlock(Rest); - } else { - Checks.push_back(std::make_pair(IsNonNull, SanitizerKind::Null)); - } - } - } - - if (SanOpts.has(SanitizerKind::ObjectSize) && - !SkippedChecks.has(SanitizerKind::ObjectSize) && - !Ty->isIncompleteType()) { - uint64_t Size = getContext().getTypeSizeInChars(Ty).getQuantity(); - - // The glvalue must refer to a large enough storage region. - // FIXME: If Address Sanitizer is enabled, insert dynamic instrumentation - // to check this. - // FIXME: Get object address space - llvm::Type *Tys[2] = { IntPtrTy, Int8PtrTy }; - llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::objectsize, Tys); - llvm::Value *Min = Builder.getFalse(); - llvm::Value *NullIsUnknown = Builder.getFalse(); - llvm::Value *CastAddr = Builder.CreateBitCast(Ptr, Int8PtrTy); - llvm::Value *LargeEnough = Builder.CreateICmpUGE( - Builder.CreateCall(F, {CastAddr, Min, NullIsUnknown}), - llvm::ConstantInt::get(IntPtrTy, Size)); - Checks.push_back(std::make_pair(LargeEnough, SanitizerKind::ObjectSize)); - } - - uint64_t AlignVal = 0; - llvm::Value *PtrAsInt = nullptr; - - if (SanOpts.has(SanitizerKind::Alignment) && - !SkippedChecks.has(SanitizerKind::Alignment)) { - AlignVal = Alignment.getQuantity(); - if (!Ty->isIncompleteType() && !AlignVal) - AlignVal = getContext().getTypeAlignInChars(Ty).getQuantity(); - - // The glvalue must be suitably aligned. - if (AlignVal > 1 && - (!PtrToAlloca || PtrToAlloca->getAlignment() < AlignVal)) { - PtrAsInt = Builder.CreatePtrToInt(Ptr, IntPtrTy); - llvm::Value *Align = Builder.CreateAnd( - PtrAsInt, llvm::ConstantInt::get(IntPtrTy, AlignVal - 1)); - llvm::Value *Aligned = - Builder.CreateICmpEQ(Align, llvm::ConstantInt::get(IntPtrTy, 0)); - if (Aligned != True) - Checks.push_back(std::make_pair(Aligned, SanitizerKind::Alignment)); - } - } - - if (Checks.size() > 0) { - // Make sure we're not losing information. Alignment needs to be a power of - // 2 - assert(!AlignVal || (uint64_t)1 << llvm::Log2_64(AlignVal) == AlignVal); - llvm::Constant *StaticData[] = { - EmitCheckSourceLocation(Loc), EmitCheckTypeDescriptor(Ty), - llvm::ConstantInt::get(Int8Ty, AlignVal ? llvm::Log2_64(AlignVal) : 1), - llvm::ConstantInt::get(Int8Ty, TCK)}; - EmitCheck(Checks, SanitizerHandler::TypeMismatch, StaticData, - PtrAsInt ? PtrAsInt : Ptr); - } - - // If possible, check that the vptr indicates that there is a subobject of - // type Ty at offset zero within this object. - // - // C++11 [basic.life]p5,6: - // [For storage which does not refer to an object within its lifetime] - // The program has undefined behavior if: - // -- the [pointer or glvalue] is used to access a non-static data member - // or call a non-static member function - if (SanOpts.has(SanitizerKind::Vptr) && - !SkippedChecks.has(SanitizerKind::Vptr) && isVptrCheckRequired(TCK, Ty)) { - // Ensure that the pointer is non-null before loading it. If there is no - // compile-time guarantee, reuse the run-time null check or emit a new one. - if (!IsGuaranteedNonNull) { - if (!IsNonNull) - IsNonNull = Builder.CreateIsNotNull(Ptr); - if (!Done) - Done = createBasicBlock("vptr.null"); - llvm::BasicBlock *VptrNotNull = createBasicBlock("vptr.not.null"); - Builder.CreateCondBr(IsNonNull, VptrNotNull, Done); - EmitBlock(VptrNotNull); - } - - // Compute a hash of the mangled name of the type. - // - // FIXME: This is not guaranteed to be deterministic! Move to a - // fingerprinting mechanism once LLVM provides one. For the time - // being the implementation happens to be deterministic. - SmallString<64> MangledName; - llvm::raw_svector_ostream Out(MangledName); - CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty.getUnqualifiedType(), - Out); - - // Blacklist based on the mangled type. - if (!CGM.getContext().getSanitizerBlacklist().isBlacklistedType( - SanitizerKind::Vptr, Out.str())) { - llvm::hash_code TypeHash = hash_value(Out.str()); - - // Load the vptr, and compute hash_16_bytes(TypeHash, vptr). - llvm::Value *Low = llvm::ConstantInt::get(Int64Ty, TypeHash); - llvm::Type *VPtrTy = llvm::PointerType::get(IntPtrTy, 0); - Address VPtrAddr(Builder.CreateBitCast(Ptr, VPtrTy), getPointerAlign()); - llvm::Value *VPtrVal = Builder.CreateLoad(VPtrAddr); - llvm::Value *High = Builder.CreateZExt(VPtrVal, Int64Ty); - - llvm::Value *Hash = emitHash16Bytes(Builder, Low, High); - Hash = Builder.CreateTrunc(Hash, IntPtrTy); - - // Look the hash up in our cache. - const int CacheSize = 128; - llvm::Type *HashTable = llvm::ArrayType::get(IntPtrTy, CacheSize); - llvm::Value *Cache = CGM.CreateRuntimeVariable(HashTable, - "__ubsan_vptr_type_cache"); - llvm::Value *Slot = Builder.CreateAnd(Hash, - llvm::ConstantInt::get(IntPtrTy, - CacheSize-1)); - llvm::Value *Indices[] = { Builder.getInt32(0), Slot }; - llvm::Value *CacheVal = - Builder.CreateAlignedLoad(Builder.CreateInBoundsGEP(Cache, Indices), - getPointerAlign()); - - // If the hash isn't in the cache, call a runtime handler to perform the - // hard work of checking whether the vptr is for an object of the right - // type. This will either fill in the cache and return, or produce a - // diagnostic. - llvm::Value *EqualHash = Builder.CreateICmpEQ(CacheVal, Hash); - llvm::Constant *StaticData[] = { - EmitCheckSourceLocation(Loc), - EmitCheckTypeDescriptor(Ty), - CGM.GetAddrOfRTTIDescriptor(Ty.getUnqualifiedType()), - llvm::ConstantInt::get(Int8Ty, TCK) - }; - llvm::Value *DynamicData[] = { Ptr, Hash }; - EmitCheck(std::make_pair(EqualHash, SanitizerKind::Vptr), - SanitizerHandler::DynamicTypeCacheMiss, StaticData, - DynamicData); - } - } - - if (Done) { - Builder.CreateBr(Done); - EmitBlock(Done); - } -} - -/// Determine whether this expression refers to a flexible array member in a -/// struct. We disable array bounds checks for such members. -static bool isFlexibleArrayMemberExpr(const Expr *E) { - // For compatibility with existing code, we treat arrays of length 0 or - // 1 as flexible array members. - const ArrayType *AT = E->getType()->castAsArrayTypeUnsafe(); - if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) { - if (CAT->getSize().ugt(1)) - return false; - } else if (!isa<IncompleteArrayType>(AT)) - return false; - - E = E->IgnoreParens(); - - // A flexible array member must be the last member in the class. - if (const auto *ME = dyn_cast<MemberExpr>(E)) { - // FIXME: If the base type of the member expr is not FD->getParent(), - // this should not be treated as a flexible array member access. - if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) { - RecordDecl::field_iterator FI( - DeclContext::decl_iterator(const_cast<FieldDecl *>(FD))); - return ++FI == FD->getParent()->field_end(); - } - } else if (const auto *IRE = dyn_cast<ObjCIvarRefExpr>(E)) { - return IRE->getDecl()->getNextIvar() == nullptr; - } - - return false; -} - -llvm::Value *CodeGenFunction::LoadPassedObjectSize(const Expr *E, - QualType EltTy) { - ASTContext &C = getContext(); - uint64_t EltSize = C.getTypeSizeInChars(EltTy).getQuantity(); - if (!EltSize) - return nullptr; - - auto *ArrayDeclRef = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()); - if (!ArrayDeclRef) - return nullptr; - - auto *ParamDecl = dyn_cast<ParmVarDecl>(ArrayDeclRef->getDecl()); - if (!ParamDecl) - return nullptr; - - auto *POSAttr = ParamDecl->getAttr<PassObjectSizeAttr>(); - if (!POSAttr) - return nullptr; - - // Don't load the size if it's a lower bound. - int POSType = POSAttr->getType(); - if (POSType != 0 && POSType != 1) - return nullptr; - - // Find the implicit size parameter. - auto PassedSizeIt = SizeArguments.find(ParamDecl); - if (PassedSizeIt == SizeArguments.end()) - return nullptr; - - const ImplicitParamDecl *PassedSizeDecl = PassedSizeIt->second; - assert(LocalDeclMap.count(PassedSizeDecl) && "Passed size not loadable"); - Address AddrOfSize = LocalDeclMap.find(PassedSizeDecl)->second; - llvm::Value *SizeInBytes = EmitLoadOfScalar(AddrOfSize, /*Volatile=*/false, - C.getSizeType(), E->getExprLoc()); - llvm::Value *SizeOfElement = - llvm::ConstantInt::get(SizeInBytes->getType(), EltSize); - return Builder.CreateUDiv(SizeInBytes, SizeOfElement); -} - -/// If Base is known to point to the start of an array, return the length of -/// that array. Return 0 if the length cannot be determined. -static llvm::Value *getArrayIndexingBound( - CodeGenFunction &CGF, const Expr *Base, QualType &IndexedType) { - // For the vector indexing extension, the bound is the number of elements. - if (const VectorType *VT = Base->getType()->getAs<VectorType>()) { - IndexedType = Base->getType(); - return CGF.Builder.getInt32(VT->getNumElements()); - } - - Base = Base->IgnoreParens(); - - if (const auto *CE = dyn_cast<CastExpr>(Base)) { - if (CE->getCastKind() == CK_ArrayToPointerDecay && - !isFlexibleArrayMemberExpr(CE->getSubExpr())) { - IndexedType = CE->getSubExpr()->getType(); - const ArrayType *AT = IndexedType->castAsArrayTypeUnsafe(); - if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) - return CGF.Builder.getInt(CAT->getSize()); - else if (const auto *VAT = dyn_cast<VariableArrayType>(AT)) - return CGF.getVLASize(VAT).NumElts; - // Ignore pass_object_size here. It's not applicable on decayed pointers. - } - } - - QualType EltTy{Base->getType()->getPointeeOrArrayElementType(), 0}; - if (llvm::Value *POS = CGF.LoadPassedObjectSize(Base, EltTy)) { - IndexedType = Base->getType(); - return POS; - } - - return nullptr; -} - -void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base, - llvm::Value *Index, QualType IndexType, - bool Accessed) { - assert(SanOpts.has(SanitizerKind::ArrayBounds) && - "should not be called unless adding bounds checks"); - SanitizerScope SanScope(this); - - QualType IndexedType; - llvm::Value *Bound = getArrayIndexingBound(*this, Base, IndexedType); - if (!Bound) - return; - - bool IndexSigned = IndexType->isSignedIntegerOrEnumerationType(); - llvm::Value *IndexVal = Builder.CreateIntCast(Index, SizeTy, IndexSigned); - llvm::Value *BoundVal = Builder.CreateIntCast(Bound, SizeTy, false); - - llvm::Constant *StaticData[] = { - EmitCheckSourceLocation(E->getExprLoc()), - EmitCheckTypeDescriptor(IndexedType), - EmitCheckTypeDescriptor(IndexType) - }; - llvm::Value *Check = Accessed ? Builder.CreateICmpULT(IndexVal, BoundVal) - : Builder.CreateICmpULE(IndexVal, BoundVal); - EmitCheck(std::make_pair(Check, SanitizerKind::ArrayBounds), - SanitizerHandler::OutOfBounds, StaticData, Index); -} - - -CodeGenFunction::ComplexPairTy CodeGenFunction:: -EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV, - bool isInc, bool isPre) { - ComplexPairTy InVal = EmitLoadOfComplex(LV, E->getExprLoc()); - - llvm::Value *NextVal; - if (isa<llvm::IntegerType>(InVal.first->getType())) { - uint64_t AmountVal = isInc ? 1 : -1; - NextVal = llvm::ConstantInt::get(InVal.first->getType(), AmountVal, true); - - // Add the inc/dec to the real part. - NextVal = Builder.CreateAdd(InVal.first, NextVal, isInc ? "inc" : "dec"); - } else { - QualType ElemTy = E->getType()->getAs<ComplexType>()->getElementType(); - llvm::APFloat FVal(getContext().getFloatTypeSemantics(ElemTy), 1); - if (!isInc) - FVal.changeSign(); - NextVal = llvm::ConstantFP::get(getLLVMContext(), FVal); - - // Add the inc/dec to the real part. - NextVal = Builder.CreateFAdd(InVal.first, NextVal, isInc ? "inc" : "dec"); - } - - ComplexPairTy IncVal(NextVal, InVal.second); - - // Store the updated result through the lvalue. - EmitStoreOfComplex(IncVal, LV, /*init*/ false); - - // If this is a postinc, return the value read from memory, otherwise use the - // updated value. - return isPre ? IncVal : InVal; -} - -void CodeGenModule::EmitExplicitCastExprType(const ExplicitCastExpr *E, - CodeGenFunction *CGF) { - // Bind VLAs in the cast type. - if (CGF && E->getType()->isVariablyModifiedType()) - CGF->EmitVariablyModifiedType(E->getType()); - - if (CGDebugInfo *DI = getModuleDebugInfo()) - DI->EmitExplicitCastType(E->getType()); -} - -//===----------------------------------------------------------------------===// -// LValue Expression Emission -//===----------------------------------------------------------------------===// - -/// EmitPointerWithAlignment - Given an expression of pointer type, try to -/// derive a more accurate bound on the alignment of the pointer. -Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E, - LValueBaseInfo *BaseInfo, - TBAAAccessInfo *TBAAInfo) { - // We allow this with ObjC object pointers because of fragile ABIs. - assert(E->getType()->isPointerType() || - E->getType()->isObjCObjectPointerType()); - E = E->IgnoreParens(); - - // Casts: - if (const CastExpr *CE = dyn_cast<CastExpr>(E)) { - if (const auto *ECE = dyn_cast<ExplicitCastExpr>(CE)) - CGM.EmitExplicitCastExprType(ECE, this); - - switch (CE->getCastKind()) { - // Non-converting casts (but not C's implicit conversion from void*). - case CK_BitCast: - case CK_NoOp: - case CK_AddressSpaceConversion: - if (auto PtrTy = CE->getSubExpr()->getType()->getAs<PointerType>()) { - if (PtrTy->getPointeeType()->isVoidType()) - break; - - LValueBaseInfo InnerBaseInfo; - TBAAAccessInfo InnerTBAAInfo; - Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), - &InnerBaseInfo, - &InnerTBAAInfo); - if (BaseInfo) *BaseInfo = InnerBaseInfo; - if (TBAAInfo) *TBAAInfo = InnerTBAAInfo; - - if (isa<ExplicitCastExpr>(CE)) { - LValueBaseInfo TargetTypeBaseInfo; - TBAAAccessInfo TargetTypeTBAAInfo; - CharUnits Align = getNaturalPointeeTypeAlignment(E->getType(), - &TargetTypeBaseInfo, - &TargetTypeTBAAInfo); - if (TBAAInfo) - *TBAAInfo = CGM.mergeTBAAInfoForCast(*TBAAInfo, - TargetTypeTBAAInfo); - // If the source l-value is opaque, honor the alignment of the - // casted-to type. - if (InnerBaseInfo.getAlignmentSource() != AlignmentSource::Decl) { - if (BaseInfo) - BaseInfo->mergeForCast(TargetTypeBaseInfo); - Addr = Address(Addr.getPointer(), Align); - } - } - - if (SanOpts.has(SanitizerKind::CFIUnrelatedCast) && - CE->getCastKind() == CK_BitCast) { - if (auto PT = E->getType()->getAs<PointerType>()) - EmitVTablePtrCheckForCast(PT->getPointeeType(), Addr.getPointer(), - /*MayBeNull=*/true, - CodeGenFunction::CFITCK_UnrelatedCast, - CE->getBeginLoc()); - } - return CE->getCastKind() != CK_AddressSpaceConversion - ? Builder.CreateBitCast(Addr, ConvertType(E->getType())) - : Builder.CreateAddrSpaceCast(Addr, - ConvertType(E->getType())); - } - break; - - // Array-to-pointer decay. - case CK_ArrayToPointerDecay: - return EmitArrayToPointerDecay(CE->getSubExpr(), BaseInfo, TBAAInfo); - - // Derived-to-base conversions. - case CK_UncheckedDerivedToBase: - case CK_DerivedToBase: { - // TODO: Support accesses to members of base classes in TBAA. For now, we - // conservatively pretend that the complete object is of the base class - // type. - if (TBAAInfo) - *TBAAInfo = CGM.getTBAAAccessInfo(E->getType()); - Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), BaseInfo); - auto Derived = CE->getSubExpr()->getType()->getPointeeCXXRecordDecl(); - return GetAddressOfBaseClass(Addr, Derived, - CE->path_begin(), CE->path_end(), - ShouldNullCheckClassCastValue(CE), - CE->getExprLoc()); - } - - // TODO: Is there any reason to treat base-to-derived conversions - // specially? - default: - break; - } - } - - // Unary &. - if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) { - if (UO->getOpcode() == UO_AddrOf) { - LValue LV = EmitLValue(UO->getSubExpr()); - if (BaseInfo) *BaseInfo = LV.getBaseInfo(); - if (TBAAInfo) *TBAAInfo = LV.getTBAAInfo(); - return LV.getAddress(); - } - } - - // TODO: conditional operators, comma. - - // Otherwise, use the alignment of the type. - CharUnits Align = getNaturalPointeeTypeAlignment(E->getType(), BaseInfo, - TBAAInfo); - return Address(EmitScalarExpr(E), Align); -} - -RValue CodeGenFunction::GetUndefRValue(QualType Ty) { - if (Ty->isVoidType()) - return RValue::get(nullptr); - - switch (getEvaluationKind(Ty)) { - case TEK_Complex: { - llvm::Type *EltTy = - ConvertType(Ty->castAs<ComplexType>()->getElementType()); - llvm::Value *U = llvm::UndefValue::get(EltTy); - return RValue::getComplex(std::make_pair(U, U)); - } - - // If this is a use of an undefined aggregate type, the aggregate must have an - // identifiable address. Just because the contents of the value are undefined - // doesn't mean that the address can't be taken and compared. - case TEK_Aggregate: { - Address DestPtr = CreateMemTemp(Ty, "undef.agg.tmp"); - return RValue::getAggregate(DestPtr); - } - - case TEK_Scalar: - return RValue::get(llvm::UndefValue::get(ConvertType(Ty))); - } - llvm_unreachable("bad evaluation kind"); -} - -RValue CodeGenFunction::EmitUnsupportedRValue(const Expr *E, - const char *Name) { - ErrorUnsupported(E, Name); - return GetUndefRValue(E->getType()); -} - -LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E, - const char *Name) { - ErrorUnsupported(E, Name); - llvm::Type *Ty = llvm::PointerType::getUnqual(ConvertType(E->getType())); - return MakeAddrLValue(Address(llvm::UndefValue::get(Ty), CharUnits::One()), - E->getType()); -} - -bool CodeGenFunction::IsWrappedCXXThis(const Expr *Obj) { - const Expr *Base = Obj; - while (!isa<CXXThisExpr>(Base)) { - // The result of a dynamic_cast can be null. - if (isa<CXXDynamicCastExpr>(Base)) - return false; - - if (const auto *CE = dyn_cast<CastExpr>(Base)) { - Base = CE->getSubExpr(); - } else if (const auto *PE = dyn_cast<ParenExpr>(Base)) { - Base = PE->getSubExpr(); - } else if (const auto *UO = dyn_cast<UnaryOperator>(Base)) { - if (UO->getOpcode() == UO_Extension) - Base = UO->getSubExpr(); - else - return false; - } else { - return false; - } - } - return true; -} - -LValue CodeGenFunction::EmitCheckedLValue(const Expr *E, TypeCheckKind TCK) { - LValue LV; - if (SanOpts.has(SanitizerKind::ArrayBounds) && isa<ArraySubscriptExpr>(E)) - LV = EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E), /*Accessed*/true); - else - LV = EmitLValue(E); - if (!isa<DeclRefExpr>(E) && !LV.isBitField() && LV.isSimple()) { - SanitizerSet SkippedChecks; - if (const auto *ME = dyn_cast<MemberExpr>(E)) { - bool IsBaseCXXThis = IsWrappedCXXThis(ME->getBase()); - if (IsBaseCXXThis) - SkippedChecks.set(SanitizerKind::Alignment, true); - if (IsBaseCXXThis || isa<DeclRefExpr>(ME->getBase())) - SkippedChecks.set(SanitizerKind::Null, true); - } - EmitTypeCheck(TCK, E->getExprLoc(), LV.getPointer(), - E->getType(), LV.getAlignment(), SkippedChecks); - } - return LV; -} - -/// EmitLValue - Emit code to compute a designator that specifies the location -/// of the expression. -/// -/// This can return one of two things: a simple address or a bitfield reference. -/// In either case, the LLVM Value* in the LValue structure is guaranteed to be -/// an LLVM pointer type. -/// -/// If this returns a bitfield reference, nothing about the pointee type of the -/// LLVM value is known: For example, it may not be a pointer to an integer. -/// -/// If this returns a normal address, and if the lvalue's C type is fixed size, -/// this method guarantees that the returned pointer type will point to an LLVM -/// type of the same size of the lvalue's type. If the lvalue has a variable -/// length type, this is not possible. -/// -LValue CodeGenFunction::EmitLValue(const Expr *E) { - ApplyDebugLocation DL(*this, E); - switch (E->getStmtClass()) { - default: return EmitUnsupportedLValue(E, "l-value expression"); - - case Expr::ObjCPropertyRefExprClass: - llvm_unreachable("cannot emit a property reference directly"); - - case Expr::ObjCSelectorExprClass: - return EmitObjCSelectorLValue(cast<ObjCSelectorExpr>(E)); - case Expr::ObjCIsaExprClass: - return EmitObjCIsaExpr(cast<ObjCIsaExpr>(E)); - case Expr::BinaryOperatorClass: - return EmitBinaryOperatorLValue(cast<BinaryOperator>(E)); - case Expr::CompoundAssignOperatorClass: { - QualType Ty = E->getType(); - if (const AtomicType *AT = Ty->getAs<AtomicType>()) - Ty = AT->getValueType(); - if (!Ty->isAnyComplexType()) - return EmitCompoundAssignmentLValue(cast<CompoundAssignOperator>(E)); - return EmitComplexCompoundAssignmentLValue(cast<CompoundAssignOperator>(E)); - } - case Expr::CallExprClass: - case Expr::CXXMemberCallExprClass: - case Expr::CXXOperatorCallExprClass: - case Expr::UserDefinedLiteralClass: - return EmitCallExprLValue(cast<CallExpr>(E)); - case Expr::VAArgExprClass: - return EmitVAArgExprLValue(cast<VAArgExpr>(E)); - case Expr::DeclRefExprClass: - return EmitDeclRefLValue(cast<DeclRefExpr>(E)); - case Expr::ConstantExprClass: - return EmitLValue(cast<ConstantExpr>(E)->getSubExpr()); - case Expr::ParenExprClass: - return EmitLValue(cast<ParenExpr>(E)->getSubExpr()); - case Expr::GenericSelectionExprClass: - return EmitLValue(cast<GenericSelectionExpr>(E)->getResultExpr()); - case Expr::PredefinedExprClass: - return EmitPredefinedLValue(cast<PredefinedExpr>(E)); - case Expr::StringLiteralClass: - return EmitStringLiteralLValue(cast<StringLiteral>(E)); - case Expr::ObjCEncodeExprClass: - return EmitObjCEncodeExprLValue(cast<ObjCEncodeExpr>(E)); - case Expr::PseudoObjectExprClass: - return EmitPseudoObjectLValue(cast<PseudoObjectExpr>(E)); - case Expr::InitListExprClass: - return EmitInitListLValue(cast<InitListExpr>(E)); - case Expr::CXXTemporaryObjectExprClass: - case Expr::CXXConstructExprClass: - return EmitCXXConstructLValue(cast<CXXConstructExpr>(E)); - case Expr::CXXBindTemporaryExprClass: - return EmitCXXBindTemporaryLValue(cast<CXXBindTemporaryExpr>(E)); - case Expr::CXXUuidofExprClass: - return EmitCXXUuidofLValue(cast<CXXUuidofExpr>(E)); - case Expr::LambdaExprClass: - return EmitLambdaLValue(cast<LambdaExpr>(E)); - - case Expr::ExprWithCleanupsClass: { - const auto *cleanups = cast<ExprWithCleanups>(E); - enterFullExpression(cleanups); - RunCleanupsScope Scope(*this); - LValue LV = EmitLValue(cleanups->getSubExpr()); - if (LV.isSimple()) { - // Defend against branches out of gnu statement expressions surrounded by - // cleanups. - llvm::Value *V = LV.getPointer(); - Scope.ForceCleanup({&V}); - return LValue::MakeAddr(Address(V, LV.getAlignment()), LV.getType(), - getContext(), LV.getBaseInfo(), LV.getTBAAInfo()); - } - // FIXME: Is it possible to create an ExprWithCleanups that produces a - // bitfield lvalue or some other non-simple lvalue? - return LV; - } - - case Expr::CXXDefaultArgExprClass: - return EmitLValue(cast<CXXDefaultArgExpr>(E)->getExpr()); - case Expr::CXXDefaultInitExprClass: { - CXXDefaultInitExprScope Scope(*this); - return EmitLValue(cast<CXXDefaultInitExpr>(E)->getExpr()); - } - case Expr::CXXTypeidExprClass: - return EmitCXXTypeidLValue(cast<CXXTypeidExpr>(E)); - - case Expr::ObjCMessageExprClass: - return EmitObjCMessageExprLValue(cast<ObjCMessageExpr>(E)); - case Expr::ObjCIvarRefExprClass: - return EmitObjCIvarRefLValue(cast<ObjCIvarRefExpr>(E)); - case Expr::StmtExprClass: - return EmitStmtExprLValue(cast<StmtExpr>(E)); - case Expr::UnaryOperatorClass: - return EmitUnaryOpLValue(cast<UnaryOperator>(E)); - case Expr::ArraySubscriptExprClass: - return EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E)); - case Expr::OMPArraySectionExprClass: - return EmitOMPArraySectionExpr(cast<OMPArraySectionExpr>(E)); - case Expr::ExtVectorElementExprClass: - return EmitExtVectorElementExpr(cast<ExtVectorElementExpr>(E)); - case Expr::MemberExprClass: - return EmitMemberExpr(cast<MemberExpr>(E)); - case Expr::CompoundLiteralExprClass: - return EmitCompoundLiteralLValue(cast<CompoundLiteralExpr>(E)); - case Expr::ConditionalOperatorClass: - return EmitConditionalOperatorLValue(cast<ConditionalOperator>(E)); - case Expr::BinaryConditionalOperatorClass: - return EmitConditionalOperatorLValue(cast<BinaryConditionalOperator>(E)); - case Expr::ChooseExprClass: - return EmitLValue(cast<ChooseExpr>(E)->getChosenSubExpr()); - case Expr::OpaqueValueExprClass: - return EmitOpaqueValueLValue(cast<OpaqueValueExpr>(E)); - case Expr::SubstNonTypeTemplateParmExprClass: - return EmitLValue(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement()); - case Expr::ImplicitCastExprClass: - case Expr::CStyleCastExprClass: - case Expr::CXXFunctionalCastExprClass: - case Expr::CXXStaticCastExprClass: - case Expr::CXXDynamicCastExprClass: - case Expr::CXXReinterpretCastExprClass: - case Expr::CXXConstCastExprClass: - case Expr::ObjCBridgedCastExprClass: - return EmitCastLValue(cast<CastExpr>(E)); - - case Expr::MaterializeTemporaryExprClass: - return EmitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(E)); - - case Expr::CoawaitExprClass: - return EmitCoawaitLValue(cast<CoawaitExpr>(E)); - case Expr::CoyieldExprClass: - return EmitCoyieldLValue(cast<CoyieldExpr>(E)); - } -} - -/// Given an object of the given canonical type, can we safely copy a -/// value out of it based on its initializer? -static bool isConstantEmittableObjectType(QualType type) { - assert(type.isCanonical()); - assert(!type->isReferenceType()); - - // Must be const-qualified but non-volatile. - Qualifiers qs = type.getLocalQualifiers(); - if (!qs.hasConst() || qs.hasVolatile()) return false; - - // Otherwise, all object types satisfy this except C++ classes with - // mutable subobjects or non-trivial copy/destroy behavior. - if (const auto *RT = dyn_cast<RecordType>(type)) - if (const auto *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) - if (RD->hasMutableFields() || !RD->isTrivial()) - return false; - - return true; -} - -/// Can we constant-emit a load of a reference to a variable of the -/// given type? This is different from predicates like -/// Decl::isUsableInConstantExpressions because we do want it to apply -/// in situations that don't necessarily satisfy the language's rules -/// for this (e.g. C++'s ODR-use rules). For example, we want to able -/// to do this with const float variables even if those variables -/// aren't marked 'constexpr'. -enum ConstantEmissionKind { - CEK_None, - CEK_AsReferenceOnly, - CEK_AsValueOrReference, - CEK_AsValueOnly -}; -static ConstantEmissionKind checkVarTypeForConstantEmission(QualType type) { - type = type.getCanonicalType(); - if (const auto *ref = dyn_cast<ReferenceType>(type)) { - if (isConstantEmittableObjectType(ref->getPointeeType())) - return CEK_AsValueOrReference; - return CEK_AsReferenceOnly; - } - if (isConstantEmittableObjectType(type)) - return CEK_AsValueOnly; - return CEK_None; -} - -/// Try to emit a reference to the given value without producing it as -/// an l-value. This is actually more than an optimization: we can't -/// produce an l-value for variables that we never actually captured -/// in a block or lambda, which means const int variables or constexpr -/// literals or similar. -CodeGenFunction::ConstantEmission -CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) { - ValueDecl *value = refExpr->getDecl(); - - // The value needs to be an enum constant or a constant variable. - ConstantEmissionKind CEK; - if (isa<ParmVarDecl>(value)) { - CEK = CEK_None; - } else if (auto *var = dyn_cast<VarDecl>(value)) { - CEK = checkVarTypeForConstantEmission(var->getType()); - } else if (isa<EnumConstantDecl>(value)) { - CEK = CEK_AsValueOnly; - } else { - CEK = CEK_None; - } - if (CEK == CEK_None) return ConstantEmission(); - - Expr::EvalResult result; - bool resultIsReference; - QualType resultType; - - // It's best to evaluate all the way as an r-value if that's permitted. - if (CEK != CEK_AsReferenceOnly && - refExpr->EvaluateAsRValue(result, getContext())) { - resultIsReference = false; - resultType = refExpr->getType(); - - // Otherwise, try to evaluate as an l-value. - } else if (CEK != CEK_AsValueOnly && - refExpr->EvaluateAsLValue(result, getContext())) { - resultIsReference = true; - resultType = value->getType(); - - // Failure. - } else { - return ConstantEmission(); - } - - // In any case, if the initializer has side-effects, abandon ship. - if (result.HasSideEffects) - return ConstantEmission(); - - // Emit as a constant. - auto C = ConstantEmitter(*this).emitAbstract(refExpr->getLocation(), - result.Val, resultType); - - // Make sure we emit a debug reference to the global variable. - // This should probably fire even for - if (isa<VarDecl>(value)) { - if (!getContext().DeclMustBeEmitted(cast<VarDecl>(value))) - EmitDeclRefExprDbgValue(refExpr, result.Val); - } else { - assert(isa<EnumConstantDecl>(value)); - EmitDeclRefExprDbgValue(refExpr, result.Val); - } - - // If we emitted a reference constant, we need to dereference that. - if (resultIsReference) - return ConstantEmission::forReference(C); - - return ConstantEmission::forValue(C); -} - -static DeclRefExpr *tryToConvertMemberExprToDeclRefExpr(CodeGenFunction &CGF, - const MemberExpr *ME) { - if (auto *VD = dyn_cast<VarDecl>(ME->getMemberDecl())) { - // Try to emit static variable member expressions as DREs. - return DeclRefExpr::Create( - CGF.getContext(), NestedNameSpecifierLoc(), SourceLocation(), VD, - /*RefersToEnclosingVariableOrCapture=*/false, ME->getExprLoc(), - ME->getType(), ME->getValueKind()); - } - return nullptr; -} - -CodeGenFunction::ConstantEmission -CodeGenFunction::tryEmitAsConstant(const MemberExpr *ME) { - if (DeclRefExpr *DRE = tryToConvertMemberExprToDeclRefExpr(*this, ME)) - return tryEmitAsConstant(DRE); - return ConstantEmission(); -} - -llvm::Value *CodeGenFunction::emitScalarConstant( - const CodeGenFunction::ConstantEmission &Constant, Expr *E) { - assert(Constant && "not a constant"); - if (Constant.isReference()) - return EmitLoadOfLValue(Constant.getReferenceLValue(*this, E), - E->getExprLoc()) - .getScalarVal(); - return Constant.getValue(); -} - -llvm::Value *CodeGenFunction::EmitLoadOfScalar(LValue lvalue, - SourceLocation Loc) { - return EmitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(), - lvalue.getType(), Loc, lvalue.getBaseInfo(), - lvalue.getTBAAInfo(), lvalue.isNontemporal()); -} - -static bool hasBooleanRepresentation(QualType Ty) { - if (Ty->isBooleanType()) - return true; - - if (const EnumType *ET = Ty->getAs<EnumType>()) - return ET->getDecl()->getIntegerType()->isBooleanType(); - - if (const AtomicType *AT = Ty->getAs<AtomicType>()) - return hasBooleanRepresentation(AT->getValueType()); - - return false; -} - -static bool getRangeForType(CodeGenFunction &CGF, QualType Ty, - llvm::APInt &Min, llvm::APInt &End, - bool StrictEnums, bool IsBool) { - const EnumType *ET = Ty->getAs<EnumType>(); - bool IsRegularCPlusPlusEnum = CGF.getLangOpts().CPlusPlus && StrictEnums && - ET && !ET->getDecl()->isFixed(); - if (!IsBool && !IsRegularCPlusPlusEnum) - return false; - - if (IsBool) { - Min = llvm::APInt(CGF.getContext().getTypeSize(Ty), 0); - End = llvm::APInt(CGF.getContext().getTypeSize(Ty), 2); - } else { - const EnumDecl *ED = ET->getDecl(); - llvm::Type *LTy = CGF.ConvertTypeForMem(ED->getIntegerType()); - unsigned Bitwidth = LTy->getScalarSizeInBits(); - unsigned NumNegativeBits = ED->getNumNegativeBits(); - unsigned NumPositiveBits = ED->getNumPositiveBits(); - - if (NumNegativeBits) { - unsigned NumBits = std::max(NumNegativeBits, NumPositiveBits + 1); - assert(NumBits <= Bitwidth); - End = llvm::APInt(Bitwidth, 1) << (NumBits - 1); - Min = -End; - } else { - assert(NumPositiveBits <= Bitwidth); - End = llvm::APInt(Bitwidth, 1) << NumPositiveBits; - Min = llvm::APInt(Bitwidth, 0); - } - } - return true; -} - -llvm::MDNode *CodeGenFunction::getRangeForLoadFromType(QualType Ty) { - llvm::APInt Min, End; - if (!getRangeForType(*this, Ty, Min, End, CGM.getCodeGenOpts().StrictEnums, - hasBooleanRepresentation(Ty))) - return nullptr; - - llvm::MDBuilder MDHelper(getLLVMContext()); - return MDHelper.createRange(Min, End); -} - -bool CodeGenFunction::EmitScalarRangeCheck(llvm::Value *Value, QualType Ty, - SourceLocation Loc) { - bool HasBoolCheck = SanOpts.has(SanitizerKind::Bool); - bool HasEnumCheck = SanOpts.has(SanitizerKind::Enum); - if (!HasBoolCheck && !HasEnumCheck) - return false; - - bool IsBool = hasBooleanRepresentation(Ty) || - NSAPI(CGM.getContext()).isObjCBOOLType(Ty); - bool NeedsBoolCheck = HasBoolCheck && IsBool; - bool NeedsEnumCheck = HasEnumCheck && Ty->getAs<EnumType>(); - if (!NeedsBoolCheck && !NeedsEnumCheck) - return false; - - // Single-bit booleans don't need to be checked. Special-case this to avoid - // a bit width mismatch when handling bitfield values. This is handled by - // EmitFromMemory for the non-bitfield case. - if (IsBool && - cast<llvm::IntegerType>(Value->getType())->getBitWidth() == 1) - return false; - - llvm::APInt Min, End; - if (!getRangeForType(*this, Ty, Min, End, /*StrictEnums=*/true, IsBool)) - return true; - - auto &Ctx = getLLVMContext(); - SanitizerScope SanScope(this); - llvm::Value *Check; - --End; - if (!Min) { - Check = Builder.CreateICmpULE(Value, llvm::ConstantInt::get(Ctx, End)); - } else { - llvm::Value *Upper = - Builder.CreateICmpSLE(Value, llvm::ConstantInt::get(Ctx, End)); - llvm::Value *Lower = - Builder.CreateICmpSGE(Value, llvm::ConstantInt::get(Ctx, Min)); - Check = Builder.CreateAnd(Upper, Lower); - } - llvm::Constant *StaticArgs[] = {EmitCheckSourceLocation(Loc), - EmitCheckTypeDescriptor(Ty)}; - SanitizerMask Kind = - NeedsEnumCheck ? SanitizerKind::Enum : SanitizerKind::Bool; - EmitCheck(std::make_pair(Check, Kind), SanitizerHandler::LoadInvalidValue, - StaticArgs, EmitCheckValue(Value)); - return true; -} - -llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile, - QualType Ty, - SourceLocation Loc, - LValueBaseInfo BaseInfo, - TBAAAccessInfo TBAAInfo, - bool isNontemporal) { - if (!CGM.getCodeGenOpts().PreserveVec3Type) { - // For better performance, handle vector loads differently. - if (Ty->isVectorType()) { - const llvm::Type *EltTy = Addr.getElementType(); - - const auto *VTy = cast<llvm::VectorType>(EltTy); - - // Handle vectors of size 3 like size 4 for better performance. - if (VTy->getNumElements() == 3) { - - // Bitcast to vec4 type. - llvm::VectorType *vec4Ty = - llvm::VectorType::get(VTy->getElementType(), 4); - Address Cast = Builder.CreateElementBitCast(Addr, vec4Ty, "castToVec4"); - // Now load value. - llvm::Value *V = Builder.CreateLoad(Cast, Volatile, "loadVec4"); - - // Shuffle vector to get vec3. - V = Builder.CreateShuffleVector(V, llvm::UndefValue::get(vec4Ty), - {0, 1, 2}, "extractVec"); - return EmitFromMemory(V, Ty); - } - } - } - - // Atomic operations have to be done on integral types. - LValue AtomicLValue = - LValue::MakeAddr(Addr, Ty, getContext(), BaseInfo, TBAAInfo); - if (Ty->isAtomicType() || LValueIsSuitableForInlineAtomic(AtomicLValue)) { - return EmitAtomicLoad(AtomicLValue, Loc).getScalarVal(); - } - - llvm::LoadInst *Load = Builder.CreateLoad(Addr, Volatile); - if (isNontemporal) { - llvm::MDNode *Node = llvm::MDNode::get( - Load->getContext(), llvm::ConstantAsMetadata::get(Builder.getInt32(1))); - Load->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node); - } - - CGM.DecorateInstructionWithTBAA(Load, TBAAInfo); - - if (EmitScalarRangeCheck(Load, Ty, Loc)) { - // In order to prevent the optimizer from throwing away the check, don't - // attach range metadata to the load. - } else if (CGM.getCodeGenOpts().OptimizationLevel > 0) - if (llvm::MDNode *RangeInfo = getRangeForLoadFromType(Ty)) - Load->setMetadata(llvm::LLVMContext::MD_range, RangeInfo); - - return EmitFromMemory(Load, Ty); -} - -llvm::Value *CodeGenFunction::EmitToMemory(llvm::Value *Value, QualType Ty) { - // Bool has a different representation in memory than in registers. - if (hasBooleanRepresentation(Ty)) { - // This should really always be an i1, but sometimes it's already - // an i8, and it's awkward to track those cases down. - if (Value->getType()->isIntegerTy(1)) - return Builder.CreateZExt(Value, ConvertTypeForMem(Ty), "frombool"); - assert(Value->getType()->isIntegerTy(getContext().getTypeSize(Ty)) && - "wrong value rep of bool"); - } - - return Value; -} - -llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) { - // Bool has a different representation in memory than in registers. - if (hasBooleanRepresentation(Ty)) { - assert(Value->getType()->isIntegerTy(getContext().getTypeSize(Ty)) && - "wrong value rep of bool"); - return Builder.CreateTrunc(Value, Builder.getInt1Ty(), "tobool"); - } - - return Value; -} - -void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr, - bool Volatile, QualType Ty, - LValueBaseInfo BaseInfo, - TBAAAccessInfo TBAAInfo, - bool isInit, bool isNontemporal) { - if (!CGM.getCodeGenOpts().PreserveVec3Type) { - // Handle vectors differently to get better performance. - if (Ty->isVectorType()) { - llvm::Type *SrcTy = Value->getType(); - auto *VecTy = dyn_cast<llvm::VectorType>(SrcTy); - // Handle vec3 special. - if (VecTy && VecTy->getNumElements() == 3) { - // Our source is a vec3, do a shuffle vector to make it a vec4. - llvm::Constant *Mask[] = {Builder.getInt32(0), Builder.getInt32(1), - Builder.getInt32(2), - llvm::UndefValue::get(Builder.getInt32Ty())}; - llvm::Value *MaskV = llvm::ConstantVector::get(Mask); - Value = Builder.CreateShuffleVector(Value, llvm::UndefValue::get(VecTy), - MaskV, "extractVec"); - SrcTy = llvm::VectorType::get(VecTy->getElementType(), 4); - } - if (Addr.getElementType() != SrcTy) { - Addr = Builder.CreateElementBitCast(Addr, SrcTy, "storetmp"); - } - } - } - - Value = EmitToMemory(Value, Ty); - - LValue AtomicLValue = - LValue::MakeAddr(Addr, Ty, getContext(), BaseInfo, TBAAInfo); - if (Ty->isAtomicType() || - (!isInit && LValueIsSuitableForInlineAtomic(AtomicLValue))) { - EmitAtomicStore(RValue::get(Value), AtomicLValue, isInit); - return; - } - - llvm::StoreInst *Store = Builder.CreateStore(Value, Addr, Volatile); - if (isNontemporal) { - llvm::MDNode *Node = - llvm::MDNode::get(Store->getContext(), - llvm::ConstantAsMetadata::get(Builder.getInt32(1))); - Store->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node); - } - - CGM.DecorateInstructionWithTBAA(Store, TBAAInfo); -} - -void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue, - bool isInit) { - EmitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(), - lvalue.getType(), lvalue.getBaseInfo(), - lvalue.getTBAAInfo(), isInit, lvalue.isNontemporal()); -} - -/// EmitLoadOfLValue - Given an expression that represents a value lvalue, this -/// method emits the address of the lvalue, then loads the result as an rvalue, -/// returning the rvalue. -RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, SourceLocation Loc) { - if (LV.isObjCWeak()) { - // load of a __weak object. - Address AddrWeakObj = LV.getAddress(); - return RValue::get(CGM.getObjCRuntime().EmitObjCWeakRead(*this, - AddrWeakObj)); - } - if (LV.getQuals().getObjCLifetime() == Qualifiers::OCL_Weak) { - // In MRC mode, we do a load+autorelease. - if (!getLangOpts().ObjCAutoRefCount) { - return RValue::get(EmitARCLoadWeak(LV.getAddress())); - } - - // In ARC mode, we load retained and then consume the value. - llvm::Value *Object = EmitARCLoadWeakRetained(LV.getAddress()); - Object = EmitObjCConsumeObject(LV.getType(), Object); - return RValue::get(Object); - } - - if (LV.isSimple()) { - assert(!LV.getType()->isFunctionType()); - - // Everything needs a load. - return RValue::get(EmitLoadOfScalar(LV, Loc)); - } - - if (LV.isVectorElt()) { - llvm::LoadInst *Load = Builder.CreateLoad(LV.getVectorAddress(), - LV.isVolatileQualified()); - return RValue::get(Builder.CreateExtractElement(Load, LV.getVectorIdx(), - "vecext")); - } - - // If this is a reference to a subset of the elements of a vector, either - // shuffle the input or extract/insert them as appropriate. - if (LV.isExtVectorElt()) - return EmitLoadOfExtVectorElementLValue(LV); - - // Global Register variables always invoke intrinsics - if (LV.isGlobalReg()) - return EmitLoadOfGlobalRegLValue(LV); - - assert(LV.isBitField() && "Unknown LValue type!"); - return EmitLoadOfBitfieldLValue(LV, Loc); -} - -RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV, - SourceLocation Loc) { - const CGBitFieldInfo &Info = LV.getBitFieldInfo(); - - // Get the output type. - llvm::Type *ResLTy = ConvertType(LV.getType()); - - Address Ptr = LV.getBitFieldAddress(); - llvm::Value *Val = Builder.CreateLoad(Ptr, LV.isVolatileQualified(), "bf.load"); - - if (Info.IsSigned) { - assert(static_cast<unsigned>(Info.Offset + Info.Size) <= Info.StorageSize); - unsigned HighBits = Info.StorageSize - Info.Offset - Info.Size; - if (HighBits) - Val = Builder.CreateShl(Val, HighBits, "bf.shl"); - if (Info.Offset + HighBits) - Val = Builder.CreateAShr(Val, Info.Offset + HighBits, "bf.ashr"); - } else { - if (Info.Offset) - Val = Builder.CreateLShr(Val, Info.Offset, "bf.lshr"); - if (static_cast<unsigned>(Info.Offset) + Info.Size < Info.StorageSize) - Val = Builder.CreateAnd(Val, llvm::APInt::getLowBitsSet(Info.StorageSize, - Info.Size), - "bf.clear"); - } - Val = Builder.CreateIntCast(Val, ResLTy, Info.IsSigned, "bf.cast"); - EmitScalarRangeCheck(Val, LV.getType(), Loc); - return RValue::get(Val); -} - -// If this is a reference to a subset of the elements of a vector, create an -// appropriate shufflevector. -RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV) { - llvm::Value *Vec = Builder.CreateLoad(LV.getExtVectorAddress(), - LV.isVolatileQualified()); - - const llvm::Constant *Elts = LV.getExtVectorElts(); - - // If the result of the expression is a non-vector type, we must be extracting - // a single element. Just codegen as an extractelement. - const VectorType *ExprVT = LV.getType()->getAs<VectorType>(); - if (!ExprVT) { - unsigned InIdx = getAccessedFieldNo(0, Elts); - llvm::Value *Elt = llvm::ConstantInt::get(SizeTy, InIdx); - return RValue::get(Builder.CreateExtractElement(Vec, Elt)); - } - - // Always use shuffle vector to try to retain the original program structure - unsigned NumResultElts = ExprVT->getNumElements(); - - SmallVector<llvm::Constant*, 4> Mask; - for (unsigned i = 0; i != NumResultElts; ++i) - Mask.push_back(Builder.getInt32(getAccessedFieldNo(i, Elts))); - - llvm::Value *MaskV = llvm::ConstantVector::get(Mask); - Vec = Builder.CreateShuffleVector(Vec, llvm::UndefValue::get(Vec->getType()), - MaskV); - return RValue::get(Vec); -} - -/// Generates lvalue for partial ext_vector access. -Address CodeGenFunction::EmitExtVectorElementLValue(LValue LV) { - Address VectorAddress = LV.getExtVectorAddress(); - const VectorType *ExprVT = LV.getType()->getAs<VectorType>(); - QualType EQT = ExprVT->getElementType(); - llvm::Type *VectorElementTy = CGM.getTypes().ConvertType(EQT); - - Address CastToPointerElement = - Builder.CreateElementBitCast(VectorAddress, VectorElementTy, - "conv.ptr.element"); - - const llvm::Constant *Elts = LV.getExtVectorElts(); - unsigned ix = getAccessedFieldNo(0, Elts); - - Address VectorBasePtrPlusIx = - Builder.CreateConstInBoundsGEP(CastToPointerElement, ix, - getContext().getTypeSizeInChars(EQT), - "vector.elt"); - - return VectorBasePtrPlusIx; -} - -/// Load of global gamed gegisters are always calls to intrinsics. -RValue CodeGenFunction::EmitLoadOfGlobalRegLValue(LValue LV) { - assert((LV.getType()->isIntegerType() || LV.getType()->isPointerType()) && - "Bad type for register variable"); - llvm::MDNode *RegName = cast<llvm::MDNode>( - cast<llvm::MetadataAsValue>(LV.getGlobalReg())->getMetadata()); - - // We accept integer and pointer types only - llvm::Type *OrigTy = CGM.getTypes().ConvertType(LV.getType()); - llvm::Type *Ty = OrigTy; - if (OrigTy->isPointerTy()) - Ty = CGM.getTypes().getDataLayout().getIntPtrType(OrigTy); - llvm::Type *Types[] = { Ty }; - - llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::read_register, Types); - llvm::Value *Call = Builder.CreateCall( - F, llvm::MetadataAsValue::get(Ty->getContext(), RegName)); - if (OrigTy->isPointerTy()) - Call = Builder.CreateIntToPtr(Call, OrigTy); - return RValue::get(Call); -} - - -/// EmitStoreThroughLValue - Store the specified rvalue into the specified -/// lvalue, where both are guaranteed to the have the same type, and that type -/// is 'Ty'. -void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, - bool isInit) { - if (!Dst.isSimple()) { - if (Dst.isVectorElt()) { - // Read/modify/write the vector, inserting the new element. - llvm::Value *Vec = Builder.CreateLoad(Dst.getVectorAddress(), - Dst.isVolatileQualified()); - Vec = Builder.CreateInsertElement(Vec, Src.getScalarVal(), - Dst.getVectorIdx(), "vecins"); - Builder.CreateStore(Vec, Dst.getVectorAddress(), - Dst.isVolatileQualified()); - return; - } - - // If this is an update of extended vector elements, insert them as - // appropriate. - if (Dst.isExtVectorElt()) - return EmitStoreThroughExtVectorComponentLValue(Src, Dst); - - if (Dst.isGlobalReg()) - return EmitStoreThroughGlobalRegLValue(Src, Dst); - - assert(Dst.isBitField() && "Unknown LValue type"); - return EmitStoreThroughBitfieldLValue(Src, Dst); - } - - // There's special magic for assigning into an ARC-qualified l-value. - if (Qualifiers::ObjCLifetime Lifetime = Dst.getQuals().getObjCLifetime()) { - switch (Lifetime) { - case Qualifiers::OCL_None: - llvm_unreachable("present but none"); - - case Qualifiers::OCL_ExplicitNone: - // nothing special - break; - - case Qualifiers::OCL_Strong: - if (isInit) { - Src = RValue::get(EmitARCRetain(Dst.getType(), Src.getScalarVal())); - break; - } - EmitARCStoreStrong(Dst, Src.getScalarVal(), /*ignore*/ true); - return; - - case Qualifiers::OCL_Weak: - if (isInit) - // Initialize and then skip the primitive store. - EmitARCInitWeak(Dst.getAddress(), Src.getScalarVal()); - else - EmitARCStoreWeak(Dst.getAddress(), Src.getScalarVal(), /*ignore*/ true); - return; - - case Qualifiers::OCL_Autoreleasing: - Src = RValue::get(EmitObjCExtendObjectLifetime(Dst.getType(), - Src.getScalarVal())); - // fall into the normal path - break; - } - } - - if (Dst.isObjCWeak() && !Dst.isNonGC()) { - // load of a __weak object. - Address LvalueDst = Dst.getAddress(); - llvm::Value *src = Src.getScalarVal(); - CGM.getObjCRuntime().EmitObjCWeakAssign(*this, src, LvalueDst); - return; - } - - if (Dst.isObjCStrong() && !Dst.isNonGC()) { - // load of a __strong object. - Address LvalueDst = Dst.getAddress(); - llvm::Value *src = Src.getScalarVal(); - if (Dst.isObjCIvar()) { - assert(Dst.getBaseIvarExp() && "BaseIvarExp is NULL"); - llvm::Type *ResultType = IntPtrTy; - Address dst = EmitPointerWithAlignment(Dst.getBaseIvarExp()); - llvm::Value *RHS = dst.getPointer(); - RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast"); - llvm::Value *LHS = - Builder.CreatePtrToInt(LvalueDst.getPointer(), ResultType, - "sub.ptr.lhs.cast"); - llvm::Value *BytesBetween = Builder.CreateSub(LHS, RHS, "ivar.offset"); - CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst, - BytesBetween); - } else if (Dst.isGlobalObjCRef()) { - CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst, - Dst.isThreadLocalRef()); - } - else - CGM.getObjCRuntime().EmitObjCStrongCastAssign(*this, src, LvalueDst); - return; - } - - assert(Src.isScalar() && "Can't emit an agg store with this method"); - EmitStoreOfScalar(Src.getScalarVal(), Dst, isInit); -} - -void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, - llvm::Value **Result) { - const CGBitFieldInfo &Info = Dst.getBitFieldInfo(); - llvm::Type *ResLTy = ConvertTypeForMem(Dst.getType()); - Address Ptr = Dst.getBitFieldAddress(); - - // Get the source value, truncated to the width of the bit-field. - llvm::Value *SrcVal = Src.getScalarVal(); - - // Cast the source to the storage type and shift it into place. - SrcVal = Builder.CreateIntCast(SrcVal, Ptr.getElementType(), - /*IsSigned=*/false); - llvm::Value *MaskedVal = SrcVal; - - // See if there are other bits in the bitfield's storage we'll need to load - // and mask together with source before storing. - if (Info.StorageSize != Info.Size) { - assert(Info.StorageSize > Info.Size && "Invalid bitfield size."); - llvm::Value *Val = - Builder.CreateLoad(Ptr, Dst.isVolatileQualified(), "bf.load"); - - // Mask the source value as needed. - if (!hasBooleanRepresentation(Dst.getType())) - SrcVal = Builder.CreateAnd(SrcVal, - llvm::APInt::getLowBitsSet(Info.StorageSize, - Info.Size), - "bf.value"); - MaskedVal = SrcVal; - if (Info.Offset) - SrcVal = Builder.CreateShl(SrcVal, Info.Offset, "bf.shl"); - - // Mask out the original value. - Val = Builder.CreateAnd(Val, - ~llvm::APInt::getBitsSet(Info.StorageSize, - Info.Offset, - Info.Offset + Info.Size), - "bf.clear"); - - // Or together the unchanged values and the source value. - SrcVal = Builder.CreateOr(Val, SrcVal, "bf.set"); - } else { - assert(Info.Offset == 0); - } - - // Write the new value back out. - Builder.CreateStore(SrcVal, Ptr, Dst.isVolatileQualified()); - - // Return the new value of the bit-field, if requested. - if (Result) { - llvm::Value *ResultVal = MaskedVal; - - // Sign extend the value if needed. - if (Info.IsSigned) { - assert(Info.Size <= Info.StorageSize); - unsigned HighBits = Info.StorageSize - Info.Size; - if (HighBits) { - ResultVal = Builder.CreateShl(ResultVal, HighBits, "bf.result.shl"); - ResultVal = Builder.CreateAShr(ResultVal, HighBits, "bf.result.ashr"); - } - } - - ResultVal = Builder.CreateIntCast(ResultVal, ResLTy, Info.IsSigned, - "bf.result.cast"); - *Result = EmitFromMemory(ResultVal, Dst.getType()); - } -} - -void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src, - LValue Dst) { - // This access turns into a read/modify/write of the vector. Load the input - // value now. - llvm::Value *Vec = Builder.CreateLoad(Dst.getExtVectorAddress(), - Dst.isVolatileQualified()); - const llvm::Constant *Elts = Dst.getExtVectorElts(); - - llvm::Value *SrcVal = Src.getScalarVal(); - - if (const VectorType *VTy = Dst.getType()->getAs<VectorType>()) { - unsigned NumSrcElts = VTy->getNumElements(); - unsigned NumDstElts = Vec->getType()->getVectorNumElements(); - if (NumDstElts == NumSrcElts) { - // Use shuffle vector is the src and destination are the same number of - // elements and restore the vector mask since it is on the side it will be - // stored. - SmallVector<llvm::Constant*, 4> Mask(NumDstElts); - for (unsigned i = 0; i != NumSrcElts; ++i) - Mask[getAccessedFieldNo(i, Elts)] = Builder.getInt32(i); - - llvm::Value *MaskV = llvm::ConstantVector::get(Mask); - Vec = Builder.CreateShuffleVector(SrcVal, - llvm::UndefValue::get(Vec->getType()), - MaskV); - } else if (NumDstElts > NumSrcElts) { - // Extended the source vector to the same length and then shuffle it - // into the destination. - // FIXME: since we're shuffling with undef, can we just use the indices - // into that? This could be simpler. - SmallVector<llvm::Constant*, 4> ExtMask; - for (unsigned i = 0; i != NumSrcElts; ++i) - ExtMask.push_back(Builder.getInt32(i)); - ExtMask.resize(NumDstElts, llvm::UndefValue::get(Int32Ty)); - llvm::Value *ExtMaskV = llvm::ConstantVector::get(ExtMask); - llvm::Value *ExtSrcVal = - Builder.CreateShuffleVector(SrcVal, - llvm::UndefValue::get(SrcVal->getType()), - ExtMaskV); - // build identity - SmallVector<llvm::Constant*, 4> Mask; - for (unsigned i = 0; i != NumDstElts; ++i) - Mask.push_back(Builder.getInt32(i)); - - // When the vector size is odd and .odd or .hi is used, the last element - // of the Elts constant array will be one past the size of the vector. - // Ignore the last element here, if it is greater than the mask size. - if (getAccessedFieldNo(NumSrcElts - 1, Elts) == Mask.size()) - NumSrcElts--; - - // modify when what gets shuffled in - for (unsigned i = 0; i != NumSrcElts; ++i) - Mask[getAccessedFieldNo(i, Elts)] = Builder.getInt32(i+NumDstElts); - llvm::Value *MaskV = llvm::ConstantVector::get(Mask); - Vec = Builder.CreateShuffleVector(Vec, ExtSrcVal, MaskV); - } else { - // We should never shorten the vector - llvm_unreachable("unexpected shorten vector length"); - } - } else { - // If the Src is a scalar (not a vector) it must be updating one element. - unsigned InIdx = getAccessedFieldNo(0, Elts); - llvm::Value *Elt = llvm::ConstantInt::get(SizeTy, InIdx); - Vec = Builder.CreateInsertElement(Vec, SrcVal, Elt); - } - - Builder.CreateStore(Vec, Dst.getExtVectorAddress(), - Dst.isVolatileQualified()); -} - -/// Store of global named registers are always calls to intrinsics. -void CodeGenFunction::EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst) { - assert((Dst.getType()->isIntegerType() || Dst.getType()->isPointerType()) && - "Bad type for register variable"); - llvm::MDNode *RegName = cast<llvm::MDNode>( - cast<llvm::MetadataAsValue>(Dst.getGlobalReg())->getMetadata()); - assert(RegName && "Register LValue is not metadata"); - - // We accept integer and pointer types only - llvm::Type *OrigTy = CGM.getTypes().ConvertType(Dst.getType()); - llvm::Type *Ty = OrigTy; - if (OrigTy->isPointerTy()) - Ty = CGM.getTypes().getDataLayout().getIntPtrType(OrigTy); - llvm::Type *Types[] = { Ty }; - - llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::write_register, Types); - llvm::Value *Value = Src.getScalarVal(); - if (OrigTy->isPointerTy()) - Value = Builder.CreatePtrToInt(Value, Ty); - Builder.CreateCall( - F, {llvm::MetadataAsValue::get(Ty->getContext(), RegName), Value}); -} - -// setObjCGCLValueClass - sets class of the lvalue for the purpose of -// generating write-barries API. It is currently a global, ivar, -// or neither. -static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E, - LValue &LV, - bool IsMemberAccess=false) { - if (Ctx.getLangOpts().getGC() == LangOptions::NonGC) - return; - - if (isa<ObjCIvarRefExpr>(E)) { - QualType ExpTy = E->getType(); - if (IsMemberAccess && ExpTy->isPointerType()) { - // If ivar is a structure pointer, assigning to field of - // this struct follows gcc's behavior and makes it a non-ivar - // writer-barrier conservatively. - ExpTy = ExpTy->getAs<PointerType>()->getPointeeType(); - if (ExpTy->isRecordType()) { - LV.setObjCIvar(false); - return; - } - } - LV.setObjCIvar(true); - auto *Exp = cast<ObjCIvarRefExpr>(const_cast<Expr *>(E)); - LV.setBaseIvarExp(Exp->getBase()); - LV.setObjCArray(E->getType()->isArrayType()); - return; - } - - if (const auto *Exp = dyn_cast<DeclRefExpr>(E)) { - if (const auto *VD = dyn_cast<VarDecl>(Exp->getDecl())) { - if (VD->hasGlobalStorage()) { - LV.setGlobalObjCRef(true); - LV.setThreadLocalRef(VD->getTLSKind() != VarDecl::TLS_None); - } - } - LV.setObjCArray(E->getType()->isArrayType()); - return; - } - - if (const auto *Exp = dyn_cast<UnaryOperator>(E)) { - setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV, IsMemberAccess); - return; - } - - if (const auto *Exp = dyn_cast<ParenExpr>(E)) { - setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV, IsMemberAccess); - if (LV.isObjCIvar()) { - // If cast is to a structure pointer, follow gcc's behavior and make it - // a non-ivar write-barrier. - QualType ExpTy = E->getType(); - if (ExpTy->isPointerType()) - ExpTy = ExpTy->getAs<PointerType>()->getPointeeType(); - if (ExpTy->isRecordType()) - LV.setObjCIvar(false); - } - return; - } - - if (const auto *Exp = dyn_cast<GenericSelectionExpr>(E)) { - setObjCGCLValueClass(Ctx, Exp->getResultExpr(), LV); - return; - } - - if (const auto *Exp = dyn_cast<ImplicitCastExpr>(E)) { - setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV, IsMemberAccess); - return; - } - - if (const auto *Exp = dyn_cast<CStyleCastExpr>(E)) { - setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV, IsMemberAccess); - return; - } - - if (const auto *Exp = dyn_cast<ObjCBridgedCastExpr>(E)) { - setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV, IsMemberAccess); - return; - } - - if (const auto *Exp = dyn_cast<ArraySubscriptExpr>(E)) { - setObjCGCLValueClass(Ctx, Exp->getBase(), LV); - if (LV.isObjCIvar() && !LV.isObjCArray()) - // Using array syntax to assigning to what an ivar points to is not - // same as assigning to the ivar itself. {id *Names;} Names[i] = 0; - LV.setObjCIvar(false); - else if (LV.isGlobalObjCRef() && !LV.isObjCArray()) - // Using array syntax to assigning to what global points to is not - // same as assigning to the global itself. {id *G;} G[i] = 0; - LV.setGlobalObjCRef(false); - return; - } - - if (const auto *Exp = dyn_cast<MemberExpr>(E)) { - setObjCGCLValueClass(Ctx, Exp->getBase(), LV, true); - // We don't know if member is an 'ivar', but this flag is looked at - // only in the context of LV.isObjCIvar(). - LV.setObjCArray(E->getType()->isArrayType()); - return; - } -} - -static llvm::Value * -EmitBitCastOfLValueToProperType(CodeGenFunction &CGF, - llvm::Value *V, llvm::Type *IRType, - StringRef Name = StringRef()) { - unsigned AS = cast<llvm::PointerType>(V->getType())->getAddressSpace(); - return CGF.Builder.CreateBitCast(V, IRType->getPointerTo(AS), Name); -} - -static LValue EmitThreadPrivateVarDeclLValue( - CodeGenFunction &CGF, const VarDecl *VD, QualType T, Address Addr, - llvm::Type *RealVarTy, SourceLocation Loc) { - Addr = CGF.CGM.getOpenMPRuntime().getAddrOfThreadPrivate(CGF, VD, Addr, Loc); - Addr = CGF.Builder.CreateElementBitCast(Addr, RealVarTy); - return CGF.MakeAddrLValue(Addr, T, AlignmentSource::Decl); -} - -static Address emitDeclTargetLinkVarDeclLValue(CodeGenFunction &CGF, - const VarDecl *VD, QualType T) { - llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); - if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_To) - return Address::invalid(); - assert(*Res == OMPDeclareTargetDeclAttr::MT_Link && "Expected link clause"); - QualType PtrTy = CGF.getContext().getPointerType(VD->getType()); - Address Addr = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD); - return CGF.EmitLoadOfPointer(Addr, PtrTy->castAs<PointerType>()); -} - -Address -CodeGenFunction::EmitLoadOfReference(LValue RefLVal, - LValueBaseInfo *PointeeBaseInfo, - TBAAAccessInfo *PointeeTBAAInfo) { - llvm::LoadInst *Load = Builder.CreateLoad(RefLVal.getAddress(), - RefLVal.isVolatile()); - CGM.DecorateInstructionWithTBAA(Load, RefLVal.getTBAAInfo()); - - CharUnits Align = getNaturalTypeAlignment(RefLVal.getType()->getPointeeType(), - PointeeBaseInfo, PointeeTBAAInfo, - /* forPointeeType= */ true); - return Address(Load, Align); -} - -LValue CodeGenFunction::EmitLoadOfReferenceLValue(LValue RefLVal) { - LValueBaseInfo PointeeBaseInfo; - TBAAAccessInfo PointeeTBAAInfo; - Address PointeeAddr = EmitLoadOfReference(RefLVal, &PointeeBaseInfo, - &PointeeTBAAInfo); - return MakeAddrLValue(PointeeAddr, RefLVal.getType()->getPointeeType(), - PointeeBaseInfo, PointeeTBAAInfo); -} - -Address CodeGenFunction::EmitLoadOfPointer(Address Ptr, - const PointerType *PtrTy, - LValueBaseInfo *BaseInfo, - TBAAAccessInfo *TBAAInfo) { - llvm::Value *Addr = Builder.CreateLoad(Ptr); - return Address(Addr, getNaturalTypeAlignment(PtrTy->getPointeeType(), - BaseInfo, TBAAInfo, - /*forPointeeType=*/true)); -} - -LValue CodeGenFunction::EmitLoadOfPointerLValue(Address PtrAddr, - const PointerType *PtrTy) { - LValueBaseInfo BaseInfo; - TBAAAccessInfo TBAAInfo; - Address Addr = EmitLoadOfPointer(PtrAddr, PtrTy, &BaseInfo, &TBAAInfo); - return MakeAddrLValue(Addr, PtrTy->getPointeeType(), BaseInfo, TBAAInfo); -} - -static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF, - const Expr *E, const VarDecl *VD) { - QualType T = E->getType(); - - // If it's thread_local, emit a call to its wrapper function instead. - if (VD->getTLSKind() == VarDecl::TLS_Dynamic && - CGF.CGM.getCXXABI().usesThreadWrapperFunction()) - return CGF.CGM.getCXXABI().EmitThreadLocalVarDeclLValue(CGF, VD, T); - // Check if the variable is marked as declare target with link clause in - // device codegen. - if (CGF.getLangOpts().OpenMPIsDevice) { - Address Addr = emitDeclTargetLinkVarDeclLValue(CGF, VD, T); - if (Addr.isValid()) - return CGF.MakeAddrLValue(Addr, T, AlignmentSource::Decl); - } - - llvm::Value *V = CGF.CGM.GetAddrOfGlobalVar(VD); - llvm::Type *RealVarTy = CGF.getTypes().ConvertTypeForMem(VD->getType()); - V = EmitBitCastOfLValueToProperType(CGF, V, RealVarTy); - CharUnits Alignment = CGF.getContext().getDeclAlign(VD); - Address Addr(V, Alignment); - // Emit reference to the private copy of the variable if it is an OpenMP - // threadprivate variable. - if (CGF.getLangOpts().OpenMP && !CGF.getLangOpts().OpenMPSimd && - VD->hasAttr<OMPThreadPrivateDeclAttr>()) { - return EmitThreadPrivateVarDeclLValue(CGF, VD, T, Addr, RealVarTy, - E->getExprLoc()); - } - LValue LV = VD->getType()->isReferenceType() ? - CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(), - AlignmentSource::Decl) : - CGF.MakeAddrLValue(Addr, T, AlignmentSource::Decl); - setObjCGCLValueClass(CGF.getContext(), E, LV); - return LV; -} - -static llvm::Constant *EmitFunctionDeclPointer(CodeGenModule &CGM, - const FunctionDecl *FD) { - if (FD->hasAttr<WeakRefAttr>()) { - ConstantAddress aliasee = CGM.GetWeakRefReference(FD); - return aliasee.getPointer(); - } - - llvm::Constant *V = CGM.GetAddrOfFunction(FD); - if (!FD->hasPrototype()) { - if (const FunctionProtoType *Proto = - FD->getType()->getAs<FunctionProtoType>()) { - // Ugly case: for a K&R-style definition, the type of the definition - // isn't the same as the type of a use. Correct for this with a - // bitcast. - QualType NoProtoType = - CGM.getContext().getFunctionNoProtoType(Proto->getReturnType()); - NoProtoType = CGM.getContext().getPointerType(NoProtoType); - V = llvm::ConstantExpr::getBitCast(V, - CGM.getTypes().ConvertType(NoProtoType)); - } - } - return V; -} - -static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF, - const Expr *E, const FunctionDecl *FD) { - llvm::Value *V = EmitFunctionDeclPointer(CGF.CGM, FD); - CharUnits Alignment = CGF.getContext().getDeclAlign(FD); - return CGF.MakeAddrLValue(V, E->getType(), Alignment, - AlignmentSource::Decl); -} - -static LValue EmitCapturedFieldLValue(CodeGenFunction &CGF, const FieldDecl *FD, - llvm::Value *ThisValue) { - QualType TagType = CGF.getContext().getTagDeclType(FD->getParent()); - LValue LV = CGF.MakeNaturalAlignAddrLValue(ThisValue, TagType); - return CGF.EmitLValueForField(LV, FD); -} - -/// Named Registers are named metadata pointing to the register name -/// which will be read from/written to as an argument to the intrinsic -/// @llvm.read/write_register. -/// So far, only the name is being passed down, but other options such as -/// register type, allocation type or even optimization options could be -/// passed down via the metadata node. -static LValue EmitGlobalNamedRegister(const VarDecl *VD, CodeGenModule &CGM) { - SmallString<64> Name("llvm.named.register."); - AsmLabelAttr *Asm = VD->getAttr<AsmLabelAttr>(); - assert(Asm->getLabel().size() < 64-Name.size() && - "Register name too big"); - Name.append(Asm->getLabel()); - llvm::NamedMDNode *M = - CGM.getModule().getOrInsertNamedMetadata(Name); - if (M->getNumOperands() == 0) { - llvm::MDString *Str = llvm::MDString::get(CGM.getLLVMContext(), - Asm->getLabel()); - llvm::Metadata *Ops[] = {Str}; - M->addOperand(llvm::MDNode::get(CGM.getLLVMContext(), Ops)); - } - - CharUnits Alignment = CGM.getContext().getDeclAlign(VD); - - llvm::Value *Ptr = - llvm::MetadataAsValue::get(CGM.getLLVMContext(), M->getOperand(0)); - return LValue::MakeGlobalReg(Address(Ptr, Alignment), VD->getType()); -} - -LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { - const NamedDecl *ND = E->getDecl(); - QualType T = E->getType(); - - if (const auto *VD = dyn_cast<VarDecl>(ND)) { - // Global Named registers access via intrinsics only - if (VD->getStorageClass() == SC_Register && - VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl()) - return EmitGlobalNamedRegister(VD, CGM); - - // A DeclRefExpr for a reference initialized by a constant expression can - // appear without being odr-used. Directly emit the constant initializer. - const Expr *Init = VD->getAnyInitializer(VD); - const auto *BD = dyn_cast_or_null<BlockDecl>(CurCodeDecl); - if (Init && !isa<ParmVarDecl>(VD) && VD->getType()->isReferenceType() && - VD->isUsableInConstantExpressions(getContext()) && - VD->checkInitIsICE() && - // Do not emit if it is private OpenMP variable. - !(E->refersToEnclosingVariableOrCapture() && - ((CapturedStmtInfo && - (LocalDeclMap.count(VD->getCanonicalDecl()) || - CapturedStmtInfo->lookup(VD->getCanonicalDecl()))) || - LambdaCaptureFields.lookup(VD->getCanonicalDecl()) || - (BD && BD->capturesVariable(VD))))) { - llvm::Constant *Val = - ConstantEmitter(*this).emitAbstract(E->getLocation(), - *VD->evaluateValue(), - VD->getType()); - assert(Val && "failed to emit reference constant expression"); - // FIXME: Eventually we will want to emit vector element references. - - // Should we be using the alignment of the constant pointer we emitted? - CharUnits Alignment = getNaturalTypeAlignment(E->getType(), - /* BaseInfo= */ nullptr, - /* TBAAInfo= */ nullptr, - /* forPointeeType= */ true); - return MakeAddrLValue(Address(Val, Alignment), T, AlignmentSource::Decl); - } - - // Check for captured variables. - if (E->refersToEnclosingVariableOrCapture()) { - VD = VD->getCanonicalDecl(); - if (auto *FD = LambdaCaptureFields.lookup(VD)) - return EmitCapturedFieldLValue(*this, FD, CXXABIThisValue); - else if (CapturedStmtInfo) { - auto I = LocalDeclMap.find(VD); - if (I != LocalDeclMap.end()) { - if (VD->getType()->isReferenceType()) - return EmitLoadOfReferenceLValue(I->second, VD->getType(), - AlignmentSource::Decl); - return MakeAddrLValue(I->second, T); - } - LValue CapLVal = - EmitCapturedFieldLValue(*this, CapturedStmtInfo->lookup(VD), - CapturedStmtInfo->getContextValue()); - return MakeAddrLValue( - Address(CapLVal.getPointer(), getContext().getDeclAlign(VD)), - CapLVal.getType(), LValueBaseInfo(AlignmentSource::Decl), - CapLVal.getTBAAInfo()); - } - - assert(isa<BlockDecl>(CurCodeDecl)); - Address addr = GetAddrOfBlockDecl(VD); - return MakeAddrLValue(addr, T, AlignmentSource::Decl); - } - } - - // FIXME: We should be able to assert this for FunctionDecls as well! - // FIXME: We should be able to assert this for all DeclRefExprs, not just - // those with a valid source location. - assert((ND->isUsed(false) || !isa<VarDecl>(ND) || - !E->getLocation().isValid()) && - "Should not use decl without marking it used!"); - - if (ND->hasAttr<WeakRefAttr>()) { - const auto *VD = cast<ValueDecl>(ND); - ConstantAddress Aliasee = CGM.GetWeakRefReference(VD); - return MakeAddrLValue(Aliasee, T, AlignmentSource::Decl); - } - - if (const auto *VD = dyn_cast<VarDecl>(ND)) { - // Check if this is a global variable. - if (VD->hasLinkage() || VD->isStaticDataMember()) - return EmitGlobalVarDeclLValue(*this, E, VD); - - Address addr = Address::invalid(); - - // The variable should generally be present in the local decl map. - auto iter = LocalDeclMap.find(VD); - if (iter != LocalDeclMap.end()) { - addr = iter->second; - - // Otherwise, it might be static local we haven't emitted yet for - // some reason; most likely, because it's in an outer function. - } else if (VD->isStaticLocal()) { - addr = Address(CGM.getOrCreateStaticVarDecl( - *VD, CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false)), - getContext().getDeclAlign(VD)); - - // No other cases for now. - } else { - llvm_unreachable("DeclRefExpr for Decl not entered in LocalDeclMap?"); - } - - - // Check for OpenMP threadprivate variables. - if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd && - VD->hasAttr<OMPThreadPrivateDeclAttr>()) { - return EmitThreadPrivateVarDeclLValue( - *this, VD, T, addr, getTypes().ConvertTypeForMem(VD->getType()), - E->getExprLoc()); - } - - // Drill into block byref variables. - bool isBlockByref = VD->isEscapingByref(); - if (isBlockByref) { - addr = emitBlockByrefAddress(addr, VD); - } - - // Drill into reference types. - LValue LV = VD->getType()->isReferenceType() ? - EmitLoadOfReferenceLValue(addr, VD->getType(), AlignmentSource::Decl) : - MakeAddrLValue(addr, T, AlignmentSource::Decl); - - bool isLocalStorage = VD->hasLocalStorage(); - - bool NonGCable = isLocalStorage && - !VD->getType()->isReferenceType() && - !isBlockByref; - if (NonGCable) { - LV.getQuals().removeObjCGCAttr(); - LV.setNonGC(true); - } - - bool isImpreciseLifetime = - (isLocalStorage && !VD->hasAttr<ObjCPreciseLifetimeAttr>()); - if (isImpreciseLifetime) - LV.setARCPreciseLifetime(ARCImpreciseLifetime); - setObjCGCLValueClass(getContext(), E, LV); - return LV; - } - - if (const auto *FD = dyn_cast<FunctionDecl>(ND)) - return EmitFunctionDeclLValue(*this, E, FD); - - // FIXME: While we're emitting a binding from an enclosing scope, all other - // DeclRefExprs we see should be implicitly treated as if they also refer to - // an enclosing scope. - if (const auto *BD = dyn_cast<BindingDecl>(ND)) - return EmitLValue(BD->getBinding()); - - llvm_unreachable("Unhandled DeclRefExpr"); -} - -LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) { - // __extension__ doesn't affect lvalue-ness. - if (E->getOpcode() == UO_Extension) - return EmitLValue(E->getSubExpr()); - - QualType ExprTy = getContext().getCanonicalType(E->getSubExpr()->getType()); - switch (E->getOpcode()) { - default: llvm_unreachable("Unknown unary operator lvalue!"); - case UO_Deref: { - QualType T = E->getSubExpr()->getType()->getPointeeType(); - assert(!T.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type"); - - LValueBaseInfo BaseInfo; - TBAAAccessInfo TBAAInfo; - Address Addr = EmitPointerWithAlignment(E->getSubExpr(), &BaseInfo, - &TBAAInfo); - LValue LV = MakeAddrLValue(Addr, T, BaseInfo, TBAAInfo); - LV.getQuals().setAddressSpace(ExprTy.getAddressSpace()); - - // We should not generate __weak write barrier on indirect reference - // of a pointer to object; as in void foo (__weak id *param); *param = 0; - // But, we continue to generate __strong write barrier on indirect write - // into a pointer to object. - if (getLangOpts().ObjC && - getLangOpts().getGC() != LangOptions::NonGC && - LV.isObjCWeak()) - LV.setNonGC(!E->isOBJCGCCandidate(getContext())); - return LV; - } - case UO_Real: - case UO_Imag: { - LValue LV = EmitLValue(E->getSubExpr()); - assert(LV.isSimple() && "real/imag on non-ordinary l-value"); - - // __real is valid on scalars. This is a faster way of testing that. - // __imag can only produce an rvalue on scalars. - if (E->getOpcode() == UO_Real && - !LV.getAddress().getElementType()->isStructTy()) { - assert(E->getSubExpr()->getType()->isArithmeticType()); - return LV; - } - - QualType T = ExprTy->castAs<ComplexType>()->getElementType(); - - Address Component = - (E->getOpcode() == UO_Real - ? emitAddrOfRealComponent(LV.getAddress(), LV.getType()) - : emitAddrOfImagComponent(LV.getAddress(), LV.getType())); - LValue ElemLV = MakeAddrLValue(Component, T, LV.getBaseInfo(), - CGM.getTBAAInfoForSubobject(LV, T)); - ElemLV.getQuals().addQualifiers(LV.getQuals()); - return ElemLV; - } - case UO_PreInc: - case UO_PreDec: { - LValue LV = EmitLValue(E->getSubExpr()); - bool isInc = E->getOpcode() == UO_PreInc; - - if (E->getType()->isAnyComplexType()) - EmitComplexPrePostIncDec(E, LV, isInc, true/*isPre*/); - else - EmitScalarPrePostIncDec(E, LV, isInc, true/*isPre*/); - return LV; - } - } -} - -LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) { - return MakeAddrLValue(CGM.GetAddrOfConstantStringFromLiteral(E), - E->getType(), AlignmentSource::Decl); -} - -LValue CodeGenFunction::EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E) { - return MakeAddrLValue(CGM.GetAddrOfConstantStringFromObjCEncode(E), - E->getType(), AlignmentSource::Decl); -} - -LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { - auto SL = E->getFunctionName(); - assert(SL != nullptr && "No StringLiteral name in PredefinedExpr"); - StringRef FnName = CurFn->getName(); - if (FnName.startswith("\01")) - FnName = FnName.substr(1); - StringRef NameItems[] = { - PredefinedExpr::getIdentKindName(E->getIdentKind()), FnName}; - std::string GVName = llvm::join(NameItems, NameItems + 2, "."); - if (auto *BD = dyn_cast_or_null<BlockDecl>(CurCodeDecl)) { - std::string Name = SL->getString(); - if (!Name.empty()) { - unsigned Discriminator = - CGM.getCXXABI().getMangleContext().getBlockId(BD, true); - if (Discriminator) - Name += "_" + Twine(Discriminator + 1).str(); - auto C = CGM.GetAddrOfConstantCString(Name, GVName.c_str()); - return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl); - } else { - auto C = CGM.GetAddrOfConstantCString(FnName, GVName.c_str()); - return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl); - } - } - auto C = CGM.GetAddrOfConstantStringFromLiteral(SL, GVName); - return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl); -} - -/// Emit a type description suitable for use by a runtime sanitizer library. The -/// format of a type descriptor is -/// -/// \code -/// { i16 TypeKind, i16 TypeInfo } -/// \endcode -/// -/// followed by an array of i8 containing the type name. TypeKind is 0 for an -/// integer, 1 for a floating point value, and -1 for anything else. -llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { - // Only emit each type's descriptor once. - if (llvm::Constant *C = CGM.getTypeDescriptorFromMap(T)) - return C; - - uint16_t TypeKind = -1; - uint16_t TypeInfo = 0; - - if (T->isIntegerType()) { - TypeKind = 0; - TypeInfo = (llvm::Log2_32(getContext().getTypeSize(T)) << 1) | - (T->isSignedIntegerType() ? 1 : 0); - } else if (T->isFloatingType()) { - TypeKind = 1; - TypeInfo = getContext().getTypeSize(T); - } - - // Format the type name as if for a diagnostic, including quotes and - // optionally an 'aka'. - SmallString<32> Buffer; - CGM.getDiags().ConvertArgToString(DiagnosticsEngine::ak_qualtype, - (intptr_t)T.getAsOpaquePtr(), - StringRef(), StringRef(), None, Buffer, - None); - - llvm::Constant *Components[] = { - Builder.getInt16(TypeKind), Builder.getInt16(TypeInfo), - llvm::ConstantDataArray::getString(getLLVMContext(), Buffer) - }; - llvm::Constant *Descriptor = llvm::ConstantStruct::getAnon(Components); - - auto *GV = new llvm::GlobalVariable( - CGM.getModule(), Descriptor->getType(), - /*isConstant=*/true, llvm::GlobalVariable::PrivateLinkage, Descriptor); - GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - CGM.getSanitizerMetadata()->disableSanitizerForGlobal(GV); - - // Remember the descriptor for this type. - CGM.setTypeDescriptorInMap(T, GV); - - return GV; -} - -llvm::Value *CodeGenFunction::EmitCheckValue(llvm::Value *V) { - llvm::Type *TargetTy = IntPtrTy; - - if (V->getType() == TargetTy) - return V; - - // Floating-point types which fit into intptr_t are bitcast to integers - // and then passed directly (after zero-extension, if necessary). - if (V->getType()->isFloatingPointTy()) { - unsigned Bits = V->getType()->getPrimitiveSizeInBits(); - if (Bits <= TargetTy->getIntegerBitWidth()) - V = Builder.CreateBitCast(V, llvm::Type::getIntNTy(getLLVMContext(), - Bits)); - } - - // Integers which fit in intptr_t are zero-extended and passed directly. - if (V->getType()->isIntegerTy() && - V->getType()->getIntegerBitWidth() <= TargetTy->getIntegerBitWidth()) - return Builder.CreateZExt(V, TargetTy); - - // Pointers are passed directly, everything else is passed by address. - if (!V->getType()->isPointerTy()) { - Address Ptr = CreateDefaultAlignTempAlloca(V->getType()); - Builder.CreateStore(V, Ptr); - V = Ptr.getPointer(); - } - return Builder.CreatePtrToInt(V, TargetTy); -} - -/// Emit a representation of a SourceLocation for passing to a handler -/// in a sanitizer runtime library. The format for this data is: -/// \code -/// struct SourceLocation { -/// const char *Filename; -/// int32_t Line, Column; -/// }; -/// \endcode -/// For an invalid SourceLocation, the Filename pointer is null. -llvm::Constant *CodeGenFunction::EmitCheckSourceLocation(SourceLocation Loc) { - llvm::Constant *Filename; - int Line, Column; - - PresumedLoc PLoc = getContext().getSourceManager().getPresumedLoc(Loc); - if (PLoc.isValid()) { - StringRef FilenameString = PLoc.getFilename(); - - int PathComponentsToStrip = - CGM.getCodeGenOpts().EmitCheckPathComponentsToStrip; - if (PathComponentsToStrip < 0) { - assert(PathComponentsToStrip != INT_MIN); - int PathComponentsToKeep = -PathComponentsToStrip; - auto I = llvm::sys::path::rbegin(FilenameString); - auto E = llvm::sys::path::rend(FilenameString); - while (I != E && --PathComponentsToKeep) - ++I; - - FilenameString = FilenameString.substr(I - E); - } else if (PathComponentsToStrip > 0) { - auto I = llvm::sys::path::begin(FilenameString); - auto E = llvm::sys::path::end(FilenameString); - while (I != E && PathComponentsToStrip--) - ++I; - - if (I != E) - FilenameString = - FilenameString.substr(I - llvm::sys::path::begin(FilenameString)); - else - FilenameString = llvm::sys::path::filename(FilenameString); - } - - auto FilenameGV = CGM.GetAddrOfConstantCString(FilenameString, ".src"); - CGM.getSanitizerMetadata()->disableSanitizerForGlobal( - cast<llvm::GlobalVariable>(FilenameGV.getPointer())); - Filename = FilenameGV.getPointer(); - Line = PLoc.getLine(); - Column = PLoc.getColumn(); - } else { - Filename = llvm::Constant::getNullValue(Int8PtrTy); - Line = Column = 0; - } - - llvm::Constant *Data[] = {Filename, Builder.getInt32(Line), - Builder.getInt32(Column)}; - - return llvm::ConstantStruct::getAnon(Data); -} - -namespace { -/// Specify under what conditions this check can be recovered -enum class CheckRecoverableKind { - /// Always terminate program execution if this check fails. - Unrecoverable, - /// Check supports recovering, runtime has both fatal (noreturn) and - /// non-fatal handlers for this check. - Recoverable, - /// Runtime conditionally aborts, always need to support recovery. - AlwaysRecoverable -}; -} - -static CheckRecoverableKind getRecoverableKind(SanitizerMask Kind) { - assert(llvm::countPopulation(Kind) == 1); - switch (Kind) { - case SanitizerKind::Vptr: - return CheckRecoverableKind::AlwaysRecoverable; - case SanitizerKind::Return: - case SanitizerKind::Unreachable: - return CheckRecoverableKind::Unrecoverable; - default: - return CheckRecoverableKind::Recoverable; - } -} - -namespace { -struct SanitizerHandlerInfo { - char const *const Name; - unsigned Version; -}; -} - -const SanitizerHandlerInfo SanitizerHandlers[] = { -#define SANITIZER_CHECK(Enum, Name, Version) {#Name, Version}, - LIST_SANITIZER_CHECKS -#undef SANITIZER_CHECK -}; - -static void emitCheckHandlerCall(CodeGenFunction &CGF, - llvm::FunctionType *FnType, - ArrayRef<llvm::Value *> FnArgs, - SanitizerHandler CheckHandler, - CheckRecoverableKind RecoverKind, bool IsFatal, - llvm::BasicBlock *ContBB) { - assert(IsFatal || RecoverKind != CheckRecoverableKind::Unrecoverable); - Optional<ApplyDebugLocation> DL; - if (!CGF.Builder.getCurrentDebugLocation()) { - // Ensure that the call has at least an artificial debug location. - DL.emplace(CGF, SourceLocation()); - } - bool NeedsAbortSuffix = - IsFatal && RecoverKind != CheckRecoverableKind::Unrecoverable; - bool MinimalRuntime = CGF.CGM.getCodeGenOpts().SanitizeMinimalRuntime; - const SanitizerHandlerInfo &CheckInfo = SanitizerHandlers[CheckHandler]; - const StringRef CheckName = CheckInfo.Name; - std::string FnName = "__ubsan_handle_" + CheckName.str(); - if (CheckInfo.Version && !MinimalRuntime) - FnName += "_v" + llvm::utostr(CheckInfo.Version); - if (MinimalRuntime) - FnName += "_minimal"; - if (NeedsAbortSuffix) - FnName += "_abort"; - bool MayReturn = - !IsFatal || RecoverKind == CheckRecoverableKind::AlwaysRecoverable; - - llvm::AttrBuilder B; - if (!MayReturn) { - B.addAttribute(llvm::Attribute::NoReturn) - .addAttribute(llvm::Attribute::NoUnwind); - } - B.addAttribute(llvm::Attribute::UWTable); - - llvm::Value *Fn = CGF.CGM.CreateRuntimeFunction( - FnType, FnName, - llvm::AttributeList::get(CGF.getLLVMContext(), - llvm::AttributeList::FunctionIndex, B), - /*Local=*/true); - llvm::CallInst *HandlerCall = CGF.EmitNounwindRuntimeCall(Fn, FnArgs); - if (!MayReturn) { - HandlerCall->setDoesNotReturn(); - CGF.Builder.CreateUnreachable(); - } else { - CGF.Builder.CreateBr(ContBB); - } -} - -void CodeGenFunction::EmitCheck( - ArrayRef<std::pair<llvm::Value *, SanitizerMask>> Checked, - SanitizerHandler CheckHandler, ArrayRef<llvm::Constant *> StaticArgs, - ArrayRef<llvm::Value *> DynamicArgs) { - assert(IsSanitizerScope); - assert(Checked.size() > 0); - assert(CheckHandler >= 0 && - size_t(CheckHandler) < llvm::array_lengthof(SanitizerHandlers)); - const StringRef CheckName = SanitizerHandlers[CheckHandler].Name; - - llvm::Value *FatalCond = nullptr; - llvm::Value *RecoverableCond = nullptr; - llvm::Value *TrapCond = nullptr; - for (int i = 0, n = Checked.size(); i < n; ++i) { - llvm::Value *Check = Checked[i].first; - // -fsanitize-trap= overrides -fsanitize-recover=. - llvm::Value *&Cond = - CGM.getCodeGenOpts().SanitizeTrap.has(Checked[i].second) - ? TrapCond - : CGM.getCodeGenOpts().SanitizeRecover.has(Checked[i].second) - ? RecoverableCond - : FatalCond; - Cond = Cond ? Builder.CreateAnd(Cond, Check) : Check; - } - - if (TrapCond) - EmitTrapCheck(TrapCond); - if (!FatalCond && !RecoverableCond) - return; - - llvm::Value *JointCond; - if (FatalCond && RecoverableCond) - JointCond = Builder.CreateAnd(FatalCond, RecoverableCond); - else - JointCond = FatalCond ? FatalCond : RecoverableCond; - assert(JointCond); - - CheckRecoverableKind RecoverKind = getRecoverableKind(Checked[0].second); - assert(SanOpts.has(Checked[0].second)); -#ifndef NDEBUG - for (int i = 1, n = Checked.size(); i < n; ++i) { - assert(RecoverKind == getRecoverableKind(Checked[i].second) && - "All recoverable kinds in a single check must be same!"); - assert(SanOpts.has(Checked[i].second)); - } -#endif - - llvm::BasicBlock *Cont = createBasicBlock("cont"); - llvm::BasicBlock *Handlers = createBasicBlock("handler." + CheckName); - llvm::Instruction *Branch = Builder.CreateCondBr(JointCond, Cont, Handlers); - // Give hint that we very much don't expect to execute the handler - // Value chosen to match UR_NONTAKEN_WEIGHT, see BranchProbabilityInfo.cpp - llvm::MDBuilder MDHelper(getLLVMContext()); - llvm::MDNode *Node = MDHelper.createBranchWeights((1U << 20) - 1, 1); - Branch->setMetadata(llvm::LLVMContext::MD_prof, Node); - EmitBlock(Handlers); - - // Handler functions take an i8* pointing to the (handler-specific) static - // information block, followed by a sequence of intptr_t arguments - // representing operand values. - SmallVector<llvm::Value *, 4> Args; - SmallVector<llvm::Type *, 4> ArgTypes; - if (!CGM.getCodeGenOpts().SanitizeMinimalRuntime) { - Args.reserve(DynamicArgs.size() + 1); - ArgTypes.reserve(DynamicArgs.size() + 1); - - // Emit handler arguments and create handler function type. - if (!StaticArgs.empty()) { - llvm::Constant *Info = llvm::ConstantStruct::getAnon(StaticArgs); - auto *InfoPtr = - new llvm::GlobalVariable(CGM.getModule(), Info->getType(), false, - llvm::GlobalVariable::PrivateLinkage, Info); - InfoPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - CGM.getSanitizerMetadata()->disableSanitizerForGlobal(InfoPtr); - Args.push_back(Builder.CreateBitCast(InfoPtr, Int8PtrTy)); - ArgTypes.push_back(Int8PtrTy); - } - - for (size_t i = 0, n = DynamicArgs.size(); i != n; ++i) { - Args.push_back(EmitCheckValue(DynamicArgs[i])); - ArgTypes.push_back(IntPtrTy); - } - } - - llvm::FunctionType *FnType = - llvm::FunctionType::get(CGM.VoidTy, ArgTypes, false); - - if (!FatalCond || !RecoverableCond) { - // Simple case: we need to generate a single handler call, either - // fatal, or non-fatal. - emitCheckHandlerCall(*this, FnType, Args, CheckHandler, RecoverKind, - (FatalCond != nullptr), Cont); - } else { - // Emit two handler calls: first one for set of unrecoverable checks, - // another one for recoverable. - llvm::BasicBlock *NonFatalHandlerBB = - createBasicBlock("non_fatal." + CheckName); - llvm::BasicBlock *FatalHandlerBB = createBasicBlock("fatal." + CheckName); - Builder.CreateCondBr(FatalCond, NonFatalHandlerBB, FatalHandlerBB); - EmitBlock(FatalHandlerBB); - emitCheckHandlerCall(*this, FnType, Args, CheckHandler, RecoverKind, true, - NonFatalHandlerBB); - EmitBlock(NonFatalHandlerBB); - emitCheckHandlerCall(*this, FnType, Args, CheckHandler, RecoverKind, false, - Cont); - } - - EmitBlock(Cont); -} - -void CodeGenFunction::EmitCfiSlowPathCheck( - SanitizerMask Kind, llvm::Value *Cond, llvm::ConstantInt *TypeId, - llvm::Value *Ptr, ArrayRef<llvm::Constant *> StaticArgs) { - llvm::BasicBlock *Cont = createBasicBlock("cfi.cont"); - - llvm::BasicBlock *CheckBB = createBasicBlock("cfi.slowpath"); - llvm::BranchInst *BI = Builder.CreateCondBr(Cond, Cont, CheckBB); - - llvm::MDBuilder MDHelper(getLLVMContext()); - llvm::MDNode *Node = MDHelper.createBranchWeights((1U << 20) - 1, 1); - BI->setMetadata(llvm::LLVMContext::MD_prof, Node); - - EmitBlock(CheckBB); - - bool WithDiag = !CGM.getCodeGenOpts().SanitizeTrap.has(Kind); - - llvm::CallInst *CheckCall; - llvm::Constant *SlowPathFn; - if (WithDiag) { - llvm::Constant *Info = llvm::ConstantStruct::getAnon(StaticArgs); - auto *InfoPtr = - new llvm::GlobalVariable(CGM.getModule(), Info->getType(), false, - llvm::GlobalVariable::PrivateLinkage, Info); - InfoPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - CGM.getSanitizerMetadata()->disableSanitizerForGlobal(InfoPtr); - - SlowPathFn = CGM.getModule().getOrInsertFunction( - "__cfi_slowpath_diag", - llvm::FunctionType::get(VoidTy, {Int64Ty, Int8PtrTy, Int8PtrTy}, - false)); - CheckCall = Builder.CreateCall( - SlowPathFn, {TypeId, Ptr, Builder.CreateBitCast(InfoPtr, Int8PtrTy)}); - } else { - SlowPathFn = CGM.getModule().getOrInsertFunction( - "__cfi_slowpath", - llvm::FunctionType::get(VoidTy, {Int64Ty, Int8PtrTy}, false)); - CheckCall = Builder.CreateCall(SlowPathFn, {TypeId, Ptr}); - } - - CGM.setDSOLocal(cast<llvm::GlobalValue>(SlowPathFn->stripPointerCasts())); - CheckCall->setDoesNotThrow(); - - EmitBlock(Cont); -} - -// Emit a stub for __cfi_check function so that the linker knows about this -// symbol in LTO mode. -void CodeGenFunction::EmitCfiCheckStub() { - llvm::Module *M = &CGM.getModule(); - auto &Ctx = M->getContext(); - llvm::Function *F = llvm::Function::Create( - llvm::FunctionType::get(VoidTy, {Int64Ty, Int8PtrTy, Int8PtrTy}, false), - llvm::GlobalValue::WeakAnyLinkage, "__cfi_check", M); - CGM.setDSOLocal(F); - llvm::BasicBlock *BB = llvm::BasicBlock::Create(Ctx, "entry", F); - // FIXME: consider emitting an intrinsic call like - // call void @llvm.cfi_check(i64 %0, i8* %1, i8* %2) - // which can be lowered in CrossDSOCFI pass to the actual contents of - // __cfi_check. This would allow inlining of __cfi_check calls. - llvm::CallInst::Create( - llvm::Intrinsic::getDeclaration(M, llvm::Intrinsic::trap), "", BB); - llvm::ReturnInst::Create(Ctx, nullptr, BB); -} - -// This function is basically a switch over the CFI failure kind, which is -// extracted from CFICheckFailData (1st function argument). Each case is either -// llvm.trap or a call to one of the two runtime handlers, based on -// -fsanitize-trap and -fsanitize-recover settings. Default case (invalid -// failure kind) traps, but this should really never happen. CFICheckFailData -// can be nullptr if the calling module has -fsanitize-trap behavior for this -// check kind; in this case __cfi_check_fail traps as well. -void CodeGenFunction::EmitCfiCheckFail() { - SanitizerScope SanScope(this); - FunctionArgList Args; - ImplicitParamDecl ArgData(getContext(), getContext().VoidPtrTy, - ImplicitParamDecl::Other); - ImplicitParamDecl ArgAddr(getContext(), getContext().VoidPtrTy, - ImplicitParamDecl::Other); - Args.push_back(&ArgData); - Args.push_back(&ArgAddr); - - const CGFunctionInfo &FI = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(getContext().VoidTy, Args); - - llvm::Function *F = llvm::Function::Create( - llvm::FunctionType::get(VoidTy, {VoidPtrTy, VoidPtrTy}, false), - llvm::GlobalValue::WeakODRLinkage, "__cfi_check_fail", &CGM.getModule()); - F->setVisibility(llvm::GlobalValue::HiddenVisibility); - - StartFunction(GlobalDecl(), CGM.getContext().VoidTy, F, FI, Args, - SourceLocation()); - - // This function should not be affected by blacklist. This function does - // not have a source location, but "src:*" would still apply. Revert any - // changes to SanOpts made in StartFunction. - SanOpts = CGM.getLangOpts().Sanitize; - - llvm::Value *Data = - EmitLoadOfScalar(GetAddrOfLocalVar(&ArgData), /*Volatile=*/false, - CGM.getContext().VoidPtrTy, ArgData.getLocation()); - llvm::Value *Addr = - EmitLoadOfScalar(GetAddrOfLocalVar(&ArgAddr), /*Volatile=*/false, - CGM.getContext().VoidPtrTy, ArgAddr.getLocation()); - - // Data == nullptr means the calling module has trap behaviour for this check. - llvm::Value *DataIsNotNullPtr = - Builder.CreateICmpNE(Data, llvm::ConstantPointerNull::get(Int8PtrTy)); - EmitTrapCheck(DataIsNotNullPtr); - - llvm::StructType *SourceLocationTy = - llvm::StructType::get(VoidPtrTy, Int32Ty, Int32Ty); - llvm::StructType *CfiCheckFailDataTy = - llvm::StructType::get(Int8Ty, SourceLocationTy, VoidPtrTy); - - llvm::Value *V = Builder.CreateConstGEP2_32( - CfiCheckFailDataTy, - Builder.CreatePointerCast(Data, CfiCheckFailDataTy->getPointerTo(0)), 0, - 0); - Address CheckKindAddr(V, getIntAlign()); - llvm::Value *CheckKind = Builder.CreateLoad(CheckKindAddr); - - llvm::Value *AllVtables = llvm::MetadataAsValue::get( - CGM.getLLVMContext(), - llvm::MDString::get(CGM.getLLVMContext(), "all-vtables")); - llvm::Value *ValidVtable = Builder.CreateZExt( - Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test), - {Addr, AllVtables}), - IntPtrTy); - - const std::pair<int, SanitizerMask> CheckKinds[] = { - {CFITCK_VCall, SanitizerKind::CFIVCall}, - {CFITCK_NVCall, SanitizerKind::CFINVCall}, - {CFITCK_DerivedCast, SanitizerKind::CFIDerivedCast}, - {CFITCK_UnrelatedCast, SanitizerKind::CFIUnrelatedCast}, - {CFITCK_ICall, SanitizerKind::CFIICall}}; - - SmallVector<std::pair<llvm::Value *, SanitizerMask>, 5> Checks; - for (auto CheckKindMaskPair : CheckKinds) { - int Kind = CheckKindMaskPair.first; - SanitizerMask Mask = CheckKindMaskPair.second; - llvm::Value *Cond = - Builder.CreateICmpNE(CheckKind, llvm::ConstantInt::get(Int8Ty, Kind)); - if (CGM.getLangOpts().Sanitize.has(Mask)) - EmitCheck(std::make_pair(Cond, Mask), SanitizerHandler::CFICheckFail, {}, - {Data, Addr, ValidVtable}); - else - EmitTrapCheck(Cond); - } - - FinishFunction(); - // The only reference to this function will be created during LTO link. - // Make sure it survives until then. - CGM.addUsedGlobal(F); -} - -void CodeGenFunction::EmitUnreachable(SourceLocation Loc) { - if (SanOpts.has(SanitizerKind::Unreachable)) { - SanitizerScope SanScope(this); - EmitCheck(std::make_pair(static_cast<llvm::Value *>(Builder.getFalse()), - SanitizerKind::Unreachable), - SanitizerHandler::BuiltinUnreachable, - EmitCheckSourceLocation(Loc), None); - } - Builder.CreateUnreachable(); -} - -void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked) { - llvm::BasicBlock *Cont = createBasicBlock("cont"); - - // If we're optimizing, collapse all calls to trap down to just one per - // function to save on code size. - if (!CGM.getCodeGenOpts().OptimizationLevel || !TrapBB) { - TrapBB = createBasicBlock("trap"); - Builder.CreateCondBr(Checked, Cont, TrapBB); - EmitBlock(TrapBB); - llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap); - TrapCall->setDoesNotReturn(); - TrapCall->setDoesNotThrow(); - Builder.CreateUnreachable(); - } else { - Builder.CreateCondBr(Checked, Cont, TrapBB); - } - - EmitBlock(Cont); -} - -llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) { - llvm::CallInst *TrapCall = Builder.CreateCall(CGM.getIntrinsic(IntrID)); - - if (!CGM.getCodeGenOpts().TrapFuncName.empty()) { - auto A = llvm::Attribute::get(getLLVMContext(), "trap-func-name", - CGM.getCodeGenOpts().TrapFuncName); - TrapCall->addAttribute(llvm::AttributeList::FunctionIndex, A); - } - - return TrapCall; -} - -Address CodeGenFunction::EmitArrayToPointerDecay(const Expr *E, - LValueBaseInfo *BaseInfo, - TBAAAccessInfo *TBAAInfo) { - assert(E->getType()->isArrayType() && - "Array to pointer decay must have array source type!"); - - // Expressions of array type can't be bitfields or vector elements. - LValue LV = EmitLValue(E); - Address Addr = LV.getAddress(); - - // If the array type was an incomplete type, we need to make sure - // the decay ends up being the right type. - llvm::Type *NewTy = ConvertType(E->getType()); - Addr = Builder.CreateElementBitCast(Addr, NewTy); - - // Note that VLA pointers are always decayed, so we don't need to do - // anything here. - if (!E->getType()->isVariableArrayType()) { - assert(isa<llvm::ArrayType>(Addr.getElementType()) && - "Expected pointer to array"); - Addr = Builder.CreateStructGEP(Addr, 0, CharUnits::Zero(), "arraydecay"); - } - - // The result of this decay conversion points to an array element within the - // base lvalue. However, since TBAA currently does not support representing - // accesses to elements of member arrays, we conservatively represent accesses - // to the pointee object as if it had no any base lvalue specified. - // TODO: Support TBAA for member arrays. - QualType EltType = E->getType()->castAsArrayTypeUnsafe()->getElementType(); - if (BaseInfo) *BaseInfo = LV.getBaseInfo(); - if (TBAAInfo) *TBAAInfo = CGM.getTBAAAccessInfo(EltType); - - return Builder.CreateElementBitCast(Addr, ConvertTypeForMem(EltType)); -} - -/// isSimpleArrayDecayOperand - If the specified expr is a simple decay from an -/// array to pointer, return the array subexpression. -static const Expr *isSimpleArrayDecayOperand(const Expr *E) { - // If this isn't just an array->pointer decay, bail out. - const auto *CE = dyn_cast<CastExpr>(E); - if (!CE || CE->getCastKind() != CK_ArrayToPointerDecay) - return nullptr; - - // If this is a decay from variable width array, bail out. - const Expr *SubExpr = CE->getSubExpr(); - if (SubExpr->getType()->isVariableArrayType()) - return nullptr; - - return SubExpr; -} - -static llvm::Value *emitArraySubscriptGEP(CodeGenFunction &CGF, - llvm::Value *ptr, - ArrayRef<llvm::Value*> indices, - bool inbounds, - bool signedIndices, - SourceLocation loc, - const llvm::Twine &name = "arrayidx") { - if (inbounds) { - return CGF.EmitCheckedInBoundsGEP(ptr, indices, signedIndices, - CodeGenFunction::NotSubtraction, loc, - name); - } else { - return CGF.Builder.CreateGEP(ptr, indices, name); - } -} - -static CharUnits getArrayElementAlign(CharUnits arrayAlign, - llvm::Value *idx, - CharUnits eltSize) { - // If we have a constant index, we can use the exact offset of the - // element we're accessing. - if (auto constantIdx = dyn_cast<llvm::ConstantInt>(idx)) { - CharUnits offset = constantIdx->getZExtValue() * eltSize; - return arrayAlign.alignmentAtOffset(offset); - - // Otherwise, use the worst-case alignment for any element. - } else { - return arrayAlign.alignmentOfArrayElement(eltSize); - } -} - -static QualType getFixedSizeElementType(const ASTContext &ctx, - const VariableArrayType *vla) { - QualType eltType; - do { - eltType = vla->getElementType(); - } while ((vla = ctx.getAsVariableArrayType(eltType))); - return eltType; -} - -static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, - ArrayRef<llvm::Value *> indices, - QualType eltType, bool inbounds, - bool signedIndices, SourceLocation loc, - const llvm::Twine &name = "arrayidx") { - // All the indices except that last must be zero. -#ifndef NDEBUG - for (auto idx : indices.drop_back()) - assert(isa<llvm::ConstantInt>(idx) && - cast<llvm::ConstantInt>(idx)->isZero()); -#endif - - // Determine the element size of the statically-sized base. This is - // the thing that the indices are expressed in terms of. - if (auto vla = CGF.getContext().getAsVariableArrayType(eltType)) { - eltType = getFixedSizeElementType(CGF.getContext(), vla); - } - - // We can use that to compute the best alignment of the element. - CharUnits eltSize = CGF.getContext().getTypeSizeInChars(eltType); - CharUnits eltAlign = - getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize); - - llvm::Value *eltPtr = emitArraySubscriptGEP( - CGF, addr.getPointer(), indices, inbounds, signedIndices, loc, name); - return Address(eltPtr, eltAlign); -} - -LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, - bool Accessed) { - // The index must always be an integer, which is not an aggregate. Emit it - // in lexical order (this complexity is, sadly, required by C++17). - llvm::Value *IdxPre = - (E->getLHS() == E->getIdx()) ? EmitScalarExpr(E->getIdx()) : nullptr; - bool SignedIndices = false; - auto EmitIdxAfterBase = [&, IdxPre](bool Promote) -> llvm::Value * { - auto *Idx = IdxPre; - if (E->getLHS() != E->getIdx()) { - assert(E->getRHS() == E->getIdx() && "index was neither LHS nor RHS"); - Idx = EmitScalarExpr(E->getIdx()); - } - - QualType IdxTy = E->getIdx()->getType(); - bool IdxSigned = IdxTy->isSignedIntegerOrEnumerationType(); - SignedIndices |= IdxSigned; - - if (SanOpts.has(SanitizerKind::ArrayBounds)) - EmitBoundsCheck(E, E->getBase(), Idx, IdxTy, Accessed); - - // Extend or truncate the index type to 32 or 64-bits. - if (Promote && Idx->getType() != IntPtrTy) - Idx = Builder.CreateIntCast(Idx, IntPtrTy, IdxSigned, "idxprom"); - - return Idx; - }; - IdxPre = nullptr; - - // If the base is a vector type, then we are forming a vector element lvalue - // with this subscript. - if (E->getBase()->getType()->isVectorType() && - !isa<ExtVectorElementExpr>(E->getBase())) { - // Emit the vector as an lvalue to get its address. - LValue LHS = EmitLValue(E->getBase()); - auto *Idx = EmitIdxAfterBase(/*Promote*/false); - assert(LHS.isSimple() && "Can only subscript lvalue vectors here!"); - return LValue::MakeVectorElt(LHS.getAddress(), Idx, E->getBase()->getType(), - LHS.getBaseInfo(), TBAAAccessInfo()); - } - - // All the other cases basically behave like simple offsetting. - - // Handle the extvector case we ignored above. - if (isa<ExtVectorElementExpr>(E->getBase())) { - LValue LV = EmitLValue(E->getBase()); - auto *Idx = EmitIdxAfterBase(/*Promote*/true); - Address Addr = EmitExtVectorElementLValue(LV); - - QualType EltType = LV.getType()->castAs<VectorType>()->getElementType(); - Addr = emitArraySubscriptGEP(*this, Addr, Idx, EltType, /*inbounds*/ true, - SignedIndices, E->getExprLoc()); - return MakeAddrLValue(Addr, EltType, LV.getBaseInfo(), - CGM.getTBAAInfoForSubobject(LV, EltType)); - } - - LValueBaseInfo EltBaseInfo; - TBAAAccessInfo EltTBAAInfo; - Address Addr = Address::invalid(); - if (const VariableArrayType *vla = - getContext().getAsVariableArrayType(E->getType())) { - // The base must be a pointer, which is not an aggregate. Emit - // it. It needs to be emitted first in case it's what captures - // the VLA bounds. - Addr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo); - auto *Idx = EmitIdxAfterBase(/*Promote*/true); - - // The element count here is the total number of non-VLA elements. - llvm::Value *numElements = getVLASize(vla).NumElts; - - // Effectively, the multiply by the VLA size is part of the GEP. - // GEP indexes are signed, and scaling an index isn't permitted to - // signed-overflow, so we use the same semantics for our explicit - // multiply. We suppress this if overflow is not undefined behavior. - if (getLangOpts().isSignedOverflowDefined()) { - Idx = Builder.CreateMul(Idx, numElements); - } else { - Idx = Builder.CreateNSWMul(Idx, numElements); - } - - Addr = emitArraySubscriptGEP(*this, Addr, Idx, vla->getElementType(), - !getLangOpts().isSignedOverflowDefined(), - SignedIndices, E->getExprLoc()); - - } else if (const ObjCObjectType *OIT = E->getType()->getAs<ObjCObjectType>()){ - // Indexing over an interface, as in "NSString *P; P[4];" - - // Emit the base pointer. - Addr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo); - auto *Idx = EmitIdxAfterBase(/*Promote*/true); - - CharUnits InterfaceSize = getContext().getTypeSizeInChars(OIT); - llvm::Value *InterfaceSizeVal = - llvm::ConstantInt::get(Idx->getType(), InterfaceSize.getQuantity()); - - llvm::Value *ScaledIdx = Builder.CreateMul(Idx, InterfaceSizeVal); - - // We don't necessarily build correct LLVM struct types for ObjC - // interfaces, so we can't rely on GEP to do this scaling - // correctly, so we need to cast to i8*. FIXME: is this actually - // true? A lot of other things in the fragile ABI would break... - llvm::Type *OrigBaseTy = Addr.getType(); - Addr = Builder.CreateElementBitCast(Addr, Int8Ty); - - // Do the GEP. - CharUnits EltAlign = - getArrayElementAlign(Addr.getAlignment(), Idx, InterfaceSize); - llvm::Value *EltPtr = - emitArraySubscriptGEP(*this, Addr.getPointer(), ScaledIdx, false, - SignedIndices, E->getExprLoc()); - Addr = Address(EltPtr, EltAlign); - - // Cast back. - Addr = Builder.CreateBitCast(Addr, OrigBaseTy); - } else if (const Expr *Array = isSimpleArrayDecayOperand(E->getBase())) { - // If this is A[i] where A is an array, the frontend will have decayed the - // base to be a ArrayToPointerDecay implicit cast. While correct, it is - // inefficient at -O0 to emit a "gep A, 0, 0" when codegen'ing it, then a - // "gep x, i" here. Emit one "gep A, 0, i". - assert(Array->getType()->isArrayType() && - "Array to pointer decay must have array source type!"); - LValue ArrayLV; - // For simple multidimensional array indexing, set the 'accessed' flag for - // better bounds-checking of the base expression. - if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Array)) - ArrayLV = EmitArraySubscriptExpr(ASE, /*Accessed*/ true); - else - ArrayLV = EmitLValue(Array); - auto *Idx = EmitIdxAfterBase(/*Promote*/true); - - // Propagate the alignment from the array itself to the result. - Addr = emitArraySubscriptGEP( - *this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx}, - E->getType(), !getLangOpts().isSignedOverflowDefined(), SignedIndices, - E->getExprLoc()); - EltBaseInfo = ArrayLV.getBaseInfo(); - EltTBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, E->getType()); - } else { - // The base must be a pointer; emit it with an estimate of its alignment. - Addr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo); - auto *Idx = EmitIdxAfterBase(/*Promote*/true); - Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(), - !getLangOpts().isSignedOverflowDefined(), - SignedIndices, E->getExprLoc()); - } - - LValue LV = MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo); - - if (getLangOpts().ObjC && - getLangOpts().getGC() != LangOptions::NonGC) { - LV.setNonGC(!E->isOBJCGCCandidate(getContext())); - setObjCGCLValueClass(getContext(), E, LV); - } - return LV; -} - -static Address emitOMPArraySectionBase(CodeGenFunction &CGF, const Expr *Base, - LValueBaseInfo &BaseInfo, - TBAAAccessInfo &TBAAInfo, - QualType BaseTy, QualType ElTy, - bool IsLowerBound) { - LValue BaseLVal; - if (auto *ASE = dyn_cast<OMPArraySectionExpr>(Base->IgnoreParenImpCasts())) { - BaseLVal = CGF.EmitOMPArraySectionExpr(ASE, IsLowerBound); - if (BaseTy->isArrayType()) { - Address Addr = BaseLVal.getAddress(); - BaseInfo = BaseLVal.getBaseInfo(); - - // If the array type was an incomplete type, we need to make sure - // the decay ends up being the right type. - llvm::Type *NewTy = CGF.ConvertType(BaseTy); - Addr = CGF.Builder.CreateElementBitCast(Addr, NewTy); - - // Note that VLA pointers are always decayed, so we don't need to do - // anything here. - if (!BaseTy->isVariableArrayType()) { - assert(isa<llvm::ArrayType>(Addr.getElementType()) && - "Expected pointer to array"); - Addr = CGF.Builder.CreateStructGEP(Addr, 0, CharUnits::Zero(), - "arraydecay"); - } - - return CGF.Builder.CreateElementBitCast(Addr, - CGF.ConvertTypeForMem(ElTy)); - } - LValueBaseInfo TypeBaseInfo; - TBAAAccessInfo TypeTBAAInfo; - CharUnits Align = CGF.getNaturalTypeAlignment(ElTy, &TypeBaseInfo, - &TypeTBAAInfo); - BaseInfo.mergeForCast(TypeBaseInfo); - TBAAInfo = CGF.CGM.mergeTBAAInfoForCast(TBAAInfo, TypeTBAAInfo); - return Address(CGF.Builder.CreateLoad(BaseLVal.getAddress()), Align); - } - return CGF.EmitPointerWithAlignment(Base, &BaseInfo, &TBAAInfo); -} - -LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, - bool IsLowerBound) { - QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(E->getBase()); - QualType ResultExprTy; - if (auto *AT = getContext().getAsArrayType(BaseTy)) - ResultExprTy = AT->getElementType(); - else - ResultExprTy = BaseTy->getPointeeType(); - llvm::Value *Idx = nullptr; - if (IsLowerBound || E->getColonLoc().isInvalid()) { - // Requesting lower bound or upper bound, but without provided length and - // without ':' symbol for the default length -> length = 1. - // Idx = LowerBound ?: 0; - if (auto *LowerBound = E->getLowerBound()) { - Idx = Builder.CreateIntCast( - EmitScalarExpr(LowerBound), IntPtrTy, - LowerBound->getType()->hasSignedIntegerRepresentation()); - } else - Idx = llvm::ConstantInt::getNullValue(IntPtrTy); - } else { - // Try to emit length or lower bound as constant. If this is possible, 1 - // is subtracted from constant length or lower bound. Otherwise, emit LLVM - // IR (LB + Len) - 1. - auto &C = CGM.getContext(); - auto *Length = E->getLength(); - llvm::APSInt ConstLength; - if (Length) { - // Idx = LowerBound + Length - 1; - if (Length->isIntegerConstantExpr(ConstLength, C)) { - ConstLength = ConstLength.zextOrTrunc(PointerWidthInBits); - Length = nullptr; - } - auto *LowerBound = E->getLowerBound(); - llvm::APSInt ConstLowerBound(PointerWidthInBits, /*isUnsigned=*/false); - if (LowerBound && LowerBound->isIntegerConstantExpr(ConstLowerBound, C)) { - ConstLowerBound = ConstLowerBound.zextOrTrunc(PointerWidthInBits); - LowerBound = nullptr; - } - if (!Length) - --ConstLength; - else if (!LowerBound) - --ConstLowerBound; - - if (Length || LowerBound) { - auto *LowerBoundVal = - LowerBound - ? Builder.CreateIntCast( - EmitScalarExpr(LowerBound), IntPtrTy, - LowerBound->getType()->hasSignedIntegerRepresentation()) - : llvm::ConstantInt::get(IntPtrTy, ConstLowerBound); - auto *LengthVal = - Length - ? Builder.CreateIntCast( - EmitScalarExpr(Length), IntPtrTy, - Length->getType()->hasSignedIntegerRepresentation()) - : llvm::ConstantInt::get(IntPtrTy, ConstLength); - Idx = Builder.CreateAdd(LowerBoundVal, LengthVal, "lb_add_len", - /*HasNUW=*/false, - !getLangOpts().isSignedOverflowDefined()); - if (Length && LowerBound) { - Idx = Builder.CreateSub( - Idx, llvm::ConstantInt::get(IntPtrTy, /*V=*/1), "idx_sub_1", - /*HasNUW=*/false, !getLangOpts().isSignedOverflowDefined()); - } - } else - Idx = llvm::ConstantInt::get(IntPtrTy, ConstLength + ConstLowerBound); - } else { - // Idx = ArraySize - 1; - QualType ArrayTy = BaseTy->isPointerType() - ? E->getBase()->IgnoreParenImpCasts()->getType() - : BaseTy; - if (auto *VAT = C.getAsVariableArrayType(ArrayTy)) { - Length = VAT->getSizeExpr(); - if (Length->isIntegerConstantExpr(ConstLength, C)) - Length = nullptr; - } else { - auto *CAT = C.getAsConstantArrayType(ArrayTy); - ConstLength = CAT->getSize(); - } - if (Length) { - auto *LengthVal = Builder.CreateIntCast( - EmitScalarExpr(Length), IntPtrTy, - Length->getType()->hasSignedIntegerRepresentation()); - Idx = Builder.CreateSub( - LengthVal, llvm::ConstantInt::get(IntPtrTy, /*V=*/1), "len_sub_1", - /*HasNUW=*/false, !getLangOpts().isSignedOverflowDefined()); - } else { - ConstLength = ConstLength.zextOrTrunc(PointerWidthInBits); - --ConstLength; - Idx = llvm::ConstantInt::get(IntPtrTy, ConstLength); - } - } - } - assert(Idx); - - Address EltPtr = Address::invalid(); - LValueBaseInfo BaseInfo; - TBAAAccessInfo TBAAInfo; - if (auto *VLA = getContext().getAsVariableArrayType(ResultExprTy)) { - // The base must be a pointer, which is not an aggregate. Emit - // it. It needs to be emitted first in case it's what captures - // the VLA bounds. - Address Base = - emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, TBAAInfo, - BaseTy, VLA->getElementType(), IsLowerBound); - // The element count here is the total number of non-VLA elements. - llvm::Value *NumElements = getVLASize(VLA).NumElts; - - // Effectively, the multiply by the VLA size is part of the GEP. - // GEP indexes are signed, and scaling an index isn't permitted to - // signed-overflow, so we use the same semantics for our explicit - // multiply. We suppress this if overflow is not undefined behavior. - if (getLangOpts().isSignedOverflowDefined()) - Idx = Builder.CreateMul(Idx, NumElements); - else - Idx = Builder.CreateNSWMul(Idx, NumElements); - EltPtr = emitArraySubscriptGEP(*this, Base, Idx, VLA->getElementType(), - !getLangOpts().isSignedOverflowDefined(), - /*SignedIndices=*/false, E->getExprLoc()); - } else if (const Expr *Array = isSimpleArrayDecayOperand(E->getBase())) { - // If this is A[i] where A is an array, the frontend will have decayed the - // base to be a ArrayToPointerDecay implicit cast. While correct, it is - // inefficient at -O0 to emit a "gep A, 0, 0" when codegen'ing it, then a - // "gep x, i" here. Emit one "gep A, 0, i". - assert(Array->getType()->isArrayType() && - "Array to pointer decay must have array source type!"); - LValue ArrayLV; - // For simple multidimensional array indexing, set the 'accessed' flag for - // better bounds-checking of the base expression. - if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Array)) - ArrayLV = EmitArraySubscriptExpr(ASE, /*Accessed*/ true); - else - ArrayLV = EmitLValue(Array); - - // Propagate the alignment from the array itself to the result. - EltPtr = emitArraySubscriptGEP( - *this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx}, - ResultExprTy, !getLangOpts().isSignedOverflowDefined(), - /*SignedIndices=*/false, E->getExprLoc()); - BaseInfo = ArrayLV.getBaseInfo(); - TBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, ResultExprTy); - } else { - Address Base = emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, - TBAAInfo, BaseTy, ResultExprTy, - IsLowerBound); - EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy, - !getLangOpts().isSignedOverflowDefined(), - /*SignedIndices=*/false, E->getExprLoc()); - } - - return MakeAddrLValue(EltPtr, ResultExprTy, BaseInfo, TBAAInfo); -} - -LValue CodeGenFunction:: -EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { - // Emit the base vector as an l-value. - LValue Base; - - // ExtVectorElementExpr's base can either be a vector or pointer to vector. - if (E->isArrow()) { - // If it is a pointer to a vector, emit the address and form an lvalue with - // it. - LValueBaseInfo BaseInfo; - TBAAAccessInfo TBAAInfo; - Address Ptr = EmitPointerWithAlignment(E->getBase(), &BaseInfo, &TBAAInfo); - const PointerType *PT = E->getBase()->getType()->getAs<PointerType>(); - Base = MakeAddrLValue(Ptr, PT->getPointeeType(), BaseInfo, TBAAInfo); - Base.getQuals().removeObjCGCAttr(); - } else if (E->getBase()->isGLValue()) { - // Otherwise, if the base is an lvalue ( as in the case of foo.x.x), - // emit the base as an lvalue. - assert(E->getBase()->getType()->isVectorType()); - Base = EmitLValue(E->getBase()); - } else { - // Otherwise, the base is a normal rvalue (as in (V+V).x), emit it as such. - assert(E->getBase()->getType()->isVectorType() && - "Result must be a vector"); - llvm::Value *Vec = EmitScalarExpr(E->getBase()); - - // Store the vector to memory (because LValue wants an address). - Address VecMem = CreateMemTemp(E->getBase()->getType()); - Builder.CreateStore(Vec, VecMem); - Base = MakeAddrLValue(VecMem, E->getBase()->getType(), - AlignmentSource::Decl); - } - - QualType type = - E->getType().withCVRQualifiers(Base.getQuals().getCVRQualifiers()); - - // Encode the element access list into a vector of unsigned indices. - SmallVector<uint32_t, 4> Indices; - E->getEncodedElementAccess(Indices); - - if (Base.isSimple()) { - llvm::Constant *CV = - llvm::ConstantDataVector::get(getLLVMContext(), Indices); - return LValue::MakeExtVectorElt(Base.getAddress(), CV, type, - Base.getBaseInfo(), TBAAAccessInfo()); - } - assert(Base.isExtVectorElt() && "Can only subscript lvalue vec elts here!"); - - llvm::Constant *BaseElts = Base.getExtVectorElts(); - SmallVector<llvm::Constant *, 4> CElts; - - for (unsigned i = 0, e = Indices.size(); i != e; ++i) - CElts.push_back(BaseElts->getAggregateElement(Indices[i])); - llvm::Constant *CV = llvm::ConstantVector::get(CElts); - return LValue::MakeExtVectorElt(Base.getExtVectorAddress(), CV, type, - Base.getBaseInfo(), TBAAAccessInfo()); -} - -LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { - if (DeclRefExpr *DRE = tryToConvertMemberExprToDeclRefExpr(*this, E)) { - EmitIgnoredExpr(E->getBase()); - return EmitDeclRefLValue(DRE); - } - - Expr *BaseExpr = E->getBase(); - // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar. - LValue BaseLV; - if (E->isArrow()) { - LValueBaseInfo BaseInfo; - TBAAAccessInfo TBAAInfo; - Address Addr = EmitPointerWithAlignment(BaseExpr, &BaseInfo, &TBAAInfo); - QualType PtrTy = BaseExpr->getType()->getPointeeType(); - SanitizerSet SkippedChecks; - bool IsBaseCXXThis = IsWrappedCXXThis(BaseExpr); - if (IsBaseCXXThis) - SkippedChecks.set(SanitizerKind::Alignment, true); - if (IsBaseCXXThis || isa<DeclRefExpr>(BaseExpr)) - SkippedChecks.set(SanitizerKind::Null, true); - EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr.getPointer(), PtrTy, - /*Alignment=*/CharUnits::Zero(), SkippedChecks); - BaseLV = MakeAddrLValue(Addr, PtrTy, BaseInfo, TBAAInfo); - } else - BaseLV = EmitCheckedLValue(BaseExpr, TCK_MemberAccess); - - NamedDecl *ND = E->getMemberDecl(); - if (auto *Field = dyn_cast<FieldDecl>(ND)) { - LValue LV = EmitLValueForField(BaseLV, Field); - setObjCGCLValueClass(getContext(), E, LV); - return LV; - } - - if (const auto *FD = dyn_cast<FunctionDecl>(ND)) - return EmitFunctionDeclLValue(*this, E, FD); - - llvm_unreachable("Unhandled member declaration!"); -} - -/// Given that we are currently emitting a lambda, emit an l-value for -/// one of its members. -LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field) { - assert(cast<CXXMethodDecl>(CurCodeDecl)->getParent()->isLambda()); - assert(cast<CXXMethodDecl>(CurCodeDecl)->getParent() == Field->getParent()); - QualType LambdaTagType = - getContext().getTagDeclType(Field->getParent()); - LValue LambdaLV = MakeNaturalAlignAddrLValue(CXXABIThisValue, LambdaTagType); - return EmitLValueForField(LambdaLV, Field); -} - -/// Drill down to the storage of a field without walking into -/// reference types. -/// -/// The resulting address doesn't necessarily have the right type. -static Address emitAddrOfFieldStorage(CodeGenFunction &CGF, Address base, - const FieldDecl *field) { - const RecordDecl *rec = field->getParent(); - - unsigned idx = - CGF.CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field); - - CharUnits offset; - // Adjust the alignment down to the given offset. - // As a special case, if the LLVM field index is 0, we know that this - // is zero. - assert((idx != 0 || CGF.getContext().getASTRecordLayout(rec) - .getFieldOffset(field->getFieldIndex()) == 0) && - "LLVM field at index zero had non-zero offset?"); - if (idx != 0) { - auto &recLayout = CGF.getContext().getASTRecordLayout(rec); - auto offsetInBits = recLayout.getFieldOffset(field->getFieldIndex()); - offset = CGF.getContext().toCharUnitsFromBits(offsetInBits); - } - - return CGF.Builder.CreateStructGEP(base, idx, offset, field->getName()); -} - -static bool hasAnyVptr(const QualType Type, const ASTContext &Context) { - const auto *RD = Type.getTypePtr()->getAsCXXRecordDecl(); - if (!RD) - return false; - - if (RD->isDynamicClass()) - return true; - - for (const auto &Base : RD->bases()) - if (hasAnyVptr(Base.getType(), Context)) - return true; - - for (const FieldDecl *Field : RD->fields()) - if (hasAnyVptr(Field->getType(), Context)) - return true; - - return false; -} - -LValue CodeGenFunction::EmitLValueForField(LValue base, - const FieldDecl *field) { - LValueBaseInfo BaseInfo = base.getBaseInfo(); - - if (field->isBitField()) { - const CGRecordLayout &RL = - CGM.getTypes().getCGRecordLayout(field->getParent()); - const CGBitFieldInfo &Info = RL.getBitFieldInfo(field); - Address Addr = base.getAddress(); - unsigned Idx = RL.getLLVMFieldNo(field); - if (Idx != 0) - // For structs, we GEP to the field that the record layout suggests. - Addr = Builder.CreateStructGEP(Addr, Idx, Info.StorageOffset, - field->getName()); - // Get the access type. - llvm::Type *FieldIntTy = - llvm::Type::getIntNTy(getLLVMContext(), Info.StorageSize); - if (Addr.getElementType() != FieldIntTy) - Addr = Builder.CreateElementBitCast(Addr, FieldIntTy); - - QualType fieldType = - field->getType().withCVRQualifiers(base.getVRQualifiers()); - // TODO: Support TBAA for bit fields. - LValueBaseInfo FieldBaseInfo(BaseInfo.getAlignmentSource()); - return LValue::MakeBitfield(Addr, Info, fieldType, FieldBaseInfo, - TBAAAccessInfo()); - } - - // Fields of may-alias structures are may-alias themselves. - // FIXME: this should get propagated down through anonymous structs - // and unions. - QualType FieldType = field->getType(); - const RecordDecl *rec = field->getParent(); - AlignmentSource BaseAlignSource = BaseInfo.getAlignmentSource(); - LValueBaseInfo FieldBaseInfo(getFieldAlignmentSource(BaseAlignSource)); - TBAAAccessInfo FieldTBAAInfo; - if (base.getTBAAInfo().isMayAlias() || - rec->hasAttr<MayAliasAttr>() || FieldType->isVectorType()) { - FieldTBAAInfo = TBAAAccessInfo::getMayAliasInfo(); - } else if (rec->isUnion()) { - // TODO: Support TBAA for unions. - FieldTBAAInfo = TBAAAccessInfo::getMayAliasInfo(); - } else { - // If no base type been assigned for the base access, then try to generate - // one for this base lvalue. - FieldTBAAInfo = base.getTBAAInfo(); - if (!FieldTBAAInfo.BaseType) { - FieldTBAAInfo.BaseType = CGM.getTBAABaseTypeInfo(base.getType()); - assert(!FieldTBAAInfo.Offset && - "Nonzero offset for an access with no base type!"); - } - - // Adjust offset to be relative to the base type. - const ASTRecordLayout &Layout = - getContext().getASTRecordLayout(field->getParent()); - unsigned CharWidth = getContext().getCharWidth(); - if (FieldTBAAInfo.BaseType) - FieldTBAAInfo.Offset += - Layout.getFieldOffset(field->getFieldIndex()) / CharWidth; - - // Update the final access type and size. - FieldTBAAInfo.AccessType = CGM.getTBAATypeInfo(FieldType); - FieldTBAAInfo.Size = - getContext().getTypeSizeInChars(FieldType).getQuantity(); - } - - Address addr = base.getAddress(); - if (auto *ClassDef = dyn_cast<CXXRecordDecl>(rec)) { - if (CGM.getCodeGenOpts().StrictVTablePointers && - ClassDef->isDynamicClass()) { - // Getting to any field of dynamic object requires stripping dynamic - // information provided by invariant.group. This is because accessing - // fields may leak the real address of dynamic object, which could result - // in miscompilation when leaked pointer would be compared. - auto *stripped = Builder.CreateStripInvariantGroup(addr.getPointer()); - addr = Address(stripped, addr.getAlignment()); - } - } - - unsigned RecordCVR = base.getVRQualifiers(); - if (rec->isUnion()) { - // For unions, there is no pointer adjustment. - assert(!FieldType->isReferenceType() && "union has reference member"); - if (CGM.getCodeGenOpts().StrictVTablePointers && - hasAnyVptr(FieldType, getContext())) - // Because unions can easily skip invariant.barriers, we need to add - // a barrier every time CXXRecord field with vptr is referenced. - addr = Address(Builder.CreateLaunderInvariantGroup(addr.getPointer()), - addr.getAlignment()); - } else { - // For structs, we GEP to the field that the record layout suggests. - addr = emitAddrOfFieldStorage(*this, addr, field); - - // If this is a reference field, load the reference right now. - if (FieldType->isReferenceType()) { - LValue RefLVal = MakeAddrLValue(addr, FieldType, FieldBaseInfo, - FieldTBAAInfo); - if (RecordCVR & Qualifiers::Volatile) - RefLVal.getQuals().addVolatile(); - addr = EmitLoadOfReference(RefLVal, &FieldBaseInfo, &FieldTBAAInfo); - - // Qualifiers on the struct don't apply to the referencee. - RecordCVR = 0; - FieldType = FieldType->getPointeeType(); - } - } - - // Make sure that the address is pointing to the right type. This is critical - // for both unions and structs. A union needs a bitcast, a struct element - // will need a bitcast if the LLVM type laid out doesn't match the desired - // type. - addr = Builder.CreateElementBitCast( - addr, CGM.getTypes().ConvertTypeForMem(FieldType), field->getName()); - - if (field->hasAttr<AnnotateAttr>()) - addr = EmitFieldAnnotations(field, addr); - - LValue LV = MakeAddrLValue(addr, FieldType, FieldBaseInfo, FieldTBAAInfo); - LV.getQuals().addCVRQualifiers(RecordCVR); - - // __weak attribute on a field is ignored. - if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak) - LV.getQuals().removeObjCGCAttr(); - - return LV; -} - -LValue -CodeGenFunction::EmitLValueForFieldInitialization(LValue Base, - const FieldDecl *Field) { - QualType FieldType = Field->getType(); - - if (!FieldType->isReferenceType()) - return EmitLValueForField(Base, Field); - - Address V = emitAddrOfFieldStorage(*this, Base.getAddress(), Field); - - // Make sure that the address is pointing to the right type. - llvm::Type *llvmType = ConvertTypeForMem(FieldType); - V = Builder.CreateElementBitCast(V, llvmType, Field->getName()); - - // TODO: Generate TBAA information that describes this access as a structure - // member access and not just an access to an object of the field's type. This - // should be similar to what we do in EmitLValueForField(). - LValueBaseInfo BaseInfo = Base.getBaseInfo(); - AlignmentSource FieldAlignSource = BaseInfo.getAlignmentSource(); - LValueBaseInfo FieldBaseInfo(getFieldAlignmentSource(FieldAlignSource)); - return MakeAddrLValue(V, FieldType, FieldBaseInfo, - CGM.getTBAAInfoForSubobject(Base, FieldType)); -} - -LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){ - if (E->isFileScope()) { - ConstantAddress GlobalPtr = CGM.GetAddrOfConstantCompoundLiteral(E); - return MakeAddrLValue(GlobalPtr, E->getType(), AlignmentSource::Decl); - } - if (E->getType()->isVariablyModifiedType()) - // make sure to emit the VLA size. - EmitVariablyModifiedType(E->getType()); - - Address DeclPtr = CreateMemTemp(E->getType(), ".compoundliteral"); - const Expr *InitExpr = E->getInitializer(); - LValue Result = MakeAddrLValue(DeclPtr, E->getType(), AlignmentSource::Decl); - - EmitAnyExprToMem(InitExpr, DeclPtr, E->getType().getQualifiers(), - /*Init*/ true); - - return Result; -} - -LValue CodeGenFunction::EmitInitListLValue(const InitListExpr *E) { - if (!E->isGLValue()) - // Initializing an aggregate temporary in C++11: T{...}. - return EmitAggExprToLValue(E); - - // An lvalue initializer list must be initializing a reference. - assert(E->isTransparent() && "non-transparent glvalue init list"); - return EmitLValue(E->getInit(0)); -} - -/// Emit the operand of a glvalue conditional operator. This is either a glvalue -/// or a (possibly-parenthesized) throw-expression. If this is a throw, no -/// LValue is returned and the current block has been terminated. -static Optional<LValue> EmitLValueOrThrowExpression(CodeGenFunction &CGF, - const Expr *Operand) { - if (auto *ThrowExpr = dyn_cast<CXXThrowExpr>(Operand->IgnoreParens())) { - CGF.EmitCXXThrowExpr(ThrowExpr, /*KeepInsertionPoint*/false); - return None; - } - - return CGF.EmitLValue(Operand); -} - -LValue CodeGenFunction:: -EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) { - if (!expr->isGLValue()) { - // ?: here should be an aggregate. - assert(hasAggregateEvaluationKind(expr->getType()) && - "Unexpected conditional operator!"); - return EmitAggExprToLValue(expr); - } - - OpaqueValueMapping binding(*this, expr); - - const Expr *condExpr = expr->getCond(); - bool CondExprBool; - if (ConstantFoldsToSimpleInteger(condExpr, CondExprBool)) { - const Expr *live = expr->getTrueExpr(), *dead = expr->getFalseExpr(); - if (!CondExprBool) std::swap(live, dead); - - if (!ContainsLabel(dead)) { - // If the true case is live, we need to track its region. - if (CondExprBool) - incrementProfileCounter(expr); - return EmitLValue(live); - } - } - - llvm::BasicBlock *lhsBlock = createBasicBlock("cond.true"); - llvm::BasicBlock *rhsBlock = createBasicBlock("cond.false"); - llvm::BasicBlock *contBlock = createBasicBlock("cond.end"); - - ConditionalEvaluation eval(*this); - EmitBranchOnBoolExpr(condExpr, lhsBlock, rhsBlock, getProfileCount(expr)); - - // Any temporaries created here are conditional. - EmitBlock(lhsBlock); - incrementProfileCounter(expr); - eval.begin(*this); - Optional<LValue> lhs = - EmitLValueOrThrowExpression(*this, expr->getTrueExpr()); - eval.end(*this); - - if (lhs && !lhs->isSimple()) - return EmitUnsupportedLValue(expr, "conditional operator"); - - lhsBlock = Builder.GetInsertBlock(); - if (lhs) - Builder.CreateBr(contBlock); - - // Any temporaries created here are conditional. - EmitBlock(rhsBlock); - eval.begin(*this); - Optional<LValue> rhs = - EmitLValueOrThrowExpression(*this, expr->getFalseExpr()); - eval.end(*this); - if (rhs && !rhs->isSimple()) - return EmitUnsupportedLValue(expr, "conditional operator"); - rhsBlock = Builder.GetInsertBlock(); - - EmitBlock(contBlock); - - if (lhs && rhs) { - llvm::PHINode *phi = Builder.CreatePHI(lhs->getPointer()->getType(), - 2, "cond-lvalue"); - phi->addIncoming(lhs->getPointer(), lhsBlock); - phi->addIncoming(rhs->getPointer(), rhsBlock); - Address result(phi, std::min(lhs->getAlignment(), rhs->getAlignment())); - AlignmentSource alignSource = - std::max(lhs->getBaseInfo().getAlignmentSource(), - rhs->getBaseInfo().getAlignmentSource()); - TBAAAccessInfo TBAAInfo = CGM.mergeTBAAInfoForConditionalOperator( - lhs->getTBAAInfo(), rhs->getTBAAInfo()); - return MakeAddrLValue(result, expr->getType(), LValueBaseInfo(alignSource), - TBAAInfo); - } else { - assert((lhs || rhs) && - "both operands of glvalue conditional are throw-expressions?"); - return lhs ? *lhs : *rhs; - } -} - -/// EmitCastLValue - Casts are never lvalues unless that cast is to a reference -/// type. If the cast is to a reference, we can have the usual lvalue result, -/// otherwise if a cast is needed by the code generator in an lvalue context, -/// then it must mean that we need the address of an aggregate in order to -/// access one of its members. This can happen for all the reasons that casts -/// are permitted with aggregate result, including noop aggregate casts, and -/// cast from scalar to union. -LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { - switch (E->getCastKind()) { - case CK_ToVoid: - case CK_BitCast: - case CK_ArrayToPointerDecay: - case CK_FunctionToPointerDecay: - case CK_NullToMemberPointer: - case CK_NullToPointer: - case CK_IntegralToPointer: - case CK_PointerToIntegral: - case CK_PointerToBoolean: - case CK_VectorSplat: - case CK_IntegralCast: - case CK_BooleanToSignedIntegral: - case CK_IntegralToBoolean: - case CK_IntegralToFloating: - case CK_FloatingToIntegral: - case CK_FloatingToBoolean: - case CK_FloatingCast: - case CK_FloatingRealToComplex: - case CK_FloatingComplexToReal: - case CK_FloatingComplexToBoolean: - case CK_FloatingComplexCast: - case CK_FloatingComplexToIntegralComplex: - case CK_IntegralRealToComplex: - case CK_IntegralComplexToReal: - case CK_IntegralComplexToBoolean: - case CK_IntegralComplexCast: - case CK_IntegralComplexToFloatingComplex: - case CK_DerivedToBaseMemberPointer: - case CK_BaseToDerivedMemberPointer: - case CK_MemberPointerToBoolean: - case CK_ReinterpretMemberPointer: - case CK_AnyPointerToBlockPointerCast: - case CK_ARCProduceObject: - case CK_ARCConsumeObject: - case CK_ARCReclaimReturnedObject: - case CK_ARCExtendBlockObject: - case CK_CopyAndAutoreleaseBlockObject: - case CK_IntToOCLSampler: - case CK_FixedPointCast: - case CK_FixedPointToBoolean: - return EmitUnsupportedLValue(E, "unexpected cast lvalue"); - - case CK_Dependent: - llvm_unreachable("dependent cast kind in IR gen!"); - - case CK_BuiltinFnToFnPtr: - llvm_unreachable("builtin functions are handled elsewhere"); - - // These are never l-values; just use the aggregate emission code. - case CK_NonAtomicToAtomic: - case CK_AtomicToNonAtomic: - return EmitAggExprToLValue(E); - - case CK_Dynamic: { - LValue LV = EmitLValue(E->getSubExpr()); - Address V = LV.getAddress(); - const auto *DCE = cast<CXXDynamicCastExpr>(E); - return MakeNaturalAlignAddrLValue(EmitDynamicCast(V, DCE), E->getType()); - } - - case CK_ConstructorConversion: - case CK_UserDefinedConversion: - case CK_CPointerToObjCPointerCast: - case CK_BlockPointerToObjCPointerCast: - case CK_NoOp: - case CK_LValueToRValue: - return EmitLValue(E->getSubExpr()); - - case CK_UncheckedDerivedToBase: - case CK_DerivedToBase: { - const RecordType *DerivedClassTy = - E->getSubExpr()->getType()->getAs<RecordType>(); - auto *DerivedClassDecl = cast<CXXRecordDecl>(DerivedClassTy->getDecl()); - - LValue LV = EmitLValue(E->getSubExpr()); - Address This = LV.getAddress(); - - // Perform the derived-to-base conversion - Address Base = GetAddressOfBaseClass( - This, DerivedClassDecl, E->path_begin(), E->path_end(), - /*NullCheckValue=*/false, E->getExprLoc()); - - // TODO: Support accesses to members of base classes in TBAA. For now, we - // conservatively pretend that the complete object is of the base class - // type. - return MakeAddrLValue(Base, E->getType(), LV.getBaseInfo(), - CGM.getTBAAInfoForSubobject(LV, E->getType())); - } - case CK_ToUnion: - return EmitAggExprToLValue(E); - case CK_BaseToDerived: { - const RecordType *DerivedClassTy = E->getType()->getAs<RecordType>(); - auto *DerivedClassDecl = cast<CXXRecordDecl>(DerivedClassTy->getDecl()); - - LValue LV = EmitLValue(E->getSubExpr()); - - // Perform the base-to-derived conversion - Address Derived = - GetAddressOfDerivedClass(LV.getAddress(), DerivedClassDecl, - E->path_begin(), E->path_end(), - /*NullCheckValue=*/false); - - // C++11 [expr.static.cast]p2: Behavior is undefined if a downcast is - // performed and the object is not of the derived type. - if (sanitizePerformTypeCheck()) - EmitTypeCheck(TCK_DowncastReference, E->getExprLoc(), - Derived.getPointer(), E->getType()); - - if (SanOpts.has(SanitizerKind::CFIDerivedCast)) - EmitVTablePtrCheckForCast(E->getType(), Derived.getPointer(), - /*MayBeNull=*/false, CFITCK_DerivedCast, - E->getBeginLoc()); - - return MakeAddrLValue(Derived, E->getType(), LV.getBaseInfo(), - CGM.getTBAAInfoForSubobject(LV, E->getType())); - } - case CK_LValueBitCast: { - // This must be a reinterpret_cast (or c-style equivalent). - const auto *CE = cast<ExplicitCastExpr>(E); - - CGM.EmitExplicitCastExprType(CE, this); - LValue LV = EmitLValue(E->getSubExpr()); - Address V = Builder.CreateBitCast(LV.getAddress(), - ConvertType(CE->getTypeAsWritten())); - - if (SanOpts.has(SanitizerKind::CFIUnrelatedCast)) - EmitVTablePtrCheckForCast(E->getType(), V.getPointer(), - /*MayBeNull=*/false, CFITCK_UnrelatedCast, - E->getBeginLoc()); - - return MakeAddrLValue(V, E->getType(), LV.getBaseInfo(), - CGM.getTBAAInfoForSubobject(LV, E->getType())); - } - case CK_AddressSpaceConversion: { - LValue LV = EmitLValue(E->getSubExpr()); - QualType DestTy = getContext().getPointerType(E->getType()); - llvm::Value *V = getTargetHooks().performAddrSpaceCast( - *this, LV.getPointer(), E->getSubExpr()->getType().getAddressSpace(), - E->getType().getAddressSpace(), ConvertType(DestTy)); - return MakeAddrLValue(Address(V, LV.getAddress().getAlignment()), - E->getType(), LV.getBaseInfo(), LV.getTBAAInfo()); - } - case CK_ObjCObjectLValueCast: { - LValue LV = EmitLValue(E->getSubExpr()); - Address V = Builder.CreateElementBitCast(LV.getAddress(), - ConvertType(E->getType())); - return MakeAddrLValue(V, E->getType(), LV.getBaseInfo(), - CGM.getTBAAInfoForSubobject(LV, E->getType())); - } - case CK_ZeroToOCLOpaqueType: - llvm_unreachable("NULL to OpenCL opaque type lvalue cast is not valid"); - } - - llvm_unreachable("Unhandled lvalue cast kind?"); -} - -LValue CodeGenFunction::EmitOpaqueValueLValue(const OpaqueValueExpr *e) { - assert(OpaqueValueMappingData::shouldBindAsLValue(e)); - return getOrCreateOpaqueLValueMapping(e); -} - -LValue -CodeGenFunction::getOrCreateOpaqueLValueMapping(const OpaqueValueExpr *e) { - assert(OpaqueValueMapping::shouldBindAsLValue(e)); - - llvm::DenseMap<const OpaqueValueExpr*,LValue>::iterator - it = OpaqueLValues.find(e); - - if (it != OpaqueLValues.end()) - return it->second; - - assert(e->isUnique() && "LValue for a nonunique OVE hasn't been emitted"); - return EmitLValue(e->getSourceExpr()); -} - -RValue -CodeGenFunction::getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e) { - assert(!OpaqueValueMapping::shouldBindAsLValue(e)); - - llvm::DenseMap<const OpaqueValueExpr*,RValue>::iterator - it = OpaqueRValues.find(e); - - if (it != OpaqueRValues.end()) - return it->second; - - assert(e->isUnique() && "RValue for a nonunique OVE hasn't been emitted"); - return EmitAnyExpr(e->getSourceExpr()); -} - -RValue CodeGenFunction::EmitRValueForField(LValue LV, - const FieldDecl *FD, - SourceLocation Loc) { - QualType FT = FD->getType(); - LValue FieldLV = EmitLValueForField(LV, FD); - switch (getEvaluationKind(FT)) { - case TEK_Complex: - return RValue::getComplex(EmitLoadOfComplex(FieldLV, Loc)); - case TEK_Aggregate: - return FieldLV.asAggregateRValue(); - case TEK_Scalar: - // This routine is used to load fields one-by-one to perform a copy, so - // don't load reference fields. - if (FD->getType()->isReferenceType()) - return RValue::get(FieldLV.getPointer()); - return EmitLoadOfLValue(FieldLV, Loc); - } - llvm_unreachable("bad evaluation kind"); -} - -//===--------------------------------------------------------------------===// -// Expression Emission -//===--------------------------------------------------------------------===// - -RValue CodeGenFunction::EmitCallExpr(const CallExpr *E, - ReturnValueSlot ReturnValue) { - // Builtins never have block type. - if (E->getCallee()->getType()->isBlockPointerType()) - return EmitBlockCallExpr(E, ReturnValue); - - if (const auto *CE = dyn_cast<CXXMemberCallExpr>(E)) - return EmitCXXMemberCallExpr(CE, ReturnValue); - - if (const auto *CE = dyn_cast<CUDAKernelCallExpr>(E)) - return EmitCUDAKernelCallExpr(CE, ReturnValue); - - if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(E)) - if (const CXXMethodDecl *MD = - dyn_cast_or_null<CXXMethodDecl>(CE->getCalleeDecl())) - return EmitCXXOperatorMemberCallExpr(CE, MD, ReturnValue); - - CGCallee callee = EmitCallee(E->getCallee()); - - if (callee.isBuiltin()) { - return EmitBuiltinExpr(callee.getBuiltinDecl(), callee.getBuiltinID(), - E, ReturnValue); - } - - if (callee.isPseudoDestructor()) { - return EmitCXXPseudoDestructorExpr(callee.getPseudoDestructorExpr()); - } - - return EmitCall(E->getCallee()->getType(), callee, E, ReturnValue); -} - -/// Emit a CallExpr without considering whether it might be a subclass. -RValue CodeGenFunction::EmitSimpleCallExpr(const CallExpr *E, - ReturnValueSlot ReturnValue) { - CGCallee Callee = EmitCallee(E->getCallee()); - return EmitCall(E->getCallee()->getType(), Callee, E, ReturnValue); -} - -static CGCallee EmitDirectCallee(CodeGenFunction &CGF, const FunctionDecl *FD) { - if (auto builtinID = FD->getBuiltinID()) { - return CGCallee::forBuiltin(builtinID, FD); - } - - llvm::Constant *calleePtr = EmitFunctionDeclPointer(CGF.CGM, FD); - return CGCallee::forDirect(calleePtr, GlobalDecl(FD)); -} - -CGCallee CodeGenFunction::EmitCallee(const Expr *E) { - E = E->IgnoreParens(); - - // Look through function-to-pointer decay. - if (auto ICE = dyn_cast<ImplicitCastExpr>(E)) { - if (ICE->getCastKind() == CK_FunctionToPointerDecay || - ICE->getCastKind() == CK_BuiltinFnToFnPtr) { - return EmitCallee(ICE->getSubExpr()); - } - - // Resolve direct calls. - } else if (auto DRE = dyn_cast<DeclRefExpr>(E)) { - if (auto FD = dyn_cast<FunctionDecl>(DRE->getDecl())) { - return EmitDirectCallee(*this, FD); - } - } else if (auto ME = dyn_cast<MemberExpr>(E)) { - if (auto FD = dyn_cast<FunctionDecl>(ME->getMemberDecl())) { - EmitIgnoredExpr(ME->getBase()); - return EmitDirectCallee(*this, FD); - } - - // Look through template substitutions. - } else if (auto NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) { - return EmitCallee(NTTP->getReplacement()); - - // Treat pseudo-destructor calls differently. - } else if (auto PDE = dyn_cast<CXXPseudoDestructorExpr>(E)) { - return CGCallee::forPseudoDestructor(PDE); - } - - // Otherwise, we have an indirect reference. - llvm::Value *calleePtr; - QualType functionType; - if (auto ptrType = E->getType()->getAs<PointerType>()) { - calleePtr = EmitScalarExpr(E); - functionType = ptrType->getPointeeType(); - } else { - functionType = E->getType(); - calleePtr = EmitLValue(E).getPointer(); - } - assert(functionType->isFunctionType()); - - GlobalDecl GD; - if (const auto *VD = - dyn_cast_or_null<VarDecl>(E->getReferencedDeclOfCallee())) - GD = GlobalDecl(VD); - - CGCalleeInfo calleeInfo(functionType->getAs<FunctionProtoType>(), GD); - CGCallee callee(calleeInfo, calleePtr); - return callee; -} - -LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) { - // Comma expressions just emit their LHS then their RHS as an l-value. - if (E->getOpcode() == BO_Comma) { - EmitIgnoredExpr(E->getLHS()); - EnsureInsertPoint(); - return EmitLValue(E->getRHS()); - } - - if (E->getOpcode() == BO_PtrMemD || - E->getOpcode() == BO_PtrMemI) - return EmitPointerToDataMemberBinaryExpr(E); - - assert(E->getOpcode() == BO_Assign && "unexpected binary l-value"); - - // Note that in all of these cases, __block variables need the RHS - // evaluated first just in case the variable gets moved by the RHS. - - switch (getEvaluationKind(E->getType())) { - case TEK_Scalar: { - switch (E->getLHS()->getType().getObjCLifetime()) { - case Qualifiers::OCL_Strong: - return EmitARCStoreStrong(E, /*ignored*/ false).first; - - case Qualifiers::OCL_Autoreleasing: - return EmitARCStoreAutoreleasing(E).first; - - // No reason to do any of these differently. - case Qualifiers::OCL_None: - case Qualifiers::OCL_ExplicitNone: - case Qualifiers::OCL_Weak: - break; - } - - RValue RV = EmitAnyExpr(E->getRHS()); - LValue LV = EmitCheckedLValue(E->getLHS(), TCK_Store); - if (RV.isScalar()) - EmitNullabilityCheck(LV, RV.getScalarVal(), E->getExprLoc()); - EmitStoreThroughLValue(RV, LV); - return LV; - } - - case TEK_Complex: - return EmitComplexAssignmentLValue(E); - - case TEK_Aggregate: - return EmitAggExprToLValue(E); - } - llvm_unreachable("bad evaluation kind"); -} - -LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) { - RValue RV = EmitCallExpr(E); - - if (!RV.isScalar()) - return MakeAddrLValue(RV.getAggregateAddress(), E->getType(), - AlignmentSource::Decl); - - assert(E->getCallReturnType(getContext())->isReferenceType() && - "Can't have a scalar return unless the return type is a " - "reference type!"); - - return MakeNaturalAlignPointeeAddrLValue(RV.getScalarVal(), E->getType()); -} - -LValue CodeGenFunction::EmitVAArgExprLValue(const VAArgExpr *E) { - // FIXME: This shouldn't require another copy. - return EmitAggExprToLValue(E); -} - -LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) { - assert(E->getType()->getAsCXXRecordDecl()->hasTrivialDestructor() - && "binding l-value to type which needs a temporary"); - AggValueSlot Slot = CreateAggTemp(E->getType()); - EmitCXXConstructExpr(E, Slot); - return MakeAddrLValue(Slot.getAddress(), E->getType(), AlignmentSource::Decl); -} - -LValue -CodeGenFunction::EmitCXXTypeidLValue(const CXXTypeidExpr *E) { - return MakeNaturalAlignAddrLValue(EmitCXXTypeidExpr(E), E->getType()); -} - -Address CodeGenFunction::EmitCXXUuidofExpr(const CXXUuidofExpr *E) { - return Builder.CreateElementBitCast(CGM.GetAddrOfUuidDescriptor(E), - ConvertType(E->getType())); -} - -LValue CodeGenFunction::EmitCXXUuidofLValue(const CXXUuidofExpr *E) { - return MakeAddrLValue(EmitCXXUuidofExpr(E), E->getType(), - AlignmentSource::Decl); -} - -LValue -CodeGenFunction::EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E) { - AggValueSlot Slot = CreateAggTemp(E->getType(), "temp.lvalue"); - Slot.setExternallyDestructed(); - EmitAggExpr(E->getSubExpr(), Slot); - EmitCXXTemporary(E->getTemporary(), E->getType(), Slot.getAddress()); - return MakeAddrLValue(Slot.getAddress(), E->getType(), AlignmentSource::Decl); -} - -LValue -CodeGenFunction::EmitLambdaLValue(const LambdaExpr *E) { - AggValueSlot Slot = CreateAggTemp(E->getType(), "temp.lvalue"); - EmitLambdaExpr(E, Slot); - return MakeAddrLValue(Slot.getAddress(), E->getType(), AlignmentSource::Decl); -} - -LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) { - RValue RV = EmitObjCMessageExpr(E); - - if (!RV.isScalar()) - return MakeAddrLValue(RV.getAggregateAddress(), E->getType(), - AlignmentSource::Decl); - - assert(E->getMethodDecl()->getReturnType()->isReferenceType() && - "Can't have a scalar return unless the return type is a " - "reference type!"); - - return MakeNaturalAlignPointeeAddrLValue(RV.getScalarVal(), E->getType()); -} - -LValue CodeGenFunction::EmitObjCSelectorLValue(const ObjCSelectorExpr *E) { - Address V = - CGM.getObjCRuntime().GetAddrOfSelector(*this, E->getSelector()); - return MakeAddrLValue(V, E->getType(), AlignmentSource::Decl); -} - -llvm::Value *CodeGenFunction::EmitIvarOffset(const ObjCInterfaceDecl *Interface, - const ObjCIvarDecl *Ivar) { - return CGM.getObjCRuntime().EmitIvarOffset(*this, Interface, Ivar); -} - -LValue CodeGenFunction::EmitLValueForIvar(QualType ObjectTy, - llvm::Value *BaseValue, - const ObjCIvarDecl *Ivar, - unsigned CVRQualifiers) { - return CGM.getObjCRuntime().EmitObjCValueForIvar(*this, ObjectTy, BaseValue, - Ivar, CVRQualifiers); -} - -LValue CodeGenFunction::EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E) { - // FIXME: A lot of the code below could be shared with EmitMemberExpr. - llvm::Value *BaseValue = nullptr; - const Expr *BaseExpr = E->getBase(); - Qualifiers BaseQuals; - QualType ObjectTy; - if (E->isArrow()) { - BaseValue = EmitScalarExpr(BaseExpr); - ObjectTy = BaseExpr->getType()->getPointeeType(); - BaseQuals = ObjectTy.getQualifiers(); - } else { - LValue BaseLV = EmitLValue(BaseExpr); - BaseValue = BaseLV.getPointer(); - ObjectTy = BaseExpr->getType(); - BaseQuals = ObjectTy.getQualifiers(); - } - - LValue LV = - EmitLValueForIvar(ObjectTy, BaseValue, E->getDecl(), - BaseQuals.getCVRQualifiers()); - setObjCGCLValueClass(getContext(), E, LV); - return LV; -} - -LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) { - // Can only get l-value for message expression returning aggregate type - RValue RV = EmitAnyExprToTemp(E); - return MakeAddrLValue(RV.getAggregateAddress(), E->getType(), - AlignmentSource::Decl); -} - -RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee, - const CallExpr *E, ReturnValueSlot ReturnValue, - llvm::Value *Chain) { - // Get the actual function type. The callee type will always be a pointer to - // function type or a block pointer type. - assert(CalleeType->isFunctionPointerType() && - "Call must have function pointer type!"); - - const Decl *TargetDecl = - OrigCallee.getAbstractInfo().getCalleeDecl().getDecl(); - - if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) - // We can only guarantee that a function is called from the correct - // context/function based on the appropriate target attributes, - // so only check in the case where we have both always_inline and target - // since otherwise we could be making a conditional call after a check for - // the proper cpu features (and it won't cause code generation issues due to - // function based code generation). - if (TargetDecl->hasAttr<AlwaysInlineAttr>() && - TargetDecl->hasAttr<TargetAttr>()) - checkTargetFeatures(E, FD); - - CalleeType = getContext().getCanonicalType(CalleeType); - - auto PointeeType = cast<PointerType>(CalleeType)->getPointeeType(); - - CGCallee Callee = OrigCallee; - - if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function) && - (!TargetDecl || !isa<FunctionDecl>(TargetDecl))) { - if (llvm::Constant *PrefixSig = - CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) { - SanitizerScope SanScope(this); - // Remove any (C++17) exception specifications, to allow calling e.g. a - // noexcept function through a non-noexcept pointer. - auto ProtoTy = - getContext().getFunctionTypeWithExceptionSpec(PointeeType, EST_None); - llvm::Constant *FTRTTIConst = - CGM.GetAddrOfRTTIDescriptor(ProtoTy, /*ForEH=*/true); - llvm::Type *PrefixStructTyElems[] = {PrefixSig->getType(), Int32Ty}; - llvm::StructType *PrefixStructTy = llvm::StructType::get( - CGM.getLLVMContext(), PrefixStructTyElems, /*isPacked=*/true); - - llvm::Value *CalleePtr = Callee.getFunctionPointer(); - - llvm::Value *CalleePrefixStruct = Builder.CreateBitCast( - CalleePtr, llvm::PointerType::getUnqual(PrefixStructTy)); - llvm::Value *CalleeSigPtr = - Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, 0, 0); - llvm::Value *CalleeSig = - Builder.CreateAlignedLoad(CalleeSigPtr, getIntAlign()); - llvm::Value *CalleeSigMatch = Builder.CreateICmpEQ(CalleeSig, PrefixSig); - - llvm::BasicBlock *Cont = createBasicBlock("cont"); - llvm::BasicBlock *TypeCheck = createBasicBlock("typecheck"); - Builder.CreateCondBr(CalleeSigMatch, TypeCheck, Cont); - - EmitBlock(TypeCheck); - llvm::Value *CalleeRTTIPtr = - Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, 0, 1); - llvm::Value *CalleeRTTIEncoded = - Builder.CreateAlignedLoad(CalleeRTTIPtr, getPointerAlign()); - llvm::Value *CalleeRTTI = - DecodeAddrUsedInPrologue(CalleePtr, CalleeRTTIEncoded); - llvm::Value *CalleeRTTIMatch = - Builder.CreateICmpEQ(CalleeRTTI, FTRTTIConst); - llvm::Constant *StaticData[] = {EmitCheckSourceLocation(E->getBeginLoc()), - EmitCheckTypeDescriptor(CalleeType)}; - EmitCheck(std::make_pair(CalleeRTTIMatch, SanitizerKind::Function), - SanitizerHandler::FunctionTypeMismatch, StaticData, CalleePtr); - - Builder.CreateBr(Cont); - EmitBlock(Cont); - } - } - - const auto *FnType = cast<FunctionType>(PointeeType); - - // If we are checking indirect calls and this call is indirect, check that the - // function pointer is a member of the bit set for the function type. - if (SanOpts.has(SanitizerKind::CFIICall) && - (!TargetDecl || !isa<FunctionDecl>(TargetDecl))) { - SanitizerScope SanScope(this); - EmitSanitizerStatReport(llvm::SanStat_CFI_ICall); - - llvm::Metadata *MD; - if (CGM.getCodeGenOpts().SanitizeCfiICallGeneralizePointers) - MD = CGM.CreateMetadataIdentifierGeneralized(QualType(FnType, 0)); - else - MD = CGM.CreateMetadataIdentifierForType(QualType(FnType, 0)); - - llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD); - - llvm::Value *CalleePtr = Callee.getFunctionPointer(); - llvm::Value *CastedCallee = Builder.CreateBitCast(CalleePtr, Int8PtrTy); - llvm::Value *TypeTest = Builder.CreateCall( - CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedCallee, TypeId}); - - auto CrossDsoTypeId = CGM.CreateCrossDsoCfiTypeId(MD); - llvm::Constant *StaticData[] = { - llvm::ConstantInt::get(Int8Ty, CFITCK_ICall), - EmitCheckSourceLocation(E->getBeginLoc()), - EmitCheckTypeDescriptor(QualType(FnType, 0)), - }; - if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && CrossDsoTypeId) { - EmitCfiSlowPathCheck(SanitizerKind::CFIICall, TypeTest, CrossDsoTypeId, - CastedCallee, StaticData); - } else { - EmitCheck(std::make_pair(TypeTest, SanitizerKind::CFIICall), - SanitizerHandler::CFICheckFail, StaticData, - {CastedCallee, llvm::UndefValue::get(IntPtrTy)}); - } - } - - CallArgList Args; - if (Chain) - Args.add(RValue::get(Builder.CreateBitCast(Chain, CGM.VoidPtrTy)), - CGM.getContext().VoidPtrTy); - - // C++17 requires that we evaluate arguments to a call using assignment syntax - // right-to-left, and that we evaluate arguments to certain other operators - // left-to-right. Note that we allow this to override the order dictated by - // the calling convention on the MS ABI, which means that parameter - // destruction order is not necessarily reverse construction order. - // FIXME: Revisit this based on C++ committee response to unimplementability. - EvaluationOrder Order = EvaluationOrder::Default; - if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(E)) { - if (OCE->isAssignmentOp()) - Order = EvaluationOrder::ForceRightToLeft; - else { - switch (OCE->getOperator()) { - case OO_LessLess: - case OO_GreaterGreater: - case OO_AmpAmp: - case OO_PipePipe: - case OO_Comma: - case OO_ArrowStar: - Order = EvaluationOrder::ForceLeftToRight; - break; - default: - break; - } - } - } - - EmitCallArgs(Args, dyn_cast<FunctionProtoType>(FnType), E->arguments(), - E->getDirectCallee(), /*ParamsToSkip*/ 0, Order); - - const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionCall( - Args, FnType, /*isChainCall=*/Chain); - - // C99 6.5.2.2p6: - // If the expression that denotes the called function has a type - // that does not include a prototype, [the default argument - // promotions are performed]. If the number of arguments does not - // equal the number of parameters, the behavior is undefined. If - // the function is defined with a type that includes a prototype, - // and either the prototype ends with an ellipsis (, ...) or the - // types of the arguments after promotion are not compatible with - // the types of the parameters, the behavior is undefined. If the - // function is defined with a type that does not include a - // prototype, and the types of the arguments after promotion are - // not compatible with those of the parameters after promotion, - // the behavior is undefined [except in some trivial cases]. - // That is, in the general case, we should assume that a call - // through an unprototyped function type works like a *non-variadic* - // call. The way we make this work is to cast to the exact type - // of the promoted arguments. - // - // Chain calls use this same code path to add the invisible chain parameter - // to the function type. - if (isa<FunctionNoProtoType>(FnType) || Chain) { - llvm::Type *CalleeTy = getTypes().GetFunctionType(FnInfo); - CalleeTy = CalleeTy->getPointerTo(); - - llvm::Value *CalleePtr = Callee.getFunctionPointer(); - CalleePtr = Builder.CreateBitCast(CalleePtr, CalleeTy, "callee.knr.cast"); - Callee.setFunctionPointer(CalleePtr); - } - - return EmitCall(FnInfo, Callee, ReturnValue, Args, nullptr, E->getExprLoc()); -} - -LValue CodeGenFunction:: -EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) { - Address BaseAddr = Address::invalid(); - if (E->getOpcode() == BO_PtrMemI) { - BaseAddr = EmitPointerWithAlignment(E->getLHS()); - } else { - BaseAddr = EmitLValue(E->getLHS()).getAddress(); - } - - llvm::Value *OffsetV = EmitScalarExpr(E->getRHS()); - - const MemberPointerType *MPT - = E->getRHS()->getType()->getAs<MemberPointerType>(); - - LValueBaseInfo BaseInfo; - TBAAAccessInfo TBAAInfo; - Address MemberAddr = - EmitCXXMemberDataPointerAddress(E, BaseAddr, OffsetV, MPT, &BaseInfo, - &TBAAInfo); - - return MakeAddrLValue(MemberAddr, MPT->getPointeeType(), BaseInfo, TBAAInfo); -} - -/// Given the address of a temporary variable, produce an r-value of -/// its type. -RValue CodeGenFunction::convertTempToRValue(Address addr, - QualType type, - SourceLocation loc) { - LValue lvalue = MakeAddrLValue(addr, type, AlignmentSource::Decl); - switch (getEvaluationKind(type)) { - case TEK_Complex: - return RValue::getComplex(EmitLoadOfComplex(lvalue, loc)); - case TEK_Aggregate: - return lvalue.asAggregateRValue(); - case TEK_Scalar: - return RValue::get(EmitLoadOfScalar(lvalue, loc)); - } - llvm_unreachable("bad evaluation kind"); -} - -void CodeGenFunction::SetFPAccuracy(llvm::Value *Val, float Accuracy) { - assert(Val->getType()->isFPOrFPVectorTy()); - if (Accuracy == 0.0 || !isa<llvm::Instruction>(Val)) - return; - - llvm::MDBuilder MDHelper(getLLVMContext()); - llvm::MDNode *Node = MDHelper.createFPMath(Accuracy); - - cast<llvm::Instruction>(Val)->setMetadata(llvm::LLVMContext::MD_fpmath, Node); -} - -namespace { - struct LValueOrRValue { - LValue LV; - RValue RV; - }; -} - -static LValueOrRValue emitPseudoObjectExpr(CodeGenFunction &CGF, - const PseudoObjectExpr *E, - bool forLValue, - AggValueSlot slot) { - SmallVector<CodeGenFunction::OpaqueValueMappingData, 4> opaques; - - // Find the result expression, if any. - const Expr *resultExpr = E->getResultExpr(); - LValueOrRValue result; - - for (PseudoObjectExpr::const_semantics_iterator - i = E->semantics_begin(), e = E->semantics_end(); i != e; ++i) { - const Expr *semantic = *i; - - // If this semantic expression is an opaque value, bind it - // to the result of its source expression. - if (const auto *ov = dyn_cast<OpaqueValueExpr>(semantic)) { - // Skip unique OVEs. - if (ov->isUnique()) { - assert(ov != resultExpr && - "A unique OVE cannot be used as the result expression"); - continue; - } - - // If this is the result expression, we may need to evaluate - // directly into the slot. - typedef CodeGenFunction::OpaqueValueMappingData OVMA; - OVMA opaqueData; - if (ov == resultExpr && ov->isRValue() && !forLValue && - CodeGenFunction::hasAggregateEvaluationKind(ov->getType())) { - CGF.EmitAggExpr(ov->getSourceExpr(), slot); - LValue LV = CGF.MakeAddrLValue(slot.getAddress(), ov->getType(), - AlignmentSource::Decl); - opaqueData = OVMA::bind(CGF, ov, LV); - result.RV = slot.asRValue(); - - // Otherwise, emit as normal. - } else { - opaqueData = OVMA::bind(CGF, ov, ov->getSourceExpr()); - - // If this is the result, also evaluate the result now. - if (ov == resultExpr) { - if (forLValue) - result.LV = CGF.EmitLValue(ov); - else - result.RV = CGF.EmitAnyExpr(ov, slot); - } - } - - opaques.push_back(opaqueData); - - // Otherwise, if the expression is the result, evaluate it - // and remember the result. - } else if (semantic == resultExpr) { - if (forLValue) - result.LV = CGF.EmitLValue(semantic); - else - result.RV = CGF.EmitAnyExpr(semantic, slot); - - // Otherwise, evaluate the expression in an ignored context. - } else { - CGF.EmitIgnoredExpr(semantic); - } - } - - // Unbind all the opaques now. - for (unsigned i = 0, e = opaques.size(); i != e; ++i) - opaques[i].unbind(CGF); - - return result; -} - -RValue CodeGenFunction::EmitPseudoObjectRValue(const PseudoObjectExpr *E, - AggValueSlot slot) { - return emitPseudoObjectExpr(*this, E, false, slot).RV; -} - -LValue CodeGenFunction::EmitPseudoObjectLValue(const PseudoObjectExpr *E) { - return emitPseudoObjectExpr(*this, E, true, AggValueSlot::ignored()).LV; -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp deleted file mode 100644 index db49b3f28a5..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp +++ /dev/null @@ -1,1935 +0,0 @@ -//===--- CGExprAgg.cpp - Emit LLVM Code from Aggregate Expressions --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code to emit Aggregate Expr nodes as LLVM code. -// -//===----------------------------------------------------------------------===// - -#include "CodeGenFunction.h" -#include "CGCXXABI.h" -#include "CGObjCRuntime.h" -#include "CodeGenModule.h" -#include "ConstantEmitter.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/StmtVisitor.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/IntrinsicInst.h" -using namespace clang; -using namespace CodeGen; - -//===----------------------------------------------------------------------===// -// Aggregate Expression Emitter -//===----------------------------------------------------------------------===// - -namespace { -class AggExprEmitter : public StmtVisitor<AggExprEmitter> { - CodeGenFunction &CGF; - CGBuilderTy &Builder; - AggValueSlot Dest; - bool IsResultUnused; - - AggValueSlot EnsureSlot(QualType T) { - if (!Dest.isIgnored()) return Dest; - return CGF.CreateAggTemp(T, "agg.tmp.ensured"); - } - void EnsureDest(QualType T) { - if (!Dest.isIgnored()) return; - Dest = CGF.CreateAggTemp(T, "agg.tmp.ensured"); - } - - // Calls `Fn` with a valid return value slot, potentially creating a temporary - // to do so. If a temporary is created, an appropriate copy into `Dest` will - // be emitted, as will lifetime markers. - // - // The given function should take a ReturnValueSlot, and return an RValue that - // points to said slot. - void withReturnValueSlot(const Expr *E, - llvm::function_ref<RValue(ReturnValueSlot)> Fn); - -public: - AggExprEmitter(CodeGenFunction &cgf, AggValueSlot Dest, bool IsResultUnused) - : CGF(cgf), Builder(CGF.Builder), Dest(Dest), - IsResultUnused(IsResultUnused) { } - - //===--------------------------------------------------------------------===// - // Utilities - //===--------------------------------------------------------------------===// - - /// EmitAggLoadOfLValue - Given an expression with aggregate type that - /// represents a value lvalue, this method emits the address of the lvalue, - /// then loads the result into DestPtr. - void EmitAggLoadOfLValue(const Expr *E); - - enum ExprValueKind { - EVK_RValue, - EVK_NonRValue - }; - - /// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired. - /// SrcIsRValue is true if source comes from an RValue. - void EmitFinalDestCopy(QualType type, const LValue &src, - ExprValueKind SrcValueKind = EVK_NonRValue); - void EmitFinalDestCopy(QualType type, RValue src); - void EmitCopy(QualType type, const AggValueSlot &dest, - const AggValueSlot &src); - - void EmitMoveFromReturnSlot(const Expr *E, RValue Src); - - void EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, - QualType ArrayQTy, InitListExpr *E); - - AggValueSlot::NeedsGCBarriers_t needsGC(QualType T) { - if (CGF.getLangOpts().getGC() && TypeRequiresGCollection(T)) - return AggValueSlot::NeedsGCBarriers; - return AggValueSlot::DoesNotNeedGCBarriers; - } - - bool TypeRequiresGCollection(QualType T); - - //===--------------------------------------------------------------------===// - // Visitor Methods - //===--------------------------------------------------------------------===// - - void Visit(Expr *E) { - ApplyDebugLocation DL(CGF, E); - StmtVisitor<AggExprEmitter>::Visit(E); - } - - void VisitStmt(Stmt *S) { - CGF.ErrorUnsupported(S, "aggregate expression"); - } - void VisitParenExpr(ParenExpr *PE) { Visit(PE->getSubExpr()); } - void VisitGenericSelectionExpr(GenericSelectionExpr *GE) { - Visit(GE->getResultExpr()); - } - void VisitCoawaitExpr(CoawaitExpr *E) { - CGF.EmitCoawaitExpr(*E, Dest, IsResultUnused); - } - void VisitCoyieldExpr(CoyieldExpr *E) { - CGF.EmitCoyieldExpr(*E, Dest, IsResultUnused); - } - void VisitUnaryCoawait(UnaryOperator *E) { Visit(E->getSubExpr()); } - void VisitUnaryExtension(UnaryOperator *E) { Visit(E->getSubExpr()); } - void VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) { - return Visit(E->getReplacement()); - } - - void VisitConstantExpr(ConstantExpr *E) { - return Visit(E->getSubExpr()); - } - - // l-values. - void VisitDeclRefExpr(DeclRefExpr *E) { EmitAggLoadOfLValue(E); } - void VisitMemberExpr(MemberExpr *ME) { EmitAggLoadOfLValue(ME); } - void VisitUnaryDeref(UnaryOperator *E) { EmitAggLoadOfLValue(E); } - void VisitStringLiteral(StringLiteral *E) { EmitAggLoadOfLValue(E); } - void VisitCompoundLiteralExpr(CompoundLiteralExpr *E); - void VisitArraySubscriptExpr(ArraySubscriptExpr *E) { - EmitAggLoadOfLValue(E); - } - void VisitPredefinedExpr(const PredefinedExpr *E) { - EmitAggLoadOfLValue(E); - } - - // Operators. - void VisitCastExpr(CastExpr *E); - void VisitCallExpr(const CallExpr *E); - void VisitStmtExpr(const StmtExpr *E); - void VisitBinaryOperator(const BinaryOperator *BO); - void VisitPointerToDataMemberBinaryOperator(const BinaryOperator *BO); - void VisitBinAssign(const BinaryOperator *E); - void VisitBinComma(const BinaryOperator *E); - void VisitBinCmp(const BinaryOperator *E); - - void VisitObjCMessageExpr(ObjCMessageExpr *E); - void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { - EmitAggLoadOfLValue(E); - } - - void VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E); - void VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO); - void VisitChooseExpr(const ChooseExpr *CE); - void VisitInitListExpr(InitListExpr *E); - void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E, - llvm::Value *outerBegin = nullptr); - void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E); - void VisitNoInitExpr(NoInitExpr *E) { } // Do nothing. - void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) { - Visit(DAE->getExpr()); - } - void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) { - CodeGenFunction::CXXDefaultInitExprScope Scope(CGF); - Visit(DIE->getExpr()); - } - void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E); - void VisitCXXConstructExpr(const CXXConstructExpr *E); - void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E); - void VisitLambdaExpr(LambdaExpr *E); - void VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E); - void VisitExprWithCleanups(ExprWithCleanups *E); - void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E); - void VisitCXXTypeidExpr(CXXTypeidExpr *E) { EmitAggLoadOfLValue(E); } - void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E); - void VisitOpaqueValueExpr(OpaqueValueExpr *E); - - void VisitPseudoObjectExpr(PseudoObjectExpr *E) { - if (E->isGLValue()) { - LValue LV = CGF.EmitPseudoObjectLValue(E); - return EmitFinalDestCopy(E->getType(), LV); - } - - CGF.EmitPseudoObjectRValue(E, EnsureSlot(E->getType())); - } - - void VisitVAArgExpr(VAArgExpr *E); - - void EmitInitializationToLValue(Expr *E, LValue Address); - void EmitNullInitializationToLValue(LValue Address); - // case Expr::ChooseExprClass: - void VisitCXXThrowExpr(const CXXThrowExpr *E) { CGF.EmitCXXThrowExpr(E); } - void VisitAtomicExpr(AtomicExpr *E) { - RValue Res = CGF.EmitAtomicExpr(E); - EmitFinalDestCopy(E->getType(), Res); - } -}; -} // end anonymous namespace. - -//===----------------------------------------------------------------------===// -// Utilities -//===----------------------------------------------------------------------===// - -/// EmitAggLoadOfLValue - Given an expression with aggregate type that -/// represents a value lvalue, this method emits the address of the lvalue, -/// then loads the result into DestPtr. -void AggExprEmitter::EmitAggLoadOfLValue(const Expr *E) { - LValue LV = CGF.EmitLValue(E); - - // If the type of the l-value is atomic, then do an atomic load. - if (LV.getType()->isAtomicType() || CGF.LValueIsSuitableForInlineAtomic(LV)) { - CGF.EmitAtomicLoad(LV, E->getExprLoc(), Dest); - return; - } - - EmitFinalDestCopy(E->getType(), LV); -} - -/// True if the given aggregate type requires special GC API calls. -bool AggExprEmitter::TypeRequiresGCollection(QualType T) { - // Only record types have members that might require garbage collection. - const RecordType *RecordTy = T->getAs<RecordType>(); - if (!RecordTy) return false; - - // Don't mess with non-trivial C++ types. - RecordDecl *Record = RecordTy->getDecl(); - if (isa<CXXRecordDecl>(Record) && - (cast<CXXRecordDecl>(Record)->hasNonTrivialCopyConstructor() || - !cast<CXXRecordDecl>(Record)->hasTrivialDestructor())) - return false; - - // Check whether the type has an object member. - return Record->hasObjectMember(); -} - -void AggExprEmitter::withReturnValueSlot( - const Expr *E, llvm::function_ref<RValue(ReturnValueSlot)> EmitCall) { - QualType RetTy = E->getType(); - bool RequiresDestruction = - Dest.isIgnored() && - RetTy.isDestructedType() == QualType::DK_nontrivial_c_struct; - - // If it makes no observable difference, save a memcpy + temporary. - // - // We need to always provide our own temporary if destruction is required. - // Otherwise, EmitCall will emit its own, notice that it's "unused", and end - // its lifetime before we have the chance to emit a proper destructor call. - bool UseTemp = Dest.isPotentiallyAliased() || Dest.requiresGCollection() || - (RequiresDestruction && !Dest.getAddress().isValid()); - - Address RetAddr = Address::invalid(); - Address RetAllocaAddr = Address::invalid(); - - EHScopeStack::stable_iterator LifetimeEndBlock; - llvm::Value *LifetimeSizePtr = nullptr; - llvm::IntrinsicInst *LifetimeStartInst = nullptr; - if (!UseTemp) { - RetAddr = Dest.getAddress(); - } else { - RetAddr = CGF.CreateMemTemp(RetTy, "tmp", &RetAllocaAddr); - uint64_t Size = - CGF.CGM.getDataLayout().getTypeAllocSize(CGF.ConvertTypeForMem(RetTy)); - LifetimeSizePtr = CGF.EmitLifetimeStart(Size, RetAllocaAddr.getPointer()); - if (LifetimeSizePtr) { - LifetimeStartInst = - cast<llvm::IntrinsicInst>(std::prev(Builder.GetInsertPoint())); - assert(LifetimeStartInst->getIntrinsicID() == - llvm::Intrinsic::lifetime_start && - "Last insertion wasn't a lifetime.start?"); - - CGF.pushFullExprCleanup<CodeGenFunction::CallLifetimeEnd>( - NormalEHLifetimeMarker, RetAllocaAddr, LifetimeSizePtr); - LifetimeEndBlock = CGF.EHStack.stable_begin(); - } - } - - RValue Src = - EmitCall(ReturnValueSlot(RetAddr, Dest.isVolatile(), IsResultUnused)); - - if (RequiresDestruction) - CGF.pushDestroy(RetTy.isDestructedType(), Src.getAggregateAddress(), RetTy); - - if (!UseTemp) - return; - - assert(Dest.getPointer() != Src.getAggregatePointer()); - EmitFinalDestCopy(E->getType(), Src); - - if (!RequiresDestruction && LifetimeStartInst) { - // If there's no dtor to run, the copy was the last use of our temporary. - // Since we're not guaranteed to be in an ExprWithCleanups, clean up - // eagerly. - CGF.DeactivateCleanupBlock(LifetimeEndBlock, LifetimeStartInst); - CGF.EmitLifetimeEnd(LifetimeSizePtr, RetAllocaAddr.getPointer()); - } -} - -/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired. -void AggExprEmitter::EmitFinalDestCopy(QualType type, RValue src) { - assert(src.isAggregate() && "value must be aggregate value!"); - LValue srcLV = CGF.MakeAddrLValue(src.getAggregateAddress(), type); - EmitFinalDestCopy(type, srcLV, EVK_RValue); -} - -/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired. -void AggExprEmitter::EmitFinalDestCopy(QualType type, const LValue &src, - ExprValueKind SrcValueKind) { - // If Dest is ignored, then we're evaluating an aggregate expression - // in a context that doesn't care about the result. Note that loads - // from volatile l-values force the existence of a non-ignored - // destination. - if (Dest.isIgnored()) - return; - - // Copy non-trivial C structs here. - LValue DstLV = CGF.MakeAddrLValue( - Dest.getAddress(), Dest.isVolatile() ? type.withVolatile() : type); - - if (SrcValueKind == EVK_RValue) { - if (type.isNonTrivialToPrimitiveDestructiveMove() == QualType::PCK_Struct) { - if (Dest.isPotentiallyAliased()) - CGF.callCStructMoveAssignmentOperator(DstLV, src); - else - CGF.callCStructMoveConstructor(DstLV, src); - return; - } - } else { - if (type.isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct) { - if (Dest.isPotentiallyAliased()) - CGF.callCStructCopyAssignmentOperator(DstLV, src); - else - CGF.callCStructCopyConstructor(DstLV, src); - return; - } - } - - AggValueSlot srcAgg = - AggValueSlot::forLValue(src, AggValueSlot::IsDestructed, - needsGC(type), AggValueSlot::IsAliased, - AggValueSlot::MayOverlap); - EmitCopy(type, Dest, srcAgg); -} - -/// Perform a copy from the source into the destination. -/// -/// \param type - the type of the aggregate being copied; qualifiers are -/// ignored -void AggExprEmitter::EmitCopy(QualType type, const AggValueSlot &dest, - const AggValueSlot &src) { - if (dest.requiresGCollection()) { - CharUnits sz = dest.getPreferredSize(CGF.getContext(), type); - llvm::Value *size = llvm::ConstantInt::get(CGF.SizeTy, sz.getQuantity()); - CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF, - dest.getAddress(), - src.getAddress(), - size); - return; - } - - // If the result of the assignment is used, copy the LHS there also. - // It's volatile if either side is. Use the minimum alignment of - // the two sides. - LValue DestLV = CGF.MakeAddrLValue(dest.getAddress(), type); - LValue SrcLV = CGF.MakeAddrLValue(src.getAddress(), type); - CGF.EmitAggregateCopy(DestLV, SrcLV, type, dest.mayOverlap(), - dest.isVolatile() || src.isVolatile()); -} - -/// Emit the initializer for a std::initializer_list initialized with a -/// real initializer list. -void -AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { - // Emit an array containing the elements. The array is externally destructed - // if the std::initializer_list object is. - ASTContext &Ctx = CGF.getContext(); - LValue Array = CGF.EmitLValue(E->getSubExpr()); - assert(Array.isSimple() && "initializer_list array not a simple lvalue"); - Address ArrayPtr = Array.getAddress(); - - const ConstantArrayType *ArrayType = - Ctx.getAsConstantArrayType(E->getSubExpr()->getType()); - assert(ArrayType && "std::initializer_list constructed from non-array"); - - // FIXME: Perform the checks on the field types in SemaInit. - RecordDecl *Record = E->getType()->castAs<RecordType>()->getDecl(); - RecordDecl::field_iterator Field = Record->field_begin(); - if (Field == Record->field_end()) { - CGF.ErrorUnsupported(E, "weird std::initializer_list"); - return; - } - - // Start pointer. - if (!Field->getType()->isPointerType() || - !Ctx.hasSameType(Field->getType()->getPointeeType(), - ArrayType->getElementType())) { - CGF.ErrorUnsupported(E, "weird std::initializer_list"); - return; - } - - AggValueSlot Dest = EnsureSlot(E->getType()); - LValue DestLV = CGF.MakeAddrLValue(Dest.getAddress(), E->getType()); - LValue Start = CGF.EmitLValueForFieldInitialization(DestLV, *Field); - llvm::Value *Zero = llvm::ConstantInt::get(CGF.PtrDiffTy, 0); - llvm::Value *IdxStart[] = { Zero, Zero }; - llvm::Value *ArrayStart = - Builder.CreateInBoundsGEP(ArrayPtr.getPointer(), IdxStart, "arraystart"); - CGF.EmitStoreThroughLValue(RValue::get(ArrayStart), Start); - ++Field; - - if (Field == Record->field_end()) { - CGF.ErrorUnsupported(E, "weird std::initializer_list"); - return; - } - - llvm::Value *Size = Builder.getInt(ArrayType->getSize()); - LValue EndOrLength = CGF.EmitLValueForFieldInitialization(DestLV, *Field); - if (Field->getType()->isPointerType() && - Ctx.hasSameType(Field->getType()->getPointeeType(), - ArrayType->getElementType())) { - // End pointer. - llvm::Value *IdxEnd[] = { Zero, Size }; - llvm::Value *ArrayEnd = - Builder.CreateInBoundsGEP(ArrayPtr.getPointer(), IdxEnd, "arrayend"); - CGF.EmitStoreThroughLValue(RValue::get(ArrayEnd), EndOrLength); - } else if (Ctx.hasSameType(Field->getType(), Ctx.getSizeType())) { - // Length. - CGF.EmitStoreThroughLValue(RValue::get(Size), EndOrLength); - } else { - CGF.ErrorUnsupported(E, "weird std::initializer_list"); - return; - } -} - -/// Determine if E is a trivial array filler, that is, one that is -/// equivalent to zero-initialization. -static bool isTrivialFiller(Expr *E) { - if (!E) - return true; - - if (isa<ImplicitValueInitExpr>(E)) - return true; - - if (auto *ILE = dyn_cast<InitListExpr>(E)) { - if (ILE->getNumInits()) - return false; - return isTrivialFiller(ILE->getArrayFiller()); - } - - if (auto *Cons = dyn_cast_or_null<CXXConstructExpr>(E)) - return Cons->getConstructor()->isDefaultConstructor() && - Cons->getConstructor()->isTrivial(); - - // FIXME: Are there other cases where we can avoid emitting an initializer? - return false; -} - -/// Emit initialization of an array from an initializer list. -void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, - QualType ArrayQTy, InitListExpr *E) { - uint64_t NumInitElements = E->getNumInits(); - - uint64_t NumArrayElements = AType->getNumElements(); - assert(NumInitElements <= NumArrayElements); - - QualType elementType = - CGF.getContext().getAsArrayType(ArrayQTy)->getElementType(); - - // DestPtr is an array*. Construct an elementType* by drilling - // down a level. - llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); - llvm::Value *indices[] = { zero, zero }; - llvm::Value *begin = - Builder.CreateInBoundsGEP(DestPtr.getPointer(), indices, "arrayinit.begin"); - - CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType); - CharUnits elementAlign = - DestPtr.getAlignment().alignmentOfArrayElement(elementSize); - - // Consider initializing the array by copying from a global. For this to be - // more efficient than per-element initialization, the size of the elements - // with explicit initializers should be large enough. - if (NumInitElements * elementSize.getQuantity() > 16 && - elementType.isTriviallyCopyableType(CGF.getContext())) { - CodeGen::CodeGenModule &CGM = CGF.CGM; - ConstantEmitter Emitter(CGM); - LangAS AS = ArrayQTy.getAddressSpace(); - if (llvm::Constant *C = Emitter.tryEmitForInitializer(E, AS, ArrayQTy)) { - auto GV = new llvm::GlobalVariable( - CGM.getModule(), C->getType(), - CGM.isTypeConstant(ArrayQTy, /* ExcludeCtorDtor= */ true), - llvm::GlobalValue::PrivateLinkage, C, "constinit", - /* InsertBefore= */ nullptr, llvm::GlobalVariable::NotThreadLocal, - CGM.getContext().getTargetAddressSpace(AS)); - Emitter.finalize(GV); - CharUnits Align = CGM.getContext().getTypeAlignInChars(ArrayQTy); - GV->setAlignment(Align.getQuantity()); - EmitFinalDestCopy(ArrayQTy, CGF.MakeAddrLValue(GV, ArrayQTy, Align)); - return; - } - } - - // Exception safety requires us to destroy all the - // already-constructed members if an initializer throws. - // For that, we'll need an EH cleanup. - QualType::DestructionKind dtorKind = elementType.isDestructedType(); - Address endOfInit = Address::invalid(); - EHScopeStack::stable_iterator cleanup; - llvm::Instruction *cleanupDominator = nullptr; - if (CGF.needsEHCleanup(dtorKind)) { - // In principle we could tell the cleanup where we are more - // directly, but the control flow can get so varied here that it - // would actually be quite complex. Therefore we go through an - // alloca. - endOfInit = CGF.CreateTempAlloca(begin->getType(), CGF.getPointerAlign(), - "arrayinit.endOfInit"); - cleanupDominator = Builder.CreateStore(begin, endOfInit); - CGF.pushIrregularPartialArrayCleanup(begin, endOfInit, elementType, - elementAlign, - CGF.getDestroyer(dtorKind)); - cleanup = CGF.EHStack.stable_begin(); - - // Otherwise, remember that we didn't need a cleanup. - } else { - dtorKind = QualType::DK_none; - } - - llvm::Value *one = llvm::ConstantInt::get(CGF.SizeTy, 1); - - // The 'current element to initialize'. The invariants on this - // variable are complicated. Essentially, after each iteration of - // the loop, it points to the last initialized element, except - // that it points to the beginning of the array before any - // elements have been initialized. - llvm::Value *element = begin; - - // Emit the explicit initializers. - for (uint64_t i = 0; i != NumInitElements; ++i) { - // Advance to the next element. - if (i > 0) { - element = Builder.CreateInBoundsGEP(element, one, "arrayinit.element"); - - // Tell the cleanup that it needs to destroy up to this - // element. TODO: some of these stores can be trivially - // observed to be unnecessary. - if (endOfInit.isValid()) Builder.CreateStore(element, endOfInit); - } - - LValue elementLV = - CGF.MakeAddrLValue(Address(element, elementAlign), elementType); - EmitInitializationToLValue(E->getInit(i), elementLV); - } - - // Check whether there's a non-trivial array-fill expression. - Expr *filler = E->getArrayFiller(); - bool hasTrivialFiller = isTrivialFiller(filler); - - // Any remaining elements need to be zero-initialized, possibly - // using the filler expression. We can skip this if the we're - // emitting to zeroed memory. - if (NumInitElements != NumArrayElements && - !(Dest.isZeroed() && hasTrivialFiller && - CGF.getTypes().isZeroInitializable(elementType))) { - - // Use an actual loop. This is basically - // do { *array++ = filler; } while (array != end); - - // Advance to the start of the rest of the array. - if (NumInitElements) { - element = Builder.CreateInBoundsGEP(element, one, "arrayinit.start"); - if (endOfInit.isValid()) Builder.CreateStore(element, endOfInit); - } - - // Compute the end of the array. - llvm::Value *end = Builder.CreateInBoundsGEP(begin, - llvm::ConstantInt::get(CGF.SizeTy, NumArrayElements), - "arrayinit.end"); - - llvm::BasicBlock *entryBB = Builder.GetInsertBlock(); - llvm::BasicBlock *bodyBB = CGF.createBasicBlock("arrayinit.body"); - - // Jump into the body. - CGF.EmitBlock(bodyBB); - llvm::PHINode *currentElement = - Builder.CreatePHI(element->getType(), 2, "arrayinit.cur"); - currentElement->addIncoming(element, entryBB); - - // Emit the actual filler expression. - { - // C++1z [class.temporary]p5: - // when a default constructor is called to initialize an element of - // an array with no corresponding initializer [...] the destruction of - // every temporary created in a default argument is sequenced before - // the construction of the next array element, if any - CodeGenFunction::RunCleanupsScope CleanupsScope(CGF); - LValue elementLV = - CGF.MakeAddrLValue(Address(currentElement, elementAlign), elementType); - if (filler) - EmitInitializationToLValue(filler, elementLV); - else - EmitNullInitializationToLValue(elementLV); - } - - // Move on to the next element. - llvm::Value *nextElement = - Builder.CreateInBoundsGEP(currentElement, one, "arrayinit.next"); - - // Tell the EH cleanup that we finished with the last element. - if (endOfInit.isValid()) Builder.CreateStore(nextElement, endOfInit); - - // Leave the loop if we're done. - llvm::Value *done = Builder.CreateICmpEQ(nextElement, end, - "arrayinit.done"); - llvm::BasicBlock *endBB = CGF.createBasicBlock("arrayinit.end"); - Builder.CreateCondBr(done, endBB, bodyBB); - currentElement->addIncoming(nextElement, Builder.GetInsertBlock()); - - CGF.EmitBlock(endBB); - } - - // Leave the partial-array cleanup if we entered one. - if (dtorKind) CGF.DeactivateCleanupBlock(cleanup, cleanupDominator); -} - -//===----------------------------------------------------------------------===// -// Visitor Methods -//===----------------------------------------------------------------------===// - -void AggExprEmitter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E){ - Visit(E->GetTemporaryExpr()); -} - -void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) { - // If this is a unique OVE, just visit its source expression. - if (e->isUnique()) - Visit(e->getSourceExpr()); - else - EmitFinalDestCopy(e->getType(), CGF.getOrCreateOpaqueLValueMapping(e)); -} - -void -AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { - if (Dest.isPotentiallyAliased() && - E->getType().isPODType(CGF.getContext())) { - // For a POD type, just emit a load of the lvalue + a copy, because our - // compound literal might alias the destination. - EmitAggLoadOfLValue(E); - return; - } - - AggValueSlot Slot = EnsureSlot(E->getType()); - CGF.EmitAggExpr(E->getInitializer(), Slot); -} - -/// Attempt to look through various unimportant expressions to find a -/// cast of the given kind. -static Expr *findPeephole(Expr *op, CastKind kind) { - while (true) { - op = op->IgnoreParens(); - if (CastExpr *castE = dyn_cast<CastExpr>(op)) { - if (castE->getCastKind() == kind) - return castE->getSubExpr(); - if (castE->getCastKind() == CK_NoOp) - continue; - } - return nullptr; - } -} - -void AggExprEmitter::VisitCastExpr(CastExpr *E) { - if (const auto *ECE = dyn_cast<ExplicitCastExpr>(E)) - CGF.CGM.EmitExplicitCastExprType(ECE, &CGF); - switch (E->getCastKind()) { - case CK_Dynamic: { - // FIXME: Can this actually happen? We have no test coverage for it. - assert(isa<CXXDynamicCastExpr>(E) && "CK_Dynamic without a dynamic_cast?"); - LValue LV = CGF.EmitCheckedLValue(E->getSubExpr(), - CodeGenFunction::TCK_Load); - // FIXME: Do we also need to handle property references here? - if (LV.isSimple()) - CGF.EmitDynamicCast(LV.getAddress(), cast<CXXDynamicCastExpr>(E)); - else - CGF.CGM.ErrorUnsupported(E, "non-simple lvalue dynamic_cast"); - - if (!Dest.isIgnored()) - CGF.CGM.ErrorUnsupported(E, "lvalue dynamic_cast with a destination"); - break; - } - - case CK_ToUnion: { - // Evaluate even if the destination is ignored. - if (Dest.isIgnored()) { - CGF.EmitAnyExpr(E->getSubExpr(), AggValueSlot::ignored(), - /*ignoreResult=*/true); - break; - } - - // GCC union extension - QualType Ty = E->getSubExpr()->getType(); - Address CastPtr = - Builder.CreateElementBitCast(Dest.getAddress(), CGF.ConvertType(Ty)); - EmitInitializationToLValue(E->getSubExpr(), - CGF.MakeAddrLValue(CastPtr, Ty)); - break; - } - - case CK_DerivedToBase: - case CK_BaseToDerived: - case CK_UncheckedDerivedToBase: { - llvm_unreachable("cannot perform hierarchy conversion in EmitAggExpr: " - "should have been unpacked before we got here"); - } - - case CK_NonAtomicToAtomic: - case CK_AtomicToNonAtomic: { - bool isToAtomic = (E->getCastKind() == CK_NonAtomicToAtomic); - - // Determine the atomic and value types. - QualType atomicType = E->getSubExpr()->getType(); - QualType valueType = E->getType(); - if (isToAtomic) std::swap(atomicType, valueType); - - assert(atomicType->isAtomicType()); - assert(CGF.getContext().hasSameUnqualifiedType(valueType, - atomicType->castAs<AtomicType>()->getValueType())); - - // Just recurse normally if we're ignoring the result or the - // atomic type doesn't change representation. - if (Dest.isIgnored() || !CGF.CGM.isPaddedAtomicType(atomicType)) { - return Visit(E->getSubExpr()); - } - - CastKind peepholeTarget = - (isToAtomic ? CK_AtomicToNonAtomic : CK_NonAtomicToAtomic); - - // These two cases are reverses of each other; try to peephole them. - if (Expr *op = findPeephole(E->getSubExpr(), peepholeTarget)) { - assert(CGF.getContext().hasSameUnqualifiedType(op->getType(), - E->getType()) && - "peephole significantly changed types?"); - return Visit(op); - } - - // If we're converting an r-value of non-atomic type to an r-value - // of atomic type, just emit directly into the relevant sub-object. - if (isToAtomic) { - AggValueSlot valueDest = Dest; - if (!valueDest.isIgnored() && CGF.CGM.isPaddedAtomicType(atomicType)) { - // Zero-initialize. (Strictly speaking, we only need to initialize - // the padding at the end, but this is simpler.) - if (!Dest.isZeroed()) - CGF.EmitNullInitialization(Dest.getAddress(), atomicType); - - // Build a GEP to refer to the subobject. - Address valueAddr = - CGF.Builder.CreateStructGEP(valueDest.getAddress(), 0, - CharUnits()); - valueDest = AggValueSlot::forAddr(valueAddr, - valueDest.getQualifiers(), - valueDest.isExternallyDestructed(), - valueDest.requiresGCollection(), - valueDest.isPotentiallyAliased(), - AggValueSlot::DoesNotOverlap, - AggValueSlot::IsZeroed); - } - - CGF.EmitAggExpr(E->getSubExpr(), valueDest); - return; - } - - // Otherwise, we're converting an atomic type to a non-atomic type. - // Make an atomic temporary, emit into that, and then copy the value out. - AggValueSlot atomicSlot = - CGF.CreateAggTemp(atomicType, "atomic-to-nonatomic.temp"); - CGF.EmitAggExpr(E->getSubExpr(), atomicSlot); - - Address valueAddr = - Builder.CreateStructGEP(atomicSlot.getAddress(), 0, CharUnits()); - RValue rvalue = RValue::getAggregate(valueAddr, atomicSlot.isVolatile()); - return EmitFinalDestCopy(valueType, rvalue); - } - - case CK_LValueToRValue: - // If we're loading from a volatile type, force the destination - // into existence. - if (E->getSubExpr()->getType().isVolatileQualified()) { - EnsureDest(E->getType()); - return Visit(E->getSubExpr()); - } - - LLVM_FALLTHROUGH; - - case CK_NoOp: - case CK_UserDefinedConversion: - case CK_ConstructorConversion: - assert(CGF.getContext().hasSameUnqualifiedType(E->getSubExpr()->getType(), - E->getType()) && - "Implicit cast types must be compatible"); - Visit(E->getSubExpr()); - break; - - case CK_LValueBitCast: - llvm_unreachable("should not be emitting lvalue bitcast as rvalue"); - - case CK_Dependent: - case CK_BitCast: - case CK_ArrayToPointerDecay: - case CK_FunctionToPointerDecay: - case CK_NullToPointer: - case CK_NullToMemberPointer: - case CK_BaseToDerivedMemberPointer: - case CK_DerivedToBaseMemberPointer: - case CK_MemberPointerToBoolean: - case CK_ReinterpretMemberPointer: - case CK_IntegralToPointer: - case CK_PointerToIntegral: - case CK_PointerToBoolean: - case CK_ToVoid: - case CK_VectorSplat: - case CK_IntegralCast: - case CK_BooleanToSignedIntegral: - case CK_IntegralToBoolean: - case CK_IntegralToFloating: - case CK_FloatingToIntegral: - case CK_FloatingToBoolean: - case CK_FloatingCast: - case CK_CPointerToObjCPointerCast: - case CK_BlockPointerToObjCPointerCast: - case CK_AnyPointerToBlockPointerCast: - case CK_ObjCObjectLValueCast: - case CK_FloatingRealToComplex: - case CK_FloatingComplexToReal: - case CK_FloatingComplexToBoolean: - case CK_FloatingComplexCast: - case CK_FloatingComplexToIntegralComplex: - case CK_IntegralRealToComplex: - case CK_IntegralComplexToReal: - case CK_IntegralComplexToBoolean: - case CK_IntegralComplexCast: - case CK_IntegralComplexToFloatingComplex: - case CK_ARCProduceObject: - case CK_ARCConsumeObject: - case CK_ARCReclaimReturnedObject: - case CK_ARCExtendBlockObject: - case CK_CopyAndAutoreleaseBlockObject: - case CK_BuiltinFnToFnPtr: - case CK_ZeroToOCLOpaqueType: - case CK_AddressSpaceConversion: - case CK_IntToOCLSampler: - case CK_FixedPointCast: - case CK_FixedPointToBoolean: - llvm_unreachable("cast kind invalid for aggregate types"); - } -} - -void AggExprEmitter::VisitCallExpr(const CallExpr *E) { - if (E->getCallReturnType(CGF.getContext())->isReferenceType()) { - EmitAggLoadOfLValue(E); - return; - } - - withReturnValueSlot(E, [&](ReturnValueSlot Slot) { - return CGF.EmitCallExpr(E, Slot); - }); -} - -void AggExprEmitter::VisitObjCMessageExpr(ObjCMessageExpr *E) { - withReturnValueSlot(E, [&](ReturnValueSlot Slot) { - return CGF.EmitObjCMessageExpr(E, Slot); - }); -} - -void AggExprEmitter::VisitBinComma(const BinaryOperator *E) { - CGF.EmitIgnoredExpr(E->getLHS()); - Visit(E->getRHS()); -} - -void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) { - CodeGenFunction::StmtExprEvaluation eval(CGF); - CGF.EmitCompoundStmt(*E->getSubStmt(), true, Dest); -} - -enum CompareKind { - CK_Less, - CK_Greater, - CK_Equal, -}; - -static llvm::Value *EmitCompare(CGBuilderTy &Builder, CodeGenFunction &CGF, - const BinaryOperator *E, llvm::Value *LHS, - llvm::Value *RHS, CompareKind Kind, - const char *NameSuffix = "") { - QualType ArgTy = E->getLHS()->getType(); - if (const ComplexType *CT = ArgTy->getAs<ComplexType>()) - ArgTy = CT->getElementType(); - - if (const auto *MPT = ArgTy->getAs<MemberPointerType>()) { - assert(Kind == CK_Equal && - "member pointers may only be compared for equality"); - return CGF.CGM.getCXXABI().EmitMemberPointerComparison( - CGF, LHS, RHS, MPT, /*IsInequality*/ false); - } - - // Compute the comparison instructions for the specified comparison kind. - struct CmpInstInfo { - const char *Name; - llvm::CmpInst::Predicate FCmp; - llvm::CmpInst::Predicate SCmp; - llvm::CmpInst::Predicate UCmp; - }; - CmpInstInfo InstInfo = [&]() -> CmpInstInfo { - using FI = llvm::FCmpInst; - using II = llvm::ICmpInst; - switch (Kind) { - case CK_Less: - return {"cmp.lt", FI::FCMP_OLT, II::ICMP_SLT, II::ICMP_ULT}; - case CK_Greater: - return {"cmp.gt", FI::FCMP_OGT, II::ICMP_SGT, II::ICMP_UGT}; - case CK_Equal: - return {"cmp.eq", FI::FCMP_OEQ, II::ICMP_EQ, II::ICMP_EQ}; - } - llvm_unreachable("Unrecognised CompareKind enum"); - }(); - - if (ArgTy->hasFloatingRepresentation()) - return Builder.CreateFCmp(InstInfo.FCmp, LHS, RHS, - llvm::Twine(InstInfo.Name) + NameSuffix); - if (ArgTy->isIntegralOrEnumerationType() || ArgTy->isPointerType()) { - auto Inst = - ArgTy->hasSignedIntegerRepresentation() ? InstInfo.SCmp : InstInfo.UCmp; - return Builder.CreateICmp(Inst, LHS, RHS, - llvm::Twine(InstInfo.Name) + NameSuffix); - } - - llvm_unreachable("unsupported aggregate binary expression should have " - "already been handled"); -} - -void AggExprEmitter::VisitBinCmp(const BinaryOperator *E) { - using llvm::BasicBlock; - using llvm::PHINode; - using llvm::Value; - assert(CGF.getContext().hasSameType(E->getLHS()->getType(), - E->getRHS()->getType())); - const ComparisonCategoryInfo &CmpInfo = - CGF.getContext().CompCategories.getInfoForType(E->getType()); - assert(CmpInfo.Record->isTriviallyCopyable() && - "cannot copy non-trivially copyable aggregate"); - - QualType ArgTy = E->getLHS()->getType(); - - // TODO: Handle comparing these types. - if (ArgTy->isVectorType()) - return CGF.ErrorUnsupported( - E, "aggregate three-way comparison with vector arguments"); - if (!ArgTy->isIntegralOrEnumerationType() && !ArgTy->isRealFloatingType() && - !ArgTy->isNullPtrType() && !ArgTy->isPointerType() && - !ArgTy->isMemberPointerType() && !ArgTy->isAnyComplexType()) { - return CGF.ErrorUnsupported(E, "aggregate three-way comparison"); - } - bool IsComplex = ArgTy->isAnyComplexType(); - - // Evaluate the operands to the expression and extract their values. - auto EmitOperand = [&](Expr *E) -> std::pair<Value *, Value *> { - RValue RV = CGF.EmitAnyExpr(E); - if (RV.isScalar()) - return {RV.getScalarVal(), nullptr}; - if (RV.isAggregate()) - return {RV.getAggregatePointer(), nullptr}; - assert(RV.isComplex()); - return RV.getComplexVal(); - }; - auto LHSValues = EmitOperand(E->getLHS()), - RHSValues = EmitOperand(E->getRHS()); - - auto EmitCmp = [&](CompareKind K) { - Value *Cmp = EmitCompare(Builder, CGF, E, LHSValues.first, RHSValues.first, - K, IsComplex ? ".r" : ""); - if (!IsComplex) - return Cmp; - assert(K == CompareKind::CK_Equal); - Value *CmpImag = EmitCompare(Builder, CGF, E, LHSValues.second, - RHSValues.second, K, ".i"); - return Builder.CreateAnd(Cmp, CmpImag, "and.eq"); - }; - auto EmitCmpRes = [&](const ComparisonCategoryInfo::ValueInfo *VInfo) { - return Builder.getInt(VInfo->getIntValue()); - }; - - Value *Select; - if (ArgTy->isNullPtrType()) { - Select = EmitCmpRes(CmpInfo.getEqualOrEquiv()); - } else if (CmpInfo.isEquality()) { - Select = Builder.CreateSelect( - EmitCmp(CK_Equal), EmitCmpRes(CmpInfo.getEqualOrEquiv()), - EmitCmpRes(CmpInfo.getNonequalOrNonequiv()), "sel.eq"); - } else if (!CmpInfo.isPartial()) { - Value *SelectOne = - Builder.CreateSelect(EmitCmp(CK_Less), EmitCmpRes(CmpInfo.getLess()), - EmitCmpRes(CmpInfo.getGreater()), "sel.lt"); - Select = Builder.CreateSelect(EmitCmp(CK_Equal), - EmitCmpRes(CmpInfo.getEqualOrEquiv()), - SelectOne, "sel.eq"); - } else { - Value *SelectEq = Builder.CreateSelect( - EmitCmp(CK_Equal), EmitCmpRes(CmpInfo.getEqualOrEquiv()), - EmitCmpRes(CmpInfo.getUnordered()), "sel.eq"); - Value *SelectGT = Builder.CreateSelect(EmitCmp(CK_Greater), - EmitCmpRes(CmpInfo.getGreater()), - SelectEq, "sel.gt"); - Select = Builder.CreateSelect( - EmitCmp(CK_Less), EmitCmpRes(CmpInfo.getLess()), SelectGT, "sel.lt"); - } - // Create the return value in the destination slot. - EnsureDest(E->getType()); - LValue DestLV = CGF.MakeAddrLValue(Dest.getAddress(), E->getType()); - - // Emit the address of the first (and only) field in the comparison category - // type, and initialize it from the constant integer value selected above. - LValue FieldLV = CGF.EmitLValueForFieldInitialization( - DestLV, *CmpInfo.Record->field_begin()); - CGF.EmitStoreThroughLValue(RValue::get(Select), FieldLV, /*IsInit*/ true); - - // All done! The result is in the Dest slot. -} - -void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) { - if (E->getOpcode() == BO_PtrMemD || E->getOpcode() == BO_PtrMemI) - VisitPointerToDataMemberBinaryOperator(E); - else - CGF.ErrorUnsupported(E, "aggregate binary expression"); -} - -void AggExprEmitter::VisitPointerToDataMemberBinaryOperator( - const BinaryOperator *E) { - LValue LV = CGF.EmitPointerToDataMemberBinaryExpr(E); - EmitFinalDestCopy(E->getType(), LV); -} - -/// Is the value of the given expression possibly a reference to or -/// into a __block variable? -static bool isBlockVarRef(const Expr *E) { - // Make sure we look through parens. - E = E->IgnoreParens(); - - // Check for a direct reference to a __block variable. - if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { - const VarDecl *var = dyn_cast<VarDecl>(DRE->getDecl()); - return (var && var->hasAttr<BlocksAttr>()); - } - - // More complicated stuff. - - // Binary operators. - if (const BinaryOperator *op = dyn_cast<BinaryOperator>(E)) { - // For an assignment or pointer-to-member operation, just care - // about the LHS. - if (op->isAssignmentOp() || op->isPtrMemOp()) - return isBlockVarRef(op->getLHS()); - - // For a comma, just care about the RHS. - if (op->getOpcode() == BO_Comma) - return isBlockVarRef(op->getRHS()); - - // FIXME: pointer arithmetic? - return false; - - // Check both sides of a conditional operator. - } else if (const AbstractConditionalOperator *op - = dyn_cast<AbstractConditionalOperator>(E)) { - return isBlockVarRef(op->getTrueExpr()) - || isBlockVarRef(op->getFalseExpr()); - - // OVEs are required to support BinaryConditionalOperators. - } else if (const OpaqueValueExpr *op - = dyn_cast<OpaqueValueExpr>(E)) { - if (const Expr *src = op->getSourceExpr()) - return isBlockVarRef(src); - - // Casts are necessary to get things like (*(int*)&var) = foo(). - // We don't really care about the kind of cast here, except - // we don't want to look through l2r casts, because it's okay - // to get the *value* in a __block variable. - } else if (const CastExpr *cast = dyn_cast<CastExpr>(E)) { - if (cast->getCastKind() == CK_LValueToRValue) - return false; - return isBlockVarRef(cast->getSubExpr()); - - // Handle unary operators. Again, just aggressively look through - // it, ignoring the operation. - } else if (const UnaryOperator *uop = dyn_cast<UnaryOperator>(E)) { - return isBlockVarRef(uop->getSubExpr()); - - // Look into the base of a field access. - } else if (const MemberExpr *mem = dyn_cast<MemberExpr>(E)) { - return isBlockVarRef(mem->getBase()); - - // Look into the base of a subscript. - } else if (const ArraySubscriptExpr *sub = dyn_cast<ArraySubscriptExpr>(E)) { - return isBlockVarRef(sub->getBase()); - } - - return false; -} - -void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { - // For an assignment to work, the value on the right has - // to be compatible with the value on the left. - assert(CGF.getContext().hasSameUnqualifiedType(E->getLHS()->getType(), - E->getRHS()->getType()) - && "Invalid assignment"); - - // If the LHS might be a __block variable, and the RHS can - // potentially cause a block copy, we need to evaluate the RHS first - // so that the assignment goes the right place. - // This is pretty semantically fragile. - if (isBlockVarRef(E->getLHS()) && - E->getRHS()->HasSideEffects(CGF.getContext())) { - // Ensure that we have a destination, and evaluate the RHS into that. - EnsureDest(E->getRHS()->getType()); - Visit(E->getRHS()); - - // Now emit the LHS and copy into it. - LValue LHS = CGF.EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store); - - // That copy is an atomic copy if the LHS is atomic. - if (LHS.getType()->isAtomicType() || - CGF.LValueIsSuitableForInlineAtomic(LHS)) { - CGF.EmitAtomicStore(Dest.asRValue(), LHS, /*isInit*/ false); - return; - } - - EmitCopy(E->getLHS()->getType(), - AggValueSlot::forLValue(LHS, AggValueSlot::IsDestructed, - needsGC(E->getLHS()->getType()), - AggValueSlot::IsAliased, - AggValueSlot::MayOverlap), - Dest); - return; - } - - LValue LHS = CGF.EmitLValue(E->getLHS()); - - // If we have an atomic type, evaluate into the destination and then - // do an atomic copy. - if (LHS.getType()->isAtomicType() || - CGF.LValueIsSuitableForInlineAtomic(LHS)) { - EnsureDest(E->getRHS()->getType()); - Visit(E->getRHS()); - CGF.EmitAtomicStore(Dest.asRValue(), LHS, /*isInit*/ false); - return; - } - - // Codegen the RHS so that it stores directly into the LHS. - AggValueSlot LHSSlot = - AggValueSlot::forLValue(LHS, AggValueSlot::IsDestructed, - needsGC(E->getLHS()->getType()), - AggValueSlot::IsAliased, - AggValueSlot::MayOverlap); - // A non-volatile aggregate destination might have volatile member. - if (!LHSSlot.isVolatile() && - CGF.hasVolatileMember(E->getLHS()->getType())) - LHSSlot.setVolatile(true); - - CGF.EmitAggExpr(E->getRHS(), LHSSlot); - - // Copy into the destination if the assignment isn't ignored. - EmitFinalDestCopy(E->getType(), LHS); -} - -void AggExprEmitter:: -VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { - llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true"); - llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false"); - llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end"); - - // Bind the common expression if necessary. - CodeGenFunction::OpaqueValueMapping binding(CGF, E); - - CodeGenFunction::ConditionalEvaluation eval(CGF); - CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock, - CGF.getProfileCount(E)); - - // Save whether the destination's lifetime is externally managed. - bool isExternallyDestructed = Dest.isExternallyDestructed(); - - eval.begin(CGF); - CGF.EmitBlock(LHSBlock); - CGF.incrementProfileCounter(E); - Visit(E->getTrueExpr()); - eval.end(CGF); - - assert(CGF.HaveInsertPoint() && "expression evaluation ended with no IP!"); - CGF.Builder.CreateBr(ContBlock); - - // If the result of an agg expression is unused, then the emission - // of the LHS might need to create a destination slot. That's fine - // with us, and we can safely emit the RHS into the same slot, but - // we shouldn't claim that it's already being destructed. - Dest.setExternallyDestructed(isExternallyDestructed); - - eval.begin(CGF); - CGF.EmitBlock(RHSBlock); - Visit(E->getFalseExpr()); - eval.end(CGF); - - CGF.EmitBlock(ContBlock); -} - -void AggExprEmitter::VisitChooseExpr(const ChooseExpr *CE) { - Visit(CE->getChosenSubExpr()); -} - -void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) { - Address ArgValue = Address::invalid(); - Address ArgPtr = CGF.EmitVAArg(VE, ArgValue); - - // If EmitVAArg fails, emit an error. - if (!ArgPtr.isValid()) { - CGF.ErrorUnsupported(VE, "aggregate va_arg expression"); - return; - } - - EmitFinalDestCopy(VE->getType(), CGF.MakeAddrLValue(ArgPtr, VE->getType())); -} - -void AggExprEmitter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { - // Ensure that we have a slot, but if we already do, remember - // whether it was externally destructed. - bool wasExternallyDestructed = Dest.isExternallyDestructed(); - EnsureDest(E->getType()); - - // We're going to push a destructor if there isn't already one. - Dest.setExternallyDestructed(); - - Visit(E->getSubExpr()); - - // Push that destructor we promised. - if (!wasExternallyDestructed) - CGF.EmitCXXTemporary(E->getTemporary(), E->getType(), Dest.getAddress()); -} - -void -AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *E) { - AggValueSlot Slot = EnsureSlot(E->getType()); - CGF.EmitCXXConstructExpr(E, Slot); -} - -void AggExprEmitter::VisitCXXInheritedCtorInitExpr( - const CXXInheritedCtorInitExpr *E) { - AggValueSlot Slot = EnsureSlot(E->getType()); - CGF.EmitInheritedCXXConstructorCall( - E->getConstructor(), E->constructsVBase(), Slot.getAddress(), - E->inheritedFromVBase(), E); -} - -void -AggExprEmitter::VisitLambdaExpr(LambdaExpr *E) { - AggValueSlot Slot = EnsureSlot(E->getType()); - CGF.EmitLambdaExpr(E, Slot); -} - -void AggExprEmitter::VisitExprWithCleanups(ExprWithCleanups *E) { - CGF.enterFullExpression(E); - CodeGenFunction::RunCleanupsScope cleanups(CGF); - Visit(E->getSubExpr()); -} - -void AggExprEmitter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { - QualType T = E->getType(); - AggValueSlot Slot = EnsureSlot(T); - EmitNullInitializationToLValue(CGF.MakeAddrLValue(Slot.getAddress(), T)); -} - -void AggExprEmitter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { - QualType T = E->getType(); - AggValueSlot Slot = EnsureSlot(T); - EmitNullInitializationToLValue(CGF.MakeAddrLValue(Slot.getAddress(), T)); -} - -/// isSimpleZero - If emitting this value will obviously just cause a store of -/// zero to memory, return true. This can return false if uncertain, so it just -/// handles simple cases. -static bool isSimpleZero(const Expr *E, CodeGenFunction &CGF) { - E = E->IgnoreParens(); - - // 0 - if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(E)) - return IL->getValue() == 0; - // +0.0 - if (const FloatingLiteral *FL = dyn_cast<FloatingLiteral>(E)) - return FL->getValue().isPosZero(); - // int() - if ((isa<ImplicitValueInitExpr>(E) || isa<CXXScalarValueInitExpr>(E)) && - CGF.getTypes().isZeroInitializable(E->getType())) - return true; - // (int*)0 - Null pointer expressions. - if (const CastExpr *ICE = dyn_cast<CastExpr>(E)) - return ICE->getCastKind() == CK_NullToPointer && - CGF.getTypes().isPointerZeroInitializable(E->getType()); - // '\0' - if (const CharacterLiteral *CL = dyn_cast<CharacterLiteral>(E)) - return CL->getValue() == 0; - - // Otherwise, hard case: conservatively return false. - return false; -} - - -void -AggExprEmitter::EmitInitializationToLValue(Expr *E, LValue LV) { - QualType type = LV.getType(); - // FIXME: Ignore result? - // FIXME: Are initializers affected by volatile? - if (Dest.isZeroed() && isSimpleZero(E, CGF)) { - // Storing "i32 0" to a zero'd memory location is a noop. - return; - } else if (isa<ImplicitValueInitExpr>(E) || isa<CXXScalarValueInitExpr>(E)) { - return EmitNullInitializationToLValue(LV); - } else if (isa<NoInitExpr>(E)) { - // Do nothing. - return; - } else if (type->isReferenceType()) { - RValue RV = CGF.EmitReferenceBindingToExpr(E); - return CGF.EmitStoreThroughLValue(RV, LV); - } - - switch (CGF.getEvaluationKind(type)) { - case TEK_Complex: - CGF.EmitComplexExprIntoLValue(E, LV, /*isInit*/ true); - return; - case TEK_Aggregate: - CGF.EmitAggExpr(E, AggValueSlot::forLValue(LV, - AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - AggValueSlot::MayOverlap, - Dest.isZeroed())); - return; - case TEK_Scalar: - if (LV.isSimple()) { - CGF.EmitScalarInit(E, /*D=*/nullptr, LV, /*Captured=*/false); - } else { - CGF.EmitStoreThroughLValue(RValue::get(CGF.EmitScalarExpr(E)), LV); - } - return; - } - llvm_unreachable("bad evaluation kind"); -} - -void AggExprEmitter::EmitNullInitializationToLValue(LValue lv) { - QualType type = lv.getType(); - - // If the destination slot is already zeroed out before the aggregate is - // copied into it, we don't have to emit any zeros here. - if (Dest.isZeroed() && CGF.getTypes().isZeroInitializable(type)) - return; - - if (CGF.hasScalarEvaluationKind(type)) { - // For non-aggregates, we can store the appropriate null constant. - llvm::Value *null = CGF.CGM.EmitNullConstant(type); - // Note that the following is not equivalent to - // EmitStoreThroughBitfieldLValue for ARC types. - if (lv.isBitField()) { - CGF.EmitStoreThroughBitfieldLValue(RValue::get(null), lv); - } else { - assert(lv.isSimple()); - CGF.EmitStoreOfScalar(null, lv, /* isInitialization */ true); - } - } else { - // There's a potential optimization opportunity in combining - // memsets; that would be easy for arrays, but relatively - // difficult for structures with the current code. - CGF.EmitNullInitialization(lv.getAddress(), lv.getType()); - } -} - -void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { -#if 0 - // FIXME: Assess perf here? Figure out what cases are worth optimizing here - // (Length of globals? Chunks of zeroed-out space?). - // - // If we can, prefer a copy from a global; this is a lot less code for long - // globals, and it's easier for the current optimizers to analyze. - if (llvm::Constant* C = CGF.CGM.EmitConstantExpr(E, E->getType(), &CGF)) { - llvm::GlobalVariable* GV = - new llvm::GlobalVariable(CGF.CGM.getModule(), C->getType(), true, - llvm::GlobalValue::InternalLinkage, C, ""); - EmitFinalDestCopy(E->getType(), CGF.MakeAddrLValue(GV, E->getType())); - return; - } -#endif - if (E->hadArrayRangeDesignator()) - CGF.ErrorUnsupported(E, "GNU array range designator extension"); - - if (E->isTransparent()) - return Visit(E->getInit(0)); - - AggValueSlot Dest = EnsureSlot(E->getType()); - - LValue DestLV = CGF.MakeAddrLValue(Dest.getAddress(), E->getType()); - - // Handle initialization of an array. - if (E->getType()->isArrayType()) { - auto AType = cast<llvm::ArrayType>(Dest.getAddress().getElementType()); - EmitArrayInit(Dest.getAddress(), AType, E->getType(), E); - return; - } - - assert(E->getType()->isRecordType() && "Only support structs/unions here!"); - - // Do struct initialization; this code just sets each individual member - // to the approprate value. This makes bitfield support automatic; - // the disadvantage is that the generated code is more difficult for - // the optimizer, especially with bitfields. - unsigned NumInitElements = E->getNumInits(); - RecordDecl *record = E->getType()->castAs<RecordType>()->getDecl(); - - // We'll need to enter cleanup scopes in case any of the element - // initializers throws an exception. - SmallVector<EHScopeStack::stable_iterator, 16> cleanups; - llvm::Instruction *cleanupDominator = nullptr; - - unsigned curInitIndex = 0; - - // Emit initialization of base classes. - if (auto *CXXRD = dyn_cast<CXXRecordDecl>(record)) { - assert(E->getNumInits() >= CXXRD->getNumBases() && - "missing initializer for base class"); - for (auto &Base : CXXRD->bases()) { - assert(!Base.isVirtual() && "should not see vbases here"); - auto *BaseRD = Base.getType()->getAsCXXRecordDecl(); - Address V = CGF.GetAddressOfDirectBaseInCompleteClass( - Dest.getAddress(), CXXRD, BaseRD, - /*isBaseVirtual*/ false); - AggValueSlot AggSlot = AggValueSlot::forAddr( - V, Qualifiers(), - AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - CGF.overlapForBaseInit(CXXRD, BaseRD, Base.isVirtual())); - CGF.EmitAggExpr(E->getInit(curInitIndex++), AggSlot); - - if (QualType::DestructionKind dtorKind = - Base.getType().isDestructedType()) { - CGF.pushDestroy(dtorKind, V, Base.getType()); - cleanups.push_back(CGF.EHStack.stable_begin()); - } - } - } - - // Prepare a 'this' for CXXDefaultInitExprs. - CodeGenFunction::FieldConstructionScope FCS(CGF, Dest.getAddress()); - - if (record->isUnion()) { - // Only initialize one field of a union. The field itself is - // specified by the initializer list. - if (!E->getInitializedFieldInUnion()) { - // Empty union; we have nothing to do. - -#ifndef NDEBUG - // Make sure that it's really an empty and not a failure of - // semantic analysis. - for (const auto *Field : record->fields()) - assert(Field->isUnnamedBitfield() && "Only unnamed bitfields allowed"); -#endif - return; - } - - // FIXME: volatility - FieldDecl *Field = E->getInitializedFieldInUnion(); - - LValue FieldLoc = CGF.EmitLValueForFieldInitialization(DestLV, Field); - if (NumInitElements) { - // Store the initializer into the field - EmitInitializationToLValue(E->getInit(0), FieldLoc); - } else { - // Default-initialize to null. - EmitNullInitializationToLValue(FieldLoc); - } - - return; - } - - // Here we iterate over the fields; this makes it simpler to both - // default-initialize fields and skip over unnamed fields. - for (const auto *field : record->fields()) { - // We're done once we hit the flexible array member. - if (field->getType()->isIncompleteArrayType()) - break; - - // Always skip anonymous bitfields. - if (field->isUnnamedBitfield()) - continue; - - // We're done if we reach the end of the explicit initializers, we - // have a zeroed object, and the rest of the fields are - // zero-initializable. - if (curInitIndex == NumInitElements && Dest.isZeroed() && - CGF.getTypes().isZeroInitializable(E->getType())) - break; - - - LValue LV = CGF.EmitLValueForFieldInitialization(DestLV, field); - // We never generate write-barries for initialized fields. - LV.setNonGC(true); - - if (curInitIndex < NumInitElements) { - // Store the initializer into the field. - EmitInitializationToLValue(E->getInit(curInitIndex++), LV); - } else { - // We're out of initializers; default-initialize to null - EmitNullInitializationToLValue(LV); - } - - // Push a destructor if necessary. - // FIXME: if we have an array of structures, all explicitly - // initialized, we can end up pushing a linear number of cleanups. - bool pushedCleanup = false; - if (QualType::DestructionKind dtorKind - = field->getType().isDestructedType()) { - assert(LV.isSimple()); - if (CGF.needsEHCleanup(dtorKind)) { - if (!cleanupDominator) - cleanupDominator = CGF.Builder.CreateAlignedLoad( - CGF.Int8Ty, - llvm::Constant::getNullValue(CGF.Int8PtrTy), - CharUnits::One()); // placeholder - - CGF.pushDestroy(EHCleanup, LV.getAddress(), field->getType(), - CGF.getDestroyer(dtorKind), false); - cleanups.push_back(CGF.EHStack.stable_begin()); - pushedCleanup = true; - } - } - - // If the GEP didn't get used because of a dead zero init or something - // else, clean it up for -O0 builds and general tidiness. - if (!pushedCleanup && LV.isSimple()) - if (llvm::GetElementPtrInst *GEP = - dyn_cast<llvm::GetElementPtrInst>(LV.getPointer())) - if (GEP->use_empty()) - GEP->eraseFromParent(); - } - - // Deactivate all the partial cleanups in reverse order, which - // generally means popping them. - for (unsigned i = cleanups.size(); i != 0; --i) - CGF.DeactivateCleanupBlock(cleanups[i-1], cleanupDominator); - - // Destroy the placeholder if we made one. - if (cleanupDominator) - cleanupDominator->eraseFromParent(); -} - -void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E, - llvm::Value *outerBegin) { - // Emit the common subexpression. - CodeGenFunction::OpaqueValueMapping binding(CGF, E->getCommonExpr()); - - Address destPtr = EnsureSlot(E->getType()).getAddress(); - uint64_t numElements = E->getArraySize().getZExtValue(); - - if (!numElements) - return; - - // destPtr is an array*. Construct an elementType* by drilling down a level. - llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); - llvm::Value *indices[] = {zero, zero}; - llvm::Value *begin = Builder.CreateInBoundsGEP(destPtr.getPointer(), indices, - "arrayinit.begin"); - - // Prepare to special-case multidimensional array initialization: we avoid - // emitting multiple destructor loops in that case. - if (!outerBegin) - outerBegin = begin; - ArrayInitLoopExpr *InnerLoop = dyn_cast<ArrayInitLoopExpr>(E->getSubExpr()); - - QualType elementType = - CGF.getContext().getAsArrayType(E->getType())->getElementType(); - CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType); - CharUnits elementAlign = - destPtr.getAlignment().alignmentOfArrayElement(elementSize); - - llvm::BasicBlock *entryBB = Builder.GetInsertBlock(); - llvm::BasicBlock *bodyBB = CGF.createBasicBlock("arrayinit.body"); - - // Jump into the body. - CGF.EmitBlock(bodyBB); - llvm::PHINode *index = - Builder.CreatePHI(zero->getType(), 2, "arrayinit.index"); - index->addIncoming(zero, entryBB); - llvm::Value *element = Builder.CreateInBoundsGEP(begin, index); - - // Prepare for a cleanup. - QualType::DestructionKind dtorKind = elementType.isDestructedType(); - EHScopeStack::stable_iterator cleanup; - if (CGF.needsEHCleanup(dtorKind) && !InnerLoop) { - if (outerBegin->getType() != element->getType()) - outerBegin = Builder.CreateBitCast(outerBegin, element->getType()); - CGF.pushRegularPartialArrayCleanup(outerBegin, element, elementType, - elementAlign, - CGF.getDestroyer(dtorKind)); - cleanup = CGF.EHStack.stable_begin(); - } else { - dtorKind = QualType::DK_none; - } - - // Emit the actual filler expression. - { - // Temporaries created in an array initialization loop are destroyed - // at the end of each iteration. - CodeGenFunction::RunCleanupsScope CleanupsScope(CGF); - CodeGenFunction::ArrayInitLoopExprScope Scope(CGF, index); - LValue elementLV = - CGF.MakeAddrLValue(Address(element, elementAlign), elementType); - - if (InnerLoop) { - // If the subexpression is an ArrayInitLoopExpr, share its cleanup. - auto elementSlot = AggValueSlot::forLValue( - elementLV, AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - AggValueSlot::DoesNotOverlap); - AggExprEmitter(CGF, elementSlot, false) - .VisitArrayInitLoopExpr(InnerLoop, outerBegin); - } else - EmitInitializationToLValue(E->getSubExpr(), elementLV); - } - - // Move on to the next element. - llvm::Value *nextIndex = Builder.CreateNUWAdd( - index, llvm::ConstantInt::get(CGF.SizeTy, 1), "arrayinit.next"); - index->addIncoming(nextIndex, Builder.GetInsertBlock()); - - // Leave the loop if we're done. - llvm::Value *done = Builder.CreateICmpEQ( - nextIndex, llvm::ConstantInt::get(CGF.SizeTy, numElements), - "arrayinit.done"); - llvm::BasicBlock *endBB = CGF.createBasicBlock("arrayinit.end"); - Builder.CreateCondBr(done, endBB, bodyBB); - - CGF.EmitBlock(endBB); - - // Leave the partial-array cleanup if we entered one. - if (dtorKind) - CGF.DeactivateCleanupBlock(cleanup, index); -} - -void AggExprEmitter::VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) { - AggValueSlot Dest = EnsureSlot(E->getType()); - - LValue DestLV = CGF.MakeAddrLValue(Dest.getAddress(), E->getType()); - EmitInitializationToLValue(E->getBase(), DestLV); - VisitInitListExpr(E->getUpdater()); -} - -//===----------------------------------------------------------------------===// -// Entry Points into this File -//===----------------------------------------------------------------------===// - -/// GetNumNonZeroBytesInInit - Get an approximate count of the number of -/// non-zero bytes that will be stored when outputting the initializer for the -/// specified initializer expression. -static CharUnits GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) { - E = E->IgnoreParens(); - - // 0 and 0.0 won't require any non-zero stores! - if (isSimpleZero(E, CGF)) return CharUnits::Zero(); - - // If this is an initlist expr, sum up the size of sizes of the (present) - // elements. If this is something weird, assume the whole thing is non-zero. - const InitListExpr *ILE = dyn_cast<InitListExpr>(E); - while (ILE && ILE->isTransparent()) - ILE = dyn_cast<InitListExpr>(ILE->getInit(0)); - if (!ILE || !CGF.getTypes().isZeroInitializable(ILE->getType())) - return CGF.getContext().getTypeSizeInChars(E->getType()); - - // InitListExprs for structs have to be handled carefully. If there are - // reference members, we need to consider the size of the reference, not the - // referencee. InitListExprs for unions and arrays can't have references. - if (const RecordType *RT = E->getType()->getAs<RecordType>()) { - if (!RT->isUnionType()) { - RecordDecl *SD = E->getType()->getAs<RecordType>()->getDecl(); - CharUnits NumNonZeroBytes = CharUnits::Zero(); - - unsigned ILEElement = 0; - if (auto *CXXRD = dyn_cast<CXXRecordDecl>(SD)) - while (ILEElement != CXXRD->getNumBases()) - NumNonZeroBytes += - GetNumNonZeroBytesInInit(ILE->getInit(ILEElement++), CGF); - for (const auto *Field : SD->fields()) { - // We're done once we hit the flexible array member or run out of - // InitListExpr elements. - if (Field->getType()->isIncompleteArrayType() || - ILEElement == ILE->getNumInits()) - break; - if (Field->isUnnamedBitfield()) - continue; - - const Expr *E = ILE->getInit(ILEElement++); - - // Reference values are always non-null and have the width of a pointer. - if (Field->getType()->isReferenceType()) - NumNonZeroBytes += CGF.getContext().toCharUnitsFromBits( - CGF.getTarget().getPointerWidth(0)); - else - NumNonZeroBytes += GetNumNonZeroBytesInInit(E, CGF); - } - - return NumNonZeroBytes; - } - } - - - CharUnits NumNonZeroBytes = CharUnits::Zero(); - for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i) - NumNonZeroBytes += GetNumNonZeroBytesInInit(ILE->getInit(i), CGF); - return NumNonZeroBytes; -} - -/// CheckAggExprForMemSetUse - If the initializer is large and has a lot of -/// zeros in it, emit a memset and avoid storing the individual zeros. -/// -static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E, - CodeGenFunction &CGF) { - // If the slot is already known to be zeroed, nothing to do. Don't mess with - // volatile stores. - if (Slot.isZeroed() || Slot.isVolatile() || !Slot.getAddress().isValid()) - return; - - // C++ objects with a user-declared constructor don't need zero'ing. - if (CGF.getLangOpts().CPlusPlus) - if (const RecordType *RT = CGF.getContext() - .getBaseElementType(E->getType())->getAs<RecordType>()) { - const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - if (RD->hasUserDeclaredConstructor()) - return; - } - - // If the type is 16-bytes or smaller, prefer individual stores over memset. - CharUnits Size = Slot.getPreferredSize(CGF.getContext(), E->getType()); - if (Size <= CharUnits::fromQuantity(16)) - return; - - // Check to see if over 3/4 of the initializer are known to be zero. If so, - // we prefer to emit memset + individual stores for the rest. - CharUnits NumNonZeroBytes = GetNumNonZeroBytesInInit(E, CGF); - if (NumNonZeroBytes*4 > Size) - return; - - // Okay, it seems like a good idea to use an initial memset, emit the call. - llvm::Constant *SizeVal = CGF.Builder.getInt64(Size.getQuantity()); - - Address Loc = Slot.getAddress(); - Loc = CGF.Builder.CreateElementBitCast(Loc, CGF.Int8Ty); - CGF.Builder.CreateMemSet(Loc, CGF.Builder.getInt8(0), SizeVal, false); - - // Tell the AggExprEmitter that the slot is known zero. - Slot.setZeroed(); -} - - - - -/// EmitAggExpr - Emit the computation of the specified expression of aggregate -/// type. The result is computed into DestPtr. Note that if DestPtr is null, -/// the value of the aggregate expression is not needed. If VolatileDest is -/// true, DestPtr cannot be 0. -void CodeGenFunction::EmitAggExpr(const Expr *E, AggValueSlot Slot) { - assert(E && hasAggregateEvaluationKind(E->getType()) && - "Invalid aggregate expression to emit"); - assert((Slot.getAddress().isValid() || Slot.isIgnored()) && - "slot has bits but no address"); - - // Optimize the slot if possible. - CheckAggExprForMemSetUse(Slot, E, *this); - - AggExprEmitter(*this, Slot, Slot.isIgnored()).Visit(const_cast<Expr*>(E)); -} - -LValue CodeGenFunction::EmitAggExprToLValue(const Expr *E) { - assert(hasAggregateEvaluationKind(E->getType()) && "Invalid argument!"); - Address Temp = CreateMemTemp(E->getType()); - LValue LV = MakeAddrLValue(Temp, E->getType()); - EmitAggExpr(E, AggValueSlot::forLValue(LV, AggValueSlot::IsNotDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - AggValueSlot::DoesNotOverlap)); - return LV; -} - -AggValueSlot::Overlap_t CodeGenFunction::overlapForBaseInit( - const CXXRecordDecl *RD, const CXXRecordDecl *BaseRD, bool IsVirtual) { - // Virtual bases are initialized first, in address order, so there's never - // any overlap during their initialization. - // - // FIXME: Under P0840, this is no longer true: the tail padding of a vbase - // of a field could be reused by a vbase of a containing class. - if (IsVirtual) - return AggValueSlot::DoesNotOverlap; - - // If the base class is laid out entirely within the nvsize of the derived - // class, its tail padding cannot yet be initialized, so we can issue - // stores at the full width of the base class. - const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); - if (Layout.getBaseClassOffset(BaseRD) + - getContext().getASTRecordLayout(BaseRD).getSize() <= - Layout.getNonVirtualSize()) - return AggValueSlot::DoesNotOverlap; - - // The tail padding may contain values we need to preserve. - return AggValueSlot::MayOverlap; -} - -void CodeGenFunction::EmitAggregateCopy(LValue Dest, LValue Src, QualType Ty, - AggValueSlot::Overlap_t MayOverlap, - bool isVolatile) { - assert(!Ty->isAnyComplexType() && "Shouldn't happen for complex"); - - Address DestPtr = Dest.getAddress(); - Address SrcPtr = Src.getAddress(); - - if (getLangOpts().CPlusPlus) { - if (const RecordType *RT = Ty->getAs<RecordType>()) { - CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl()); - assert((Record->hasTrivialCopyConstructor() || - Record->hasTrivialCopyAssignment() || - Record->hasTrivialMoveConstructor() || - Record->hasTrivialMoveAssignment() || - Record->isUnion()) && - "Trying to aggregate-copy a type without a trivial copy/move " - "constructor or assignment operator"); - // Ignore empty classes in C++. - if (Record->isEmpty()) - return; - } - } - - // Aggregate assignment turns into llvm.memcpy. This is almost valid per - // C99 6.5.16.1p3, which states "If the value being stored in an object is - // read from another object that overlaps in anyway the storage of the first - // object, then the overlap shall be exact and the two objects shall have - // qualified or unqualified versions of a compatible type." - // - // memcpy is not defined if the source and destination pointers are exactly - // equal, but other compilers do this optimization, and almost every memcpy - // implementation handles this case safely. If there is a libc that does not - // safely handle this, we can add a target hook. - - // Get data size info for this aggregate. Don't copy the tail padding if this - // might be a potentially-overlapping subobject, since the tail padding might - // be occupied by a different object. Otherwise, copying it is fine. - std::pair<CharUnits, CharUnits> TypeInfo; - if (MayOverlap) - TypeInfo = getContext().getTypeInfoDataSizeInChars(Ty); - else - TypeInfo = getContext().getTypeInfoInChars(Ty); - - llvm::Value *SizeVal = nullptr; - if (TypeInfo.first.isZero()) { - // But note that getTypeInfo returns 0 for a VLA. - if (auto *VAT = dyn_cast_or_null<VariableArrayType>( - getContext().getAsArrayType(Ty))) { - QualType BaseEltTy; - SizeVal = emitArrayLength(VAT, BaseEltTy, DestPtr); - TypeInfo = getContext().getTypeInfoInChars(BaseEltTy); - assert(!TypeInfo.first.isZero()); - SizeVal = Builder.CreateNUWMul( - SizeVal, - llvm::ConstantInt::get(SizeTy, TypeInfo.first.getQuantity())); - } - } - if (!SizeVal) { - SizeVal = llvm::ConstantInt::get(SizeTy, TypeInfo.first.getQuantity()); - } - - // FIXME: If we have a volatile struct, the optimizer can remove what might - // appear to be `extra' memory ops: - // - // volatile struct { int i; } a, b; - // - // int main() { - // a = b; - // a = b; - // } - // - // we need to use a different call here. We use isVolatile to indicate when - // either the source or the destination is volatile. - - DestPtr = Builder.CreateElementBitCast(DestPtr, Int8Ty); - SrcPtr = Builder.CreateElementBitCast(SrcPtr, Int8Ty); - - // Don't do any of the memmove_collectable tests if GC isn't set. - if (CGM.getLangOpts().getGC() == LangOptions::NonGC) { - // fall through - } else if (const RecordType *RecordTy = Ty->getAs<RecordType>()) { - RecordDecl *Record = RecordTy->getDecl(); - if (Record->hasObjectMember()) { - CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr, - SizeVal); - return; - } - } else if (Ty->isArrayType()) { - QualType BaseType = getContext().getBaseElementType(Ty); - if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) { - if (RecordTy->getDecl()->hasObjectMember()) { - CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr, - SizeVal); - return; - } - } - } - - auto Inst = Builder.CreateMemCpy(DestPtr, SrcPtr, SizeVal, isVolatile); - - // Determine the metadata to describe the position of any padding in this - // memcpy, as well as the TBAA tags for the members of the struct, in case - // the optimizer wishes to expand it in to scalar memory operations. - if (llvm::MDNode *TBAAStructTag = CGM.getTBAAStructInfo(Ty)) - Inst->setMetadata(llvm::LLVMContext::MD_tbaa_struct, TBAAStructTag); - - if (CGM.getCodeGenOpts().NewStructPathTBAA) { - TBAAAccessInfo TBAAInfo = CGM.mergeTBAAInfoForMemoryTransfer( - Dest.getTBAAInfo(), Src.getTBAAInfo()); - CGM.DecorateInstructionWithTBAA(Inst, TBAAInfo); - } -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp deleted file mode 100644 index 884ce96859c..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp +++ /dev/null @@ -1,2273 +0,0 @@ -//===--- CGExprCXX.cpp - Emit LLVM Code for C++ expressions ---------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code dealing with code generation of C++ expressions -// -//===----------------------------------------------------------------------===// - -#include "CodeGenFunction.h" -#include "CGCUDARuntime.h" -#include "CGCXXABI.h" -#include "CGDebugInfo.h" -#include "CGObjCRuntime.h" -#include "ConstantEmitter.h" -#include "clang/Basic/CodeGenOptions.h" -#include "clang/CodeGen/CGFunctionInfo.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/Intrinsics.h" - -using namespace clang; -using namespace CodeGen; - -namespace { -struct MemberCallInfo { - RequiredArgs ReqArgs; - // Number of prefix arguments for the call. Ignores the `this` pointer. - unsigned PrefixSize; -}; -} - -static MemberCallInfo -commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, const CXXMethodDecl *MD, - llvm::Value *This, llvm::Value *ImplicitParam, - QualType ImplicitParamTy, const CallExpr *CE, - CallArgList &Args, CallArgList *RtlArgs) { - assert(CE == nullptr || isa<CXXMemberCallExpr>(CE) || - isa<CXXOperatorCallExpr>(CE)); - assert(MD->isInstance() && - "Trying to emit a member or operator call expr on a static method!"); - ASTContext &C = CGF.getContext(); - - // Push the this ptr. - const CXXRecordDecl *RD = - CGF.CGM.getCXXABI().getThisArgumentTypeForMethod(MD); - Args.add(RValue::get(This), - RD ? C.getPointerType(C.getTypeDeclType(RD)) : C.VoidPtrTy); - - // If there is an implicit parameter (e.g. VTT), emit it. - if (ImplicitParam) { - Args.add(RValue::get(ImplicitParam), ImplicitParamTy); - } - - const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); - RequiredArgs required = RequiredArgs::forPrototypePlus(FPT, Args.size(), MD); - unsigned PrefixSize = Args.size() - 1; - - // And the rest of the call args. - if (RtlArgs) { - // Special case: if the caller emitted the arguments right-to-left already - // (prior to emitting the *this argument), we're done. This happens for - // assignment operators. - Args.addFrom(*RtlArgs); - } else if (CE) { - // Special case: skip first argument of CXXOperatorCall (it is "this"). - unsigned ArgsToSkip = isa<CXXOperatorCallExpr>(CE) ? 1 : 0; - CGF.EmitCallArgs(Args, FPT, drop_begin(CE->arguments(), ArgsToSkip), - CE->getDirectCallee()); - } else { - assert( - FPT->getNumParams() == 0 && - "No CallExpr specified for function with non-zero number of arguments"); - } - return {required, PrefixSize}; -} - -RValue CodeGenFunction::EmitCXXMemberOrOperatorCall( - const CXXMethodDecl *MD, const CGCallee &Callee, - ReturnValueSlot ReturnValue, - llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy, - const CallExpr *CE, CallArgList *RtlArgs) { - const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); - CallArgList Args; - MemberCallInfo CallInfo = commonEmitCXXMemberOrOperatorCall( - *this, MD, This, ImplicitParam, ImplicitParamTy, CE, Args, RtlArgs); - auto &FnInfo = CGM.getTypes().arrangeCXXMethodCall( - Args, FPT, CallInfo.ReqArgs, CallInfo.PrefixSize); - return EmitCall(FnInfo, Callee, ReturnValue, Args, nullptr, - CE ? CE->getExprLoc() : SourceLocation()); -} - -RValue CodeGenFunction::EmitCXXDestructorCall( - const CXXDestructorDecl *DD, const CGCallee &Callee, llvm::Value *This, - llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *CE, - StructorType Type) { - CallArgList Args; - commonEmitCXXMemberOrOperatorCall(*this, DD, This, ImplicitParam, - ImplicitParamTy, CE, Args, nullptr); - return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(DD, Type), - Callee, ReturnValueSlot(), Args); -} - -RValue CodeGenFunction::EmitCXXPseudoDestructorExpr( - const CXXPseudoDestructorExpr *E) { - QualType DestroyedType = E->getDestroyedType(); - if (DestroyedType.hasStrongOrWeakObjCLifetime()) { - // Automatic Reference Counting: - // If the pseudo-expression names a retainable object with weak or - // strong lifetime, the object shall be released. - Expr *BaseExpr = E->getBase(); - Address BaseValue = Address::invalid(); - Qualifiers BaseQuals; - - // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar. - if (E->isArrow()) { - BaseValue = EmitPointerWithAlignment(BaseExpr); - const PointerType *PTy = BaseExpr->getType()->getAs<PointerType>(); - BaseQuals = PTy->getPointeeType().getQualifiers(); - } else { - LValue BaseLV = EmitLValue(BaseExpr); - BaseValue = BaseLV.getAddress(); - QualType BaseTy = BaseExpr->getType(); - BaseQuals = BaseTy.getQualifiers(); - } - - switch (DestroyedType.getObjCLifetime()) { - case Qualifiers::OCL_None: - case Qualifiers::OCL_ExplicitNone: - case Qualifiers::OCL_Autoreleasing: - break; - - case Qualifiers::OCL_Strong: - EmitARCRelease(Builder.CreateLoad(BaseValue, - DestroyedType.isVolatileQualified()), - ARCPreciseLifetime); - break; - - case Qualifiers::OCL_Weak: - EmitARCDestroyWeak(BaseValue); - break; - } - } else { - // C++ [expr.pseudo]p1: - // The result shall only be used as the operand for the function call - // operator (), and the result of such a call has type void. The only - // effect is the evaluation of the postfix-expression before the dot or - // arrow. - EmitIgnoredExpr(E->getBase()); - } - - return RValue::get(nullptr); -} - -static CXXRecordDecl *getCXXRecord(const Expr *E) { - QualType T = E->getType(); - if (const PointerType *PTy = T->getAs<PointerType>()) - T = PTy->getPointeeType(); - const RecordType *Ty = T->castAs<RecordType>(); - return cast<CXXRecordDecl>(Ty->getDecl()); -} - -// Note: This function also emit constructor calls to support a MSVC -// extensions allowing explicit constructor function call. -RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, - ReturnValueSlot ReturnValue) { - const Expr *callee = CE->getCallee()->IgnoreParens(); - - if (isa<BinaryOperator>(callee)) - return EmitCXXMemberPointerCallExpr(CE, ReturnValue); - - const MemberExpr *ME = cast<MemberExpr>(callee); - const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl()); - - if (MD->isStatic()) { - // The method is static, emit it as we would a regular call. - CGCallee callee = - CGCallee::forDirect(CGM.GetAddrOfFunction(MD), GlobalDecl(MD)); - return EmitCall(getContext().getPointerType(MD->getType()), callee, CE, - ReturnValue); - } - - bool HasQualifier = ME->hasQualifier(); - NestedNameSpecifier *Qualifier = HasQualifier ? ME->getQualifier() : nullptr; - bool IsArrow = ME->isArrow(); - const Expr *Base = ME->getBase(); - - return EmitCXXMemberOrOperatorMemberCallExpr( - CE, MD, ReturnValue, HasQualifier, Qualifier, IsArrow, Base); -} - -RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( - const CallExpr *CE, const CXXMethodDecl *MD, ReturnValueSlot ReturnValue, - bool HasQualifier, NestedNameSpecifier *Qualifier, bool IsArrow, - const Expr *Base) { - assert(isa<CXXMemberCallExpr>(CE) || isa<CXXOperatorCallExpr>(CE)); - - // Compute the object pointer. - bool CanUseVirtualCall = MD->isVirtual() && !HasQualifier; - - const CXXMethodDecl *DevirtualizedMethod = nullptr; - if (CanUseVirtualCall && - MD->getDevirtualizedMethod(Base, getLangOpts().AppleKext)) { - const CXXRecordDecl *BestDynamicDecl = Base->getBestDynamicClassType(); - DevirtualizedMethod = MD->getCorrespondingMethodInClass(BestDynamicDecl); - assert(DevirtualizedMethod); - const CXXRecordDecl *DevirtualizedClass = DevirtualizedMethod->getParent(); - const Expr *Inner = Base->ignoreParenBaseCasts(); - if (DevirtualizedMethod->getReturnType().getCanonicalType() != - MD->getReturnType().getCanonicalType()) - // If the return types are not the same, this might be a case where more - // code needs to run to compensate for it. For example, the derived - // method might return a type that inherits form from the return - // type of MD and has a prefix. - // For now we just avoid devirtualizing these covariant cases. - DevirtualizedMethod = nullptr; - else if (getCXXRecord(Inner) == DevirtualizedClass) - // If the class of the Inner expression is where the dynamic method - // is defined, build the this pointer from it. - Base = Inner; - else if (getCXXRecord(Base) != DevirtualizedClass) { - // If the method is defined in a class that is not the best dynamic - // one or the one of the full expression, we would have to build - // a derived-to-base cast to compute the correct this pointer, but - // we don't have support for that yet, so do a virtual call. - DevirtualizedMethod = nullptr; - } - } - - // C++17 demands that we evaluate the RHS of a (possibly-compound) assignment - // operator before the LHS. - CallArgList RtlArgStorage; - CallArgList *RtlArgs = nullptr; - if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(CE)) { - if (OCE->isAssignmentOp()) { - RtlArgs = &RtlArgStorage; - EmitCallArgs(*RtlArgs, MD->getType()->castAs<FunctionProtoType>(), - drop_begin(CE->arguments(), 1), CE->getDirectCallee(), - /*ParamsToSkip*/0, EvaluationOrder::ForceRightToLeft); - } - } - - LValue This; - if (IsArrow) { - LValueBaseInfo BaseInfo; - TBAAAccessInfo TBAAInfo; - Address ThisValue = EmitPointerWithAlignment(Base, &BaseInfo, &TBAAInfo); - This = MakeAddrLValue(ThisValue, Base->getType(), BaseInfo, TBAAInfo); - } else { - This = EmitLValue(Base); - } - - - if (MD->isTrivial() || (MD->isDefaulted() && MD->getParent()->isUnion())) { - if (isa<CXXDestructorDecl>(MD)) return RValue::get(nullptr); - if (isa<CXXConstructorDecl>(MD) && - cast<CXXConstructorDecl>(MD)->isDefaultConstructor()) - return RValue::get(nullptr); - - if (!MD->getParent()->mayInsertExtraPadding()) { - if (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()) { - // We don't like to generate the trivial copy/move assignment operator - // when it isn't necessary; just produce the proper effect here. - LValue RHS = isa<CXXOperatorCallExpr>(CE) - ? MakeNaturalAlignAddrLValue( - (*RtlArgs)[0].getRValue(*this).getScalarVal(), - (*(CE->arg_begin() + 1))->getType()) - : EmitLValue(*CE->arg_begin()); - EmitAggregateAssign(This, RHS, CE->getType()); - return RValue::get(This.getPointer()); - } - - if (isa<CXXConstructorDecl>(MD) && - cast<CXXConstructorDecl>(MD)->isCopyOrMoveConstructor()) { - // Trivial move and copy ctor are the same. - assert(CE->getNumArgs() == 1 && "unexpected argcount for trivial ctor"); - const Expr *Arg = *CE->arg_begin(); - LValue RHS = EmitLValue(Arg); - LValue Dest = MakeAddrLValue(This.getAddress(), Arg->getType()); - // This is the MSVC p->Ctor::Ctor(...) extension. We assume that's - // constructing a new complete object of type Ctor. - EmitAggregateCopy(Dest, RHS, Arg->getType(), - AggValueSlot::DoesNotOverlap); - return RValue::get(This.getPointer()); - } - llvm_unreachable("unknown trivial member function"); - } - } - - // Compute the function type we're calling. - const CXXMethodDecl *CalleeDecl = - DevirtualizedMethod ? DevirtualizedMethod : MD; - const CGFunctionInfo *FInfo = nullptr; - if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(CalleeDecl)) - FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration( - Dtor, StructorType::Complete); - else if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(CalleeDecl)) - FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration( - Ctor, StructorType::Complete); - else - FInfo = &CGM.getTypes().arrangeCXXMethodDeclaration(CalleeDecl); - - llvm::FunctionType *Ty = CGM.getTypes().GetFunctionType(*FInfo); - - // C++11 [class.mfct.non-static]p2: - // If a non-static member function of a class X is called for an object that - // is not of type X, or of a type derived from X, the behavior is undefined. - SourceLocation CallLoc; - ASTContext &C = getContext(); - if (CE) - CallLoc = CE->getExprLoc(); - - SanitizerSet SkippedChecks; - if (const auto *CMCE = dyn_cast<CXXMemberCallExpr>(CE)) { - auto *IOA = CMCE->getImplicitObjectArgument(); - bool IsImplicitObjectCXXThis = IsWrappedCXXThis(IOA); - if (IsImplicitObjectCXXThis) - SkippedChecks.set(SanitizerKind::Alignment, true); - if (IsImplicitObjectCXXThis || isa<DeclRefExpr>(IOA)) - SkippedChecks.set(SanitizerKind::Null, true); - } - EmitTypeCheck( - isa<CXXConstructorDecl>(CalleeDecl) ? CodeGenFunction::TCK_ConstructorCall - : CodeGenFunction::TCK_MemberCall, - CallLoc, This.getPointer(), C.getRecordType(CalleeDecl->getParent()), - /*Alignment=*/CharUnits::Zero(), SkippedChecks); - - // FIXME: Uses of 'MD' past this point need to be audited. We may need to use - // 'CalleeDecl' instead. - - // C++ [class.virtual]p12: - // Explicit qualification with the scope operator (5.1) suppresses the - // virtual call mechanism. - // - // We also don't emit a virtual call if the base expression has a record type - // because then we know what the type is. - bool UseVirtualCall = CanUseVirtualCall && !DevirtualizedMethod; - - if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) { - assert(CE->arg_begin() == CE->arg_end() && - "Destructor shouldn't have explicit parameters"); - assert(ReturnValue.isNull() && "Destructor shouldn't have return value"); - if (UseVirtualCall) { - CGM.getCXXABI().EmitVirtualDestructorCall( - *this, Dtor, Dtor_Complete, This.getAddress(), - cast<CXXMemberCallExpr>(CE)); - } else { - CGCallee Callee; - if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier) - Callee = BuildAppleKextVirtualCall(MD, Qualifier, Ty); - else if (!DevirtualizedMethod) - Callee = CGCallee::forDirect( - CGM.getAddrOfCXXStructor(Dtor, StructorType::Complete, FInfo, Ty), - GlobalDecl(Dtor, Dtor_Complete)); - else { - const CXXDestructorDecl *DDtor = - cast<CXXDestructorDecl>(DevirtualizedMethod); - Callee = CGCallee::forDirect( - CGM.GetAddrOfFunction(GlobalDecl(DDtor, Dtor_Complete), Ty), - GlobalDecl(DDtor, Dtor_Complete)); - } - EmitCXXMemberOrOperatorCall( - CalleeDecl, Callee, ReturnValue, This.getPointer(), - /*ImplicitParam=*/nullptr, QualType(), CE, nullptr); - } - return RValue::get(nullptr); - } - - CGCallee Callee; - if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) { - Callee = CGCallee::forDirect( - CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty), - GlobalDecl(Ctor, Ctor_Complete)); - } else if (UseVirtualCall) { - Callee = CGCallee::forVirtual(CE, MD, This.getAddress(), Ty); - } else { - if (SanOpts.has(SanitizerKind::CFINVCall) && - MD->getParent()->isDynamicClass()) { - llvm::Value *VTable; - const CXXRecordDecl *RD; - std::tie(VTable, RD) = - CGM.getCXXABI().LoadVTablePtr(*this, This.getAddress(), - MD->getParent()); - EmitVTablePtrCheckForCall(RD, VTable, CFITCK_NVCall, CE->getBeginLoc()); - } - - if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier) - Callee = BuildAppleKextVirtualCall(MD, Qualifier, Ty); - else if (!DevirtualizedMethod) - Callee = - CGCallee::forDirect(CGM.GetAddrOfFunction(MD, Ty), GlobalDecl(MD)); - else { - Callee = - CGCallee::forDirect(CGM.GetAddrOfFunction(DevirtualizedMethod, Ty), - GlobalDecl(DevirtualizedMethod)); - } - } - - if (MD->isVirtual()) { - Address NewThisAddr = - CGM.getCXXABI().adjustThisArgumentForVirtualFunctionCall( - *this, CalleeDecl, This.getAddress(), UseVirtualCall); - This.setAddress(NewThisAddr); - } - - return EmitCXXMemberOrOperatorCall( - CalleeDecl, Callee, ReturnValue, This.getPointer(), - /*ImplicitParam=*/nullptr, QualType(), CE, RtlArgs); -} - -RValue -CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, - ReturnValueSlot ReturnValue) { - const BinaryOperator *BO = - cast<BinaryOperator>(E->getCallee()->IgnoreParens()); - const Expr *BaseExpr = BO->getLHS(); - const Expr *MemFnExpr = BO->getRHS(); - - const MemberPointerType *MPT = - MemFnExpr->getType()->castAs<MemberPointerType>(); - - const FunctionProtoType *FPT = - MPT->getPointeeType()->castAs<FunctionProtoType>(); - const CXXRecordDecl *RD = - cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl()); - - // Emit the 'this' pointer. - Address This = Address::invalid(); - if (BO->getOpcode() == BO_PtrMemI) - This = EmitPointerWithAlignment(BaseExpr); - else - This = EmitLValue(BaseExpr).getAddress(); - - EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This.getPointer(), - QualType(MPT->getClass(), 0)); - - // Get the member function pointer. - llvm::Value *MemFnPtr = EmitScalarExpr(MemFnExpr); - - // Ask the ABI to load the callee. Note that This is modified. - llvm::Value *ThisPtrForCall = nullptr; - CGCallee Callee = - CGM.getCXXABI().EmitLoadOfMemberFunctionPointer(*this, BO, This, - ThisPtrForCall, MemFnPtr, MPT); - - CallArgList Args; - - QualType ThisType = - getContext().getPointerType(getContext().getTagDeclType(RD)); - - // Push the this ptr. - Args.add(RValue::get(ThisPtrForCall), ThisType); - - RequiredArgs required = - RequiredArgs::forPrototypePlus(FPT, 1, /*FD=*/nullptr); - - // And the rest of the call args - EmitCallArgs(Args, FPT, E->arguments()); - return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required, - /*PrefixSize=*/0), - Callee, ReturnValue, Args, nullptr, E->getExprLoc()); -} - -RValue -CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, - const CXXMethodDecl *MD, - ReturnValueSlot ReturnValue) { - assert(MD->isInstance() && - "Trying to emit a member call expr on a static method!"); - return EmitCXXMemberOrOperatorMemberCallExpr( - E, MD, ReturnValue, /*HasQualifier=*/false, /*Qualifier=*/nullptr, - /*IsArrow=*/false, E->getArg(0)); -} - -RValue CodeGenFunction::EmitCUDAKernelCallExpr(const CUDAKernelCallExpr *E, - ReturnValueSlot ReturnValue) { - return CGM.getCUDARuntime().EmitCUDAKernelCallExpr(*this, E, ReturnValue); -} - -static void EmitNullBaseClassInitialization(CodeGenFunction &CGF, - Address DestPtr, - const CXXRecordDecl *Base) { - if (Base->isEmpty()) - return; - - DestPtr = CGF.Builder.CreateElementBitCast(DestPtr, CGF.Int8Ty); - - const ASTRecordLayout &Layout = CGF.getContext().getASTRecordLayout(Base); - CharUnits NVSize = Layout.getNonVirtualSize(); - - // We cannot simply zero-initialize the entire base sub-object if vbptrs are - // present, they are initialized by the most derived class before calling the - // constructor. - SmallVector<std::pair<CharUnits, CharUnits>, 1> Stores; - Stores.emplace_back(CharUnits::Zero(), NVSize); - - // Each store is split by the existence of a vbptr. - CharUnits VBPtrWidth = CGF.getPointerSize(); - std::vector<CharUnits> VBPtrOffsets = - CGF.CGM.getCXXABI().getVBPtrOffsets(Base); - for (CharUnits VBPtrOffset : VBPtrOffsets) { - // Stop before we hit any virtual base pointers located in virtual bases. - if (VBPtrOffset >= NVSize) - break; - std::pair<CharUnits, CharUnits> LastStore = Stores.pop_back_val(); - CharUnits LastStoreOffset = LastStore.first; - CharUnits LastStoreSize = LastStore.second; - - CharUnits SplitBeforeOffset = LastStoreOffset; - CharUnits SplitBeforeSize = VBPtrOffset - SplitBeforeOffset; - assert(!SplitBeforeSize.isNegative() && "negative store size!"); - if (!SplitBeforeSize.isZero()) - Stores.emplace_back(SplitBeforeOffset, SplitBeforeSize); - - CharUnits SplitAfterOffset = VBPtrOffset + VBPtrWidth; - CharUnits SplitAfterSize = LastStoreSize - SplitAfterOffset; - assert(!SplitAfterSize.isNegative() && "negative store size!"); - if (!SplitAfterSize.isZero()) - Stores.emplace_back(SplitAfterOffset, SplitAfterSize); - } - - // If the type contains a pointer to data member we can't memset it to zero. - // Instead, create a null constant and copy it to the destination. - // TODO: there are other patterns besides zero that we can usefully memset, - // like -1, which happens to be the pattern used by member-pointers. - // TODO: isZeroInitializable can be over-conservative in the case where a - // virtual base contains a member pointer. - llvm::Constant *NullConstantForBase = CGF.CGM.EmitNullConstantForBase(Base); - if (!NullConstantForBase->isNullValue()) { - llvm::GlobalVariable *NullVariable = new llvm::GlobalVariable( - CGF.CGM.getModule(), NullConstantForBase->getType(), - /*isConstant=*/true, llvm::GlobalVariable::PrivateLinkage, - NullConstantForBase, Twine()); - - CharUnits Align = std::max(Layout.getNonVirtualAlignment(), - DestPtr.getAlignment()); - NullVariable->setAlignment(Align.getQuantity()); - - Address SrcPtr = Address(CGF.EmitCastToVoidPtr(NullVariable), Align); - - // Get and call the appropriate llvm.memcpy overload. - for (std::pair<CharUnits, CharUnits> Store : Stores) { - CharUnits StoreOffset = Store.first; - CharUnits StoreSize = Store.second; - llvm::Value *StoreSizeVal = CGF.CGM.getSize(StoreSize); - CGF.Builder.CreateMemCpy( - CGF.Builder.CreateConstInBoundsByteGEP(DestPtr, StoreOffset), - CGF.Builder.CreateConstInBoundsByteGEP(SrcPtr, StoreOffset), - StoreSizeVal); - } - - // Otherwise, just memset the whole thing to zero. This is legal - // because in LLVM, all default initializers (other than the ones we just - // handled above) are guaranteed to have a bit pattern of all zeros. - } else { - for (std::pair<CharUnits, CharUnits> Store : Stores) { - CharUnits StoreOffset = Store.first; - CharUnits StoreSize = Store.second; - llvm::Value *StoreSizeVal = CGF.CGM.getSize(StoreSize); - CGF.Builder.CreateMemSet( - CGF.Builder.CreateConstInBoundsByteGEP(DestPtr, StoreOffset), - CGF.Builder.getInt8(0), StoreSizeVal); - } - } -} - -void -CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E, - AggValueSlot Dest) { - assert(!Dest.isIgnored() && "Must have a destination!"); - const CXXConstructorDecl *CD = E->getConstructor(); - - // If we require zero initialization before (or instead of) calling the - // constructor, as can be the case with a non-user-provided default - // constructor, emit the zero initialization now, unless destination is - // already zeroed. - if (E->requiresZeroInitialization() && !Dest.isZeroed()) { - switch (E->getConstructionKind()) { - case CXXConstructExpr::CK_Delegating: - case CXXConstructExpr::CK_Complete: - EmitNullInitialization(Dest.getAddress(), E->getType()); - break; - case CXXConstructExpr::CK_VirtualBase: - case CXXConstructExpr::CK_NonVirtualBase: - EmitNullBaseClassInitialization(*this, Dest.getAddress(), - CD->getParent()); - break; - } - } - - // If this is a call to a trivial default constructor, do nothing. - if (CD->isTrivial() && CD->isDefaultConstructor()) - return; - - // Elide the constructor if we're constructing from a temporary. - // The temporary check is required because Sema sets this on NRVO - // returns. - if (getLangOpts().ElideConstructors && E->isElidable()) { - assert(getContext().hasSameUnqualifiedType(E->getType(), - E->getArg(0)->getType())); - if (E->getArg(0)->isTemporaryObject(getContext(), CD->getParent())) { - EmitAggExpr(E->getArg(0), Dest); - return; - } - } - - if (const ArrayType *arrayType - = getContext().getAsArrayType(E->getType())) { - EmitCXXAggrConstructorCall(CD, arrayType, Dest.getAddress(), E, - Dest.isSanitizerChecked()); - } else { - CXXCtorType Type = Ctor_Complete; - bool ForVirtualBase = false; - bool Delegating = false; - - switch (E->getConstructionKind()) { - case CXXConstructExpr::CK_Delegating: - // We should be emitting a constructor; GlobalDecl will assert this - Type = CurGD.getCtorType(); - Delegating = true; - break; - - case CXXConstructExpr::CK_Complete: - Type = Ctor_Complete; - break; - - case CXXConstructExpr::CK_VirtualBase: - ForVirtualBase = true; - LLVM_FALLTHROUGH; - - case CXXConstructExpr::CK_NonVirtualBase: - Type = Ctor_Base; - } - - // Call the constructor. - EmitCXXConstructorCall(CD, Type, ForVirtualBase, Delegating, - Dest.getAddress(), E, Dest.mayOverlap(), - Dest.isSanitizerChecked()); - } -} - -void CodeGenFunction::EmitSynthesizedCXXCopyCtor(Address Dest, Address Src, - const Expr *Exp) { - if (const ExprWithCleanups *E = dyn_cast<ExprWithCleanups>(Exp)) - Exp = E->getSubExpr(); - assert(isa<CXXConstructExpr>(Exp) && - "EmitSynthesizedCXXCopyCtor - unknown copy ctor expr"); - const CXXConstructExpr* E = cast<CXXConstructExpr>(Exp); - const CXXConstructorDecl *CD = E->getConstructor(); - RunCleanupsScope Scope(*this); - - // If we require zero initialization before (or instead of) calling the - // constructor, as can be the case with a non-user-provided default - // constructor, emit the zero initialization now. - // FIXME. Do I still need this for a copy ctor synthesis? - if (E->requiresZeroInitialization()) - EmitNullInitialization(Dest, E->getType()); - - assert(!getContext().getAsConstantArrayType(E->getType()) - && "EmitSynthesizedCXXCopyCtor - Copied-in Array"); - EmitSynthesizedCXXCopyCtorCall(CD, Dest, Src, E); -} - -static CharUnits CalculateCookiePadding(CodeGenFunction &CGF, - const CXXNewExpr *E) { - if (!E->isArray()) - return CharUnits::Zero(); - - // No cookie is required if the operator new[] being used is the - // reserved placement operator new[]. - if (E->getOperatorNew()->isReservedGlobalPlacementOperator()) - return CharUnits::Zero(); - - return CGF.CGM.getCXXABI().GetArrayCookieSize(E); -} - -static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF, - const CXXNewExpr *e, - unsigned minElements, - llvm::Value *&numElements, - llvm::Value *&sizeWithoutCookie) { - QualType type = e->getAllocatedType(); - - if (!e->isArray()) { - CharUnits typeSize = CGF.getContext().getTypeSizeInChars(type); - sizeWithoutCookie - = llvm::ConstantInt::get(CGF.SizeTy, typeSize.getQuantity()); - return sizeWithoutCookie; - } - - // The width of size_t. - unsigned sizeWidth = CGF.SizeTy->getBitWidth(); - - // Figure out the cookie size. - llvm::APInt cookieSize(sizeWidth, - CalculateCookiePadding(CGF, e).getQuantity()); - - // Emit the array size expression. - // We multiply the size of all dimensions for NumElements. - // e.g for 'int[2][3]', ElemType is 'int' and NumElements is 6. - numElements = - ConstantEmitter(CGF).tryEmitAbstract(e->getArraySize(), e->getType()); - if (!numElements) - numElements = CGF.EmitScalarExpr(e->getArraySize()); - assert(isa<llvm::IntegerType>(numElements->getType())); - - // The number of elements can be have an arbitrary integer type; - // essentially, we need to multiply it by a constant factor, add a - // cookie size, and verify that the result is representable as a - // size_t. That's just a gloss, though, and it's wrong in one - // important way: if the count is negative, it's an error even if - // the cookie size would bring the total size >= 0. - bool isSigned - = e->getArraySize()->getType()->isSignedIntegerOrEnumerationType(); - llvm::IntegerType *numElementsType - = cast<llvm::IntegerType>(numElements->getType()); - unsigned numElementsWidth = numElementsType->getBitWidth(); - - // Compute the constant factor. - llvm::APInt arraySizeMultiplier(sizeWidth, 1); - while (const ConstantArrayType *CAT - = CGF.getContext().getAsConstantArrayType(type)) { - type = CAT->getElementType(); - arraySizeMultiplier *= CAT->getSize(); - } - - CharUnits typeSize = CGF.getContext().getTypeSizeInChars(type); - llvm::APInt typeSizeMultiplier(sizeWidth, typeSize.getQuantity()); - typeSizeMultiplier *= arraySizeMultiplier; - - // This will be a size_t. - llvm::Value *size; - - // If someone is doing 'new int[42]' there is no need to do a dynamic check. - // Don't bloat the -O0 code. - if (llvm::ConstantInt *numElementsC = - dyn_cast<llvm::ConstantInt>(numElements)) { - const llvm::APInt &count = numElementsC->getValue(); - - bool hasAnyOverflow = false; - - // If 'count' was a negative number, it's an overflow. - if (isSigned && count.isNegative()) - hasAnyOverflow = true; - - // We want to do all this arithmetic in size_t. If numElements is - // wider than that, check whether it's already too big, and if so, - // overflow. - else if (numElementsWidth > sizeWidth && - numElementsWidth - sizeWidth > count.countLeadingZeros()) - hasAnyOverflow = true; - - // Okay, compute a count at the right width. - llvm::APInt adjustedCount = count.zextOrTrunc(sizeWidth); - - // If there is a brace-initializer, we cannot allocate fewer elements than - // there are initializers. If we do, that's treated like an overflow. - if (adjustedCount.ult(minElements)) - hasAnyOverflow = true; - - // Scale numElements by that. This might overflow, but we don't - // care because it only overflows if allocationSize does, too, and - // if that overflows then we shouldn't use this. - numElements = llvm::ConstantInt::get(CGF.SizeTy, - adjustedCount * arraySizeMultiplier); - - // Compute the size before cookie, and track whether it overflowed. - bool overflow; - llvm::APInt allocationSize - = adjustedCount.umul_ov(typeSizeMultiplier, overflow); - hasAnyOverflow |= overflow; - - // Add in the cookie, and check whether it's overflowed. - if (cookieSize != 0) { - // Save the current size without a cookie. This shouldn't be - // used if there was overflow. - sizeWithoutCookie = llvm::ConstantInt::get(CGF.SizeTy, allocationSize); - - allocationSize = allocationSize.uadd_ov(cookieSize, overflow); - hasAnyOverflow |= overflow; - } - - // On overflow, produce a -1 so operator new will fail. - if (hasAnyOverflow) { - size = llvm::Constant::getAllOnesValue(CGF.SizeTy); - } else { - size = llvm::ConstantInt::get(CGF.SizeTy, allocationSize); - } - - // Otherwise, we might need to use the overflow intrinsics. - } else { - // There are up to five conditions we need to test for: - // 1) if isSigned, we need to check whether numElements is negative; - // 2) if numElementsWidth > sizeWidth, we need to check whether - // numElements is larger than something representable in size_t; - // 3) if minElements > 0, we need to check whether numElements is smaller - // than that. - // 4) we need to compute - // sizeWithoutCookie := numElements * typeSizeMultiplier - // and check whether it overflows; and - // 5) if we need a cookie, we need to compute - // size := sizeWithoutCookie + cookieSize - // and check whether it overflows. - - llvm::Value *hasOverflow = nullptr; - - // If numElementsWidth > sizeWidth, then one way or another, we're - // going to have to do a comparison for (2), and this happens to - // take care of (1), too. - if (numElementsWidth > sizeWidth) { - llvm::APInt threshold(numElementsWidth, 1); - threshold <<= sizeWidth; - - llvm::Value *thresholdV - = llvm::ConstantInt::get(numElementsType, threshold); - - hasOverflow = CGF.Builder.CreateICmpUGE(numElements, thresholdV); - numElements = CGF.Builder.CreateTrunc(numElements, CGF.SizeTy); - - // Otherwise, if we're signed, we want to sext up to size_t. - } else if (isSigned) { - if (numElementsWidth < sizeWidth) - numElements = CGF.Builder.CreateSExt(numElements, CGF.SizeTy); - - // If there's a non-1 type size multiplier, then we can do the - // signedness check at the same time as we do the multiply - // because a negative number times anything will cause an - // unsigned overflow. Otherwise, we have to do it here. But at least - // in this case, we can subsume the >= minElements check. - if (typeSizeMultiplier == 1) - hasOverflow = CGF.Builder.CreateICmpSLT(numElements, - llvm::ConstantInt::get(CGF.SizeTy, minElements)); - - // Otherwise, zext up to size_t if necessary. - } else if (numElementsWidth < sizeWidth) { - numElements = CGF.Builder.CreateZExt(numElements, CGF.SizeTy); - } - - assert(numElements->getType() == CGF.SizeTy); - - if (minElements) { - // Don't allow allocation of fewer elements than we have initializers. - if (!hasOverflow) { - hasOverflow = CGF.Builder.CreateICmpULT(numElements, - llvm::ConstantInt::get(CGF.SizeTy, minElements)); - } else if (numElementsWidth > sizeWidth) { - // The other existing overflow subsumes this check. - // We do an unsigned comparison, since any signed value < -1 is - // taken care of either above or below. - hasOverflow = CGF.Builder.CreateOr(hasOverflow, - CGF.Builder.CreateICmpULT(numElements, - llvm::ConstantInt::get(CGF.SizeTy, minElements))); - } - } - - size = numElements; - - // Multiply by the type size if necessary. This multiplier - // includes all the factors for nested arrays. - // - // This step also causes numElements to be scaled up by the - // nested-array factor if necessary. Overflow on this computation - // can be ignored because the result shouldn't be used if - // allocation fails. - if (typeSizeMultiplier != 1) { - llvm::Value *umul_with_overflow - = CGF.CGM.getIntrinsic(llvm::Intrinsic::umul_with_overflow, CGF.SizeTy); - - llvm::Value *tsmV = - llvm::ConstantInt::get(CGF.SizeTy, typeSizeMultiplier); - llvm::Value *result = - CGF.Builder.CreateCall(umul_with_overflow, {size, tsmV}); - - llvm::Value *overflowed = CGF.Builder.CreateExtractValue(result, 1); - if (hasOverflow) - hasOverflow = CGF.Builder.CreateOr(hasOverflow, overflowed); - else - hasOverflow = overflowed; - - size = CGF.Builder.CreateExtractValue(result, 0); - - // Also scale up numElements by the array size multiplier. - if (arraySizeMultiplier != 1) { - // If the base element type size is 1, then we can re-use the - // multiply we just did. - if (typeSize.isOne()) { - assert(arraySizeMultiplier == typeSizeMultiplier); - numElements = size; - - // Otherwise we need a separate multiply. - } else { - llvm::Value *asmV = - llvm::ConstantInt::get(CGF.SizeTy, arraySizeMultiplier); - numElements = CGF.Builder.CreateMul(numElements, asmV); - } - } - } else { - // numElements doesn't need to be scaled. - assert(arraySizeMultiplier == 1); - } - - // Add in the cookie size if necessary. - if (cookieSize != 0) { - sizeWithoutCookie = size; - - llvm::Value *uadd_with_overflow - = CGF.CGM.getIntrinsic(llvm::Intrinsic::uadd_with_overflow, CGF.SizeTy); - - llvm::Value *cookieSizeV = llvm::ConstantInt::get(CGF.SizeTy, cookieSize); - llvm::Value *result = - CGF.Builder.CreateCall(uadd_with_overflow, {size, cookieSizeV}); - - llvm::Value *overflowed = CGF.Builder.CreateExtractValue(result, 1); - if (hasOverflow) - hasOverflow = CGF.Builder.CreateOr(hasOverflow, overflowed); - else - hasOverflow = overflowed; - - size = CGF.Builder.CreateExtractValue(result, 0); - } - - // If we had any possibility of dynamic overflow, make a select to - // overwrite 'size' with an all-ones value, which should cause - // operator new to throw. - if (hasOverflow) - size = CGF.Builder.CreateSelect(hasOverflow, - llvm::Constant::getAllOnesValue(CGF.SizeTy), - size); - } - - if (cookieSize == 0) - sizeWithoutCookie = size; - else - assert(sizeWithoutCookie && "didn't set sizeWithoutCookie?"); - - return size; -} - -static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const Expr *Init, - QualType AllocType, Address NewPtr, - AggValueSlot::Overlap_t MayOverlap) { - // FIXME: Refactor with EmitExprAsInit. - switch (CGF.getEvaluationKind(AllocType)) { - case TEK_Scalar: - CGF.EmitScalarInit(Init, nullptr, - CGF.MakeAddrLValue(NewPtr, AllocType), false); - return; - case TEK_Complex: - CGF.EmitComplexExprIntoLValue(Init, CGF.MakeAddrLValue(NewPtr, AllocType), - /*isInit*/ true); - return; - case TEK_Aggregate: { - AggValueSlot Slot - = AggValueSlot::forAddr(NewPtr, AllocType.getQualifiers(), - AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - MayOverlap, AggValueSlot::IsNotZeroed, - AggValueSlot::IsSanitizerChecked); - CGF.EmitAggExpr(Init, Slot); - return; - } - } - llvm_unreachable("bad evaluation kind"); -} - -void CodeGenFunction::EmitNewArrayInitializer( - const CXXNewExpr *E, QualType ElementType, llvm::Type *ElementTy, - Address BeginPtr, llvm::Value *NumElements, - llvm::Value *AllocSizeWithoutCookie) { - // If we have a type with trivial initialization and no initializer, - // there's nothing to do. - if (!E->hasInitializer()) - return; - - Address CurPtr = BeginPtr; - - unsigned InitListElements = 0; - - const Expr *Init = E->getInitializer(); - Address EndOfInit = Address::invalid(); - QualType::DestructionKind DtorKind = ElementType.isDestructedType(); - EHScopeStack::stable_iterator Cleanup; - llvm::Instruction *CleanupDominator = nullptr; - - CharUnits ElementSize = getContext().getTypeSizeInChars(ElementType); - CharUnits ElementAlign = - BeginPtr.getAlignment().alignmentOfArrayElement(ElementSize); - - // Attempt to perform zero-initialization using memset. - auto TryMemsetInitialization = [&]() -> bool { - // FIXME: If the type is a pointer-to-data-member under the Itanium ABI, - // we can initialize with a memset to -1. - if (!CGM.getTypes().isZeroInitializable(ElementType)) - return false; - - // Optimization: since zero initialization will just set the memory - // to all zeroes, generate a single memset to do it in one shot. - - // Subtract out the size of any elements we've already initialized. - auto *RemainingSize = AllocSizeWithoutCookie; - if (InitListElements) { - // We know this can't overflow; we check this when doing the allocation. - auto *InitializedSize = llvm::ConstantInt::get( - RemainingSize->getType(), - getContext().getTypeSizeInChars(ElementType).getQuantity() * - InitListElements); - RemainingSize = Builder.CreateSub(RemainingSize, InitializedSize); - } - - // Create the memset. - Builder.CreateMemSet(CurPtr, Builder.getInt8(0), RemainingSize, false); - return true; - }; - - // If the initializer is an initializer list, first do the explicit elements. - if (const InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) { - // Initializing from a (braced) string literal is a special case; the init - // list element does not initialize a (single) array element. - if (ILE->isStringLiteralInit()) { - // Initialize the initial portion of length equal to that of the string - // literal. The allocation must be for at least this much; we emitted a - // check for that earlier. - AggValueSlot Slot = - AggValueSlot::forAddr(CurPtr, ElementType.getQualifiers(), - AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - AggValueSlot::DoesNotOverlap, - AggValueSlot::IsNotZeroed, - AggValueSlot::IsSanitizerChecked); - EmitAggExpr(ILE->getInit(0), Slot); - - // Move past these elements. - InitListElements = - cast<ConstantArrayType>(ILE->getType()->getAsArrayTypeUnsafe()) - ->getSize().getZExtValue(); - CurPtr = - Address(Builder.CreateInBoundsGEP(CurPtr.getPointer(), - Builder.getSize(InitListElements), - "string.init.end"), - CurPtr.getAlignment().alignmentAtOffset(InitListElements * - ElementSize)); - - // Zero out the rest, if any remain. - llvm::ConstantInt *ConstNum = dyn_cast<llvm::ConstantInt>(NumElements); - if (!ConstNum || !ConstNum->equalsInt(InitListElements)) { - bool OK = TryMemsetInitialization(); - (void)OK; - assert(OK && "couldn't memset character type?"); - } - return; - } - - InitListElements = ILE->getNumInits(); - - // If this is a multi-dimensional array new, we will initialize multiple - // elements with each init list element. - QualType AllocType = E->getAllocatedType(); - if (const ConstantArrayType *CAT = dyn_cast_or_null<ConstantArrayType>( - AllocType->getAsArrayTypeUnsafe())) { - ElementTy = ConvertTypeForMem(AllocType); - CurPtr = Builder.CreateElementBitCast(CurPtr, ElementTy); - InitListElements *= getContext().getConstantArrayElementCount(CAT); - } - - // Enter a partial-destruction Cleanup if necessary. - if (needsEHCleanup(DtorKind)) { - // In principle we could tell the Cleanup where we are more - // directly, but the control flow can get so varied here that it - // would actually be quite complex. Therefore we go through an - // alloca. - EndOfInit = CreateTempAlloca(BeginPtr.getType(), getPointerAlign(), - "array.init.end"); - CleanupDominator = Builder.CreateStore(BeginPtr.getPointer(), EndOfInit); - pushIrregularPartialArrayCleanup(BeginPtr.getPointer(), EndOfInit, - ElementType, ElementAlign, - getDestroyer(DtorKind)); - Cleanup = EHStack.stable_begin(); - } - - CharUnits StartAlign = CurPtr.getAlignment(); - for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i) { - // Tell the cleanup that it needs to destroy up to this - // element. TODO: some of these stores can be trivially - // observed to be unnecessary. - if (EndOfInit.isValid()) { - auto FinishedPtr = - Builder.CreateBitCast(CurPtr.getPointer(), BeginPtr.getType()); - Builder.CreateStore(FinishedPtr, EndOfInit); - } - // FIXME: If the last initializer is an incomplete initializer list for - // an array, and we have an array filler, we can fold together the two - // initialization loops. - StoreAnyExprIntoOneUnit(*this, ILE->getInit(i), - ILE->getInit(i)->getType(), CurPtr, - AggValueSlot::DoesNotOverlap); - CurPtr = Address(Builder.CreateInBoundsGEP(CurPtr.getPointer(), - Builder.getSize(1), - "array.exp.next"), - StartAlign.alignmentAtOffset((i + 1) * ElementSize)); - } - - // The remaining elements are filled with the array filler expression. - Init = ILE->getArrayFiller(); - - // Extract the initializer for the individual array elements by pulling - // out the array filler from all the nested initializer lists. This avoids - // generating a nested loop for the initialization. - while (Init && Init->getType()->isConstantArrayType()) { - auto *SubILE = dyn_cast<InitListExpr>(Init); - if (!SubILE) - break; - assert(SubILE->getNumInits() == 0 && "explicit inits in array filler?"); - Init = SubILE->getArrayFiller(); - } - - // Switch back to initializing one base element at a time. - CurPtr = Builder.CreateBitCast(CurPtr, BeginPtr.getType()); - } - - // If all elements have already been initialized, skip any further - // initialization. - llvm::ConstantInt *ConstNum = dyn_cast<llvm::ConstantInt>(NumElements); - if (ConstNum && ConstNum->getZExtValue() <= InitListElements) { - // If there was a Cleanup, deactivate it. - if (CleanupDominator) - DeactivateCleanupBlock(Cleanup, CleanupDominator); - return; - } - - assert(Init && "have trailing elements to initialize but no initializer"); - - // If this is a constructor call, try to optimize it out, and failing that - // emit a single loop to initialize all remaining elements. - if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) { - CXXConstructorDecl *Ctor = CCE->getConstructor(); - if (Ctor->isTrivial()) { - // If new expression did not specify value-initialization, then there - // is no initialization. - if (!CCE->requiresZeroInitialization() || Ctor->getParent()->isEmpty()) - return; - - if (TryMemsetInitialization()) - return; - } - - // Store the new Cleanup position for irregular Cleanups. - // - // FIXME: Share this cleanup with the constructor call emission rather than - // having it create a cleanup of its own. - if (EndOfInit.isValid()) - Builder.CreateStore(CurPtr.getPointer(), EndOfInit); - - // Emit a constructor call loop to initialize the remaining elements. - if (InitListElements) - NumElements = Builder.CreateSub( - NumElements, - llvm::ConstantInt::get(NumElements->getType(), InitListElements)); - EmitCXXAggrConstructorCall(Ctor, NumElements, CurPtr, CCE, - /*NewPointerIsChecked*/true, - CCE->requiresZeroInitialization()); - return; - } - - // If this is value-initialization, we can usually use memset. - ImplicitValueInitExpr IVIE(ElementType); - if (isa<ImplicitValueInitExpr>(Init)) { - if (TryMemsetInitialization()) - return; - - // Switch to an ImplicitValueInitExpr for the element type. This handles - // only one case: multidimensional array new of pointers to members. In - // all other cases, we already have an initializer for the array element. - Init = &IVIE; - } - - // At this point we should have found an initializer for the individual - // elements of the array. - assert(getContext().hasSameUnqualifiedType(ElementType, Init->getType()) && - "got wrong type of element to initialize"); - - // If we have an empty initializer list, we can usually use memset. - if (auto *ILE = dyn_cast<InitListExpr>(Init)) - if (ILE->getNumInits() == 0 && TryMemsetInitialization()) - return; - - // If we have a struct whose every field is value-initialized, we can - // usually use memset. - if (auto *ILE = dyn_cast<InitListExpr>(Init)) { - if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) { - if (RType->getDecl()->isStruct()) { - unsigned NumElements = 0; - if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RType->getDecl())) - NumElements = CXXRD->getNumBases(); - for (auto *Field : RType->getDecl()->fields()) - if (!Field->isUnnamedBitfield()) - ++NumElements; - // FIXME: Recurse into nested InitListExprs. - if (ILE->getNumInits() == NumElements) - for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i) - if (!isa<ImplicitValueInitExpr>(ILE->getInit(i))) - --NumElements; - if (ILE->getNumInits() == NumElements && TryMemsetInitialization()) - return; - } - } - } - - // Create the loop blocks. - llvm::BasicBlock *EntryBB = Builder.GetInsertBlock(); - llvm::BasicBlock *LoopBB = createBasicBlock("new.loop"); - llvm::BasicBlock *ContBB = createBasicBlock("new.loop.end"); - - // Find the end of the array, hoisted out of the loop. - llvm::Value *EndPtr = - Builder.CreateInBoundsGEP(BeginPtr.getPointer(), NumElements, "array.end"); - - // If the number of elements isn't constant, we have to now check if there is - // anything left to initialize. - if (!ConstNum) { - llvm::Value *IsEmpty = - Builder.CreateICmpEQ(CurPtr.getPointer(), EndPtr, "array.isempty"); - Builder.CreateCondBr(IsEmpty, ContBB, LoopBB); - } - - // Enter the loop. - EmitBlock(LoopBB); - - // Set up the current-element phi. - llvm::PHINode *CurPtrPhi = - Builder.CreatePHI(CurPtr.getType(), 2, "array.cur"); - CurPtrPhi->addIncoming(CurPtr.getPointer(), EntryBB); - - CurPtr = Address(CurPtrPhi, ElementAlign); - - // Store the new Cleanup position for irregular Cleanups. - if (EndOfInit.isValid()) - Builder.CreateStore(CurPtr.getPointer(), EndOfInit); - - // Enter a partial-destruction Cleanup if necessary. - if (!CleanupDominator && needsEHCleanup(DtorKind)) { - pushRegularPartialArrayCleanup(BeginPtr.getPointer(), CurPtr.getPointer(), - ElementType, ElementAlign, - getDestroyer(DtorKind)); - Cleanup = EHStack.stable_begin(); - CleanupDominator = Builder.CreateUnreachable(); - } - - // Emit the initializer into this element. - StoreAnyExprIntoOneUnit(*this, Init, Init->getType(), CurPtr, - AggValueSlot::DoesNotOverlap); - - // Leave the Cleanup if we entered one. - if (CleanupDominator) { - DeactivateCleanupBlock(Cleanup, CleanupDominator); - CleanupDominator->eraseFromParent(); - } - - // Advance to the next element by adjusting the pointer type as necessary. - llvm::Value *NextPtr = - Builder.CreateConstInBoundsGEP1_32(ElementTy, CurPtr.getPointer(), 1, - "array.next"); - - // Check whether we've gotten to the end of the array and, if so, - // exit the loop. - llvm::Value *IsEnd = Builder.CreateICmpEQ(NextPtr, EndPtr, "array.atend"); - Builder.CreateCondBr(IsEnd, ContBB, LoopBB); - CurPtrPhi->addIncoming(NextPtr, Builder.GetInsertBlock()); - - EmitBlock(ContBB); -} - -static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E, - QualType ElementType, llvm::Type *ElementTy, - Address NewPtr, llvm::Value *NumElements, - llvm::Value *AllocSizeWithoutCookie) { - ApplyDebugLocation DL(CGF, E); - if (E->isArray()) - CGF.EmitNewArrayInitializer(E, ElementType, ElementTy, NewPtr, NumElements, - AllocSizeWithoutCookie); - else if (const Expr *Init = E->getInitializer()) - StoreAnyExprIntoOneUnit(CGF, Init, E->getAllocatedType(), NewPtr, - AggValueSlot::DoesNotOverlap); -} - -/// Emit a call to an operator new or operator delete function, as implicitly -/// created by new-expressions and delete-expressions. -static RValue EmitNewDeleteCall(CodeGenFunction &CGF, - const FunctionDecl *CalleeDecl, - const FunctionProtoType *CalleeType, - const CallArgList &Args) { - llvm::Instruction *CallOrInvoke; - llvm::Constant *CalleePtr = CGF.CGM.GetAddrOfFunction(CalleeDecl); - CGCallee Callee = CGCallee::forDirect(CalleePtr, GlobalDecl(CalleeDecl)); - RValue RV = - CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall( - Args, CalleeType, /*chainCall=*/false), - Callee, ReturnValueSlot(), Args, &CallOrInvoke); - - /// C++1y [expr.new]p10: - /// [In a new-expression,] an implementation is allowed to omit a call - /// to a replaceable global allocation function. - /// - /// We model such elidable calls with the 'builtin' attribute. - llvm::Function *Fn = dyn_cast<llvm::Function>(CalleePtr); - if (CalleeDecl->isReplaceableGlobalAllocationFunction() && - Fn && Fn->hasFnAttribute(llvm::Attribute::NoBuiltin)) { - // FIXME: Add addAttribute to CallSite. - if (llvm::CallInst *CI = dyn_cast<llvm::CallInst>(CallOrInvoke)) - CI->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::Builtin); - else if (llvm::InvokeInst *II = dyn_cast<llvm::InvokeInst>(CallOrInvoke)) - II->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::Builtin); - else - llvm_unreachable("unexpected kind of call instruction"); - } - - return RV; -} - -RValue CodeGenFunction::EmitBuiltinNewDeleteCall(const FunctionProtoType *Type, - const CallExpr *TheCall, - bool IsDelete) { - CallArgList Args; - EmitCallArgs(Args, Type->getParamTypes(), TheCall->arguments()); - // Find the allocation or deallocation function that we're calling. - ASTContext &Ctx = getContext(); - DeclarationName Name = Ctx.DeclarationNames - .getCXXOperatorName(IsDelete ? OO_Delete : OO_New); - - for (auto *Decl : Ctx.getTranslationUnitDecl()->lookup(Name)) - if (auto *FD = dyn_cast<FunctionDecl>(Decl)) - if (Ctx.hasSameType(FD->getType(), QualType(Type, 0))) - return EmitNewDeleteCall(*this, FD, Type, Args); - llvm_unreachable("predeclared global operator new/delete is missing"); -} - -namespace { -/// The parameters to pass to a usual operator delete. -struct UsualDeleteParams { - bool DestroyingDelete = false; - bool Size = false; - bool Alignment = false; -}; -} - -static UsualDeleteParams getUsualDeleteParams(const FunctionDecl *FD) { - UsualDeleteParams Params; - - const FunctionProtoType *FPT = FD->getType()->castAs<FunctionProtoType>(); - auto AI = FPT->param_type_begin(), AE = FPT->param_type_end(); - - // The first argument is always a void*. - ++AI; - - // The next parameter may be a std::destroying_delete_t. - if (FD->isDestroyingOperatorDelete()) { - Params.DestroyingDelete = true; - assert(AI != AE); - ++AI; - } - - // Figure out what other parameters we should be implicitly passing. - if (AI != AE && (*AI)->isIntegerType()) { - Params.Size = true; - ++AI; - } - - if (AI != AE && (*AI)->isAlignValT()) { - Params.Alignment = true; - ++AI; - } - - assert(AI == AE && "unexpected usual deallocation function parameter"); - return Params; -} - -namespace { - /// A cleanup to call the given 'operator delete' function upon abnormal - /// exit from a new expression. Templated on a traits type that deals with - /// ensuring that the arguments dominate the cleanup if necessary. - template<typename Traits> - class CallDeleteDuringNew final : public EHScopeStack::Cleanup { - /// Type used to hold llvm::Value*s. - typedef typename Traits::ValueTy ValueTy; - /// Type used to hold RValues. - typedef typename Traits::RValueTy RValueTy; - struct PlacementArg { - RValueTy ArgValue; - QualType ArgType; - }; - - unsigned NumPlacementArgs : 31; - unsigned PassAlignmentToPlacementDelete : 1; - const FunctionDecl *OperatorDelete; - ValueTy Ptr; - ValueTy AllocSize; - CharUnits AllocAlign; - - PlacementArg *getPlacementArgs() { - return reinterpret_cast<PlacementArg *>(this + 1); - } - - public: - static size_t getExtraSize(size_t NumPlacementArgs) { - return NumPlacementArgs * sizeof(PlacementArg); - } - - CallDeleteDuringNew(size_t NumPlacementArgs, - const FunctionDecl *OperatorDelete, ValueTy Ptr, - ValueTy AllocSize, bool PassAlignmentToPlacementDelete, - CharUnits AllocAlign) - : NumPlacementArgs(NumPlacementArgs), - PassAlignmentToPlacementDelete(PassAlignmentToPlacementDelete), - OperatorDelete(OperatorDelete), Ptr(Ptr), AllocSize(AllocSize), - AllocAlign(AllocAlign) {} - - void setPlacementArg(unsigned I, RValueTy Arg, QualType Type) { - assert(I < NumPlacementArgs && "index out of range"); - getPlacementArgs()[I] = {Arg, Type}; - } - - void Emit(CodeGenFunction &CGF, Flags flags) override { - const FunctionProtoType *FPT = - OperatorDelete->getType()->getAs<FunctionProtoType>(); - CallArgList DeleteArgs; - - // The first argument is always a void* (or C* for a destroying operator - // delete for class type C). - DeleteArgs.add(Traits::get(CGF, Ptr), FPT->getParamType(0)); - - // Figure out what other parameters we should be implicitly passing. - UsualDeleteParams Params; - if (NumPlacementArgs) { - // A placement deallocation function is implicitly passed an alignment - // if the placement allocation function was, but is never passed a size. - Params.Alignment = PassAlignmentToPlacementDelete; - } else { - // For a non-placement new-expression, 'operator delete' can take a - // size and/or an alignment if it has the right parameters. - Params = getUsualDeleteParams(OperatorDelete); - } - - assert(!Params.DestroyingDelete && - "should not call destroying delete in a new-expression"); - - // The second argument can be a std::size_t (for non-placement delete). - if (Params.Size) - DeleteArgs.add(Traits::get(CGF, AllocSize), - CGF.getContext().getSizeType()); - - // The next (second or third) argument can be a std::align_val_t, which - // is an enum whose underlying type is std::size_t. - // FIXME: Use the right type as the parameter type. Note that in a call - // to operator delete(size_t, ...), we may not have it available. - if (Params.Alignment) - DeleteArgs.add(RValue::get(llvm::ConstantInt::get( - CGF.SizeTy, AllocAlign.getQuantity())), - CGF.getContext().getSizeType()); - - // Pass the rest of the arguments, which must match exactly. - for (unsigned I = 0; I != NumPlacementArgs; ++I) { - auto Arg = getPlacementArgs()[I]; - DeleteArgs.add(Traits::get(CGF, Arg.ArgValue), Arg.ArgType); - } - - // Call 'operator delete'. - EmitNewDeleteCall(CGF, OperatorDelete, FPT, DeleteArgs); - } - }; -} - -/// Enter a cleanup to call 'operator delete' if the initializer in a -/// new-expression throws. -static void EnterNewDeleteCleanup(CodeGenFunction &CGF, - const CXXNewExpr *E, - Address NewPtr, - llvm::Value *AllocSize, - CharUnits AllocAlign, - const CallArgList &NewArgs) { - unsigned NumNonPlacementArgs = E->passAlignment() ? 2 : 1; - - // If we're not inside a conditional branch, then the cleanup will - // dominate and we can do the easier (and more efficient) thing. - if (!CGF.isInConditionalBranch()) { - struct DirectCleanupTraits { - typedef llvm::Value *ValueTy; - typedef RValue RValueTy; - static RValue get(CodeGenFunction &, ValueTy V) { return RValue::get(V); } - static RValue get(CodeGenFunction &, RValueTy V) { return V; } - }; - - typedef CallDeleteDuringNew<DirectCleanupTraits> DirectCleanup; - - DirectCleanup *Cleanup = CGF.EHStack - .pushCleanupWithExtra<DirectCleanup>(EHCleanup, - E->getNumPlacementArgs(), - E->getOperatorDelete(), - NewPtr.getPointer(), - AllocSize, - E->passAlignment(), - AllocAlign); - for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) { - auto &Arg = NewArgs[I + NumNonPlacementArgs]; - Cleanup->setPlacementArg(I, Arg.getRValue(CGF), Arg.Ty); - } - - return; - } - - // Otherwise, we need to save all this stuff. - DominatingValue<RValue>::saved_type SavedNewPtr = - DominatingValue<RValue>::save(CGF, RValue::get(NewPtr.getPointer())); - DominatingValue<RValue>::saved_type SavedAllocSize = - DominatingValue<RValue>::save(CGF, RValue::get(AllocSize)); - - struct ConditionalCleanupTraits { - typedef DominatingValue<RValue>::saved_type ValueTy; - typedef DominatingValue<RValue>::saved_type RValueTy; - static RValue get(CodeGenFunction &CGF, ValueTy V) { - return V.restore(CGF); - } - }; - typedef CallDeleteDuringNew<ConditionalCleanupTraits> ConditionalCleanup; - - ConditionalCleanup *Cleanup = CGF.EHStack - .pushCleanupWithExtra<ConditionalCleanup>(EHCleanup, - E->getNumPlacementArgs(), - E->getOperatorDelete(), - SavedNewPtr, - SavedAllocSize, - E->passAlignment(), - AllocAlign); - for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) { - auto &Arg = NewArgs[I + NumNonPlacementArgs]; - Cleanup->setPlacementArg( - I, DominatingValue<RValue>::save(CGF, Arg.getRValue(CGF)), Arg.Ty); - } - - CGF.initFullExprCleanup(); -} - -llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { - // The element type being allocated. - QualType allocType = getContext().getBaseElementType(E->getAllocatedType()); - - // 1. Build a call to the allocation function. - FunctionDecl *allocator = E->getOperatorNew(); - - // If there is a brace-initializer, cannot allocate fewer elements than inits. - unsigned minElements = 0; - if (E->isArray() && E->hasInitializer()) { - const InitListExpr *ILE = dyn_cast<InitListExpr>(E->getInitializer()); - if (ILE && ILE->isStringLiteralInit()) - minElements = - cast<ConstantArrayType>(ILE->getType()->getAsArrayTypeUnsafe()) - ->getSize().getZExtValue(); - else if (ILE) - minElements = ILE->getNumInits(); - } - - llvm::Value *numElements = nullptr; - llvm::Value *allocSizeWithoutCookie = nullptr; - llvm::Value *allocSize = - EmitCXXNewAllocSize(*this, E, minElements, numElements, - allocSizeWithoutCookie); - CharUnits allocAlign = getContext().getTypeAlignInChars(allocType); - - // Emit the allocation call. If the allocator is a global placement - // operator, just "inline" it directly. - Address allocation = Address::invalid(); - CallArgList allocatorArgs; - if (allocator->isReservedGlobalPlacementOperator()) { - assert(E->getNumPlacementArgs() == 1); - const Expr *arg = *E->placement_arguments().begin(); - - LValueBaseInfo BaseInfo; - allocation = EmitPointerWithAlignment(arg, &BaseInfo); - - // The pointer expression will, in many cases, be an opaque void*. - // In these cases, discard the computed alignment and use the - // formal alignment of the allocated type. - if (BaseInfo.getAlignmentSource() != AlignmentSource::Decl) - allocation = Address(allocation.getPointer(), allocAlign); - - // Set up allocatorArgs for the call to operator delete if it's not - // the reserved global operator. - if (E->getOperatorDelete() && - !E->getOperatorDelete()->isReservedGlobalPlacementOperator()) { - allocatorArgs.add(RValue::get(allocSize), getContext().getSizeType()); - allocatorArgs.add(RValue::get(allocation.getPointer()), arg->getType()); - } - - } else { - const FunctionProtoType *allocatorType = - allocator->getType()->castAs<FunctionProtoType>(); - unsigned ParamsToSkip = 0; - - // The allocation size is the first argument. - QualType sizeType = getContext().getSizeType(); - allocatorArgs.add(RValue::get(allocSize), sizeType); - ++ParamsToSkip; - - if (allocSize != allocSizeWithoutCookie) { - CharUnits cookieAlign = getSizeAlign(); // FIXME: Ask the ABI. - allocAlign = std::max(allocAlign, cookieAlign); - } - - // The allocation alignment may be passed as the second argument. - if (E->passAlignment()) { - QualType AlignValT = sizeType; - if (allocatorType->getNumParams() > 1) { - AlignValT = allocatorType->getParamType(1); - assert(getContext().hasSameUnqualifiedType( - AlignValT->castAs<EnumType>()->getDecl()->getIntegerType(), - sizeType) && - "wrong type for alignment parameter"); - ++ParamsToSkip; - } else { - // Corner case, passing alignment to 'operator new(size_t, ...)'. - assert(allocator->isVariadic() && "can't pass alignment to allocator"); - } - allocatorArgs.add( - RValue::get(llvm::ConstantInt::get(SizeTy, allocAlign.getQuantity())), - AlignValT); - } - - // FIXME: Why do we not pass a CalleeDecl here? - EmitCallArgs(allocatorArgs, allocatorType, E->placement_arguments(), - /*AC*/AbstractCallee(), /*ParamsToSkip*/ParamsToSkip); - - RValue RV = - EmitNewDeleteCall(*this, allocator, allocatorType, allocatorArgs); - - // If this was a call to a global replaceable allocation function that does - // not take an alignment argument, the allocator is known to produce - // storage that's suitably aligned for any object that fits, up to a known - // threshold. Otherwise assume it's suitably aligned for the allocated type. - CharUnits allocationAlign = allocAlign; - if (!E->passAlignment() && - allocator->isReplaceableGlobalAllocationFunction()) { - unsigned AllocatorAlign = llvm::PowerOf2Floor(std::min<uint64_t>( - Target.getNewAlign(), getContext().getTypeSize(allocType))); - allocationAlign = std::max( - allocationAlign, getContext().toCharUnitsFromBits(AllocatorAlign)); - } - - allocation = Address(RV.getScalarVal(), allocationAlign); - } - - // Emit a null check on the allocation result if the allocation - // function is allowed to return null (because it has a non-throwing - // exception spec or is the reserved placement new) and we have an - // interesting initializer will be running sanitizers on the initialization. - bool nullCheck = E->shouldNullCheckAllocation() && - (!allocType.isPODType(getContext()) || E->hasInitializer() || - sanitizePerformTypeCheck()); - - llvm::BasicBlock *nullCheckBB = nullptr; - llvm::BasicBlock *contBB = nullptr; - - // The null-check means that the initializer is conditionally - // evaluated. - ConditionalEvaluation conditional(*this); - - if (nullCheck) { - conditional.begin(*this); - - nullCheckBB = Builder.GetInsertBlock(); - llvm::BasicBlock *notNullBB = createBasicBlock("new.notnull"); - contBB = createBasicBlock("new.cont"); - - llvm::Value *isNull = - Builder.CreateIsNull(allocation.getPointer(), "new.isnull"); - Builder.CreateCondBr(isNull, contBB, notNullBB); - EmitBlock(notNullBB); - } - - // If there's an operator delete, enter a cleanup to call it if an - // exception is thrown. - EHScopeStack::stable_iterator operatorDeleteCleanup; - llvm::Instruction *cleanupDominator = nullptr; - if (E->getOperatorDelete() && - !E->getOperatorDelete()->isReservedGlobalPlacementOperator()) { - EnterNewDeleteCleanup(*this, E, allocation, allocSize, allocAlign, - allocatorArgs); - operatorDeleteCleanup = EHStack.stable_begin(); - cleanupDominator = Builder.CreateUnreachable(); - } - - assert((allocSize == allocSizeWithoutCookie) == - CalculateCookiePadding(*this, E).isZero()); - if (allocSize != allocSizeWithoutCookie) { - assert(E->isArray()); - allocation = CGM.getCXXABI().InitializeArrayCookie(*this, allocation, - numElements, - E, allocType); - } - - llvm::Type *elementTy = ConvertTypeForMem(allocType); - Address result = Builder.CreateElementBitCast(allocation, elementTy); - - // Passing pointer through launder.invariant.group to avoid propagation of - // vptrs information which may be included in previous type. - // To not break LTO with different optimizations levels, we do it regardless - // of optimization level. - if (CGM.getCodeGenOpts().StrictVTablePointers && - allocator->isReservedGlobalPlacementOperator()) - result = Address(Builder.CreateLaunderInvariantGroup(result.getPointer()), - result.getAlignment()); - - // Emit sanitizer checks for pointer value now, so that in the case of an - // array it was checked only once and not at each constructor call. - EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, - E->getAllocatedTypeSourceInfo()->getTypeLoc().getBeginLoc(), - result.getPointer(), allocType); - - EmitNewInitializer(*this, E, allocType, elementTy, result, numElements, - allocSizeWithoutCookie); - if (E->isArray()) { - // NewPtr is a pointer to the base element type. If we're - // allocating an array of arrays, we'll need to cast back to the - // array pointer type. - llvm::Type *resultType = ConvertTypeForMem(E->getType()); - if (result.getType() != resultType) - result = Builder.CreateBitCast(result, resultType); - } - - // Deactivate the 'operator delete' cleanup if we finished - // initialization. - if (operatorDeleteCleanup.isValid()) { - DeactivateCleanupBlock(operatorDeleteCleanup, cleanupDominator); - cleanupDominator->eraseFromParent(); - } - - llvm::Value *resultPtr = result.getPointer(); - if (nullCheck) { - conditional.end(*this); - - llvm::BasicBlock *notNullBB = Builder.GetInsertBlock(); - EmitBlock(contBB); - - llvm::PHINode *PHI = Builder.CreatePHI(resultPtr->getType(), 2); - PHI->addIncoming(resultPtr, notNullBB); - PHI->addIncoming(llvm::Constant::getNullValue(resultPtr->getType()), - nullCheckBB); - - resultPtr = PHI; - } - - return resultPtr; -} - -void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD, - llvm::Value *Ptr, QualType DeleteTy, - llvm::Value *NumElements, - CharUnits CookieSize) { - assert((!NumElements && CookieSize.isZero()) || - DeleteFD->getOverloadedOperator() == OO_Array_Delete); - - const FunctionProtoType *DeleteFTy = - DeleteFD->getType()->getAs<FunctionProtoType>(); - - CallArgList DeleteArgs; - - auto Params = getUsualDeleteParams(DeleteFD); - auto ParamTypeIt = DeleteFTy->param_type_begin(); - - // Pass the pointer itself. - QualType ArgTy = *ParamTypeIt++; - llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy)); - DeleteArgs.add(RValue::get(DeletePtr), ArgTy); - - // Pass the std::destroying_delete tag if present. - if (Params.DestroyingDelete) { - QualType DDTag = *ParamTypeIt++; - // Just pass an 'undef'. We expect the tag type to be an empty struct. - auto *V = llvm::UndefValue::get(getTypes().ConvertType(DDTag)); - DeleteArgs.add(RValue::get(V), DDTag); - } - - // Pass the size if the delete function has a size_t parameter. - if (Params.Size) { - QualType SizeType = *ParamTypeIt++; - CharUnits DeleteTypeSize = getContext().getTypeSizeInChars(DeleteTy); - llvm::Value *Size = llvm::ConstantInt::get(ConvertType(SizeType), - DeleteTypeSize.getQuantity()); - - // For array new, multiply by the number of elements. - if (NumElements) - Size = Builder.CreateMul(Size, NumElements); - - // If there is a cookie, add the cookie size. - if (!CookieSize.isZero()) - Size = Builder.CreateAdd( - Size, llvm::ConstantInt::get(SizeTy, CookieSize.getQuantity())); - - DeleteArgs.add(RValue::get(Size), SizeType); - } - - // Pass the alignment if the delete function has an align_val_t parameter. - if (Params.Alignment) { - QualType AlignValType = *ParamTypeIt++; - CharUnits DeleteTypeAlign = getContext().toCharUnitsFromBits( - getContext().getTypeAlignIfKnown(DeleteTy)); - llvm::Value *Align = llvm::ConstantInt::get(ConvertType(AlignValType), - DeleteTypeAlign.getQuantity()); - DeleteArgs.add(RValue::get(Align), AlignValType); - } - - assert(ParamTypeIt == DeleteFTy->param_type_end() && - "unknown parameter to usual delete function"); - - // Emit the call to delete. - EmitNewDeleteCall(*this, DeleteFD, DeleteFTy, DeleteArgs); -} - -namespace { - /// Calls the given 'operator delete' on a single object. - struct CallObjectDelete final : EHScopeStack::Cleanup { - llvm::Value *Ptr; - const FunctionDecl *OperatorDelete; - QualType ElementType; - - CallObjectDelete(llvm::Value *Ptr, - const FunctionDecl *OperatorDelete, - QualType ElementType) - : Ptr(Ptr), OperatorDelete(OperatorDelete), ElementType(ElementType) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - CGF.EmitDeleteCall(OperatorDelete, Ptr, ElementType); - } - }; -} - -void -CodeGenFunction::pushCallObjectDeleteCleanup(const FunctionDecl *OperatorDelete, - llvm::Value *CompletePtr, - QualType ElementType) { - EHStack.pushCleanup<CallObjectDelete>(NormalAndEHCleanup, CompletePtr, - OperatorDelete, ElementType); -} - -/// Emit the code for deleting a single object with a destroying operator -/// delete. If the element type has a non-virtual destructor, Ptr has already -/// been converted to the type of the parameter of 'operator delete'. Otherwise -/// Ptr points to an object of the static type. -static void EmitDestroyingObjectDelete(CodeGenFunction &CGF, - const CXXDeleteExpr *DE, Address Ptr, - QualType ElementType) { - auto *Dtor = ElementType->getAsCXXRecordDecl()->getDestructor(); - if (Dtor && Dtor->isVirtual()) - CGF.CGM.getCXXABI().emitVirtualObjectDelete(CGF, DE, Ptr, ElementType, - Dtor); - else - CGF.EmitDeleteCall(DE->getOperatorDelete(), Ptr.getPointer(), ElementType); -} - -/// Emit the code for deleting a single object. -static void EmitObjectDelete(CodeGenFunction &CGF, - const CXXDeleteExpr *DE, - Address Ptr, - QualType ElementType) { - // C++11 [expr.delete]p3: - // If the static type of the object to be deleted is different from its - // dynamic type, the static type shall be a base class of the dynamic type - // of the object to be deleted and the static type shall have a virtual - // destructor or the behavior is undefined. - CGF.EmitTypeCheck(CodeGenFunction::TCK_MemberCall, - DE->getExprLoc(), Ptr.getPointer(), - ElementType); - - const FunctionDecl *OperatorDelete = DE->getOperatorDelete(); - assert(!OperatorDelete->isDestroyingOperatorDelete()); - - // Find the destructor for the type, if applicable. If the - // destructor is virtual, we'll just emit the vcall and return. - const CXXDestructorDecl *Dtor = nullptr; - if (const RecordType *RT = ElementType->getAs<RecordType>()) { - CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - if (RD->hasDefinition() && !RD->hasTrivialDestructor()) { - Dtor = RD->getDestructor(); - - if (Dtor->isVirtual()) { - CGF.CGM.getCXXABI().emitVirtualObjectDelete(CGF, DE, Ptr, ElementType, - Dtor); - return; - } - } - } - - // Make sure that we call delete even if the dtor throws. - // This doesn't have to a conditional cleanup because we're going - // to pop it off in a second. - CGF.EHStack.pushCleanup<CallObjectDelete>(NormalAndEHCleanup, - Ptr.getPointer(), - OperatorDelete, ElementType); - - if (Dtor) - CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, - /*ForVirtualBase=*/false, - /*Delegating=*/false, - Ptr); - else if (auto Lifetime = ElementType.getObjCLifetime()) { - switch (Lifetime) { - case Qualifiers::OCL_None: - case Qualifiers::OCL_ExplicitNone: - case Qualifiers::OCL_Autoreleasing: - break; - - case Qualifiers::OCL_Strong: - CGF.EmitARCDestroyStrong(Ptr, ARCPreciseLifetime); - break; - - case Qualifiers::OCL_Weak: - CGF.EmitARCDestroyWeak(Ptr); - break; - } - } - - CGF.PopCleanupBlock(); -} - -namespace { - /// Calls the given 'operator delete' on an array of objects. - struct CallArrayDelete final : EHScopeStack::Cleanup { - llvm::Value *Ptr; - const FunctionDecl *OperatorDelete; - llvm::Value *NumElements; - QualType ElementType; - CharUnits CookieSize; - - CallArrayDelete(llvm::Value *Ptr, - const FunctionDecl *OperatorDelete, - llvm::Value *NumElements, - QualType ElementType, - CharUnits CookieSize) - : Ptr(Ptr), OperatorDelete(OperatorDelete), NumElements(NumElements), - ElementType(ElementType), CookieSize(CookieSize) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - CGF.EmitDeleteCall(OperatorDelete, Ptr, ElementType, NumElements, - CookieSize); - } - }; -} - -/// Emit the code for deleting an array of objects. -static void EmitArrayDelete(CodeGenFunction &CGF, - const CXXDeleteExpr *E, - Address deletedPtr, - QualType elementType) { - llvm::Value *numElements = nullptr; - llvm::Value *allocatedPtr = nullptr; - CharUnits cookieSize; - CGF.CGM.getCXXABI().ReadArrayCookie(CGF, deletedPtr, E, elementType, - numElements, allocatedPtr, cookieSize); - - assert(allocatedPtr && "ReadArrayCookie didn't set allocated pointer"); - - // Make sure that we call delete even if one of the dtors throws. - const FunctionDecl *operatorDelete = E->getOperatorDelete(); - CGF.EHStack.pushCleanup<CallArrayDelete>(NormalAndEHCleanup, - allocatedPtr, operatorDelete, - numElements, elementType, - cookieSize); - - // Destroy the elements. - if (QualType::DestructionKind dtorKind = elementType.isDestructedType()) { - assert(numElements && "no element count for a type with a destructor!"); - - CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType); - CharUnits elementAlign = - deletedPtr.getAlignment().alignmentOfArrayElement(elementSize); - - llvm::Value *arrayBegin = deletedPtr.getPointer(); - llvm::Value *arrayEnd = - CGF.Builder.CreateInBoundsGEP(arrayBegin, numElements, "delete.end"); - - // Note that it is legal to allocate a zero-length array, and we - // can never fold the check away because the length should always - // come from a cookie. - CGF.emitArrayDestroy(arrayBegin, arrayEnd, elementType, elementAlign, - CGF.getDestroyer(dtorKind), - /*checkZeroLength*/ true, - CGF.needsEHCleanup(dtorKind)); - } - - // Pop the cleanup block. - CGF.PopCleanupBlock(); -} - -void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { - const Expr *Arg = E->getArgument(); - Address Ptr = EmitPointerWithAlignment(Arg); - - // Null check the pointer. - llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull"); - llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end"); - - llvm::Value *IsNull = Builder.CreateIsNull(Ptr.getPointer(), "isnull"); - - Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull); - EmitBlock(DeleteNotNull); - - QualType DeleteTy = E->getDestroyedType(); - - // A destroying operator delete overrides the entire operation of the - // delete expression. - if (E->getOperatorDelete()->isDestroyingOperatorDelete()) { - EmitDestroyingObjectDelete(*this, E, Ptr, DeleteTy); - EmitBlock(DeleteEnd); - return; - } - - // We might be deleting a pointer to array. If so, GEP down to the - // first non-array element. - // (this assumes that A(*)[3][7] is converted to [3 x [7 x %A]]*) - if (DeleteTy->isConstantArrayType()) { - llvm::Value *Zero = Builder.getInt32(0); - SmallVector<llvm::Value*,8> GEP; - - GEP.push_back(Zero); // point at the outermost array - - // For each layer of array type we're pointing at: - while (const ConstantArrayType *Arr - = getContext().getAsConstantArrayType(DeleteTy)) { - // 1. Unpeel the array type. - DeleteTy = Arr->getElementType(); - - // 2. GEP to the first element of the array. - GEP.push_back(Zero); - } - - Ptr = Address(Builder.CreateInBoundsGEP(Ptr.getPointer(), GEP, "del.first"), - Ptr.getAlignment()); - } - - assert(ConvertTypeForMem(DeleteTy) == Ptr.getElementType()); - - if (E->isArrayForm()) { - EmitArrayDelete(*this, E, Ptr, DeleteTy); - } else { - EmitObjectDelete(*this, E, Ptr, DeleteTy); - } - - EmitBlock(DeleteEnd); -} - -static bool isGLValueFromPointerDeref(const Expr *E) { - E = E->IgnoreParens(); - - if (const auto *CE = dyn_cast<CastExpr>(E)) { - if (!CE->getSubExpr()->isGLValue()) - return false; - return isGLValueFromPointerDeref(CE->getSubExpr()); - } - - if (const auto *OVE = dyn_cast<OpaqueValueExpr>(E)) - return isGLValueFromPointerDeref(OVE->getSourceExpr()); - - if (const auto *BO = dyn_cast<BinaryOperator>(E)) - if (BO->getOpcode() == BO_Comma) - return isGLValueFromPointerDeref(BO->getRHS()); - - if (const auto *ACO = dyn_cast<AbstractConditionalOperator>(E)) - return isGLValueFromPointerDeref(ACO->getTrueExpr()) || - isGLValueFromPointerDeref(ACO->getFalseExpr()); - - // C++11 [expr.sub]p1: - // The expression E1[E2] is identical (by definition) to *((E1)+(E2)) - if (isa<ArraySubscriptExpr>(E)) - return true; - - if (const auto *UO = dyn_cast<UnaryOperator>(E)) - if (UO->getOpcode() == UO_Deref) - return true; - - return false; -} - -static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E, - llvm::Type *StdTypeInfoPtrTy) { - // Get the vtable pointer. - Address ThisPtr = CGF.EmitLValue(E).getAddress(); - - QualType SrcRecordTy = E->getType(); - - // C++ [class.cdtor]p4: - // If the operand of typeid refers to the object under construction or - // destruction and the static type of the operand is neither the constructor - // or destructor’s class nor one of its bases, the behavior is undefined. - CGF.EmitTypeCheck(CodeGenFunction::TCK_DynamicOperation, E->getExprLoc(), - ThisPtr.getPointer(), SrcRecordTy); - - // C++ [expr.typeid]p2: - // If the glvalue expression is obtained by applying the unary * operator to - // a pointer and the pointer is a null pointer value, the typeid expression - // throws the std::bad_typeid exception. - // - // However, this paragraph's intent is not clear. We choose a very generous - // interpretation which implores us to consider comma operators, conditional - // operators, parentheses and other such constructs. - if (CGF.CGM.getCXXABI().shouldTypeidBeNullChecked( - isGLValueFromPointerDeref(E), SrcRecordTy)) { - llvm::BasicBlock *BadTypeidBlock = - CGF.createBasicBlock("typeid.bad_typeid"); - llvm::BasicBlock *EndBlock = CGF.createBasicBlock("typeid.end"); - - llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr.getPointer()); - CGF.Builder.CreateCondBr(IsNull, BadTypeidBlock, EndBlock); - - CGF.EmitBlock(BadTypeidBlock); - CGF.CGM.getCXXABI().EmitBadTypeidCall(CGF); - CGF.EmitBlock(EndBlock); - } - - return CGF.CGM.getCXXABI().EmitTypeid(CGF, SrcRecordTy, ThisPtr, - StdTypeInfoPtrTy); -} - -llvm::Value *CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) { - llvm::Type *StdTypeInfoPtrTy = - ConvertType(E->getType())->getPointerTo(); - - if (E->isTypeOperand()) { - llvm::Constant *TypeInfo = - CGM.GetAddrOfRTTIDescriptor(E->getTypeOperand(getContext())); - return Builder.CreateBitCast(TypeInfo, StdTypeInfoPtrTy); - } - - // C++ [expr.typeid]p2: - // When typeid is applied to a glvalue expression whose type is a - // polymorphic class type, the result refers to a std::type_info object - // representing the type of the most derived object (that is, the dynamic - // type) to which the glvalue refers. - if (E->isPotentiallyEvaluated()) - return EmitTypeidFromVTable(*this, E->getExprOperand(), - StdTypeInfoPtrTy); - - QualType OperandTy = E->getExprOperand()->getType(); - return Builder.CreateBitCast(CGM.GetAddrOfRTTIDescriptor(OperandTy), - StdTypeInfoPtrTy); -} - -static llvm::Value *EmitDynamicCastToNull(CodeGenFunction &CGF, - QualType DestTy) { - llvm::Type *DestLTy = CGF.ConvertType(DestTy); - if (DestTy->isPointerType()) - return llvm::Constant::getNullValue(DestLTy); - - /// C++ [expr.dynamic.cast]p9: - /// A failed cast to reference type throws std::bad_cast - if (!CGF.CGM.getCXXABI().EmitBadCastCall(CGF)) - return nullptr; - - CGF.EmitBlock(CGF.createBasicBlock("dynamic_cast.end")); - return llvm::UndefValue::get(DestLTy); -} - -llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr, - const CXXDynamicCastExpr *DCE) { - CGM.EmitExplicitCastExprType(DCE, this); - QualType DestTy = DCE->getTypeAsWritten(); - - QualType SrcTy = DCE->getSubExpr()->getType(); - - // C++ [expr.dynamic.cast]p7: - // If T is "pointer to cv void," then the result is a pointer to the most - // derived object pointed to by v. - const PointerType *DestPTy = DestTy->getAs<PointerType>(); - - bool isDynamicCastToVoid; - QualType SrcRecordTy; - QualType DestRecordTy; - if (DestPTy) { - isDynamicCastToVoid = DestPTy->getPointeeType()->isVoidType(); - SrcRecordTy = SrcTy->castAs<PointerType>()->getPointeeType(); - DestRecordTy = DestPTy->getPointeeType(); - } else { - isDynamicCastToVoid = false; - SrcRecordTy = SrcTy; - DestRecordTy = DestTy->castAs<ReferenceType>()->getPointeeType(); - } - - // C++ [class.cdtor]p5: - // If the operand of the dynamic_cast refers to the object under - // construction or destruction and the static type of the operand is not a - // pointer to or object of the constructor or destructor’s own class or one - // of its bases, the dynamic_cast results in undefined behavior. - EmitTypeCheck(TCK_DynamicOperation, DCE->getExprLoc(), ThisAddr.getPointer(), - SrcRecordTy); - - if (DCE->isAlwaysNull()) - if (llvm::Value *T = EmitDynamicCastToNull(*this, DestTy)) - return T; - - assert(SrcRecordTy->isRecordType() && "source type must be a record type!"); - - // C++ [expr.dynamic.cast]p4: - // If the value of v is a null pointer value in the pointer case, the result - // is the null pointer value of type T. - bool ShouldNullCheckSrcValue = - CGM.getCXXABI().shouldDynamicCastCallBeNullChecked(SrcTy->isPointerType(), - SrcRecordTy); - - llvm::BasicBlock *CastNull = nullptr; - llvm::BasicBlock *CastNotNull = nullptr; - llvm::BasicBlock *CastEnd = createBasicBlock("dynamic_cast.end"); - - if (ShouldNullCheckSrcValue) { - CastNull = createBasicBlock("dynamic_cast.null"); - CastNotNull = createBasicBlock("dynamic_cast.notnull"); - - llvm::Value *IsNull = Builder.CreateIsNull(ThisAddr.getPointer()); - Builder.CreateCondBr(IsNull, CastNull, CastNotNull); - EmitBlock(CastNotNull); - } - - llvm::Value *Value; - if (isDynamicCastToVoid) { - Value = CGM.getCXXABI().EmitDynamicCastToVoid(*this, ThisAddr, SrcRecordTy, - DestTy); - } else { - assert(DestRecordTy->isRecordType() && - "destination type must be a record type!"); - Value = CGM.getCXXABI().EmitDynamicCastCall(*this, ThisAddr, SrcRecordTy, - DestTy, DestRecordTy, CastEnd); - CastNotNull = Builder.GetInsertBlock(); - } - - if (ShouldNullCheckSrcValue) { - EmitBranch(CastEnd); - - EmitBlock(CastNull); - EmitBranch(CastEnd); - } - - EmitBlock(CastEnd); - - if (ShouldNullCheckSrcValue) { - llvm::PHINode *PHI = Builder.CreatePHI(Value->getType(), 2); - PHI->addIncoming(Value, CastNotNull); - PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), CastNull); - - Value = PHI; - } - - return Value; -} - -void CodeGenFunction::EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Slot) { - LValue SlotLV = MakeAddrLValue(Slot.getAddress(), E->getType()); - - CXXRecordDecl::field_iterator CurField = E->getLambdaClass()->field_begin(); - for (LambdaExpr::const_capture_init_iterator i = E->capture_init_begin(), - e = E->capture_init_end(); - i != e; ++i, ++CurField) { - // Emit initialization - LValue LV = EmitLValueForFieldInitialization(SlotLV, *CurField); - if (CurField->hasCapturedVLAType()) { - auto VAT = CurField->getCapturedVLAType(); - EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV); - } else { - EmitInitializerForField(*CurField, LV, *i); - } - } -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp deleted file mode 100644 index 2db693b44c9..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp +++ /dev/null @@ -1,1158 +0,0 @@ -//===--- CGExprComplex.cpp - Emit LLVM Code for Complex Exprs -------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code to emit Expr nodes with complex types as LLVM code. -// -//===----------------------------------------------------------------------===// - -#include "CodeGenFunction.h" -#include "CodeGenModule.h" -#include "clang/AST/StmtVisitor.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/MDBuilder.h" -#include "llvm/IR/Metadata.h" -#include <algorithm> -using namespace clang; -using namespace CodeGen; - -//===----------------------------------------------------------------------===// -// Complex Expression Emitter -//===----------------------------------------------------------------------===// - -typedef CodeGenFunction::ComplexPairTy ComplexPairTy; - -/// Return the complex type that we are meant to emit. -static const ComplexType *getComplexType(QualType type) { - type = type.getCanonicalType(); - if (const ComplexType *comp = dyn_cast<ComplexType>(type)) { - return comp; - } else { - return cast<ComplexType>(cast<AtomicType>(type)->getValueType()); - } -} - -namespace { -class ComplexExprEmitter - : public StmtVisitor<ComplexExprEmitter, ComplexPairTy> { - CodeGenFunction &CGF; - CGBuilderTy &Builder; - bool IgnoreReal; - bool IgnoreImag; -public: - ComplexExprEmitter(CodeGenFunction &cgf, bool ir=false, bool ii=false) - : CGF(cgf), Builder(CGF.Builder), IgnoreReal(ir), IgnoreImag(ii) { - } - - - //===--------------------------------------------------------------------===// - // Utilities - //===--------------------------------------------------------------------===// - - bool TestAndClearIgnoreReal() { - bool I = IgnoreReal; - IgnoreReal = false; - return I; - } - bool TestAndClearIgnoreImag() { - bool I = IgnoreImag; - IgnoreImag = false; - return I; - } - - /// EmitLoadOfLValue - Given an expression with complex type that represents a - /// value l-value, this method emits the address of the l-value, then loads - /// and returns the result. - ComplexPairTy EmitLoadOfLValue(const Expr *E) { - return EmitLoadOfLValue(CGF.EmitLValue(E), E->getExprLoc()); - } - - ComplexPairTy EmitLoadOfLValue(LValue LV, SourceLocation Loc); - - /// EmitStoreOfComplex - Store the specified real/imag parts into the - /// specified value pointer. - void EmitStoreOfComplex(ComplexPairTy Val, LValue LV, bool isInit); - - /// Emit a cast from complex value Val to DestType. - ComplexPairTy EmitComplexToComplexCast(ComplexPairTy Val, QualType SrcType, - QualType DestType, SourceLocation Loc); - /// Emit a cast from scalar value Val to DestType. - ComplexPairTy EmitScalarToComplexCast(llvm::Value *Val, QualType SrcType, - QualType DestType, SourceLocation Loc); - - //===--------------------------------------------------------------------===// - // Visitor Methods - //===--------------------------------------------------------------------===// - - ComplexPairTy Visit(Expr *E) { - ApplyDebugLocation DL(CGF, E); - return StmtVisitor<ComplexExprEmitter, ComplexPairTy>::Visit(E); - } - - ComplexPairTy VisitStmt(Stmt *S) { - S->dump(CGF.getContext().getSourceManager()); - llvm_unreachable("Stmt can't have complex result type!"); - } - ComplexPairTy VisitExpr(Expr *S); - ComplexPairTy VisitConstantExpr(ConstantExpr *E) { - return Visit(E->getSubExpr()); - } - ComplexPairTy VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr());} - ComplexPairTy VisitGenericSelectionExpr(GenericSelectionExpr *GE) { - return Visit(GE->getResultExpr()); - } - ComplexPairTy VisitImaginaryLiteral(const ImaginaryLiteral *IL); - ComplexPairTy - VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *PE) { - return Visit(PE->getReplacement()); - } - ComplexPairTy VisitCoawaitExpr(CoawaitExpr *S) { - return CGF.EmitCoawaitExpr(*S).getComplexVal(); - } - ComplexPairTy VisitCoyieldExpr(CoyieldExpr *S) { - return CGF.EmitCoyieldExpr(*S).getComplexVal(); - } - ComplexPairTy VisitUnaryCoawait(const UnaryOperator *E) { - return Visit(E->getSubExpr()); - } - - ComplexPairTy emitConstant(const CodeGenFunction::ConstantEmission &Constant, - Expr *E) { - assert(Constant && "not a constant"); - if (Constant.isReference()) - return EmitLoadOfLValue(Constant.getReferenceLValue(CGF, E), - E->getExprLoc()); - - llvm::Constant *pair = Constant.getValue(); - return ComplexPairTy(pair->getAggregateElement(0U), - pair->getAggregateElement(1U)); - } - - // l-values. - ComplexPairTy VisitDeclRefExpr(DeclRefExpr *E) { - if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(E)) - return emitConstant(Constant, E); - return EmitLoadOfLValue(E); - } - ComplexPairTy VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { - return EmitLoadOfLValue(E); - } - ComplexPairTy VisitObjCMessageExpr(ObjCMessageExpr *E) { - return CGF.EmitObjCMessageExpr(E).getComplexVal(); - } - ComplexPairTy VisitArraySubscriptExpr(Expr *E) { return EmitLoadOfLValue(E); } - ComplexPairTy VisitMemberExpr(MemberExpr *ME) { - if (CodeGenFunction::ConstantEmission Constant = - CGF.tryEmitAsConstant(ME)) { - CGF.EmitIgnoredExpr(ME->getBase()); - return emitConstant(Constant, ME); - } - return EmitLoadOfLValue(ME); - } - ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) { - if (E->isGLValue()) - return EmitLoadOfLValue(CGF.getOrCreateOpaqueLValueMapping(E), - E->getExprLoc()); - return CGF.getOrCreateOpaqueRValueMapping(E).getComplexVal(); - } - - ComplexPairTy VisitPseudoObjectExpr(PseudoObjectExpr *E) { - return CGF.EmitPseudoObjectRValue(E).getComplexVal(); - } - - // FIXME: CompoundLiteralExpr - - ComplexPairTy EmitCast(CastKind CK, Expr *Op, QualType DestTy); - ComplexPairTy VisitImplicitCastExpr(ImplicitCastExpr *E) { - // Unlike for scalars, we don't have to worry about function->ptr demotion - // here. - return EmitCast(E->getCastKind(), E->getSubExpr(), E->getType()); - } - ComplexPairTy VisitCastExpr(CastExpr *E) { - if (const auto *ECE = dyn_cast<ExplicitCastExpr>(E)) - CGF.CGM.EmitExplicitCastExprType(ECE, &CGF); - return EmitCast(E->getCastKind(), E->getSubExpr(), E->getType()); - } - ComplexPairTy VisitCallExpr(const CallExpr *E); - ComplexPairTy VisitStmtExpr(const StmtExpr *E); - - // Operators. - ComplexPairTy VisitPrePostIncDec(const UnaryOperator *E, - bool isInc, bool isPre) { - LValue LV = CGF.EmitLValue(E->getSubExpr()); - return CGF.EmitComplexPrePostIncDec(E, LV, isInc, isPre); - } - ComplexPairTy VisitUnaryPostDec(const UnaryOperator *E) { - return VisitPrePostIncDec(E, false, false); - } - ComplexPairTy VisitUnaryPostInc(const UnaryOperator *E) { - return VisitPrePostIncDec(E, true, false); - } - ComplexPairTy VisitUnaryPreDec(const UnaryOperator *E) { - return VisitPrePostIncDec(E, false, true); - } - ComplexPairTy VisitUnaryPreInc(const UnaryOperator *E) { - return VisitPrePostIncDec(E, true, true); - } - ComplexPairTy VisitUnaryDeref(const Expr *E) { return EmitLoadOfLValue(E); } - ComplexPairTy VisitUnaryPlus (const UnaryOperator *E) { - TestAndClearIgnoreReal(); - TestAndClearIgnoreImag(); - return Visit(E->getSubExpr()); - } - ComplexPairTy VisitUnaryMinus (const UnaryOperator *E); - ComplexPairTy VisitUnaryNot (const UnaryOperator *E); - // LNot,Real,Imag never return complex. - ComplexPairTy VisitUnaryExtension(const UnaryOperator *E) { - return Visit(E->getSubExpr()); - } - ComplexPairTy VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) { - return Visit(DAE->getExpr()); - } - ComplexPairTy VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) { - CodeGenFunction::CXXDefaultInitExprScope Scope(CGF); - return Visit(DIE->getExpr()); - } - ComplexPairTy VisitExprWithCleanups(ExprWithCleanups *E) { - CGF.enterFullExpression(E); - CodeGenFunction::RunCleanupsScope Scope(CGF); - ComplexPairTy Vals = Visit(E->getSubExpr()); - // Defend against dominance problems caused by jumps out of expression - // evaluation through the shared cleanup block. - Scope.ForceCleanup({&Vals.first, &Vals.second}); - return Vals; - } - ComplexPairTy VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { - assert(E->getType()->isAnyComplexType() && "Expected complex type!"); - QualType Elem = E->getType()->castAs<ComplexType>()->getElementType(); - llvm::Constant *Null = llvm::Constant::getNullValue(CGF.ConvertType(Elem)); - return ComplexPairTy(Null, Null); - } - ComplexPairTy VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { - assert(E->getType()->isAnyComplexType() && "Expected complex type!"); - QualType Elem = E->getType()->castAs<ComplexType>()->getElementType(); - llvm::Constant *Null = - llvm::Constant::getNullValue(CGF.ConvertType(Elem)); - return ComplexPairTy(Null, Null); - } - - struct BinOpInfo { - ComplexPairTy LHS; - ComplexPairTy RHS; - QualType Ty; // Computation Type. - }; - - BinOpInfo EmitBinOps(const BinaryOperator *E); - LValue EmitCompoundAssignLValue(const CompoundAssignOperator *E, - ComplexPairTy (ComplexExprEmitter::*Func) - (const BinOpInfo &), - RValue &Val); - ComplexPairTy EmitCompoundAssign(const CompoundAssignOperator *E, - ComplexPairTy (ComplexExprEmitter::*Func) - (const BinOpInfo &)); - - ComplexPairTy EmitBinAdd(const BinOpInfo &Op); - ComplexPairTy EmitBinSub(const BinOpInfo &Op); - ComplexPairTy EmitBinMul(const BinOpInfo &Op); - ComplexPairTy EmitBinDiv(const BinOpInfo &Op); - - ComplexPairTy EmitComplexBinOpLibCall(StringRef LibCallName, - const BinOpInfo &Op); - - ComplexPairTy VisitBinAdd(const BinaryOperator *E) { - return EmitBinAdd(EmitBinOps(E)); - } - ComplexPairTy VisitBinSub(const BinaryOperator *E) { - return EmitBinSub(EmitBinOps(E)); - } - ComplexPairTy VisitBinMul(const BinaryOperator *E) { - return EmitBinMul(EmitBinOps(E)); - } - ComplexPairTy VisitBinDiv(const BinaryOperator *E) { - return EmitBinDiv(EmitBinOps(E)); - } - - // Compound assignments. - ComplexPairTy VisitBinAddAssign(const CompoundAssignOperator *E) { - return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinAdd); - } - ComplexPairTy VisitBinSubAssign(const CompoundAssignOperator *E) { - return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinSub); - } - ComplexPairTy VisitBinMulAssign(const CompoundAssignOperator *E) { - return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinMul); - } - ComplexPairTy VisitBinDivAssign(const CompoundAssignOperator *E) { - return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinDiv); - } - - // GCC rejects rem/and/or/xor for integer complex. - // Logical and/or always return int, never complex. - - // No comparisons produce a complex result. - - LValue EmitBinAssignLValue(const BinaryOperator *E, - ComplexPairTy &Val); - ComplexPairTy VisitBinAssign (const BinaryOperator *E); - ComplexPairTy VisitBinComma (const BinaryOperator *E); - - - ComplexPairTy - VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO); - ComplexPairTy VisitChooseExpr(ChooseExpr *CE); - - ComplexPairTy VisitInitListExpr(InitListExpr *E); - - ComplexPairTy VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { - return EmitLoadOfLValue(E); - } - - ComplexPairTy VisitVAArgExpr(VAArgExpr *E); - - ComplexPairTy VisitAtomicExpr(AtomicExpr *E) { - return CGF.EmitAtomicExpr(E).getComplexVal(); - } -}; -} // end anonymous namespace. - -//===----------------------------------------------------------------------===// -// Utilities -//===----------------------------------------------------------------------===// - -Address CodeGenFunction::emitAddrOfRealComponent(Address addr, - QualType complexType) { - CharUnits offset = CharUnits::Zero(); - return Builder.CreateStructGEP(addr, 0, offset, addr.getName() + ".realp"); -} - -Address CodeGenFunction::emitAddrOfImagComponent(Address addr, - QualType complexType) { - QualType eltType = complexType->castAs<ComplexType>()->getElementType(); - CharUnits offset = getContext().getTypeSizeInChars(eltType); - return Builder.CreateStructGEP(addr, 1, offset, addr.getName() + ".imagp"); -} - -/// EmitLoadOfLValue - Given an RValue reference for a complex, emit code to -/// load the real and imaginary pieces, returning them as Real/Imag. -ComplexPairTy ComplexExprEmitter::EmitLoadOfLValue(LValue lvalue, - SourceLocation loc) { - assert(lvalue.isSimple() && "non-simple complex l-value?"); - if (lvalue.getType()->isAtomicType()) - return CGF.EmitAtomicLoad(lvalue, loc).getComplexVal(); - - Address SrcPtr = lvalue.getAddress(); - bool isVolatile = lvalue.isVolatileQualified(); - - llvm::Value *Real = nullptr, *Imag = nullptr; - - if (!IgnoreReal || isVolatile) { - Address RealP = CGF.emitAddrOfRealComponent(SrcPtr, lvalue.getType()); - Real = Builder.CreateLoad(RealP, isVolatile, SrcPtr.getName() + ".real"); - } - - if (!IgnoreImag || isVolatile) { - Address ImagP = CGF.emitAddrOfImagComponent(SrcPtr, lvalue.getType()); - Imag = Builder.CreateLoad(ImagP, isVolatile, SrcPtr.getName() + ".imag"); - } - - return ComplexPairTy(Real, Imag); -} - -/// EmitStoreOfComplex - Store the specified real/imag parts into the -/// specified value pointer. -void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, LValue lvalue, - bool isInit) { - if (lvalue.getType()->isAtomicType() || - (!isInit && CGF.LValueIsSuitableForInlineAtomic(lvalue))) - return CGF.EmitAtomicStore(RValue::getComplex(Val), lvalue, isInit); - - Address Ptr = lvalue.getAddress(); - Address RealPtr = CGF.emitAddrOfRealComponent(Ptr, lvalue.getType()); - Address ImagPtr = CGF.emitAddrOfImagComponent(Ptr, lvalue.getType()); - - Builder.CreateStore(Val.first, RealPtr, lvalue.isVolatileQualified()); - Builder.CreateStore(Val.second, ImagPtr, lvalue.isVolatileQualified()); -} - - - -//===----------------------------------------------------------------------===// -// Visitor Methods -//===----------------------------------------------------------------------===// - -ComplexPairTy ComplexExprEmitter::VisitExpr(Expr *E) { - CGF.ErrorUnsupported(E, "complex expression"); - llvm::Type *EltTy = - CGF.ConvertType(getComplexType(E->getType())->getElementType()); - llvm::Value *U = llvm::UndefValue::get(EltTy); - return ComplexPairTy(U, U); -} - -ComplexPairTy ComplexExprEmitter:: -VisitImaginaryLiteral(const ImaginaryLiteral *IL) { - llvm::Value *Imag = CGF.EmitScalarExpr(IL->getSubExpr()); - return ComplexPairTy(llvm::Constant::getNullValue(Imag->getType()), Imag); -} - - -ComplexPairTy ComplexExprEmitter::VisitCallExpr(const CallExpr *E) { - if (E->getCallReturnType(CGF.getContext())->isReferenceType()) - return EmitLoadOfLValue(E); - - return CGF.EmitCallExpr(E).getComplexVal(); -} - -ComplexPairTy ComplexExprEmitter::VisitStmtExpr(const StmtExpr *E) { - CodeGenFunction::StmtExprEvaluation eval(CGF); - Address RetAlloca = CGF.EmitCompoundStmt(*E->getSubStmt(), true); - assert(RetAlloca.isValid() && "Expected complex return value"); - return EmitLoadOfLValue(CGF.MakeAddrLValue(RetAlloca, E->getType()), - E->getExprLoc()); -} - -/// Emit a cast from complex value Val to DestType. -ComplexPairTy ComplexExprEmitter::EmitComplexToComplexCast(ComplexPairTy Val, - QualType SrcType, - QualType DestType, - SourceLocation Loc) { - // Get the src/dest element type. - SrcType = SrcType->castAs<ComplexType>()->getElementType(); - DestType = DestType->castAs<ComplexType>()->getElementType(); - - // C99 6.3.1.6: When a value of complex type is converted to another - // complex type, both the real and imaginary parts follow the conversion - // rules for the corresponding real types. - Val.first = CGF.EmitScalarConversion(Val.first, SrcType, DestType, Loc); - Val.second = CGF.EmitScalarConversion(Val.second, SrcType, DestType, Loc); - return Val; -} - -ComplexPairTy ComplexExprEmitter::EmitScalarToComplexCast(llvm::Value *Val, - QualType SrcType, - QualType DestType, - SourceLocation Loc) { - // Convert the input element to the element type of the complex. - DestType = DestType->castAs<ComplexType>()->getElementType(); - Val = CGF.EmitScalarConversion(Val, SrcType, DestType, Loc); - - // Return (realval, 0). - return ComplexPairTy(Val, llvm::Constant::getNullValue(Val->getType())); -} - -ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op, - QualType DestTy) { - switch (CK) { - case CK_Dependent: llvm_unreachable("dependent cast kind in IR gen!"); - - // Atomic to non-atomic casts may be more than a no-op for some platforms and - // for some types. - case CK_AtomicToNonAtomic: - case CK_NonAtomicToAtomic: - case CK_NoOp: - case CK_LValueToRValue: - case CK_UserDefinedConversion: - return Visit(Op); - - case CK_LValueBitCast: { - LValue origLV = CGF.EmitLValue(Op); - Address V = origLV.getAddress(); - V = Builder.CreateElementBitCast(V, CGF.ConvertType(DestTy)); - return EmitLoadOfLValue(CGF.MakeAddrLValue(V, DestTy), Op->getExprLoc()); - } - - case CK_BitCast: - case CK_BaseToDerived: - case CK_DerivedToBase: - case CK_UncheckedDerivedToBase: - case CK_Dynamic: - case CK_ToUnion: - case CK_ArrayToPointerDecay: - case CK_FunctionToPointerDecay: - case CK_NullToPointer: - case CK_NullToMemberPointer: - case CK_BaseToDerivedMemberPointer: - case CK_DerivedToBaseMemberPointer: - case CK_MemberPointerToBoolean: - case CK_ReinterpretMemberPointer: - case CK_ConstructorConversion: - case CK_IntegralToPointer: - case CK_PointerToIntegral: - case CK_PointerToBoolean: - case CK_ToVoid: - case CK_VectorSplat: - case CK_IntegralCast: - case CK_BooleanToSignedIntegral: - case CK_IntegralToBoolean: - case CK_IntegralToFloating: - case CK_FloatingToIntegral: - case CK_FloatingToBoolean: - case CK_FloatingCast: - case CK_CPointerToObjCPointerCast: - case CK_BlockPointerToObjCPointerCast: - case CK_AnyPointerToBlockPointerCast: - case CK_ObjCObjectLValueCast: - case CK_FloatingComplexToReal: - case CK_FloatingComplexToBoolean: - case CK_IntegralComplexToReal: - case CK_IntegralComplexToBoolean: - case CK_ARCProduceObject: - case CK_ARCConsumeObject: - case CK_ARCReclaimReturnedObject: - case CK_ARCExtendBlockObject: - case CK_CopyAndAutoreleaseBlockObject: - case CK_BuiltinFnToFnPtr: - case CK_ZeroToOCLOpaqueType: - case CK_AddressSpaceConversion: - case CK_IntToOCLSampler: - case CK_FixedPointCast: - case CK_FixedPointToBoolean: - llvm_unreachable("invalid cast kind for complex value"); - - case CK_FloatingRealToComplex: - case CK_IntegralRealToComplex: - return EmitScalarToComplexCast(CGF.EmitScalarExpr(Op), Op->getType(), - DestTy, Op->getExprLoc()); - - case CK_FloatingComplexCast: - case CK_FloatingComplexToIntegralComplex: - case CK_IntegralComplexCast: - case CK_IntegralComplexToFloatingComplex: - return EmitComplexToComplexCast(Visit(Op), Op->getType(), DestTy, - Op->getExprLoc()); - } - - llvm_unreachable("unknown cast resulting in complex value"); -} - -ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E) { - TestAndClearIgnoreReal(); - TestAndClearIgnoreImag(); - ComplexPairTy Op = Visit(E->getSubExpr()); - - llvm::Value *ResR, *ResI; - if (Op.first->getType()->isFloatingPointTy()) { - ResR = Builder.CreateFNeg(Op.first, "neg.r"); - ResI = Builder.CreateFNeg(Op.second, "neg.i"); - } else { - ResR = Builder.CreateNeg(Op.first, "neg.r"); - ResI = Builder.CreateNeg(Op.second, "neg.i"); - } - return ComplexPairTy(ResR, ResI); -} - -ComplexPairTy ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *E) { - TestAndClearIgnoreReal(); - TestAndClearIgnoreImag(); - // ~(a+ib) = a + i*-b - ComplexPairTy Op = Visit(E->getSubExpr()); - llvm::Value *ResI; - if (Op.second->getType()->isFloatingPointTy()) - ResI = Builder.CreateFNeg(Op.second, "conj.i"); - else - ResI = Builder.CreateNeg(Op.second, "conj.i"); - - return ComplexPairTy(Op.first, ResI); -} - -ComplexPairTy ComplexExprEmitter::EmitBinAdd(const BinOpInfo &Op) { - llvm::Value *ResR, *ResI; - - if (Op.LHS.first->getType()->isFloatingPointTy()) { - ResR = Builder.CreateFAdd(Op.LHS.first, Op.RHS.first, "add.r"); - if (Op.LHS.second && Op.RHS.second) - ResI = Builder.CreateFAdd(Op.LHS.second, Op.RHS.second, "add.i"); - else - ResI = Op.LHS.second ? Op.LHS.second : Op.RHS.second; - assert(ResI && "Only one operand may be real!"); - } else { - ResR = Builder.CreateAdd(Op.LHS.first, Op.RHS.first, "add.r"); - assert(Op.LHS.second && Op.RHS.second && - "Both operands of integer complex operators must be complex!"); - ResI = Builder.CreateAdd(Op.LHS.second, Op.RHS.second, "add.i"); - } - return ComplexPairTy(ResR, ResI); -} - -ComplexPairTy ComplexExprEmitter::EmitBinSub(const BinOpInfo &Op) { - llvm::Value *ResR, *ResI; - if (Op.LHS.first->getType()->isFloatingPointTy()) { - ResR = Builder.CreateFSub(Op.LHS.first, Op.RHS.first, "sub.r"); - if (Op.LHS.second && Op.RHS.second) - ResI = Builder.CreateFSub(Op.LHS.second, Op.RHS.second, "sub.i"); - else - ResI = Op.LHS.second ? Op.LHS.second - : Builder.CreateFNeg(Op.RHS.second, "sub.i"); - assert(ResI && "Only one operand may be real!"); - } else { - ResR = Builder.CreateSub(Op.LHS.first, Op.RHS.first, "sub.r"); - assert(Op.LHS.second && Op.RHS.second && - "Both operands of integer complex operators must be complex!"); - ResI = Builder.CreateSub(Op.LHS.second, Op.RHS.second, "sub.i"); - } - return ComplexPairTy(ResR, ResI); -} - -/// Emit a libcall for a binary operation on complex types. -ComplexPairTy ComplexExprEmitter::EmitComplexBinOpLibCall(StringRef LibCallName, - const BinOpInfo &Op) { - CallArgList Args; - Args.add(RValue::get(Op.LHS.first), - Op.Ty->castAs<ComplexType>()->getElementType()); - Args.add(RValue::get(Op.LHS.second), - Op.Ty->castAs<ComplexType>()->getElementType()); - Args.add(RValue::get(Op.RHS.first), - Op.Ty->castAs<ComplexType>()->getElementType()); - Args.add(RValue::get(Op.RHS.second), - Op.Ty->castAs<ComplexType>()->getElementType()); - - // We *must* use the full CG function call building logic here because the - // complex type has special ABI handling. We also should not forget about - // special calling convention which may be used for compiler builtins. - - // We create a function qualified type to state that this call does not have - // any exceptions. - FunctionProtoType::ExtProtoInfo EPI; - EPI = EPI.withExceptionSpec( - FunctionProtoType::ExceptionSpecInfo(EST_BasicNoexcept)); - SmallVector<QualType, 4> ArgsQTys( - 4, Op.Ty->castAs<ComplexType>()->getElementType()); - QualType FQTy = CGF.getContext().getFunctionType(Op.Ty, ArgsQTys, EPI); - const CGFunctionInfo &FuncInfo = CGF.CGM.getTypes().arrangeFreeFunctionCall( - Args, cast<FunctionType>(FQTy.getTypePtr()), false); - - llvm::FunctionType *FTy = CGF.CGM.getTypes().GetFunctionType(FuncInfo); - llvm::Constant *Func = CGF.CGM.CreateBuiltinFunction(FTy, LibCallName); - CGCallee Callee = CGCallee::forDirect(Func, FQTy->getAs<FunctionProtoType>()); - - llvm::Instruction *Call; - RValue Res = CGF.EmitCall(FuncInfo, Callee, ReturnValueSlot(), Args, &Call); - cast<llvm::CallInst>(Call)->setCallingConv(CGF.CGM.getRuntimeCC()); - return Res.getComplexVal(); -} - -/// Lookup the libcall name for a given floating point type complex -/// multiply. -static StringRef getComplexMultiplyLibCallName(llvm::Type *Ty) { - switch (Ty->getTypeID()) { - default: - llvm_unreachable("Unsupported floating point type!"); - case llvm::Type::HalfTyID: - return "__mulhc3"; - case llvm::Type::FloatTyID: - return "__mulsc3"; - case llvm::Type::DoubleTyID: - return "__muldc3"; - case llvm::Type::PPC_FP128TyID: - return "__multc3"; - case llvm::Type::X86_FP80TyID: - return "__mulxc3"; - case llvm::Type::FP128TyID: - return "__multc3"; - } -} - -// See C11 Annex G.5.1 for the semantics of multiplicative operators on complex -// typed values. -ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) { - using llvm::Value; - Value *ResR, *ResI; - llvm::MDBuilder MDHelper(CGF.getLLVMContext()); - - if (Op.LHS.first->getType()->isFloatingPointTy()) { - // The general formulation is: - // (a + ib) * (c + id) = (a * c - b * d) + i(a * d + b * c) - // - // But we can fold away components which would be zero due to a real - // operand according to C11 Annex G.5.1p2. - // FIXME: C11 also provides for imaginary types which would allow folding - // still more of this within the type system. - - if (Op.LHS.second && Op.RHS.second) { - // If both operands are complex, emit the core math directly, and then - // test for NaNs. If we find NaNs in the result, we delegate to a libcall - // to carefully re-compute the correct infinity representation if - // possible. The expectation is that the presence of NaNs here is - // *extremely* rare, and so the cost of the libcall is almost irrelevant. - // This is good, because the libcall re-computes the core multiplication - // exactly the same as we do here and re-tests for NaNs in order to be - // a generic complex*complex libcall. - - // First compute the four products. - Value *AC = Builder.CreateFMul(Op.LHS.first, Op.RHS.first, "mul_ac"); - Value *BD = Builder.CreateFMul(Op.LHS.second, Op.RHS.second, "mul_bd"); - Value *AD = Builder.CreateFMul(Op.LHS.first, Op.RHS.second, "mul_ad"); - Value *BC = Builder.CreateFMul(Op.LHS.second, Op.RHS.first, "mul_bc"); - - // The real part is the difference of the first two, the imaginary part is - // the sum of the second. - ResR = Builder.CreateFSub(AC, BD, "mul_r"); - ResI = Builder.CreateFAdd(AD, BC, "mul_i"); - - // Emit the test for the real part becoming NaN and create a branch to - // handle it. We test for NaN by comparing the number to itself. - Value *IsRNaN = Builder.CreateFCmpUNO(ResR, ResR, "isnan_cmp"); - llvm::BasicBlock *ContBB = CGF.createBasicBlock("complex_mul_cont"); - llvm::BasicBlock *INaNBB = CGF.createBasicBlock("complex_mul_imag_nan"); - llvm::Instruction *Branch = Builder.CreateCondBr(IsRNaN, INaNBB, ContBB); - llvm::BasicBlock *OrigBB = Branch->getParent(); - - // Give hint that we very much don't expect to see NaNs. - // Value chosen to match UR_NONTAKEN_WEIGHT, see BranchProbabilityInfo.cpp - llvm::MDNode *BrWeight = MDHelper.createBranchWeights(1, (1U << 20) - 1); - Branch->setMetadata(llvm::LLVMContext::MD_prof, BrWeight); - - // Now test the imaginary part and create its branch. - CGF.EmitBlock(INaNBB); - Value *IsINaN = Builder.CreateFCmpUNO(ResI, ResI, "isnan_cmp"); - llvm::BasicBlock *LibCallBB = CGF.createBasicBlock("complex_mul_libcall"); - Branch = Builder.CreateCondBr(IsINaN, LibCallBB, ContBB); - Branch->setMetadata(llvm::LLVMContext::MD_prof, BrWeight); - - // Now emit the libcall on this slowest of the slow paths. - CGF.EmitBlock(LibCallBB); - Value *LibCallR, *LibCallI; - std::tie(LibCallR, LibCallI) = EmitComplexBinOpLibCall( - getComplexMultiplyLibCallName(Op.LHS.first->getType()), Op); - Builder.CreateBr(ContBB); - - // Finally continue execution by phi-ing together the different - // computation paths. - CGF.EmitBlock(ContBB); - llvm::PHINode *RealPHI = Builder.CreatePHI(ResR->getType(), 3, "real_mul_phi"); - RealPHI->addIncoming(ResR, OrigBB); - RealPHI->addIncoming(ResR, INaNBB); - RealPHI->addIncoming(LibCallR, LibCallBB); - llvm::PHINode *ImagPHI = Builder.CreatePHI(ResI->getType(), 3, "imag_mul_phi"); - ImagPHI->addIncoming(ResI, OrigBB); - ImagPHI->addIncoming(ResI, INaNBB); - ImagPHI->addIncoming(LibCallI, LibCallBB); - return ComplexPairTy(RealPHI, ImagPHI); - } - assert((Op.LHS.second || Op.RHS.second) && - "At least one operand must be complex!"); - - // If either of the operands is a real rather than a complex, the - // imaginary component is ignored when computing the real component of the - // result. - ResR = Builder.CreateFMul(Op.LHS.first, Op.RHS.first, "mul.rl"); - - ResI = Op.LHS.second - ? Builder.CreateFMul(Op.LHS.second, Op.RHS.first, "mul.il") - : Builder.CreateFMul(Op.LHS.first, Op.RHS.second, "mul.ir"); - } else { - assert(Op.LHS.second && Op.RHS.second && - "Both operands of integer complex operators must be complex!"); - Value *ResRl = Builder.CreateMul(Op.LHS.first, Op.RHS.first, "mul.rl"); - Value *ResRr = Builder.CreateMul(Op.LHS.second, Op.RHS.second, "mul.rr"); - ResR = Builder.CreateSub(ResRl, ResRr, "mul.r"); - - Value *ResIl = Builder.CreateMul(Op.LHS.second, Op.RHS.first, "mul.il"); - Value *ResIr = Builder.CreateMul(Op.LHS.first, Op.RHS.second, "mul.ir"); - ResI = Builder.CreateAdd(ResIl, ResIr, "mul.i"); - } - return ComplexPairTy(ResR, ResI); -} - -// See C11 Annex G.5.1 for the semantics of multiplicative operators on complex -// typed values. -ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) { - llvm::Value *LHSr = Op.LHS.first, *LHSi = Op.LHS.second; - llvm::Value *RHSr = Op.RHS.first, *RHSi = Op.RHS.second; - - llvm::Value *DSTr, *DSTi; - if (LHSr->getType()->isFloatingPointTy()) { - // If we have a complex operand on the RHS and FastMath is not allowed, we - // delegate to a libcall to handle all of the complexities and minimize - // underflow/overflow cases. When FastMath is allowed we construct the - // divide inline using the same algorithm as for integer operands. - // - // FIXME: We would be able to avoid the libcall in many places if we - // supported imaginary types in addition to complex types. - if (RHSi && !CGF.getLangOpts().FastMath) { - BinOpInfo LibCallOp = Op; - // If LHS was a real, supply a null imaginary part. - if (!LHSi) - LibCallOp.LHS.second = llvm::Constant::getNullValue(LHSr->getType()); - - switch (LHSr->getType()->getTypeID()) { - default: - llvm_unreachable("Unsupported floating point type!"); - case llvm::Type::HalfTyID: - return EmitComplexBinOpLibCall("__divhc3", LibCallOp); - case llvm::Type::FloatTyID: - return EmitComplexBinOpLibCall("__divsc3", LibCallOp); - case llvm::Type::DoubleTyID: - return EmitComplexBinOpLibCall("__divdc3", LibCallOp); - case llvm::Type::PPC_FP128TyID: - return EmitComplexBinOpLibCall("__divtc3", LibCallOp); - case llvm::Type::X86_FP80TyID: - return EmitComplexBinOpLibCall("__divxc3", LibCallOp); - case llvm::Type::FP128TyID: - return EmitComplexBinOpLibCall("__divtc3", LibCallOp); - } - } else if (RHSi) { - if (!LHSi) - LHSi = llvm::Constant::getNullValue(RHSi->getType()); - - // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) - llvm::Value *AC = Builder.CreateFMul(LHSr, RHSr); // a*c - llvm::Value *BD = Builder.CreateFMul(LHSi, RHSi); // b*d - llvm::Value *ACpBD = Builder.CreateFAdd(AC, BD); // ac+bd - - llvm::Value *CC = Builder.CreateFMul(RHSr, RHSr); // c*c - llvm::Value *DD = Builder.CreateFMul(RHSi, RHSi); // d*d - llvm::Value *CCpDD = Builder.CreateFAdd(CC, DD); // cc+dd - - llvm::Value *BC = Builder.CreateFMul(LHSi, RHSr); // b*c - llvm::Value *AD = Builder.CreateFMul(LHSr, RHSi); // a*d - llvm::Value *BCmAD = Builder.CreateFSub(BC, AD); // bc-ad - - DSTr = Builder.CreateFDiv(ACpBD, CCpDD); - DSTi = Builder.CreateFDiv(BCmAD, CCpDD); - } else { - assert(LHSi && "Can have at most one non-complex operand!"); - - DSTr = Builder.CreateFDiv(LHSr, RHSr); - DSTi = Builder.CreateFDiv(LHSi, RHSr); - } - } else { - assert(Op.LHS.second && Op.RHS.second && - "Both operands of integer complex operators must be complex!"); - // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) - llvm::Value *Tmp1 = Builder.CreateMul(LHSr, RHSr); // a*c - llvm::Value *Tmp2 = Builder.CreateMul(LHSi, RHSi); // b*d - llvm::Value *Tmp3 = Builder.CreateAdd(Tmp1, Tmp2); // ac+bd - - llvm::Value *Tmp4 = Builder.CreateMul(RHSr, RHSr); // c*c - llvm::Value *Tmp5 = Builder.CreateMul(RHSi, RHSi); // d*d - llvm::Value *Tmp6 = Builder.CreateAdd(Tmp4, Tmp5); // cc+dd - - llvm::Value *Tmp7 = Builder.CreateMul(LHSi, RHSr); // b*c - llvm::Value *Tmp8 = Builder.CreateMul(LHSr, RHSi); // a*d - llvm::Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8); // bc-ad - - if (Op.Ty->castAs<ComplexType>()->getElementType()->isUnsignedIntegerType()) { - DSTr = Builder.CreateUDiv(Tmp3, Tmp6); - DSTi = Builder.CreateUDiv(Tmp9, Tmp6); - } else { - DSTr = Builder.CreateSDiv(Tmp3, Tmp6); - DSTi = Builder.CreateSDiv(Tmp9, Tmp6); - } - } - - return ComplexPairTy(DSTr, DSTi); -} - -ComplexExprEmitter::BinOpInfo -ComplexExprEmitter::EmitBinOps(const BinaryOperator *E) { - TestAndClearIgnoreReal(); - TestAndClearIgnoreImag(); - BinOpInfo Ops; - if (E->getLHS()->getType()->isRealFloatingType()) - Ops.LHS = ComplexPairTy(CGF.EmitScalarExpr(E->getLHS()), nullptr); - else - Ops.LHS = Visit(E->getLHS()); - if (E->getRHS()->getType()->isRealFloatingType()) - Ops.RHS = ComplexPairTy(CGF.EmitScalarExpr(E->getRHS()), nullptr); - else - Ops.RHS = Visit(E->getRHS()); - - Ops.Ty = E->getType(); - return Ops; -} - - -LValue ComplexExprEmitter:: -EmitCompoundAssignLValue(const CompoundAssignOperator *E, - ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&), - RValue &Val) { - TestAndClearIgnoreReal(); - TestAndClearIgnoreImag(); - QualType LHSTy = E->getLHS()->getType(); - if (const AtomicType *AT = LHSTy->getAs<AtomicType>()) - LHSTy = AT->getValueType(); - - BinOpInfo OpInfo; - - // Load the RHS and LHS operands. - // __block variables need to have the rhs evaluated first, plus this should - // improve codegen a little. - OpInfo.Ty = E->getComputationResultType(); - QualType ComplexElementTy = cast<ComplexType>(OpInfo.Ty)->getElementType(); - - // The RHS should have been converted to the computation type. - if (E->getRHS()->getType()->isRealFloatingType()) { - assert( - CGF.getContext() - .hasSameUnqualifiedType(ComplexElementTy, E->getRHS()->getType())); - OpInfo.RHS = ComplexPairTy(CGF.EmitScalarExpr(E->getRHS()), nullptr); - } else { - assert(CGF.getContext() - .hasSameUnqualifiedType(OpInfo.Ty, E->getRHS()->getType())); - OpInfo.RHS = Visit(E->getRHS()); - } - - LValue LHS = CGF.EmitLValue(E->getLHS()); - - // Load from the l-value and convert it. - SourceLocation Loc = E->getExprLoc(); - if (LHSTy->isAnyComplexType()) { - ComplexPairTy LHSVal = EmitLoadOfLValue(LHS, Loc); - OpInfo.LHS = EmitComplexToComplexCast(LHSVal, LHSTy, OpInfo.Ty, Loc); - } else { - llvm::Value *LHSVal = CGF.EmitLoadOfScalar(LHS, Loc); - // For floating point real operands we can directly pass the scalar form - // to the binary operator emission and potentially get more efficient code. - if (LHSTy->isRealFloatingType()) { - if (!CGF.getContext().hasSameUnqualifiedType(ComplexElementTy, LHSTy)) - LHSVal = CGF.EmitScalarConversion(LHSVal, LHSTy, ComplexElementTy, Loc); - OpInfo.LHS = ComplexPairTy(LHSVal, nullptr); - } else { - OpInfo.LHS = EmitScalarToComplexCast(LHSVal, LHSTy, OpInfo.Ty, Loc); - } - } - - // Expand the binary operator. - ComplexPairTy Result = (this->*Func)(OpInfo); - - // Truncate the result and store it into the LHS lvalue. - if (LHSTy->isAnyComplexType()) { - ComplexPairTy ResVal = - EmitComplexToComplexCast(Result, OpInfo.Ty, LHSTy, Loc); - EmitStoreOfComplex(ResVal, LHS, /*isInit*/ false); - Val = RValue::getComplex(ResVal); - } else { - llvm::Value *ResVal = - CGF.EmitComplexToScalarConversion(Result, OpInfo.Ty, LHSTy, Loc); - CGF.EmitStoreOfScalar(ResVal, LHS, /*isInit*/ false); - Val = RValue::get(ResVal); - } - - return LHS; -} - -// Compound assignments. -ComplexPairTy ComplexExprEmitter:: -EmitCompoundAssign(const CompoundAssignOperator *E, - ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&)){ - RValue Val; - LValue LV = EmitCompoundAssignLValue(E, Func, Val); - - // The result of an assignment in C is the assigned r-value. - if (!CGF.getLangOpts().CPlusPlus) - return Val.getComplexVal(); - - // If the lvalue is non-volatile, return the computed value of the assignment. - if (!LV.isVolatileQualified()) - return Val.getComplexVal(); - - return EmitLoadOfLValue(LV, E->getExprLoc()); -} - -LValue ComplexExprEmitter::EmitBinAssignLValue(const BinaryOperator *E, - ComplexPairTy &Val) { - assert(CGF.getContext().hasSameUnqualifiedType(E->getLHS()->getType(), - E->getRHS()->getType()) && - "Invalid assignment"); - TestAndClearIgnoreReal(); - TestAndClearIgnoreImag(); - - // Emit the RHS. __block variables need the RHS evaluated first. - Val = Visit(E->getRHS()); - - // Compute the address to store into. - LValue LHS = CGF.EmitLValue(E->getLHS()); - - // Store the result value into the LHS lvalue. - EmitStoreOfComplex(Val, LHS, /*isInit*/ false); - - return LHS; -} - -ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) { - ComplexPairTy Val; - LValue LV = EmitBinAssignLValue(E, Val); - - // The result of an assignment in C is the assigned r-value. - if (!CGF.getLangOpts().CPlusPlus) - return Val; - - // If the lvalue is non-volatile, return the computed value of the assignment. - if (!LV.isVolatileQualified()) - return Val; - - return EmitLoadOfLValue(LV, E->getExprLoc()); -} - -ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) { - CGF.EmitIgnoredExpr(E->getLHS()); - return Visit(E->getRHS()); -} - -ComplexPairTy ComplexExprEmitter:: -VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { - TestAndClearIgnoreReal(); - TestAndClearIgnoreImag(); - llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true"); - llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false"); - llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end"); - - // Bind the common expression if necessary. - CodeGenFunction::OpaqueValueMapping binding(CGF, E); - - - CodeGenFunction::ConditionalEvaluation eval(CGF); - CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock, - CGF.getProfileCount(E)); - - eval.begin(CGF); - CGF.EmitBlock(LHSBlock); - CGF.incrementProfileCounter(E); - ComplexPairTy LHS = Visit(E->getTrueExpr()); - LHSBlock = Builder.GetInsertBlock(); - CGF.EmitBranch(ContBlock); - eval.end(CGF); - - eval.begin(CGF); - CGF.EmitBlock(RHSBlock); - ComplexPairTy RHS = Visit(E->getFalseExpr()); - RHSBlock = Builder.GetInsertBlock(); - CGF.EmitBlock(ContBlock); - eval.end(CGF); - - // Create a PHI node for the real part. - llvm::PHINode *RealPN = Builder.CreatePHI(LHS.first->getType(), 2, "cond.r"); - RealPN->addIncoming(LHS.first, LHSBlock); - RealPN->addIncoming(RHS.first, RHSBlock); - - // Create a PHI node for the imaginary part. - llvm::PHINode *ImagPN = Builder.CreatePHI(LHS.first->getType(), 2, "cond.i"); - ImagPN->addIncoming(LHS.second, LHSBlock); - ImagPN->addIncoming(RHS.second, RHSBlock); - - return ComplexPairTy(RealPN, ImagPN); -} - -ComplexPairTy ComplexExprEmitter::VisitChooseExpr(ChooseExpr *E) { - return Visit(E->getChosenSubExpr()); -} - -ComplexPairTy ComplexExprEmitter::VisitInitListExpr(InitListExpr *E) { - bool Ignore = TestAndClearIgnoreReal(); - (void)Ignore; - assert (Ignore == false && "init list ignored"); - Ignore = TestAndClearIgnoreImag(); - (void)Ignore; - assert (Ignore == false && "init list ignored"); - - if (E->getNumInits() == 2) { - llvm::Value *Real = CGF.EmitScalarExpr(E->getInit(0)); - llvm::Value *Imag = CGF.EmitScalarExpr(E->getInit(1)); - return ComplexPairTy(Real, Imag); - } else if (E->getNumInits() == 1) { - return Visit(E->getInit(0)); - } - - // Empty init list initializes to null - assert(E->getNumInits() == 0 && "Unexpected number of inits"); - QualType Ty = E->getType()->castAs<ComplexType>()->getElementType(); - llvm::Type* LTy = CGF.ConvertType(Ty); - llvm::Value* zeroConstant = llvm::Constant::getNullValue(LTy); - return ComplexPairTy(zeroConstant, zeroConstant); -} - -ComplexPairTy ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *E) { - Address ArgValue = Address::invalid(); - Address ArgPtr = CGF.EmitVAArg(E, ArgValue); - - if (!ArgPtr.isValid()) { - CGF.ErrorUnsupported(E, "complex va_arg expression"); - llvm::Type *EltTy = - CGF.ConvertType(E->getType()->castAs<ComplexType>()->getElementType()); - llvm::Value *U = llvm::UndefValue::get(EltTy); - return ComplexPairTy(U, U); - } - - return EmitLoadOfLValue(CGF.MakeAddrLValue(ArgPtr, E->getType()), - E->getExprLoc()); -} - -//===----------------------------------------------------------------------===// -// Entry Point into this File -//===----------------------------------------------------------------------===// - -/// EmitComplexExpr - Emit the computation of the specified expression of -/// complex type, ignoring the result. -ComplexPairTy CodeGenFunction::EmitComplexExpr(const Expr *E, bool IgnoreReal, - bool IgnoreImag) { - assert(E && getComplexType(E->getType()) && - "Invalid complex expression to emit"); - - return ComplexExprEmitter(*this, IgnoreReal, IgnoreImag) - .Visit(const_cast<Expr *>(E)); -} - -void CodeGenFunction::EmitComplexExprIntoLValue(const Expr *E, LValue dest, - bool isInit) { - assert(E && getComplexType(E->getType()) && - "Invalid complex expression to emit"); - ComplexExprEmitter Emitter(*this); - ComplexPairTy Val = Emitter.Visit(const_cast<Expr*>(E)); - Emitter.EmitStoreOfComplex(Val, dest, isInit); -} - -/// EmitStoreOfComplex - Store a complex number into the specified l-value. -void CodeGenFunction::EmitStoreOfComplex(ComplexPairTy V, LValue dest, - bool isInit) { - ComplexExprEmitter(*this).EmitStoreOfComplex(V, dest, isInit); -} - -/// EmitLoadOfComplex - Load a complex number from the specified address. -ComplexPairTy CodeGenFunction::EmitLoadOfComplex(LValue src, - SourceLocation loc) { - return ComplexExprEmitter(*this).EmitLoadOfLValue(src, loc); -} - -LValue CodeGenFunction::EmitComplexAssignmentLValue(const BinaryOperator *E) { - assert(E->getOpcode() == BO_Assign); - ComplexPairTy Val; // ignored - return ComplexExprEmitter(*this).EmitBinAssignLValue(E, Val); -} - -typedef ComplexPairTy (ComplexExprEmitter::*CompoundFunc)( - const ComplexExprEmitter::BinOpInfo &); - -static CompoundFunc getComplexOp(BinaryOperatorKind Op) { - switch (Op) { - case BO_MulAssign: return &ComplexExprEmitter::EmitBinMul; - case BO_DivAssign: return &ComplexExprEmitter::EmitBinDiv; - case BO_SubAssign: return &ComplexExprEmitter::EmitBinSub; - case BO_AddAssign: return &ComplexExprEmitter::EmitBinAdd; - default: - llvm_unreachable("unexpected complex compound assignment"); - } -} - -LValue CodeGenFunction:: -EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E) { - CompoundFunc Op = getComplexOp(E->getOpcode()); - RValue Val; - return ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Op, Val); -} - -LValue CodeGenFunction:: -EmitScalarCompoundAssignWithComplex(const CompoundAssignOperator *E, - llvm::Value *&Result) { - CompoundFunc Op = getComplexOp(E->getOpcode()); - RValue Val; - LValue Ret = ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Op, Val); - Result = Val.getScalarVal(); - return Ret; -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp deleted file mode 100644 index c9475840aee..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp +++ /dev/null @@ -1,2176 +0,0 @@ -//===--- CGExprConstant.cpp - Emit LLVM Code from Constant Expressions ----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code to emit Constant Expr nodes as LLVM code. -// -//===----------------------------------------------------------------------===// - -#include "CodeGenFunction.h" -#include "CGCXXABI.h" -#include "CGObjCRuntime.h" -#include "CGRecordLayout.h" -#include "CodeGenModule.h" -#include "ConstantEmitter.h" -#include "TargetInfo.h" -#include "clang/AST/APValue.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/RecordLayout.h" -#include "clang/AST/StmtVisitor.h" -#include "clang/Basic/Builtins.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalVariable.h" -using namespace clang; -using namespace CodeGen; - -//===----------------------------------------------------------------------===// -// ConstStructBuilder -//===----------------------------------------------------------------------===// - -namespace { -class ConstExprEmitter; -class ConstStructBuilder { - CodeGenModule &CGM; - ConstantEmitter &Emitter; - - bool Packed; - CharUnits NextFieldOffsetInChars; - CharUnits LLVMStructAlignment; - SmallVector<llvm::Constant *, 32> Elements; -public: - static llvm::Constant *BuildStruct(ConstantEmitter &Emitter, - ConstExprEmitter *ExprEmitter, - llvm::Constant *Base, - InitListExpr *Updater, - QualType ValTy); - static llvm::Constant *BuildStruct(ConstantEmitter &Emitter, - InitListExpr *ILE, QualType StructTy); - static llvm::Constant *BuildStruct(ConstantEmitter &Emitter, - const APValue &Value, QualType ValTy); - -private: - ConstStructBuilder(ConstantEmitter &emitter) - : CGM(emitter.CGM), Emitter(emitter), Packed(false), - NextFieldOffsetInChars(CharUnits::Zero()), - LLVMStructAlignment(CharUnits::One()) { } - - void AppendField(const FieldDecl *Field, uint64_t FieldOffset, - llvm::Constant *InitExpr); - - void AppendBytes(CharUnits FieldOffsetInChars, llvm::Constant *InitCst); - - void AppendBitField(const FieldDecl *Field, uint64_t FieldOffset, - llvm::ConstantInt *InitExpr); - - void AppendPadding(CharUnits PadSize); - - void AppendTailPadding(CharUnits RecordSize); - - void ConvertStructToPacked(); - - bool Build(InitListExpr *ILE); - bool Build(ConstExprEmitter *Emitter, llvm::Constant *Base, - InitListExpr *Updater); - bool Build(const APValue &Val, const RecordDecl *RD, bool IsPrimaryBase, - const CXXRecordDecl *VTableClass, CharUnits BaseOffset); - llvm::Constant *Finalize(QualType Ty); - - CharUnits getAlignment(const llvm::Constant *C) const { - if (Packed) return CharUnits::One(); - return CharUnits::fromQuantity( - CGM.getDataLayout().getABITypeAlignment(C->getType())); - } - - CharUnits getSizeInChars(const llvm::Constant *C) const { - return CharUnits::fromQuantity( - CGM.getDataLayout().getTypeAllocSize(C->getType())); - } -}; - -void ConstStructBuilder:: -AppendField(const FieldDecl *Field, uint64_t FieldOffset, - llvm::Constant *InitCst) { - const ASTContext &Context = CGM.getContext(); - - CharUnits FieldOffsetInChars = Context.toCharUnitsFromBits(FieldOffset); - - AppendBytes(FieldOffsetInChars, InitCst); -} - -void ConstStructBuilder:: -AppendBytes(CharUnits FieldOffsetInChars, llvm::Constant *InitCst) { - - assert(NextFieldOffsetInChars <= FieldOffsetInChars - && "Field offset mismatch!"); - - CharUnits FieldAlignment = getAlignment(InitCst); - - // Round up the field offset to the alignment of the field type. - CharUnits AlignedNextFieldOffsetInChars = - NextFieldOffsetInChars.alignTo(FieldAlignment); - - if (AlignedNextFieldOffsetInChars < FieldOffsetInChars) { - // We need to append padding. - AppendPadding(FieldOffsetInChars - NextFieldOffsetInChars); - - assert(NextFieldOffsetInChars == FieldOffsetInChars && - "Did not add enough padding!"); - - AlignedNextFieldOffsetInChars = - NextFieldOffsetInChars.alignTo(FieldAlignment); - } - - if (AlignedNextFieldOffsetInChars > FieldOffsetInChars) { - assert(!Packed && "Alignment is wrong even with a packed struct!"); - - // Convert the struct to a packed struct. - ConvertStructToPacked(); - - // After we pack the struct, we may need to insert padding. - if (NextFieldOffsetInChars < FieldOffsetInChars) { - // We need to append padding. - AppendPadding(FieldOffsetInChars - NextFieldOffsetInChars); - - assert(NextFieldOffsetInChars == FieldOffsetInChars && - "Did not add enough padding!"); - } - AlignedNextFieldOffsetInChars = NextFieldOffsetInChars; - } - - // Add the field. - Elements.push_back(InitCst); - NextFieldOffsetInChars = AlignedNextFieldOffsetInChars + - getSizeInChars(InitCst); - - if (Packed) - assert(LLVMStructAlignment == CharUnits::One() && - "Packed struct not byte-aligned!"); - else - LLVMStructAlignment = std::max(LLVMStructAlignment, FieldAlignment); -} - -void ConstStructBuilder::AppendBitField(const FieldDecl *Field, - uint64_t FieldOffset, - llvm::ConstantInt *CI) { - const ASTContext &Context = CGM.getContext(); - const uint64_t CharWidth = Context.getCharWidth(); - uint64_t NextFieldOffsetInBits = Context.toBits(NextFieldOffsetInChars); - if (FieldOffset > NextFieldOffsetInBits) { - // We need to add padding. - CharUnits PadSize = Context.toCharUnitsFromBits( - llvm::alignTo(FieldOffset - NextFieldOffsetInBits, - Context.getTargetInfo().getCharAlign())); - - AppendPadding(PadSize); - } - - uint64_t FieldSize = Field->getBitWidthValue(Context); - - llvm::APInt FieldValue = CI->getValue(); - - // Promote the size of FieldValue if necessary - // FIXME: This should never occur, but currently it can because initializer - // constants are cast to bool, and because clang is not enforcing bitfield - // width limits. - if (FieldSize > FieldValue.getBitWidth()) - FieldValue = FieldValue.zext(FieldSize); - - // Truncate the size of FieldValue to the bit field size. - if (FieldSize < FieldValue.getBitWidth()) - FieldValue = FieldValue.trunc(FieldSize); - - NextFieldOffsetInBits = Context.toBits(NextFieldOffsetInChars); - if (FieldOffset < NextFieldOffsetInBits) { - // Either part of the field or the entire field can go into the previous - // byte. - assert(!Elements.empty() && "Elements can't be empty!"); - - unsigned BitsInPreviousByte = NextFieldOffsetInBits - FieldOffset; - - bool FitsCompletelyInPreviousByte = - BitsInPreviousByte >= FieldValue.getBitWidth(); - - llvm::APInt Tmp = FieldValue; - - if (!FitsCompletelyInPreviousByte) { - unsigned NewFieldWidth = FieldSize - BitsInPreviousByte; - - if (CGM.getDataLayout().isBigEndian()) { - Tmp.lshrInPlace(NewFieldWidth); - Tmp = Tmp.trunc(BitsInPreviousByte); - - // We want the remaining high bits. - FieldValue = FieldValue.trunc(NewFieldWidth); - } else { - Tmp = Tmp.trunc(BitsInPreviousByte); - - // We want the remaining low bits. - FieldValue.lshrInPlace(BitsInPreviousByte); - FieldValue = FieldValue.trunc(NewFieldWidth); - } - } - - Tmp = Tmp.zext(CharWidth); - if (CGM.getDataLayout().isBigEndian()) { - if (FitsCompletelyInPreviousByte) - Tmp = Tmp.shl(BitsInPreviousByte - FieldValue.getBitWidth()); - } else { - Tmp = Tmp.shl(CharWidth - BitsInPreviousByte); - } - - // 'or' in the bits that go into the previous byte. - llvm::Value *LastElt = Elements.back(); - if (llvm::ConstantInt *Val = dyn_cast<llvm::ConstantInt>(LastElt)) - Tmp |= Val->getValue(); - else { - assert(isa<llvm::UndefValue>(LastElt)); - // If there is an undef field that we're adding to, it can either be a - // scalar undef (in which case, we just replace it with our field) or it - // is an array. If it is an array, we have to pull one byte off the - // array so that the other undef bytes stay around. - if (!isa<llvm::IntegerType>(LastElt->getType())) { - // The undef padding will be a multibyte array, create a new smaller - // padding and then an hole for our i8 to get plopped into. - assert(isa<llvm::ArrayType>(LastElt->getType()) && - "Expected array padding of undefs"); - llvm::ArrayType *AT = cast<llvm::ArrayType>(LastElt->getType()); - assert(AT->getElementType()->isIntegerTy(CharWidth) && - AT->getNumElements() != 0 && - "Expected non-empty array padding of undefs"); - - // Remove the padding array. - NextFieldOffsetInChars -= CharUnits::fromQuantity(AT->getNumElements()); - Elements.pop_back(); - - // Add the padding back in two chunks. - AppendPadding(CharUnits::fromQuantity(AT->getNumElements()-1)); - AppendPadding(CharUnits::One()); - assert(isa<llvm::UndefValue>(Elements.back()) && - Elements.back()->getType()->isIntegerTy(CharWidth) && - "Padding addition didn't work right"); - } - } - - Elements.back() = llvm::ConstantInt::get(CGM.getLLVMContext(), Tmp); - - if (FitsCompletelyInPreviousByte) - return; - } - - while (FieldValue.getBitWidth() > CharWidth) { - llvm::APInt Tmp; - - if (CGM.getDataLayout().isBigEndian()) { - // We want the high bits. - Tmp = - FieldValue.lshr(FieldValue.getBitWidth() - CharWidth).trunc(CharWidth); - } else { - // We want the low bits. - Tmp = FieldValue.trunc(CharWidth); - - FieldValue.lshrInPlace(CharWidth); - } - - Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(), Tmp)); - ++NextFieldOffsetInChars; - - FieldValue = FieldValue.trunc(FieldValue.getBitWidth() - CharWidth); - } - - assert(FieldValue.getBitWidth() > 0 && - "Should have at least one bit left!"); - assert(FieldValue.getBitWidth() <= CharWidth && - "Should not have more than a byte left!"); - - if (FieldValue.getBitWidth() < CharWidth) { - if (CGM.getDataLayout().isBigEndian()) { - unsigned BitWidth = FieldValue.getBitWidth(); - - FieldValue = FieldValue.zext(CharWidth) << (CharWidth - BitWidth); - } else - FieldValue = FieldValue.zext(CharWidth); - } - - // Append the last element. - Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(), - FieldValue)); - ++NextFieldOffsetInChars; -} - -void ConstStructBuilder::AppendPadding(CharUnits PadSize) { - if (PadSize.isZero()) - return; - - llvm::Type *Ty = CGM.Int8Ty; - if (PadSize > CharUnits::One()) - Ty = llvm::ArrayType::get(Ty, PadSize.getQuantity()); - - llvm::Constant *C = llvm::UndefValue::get(Ty); - Elements.push_back(C); - assert(getAlignment(C) == CharUnits::One() && - "Padding must have 1 byte alignment!"); - - NextFieldOffsetInChars += getSizeInChars(C); -} - -void ConstStructBuilder::AppendTailPadding(CharUnits RecordSize) { - assert(NextFieldOffsetInChars <= RecordSize && - "Size mismatch!"); - - AppendPadding(RecordSize - NextFieldOffsetInChars); -} - -void ConstStructBuilder::ConvertStructToPacked() { - SmallVector<llvm::Constant *, 16> PackedElements; - CharUnits ElementOffsetInChars = CharUnits::Zero(); - - for (unsigned i = 0, e = Elements.size(); i != e; ++i) { - llvm::Constant *C = Elements[i]; - - CharUnits ElementAlign = CharUnits::fromQuantity( - CGM.getDataLayout().getABITypeAlignment(C->getType())); - CharUnits AlignedElementOffsetInChars = - ElementOffsetInChars.alignTo(ElementAlign); - - if (AlignedElementOffsetInChars > ElementOffsetInChars) { - // We need some padding. - CharUnits NumChars = - AlignedElementOffsetInChars - ElementOffsetInChars; - - llvm::Type *Ty = CGM.Int8Ty; - if (NumChars > CharUnits::One()) - Ty = llvm::ArrayType::get(Ty, NumChars.getQuantity()); - - llvm::Constant *Padding = llvm::UndefValue::get(Ty); - PackedElements.push_back(Padding); - ElementOffsetInChars += getSizeInChars(Padding); - } - - PackedElements.push_back(C); - ElementOffsetInChars += getSizeInChars(C); - } - - assert(ElementOffsetInChars == NextFieldOffsetInChars && - "Packing the struct changed its size!"); - - Elements.swap(PackedElements); - LLVMStructAlignment = CharUnits::One(); - Packed = true; -} - -bool ConstStructBuilder::Build(InitListExpr *ILE) { - RecordDecl *RD = ILE->getType()->getAs<RecordType>()->getDecl(); - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - - unsigned FieldNo = 0; - unsigned ElementNo = 0; - - // Bail out if we have base classes. We could support these, but they only - // arise in C++1z where we will have already constant folded most interesting - // cases. FIXME: There are still a few more cases we can handle this way. - if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) - if (CXXRD->getNumBases()) - return false; - - for (RecordDecl::field_iterator Field = RD->field_begin(), - FieldEnd = RD->field_end(); Field != FieldEnd; ++Field, ++FieldNo) { - // If this is a union, skip all the fields that aren't being initialized. - if (RD->isUnion() && ILE->getInitializedFieldInUnion() != *Field) - continue; - - // Don't emit anonymous bitfields, they just affect layout. - if (Field->isUnnamedBitfield()) - continue; - - // Get the initializer. A struct can include fields without initializers, - // we just use explicit null values for them. - llvm::Constant *EltInit; - if (ElementNo < ILE->getNumInits()) - EltInit = Emitter.tryEmitPrivateForMemory(ILE->getInit(ElementNo++), - Field->getType()); - else - EltInit = Emitter.emitNullForMemory(Field->getType()); - - if (!EltInit) - return false; - - if (!Field->isBitField()) { - // Handle non-bitfield members. - AppendField(*Field, Layout.getFieldOffset(FieldNo), EltInit); - } else { - // Otherwise we have a bitfield. - if (auto *CI = dyn_cast<llvm::ConstantInt>(EltInit)) { - AppendBitField(*Field, Layout.getFieldOffset(FieldNo), CI); - } else { - // We are trying to initialize a bitfield with a non-trivial constant, - // this must require run-time code. - return false; - } - } - } - - return true; -} - -namespace { -struct BaseInfo { - BaseInfo(const CXXRecordDecl *Decl, CharUnits Offset, unsigned Index) - : Decl(Decl), Offset(Offset), Index(Index) { - } - - const CXXRecordDecl *Decl; - CharUnits Offset; - unsigned Index; - - bool operator<(const BaseInfo &O) const { return Offset < O.Offset; } -}; -} - -bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD, - bool IsPrimaryBase, - const CXXRecordDecl *VTableClass, - CharUnits Offset) { - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - - if (const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD)) { - // Add a vtable pointer, if we need one and it hasn't already been added. - if (CD->isDynamicClass() && !IsPrimaryBase) { - llvm::Constant *VTableAddressPoint = - CGM.getCXXABI().getVTableAddressPointForConstExpr( - BaseSubobject(CD, Offset), VTableClass); - AppendBytes(Offset, VTableAddressPoint); - } - - // Accumulate and sort bases, in order to visit them in address order, which - // may not be the same as declaration order. - SmallVector<BaseInfo, 8> Bases; - Bases.reserve(CD->getNumBases()); - unsigned BaseNo = 0; - for (CXXRecordDecl::base_class_const_iterator Base = CD->bases_begin(), - BaseEnd = CD->bases_end(); Base != BaseEnd; ++Base, ++BaseNo) { - assert(!Base->isVirtual() && "should not have virtual bases here"); - const CXXRecordDecl *BD = Base->getType()->getAsCXXRecordDecl(); - CharUnits BaseOffset = Layout.getBaseClassOffset(BD); - Bases.push_back(BaseInfo(BD, BaseOffset, BaseNo)); - } - std::stable_sort(Bases.begin(), Bases.end()); - - for (unsigned I = 0, N = Bases.size(); I != N; ++I) { - BaseInfo &Base = Bases[I]; - - bool IsPrimaryBase = Layout.getPrimaryBase() == Base.Decl; - Build(Val.getStructBase(Base.Index), Base.Decl, IsPrimaryBase, - VTableClass, Offset + Base.Offset); - } - } - - unsigned FieldNo = 0; - uint64_t OffsetBits = CGM.getContext().toBits(Offset); - - for (RecordDecl::field_iterator Field = RD->field_begin(), - FieldEnd = RD->field_end(); Field != FieldEnd; ++Field, ++FieldNo) { - // If this is a union, skip all the fields that aren't being initialized. - if (RD->isUnion() && Val.getUnionField() != *Field) - continue; - - // Don't emit anonymous bitfields, they just affect layout. - if (Field->isUnnamedBitfield()) - continue; - - // Emit the value of the initializer. - const APValue &FieldValue = - RD->isUnion() ? Val.getUnionValue() : Val.getStructField(FieldNo); - llvm::Constant *EltInit = - Emitter.tryEmitPrivateForMemory(FieldValue, Field->getType()); - if (!EltInit) - return false; - - if (!Field->isBitField()) { - // Handle non-bitfield members. - AppendField(*Field, Layout.getFieldOffset(FieldNo) + OffsetBits, EltInit); - } else { - // Otherwise we have a bitfield. - AppendBitField(*Field, Layout.getFieldOffset(FieldNo) + OffsetBits, - cast<llvm::ConstantInt>(EltInit)); - } - } - - return true; -} - -llvm::Constant *ConstStructBuilder::Finalize(QualType Ty) { - RecordDecl *RD = Ty->getAs<RecordType>()->getDecl(); - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - - CharUnits LayoutSizeInChars = Layout.getSize(); - - if (NextFieldOffsetInChars > LayoutSizeInChars) { - // If the struct is bigger than the size of the record type, - // we must have a flexible array member at the end. - assert(RD->hasFlexibleArrayMember() && - "Must have flexible array member if struct is bigger than type!"); - - // No tail padding is necessary. - } else { - // Append tail padding if necessary. - CharUnits LLVMSizeInChars = - NextFieldOffsetInChars.alignTo(LLVMStructAlignment); - - if (LLVMSizeInChars != LayoutSizeInChars) - AppendTailPadding(LayoutSizeInChars); - - LLVMSizeInChars = NextFieldOffsetInChars.alignTo(LLVMStructAlignment); - - // Check if we need to convert the struct to a packed struct. - if (NextFieldOffsetInChars <= LayoutSizeInChars && - LLVMSizeInChars > LayoutSizeInChars) { - assert(!Packed && "Size mismatch!"); - - ConvertStructToPacked(); - assert(NextFieldOffsetInChars <= LayoutSizeInChars && - "Converting to packed did not help!"); - } - - LLVMSizeInChars = NextFieldOffsetInChars.alignTo(LLVMStructAlignment); - - assert(LayoutSizeInChars == LLVMSizeInChars && - "Tail padding mismatch!"); - } - - // Pick the type to use. If the type is layout identical to the ConvertType - // type then use it, otherwise use whatever the builder produced for us. - llvm::StructType *STy = - llvm::ConstantStruct::getTypeForElements(CGM.getLLVMContext(), - Elements, Packed); - llvm::Type *ValTy = CGM.getTypes().ConvertType(Ty); - if (llvm::StructType *ValSTy = dyn_cast<llvm::StructType>(ValTy)) { - if (ValSTy->isLayoutIdentical(STy)) - STy = ValSTy; - } - - llvm::Constant *Result = llvm::ConstantStruct::get(STy, Elements); - - assert(NextFieldOffsetInChars.alignTo(getAlignment(Result)) == - getSizeInChars(Result) && - "Size mismatch!"); - - return Result; -} - -llvm::Constant *ConstStructBuilder::BuildStruct(ConstantEmitter &Emitter, - ConstExprEmitter *ExprEmitter, - llvm::Constant *Base, - InitListExpr *Updater, - QualType ValTy) { - ConstStructBuilder Builder(Emitter); - if (!Builder.Build(ExprEmitter, Base, Updater)) - return nullptr; - return Builder.Finalize(ValTy); -} - -llvm::Constant *ConstStructBuilder::BuildStruct(ConstantEmitter &Emitter, - InitListExpr *ILE, - QualType ValTy) { - ConstStructBuilder Builder(Emitter); - - if (!Builder.Build(ILE)) - return nullptr; - - return Builder.Finalize(ValTy); -} - -llvm::Constant *ConstStructBuilder::BuildStruct(ConstantEmitter &Emitter, - const APValue &Val, - QualType ValTy) { - ConstStructBuilder Builder(Emitter); - - const RecordDecl *RD = ValTy->castAs<RecordType>()->getDecl(); - const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD); - if (!Builder.Build(Val, RD, false, CD, CharUnits::Zero())) - return nullptr; - - return Builder.Finalize(ValTy); -} - - -//===----------------------------------------------------------------------===// -// ConstExprEmitter -//===----------------------------------------------------------------------===// - -static ConstantAddress tryEmitGlobalCompoundLiteral(CodeGenModule &CGM, - CodeGenFunction *CGF, - const CompoundLiteralExpr *E) { - CharUnits Align = CGM.getContext().getTypeAlignInChars(E->getType()); - if (llvm::GlobalVariable *Addr = - CGM.getAddrOfConstantCompoundLiteralIfEmitted(E)) - return ConstantAddress(Addr, Align); - - LangAS addressSpace = E->getType().getAddressSpace(); - - ConstantEmitter emitter(CGM, CGF); - llvm::Constant *C = emitter.tryEmitForInitializer(E->getInitializer(), - addressSpace, E->getType()); - if (!C) { - assert(!E->isFileScope() && - "file-scope compound literal did not have constant initializer!"); - return ConstantAddress::invalid(); - } - - auto GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), - CGM.isTypeConstant(E->getType(), true), - llvm::GlobalValue::InternalLinkage, - C, ".compoundliteral", nullptr, - llvm::GlobalVariable::NotThreadLocal, - CGM.getContext().getTargetAddressSpace(addressSpace)); - emitter.finalize(GV); - GV->setAlignment(Align.getQuantity()); - CGM.setAddrOfConstantCompoundLiteral(E, GV); - return ConstantAddress(GV, Align); -} - -static llvm::Constant * -EmitArrayConstant(CodeGenModule &CGM, const ConstantArrayType *DestType, - llvm::Type *CommonElementType, unsigned ArrayBound, - SmallVectorImpl<llvm::Constant *> &Elements, - llvm::Constant *Filler) { - // Figure out how long the initial prefix of non-zero elements is. - unsigned NonzeroLength = ArrayBound; - if (Elements.size() < NonzeroLength && Filler->isNullValue()) - NonzeroLength = Elements.size(); - if (NonzeroLength == Elements.size()) { - while (NonzeroLength > 0 && Elements[NonzeroLength - 1]->isNullValue()) - --NonzeroLength; - } - - if (NonzeroLength == 0) { - return llvm::ConstantAggregateZero::get( - CGM.getTypes().ConvertType(QualType(DestType, 0))); - } - - // Add a zeroinitializer array filler if we have lots of trailing zeroes. - unsigned TrailingZeroes = ArrayBound - NonzeroLength; - if (TrailingZeroes >= 8) { - assert(Elements.size() >= NonzeroLength && - "missing initializer for non-zero element"); - - // If all the elements had the same type up to the trailing zeroes, emit a - // struct of two arrays (the nonzero data and the zeroinitializer). - if (CommonElementType && NonzeroLength >= 8) { - llvm::Constant *Initial = llvm::ConstantArray::get( - llvm::ArrayType::get(CommonElementType, NonzeroLength), - makeArrayRef(Elements).take_front(NonzeroLength)); - Elements.resize(2); - Elements[0] = Initial; - } else { - Elements.resize(NonzeroLength + 1); - } - - auto *FillerType = - CommonElementType - ? CommonElementType - : CGM.getTypes().ConvertType(DestType->getElementType()); - FillerType = llvm::ArrayType::get(FillerType, TrailingZeroes); - Elements.back() = llvm::ConstantAggregateZero::get(FillerType); - CommonElementType = nullptr; - } else if (Elements.size() != ArrayBound) { - // Otherwise pad to the right size with the filler if necessary. - Elements.resize(ArrayBound, Filler); - if (Filler->getType() != CommonElementType) - CommonElementType = nullptr; - } - - // If all elements have the same type, just emit an array constant. - if (CommonElementType) - return llvm::ConstantArray::get( - llvm::ArrayType::get(CommonElementType, ArrayBound), Elements); - - // We have mixed types. Use a packed struct. - llvm::SmallVector<llvm::Type *, 16> Types; - Types.reserve(Elements.size()); - for (llvm::Constant *Elt : Elements) - Types.push_back(Elt->getType()); - llvm::StructType *SType = - llvm::StructType::get(CGM.getLLVMContext(), Types, true); - return llvm::ConstantStruct::get(SType, Elements); -} - -/// This class only needs to handle two cases: -/// 1) Literals (this is used by APValue emission to emit literals). -/// 2) Arrays, structs and unions (outside C++11 mode, we don't currently -/// constant fold these types). -class ConstExprEmitter : - public StmtVisitor<ConstExprEmitter, llvm::Constant*, QualType> { - CodeGenModule &CGM; - ConstantEmitter &Emitter; - llvm::LLVMContext &VMContext; -public: - ConstExprEmitter(ConstantEmitter &emitter) - : CGM(emitter.CGM), Emitter(emitter), VMContext(CGM.getLLVMContext()) { - } - - //===--------------------------------------------------------------------===// - // Visitor Methods - //===--------------------------------------------------------------------===// - - llvm::Constant *VisitStmt(Stmt *S, QualType T) { - return nullptr; - } - - llvm::Constant *VisitConstantExpr(ConstantExpr *CE, QualType T) { - return Visit(CE->getSubExpr(), T); - } - - llvm::Constant *VisitParenExpr(ParenExpr *PE, QualType T) { - return Visit(PE->getSubExpr(), T); - } - - llvm::Constant * - VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *PE, - QualType T) { - return Visit(PE->getReplacement(), T); - } - - llvm::Constant *VisitGenericSelectionExpr(GenericSelectionExpr *GE, - QualType T) { - return Visit(GE->getResultExpr(), T); - } - - llvm::Constant *VisitChooseExpr(ChooseExpr *CE, QualType T) { - return Visit(CE->getChosenSubExpr(), T); - } - - llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E, QualType T) { - return Visit(E->getInitializer(), T); - } - - llvm::Constant *VisitCastExpr(CastExpr *E, QualType destType) { - if (const auto *ECE = dyn_cast<ExplicitCastExpr>(E)) - CGM.EmitExplicitCastExprType(ECE, Emitter.CGF); - Expr *subExpr = E->getSubExpr(); - - switch (E->getCastKind()) { - case CK_ToUnion: { - // GCC cast to union extension - assert(E->getType()->isUnionType() && - "Destination type is not union type!"); - - auto field = E->getTargetUnionField(); - - auto C = Emitter.tryEmitPrivateForMemory(subExpr, field->getType()); - if (!C) return nullptr; - - auto destTy = ConvertType(destType); - if (C->getType() == destTy) return C; - - // Build a struct with the union sub-element as the first member, - // and padded to the appropriate size. - SmallVector<llvm::Constant*, 2> Elts; - SmallVector<llvm::Type*, 2> Types; - Elts.push_back(C); - Types.push_back(C->getType()); - unsigned CurSize = CGM.getDataLayout().getTypeAllocSize(C->getType()); - unsigned TotalSize = CGM.getDataLayout().getTypeAllocSize(destTy); - - assert(CurSize <= TotalSize && "Union size mismatch!"); - if (unsigned NumPadBytes = TotalSize - CurSize) { - llvm::Type *Ty = CGM.Int8Ty; - if (NumPadBytes > 1) - Ty = llvm::ArrayType::get(Ty, NumPadBytes); - - Elts.push_back(llvm::UndefValue::get(Ty)); - Types.push_back(Ty); - } - - llvm::StructType *STy = llvm::StructType::get(VMContext, Types, false); - return llvm::ConstantStruct::get(STy, Elts); - } - - case CK_AddressSpaceConversion: { - auto C = Emitter.tryEmitPrivate(subExpr, subExpr->getType()); - if (!C) return nullptr; - LangAS destAS = E->getType()->getPointeeType().getAddressSpace(); - LangAS srcAS = subExpr->getType()->getPointeeType().getAddressSpace(); - llvm::Type *destTy = ConvertType(E->getType()); - return CGM.getTargetCodeGenInfo().performAddrSpaceCast(CGM, C, srcAS, - destAS, destTy); - } - - case CK_LValueToRValue: - case CK_AtomicToNonAtomic: - case CK_NonAtomicToAtomic: - case CK_NoOp: - case CK_ConstructorConversion: - return Visit(subExpr, destType); - - case CK_IntToOCLSampler: - llvm_unreachable("global sampler variables are not generated"); - - case CK_Dependent: llvm_unreachable("saw dependent cast!"); - - case CK_BuiltinFnToFnPtr: - llvm_unreachable("builtin functions are handled elsewhere"); - - case CK_ReinterpretMemberPointer: - case CK_DerivedToBaseMemberPointer: - case CK_BaseToDerivedMemberPointer: { - auto C = Emitter.tryEmitPrivate(subExpr, subExpr->getType()); - if (!C) return nullptr; - return CGM.getCXXABI().EmitMemberPointerConversion(E, C); - } - - // These will never be supported. - case CK_ObjCObjectLValueCast: - case CK_ARCProduceObject: - case CK_ARCConsumeObject: - case CK_ARCReclaimReturnedObject: - case CK_ARCExtendBlockObject: - case CK_CopyAndAutoreleaseBlockObject: - return nullptr; - - // These don't need to be handled here because Evaluate knows how to - // evaluate them in the cases where they can be folded. - case CK_BitCast: - case CK_ToVoid: - case CK_Dynamic: - case CK_LValueBitCast: - case CK_NullToMemberPointer: - case CK_UserDefinedConversion: - case CK_CPointerToObjCPointerCast: - case CK_BlockPointerToObjCPointerCast: - case CK_AnyPointerToBlockPointerCast: - case CK_ArrayToPointerDecay: - case CK_FunctionToPointerDecay: - case CK_BaseToDerived: - case CK_DerivedToBase: - case CK_UncheckedDerivedToBase: - case CK_MemberPointerToBoolean: - case CK_VectorSplat: - case CK_FloatingRealToComplex: - case CK_FloatingComplexToReal: - case CK_FloatingComplexToBoolean: - case CK_FloatingComplexCast: - case CK_FloatingComplexToIntegralComplex: - case CK_IntegralRealToComplex: - case CK_IntegralComplexToReal: - case CK_IntegralComplexToBoolean: - case CK_IntegralComplexCast: - case CK_IntegralComplexToFloatingComplex: - case CK_PointerToIntegral: - case CK_PointerToBoolean: - case CK_NullToPointer: - case CK_IntegralCast: - case CK_BooleanToSignedIntegral: - case CK_IntegralToPointer: - case CK_IntegralToBoolean: - case CK_IntegralToFloating: - case CK_FloatingToIntegral: - case CK_FloatingToBoolean: - case CK_FloatingCast: - case CK_FixedPointCast: - case CK_FixedPointToBoolean: - case CK_ZeroToOCLOpaqueType: - return nullptr; - } - llvm_unreachable("Invalid CastKind"); - } - - llvm::Constant *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE, QualType T) { - return Visit(DAE->getExpr(), T); - } - - llvm::Constant *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE, QualType T) { - // No need for a DefaultInitExprScope: we don't handle 'this' in a - // constant expression. - return Visit(DIE->getExpr(), T); - } - - llvm::Constant *VisitExprWithCleanups(ExprWithCleanups *E, QualType T) { - if (!E->cleanupsHaveSideEffects()) - return Visit(E->getSubExpr(), T); - return nullptr; - } - - llvm::Constant *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E, - QualType T) { - return Visit(E->GetTemporaryExpr(), T); - } - - llvm::Constant *EmitArrayInitialization(InitListExpr *ILE, QualType T) { - auto *CAT = CGM.getContext().getAsConstantArrayType(ILE->getType()); - assert(CAT && "can't emit array init for non-constant-bound array"); - unsigned NumInitElements = ILE->getNumInits(); - unsigned NumElements = CAT->getSize().getZExtValue(); - - // Initialising an array requires us to automatically - // initialise any elements that have not been initialised explicitly - unsigned NumInitableElts = std::min(NumInitElements, NumElements); - - QualType EltType = CAT->getElementType(); - - // Initialize remaining array elements. - llvm::Constant *fillC = nullptr; - if (Expr *filler = ILE->getArrayFiller()) { - fillC = Emitter.tryEmitAbstractForMemory(filler, EltType); - if (!fillC) - return nullptr; - } - - // Copy initializer elements. - SmallVector<llvm::Constant*, 16> Elts; - if (fillC && fillC->isNullValue()) - Elts.reserve(NumInitableElts + 1); - else - Elts.reserve(NumElements); - - llvm::Type *CommonElementType = nullptr; - for (unsigned i = 0; i < NumInitableElts; ++i) { - Expr *Init = ILE->getInit(i); - llvm::Constant *C = Emitter.tryEmitPrivateForMemory(Init, EltType); - if (!C) - return nullptr; - if (i == 0) - CommonElementType = C->getType(); - else if (C->getType() != CommonElementType) - CommonElementType = nullptr; - Elts.push_back(C); - } - - return EmitArrayConstant(CGM, CAT, CommonElementType, NumElements, Elts, - fillC); - } - - llvm::Constant *EmitRecordInitialization(InitListExpr *ILE, QualType T) { - return ConstStructBuilder::BuildStruct(Emitter, ILE, T); - } - - llvm::Constant *VisitImplicitValueInitExpr(ImplicitValueInitExpr* E, - QualType T) { - return CGM.EmitNullConstant(T); - } - - llvm::Constant *VisitInitListExpr(InitListExpr *ILE, QualType T) { - if (ILE->isTransparent()) - return Visit(ILE->getInit(0), T); - - if (ILE->getType()->isArrayType()) - return EmitArrayInitialization(ILE, T); - - if (ILE->getType()->isRecordType()) - return EmitRecordInitialization(ILE, T); - - return nullptr; - } - - llvm::Constant *EmitDesignatedInitUpdater(llvm::Constant *Base, - InitListExpr *Updater, - QualType destType) { - if (auto destAT = CGM.getContext().getAsArrayType(destType)) { - llvm::ArrayType *AType = cast<llvm::ArrayType>(ConvertType(destType)); - llvm::Type *ElemType = AType->getElementType(); - - unsigned NumInitElements = Updater->getNumInits(); - unsigned NumElements = AType->getNumElements(); - - std::vector<llvm::Constant *> Elts; - Elts.reserve(NumElements); - - QualType destElemType = destAT->getElementType(); - - if (auto DataArray = dyn_cast<llvm::ConstantDataArray>(Base)) - for (unsigned i = 0; i != NumElements; ++i) - Elts.push_back(DataArray->getElementAsConstant(i)); - else if (auto Array = dyn_cast<llvm::ConstantArray>(Base)) - for (unsigned i = 0; i != NumElements; ++i) - Elts.push_back(Array->getOperand(i)); - else - return nullptr; // FIXME: other array types not implemented - - llvm::Constant *fillC = nullptr; - if (Expr *filler = Updater->getArrayFiller()) - if (!isa<NoInitExpr>(filler)) - fillC = Emitter.tryEmitAbstractForMemory(filler, destElemType); - bool RewriteType = (fillC && fillC->getType() != ElemType); - - for (unsigned i = 0; i != NumElements; ++i) { - Expr *Init = nullptr; - if (i < NumInitElements) - Init = Updater->getInit(i); - - if (!Init && fillC) - Elts[i] = fillC; - else if (!Init || isa<NoInitExpr>(Init)) - ; // Do nothing. - else if (InitListExpr *ChildILE = dyn_cast<InitListExpr>(Init)) - Elts[i] = EmitDesignatedInitUpdater(Elts[i], ChildILE, destElemType); - else - Elts[i] = Emitter.tryEmitPrivateForMemory(Init, destElemType); - - if (!Elts[i]) - return nullptr; - RewriteType |= (Elts[i]->getType() != ElemType); - } - - if (RewriteType) { - std::vector<llvm::Type *> Types; - Types.reserve(NumElements); - for (unsigned i = 0; i != NumElements; ++i) - Types.push_back(Elts[i]->getType()); - llvm::StructType *SType = llvm::StructType::get(AType->getContext(), - Types, true); - return llvm::ConstantStruct::get(SType, Elts); - } - - return llvm::ConstantArray::get(AType, Elts); - } - - if (destType->isRecordType()) - return ConstStructBuilder::BuildStruct(Emitter, this, Base, Updater, - destType); - - return nullptr; - } - - llvm::Constant *VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E, - QualType destType) { - auto C = Visit(E->getBase(), destType); - if (!C) return nullptr; - return EmitDesignatedInitUpdater(C, E->getUpdater(), destType); - } - - llvm::Constant *VisitCXXConstructExpr(CXXConstructExpr *E, QualType Ty) { - if (!E->getConstructor()->isTrivial()) - return nullptr; - - // FIXME: We should not have to call getBaseElementType here. - const RecordType *RT = - CGM.getContext().getBaseElementType(Ty)->getAs<RecordType>(); - const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - - // If the class doesn't have a trivial destructor, we can't emit it as a - // constant expr. - if (!RD->hasTrivialDestructor()) - return nullptr; - - // Only copy and default constructors can be trivial. - - - if (E->getNumArgs()) { - assert(E->getNumArgs() == 1 && "trivial ctor with > 1 argument"); - assert(E->getConstructor()->isCopyOrMoveConstructor() && - "trivial ctor has argument but isn't a copy/move ctor"); - - Expr *Arg = E->getArg(0); - assert(CGM.getContext().hasSameUnqualifiedType(Ty, Arg->getType()) && - "argument to copy ctor is of wrong type"); - - return Visit(Arg, Ty); - } - - return CGM.EmitNullConstant(Ty); - } - - llvm::Constant *VisitStringLiteral(StringLiteral *E, QualType T) { - return CGM.GetConstantArrayFromStringLiteral(E); - } - - llvm::Constant *VisitObjCEncodeExpr(ObjCEncodeExpr *E, QualType T) { - // This must be an @encode initializing an array in a static initializer. - // Don't emit it as the address of the string, emit the string data itself - // as an inline array. - std::string Str; - CGM.getContext().getObjCEncodingForType(E->getEncodedType(), Str); - const ConstantArrayType *CAT = CGM.getContext().getAsConstantArrayType(T); - - // Resize the string to the right size, adding zeros at the end, or - // truncating as needed. - Str.resize(CAT->getSize().getZExtValue(), '\0'); - return llvm::ConstantDataArray::getString(VMContext, Str, false); - } - - llvm::Constant *VisitUnaryExtension(const UnaryOperator *E, QualType T) { - return Visit(E->getSubExpr(), T); - } - - // Utility methods - llvm::Type *ConvertType(QualType T) { - return CGM.getTypes().ConvertType(T); - } -}; - -} // end anonymous namespace. - -bool ConstStructBuilder::Build(ConstExprEmitter *ExprEmitter, - llvm::Constant *Base, - InitListExpr *Updater) { - assert(Base && "base expression should not be empty"); - - QualType ExprType = Updater->getType(); - RecordDecl *RD = ExprType->getAs<RecordType>()->getDecl(); - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - const llvm::StructLayout *BaseLayout = CGM.getDataLayout().getStructLayout( - cast<llvm::StructType>(Base->getType())); - unsigned FieldNo = -1; - unsigned ElementNo = 0; - - // Bail out if we have base classes. We could support these, but they only - // arise in C++1z where we will have already constant folded most interesting - // cases. FIXME: There are still a few more cases we can handle this way. - if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) - if (CXXRD->getNumBases()) - return false; - - for (FieldDecl *Field : RD->fields()) { - ++FieldNo; - - if (RD->isUnion() && Updater->getInitializedFieldInUnion() != Field) - continue; - - // Skip anonymous bitfields. - if (Field->isUnnamedBitfield()) - continue; - - llvm::Constant *EltInit = Base->getAggregateElement(ElementNo); - - // Bail out if the type of the ConstantStruct does not have the same layout - // as the type of the InitListExpr. - if (CGM.getTypes().ConvertType(Field->getType()) != EltInit->getType() || - Layout.getFieldOffset(ElementNo) != - BaseLayout->getElementOffsetInBits(ElementNo)) - return false; - - // Get the initializer. If we encounter an empty field or a NoInitExpr, - // we use values from the base expression. - Expr *Init = nullptr; - if (ElementNo < Updater->getNumInits()) - Init = Updater->getInit(ElementNo); - - if (!Init || isa<NoInitExpr>(Init)) - ; // Do nothing. - else if (InitListExpr *ChildILE = dyn_cast<InitListExpr>(Init)) - EltInit = ExprEmitter->EmitDesignatedInitUpdater(EltInit, ChildILE, - Field->getType()); - else - EltInit = Emitter.tryEmitPrivateForMemory(Init, Field->getType()); - - ++ElementNo; - - if (!EltInit) - return false; - - if (!Field->isBitField()) - AppendField(Field, Layout.getFieldOffset(FieldNo), EltInit); - else if (llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(EltInit)) - AppendBitField(Field, Layout.getFieldOffset(FieldNo), CI); - else - // Initializing a bitfield with a non-trivial constant? - return false; - } - - return true; -} - -llvm::Constant *ConstantEmitter::validateAndPopAbstract(llvm::Constant *C, - AbstractState saved) { - Abstract = saved.OldValue; - - assert(saved.OldPlaceholdersSize == PlaceholderAddresses.size() && - "created a placeholder while doing an abstract emission?"); - - // No validation necessary for now. - // No cleanup to do for now. - return C; -} - -llvm::Constant * -ConstantEmitter::tryEmitAbstractForInitializer(const VarDecl &D) { - auto state = pushAbstract(); - auto C = tryEmitPrivateForVarInit(D); - return validateAndPopAbstract(C, state); -} - -llvm::Constant * -ConstantEmitter::tryEmitAbstract(const Expr *E, QualType destType) { - auto state = pushAbstract(); - auto C = tryEmitPrivate(E, destType); - return validateAndPopAbstract(C, state); -} - -llvm::Constant * -ConstantEmitter::tryEmitAbstract(const APValue &value, QualType destType) { - auto state = pushAbstract(); - auto C = tryEmitPrivate(value, destType); - return validateAndPopAbstract(C, state); -} - -llvm::Constant * -ConstantEmitter::emitAbstract(const Expr *E, QualType destType) { - auto state = pushAbstract(); - auto C = tryEmitPrivate(E, destType); - C = validateAndPopAbstract(C, state); - if (!C) { - CGM.Error(E->getExprLoc(), - "internal error: could not emit constant value \"abstractly\""); - C = CGM.EmitNullConstant(destType); - } - return C; -} - -llvm::Constant * -ConstantEmitter::emitAbstract(SourceLocation loc, const APValue &value, - QualType destType) { - auto state = pushAbstract(); - auto C = tryEmitPrivate(value, destType); - C = validateAndPopAbstract(C, state); - if (!C) { - CGM.Error(loc, - "internal error: could not emit constant value \"abstractly\""); - C = CGM.EmitNullConstant(destType); - } - return C; -} - -llvm::Constant *ConstantEmitter::tryEmitForInitializer(const VarDecl &D) { - initializeNonAbstract(D.getType().getAddressSpace()); - return markIfFailed(tryEmitPrivateForVarInit(D)); -} - -llvm::Constant *ConstantEmitter::tryEmitForInitializer(const Expr *E, - LangAS destAddrSpace, - QualType destType) { - initializeNonAbstract(destAddrSpace); - return markIfFailed(tryEmitPrivateForMemory(E, destType)); -} - -llvm::Constant *ConstantEmitter::emitForInitializer(const APValue &value, - LangAS destAddrSpace, - QualType destType) { - initializeNonAbstract(destAddrSpace); - auto C = tryEmitPrivateForMemory(value, destType); - assert(C && "couldn't emit constant value non-abstractly?"); - return C; -} - -llvm::GlobalValue *ConstantEmitter::getCurrentAddrPrivate() { - assert(!Abstract && "cannot get current address for abstract constant"); - - - - // Make an obviously ill-formed global that should blow up compilation - // if it survives. - auto global = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8Ty, true, - llvm::GlobalValue::PrivateLinkage, - /*init*/ nullptr, - /*name*/ "", - /*before*/ nullptr, - llvm::GlobalVariable::NotThreadLocal, - CGM.getContext().getTargetAddressSpace(DestAddressSpace)); - - PlaceholderAddresses.push_back(std::make_pair(nullptr, global)); - - return global; -} - -void ConstantEmitter::registerCurrentAddrPrivate(llvm::Constant *signal, - llvm::GlobalValue *placeholder) { - assert(!PlaceholderAddresses.empty()); - assert(PlaceholderAddresses.back().first == nullptr); - assert(PlaceholderAddresses.back().second == placeholder); - PlaceholderAddresses.back().first = signal; -} - -namespace { - struct ReplacePlaceholders { - CodeGenModule &CGM; - - /// The base address of the global. - llvm::Constant *Base; - llvm::Type *BaseValueTy = nullptr; - - /// The placeholder addresses that were registered during emission. - llvm::DenseMap<llvm::Constant*, llvm::GlobalVariable*> PlaceholderAddresses; - - /// The locations of the placeholder signals. - llvm::DenseMap<llvm::GlobalVariable*, llvm::Constant*> Locations; - - /// The current index stack. We use a simple unsigned stack because - /// we assume that placeholders will be relatively sparse in the - /// initializer, but we cache the index values we find just in case. - llvm::SmallVector<unsigned, 8> Indices; - llvm::SmallVector<llvm::Constant*, 8> IndexValues; - - ReplacePlaceholders(CodeGenModule &CGM, llvm::Constant *base, - ArrayRef<std::pair<llvm::Constant*, - llvm::GlobalVariable*>> addresses) - : CGM(CGM), Base(base), - PlaceholderAddresses(addresses.begin(), addresses.end()) { - } - - void replaceInInitializer(llvm::Constant *init) { - // Remember the type of the top-most initializer. - BaseValueTy = init->getType(); - - // Initialize the stack. - Indices.push_back(0); - IndexValues.push_back(nullptr); - - // Recurse into the initializer. - findLocations(init); - - // Check invariants. - assert(IndexValues.size() == Indices.size() && "mismatch"); - assert(Indices.size() == 1 && "didn't pop all indices"); - - // Do the replacement; this basically invalidates 'init'. - assert(Locations.size() == PlaceholderAddresses.size() && - "missed a placeholder?"); - - // We're iterating over a hashtable, so this would be a source of - // non-determinism in compiler output *except* that we're just - // messing around with llvm::Constant structures, which never itself - // does anything that should be visible in compiler output. - for (auto &entry : Locations) { - assert(entry.first->getParent() == nullptr && "not a placeholder!"); - entry.first->replaceAllUsesWith(entry.second); - entry.first->eraseFromParent(); - } - } - - private: - void findLocations(llvm::Constant *init) { - // Recurse into aggregates. - if (auto agg = dyn_cast<llvm::ConstantAggregate>(init)) { - for (unsigned i = 0, e = agg->getNumOperands(); i != e; ++i) { - Indices.push_back(i); - IndexValues.push_back(nullptr); - - findLocations(agg->getOperand(i)); - - IndexValues.pop_back(); - Indices.pop_back(); - } - return; - } - - // Otherwise, check for registered constants. - while (true) { - auto it = PlaceholderAddresses.find(init); - if (it != PlaceholderAddresses.end()) { - setLocation(it->second); - break; - } - - // Look through bitcasts or other expressions. - if (auto expr = dyn_cast<llvm::ConstantExpr>(init)) { - init = expr->getOperand(0); - } else { - break; - } - } - } - - void setLocation(llvm::GlobalVariable *placeholder) { - assert(Locations.find(placeholder) == Locations.end() && - "already found location for placeholder!"); - - // Lazily fill in IndexValues with the values from Indices. - // We do this in reverse because we should always have a strict - // prefix of indices from the start. - assert(Indices.size() == IndexValues.size()); - for (size_t i = Indices.size() - 1; i != size_t(-1); --i) { - if (IndexValues[i]) { -#ifndef NDEBUG - for (size_t j = 0; j != i + 1; ++j) { - assert(IndexValues[j] && - isa<llvm::ConstantInt>(IndexValues[j]) && - cast<llvm::ConstantInt>(IndexValues[j])->getZExtValue() - == Indices[j]); - } -#endif - break; - } - - IndexValues[i] = llvm::ConstantInt::get(CGM.Int32Ty, Indices[i]); - } - - // Form a GEP and then bitcast to the placeholder type so that the - // replacement will succeed. - llvm::Constant *location = - llvm::ConstantExpr::getInBoundsGetElementPtr(BaseValueTy, - Base, IndexValues); - location = llvm::ConstantExpr::getBitCast(location, - placeholder->getType()); - - Locations.insert({placeholder, location}); - } - }; -} - -void ConstantEmitter::finalize(llvm::GlobalVariable *global) { - assert(InitializedNonAbstract && - "finalizing emitter that was used for abstract emission?"); - assert(!Finalized && "finalizing emitter multiple times"); - assert(global->getInitializer()); - - // Note that we might also be Failed. - Finalized = true; - - if (!PlaceholderAddresses.empty()) { - ReplacePlaceholders(CGM, global, PlaceholderAddresses) - .replaceInInitializer(global->getInitializer()); - PlaceholderAddresses.clear(); // satisfy - } -} - -ConstantEmitter::~ConstantEmitter() { - assert((!InitializedNonAbstract || Finalized || Failed) && - "not finalized after being initialized for non-abstract emission"); - assert(PlaceholderAddresses.empty() && "unhandled placeholders"); -} - -static QualType getNonMemoryType(CodeGenModule &CGM, QualType type) { - if (auto AT = type->getAs<AtomicType>()) { - return CGM.getContext().getQualifiedType(AT->getValueType(), - type.getQualifiers()); - } - return type; -} - -llvm::Constant *ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &D) { - // Make a quick check if variable can be default NULL initialized - // and avoid going through rest of code which may do, for c++11, - // initialization of memory to all NULLs. - if (!D.hasLocalStorage()) { - QualType Ty = CGM.getContext().getBaseElementType(D.getType()); - if (Ty->isRecordType()) - if (const CXXConstructExpr *E = - dyn_cast_or_null<CXXConstructExpr>(D.getInit())) { - const CXXConstructorDecl *CD = E->getConstructor(); - if (CD->isTrivial() && CD->isDefaultConstructor()) - return CGM.EmitNullConstant(D.getType()); - } - InConstantContext = true; - } - - QualType destType = D.getType(); - - // Try to emit the initializer. Note that this can allow some things that - // are not allowed by tryEmitPrivateForMemory alone. - if (auto value = D.evaluateValue()) { - return tryEmitPrivateForMemory(*value, destType); - } - - // FIXME: Implement C++11 [basic.start.init]p2: if the initializer of a - // reference is a constant expression, and the reference binds to a temporary, - // then constant initialization is performed. ConstExprEmitter will - // incorrectly emit a prvalue constant in this case, and the calling code - // interprets that as the (pointer) value of the reference, rather than the - // desired value of the referee. - if (destType->isReferenceType()) - return nullptr; - - const Expr *E = D.getInit(); - assert(E && "No initializer to emit"); - - auto nonMemoryDestType = getNonMemoryType(CGM, destType); - auto C = - ConstExprEmitter(*this).Visit(const_cast<Expr*>(E), nonMemoryDestType); - return (C ? emitForMemory(C, destType) : nullptr); -} - -llvm::Constant * -ConstantEmitter::tryEmitAbstractForMemory(const Expr *E, QualType destType) { - auto nonMemoryDestType = getNonMemoryType(CGM, destType); - auto C = tryEmitAbstract(E, nonMemoryDestType); - return (C ? emitForMemory(C, destType) : nullptr); -} - -llvm::Constant * -ConstantEmitter::tryEmitAbstractForMemory(const APValue &value, - QualType destType) { - auto nonMemoryDestType = getNonMemoryType(CGM, destType); - auto C = tryEmitAbstract(value, nonMemoryDestType); - return (C ? emitForMemory(C, destType) : nullptr); -} - -llvm::Constant *ConstantEmitter::tryEmitPrivateForMemory(const Expr *E, - QualType destType) { - auto nonMemoryDestType = getNonMemoryType(CGM, destType); - llvm::Constant *C = tryEmitPrivate(E, nonMemoryDestType); - return (C ? emitForMemory(C, destType) : nullptr); -} - -llvm::Constant *ConstantEmitter::tryEmitPrivateForMemory(const APValue &value, - QualType destType) { - auto nonMemoryDestType = getNonMemoryType(CGM, destType); - auto C = tryEmitPrivate(value, nonMemoryDestType); - return (C ? emitForMemory(C, destType) : nullptr); -} - -llvm::Constant *ConstantEmitter::emitForMemory(CodeGenModule &CGM, - llvm::Constant *C, - QualType destType) { - // For an _Atomic-qualified constant, we may need to add tail padding. - if (auto AT = destType->getAs<AtomicType>()) { - QualType destValueType = AT->getValueType(); - C = emitForMemory(CGM, C, destValueType); - - uint64_t innerSize = CGM.getContext().getTypeSize(destValueType); - uint64_t outerSize = CGM.getContext().getTypeSize(destType); - if (innerSize == outerSize) - return C; - - assert(innerSize < outerSize && "emitted over-large constant for atomic"); - llvm::Constant *elts[] = { - C, - llvm::ConstantAggregateZero::get( - llvm::ArrayType::get(CGM.Int8Ty, (outerSize - innerSize) / 8)) - }; - return llvm::ConstantStruct::getAnon(elts); - } - - // Zero-extend bool. - if (C->getType()->isIntegerTy(1)) { - llvm::Type *boolTy = CGM.getTypes().ConvertTypeForMem(destType); - return llvm::ConstantExpr::getZExt(C, boolTy); - } - - return C; -} - -llvm::Constant *ConstantEmitter::tryEmitPrivate(const Expr *E, - QualType destType) { - Expr::EvalResult Result; - - bool Success = false; - - if (destType->isReferenceType()) - Success = E->EvaluateAsLValue(Result, CGM.getContext()); - else - Success = E->EvaluateAsRValue(Result, CGM.getContext(), InConstantContext); - - llvm::Constant *C; - if (Success && !Result.HasSideEffects) - C = tryEmitPrivate(Result.Val, destType); - else - C = ConstExprEmitter(*this).Visit(const_cast<Expr*>(E), destType); - - return C; -} - -llvm::Constant *CodeGenModule::getNullPointer(llvm::PointerType *T, QualType QT) { - return getTargetCodeGenInfo().getNullPointer(*this, T, QT); -} - -namespace { -/// A struct which can be used to peephole certain kinds of finalization -/// that normally happen during l-value emission. -struct ConstantLValue { - llvm::Constant *Value; - bool HasOffsetApplied; - - /*implicit*/ ConstantLValue(llvm::Constant *value, - bool hasOffsetApplied = false) - : Value(value), HasOffsetApplied(false) {} - - /*implicit*/ ConstantLValue(ConstantAddress address) - : ConstantLValue(address.getPointer()) {} -}; - -/// A helper class for emitting constant l-values. -class ConstantLValueEmitter : public ConstStmtVisitor<ConstantLValueEmitter, - ConstantLValue> { - CodeGenModule &CGM; - ConstantEmitter &Emitter; - const APValue &Value; - QualType DestType; - - // Befriend StmtVisitorBase so that we don't have to expose Visit*. - friend StmtVisitorBase; - -public: - ConstantLValueEmitter(ConstantEmitter &emitter, const APValue &value, - QualType destType) - : CGM(emitter.CGM), Emitter(emitter), Value(value), DestType(destType) {} - - llvm::Constant *tryEmit(); - -private: - llvm::Constant *tryEmitAbsolute(llvm::Type *destTy); - ConstantLValue tryEmitBase(const APValue::LValueBase &base); - - ConstantLValue VisitStmt(const Stmt *S) { return nullptr; } - ConstantLValue VisitConstantExpr(const ConstantExpr *E); - ConstantLValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *E); - ConstantLValue VisitStringLiteral(const StringLiteral *E); - ConstantLValue VisitObjCEncodeExpr(const ObjCEncodeExpr *E); - ConstantLValue VisitObjCStringLiteral(const ObjCStringLiteral *E); - ConstantLValue VisitPredefinedExpr(const PredefinedExpr *E); - ConstantLValue VisitAddrLabelExpr(const AddrLabelExpr *E); - ConstantLValue VisitCallExpr(const CallExpr *E); - ConstantLValue VisitBlockExpr(const BlockExpr *E); - ConstantLValue VisitCXXTypeidExpr(const CXXTypeidExpr *E); - ConstantLValue VisitCXXUuidofExpr(const CXXUuidofExpr *E); - ConstantLValue VisitMaterializeTemporaryExpr( - const MaterializeTemporaryExpr *E); - - bool hasNonZeroOffset() const { - return !Value.getLValueOffset().isZero(); - } - - /// Return the value offset. - llvm::Constant *getOffset() { - return llvm::ConstantInt::get(CGM.Int64Ty, - Value.getLValueOffset().getQuantity()); - } - - /// Apply the value offset to the given constant. - llvm::Constant *applyOffset(llvm::Constant *C) { - if (!hasNonZeroOffset()) - return C; - - llvm::Type *origPtrTy = C->getType(); - unsigned AS = origPtrTy->getPointerAddressSpace(); - llvm::Type *charPtrTy = CGM.Int8Ty->getPointerTo(AS); - C = llvm::ConstantExpr::getBitCast(C, charPtrTy); - C = llvm::ConstantExpr::getGetElementPtr(CGM.Int8Ty, C, getOffset()); - C = llvm::ConstantExpr::getPointerCast(C, origPtrTy); - return C; - } -}; - -} - -llvm::Constant *ConstantLValueEmitter::tryEmit() { - const APValue::LValueBase &base = Value.getLValueBase(); - - // Certain special array initializers are represented in APValue - // as l-values referring to the base expression which generates the - // array. This happens with e.g. string literals. These should - // probably just get their own representation kind in APValue. - if (DestType->isArrayType()) { - assert(!hasNonZeroOffset() && "offset on array initializer"); - auto expr = const_cast<Expr*>(base.get<const Expr*>()); - return ConstExprEmitter(Emitter).Visit(expr, DestType); - } - - // Otherwise, the destination type should be a pointer or reference - // type, but it might also be a cast thereof. - // - // FIXME: the chain of casts required should be reflected in the APValue. - // We need this in order to correctly handle things like a ptrtoint of a - // non-zero null pointer and addrspace casts that aren't trivially - // represented in LLVM IR. - auto destTy = CGM.getTypes().ConvertTypeForMem(DestType); - assert(isa<llvm::IntegerType>(destTy) || isa<llvm::PointerType>(destTy)); - - // If there's no base at all, this is a null or absolute pointer, - // possibly cast back to an integer type. - if (!base) { - return tryEmitAbsolute(destTy); - } - - // Otherwise, try to emit the base. - ConstantLValue result = tryEmitBase(base); - - // If that failed, we're done. - llvm::Constant *value = result.Value; - if (!value) return nullptr; - - // Apply the offset if necessary and not already done. - if (!result.HasOffsetApplied) { - value = applyOffset(value); - } - - // Convert to the appropriate type; this could be an lvalue for - // an integer. FIXME: performAddrSpaceCast - if (isa<llvm::PointerType>(destTy)) - return llvm::ConstantExpr::getPointerCast(value, destTy); - - return llvm::ConstantExpr::getPtrToInt(value, destTy); -} - -/// Try to emit an absolute l-value, such as a null pointer or an integer -/// bitcast to pointer type. -llvm::Constant * -ConstantLValueEmitter::tryEmitAbsolute(llvm::Type *destTy) { - auto offset = getOffset(); - - // If we're producing a pointer, this is easy. - if (auto destPtrTy = cast<llvm::PointerType>(destTy)) { - if (Value.isNullPointer()) { - // FIXME: integer offsets from non-zero null pointers. - return CGM.getNullPointer(destPtrTy, DestType); - } - - // Convert the integer to a pointer-sized integer before converting it - // to a pointer. - // FIXME: signedness depends on the original integer type. - auto intptrTy = CGM.getDataLayout().getIntPtrType(destPtrTy); - llvm::Constant *C = offset; - C = llvm::ConstantExpr::getIntegerCast(getOffset(), intptrTy, - /*isSigned*/ false); - C = llvm::ConstantExpr::getIntToPtr(C, destPtrTy); - return C; - } - - // Otherwise, we're basically returning an integer constant. - - // FIXME: this does the wrong thing with ptrtoint of a null pointer, - // but since we don't know the original pointer type, there's not much - // we can do about it. - - auto C = getOffset(); - C = llvm::ConstantExpr::getIntegerCast(C, destTy, /*isSigned*/ false); - return C; -} - -ConstantLValue -ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) { - // Handle values. - if (const ValueDecl *D = base.dyn_cast<const ValueDecl*>()) { - if (D->hasAttr<WeakRefAttr>()) - return CGM.GetWeakRefReference(D).getPointer(); - - if (auto FD = dyn_cast<FunctionDecl>(D)) - return CGM.GetAddrOfFunction(FD); - - if (auto VD = dyn_cast<VarDecl>(D)) { - // We can never refer to a variable with local storage. - if (!VD->hasLocalStorage()) { - if (VD->isFileVarDecl() || VD->hasExternalStorage()) - return CGM.GetAddrOfGlobalVar(VD); - - if (VD->isLocalVarDecl()) { - return CGM.getOrCreateStaticVarDecl( - *VD, CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false)); - } - } - } - - return nullptr; - } - - // Otherwise, it must be an expression. - return Visit(base.get<const Expr*>()); -} - -ConstantLValue -ConstantLValueEmitter::VisitConstantExpr(const ConstantExpr *E) { - return Visit(E->getSubExpr()); -} - -ConstantLValue -ConstantLValueEmitter::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { - return tryEmitGlobalCompoundLiteral(CGM, Emitter.CGF, E); -} - -ConstantLValue -ConstantLValueEmitter::VisitStringLiteral(const StringLiteral *E) { - return CGM.GetAddrOfConstantStringFromLiteral(E); -} - -ConstantLValue -ConstantLValueEmitter::VisitObjCEncodeExpr(const ObjCEncodeExpr *E) { - return CGM.GetAddrOfConstantStringFromObjCEncode(E); -} - -ConstantLValue -ConstantLValueEmitter::VisitObjCStringLiteral(const ObjCStringLiteral *E) { - auto C = CGM.getObjCRuntime().GenerateConstantString(E->getString()); - return C.getElementBitCast(CGM.getTypes().ConvertTypeForMem(E->getType())); -} - -ConstantLValue -ConstantLValueEmitter::VisitPredefinedExpr(const PredefinedExpr *E) { - if (auto CGF = Emitter.CGF) { - LValue Res = CGF->EmitPredefinedLValue(E); - return cast<ConstantAddress>(Res.getAddress()); - } - - auto kind = E->getIdentKind(); - if (kind == PredefinedExpr::PrettyFunction) { - return CGM.GetAddrOfConstantCString("top level", ".tmp"); - } - - return CGM.GetAddrOfConstantCString("", ".tmp"); -} - -ConstantLValue -ConstantLValueEmitter::VisitAddrLabelExpr(const AddrLabelExpr *E) { - assert(Emitter.CGF && "Invalid address of label expression outside function"); - llvm::Constant *Ptr = Emitter.CGF->GetAddrOfLabel(E->getLabel()); - Ptr = llvm::ConstantExpr::getBitCast(Ptr, - CGM.getTypes().ConvertType(E->getType())); - return Ptr; -} - -ConstantLValue -ConstantLValueEmitter::VisitCallExpr(const CallExpr *E) { - unsigned builtin = E->getBuiltinCallee(); - if (builtin != Builtin::BI__builtin___CFStringMakeConstantString && - builtin != Builtin::BI__builtin___NSStringMakeConstantString) - return nullptr; - - auto literal = cast<StringLiteral>(E->getArg(0)->IgnoreParenCasts()); - if (builtin == Builtin::BI__builtin___NSStringMakeConstantString) { - return CGM.getObjCRuntime().GenerateConstantString(literal); - } else { - // FIXME: need to deal with UCN conversion issues. - return CGM.GetAddrOfConstantCFString(literal); - } -} - -ConstantLValue -ConstantLValueEmitter::VisitBlockExpr(const BlockExpr *E) { - StringRef functionName; - if (auto CGF = Emitter.CGF) - functionName = CGF->CurFn->getName(); - else - functionName = "global"; - - return CGM.GetAddrOfGlobalBlock(E, functionName); -} - -ConstantLValue -ConstantLValueEmitter::VisitCXXTypeidExpr(const CXXTypeidExpr *E) { - QualType T; - if (E->isTypeOperand()) - T = E->getTypeOperand(CGM.getContext()); - else - T = E->getExprOperand()->getType(); - return CGM.GetAddrOfRTTIDescriptor(T); -} - -ConstantLValue -ConstantLValueEmitter::VisitCXXUuidofExpr(const CXXUuidofExpr *E) { - return CGM.GetAddrOfUuidDescriptor(E); -} - -ConstantLValue -ConstantLValueEmitter::VisitMaterializeTemporaryExpr( - const MaterializeTemporaryExpr *E) { - assert(E->getStorageDuration() == SD_Static); - SmallVector<const Expr *, 2> CommaLHSs; - SmallVector<SubobjectAdjustment, 2> Adjustments; - const Expr *Inner = E->GetTemporaryExpr() - ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); - return CGM.GetAddrOfGlobalTemporary(E, Inner); -} - -llvm::Constant *ConstantEmitter::tryEmitPrivate(const APValue &Value, - QualType DestType) { - switch (Value.getKind()) { - case APValue::Uninitialized: - llvm_unreachable("Constant expressions should be initialized."); - case APValue::LValue: - return ConstantLValueEmitter(*this, Value, DestType).tryEmit(); - case APValue::Int: - return llvm::ConstantInt::get(CGM.getLLVMContext(), Value.getInt()); - case APValue::ComplexInt: { - llvm::Constant *Complex[2]; - - Complex[0] = llvm::ConstantInt::get(CGM.getLLVMContext(), - Value.getComplexIntReal()); - Complex[1] = llvm::ConstantInt::get(CGM.getLLVMContext(), - Value.getComplexIntImag()); - - // FIXME: the target may want to specify that this is packed. - llvm::StructType *STy = - llvm::StructType::get(Complex[0]->getType(), Complex[1]->getType()); - return llvm::ConstantStruct::get(STy, Complex); - } - case APValue::Float: { - const llvm::APFloat &Init = Value.getFloat(); - if (&Init.getSemantics() == &llvm::APFloat::IEEEhalf() && - !CGM.getContext().getLangOpts().NativeHalfType && - CGM.getContext().getTargetInfo().useFP16ConversionIntrinsics()) - return llvm::ConstantInt::get(CGM.getLLVMContext(), - Init.bitcastToAPInt()); - else - return llvm::ConstantFP::get(CGM.getLLVMContext(), Init); - } - case APValue::ComplexFloat: { - llvm::Constant *Complex[2]; - - Complex[0] = llvm::ConstantFP::get(CGM.getLLVMContext(), - Value.getComplexFloatReal()); - Complex[1] = llvm::ConstantFP::get(CGM.getLLVMContext(), - Value.getComplexFloatImag()); - - // FIXME: the target may want to specify that this is packed. - llvm::StructType *STy = - llvm::StructType::get(Complex[0]->getType(), Complex[1]->getType()); - return llvm::ConstantStruct::get(STy, Complex); - } - case APValue::Vector: { - unsigned NumElts = Value.getVectorLength(); - SmallVector<llvm::Constant *, 4> Inits(NumElts); - - for (unsigned I = 0; I != NumElts; ++I) { - const APValue &Elt = Value.getVectorElt(I); - if (Elt.isInt()) - Inits[I] = llvm::ConstantInt::get(CGM.getLLVMContext(), Elt.getInt()); - else if (Elt.isFloat()) - Inits[I] = llvm::ConstantFP::get(CGM.getLLVMContext(), Elt.getFloat()); - else - llvm_unreachable("unsupported vector element type"); - } - return llvm::ConstantVector::get(Inits); - } - case APValue::AddrLabelDiff: { - const AddrLabelExpr *LHSExpr = Value.getAddrLabelDiffLHS(); - const AddrLabelExpr *RHSExpr = Value.getAddrLabelDiffRHS(); - llvm::Constant *LHS = tryEmitPrivate(LHSExpr, LHSExpr->getType()); - llvm::Constant *RHS = tryEmitPrivate(RHSExpr, RHSExpr->getType()); - if (!LHS || !RHS) return nullptr; - - // Compute difference - llvm::Type *ResultType = CGM.getTypes().ConvertType(DestType); - LHS = llvm::ConstantExpr::getPtrToInt(LHS, CGM.IntPtrTy); - RHS = llvm::ConstantExpr::getPtrToInt(RHS, CGM.IntPtrTy); - llvm::Constant *AddrLabelDiff = llvm::ConstantExpr::getSub(LHS, RHS); - - // LLVM is a bit sensitive about the exact format of the - // address-of-label difference; make sure to truncate after - // the subtraction. - return llvm::ConstantExpr::getTruncOrBitCast(AddrLabelDiff, ResultType); - } - case APValue::Struct: - case APValue::Union: - return ConstStructBuilder::BuildStruct(*this, Value, DestType); - case APValue::Array: { - const ConstantArrayType *CAT = - CGM.getContext().getAsConstantArrayType(DestType); - unsigned NumElements = Value.getArraySize(); - unsigned NumInitElts = Value.getArrayInitializedElts(); - - // Emit array filler, if there is one. - llvm::Constant *Filler = nullptr; - if (Value.hasArrayFiller()) { - Filler = tryEmitAbstractForMemory(Value.getArrayFiller(), - CAT->getElementType()); - if (!Filler) - return nullptr; - } - - // Emit initializer elements. - SmallVector<llvm::Constant*, 16> Elts; - if (Filler && Filler->isNullValue()) - Elts.reserve(NumInitElts + 1); - else - Elts.reserve(NumElements); - - llvm::Type *CommonElementType = nullptr; - for (unsigned I = 0; I < NumInitElts; ++I) { - llvm::Constant *C = tryEmitPrivateForMemory( - Value.getArrayInitializedElt(I), CAT->getElementType()); - if (!C) return nullptr; - - if (I == 0) - CommonElementType = C->getType(); - else if (C->getType() != CommonElementType) - CommonElementType = nullptr; - Elts.push_back(C); - } - - // This means that the array type is probably "IncompleteType" or some - // type that is not ConstantArray. - if (CAT == nullptr && CommonElementType == nullptr && !NumInitElts) { - const ArrayType *AT = CGM.getContext().getAsArrayType(DestType); - CommonElementType = CGM.getTypes().ConvertType(AT->getElementType()); - llvm::ArrayType *AType = llvm::ArrayType::get(CommonElementType, - NumElements); - return llvm::ConstantAggregateZero::get(AType); - } - - return EmitArrayConstant(CGM, CAT, CommonElementType, NumElements, Elts, - Filler); - } - case APValue::MemberPointer: - return CGM.getCXXABI().EmitMemberPointer(Value, DestType); - } - llvm_unreachable("Unknown APValue kind"); -} - -llvm::GlobalVariable *CodeGenModule::getAddrOfConstantCompoundLiteralIfEmitted( - const CompoundLiteralExpr *E) { - return EmittedCompoundLiterals.lookup(E); -} - -void CodeGenModule::setAddrOfConstantCompoundLiteral( - const CompoundLiteralExpr *CLE, llvm::GlobalVariable *GV) { - bool Ok = EmittedCompoundLiterals.insert(std::make_pair(CLE, GV)).second; - (void)Ok; - assert(Ok && "CLE has already been emitted!"); -} - -ConstantAddress -CodeGenModule::GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *E) { - assert(E->isFileScope() && "not a file-scope compound literal expr"); - return tryEmitGlobalCompoundLiteral(*this, nullptr, E); -} - -llvm::Constant * -CodeGenModule::getMemberPointerConstant(const UnaryOperator *uo) { - // Member pointer constants always have a very particular form. - const MemberPointerType *type = cast<MemberPointerType>(uo->getType()); - const ValueDecl *decl = cast<DeclRefExpr>(uo->getSubExpr())->getDecl(); - - // A member function pointer. - if (const CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(decl)) - return getCXXABI().EmitMemberFunctionPointer(method); - - // Otherwise, a member data pointer. - uint64_t fieldOffset = getContext().getFieldOffset(decl); - CharUnits chars = getContext().toCharUnitsFromBits((int64_t) fieldOffset); - return getCXXABI().EmitMemberDataPointer(type, chars); -} - -static llvm::Constant *EmitNullConstantForBase(CodeGenModule &CGM, - llvm::Type *baseType, - const CXXRecordDecl *base); - -static llvm::Constant *EmitNullConstant(CodeGenModule &CGM, - const RecordDecl *record, - bool asCompleteObject) { - const CGRecordLayout &layout = CGM.getTypes().getCGRecordLayout(record); - llvm::StructType *structure = - (asCompleteObject ? layout.getLLVMType() - : layout.getBaseSubobjectLLVMType()); - - unsigned numElements = structure->getNumElements(); - std::vector<llvm::Constant *> elements(numElements); - - auto CXXR = dyn_cast<CXXRecordDecl>(record); - // Fill in all the bases. - if (CXXR) { - for (const auto &I : CXXR->bases()) { - if (I.isVirtual()) { - // Ignore virtual bases; if we're laying out for a complete - // object, we'll lay these out later. - continue; - } - - const CXXRecordDecl *base = - cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl()); - - // Ignore empty bases. - if (base->isEmpty() || - CGM.getContext().getASTRecordLayout(base).getNonVirtualSize() - .isZero()) - continue; - - unsigned fieldIndex = layout.getNonVirtualBaseLLVMFieldNo(base); - llvm::Type *baseType = structure->getElementType(fieldIndex); - elements[fieldIndex] = EmitNullConstantForBase(CGM, baseType, base); - } - } - - // Fill in all the fields. - for (const auto *Field : record->fields()) { - // Fill in non-bitfields. (Bitfields always use a zero pattern, which we - // will fill in later.) - if (!Field->isBitField()) { - unsigned fieldIndex = layout.getLLVMFieldNo(Field); - elements[fieldIndex] = CGM.EmitNullConstant(Field->getType()); - } - - // For unions, stop after the first named field. - if (record->isUnion()) { - if (Field->getIdentifier()) - break; - if (const auto *FieldRD = Field->getType()->getAsRecordDecl()) - if (FieldRD->findFirstNamedDataMember()) - break; - } - } - - // Fill in the virtual bases, if we're working with the complete object. - if (CXXR && asCompleteObject) { - for (const auto &I : CXXR->vbases()) { - const CXXRecordDecl *base = - cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl()); - - // Ignore empty bases. - if (base->isEmpty()) - continue; - - unsigned fieldIndex = layout.getVirtualBaseIndex(base); - - // We might have already laid this field out. - if (elements[fieldIndex]) continue; - - llvm::Type *baseType = structure->getElementType(fieldIndex); - elements[fieldIndex] = EmitNullConstantForBase(CGM, baseType, base); - } - } - - // Now go through all other fields and zero them out. - for (unsigned i = 0; i != numElements; ++i) { - if (!elements[i]) - elements[i] = llvm::Constant::getNullValue(structure->getElementType(i)); - } - - return llvm::ConstantStruct::get(structure, elements); -} - -/// Emit the null constant for a base subobject. -static llvm::Constant *EmitNullConstantForBase(CodeGenModule &CGM, - llvm::Type *baseType, - const CXXRecordDecl *base) { - const CGRecordLayout &baseLayout = CGM.getTypes().getCGRecordLayout(base); - - // Just zero out bases that don't have any pointer to data members. - if (baseLayout.isZeroInitializableAsBase()) - return llvm::Constant::getNullValue(baseType); - - // Otherwise, we can just use its null constant. - return EmitNullConstant(CGM, base, /*asCompleteObject=*/false); -} - -llvm::Constant *ConstantEmitter::emitNullForMemory(CodeGenModule &CGM, - QualType T) { - return emitForMemory(CGM, CGM.EmitNullConstant(T), T); -} - -llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { - if (T->getAs<PointerType>()) - return getNullPointer( - cast<llvm::PointerType>(getTypes().ConvertTypeForMem(T)), T); - - if (getTypes().isZeroInitializable(T)) - return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T)); - - if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(T)) { - llvm::ArrayType *ATy = - cast<llvm::ArrayType>(getTypes().ConvertTypeForMem(T)); - - QualType ElementTy = CAT->getElementType(); - - llvm::Constant *Element = - ConstantEmitter::emitNullForMemory(*this, ElementTy); - unsigned NumElements = CAT->getSize().getZExtValue(); - SmallVector<llvm::Constant *, 8> Array(NumElements, Element); - return llvm::ConstantArray::get(ATy, Array); - } - - if (const RecordType *RT = T->getAs<RecordType>()) - return ::EmitNullConstant(*this, RT->getDecl(), /*complete object*/ true); - - assert(T->isMemberDataPointerType() && - "Should only see pointers to data members here!"); - - return getCXXABI().EmitNullMemberPointer(T->castAs<MemberPointerType>()); -} - -llvm::Constant * -CodeGenModule::EmitNullConstantForBase(const CXXRecordDecl *Record) { - return ::EmitNullConstant(*this, Record, false); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp deleted file mode 100644 index 1c14d4c99a2..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp +++ /dev/null @@ -1,4526 +0,0 @@ -//===--- CGExprScalar.cpp - Emit LLVM Code for Scalar Exprs ---------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code to emit Expr nodes with scalar LLVM types as LLVM code. -// -//===----------------------------------------------------------------------===// - -#include "CGCXXABI.h" -#include "CGCleanup.h" -#include "CGDebugInfo.h" -#include "CGObjCRuntime.h" -#include "CodeGenFunction.h" -#include "CodeGenModule.h" -#include "TargetInfo.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/Expr.h" -#include "clang/AST/RecordLayout.h" -#include "clang/AST/StmtVisitor.h" -#include "clang/Basic/CodeGenOptions.h" -#include "clang/Basic/FixedPoint.h" -#include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/Optional.h" -#include "llvm/IR/CFG.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GetElementPtrTypeIterator.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Module.h" -#include <cstdarg> - -using namespace clang; -using namespace CodeGen; -using llvm::Value; - -//===----------------------------------------------------------------------===// -// Scalar Expression Emitter -//===----------------------------------------------------------------------===// - -namespace { - -/// Determine whether the given binary operation may overflow. -/// Sets \p Result to the value of the operation for BO_Add, BO_Sub, BO_Mul, -/// and signed BO_{Div,Rem}. For these opcodes, and for unsigned BO_{Div,Rem}, -/// the returned overflow check is precise. The returned value is 'true' for -/// all other opcodes, to be conservative. -bool mayHaveIntegerOverflow(llvm::ConstantInt *LHS, llvm::ConstantInt *RHS, - BinaryOperator::Opcode Opcode, bool Signed, - llvm::APInt &Result) { - // Assume overflow is possible, unless we can prove otherwise. - bool Overflow = true; - const auto &LHSAP = LHS->getValue(); - const auto &RHSAP = RHS->getValue(); - if (Opcode == BO_Add) { - if (Signed) - Result = LHSAP.sadd_ov(RHSAP, Overflow); - else - Result = LHSAP.uadd_ov(RHSAP, Overflow); - } else if (Opcode == BO_Sub) { - if (Signed) - Result = LHSAP.ssub_ov(RHSAP, Overflow); - else - Result = LHSAP.usub_ov(RHSAP, Overflow); - } else if (Opcode == BO_Mul) { - if (Signed) - Result = LHSAP.smul_ov(RHSAP, Overflow); - else - Result = LHSAP.umul_ov(RHSAP, Overflow); - } else if (Opcode == BO_Div || Opcode == BO_Rem) { - if (Signed && !RHS->isZero()) - Result = LHSAP.sdiv_ov(RHSAP, Overflow); - else - return false; - } - return Overflow; -} - -struct BinOpInfo { - Value *LHS; - Value *RHS; - QualType Ty; // Computation Type. - BinaryOperator::Opcode Opcode; // Opcode of BinOp to perform - FPOptions FPFeatures; - const Expr *E; // Entire expr, for error unsupported. May not be binop. - - /// Check if the binop can result in integer overflow. - bool mayHaveIntegerOverflow() const { - // Without constant input, we can't rule out overflow. - auto *LHSCI = dyn_cast<llvm::ConstantInt>(LHS); - auto *RHSCI = dyn_cast<llvm::ConstantInt>(RHS); - if (!LHSCI || !RHSCI) - return true; - - llvm::APInt Result; - return ::mayHaveIntegerOverflow( - LHSCI, RHSCI, Opcode, Ty->hasSignedIntegerRepresentation(), Result); - } - - /// Check if the binop computes a division or a remainder. - bool isDivremOp() const { - return Opcode == BO_Div || Opcode == BO_Rem || Opcode == BO_DivAssign || - Opcode == BO_RemAssign; - } - - /// Check if the binop can result in an integer division by zero. - bool mayHaveIntegerDivisionByZero() const { - if (isDivremOp()) - if (auto *CI = dyn_cast<llvm::ConstantInt>(RHS)) - return CI->isZero(); - return true; - } - - /// Check if the binop can result in a float division by zero. - bool mayHaveFloatDivisionByZero() const { - if (isDivremOp()) - if (auto *CFP = dyn_cast<llvm::ConstantFP>(RHS)) - return CFP->isZero(); - return true; - } -}; - -static bool MustVisitNullValue(const Expr *E) { - // If a null pointer expression's type is the C++0x nullptr_t, then - // it's not necessarily a simple constant and it must be evaluated - // for its potential side effects. - return E->getType()->isNullPtrType(); -} - -/// If \p E is a widened promoted integer, get its base (unpromoted) type. -static llvm::Optional<QualType> getUnwidenedIntegerType(const ASTContext &Ctx, - const Expr *E) { - const Expr *Base = E->IgnoreImpCasts(); - if (E == Base) - return llvm::None; - - QualType BaseTy = Base->getType(); - if (!BaseTy->isPromotableIntegerType() || - Ctx.getTypeSize(BaseTy) >= Ctx.getTypeSize(E->getType())) - return llvm::None; - - return BaseTy; -} - -/// Check if \p E is a widened promoted integer. -static bool IsWidenedIntegerOp(const ASTContext &Ctx, const Expr *E) { - return getUnwidenedIntegerType(Ctx, E).hasValue(); -} - -/// Check if we can skip the overflow check for \p Op. -static bool CanElideOverflowCheck(const ASTContext &Ctx, const BinOpInfo &Op) { - assert((isa<UnaryOperator>(Op.E) || isa<BinaryOperator>(Op.E)) && - "Expected a unary or binary operator"); - - // If the binop has constant inputs and we can prove there is no overflow, - // we can elide the overflow check. - if (!Op.mayHaveIntegerOverflow()) - return true; - - // If a unary op has a widened operand, the op cannot overflow. - if (const auto *UO = dyn_cast<UnaryOperator>(Op.E)) - return !UO->canOverflow(); - - // We usually don't need overflow checks for binops with widened operands. - // Multiplication with promoted unsigned operands is a special case. - const auto *BO = cast<BinaryOperator>(Op.E); - auto OptionalLHSTy = getUnwidenedIntegerType(Ctx, BO->getLHS()); - if (!OptionalLHSTy) - return false; - - auto OptionalRHSTy = getUnwidenedIntegerType(Ctx, BO->getRHS()); - if (!OptionalRHSTy) - return false; - - QualType LHSTy = *OptionalLHSTy; - QualType RHSTy = *OptionalRHSTy; - - // This is the simple case: binops without unsigned multiplication, and with - // widened operands. No overflow check is needed here. - if ((Op.Opcode != BO_Mul && Op.Opcode != BO_MulAssign) || - !LHSTy->isUnsignedIntegerType() || !RHSTy->isUnsignedIntegerType()) - return true; - - // For unsigned multiplication the overflow check can be elided if either one - // of the unpromoted types are less than half the size of the promoted type. - unsigned PromotedSize = Ctx.getTypeSize(Op.E->getType()); - return (2 * Ctx.getTypeSize(LHSTy)) < PromotedSize || - (2 * Ctx.getTypeSize(RHSTy)) < PromotedSize; -} - -/// Update the FastMathFlags of LLVM IR from the FPOptions in LangOptions. -static void updateFastMathFlags(llvm::FastMathFlags &FMF, - FPOptions FPFeatures) { - FMF.setAllowContract(FPFeatures.allowFPContractAcrossStatement()); -} - -/// Propagate fast-math flags from \p Op to the instruction in \p V. -static Value *propagateFMFlags(Value *V, const BinOpInfo &Op) { - if (auto *I = dyn_cast<llvm::Instruction>(V)) { - llvm::FastMathFlags FMF = I->getFastMathFlags(); - updateFastMathFlags(FMF, Op.FPFeatures); - I->setFastMathFlags(FMF); - } - return V; -} - -class ScalarExprEmitter - : public StmtVisitor<ScalarExprEmitter, Value*> { - CodeGenFunction &CGF; - CGBuilderTy &Builder; - bool IgnoreResultAssign; - llvm::LLVMContext &VMContext; -public: - - ScalarExprEmitter(CodeGenFunction &cgf, bool ira=false) - : CGF(cgf), Builder(CGF.Builder), IgnoreResultAssign(ira), - VMContext(cgf.getLLVMContext()) { - } - - //===--------------------------------------------------------------------===// - // Utilities - //===--------------------------------------------------------------------===// - - bool TestAndClearIgnoreResultAssign() { - bool I = IgnoreResultAssign; - IgnoreResultAssign = false; - return I; - } - - llvm::Type *ConvertType(QualType T) { return CGF.ConvertType(T); } - LValue EmitLValue(const Expr *E) { return CGF.EmitLValue(E); } - LValue EmitCheckedLValue(const Expr *E, CodeGenFunction::TypeCheckKind TCK) { - return CGF.EmitCheckedLValue(E, TCK); - } - - void EmitBinOpCheck(ArrayRef<std::pair<Value *, SanitizerMask>> Checks, - const BinOpInfo &Info); - - Value *EmitLoadOfLValue(LValue LV, SourceLocation Loc) { - return CGF.EmitLoadOfLValue(LV, Loc).getScalarVal(); - } - - void EmitLValueAlignmentAssumption(const Expr *E, Value *V) { - const AlignValueAttr *AVAttr = nullptr; - if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) { - const ValueDecl *VD = DRE->getDecl(); - - if (VD->getType()->isReferenceType()) { - if (const auto *TTy = - dyn_cast<TypedefType>(VD->getType().getNonReferenceType())) - AVAttr = TTy->getDecl()->getAttr<AlignValueAttr>(); - } else { - // Assumptions for function parameters are emitted at the start of the - // function, so there is no need to repeat that here, - // unless the alignment-assumption sanitizer is enabled, - // then we prefer the assumption over alignment attribute - // on IR function param. - if (isa<ParmVarDecl>(VD) && !CGF.SanOpts.has(SanitizerKind::Alignment)) - return; - - AVAttr = VD->getAttr<AlignValueAttr>(); - } - } - - if (!AVAttr) - if (const auto *TTy = - dyn_cast<TypedefType>(E->getType())) - AVAttr = TTy->getDecl()->getAttr<AlignValueAttr>(); - - if (!AVAttr) - return; - - Value *AlignmentValue = CGF.EmitScalarExpr(AVAttr->getAlignment()); - llvm::ConstantInt *AlignmentCI = cast<llvm::ConstantInt>(AlignmentValue); - CGF.EmitAlignmentAssumption(V, E, AVAttr->getLocation(), - AlignmentCI->getZExtValue()); - } - - /// EmitLoadOfLValue - Given an expression with complex type that represents a - /// value l-value, this method emits the address of the l-value, then loads - /// and returns the result. - Value *EmitLoadOfLValue(const Expr *E) { - Value *V = EmitLoadOfLValue(EmitCheckedLValue(E, CodeGenFunction::TCK_Load), - E->getExprLoc()); - - EmitLValueAlignmentAssumption(E, V); - return V; - } - - /// EmitConversionToBool - Convert the specified expression value to a - /// boolean (i1) truth value. This is equivalent to "Val != 0". - Value *EmitConversionToBool(Value *Src, QualType DstTy); - - /// Emit a check that a conversion to or from a floating-point type does not - /// overflow. - void EmitFloatConversionCheck(Value *OrigSrc, QualType OrigSrcType, - Value *Src, QualType SrcType, QualType DstType, - llvm::Type *DstTy, SourceLocation Loc); - - /// Known implicit conversion check kinds. - /// Keep in sync with the enum of the same name in ubsan_handlers.h - enum ImplicitConversionCheckKind : unsigned char { - ICCK_IntegerTruncation = 0, // Legacy, was only used by clang 7. - ICCK_UnsignedIntegerTruncation = 1, - ICCK_SignedIntegerTruncation = 2, - ICCK_IntegerSignChange = 3, - ICCK_SignedIntegerTruncationOrSignChange = 4, - }; - - /// Emit a check that an [implicit] truncation of an integer does not - /// discard any bits. It is not UB, so we use the value after truncation. - void EmitIntegerTruncationCheck(Value *Src, QualType SrcType, Value *Dst, - QualType DstType, SourceLocation Loc); - - /// Emit a check that an [implicit] conversion of an integer does not change - /// the sign of the value. It is not UB, so we use the value after conversion. - /// NOTE: Src and Dst may be the exact same value! (point to the same thing) - void EmitIntegerSignChangeCheck(Value *Src, QualType SrcType, Value *Dst, - QualType DstType, SourceLocation Loc); - - /// Emit a conversion from the specified type to the specified destination - /// type, both of which are LLVM scalar types. - struct ScalarConversionOpts { - bool TreatBooleanAsSigned; - bool EmitImplicitIntegerTruncationChecks; - bool EmitImplicitIntegerSignChangeChecks; - - ScalarConversionOpts() - : TreatBooleanAsSigned(false), - EmitImplicitIntegerTruncationChecks(false), - EmitImplicitIntegerSignChangeChecks(false) {} - - ScalarConversionOpts(clang::SanitizerSet SanOpts) - : TreatBooleanAsSigned(false), - EmitImplicitIntegerTruncationChecks( - SanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)), - EmitImplicitIntegerSignChangeChecks( - SanOpts.has(SanitizerKind::ImplicitIntegerSignChange)) {} - }; - Value * - EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy, - SourceLocation Loc, - ScalarConversionOpts Opts = ScalarConversionOpts()); - - Value *EmitFixedPointConversion(Value *Src, QualType SrcTy, QualType DstTy, - SourceLocation Loc); - - /// Emit a conversion from the specified complex type to the specified - /// destination type, where the destination type is an LLVM scalar type. - Value *EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src, - QualType SrcTy, QualType DstTy, - SourceLocation Loc); - - /// EmitNullValue - Emit a value that corresponds to null for the given type. - Value *EmitNullValue(QualType Ty); - - /// EmitFloatToBoolConversion - Perform an FP to boolean conversion. - Value *EmitFloatToBoolConversion(Value *V) { - // Compare against 0.0 for fp scalars. - llvm::Value *Zero = llvm::Constant::getNullValue(V->getType()); - return Builder.CreateFCmpUNE(V, Zero, "tobool"); - } - - /// EmitPointerToBoolConversion - Perform a pointer to boolean conversion. - Value *EmitPointerToBoolConversion(Value *V, QualType QT) { - Value *Zero = CGF.CGM.getNullPointer(cast<llvm::PointerType>(V->getType()), QT); - - return Builder.CreateICmpNE(V, Zero, "tobool"); - } - - Value *EmitIntToBoolConversion(Value *V) { - // Because of the type rules of C, we often end up computing a - // logical value, then zero extending it to int, then wanting it - // as a logical value again. Optimize this common case. - if (llvm::ZExtInst *ZI = dyn_cast<llvm::ZExtInst>(V)) { - if (ZI->getOperand(0)->getType() == Builder.getInt1Ty()) { - Value *Result = ZI->getOperand(0); - // If there aren't any more uses, zap the instruction to save space. - // Note that there can be more uses, for example if this - // is the result of an assignment. - if (ZI->use_empty()) - ZI->eraseFromParent(); - return Result; - } - } - - return Builder.CreateIsNotNull(V, "tobool"); - } - - //===--------------------------------------------------------------------===// - // Visitor Methods - //===--------------------------------------------------------------------===// - - Value *Visit(Expr *E) { - ApplyDebugLocation DL(CGF, E); - return StmtVisitor<ScalarExprEmitter, Value*>::Visit(E); - } - - Value *VisitStmt(Stmt *S) { - S->dump(CGF.getContext().getSourceManager()); - llvm_unreachable("Stmt can't have complex result type!"); - } - Value *VisitExpr(Expr *S); - - Value *VisitConstantExpr(ConstantExpr *E) { - return Visit(E->getSubExpr()); - } - Value *VisitParenExpr(ParenExpr *PE) { - return Visit(PE->getSubExpr()); - } - Value *VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) { - return Visit(E->getReplacement()); - } - Value *VisitGenericSelectionExpr(GenericSelectionExpr *GE) { - return Visit(GE->getResultExpr()); - } - Value *VisitCoawaitExpr(CoawaitExpr *S) { - return CGF.EmitCoawaitExpr(*S).getScalarVal(); - } - Value *VisitCoyieldExpr(CoyieldExpr *S) { - return CGF.EmitCoyieldExpr(*S).getScalarVal(); - } - Value *VisitUnaryCoawait(const UnaryOperator *E) { - return Visit(E->getSubExpr()); - } - - // Leaves. - Value *VisitIntegerLiteral(const IntegerLiteral *E) { - return Builder.getInt(E->getValue()); - } - Value *VisitFixedPointLiteral(const FixedPointLiteral *E) { - return Builder.getInt(E->getValue()); - } - Value *VisitFloatingLiteral(const FloatingLiteral *E) { - return llvm::ConstantFP::get(VMContext, E->getValue()); - } - Value *VisitCharacterLiteral(const CharacterLiteral *E) { - return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue()); - } - Value *VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E) { - return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue()); - } - Value *VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) { - return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue()); - } - Value *VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) { - return EmitNullValue(E->getType()); - } - Value *VisitGNUNullExpr(const GNUNullExpr *E) { - return EmitNullValue(E->getType()); - } - Value *VisitOffsetOfExpr(OffsetOfExpr *E); - Value *VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E); - Value *VisitAddrLabelExpr(const AddrLabelExpr *E) { - llvm::Value *V = CGF.GetAddrOfLabel(E->getLabel()); - return Builder.CreateBitCast(V, ConvertType(E->getType())); - } - - Value *VisitSizeOfPackExpr(SizeOfPackExpr *E) { - return llvm::ConstantInt::get(ConvertType(E->getType()),E->getPackLength()); - } - - Value *VisitPseudoObjectExpr(PseudoObjectExpr *E) { - return CGF.EmitPseudoObjectRValue(E).getScalarVal(); - } - - Value *VisitOpaqueValueExpr(OpaqueValueExpr *E) { - if (E->isGLValue()) - return EmitLoadOfLValue(CGF.getOrCreateOpaqueLValueMapping(E), - E->getExprLoc()); - - // Otherwise, assume the mapping is the scalar directly. - return CGF.getOrCreateOpaqueRValueMapping(E).getScalarVal(); - } - - // l-values. - Value *VisitDeclRefExpr(DeclRefExpr *E) { - if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(E)) - return CGF.emitScalarConstant(Constant, E); - return EmitLoadOfLValue(E); - } - - Value *VisitObjCSelectorExpr(ObjCSelectorExpr *E) { - return CGF.EmitObjCSelectorExpr(E); - } - Value *VisitObjCProtocolExpr(ObjCProtocolExpr *E) { - return CGF.EmitObjCProtocolExpr(E); - } - Value *VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { - return EmitLoadOfLValue(E); - } - Value *VisitObjCMessageExpr(ObjCMessageExpr *E) { - if (E->getMethodDecl() && - E->getMethodDecl()->getReturnType()->isReferenceType()) - return EmitLoadOfLValue(E); - return CGF.EmitObjCMessageExpr(E).getScalarVal(); - } - - Value *VisitObjCIsaExpr(ObjCIsaExpr *E) { - LValue LV = CGF.EmitObjCIsaExpr(E); - Value *V = CGF.EmitLoadOfLValue(LV, E->getExprLoc()).getScalarVal(); - return V; - } - - Value *VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *E) { - VersionTuple Version = E->getVersion(); - - // If we're checking for a platform older than our minimum deployment - // target, we can fold the check away. - if (Version <= CGF.CGM.getTarget().getPlatformMinVersion()) - return llvm::ConstantInt::get(Builder.getInt1Ty(), 1); - - Optional<unsigned> Min = Version.getMinor(), SMin = Version.getSubminor(); - llvm::Value *Args[] = { - llvm::ConstantInt::get(CGF.CGM.Int32Ty, Version.getMajor()), - llvm::ConstantInt::get(CGF.CGM.Int32Ty, Min ? *Min : 0), - llvm::ConstantInt::get(CGF.CGM.Int32Ty, SMin ? *SMin : 0), - }; - - return CGF.EmitBuiltinAvailable(Args); - } - - Value *VisitArraySubscriptExpr(ArraySubscriptExpr *E); - Value *VisitShuffleVectorExpr(ShuffleVectorExpr *E); - Value *VisitConvertVectorExpr(ConvertVectorExpr *E); - Value *VisitMemberExpr(MemberExpr *E); - Value *VisitExtVectorElementExpr(Expr *E) { return EmitLoadOfLValue(E); } - Value *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { - return EmitLoadOfLValue(E); - } - - Value *VisitInitListExpr(InitListExpr *E); - - Value *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) { - assert(CGF.getArrayInitIndex() && - "ArrayInitIndexExpr not inside an ArrayInitLoopExpr?"); - return CGF.getArrayInitIndex(); - } - - Value *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { - return EmitNullValue(E->getType()); - } - Value *VisitExplicitCastExpr(ExplicitCastExpr *E) { - CGF.CGM.EmitExplicitCastExprType(E, &CGF); - return VisitCastExpr(E); - } - Value *VisitCastExpr(CastExpr *E); - - Value *VisitCallExpr(const CallExpr *E) { - if (E->getCallReturnType(CGF.getContext())->isReferenceType()) - return EmitLoadOfLValue(E); - - Value *V = CGF.EmitCallExpr(E).getScalarVal(); - - EmitLValueAlignmentAssumption(E, V); - return V; - } - - Value *VisitStmtExpr(const StmtExpr *E); - - // Unary Operators. - Value *VisitUnaryPostDec(const UnaryOperator *E) { - LValue LV = EmitLValue(E->getSubExpr()); - return EmitScalarPrePostIncDec(E, LV, false, false); - } - Value *VisitUnaryPostInc(const UnaryOperator *E) { - LValue LV = EmitLValue(E->getSubExpr()); - return EmitScalarPrePostIncDec(E, LV, true, false); - } - Value *VisitUnaryPreDec(const UnaryOperator *E) { - LValue LV = EmitLValue(E->getSubExpr()); - return EmitScalarPrePostIncDec(E, LV, false, true); - } - Value *VisitUnaryPreInc(const UnaryOperator *E) { - LValue LV = EmitLValue(E->getSubExpr()); - return EmitScalarPrePostIncDec(E, LV, true, true); - } - - llvm::Value *EmitIncDecConsiderOverflowBehavior(const UnaryOperator *E, - llvm::Value *InVal, - bool IsInc); - - llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, - bool isInc, bool isPre); - - - Value *VisitUnaryAddrOf(const UnaryOperator *E) { - if (isa<MemberPointerType>(E->getType())) // never sugared - return CGF.CGM.getMemberPointerConstant(E); - - return EmitLValue(E->getSubExpr()).getPointer(); - } - Value *VisitUnaryDeref(const UnaryOperator *E) { - if (E->getType()->isVoidType()) - return Visit(E->getSubExpr()); // the actual value should be unused - return EmitLoadOfLValue(E); - } - Value *VisitUnaryPlus(const UnaryOperator *E) { - // This differs from gcc, though, most likely due to a bug in gcc. - TestAndClearIgnoreResultAssign(); - return Visit(E->getSubExpr()); - } - Value *VisitUnaryMinus (const UnaryOperator *E); - Value *VisitUnaryNot (const UnaryOperator *E); - Value *VisitUnaryLNot (const UnaryOperator *E); - Value *VisitUnaryReal (const UnaryOperator *E); - Value *VisitUnaryImag (const UnaryOperator *E); - Value *VisitUnaryExtension(const UnaryOperator *E) { - return Visit(E->getSubExpr()); - } - - // C++ - Value *VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E) { - return EmitLoadOfLValue(E); - } - - Value *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) { - return Visit(DAE->getExpr()); - } - Value *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) { - CodeGenFunction::CXXDefaultInitExprScope Scope(CGF); - return Visit(DIE->getExpr()); - } - Value *VisitCXXThisExpr(CXXThisExpr *TE) { - return CGF.LoadCXXThis(); - } - - Value *VisitExprWithCleanups(ExprWithCleanups *E); - Value *VisitCXXNewExpr(const CXXNewExpr *E) { - return CGF.EmitCXXNewExpr(E); - } - Value *VisitCXXDeleteExpr(const CXXDeleteExpr *E) { - CGF.EmitCXXDeleteExpr(E); - return nullptr; - } - - Value *VisitTypeTraitExpr(const TypeTraitExpr *E) { - return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue()); - } - - Value *VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) { - return llvm::ConstantInt::get(Builder.getInt32Ty(), E->getValue()); - } - - Value *VisitExpressionTraitExpr(const ExpressionTraitExpr *E) { - return llvm::ConstantInt::get(Builder.getInt1Ty(), E->getValue()); - } - - Value *VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *E) { - // C++ [expr.pseudo]p1: - // The result shall only be used as the operand for the function call - // operator (), and the result of such a call has type void. The only - // effect is the evaluation of the postfix-expression before the dot or - // arrow. - CGF.EmitScalarExpr(E->getBase()); - return nullptr; - } - - Value *VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) { - return EmitNullValue(E->getType()); - } - - Value *VisitCXXThrowExpr(const CXXThrowExpr *E) { - CGF.EmitCXXThrowExpr(E); - return nullptr; - } - - Value *VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) { - return Builder.getInt1(E->getValue()); - } - - // Binary Operators. - Value *EmitMul(const BinOpInfo &Ops) { - if (Ops.Ty->isSignedIntegerOrEnumerationType()) { - switch (CGF.getLangOpts().getSignedOverflowBehavior()) { - case LangOptions::SOB_Defined: - return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul"); - case LangOptions::SOB_Undefined: - if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) - return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul"); - LLVM_FALLTHROUGH; - case LangOptions::SOB_Trapping: - if (CanElideOverflowCheck(CGF.getContext(), Ops)) - return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul"); - return EmitOverflowCheckedBinOp(Ops); - } - } - - if (Ops.Ty->isUnsignedIntegerType() && - CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow) && - !CanElideOverflowCheck(CGF.getContext(), Ops)) - return EmitOverflowCheckedBinOp(Ops); - - if (Ops.LHS->getType()->isFPOrFPVectorTy()) { - Value *V = Builder.CreateFMul(Ops.LHS, Ops.RHS, "mul"); - return propagateFMFlags(V, Ops); - } - return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul"); - } - /// Create a binary op that checks for overflow. - /// Currently only supports +, - and *. - Value *EmitOverflowCheckedBinOp(const BinOpInfo &Ops); - - // Check for undefined division and modulus behaviors. - void EmitUndefinedBehaviorIntegerDivAndRemCheck(const BinOpInfo &Ops, - llvm::Value *Zero,bool isDiv); - // Common helper for getting how wide LHS of shift is. - static Value *GetWidthMinusOneValue(Value* LHS,Value* RHS); - Value *EmitDiv(const BinOpInfo &Ops); - Value *EmitRem(const BinOpInfo &Ops); - Value *EmitAdd(const BinOpInfo &Ops); - Value *EmitSub(const BinOpInfo &Ops); - Value *EmitShl(const BinOpInfo &Ops); - Value *EmitShr(const BinOpInfo &Ops); - Value *EmitAnd(const BinOpInfo &Ops) { - return Builder.CreateAnd(Ops.LHS, Ops.RHS, "and"); - } - Value *EmitXor(const BinOpInfo &Ops) { - return Builder.CreateXor(Ops.LHS, Ops.RHS, "xor"); - } - Value *EmitOr (const BinOpInfo &Ops) { - return Builder.CreateOr(Ops.LHS, Ops.RHS, "or"); - } - - BinOpInfo EmitBinOps(const BinaryOperator *E); - LValue EmitCompoundAssignLValue(const CompoundAssignOperator *E, - Value *(ScalarExprEmitter::*F)(const BinOpInfo &), - Value *&Result); - - Value *EmitCompoundAssign(const CompoundAssignOperator *E, - Value *(ScalarExprEmitter::*F)(const BinOpInfo &)); - - // Binary operators and binary compound assignment operators. -#define HANDLEBINOP(OP) \ - Value *VisitBin ## OP(const BinaryOperator *E) { \ - return Emit ## OP(EmitBinOps(E)); \ - } \ - Value *VisitBin ## OP ## Assign(const CompoundAssignOperator *E) { \ - return EmitCompoundAssign(E, &ScalarExprEmitter::Emit ## OP); \ - } - HANDLEBINOP(Mul) - HANDLEBINOP(Div) - HANDLEBINOP(Rem) - HANDLEBINOP(Add) - HANDLEBINOP(Sub) - HANDLEBINOP(Shl) - HANDLEBINOP(Shr) - HANDLEBINOP(And) - HANDLEBINOP(Xor) - HANDLEBINOP(Or) -#undef HANDLEBINOP - - // Comparisons. - Value *EmitCompare(const BinaryOperator *E, llvm::CmpInst::Predicate UICmpOpc, - llvm::CmpInst::Predicate SICmpOpc, - llvm::CmpInst::Predicate FCmpOpc); -#define VISITCOMP(CODE, UI, SI, FP) \ - Value *VisitBin##CODE(const BinaryOperator *E) { \ - return EmitCompare(E, llvm::ICmpInst::UI, llvm::ICmpInst::SI, \ - llvm::FCmpInst::FP); } - VISITCOMP(LT, ICMP_ULT, ICMP_SLT, FCMP_OLT) - VISITCOMP(GT, ICMP_UGT, ICMP_SGT, FCMP_OGT) - VISITCOMP(LE, ICMP_ULE, ICMP_SLE, FCMP_OLE) - VISITCOMP(GE, ICMP_UGE, ICMP_SGE, FCMP_OGE) - VISITCOMP(EQ, ICMP_EQ , ICMP_EQ , FCMP_OEQ) - VISITCOMP(NE, ICMP_NE , ICMP_NE , FCMP_UNE) -#undef VISITCOMP - - Value *VisitBinAssign (const BinaryOperator *E); - - Value *VisitBinLAnd (const BinaryOperator *E); - Value *VisitBinLOr (const BinaryOperator *E); - Value *VisitBinComma (const BinaryOperator *E); - - Value *VisitBinPtrMemD(const Expr *E) { return EmitLoadOfLValue(E); } - Value *VisitBinPtrMemI(const Expr *E) { return EmitLoadOfLValue(E); } - - // Other Operators. - Value *VisitBlockExpr(const BlockExpr *BE); - Value *VisitAbstractConditionalOperator(const AbstractConditionalOperator *); - Value *VisitChooseExpr(ChooseExpr *CE); - Value *VisitVAArgExpr(VAArgExpr *VE); - Value *VisitObjCStringLiteral(const ObjCStringLiteral *E) { - return CGF.EmitObjCStringLiteral(E); - } - Value *VisitObjCBoxedExpr(ObjCBoxedExpr *E) { - return CGF.EmitObjCBoxedExpr(E); - } - Value *VisitObjCArrayLiteral(ObjCArrayLiteral *E) { - return CGF.EmitObjCArrayLiteral(E); - } - Value *VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { - return CGF.EmitObjCDictionaryLiteral(E); - } - Value *VisitAsTypeExpr(AsTypeExpr *CE); - Value *VisitAtomicExpr(AtomicExpr *AE); -}; -} // end anonymous namespace. - -//===----------------------------------------------------------------------===// -// Utilities -//===----------------------------------------------------------------------===// - -/// EmitConversionToBool - Convert the specified expression value to a -/// boolean (i1) truth value. This is equivalent to "Val != 0". -Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) { - assert(SrcType.isCanonical() && "EmitScalarConversion strips typedefs"); - - if (SrcType->isRealFloatingType()) - return EmitFloatToBoolConversion(Src); - - if (const MemberPointerType *MPT = dyn_cast<MemberPointerType>(SrcType)) - return CGF.CGM.getCXXABI().EmitMemberPointerIsNotNull(CGF, Src, MPT); - - assert((SrcType->isIntegerType() || isa<llvm::PointerType>(Src->getType())) && - "Unknown scalar type to convert"); - - if (isa<llvm::IntegerType>(Src->getType())) - return EmitIntToBoolConversion(Src); - - assert(isa<llvm::PointerType>(Src->getType())); - return EmitPointerToBoolConversion(Src, SrcType); -} - -void ScalarExprEmitter::EmitFloatConversionCheck( - Value *OrigSrc, QualType OrigSrcType, Value *Src, QualType SrcType, - QualType DstType, llvm::Type *DstTy, SourceLocation Loc) { - CodeGenFunction::SanitizerScope SanScope(&CGF); - using llvm::APFloat; - using llvm::APSInt; - - llvm::Type *SrcTy = Src->getType(); - - llvm::Value *Check = nullptr; - if (llvm::IntegerType *IntTy = dyn_cast<llvm::IntegerType>(SrcTy)) { - // Integer to floating-point. This can fail for unsigned short -> __half - // or unsigned __int128 -> float. - assert(DstType->isFloatingType()); - bool SrcIsUnsigned = OrigSrcType->isUnsignedIntegerOrEnumerationType(); - - APFloat LargestFloat = - APFloat::getLargest(CGF.getContext().getFloatTypeSemantics(DstType)); - APSInt LargestInt(IntTy->getBitWidth(), SrcIsUnsigned); - - bool IsExact; - if (LargestFloat.convertToInteger(LargestInt, APFloat::rmTowardZero, - &IsExact) != APFloat::opOK) - // The range of representable values of this floating point type includes - // all values of this integer type. Don't need an overflow check. - return; - - llvm::Value *Max = llvm::ConstantInt::get(VMContext, LargestInt); - if (SrcIsUnsigned) - Check = Builder.CreateICmpULE(Src, Max); - else { - llvm::Value *Min = llvm::ConstantInt::get(VMContext, -LargestInt); - llvm::Value *GE = Builder.CreateICmpSGE(Src, Min); - llvm::Value *LE = Builder.CreateICmpSLE(Src, Max); - Check = Builder.CreateAnd(GE, LE); - } - } else { - const llvm::fltSemantics &SrcSema = - CGF.getContext().getFloatTypeSemantics(OrigSrcType); - if (isa<llvm::IntegerType>(DstTy)) { - // Floating-point to integer. This has undefined behavior if the source is - // +-Inf, NaN, or doesn't fit into the destination type (after truncation - // to an integer). - unsigned Width = CGF.getContext().getIntWidth(DstType); - bool Unsigned = DstType->isUnsignedIntegerOrEnumerationType(); - - APSInt Min = APSInt::getMinValue(Width, Unsigned); - APFloat MinSrc(SrcSema, APFloat::uninitialized); - if (MinSrc.convertFromAPInt(Min, !Unsigned, APFloat::rmTowardZero) & - APFloat::opOverflow) - // Don't need an overflow check for lower bound. Just check for - // -Inf/NaN. - MinSrc = APFloat::getInf(SrcSema, true); - else - // Find the largest value which is too small to represent (before - // truncation toward zero). - MinSrc.subtract(APFloat(SrcSema, 1), APFloat::rmTowardNegative); - - APSInt Max = APSInt::getMaxValue(Width, Unsigned); - APFloat MaxSrc(SrcSema, APFloat::uninitialized); - if (MaxSrc.convertFromAPInt(Max, !Unsigned, APFloat::rmTowardZero) & - APFloat::opOverflow) - // Don't need an overflow check for upper bound. Just check for - // +Inf/NaN. - MaxSrc = APFloat::getInf(SrcSema, false); - else - // Find the smallest value which is too large to represent (before - // truncation toward zero). - MaxSrc.add(APFloat(SrcSema, 1), APFloat::rmTowardPositive); - - // If we're converting from __half, convert the range to float to match - // the type of src. - if (OrigSrcType->isHalfType()) { - const llvm::fltSemantics &Sema = - CGF.getContext().getFloatTypeSemantics(SrcType); - bool IsInexact; - MinSrc.convert(Sema, APFloat::rmTowardZero, &IsInexact); - MaxSrc.convert(Sema, APFloat::rmTowardZero, &IsInexact); - } - - llvm::Value *GE = - Builder.CreateFCmpOGT(Src, llvm::ConstantFP::get(VMContext, MinSrc)); - llvm::Value *LE = - Builder.CreateFCmpOLT(Src, llvm::ConstantFP::get(VMContext, MaxSrc)); - Check = Builder.CreateAnd(GE, LE); - } else { - // FIXME: Maybe split this sanitizer out from float-cast-overflow. - // - // Floating-point to floating-point. This has undefined behavior if the - // source is not in the range of representable values of the destination - // type. The C and C++ standards are spectacularly unclear here. We - // diagnose finite out-of-range conversions, but allow infinities and NaNs - // to convert to the corresponding value in the smaller type. - // - // C11 Annex F gives all such conversions defined behavior for IEC 60559 - // conforming implementations. Unfortunately, LLVM's fptrunc instruction - // does not. - - // Converting from a lower rank to a higher rank can never have - // undefined behavior, since higher-rank types must have a superset - // of values of lower-rank types. - if (CGF.getContext().getFloatingTypeOrder(OrigSrcType, DstType) != 1) - return; - - assert(!OrigSrcType->isHalfType() && - "should not check conversion from __half, it has the lowest rank"); - - const llvm::fltSemantics &DstSema = - CGF.getContext().getFloatTypeSemantics(DstType); - APFloat MinBad = APFloat::getLargest(DstSema, false); - APFloat MaxBad = APFloat::getInf(DstSema, false); - - bool IsInexact; - MinBad.convert(SrcSema, APFloat::rmTowardZero, &IsInexact); - MaxBad.convert(SrcSema, APFloat::rmTowardZero, &IsInexact); - - Value *AbsSrc = CGF.EmitNounwindRuntimeCall( - CGF.CGM.getIntrinsic(llvm::Intrinsic::fabs, Src->getType()), Src); - llvm::Value *GE = - Builder.CreateFCmpOGT(AbsSrc, llvm::ConstantFP::get(VMContext, MinBad)); - llvm::Value *LE = - Builder.CreateFCmpOLT(AbsSrc, llvm::ConstantFP::get(VMContext, MaxBad)); - Check = Builder.CreateNot(Builder.CreateAnd(GE, LE)); - } - } - - llvm::Constant *StaticArgs[] = {CGF.EmitCheckSourceLocation(Loc), - CGF.EmitCheckTypeDescriptor(OrigSrcType), - CGF.EmitCheckTypeDescriptor(DstType)}; - CGF.EmitCheck(std::make_pair(Check, SanitizerKind::FloatCastOverflow), - SanitizerHandler::FloatCastOverflow, StaticArgs, OrigSrc); -} - -// Should be called within CodeGenFunction::SanitizerScope RAII scope. -// Returns 'i1 false' when the truncation Src -> Dst was lossy. -static std::pair<ScalarExprEmitter::ImplicitConversionCheckKind, - std::pair<llvm::Value *, SanitizerMask>> -EmitIntegerTruncationCheckHelper(Value *Src, QualType SrcType, Value *Dst, - QualType DstType, CGBuilderTy &Builder) { - llvm::Type *SrcTy = Src->getType(); - llvm::Type *DstTy = Dst->getType(); - (void)DstTy; // Only used in assert() - - // This should be truncation of integral types. - assert(Src != Dst); - assert(SrcTy->getScalarSizeInBits() > Dst->getType()->getScalarSizeInBits()); - assert(isa<llvm::IntegerType>(SrcTy) && isa<llvm::IntegerType>(DstTy) && - "non-integer llvm type"); - - bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType(); - bool DstSigned = DstType->isSignedIntegerOrEnumerationType(); - - // If both (src and dst) types are unsigned, then it's an unsigned truncation. - // Else, it is a signed truncation. - ScalarExprEmitter::ImplicitConversionCheckKind Kind; - SanitizerMask Mask; - if (!SrcSigned && !DstSigned) { - Kind = ScalarExprEmitter::ICCK_UnsignedIntegerTruncation; - Mask = SanitizerKind::ImplicitUnsignedIntegerTruncation; - } else { - Kind = ScalarExprEmitter::ICCK_SignedIntegerTruncation; - Mask = SanitizerKind::ImplicitSignedIntegerTruncation; - } - - llvm::Value *Check = nullptr; - // 1. Extend the truncated value back to the same width as the Src. - Check = Builder.CreateIntCast(Dst, SrcTy, DstSigned, "anyext"); - // 2. Equality-compare with the original source value - Check = Builder.CreateICmpEQ(Check, Src, "truncheck"); - // If the comparison result is 'i1 false', then the truncation was lossy. - return std::make_pair(Kind, std::make_pair(Check, Mask)); -} - -void ScalarExprEmitter::EmitIntegerTruncationCheck(Value *Src, QualType SrcType, - Value *Dst, QualType DstType, - SourceLocation Loc) { - if (!CGF.SanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)) - return; - - // We only care about int->int conversions here. - // We ignore conversions to/from pointer and/or bool. - if (!(SrcType->isIntegerType() && DstType->isIntegerType())) - return; - - unsigned SrcBits = Src->getType()->getScalarSizeInBits(); - unsigned DstBits = Dst->getType()->getScalarSizeInBits(); - // This must be truncation. Else we do not care. - if (SrcBits <= DstBits) - return; - - assert(!DstType->isBooleanType() && "we should not get here with booleans."); - - // If the integer sign change sanitizer is enabled, - // and we are truncating from larger unsigned type to smaller signed type, - // let that next sanitizer deal with it. - bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType(); - bool DstSigned = DstType->isSignedIntegerOrEnumerationType(); - if (CGF.SanOpts.has(SanitizerKind::ImplicitIntegerSignChange) && - (!SrcSigned && DstSigned)) - return; - - CodeGenFunction::SanitizerScope SanScope(&CGF); - - std::pair<ScalarExprEmitter::ImplicitConversionCheckKind, - std::pair<llvm::Value *, SanitizerMask>> - Check = - EmitIntegerTruncationCheckHelper(Src, SrcType, Dst, DstType, Builder); - // If the comparison result is 'i1 false', then the truncation was lossy. - - // Do we care about this type of truncation? - if (!CGF.SanOpts.has(Check.second.second)) - return; - - llvm::Constant *StaticArgs[] = { - CGF.EmitCheckSourceLocation(Loc), CGF.EmitCheckTypeDescriptor(SrcType), - CGF.EmitCheckTypeDescriptor(DstType), - llvm::ConstantInt::get(Builder.getInt8Ty(), Check.first)}; - CGF.EmitCheck(Check.second, SanitizerHandler::ImplicitConversion, StaticArgs, - {Src, Dst}); -} - -// Should be called within CodeGenFunction::SanitizerScope RAII scope. -// Returns 'i1 false' when the conversion Src -> Dst changed the sign. -static std::pair<ScalarExprEmitter::ImplicitConversionCheckKind, - std::pair<llvm::Value *, SanitizerMask>> -EmitIntegerSignChangeCheckHelper(Value *Src, QualType SrcType, Value *Dst, - QualType DstType, CGBuilderTy &Builder) { - llvm::Type *SrcTy = Src->getType(); - llvm::Type *DstTy = Dst->getType(); - - assert(isa<llvm::IntegerType>(SrcTy) && isa<llvm::IntegerType>(DstTy) && - "non-integer llvm type"); - - bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType(); - bool DstSigned = DstType->isSignedIntegerOrEnumerationType(); - (void)SrcSigned; // Only used in assert() - (void)DstSigned; // Only used in assert() - unsigned SrcBits = SrcTy->getScalarSizeInBits(); - unsigned DstBits = DstTy->getScalarSizeInBits(); - (void)SrcBits; // Only used in assert() - (void)DstBits; // Only used in assert() - - assert(((SrcBits != DstBits) || (SrcSigned != DstSigned)) && - "either the widths should be different, or the signednesses."); - - // NOTE: zero value is considered to be non-negative. - auto EmitIsNegativeTest = [&Builder](Value *V, QualType VType, - const char *Name) -> Value * { - // Is this value a signed type? - bool VSigned = VType->isSignedIntegerOrEnumerationType(); - llvm::Type *VTy = V->getType(); - if (!VSigned) { - // If the value is unsigned, then it is never negative. - // FIXME: can we encounter non-scalar VTy here? - return llvm::ConstantInt::getFalse(VTy->getContext()); - } - // Get the zero of the same type with which we will be comparing. - llvm::Constant *Zero = llvm::ConstantInt::get(VTy, 0); - // %V.isnegative = icmp slt %V, 0 - // I.e is %V *strictly* less than zero, does it have negative value? - return Builder.CreateICmp(llvm::ICmpInst::ICMP_SLT, V, Zero, - llvm::Twine(Name) + "." + V->getName() + - ".negativitycheck"); - }; - - // 1. Was the old Value negative? - llvm::Value *SrcIsNegative = EmitIsNegativeTest(Src, SrcType, "src"); - // 2. Is the new Value negative? - llvm::Value *DstIsNegative = EmitIsNegativeTest(Dst, DstType, "dst"); - // 3. Now, was the 'negativity status' preserved during the conversion? - // NOTE: conversion from negative to zero is considered to change the sign. - // (We want to get 'false' when the conversion changed the sign) - // So we should just equality-compare the negativity statuses. - llvm::Value *Check = nullptr; - Check = Builder.CreateICmpEQ(SrcIsNegative, DstIsNegative, "signchangecheck"); - // If the comparison result is 'false', then the conversion changed the sign. - return std::make_pair( - ScalarExprEmitter::ICCK_IntegerSignChange, - std::make_pair(Check, SanitizerKind::ImplicitIntegerSignChange)); -} - -void ScalarExprEmitter::EmitIntegerSignChangeCheck(Value *Src, QualType SrcType, - Value *Dst, QualType DstType, - SourceLocation Loc) { - if (!CGF.SanOpts.has(SanitizerKind::ImplicitIntegerSignChange)) - return; - - llvm::Type *SrcTy = Src->getType(); - llvm::Type *DstTy = Dst->getType(); - - // We only care about int->int conversions here. - // We ignore conversions to/from pointer and/or bool. - if (!(SrcType->isIntegerType() && DstType->isIntegerType())) - return; - - bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType(); - bool DstSigned = DstType->isSignedIntegerOrEnumerationType(); - unsigned SrcBits = SrcTy->getScalarSizeInBits(); - unsigned DstBits = DstTy->getScalarSizeInBits(); - - // Now, we do not need to emit the check in *all* of the cases. - // We can avoid emitting it in some obvious cases where it would have been - // dropped by the opt passes (instcombine) always anyways. - // If it's a cast between effectively the same type, no check. - // NOTE: this is *not* equivalent to checking the canonical types. - if (SrcSigned == DstSigned && SrcBits == DstBits) - return; - // At least one of the values needs to have signed type. - // If both are unsigned, then obviously, neither of them can be negative. - if (!SrcSigned && !DstSigned) - return; - // If the conversion is to *larger* *signed* type, then no check is needed. - // Because either sign-extension happens (so the sign will remain), - // or zero-extension will happen (the sign bit will be zero.) - if ((DstBits > SrcBits) && DstSigned) - return; - if (CGF.SanOpts.has(SanitizerKind::ImplicitSignedIntegerTruncation) && - (SrcBits > DstBits) && SrcSigned) { - // If the signed integer truncation sanitizer is enabled, - // and this is a truncation from signed type, then no check is needed. - // Because here sign change check is interchangeable with truncation check. - return; - } - // That's it. We can't rule out any more cases with the data we have. - - CodeGenFunction::SanitizerScope SanScope(&CGF); - - std::pair<ScalarExprEmitter::ImplicitConversionCheckKind, - std::pair<llvm::Value *, SanitizerMask>> - Check; - - // Each of these checks needs to return 'false' when an issue was detected. - ImplicitConversionCheckKind CheckKind; - llvm::SmallVector<std::pair<llvm::Value *, SanitizerMask>, 2> Checks; - // So we can 'and' all the checks together, and still get 'false', - // if at least one of the checks detected an issue. - - Check = EmitIntegerSignChangeCheckHelper(Src, SrcType, Dst, DstType, Builder); - CheckKind = Check.first; - Checks.emplace_back(Check.second); - - if (CGF.SanOpts.has(SanitizerKind::ImplicitSignedIntegerTruncation) && - (SrcBits > DstBits) && !SrcSigned && DstSigned) { - // If the signed integer truncation sanitizer was enabled, - // and we are truncating from larger unsigned type to smaller signed type, - // let's handle the case we skipped in that check. - Check = - EmitIntegerTruncationCheckHelper(Src, SrcType, Dst, DstType, Builder); - CheckKind = ICCK_SignedIntegerTruncationOrSignChange; - Checks.emplace_back(Check.second); - // If the comparison result is 'i1 false', then the truncation was lossy. - } - - llvm::Constant *StaticArgs[] = { - CGF.EmitCheckSourceLocation(Loc), CGF.EmitCheckTypeDescriptor(SrcType), - CGF.EmitCheckTypeDescriptor(DstType), - llvm::ConstantInt::get(Builder.getInt8Ty(), CheckKind)}; - // EmitCheck() will 'and' all the checks together. - CGF.EmitCheck(Checks, SanitizerHandler::ImplicitConversion, StaticArgs, - {Src, Dst}); -} - -/// Emit a conversion from the specified type to the specified destination type, -/// both of which are LLVM scalar types. -Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, - QualType DstType, - SourceLocation Loc, - ScalarConversionOpts Opts) { - // All conversions involving fixed point types should be handled by the - // EmitFixedPoint family functions. This is done to prevent bloating up this - // function more, and although fixed point numbers are represented by - // integers, we do not want to follow any logic that assumes they should be - // treated as integers. - // TODO(leonardchan): When necessary, add another if statement checking for - // conversions to fixed point types from other types. - if (SrcType->isFixedPointType()) { - if (DstType->isFixedPointType()) { - return EmitFixedPointConversion(Src, SrcType, DstType, Loc); - } else if (DstType->isBooleanType()) { - // We do not need to check the padding bit on unsigned types if unsigned - // padding is enabled because overflow into this bit is undefined - // behavior. - return Builder.CreateIsNotNull(Src, "tobool"); - } - - llvm_unreachable( - "Unhandled scalar conversion involving a fixed point type."); - } - - QualType NoncanonicalSrcType = SrcType; - QualType NoncanonicalDstType = DstType; - - SrcType = CGF.getContext().getCanonicalType(SrcType); - DstType = CGF.getContext().getCanonicalType(DstType); - if (SrcType == DstType) return Src; - - if (DstType->isVoidType()) return nullptr; - - llvm::Value *OrigSrc = Src; - QualType OrigSrcType = SrcType; - llvm::Type *SrcTy = Src->getType(); - - // Handle conversions to bool first, they are special: comparisons against 0. - if (DstType->isBooleanType()) - return EmitConversionToBool(Src, SrcType); - - llvm::Type *DstTy = ConvertType(DstType); - - // Cast from half through float if half isn't a native type. - if (SrcType->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) { - // Cast to FP using the intrinsic if the half type itself isn't supported. - if (DstTy->isFloatingPointTy()) { - if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) - return Builder.CreateCall( - CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16, DstTy), - Src); - } else { - // Cast to other types through float, using either the intrinsic or FPExt, - // depending on whether the half type itself is supported - // (as opposed to operations on half, available with NativeHalfType). - if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) { - Src = Builder.CreateCall( - CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16, - CGF.CGM.FloatTy), - Src); - } else { - Src = Builder.CreateFPExt(Src, CGF.CGM.FloatTy, "conv"); - } - SrcType = CGF.getContext().FloatTy; - SrcTy = CGF.FloatTy; - } - } - - // Ignore conversions like int -> uint. - if (SrcTy == DstTy) { - if (Opts.EmitImplicitIntegerSignChangeChecks) - EmitIntegerSignChangeCheck(Src, NoncanonicalSrcType, Src, - NoncanonicalDstType, Loc); - - return Src; - } - - // Handle pointer conversions next: pointers can only be converted to/from - // other pointers and integers. Check for pointer types in terms of LLVM, as - // some native types (like Obj-C id) may map to a pointer type. - if (auto DstPT = dyn_cast<llvm::PointerType>(DstTy)) { - // The source value may be an integer, or a pointer. - if (isa<llvm::PointerType>(SrcTy)) - return Builder.CreateBitCast(Src, DstTy, "conv"); - - assert(SrcType->isIntegerType() && "Not ptr->ptr or int->ptr conversion?"); - // First, convert to the correct width so that we control the kind of - // extension. - llvm::Type *MiddleTy = CGF.CGM.getDataLayout().getIntPtrType(DstPT); - bool InputSigned = SrcType->isSignedIntegerOrEnumerationType(); - llvm::Value* IntResult = - Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv"); - // Then, cast to pointer. - return Builder.CreateIntToPtr(IntResult, DstTy, "conv"); - } - - if (isa<llvm::PointerType>(SrcTy)) { - // Must be an ptr to int cast. - assert(isa<llvm::IntegerType>(DstTy) && "not ptr->int?"); - return Builder.CreatePtrToInt(Src, DstTy, "conv"); - } - - // A scalar can be splatted to an extended vector of the same element type - if (DstType->isExtVectorType() && !SrcType->isVectorType()) { - // Sema should add casts to make sure that the source expression's type is - // the same as the vector's element type (sans qualifiers) - assert(DstType->castAs<ExtVectorType>()->getElementType().getTypePtr() == - SrcType.getTypePtr() && - "Splatted expr doesn't match with vector element type?"); - - // Splat the element across to all elements - unsigned NumElements = DstTy->getVectorNumElements(); - return Builder.CreateVectorSplat(NumElements, Src, "splat"); - } - - if (isa<llvm::VectorType>(SrcTy) || isa<llvm::VectorType>(DstTy)) { - // Allow bitcast from vector to integer/fp of the same size. - unsigned SrcSize = SrcTy->getPrimitiveSizeInBits(); - unsigned DstSize = DstTy->getPrimitiveSizeInBits(); - if (SrcSize == DstSize) - return Builder.CreateBitCast(Src, DstTy, "conv"); - - // Conversions between vectors of different sizes are not allowed except - // when vectors of half are involved. Operations on storage-only half - // vectors require promoting half vector operands to float vectors and - // truncating the result, which is either an int or float vector, to a - // short or half vector. - - // Source and destination are both expected to be vectors. - llvm::Type *SrcElementTy = SrcTy->getVectorElementType(); - llvm::Type *DstElementTy = DstTy->getVectorElementType(); - (void)DstElementTy; - - assert(((SrcElementTy->isIntegerTy() && - DstElementTy->isIntegerTy()) || - (SrcElementTy->isFloatingPointTy() && - DstElementTy->isFloatingPointTy())) && - "unexpected conversion between a floating-point vector and an " - "integer vector"); - - // Truncate an i32 vector to an i16 vector. - if (SrcElementTy->isIntegerTy()) - return Builder.CreateIntCast(Src, DstTy, false, "conv"); - - // Truncate a float vector to a half vector. - if (SrcSize > DstSize) - return Builder.CreateFPTrunc(Src, DstTy, "conv"); - - // Promote a half vector to a float vector. - return Builder.CreateFPExt(Src, DstTy, "conv"); - } - - // Finally, we have the arithmetic types: real int/float. - Value *Res = nullptr; - llvm::Type *ResTy = DstTy; - - // An overflowing conversion has undefined behavior if either the source type - // or the destination type is a floating-point type. - if (CGF.SanOpts.has(SanitizerKind::FloatCastOverflow) && - (OrigSrcType->isFloatingType() || DstType->isFloatingType())) - EmitFloatConversionCheck(OrigSrc, OrigSrcType, Src, SrcType, DstType, DstTy, - Loc); - - // Cast to half through float if half isn't a native type. - if (DstType->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) { - // Make sure we cast in a single step if from another FP type. - if (SrcTy->isFloatingPointTy()) { - // Use the intrinsic if the half type itself isn't supported - // (as opposed to operations on half, available with NativeHalfType). - if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) - return Builder.CreateCall( - CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16, SrcTy), Src); - // If the half type is supported, just use an fptrunc. - return Builder.CreateFPTrunc(Src, DstTy); - } - DstTy = CGF.FloatTy; - } - - if (isa<llvm::IntegerType>(SrcTy)) { - bool InputSigned = SrcType->isSignedIntegerOrEnumerationType(); - if (SrcType->isBooleanType() && Opts.TreatBooleanAsSigned) { - InputSigned = true; - } - if (isa<llvm::IntegerType>(DstTy)) - Res = Builder.CreateIntCast(Src, DstTy, InputSigned, "conv"); - else if (InputSigned) - Res = Builder.CreateSIToFP(Src, DstTy, "conv"); - else - Res = Builder.CreateUIToFP(Src, DstTy, "conv"); - } else if (isa<llvm::IntegerType>(DstTy)) { - assert(SrcTy->isFloatingPointTy() && "Unknown real conversion"); - if (DstType->isSignedIntegerOrEnumerationType()) - Res = Builder.CreateFPToSI(Src, DstTy, "conv"); - else - Res = Builder.CreateFPToUI(Src, DstTy, "conv"); - } else { - assert(SrcTy->isFloatingPointTy() && DstTy->isFloatingPointTy() && - "Unknown real conversion"); - if (DstTy->getTypeID() < SrcTy->getTypeID()) - Res = Builder.CreateFPTrunc(Src, DstTy, "conv"); - else - Res = Builder.CreateFPExt(Src, DstTy, "conv"); - } - - if (DstTy != ResTy) { - if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) { - assert(ResTy->isIntegerTy(16) && "Only half FP requires extra conversion"); - Res = Builder.CreateCall( - CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16, CGF.CGM.FloatTy), - Res); - } else { - Res = Builder.CreateFPTrunc(Res, ResTy, "conv"); - } - } - - if (Opts.EmitImplicitIntegerTruncationChecks) - EmitIntegerTruncationCheck(Src, NoncanonicalSrcType, Res, - NoncanonicalDstType, Loc); - - if (Opts.EmitImplicitIntegerSignChangeChecks) - EmitIntegerSignChangeCheck(Src, NoncanonicalSrcType, Res, - NoncanonicalDstType, Loc); - - return Res; -} - -Value *ScalarExprEmitter::EmitFixedPointConversion(Value *Src, QualType SrcTy, - QualType DstTy, - SourceLocation Loc) { - using llvm::APInt; - using llvm::ConstantInt; - using llvm::Value; - - assert(SrcTy->isFixedPointType()); - assert(DstTy->isFixedPointType()); - - FixedPointSemantics SrcFPSema = - CGF.getContext().getFixedPointSemantics(SrcTy); - FixedPointSemantics DstFPSema = - CGF.getContext().getFixedPointSemantics(DstTy); - unsigned SrcWidth = SrcFPSema.getWidth(); - unsigned DstWidth = DstFPSema.getWidth(); - unsigned SrcScale = SrcFPSema.getScale(); - unsigned DstScale = DstFPSema.getScale(); - bool SrcIsSigned = SrcFPSema.isSigned(); - bool DstIsSigned = DstFPSema.isSigned(); - - llvm::Type *DstIntTy = Builder.getIntNTy(DstWidth); - - Value *Result = Src; - unsigned ResultWidth = SrcWidth; - - if (!DstFPSema.isSaturated()) { - // Downscale. - if (DstScale < SrcScale) - Result = SrcIsSigned ? - Builder.CreateAShr(Result, SrcScale - DstScale, "downscale") : - Builder.CreateLShr(Result, SrcScale - DstScale, "downscale"); - - // Resize. - Result = Builder.CreateIntCast(Result, DstIntTy, SrcIsSigned, "resize"); - - // Upscale. - if (DstScale > SrcScale) - Result = Builder.CreateShl(Result, DstScale - SrcScale, "upscale"); - } else { - // Adjust the number of fractional bits. - if (DstScale > SrcScale) { - ResultWidth = SrcWidth + DstScale - SrcScale; - llvm::Type *UpscaledTy = Builder.getIntNTy(ResultWidth); - Result = Builder.CreateIntCast(Result, UpscaledTy, SrcIsSigned, "resize"); - Result = Builder.CreateShl(Result, DstScale - SrcScale, "upscale"); - } else if (DstScale < SrcScale) { - Result = SrcIsSigned ? - Builder.CreateAShr(Result, SrcScale - DstScale, "downscale") : - Builder.CreateLShr(Result, SrcScale - DstScale, "downscale"); - } - - // Handle saturation. - bool LessIntBits = DstFPSema.getIntegralBits() < SrcFPSema.getIntegralBits(); - if (LessIntBits) { - Value *Max = ConstantInt::get( - CGF.getLLVMContext(), - APFixedPoint::getMax(DstFPSema).getValue().extOrTrunc(ResultWidth)); - Value *TooHigh = SrcIsSigned ? Builder.CreateICmpSGT(Result, Max) - : Builder.CreateICmpUGT(Result, Max); - Result = Builder.CreateSelect(TooHigh, Max, Result, "satmax"); - } - // Cannot overflow min to dest type if src is unsigned since all fixed - // point types can cover the unsigned min of 0. - if (SrcIsSigned && (LessIntBits || !DstIsSigned)) { - Value *Min = ConstantInt::get( - CGF.getLLVMContext(), - APFixedPoint::getMin(DstFPSema).getValue().extOrTrunc(ResultWidth)); - Value *TooLow = Builder.CreateICmpSLT(Result, Min); - Result = Builder.CreateSelect(TooLow, Min, Result, "satmin"); - } - - // Resize the integer part to get the final destination size. - Result = Builder.CreateIntCast(Result, DstIntTy, SrcIsSigned, "resize"); - } - return Result; -} - -/// Emit a conversion from the specified complex type to the specified -/// destination type, where the destination type is an LLVM scalar type. -Value *ScalarExprEmitter::EmitComplexToScalarConversion( - CodeGenFunction::ComplexPairTy Src, QualType SrcTy, QualType DstTy, - SourceLocation Loc) { - // Get the source element type. - SrcTy = SrcTy->castAs<ComplexType>()->getElementType(); - - // Handle conversions to bool first, they are special: comparisons against 0. - if (DstTy->isBooleanType()) { - // Complex != 0 -> (Real != 0) | (Imag != 0) - Src.first = EmitScalarConversion(Src.first, SrcTy, DstTy, Loc); - Src.second = EmitScalarConversion(Src.second, SrcTy, DstTy, Loc); - return Builder.CreateOr(Src.first, Src.second, "tobool"); - } - - // C99 6.3.1.7p2: "When a value of complex type is converted to a real type, - // the imaginary part of the complex value is discarded and the value of the - // real part is converted according to the conversion rules for the - // corresponding real type. - return EmitScalarConversion(Src.first, SrcTy, DstTy, Loc); -} - -Value *ScalarExprEmitter::EmitNullValue(QualType Ty) { - return CGF.EmitFromMemory(CGF.CGM.EmitNullConstant(Ty), Ty); -} - -/// Emit a sanitization check for the given "binary" operation (which -/// might actually be a unary increment which has been lowered to a binary -/// operation). The check passes if all values in \p Checks (which are \c i1), -/// are \c true. -void ScalarExprEmitter::EmitBinOpCheck( - ArrayRef<std::pair<Value *, SanitizerMask>> Checks, const BinOpInfo &Info) { - assert(CGF.IsSanitizerScope); - SanitizerHandler Check; - SmallVector<llvm::Constant *, 4> StaticData; - SmallVector<llvm::Value *, 2> DynamicData; - - BinaryOperatorKind Opcode = Info.Opcode; - if (BinaryOperator::isCompoundAssignmentOp(Opcode)) - Opcode = BinaryOperator::getOpForCompoundAssignment(Opcode); - - StaticData.push_back(CGF.EmitCheckSourceLocation(Info.E->getExprLoc())); - const UnaryOperator *UO = dyn_cast<UnaryOperator>(Info.E); - if (UO && UO->getOpcode() == UO_Minus) { - Check = SanitizerHandler::NegateOverflow; - StaticData.push_back(CGF.EmitCheckTypeDescriptor(UO->getType())); - DynamicData.push_back(Info.RHS); - } else { - if (BinaryOperator::isShiftOp(Opcode)) { - // Shift LHS negative or too large, or RHS out of bounds. - Check = SanitizerHandler::ShiftOutOfBounds; - const BinaryOperator *BO = cast<BinaryOperator>(Info.E); - StaticData.push_back( - CGF.EmitCheckTypeDescriptor(BO->getLHS()->getType())); - StaticData.push_back( - CGF.EmitCheckTypeDescriptor(BO->getRHS()->getType())); - } else if (Opcode == BO_Div || Opcode == BO_Rem) { - // Divide or modulo by zero, or signed overflow (eg INT_MAX / -1). - Check = SanitizerHandler::DivremOverflow; - StaticData.push_back(CGF.EmitCheckTypeDescriptor(Info.Ty)); - } else { - // Arithmetic overflow (+, -, *). - switch (Opcode) { - case BO_Add: Check = SanitizerHandler::AddOverflow; break; - case BO_Sub: Check = SanitizerHandler::SubOverflow; break; - case BO_Mul: Check = SanitizerHandler::MulOverflow; break; - default: llvm_unreachable("unexpected opcode for bin op check"); - } - StaticData.push_back(CGF.EmitCheckTypeDescriptor(Info.Ty)); - } - DynamicData.push_back(Info.LHS); - DynamicData.push_back(Info.RHS); - } - - CGF.EmitCheck(Checks, Check, StaticData, DynamicData); -} - -//===----------------------------------------------------------------------===// -// Visitor Methods -//===----------------------------------------------------------------------===// - -Value *ScalarExprEmitter::VisitExpr(Expr *E) { - CGF.ErrorUnsupported(E, "scalar expression"); - if (E->getType()->isVoidType()) - return nullptr; - return llvm::UndefValue::get(CGF.ConvertType(E->getType())); -} - -Value *ScalarExprEmitter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { - // Vector Mask Case - if (E->getNumSubExprs() == 2) { - Value *LHS = CGF.EmitScalarExpr(E->getExpr(0)); - Value *RHS = CGF.EmitScalarExpr(E->getExpr(1)); - Value *Mask; - - llvm::VectorType *LTy = cast<llvm::VectorType>(LHS->getType()); - unsigned LHSElts = LTy->getNumElements(); - - Mask = RHS; - - llvm::VectorType *MTy = cast<llvm::VectorType>(Mask->getType()); - - // Mask off the high bits of each shuffle index. - Value *MaskBits = - llvm::ConstantInt::get(MTy, llvm::NextPowerOf2(LHSElts - 1) - 1); - Mask = Builder.CreateAnd(Mask, MaskBits, "mask"); - - // newv = undef - // mask = mask & maskbits - // for each elt - // n = extract mask i - // x = extract val n - // newv = insert newv, x, i - llvm::VectorType *RTy = llvm::VectorType::get(LTy->getElementType(), - MTy->getNumElements()); - Value* NewV = llvm::UndefValue::get(RTy); - for (unsigned i = 0, e = MTy->getNumElements(); i != e; ++i) { - Value *IIndx = llvm::ConstantInt::get(CGF.SizeTy, i); - Value *Indx = Builder.CreateExtractElement(Mask, IIndx, "shuf_idx"); - - Value *VExt = Builder.CreateExtractElement(LHS, Indx, "shuf_elt"); - NewV = Builder.CreateInsertElement(NewV, VExt, IIndx, "shuf_ins"); - } - return NewV; - } - - Value* V1 = CGF.EmitScalarExpr(E->getExpr(0)); - Value* V2 = CGF.EmitScalarExpr(E->getExpr(1)); - - SmallVector<llvm::Constant*, 32> indices; - for (unsigned i = 2; i < E->getNumSubExprs(); ++i) { - llvm::APSInt Idx = E->getShuffleMaskIdx(CGF.getContext(), i-2); - // Check for -1 and output it as undef in the IR. - if (Idx.isSigned() && Idx.isAllOnesValue()) - indices.push_back(llvm::UndefValue::get(CGF.Int32Ty)); - else - indices.push_back(Builder.getInt32(Idx.getZExtValue())); - } - - Value *SV = llvm::ConstantVector::get(indices); - return Builder.CreateShuffleVector(V1, V2, SV, "shuffle"); -} - -Value *ScalarExprEmitter::VisitConvertVectorExpr(ConvertVectorExpr *E) { - QualType SrcType = E->getSrcExpr()->getType(), - DstType = E->getType(); - - Value *Src = CGF.EmitScalarExpr(E->getSrcExpr()); - - SrcType = CGF.getContext().getCanonicalType(SrcType); - DstType = CGF.getContext().getCanonicalType(DstType); - if (SrcType == DstType) return Src; - - assert(SrcType->isVectorType() && - "ConvertVector source type must be a vector"); - assert(DstType->isVectorType() && - "ConvertVector destination type must be a vector"); - - llvm::Type *SrcTy = Src->getType(); - llvm::Type *DstTy = ConvertType(DstType); - - // Ignore conversions like int -> uint. - if (SrcTy == DstTy) - return Src; - - QualType SrcEltType = SrcType->getAs<VectorType>()->getElementType(), - DstEltType = DstType->getAs<VectorType>()->getElementType(); - - assert(SrcTy->isVectorTy() && - "ConvertVector source IR type must be a vector"); - assert(DstTy->isVectorTy() && - "ConvertVector destination IR type must be a vector"); - - llvm::Type *SrcEltTy = SrcTy->getVectorElementType(), - *DstEltTy = DstTy->getVectorElementType(); - - if (DstEltType->isBooleanType()) { - assert((SrcEltTy->isFloatingPointTy() || - isa<llvm::IntegerType>(SrcEltTy)) && "Unknown boolean conversion"); - - llvm::Value *Zero = llvm::Constant::getNullValue(SrcTy); - if (SrcEltTy->isFloatingPointTy()) { - return Builder.CreateFCmpUNE(Src, Zero, "tobool"); - } else { - return Builder.CreateICmpNE(Src, Zero, "tobool"); - } - } - - // We have the arithmetic types: real int/float. - Value *Res = nullptr; - - if (isa<llvm::IntegerType>(SrcEltTy)) { - bool InputSigned = SrcEltType->isSignedIntegerOrEnumerationType(); - if (isa<llvm::IntegerType>(DstEltTy)) - Res = Builder.CreateIntCast(Src, DstTy, InputSigned, "conv"); - else if (InputSigned) - Res = Builder.CreateSIToFP(Src, DstTy, "conv"); - else - Res = Builder.CreateUIToFP(Src, DstTy, "conv"); - } else if (isa<llvm::IntegerType>(DstEltTy)) { - assert(SrcEltTy->isFloatingPointTy() && "Unknown real conversion"); - if (DstEltType->isSignedIntegerOrEnumerationType()) - Res = Builder.CreateFPToSI(Src, DstTy, "conv"); - else - Res = Builder.CreateFPToUI(Src, DstTy, "conv"); - } else { - assert(SrcEltTy->isFloatingPointTy() && DstEltTy->isFloatingPointTy() && - "Unknown real conversion"); - if (DstEltTy->getTypeID() < SrcEltTy->getTypeID()) - Res = Builder.CreateFPTrunc(Src, DstTy, "conv"); - else - Res = Builder.CreateFPExt(Src, DstTy, "conv"); - } - - return Res; -} - -Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) { - if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(E)) { - CGF.EmitIgnoredExpr(E->getBase()); - return CGF.emitScalarConstant(Constant, E); - } else { - Expr::EvalResult Result; - if (E->EvaluateAsInt(Result, CGF.getContext(), Expr::SE_AllowSideEffects)) { - llvm::APSInt Value = Result.Val.getInt(); - CGF.EmitIgnoredExpr(E->getBase()); - return Builder.getInt(Value); - } - } - - return EmitLoadOfLValue(E); -} - -Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { - TestAndClearIgnoreResultAssign(); - - // Emit subscript expressions in rvalue context's. For most cases, this just - // loads the lvalue formed by the subscript expr. However, we have to be - // careful, because the base of a vector subscript is occasionally an rvalue, - // so we can't get it as an lvalue. - if (!E->getBase()->getType()->isVectorType()) - return EmitLoadOfLValue(E); - - // Handle the vector case. The base must be a vector, the index must be an - // integer value. - Value *Base = Visit(E->getBase()); - Value *Idx = Visit(E->getIdx()); - QualType IdxTy = E->getIdx()->getType(); - - if (CGF.SanOpts.has(SanitizerKind::ArrayBounds)) - CGF.EmitBoundsCheck(E, E->getBase(), Idx, IdxTy, /*Accessed*/true); - - return Builder.CreateExtractElement(Base, Idx, "vecext"); -} - -static llvm::Constant *getMaskElt(llvm::ShuffleVectorInst *SVI, unsigned Idx, - unsigned Off, llvm::Type *I32Ty) { - int MV = SVI->getMaskValue(Idx); - if (MV == -1) - return llvm::UndefValue::get(I32Ty); - return llvm::ConstantInt::get(I32Ty, Off+MV); -} - -static llvm::Constant *getAsInt32(llvm::ConstantInt *C, llvm::Type *I32Ty) { - if (C->getBitWidth() != 32) { - assert(llvm::ConstantInt::isValueValidForType(I32Ty, - C->getZExtValue()) && - "Index operand too large for shufflevector mask!"); - return llvm::ConstantInt::get(I32Ty, C->getZExtValue()); - } - return C; -} - -Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { - bool Ignore = TestAndClearIgnoreResultAssign(); - (void)Ignore; - assert (Ignore == false && "init list ignored"); - unsigned NumInitElements = E->getNumInits(); - - if (E->hadArrayRangeDesignator()) - CGF.ErrorUnsupported(E, "GNU array range designator extension"); - - llvm::VectorType *VType = - dyn_cast<llvm::VectorType>(ConvertType(E->getType())); - - if (!VType) { - if (NumInitElements == 0) { - // C++11 value-initialization for the scalar. - return EmitNullValue(E->getType()); - } - // We have a scalar in braces. Just use the first element. - return Visit(E->getInit(0)); - } - - unsigned ResElts = VType->getNumElements(); - - // Loop over initializers collecting the Value for each, and remembering - // whether the source was swizzle (ExtVectorElementExpr). This will allow - // us to fold the shuffle for the swizzle into the shuffle for the vector - // initializer, since LLVM optimizers generally do not want to touch - // shuffles. - unsigned CurIdx = 0; - bool VIsUndefShuffle = false; - llvm::Value *V = llvm::UndefValue::get(VType); - for (unsigned i = 0; i != NumInitElements; ++i) { - Expr *IE = E->getInit(i); - Value *Init = Visit(IE); - SmallVector<llvm::Constant*, 16> Args; - - llvm::VectorType *VVT = dyn_cast<llvm::VectorType>(Init->getType()); - - // Handle scalar elements. If the scalar initializer is actually one - // element of a different vector of the same width, use shuffle instead of - // extract+insert. - if (!VVT) { - if (isa<ExtVectorElementExpr>(IE)) { - llvm::ExtractElementInst *EI = cast<llvm::ExtractElementInst>(Init); - - if (EI->getVectorOperandType()->getNumElements() == ResElts) { - llvm::ConstantInt *C = cast<llvm::ConstantInt>(EI->getIndexOperand()); - Value *LHS = nullptr, *RHS = nullptr; - if (CurIdx == 0) { - // insert into undef -> shuffle (src, undef) - // shufflemask must use an i32 - Args.push_back(getAsInt32(C, CGF.Int32Ty)); - Args.resize(ResElts, llvm::UndefValue::get(CGF.Int32Ty)); - - LHS = EI->getVectorOperand(); - RHS = V; - VIsUndefShuffle = true; - } else if (VIsUndefShuffle) { - // insert into undefshuffle && size match -> shuffle (v, src) - llvm::ShuffleVectorInst *SVV = cast<llvm::ShuffleVectorInst>(V); - for (unsigned j = 0; j != CurIdx; ++j) - Args.push_back(getMaskElt(SVV, j, 0, CGF.Int32Ty)); - Args.push_back(Builder.getInt32(ResElts + C->getZExtValue())); - Args.resize(ResElts, llvm::UndefValue::get(CGF.Int32Ty)); - - LHS = cast<llvm::ShuffleVectorInst>(V)->getOperand(0); - RHS = EI->getVectorOperand(); - VIsUndefShuffle = false; - } - if (!Args.empty()) { - llvm::Constant *Mask = llvm::ConstantVector::get(Args); - V = Builder.CreateShuffleVector(LHS, RHS, Mask); - ++CurIdx; - continue; - } - } - } - V = Builder.CreateInsertElement(V, Init, Builder.getInt32(CurIdx), - "vecinit"); - VIsUndefShuffle = false; - ++CurIdx; - continue; - } - - unsigned InitElts = VVT->getNumElements(); - - // If the initializer is an ExtVecEltExpr (a swizzle), and the swizzle's - // input is the same width as the vector being constructed, generate an - // optimized shuffle of the swizzle input into the result. - unsigned Offset = (CurIdx == 0) ? 0 : ResElts; - if (isa<ExtVectorElementExpr>(IE)) { - llvm::ShuffleVectorInst *SVI = cast<llvm::ShuffleVectorInst>(Init); - Value *SVOp = SVI->getOperand(0); - llvm::VectorType *OpTy = cast<llvm::VectorType>(SVOp->getType()); - - if (OpTy->getNumElements() == ResElts) { - for (unsigned j = 0; j != CurIdx; ++j) { - // If the current vector initializer is a shuffle with undef, merge - // this shuffle directly into it. - if (VIsUndefShuffle) { - Args.push_back(getMaskElt(cast<llvm::ShuffleVectorInst>(V), j, 0, - CGF.Int32Ty)); - } else { - Args.push_back(Builder.getInt32(j)); - } - } - for (unsigned j = 0, je = InitElts; j != je; ++j) - Args.push_back(getMaskElt(SVI, j, Offset, CGF.Int32Ty)); - Args.resize(ResElts, llvm::UndefValue::get(CGF.Int32Ty)); - - if (VIsUndefShuffle) - V = cast<llvm::ShuffleVectorInst>(V)->getOperand(0); - - Init = SVOp; - } - } - - // Extend init to result vector length, and then shuffle its contribution - // to the vector initializer into V. - if (Args.empty()) { - for (unsigned j = 0; j != InitElts; ++j) - Args.push_back(Builder.getInt32(j)); - Args.resize(ResElts, llvm::UndefValue::get(CGF.Int32Ty)); - llvm::Constant *Mask = llvm::ConstantVector::get(Args); - Init = Builder.CreateShuffleVector(Init, llvm::UndefValue::get(VVT), - Mask, "vext"); - - Args.clear(); - for (unsigned j = 0; j != CurIdx; ++j) - Args.push_back(Builder.getInt32(j)); - for (unsigned j = 0; j != InitElts; ++j) - Args.push_back(Builder.getInt32(j+Offset)); - Args.resize(ResElts, llvm::UndefValue::get(CGF.Int32Ty)); - } - - // If V is undef, make sure it ends up on the RHS of the shuffle to aid - // merging subsequent shuffles into this one. - if (CurIdx == 0) - std::swap(V, Init); - llvm::Constant *Mask = llvm::ConstantVector::get(Args); - V = Builder.CreateShuffleVector(V, Init, Mask, "vecinit"); - VIsUndefShuffle = isa<llvm::UndefValue>(Init); - CurIdx += InitElts; - } - - // FIXME: evaluate codegen vs. shuffling against constant null vector. - // Emit remaining default initializers. - llvm::Type *EltTy = VType->getElementType(); - - // Emit remaining default initializers - for (/* Do not initialize i*/; CurIdx < ResElts; ++CurIdx) { - Value *Idx = Builder.getInt32(CurIdx); - llvm::Value *Init = llvm::Constant::getNullValue(EltTy); - V = Builder.CreateInsertElement(V, Init, Idx, "vecinit"); - } - return V; -} - -bool CodeGenFunction::ShouldNullCheckClassCastValue(const CastExpr *CE) { - const Expr *E = CE->getSubExpr(); - - if (CE->getCastKind() == CK_UncheckedDerivedToBase) - return false; - - if (isa<CXXThisExpr>(E->IgnoreParens())) { - // We always assume that 'this' is never null. - return false; - } - - if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(CE)) { - // And that glvalue casts are never null. - if (ICE->getValueKind() != VK_RValue) - return false; - } - - return true; -} - -// VisitCastExpr - Emit code for an explicit or implicit cast. Implicit casts -// have to handle a more broad range of conversions than explicit casts, as they -// handle things like function to ptr-to-function decay etc. -Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { - Expr *E = CE->getSubExpr(); - QualType DestTy = CE->getType(); - CastKind Kind = CE->getCastKind(); - - // These cases are generally not written to ignore the result of - // evaluating their sub-expressions, so we clear this now. - bool Ignored = TestAndClearIgnoreResultAssign(); - - // Since almost all cast kinds apply to scalars, this switch doesn't have - // a default case, so the compiler will warn on a missing case. The cases - // are in the same order as in the CastKind enum. - switch (Kind) { - case CK_Dependent: llvm_unreachable("dependent cast kind in IR gen!"); - case CK_BuiltinFnToFnPtr: - llvm_unreachable("builtin functions are handled elsewhere"); - - case CK_LValueBitCast: - case CK_ObjCObjectLValueCast: { - Address Addr = EmitLValue(E).getAddress(); - Addr = Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(DestTy)); - LValue LV = CGF.MakeAddrLValue(Addr, DestTy); - return EmitLoadOfLValue(LV, CE->getExprLoc()); - } - - case CK_CPointerToObjCPointerCast: - case CK_BlockPointerToObjCPointerCast: - case CK_AnyPointerToBlockPointerCast: - case CK_BitCast: { - Value *Src = Visit(const_cast<Expr*>(E)); - llvm::Type *SrcTy = Src->getType(); - llvm::Type *DstTy = ConvertType(DestTy); - if (SrcTy->isPtrOrPtrVectorTy() && DstTy->isPtrOrPtrVectorTy() && - SrcTy->getPointerAddressSpace() != DstTy->getPointerAddressSpace()) { - llvm_unreachable("wrong cast for pointers in different address spaces" - "(must be an address space cast)!"); - } - - if (CGF.SanOpts.has(SanitizerKind::CFIUnrelatedCast)) { - if (auto PT = DestTy->getAs<PointerType>()) - CGF.EmitVTablePtrCheckForCast(PT->getPointeeType(), Src, - /*MayBeNull=*/true, - CodeGenFunction::CFITCK_UnrelatedCast, - CE->getBeginLoc()); - } - - if (CGF.CGM.getCodeGenOpts().StrictVTablePointers) { - const QualType SrcType = E->getType(); - - if (SrcType.mayBeNotDynamicClass() && DestTy.mayBeDynamicClass()) { - // Casting to pointer that could carry dynamic information (provided by - // invariant.group) requires launder. - Src = Builder.CreateLaunderInvariantGroup(Src); - } else if (SrcType.mayBeDynamicClass() && DestTy.mayBeNotDynamicClass()) { - // Casting to pointer that does not carry dynamic information (provided - // by invariant.group) requires stripping it. Note that we don't do it - // if the source could not be dynamic type and destination could be - // dynamic because dynamic information is already laundered. It is - // because launder(strip(src)) == launder(src), so there is no need to - // add extra strip before launder. - Src = Builder.CreateStripInvariantGroup(Src); - } - } - - return Builder.CreateBitCast(Src, DstTy); - } - case CK_AddressSpaceConversion: { - Expr::EvalResult Result; - if (E->EvaluateAsRValue(Result, CGF.getContext()) && - Result.Val.isNullPointer()) { - // If E has side effect, it is emitted even if its final result is a - // null pointer. In that case, a DCE pass should be able to - // eliminate the useless instructions emitted during translating E. - if (Result.HasSideEffects) - Visit(E); - return CGF.CGM.getNullPointer(cast<llvm::PointerType>( - ConvertType(DestTy)), DestTy); - } - // Since target may map different address spaces in AST to the same address - // space, an address space conversion may end up as a bitcast. - return CGF.CGM.getTargetCodeGenInfo().performAddrSpaceCast( - CGF, Visit(E), E->getType()->getPointeeType().getAddressSpace(), - DestTy->getPointeeType().getAddressSpace(), ConvertType(DestTy)); - } - case CK_AtomicToNonAtomic: - case CK_NonAtomicToAtomic: - case CK_NoOp: - case CK_UserDefinedConversion: - return Visit(const_cast<Expr*>(E)); - - case CK_BaseToDerived: { - const CXXRecordDecl *DerivedClassDecl = DestTy->getPointeeCXXRecordDecl(); - assert(DerivedClassDecl && "BaseToDerived arg isn't a C++ object pointer!"); - - Address Base = CGF.EmitPointerWithAlignment(E); - Address Derived = - CGF.GetAddressOfDerivedClass(Base, DerivedClassDecl, - CE->path_begin(), CE->path_end(), - CGF.ShouldNullCheckClassCastValue(CE)); - - // C++11 [expr.static.cast]p11: Behavior is undefined if a downcast is - // performed and the object is not of the derived type. - if (CGF.sanitizePerformTypeCheck()) - CGF.EmitTypeCheck(CodeGenFunction::TCK_DowncastPointer, CE->getExprLoc(), - Derived.getPointer(), DestTy->getPointeeType()); - - if (CGF.SanOpts.has(SanitizerKind::CFIDerivedCast)) - CGF.EmitVTablePtrCheckForCast( - DestTy->getPointeeType(), Derived.getPointer(), - /*MayBeNull=*/true, CodeGenFunction::CFITCK_DerivedCast, - CE->getBeginLoc()); - - return Derived.getPointer(); - } - case CK_UncheckedDerivedToBase: - case CK_DerivedToBase: { - // The EmitPointerWithAlignment path does this fine; just discard - // the alignment. - return CGF.EmitPointerWithAlignment(CE).getPointer(); - } - - case CK_Dynamic: { - Address V = CGF.EmitPointerWithAlignment(E); - const CXXDynamicCastExpr *DCE = cast<CXXDynamicCastExpr>(CE); - return CGF.EmitDynamicCast(V, DCE); - } - - case CK_ArrayToPointerDecay: - return CGF.EmitArrayToPointerDecay(E).getPointer(); - case CK_FunctionToPointerDecay: - return EmitLValue(E).getPointer(); - - case CK_NullToPointer: - if (MustVisitNullValue(E)) - (void) Visit(E); - - return CGF.CGM.getNullPointer(cast<llvm::PointerType>(ConvertType(DestTy)), - DestTy); - - case CK_NullToMemberPointer: { - if (MustVisitNullValue(E)) - (void) Visit(E); - - const MemberPointerType *MPT = CE->getType()->getAs<MemberPointerType>(); - return CGF.CGM.getCXXABI().EmitNullMemberPointer(MPT); - } - - case CK_ReinterpretMemberPointer: - case CK_BaseToDerivedMemberPointer: - case CK_DerivedToBaseMemberPointer: { - Value *Src = Visit(E); - - // Note that the AST doesn't distinguish between checked and - // unchecked member pointer conversions, so we always have to - // implement checked conversions here. This is inefficient when - // actual control flow may be required in order to perform the - // check, which it is for data member pointers (but not member - // function pointers on Itanium and ARM). - return CGF.CGM.getCXXABI().EmitMemberPointerConversion(CGF, CE, Src); - } - - case CK_ARCProduceObject: - return CGF.EmitARCRetainScalarExpr(E); - case CK_ARCConsumeObject: - return CGF.EmitObjCConsumeObject(E->getType(), Visit(E)); - case CK_ARCReclaimReturnedObject: - return CGF.EmitARCReclaimReturnedObject(E, /*allowUnsafe*/ Ignored); - case CK_ARCExtendBlockObject: - return CGF.EmitARCExtendBlockObject(E); - - case CK_CopyAndAutoreleaseBlockObject: - return CGF.EmitBlockCopyAndAutorelease(Visit(E), E->getType()); - - case CK_FloatingRealToComplex: - case CK_FloatingComplexCast: - case CK_IntegralRealToComplex: - case CK_IntegralComplexCast: - case CK_IntegralComplexToFloatingComplex: - case CK_FloatingComplexToIntegralComplex: - case CK_ConstructorConversion: - case CK_ToUnion: - llvm_unreachable("scalar cast to non-scalar value"); - - case CK_LValueToRValue: - assert(CGF.getContext().hasSameUnqualifiedType(E->getType(), DestTy)); - assert(E->isGLValue() && "lvalue-to-rvalue applied to r-value!"); - return Visit(const_cast<Expr*>(E)); - - case CK_IntegralToPointer: { - Value *Src = Visit(const_cast<Expr*>(E)); - - // First, convert to the correct width so that we control the kind of - // extension. - auto DestLLVMTy = ConvertType(DestTy); - llvm::Type *MiddleTy = CGF.CGM.getDataLayout().getIntPtrType(DestLLVMTy); - bool InputSigned = E->getType()->isSignedIntegerOrEnumerationType(); - llvm::Value* IntResult = - Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv"); - - auto *IntToPtr = Builder.CreateIntToPtr(IntResult, DestLLVMTy); - - if (CGF.CGM.getCodeGenOpts().StrictVTablePointers) { - // Going from integer to pointer that could be dynamic requires reloading - // dynamic information from invariant.group. - if (DestTy.mayBeDynamicClass()) - IntToPtr = Builder.CreateLaunderInvariantGroup(IntToPtr); - } - return IntToPtr; - } - case CK_PointerToIntegral: { - assert(!DestTy->isBooleanType() && "bool should use PointerToBool"); - auto *PtrExpr = Visit(E); - - if (CGF.CGM.getCodeGenOpts().StrictVTablePointers) { - const QualType SrcType = E->getType(); - - // Casting to integer requires stripping dynamic information as it does - // not carries it. - if (SrcType.mayBeDynamicClass()) - PtrExpr = Builder.CreateStripInvariantGroup(PtrExpr); - } - - return Builder.CreatePtrToInt(PtrExpr, ConvertType(DestTy)); - } - case CK_ToVoid: { - CGF.EmitIgnoredExpr(E); - return nullptr; - } - case CK_VectorSplat: { - llvm::Type *DstTy = ConvertType(DestTy); - Value *Elt = Visit(const_cast<Expr*>(E)); - // Splat the element across to all elements - unsigned NumElements = DstTy->getVectorNumElements(); - return Builder.CreateVectorSplat(NumElements, Elt, "splat"); - } - - case CK_FixedPointCast: - return EmitScalarConversion(Visit(E), E->getType(), DestTy, - CE->getExprLoc()); - - case CK_FixedPointToBoolean: - assert(E->getType()->isFixedPointType() && - "Expected src type to be fixed point type"); - assert(DestTy->isBooleanType() && "Expected dest type to be boolean type"); - return EmitScalarConversion(Visit(E), E->getType(), DestTy, - CE->getExprLoc()); - - case CK_IntegralCast: { - ScalarConversionOpts Opts; - if (auto *ICE = dyn_cast<ImplicitCastExpr>(CE)) { - if (!ICE->isPartOfExplicitCast()) - Opts = ScalarConversionOpts(CGF.SanOpts); - } - return EmitScalarConversion(Visit(E), E->getType(), DestTy, - CE->getExprLoc(), Opts); - } - case CK_IntegralToFloating: - case CK_FloatingToIntegral: - case CK_FloatingCast: - return EmitScalarConversion(Visit(E), E->getType(), DestTy, - CE->getExprLoc()); - case CK_BooleanToSignedIntegral: { - ScalarConversionOpts Opts; - Opts.TreatBooleanAsSigned = true; - return EmitScalarConversion(Visit(E), E->getType(), DestTy, - CE->getExprLoc(), Opts); - } - case CK_IntegralToBoolean: - return EmitIntToBoolConversion(Visit(E)); - case CK_PointerToBoolean: - return EmitPointerToBoolConversion(Visit(E), E->getType()); - case CK_FloatingToBoolean: - return EmitFloatToBoolConversion(Visit(E)); - case CK_MemberPointerToBoolean: { - llvm::Value *MemPtr = Visit(E); - const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>(); - return CGF.CGM.getCXXABI().EmitMemberPointerIsNotNull(CGF, MemPtr, MPT); - } - - case CK_FloatingComplexToReal: - case CK_IntegralComplexToReal: - return CGF.EmitComplexExpr(E, false, true).first; - - case CK_FloatingComplexToBoolean: - case CK_IntegralComplexToBoolean: { - CodeGenFunction::ComplexPairTy V = CGF.EmitComplexExpr(E); - - // TODO: kill this function off, inline appropriate case here - return EmitComplexToScalarConversion(V, E->getType(), DestTy, - CE->getExprLoc()); - } - - case CK_ZeroToOCLOpaqueType: { - assert((DestTy->isEventT() || DestTy->isQueueT() || - DestTy->isOCLIntelSubgroupAVCType()) && - "CK_ZeroToOCLEvent cast on non-event type"); - return llvm::Constant::getNullValue(ConvertType(DestTy)); - } - - case CK_IntToOCLSampler: - return CGF.CGM.createOpenCLIntToSamplerConversion(E, CGF); - - } // end of switch - - llvm_unreachable("unknown scalar cast"); -} - -Value *ScalarExprEmitter::VisitStmtExpr(const StmtExpr *E) { - CodeGenFunction::StmtExprEvaluation eval(CGF); - Address RetAlloca = CGF.EmitCompoundStmt(*E->getSubStmt(), - !E->getType()->isVoidType()); - if (!RetAlloca.isValid()) - return nullptr; - return CGF.EmitLoadOfScalar(CGF.MakeAddrLValue(RetAlloca, E->getType()), - E->getExprLoc()); -} - -Value *ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *E) { - CGF.enterFullExpression(E); - CodeGenFunction::RunCleanupsScope Scope(CGF); - Value *V = Visit(E->getSubExpr()); - // Defend against dominance problems caused by jumps out of expression - // evaluation through the shared cleanup block. - Scope.ForceCleanup({&V}); - return V; -} - -//===----------------------------------------------------------------------===// -// Unary Operators -//===----------------------------------------------------------------------===// - -static BinOpInfo createBinOpInfoFromIncDec(const UnaryOperator *E, - llvm::Value *InVal, bool IsInc) { - BinOpInfo BinOp; - BinOp.LHS = InVal; - BinOp.RHS = llvm::ConstantInt::get(InVal->getType(), 1, false); - BinOp.Ty = E->getType(); - BinOp.Opcode = IsInc ? BO_Add : BO_Sub; - // FIXME: once UnaryOperator carries FPFeatures, copy it here. - BinOp.E = E; - return BinOp; -} - -llvm::Value *ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior( - const UnaryOperator *E, llvm::Value *InVal, bool IsInc) { - llvm::Value *Amount = - llvm::ConstantInt::get(InVal->getType(), IsInc ? 1 : -1, true); - StringRef Name = IsInc ? "inc" : "dec"; - switch (CGF.getLangOpts().getSignedOverflowBehavior()) { - case LangOptions::SOB_Defined: - return Builder.CreateAdd(InVal, Amount, Name); - case LangOptions::SOB_Undefined: - if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) - return Builder.CreateNSWAdd(InVal, Amount, Name); - LLVM_FALLTHROUGH; - case LangOptions::SOB_Trapping: - if (!E->canOverflow()) - return Builder.CreateNSWAdd(InVal, Amount, Name); - return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(E, InVal, IsInc)); - } - llvm_unreachable("Unknown SignedOverflowBehaviorTy"); -} - -llvm::Value * -ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, - bool isInc, bool isPre) { - - QualType type = E->getSubExpr()->getType(); - llvm::PHINode *atomicPHI = nullptr; - llvm::Value *value; - llvm::Value *input; - - int amount = (isInc ? 1 : -1); - bool isSubtraction = !isInc; - - if (const AtomicType *atomicTy = type->getAs<AtomicType>()) { - type = atomicTy->getValueType(); - if (isInc && type->isBooleanType()) { - llvm::Value *True = CGF.EmitToMemory(Builder.getTrue(), type); - if (isPre) { - Builder.CreateStore(True, LV.getAddress(), LV.isVolatileQualified()) - ->setAtomic(llvm::AtomicOrdering::SequentiallyConsistent); - return Builder.getTrue(); - } - // For atomic bool increment, we just store true and return it for - // preincrement, do an atomic swap with true for postincrement - return Builder.CreateAtomicRMW( - llvm::AtomicRMWInst::Xchg, LV.getPointer(), True, - llvm::AtomicOrdering::SequentiallyConsistent); - } - // Special case for atomic increment / decrement on integers, emit - // atomicrmw instructions. We skip this if we want to be doing overflow - // checking, and fall into the slow path with the atomic cmpxchg loop. - if (!type->isBooleanType() && type->isIntegerType() && - !(type->isUnsignedIntegerType() && - CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) && - CGF.getLangOpts().getSignedOverflowBehavior() != - LangOptions::SOB_Trapping) { - llvm::AtomicRMWInst::BinOp aop = isInc ? llvm::AtomicRMWInst::Add : - llvm::AtomicRMWInst::Sub; - llvm::Instruction::BinaryOps op = isInc ? llvm::Instruction::Add : - llvm::Instruction::Sub; - llvm::Value *amt = CGF.EmitToMemory( - llvm::ConstantInt::get(ConvertType(type), 1, true), type); - llvm::Value *old = Builder.CreateAtomicRMW(aop, - LV.getPointer(), amt, llvm::AtomicOrdering::SequentiallyConsistent); - return isPre ? Builder.CreateBinOp(op, old, amt) : old; - } - value = EmitLoadOfLValue(LV, E->getExprLoc()); - input = value; - // For every other atomic operation, we need to emit a load-op-cmpxchg loop - llvm::BasicBlock *startBB = Builder.GetInsertBlock(); - llvm::BasicBlock *opBB = CGF.createBasicBlock("atomic_op", CGF.CurFn); - value = CGF.EmitToMemory(value, type); - Builder.CreateBr(opBB); - Builder.SetInsertPoint(opBB); - atomicPHI = Builder.CreatePHI(value->getType(), 2); - atomicPHI->addIncoming(value, startBB); - value = atomicPHI; - } else { - value = EmitLoadOfLValue(LV, E->getExprLoc()); - input = value; - } - - // Special case of integer increment that we have to check first: bool++. - // Due to promotion rules, we get: - // bool++ -> bool = bool + 1 - // -> bool = (int)bool + 1 - // -> bool = ((int)bool + 1 != 0) - // An interesting aspect of this is that increment is always true. - // Decrement does not have this property. - if (isInc && type->isBooleanType()) { - value = Builder.getTrue(); - - // Most common case by far: integer increment. - } else if (type->isIntegerType()) { - // Note that signed integer inc/dec with width less than int can't - // overflow because of promotion rules; we're just eliding a few steps here. - if (E->canOverflow() && type->isSignedIntegerOrEnumerationType()) { - value = EmitIncDecConsiderOverflowBehavior(E, value, isInc); - } else if (E->canOverflow() && type->isUnsignedIntegerType() && - CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) { - value = - EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(E, value, isInc)); - } else { - llvm::Value *amt = llvm::ConstantInt::get(value->getType(), amount, true); - value = Builder.CreateAdd(value, amt, isInc ? "inc" : "dec"); - } - - // Next most common: pointer increment. - } else if (const PointerType *ptr = type->getAs<PointerType>()) { - QualType type = ptr->getPointeeType(); - - // VLA types don't have constant size. - if (const VariableArrayType *vla - = CGF.getContext().getAsVariableArrayType(type)) { - llvm::Value *numElts = CGF.getVLASize(vla).NumElts; - if (!isInc) numElts = Builder.CreateNSWNeg(numElts, "vla.negsize"); - if (CGF.getLangOpts().isSignedOverflowDefined()) - value = Builder.CreateGEP(value, numElts, "vla.inc"); - else - value = CGF.EmitCheckedInBoundsGEP( - value, numElts, /*SignedIndices=*/false, isSubtraction, - E->getExprLoc(), "vla.inc"); - - // Arithmetic on function pointers (!) is just +-1. - } else if (type->isFunctionType()) { - llvm::Value *amt = Builder.getInt32(amount); - - value = CGF.EmitCastToVoidPtr(value); - if (CGF.getLangOpts().isSignedOverflowDefined()) - value = Builder.CreateGEP(value, amt, "incdec.funcptr"); - else - value = CGF.EmitCheckedInBoundsGEP(value, amt, /*SignedIndices=*/false, - isSubtraction, E->getExprLoc(), - "incdec.funcptr"); - value = Builder.CreateBitCast(value, input->getType()); - - // For everything else, we can just do a simple increment. - } else { - llvm::Value *amt = Builder.getInt32(amount); - if (CGF.getLangOpts().isSignedOverflowDefined()) - value = Builder.CreateGEP(value, amt, "incdec.ptr"); - else - value = CGF.EmitCheckedInBoundsGEP(value, amt, /*SignedIndices=*/false, - isSubtraction, E->getExprLoc(), - "incdec.ptr"); - } - - // Vector increment/decrement. - } else if (type->isVectorType()) { - if (type->hasIntegerRepresentation()) { - llvm::Value *amt = llvm::ConstantInt::get(value->getType(), amount); - - value = Builder.CreateAdd(value, amt, isInc ? "inc" : "dec"); - } else { - value = Builder.CreateFAdd( - value, - llvm::ConstantFP::get(value->getType(), amount), - isInc ? "inc" : "dec"); - } - - // Floating point. - } else if (type->isRealFloatingType()) { - // Add the inc/dec to the real part. - llvm::Value *amt; - - if (type->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) { - // Another special case: half FP increment should be done via float - if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) { - value = Builder.CreateCall( - CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16, - CGF.CGM.FloatTy), - input, "incdec.conv"); - } else { - value = Builder.CreateFPExt(input, CGF.CGM.FloatTy, "incdec.conv"); - } - } - - if (value->getType()->isFloatTy()) - amt = llvm::ConstantFP::get(VMContext, - llvm::APFloat(static_cast<float>(amount))); - else if (value->getType()->isDoubleTy()) - amt = llvm::ConstantFP::get(VMContext, - llvm::APFloat(static_cast<double>(amount))); - else { - // Remaining types are Half, LongDouble or __float128. Convert from float. - llvm::APFloat F(static_cast<float>(amount)); - bool ignored; - const llvm::fltSemantics *FS; - // Don't use getFloatTypeSemantics because Half isn't - // necessarily represented using the "half" LLVM type. - if (value->getType()->isFP128Ty()) - FS = &CGF.getTarget().getFloat128Format(); - else if (value->getType()->isHalfTy()) - FS = &CGF.getTarget().getHalfFormat(); - else - FS = &CGF.getTarget().getLongDoubleFormat(); - F.convert(*FS, llvm::APFloat::rmTowardZero, &ignored); - amt = llvm::ConstantFP::get(VMContext, F); - } - value = Builder.CreateFAdd(value, amt, isInc ? "inc" : "dec"); - - if (type->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) { - if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) { - value = Builder.CreateCall( - CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16, - CGF.CGM.FloatTy), - value, "incdec.conv"); - } else { - value = Builder.CreateFPTrunc(value, input->getType(), "incdec.conv"); - } - } - - // Objective-C pointer types. - } else { - const ObjCObjectPointerType *OPT = type->castAs<ObjCObjectPointerType>(); - value = CGF.EmitCastToVoidPtr(value); - - CharUnits size = CGF.getContext().getTypeSizeInChars(OPT->getObjectType()); - if (!isInc) size = -size; - llvm::Value *sizeValue = - llvm::ConstantInt::get(CGF.SizeTy, size.getQuantity()); - - if (CGF.getLangOpts().isSignedOverflowDefined()) - value = Builder.CreateGEP(value, sizeValue, "incdec.objptr"); - else - value = CGF.EmitCheckedInBoundsGEP(value, sizeValue, - /*SignedIndices=*/false, isSubtraction, - E->getExprLoc(), "incdec.objptr"); - value = Builder.CreateBitCast(value, input->getType()); - } - - if (atomicPHI) { - llvm::BasicBlock *opBB = Builder.GetInsertBlock(); - llvm::BasicBlock *contBB = CGF.createBasicBlock("atomic_cont", CGF.CurFn); - auto Pair = CGF.EmitAtomicCompareExchange( - LV, RValue::get(atomicPHI), RValue::get(value), E->getExprLoc()); - llvm::Value *old = CGF.EmitToMemory(Pair.first.getScalarVal(), type); - llvm::Value *success = Pair.second; - atomicPHI->addIncoming(old, opBB); - Builder.CreateCondBr(success, contBB, opBB); - Builder.SetInsertPoint(contBB); - return isPre ? value : input; - } - - // Store the updated result through the lvalue. - if (LV.isBitField()) - CGF.EmitStoreThroughBitfieldLValue(RValue::get(value), LV, &value); - else - CGF.EmitStoreThroughLValue(RValue::get(value), LV); - - // If this is a postinc, return the value read from memory, otherwise use the - // updated value. - return isPre ? value : input; -} - - - -Value *ScalarExprEmitter::VisitUnaryMinus(const UnaryOperator *E) { - TestAndClearIgnoreResultAssign(); - // Emit unary minus with EmitSub so we handle overflow cases etc. - BinOpInfo BinOp; - BinOp.RHS = Visit(E->getSubExpr()); - - if (BinOp.RHS->getType()->isFPOrFPVectorTy()) - BinOp.LHS = llvm::ConstantFP::getZeroValueForNegation(BinOp.RHS->getType()); - else - BinOp.LHS = llvm::Constant::getNullValue(BinOp.RHS->getType()); - BinOp.Ty = E->getType(); - BinOp.Opcode = BO_Sub; - // FIXME: once UnaryOperator carries FPFeatures, copy it here. - BinOp.E = E; - return EmitSub(BinOp); -} - -Value *ScalarExprEmitter::VisitUnaryNot(const UnaryOperator *E) { - TestAndClearIgnoreResultAssign(); - Value *Op = Visit(E->getSubExpr()); - return Builder.CreateNot(Op, "neg"); -} - -Value *ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *E) { - // Perform vector logical not on comparison with zero vector. - if (E->getType()->isExtVectorType()) { - Value *Oper = Visit(E->getSubExpr()); - Value *Zero = llvm::Constant::getNullValue(Oper->getType()); - Value *Result; - if (Oper->getType()->isFPOrFPVectorTy()) - Result = Builder.CreateFCmp(llvm::CmpInst::FCMP_OEQ, Oper, Zero, "cmp"); - else - Result = Builder.CreateICmp(llvm::CmpInst::ICMP_EQ, Oper, Zero, "cmp"); - return Builder.CreateSExt(Result, ConvertType(E->getType()), "sext"); - } - - // Compare operand to zero. - Value *BoolVal = CGF.EvaluateExprAsBool(E->getSubExpr()); - - // Invert value. - // TODO: Could dynamically modify easy computations here. For example, if - // the operand is an icmp ne, turn into icmp eq. - BoolVal = Builder.CreateNot(BoolVal, "lnot"); - - // ZExt result to the expr type. - return Builder.CreateZExt(BoolVal, ConvertType(E->getType()), "lnot.ext"); -} - -Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) { - // Try folding the offsetof to a constant. - Expr::EvalResult EVResult; - if (E->EvaluateAsInt(EVResult, CGF.getContext())) { - llvm::APSInt Value = EVResult.Val.getInt(); - return Builder.getInt(Value); - } - - // Loop over the components of the offsetof to compute the value. - unsigned n = E->getNumComponents(); - llvm::Type* ResultType = ConvertType(E->getType()); - llvm::Value* Result = llvm::Constant::getNullValue(ResultType); - QualType CurrentType = E->getTypeSourceInfo()->getType(); - for (unsigned i = 0; i != n; ++i) { - OffsetOfNode ON = E->getComponent(i); - llvm::Value *Offset = nullptr; - switch (ON.getKind()) { - case OffsetOfNode::Array: { - // Compute the index - Expr *IdxExpr = E->getIndexExpr(ON.getArrayExprIndex()); - llvm::Value* Idx = CGF.EmitScalarExpr(IdxExpr); - bool IdxSigned = IdxExpr->getType()->isSignedIntegerOrEnumerationType(); - Idx = Builder.CreateIntCast(Idx, ResultType, IdxSigned, "conv"); - - // Save the element type - CurrentType = - CGF.getContext().getAsArrayType(CurrentType)->getElementType(); - - // Compute the element size - llvm::Value* ElemSize = llvm::ConstantInt::get(ResultType, - CGF.getContext().getTypeSizeInChars(CurrentType).getQuantity()); - - // Multiply out to compute the result - Offset = Builder.CreateMul(Idx, ElemSize); - break; - } - - case OffsetOfNode::Field: { - FieldDecl *MemberDecl = ON.getField(); - RecordDecl *RD = CurrentType->getAs<RecordType>()->getDecl(); - const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD); - - // Compute the index of the field in its parent. - unsigned i = 0; - // FIXME: It would be nice if we didn't have to loop here! - for (RecordDecl::field_iterator Field = RD->field_begin(), - FieldEnd = RD->field_end(); - Field != FieldEnd; ++Field, ++i) { - if (*Field == MemberDecl) - break; - } - assert(i < RL.getFieldCount() && "offsetof field in wrong type"); - - // Compute the offset to the field - int64_t OffsetInt = RL.getFieldOffset(i) / - CGF.getContext().getCharWidth(); - Offset = llvm::ConstantInt::get(ResultType, OffsetInt); - - // Save the element type. - CurrentType = MemberDecl->getType(); - break; - } - - case OffsetOfNode::Identifier: - llvm_unreachable("dependent __builtin_offsetof"); - - case OffsetOfNode::Base: { - if (ON.getBase()->isVirtual()) { - CGF.ErrorUnsupported(E, "virtual base in offsetof"); - continue; - } - - RecordDecl *RD = CurrentType->getAs<RecordType>()->getDecl(); - const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD); - - // Save the element type. - CurrentType = ON.getBase()->getType(); - - // Compute the offset to the base. - const RecordType *BaseRT = CurrentType->getAs<RecordType>(); - CXXRecordDecl *BaseRD = cast<CXXRecordDecl>(BaseRT->getDecl()); - CharUnits OffsetInt = RL.getBaseClassOffset(BaseRD); - Offset = llvm::ConstantInt::get(ResultType, OffsetInt.getQuantity()); - break; - } - } - Result = Builder.CreateAdd(Result, Offset); - } - return Result; -} - -/// VisitUnaryExprOrTypeTraitExpr - Return the size or alignment of the type of -/// argument of the sizeof expression as an integer. -Value * -ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr( - const UnaryExprOrTypeTraitExpr *E) { - QualType TypeToSize = E->getTypeOfArgument(); - if (E->getKind() == UETT_SizeOf) { - if (const VariableArrayType *VAT = - CGF.getContext().getAsVariableArrayType(TypeToSize)) { - if (E->isArgumentType()) { - // sizeof(type) - make sure to emit the VLA size. - CGF.EmitVariablyModifiedType(TypeToSize); - } else { - // C99 6.5.3.4p2: If the argument is an expression of type - // VLA, it is evaluated. - CGF.EmitIgnoredExpr(E->getArgumentExpr()); - } - - auto VlaSize = CGF.getVLASize(VAT); - llvm::Value *size = VlaSize.NumElts; - - // Scale the number of non-VLA elements by the non-VLA element size. - CharUnits eltSize = CGF.getContext().getTypeSizeInChars(VlaSize.Type); - if (!eltSize.isOne()) - size = CGF.Builder.CreateNUWMul(CGF.CGM.getSize(eltSize), size); - - return size; - } - } else if (E->getKind() == UETT_OpenMPRequiredSimdAlign) { - auto Alignment = - CGF.getContext() - .toCharUnitsFromBits(CGF.getContext().getOpenMPDefaultSimdAlign( - E->getTypeOfArgument()->getPointeeType())) - .getQuantity(); - return llvm::ConstantInt::get(CGF.SizeTy, Alignment); - } - - // If this isn't sizeof(vla), the result must be constant; use the constant - // folding logic so we don't have to duplicate it here. - return Builder.getInt(E->EvaluateKnownConstInt(CGF.getContext())); -} - -Value *ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *E) { - Expr *Op = E->getSubExpr(); - if (Op->getType()->isAnyComplexType()) { - // If it's an l-value, load through the appropriate subobject l-value. - // Note that we have to ask E because Op might be an l-value that - // this won't work for, e.g. an Obj-C property. - if (E->isGLValue()) - return CGF.EmitLoadOfLValue(CGF.EmitLValue(E), - E->getExprLoc()).getScalarVal(); - - // Otherwise, calculate and project. - return CGF.EmitComplexExpr(Op, false, true).first; - } - - return Visit(Op); -} - -Value *ScalarExprEmitter::VisitUnaryImag(const UnaryOperator *E) { - Expr *Op = E->getSubExpr(); - if (Op->getType()->isAnyComplexType()) { - // If it's an l-value, load through the appropriate subobject l-value. - // Note that we have to ask E because Op might be an l-value that - // this won't work for, e.g. an Obj-C property. - if (Op->isGLValue()) - return CGF.EmitLoadOfLValue(CGF.EmitLValue(E), - E->getExprLoc()).getScalarVal(); - - // Otherwise, calculate and project. - return CGF.EmitComplexExpr(Op, true, false).second; - } - - // __imag on a scalar returns zero. Emit the subexpr to ensure side - // effects are evaluated, but not the actual value. - if (Op->isGLValue()) - CGF.EmitLValue(Op); - else - CGF.EmitScalarExpr(Op, true); - return llvm::Constant::getNullValue(ConvertType(E->getType())); -} - -//===----------------------------------------------------------------------===// -// Binary Operators -//===----------------------------------------------------------------------===// - -BinOpInfo ScalarExprEmitter::EmitBinOps(const BinaryOperator *E) { - TestAndClearIgnoreResultAssign(); - BinOpInfo Result; - Result.LHS = Visit(E->getLHS()); - Result.RHS = Visit(E->getRHS()); - Result.Ty = E->getType(); - Result.Opcode = E->getOpcode(); - Result.FPFeatures = E->getFPFeatures(); - Result.E = E; - return Result; -} - -LValue ScalarExprEmitter::EmitCompoundAssignLValue( - const CompoundAssignOperator *E, - Value *(ScalarExprEmitter::*Func)(const BinOpInfo &), - Value *&Result) { - QualType LHSTy = E->getLHS()->getType(); - BinOpInfo OpInfo; - - if (E->getComputationResultType()->isAnyComplexType()) - return CGF.EmitScalarCompoundAssignWithComplex(E, Result); - - // Emit the RHS first. __block variables need to have the rhs evaluated - // first, plus this should improve codegen a little. - OpInfo.RHS = Visit(E->getRHS()); - OpInfo.Ty = E->getComputationResultType(); - OpInfo.Opcode = E->getOpcode(); - OpInfo.FPFeatures = E->getFPFeatures(); - OpInfo.E = E; - // Load/convert the LHS. - LValue LHSLV = EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store); - - llvm::PHINode *atomicPHI = nullptr; - if (const AtomicType *atomicTy = LHSTy->getAs<AtomicType>()) { - QualType type = atomicTy->getValueType(); - if (!type->isBooleanType() && type->isIntegerType() && - !(type->isUnsignedIntegerType() && - CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) && - CGF.getLangOpts().getSignedOverflowBehavior() != - LangOptions::SOB_Trapping) { - llvm::AtomicRMWInst::BinOp aop = llvm::AtomicRMWInst::BAD_BINOP; - switch (OpInfo.Opcode) { - // We don't have atomicrmw operands for *, %, /, <<, >> - case BO_MulAssign: case BO_DivAssign: - case BO_RemAssign: - case BO_ShlAssign: - case BO_ShrAssign: - break; - case BO_AddAssign: - aop = llvm::AtomicRMWInst::Add; - break; - case BO_SubAssign: - aop = llvm::AtomicRMWInst::Sub; - break; - case BO_AndAssign: - aop = llvm::AtomicRMWInst::And; - break; - case BO_XorAssign: - aop = llvm::AtomicRMWInst::Xor; - break; - case BO_OrAssign: - aop = llvm::AtomicRMWInst::Or; - break; - default: - llvm_unreachable("Invalid compound assignment type"); - } - if (aop != llvm::AtomicRMWInst::BAD_BINOP) { - llvm::Value *amt = CGF.EmitToMemory( - EmitScalarConversion(OpInfo.RHS, E->getRHS()->getType(), LHSTy, - E->getExprLoc()), - LHSTy); - Builder.CreateAtomicRMW(aop, LHSLV.getPointer(), amt, - llvm::AtomicOrdering::SequentiallyConsistent); - return LHSLV; - } - } - // FIXME: For floating point types, we should be saving and restoring the - // floating point environment in the loop. - llvm::BasicBlock *startBB = Builder.GetInsertBlock(); - llvm::BasicBlock *opBB = CGF.createBasicBlock("atomic_op", CGF.CurFn); - OpInfo.LHS = EmitLoadOfLValue(LHSLV, E->getExprLoc()); - OpInfo.LHS = CGF.EmitToMemory(OpInfo.LHS, type); - Builder.CreateBr(opBB); - Builder.SetInsertPoint(opBB); - atomicPHI = Builder.CreatePHI(OpInfo.LHS->getType(), 2); - atomicPHI->addIncoming(OpInfo.LHS, startBB); - OpInfo.LHS = atomicPHI; - } - else - OpInfo.LHS = EmitLoadOfLValue(LHSLV, E->getExprLoc()); - - SourceLocation Loc = E->getExprLoc(); - OpInfo.LHS = - EmitScalarConversion(OpInfo.LHS, LHSTy, E->getComputationLHSType(), Loc); - - // Expand the binary operator. - Result = (this->*Func)(OpInfo); - - // Convert the result back to the LHS type, - // potentially with Implicit Conversion sanitizer check. - Result = EmitScalarConversion(Result, E->getComputationResultType(), LHSTy, - Loc, ScalarConversionOpts(CGF.SanOpts)); - - if (atomicPHI) { - llvm::BasicBlock *opBB = Builder.GetInsertBlock(); - llvm::BasicBlock *contBB = CGF.createBasicBlock("atomic_cont", CGF.CurFn); - auto Pair = CGF.EmitAtomicCompareExchange( - LHSLV, RValue::get(atomicPHI), RValue::get(Result), E->getExprLoc()); - llvm::Value *old = CGF.EmitToMemory(Pair.first.getScalarVal(), LHSTy); - llvm::Value *success = Pair.second; - atomicPHI->addIncoming(old, opBB); - Builder.CreateCondBr(success, contBB, opBB); - Builder.SetInsertPoint(contBB); - return LHSLV; - } - - // Store the result value into the LHS lvalue. Bit-fields are handled - // specially because the result is altered by the store, i.e., [C99 6.5.16p1] - // 'An assignment expression has the value of the left operand after the - // assignment...'. - if (LHSLV.isBitField()) - CGF.EmitStoreThroughBitfieldLValue(RValue::get(Result), LHSLV, &Result); - else - CGF.EmitStoreThroughLValue(RValue::get(Result), LHSLV); - - return LHSLV; -} - -Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E, - Value *(ScalarExprEmitter::*Func)(const BinOpInfo &)) { - bool Ignore = TestAndClearIgnoreResultAssign(); - Value *RHS; - LValue LHS = EmitCompoundAssignLValue(E, Func, RHS); - - // If the result is clearly ignored, return now. - if (Ignore) - return nullptr; - - // The result of an assignment in C is the assigned r-value. - if (!CGF.getLangOpts().CPlusPlus) - return RHS; - - // If the lvalue is non-volatile, return the computed value of the assignment. - if (!LHS.isVolatileQualified()) - return RHS; - - // Otherwise, reload the value. - return EmitLoadOfLValue(LHS, E->getExprLoc()); -} - -void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck( - const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) { - SmallVector<std::pair<llvm::Value *, SanitizerMask>, 2> Checks; - - if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero)) { - Checks.push_back(std::make_pair(Builder.CreateICmpNE(Ops.RHS, Zero), - SanitizerKind::IntegerDivideByZero)); - } - - const auto *BO = cast<BinaryOperator>(Ops.E); - if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow) && - Ops.Ty->hasSignedIntegerRepresentation() && - !IsWidenedIntegerOp(CGF.getContext(), BO->getLHS()) && - Ops.mayHaveIntegerOverflow()) { - llvm::IntegerType *Ty = cast<llvm::IntegerType>(Zero->getType()); - - llvm::Value *IntMin = - Builder.getInt(llvm::APInt::getSignedMinValue(Ty->getBitWidth())); - llvm::Value *NegOne = llvm::ConstantInt::get(Ty, -1ULL); - - llvm::Value *LHSCmp = Builder.CreateICmpNE(Ops.LHS, IntMin); - llvm::Value *RHSCmp = Builder.CreateICmpNE(Ops.RHS, NegOne); - llvm::Value *NotOverflow = Builder.CreateOr(LHSCmp, RHSCmp, "or"); - Checks.push_back( - std::make_pair(NotOverflow, SanitizerKind::SignedIntegerOverflow)); - } - - if (Checks.size() > 0) - EmitBinOpCheck(Checks, Ops); -} - -Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) { - { - CodeGenFunction::SanitizerScope SanScope(&CGF); - if ((CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero) || - CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) && - Ops.Ty->isIntegerType() && - (Ops.mayHaveIntegerDivisionByZero() || Ops.mayHaveIntegerOverflow())) { - llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); - EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, true); - } else if (CGF.SanOpts.has(SanitizerKind::FloatDivideByZero) && - Ops.Ty->isRealFloatingType() && - Ops.mayHaveFloatDivisionByZero()) { - llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); - llvm::Value *NonZero = Builder.CreateFCmpUNE(Ops.RHS, Zero); - EmitBinOpCheck(std::make_pair(NonZero, SanitizerKind::FloatDivideByZero), - Ops); - } - } - - if (Ops.LHS->getType()->isFPOrFPVectorTy()) { - llvm::Value *Val = Builder.CreateFDiv(Ops.LHS, Ops.RHS, "div"); - if (CGF.getLangOpts().OpenCL && - !CGF.CGM.getCodeGenOpts().CorrectlyRoundedDivSqrt) { - // OpenCL v1.1 s7.4: minimum accuracy of single precision / is 2.5ulp - // OpenCL v1.2 s5.6.4.2: The -cl-fp32-correctly-rounded-divide-sqrt - // build option allows an application to specify that single precision - // floating-point divide (x/y and 1/x) and sqrt used in the program - // source are correctly rounded. - llvm::Type *ValTy = Val->getType(); - if (ValTy->isFloatTy() || - (isa<llvm::VectorType>(ValTy) && - cast<llvm::VectorType>(ValTy)->getElementType()->isFloatTy())) - CGF.SetFPAccuracy(Val, 2.5); - } - return Val; - } - else if (Ops.Ty->hasUnsignedIntegerRepresentation()) - return Builder.CreateUDiv(Ops.LHS, Ops.RHS, "div"); - else - return Builder.CreateSDiv(Ops.LHS, Ops.RHS, "div"); -} - -Value *ScalarExprEmitter::EmitRem(const BinOpInfo &Ops) { - // Rem in C can't be a floating point type: C99 6.5.5p2. - if ((CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero) || - CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) && - Ops.Ty->isIntegerType() && - (Ops.mayHaveIntegerDivisionByZero() || Ops.mayHaveIntegerOverflow())) { - CodeGenFunction::SanitizerScope SanScope(&CGF); - llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); - EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, false); - } - - if (Ops.Ty->hasUnsignedIntegerRepresentation()) - return Builder.CreateURem(Ops.LHS, Ops.RHS, "rem"); - else - return Builder.CreateSRem(Ops.LHS, Ops.RHS, "rem"); -} - -Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) { - unsigned IID; - unsigned OpID = 0; - - bool isSigned = Ops.Ty->isSignedIntegerOrEnumerationType(); - switch (Ops.Opcode) { - case BO_Add: - case BO_AddAssign: - OpID = 1; - IID = isSigned ? llvm::Intrinsic::sadd_with_overflow : - llvm::Intrinsic::uadd_with_overflow; - break; - case BO_Sub: - case BO_SubAssign: - OpID = 2; - IID = isSigned ? llvm::Intrinsic::ssub_with_overflow : - llvm::Intrinsic::usub_with_overflow; - break; - case BO_Mul: - case BO_MulAssign: - OpID = 3; - IID = isSigned ? llvm::Intrinsic::smul_with_overflow : - llvm::Intrinsic::umul_with_overflow; - break; - default: - llvm_unreachable("Unsupported operation for overflow detection"); - } - OpID <<= 1; - if (isSigned) - OpID |= 1; - - CodeGenFunction::SanitizerScope SanScope(&CGF); - llvm::Type *opTy = CGF.CGM.getTypes().ConvertType(Ops.Ty); - - llvm::Function *intrinsic = CGF.CGM.getIntrinsic(IID, opTy); - - Value *resultAndOverflow = Builder.CreateCall(intrinsic, {Ops.LHS, Ops.RHS}); - Value *result = Builder.CreateExtractValue(resultAndOverflow, 0); - Value *overflow = Builder.CreateExtractValue(resultAndOverflow, 1); - - // Handle overflow with llvm.trap if no custom handler has been specified. - const std::string *handlerName = - &CGF.getLangOpts().OverflowHandler; - if (handlerName->empty()) { - // If the signed-integer-overflow sanitizer is enabled, emit a call to its - // runtime. Otherwise, this is a -ftrapv check, so just emit a trap. - if (!isSigned || CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) { - llvm::Value *NotOverflow = Builder.CreateNot(overflow); - SanitizerMask Kind = isSigned ? SanitizerKind::SignedIntegerOverflow - : SanitizerKind::UnsignedIntegerOverflow; - EmitBinOpCheck(std::make_pair(NotOverflow, Kind), Ops); - } else - CGF.EmitTrapCheck(Builder.CreateNot(overflow)); - return result; - } - - // Branch in case of overflow. - llvm::BasicBlock *initialBB = Builder.GetInsertBlock(); - llvm::BasicBlock *continueBB = - CGF.createBasicBlock("nooverflow", CGF.CurFn, initialBB->getNextNode()); - llvm::BasicBlock *overflowBB = CGF.createBasicBlock("overflow", CGF.CurFn); - - Builder.CreateCondBr(overflow, overflowBB, continueBB); - - // If an overflow handler is set, then we want to call it and then use its - // result, if it returns. - Builder.SetInsertPoint(overflowBB); - - // Get the overflow handler. - llvm::Type *Int8Ty = CGF.Int8Ty; - llvm::Type *argTypes[] = { CGF.Int64Ty, CGF.Int64Ty, Int8Ty, Int8Ty }; - llvm::FunctionType *handlerTy = - llvm::FunctionType::get(CGF.Int64Ty, argTypes, true); - llvm::Value *handler = CGF.CGM.CreateRuntimeFunction(handlerTy, *handlerName); - - // Sign extend the args to 64-bit, so that we can use the same handler for - // all types of overflow. - llvm::Value *lhs = Builder.CreateSExt(Ops.LHS, CGF.Int64Ty); - llvm::Value *rhs = Builder.CreateSExt(Ops.RHS, CGF.Int64Ty); - - // Call the handler with the two arguments, the operation, and the size of - // the result. - llvm::Value *handlerArgs[] = { - lhs, - rhs, - Builder.getInt8(OpID), - Builder.getInt8(cast<llvm::IntegerType>(opTy)->getBitWidth()) - }; - llvm::Value *handlerResult = - CGF.EmitNounwindRuntimeCall(handler, handlerArgs); - - // Truncate the result back to the desired size. - handlerResult = Builder.CreateTrunc(handlerResult, opTy); - Builder.CreateBr(continueBB); - - Builder.SetInsertPoint(continueBB); - llvm::PHINode *phi = Builder.CreatePHI(opTy, 2); - phi->addIncoming(result, initialBB); - phi->addIncoming(handlerResult, overflowBB); - - return phi; -} - -/// Emit pointer + index arithmetic. -static Value *emitPointerArithmetic(CodeGenFunction &CGF, - const BinOpInfo &op, - bool isSubtraction) { - // Must have binary (not unary) expr here. Unary pointer - // increment/decrement doesn't use this path. - const BinaryOperator *expr = cast<BinaryOperator>(op.E); - - Value *pointer = op.LHS; - Expr *pointerOperand = expr->getLHS(); - Value *index = op.RHS; - Expr *indexOperand = expr->getRHS(); - - // In a subtraction, the LHS is always the pointer. - if (!isSubtraction && !pointer->getType()->isPointerTy()) { - std::swap(pointer, index); - std::swap(pointerOperand, indexOperand); - } - - bool isSigned = indexOperand->getType()->isSignedIntegerOrEnumerationType(); - - unsigned width = cast<llvm::IntegerType>(index->getType())->getBitWidth(); - auto &DL = CGF.CGM.getDataLayout(); - auto PtrTy = cast<llvm::PointerType>(pointer->getType()); - - // Some versions of glibc and gcc use idioms (particularly in their malloc - // routines) that add a pointer-sized integer (known to be a pointer value) - // to a null pointer in order to cast the value back to an integer or as - // part of a pointer alignment algorithm. This is undefined behavior, but - // we'd like to be able to compile programs that use it. - // - // Normally, we'd generate a GEP with a null-pointer base here in response - // to that code, but it's also UB to dereference a pointer created that - // way. Instead (as an acknowledged hack to tolerate the idiom) we will - // generate a direct cast of the integer value to a pointer. - // - // The idiom (p = nullptr + N) is not met if any of the following are true: - // - // The operation is subtraction. - // The index is not pointer-sized. - // The pointer type is not byte-sized. - // - if (BinaryOperator::isNullPointerArithmeticExtension(CGF.getContext(), - op.Opcode, - expr->getLHS(), - expr->getRHS())) - return CGF.Builder.CreateIntToPtr(index, pointer->getType()); - - if (width != DL.getTypeSizeInBits(PtrTy)) { - // Zero-extend or sign-extend the pointer value according to - // whether the index is signed or not. - index = CGF.Builder.CreateIntCast(index, DL.getIntPtrType(PtrTy), isSigned, - "idx.ext"); - } - - // If this is subtraction, negate the index. - if (isSubtraction) - index = CGF.Builder.CreateNeg(index, "idx.neg"); - - if (CGF.SanOpts.has(SanitizerKind::ArrayBounds)) - CGF.EmitBoundsCheck(op.E, pointerOperand, index, indexOperand->getType(), - /*Accessed*/ false); - - const PointerType *pointerType - = pointerOperand->getType()->getAs<PointerType>(); - if (!pointerType) { - QualType objectType = pointerOperand->getType() - ->castAs<ObjCObjectPointerType>() - ->getPointeeType(); - llvm::Value *objectSize - = CGF.CGM.getSize(CGF.getContext().getTypeSizeInChars(objectType)); - - index = CGF.Builder.CreateMul(index, objectSize); - - Value *result = CGF.Builder.CreateBitCast(pointer, CGF.VoidPtrTy); - result = CGF.Builder.CreateGEP(result, index, "add.ptr"); - return CGF.Builder.CreateBitCast(result, pointer->getType()); - } - - QualType elementType = pointerType->getPointeeType(); - if (const VariableArrayType *vla - = CGF.getContext().getAsVariableArrayType(elementType)) { - // The element count here is the total number of non-VLA elements. - llvm::Value *numElements = CGF.getVLASize(vla).NumElts; - - // Effectively, the multiply by the VLA size is part of the GEP. - // GEP indexes are signed, and scaling an index isn't permitted to - // signed-overflow, so we use the same semantics for our explicit - // multiply. We suppress this if overflow is not undefined behavior. - if (CGF.getLangOpts().isSignedOverflowDefined()) { - index = CGF.Builder.CreateMul(index, numElements, "vla.index"); - pointer = CGF.Builder.CreateGEP(pointer, index, "add.ptr"); - } else { - index = CGF.Builder.CreateNSWMul(index, numElements, "vla.index"); - pointer = - CGF.EmitCheckedInBoundsGEP(pointer, index, isSigned, isSubtraction, - op.E->getExprLoc(), "add.ptr"); - } - return pointer; - } - - // Explicitly handle GNU void* and function pointer arithmetic extensions. The - // GNU void* casts amount to no-ops since our void* type is i8*, but this is - // future proof. - if (elementType->isVoidType() || elementType->isFunctionType()) { - Value *result = CGF.Builder.CreateBitCast(pointer, CGF.VoidPtrTy); - result = CGF.Builder.CreateGEP(result, index, "add.ptr"); - return CGF.Builder.CreateBitCast(result, pointer->getType()); - } - - if (CGF.getLangOpts().isSignedOverflowDefined()) - return CGF.Builder.CreateGEP(pointer, index, "add.ptr"); - - return CGF.EmitCheckedInBoundsGEP(pointer, index, isSigned, isSubtraction, - op.E->getExprLoc(), "add.ptr"); -} - -// Construct an fmuladd intrinsic to represent a fused mul-add of MulOp and -// Addend. Use negMul and negAdd to negate the first operand of the Mul or -// the add operand respectively. This allows fmuladd to represent a*b-c, or -// c-a*b. Patterns in LLVM should catch the negated forms and translate them to -// efficient operations. -static Value* buildFMulAdd(llvm::BinaryOperator *MulOp, Value *Addend, - const CodeGenFunction &CGF, CGBuilderTy &Builder, - bool negMul, bool negAdd) { - assert(!(negMul && negAdd) && "Only one of negMul and negAdd should be set."); - - Value *MulOp0 = MulOp->getOperand(0); - Value *MulOp1 = MulOp->getOperand(1); - if (negMul) { - MulOp0 = - Builder.CreateFSub( - llvm::ConstantFP::getZeroValueForNegation(MulOp0->getType()), MulOp0, - "neg"); - } else if (negAdd) { - Addend = - Builder.CreateFSub( - llvm::ConstantFP::getZeroValueForNegation(Addend->getType()), Addend, - "neg"); - } - - Value *FMulAdd = Builder.CreateCall( - CGF.CGM.getIntrinsic(llvm::Intrinsic::fmuladd, Addend->getType()), - {MulOp0, MulOp1, Addend}); - MulOp->eraseFromParent(); - - return FMulAdd; -} - -// Check whether it would be legal to emit an fmuladd intrinsic call to -// represent op and if so, build the fmuladd. -// -// Checks that (a) the operation is fusable, and (b) -ffp-contract=on. -// Does NOT check the type of the operation - it's assumed that this function -// will be called from contexts where it's known that the type is contractable. -static Value* tryEmitFMulAdd(const BinOpInfo &op, - const CodeGenFunction &CGF, CGBuilderTy &Builder, - bool isSub=false) { - - assert((op.Opcode == BO_Add || op.Opcode == BO_AddAssign || - op.Opcode == BO_Sub || op.Opcode == BO_SubAssign) && - "Only fadd/fsub can be the root of an fmuladd."); - - // Check whether this op is marked as fusable. - if (!op.FPFeatures.allowFPContractWithinStatement()) - return nullptr; - - // We have a potentially fusable op. Look for a mul on one of the operands. - // Also, make sure that the mul result isn't used directly. In that case, - // there's no point creating a muladd operation. - if (auto *LHSBinOp = dyn_cast<llvm::BinaryOperator>(op.LHS)) { - if (LHSBinOp->getOpcode() == llvm::Instruction::FMul && - LHSBinOp->use_empty()) - return buildFMulAdd(LHSBinOp, op.RHS, CGF, Builder, false, isSub); - } - if (auto *RHSBinOp = dyn_cast<llvm::BinaryOperator>(op.RHS)) { - if (RHSBinOp->getOpcode() == llvm::Instruction::FMul && - RHSBinOp->use_empty()) - return buildFMulAdd(RHSBinOp, op.LHS, CGF, Builder, isSub, false); - } - - return nullptr; -} - -Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &op) { - if (op.LHS->getType()->isPointerTy() || - op.RHS->getType()->isPointerTy()) - return emitPointerArithmetic(CGF, op, CodeGenFunction::NotSubtraction); - - if (op.Ty->isSignedIntegerOrEnumerationType()) { - switch (CGF.getLangOpts().getSignedOverflowBehavior()) { - case LangOptions::SOB_Defined: - return Builder.CreateAdd(op.LHS, op.RHS, "add"); - case LangOptions::SOB_Undefined: - if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) - return Builder.CreateNSWAdd(op.LHS, op.RHS, "add"); - LLVM_FALLTHROUGH; - case LangOptions::SOB_Trapping: - if (CanElideOverflowCheck(CGF.getContext(), op)) - return Builder.CreateNSWAdd(op.LHS, op.RHS, "add"); - return EmitOverflowCheckedBinOp(op); - } - } - - if (op.Ty->isUnsignedIntegerType() && - CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow) && - !CanElideOverflowCheck(CGF.getContext(), op)) - return EmitOverflowCheckedBinOp(op); - - if (op.LHS->getType()->isFPOrFPVectorTy()) { - // Try to form an fmuladd. - if (Value *FMulAdd = tryEmitFMulAdd(op, CGF, Builder)) - return FMulAdd; - - Value *V = Builder.CreateFAdd(op.LHS, op.RHS, "add"); - return propagateFMFlags(V, op); - } - - return Builder.CreateAdd(op.LHS, op.RHS, "add"); -} - -Value *ScalarExprEmitter::EmitSub(const BinOpInfo &op) { - // The LHS is always a pointer if either side is. - if (!op.LHS->getType()->isPointerTy()) { - if (op.Ty->isSignedIntegerOrEnumerationType()) { - switch (CGF.getLangOpts().getSignedOverflowBehavior()) { - case LangOptions::SOB_Defined: - return Builder.CreateSub(op.LHS, op.RHS, "sub"); - case LangOptions::SOB_Undefined: - if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) - return Builder.CreateNSWSub(op.LHS, op.RHS, "sub"); - LLVM_FALLTHROUGH; - case LangOptions::SOB_Trapping: - if (CanElideOverflowCheck(CGF.getContext(), op)) - return Builder.CreateNSWSub(op.LHS, op.RHS, "sub"); - return EmitOverflowCheckedBinOp(op); - } - } - - if (op.Ty->isUnsignedIntegerType() && - CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow) && - !CanElideOverflowCheck(CGF.getContext(), op)) - return EmitOverflowCheckedBinOp(op); - - if (op.LHS->getType()->isFPOrFPVectorTy()) { - // Try to form an fmuladd. - if (Value *FMulAdd = tryEmitFMulAdd(op, CGF, Builder, true)) - return FMulAdd; - Value *V = Builder.CreateFSub(op.LHS, op.RHS, "sub"); - return propagateFMFlags(V, op); - } - - return Builder.CreateSub(op.LHS, op.RHS, "sub"); - } - - // If the RHS is not a pointer, then we have normal pointer - // arithmetic. - if (!op.RHS->getType()->isPointerTy()) - return emitPointerArithmetic(CGF, op, CodeGenFunction::IsSubtraction); - - // Otherwise, this is a pointer subtraction. - - // Do the raw subtraction part. - llvm::Value *LHS - = Builder.CreatePtrToInt(op.LHS, CGF.PtrDiffTy, "sub.ptr.lhs.cast"); - llvm::Value *RHS - = Builder.CreatePtrToInt(op.RHS, CGF.PtrDiffTy, "sub.ptr.rhs.cast"); - Value *diffInChars = Builder.CreateSub(LHS, RHS, "sub.ptr.sub"); - - // Okay, figure out the element size. - const BinaryOperator *expr = cast<BinaryOperator>(op.E); - QualType elementType = expr->getLHS()->getType()->getPointeeType(); - - llvm::Value *divisor = nullptr; - - // For a variable-length array, this is going to be non-constant. - if (const VariableArrayType *vla - = CGF.getContext().getAsVariableArrayType(elementType)) { - auto VlaSize = CGF.getVLASize(vla); - elementType = VlaSize.Type; - divisor = VlaSize.NumElts; - - // Scale the number of non-VLA elements by the non-VLA element size. - CharUnits eltSize = CGF.getContext().getTypeSizeInChars(elementType); - if (!eltSize.isOne()) - divisor = CGF.Builder.CreateNUWMul(CGF.CGM.getSize(eltSize), divisor); - - // For everything elese, we can just compute it, safe in the - // assumption that Sema won't let anything through that we can't - // safely compute the size of. - } else { - CharUnits elementSize; - // Handle GCC extension for pointer arithmetic on void* and - // function pointer types. - if (elementType->isVoidType() || elementType->isFunctionType()) - elementSize = CharUnits::One(); - else - elementSize = CGF.getContext().getTypeSizeInChars(elementType); - - // Don't even emit the divide for element size of 1. - if (elementSize.isOne()) - return diffInChars; - - divisor = CGF.CGM.getSize(elementSize); - } - - // Otherwise, do a full sdiv. This uses the "exact" form of sdiv, since - // pointer difference in C is only defined in the case where both operands - // are pointing to elements of an array. - return Builder.CreateExactSDiv(diffInChars, divisor, "sub.ptr.div"); -} - -Value *ScalarExprEmitter::GetWidthMinusOneValue(Value* LHS,Value* RHS) { - llvm::IntegerType *Ty; - if (llvm::VectorType *VT = dyn_cast<llvm::VectorType>(LHS->getType())) - Ty = cast<llvm::IntegerType>(VT->getElementType()); - else - Ty = cast<llvm::IntegerType>(LHS->getType()); - return llvm::ConstantInt::get(RHS->getType(), Ty->getBitWidth() - 1); -} - -Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) { - // LLVM requires the LHS and RHS to be the same type: promote or truncate the - // RHS to the same size as the LHS. - Value *RHS = Ops.RHS; - if (Ops.LHS->getType() != RHS->getType()) - RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom"); - - bool SanitizeBase = CGF.SanOpts.has(SanitizerKind::ShiftBase) && - Ops.Ty->hasSignedIntegerRepresentation() && - !CGF.getLangOpts().isSignedOverflowDefined(); - bool SanitizeExponent = CGF.SanOpts.has(SanitizerKind::ShiftExponent); - // OpenCL 6.3j: shift values are effectively % word size of LHS. - if (CGF.getLangOpts().OpenCL) - RHS = - Builder.CreateAnd(RHS, GetWidthMinusOneValue(Ops.LHS, RHS), "shl.mask"); - else if ((SanitizeBase || SanitizeExponent) && - isa<llvm::IntegerType>(Ops.LHS->getType())) { - CodeGenFunction::SanitizerScope SanScope(&CGF); - SmallVector<std::pair<Value *, SanitizerMask>, 2> Checks; - llvm::Value *WidthMinusOne = GetWidthMinusOneValue(Ops.LHS, Ops.RHS); - llvm::Value *ValidExponent = Builder.CreateICmpULE(Ops.RHS, WidthMinusOne); - - if (SanitizeExponent) { - Checks.push_back( - std::make_pair(ValidExponent, SanitizerKind::ShiftExponent)); - } - - if (SanitizeBase) { - // Check whether we are shifting any non-zero bits off the top of the - // integer. We only emit this check if exponent is valid - otherwise - // instructions below will have undefined behavior themselves. - llvm::BasicBlock *Orig = Builder.GetInsertBlock(); - llvm::BasicBlock *Cont = CGF.createBasicBlock("cont"); - llvm::BasicBlock *CheckShiftBase = CGF.createBasicBlock("check"); - Builder.CreateCondBr(ValidExponent, CheckShiftBase, Cont); - llvm::Value *PromotedWidthMinusOne = - (RHS == Ops.RHS) ? WidthMinusOne - : GetWidthMinusOneValue(Ops.LHS, RHS); - CGF.EmitBlock(CheckShiftBase); - llvm::Value *BitsShiftedOff = Builder.CreateLShr( - Ops.LHS, Builder.CreateSub(PromotedWidthMinusOne, RHS, "shl.zeros", - /*NUW*/ true, /*NSW*/ true), - "shl.check"); - if (CGF.getLangOpts().CPlusPlus) { - // In C99, we are not permitted to shift a 1 bit into the sign bit. - // Under C++11's rules, shifting a 1 bit into the sign bit is - // OK, but shifting a 1 bit out of it is not. (C89 and C++03 don't - // define signed left shifts, so we use the C99 and C++11 rules there). - llvm::Value *One = llvm::ConstantInt::get(BitsShiftedOff->getType(), 1); - BitsShiftedOff = Builder.CreateLShr(BitsShiftedOff, One); - } - llvm::Value *Zero = llvm::ConstantInt::get(BitsShiftedOff->getType(), 0); - llvm::Value *ValidBase = Builder.CreateICmpEQ(BitsShiftedOff, Zero); - CGF.EmitBlock(Cont); - llvm::PHINode *BaseCheck = Builder.CreatePHI(ValidBase->getType(), 2); - BaseCheck->addIncoming(Builder.getTrue(), Orig); - BaseCheck->addIncoming(ValidBase, CheckShiftBase); - Checks.push_back(std::make_pair(BaseCheck, SanitizerKind::ShiftBase)); - } - - assert(!Checks.empty()); - EmitBinOpCheck(Checks, Ops); - } - - return Builder.CreateShl(Ops.LHS, RHS, "shl"); -} - -Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) { - // LLVM requires the LHS and RHS to be the same type: promote or truncate the - // RHS to the same size as the LHS. - Value *RHS = Ops.RHS; - if (Ops.LHS->getType() != RHS->getType()) - RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom"); - - // OpenCL 6.3j: shift values are effectively % word size of LHS. - if (CGF.getLangOpts().OpenCL) - RHS = - Builder.CreateAnd(RHS, GetWidthMinusOneValue(Ops.LHS, RHS), "shr.mask"); - else if (CGF.SanOpts.has(SanitizerKind::ShiftExponent) && - isa<llvm::IntegerType>(Ops.LHS->getType())) { - CodeGenFunction::SanitizerScope SanScope(&CGF); - llvm::Value *Valid = - Builder.CreateICmpULE(RHS, GetWidthMinusOneValue(Ops.LHS, RHS)); - EmitBinOpCheck(std::make_pair(Valid, SanitizerKind::ShiftExponent), Ops); - } - - if (Ops.Ty->hasUnsignedIntegerRepresentation()) - return Builder.CreateLShr(Ops.LHS, RHS, "shr"); - return Builder.CreateAShr(Ops.LHS, RHS, "shr"); -} - -enum IntrinsicType { VCMPEQ, VCMPGT }; -// return corresponding comparison intrinsic for given vector type -static llvm::Intrinsic::ID GetIntrinsic(IntrinsicType IT, - BuiltinType::Kind ElemKind) { - switch (ElemKind) { - default: llvm_unreachable("unexpected element type"); - case BuiltinType::Char_U: - case BuiltinType::UChar: - return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequb_p : - llvm::Intrinsic::ppc_altivec_vcmpgtub_p; - case BuiltinType::Char_S: - case BuiltinType::SChar: - return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequb_p : - llvm::Intrinsic::ppc_altivec_vcmpgtsb_p; - case BuiltinType::UShort: - return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequh_p : - llvm::Intrinsic::ppc_altivec_vcmpgtuh_p; - case BuiltinType::Short: - return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequh_p : - llvm::Intrinsic::ppc_altivec_vcmpgtsh_p; - case BuiltinType::UInt: - return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequw_p : - llvm::Intrinsic::ppc_altivec_vcmpgtuw_p; - case BuiltinType::Int: - return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequw_p : - llvm::Intrinsic::ppc_altivec_vcmpgtsw_p; - case BuiltinType::ULong: - case BuiltinType::ULongLong: - return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequd_p : - llvm::Intrinsic::ppc_altivec_vcmpgtud_p; - case BuiltinType::Long: - case BuiltinType::LongLong: - return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequd_p : - llvm::Intrinsic::ppc_altivec_vcmpgtsd_p; - case BuiltinType::Float: - return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpeqfp_p : - llvm::Intrinsic::ppc_altivec_vcmpgtfp_p; - case BuiltinType::Double: - return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_vsx_xvcmpeqdp_p : - llvm::Intrinsic::ppc_vsx_xvcmpgtdp_p; - } -} - -Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E, - llvm::CmpInst::Predicate UICmpOpc, - llvm::CmpInst::Predicate SICmpOpc, - llvm::CmpInst::Predicate FCmpOpc) { - TestAndClearIgnoreResultAssign(); - Value *Result; - QualType LHSTy = E->getLHS()->getType(); - QualType RHSTy = E->getRHS()->getType(); - if (const MemberPointerType *MPT = LHSTy->getAs<MemberPointerType>()) { - assert(E->getOpcode() == BO_EQ || - E->getOpcode() == BO_NE); - Value *LHS = CGF.EmitScalarExpr(E->getLHS()); - Value *RHS = CGF.EmitScalarExpr(E->getRHS()); - Result = CGF.CGM.getCXXABI().EmitMemberPointerComparison( - CGF, LHS, RHS, MPT, E->getOpcode() == BO_NE); - } else if (!LHSTy->isAnyComplexType() && !RHSTy->isAnyComplexType()) { - Value *LHS = Visit(E->getLHS()); - Value *RHS = Visit(E->getRHS()); - - // If AltiVec, the comparison results in a numeric type, so we use - // intrinsics comparing vectors and giving 0 or 1 as a result - if (LHSTy->isVectorType() && !E->getType()->isVectorType()) { - // constants for mapping CR6 register bits to predicate result - enum { CR6_EQ=0, CR6_EQ_REV, CR6_LT, CR6_LT_REV } CR6; - - llvm::Intrinsic::ID ID = llvm::Intrinsic::not_intrinsic; - - // in several cases vector arguments order will be reversed - Value *FirstVecArg = LHS, - *SecondVecArg = RHS; - - QualType ElTy = LHSTy->getAs<VectorType>()->getElementType(); - const BuiltinType *BTy = ElTy->getAs<BuiltinType>(); - BuiltinType::Kind ElementKind = BTy->getKind(); - - switch(E->getOpcode()) { - default: llvm_unreachable("is not a comparison operation"); - case BO_EQ: - CR6 = CR6_LT; - ID = GetIntrinsic(VCMPEQ, ElementKind); - break; - case BO_NE: - CR6 = CR6_EQ; - ID = GetIntrinsic(VCMPEQ, ElementKind); - break; - case BO_LT: - CR6 = CR6_LT; - ID = GetIntrinsic(VCMPGT, ElementKind); - std::swap(FirstVecArg, SecondVecArg); - break; - case BO_GT: - CR6 = CR6_LT; - ID = GetIntrinsic(VCMPGT, ElementKind); - break; - case BO_LE: - if (ElementKind == BuiltinType::Float) { - CR6 = CR6_LT; - ID = llvm::Intrinsic::ppc_altivec_vcmpgefp_p; - std::swap(FirstVecArg, SecondVecArg); - } - else { - CR6 = CR6_EQ; - ID = GetIntrinsic(VCMPGT, ElementKind); - } - break; - case BO_GE: - if (ElementKind == BuiltinType::Float) { - CR6 = CR6_LT; - ID = llvm::Intrinsic::ppc_altivec_vcmpgefp_p; - } - else { - CR6 = CR6_EQ; - ID = GetIntrinsic(VCMPGT, ElementKind); - std::swap(FirstVecArg, SecondVecArg); - } - break; - } - - Value *CR6Param = Builder.getInt32(CR6); - llvm::Function *F = CGF.CGM.getIntrinsic(ID); - Result = Builder.CreateCall(F, {CR6Param, FirstVecArg, SecondVecArg}); - - // The result type of intrinsic may not be same as E->getType(). - // If E->getType() is not BoolTy, EmitScalarConversion will do the - // conversion work. If E->getType() is BoolTy, EmitScalarConversion will - // do nothing, if ResultTy is not i1 at the same time, it will cause - // crash later. - llvm::IntegerType *ResultTy = cast<llvm::IntegerType>(Result->getType()); - if (ResultTy->getBitWidth() > 1 && - E->getType() == CGF.getContext().BoolTy) - Result = Builder.CreateTrunc(Result, Builder.getInt1Ty()); - return EmitScalarConversion(Result, CGF.getContext().BoolTy, E->getType(), - E->getExprLoc()); - } - - if (LHS->getType()->isFPOrFPVectorTy()) { - Result = Builder.CreateFCmp(FCmpOpc, LHS, RHS, "cmp"); - } else if (LHSTy->hasSignedIntegerRepresentation()) { - Result = Builder.CreateICmp(SICmpOpc, LHS, RHS, "cmp"); - } else { - // Unsigned integers and pointers. - - if (CGF.CGM.getCodeGenOpts().StrictVTablePointers && - !isa<llvm::ConstantPointerNull>(LHS) && - !isa<llvm::ConstantPointerNull>(RHS)) { - - // Dynamic information is required to be stripped for comparisons, - // because it could leak the dynamic information. Based on comparisons - // of pointers to dynamic objects, the optimizer can replace one pointer - // with another, which might be incorrect in presence of invariant - // groups. Comparison with null is safe because null does not carry any - // dynamic information. - if (LHSTy.mayBeDynamicClass()) - LHS = Builder.CreateStripInvariantGroup(LHS); - if (RHSTy.mayBeDynamicClass()) - RHS = Builder.CreateStripInvariantGroup(RHS); - } - - Result = Builder.CreateICmp(UICmpOpc, LHS, RHS, "cmp"); - } - - // If this is a vector comparison, sign extend the result to the appropriate - // vector integer type and return it (don't convert to bool). - if (LHSTy->isVectorType()) - return Builder.CreateSExt(Result, ConvertType(E->getType()), "sext"); - - } else { - // Complex Comparison: can only be an equality comparison. - CodeGenFunction::ComplexPairTy LHS, RHS; - QualType CETy; - if (auto *CTy = LHSTy->getAs<ComplexType>()) { - LHS = CGF.EmitComplexExpr(E->getLHS()); - CETy = CTy->getElementType(); - } else { - LHS.first = Visit(E->getLHS()); - LHS.second = llvm::Constant::getNullValue(LHS.first->getType()); - CETy = LHSTy; - } - if (auto *CTy = RHSTy->getAs<ComplexType>()) { - RHS = CGF.EmitComplexExpr(E->getRHS()); - assert(CGF.getContext().hasSameUnqualifiedType(CETy, - CTy->getElementType()) && - "The element types must always match."); - (void)CTy; - } else { - RHS.first = Visit(E->getRHS()); - RHS.second = llvm::Constant::getNullValue(RHS.first->getType()); - assert(CGF.getContext().hasSameUnqualifiedType(CETy, RHSTy) && - "The element types must always match."); - } - - Value *ResultR, *ResultI; - if (CETy->isRealFloatingType()) { - ResultR = Builder.CreateFCmp(FCmpOpc, LHS.first, RHS.first, "cmp.r"); - ResultI = Builder.CreateFCmp(FCmpOpc, LHS.second, RHS.second, "cmp.i"); - } else { - // Complex comparisons can only be equality comparisons. As such, signed - // and unsigned opcodes are the same. - ResultR = Builder.CreateICmp(UICmpOpc, LHS.first, RHS.first, "cmp.r"); - ResultI = Builder.CreateICmp(UICmpOpc, LHS.second, RHS.second, "cmp.i"); - } - - if (E->getOpcode() == BO_EQ) { - Result = Builder.CreateAnd(ResultR, ResultI, "and.ri"); - } else { - assert(E->getOpcode() == BO_NE && - "Complex comparison other than == or != ?"); - Result = Builder.CreateOr(ResultR, ResultI, "or.ri"); - } - } - - return EmitScalarConversion(Result, CGF.getContext().BoolTy, E->getType(), - E->getExprLoc()); -} - -Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) { - bool Ignore = TestAndClearIgnoreResultAssign(); - - Value *RHS; - LValue LHS; - - switch (E->getLHS()->getType().getObjCLifetime()) { - case Qualifiers::OCL_Strong: - std::tie(LHS, RHS) = CGF.EmitARCStoreStrong(E, Ignore); - break; - - case Qualifiers::OCL_Autoreleasing: - std::tie(LHS, RHS) = CGF.EmitARCStoreAutoreleasing(E); - break; - - case Qualifiers::OCL_ExplicitNone: - std::tie(LHS, RHS) = CGF.EmitARCStoreUnsafeUnretained(E, Ignore); - break; - - case Qualifiers::OCL_Weak: - RHS = Visit(E->getRHS()); - LHS = EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store); - RHS = CGF.EmitARCStoreWeak(LHS.getAddress(), RHS, Ignore); - break; - - case Qualifiers::OCL_None: - // __block variables need to have the rhs evaluated first, plus - // this should improve codegen just a little. - RHS = Visit(E->getRHS()); - LHS = EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store); - - // Store the value into the LHS. Bit-fields are handled specially - // because the result is altered by the store, i.e., [C99 6.5.16p1] - // 'An assignment expression has the value of the left operand after - // the assignment...'. - if (LHS.isBitField()) { - CGF.EmitStoreThroughBitfieldLValue(RValue::get(RHS), LHS, &RHS); - } else { - CGF.EmitNullabilityCheck(LHS, RHS, E->getExprLoc()); - CGF.EmitStoreThroughLValue(RValue::get(RHS), LHS); - } - } - - // If the result is clearly ignored, return now. - if (Ignore) - return nullptr; - - // The result of an assignment in C is the assigned r-value. - if (!CGF.getLangOpts().CPlusPlus) - return RHS; - - // If the lvalue is non-volatile, return the computed value of the assignment. - if (!LHS.isVolatileQualified()) - return RHS; - - // Otherwise, reload the value. - return EmitLoadOfLValue(LHS, E->getExprLoc()); -} - -Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) { - // Perform vector logical and on comparisons with zero vectors. - if (E->getType()->isVectorType()) { - CGF.incrementProfileCounter(E); - - Value *LHS = Visit(E->getLHS()); - Value *RHS = Visit(E->getRHS()); - Value *Zero = llvm::ConstantAggregateZero::get(LHS->getType()); - if (LHS->getType()->isFPOrFPVectorTy()) { - LHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, LHS, Zero, "cmp"); - RHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, RHS, Zero, "cmp"); - } else { - LHS = Builder.CreateICmp(llvm::CmpInst::ICMP_NE, LHS, Zero, "cmp"); - RHS = Builder.CreateICmp(llvm::CmpInst::ICMP_NE, RHS, Zero, "cmp"); - } - Value *And = Builder.CreateAnd(LHS, RHS); - return Builder.CreateSExt(And, ConvertType(E->getType()), "sext"); - } - - llvm::Type *ResTy = ConvertType(E->getType()); - - // If we have 0 && RHS, see if we can elide RHS, if so, just return 0. - // If we have 1 && X, just emit X without inserting the control flow. - bool LHSCondVal; - if (CGF.ConstantFoldsToSimpleInteger(E->getLHS(), LHSCondVal)) { - if (LHSCondVal) { // If we have 1 && X, just emit X. - CGF.incrementProfileCounter(E); - - Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS()); - // ZExt result to int or bool. - return Builder.CreateZExtOrBitCast(RHSCond, ResTy, "land.ext"); - } - - // 0 && RHS: If it is safe, just elide the RHS, and return 0/false. - if (!CGF.ContainsLabel(E->getRHS())) - return llvm::Constant::getNullValue(ResTy); - } - - llvm::BasicBlock *ContBlock = CGF.createBasicBlock("land.end"); - llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("land.rhs"); - - CodeGenFunction::ConditionalEvaluation eval(CGF); - - // Branch on the LHS first. If it is false, go to the failure (cont) block. - CGF.EmitBranchOnBoolExpr(E->getLHS(), RHSBlock, ContBlock, - CGF.getProfileCount(E->getRHS())); - - // Any edges into the ContBlock are now from an (indeterminate number of) - // edges from this first condition. All of these values will be false. Start - // setting up the PHI node in the Cont Block for this. - llvm::PHINode *PN = llvm::PHINode::Create(llvm::Type::getInt1Ty(VMContext), 2, - "", ContBlock); - for (llvm::pred_iterator PI = pred_begin(ContBlock), PE = pred_end(ContBlock); - PI != PE; ++PI) - PN->addIncoming(llvm::ConstantInt::getFalse(VMContext), *PI); - - eval.begin(CGF); - CGF.EmitBlock(RHSBlock); - CGF.incrementProfileCounter(E); - Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS()); - eval.end(CGF); - - // Reaquire the RHS block, as there may be subblocks inserted. - RHSBlock = Builder.GetInsertBlock(); - - // Emit an unconditional branch from this block to ContBlock. - { - // There is no need to emit line number for unconditional branch. - auto NL = ApplyDebugLocation::CreateEmpty(CGF); - CGF.EmitBlock(ContBlock); - } - // Insert an entry into the phi node for the edge with the value of RHSCond. - PN->addIncoming(RHSCond, RHSBlock); - - // Artificial location to preserve the scope information - { - auto NL = ApplyDebugLocation::CreateArtificial(CGF); - PN->setDebugLoc(Builder.getCurrentDebugLocation()); - } - - // ZExt result to int. - return Builder.CreateZExtOrBitCast(PN, ResTy, "land.ext"); -} - -Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) { - // Perform vector logical or on comparisons with zero vectors. - if (E->getType()->isVectorType()) { - CGF.incrementProfileCounter(E); - - Value *LHS = Visit(E->getLHS()); - Value *RHS = Visit(E->getRHS()); - Value *Zero = llvm::ConstantAggregateZero::get(LHS->getType()); - if (LHS->getType()->isFPOrFPVectorTy()) { - LHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, LHS, Zero, "cmp"); - RHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, RHS, Zero, "cmp"); - } else { - LHS = Builder.CreateICmp(llvm::CmpInst::ICMP_NE, LHS, Zero, "cmp"); - RHS = Builder.CreateICmp(llvm::CmpInst::ICMP_NE, RHS, Zero, "cmp"); - } - Value *Or = Builder.CreateOr(LHS, RHS); - return Builder.CreateSExt(Or, ConvertType(E->getType()), "sext"); - } - - llvm::Type *ResTy = ConvertType(E->getType()); - - // If we have 1 || RHS, see if we can elide RHS, if so, just return 1. - // If we have 0 || X, just emit X without inserting the control flow. - bool LHSCondVal; - if (CGF.ConstantFoldsToSimpleInteger(E->getLHS(), LHSCondVal)) { - if (!LHSCondVal) { // If we have 0 || X, just emit X. - CGF.incrementProfileCounter(E); - - Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS()); - // ZExt result to int or bool. - return Builder.CreateZExtOrBitCast(RHSCond, ResTy, "lor.ext"); - } - - // 1 || RHS: If it is safe, just elide the RHS, and return 1/true. - if (!CGF.ContainsLabel(E->getRHS())) - return llvm::ConstantInt::get(ResTy, 1); - } - - llvm::BasicBlock *ContBlock = CGF.createBasicBlock("lor.end"); - llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("lor.rhs"); - - CodeGenFunction::ConditionalEvaluation eval(CGF); - - // Branch on the LHS first. If it is true, go to the success (cont) block. - CGF.EmitBranchOnBoolExpr(E->getLHS(), ContBlock, RHSBlock, - CGF.getCurrentProfileCount() - - CGF.getProfileCount(E->getRHS())); - - // Any edges into the ContBlock are now from an (indeterminate number of) - // edges from this first condition. All of these values will be true. Start - // setting up the PHI node in the Cont Block for this. - llvm::PHINode *PN = llvm::PHINode::Create(llvm::Type::getInt1Ty(VMContext), 2, - "", ContBlock); - for (llvm::pred_iterator PI = pred_begin(ContBlock), PE = pred_end(ContBlock); - PI != PE; ++PI) - PN->addIncoming(llvm::ConstantInt::getTrue(VMContext), *PI); - - eval.begin(CGF); - - // Emit the RHS condition as a bool value. - CGF.EmitBlock(RHSBlock); - CGF.incrementProfileCounter(E); - Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS()); - - eval.end(CGF); - - // Reaquire the RHS block, as there may be subblocks inserted. - RHSBlock = Builder.GetInsertBlock(); - - // Emit an unconditional branch from this block to ContBlock. Insert an entry - // into the phi node for the edge with the value of RHSCond. - CGF.EmitBlock(ContBlock); - PN->addIncoming(RHSCond, RHSBlock); - - // ZExt result to int. - return Builder.CreateZExtOrBitCast(PN, ResTy, "lor.ext"); -} - -Value *ScalarExprEmitter::VisitBinComma(const BinaryOperator *E) { - CGF.EmitIgnoredExpr(E->getLHS()); - CGF.EnsureInsertPoint(); - return Visit(E->getRHS()); -} - -//===----------------------------------------------------------------------===// -// Other Operators -//===----------------------------------------------------------------------===// - -/// isCheapEnoughToEvaluateUnconditionally - Return true if the specified -/// expression is cheap enough and side-effect-free enough to evaluate -/// unconditionally instead of conditionally. This is used to convert control -/// flow into selects in some cases. -static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E, - CodeGenFunction &CGF) { - // Anything that is an integer or floating point constant is fine. - return E->IgnoreParens()->isEvaluatable(CGF.getContext()); - - // Even non-volatile automatic variables can't be evaluated unconditionally. - // Referencing a thread_local may cause non-trivial initialization work to - // occur. If we're inside a lambda and one of the variables is from the scope - // outside the lambda, that function may have returned already. Reading its - // locals is a bad idea. Also, these reads may introduce races there didn't - // exist in the source-level program. -} - - -Value *ScalarExprEmitter:: -VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { - TestAndClearIgnoreResultAssign(); - - // Bind the common expression if necessary. - CodeGenFunction::OpaqueValueMapping binding(CGF, E); - - Expr *condExpr = E->getCond(); - Expr *lhsExpr = E->getTrueExpr(); - Expr *rhsExpr = E->getFalseExpr(); - - // If the condition constant folds and can be elided, try to avoid emitting - // the condition and the dead arm. - bool CondExprBool; - if (CGF.ConstantFoldsToSimpleInteger(condExpr, CondExprBool)) { - Expr *live = lhsExpr, *dead = rhsExpr; - if (!CondExprBool) std::swap(live, dead); - - // If the dead side doesn't have labels we need, just emit the Live part. - if (!CGF.ContainsLabel(dead)) { - if (CondExprBool) - CGF.incrementProfileCounter(E); - Value *Result = Visit(live); - - // If the live part is a throw expression, it acts like it has a void - // type, so evaluating it returns a null Value*. However, a conditional - // with non-void type must return a non-null Value*. - if (!Result && !E->getType()->isVoidType()) - Result = llvm::UndefValue::get(CGF.ConvertType(E->getType())); - - return Result; - } - } - - // OpenCL: If the condition is a vector, we can treat this condition like - // the select function. - if (CGF.getLangOpts().OpenCL - && condExpr->getType()->isVectorType()) { - CGF.incrementProfileCounter(E); - - llvm::Value *CondV = CGF.EmitScalarExpr(condExpr); - llvm::Value *LHS = Visit(lhsExpr); - llvm::Value *RHS = Visit(rhsExpr); - - llvm::Type *condType = ConvertType(condExpr->getType()); - llvm::VectorType *vecTy = cast<llvm::VectorType>(condType); - - unsigned numElem = vecTy->getNumElements(); - llvm::Type *elemType = vecTy->getElementType(); - - llvm::Value *zeroVec = llvm::Constant::getNullValue(vecTy); - llvm::Value *TestMSB = Builder.CreateICmpSLT(CondV, zeroVec); - llvm::Value *tmp = Builder.CreateSExt(TestMSB, - llvm::VectorType::get(elemType, - numElem), - "sext"); - llvm::Value *tmp2 = Builder.CreateNot(tmp); - - // Cast float to int to perform ANDs if necessary. - llvm::Value *RHSTmp = RHS; - llvm::Value *LHSTmp = LHS; - bool wasCast = false; - llvm::VectorType *rhsVTy = cast<llvm::VectorType>(RHS->getType()); - if (rhsVTy->getElementType()->isFloatingPointTy()) { - RHSTmp = Builder.CreateBitCast(RHS, tmp2->getType()); - LHSTmp = Builder.CreateBitCast(LHS, tmp->getType()); - wasCast = true; - } - - llvm::Value *tmp3 = Builder.CreateAnd(RHSTmp, tmp2); - llvm::Value *tmp4 = Builder.CreateAnd(LHSTmp, tmp); - llvm::Value *tmp5 = Builder.CreateOr(tmp3, tmp4, "cond"); - if (wasCast) - tmp5 = Builder.CreateBitCast(tmp5, RHS->getType()); - - return tmp5; - } - - // If this is a really simple expression (like x ? 4 : 5), emit this as a - // select instead of as control flow. We can only do this if it is cheap and - // safe to evaluate the LHS and RHS unconditionally. - if (isCheapEnoughToEvaluateUnconditionally(lhsExpr, CGF) && - isCheapEnoughToEvaluateUnconditionally(rhsExpr, CGF)) { - llvm::Value *CondV = CGF.EvaluateExprAsBool(condExpr); - llvm::Value *StepV = Builder.CreateZExtOrBitCast(CondV, CGF.Int64Ty); - - CGF.incrementProfileCounter(E, StepV); - - llvm::Value *LHS = Visit(lhsExpr); - llvm::Value *RHS = Visit(rhsExpr); - if (!LHS) { - // If the conditional has void type, make sure we return a null Value*. - assert(!RHS && "LHS and RHS types must match"); - return nullptr; - } - return Builder.CreateSelect(CondV, LHS, RHS, "cond"); - } - - llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true"); - llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false"); - llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end"); - - CodeGenFunction::ConditionalEvaluation eval(CGF); - CGF.EmitBranchOnBoolExpr(condExpr, LHSBlock, RHSBlock, - CGF.getProfileCount(lhsExpr)); - - CGF.EmitBlock(LHSBlock); - CGF.incrementProfileCounter(E); - eval.begin(CGF); - Value *LHS = Visit(lhsExpr); - eval.end(CGF); - - LHSBlock = Builder.GetInsertBlock(); - Builder.CreateBr(ContBlock); - - CGF.EmitBlock(RHSBlock); - eval.begin(CGF); - Value *RHS = Visit(rhsExpr); - eval.end(CGF); - - RHSBlock = Builder.GetInsertBlock(); - CGF.EmitBlock(ContBlock); - - // If the LHS or RHS is a throw expression, it will be legitimately null. - if (!LHS) - return RHS; - if (!RHS) - return LHS; - - // Create a PHI node for the real part. - llvm::PHINode *PN = Builder.CreatePHI(LHS->getType(), 2, "cond"); - PN->addIncoming(LHS, LHSBlock); - PN->addIncoming(RHS, RHSBlock); - return PN; -} - -Value *ScalarExprEmitter::VisitChooseExpr(ChooseExpr *E) { - return Visit(E->getChosenSubExpr()); -} - -Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) { - QualType Ty = VE->getType(); - - if (Ty->isVariablyModifiedType()) - CGF.EmitVariablyModifiedType(Ty); - - Address ArgValue = Address::invalid(); - Address ArgPtr = CGF.EmitVAArg(VE, ArgValue); - - llvm::Type *ArgTy = ConvertType(VE->getType()); - - // If EmitVAArg fails, emit an error. - if (!ArgPtr.isValid()) { - CGF.ErrorUnsupported(VE, "va_arg expression"); - return llvm::UndefValue::get(ArgTy); - } - - // FIXME Volatility. - llvm::Value *Val = Builder.CreateLoad(ArgPtr); - - // If EmitVAArg promoted the type, we must truncate it. - if (ArgTy != Val->getType()) { - if (ArgTy->isPointerTy() && !Val->getType()->isPointerTy()) - Val = Builder.CreateIntToPtr(Val, ArgTy); - else - Val = Builder.CreateTrunc(Val, ArgTy); - } - - return Val; -} - -Value *ScalarExprEmitter::VisitBlockExpr(const BlockExpr *block) { - return CGF.EmitBlockLiteral(block); -} - -// Convert a vec3 to vec4, or vice versa. -static Value *ConvertVec3AndVec4(CGBuilderTy &Builder, CodeGenFunction &CGF, - Value *Src, unsigned NumElementsDst) { - llvm::Value *UnV = llvm::UndefValue::get(Src->getType()); - SmallVector<llvm::Constant*, 4> Args; - Args.push_back(Builder.getInt32(0)); - Args.push_back(Builder.getInt32(1)); - Args.push_back(Builder.getInt32(2)); - if (NumElementsDst == 4) - Args.push_back(llvm::UndefValue::get(CGF.Int32Ty)); - llvm::Constant *Mask = llvm::ConstantVector::get(Args); - return Builder.CreateShuffleVector(Src, UnV, Mask); -} - -// Create cast instructions for converting LLVM value \p Src to LLVM type \p -// DstTy. \p Src has the same size as \p DstTy. Both are single value types -// but could be scalar or vectors of different lengths, and either can be -// pointer. -// There are 4 cases: -// 1. non-pointer -> non-pointer : needs 1 bitcast -// 2. pointer -> pointer : needs 1 bitcast or addrspacecast -// 3. pointer -> non-pointer -// a) pointer -> intptr_t : needs 1 ptrtoint -// b) pointer -> non-intptr_t : needs 1 ptrtoint then 1 bitcast -// 4. non-pointer -> pointer -// a) intptr_t -> pointer : needs 1 inttoptr -// b) non-intptr_t -> pointer : needs 1 bitcast then 1 inttoptr -// Note: for cases 3b and 4b two casts are required since LLVM casts do not -// allow casting directly between pointer types and non-integer non-pointer -// types. -static Value *createCastsForTypeOfSameSize(CGBuilderTy &Builder, - const llvm::DataLayout &DL, - Value *Src, llvm::Type *DstTy, - StringRef Name = "") { - auto SrcTy = Src->getType(); - - // Case 1. - if (!SrcTy->isPointerTy() && !DstTy->isPointerTy()) - return Builder.CreateBitCast(Src, DstTy, Name); - - // Case 2. - if (SrcTy->isPointerTy() && DstTy->isPointerTy()) - return Builder.CreatePointerBitCastOrAddrSpaceCast(Src, DstTy, Name); - - // Case 3. - if (SrcTy->isPointerTy() && !DstTy->isPointerTy()) { - // Case 3b. - if (!DstTy->isIntegerTy()) - Src = Builder.CreatePtrToInt(Src, DL.getIntPtrType(SrcTy)); - // Cases 3a and 3b. - return Builder.CreateBitOrPointerCast(Src, DstTy, Name); - } - - // Case 4b. - if (!SrcTy->isIntegerTy()) - Src = Builder.CreateBitCast(Src, DL.getIntPtrType(DstTy)); - // Cases 4a and 4b. - return Builder.CreateIntToPtr(Src, DstTy, Name); -} - -Value *ScalarExprEmitter::VisitAsTypeExpr(AsTypeExpr *E) { - Value *Src = CGF.EmitScalarExpr(E->getSrcExpr()); - llvm::Type *DstTy = ConvertType(E->getType()); - - llvm::Type *SrcTy = Src->getType(); - unsigned NumElementsSrc = isa<llvm::VectorType>(SrcTy) ? - cast<llvm::VectorType>(SrcTy)->getNumElements() : 0; - unsigned NumElementsDst = isa<llvm::VectorType>(DstTy) ? - cast<llvm::VectorType>(DstTy)->getNumElements() : 0; - - // Going from vec3 to non-vec3 is a special case and requires a shuffle - // vector to get a vec4, then a bitcast if the target type is different. - if (NumElementsSrc == 3 && NumElementsDst != 3) { - Src = ConvertVec3AndVec4(Builder, CGF, Src, 4); - - if (!CGF.CGM.getCodeGenOpts().PreserveVec3Type) { - Src = createCastsForTypeOfSameSize(Builder, CGF.CGM.getDataLayout(), Src, - DstTy); - } - - Src->setName("astype"); - return Src; - } - - // Going from non-vec3 to vec3 is a special case and requires a bitcast - // to vec4 if the original type is not vec4, then a shuffle vector to - // get a vec3. - if (NumElementsSrc != 3 && NumElementsDst == 3) { - if (!CGF.CGM.getCodeGenOpts().PreserveVec3Type) { - auto Vec4Ty = llvm::VectorType::get(DstTy->getVectorElementType(), 4); - Src = createCastsForTypeOfSameSize(Builder, CGF.CGM.getDataLayout(), Src, - Vec4Ty); - } - - Src = ConvertVec3AndVec4(Builder, CGF, Src, 3); - Src->setName("astype"); - return Src; - } - - return Src = createCastsForTypeOfSameSize(Builder, CGF.CGM.getDataLayout(), - Src, DstTy, "astype"); -} - -Value *ScalarExprEmitter::VisitAtomicExpr(AtomicExpr *E) { - return CGF.EmitAtomicExpr(E).getScalarVal(); -} - -//===----------------------------------------------------------------------===// -// Entry Point into this File -//===----------------------------------------------------------------------===// - -/// Emit the computation of the specified expression of scalar type, ignoring -/// the result. -Value *CodeGenFunction::EmitScalarExpr(const Expr *E, bool IgnoreResultAssign) { - assert(E && hasScalarEvaluationKind(E->getType()) && - "Invalid scalar expression to emit"); - - return ScalarExprEmitter(*this, IgnoreResultAssign) - .Visit(const_cast<Expr *>(E)); -} - -/// Emit a conversion from the specified type to the specified destination type, -/// both of which are LLVM scalar types. -Value *CodeGenFunction::EmitScalarConversion(Value *Src, QualType SrcTy, - QualType DstTy, - SourceLocation Loc) { - assert(hasScalarEvaluationKind(SrcTy) && hasScalarEvaluationKind(DstTy) && - "Invalid scalar expression to emit"); - return ScalarExprEmitter(*this).EmitScalarConversion(Src, SrcTy, DstTy, Loc); -} - -/// Emit a conversion from the specified complex type to the specified -/// destination type, where the destination type is an LLVM scalar type. -Value *CodeGenFunction::EmitComplexToScalarConversion(ComplexPairTy Src, - QualType SrcTy, - QualType DstTy, - SourceLocation Loc) { - assert(SrcTy->isAnyComplexType() && hasScalarEvaluationKind(DstTy) && - "Invalid complex -> scalar conversion"); - return ScalarExprEmitter(*this) - .EmitComplexToScalarConversion(Src, SrcTy, DstTy, Loc); -} - - -llvm::Value *CodeGenFunction:: -EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, - bool isInc, bool isPre) { - return ScalarExprEmitter(*this).EmitScalarPrePostIncDec(E, LV, isInc, isPre); -} - -LValue CodeGenFunction::EmitObjCIsaExpr(const ObjCIsaExpr *E) { - // object->isa or (*object).isa - // Generate code as for: *(Class*)object - - Expr *BaseExpr = E->getBase(); - Address Addr = Address::invalid(); - if (BaseExpr->isRValue()) { - Addr = Address(EmitScalarExpr(BaseExpr), getPointerAlign()); - } else { - Addr = EmitLValue(BaseExpr).getAddress(); - } - - // Cast the address to Class*. - Addr = Builder.CreateElementBitCast(Addr, ConvertType(E->getType())); - return MakeAddrLValue(Addr, E->getType()); -} - - -LValue CodeGenFunction::EmitCompoundAssignmentLValue( - const CompoundAssignOperator *E) { - ScalarExprEmitter Scalar(*this); - Value *Result = nullptr; - switch (E->getOpcode()) { -#define COMPOUND_OP(Op) \ - case BO_##Op##Assign: \ - return Scalar.EmitCompoundAssignLValue(E, &ScalarExprEmitter::Emit##Op, \ - Result) - COMPOUND_OP(Mul); - COMPOUND_OP(Div); - COMPOUND_OP(Rem); - COMPOUND_OP(Add); - COMPOUND_OP(Sub); - COMPOUND_OP(Shl); - COMPOUND_OP(Shr); - COMPOUND_OP(And); - COMPOUND_OP(Xor); - COMPOUND_OP(Or); -#undef COMPOUND_OP - - case BO_PtrMemD: - case BO_PtrMemI: - case BO_Mul: - case BO_Div: - case BO_Rem: - case BO_Add: - case BO_Sub: - case BO_Shl: - case BO_Shr: - case BO_LT: - case BO_GT: - case BO_LE: - case BO_GE: - case BO_EQ: - case BO_NE: - case BO_Cmp: - case BO_And: - case BO_Xor: - case BO_Or: - case BO_LAnd: - case BO_LOr: - case BO_Assign: - case BO_Comma: - llvm_unreachable("Not valid compound assignment operators"); - } - - llvm_unreachable("Unhandled compound assignment operator"); -} - -Value *CodeGenFunction::EmitCheckedInBoundsGEP(Value *Ptr, - ArrayRef<Value *> IdxList, - bool SignedIndices, - bool IsSubtraction, - SourceLocation Loc, - const Twine &Name) { - Value *GEPVal = Builder.CreateInBoundsGEP(Ptr, IdxList, Name); - - // If the pointer overflow sanitizer isn't enabled, do nothing. - if (!SanOpts.has(SanitizerKind::PointerOverflow)) - return GEPVal; - - // If the GEP has already been reduced to a constant, leave it be. - if (isa<llvm::Constant>(GEPVal)) - return GEPVal; - - // Only check for overflows in the default address space. - if (GEPVal->getType()->getPointerAddressSpace()) - return GEPVal; - - auto *GEP = cast<llvm::GEPOperator>(GEPVal); - assert(GEP->isInBounds() && "Expected inbounds GEP"); - - SanitizerScope SanScope(this); - auto &VMContext = getLLVMContext(); - const auto &DL = CGM.getDataLayout(); - auto *IntPtrTy = DL.getIntPtrType(GEP->getPointerOperandType()); - - // Grab references to the signed add/mul overflow intrinsics for intptr_t. - auto *Zero = llvm::ConstantInt::getNullValue(IntPtrTy); - auto *SAddIntrinsic = - CGM.getIntrinsic(llvm::Intrinsic::sadd_with_overflow, IntPtrTy); - auto *SMulIntrinsic = - CGM.getIntrinsic(llvm::Intrinsic::smul_with_overflow, IntPtrTy); - - // The total (signed) byte offset for the GEP. - llvm::Value *TotalOffset = nullptr; - // The offset overflow flag - true if the total offset overflows. - llvm::Value *OffsetOverflows = Builder.getFalse(); - - /// Return the result of the given binary operation. - auto eval = [&](BinaryOperator::Opcode Opcode, llvm::Value *LHS, - llvm::Value *RHS) -> llvm::Value * { - assert((Opcode == BO_Add || Opcode == BO_Mul) && "Can't eval binop"); - - // If the operands are constants, return a constant result. - if (auto *LHSCI = dyn_cast<llvm::ConstantInt>(LHS)) { - if (auto *RHSCI = dyn_cast<llvm::ConstantInt>(RHS)) { - llvm::APInt N; - bool HasOverflow = mayHaveIntegerOverflow(LHSCI, RHSCI, Opcode, - /*Signed=*/true, N); - if (HasOverflow) - OffsetOverflows = Builder.getTrue(); - return llvm::ConstantInt::get(VMContext, N); - } - } - - // Otherwise, compute the result with checked arithmetic. - auto *ResultAndOverflow = Builder.CreateCall( - (Opcode == BO_Add) ? SAddIntrinsic : SMulIntrinsic, {LHS, RHS}); - OffsetOverflows = Builder.CreateOr( - Builder.CreateExtractValue(ResultAndOverflow, 1), OffsetOverflows); - return Builder.CreateExtractValue(ResultAndOverflow, 0); - }; - - // Determine the total byte offset by looking at each GEP operand. - for (auto GTI = llvm::gep_type_begin(GEP), GTE = llvm::gep_type_end(GEP); - GTI != GTE; ++GTI) { - llvm::Value *LocalOffset; - auto *Index = GTI.getOperand(); - // Compute the local offset contributed by this indexing step: - if (auto *STy = GTI.getStructTypeOrNull()) { - // For struct indexing, the local offset is the byte position of the - // specified field. - unsigned FieldNo = cast<llvm::ConstantInt>(Index)->getZExtValue(); - LocalOffset = llvm::ConstantInt::get( - IntPtrTy, DL.getStructLayout(STy)->getElementOffset(FieldNo)); - } else { - // Otherwise this is array-like indexing. The local offset is the index - // multiplied by the element size. - auto *ElementSize = llvm::ConstantInt::get( - IntPtrTy, DL.getTypeAllocSize(GTI.getIndexedType())); - auto *IndexS = Builder.CreateIntCast(Index, IntPtrTy, /*isSigned=*/true); - LocalOffset = eval(BO_Mul, ElementSize, IndexS); - } - - // If this is the first offset, set it as the total offset. Otherwise, add - // the local offset into the running total. - if (!TotalOffset || TotalOffset == Zero) - TotalOffset = LocalOffset; - else - TotalOffset = eval(BO_Add, TotalOffset, LocalOffset); - } - - // Common case: if the total offset is zero, don't emit a check. - if (TotalOffset == Zero) - return GEPVal; - - // Now that we've computed the total offset, add it to the base pointer (with - // wrapping semantics). - auto *IntPtr = Builder.CreatePtrToInt(GEP->getPointerOperand(), IntPtrTy); - auto *ComputedGEP = Builder.CreateAdd(IntPtr, TotalOffset); - - // The GEP is valid if: - // 1) The total offset doesn't overflow, and - // 2) The sign of the difference between the computed address and the base - // pointer matches the sign of the total offset. - llvm::Value *ValidGEP; - auto *NoOffsetOverflow = Builder.CreateNot(OffsetOverflows); - if (SignedIndices) { - auto *PosOrZeroValid = Builder.CreateICmpUGE(ComputedGEP, IntPtr); - auto *PosOrZeroOffset = Builder.CreateICmpSGE(TotalOffset, Zero); - llvm::Value *NegValid = Builder.CreateICmpULT(ComputedGEP, IntPtr); - ValidGEP = Builder.CreateAnd( - Builder.CreateSelect(PosOrZeroOffset, PosOrZeroValid, NegValid), - NoOffsetOverflow); - } else if (!SignedIndices && !IsSubtraction) { - auto *PosOrZeroValid = Builder.CreateICmpUGE(ComputedGEP, IntPtr); - ValidGEP = Builder.CreateAnd(PosOrZeroValid, NoOffsetOverflow); - } else { - auto *NegOrZeroValid = Builder.CreateICmpULE(ComputedGEP, IntPtr); - ValidGEP = Builder.CreateAnd(NegOrZeroValid, NoOffsetOverflow); - } - - llvm::Constant *StaticArgs[] = {EmitCheckSourceLocation(Loc)}; - // Pass the computed GEP to the runtime to avoid emitting poisoned arguments. - llvm::Value *DynamicArgs[] = {IntPtr, ComputedGEP}; - EmitCheck(std::make_pair(ValidGEP, SanitizerKind::PointerOverflow), - SanitizerHandler::PointerOverflow, StaticArgs, DynamicArgs); - - return GEPVal; -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGGPUBuiltin.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGGPUBuiltin.cpp deleted file mode 100644 index b5375ffb8db..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGGPUBuiltin.cpp +++ /dev/null @@ -1,123 +0,0 @@ -//===------ CGGPUBuiltin.cpp - Codegen for GPU builtins -------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Generates code for built-in GPU calls which are not runtime-specific. -// (Runtime-specific codegen lives in programming model specific files.) -// -//===----------------------------------------------------------------------===// - -#include "CodeGenFunction.h" -#include "clang/Basic/Builtins.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/Instruction.h" -#include "llvm/Support/MathExtras.h" - -using namespace clang; -using namespace CodeGen; - -static llvm::Function *GetVprintfDeclaration(llvm::Module &M) { - llvm::Type *ArgTypes[] = {llvm::Type::getInt8PtrTy(M.getContext()), - llvm::Type::getInt8PtrTy(M.getContext())}; - llvm::FunctionType *VprintfFuncType = llvm::FunctionType::get( - llvm::Type::getInt32Ty(M.getContext()), ArgTypes, false); - - if (auto* F = M.getFunction("vprintf")) { - // Our CUDA system header declares vprintf with the right signature, so - // nobody else should have been able to declare vprintf with a bogus - // signature. - assert(F->getFunctionType() == VprintfFuncType); - return F; - } - - // vprintf doesn't already exist; create a declaration and insert it into the - // module. - return llvm::Function::Create( - VprintfFuncType, llvm::GlobalVariable::ExternalLinkage, "vprintf", &M); -} - -// Transforms a call to printf into a call to the NVPTX vprintf syscall (which -// isn't particularly special; it's invoked just like a regular function). -// vprintf takes two args: A format string, and a pointer to a buffer containing -// the varargs. -// -// For example, the call -// -// printf("format string", arg1, arg2, arg3); -// -// is converted into something resembling -// -// struct Tmp { -// Arg1 a1; -// Arg2 a2; -// Arg3 a3; -// }; -// char* buf = alloca(sizeof(Tmp)); -// *(Tmp*)buf = {a1, a2, a3}; -// vprintf("format string", buf); -// -// buf is aligned to the max of {alignof(Arg1), ...}. Furthermore, each of the -// args is itself aligned to its preferred alignment. -// -// Note that by the time this function runs, E's args have already undergone the -// standard C vararg promotion (short -> int, float -> double, etc.). -RValue -CodeGenFunction::EmitNVPTXDevicePrintfCallExpr(const CallExpr *E, - ReturnValueSlot ReturnValue) { - assert(getTarget().getTriple().isNVPTX()); - assert(E->getBuiltinCallee() == Builtin::BIprintf); - assert(E->getNumArgs() >= 1); // printf always has at least one arg. - - const llvm::DataLayout &DL = CGM.getDataLayout(); - llvm::LLVMContext &Ctx = CGM.getLLVMContext(); - - CallArgList Args; - EmitCallArgs(Args, - E->getDirectCallee()->getType()->getAs<FunctionProtoType>(), - E->arguments(), E->getDirectCallee(), - /* ParamsToSkip = */ 0); - - // We don't know how to emit non-scalar varargs. - if (std::any_of(Args.begin() + 1, Args.end(), [&](const CallArg &A) { - return !A.getRValue(*this).isScalar(); - })) { - CGM.ErrorUnsupported(E, "non-scalar arg to printf"); - return RValue::get(llvm::ConstantInt::get(IntTy, 0)); - } - - // Construct and fill the args buffer that we'll pass to vprintf. - llvm::Value *BufferPtr; - if (Args.size() <= 1) { - // If there are no args, pass a null pointer to vprintf. - BufferPtr = llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(Ctx)); - } else { - llvm::SmallVector<llvm::Type *, 8> ArgTypes; - for (unsigned I = 1, NumArgs = Args.size(); I < NumArgs; ++I) - ArgTypes.push_back(Args[I].getRValue(*this).getScalarVal()->getType()); - - // Using llvm::StructType is correct only because printf doesn't accept - // aggregates. If we had to handle aggregates here, we'd have to manually - // compute the offsets within the alloca -- we wouldn't be able to assume - // that the alignment of the llvm type was the same as the alignment of the - // clang type. - llvm::Type *AllocaTy = llvm::StructType::create(ArgTypes, "printf_args"); - llvm::Value *Alloca = CreateTempAlloca(AllocaTy); - - for (unsigned I = 1, NumArgs = Args.size(); I < NumArgs; ++I) { - llvm::Value *P = Builder.CreateStructGEP(AllocaTy, Alloca, I - 1); - llvm::Value *Arg = Args[I].getRValue(*this).getScalarVal(); - Builder.CreateAlignedStore(Arg, P, DL.getPrefTypeAlignment(Arg->getType())); - } - BufferPtr = Builder.CreatePointerCast(Alloca, llvm::Type::getInt8PtrTy(Ctx)); - } - - // Invoke vprintf and return. - llvm::Function* VprintfFunc = GetVprintfDeclaration(CGM.getModule()); - return RValue::get(Builder.CreateCall( - VprintfFunc, {Args[0].getRValue(*this).getScalarVal(), BufferPtr})); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGLoopInfo.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGLoopInfo.cpp deleted file mode 100644 index fd0a9c773a2..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGLoopInfo.cpp +++ /dev/null @@ -1,402 +0,0 @@ -//===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- C++ -*-------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "CGLoopInfo.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Attr.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/CFG.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Metadata.h" -using namespace clang::CodeGen; -using namespace llvm; - -static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs, - const llvm::DebugLoc &StartLoc, - const llvm::DebugLoc &EndLoc, MDNode *&AccGroup) { - - if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 && - Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 && - Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled && - Attrs.PipelineInitiationInterval == 0 && - Attrs.VectorizeEnable == LoopAttributes::Unspecified && - Attrs.UnrollEnable == LoopAttributes::Unspecified && - Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified && - Attrs.DistributeEnable == LoopAttributes::Unspecified && !StartLoc && - !EndLoc) - return nullptr; - - SmallVector<Metadata *, 4> Args; - // Reserve operand 0 for loop id self reference. - auto TempNode = MDNode::getTemporary(Ctx, None); - Args.push_back(TempNode.get()); - - // If we have a valid start debug location for the loop, add it. - if (StartLoc) { - Args.push_back(StartLoc.getAsMDNode()); - - // If we also have a valid end debug location for the loop, add it. - if (EndLoc) - Args.push_back(EndLoc.getAsMDNode()); - } - - // Setting vectorize.width - if (Attrs.VectorizeWidth > 0) { - Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.width"), - ConstantAsMetadata::get(ConstantInt::get( - Type::getInt32Ty(Ctx), Attrs.VectorizeWidth))}; - Args.push_back(MDNode::get(Ctx, Vals)); - } - - // Setting interleave.count - if (Attrs.InterleaveCount > 0) { - Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.interleave.count"), - ConstantAsMetadata::get(ConstantInt::get( - Type::getInt32Ty(Ctx), Attrs.InterleaveCount))}; - Args.push_back(MDNode::get(Ctx, Vals)); - } - - // Setting unroll.count - if (Attrs.UnrollCount > 0) { - Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"), - ConstantAsMetadata::get(ConstantInt::get( - Type::getInt32Ty(Ctx), Attrs.UnrollCount))}; - Args.push_back(MDNode::get(Ctx, Vals)); - } - - // Setting unroll_and_jam.count - if (Attrs.UnrollAndJamCount > 0) { - Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll_and_jam.count"), - ConstantAsMetadata::get(ConstantInt::get( - Type::getInt32Ty(Ctx), Attrs.UnrollAndJamCount))}; - Args.push_back(MDNode::get(Ctx, Vals)); - } - - // Setting vectorize.enable - if (Attrs.VectorizeEnable != LoopAttributes::Unspecified) { - Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.enable"), - ConstantAsMetadata::get(ConstantInt::get( - Type::getInt1Ty(Ctx), (Attrs.VectorizeEnable == - LoopAttributes::Enable)))}; - Args.push_back(MDNode::get(Ctx, Vals)); - } - - // Setting unroll.full or unroll.disable - if (Attrs.UnrollEnable != LoopAttributes::Unspecified) { - std::string Name; - if (Attrs.UnrollEnable == LoopAttributes::Enable) - Name = "llvm.loop.unroll.enable"; - else if (Attrs.UnrollEnable == LoopAttributes::Full) - Name = "llvm.loop.unroll.full"; - else - Name = "llvm.loop.unroll.disable"; - Metadata *Vals[] = {MDString::get(Ctx, Name)}; - Args.push_back(MDNode::get(Ctx, Vals)); - } - - // Setting unroll_and_jam.full or unroll_and_jam.disable - if (Attrs.UnrollAndJamEnable != LoopAttributes::Unspecified) { - std::string Name; - if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable) - Name = "llvm.loop.unroll_and_jam.enable"; - else if (Attrs.UnrollAndJamEnable == LoopAttributes::Full) - Name = "llvm.loop.unroll_and_jam.full"; - else - Name = "llvm.loop.unroll_and_jam.disable"; - Metadata *Vals[] = {MDString::get(Ctx, Name)}; - Args.push_back(MDNode::get(Ctx, Vals)); - } - - if (Attrs.DistributeEnable != LoopAttributes::Unspecified) { - Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"), - ConstantAsMetadata::get(ConstantInt::get( - Type::getInt1Ty(Ctx), (Attrs.DistributeEnable == - LoopAttributes::Enable)))}; - Args.push_back(MDNode::get(Ctx, Vals)); - } - - if (Attrs.IsParallel) { - AccGroup = MDNode::getDistinct(Ctx, {}); - Args.push_back(MDNode::get( - Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup})); - } - - if (Attrs.PipelineDisabled) { - Metadata *Vals[] = { - MDString::get(Ctx, "llvm.loop.pipeline.disable"), - ConstantAsMetadata::get(ConstantInt::get( - Type::getInt1Ty(Ctx), (Attrs.PipelineDisabled == true)))}; - Args.push_back(MDNode::get(Ctx, Vals)); - } - - if (Attrs.PipelineInitiationInterval > 0) { - Metadata *Vals[] = { - MDString::get(Ctx, "llvm.loop.pipeline.initiationinterval"), - ConstantAsMetadata::get(ConstantInt::get( - Type::getInt32Ty(Ctx), Attrs.PipelineInitiationInterval))}; - Args.push_back(MDNode::get(Ctx, Vals)); - } - - // Set the first operand to itself. - MDNode *LoopID = MDNode::get(Ctx, Args); - LoopID->replaceOperandWith(0, LoopID); - return LoopID; -} - -LoopAttributes::LoopAttributes(bool IsParallel) - : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified), - UnrollEnable(LoopAttributes::Unspecified), - UnrollAndJamEnable(LoopAttributes::Unspecified), VectorizeWidth(0), - InterleaveCount(0), UnrollCount(0), UnrollAndJamCount(0), - DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false), - PipelineInitiationInterval(0) {} - -void LoopAttributes::clear() { - IsParallel = false; - VectorizeWidth = 0; - InterleaveCount = 0; - UnrollCount = 0; - UnrollAndJamCount = 0; - VectorizeEnable = LoopAttributes::Unspecified; - UnrollEnable = LoopAttributes::Unspecified; - UnrollAndJamEnable = LoopAttributes::Unspecified; - DistributeEnable = LoopAttributes::Unspecified; - PipelineDisabled = false; - PipelineInitiationInterval = 0; -} - -LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs, - const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc) - : LoopID(nullptr), Header(Header), Attrs(Attrs) { - LoopID = - createMetadata(Header->getContext(), Attrs, StartLoc, EndLoc, AccGroup); -} - -void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc, - const llvm::DebugLoc &EndLoc) { - Active.push_back(LoopInfo(Header, StagedAttrs, StartLoc, EndLoc)); - // Clear the attributes so nested loops do not inherit them. - StagedAttrs.clear(); -} - -void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx, - ArrayRef<const clang::Attr *> Attrs, - const llvm::DebugLoc &StartLoc, - const llvm::DebugLoc &EndLoc) { - - // Identify loop hint attributes from Attrs. - for (const auto *Attr : Attrs) { - const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr); - const OpenCLUnrollHintAttr *OpenCLHint = - dyn_cast<OpenCLUnrollHintAttr>(Attr); - - // Skip non loop hint attributes - if (!LH && !OpenCLHint) { - continue; - } - - LoopHintAttr::OptionType Option = LoopHintAttr::Unroll; - LoopHintAttr::LoopHintState State = LoopHintAttr::Disable; - unsigned ValueInt = 1; - // Translate opencl_unroll_hint attribute argument to - // equivalent LoopHintAttr enums. - // OpenCL v2.0 s6.11.5: - // 0 - full unroll (no argument). - // 1 - disable unroll. - // other positive integer n - unroll by n. - if (OpenCLHint) { - ValueInt = OpenCLHint->getUnrollHint(); - if (ValueInt == 0) { - State = LoopHintAttr::Full; - } else if (ValueInt != 1) { - Option = LoopHintAttr::UnrollCount; - State = LoopHintAttr::Numeric; - } - } else if (LH) { - auto *ValueExpr = LH->getValue(); - if (ValueExpr) { - llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx); - ValueInt = ValueAPS.getSExtValue(); - } - - Option = LH->getOption(); - State = LH->getState(); - } - switch (State) { - case LoopHintAttr::Disable: - switch (Option) { - case LoopHintAttr::Vectorize: - // Disable vectorization by specifying a width of 1. - setVectorizeWidth(1); - break; - case LoopHintAttr::Interleave: - // Disable interleaving by speciyfing a count of 1. - setInterleaveCount(1); - break; - case LoopHintAttr::Unroll: - setUnrollState(LoopAttributes::Disable); - break; - case LoopHintAttr::UnrollAndJam: - setUnrollAndJamState(LoopAttributes::Disable); - break; - case LoopHintAttr::Distribute: - setDistributeState(false); - break; - case LoopHintAttr::PipelineDisabled: - setPipelineDisabled(true); - break; - case LoopHintAttr::UnrollCount: - case LoopHintAttr::UnrollAndJamCount: - case LoopHintAttr::VectorizeWidth: - case LoopHintAttr::InterleaveCount: - case LoopHintAttr::PipelineInitiationInterval: - llvm_unreachable("Options cannot be disabled."); - break; - } - break; - case LoopHintAttr::Enable: - switch (Option) { - case LoopHintAttr::Vectorize: - case LoopHintAttr::Interleave: - setVectorizeEnable(true); - break; - case LoopHintAttr::Unroll: - setUnrollState(LoopAttributes::Enable); - break; - case LoopHintAttr::UnrollAndJam: - setUnrollAndJamState(LoopAttributes::Enable); - break; - case LoopHintAttr::Distribute: - setDistributeState(true); - break; - case LoopHintAttr::UnrollCount: - case LoopHintAttr::UnrollAndJamCount: - case LoopHintAttr::VectorizeWidth: - case LoopHintAttr::InterleaveCount: - case LoopHintAttr::PipelineDisabled: - case LoopHintAttr::PipelineInitiationInterval: - llvm_unreachable("Options cannot enabled."); - break; - } - break; - case LoopHintAttr::AssumeSafety: - switch (Option) { - case LoopHintAttr::Vectorize: - case LoopHintAttr::Interleave: - // Apply "llvm.mem.parallel_loop_access" metadata to load/stores. - setParallel(true); - setVectorizeEnable(true); - break; - case LoopHintAttr::Unroll: - case LoopHintAttr::UnrollAndJam: - case LoopHintAttr::UnrollCount: - case LoopHintAttr::UnrollAndJamCount: - case LoopHintAttr::VectorizeWidth: - case LoopHintAttr::InterleaveCount: - case LoopHintAttr::Distribute: - case LoopHintAttr::PipelineDisabled: - case LoopHintAttr::PipelineInitiationInterval: - llvm_unreachable("Options cannot be used to assume mem safety."); - break; - } - break; - case LoopHintAttr::Full: - switch (Option) { - case LoopHintAttr::Unroll: - setUnrollState(LoopAttributes::Full); - break; - case LoopHintAttr::UnrollAndJam: - setUnrollAndJamState(LoopAttributes::Full); - break; - case LoopHintAttr::Vectorize: - case LoopHintAttr::Interleave: - case LoopHintAttr::UnrollCount: - case LoopHintAttr::UnrollAndJamCount: - case LoopHintAttr::VectorizeWidth: - case LoopHintAttr::InterleaveCount: - case LoopHintAttr::Distribute: - case LoopHintAttr::PipelineDisabled: - case LoopHintAttr::PipelineInitiationInterval: - llvm_unreachable("Options cannot be used with 'full' hint."); - break; - } - break; - case LoopHintAttr::Numeric: - switch (Option) { - case LoopHintAttr::VectorizeWidth: - setVectorizeWidth(ValueInt); - break; - case LoopHintAttr::InterleaveCount: - setInterleaveCount(ValueInt); - break; - case LoopHintAttr::UnrollCount: - setUnrollCount(ValueInt); - break; - case LoopHintAttr::UnrollAndJamCount: - setUnrollAndJamCount(ValueInt); - break; - case LoopHintAttr::PipelineInitiationInterval: - setPipelineInitiationInterval(ValueInt); - break; - case LoopHintAttr::Unroll: - case LoopHintAttr::UnrollAndJam: - case LoopHintAttr::Vectorize: - case LoopHintAttr::Interleave: - case LoopHintAttr::Distribute: - case LoopHintAttr::PipelineDisabled: - llvm_unreachable("Options cannot be assigned a value."); - break; - } - break; - } - } - - /// Stage the attributes. - push(Header, StartLoc, EndLoc); -} - -void LoopInfoStack::pop() { - assert(!Active.empty() && "No active loops to pop"); - Active.pop_back(); -} - -void LoopInfoStack::InsertHelper(Instruction *I) const { - if (I->mayReadOrWriteMemory()) { - SmallVector<Metadata *, 4> AccessGroups; - for (const LoopInfo &AL : Active) { - // Here we assume that every loop that has an access group is parallel. - if (MDNode *Group = AL.getAccessGroup()) - AccessGroups.push_back(Group); - } - MDNode *UnionMD = nullptr; - if (AccessGroups.size() == 1) - UnionMD = cast<MDNode>(AccessGroups[0]); - else if (AccessGroups.size() >= 2) - UnionMD = MDNode::get(I->getContext(), AccessGroups); - I->setMetadata("llvm.access.group", UnionMD); - } - - if (!hasInfo()) - return; - - const LoopInfo &L = getInfo(); - if (!L.getLoopID()) - return; - - if (I->isTerminator()) { - for (BasicBlock *Succ : successors(I)) - if (Succ == L.getHeader()) { - I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID()); - break; - } - return; - } -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGLoopInfo.h b/gnu/llvm/tools/clang/lib/CodeGen/CGLoopInfo.h deleted file mode 100644 index 84ba03bfb00..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGLoopInfo.h +++ /dev/null @@ -1,203 +0,0 @@ -//===---- CGLoopInfo.h - LLVM CodeGen for loop metadata -*- C++ -*---------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This is the internal state used for llvm translation for loop statement -// metadata. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CGLOOPINFO_H -#define LLVM_CLANG_LIB_CODEGEN_CGLOOPINFO_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Compiler.h" - -namespace llvm { -class BasicBlock; -class Instruction; -class MDNode; -} // end namespace llvm - -namespace clang { -class Attr; -class ASTContext; -namespace CodeGen { - -/// Attributes that may be specified on loops. -struct LoopAttributes { - explicit LoopAttributes(bool IsParallel = false); - void clear(); - - /// Generate llvm.loop.parallel metadata for loads and stores. - bool IsParallel; - - /// State of loop vectorization or unrolling. - enum LVEnableState { Unspecified, Enable, Disable, Full }; - - /// Value for llvm.loop.vectorize.enable metadata. - LVEnableState VectorizeEnable; - - /// Value for llvm.loop.unroll.* metadata (enable, disable, or full). - LVEnableState UnrollEnable; - - /// Value for llvm.loop.unroll_and_jam.* metadata (enable, disable, or full). - LVEnableState UnrollAndJamEnable; - - /// Value for llvm.loop.vectorize.width metadata. - unsigned VectorizeWidth; - - /// Value for llvm.loop.interleave.count metadata. - unsigned InterleaveCount; - - /// llvm.unroll. - unsigned UnrollCount; - - /// llvm.unroll. - unsigned UnrollAndJamCount; - - /// Value for llvm.loop.distribute.enable metadata. - LVEnableState DistributeEnable; - - /// Value for llvm.loop.pipeline.disable metadata. - bool PipelineDisabled; - - /// Value for llvm.loop.pipeline.iicount metadata. - unsigned PipelineInitiationInterval; -}; - -/// Information used when generating a structured loop. -class LoopInfo { -public: - /// Construct a new LoopInfo for the loop with entry Header. - LoopInfo(llvm::BasicBlock *Header, const LoopAttributes &Attrs, - const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc); - - /// Get the loop id metadata for this loop. - llvm::MDNode *getLoopID() const { return LoopID; } - - /// Get the header block of this loop. - llvm::BasicBlock *getHeader() const { return Header; } - - /// Get the set of attributes active for this loop. - const LoopAttributes &getAttributes() const { return Attrs; } - - /// Return this loop's access group or nullptr if it does not have one. - llvm::MDNode *getAccessGroup() const { return AccGroup; } - -private: - /// Loop ID metadata. - llvm::MDNode *LoopID; - /// Header block of this loop. - llvm::BasicBlock *Header; - /// The attributes for this loop. - LoopAttributes Attrs; - /// The access group for memory accesses parallel to this loop. - llvm::MDNode *AccGroup = nullptr; -}; - -/// A stack of loop information corresponding to loop nesting levels. -/// This stack can be used to prepare attributes which are applied when a loop -/// is emitted. -class LoopInfoStack { - LoopInfoStack(const LoopInfoStack &) = delete; - void operator=(const LoopInfoStack &) = delete; - -public: - LoopInfoStack() {} - - /// Begin a new structured loop. The set of staged attributes will be - /// applied to the loop and then cleared. - void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc, - const llvm::DebugLoc &EndLoc); - - /// Begin a new structured loop. Stage attributes from the Attrs list. - /// The staged attributes are applied to the loop and then cleared. - void push(llvm::BasicBlock *Header, clang::ASTContext &Ctx, - llvm::ArrayRef<const Attr *> Attrs, const llvm::DebugLoc &StartLoc, - const llvm::DebugLoc &EndLoc); - - /// End the current loop. - void pop(); - - /// Return the top loop id metadata. - llvm::MDNode *getCurLoopID() const { return getInfo().getLoopID(); } - - /// Return true if the top loop is parallel. - bool getCurLoopParallel() const { - return hasInfo() ? getInfo().getAttributes().IsParallel : false; - } - - /// Function called by the CodeGenFunction when an instruction is - /// created. - void InsertHelper(llvm::Instruction *I) const; - - /// Set the next pushed loop as parallel. - void setParallel(bool Enable = true) { StagedAttrs.IsParallel = Enable; } - - /// Set the next pushed loop 'vectorize.enable' - void setVectorizeEnable(bool Enable = true) { - StagedAttrs.VectorizeEnable = - Enable ? LoopAttributes::Enable : LoopAttributes::Disable; - } - - /// Set the next pushed loop as a distribution candidate. - void setDistributeState(bool Enable = true) { - StagedAttrs.DistributeEnable = - Enable ? LoopAttributes::Enable : LoopAttributes::Disable; - } - - /// Set the next pushed loop unroll state. - void setUnrollState(const LoopAttributes::LVEnableState &State) { - StagedAttrs.UnrollEnable = State; - } - - /// Set the next pushed loop unroll_and_jam state. - void setUnrollAndJamState(const LoopAttributes::LVEnableState &State) { - StagedAttrs.UnrollAndJamEnable = State; - } - - /// Set the vectorize width for the next loop pushed. - void setVectorizeWidth(unsigned W) { StagedAttrs.VectorizeWidth = W; } - - /// Set the interleave count for the next loop pushed. - void setInterleaveCount(unsigned C) { StagedAttrs.InterleaveCount = C; } - - /// Set the unroll count for the next loop pushed. - void setUnrollCount(unsigned C) { StagedAttrs.UnrollCount = C; } - - /// \brief Set the unroll count for the next loop pushed. - void setUnrollAndJamCount(unsigned C) { StagedAttrs.UnrollAndJamCount = C; } - - /// Set the pipeline disabled state. - void setPipelineDisabled(bool S) { StagedAttrs.PipelineDisabled = S; } - - /// Set the pipeline initiation interval. - void setPipelineInitiationInterval(unsigned C) { - StagedAttrs.PipelineInitiationInterval = C; - } - -private: - /// Returns true if there is LoopInfo on the stack. - bool hasInfo() const { return !Active.empty(); } - /// Return the LoopInfo for the current loop. HasInfo should be called - /// first to ensure LoopInfo is present. - const LoopInfo &getInfo() const { return Active.back(); } - /// The set of attributes that will be applied to the next pushed loop. - LoopAttributes StagedAttrs; - /// Stack of active loops. - llvm::SmallVector<LoopInfo, 4> Active; -}; - -} // end namespace CodeGen -} // end namespace clang - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGNonTrivialStruct.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGNonTrivialStruct.cpp deleted file mode 100644 index c6a96a91262..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGNonTrivialStruct.cpp +++ /dev/null @@ -1,906 +0,0 @@ -//===--- CGNonTrivialStruct.cpp - Emit Special Functions for C Structs ----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines functions to generate various special functions for C -// structs. -// -//===----------------------------------------------------------------------===// - -#include "CodeGenFunction.h" -#include "CodeGenModule.h" -#include "clang/AST/NonTrivialTypeVisitor.h" -#include "llvm/Support/ScopedPrinter.h" -#include <array> - -using namespace clang; -using namespace CodeGen; - -// Return the size of a field in number of bits. -static uint64_t getFieldSize(const FieldDecl *FD, QualType FT, - ASTContext &Ctx) { - if (FD && FD->isBitField()) - return FD->getBitWidthValue(Ctx); - return Ctx.getTypeSize(FT); -} - -namespace { -enum { DstIdx = 0, SrcIdx = 1 }; -const char *ValNameStr[2] = {"dst", "src"}; - -template <class Derived> struct StructVisitor { - StructVisitor(ASTContext &Ctx) : Ctx(Ctx) {} - - template <class... Ts> - void visitStructFields(QualType QT, CharUnits CurStructOffset, Ts... Args) { - const RecordDecl *RD = QT->castAs<RecordType>()->getDecl(); - - // Iterate over the fields of the struct. - for (const FieldDecl *FD : RD->fields()) { - QualType FT = FD->getType(); - FT = QT.isVolatileQualified() ? FT.withVolatile() : FT; - asDerived().visit(FT, FD, CurStructOffset, Args...); - } - - asDerived().flushTrivialFields(Args...); - } - - template <class... Ts> void visitTrivial(Ts... Args) {} - - template <class... Ts> void visitCXXDestructor(Ts... Args) { - llvm_unreachable("field of a C++ struct type is not expected"); - } - - template <class... Ts> void flushTrivialFields(Ts... Args) {} - - uint64_t getFieldOffsetInBits(const FieldDecl *FD) { - return FD ? Ctx.getASTRecordLayout(FD->getParent()) - .getFieldOffset(FD->getFieldIndex()) - : 0; - } - - CharUnits getFieldOffset(const FieldDecl *FD) { - return Ctx.toCharUnitsFromBits(getFieldOffsetInBits(FD)); - } - - Derived &asDerived() { return static_cast<Derived &>(*this); } - - ASTContext &getContext() { return Ctx; } - ASTContext &Ctx; -}; - -template <class Derived, bool IsMove> -struct CopyStructVisitor : StructVisitor<Derived>, - CopiedTypeVisitor<Derived, IsMove> { - using StructVisitor<Derived>::asDerived; - using Super = CopiedTypeVisitor<Derived, IsMove>; - - CopyStructVisitor(ASTContext &Ctx) : StructVisitor<Derived>(Ctx) {} - - template <class... Ts> - void preVisit(QualType::PrimitiveCopyKind PCK, QualType FT, - const FieldDecl *FD, CharUnits CurStructOffsset, - Ts &&... Args) { - if (PCK) - asDerived().flushTrivialFields(std::forward<Ts>(Args)...); - } - - template <class... Ts> - void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT, - const FieldDecl *FD, CharUnits CurStructOffsset, - Ts &&... Args) { - if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) { - asDerived().visitArray(PCK, AT, FT.isVolatileQualified(), FD, - CurStructOffsset, std::forward<Ts>(Args)...); - return; - } - - Super::visitWithKind(PCK, FT, FD, CurStructOffsset, - std::forward<Ts>(Args)...); - } - - template <class... Ts> - void visitTrivial(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset, - Ts... Args) { - assert(!FT.isVolatileQualified() && "volatile field not expected"); - ASTContext &Ctx = asDerived().getContext(); - uint64_t FieldSize = getFieldSize(FD, FT, Ctx); - - // Ignore zero-sized fields. - if (FieldSize == 0) - return; - - uint64_t FStartInBits = asDerived().getFieldOffsetInBits(FD); - uint64_t FEndInBits = FStartInBits + FieldSize; - uint64_t RoundedFEnd = llvm::alignTo(FEndInBits, Ctx.getCharWidth()); - - // Set Start if this is the first field of a sequence of trivial fields. - if (Start == End) - Start = CurStructOffset + Ctx.toCharUnitsFromBits(FStartInBits); - End = CurStructOffset + Ctx.toCharUnitsFromBits(RoundedFEnd); - } - - CharUnits Start = CharUnits::Zero(), End = CharUnits::Zero(); -}; - -// This function creates the mangled name of a special function of a non-trivial -// C struct. Since there is no ODR in C, the function is mangled based on the -// struct contents and not the name. The mangled name has the following -// structure: -// -// <function-name> ::= <prefix> <alignment-info> "_" <struct-field-info> -// <prefix> ::= "__destructor_" | "__default_constructor_" | -// "__copy_constructor_" | "__move_constructor_" | -// "__copy_assignment_" | "__move_assignment_" -// <alignment-info> ::= <dst-alignment> ["_" <src-alignment>] -// <struct-field-info> ::= <field-info>+ -// <field-info> ::= <struct-or-scalar-field-info> | <array-field-info> -// <struct-or-scalar-field-info> ::= <struct-field-info> | <strong-field-info> | -// <trivial-field-info> -// <array-field-info> ::= "_AB" <array-offset> "s" <element-size> "n" -// <num-elements> <innermost-element-info> "_AE" -// <innermost-element-info> ::= <struct-or-scalar-field-info> -// <strong-field-info> ::= "_s" ["b"] ["v"] <field-offset> -// <trivial-field-info> ::= "_t" ["v"] <field-offset> "_" <field-size> - -template <class Derived> struct GenFuncNameBase { - std::string getVolatileOffsetStr(bool IsVolatile, CharUnits Offset) { - std::string S; - if (IsVolatile) - S = "v"; - S += llvm::to_string(Offset.getQuantity()); - return S; - } - - void visitARCStrong(QualType FT, const FieldDecl *FD, - CharUnits CurStructOffset) { - appendStr("_s"); - if (FT->isBlockPointerType()) - appendStr("b"); - CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD); - appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset)); - } - - void visitARCWeak(QualType FT, const FieldDecl *FD, - CharUnits CurStructOffset) { - appendStr("_w"); - CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD); - appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset)); - } - - void visitStruct(QualType QT, const FieldDecl *FD, - CharUnits CurStructOffset) { - CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD); - asDerived().visitStructFields(QT, FieldOffset); - } - - template <class FieldKind> - void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile, - const FieldDecl *FD, CharUnits CurStructOffset) { - // String for non-volatile trivial fields is emitted when - // flushTrivialFields is called. - if (!FK) - return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset); - - asDerived().flushTrivialFields(); - CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD); - ASTContext &Ctx = asDerived().getContext(); - const ConstantArrayType *CAT = cast<ConstantArrayType>(AT); - unsigned NumElts = Ctx.getConstantArrayElementCount(CAT); - QualType EltTy = Ctx.getBaseElementType(CAT); - CharUnits EltSize = Ctx.getTypeSizeInChars(EltTy); - appendStr("_AB" + llvm::to_string(FieldOffset.getQuantity()) + "s" + - llvm::to_string(EltSize.getQuantity()) + "n" + - llvm::to_string(NumElts)); - EltTy = IsVolatile ? EltTy.withVolatile() : EltTy; - asDerived().visitWithKind(FK, EltTy, nullptr, FieldOffset); - appendStr("_AE"); - } - - void appendStr(StringRef Str) { Name += Str; } - - std::string getName(QualType QT, bool IsVolatile) { - QT = IsVolatile ? QT.withVolatile() : QT; - asDerived().visitStructFields(QT, CharUnits::Zero()); - return Name; - } - - Derived &asDerived() { return static_cast<Derived &>(*this); } - - std::string Name; -}; - -template <class Derived> -struct GenUnaryFuncName : StructVisitor<Derived>, GenFuncNameBase<Derived> { - GenUnaryFuncName(StringRef Prefix, CharUnits DstAlignment, ASTContext &Ctx) - : StructVisitor<Derived>(Ctx) { - this->appendStr(Prefix); - this->appendStr(llvm::to_string(DstAlignment.getQuantity())); - } -}; - -// Helper function to create a null constant. -static llvm::Constant *getNullForVariable(Address Addr) { - llvm::Type *Ty = Addr.getElementType(); - return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(Ty)); -} - -template <bool IsMove> -struct GenBinaryFuncName : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>, - GenFuncNameBase<GenBinaryFuncName<IsMove>> { - - GenBinaryFuncName(StringRef Prefix, CharUnits DstAlignment, - CharUnits SrcAlignment, ASTContext &Ctx) - : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>(Ctx) { - this->appendStr(Prefix); - this->appendStr(llvm::to_string(DstAlignment.getQuantity())); - this->appendStr("_" + llvm::to_string(SrcAlignment.getQuantity())); - } - - void flushTrivialFields() { - if (this->Start == this->End) - return; - - this->appendStr("_t" + llvm::to_string(this->Start.getQuantity()) + "w" + - llvm::to_string((this->End - this->Start).getQuantity())); - - this->Start = this->End = CharUnits::Zero(); - } - - void visitVolatileTrivial(QualType FT, const FieldDecl *FD, - CharUnits CurStackOffset) { - // Because volatile fields can be bit-fields and are individually copied, - // their offset and width are in bits. - uint64_t OffsetInBits = - this->Ctx.toBits(CurStackOffset) + this->getFieldOffsetInBits(FD); - this->appendStr("_tv" + llvm::to_string(OffsetInBits) + "w" + - llvm::to_string(getFieldSize(FD, FT, this->Ctx))); - } -}; - -struct GenDefaultInitializeFuncName - : GenUnaryFuncName<GenDefaultInitializeFuncName>, - DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName> { - using Super = DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName>; - GenDefaultInitializeFuncName(CharUnits DstAlignment, ASTContext &Ctx) - : GenUnaryFuncName<GenDefaultInitializeFuncName>("__default_constructor_", - DstAlignment, Ctx) {} - void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT, - const FieldDecl *FD, CharUnits CurStructOffset) { - if (const auto *AT = getContext().getAsArrayType(FT)) { - visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset); - return; - } - - Super::visitWithKind(PDIK, FT, FD, CurStructOffset); - } -}; - -struct GenDestructorFuncName : GenUnaryFuncName<GenDestructorFuncName>, - DestructedTypeVisitor<GenDestructorFuncName> { - using Super = DestructedTypeVisitor<GenDestructorFuncName>; - GenDestructorFuncName(const char *Prefix, CharUnits DstAlignment, - ASTContext &Ctx) - : GenUnaryFuncName<GenDestructorFuncName>(Prefix, DstAlignment, - Ctx) {} - void visitWithKind(QualType::DestructionKind DK, QualType FT, - const FieldDecl *FD, CharUnits CurStructOffset) { - if (const auto *AT = getContext().getAsArrayType(FT)) { - visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset); - return; - } - - Super::visitWithKind(DK, FT, FD, CurStructOffset); - } -}; - -// Helper function that creates CGFunctionInfo for an N-ary special function. -template <size_t N> -static const CGFunctionInfo &getFunctionInfo(CodeGenModule &CGM, - FunctionArgList &Args) { - ASTContext &Ctx = CGM.getContext(); - llvm::SmallVector<ImplicitParamDecl *, N> Params; - QualType ParamTy = Ctx.getPointerType(Ctx.VoidPtrTy); - - for (unsigned I = 0; I < N; ++I) - Params.push_back(ImplicitParamDecl::Create( - Ctx, nullptr, SourceLocation(), &Ctx.Idents.get(ValNameStr[I]), ParamTy, - ImplicitParamDecl::Other)); - - for (auto &P : Params) - Args.push_back(P); - - return CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args); -} - -// Template classes that are used as bases for classes that emit special -// functions. -template <class Derived> struct GenFuncBase { - template <size_t N> - void visitStruct(QualType FT, const FieldDecl *FD, CharUnits CurStackOffset, - std::array<Address, N> Addrs) { - this->asDerived().callSpecialFunction( - FT, CurStackOffset + asDerived().getFieldOffset(FD), Addrs); - } - - template <class FieldKind, size_t N> - void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile, - const FieldDecl *FD, CharUnits CurStackOffset, - std::array<Address, N> Addrs) { - // Non-volatile trivial fields are copied when flushTrivialFields is called. - if (!FK) - return asDerived().visitTrivial(QualType(AT, 0), FD, CurStackOffset, - Addrs); - - asDerived().flushTrivialFields(Addrs); - CodeGenFunction &CGF = *this->CGF; - ASTContext &Ctx = CGF.getContext(); - - // Compute the end address. - QualType BaseEltQT; - std::array<Address, N> StartAddrs = Addrs; - for (unsigned I = 0; I < N; ++I) - StartAddrs[I] = getAddrWithOffset(Addrs[I], CurStackOffset, FD); - Address DstAddr = StartAddrs[DstIdx]; - llvm::Value *NumElts = CGF.emitArrayLength(AT, BaseEltQT, DstAddr); - unsigned BaseEltSize = Ctx.getTypeSizeInChars(BaseEltQT).getQuantity(); - llvm::Value *BaseEltSizeVal = - llvm::ConstantInt::get(NumElts->getType(), BaseEltSize); - llvm::Value *SizeInBytes = - CGF.Builder.CreateNUWMul(BaseEltSizeVal, NumElts); - Address BC = CGF.Builder.CreateBitCast(DstAddr, CGF.CGM.Int8PtrTy); - llvm::Value *DstArrayEnd = - CGF.Builder.CreateInBoundsGEP(BC.getPointer(), SizeInBytes); - DstArrayEnd = CGF.Builder.CreateBitCast(DstArrayEnd, CGF.CGM.Int8PtrPtrTy, - "dstarray.end"); - llvm::BasicBlock *PreheaderBB = CGF.Builder.GetInsertBlock(); - - // Create the header block and insert the phi instructions. - llvm::BasicBlock *HeaderBB = CGF.createBasicBlock("loop.header"); - CGF.EmitBlock(HeaderBB); - llvm::PHINode *PHIs[N]; - - for (unsigned I = 0; I < N; ++I) { - PHIs[I] = CGF.Builder.CreatePHI(CGF.CGM.Int8PtrPtrTy, 2, "addr.cur"); - PHIs[I]->addIncoming(StartAddrs[I].getPointer(), PreheaderBB); - } - - // Create the exit and loop body blocks. - llvm::BasicBlock *ExitBB = CGF.createBasicBlock("loop.exit"); - llvm::BasicBlock *LoopBB = CGF.createBasicBlock("loop.body"); - - // Emit the comparison and conditional branch instruction that jumps to - // either the exit or the loop body. - llvm::Value *Done = - CGF.Builder.CreateICmpEQ(PHIs[DstIdx], DstArrayEnd, "done"); - CGF.Builder.CreateCondBr(Done, ExitBB, LoopBB); - - // Visit the element of the array in the loop body. - CGF.EmitBlock(LoopBB); - QualType EltQT = AT->getElementType(); - CharUnits EltSize = Ctx.getTypeSizeInChars(EltQT); - std::array<Address, N> NewAddrs = Addrs; - - for (unsigned I = 0; I < N; ++I) - NewAddrs[I] = Address( - PHIs[I], StartAddrs[I].getAlignment().alignmentAtOffset(EltSize)); - - EltQT = IsVolatile ? EltQT.withVolatile() : EltQT; - this->asDerived().visitWithKind(FK, EltQT, nullptr, CharUnits::Zero(), - NewAddrs); - - LoopBB = CGF.Builder.GetInsertBlock(); - - for (unsigned I = 0; I < N; ++I) { - // Instrs to update the destination and source addresses. - // Update phi instructions. - NewAddrs[I] = getAddrWithOffset(NewAddrs[I], EltSize); - PHIs[I]->addIncoming(NewAddrs[I].getPointer(), LoopBB); - } - - // Insert an unconditional branch to the header block. - CGF.Builder.CreateBr(HeaderBB); - CGF.EmitBlock(ExitBB); - } - - /// Return an address with the specified offset from the passed address. - Address getAddrWithOffset(Address Addr, CharUnits Offset) { - assert(Addr.isValid() && "invalid address"); - if (Offset.getQuantity() == 0) - return Addr; - Addr = CGF->Builder.CreateBitCast(Addr, CGF->CGM.Int8PtrTy); - Addr = CGF->Builder.CreateConstInBoundsGEP(Addr, Offset.getQuantity(), - CharUnits::One()); - return CGF->Builder.CreateBitCast(Addr, CGF->CGM.Int8PtrPtrTy); - } - - Address getAddrWithOffset(Address Addr, CharUnits StructFieldOffset, - const FieldDecl *FD) { - return getAddrWithOffset(Addr, StructFieldOffset + - asDerived().getFieldOffset(FD)); - } - - template <size_t N> - llvm::Function * - getFunction(StringRef FuncName, QualType QT, std::array<Address, N> Addrs, - std::array<CharUnits, N> Alignments, CodeGenModule &CGM) { - // If the special function already exists in the module, return it. - if (llvm::Function *F = CGM.getModule().getFunction(FuncName)) { - bool WrongType = false; - if (!F->getReturnType()->isVoidTy()) - WrongType = true; - else { - for (const llvm::Argument &Arg : F->args()) - if (Arg.getType() != CGM.Int8PtrPtrTy) - WrongType = true; - } - - if (WrongType) { - std::string FuncName = F->getName(); - SourceLocation Loc = QT->castAs<RecordType>()->getDecl()->getLocation(); - CGM.Error(Loc, "special function " + FuncName + - " for non-trivial C struct has incorrect type"); - return nullptr; - } - return F; - } - - ASTContext &Ctx = CGM.getContext(); - FunctionArgList Args; - const CGFunctionInfo &FI = getFunctionInfo<N>(CGM, Args); - llvm::FunctionType *FuncTy = CGM.getTypes().GetFunctionType(FI); - llvm::Function *F = - llvm::Function::Create(FuncTy, llvm::GlobalValue::LinkOnceODRLinkage, - FuncName, &CGM.getModule()); - F->setVisibility(llvm::GlobalValue::HiddenVisibility); - CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F); - CGM.SetLLVMFunctionAttributesForDefinition(nullptr, F); - IdentifierInfo *II = &Ctx.Idents.get(FuncName); - FunctionDecl *FD = FunctionDecl::Create( - Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), - II, Ctx.getFunctionType(Ctx.VoidTy, llvm::None, {}), nullptr, - SC_PrivateExtern, false, false); - CodeGenFunction NewCGF(CGM); - setCGF(&NewCGF); - CGF->StartFunction(FD, Ctx.VoidTy, F, FI, Args); - - for (unsigned I = 0; I < N; ++I) { - llvm::Value *V = CGF->Builder.CreateLoad(CGF->GetAddrOfLocalVar(Args[I])); - Addrs[I] = Address(V, Alignments[I]); - } - - asDerived().visitStructFields(QT, CharUnits::Zero(), Addrs); - CGF->FinishFunction(); - return F; - } - - template <size_t N> - void callFunc(StringRef FuncName, QualType QT, std::array<Address, N> Addrs, - CodeGenFunction &CallerCGF) { - std::array<CharUnits, N> Alignments; - llvm::Value *Ptrs[N]; - - for (unsigned I = 0; I < N; ++I) { - Alignments[I] = Addrs[I].getAlignment(); - Ptrs[I] = - CallerCGF.Builder.CreateBitCast(Addrs[I], CallerCGF.CGM.Int8PtrPtrTy) - .getPointer(); - } - - if (llvm::Function *F = - getFunction(FuncName, QT, Addrs, Alignments, CallerCGF.CGM)) - CallerCGF.EmitNounwindRuntimeCall(F, Ptrs); - } - - Derived &asDerived() { return static_cast<Derived &>(*this); } - - void setCGF(CodeGenFunction *F) { CGF = F; } - - CodeGenFunction *CGF = nullptr; -}; - -template <class Derived, bool IsMove> -struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>, - GenFuncBase<Derived> { - GenBinaryFunc(ASTContext &Ctx) : CopyStructVisitor<Derived, IsMove>(Ctx) {} - - void flushTrivialFields(std::array<Address, 2> Addrs) { - CharUnits Size = this->End - this->Start; - - if (Size.getQuantity() == 0) - return; - - Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], this->Start); - Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], this->Start); - - // Emit memcpy. - if (Size.getQuantity() >= 16 || !llvm::isPowerOf2_32(Size.getQuantity())) { - llvm::Value *SizeVal = - llvm::ConstantInt::get(this->CGF->SizeTy, Size.getQuantity()); - DstAddr = - this->CGF->Builder.CreateElementBitCast(DstAddr, this->CGF->Int8Ty); - SrcAddr = - this->CGF->Builder.CreateElementBitCast(SrcAddr, this->CGF->Int8Ty); - this->CGF->Builder.CreateMemCpy(DstAddr, SrcAddr, SizeVal, false); - } else { - llvm::Type *Ty = llvm::Type::getIntNTy( - this->CGF->getLLVMContext(), - Size.getQuantity() * this->CGF->getContext().getCharWidth()); - DstAddr = this->CGF->Builder.CreateElementBitCast(DstAddr, Ty); - SrcAddr = this->CGF->Builder.CreateElementBitCast(SrcAddr, Ty); - llvm::Value *SrcVal = this->CGF->Builder.CreateLoad(SrcAddr, false); - this->CGF->Builder.CreateStore(SrcVal, DstAddr, false); - } - - this->Start = this->End = CharUnits::Zero(); - } - - template <class... Ts> - void visitVolatileTrivial(QualType FT, const FieldDecl *FD, CharUnits Offset, - std::array<Address, 2> Addrs) { - LValue DstLV, SrcLV; - if (FD) { - QualType RT = QualType(FD->getParent()->getTypeForDecl(), 0); - llvm::PointerType *PtrTy = this->CGF->ConvertType(RT)->getPointerTo(); - Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset); - LValue DstBase = this->CGF->MakeAddrLValue( - this->CGF->Builder.CreateBitCast(DstAddr, PtrTy), FT); - DstLV = this->CGF->EmitLValueForField(DstBase, FD); - Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], Offset); - LValue SrcBase = this->CGF->MakeAddrLValue( - this->CGF->Builder.CreateBitCast(SrcAddr, PtrTy), FT); - SrcLV = this->CGF->EmitLValueForField(SrcBase, FD); - } else { - llvm::PointerType *Ty = this->CGF->ConvertType(FT)->getPointerTo(); - Address DstAddr = this->CGF->Builder.CreateBitCast(Addrs[DstIdx], Ty); - Address SrcAddr = this->CGF->Builder.CreateBitCast(Addrs[SrcIdx], Ty); - DstLV = this->CGF->MakeAddrLValue(DstAddr, FT); - SrcLV = this->CGF->MakeAddrLValue(SrcAddr, FT); - } - RValue SrcVal = this->CGF->EmitLoadOfLValue(SrcLV, SourceLocation()); - this->CGF->EmitStoreThroughLValue(SrcVal, DstLV); - } -}; - -// These classes that emit the special functions for a non-trivial struct. -struct GenDestructor : StructVisitor<GenDestructor>, - GenFuncBase<GenDestructor>, - DestructedTypeVisitor<GenDestructor> { - using Super = DestructedTypeVisitor<GenDestructor>; - GenDestructor(ASTContext &Ctx) : StructVisitor<GenDestructor>(Ctx) {} - - void visitWithKind(QualType::DestructionKind DK, QualType FT, - const FieldDecl *FD, CharUnits CurStructOffset, - std::array<Address, 1> Addrs) { - if (const auto *AT = getContext().getAsArrayType(FT)) { - visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset, Addrs); - return; - } - - Super::visitWithKind(DK, FT, FD, CurStructOffset, Addrs); - } - - void visitARCStrong(QualType QT, const FieldDecl *FD, - CharUnits CurStackOffset, std::array<Address, 1> Addrs) { - CGF->destroyARCStrongImprecise( - *CGF, getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT); - } - - void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset, - std::array<Address, 1> Addrs) { - CGF->destroyARCWeak( - *CGF, getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT); - } - - void callSpecialFunction(QualType FT, CharUnits Offset, - std::array<Address, 1> Addrs) { - CGF->callCStructDestructor( - CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT)); - } -}; - -struct GenDefaultInitialize - : StructVisitor<GenDefaultInitialize>, - GenFuncBase<GenDefaultInitialize>, - DefaultInitializedTypeVisitor<GenDefaultInitialize> { - using Super = DefaultInitializedTypeVisitor<GenDefaultInitialize>; - typedef GenFuncBase<GenDefaultInitialize> GenFuncBaseTy; - - GenDefaultInitialize(ASTContext &Ctx) - : StructVisitor<GenDefaultInitialize>(Ctx) {} - - void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT, - const FieldDecl *FD, CharUnits CurStructOffset, - std::array<Address, 1> Addrs) { - if (const auto *AT = getContext().getAsArrayType(FT)) { - visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset, - Addrs); - return; - } - - Super::visitWithKind(PDIK, FT, FD, CurStructOffset, Addrs); - } - - void visitARCStrong(QualType QT, const FieldDecl *FD, - CharUnits CurStackOffset, std::array<Address, 1> Addrs) { - CGF->EmitNullInitialization( - getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT); - } - - void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset, - std::array<Address, 1> Addrs) { - CGF->EmitNullInitialization( - getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT); - } - - template <class FieldKind, size_t... Is> - void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile, - const FieldDecl *FD, CharUnits CurStackOffset, - std::array<Address, 1> Addrs) { - if (!FK) - return visitTrivial(QualType(AT, 0), FD, CurStackOffset, Addrs); - - ASTContext &Ctx = getContext(); - CharUnits Size = Ctx.getTypeSizeInChars(QualType(AT, 0)); - QualType EltTy = Ctx.getBaseElementType(QualType(AT, 0)); - - if (Size < CharUnits::fromQuantity(16) || EltTy->getAs<RecordType>()) { - GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStackOffset, Addrs); - return; - } - - llvm::Constant *SizeVal = CGF->Builder.getInt64(Size.getQuantity()); - Address DstAddr = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD); - Address Loc = CGF->Builder.CreateElementBitCast(DstAddr, CGF->Int8Ty); - CGF->Builder.CreateMemSet(Loc, CGF->Builder.getInt8(0), SizeVal, - IsVolatile); - } - - void callSpecialFunction(QualType FT, CharUnits Offset, - std::array<Address, 1> Addrs) { - CGF->callCStructDefaultConstructor( - CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT)); - } -}; - -struct GenCopyConstructor : GenBinaryFunc<GenCopyConstructor, false> { - GenCopyConstructor(ASTContext &Ctx) - : GenBinaryFunc<GenCopyConstructor, false>(Ctx) {} - - void visitARCStrong(QualType QT, const FieldDecl *FD, - CharUnits CurStackOffset, std::array<Address, 2> Addrs) { - Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD); - Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD); - llvm::Value *SrcVal = CGF->EmitLoadOfScalar( - Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation()); - llvm::Value *Val = CGF->EmitARCRetain(QT, SrcVal); - CGF->EmitStoreOfScalar(Val, CGF->MakeAddrLValue(Addrs[DstIdx], QT), true); - } - - void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset, - std::array<Address, 2> Addrs) { - Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD); - Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD); - CGF->EmitARCCopyWeak(Addrs[DstIdx], Addrs[SrcIdx]); - } - - void callSpecialFunction(QualType FT, CharUnits Offset, - std::array<Address, 2> Addrs) { - CGF->callCStructCopyConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT), - CGF->MakeAddrLValue(Addrs[SrcIdx], FT)); - } -}; - -struct GenMoveConstructor : GenBinaryFunc<GenMoveConstructor, true> { - GenMoveConstructor(ASTContext &Ctx) - : GenBinaryFunc<GenMoveConstructor, true>(Ctx) {} - - void visitARCStrong(QualType QT, const FieldDecl *FD, - CharUnits CurStackOffset, std::array<Address, 2> Addrs) { - Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD); - Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD); - LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT); - llvm::Value *SrcVal = - CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal(); - CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress()), SrcLV); - CGF->EmitStoreOfScalar(SrcVal, CGF->MakeAddrLValue(Addrs[DstIdx], QT), - /* isInitialization */ true); - } - - void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset, - std::array<Address, 2> Addrs) { - Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD); - Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD); - CGF->EmitARCMoveWeak(Addrs[DstIdx], Addrs[SrcIdx]); - } - - void callSpecialFunction(QualType FT, CharUnits Offset, - std::array<Address, 2> Addrs) { - CGF->callCStructMoveConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT), - CGF->MakeAddrLValue(Addrs[SrcIdx], FT)); - } -}; - -struct GenCopyAssignment : GenBinaryFunc<GenCopyAssignment, false> { - GenCopyAssignment(ASTContext &Ctx) - : GenBinaryFunc<GenCopyAssignment, false>(Ctx) {} - - void visitARCStrong(QualType QT, const FieldDecl *FD, - CharUnits CurStackOffset, std::array<Address, 2> Addrs) { - Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD); - Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD); - llvm::Value *SrcVal = CGF->EmitLoadOfScalar( - Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation()); - CGF->EmitARCStoreStrong(CGF->MakeAddrLValue(Addrs[DstIdx], QT), SrcVal, - false); - } - - void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset, - std::array<Address, 2> Addrs) { - Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD); - Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD); - CGF->emitARCCopyAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]); - } - - void callSpecialFunction(QualType FT, CharUnits Offset, - std::array<Address, 2> Addrs) { - CGF->callCStructCopyAssignmentOperator( - CGF->MakeAddrLValue(Addrs[DstIdx], FT), - CGF->MakeAddrLValue(Addrs[SrcIdx], FT)); - } -}; - -struct GenMoveAssignment : GenBinaryFunc<GenMoveAssignment, true> { - GenMoveAssignment(ASTContext &Ctx) - : GenBinaryFunc<GenMoveAssignment, true>(Ctx) {} - - void visitARCStrong(QualType QT, const FieldDecl *FD, - CharUnits CurStackOffset, std::array<Address, 2> Addrs) { - Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD); - Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD); - LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT); - llvm::Value *SrcVal = - CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal(); - CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress()), SrcLV); - LValue DstLV = CGF->MakeAddrLValue(Addrs[DstIdx], QT); - llvm::Value *DstVal = - CGF->EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal(); - CGF->EmitStoreOfScalar(SrcVal, DstLV); - CGF->EmitARCRelease(DstVal, ARCImpreciseLifetime); - } - - void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset, - std::array<Address, 2> Addrs) { - Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD); - Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD); - CGF->emitARCMoveAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]); - } - - void callSpecialFunction(QualType FT, CharUnits Offset, - std::array<Address, 2> Addrs) { - CGF->callCStructMoveAssignmentOperator( - CGF->MakeAddrLValue(Addrs[DstIdx], FT), - CGF->MakeAddrLValue(Addrs[SrcIdx], FT)); - } -}; - -} // namespace - -void CodeGenFunction::destroyNonTrivialCStruct(CodeGenFunction &CGF, - Address Addr, QualType Type) { - CGF.callCStructDestructor(CGF.MakeAddrLValue(Addr, Type)); -} - -// Default-initialize a variable that is a non-trivial struct or an array of -// such structure. -void CodeGenFunction::defaultInitNonTrivialCStructVar(LValue Dst) { - GenDefaultInitialize Gen(getContext()); - Address DstPtr = Builder.CreateBitCast(Dst.getAddress(), CGM.Int8PtrPtrTy); - Gen.setCGF(this); - QualType QT = Dst.getType(); - QT = Dst.isVolatile() ? QT.withVolatile() : QT; - Gen.visit(QT, nullptr, CharUnits::Zero(), std::array<Address, 1>({{DstPtr}})); -} - -template <class G, size_t N> -static void callSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, - bool IsVolatile, CodeGenFunction &CGF, - std::array<Address, N> Addrs) { - for (unsigned I = 0; I < N; ++I) - Addrs[I] = CGF.Builder.CreateBitCast(Addrs[I], CGF.CGM.Int8PtrPtrTy); - QT = IsVolatile ? QT.withVolatile() : QT; - Gen.callFunc(FuncName, QT, Addrs, CGF); -} - -// Functions to emit calls to the special functions of a non-trivial C struct. -void CodeGenFunction::callCStructDefaultConstructor(LValue Dst) { - bool IsVolatile = Dst.isVolatile(); - Address DstPtr = Dst.getAddress(); - QualType QT = Dst.getType(); - GenDefaultInitializeFuncName GenName(DstPtr.getAlignment(), getContext()); - std::string FuncName = GenName.getName(QT, IsVolatile); - callSpecialFunction(GenDefaultInitialize(getContext()), FuncName, QT, - IsVolatile, *this, std::array<Address, 1>({{DstPtr}})); -} - -std::string -CodeGenFunction::getNonTrivialCopyConstructorStr(QualType QT, - CharUnits Alignment, - bool IsVolatile, - ASTContext &Ctx) { - GenBinaryFuncName<false> GenName("", Alignment, Alignment, Ctx); - return GenName.getName(QT, IsVolatile); -} - -std::string -CodeGenFunction::getNonTrivialDestructorStr(QualType QT, CharUnits Alignment, - bool IsVolatile, ASTContext &Ctx) { - GenDestructorFuncName GenName("", Alignment, Ctx); - return GenName.getName(QT, IsVolatile); -} - -void CodeGenFunction::callCStructDestructor(LValue Dst) { - bool IsVolatile = Dst.isVolatile(); - Address DstPtr = Dst.getAddress(); - QualType QT = Dst.getType(); - GenDestructorFuncName GenName("__destructor_", DstPtr.getAlignment(), - getContext()); - std::string FuncName = GenName.getName(QT, IsVolatile); - callSpecialFunction(GenDestructor(getContext()), FuncName, QT, IsVolatile, - *this, std::array<Address, 1>({{DstPtr}})); -} - -void CodeGenFunction::callCStructCopyConstructor(LValue Dst, LValue Src) { - bool IsVolatile = Dst.isVolatile() || Src.isVolatile(); - Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress(); - QualType QT = Dst.getType(); - GenBinaryFuncName<false> GenName("__copy_constructor_", DstPtr.getAlignment(), - SrcPtr.getAlignment(), getContext()); - std::string FuncName = GenName.getName(QT, IsVolatile); - callSpecialFunction(GenCopyConstructor(getContext()), FuncName, QT, - IsVolatile, *this, - std::array<Address, 2>({{DstPtr, SrcPtr}})); -} - -void CodeGenFunction::callCStructCopyAssignmentOperator(LValue Dst, LValue Src - -) { - bool IsVolatile = Dst.isVolatile() || Src.isVolatile(); - Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress(); - QualType QT = Dst.getType(); - GenBinaryFuncName<false> GenName("__copy_assignment_", DstPtr.getAlignment(), - SrcPtr.getAlignment(), getContext()); - std::string FuncName = GenName.getName(QT, IsVolatile); - callSpecialFunction(GenCopyAssignment(getContext()), FuncName, QT, IsVolatile, - *this, std::array<Address, 2>({{DstPtr, SrcPtr}})); -} - -void CodeGenFunction::callCStructMoveConstructor(LValue Dst, LValue Src) { - bool IsVolatile = Dst.isVolatile() || Src.isVolatile(); - Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress(); - QualType QT = Dst.getType(); - GenBinaryFuncName<true> GenName("__move_constructor_", DstPtr.getAlignment(), - SrcPtr.getAlignment(), getContext()); - std::string FuncName = GenName.getName(QT, IsVolatile); - callSpecialFunction(GenMoveConstructor(getContext()), FuncName, QT, - IsVolatile, *this, - std::array<Address, 2>({{DstPtr, SrcPtr}})); -} - -void CodeGenFunction::callCStructMoveAssignmentOperator(LValue Dst, LValue Src - -) { - bool IsVolatile = Dst.isVolatile() || Src.isVolatile(); - Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress(); - QualType QT = Dst.getType(); - GenBinaryFuncName<true> GenName("__move_assignment_", DstPtr.getAlignment(), - SrcPtr.getAlignment(), getContext()); - std::string FuncName = GenName.getName(QT, IsVolatile); - callSpecialFunction(GenMoveAssignment(getContext()), FuncName, QT, IsVolatile, - *this, std::array<Address, 2>({{DstPtr, SrcPtr}})); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGObjC.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGObjC.cpp deleted file mode 100644 index 9c66ff0e8fb..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGObjC.cpp +++ /dev/null @@ -1,3665 +0,0 @@ -//===---- CGObjC.cpp - Emit LLVM Code for Objective-C ---------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code to emit Objective-C code as LLVM code. -// -//===----------------------------------------------------------------------===// - -#include "CGDebugInfo.h" -#include "CGObjCRuntime.h" -#include "CodeGenFunction.h" -#include "CodeGenModule.h" -#include "TargetInfo.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/StmtObjC.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/CodeGen/CGFunctionInfo.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/InlineAsm.h" -using namespace clang; -using namespace CodeGen; - -typedef llvm::PointerIntPair<llvm::Value*,1,bool> TryEmitResult; -static TryEmitResult -tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e); -static RValue AdjustObjCObjectType(CodeGenFunction &CGF, - QualType ET, - RValue Result); - -/// Given the address of a variable of pointer type, find the correct -/// null to store into it. -static llvm::Constant *getNullForVariable(Address addr) { - llvm::Type *type = addr.getElementType(); - return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(type)); -} - -/// Emits an instance of NSConstantString representing the object. -llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E) -{ - llvm::Constant *C = - CGM.getObjCRuntime().GenerateConstantString(E->getString()).getPointer(); - // FIXME: This bitcast should just be made an invariant on the Runtime. - return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType())); -} - -/// EmitObjCBoxedExpr - This routine generates code to call -/// the appropriate expression boxing method. This will either be -/// one of +[NSNumber numberWith<Type>:], or +[NSString stringWithUTF8String:], -/// or [NSValue valueWithBytes:objCType:]. -/// -llvm::Value * -CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) { - // Generate the correct selector for this literal's concrete type. - // Get the method. - const ObjCMethodDecl *BoxingMethod = E->getBoxingMethod(); - const Expr *SubExpr = E->getSubExpr(); - assert(BoxingMethod && "BoxingMethod is null"); - assert(BoxingMethod->isClassMethod() && "BoxingMethod must be a class method"); - Selector Sel = BoxingMethod->getSelector(); - - // Generate a reference to the class pointer, which will be the receiver. - // Assumes that the method was introduced in the class that should be - // messaged (avoids pulling it out of the result type). - CGObjCRuntime &Runtime = CGM.getObjCRuntime(); - const ObjCInterfaceDecl *ClassDecl = BoxingMethod->getClassInterface(); - llvm::Value *Receiver = Runtime.GetClass(*this, ClassDecl); - - CallArgList Args; - const ParmVarDecl *ArgDecl = *BoxingMethod->param_begin(); - QualType ArgQT = ArgDecl->getType().getUnqualifiedType(); - - // ObjCBoxedExpr supports boxing of structs and unions - // via [NSValue valueWithBytes:objCType:] - const QualType ValueType(SubExpr->getType().getCanonicalType()); - if (ValueType->isObjCBoxableRecordType()) { - // Emit CodeGen for first parameter - // and cast value to correct type - Address Temporary = CreateMemTemp(SubExpr->getType()); - EmitAnyExprToMem(SubExpr, Temporary, Qualifiers(), /*isInit*/ true); - Address BitCast = Builder.CreateBitCast(Temporary, ConvertType(ArgQT)); - Args.add(RValue::get(BitCast.getPointer()), ArgQT); - - // Create char array to store type encoding - std::string Str; - getContext().getObjCEncodingForType(ValueType, Str); - llvm::Constant *GV = CGM.GetAddrOfConstantCString(Str).getPointer(); - - // Cast type encoding to correct type - const ParmVarDecl *EncodingDecl = BoxingMethod->parameters()[1]; - QualType EncodingQT = EncodingDecl->getType().getUnqualifiedType(); - llvm::Value *Cast = Builder.CreateBitCast(GV, ConvertType(EncodingQT)); - - Args.add(RValue::get(Cast), EncodingQT); - } else { - Args.add(EmitAnyExpr(SubExpr), ArgQT); - } - - RValue result = Runtime.GenerateMessageSend( - *this, ReturnValueSlot(), BoxingMethod->getReturnType(), Sel, Receiver, - Args, ClassDecl, BoxingMethod); - return Builder.CreateBitCast(result.getScalarVal(), - ConvertType(E->getType())); -} - -llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E, - const ObjCMethodDecl *MethodWithObjects) { - ASTContext &Context = CGM.getContext(); - const ObjCDictionaryLiteral *DLE = nullptr; - const ObjCArrayLiteral *ALE = dyn_cast<ObjCArrayLiteral>(E); - if (!ALE) - DLE = cast<ObjCDictionaryLiteral>(E); - - // Optimize empty collections by referencing constants, when available. - uint64_t NumElements = - ALE ? ALE->getNumElements() : DLE->getNumElements(); - if (NumElements == 0 && CGM.getLangOpts().ObjCRuntime.hasEmptyCollections()) { - StringRef ConstantName = ALE ? "__NSArray0__" : "__NSDictionary0__"; - QualType IdTy(CGM.getContext().getObjCIdType()); - llvm::Constant *Constant = - CGM.CreateRuntimeVariable(ConvertType(IdTy), ConstantName); - LValue LV = MakeNaturalAlignAddrLValue(Constant, IdTy); - llvm::Value *Ptr = EmitLoadOfScalar(LV, E->getBeginLoc()); - cast<llvm::LoadInst>(Ptr)->setMetadata( - CGM.getModule().getMDKindID("invariant.load"), - llvm::MDNode::get(getLLVMContext(), None)); - return Builder.CreateBitCast(Ptr, ConvertType(E->getType())); - } - - // Compute the type of the array we're initializing. - llvm::APInt APNumElements(Context.getTypeSize(Context.getSizeType()), - NumElements); - QualType ElementType = Context.getObjCIdType().withConst(); - QualType ElementArrayType - = Context.getConstantArrayType(ElementType, APNumElements, - ArrayType::Normal, /*IndexTypeQuals=*/0); - - // Allocate the temporary array(s). - Address Objects = CreateMemTemp(ElementArrayType, "objects"); - Address Keys = Address::invalid(); - if (DLE) - Keys = CreateMemTemp(ElementArrayType, "keys"); - - // In ARC, we may need to do extra work to keep all the keys and - // values alive until after the call. - SmallVector<llvm::Value *, 16> NeededObjects; - bool TrackNeededObjects = - (getLangOpts().ObjCAutoRefCount && - CGM.getCodeGenOpts().OptimizationLevel != 0); - - // Perform the actual initialialization of the array(s). - for (uint64_t i = 0; i < NumElements; i++) { - if (ALE) { - // Emit the element and store it to the appropriate array slot. - const Expr *Rhs = ALE->getElement(i); - LValue LV = MakeAddrLValue( - Builder.CreateConstArrayGEP(Objects, i, getPointerSize()), - ElementType, AlignmentSource::Decl); - - llvm::Value *value = EmitScalarExpr(Rhs); - EmitStoreThroughLValue(RValue::get(value), LV, true); - if (TrackNeededObjects) { - NeededObjects.push_back(value); - } - } else { - // Emit the key and store it to the appropriate array slot. - const Expr *Key = DLE->getKeyValueElement(i).Key; - LValue KeyLV = MakeAddrLValue( - Builder.CreateConstArrayGEP(Keys, i, getPointerSize()), - ElementType, AlignmentSource::Decl); - llvm::Value *keyValue = EmitScalarExpr(Key); - EmitStoreThroughLValue(RValue::get(keyValue), KeyLV, /*isInit=*/true); - - // Emit the value and store it to the appropriate array slot. - const Expr *Value = DLE->getKeyValueElement(i).Value; - LValue ValueLV = MakeAddrLValue( - Builder.CreateConstArrayGEP(Objects, i, getPointerSize()), - ElementType, AlignmentSource::Decl); - llvm::Value *valueValue = EmitScalarExpr(Value); - EmitStoreThroughLValue(RValue::get(valueValue), ValueLV, /*isInit=*/true); - if (TrackNeededObjects) { - NeededObjects.push_back(keyValue); - NeededObjects.push_back(valueValue); - } - } - } - - // Generate the argument list. - CallArgList Args; - ObjCMethodDecl::param_const_iterator PI = MethodWithObjects->param_begin(); - const ParmVarDecl *argDecl = *PI++; - QualType ArgQT = argDecl->getType().getUnqualifiedType(); - Args.add(RValue::get(Objects.getPointer()), ArgQT); - if (DLE) { - argDecl = *PI++; - ArgQT = argDecl->getType().getUnqualifiedType(); - Args.add(RValue::get(Keys.getPointer()), ArgQT); - } - argDecl = *PI; - ArgQT = argDecl->getType().getUnqualifiedType(); - llvm::Value *Count = - llvm::ConstantInt::get(CGM.getTypes().ConvertType(ArgQT), NumElements); - Args.add(RValue::get(Count), ArgQT); - - // Generate a reference to the class pointer, which will be the receiver. - Selector Sel = MethodWithObjects->getSelector(); - QualType ResultType = E->getType(); - const ObjCObjectPointerType *InterfacePointerType - = ResultType->getAsObjCInterfacePointerType(); - ObjCInterfaceDecl *Class - = InterfacePointerType->getObjectType()->getInterface(); - CGObjCRuntime &Runtime = CGM.getObjCRuntime(); - llvm::Value *Receiver = Runtime.GetClass(*this, Class); - - // Generate the message send. - RValue result = Runtime.GenerateMessageSend( - *this, ReturnValueSlot(), MethodWithObjects->getReturnType(), Sel, - Receiver, Args, Class, MethodWithObjects); - - // The above message send needs these objects, but in ARC they are - // passed in a buffer that is essentially __unsafe_unretained. - // Therefore we must prevent the optimizer from releasing them until - // after the call. - if (TrackNeededObjects) { - EmitARCIntrinsicUse(NeededObjects); - } - - return Builder.CreateBitCast(result.getScalarVal(), - ConvertType(E->getType())); -} - -llvm::Value *CodeGenFunction::EmitObjCArrayLiteral(const ObjCArrayLiteral *E) { - return EmitObjCCollectionLiteral(E, E->getArrayWithObjectsMethod()); -} - -llvm::Value *CodeGenFunction::EmitObjCDictionaryLiteral( - const ObjCDictionaryLiteral *E) { - return EmitObjCCollectionLiteral(E, E->getDictWithObjectsMethod()); -} - -/// Emit a selector. -llvm::Value *CodeGenFunction::EmitObjCSelectorExpr(const ObjCSelectorExpr *E) { - // Untyped selector. - // Note that this implementation allows for non-constant strings to be passed - // as arguments to @selector(). Currently, the only thing preventing this - // behaviour is the type checking in the front end. - return CGM.getObjCRuntime().GetSelector(*this, E->getSelector()); -} - -llvm::Value *CodeGenFunction::EmitObjCProtocolExpr(const ObjCProtocolExpr *E) { - // FIXME: This should pass the Decl not the name. - return CGM.getObjCRuntime().GenerateProtocolRef(*this, E->getProtocol()); -} - -/// Adjust the type of an Objective-C object that doesn't match up due -/// to type erasure at various points, e.g., related result types or the use -/// of parameterized classes. -static RValue AdjustObjCObjectType(CodeGenFunction &CGF, QualType ExpT, - RValue Result) { - if (!ExpT->isObjCRetainableType()) - return Result; - - // If the converted types are the same, we're done. - llvm::Type *ExpLLVMTy = CGF.ConvertType(ExpT); - if (ExpLLVMTy == Result.getScalarVal()->getType()) - return Result; - - // We have applied a substitution. Cast the rvalue appropriately. - return RValue::get(CGF.Builder.CreateBitCast(Result.getScalarVal(), - ExpLLVMTy)); -} - -/// Decide whether to extend the lifetime of the receiver of a -/// returns-inner-pointer message. -static bool -shouldExtendReceiverForInnerPointerMessage(const ObjCMessageExpr *message) { - switch (message->getReceiverKind()) { - - // For a normal instance message, we should extend unless the - // receiver is loaded from a variable with precise lifetime. - case ObjCMessageExpr::Instance: { - const Expr *receiver = message->getInstanceReceiver(); - - // Look through OVEs. - if (auto opaque = dyn_cast<OpaqueValueExpr>(receiver)) { - if (opaque->getSourceExpr()) - receiver = opaque->getSourceExpr()->IgnoreParens(); - } - - const ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(receiver); - if (!ice || ice->getCastKind() != CK_LValueToRValue) return true; - receiver = ice->getSubExpr()->IgnoreParens(); - - // Look through OVEs. - if (auto opaque = dyn_cast<OpaqueValueExpr>(receiver)) { - if (opaque->getSourceExpr()) - receiver = opaque->getSourceExpr()->IgnoreParens(); - } - - // Only __strong variables. - if (receiver->getType().getObjCLifetime() != Qualifiers::OCL_Strong) - return true; - - // All ivars and fields have precise lifetime. - if (isa<MemberExpr>(receiver) || isa<ObjCIvarRefExpr>(receiver)) - return false; - - // Otherwise, check for variables. - const DeclRefExpr *declRef = dyn_cast<DeclRefExpr>(ice->getSubExpr()); - if (!declRef) return true; - const VarDecl *var = dyn_cast<VarDecl>(declRef->getDecl()); - if (!var) return true; - - // All variables have precise lifetime except local variables with - // automatic storage duration that aren't specially marked. - return (var->hasLocalStorage() && - !var->hasAttr<ObjCPreciseLifetimeAttr>()); - } - - case ObjCMessageExpr::Class: - case ObjCMessageExpr::SuperClass: - // It's never necessary for class objects. - return false; - - case ObjCMessageExpr::SuperInstance: - // We generally assume that 'self' lives throughout a method call. - return false; - } - - llvm_unreachable("invalid receiver kind"); -} - -/// Given an expression of ObjC pointer type, check whether it was -/// immediately loaded from an ARC __weak l-value. -static const Expr *findWeakLValue(const Expr *E) { - assert(E->getType()->isObjCRetainableType()); - E = E->IgnoreParens(); - if (auto CE = dyn_cast<CastExpr>(E)) { - if (CE->getCastKind() == CK_LValueToRValue) { - if (CE->getSubExpr()->getType().getObjCLifetime() == Qualifiers::OCL_Weak) - return CE->getSubExpr(); - } - } - - return nullptr; -} - -/// The ObjC runtime may provide entrypoints that are likely to be faster -/// than an ordinary message send of the appropriate selector. -/// -/// The entrypoints are guaranteed to be equivalent to just sending the -/// corresponding message. If the entrypoint is implemented naively as just a -/// message send, using it is a trade-off: it sacrifices a few cycles of -/// overhead to save a small amount of code. However, it's possible for -/// runtimes to detect and special-case classes that use "standard" -/// behavior; if that's dynamically a large proportion of all objects, using -/// the entrypoint will also be faster than using a message send. -/// -/// If the runtime does support a required entrypoint, then this method will -/// generate a call and return the resulting value. Otherwise it will return -/// None and the caller can generate a msgSend instead. -static Optional<llvm::Value *> -tryGenerateSpecializedMessageSend(CodeGenFunction &CGF, QualType ResultType, - llvm::Value *Receiver, - const CallArgList& Args, Selector Sel, - const ObjCMethodDecl *method, - bool isClassMessage) { - auto &CGM = CGF.CGM; - if (!CGM.getCodeGenOpts().ObjCConvertMessagesToRuntimeCalls) - return None; - - auto &Runtime = CGM.getLangOpts().ObjCRuntime; - switch (Sel.getMethodFamily()) { - case OMF_alloc: - if (isClassMessage && - Runtime.shouldUseRuntimeFunctionsForAlloc() && - ResultType->isObjCObjectPointerType()) { - // [Foo alloc] -> objc_alloc(Foo) - if (Sel.isUnarySelector() && Sel.getNameForSlot(0) == "alloc") - return CGF.EmitObjCAlloc(Receiver, CGF.ConvertType(ResultType)); - // [Foo allocWithZone:nil] -> objc_allocWithZone(Foo) - if (Sel.isKeywordSelector() && Sel.getNumArgs() == 1 && - Args.size() == 1 && Args.front().getType()->isPointerType() && - Sel.getNameForSlot(0) == "allocWithZone") { - const llvm::Value* arg = Args.front().getKnownRValue().getScalarVal(); - if (isa<llvm::ConstantPointerNull>(arg)) - return CGF.EmitObjCAllocWithZone(Receiver, - CGF.ConvertType(ResultType)); - return None; - } - } - break; - - case OMF_autorelease: - if (ResultType->isObjCObjectPointerType() && - CGM.getLangOpts().getGC() == LangOptions::NonGC && - Runtime.shouldUseARCFunctionsForRetainRelease()) - return CGF.EmitObjCAutorelease(Receiver, CGF.ConvertType(ResultType)); - break; - - case OMF_retain: - if (ResultType->isObjCObjectPointerType() && - CGM.getLangOpts().getGC() == LangOptions::NonGC && - Runtime.shouldUseARCFunctionsForRetainRelease()) - return CGF.EmitObjCRetainNonBlock(Receiver, CGF.ConvertType(ResultType)); - break; - - case OMF_release: - if (ResultType->isVoidType() && - CGM.getLangOpts().getGC() == LangOptions::NonGC && - Runtime.shouldUseARCFunctionsForRetainRelease()) { - CGF.EmitObjCRelease(Receiver, ARCPreciseLifetime); - return nullptr; - } - break; - - default: - break; - } - return None; -} - -RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E, - ReturnValueSlot Return) { - // Only the lookup mechanism and first two arguments of the method - // implementation vary between runtimes. We can get the receiver and - // arguments in generic code. - - bool isDelegateInit = E->isDelegateInitCall(); - - const ObjCMethodDecl *method = E->getMethodDecl(); - - // If the method is -retain, and the receiver's being loaded from - // a __weak variable, peephole the entire operation to objc_loadWeakRetained. - if (method && E->getReceiverKind() == ObjCMessageExpr::Instance && - method->getMethodFamily() == OMF_retain) { - if (auto lvalueExpr = findWeakLValue(E->getInstanceReceiver())) { - LValue lvalue = EmitLValue(lvalueExpr); - llvm::Value *result = EmitARCLoadWeakRetained(lvalue.getAddress()); - return AdjustObjCObjectType(*this, E->getType(), RValue::get(result)); - } - } - - // We don't retain the receiver in delegate init calls, and this is - // safe because the receiver value is always loaded from 'self', - // which we zero out. We don't want to Block_copy block receivers, - // though. - bool retainSelf = - (!isDelegateInit && - CGM.getLangOpts().ObjCAutoRefCount && - method && - method->hasAttr<NSConsumesSelfAttr>()); - - CGObjCRuntime &Runtime = CGM.getObjCRuntime(); - bool isSuperMessage = false; - bool isClassMessage = false; - ObjCInterfaceDecl *OID = nullptr; - // Find the receiver - QualType ReceiverType; - llvm::Value *Receiver = nullptr; - switch (E->getReceiverKind()) { - case ObjCMessageExpr::Instance: - ReceiverType = E->getInstanceReceiver()->getType(); - if (retainSelf) { - TryEmitResult ter = tryEmitARCRetainScalarExpr(*this, - E->getInstanceReceiver()); - Receiver = ter.getPointer(); - if (ter.getInt()) retainSelf = false; - } else - Receiver = EmitScalarExpr(E->getInstanceReceiver()); - break; - - case ObjCMessageExpr::Class: { - ReceiverType = E->getClassReceiver(); - const ObjCObjectType *ObjTy = ReceiverType->getAs<ObjCObjectType>(); - assert(ObjTy && "Invalid Objective-C class message send"); - OID = ObjTy->getInterface(); - assert(OID && "Invalid Objective-C class message send"); - Receiver = Runtime.GetClass(*this, OID); - isClassMessage = true; - break; - } - - case ObjCMessageExpr::SuperInstance: - ReceiverType = E->getSuperType(); - Receiver = LoadObjCSelf(); - isSuperMessage = true; - break; - - case ObjCMessageExpr::SuperClass: - ReceiverType = E->getSuperType(); - Receiver = LoadObjCSelf(); - isSuperMessage = true; - isClassMessage = true; - break; - } - - if (retainSelf) - Receiver = EmitARCRetainNonBlock(Receiver); - - // In ARC, we sometimes want to "extend the lifetime" - // (i.e. retain+autorelease) of receivers of returns-inner-pointer - // messages. - if (getLangOpts().ObjCAutoRefCount && method && - method->hasAttr<ObjCReturnsInnerPointerAttr>() && - shouldExtendReceiverForInnerPointerMessage(E)) - Receiver = EmitARCRetainAutorelease(ReceiverType, Receiver); - - QualType ResultType = method ? method->getReturnType() : E->getType(); - - CallArgList Args; - EmitCallArgs(Args, method, E->arguments(), /*AC*/AbstractCallee(method)); - - // For delegate init calls in ARC, do an unsafe store of null into - // self. This represents the call taking direct ownership of that - // value. We have to do this after emitting the other call - // arguments because they might also reference self, but we don't - // have to worry about any of them modifying self because that would - // be an undefined read and write of an object in unordered - // expressions. - if (isDelegateInit) { - assert(getLangOpts().ObjCAutoRefCount && - "delegate init calls should only be marked in ARC"); - - // Do an unsafe store of null into self. - Address selfAddr = - GetAddrOfLocalVar(cast<ObjCMethodDecl>(CurCodeDecl)->getSelfDecl()); - Builder.CreateStore(getNullForVariable(selfAddr), selfAddr); - } - - RValue result; - if (isSuperMessage) { - // super is only valid in an Objective-C method - const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); - bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); - result = Runtime.GenerateMessageSendSuper(*this, Return, ResultType, - E->getSelector(), - OMD->getClassInterface(), - isCategoryImpl, - Receiver, - isClassMessage, - Args, - method); - } else { - // Call runtime methods directly if we can. - if (Optional<llvm::Value *> SpecializedResult = - tryGenerateSpecializedMessageSend(*this, ResultType, Receiver, Args, - E->getSelector(), method, - isClassMessage)) { - result = RValue::get(SpecializedResult.getValue()); - } else { - result = Runtime.GenerateMessageSend(*this, Return, ResultType, - E->getSelector(), Receiver, Args, - OID, method); - } - } - - // For delegate init calls in ARC, implicitly store the result of - // the call back into self. This takes ownership of the value. - if (isDelegateInit) { - Address selfAddr = - GetAddrOfLocalVar(cast<ObjCMethodDecl>(CurCodeDecl)->getSelfDecl()); - llvm::Value *newSelf = result.getScalarVal(); - - // The delegate return type isn't necessarily a matching type; in - // fact, it's quite likely to be 'id'. - llvm::Type *selfTy = selfAddr.getElementType(); - newSelf = Builder.CreateBitCast(newSelf, selfTy); - - Builder.CreateStore(newSelf, selfAddr); - } - - return AdjustObjCObjectType(*this, E->getType(), result); -} - -namespace { -struct FinishARCDealloc final : EHScopeStack::Cleanup { - void Emit(CodeGenFunction &CGF, Flags flags) override { - const ObjCMethodDecl *method = cast<ObjCMethodDecl>(CGF.CurCodeDecl); - - const ObjCImplDecl *impl = cast<ObjCImplDecl>(method->getDeclContext()); - const ObjCInterfaceDecl *iface = impl->getClassInterface(); - if (!iface->getSuperClass()) return; - - bool isCategory = isa<ObjCCategoryImplDecl>(impl); - - // Call [super dealloc] if we have a superclass. - llvm::Value *self = CGF.LoadObjCSelf(); - - CallArgList args; - CGF.CGM.getObjCRuntime().GenerateMessageSendSuper(CGF, ReturnValueSlot(), - CGF.getContext().VoidTy, - method->getSelector(), - iface, - isCategory, - self, - /*is class msg*/ false, - args, - method); - } -}; -} - -/// StartObjCMethod - Begin emission of an ObjCMethod. This generates -/// the LLVM function and sets the other context used by -/// CodeGenFunction. -void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD, - const ObjCContainerDecl *CD) { - SourceLocation StartLoc = OMD->getBeginLoc(); - FunctionArgList args; - // Check if we should generate debug info for this method. - if (OMD->hasAttr<NoDebugAttr>()) - DebugInfo = nullptr; // disable debug info indefinitely for this function - - llvm::Function *Fn = CGM.getObjCRuntime().GenerateMethod(OMD, CD); - - const CGFunctionInfo &FI = CGM.getTypes().arrangeObjCMethodDeclaration(OMD); - CGM.SetInternalFunctionAttributes(OMD, Fn, FI); - - args.push_back(OMD->getSelfDecl()); - args.push_back(OMD->getCmdDecl()); - - args.append(OMD->param_begin(), OMD->param_end()); - - CurGD = OMD; - CurEHLocation = OMD->getEndLoc(); - - StartFunction(OMD, OMD->getReturnType(), Fn, FI, args, - OMD->getLocation(), StartLoc); - - // In ARC, certain methods get an extra cleanup. - if (CGM.getLangOpts().ObjCAutoRefCount && - OMD->isInstanceMethod() && - OMD->getSelector().isUnarySelector()) { - const IdentifierInfo *ident = - OMD->getSelector().getIdentifierInfoForSlot(0); - if (ident->isStr("dealloc")) - EHStack.pushCleanup<FinishARCDealloc>(getARCCleanupKind()); - } -} - -static llvm::Value *emitARCRetainLoadOfScalar(CodeGenFunction &CGF, - LValue lvalue, QualType type); - -/// Generate an Objective-C method. An Objective-C method is a C function with -/// its pointer, name, and types registered in the class structure. -void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) { - StartObjCMethod(OMD, OMD->getClassInterface()); - PGO.assignRegionCounters(GlobalDecl(OMD), CurFn); - assert(isa<CompoundStmt>(OMD->getBody())); - incrementProfileCounter(OMD->getBody()); - EmitCompoundStmtWithoutScope(*cast<CompoundStmt>(OMD->getBody())); - FinishFunction(OMD->getBodyRBrace()); -} - -/// emitStructGetterCall - Call the runtime function to load a property -/// into the return value slot. -static void emitStructGetterCall(CodeGenFunction &CGF, ObjCIvarDecl *ivar, - bool isAtomic, bool hasStrong) { - ASTContext &Context = CGF.getContext(); - - Address src = - CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), CGF.LoadObjCSelf(), ivar, 0) - .getAddress(); - - // objc_copyStruct (ReturnValue, &structIvar, - // sizeof (Type of Ivar), isAtomic, false); - CallArgList args; - - Address dest = CGF.Builder.CreateBitCast(CGF.ReturnValue, CGF.VoidPtrTy); - args.add(RValue::get(dest.getPointer()), Context.VoidPtrTy); - - src = CGF.Builder.CreateBitCast(src, CGF.VoidPtrTy); - args.add(RValue::get(src.getPointer()), Context.VoidPtrTy); - - CharUnits size = CGF.getContext().getTypeSizeInChars(ivar->getType()); - args.add(RValue::get(CGF.CGM.getSize(size)), Context.getSizeType()); - args.add(RValue::get(CGF.Builder.getInt1(isAtomic)), Context.BoolTy); - args.add(RValue::get(CGF.Builder.getInt1(hasStrong)), Context.BoolTy); - - llvm::Constant *fn = CGF.CGM.getObjCRuntime().GetGetStructFunction(); - CGCallee callee = CGCallee::forDirect(fn); - CGF.EmitCall(CGF.getTypes().arrangeBuiltinFunctionCall(Context.VoidTy, args), - callee, ReturnValueSlot(), args); -} - -/// Determine whether the given architecture supports unaligned atomic -/// accesses. They don't have to be fast, just faster than a function -/// call and a mutex. -static bool hasUnalignedAtomics(llvm::Triple::ArchType arch) { - // FIXME: Allow unaligned atomic load/store on x86. (It is not - // currently supported by the backend.) - return 0; -} - -/// Return the maximum size that permits atomic accesses for the given -/// architecture. -static CharUnits getMaxAtomicAccessSize(CodeGenModule &CGM, - llvm::Triple::ArchType arch) { - // ARM has 8-byte atomic accesses, but it's not clear whether we - // want to rely on them here. - - // In the default case, just assume that any size up to a pointer is - // fine given adequate alignment. - return CharUnits::fromQuantity(CGM.PointerSizeInBytes); -} - -namespace { - class PropertyImplStrategy { - public: - enum StrategyKind { - /// The 'native' strategy is to use the architecture's provided - /// reads and writes. - Native, - - /// Use objc_setProperty and objc_getProperty. - GetSetProperty, - - /// Use objc_setProperty for the setter, but use expression - /// evaluation for the getter. - SetPropertyAndExpressionGet, - - /// Use objc_copyStruct. - CopyStruct, - - /// The 'expression' strategy is to emit normal assignment or - /// lvalue-to-rvalue expressions. - Expression - }; - - StrategyKind getKind() const { return StrategyKind(Kind); } - - bool hasStrongMember() const { return HasStrong; } - bool isAtomic() const { return IsAtomic; } - bool isCopy() const { return IsCopy; } - - CharUnits getIvarSize() const { return IvarSize; } - CharUnits getIvarAlignment() const { return IvarAlignment; } - - PropertyImplStrategy(CodeGenModule &CGM, - const ObjCPropertyImplDecl *propImpl); - - private: - unsigned Kind : 8; - unsigned IsAtomic : 1; - unsigned IsCopy : 1; - unsigned HasStrong : 1; - - CharUnits IvarSize; - CharUnits IvarAlignment; - }; -} - -/// Pick an implementation strategy for the given property synthesis. -PropertyImplStrategy::PropertyImplStrategy(CodeGenModule &CGM, - const ObjCPropertyImplDecl *propImpl) { - const ObjCPropertyDecl *prop = propImpl->getPropertyDecl(); - ObjCPropertyDecl::SetterKind setterKind = prop->getSetterKind(); - - IsCopy = (setterKind == ObjCPropertyDecl::Copy); - IsAtomic = prop->isAtomic(); - HasStrong = false; // doesn't matter here. - - // Evaluate the ivar's size and alignment. - ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); - QualType ivarType = ivar->getType(); - std::tie(IvarSize, IvarAlignment) = - CGM.getContext().getTypeInfoInChars(ivarType); - - // If we have a copy property, we always have to use getProperty/setProperty. - // TODO: we could actually use setProperty and an expression for non-atomics. - if (IsCopy) { - Kind = GetSetProperty; - return; - } - - // Handle retain. - if (setterKind == ObjCPropertyDecl::Retain) { - // In GC-only, there's nothing special that needs to be done. - if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) { - // fallthrough - - // In ARC, if the property is non-atomic, use expression emission, - // which translates to objc_storeStrong. This isn't required, but - // it's slightly nicer. - } else if (CGM.getLangOpts().ObjCAutoRefCount && !IsAtomic) { - // Using standard expression emission for the setter is only - // acceptable if the ivar is __strong, which won't be true if - // the property is annotated with __attribute__((NSObject)). - // TODO: falling all the way back to objc_setProperty here is - // just laziness, though; we could still use objc_storeStrong - // if we hacked it right. - if (ivarType.getObjCLifetime() == Qualifiers::OCL_Strong) - Kind = Expression; - else - Kind = SetPropertyAndExpressionGet; - return; - - // Otherwise, we need to at least use setProperty. However, if - // the property isn't atomic, we can use normal expression - // emission for the getter. - } else if (!IsAtomic) { - Kind = SetPropertyAndExpressionGet; - return; - - // Otherwise, we have to use both setProperty and getProperty. - } else { - Kind = GetSetProperty; - return; - } - } - - // If we're not atomic, just use expression accesses. - if (!IsAtomic) { - Kind = Expression; - return; - } - - // Properties on bitfield ivars need to be emitted using expression - // accesses even if they're nominally atomic. - if (ivar->isBitField()) { - Kind = Expression; - return; - } - - // GC-qualified or ARC-qualified ivars need to be emitted as - // expressions. This actually works out to being atomic anyway, - // except for ARC __strong, but that should trigger the above code. - if (ivarType.hasNonTrivialObjCLifetime() || - (CGM.getLangOpts().getGC() && - CGM.getContext().getObjCGCAttrKind(ivarType))) { - Kind = Expression; - return; - } - - // Compute whether the ivar has strong members. - if (CGM.getLangOpts().getGC()) - if (const RecordType *recordType = ivarType->getAs<RecordType>()) - HasStrong = recordType->getDecl()->hasObjectMember(); - - // We can never access structs with object members with a native - // access, because we need to use write barriers. This is what - // objc_copyStruct is for. - if (HasStrong) { - Kind = CopyStruct; - return; - } - - // Otherwise, this is target-dependent and based on the size and - // alignment of the ivar. - - // If the size of the ivar is not a power of two, give up. We don't - // want to get into the business of doing compare-and-swaps. - if (!IvarSize.isPowerOfTwo()) { - Kind = CopyStruct; - return; - } - - llvm::Triple::ArchType arch = - CGM.getTarget().getTriple().getArch(); - - // Most architectures require memory to fit within a single cache - // line, so the alignment has to be at least the size of the access. - // Otherwise we have to grab a lock. - if (IvarAlignment < IvarSize && !hasUnalignedAtomics(arch)) { - Kind = CopyStruct; - return; - } - - // If the ivar's size exceeds the architecture's maximum atomic - // access size, we have to use CopyStruct. - if (IvarSize > getMaxAtomicAccessSize(CGM, arch)) { - Kind = CopyStruct; - return; - } - - // Otherwise, we can use native loads and stores. - Kind = Native; -} - -/// Generate an Objective-C property getter function. -/// -/// The given Decl must be an ObjCImplementationDecl. \@synthesize -/// is illegal within a category. -void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, - const ObjCPropertyImplDecl *PID) { - llvm::Constant *AtomicHelperFn = - CodeGenFunction(CGM).GenerateObjCAtomicGetterCopyHelperFunction(PID); - const ObjCPropertyDecl *PD = PID->getPropertyDecl(); - ObjCMethodDecl *OMD = PD->getGetterMethodDecl(); - assert(OMD && "Invalid call to generate getter (empty method)"); - StartObjCMethod(OMD, IMP->getClassInterface()); - - generateObjCGetterBody(IMP, PID, OMD, AtomicHelperFn); - - FinishFunction(); -} - -static bool hasTrivialGetExpr(const ObjCPropertyImplDecl *propImpl) { - const Expr *getter = propImpl->getGetterCXXConstructor(); - if (!getter) return true; - - // Sema only makes only of these when the ivar has a C++ class type, - // so the form is pretty constrained. - - // If the property has a reference type, we might just be binding a - // reference, in which case the result will be a gl-value. We should - // treat this as a non-trivial operation. - if (getter->isGLValue()) - return false; - - // If we selected a trivial copy-constructor, we're okay. - if (const CXXConstructExpr *construct = dyn_cast<CXXConstructExpr>(getter)) - return (construct->getConstructor()->isTrivial()); - - // The constructor might require cleanups (in which case it's never - // trivial). - assert(isa<ExprWithCleanups>(getter)); - return false; -} - -/// emitCPPObjectAtomicGetterCall - Call the runtime function to -/// copy the ivar into the resturn slot. -static void emitCPPObjectAtomicGetterCall(CodeGenFunction &CGF, - llvm::Value *returnAddr, - ObjCIvarDecl *ivar, - llvm::Constant *AtomicHelperFn) { - // objc_copyCppObjectAtomic (&returnSlot, &CppObjectIvar, - // AtomicHelperFn); - CallArgList args; - - // The 1st argument is the return Slot. - args.add(RValue::get(returnAddr), CGF.getContext().VoidPtrTy); - - // The 2nd argument is the address of the ivar. - llvm::Value *ivarAddr = - CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), - CGF.LoadObjCSelf(), ivar, 0).getPointer(); - ivarAddr = CGF.Builder.CreateBitCast(ivarAddr, CGF.Int8PtrTy); - args.add(RValue::get(ivarAddr), CGF.getContext().VoidPtrTy); - - // Third argument is the helper function. - args.add(RValue::get(AtomicHelperFn), CGF.getContext().VoidPtrTy); - - llvm::Constant *copyCppAtomicObjectFn = - CGF.CGM.getObjCRuntime().GetCppAtomicObjectGetFunction(); - CGCallee callee = CGCallee::forDirect(copyCppAtomicObjectFn); - CGF.EmitCall( - CGF.getTypes().arrangeBuiltinFunctionCall(CGF.getContext().VoidTy, args), - callee, ReturnValueSlot(), args); -} - -void -CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, - const ObjCPropertyImplDecl *propImpl, - const ObjCMethodDecl *GetterMethodDecl, - llvm::Constant *AtomicHelperFn) { - // If there's a non-trivial 'get' expression, we just have to emit that. - if (!hasTrivialGetExpr(propImpl)) { - if (!AtomicHelperFn) { - auto *ret = ReturnStmt::Create(getContext(), SourceLocation(), - propImpl->getGetterCXXConstructor(), - /* NRVOCandidate=*/nullptr); - EmitReturnStmt(*ret); - } - else { - ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); - emitCPPObjectAtomicGetterCall(*this, ReturnValue.getPointer(), - ivar, AtomicHelperFn); - } - return; - } - - const ObjCPropertyDecl *prop = propImpl->getPropertyDecl(); - QualType propType = prop->getType(); - ObjCMethodDecl *getterMethod = prop->getGetterMethodDecl(); - - ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); - - // Pick an implementation strategy. - PropertyImplStrategy strategy(CGM, propImpl); - switch (strategy.getKind()) { - case PropertyImplStrategy::Native: { - // We don't need to do anything for a zero-size struct. - if (strategy.getIvarSize().isZero()) - return; - - LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), ivar, 0); - - // Currently, all atomic accesses have to be through integer - // types, so there's no point in trying to pick a prettier type. - uint64_t ivarSize = getContext().toBits(strategy.getIvarSize()); - llvm::Type *bitcastType = llvm::Type::getIntNTy(getLLVMContext(), ivarSize); - bitcastType = bitcastType->getPointerTo(); // addrspace 0 okay - - // Perform an atomic load. This does not impose ordering constraints. - Address ivarAddr = LV.getAddress(); - ivarAddr = Builder.CreateBitCast(ivarAddr, bitcastType); - llvm::LoadInst *load = Builder.CreateLoad(ivarAddr, "load"); - load->setAtomic(llvm::AtomicOrdering::Unordered); - - // Store that value into the return address. Doing this with a - // bitcast is likely to produce some pretty ugly IR, but it's not - // the *most* terrible thing in the world. - llvm::Type *retTy = ConvertType(getterMethod->getReturnType()); - uint64_t retTySize = CGM.getDataLayout().getTypeSizeInBits(retTy); - llvm::Value *ivarVal = load; - if (ivarSize > retTySize) { - llvm::Type *newTy = llvm::Type::getIntNTy(getLLVMContext(), retTySize); - ivarVal = Builder.CreateTrunc(load, newTy); - bitcastType = newTy->getPointerTo(); - } - Builder.CreateStore(ivarVal, - Builder.CreateBitCast(ReturnValue, bitcastType)); - - // Make sure we don't do an autorelease. - AutoreleaseResult = false; - return; - } - - case PropertyImplStrategy::GetSetProperty: { - llvm::Constant *getPropertyFn = - CGM.getObjCRuntime().GetPropertyGetFunction(); - if (!getPropertyFn) { - CGM.ErrorUnsupported(propImpl, "Obj-C getter requiring atomic copy"); - return; - } - CGCallee callee = CGCallee::forDirect(getPropertyFn); - - // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true). - // FIXME: Can't this be simpler? This might even be worse than the - // corresponding gcc code. - llvm::Value *cmd = - Builder.CreateLoad(GetAddrOfLocalVar(getterMethod->getCmdDecl()), "cmd"); - llvm::Value *self = Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy); - llvm::Value *ivarOffset = - EmitIvarOffset(classImpl->getClassInterface(), ivar); - - CallArgList args; - args.add(RValue::get(self), getContext().getObjCIdType()); - args.add(RValue::get(cmd), getContext().getObjCSelType()); - args.add(RValue::get(ivarOffset), getContext().getPointerDiffType()); - args.add(RValue::get(Builder.getInt1(strategy.isAtomic())), - getContext().BoolTy); - - // FIXME: We shouldn't need to get the function info here, the - // runtime already should have computed it to build the function. - llvm::Instruction *CallInstruction; - RValue RV = EmitCall( - getTypes().arrangeBuiltinFunctionCall(propType, args), - callee, ReturnValueSlot(), args, &CallInstruction); - if (llvm::CallInst *call = dyn_cast<llvm::CallInst>(CallInstruction)) - call->setTailCall(); - - // We need to fix the type here. Ivars with copy & retain are - // always objects so we don't need to worry about complex or - // aggregates. - RV = RValue::get(Builder.CreateBitCast( - RV.getScalarVal(), - getTypes().ConvertType(getterMethod->getReturnType()))); - - EmitReturnOfRValue(RV, propType); - - // objc_getProperty does an autorelease, so we should suppress ours. - AutoreleaseResult = false; - - return; - } - - case PropertyImplStrategy::CopyStruct: - emitStructGetterCall(*this, ivar, strategy.isAtomic(), - strategy.hasStrongMember()); - return; - - case PropertyImplStrategy::Expression: - case PropertyImplStrategy::SetPropertyAndExpressionGet: { - LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), ivar, 0); - - QualType ivarType = ivar->getType(); - switch (getEvaluationKind(ivarType)) { - case TEK_Complex: { - ComplexPairTy pair = EmitLoadOfComplex(LV, SourceLocation()); - EmitStoreOfComplex(pair, MakeAddrLValue(ReturnValue, ivarType), - /*init*/ true); - return; - } - case TEK_Aggregate: { - // The return value slot is guaranteed to not be aliased, but - // that's not necessarily the same as "on the stack", so - // we still potentially need objc_memmove_collectable. - EmitAggregateCopy(/* Dest= */ MakeAddrLValue(ReturnValue, ivarType), - /* Src= */ LV, ivarType, overlapForReturnValue()); - return; - } - case TEK_Scalar: { - llvm::Value *value; - if (propType->isReferenceType()) { - value = LV.getAddress().getPointer(); - } else { - // We want to load and autoreleaseReturnValue ARC __weak ivars. - if (LV.getQuals().getObjCLifetime() == Qualifiers::OCL_Weak) { - if (getLangOpts().ObjCAutoRefCount) { - value = emitARCRetainLoadOfScalar(*this, LV, ivarType); - } else { - value = EmitARCLoadWeak(LV.getAddress()); - } - - // Otherwise we want to do a simple load, suppressing the - // final autorelease. - } else { - value = EmitLoadOfLValue(LV, SourceLocation()).getScalarVal(); - AutoreleaseResult = false; - } - - value = Builder.CreateBitCast( - value, ConvertType(GetterMethodDecl->getReturnType())); - } - - EmitReturnOfRValue(RValue::get(value), propType); - return; - } - } - llvm_unreachable("bad evaluation kind"); - } - - } - llvm_unreachable("bad @property implementation strategy!"); -} - -/// emitStructSetterCall - Call the runtime function to store the value -/// from the first formal parameter into the given ivar. -static void emitStructSetterCall(CodeGenFunction &CGF, ObjCMethodDecl *OMD, - ObjCIvarDecl *ivar) { - // objc_copyStruct (&structIvar, &Arg, - // sizeof (struct something), true, false); - CallArgList args; - - // The first argument is the address of the ivar. - llvm::Value *ivarAddr = CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), - CGF.LoadObjCSelf(), ivar, 0) - .getPointer(); - ivarAddr = CGF.Builder.CreateBitCast(ivarAddr, CGF.Int8PtrTy); - args.add(RValue::get(ivarAddr), CGF.getContext().VoidPtrTy); - - // The second argument is the address of the parameter variable. - ParmVarDecl *argVar = *OMD->param_begin(); - DeclRefExpr argRef(CGF.getContext(), argVar, false, - argVar->getType().getNonReferenceType(), VK_LValue, - SourceLocation()); - llvm::Value *argAddr = CGF.EmitLValue(&argRef).getPointer(); - argAddr = CGF.Builder.CreateBitCast(argAddr, CGF.Int8PtrTy); - args.add(RValue::get(argAddr), CGF.getContext().VoidPtrTy); - - // The third argument is the sizeof the type. - llvm::Value *size = - CGF.CGM.getSize(CGF.getContext().getTypeSizeInChars(ivar->getType())); - args.add(RValue::get(size), CGF.getContext().getSizeType()); - - // The fourth argument is the 'isAtomic' flag. - args.add(RValue::get(CGF.Builder.getTrue()), CGF.getContext().BoolTy); - - // The fifth argument is the 'hasStrong' flag. - // FIXME: should this really always be false? - args.add(RValue::get(CGF.Builder.getFalse()), CGF.getContext().BoolTy); - - llvm::Constant *fn = CGF.CGM.getObjCRuntime().GetSetStructFunction(); - CGCallee callee = CGCallee::forDirect(fn); - CGF.EmitCall( - CGF.getTypes().arrangeBuiltinFunctionCall(CGF.getContext().VoidTy, args), - callee, ReturnValueSlot(), args); -} - -/// emitCPPObjectAtomicSetterCall - Call the runtime function to store -/// the value from the first formal parameter into the given ivar, using -/// the Cpp API for atomic Cpp objects with non-trivial copy assignment. -static void emitCPPObjectAtomicSetterCall(CodeGenFunction &CGF, - ObjCMethodDecl *OMD, - ObjCIvarDecl *ivar, - llvm::Constant *AtomicHelperFn) { - // objc_copyCppObjectAtomic (&CppObjectIvar, &Arg, - // AtomicHelperFn); - CallArgList args; - - // The first argument is the address of the ivar. - llvm::Value *ivarAddr = - CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), - CGF.LoadObjCSelf(), ivar, 0).getPointer(); - ivarAddr = CGF.Builder.CreateBitCast(ivarAddr, CGF.Int8PtrTy); - args.add(RValue::get(ivarAddr), CGF.getContext().VoidPtrTy); - - // The second argument is the address of the parameter variable. - ParmVarDecl *argVar = *OMD->param_begin(); - DeclRefExpr argRef(CGF.getContext(), argVar, false, - argVar->getType().getNonReferenceType(), VK_LValue, - SourceLocation()); - llvm::Value *argAddr = CGF.EmitLValue(&argRef).getPointer(); - argAddr = CGF.Builder.CreateBitCast(argAddr, CGF.Int8PtrTy); - args.add(RValue::get(argAddr), CGF.getContext().VoidPtrTy); - - // Third argument is the helper function. - args.add(RValue::get(AtomicHelperFn), CGF.getContext().VoidPtrTy); - - llvm::Constant *fn = - CGF.CGM.getObjCRuntime().GetCppAtomicObjectSetFunction(); - CGCallee callee = CGCallee::forDirect(fn); - CGF.EmitCall( - CGF.getTypes().arrangeBuiltinFunctionCall(CGF.getContext().VoidTy, args), - callee, ReturnValueSlot(), args); -} - - -static bool hasTrivialSetExpr(const ObjCPropertyImplDecl *PID) { - Expr *setter = PID->getSetterCXXAssignment(); - if (!setter) return true; - - // Sema only makes only of these when the ivar has a C++ class type, - // so the form is pretty constrained. - - // An operator call is trivial if the function it calls is trivial. - // This also implies that there's nothing non-trivial going on with - // the arguments, because operator= can only be trivial if it's a - // synthesized assignment operator and therefore both parameters are - // references. - if (CallExpr *call = dyn_cast<CallExpr>(setter)) { - if (const FunctionDecl *callee - = dyn_cast_or_null<FunctionDecl>(call->getCalleeDecl())) - if (callee->isTrivial()) - return true; - return false; - } - - assert(isa<ExprWithCleanups>(setter)); - return false; -} - -static bool UseOptimizedSetter(CodeGenModule &CGM) { - if (CGM.getLangOpts().getGC() != LangOptions::NonGC) - return false; - return CGM.getLangOpts().ObjCRuntime.hasOptimizedSetter(); -} - -void -CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, - const ObjCPropertyImplDecl *propImpl, - llvm::Constant *AtomicHelperFn) { - const ObjCPropertyDecl *prop = propImpl->getPropertyDecl(); - ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); - ObjCMethodDecl *setterMethod = prop->getSetterMethodDecl(); - - // Just use the setter expression if Sema gave us one and it's - // non-trivial. - if (!hasTrivialSetExpr(propImpl)) { - if (!AtomicHelperFn) - // If non-atomic, assignment is called directly. - EmitStmt(propImpl->getSetterCXXAssignment()); - else - // If atomic, assignment is called via a locking api. - emitCPPObjectAtomicSetterCall(*this, setterMethod, ivar, - AtomicHelperFn); - return; - } - - PropertyImplStrategy strategy(CGM, propImpl); - switch (strategy.getKind()) { - case PropertyImplStrategy::Native: { - // We don't need to do anything for a zero-size struct. - if (strategy.getIvarSize().isZero()) - return; - - Address argAddr = GetAddrOfLocalVar(*setterMethod->param_begin()); - - LValue ivarLValue = - EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), ivar, /*quals*/ 0); - Address ivarAddr = ivarLValue.getAddress(); - - // Currently, all atomic accesses have to be through integer - // types, so there's no point in trying to pick a prettier type. - llvm::Type *bitcastType = - llvm::Type::getIntNTy(getLLVMContext(), - getContext().toBits(strategy.getIvarSize())); - - // Cast both arguments to the chosen operation type. - argAddr = Builder.CreateElementBitCast(argAddr, bitcastType); - ivarAddr = Builder.CreateElementBitCast(ivarAddr, bitcastType); - - // This bitcast load is likely to cause some nasty IR. - llvm::Value *load = Builder.CreateLoad(argAddr); - - // Perform an atomic store. There are no memory ordering requirements. - llvm::StoreInst *store = Builder.CreateStore(load, ivarAddr); - store->setAtomic(llvm::AtomicOrdering::Unordered); - return; - } - - case PropertyImplStrategy::GetSetProperty: - case PropertyImplStrategy::SetPropertyAndExpressionGet: { - - llvm::Constant *setOptimizedPropertyFn = nullptr; - llvm::Constant *setPropertyFn = nullptr; - if (UseOptimizedSetter(CGM)) { - // 10.8 and iOS 6.0 code and GC is off - setOptimizedPropertyFn = - CGM.getObjCRuntime() - .GetOptimizedPropertySetFunction(strategy.isAtomic(), - strategy.isCopy()); - if (!setOptimizedPropertyFn) { - CGM.ErrorUnsupported(propImpl, "Obj-C optimized setter - NYI"); - return; - } - } - else { - setPropertyFn = CGM.getObjCRuntime().GetPropertySetFunction(); - if (!setPropertyFn) { - CGM.ErrorUnsupported(propImpl, "Obj-C setter requiring atomic copy"); - return; - } - } - - // Emit objc_setProperty((id) self, _cmd, offset, arg, - // <is-atomic>, <is-copy>). - llvm::Value *cmd = - Builder.CreateLoad(GetAddrOfLocalVar(setterMethod->getCmdDecl())); - llvm::Value *self = - Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy); - llvm::Value *ivarOffset = - EmitIvarOffset(classImpl->getClassInterface(), ivar); - Address argAddr = GetAddrOfLocalVar(*setterMethod->param_begin()); - llvm::Value *arg = Builder.CreateLoad(argAddr, "arg"); - arg = Builder.CreateBitCast(arg, VoidPtrTy); - - CallArgList args; - args.add(RValue::get(self), getContext().getObjCIdType()); - args.add(RValue::get(cmd), getContext().getObjCSelType()); - if (setOptimizedPropertyFn) { - args.add(RValue::get(arg), getContext().getObjCIdType()); - args.add(RValue::get(ivarOffset), getContext().getPointerDiffType()); - CGCallee callee = CGCallee::forDirect(setOptimizedPropertyFn); - EmitCall(getTypes().arrangeBuiltinFunctionCall(getContext().VoidTy, args), - callee, ReturnValueSlot(), args); - } else { - args.add(RValue::get(ivarOffset), getContext().getPointerDiffType()); - args.add(RValue::get(arg), getContext().getObjCIdType()); - args.add(RValue::get(Builder.getInt1(strategy.isAtomic())), - getContext().BoolTy); - args.add(RValue::get(Builder.getInt1(strategy.isCopy())), - getContext().BoolTy); - // FIXME: We shouldn't need to get the function info here, the runtime - // already should have computed it to build the function. - CGCallee callee = CGCallee::forDirect(setPropertyFn); - EmitCall(getTypes().arrangeBuiltinFunctionCall(getContext().VoidTy, args), - callee, ReturnValueSlot(), args); - } - - return; - } - - case PropertyImplStrategy::CopyStruct: - emitStructSetterCall(*this, setterMethod, ivar); - return; - - case PropertyImplStrategy::Expression: - break; - } - - // Otherwise, fake up some ASTs and emit a normal assignment. - ValueDecl *selfDecl = setterMethod->getSelfDecl(); - DeclRefExpr self(getContext(), selfDecl, false, selfDecl->getType(), - VK_LValue, SourceLocation()); - ImplicitCastExpr selfLoad(ImplicitCastExpr::OnStack, - selfDecl->getType(), CK_LValueToRValue, &self, - VK_RValue); - ObjCIvarRefExpr ivarRef(ivar, ivar->getType().getNonReferenceType(), - SourceLocation(), SourceLocation(), - &selfLoad, true, true); - - ParmVarDecl *argDecl = *setterMethod->param_begin(); - QualType argType = argDecl->getType().getNonReferenceType(); - DeclRefExpr arg(getContext(), argDecl, false, argType, VK_LValue, - SourceLocation()); - ImplicitCastExpr argLoad(ImplicitCastExpr::OnStack, - argType.getUnqualifiedType(), CK_LValueToRValue, - &arg, VK_RValue); - - // The property type can differ from the ivar type in some situations with - // Objective-C pointer types, we can always bit cast the RHS in these cases. - // The following absurdity is just to ensure well-formed IR. - CastKind argCK = CK_NoOp; - if (ivarRef.getType()->isObjCObjectPointerType()) { - if (argLoad.getType()->isObjCObjectPointerType()) - argCK = CK_BitCast; - else if (argLoad.getType()->isBlockPointerType()) - argCK = CK_BlockPointerToObjCPointerCast; - else - argCK = CK_CPointerToObjCPointerCast; - } else if (ivarRef.getType()->isBlockPointerType()) { - if (argLoad.getType()->isBlockPointerType()) - argCK = CK_BitCast; - else - argCK = CK_AnyPointerToBlockPointerCast; - } else if (ivarRef.getType()->isPointerType()) { - argCK = CK_BitCast; - } - ImplicitCastExpr argCast(ImplicitCastExpr::OnStack, - ivarRef.getType(), argCK, &argLoad, - VK_RValue); - Expr *finalArg = &argLoad; - if (!getContext().hasSameUnqualifiedType(ivarRef.getType(), - argLoad.getType())) - finalArg = &argCast; - - - BinaryOperator assign(&ivarRef, finalArg, BO_Assign, - ivarRef.getType(), VK_RValue, OK_Ordinary, - SourceLocation(), FPOptions()); - EmitStmt(&assign); -} - -/// Generate an Objective-C property setter function. -/// -/// The given Decl must be an ObjCImplementationDecl. \@synthesize -/// is illegal within a category. -void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, - const ObjCPropertyImplDecl *PID) { - llvm::Constant *AtomicHelperFn = - CodeGenFunction(CGM).GenerateObjCAtomicSetterCopyHelperFunction(PID); - const ObjCPropertyDecl *PD = PID->getPropertyDecl(); - ObjCMethodDecl *OMD = PD->getSetterMethodDecl(); - assert(OMD && "Invalid call to generate setter (empty method)"); - StartObjCMethod(OMD, IMP->getClassInterface()); - - generateObjCSetterBody(IMP, PID, AtomicHelperFn); - - FinishFunction(); -} - -namespace { - struct DestroyIvar final : EHScopeStack::Cleanup { - private: - llvm::Value *addr; - const ObjCIvarDecl *ivar; - CodeGenFunction::Destroyer *destroyer; - bool useEHCleanupForArray; - public: - DestroyIvar(llvm::Value *addr, const ObjCIvarDecl *ivar, - CodeGenFunction::Destroyer *destroyer, - bool useEHCleanupForArray) - : addr(addr), ivar(ivar), destroyer(destroyer), - useEHCleanupForArray(useEHCleanupForArray) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - LValue lvalue - = CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), addr, ivar, /*CVR*/ 0); - CGF.emitDestroy(lvalue.getAddress(), ivar->getType(), destroyer, - flags.isForNormalCleanup() && useEHCleanupForArray); - } - }; -} - -/// Like CodeGenFunction::destroyARCStrong, but do it with a call. -static void destroyARCStrongWithStore(CodeGenFunction &CGF, - Address addr, - QualType type) { - llvm::Value *null = getNullForVariable(addr); - CGF.EmitARCStoreStrongCall(addr, null, /*ignored*/ true); -} - -static void emitCXXDestructMethod(CodeGenFunction &CGF, - ObjCImplementationDecl *impl) { - CodeGenFunction::RunCleanupsScope scope(CGF); - - llvm::Value *self = CGF.LoadObjCSelf(); - - const ObjCInterfaceDecl *iface = impl->getClassInterface(); - for (const ObjCIvarDecl *ivar = iface->all_declared_ivar_begin(); - ivar; ivar = ivar->getNextIvar()) { - QualType type = ivar->getType(); - - // Check whether the ivar is a destructible type. - QualType::DestructionKind dtorKind = type.isDestructedType(); - if (!dtorKind) continue; - - CodeGenFunction::Destroyer *destroyer = nullptr; - - // Use a call to objc_storeStrong to destroy strong ivars, for the - // general benefit of the tools. - if (dtorKind == QualType::DK_objc_strong_lifetime) { - destroyer = destroyARCStrongWithStore; - - // Otherwise use the default for the destruction kind. - } else { - destroyer = CGF.getDestroyer(dtorKind); - } - - CleanupKind cleanupKind = CGF.getCleanupKind(dtorKind); - - CGF.EHStack.pushCleanup<DestroyIvar>(cleanupKind, self, ivar, destroyer, - cleanupKind & EHCleanup); - } - - assert(scope.requiresCleanups() && "nothing to do in .cxx_destruct?"); -} - -void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP, - ObjCMethodDecl *MD, - bool ctor) { - MD->createImplicitParams(CGM.getContext(), IMP->getClassInterface()); - StartObjCMethod(MD, IMP->getClassInterface()); - - // Emit .cxx_construct. - if (ctor) { - // Suppress the final autorelease in ARC. - AutoreleaseResult = false; - - for (const auto *IvarInit : IMP->inits()) { - FieldDecl *Field = IvarInit->getAnyMember(); - ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(Field); - LValue LV = EmitLValueForIvar(TypeOfSelfObject(), - LoadObjCSelf(), Ivar, 0); - EmitAggExpr(IvarInit->getInit(), - AggValueSlot::forLValue(LV, AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - AggValueSlot::DoesNotOverlap)); - } - // constructor returns 'self'. - CodeGenTypes &Types = CGM.getTypes(); - QualType IdTy(CGM.getContext().getObjCIdType()); - llvm::Value *SelfAsId = - Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); - EmitReturnOfRValue(RValue::get(SelfAsId), IdTy); - - // Emit .cxx_destruct. - } else { - emitCXXDestructMethod(*this, IMP); - } - FinishFunction(); -} - -llvm::Value *CodeGenFunction::LoadObjCSelf() { - VarDecl *Self = cast<ObjCMethodDecl>(CurFuncDecl)->getSelfDecl(); - DeclRefExpr DRE(getContext(), Self, - /*is enclosing local*/ (CurFuncDecl != CurCodeDecl), - Self->getType(), VK_LValue, SourceLocation()); - return EmitLoadOfScalar(EmitDeclRefLValue(&DRE), SourceLocation()); -} - -QualType CodeGenFunction::TypeOfSelfObject() { - const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); - ImplicitParamDecl *selfDecl = OMD->getSelfDecl(); - const ObjCObjectPointerType *PTy = cast<ObjCObjectPointerType>( - getContext().getCanonicalType(selfDecl->getType())); - return PTy->getPointeeType(); -} - -void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ - llvm::Constant *EnumerationMutationFnPtr = - CGM.getObjCRuntime().EnumerationMutationFunction(); - if (!EnumerationMutationFnPtr) { - CGM.ErrorUnsupported(&S, "Obj-C fast enumeration for this runtime"); - return; - } - CGCallee EnumerationMutationFn = - CGCallee::forDirect(EnumerationMutationFnPtr); - - CGDebugInfo *DI = getDebugInfo(); - if (DI) - DI->EmitLexicalBlockStart(Builder, S.getSourceRange().getBegin()); - - RunCleanupsScope ForScope(*this); - - // The local variable comes into scope immediately. - AutoVarEmission variable = AutoVarEmission::invalid(); - if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) - variable = EmitAutoVarAlloca(*cast<VarDecl>(SD->getSingleDecl())); - - JumpDest LoopEnd = getJumpDestInCurrentScope("forcoll.end"); - - // Fast enumeration state. - QualType StateTy = CGM.getObjCFastEnumerationStateType(); - Address StatePtr = CreateMemTemp(StateTy, "state.ptr"); - EmitNullInitialization(StatePtr, StateTy); - - // Number of elements in the items array. - static const unsigned NumItems = 16; - - // Fetch the countByEnumeratingWithState:objects:count: selector. - IdentifierInfo *II[] = { - &CGM.getContext().Idents.get("countByEnumeratingWithState"), - &CGM.getContext().Idents.get("objects"), - &CGM.getContext().Idents.get("count") - }; - Selector FastEnumSel = - CGM.getContext().Selectors.getSelector(llvm::array_lengthof(II), &II[0]); - - QualType ItemsTy = - getContext().getConstantArrayType(getContext().getObjCIdType(), - llvm::APInt(32, NumItems), - ArrayType::Normal, 0); - Address ItemsPtr = CreateMemTemp(ItemsTy, "items.ptr"); - - // Emit the collection pointer. In ARC, we do a retain. - llvm::Value *Collection; - if (getLangOpts().ObjCAutoRefCount) { - Collection = EmitARCRetainScalarExpr(S.getCollection()); - - // Enter a cleanup to do the release. - EmitObjCConsumeObject(S.getCollection()->getType(), Collection); - } else { - Collection = EmitScalarExpr(S.getCollection()); - } - - // The 'continue' label needs to appear within the cleanup for the - // collection object. - JumpDest AfterBody = getJumpDestInCurrentScope("forcoll.next"); - - // Send it our message: - CallArgList Args; - - // The first argument is a temporary of the enumeration-state type. - Args.add(RValue::get(StatePtr.getPointer()), - getContext().getPointerType(StateTy)); - - // The second argument is a temporary array with space for NumItems - // pointers. We'll actually be loading elements from the array - // pointer written into the control state; this buffer is so that - // collections that *aren't* backed by arrays can still queue up - // batches of elements. - Args.add(RValue::get(ItemsPtr.getPointer()), - getContext().getPointerType(ItemsTy)); - - // The third argument is the capacity of that temporary array. - llvm::Type *NSUIntegerTy = ConvertType(getContext().getNSUIntegerType()); - llvm::Constant *Count = llvm::ConstantInt::get(NSUIntegerTy, NumItems); - Args.add(RValue::get(Count), getContext().getNSUIntegerType()); - - // Start the enumeration. - RValue CountRV = - CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(), - getContext().getNSUIntegerType(), - FastEnumSel, Collection, Args); - - // The initial number of objects that were returned in the buffer. - llvm::Value *initialBufferLimit = CountRV.getScalarVal(); - - llvm::BasicBlock *EmptyBB = createBasicBlock("forcoll.empty"); - llvm::BasicBlock *LoopInitBB = createBasicBlock("forcoll.loopinit"); - - llvm::Value *zero = llvm::Constant::getNullValue(NSUIntegerTy); - - // If the limit pointer was zero to begin with, the collection is - // empty; skip all this. Set the branch weight assuming this has the same - // probability of exiting the loop as any other loop exit. - uint64_t EntryCount = getCurrentProfileCount(); - Builder.CreateCondBr( - Builder.CreateICmpEQ(initialBufferLimit, zero, "iszero"), EmptyBB, - LoopInitBB, - createProfileWeights(EntryCount, getProfileCount(S.getBody()))); - - // Otherwise, initialize the loop. - EmitBlock(LoopInitBB); - - // Save the initial mutations value. This is the value at an - // address that was written into the state object by - // countByEnumeratingWithState:objects:count:. - Address StateMutationsPtrPtr = Builder.CreateStructGEP( - StatePtr, 2, 2 * getPointerSize(), "mutationsptr.ptr"); - llvm::Value *StateMutationsPtr - = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr"); - - llvm::Value *initialMutations = - Builder.CreateAlignedLoad(StateMutationsPtr, getPointerAlign(), - "forcoll.initial-mutations"); - - // Start looping. This is the point we return to whenever we have a - // fresh, non-empty batch of objects. - llvm::BasicBlock *LoopBodyBB = createBasicBlock("forcoll.loopbody"); - EmitBlock(LoopBodyBB); - - // The current index into the buffer. - llvm::PHINode *index = Builder.CreatePHI(NSUIntegerTy, 3, "forcoll.index"); - index->addIncoming(zero, LoopInitBB); - - // The current buffer size. - llvm::PHINode *count = Builder.CreatePHI(NSUIntegerTy, 3, "forcoll.count"); - count->addIncoming(initialBufferLimit, LoopInitBB); - - incrementProfileCounter(&S); - - // Check whether the mutations value has changed from where it was - // at start. StateMutationsPtr should actually be invariant between - // refreshes. - StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr"); - llvm::Value *currentMutations - = Builder.CreateAlignedLoad(StateMutationsPtr, getPointerAlign(), - "statemutations"); - - llvm::BasicBlock *WasMutatedBB = createBasicBlock("forcoll.mutated"); - llvm::BasicBlock *WasNotMutatedBB = createBasicBlock("forcoll.notmutated"); - - Builder.CreateCondBr(Builder.CreateICmpEQ(currentMutations, initialMutations), - WasNotMutatedBB, WasMutatedBB); - - // If so, call the enumeration-mutation function. - EmitBlock(WasMutatedBB); - llvm::Value *V = - Builder.CreateBitCast(Collection, - ConvertType(getContext().getObjCIdType())); - CallArgList Args2; - Args2.add(RValue::get(V), getContext().getObjCIdType()); - // FIXME: We shouldn't need to get the function info here, the runtime already - // should have computed it to build the function. - EmitCall( - CGM.getTypes().arrangeBuiltinFunctionCall(getContext().VoidTy, Args2), - EnumerationMutationFn, ReturnValueSlot(), Args2); - - // Otherwise, or if the mutation function returns, just continue. - EmitBlock(WasNotMutatedBB); - - // Initialize the element variable. - RunCleanupsScope elementVariableScope(*this); - bool elementIsVariable; - LValue elementLValue; - QualType elementType; - if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) { - // Initialize the variable, in case it's a __block variable or something. - EmitAutoVarInit(variable); - - const VarDecl *D = cast<VarDecl>(SD->getSingleDecl()); - DeclRefExpr tempDRE(getContext(), const_cast<VarDecl *>(D), false, - D->getType(), VK_LValue, SourceLocation()); - elementLValue = EmitLValue(&tempDRE); - elementType = D->getType(); - elementIsVariable = true; - - if (D->isARCPseudoStrong()) - elementLValue.getQuals().setObjCLifetime(Qualifiers::OCL_ExplicitNone); - } else { - elementLValue = LValue(); // suppress warning - elementType = cast<Expr>(S.getElement())->getType(); - elementIsVariable = false; - } - llvm::Type *convertedElementType = ConvertType(elementType); - - // Fetch the buffer out of the enumeration state. - // TODO: this pointer should actually be invariant between - // refreshes, which would help us do certain loop optimizations. - Address StateItemsPtr = Builder.CreateStructGEP( - StatePtr, 1, getPointerSize(), "stateitems.ptr"); - llvm::Value *EnumStateItems = - Builder.CreateLoad(StateItemsPtr, "stateitems"); - - // Fetch the value at the current index from the buffer. - llvm::Value *CurrentItemPtr = - Builder.CreateGEP(EnumStateItems, index, "currentitem.ptr"); - llvm::Value *CurrentItem = - Builder.CreateAlignedLoad(CurrentItemPtr, getPointerAlign()); - - // Cast that value to the right type. - CurrentItem = Builder.CreateBitCast(CurrentItem, convertedElementType, - "currentitem"); - - // Make sure we have an l-value. Yes, this gets evaluated every - // time through the loop. - if (!elementIsVariable) { - elementLValue = EmitLValue(cast<Expr>(S.getElement())); - EmitStoreThroughLValue(RValue::get(CurrentItem), elementLValue); - } else { - EmitStoreThroughLValue(RValue::get(CurrentItem), elementLValue, - /*isInit*/ true); - } - - // If we do have an element variable, this assignment is the end of - // its initialization. - if (elementIsVariable) - EmitAutoVarCleanups(variable); - - // Perform the loop body, setting up break and continue labels. - BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody)); - { - RunCleanupsScope Scope(*this); - EmitStmt(S.getBody()); - } - BreakContinueStack.pop_back(); - - // Destroy the element variable now. - elementVariableScope.ForceCleanup(); - - // Check whether there are more elements. - EmitBlock(AfterBody.getBlock()); - - llvm::BasicBlock *FetchMoreBB = createBasicBlock("forcoll.refetch"); - - // First we check in the local buffer. - llvm::Value *indexPlusOne = - Builder.CreateAdd(index, llvm::ConstantInt::get(NSUIntegerTy, 1)); - - // If we haven't overrun the buffer yet, we can continue. - // Set the branch weights based on the simplifying assumption that this is - // like a while-loop, i.e., ignoring that the false branch fetches more - // elements and then returns to the loop. - Builder.CreateCondBr( - Builder.CreateICmpULT(indexPlusOne, count), LoopBodyBB, FetchMoreBB, - createProfileWeights(getProfileCount(S.getBody()), EntryCount)); - - index->addIncoming(indexPlusOne, AfterBody.getBlock()); - count->addIncoming(count, AfterBody.getBlock()); - - // Otherwise, we have to fetch more elements. - EmitBlock(FetchMoreBB); - - CountRV = - CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(), - getContext().getNSUIntegerType(), - FastEnumSel, Collection, Args); - - // If we got a zero count, we're done. - llvm::Value *refetchCount = CountRV.getScalarVal(); - - // (note that the message send might split FetchMoreBB) - index->addIncoming(zero, Builder.GetInsertBlock()); - count->addIncoming(refetchCount, Builder.GetInsertBlock()); - - Builder.CreateCondBr(Builder.CreateICmpEQ(refetchCount, zero), - EmptyBB, LoopBodyBB); - - // No more elements. - EmitBlock(EmptyBB); - - if (!elementIsVariable) { - // If the element was not a declaration, set it to be null. - - llvm::Value *null = llvm::Constant::getNullValue(convertedElementType); - elementLValue = EmitLValue(cast<Expr>(S.getElement())); - EmitStoreThroughLValue(RValue::get(null), elementLValue); - } - - if (DI) - DI->EmitLexicalBlockEnd(Builder, S.getSourceRange().getEnd()); - - ForScope.ForceCleanup(); - EmitBlock(LoopEnd.getBlock()); -} - -void CodeGenFunction::EmitObjCAtTryStmt(const ObjCAtTryStmt &S) { - CGM.getObjCRuntime().EmitTryStmt(*this, S); -} - -void CodeGenFunction::EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S) { - CGM.getObjCRuntime().EmitThrowStmt(*this, S); -} - -void CodeGenFunction::EmitObjCAtSynchronizedStmt( - const ObjCAtSynchronizedStmt &S) { - CGM.getObjCRuntime().EmitSynchronizedStmt(*this, S); -} - -namespace { - struct CallObjCRelease final : EHScopeStack::Cleanup { - CallObjCRelease(llvm::Value *object) : object(object) {} - llvm::Value *object; - - void Emit(CodeGenFunction &CGF, Flags flags) override { - // Releases at the end of the full-expression are imprecise. - CGF.EmitARCRelease(object, ARCImpreciseLifetime); - } - }; -} - -/// Produce the code for a CK_ARCConsumeObject. Does a primitive -/// release at the end of the full-expression. -llvm::Value *CodeGenFunction::EmitObjCConsumeObject(QualType type, - llvm::Value *object) { - // If we're in a conditional branch, we need to make the cleanup - // conditional. - pushFullExprCleanup<CallObjCRelease>(getARCCleanupKind(), object); - return object; -} - -llvm::Value *CodeGenFunction::EmitObjCExtendObjectLifetime(QualType type, - llvm::Value *value) { - return EmitARCRetainAutorelease(type, value); -} - -/// Given a number of pointers, inform the optimizer that they're -/// being intrinsically used up until this point in the program. -void CodeGenFunction::EmitARCIntrinsicUse(ArrayRef<llvm::Value*> values) { - llvm::Constant *&fn = CGM.getObjCEntrypoints().clang_arc_use; - if (!fn) - fn = CGM.getIntrinsic(llvm::Intrinsic::objc_clang_arc_use); - - // This isn't really a "runtime" function, but as an intrinsic it - // doesn't really matter as long as we align things up. - EmitNounwindRuntimeCall(fn, values); -} - -static void setARCRuntimeFunctionLinkage(CodeGenModule &CGM, - llvm::Constant *RTF) { - if (auto *F = dyn_cast<llvm::Function>(RTF)) { - // If the target runtime doesn't naturally support ARC, emit weak - // references to the runtime support library. We don't really - // permit this to fail, but we need a particular relocation style. - if (!CGM.getLangOpts().ObjCRuntime.hasNativeARC() && - !CGM.getTriple().isOSBinFormatCOFF()) { - F->setLinkage(llvm::Function::ExternalWeakLinkage); - } - } -} - -/// Perform an operation having the signature -/// i8* (i8*) -/// where a null input causes a no-op and returns null. -static llvm::Value *emitARCValueOperation(CodeGenFunction &CGF, - llvm::Value *value, - llvm::Type *returnType, - llvm::Constant *&fn, - llvm::Intrinsic::ID IntID, - bool isTailCall = false) { - if (isa<llvm::ConstantPointerNull>(value)) - return value; - - if (!fn) { - fn = CGF.CGM.getIntrinsic(IntID); - setARCRuntimeFunctionLinkage(CGF.CGM, fn); - } - - // Cast the argument to 'id'. - llvm::Type *origType = returnType ? returnType : value->getType(); - value = CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy); - - // Call the function. - llvm::CallInst *call = CGF.EmitNounwindRuntimeCall(fn, value); - if (isTailCall) - call->setTailCall(); - - // Cast the result back to the original type. - return CGF.Builder.CreateBitCast(call, origType); -} - -/// Perform an operation having the following signature: -/// i8* (i8**) -static llvm::Value *emitARCLoadOperation(CodeGenFunction &CGF, - Address addr, - llvm::Constant *&fn, - llvm::Intrinsic::ID IntID) { - if (!fn) { - fn = CGF.CGM.getIntrinsic(IntID); - setARCRuntimeFunctionLinkage(CGF.CGM, fn); - } - - // Cast the argument to 'id*'. - llvm::Type *origType = addr.getElementType(); - addr = CGF.Builder.CreateBitCast(addr, CGF.Int8PtrPtrTy); - - // Call the function. - llvm::Value *result = CGF.EmitNounwindRuntimeCall(fn, addr.getPointer()); - - // Cast the result back to a dereference of the original type. - if (origType != CGF.Int8PtrTy) - result = CGF.Builder.CreateBitCast(result, origType); - - return result; -} - -/// Perform an operation having the following signature: -/// i8* (i8**, i8*) -static llvm::Value *emitARCStoreOperation(CodeGenFunction &CGF, - Address addr, - llvm::Value *value, - llvm::Constant *&fn, - llvm::Intrinsic::ID IntID, - bool ignored) { - assert(addr.getElementType() == value->getType()); - - if (!fn) { - fn = CGF.CGM.getIntrinsic(IntID); - setARCRuntimeFunctionLinkage(CGF.CGM, fn); - } - - llvm::Type *origType = value->getType(); - - llvm::Value *args[] = { - CGF.Builder.CreateBitCast(addr.getPointer(), CGF.Int8PtrPtrTy), - CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy) - }; - llvm::CallInst *result = CGF.EmitNounwindRuntimeCall(fn, args); - - if (ignored) return nullptr; - - return CGF.Builder.CreateBitCast(result, origType); -} - -/// Perform an operation having the following signature: -/// void (i8**, i8**) -static void emitARCCopyOperation(CodeGenFunction &CGF, - Address dst, - Address src, - llvm::Constant *&fn, - llvm::Intrinsic::ID IntID) { - assert(dst.getType() == src.getType()); - - if (!fn) { - fn = CGF.CGM.getIntrinsic(IntID); - setARCRuntimeFunctionLinkage(CGF.CGM, fn); - } - - llvm::Value *args[] = { - CGF.Builder.CreateBitCast(dst.getPointer(), CGF.Int8PtrPtrTy), - CGF.Builder.CreateBitCast(src.getPointer(), CGF.Int8PtrPtrTy) - }; - CGF.EmitNounwindRuntimeCall(fn, args); -} - -/// Perform an operation having the signature -/// i8* (i8*) -/// where a null input causes a no-op and returns null. -static llvm::Value *emitObjCValueOperation(CodeGenFunction &CGF, - llvm::Value *value, - llvm::Type *returnType, - llvm::Constant *&fn, - StringRef fnName) { - if (isa<llvm::ConstantPointerNull>(value)) - return value; - - if (!fn) { - llvm::FunctionType *fnType = - llvm::FunctionType::get(CGF.Int8PtrTy, CGF.Int8PtrTy, false); - fn = CGF.CGM.CreateRuntimeFunction(fnType, fnName); - - // We have Native ARC, so set nonlazybind attribute for performance - if (llvm::Function *f = dyn_cast<llvm::Function>(fn)) - if (fnName == "objc_retain") - f->addFnAttr(llvm::Attribute::NonLazyBind); - } - - // Cast the argument to 'id'. - llvm::Type *origType = returnType ? returnType : value->getType(); - value = CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy); - - // Call the function. - llvm::CallInst *call = CGF.EmitNounwindRuntimeCall(fn, value); - - // Cast the result back to the original type. - return CGF.Builder.CreateBitCast(call, origType); -} - -/// Produce the code to do a retain. Based on the type, calls one of: -/// call i8* \@objc_retain(i8* %value) -/// call i8* \@objc_retainBlock(i8* %value) -llvm::Value *CodeGenFunction::EmitARCRetain(QualType type, llvm::Value *value) { - if (type->isBlockPointerType()) - return EmitARCRetainBlock(value, /*mandatory*/ false); - else - return EmitARCRetainNonBlock(value); -} - -/// Retain the given object, with normal retain semantics. -/// call i8* \@objc_retain(i8* %value) -llvm::Value *CodeGenFunction::EmitARCRetainNonBlock(llvm::Value *value) { - return emitARCValueOperation(*this, value, nullptr, - CGM.getObjCEntrypoints().objc_retain, - llvm::Intrinsic::objc_retain); -} - -/// Retain the given block, with _Block_copy semantics. -/// call i8* \@objc_retainBlock(i8* %value) -/// -/// \param mandatory - If false, emit the call with metadata -/// indicating that it's okay for the optimizer to eliminate this call -/// if it can prove that the block never escapes except down the stack. -llvm::Value *CodeGenFunction::EmitARCRetainBlock(llvm::Value *value, - bool mandatory) { - llvm::Value *result - = emitARCValueOperation(*this, value, nullptr, - CGM.getObjCEntrypoints().objc_retainBlock, - llvm::Intrinsic::objc_retainBlock); - - // If the copy isn't mandatory, add !clang.arc.copy_on_escape to - // tell the optimizer that it doesn't need to do this copy if the - // block doesn't escape, where being passed as an argument doesn't - // count as escaping. - if (!mandatory && isa<llvm::Instruction>(result)) { - llvm::CallInst *call - = cast<llvm::CallInst>(result->stripPointerCasts()); - assert(call->getCalledValue() == CGM.getObjCEntrypoints().objc_retainBlock); - - call->setMetadata("clang.arc.copy_on_escape", - llvm::MDNode::get(Builder.getContext(), None)); - } - - return result; -} - -static void emitAutoreleasedReturnValueMarker(CodeGenFunction &CGF) { - // Fetch the void(void) inline asm which marks that we're going to - // do something with the autoreleased return value. - llvm::InlineAsm *&marker - = CGF.CGM.getObjCEntrypoints().retainAutoreleasedReturnValueMarker; - if (!marker) { - StringRef assembly - = CGF.CGM.getTargetCodeGenInfo() - .getARCRetainAutoreleasedReturnValueMarker(); - - // If we have an empty assembly string, there's nothing to do. - if (assembly.empty()) { - - // Otherwise, at -O0, build an inline asm that we're going to call - // in a moment. - } else if (CGF.CGM.getCodeGenOpts().OptimizationLevel == 0) { - llvm::FunctionType *type = - llvm::FunctionType::get(CGF.VoidTy, /*variadic*/false); - - marker = llvm::InlineAsm::get(type, assembly, "", /*sideeffects*/ true); - - // If we're at -O1 and above, we don't want to litter the code - // with this marker yet, so leave a breadcrumb for the ARC - // optimizer to pick up. - } else { - llvm::NamedMDNode *metadata = - CGF.CGM.getModule().getOrInsertNamedMetadata( - "clang.arc.retainAutoreleasedReturnValueMarker"); - assert(metadata->getNumOperands() <= 1); - if (metadata->getNumOperands() == 0) { - auto &ctx = CGF.getLLVMContext(); - metadata->addOperand(llvm::MDNode::get(ctx, - llvm::MDString::get(ctx, assembly))); - } - } - } - - // Call the marker asm if we made one, which we do only at -O0. - if (marker) - CGF.Builder.CreateCall(marker, None, CGF.getBundlesForFunclet(marker)); -} - -/// Retain the given object which is the result of a function call. -/// call i8* \@objc_retainAutoreleasedReturnValue(i8* %value) -/// -/// Yes, this function name is one character away from a different -/// call with completely different semantics. -llvm::Value * -CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) { - emitAutoreleasedReturnValueMarker(*this); - return emitARCValueOperation(*this, value, nullptr, - CGM.getObjCEntrypoints().objc_retainAutoreleasedReturnValue, - llvm::Intrinsic::objc_retainAutoreleasedReturnValue); -} - -/// Claim a possibly-autoreleased return value at +0. This is only -/// valid to do in contexts which do not rely on the retain to keep -/// the object valid for all of its uses; for example, when -/// the value is ignored, or when it is being assigned to an -/// __unsafe_unretained variable. -/// -/// call i8* \@objc_unsafeClaimAutoreleasedReturnValue(i8* %value) -llvm::Value * -CodeGenFunction::EmitARCUnsafeClaimAutoreleasedReturnValue(llvm::Value *value) { - emitAutoreleasedReturnValueMarker(*this); - return emitARCValueOperation(*this, value, nullptr, - CGM.getObjCEntrypoints().objc_unsafeClaimAutoreleasedReturnValue, - llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue); -} - -/// Release the given object. -/// call void \@objc_release(i8* %value) -void CodeGenFunction::EmitARCRelease(llvm::Value *value, - ARCPreciseLifetime_t precise) { - if (isa<llvm::ConstantPointerNull>(value)) return; - - llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_release; - if (!fn) { - fn = CGM.getIntrinsic(llvm::Intrinsic::objc_release); - setARCRuntimeFunctionLinkage(CGM, fn); - } - - // Cast the argument to 'id'. - value = Builder.CreateBitCast(value, Int8PtrTy); - - // Call objc_release. - llvm::CallInst *call = EmitNounwindRuntimeCall(fn, value); - - if (precise == ARCImpreciseLifetime) { - call->setMetadata("clang.imprecise_release", - llvm::MDNode::get(Builder.getContext(), None)); - } -} - -/// Destroy a __strong variable. -/// -/// At -O0, emit a call to store 'null' into the address; -/// instrumenting tools prefer this because the address is exposed, -/// but it's relatively cumbersome to optimize. -/// -/// At -O1 and above, just load and call objc_release. -/// -/// call void \@objc_storeStrong(i8** %addr, i8* null) -void CodeGenFunction::EmitARCDestroyStrong(Address addr, - ARCPreciseLifetime_t precise) { - if (CGM.getCodeGenOpts().OptimizationLevel == 0) { - llvm::Value *null = getNullForVariable(addr); - EmitARCStoreStrongCall(addr, null, /*ignored*/ true); - return; - } - - llvm::Value *value = Builder.CreateLoad(addr); - EmitARCRelease(value, precise); -} - -/// Store into a strong object. Always calls this: -/// call void \@objc_storeStrong(i8** %addr, i8* %value) -llvm::Value *CodeGenFunction::EmitARCStoreStrongCall(Address addr, - llvm::Value *value, - bool ignored) { - assert(addr.getElementType() == value->getType()); - - llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_storeStrong; - if (!fn) { - fn = CGM.getIntrinsic(llvm::Intrinsic::objc_storeStrong); - setARCRuntimeFunctionLinkage(CGM, fn); - } - - llvm::Value *args[] = { - Builder.CreateBitCast(addr.getPointer(), Int8PtrPtrTy), - Builder.CreateBitCast(value, Int8PtrTy) - }; - EmitNounwindRuntimeCall(fn, args); - - if (ignored) return nullptr; - return value; -} - -/// Store into a strong object. Sometimes calls this: -/// call void \@objc_storeStrong(i8** %addr, i8* %value) -/// Other times, breaks it down into components. -llvm::Value *CodeGenFunction::EmitARCStoreStrong(LValue dst, - llvm::Value *newValue, - bool ignored) { - QualType type = dst.getType(); - bool isBlock = type->isBlockPointerType(); - - // Use a store barrier at -O0 unless this is a block type or the - // lvalue is inadequately aligned. - if (shouldUseFusedARCCalls() && - !isBlock && - (dst.getAlignment().isZero() || - dst.getAlignment() >= CharUnits::fromQuantity(PointerAlignInBytes))) { - return EmitARCStoreStrongCall(dst.getAddress(), newValue, ignored); - } - - // Otherwise, split it out. - - // Retain the new value. - newValue = EmitARCRetain(type, newValue); - - // Read the old value. - llvm::Value *oldValue = EmitLoadOfScalar(dst, SourceLocation()); - - // Store. We do this before the release so that any deallocs won't - // see the old value. - EmitStoreOfScalar(newValue, dst); - - // Finally, release the old value. - EmitARCRelease(oldValue, dst.isARCPreciseLifetime()); - - return newValue; -} - -/// Autorelease the given object. -/// call i8* \@objc_autorelease(i8* %value) -llvm::Value *CodeGenFunction::EmitARCAutorelease(llvm::Value *value) { - return emitARCValueOperation(*this, value, nullptr, - CGM.getObjCEntrypoints().objc_autorelease, - llvm::Intrinsic::objc_autorelease); -} - -/// Autorelease the given object. -/// call i8* \@objc_autoreleaseReturnValue(i8* %value) -llvm::Value * -CodeGenFunction::EmitARCAutoreleaseReturnValue(llvm::Value *value) { - return emitARCValueOperation(*this, value, nullptr, - CGM.getObjCEntrypoints().objc_autoreleaseReturnValue, - llvm::Intrinsic::objc_autoreleaseReturnValue, - /*isTailCall*/ true); -} - -/// Do a fused retain/autorelease of the given object. -/// call i8* \@objc_retainAutoreleaseReturnValue(i8* %value) -llvm::Value * -CodeGenFunction::EmitARCRetainAutoreleaseReturnValue(llvm::Value *value) { - return emitARCValueOperation(*this, value, nullptr, - CGM.getObjCEntrypoints().objc_retainAutoreleaseReturnValue, - llvm::Intrinsic::objc_retainAutoreleaseReturnValue, - /*isTailCall*/ true); -} - -/// Do a fused retain/autorelease of the given object. -/// call i8* \@objc_retainAutorelease(i8* %value) -/// or -/// %retain = call i8* \@objc_retainBlock(i8* %value) -/// call i8* \@objc_autorelease(i8* %retain) -llvm::Value *CodeGenFunction::EmitARCRetainAutorelease(QualType type, - llvm::Value *value) { - if (!type->isBlockPointerType()) - return EmitARCRetainAutoreleaseNonBlock(value); - - if (isa<llvm::ConstantPointerNull>(value)) return value; - - llvm::Type *origType = value->getType(); - value = Builder.CreateBitCast(value, Int8PtrTy); - value = EmitARCRetainBlock(value, /*mandatory*/ true); - value = EmitARCAutorelease(value); - return Builder.CreateBitCast(value, origType); -} - -/// Do a fused retain/autorelease of the given object. -/// call i8* \@objc_retainAutorelease(i8* %value) -llvm::Value * -CodeGenFunction::EmitARCRetainAutoreleaseNonBlock(llvm::Value *value) { - return emitARCValueOperation(*this, value, nullptr, - CGM.getObjCEntrypoints().objc_retainAutorelease, - llvm::Intrinsic::objc_retainAutorelease); -} - -/// i8* \@objc_loadWeak(i8** %addr) -/// Essentially objc_autorelease(objc_loadWeakRetained(addr)). -llvm::Value *CodeGenFunction::EmitARCLoadWeak(Address addr) { - return emitARCLoadOperation(*this, addr, - CGM.getObjCEntrypoints().objc_loadWeak, - llvm::Intrinsic::objc_loadWeak); -} - -/// i8* \@objc_loadWeakRetained(i8** %addr) -llvm::Value *CodeGenFunction::EmitARCLoadWeakRetained(Address addr) { - return emitARCLoadOperation(*this, addr, - CGM.getObjCEntrypoints().objc_loadWeakRetained, - llvm::Intrinsic::objc_loadWeakRetained); -} - -/// i8* \@objc_storeWeak(i8** %addr, i8* %value) -/// Returns %value. -llvm::Value *CodeGenFunction::EmitARCStoreWeak(Address addr, - llvm::Value *value, - bool ignored) { - return emitARCStoreOperation(*this, addr, value, - CGM.getObjCEntrypoints().objc_storeWeak, - llvm::Intrinsic::objc_storeWeak, ignored); -} - -/// i8* \@objc_initWeak(i8** %addr, i8* %value) -/// Returns %value. %addr is known to not have a current weak entry. -/// Essentially equivalent to: -/// *addr = nil; objc_storeWeak(addr, value); -void CodeGenFunction::EmitARCInitWeak(Address addr, llvm::Value *value) { - // If we're initializing to null, just write null to memory; no need - // to get the runtime involved. But don't do this if optimization - // is enabled, because accounting for this would make the optimizer - // much more complicated. - if (isa<llvm::ConstantPointerNull>(value) && - CGM.getCodeGenOpts().OptimizationLevel == 0) { - Builder.CreateStore(value, addr); - return; - } - - emitARCStoreOperation(*this, addr, value, - CGM.getObjCEntrypoints().objc_initWeak, - llvm::Intrinsic::objc_initWeak, /*ignored*/ true); -} - -/// void \@objc_destroyWeak(i8** %addr) -/// Essentially objc_storeWeak(addr, nil). -void CodeGenFunction::EmitARCDestroyWeak(Address addr) { - llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_destroyWeak; - if (!fn) { - fn = CGM.getIntrinsic(llvm::Intrinsic::objc_destroyWeak); - setARCRuntimeFunctionLinkage(CGM, fn); - } - - // Cast the argument to 'id*'. - addr = Builder.CreateBitCast(addr, Int8PtrPtrTy); - - EmitNounwindRuntimeCall(fn, addr.getPointer()); -} - -/// void \@objc_moveWeak(i8** %dest, i8** %src) -/// Disregards the current value in %dest. Leaves %src pointing to nothing. -/// Essentially (objc_copyWeak(dest, src), objc_destroyWeak(src)). -void CodeGenFunction::EmitARCMoveWeak(Address dst, Address src) { - emitARCCopyOperation(*this, dst, src, - CGM.getObjCEntrypoints().objc_moveWeak, - llvm::Intrinsic::objc_moveWeak); -} - -/// void \@objc_copyWeak(i8** %dest, i8** %src) -/// Disregards the current value in %dest. Essentially -/// objc_release(objc_initWeak(dest, objc_readWeakRetained(src))) -void CodeGenFunction::EmitARCCopyWeak(Address dst, Address src) { - emitARCCopyOperation(*this, dst, src, - CGM.getObjCEntrypoints().objc_copyWeak, - llvm::Intrinsic::objc_copyWeak); -} - -void CodeGenFunction::emitARCCopyAssignWeak(QualType Ty, Address DstAddr, - Address SrcAddr) { - llvm::Value *Object = EmitARCLoadWeakRetained(SrcAddr); - Object = EmitObjCConsumeObject(Ty, Object); - EmitARCStoreWeak(DstAddr, Object, false); -} - -void CodeGenFunction::emitARCMoveAssignWeak(QualType Ty, Address DstAddr, - Address SrcAddr) { - llvm::Value *Object = EmitARCLoadWeakRetained(SrcAddr); - Object = EmitObjCConsumeObject(Ty, Object); - EmitARCStoreWeak(DstAddr, Object, false); - EmitARCDestroyWeak(SrcAddr); -} - -/// Produce the code to do a objc_autoreleasepool_push. -/// call i8* \@objc_autoreleasePoolPush(void) -llvm::Value *CodeGenFunction::EmitObjCAutoreleasePoolPush() { - llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_autoreleasePoolPush; - if (!fn) { - fn = CGM.getIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPush); - setARCRuntimeFunctionLinkage(CGM, fn); - } - - return EmitNounwindRuntimeCall(fn); -} - -/// Produce the code to do a primitive release. -/// call void \@objc_autoreleasePoolPop(i8* %ptr) -void CodeGenFunction::EmitObjCAutoreleasePoolPop(llvm::Value *value) { - assert(value->getType() == Int8PtrTy); - - if (getInvokeDest()) { - // Call the runtime method not the intrinsic if we are handling exceptions - llvm::Constant *&fn = - CGM.getObjCEntrypoints().objc_autoreleasePoolPopInvoke; - if (!fn) { - llvm::FunctionType *fnType = - llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrTy, false); - fn = CGM.CreateRuntimeFunction(fnType, "objc_autoreleasePoolPop"); - setARCRuntimeFunctionLinkage(CGM, fn); - } - - // objc_autoreleasePoolPop can throw. - EmitRuntimeCallOrInvoke(fn, value); - } else { - llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_autoreleasePoolPop; - if (!fn) { - fn = CGM.getIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPop); - setARCRuntimeFunctionLinkage(CGM, fn); - } - - EmitRuntimeCall(fn, value); - } -} - -/// Produce the code to do an MRR version objc_autoreleasepool_push. -/// Which is: [[NSAutoreleasePool alloc] init]; -/// Where alloc is declared as: + (id) alloc; in NSAutoreleasePool class. -/// init is declared as: - (id) init; in its NSObject super class. -/// -llvm::Value *CodeGenFunction::EmitObjCMRRAutoreleasePoolPush() { - CGObjCRuntime &Runtime = CGM.getObjCRuntime(); - llvm::Value *Receiver = Runtime.EmitNSAutoreleasePoolClassRef(*this); - // [NSAutoreleasePool alloc] - IdentifierInfo *II = &CGM.getContext().Idents.get("alloc"); - Selector AllocSel = getContext().Selectors.getSelector(0, &II); - CallArgList Args; - RValue AllocRV = - Runtime.GenerateMessageSend(*this, ReturnValueSlot(), - getContext().getObjCIdType(), - AllocSel, Receiver, Args); - - // [Receiver init] - Receiver = AllocRV.getScalarVal(); - II = &CGM.getContext().Idents.get("init"); - Selector InitSel = getContext().Selectors.getSelector(0, &II); - RValue InitRV = - Runtime.GenerateMessageSend(*this, ReturnValueSlot(), - getContext().getObjCIdType(), - InitSel, Receiver, Args); - return InitRV.getScalarVal(); -} - -/// Allocate the given objc object. -/// call i8* \@objc_alloc(i8* %value) -llvm::Value *CodeGenFunction::EmitObjCAlloc(llvm::Value *value, - llvm::Type *resultType) { - return emitObjCValueOperation(*this, value, resultType, - CGM.getObjCEntrypoints().objc_alloc, - "objc_alloc"); -} - -/// Allocate the given objc object. -/// call i8* \@objc_allocWithZone(i8* %value) -llvm::Value *CodeGenFunction::EmitObjCAllocWithZone(llvm::Value *value, - llvm::Type *resultType) { - return emitObjCValueOperation(*this, value, resultType, - CGM.getObjCEntrypoints().objc_allocWithZone, - "objc_allocWithZone"); -} - -/// Produce the code to do a primitive release. -/// [tmp drain]; -void CodeGenFunction::EmitObjCMRRAutoreleasePoolPop(llvm::Value *Arg) { - IdentifierInfo *II = &CGM.getContext().Idents.get("drain"); - Selector DrainSel = getContext().Selectors.getSelector(0, &II); - CallArgList Args; - CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(), - getContext().VoidTy, DrainSel, Arg, Args); -} - -void CodeGenFunction::destroyARCStrongPrecise(CodeGenFunction &CGF, - Address addr, - QualType type) { - CGF.EmitARCDestroyStrong(addr, ARCPreciseLifetime); -} - -void CodeGenFunction::destroyARCStrongImprecise(CodeGenFunction &CGF, - Address addr, - QualType type) { - CGF.EmitARCDestroyStrong(addr, ARCImpreciseLifetime); -} - -void CodeGenFunction::destroyARCWeak(CodeGenFunction &CGF, - Address addr, - QualType type) { - CGF.EmitARCDestroyWeak(addr); -} - -void CodeGenFunction::emitARCIntrinsicUse(CodeGenFunction &CGF, Address addr, - QualType type) { - llvm::Value *value = CGF.Builder.CreateLoad(addr); - CGF.EmitARCIntrinsicUse(value); -} - -/// Autorelease the given object. -/// call i8* \@objc_autorelease(i8* %value) -llvm::Value *CodeGenFunction::EmitObjCAutorelease(llvm::Value *value, - llvm::Type *returnType) { - return emitObjCValueOperation(*this, value, returnType, - CGM.getObjCEntrypoints().objc_autoreleaseRuntimeFunction, - "objc_autorelease"); -} - -/// Retain the given object, with normal retain semantics. -/// call i8* \@objc_retain(i8* %value) -llvm::Value *CodeGenFunction::EmitObjCRetainNonBlock(llvm::Value *value, - llvm::Type *returnType) { - return emitObjCValueOperation(*this, value, returnType, - CGM.getObjCEntrypoints().objc_retainRuntimeFunction, - "objc_retain"); -} - -/// Release the given object. -/// call void \@objc_release(i8* %value) -void CodeGenFunction::EmitObjCRelease(llvm::Value *value, - ARCPreciseLifetime_t precise) { - if (isa<llvm::ConstantPointerNull>(value)) return; - - llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_release; - if (!fn) { - if (!fn) { - llvm::FunctionType *fnType = - llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrTy, false); - fn = CGM.CreateRuntimeFunction(fnType, "objc_release"); - setARCRuntimeFunctionLinkage(CGM, fn); - // We have Native ARC, so set nonlazybind attribute for performance - if (llvm::Function *f = dyn_cast<llvm::Function>(fn)) - f->addFnAttr(llvm::Attribute::NonLazyBind); - } - } - - // Cast the argument to 'id'. - value = Builder.CreateBitCast(value, Int8PtrTy); - - // Call objc_release. - llvm::CallInst *call = EmitNounwindRuntimeCall(fn, value); - - if (precise == ARCImpreciseLifetime) { - call->setMetadata("clang.imprecise_release", - llvm::MDNode::get(Builder.getContext(), None)); - } -} - -namespace { - struct CallObjCAutoreleasePoolObject final : EHScopeStack::Cleanup { - llvm::Value *Token; - - CallObjCAutoreleasePoolObject(llvm::Value *token) : Token(token) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - CGF.EmitObjCAutoreleasePoolPop(Token); - } - }; - struct CallObjCMRRAutoreleasePoolObject final : EHScopeStack::Cleanup { - llvm::Value *Token; - - CallObjCMRRAutoreleasePoolObject(llvm::Value *token) : Token(token) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - CGF.EmitObjCMRRAutoreleasePoolPop(Token); - } - }; -} - -void CodeGenFunction::EmitObjCAutoreleasePoolCleanup(llvm::Value *Ptr) { - if (CGM.getLangOpts().ObjCAutoRefCount) - EHStack.pushCleanup<CallObjCAutoreleasePoolObject>(NormalCleanup, Ptr); - else - EHStack.pushCleanup<CallObjCMRRAutoreleasePoolObject>(NormalCleanup, Ptr); -} - -static bool shouldRetainObjCLifetime(Qualifiers::ObjCLifetime lifetime) { - switch (lifetime) { - case Qualifiers::OCL_None: - case Qualifiers::OCL_ExplicitNone: - case Qualifiers::OCL_Strong: - case Qualifiers::OCL_Autoreleasing: - return true; - - case Qualifiers::OCL_Weak: - return false; - } - - llvm_unreachable("impossible lifetime!"); -} - -static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF, - LValue lvalue, - QualType type) { - llvm::Value *result; - bool shouldRetain = shouldRetainObjCLifetime(type.getObjCLifetime()); - if (shouldRetain) { - result = CGF.EmitLoadOfLValue(lvalue, SourceLocation()).getScalarVal(); - } else { - assert(type.getObjCLifetime() == Qualifiers::OCL_Weak); - result = CGF.EmitARCLoadWeakRetained(lvalue.getAddress()); - } - return TryEmitResult(result, !shouldRetain); -} - -static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF, - const Expr *e) { - e = e->IgnoreParens(); - QualType type = e->getType(); - - // If we're loading retained from a __strong xvalue, we can avoid - // an extra retain/release pair by zeroing out the source of this - // "move" operation. - if (e->isXValue() && - !type.isConstQualified() && - type.getObjCLifetime() == Qualifiers::OCL_Strong) { - // Emit the lvalue. - LValue lv = CGF.EmitLValue(e); - - // Load the object pointer. - llvm::Value *result = CGF.EmitLoadOfLValue(lv, - SourceLocation()).getScalarVal(); - - // Set the source pointer to NULL. - CGF.EmitStoreOfScalar(getNullForVariable(lv.getAddress()), lv); - - return TryEmitResult(result, true); - } - - // As a very special optimization, in ARC++, if the l-value is the - // result of a non-volatile assignment, do a simple retain of the - // result of the call to objc_storeWeak instead of reloading. - if (CGF.getLangOpts().CPlusPlus && - !type.isVolatileQualified() && - type.getObjCLifetime() == Qualifiers::OCL_Weak && - isa<BinaryOperator>(e) && - cast<BinaryOperator>(e)->getOpcode() == BO_Assign) - return TryEmitResult(CGF.EmitScalarExpr(e), false); - - // Try to emit code for scalar constant instead of emitting LValue and - // loading it because we are not guaranteed to have an l-value. One of such - // cases is DeclRefExpr referencing non-odr-used constant-evaluated variable. - if (const auto *decl_expr = dyn_cast<DeclRefExpr>(e)) { - auto *DRE = const_cast<DeclRefExpr *>(decl_expr); - if (CodeGenFunction::ConstantEmission constant = CGF.tryEmitAsConstant(DRE)) - return TryEmitResult(CGF.emitScalarConstant(constant, DRE), - !shouldRetainObjCLifetime(type.getObjCLifetime())); - } - - return tryEmitARCRetainLoadOfScalar(CGF, CGF.EmitLValue(e), type); -} - -typedef llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, - llvm::Value *value)> - ValueTransform; - -/// Insert code immediately after a call. -static llvm::Value *emitARCOperationAfterCall(CodeGenFunction &CGF, - llvm::Value *value, - ValueTransform doAfterCall, - ValueTransform doFallback) { - if (llvm::CallInst *call = dyn_cast<llvm::CallInst>(value)) { - CGBuilderTy::InsertPoint ip = CGF.Builder.saveIP(); - - // Place the retain immediately following the call. - CGF.Builder.SetInsertPoint(call->getParent(), - ++llvm::BasicBlock::iterator(call)); - value = doAfterCall(CGF, value); - - CGF.Builder.restoreIP(ip); - return value; - } else if (llvm::InvokeInst *invoke = dyn_cast<llvm::InvokeInst>(value)) { - CGBuilderTy::InsertPoint ip = CGF.Builder.saveIP(); - - // Place the retain at the beginning of the normal destination block. - llvm::BasicBlock *BB = invoke->getNormalDest(); - CGF.Builder.SetInsertPoint(BB, BB->begin()); - value = doAfterCall(CGF, value); - - CGF.Builder.restoreIP(ip); - return value; - - // Bitcasts can arise because of related-result returns. Rewrite - // the operand. - } else if (llvm::BitCastInst *bitcast = dyn_cast<llvm::BitCastInst>(value)) { - llvm::Value *operand = bitcast->getOperand(0); - operand = emitARCOperationAfterCall(CGF, operand, doAfterCall, doFallback); - bitcast->setOperand(0, operand); - return bitcast; - - // Generic fall-back case. - } else { - // Retain using the non-block variant: we never need to do a copy - // of a block that's been returned to us. - return doFallback(CGF, value); - } -} - -/// Given that the given expression is some sort of call (which does -/// not return retained), emit a retain following it. -static llvm::Value *emitARCRetainCallResult(CodeGenFunction &CGF, - const Expr *e) { - llvm::Value *value = CGF.EmitScalarExpr(e); - return emitARCOperationAfterCall(CGF, value, - [](CodeGenFunction &CGF, llvm::Value *value) { - return CGF.EmitARCRetainAutoreleasedReturnValue(value); - }, - [](CodeGenFunction &CGF, llvm::Value *value) { - return CGF.EmitARCRetainNonBlock(value); - }); -} - -/// Given that the given expression is some sort of call (which does -/// not return retained), perform an unsafeClaim following it. -static llvm::Value *emitARCUnsafeClaimCallResult(CodeGenFunction &CGF, - const Expr *e) { - llvm::Value *value = CGF.EmitScalarExpr(e); - return emitARCOperationAfterCall(CGF, value, - [](CodeGenFunction &CGF, llvm::Value *value) { - return CGF.EmitARCUnsafeClaimAutoreleasedReturnValue(value); - }, - [](CodeGenFunction &CGF, llvm::Value *value) { - return value; - }); -} - -llvm::Value *CodeGenFunction::EmitARCReclaimReturnedObject(const Expr *E, - bool allowUnsafeClaim) { - if (allowUnsafeClaim && - CGM.getLangOpts().ObjCRuntime.hasARCUnsafeClaimAutoreleasedReturnValue()) { - return emitARCUnsafeClaimCallResult(*this, E); - } else { - llvm::Value *value = emitARCRetainCallResult(*this, E); - return EmitObjCConsumeObject(E->getType(), value); - } -} - -/// Determine whether it might be important to emit a separate -/// objc_retain_block on the result of the given expression, or -/// whether it's okay to just emit it in a +1 context. -static bool shouldEmitSeparateBlockRetain(const Expr *e) { - assert(e->getType()->isBlockPointerType()); - e = e->IgnoreParens(); - - // For future goodness, emit block expressions directly in +1 - // contexts if we can. - if (isa<BlockExpr>(e)) - return false; - - if (const CastExpr *cast = dyn_cast<CastExpr>(e)) { - switch (cast->getCastKind()) { - // Emitting these operations in +1 contexts is goodness. - case CK_LValueToRValue: - case CK_ARCReclaimReturnedObject: - case CK_ARCConsumeObject: - case CK_ARCProduceObject: - return false; - - // These operations preserve a block type. - case CK_NoOp: - case CK_BitCast: - return shouldEmitSeparateBlockRetain(cast->getSubExpr()); - - // These operations are known to be bad (or haven't been considered). - case CK_AnyPointerToBlockPointerCast: - default: - return true; - } - } - - return true; -} - -namespace { -/// A CRTP base class for emitting expressions of retainable object -/// pointer type in ARC. -template <typename Impl, typename Result> class ARCExprEmitter { -protected: - CodeGenFunction &CGF; - Impl &asImpl() { return *static_cast<Impl*>(this); } - - ARCExprEmitter(CodeGenFunction &CGF) : CGF(CGF) {} - -public: - Result visit(const Expr *e); - Result visitCastExpr(const CastExpr *e); - Result visitPseudoObjectExpr(const PseudoObjectExpr *e); - Result visitBinaryOperator(const BinaryOperator *e); - Result visitBinAssign(const BinaryOperator *e); - Result visitBinAssignUnsafeUnretained(const BinaryOperator *e); - Result visitBinAssignAutoreleasing(const BinaryOperator *e); - Result visitBinAssignWeak(const BinaryOperator *e); - Result visitBinAssignStrong(const BinaryOperator *e); - - // Minimal implementation: - // Result visitLValueToRValue(const Expr *e) - // Result visitConsumeObject(const Expr *e) - // Result visitExtendBlockObject(const Expr *e) - // Result visitReclaimReturnedObject(const Expr *e) - // Result visitCall(const Expr *e) - // Result visitExpr(const Expr *e) - // - // Result emitBitCast(Result result, llvm::Type *resultType) - // llvm::Value *getValueOfResult(Result result) -}; -} - -/// Try to emit a PseudoObjectExpr under special ARC rules. -/// -/// This massively duplicates emitPseudoObjectRValue. -template <typename Impl, typename Result> -Result -ARCExprEmitter<Impl,Result>::visitPseudoObjectExpr(const PseudoObjectExpr *E) { - SmallVector<CodeGenFunction::OpaqueValueMappingData, 4> opaques; - - // Find the result expression. - const Expr *resultExpr = E->getResultExpr(); - assert(resultExpr); - Result result; - - for (PseudoObjectExpr::const_semantics_iterator - i = E->semantics_begin(), e = E->semantics_end(); i != e; ++i) { - const Expr *semantic = *i; - - // If this semantic expression is an opaque value, bind it - // to the result of its source expression. - if (const OpaqueValueExpr *ov = dyn_cast<OpaqueValueExpr>(semantic)) { - typedef CodeGenFunction::OpaqueValueMappingData OVMA; - OVMA opaqueData; - - // If this semantic is the result of the pseudo-object - // expression, try to evaluate the source as +1. - if (ov == resultExpr) { - assert(!OVMA::shouldBindAsLValue(ov)); - result = asImpl().visit(ov->getSourceExpr()); - opaqueData = OVMA::bind(CGF, ov, - RValue::get(asImpl().getValueOfResult(result))); - - // Otherwise, just bind it. - } else { - opaqueData = OVMA::bind(CGF, ov, ov->getSourceExpr()); - } - opaques.push_back(opaqueData); - - // Otherwise, if the expression is the result, evaluate it - // and remember the result. - } else if (semantic == resultExpr) { - result = asImpl().visit(semantic); - - // Otherwise, evaluate the expression in an ignored context. - } else { - CGF.EmitIgnoredExpr(semantic); - } - } - - // Unbind all the opaques now. - for (unsigned i = 0, e = opaques.size(); i != e; ++i) - opaques[i].unbind(CGF); - - return result; -} - -template <typename Impl, typename Result> -Result ARCExprEmitter<Impl,Result>::visitCastExpr(const CastExpr *e) { - switch (e->getCastKind()) { - - // No-op casts don't change the type, so we just ignore them. - case CK_NoOp: - return asImpl().visit(e->getSubExpr()); - - // These casts can change the type. - case CK_CPointerToObjCPointerCast: - case CK_BlockPointerToObjCPointerCast: - case CK_AnyPointerToBlockPointerCast: - case CK_BitCast: { - llvm::Type *resultType = CGF.ConvertType(e->getType()); - assert(e->getSubExpr()->getType()->hasPointerRepresentation()); - Result result = asImpl().visit(e->getSubExpr()); - return asImpl().emitBitCast(result, resultType); - } - - // Handle some casts specially. - case CK_LValueToRValue: - return asImpl().visitLValueToRValue(e->getSubExpr()); - case CK_ARCConsumeObject: - return asImpl().visitConsumeObject(e->getSubExpr()); - case CK_ARCExtendBlockObject: - return asImpl().visitExtendBlockObject(e->getSubExpr()); - case CK_ARCReclaimReturnedObject: - return asImpl().visitReclaimReturnedObject(e->getSubExpr()); - - // Otherwise, use the default logic. - default: - return asImpl().visitExpr(e); - } -} - -template <typename Impl, typename Result> -Result -ARCExprEmitter<Impl,Result>::visitBinaryOperator(const BinaryOperator *e) { - switch (e->getOpcode()) { - case BO_Comma: - CGF.EmitIgnoredExpr(e->getLHS()); - CGF.EnsureInsertPoint(); - return asImpl().visit(e->getRHS()); - - case BO_Assign: - return asImpl().visitBinAssign(e); - - default: - return asImpl().visitExpr(e); - } -} - -template <typename Impl, typename Result> -Result ARCExprEmitter<Impl,Result>::visitBinAssign(const BinaryOperator *e) { - switch (e->getLHS()->getType().getObjCLifetime()) { - case Qualifiers::OCL_ExplicitNone: - return asImpl().visitBinAssignUnsafeUnretained(e); - - case Qualifiers::OCL_Weak: - return asImpl().visitBinAssignWeak(e); - - case Qualifiers::OCL_Autoreleasing: - return asImpl().visitBinAssignAutoreleasing(e); - - case Qualifiers::OCL_Strong: - return asImpl().visitBinAssignStrong(e); - - case Qualifiers::OCL_None: - return asImpl().visitExpr(e); - } - llvm_unreachable("bad ObjC ownership qualifier"); -} - -/// The default rule for __unsafe_unretained emits the RHS recursively, -/// stores into the unsafe variable, and propagates the result outward. -template <typename Impl, typename Result> -Result ARCExprEmitter<Impl,Result>:: - visitBinAssignUnsafeUnretained(const BinaryOperator *e) { - // Recursively emit the RHS. - // For __block safety, do this before emitting the LHS. - Result result = asImpl().visit(e->getRHS()); - - // Perform the store. - LValue lvalue = - CGF.EmitCheckedLValue(e->getLHS(), CodeGenFunction::TCK_Store); - CGF.EmitStoreThroughLValue(RValue::get(asImpl().getValueOfResult(result)), - lvalue); - - return result; -} - -template <typename Impl, typename Result> -Result -ARCExprEmitter<Impl,Result>::visitBinAssignAutoreleasing(const BinaryOperator *e) { - return asImpl().visitExpr(e); -} - -template <typename Impl, typename Result> -Result -ARCExprEmitter<Impl,Result>::visitBinAssignWeak(const BinaryOperator *e) { - return asImpl().visitExpr(e); -} - -template <typename Impl, typename Result> -Result -ARCExprEmitter<Impl,Result>::visitBinAssignStrong(const BinaryOperator *e) { - return asImpl().visitExpr(e); -} - -/// The general expression-emission logic. -template <typename Impl, typename Result> -Result ARCExprEmitter<Impl,Result>::visit(const Expr *e) { - // We should *never* see a nested full-expression here, because if - // we fail to emit at +1, our caller must not retain after we close - // out the full-expression. This isn't as important in the unsafe - // emitter. - assert(!isa<ExprWithCleanups>(e)); - - // Look through parens, __extension__, generic selection, etc. - e = e->IgnoreParens(); - - // Handle certain kinds of casts. - if (const CastExpr *ce = dyn_cast<CastExpr>(e)) { - return asImpl().visitCastExpr(ce); - - // Handle the comma operator. - } else if (auto op = dyn_cast<BinaryOperator>(e)) { - return asImpl().visitBinaryOperator(op); - - // TODO: handle conditional operators here - - // For calls and message sends, use the retained-call logic. - // Delegate inits are a special case in that they're the only - // returns-retained expression that *isn't* surrounded by - // a consume. - } else if (isa<CallExpr>(e) || - (isa<ObjCMessageExpr>(e) && - !cast<ObjCMessageExpr>(e)->isDelegateInitCall())) { - return asImpl().visitCall(e); - - // Look through pseudo-object expressions. - } else if (const PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(e)) { - return asImpl().visitPseudoObjectExpr(pseudo); - } - - return asImpl().visitExpr(e); -} - -namespace { - -/// An emitter for +1 results. -struct ARCRetainExprEmitter : - public ARCExprEmitter<ARCRetainExprEmitter, TryEmitResult> { - - ARCRetainExprEmitter(CodeGenFunction &CGF) : ARCExprEmitter(CGF) {} - - llvm::Value *getValueOfResult(TryEmitResult result) { - return result.getPointer(); - } - - TryEmitResult emitBitCast(TryEmitResult result, llvm::Type *resultType) { - llvm::Value *value = result.getPointer(); - value = CGF.Builder.CreateBitCast(value, resultType); - result.setPointer(value); - return result; - } - - TryEmitResult visitLValueToRValue(const Expr *e) { - return tryEmitARCRetainLoadOfScalar(CGF, e); - } - - /// For consumptions, just emit the subexpression and thus elide - /// the retain/release pair. - TryEmitResult visitConsumeObject(const Expr *e) { - llvm::Value *result = CGF.EmitScalarExpr(e); - return TryEmitResult(result, true); - } - - /// Block extends are net +0. Naively, we could just recurse on - /// the subexpression, but actually we need to ensure that the - /// value is copied as a block, so there's a little filter here. - TryEmitResult visitExtendBlockObject(const Expr *e) { - llvm::Value *result; // will be a +0 value - - // If we can't safely assume the sub-expression will produce a - // block-copied value, emit the sub-expression at +0. - if (shouldEmitSeparateBlockRetain(e)) { - result = CGF.EmitScalarExpr(e); - - // Otherwise, try to emit the sub-expression at +1 recursively. - } else { - TryEmitResult subresult = asImpl().visit(e); - - // If that produced a retained value, just use that. - if (subresult.getInt()) { - return subresult; - } - - // Otherwise it's +0. - result = subresult.getPointer(); - } - - // Retain the object as a block. - result = CGF.EmitARCRetainBlock(result, /*mandatory*/ true); - return TryEmitResult(result, true); - } - - /// For reclaims, emit the subexpression as a retained call and - /// skip the consumption. - TryEmitResult visitReclaimReturnedObject(const Expr *e) { - llvm::Value *result = emitARCRetainCallResult(CGF, e); - return TryEmitResult(result, true); - } - - /// When we have an undecorated call, retroactively do a claim. - TryEmitResult visitCall(const Expr *e) { - llvm::Value *result = emitARCRetainCallResult(CGF, e); - return TryEmitResult(result, true); - } - - // TODO: maybe special-case visitBinAssignWeak? - - TryEmitResult visitExpr(const Expr *e) { - // We didn't find an obvious production, so emit what we've got and - // tell the caller that we didn't manage to retain. - llvm::Value *result = CGF.EmitScalarExpr(e); - return TryEmitResult(result, false); - } -}; -} - -static TryEmitResult -tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e) { - return ARCRetainExprEmitter(CGF).visit(e); -} - -static llvm::Value *emitARCRetainLoadOfScalar(CodeGenFunction &CGF, - LValue lvalue, - QualType type) { - TryEmitResult result = tryEmitARCRetainLoadOfScalar(CGF, lvalue, type); - llvm::Value *value = result.getPointer(); - if (!result.getInt()) - value = CGF.EmitARCRetain(type, value); - return value; -} - -/// EmitARCRetainScalarExpr - Semantically equivalent to -/// EmitARCRetainObject(e->getType(), EmitScalarExpr(e)), but making a -/// best-effort attempt to peephole expressions that naturally produce -/// retained objects. -llvm::Value *CodeGenFunction::EmitARCRetainScalarExpr(const Expr *e) { - // The retain needs to happen within the full-expression. - if (const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(e)) { - enterFullExpression(cleanups); - RunCleanupsScope scope(*this); - return EmitARCRetainScalarExpr(cleanups->getSubExpr()); - } - - TryEmitResult result = tryEmitARCRetainScalarExpr(*this, e); - llvm::Value *value = result.getPointer(); - if (!result.getInt()) - value = EmitARCRetain(e->getType(), value); - return value; -} - -llvm::Value * -CodeGenFunction::EmitARCRetainAutoreleaseScalarExpr(const Expr *e) { - // The retain needs to happen within the full-expression. - if (const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(e)) { - enterFullExpression(cleanups); - RunCleanupsScope scope(*this); - return EmitARCRetainAutoreleaseScalarExpr(cleanups->getSubExpr()); - } - - TryEmitResult result = tryEmitARCRetainScalarExpr(*this, e); - llvm::Value *value = result.getPointer(); - if (result.getInt()) - value = EmitARCAutorelease(value); - else - value = EmitARCRetainAutorelease(e->getType(), value); - return value; -} - -llvm::Value *CodeGenFunction::EmitARCExtendBlockObject(const Expr *e) { - llvm::Value *result; - bool doRetain; - - if (shouldEmitSeparateBlockRetain(e)) { - result = EmitScalarExpr(e); - doRetain = true; - } else { - TryEmitResult subresult = tryEmitARCRetainScalarExpr(*this, e); - result = subresult.getPointer(); - doRetain = !subresult.getInt(); - } - - if (doRetain) - result = EmitARCRetainBlock(result, /*mandatory*/ true); - return EmitObjCConsumeObject(e->getType(), result); -} - -llvm::Value *CodeGenFunction::EmitObjCThrowOperand(const Expr *expr) { - // In ARC, retain and autorelease the expression. - if (getLangOpts().ObjCAutoRefCount) { - // Do so before running any cleanups for the full-expression. - // EmitARCRetainAutoreleaseScalarExpr does this for us. - return EmitARCRetainAutoreleaseScalarExpr(expr); - } - - // Otherwise, use the normal scalar-expression emission. The - // exception machinery doesn't do anything special with the - // exception like retaining it, so there's no safety associated with - // only running cleanups after the throw has started, and when it - // matters it tends to be substantially inferior code. - return EmitScalarExpr(expr); -} - -namespace { - -/// An emitter for assigning into an __unsafe_unretained context. -struct ARCUnsafeUnretainedExprEmitter : - public ARCExprEmitter<ARCUnsafeUnretainedExprEmitter, llvm::Value*> { - - ARCUnsafeUnretainedExprEmitter(CodeGenFunction &CGF) : ARCExprEmitter(CGF) {} - - llvm::Value *getValueOfResult(llvm::Value *value) { - return value; - } - - llvm::Value *emitBitCast(llvm::Value *value, llvm::Type *resultType) { - return CGF.Builder.CreateBitCast(value, resultType); - } - - llvm::Value *visitLValueToRValue(const Expr *e) { - return CGF.EmitScalarExpr(e); - } - - /// For consumptions, just emit the subexpression and perform the - /// consumption like normal. - llvm::Value *visitConsumeObject(const Expr *e) { - llvm::Value *value = CGF.EmitScalarExpr(e); - return CGF.EmitObjCConsumeObject(e->getType(), value); - } - - /// No special logic for block extensions. (This probably can't - /// actually happen in this emitter, though.) - llvm::Value *visitExtendBlockObject(const Expr *e) { - return CGF.EmitARCExtendBlockObject(e); - } - - /// For reclaims, perform an unsafeClaim if that's enabled. - llvm::Value *visitReclaimReturnedObject(const Expr *e) { - return CGF.EmitARCReclaimReturnedObject(e, /*unsafe*/ true); - } - - /// When we have an undecorated call, just emit it without adding - /// the unsafeClaim. - llvm::Value *visitCall(const Expr *e) { - return CGF.EmitScalarExpr(e); - } - - /// Just do normal scalar emission in the default case. - llvm::Value *visitExpr(const Expr *e) { - return CGF.EmitScalarExpr(e); - } -}; -} - -static llvm::Value *emitARCUnsafeUnretainedScalarExpr(CodeGenFunction &CGF, - const Expr *e) { - return ARCUnsafeUnretainedExprEmitter(CGF).visit(e); -} - -/// EmitARCUnsafeUnretainedScalarExpr - Semantically equivalent to -/// immediately releasing the resut of EmitARCRetainScalarExpr, but -/// avoiding any spurious retains, including by performing reclaims -/// with objc_unsafeClaimAutoreleasedReturnValue. -llvm::Value *CodeGenFunction::EmitARCUnsafeUnretainedScalarExpr(const Expr *e) { - // Look through full-expressions. - if (const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(e)) { - enterFullExpression(cleanups); - RunCleanupsScope scope(*this); - return emitARCUnsafeUnretainedScalarExpr(*this, cleanups->getSubExpr()); - } - - return emitARCUnsafeUnretainedScalarExpr(*this, e); -} - -std::pair<LValue,llvm::Value*> -CodeGenFunction::EmitARCStoreUnsafeUnretained(const BinaryOperator *e, - bool ignored) { - // Evaluate the RHS first. If we're ignoring the result, assume - // that we can emit at an unsafe +0. - llvm::Value *value; - if (ignored) { - value = EmitARCUnsafeUnretainedScalarExpr(e->getRHS()); - } else { - value = EmitScalarExpr(e->getRHS()); - } - - // Emit the LHS and perform the store. - LValue lvalue = EmitLValue(e->getLHS()); - EmitStoreOfScalar(value, lvalue); - - return std::pair<LValue,llvm::Value*>(std::move(lvalue), value); -} - -std::pair<LValue,llvm::Value*> -CodeGenFunction::EmitARCStoreStrong(const BinaryOperator *e, - bool ignored) { - // Evaluate the RHS first. - TryEmitResult result = tryEmitARCRetainScalarExpr(*this, e->getRHS()); - llvm::Value *value = result.getPointer(); - - bool hasImmediateRetain = result.getInt(); - - // If we didn't emit a retained object, and the l-value is of block - // type, then we need to emit the block-retain immediately in case - // it invalidates the l-value. - if (!hasImmediateRetain && e->getType()->isBlockPointerType()) { - value = EmitARCRetainBlock(value, /*mandatory*/ false); - hasImmediateRetain = true; - } - - LValue lvalue = EmitLValue(e->getLHS()); - - // If the RHS was emitted retained, expand this. - if (hasImmediateRetain) { - llvm::Value *oldValue = EmitLoadOfScalar(lvalue, SourceLocation()); - EmitStoreOfScalar(value, lvalue); - EmitARCRelease(oldValue, lvalue.isARCPreciseLifetime()); - } else { - value = EmitARCStoreStrong(lvalue, value, ignored); - } - - return std::pair<LValue,llvm::Value*>(lvalue, value); -} - -std::pair<LValue,llvm::Value*> -CodeGenFunction::EmitARCStoreAutoreleasing(const BinaryOperator *e) { - llvm::Value *value = EmitARCRetainAutoreleaseScalarExpr(e->getRHS()); - LValue lvalue = EmitLValue(e->getLHS()); - - EmitStoreOfScalar(value, lvalue); - - return std::pair<LValue,llvm::Value*>(lvalue, value); -} - -void CodeGenFunction::EmitObjCAutoreleasePoolStmt( - const ObjCAutoreleasePoolStmt &ARPS) { - const Stmt *subStmt = ARPS.getSubStmt(); - const CompoundStmt &S = cast<CompoundStmt>(*subStmt); - - CGDebugInfo *DI = getDebugInfo(); - if (DI) - DI->EmitLexicalBlockStart(Builder, S.getLBracLoc()); - - // Keep track of the current cleanup stack depth. - RunCleanupsScope Scope(*this); - if (CGM.getLangOpts().ObjCRuntime.hasNativeARC()) { - llvm::Value *token = EmitObjCAutoreleasePoolPush(); - EHStack.pushCleanup<CallObjCAutoreleasePoolObject>(NormalCleanup, token); - } else { - llvm::Value *token = EmitObjCMRRAutoreleasePoolPush(); - EHStack.pushCleanup<CallObjCMRRAutoreleasePoolObject>(NormalCleanup, token); - } - - for (const auto *I : S.body()) - EmitStmt(I); - - if (DI) - DI->EmitLexicalBlockEnd(Builder, S.getRBracLoc()); -} - -/// EmitExtendGCLifetime - Given a pointer to an Objective-C object, -/// make sure it survives garbage collection until this point. -void CodeGenFunction::EmitExtendGCLifetime(llvm::Value *object) { - // We just use an inline assembly. - llvm::FunctionType *extenderType - = llvm::FunctionType::get(VoidTy, VoidPtrTy, RequiredArgs::All); - llvm::Value *extender - = llvm::InlineAsm::get(extenderType, - /* assembly */ "", - /* constraints */ "r", - /* side effects */ true); - - object = Builder.CreateBitCast(object, VoidPtrTy); - EmitNounwindRuntimeCall(extender, object); -} - -/// GenerateObjCAtomicSetterCopyHelperFunction - Given a c++ object type with -/// non-trivial copy assignment function, produce following helper function. -/// static void copyHelper(Ty *dest, const Ty *source) { *dest = *source; } -/// -llvm::Constant * -CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction( - const ObjCPropertyImplDecl *PID) { - if (!getLangOpts().CPlusPlus || - !getLangOpts().ObjCRuntime.hasAtomicCopyHelper()) - return nullptr; - QualType Ty = PID->getPropertyIvarDecl()->getType(); - if (!Ty->isRecordType()) - return nullptr; - const ObjCPropertyDecl *PD = PID->getPropertyDecl(); - if ((!(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_atomic))) - return nullptr; - llvm::Constant *HelperFn = nullptr; - if (hasTrivialSetExpr(PID)) - return nullptr; - assert(PID->getSetterCXXAssignment() && "SetterCXXAssignment - null"); - if ((HelperFn = CGM.getAtomicSetterHelperFnMap(Ty))) - return HelperFn; - - ASTContext &C = getContext(); - IdentifierInfo *II - = &CGM.getContext().Idents.get("__assign_helper_atomic_property_"); - - QualType ReturnTy = C.VoidTy; - QualType DestTy = C.getPointerType(Ty); - QualType SrcTy = Ty; - SrcTy.addConst(); - SrcTy = C.getPointerType(SrcTy); - - SmallVector<QualType, 2> ArgTys; - ArgTys.push_back(DestTy); - ArgTys.push_back(SrcTy); - QualType FunctionTy = C.getFunctionType(ReturnTy, ArgTys, {}); - - FunctionDecl *FD = FunctionDecl::Create( - C, C.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II, - FunctionTy, nullptr, SC_Static, false, false); - - FunctionArgList args; - ImplicitParamDecl DstDecl(C, FD, SourceLocation(), /*Id=*/nullptr, DestTy, - ImplicitParamDecl::Other); - args.push_back(&DstDecl); - ImplicitParamDecl SrcDecl(C, FD, SourceLocation(), /*Id=*/nullptr, SrcTy, - ImplicitParamDecl::Other); - args.push_back(&SrcDecl); - - const CGFunctionInfo &FI = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args); - - llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI); - - llvm::Function *Fn = - llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, - "__assign_helper_atomic_property_", - &CGM.getModule()); - - CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI); - - StartFunction(FD, ReturnTy, Fn, FI, args); - - DeclRefExpr DstExpr(getContext(), &DstDecl, false, DestTy, VK_RValue, - SourceLocation()); - UnaryOperator DST(&DstExpr, UO_Deref, DestTy->getPointeeType(), - VK_LValue, OK_Ordinary, SourceLocation(), false); - - DeclRefExpr SrcExpr(getContext(), &SrcDecl, false, SrcTy, VK_RValue, - SourceLocation()); - UnaryOperator SRC(&SrcExpr, UO_Deref, SrcTy->getPointeeType(), - VK_LValue, OK_Ordinary, SourceLocation(), false); - - Expr *Args[2] = { &DST, &SRC }; - CallExpr *CalleeExp = cast<CallExpr>(PID->getSetterCXXAssignment()); - CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create( - C, OO_Equal, CalleeExp->getCallee(), Args, DestTy->getPointeeType(), - VK_LValue, SourceLocation(), FPOptions()); - - EmitStmt(TheCall); - - FinishFunction(); - HelperFn = llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy); - CGM.setAtomicSetterHelperFnMap(Ty, HelperFn); - return HelperFn; -} - -llvm::Constant * -CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction( - const ObjCPropertyImplDecl *PID) { - if (!getLangOpts().CPlusPlus || - !getLangOpts().ObjCRuntime.hasAtomicCopyHelper()) - return nullptr; - const ObjCPropertyDecl *PD = PID->getPropertyDecl(); - QualType Ty = PD->getType(); - if (!Ty->isRecordType()) - return nullptr; - if ((!(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_atomic))) - return nullptr; - llvm::Constant *HelperFn = nullptr; - if (hasTrivialGetExpr(PID)) - return nullptr; - assert(PID->getGetterCXXConstructor() && "getGetterCXXConstructor - null"); - if ((HelperFn = CGM.getAtomicGetterHelperFnMap(Ty))) - return HelperFn; - - ASTContext &C = getContext(); - IdentifierInfo *II = - &CGM.getContext().Idents.get("__copy_helper_atomic_property_"); - - QualType ReturnTy = C.VoidTy; - QualType DestTy = C.getPointerType(Ty); - QualType SrcTy = Ty; - SrcTy.addConst(); - SrcTy = C.getPointerType(SrcTy); - - SmallVector<QualType, 2> ArgTys; - ArgTys.push_back(DestTy); - ArgTys.push_back(SrcTy); - QualType FunctionTy = C.getFunctionType(ReturnTy, ArgTys, {}); - - FunctionDecl *FD = FunctionDecl::Create( - C, C.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II, - FunctionTy, nullptr, SC_Static, false, false); - - FunctionArgList args; - ImplicitParamDecl DstDecl(C, FD, SourceLocation(), /*Id=*/nullptr, DestTy, - ImplicitParamDecl::Other); - args.push_back(&DstDecl); - ImplicitParamDecl SrcDecl(C, FD, SourceLocation(), /*Id=*/nullptr, SrcTy, - ImplicitParamDecl::Other); - args.push_back(&SrcDecl); - - const CGFunctionInfo &FI = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args); - - llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI); - - llvm::Function *Fn = llvm::Function::Create( - LTy, llvm::GlobalValue::InternalLinkage, "__copy_helper_atomic_property_", - &CGM.getModule()); - - CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI); - - StartFunction(FD, ReturnTy, Fn, FI, args); - - DeclRefExpr SrcExpr(getContext(), &SrcDecl, false, SrcTy, VK_RValue, - SourceLocation()); - - UnaryOperator SRC(&SrcExpr, UO_Deref, SrcTy->getPointeeType(), - VK_LValue, OK_Ordinary, SourceLocation(), false); - - CXXConstructExpr *CXXConstExpr = - cast<CXXConstructExpr>(PID->getGetterCXXConstructor()); - - SmallVector<Expr*, 4> ConstructorArgs; - ConstructorArgs.push_back(&SRC); - ConstructorArgs.append(std::next(CXXConstExpr->arg_begin()), - CXXConstExpr->arg_end()); - - CXXConstructExpr *TheCXXConstructExpr = - CXXConstructExpr::Create(C, Ty, SourceLocation(), - CXXConstExpr->getConstructor(), - CXXConstExpr->isElidable(), - ConstructorArgs, - CXXConstExpr->hadMultipleCandidates(), - CXXConstExpr->isListInitialization(), - CXXConstExpr->isStdInitListInitialization(), - CXXConstExpr->requiresZeroInitialization(), - CXXConstExpr->getConstructionKind(), - SourceRange()); - - DeclRefExpr DstExpr(getContext(), &DstDecl, false, DestTy, VK_RValue, - SourceLocation()); - - RValue DV = EmitAnyExpr(&DstExpr); - CharUnits Alignment - = getContext().getTypeAlignInChars(TheCXXConstructExpr->getType()); - EmitAggExpr(TheCXXConstructExpr, - AggValueSlot::forAddr(Address(DV.getScalarVal(), Alignment), - Qualifiers(), - AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - AggValueSlot::DoesNotOverlap)); - - FinishFunction(); - HelperFn = llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy); - CGM.setAtomicGetterHelperFnMap(Ty, HelperFn); - return HelperFn; -} - -llvm::Value * -CodeGenFunction::EmitBlockCopyAndAutorelease(llvm::Value *Block, QualType Ty) { - // Get selectors for retain/autorelease. - IdentifierInfo *CopyID = &getContext().Idents.get("copy"); - Selector CopySelector = - getContext().Selectors.getNullarySelector(CopyID); - IdentifierInfo *AutoreleaseID = &getContext().Idents.get("autorelease"); - Selector AutoreleaseSelector = - getContext().Selectors.getNullarySelector(AutoreleaseID); - - // Emit calls to retain/autorelease. - CGObjCRuntime &Runtime = CGM.getObjCRuntime(); - llvm::Value *Val = Block; - RValue Result; - Result = Runtime.GenerateMessageSend(*this, ReturnValueSlot(), - Ty, CopySelector, - Val, CallArgList(), nullptr, nullptr); - Val = Result.getScalarVal(); - Result = Runtime.GenerateMessageSend(*this, ReturnValueSlot(), - Ty, AutoreleaseSelector, - Val, CallArgList(), nullptr, nullptr); - Val = Result.getScalarVal(); - return Val; -} - -llvm::Value * -CodeGenFunction::EmitBuiltinAvailable(ArrayRef<llvm::Value *> Args) { - assert(Args.size() == 3 && "Expected 3 argument here!"); - - if (!CGM.IsOSVersionAtLeastFn) { - llvm::FunctionType *FTy = - llvm::FunctionType::get(Int32Ty, {Int32Ty, Int32Ty, Int32Ty}, false); - CGM.IsOSVersionAtLeastFn = - CGM.CreateRuntimeFunction(FTy, "__isOSVersionAtLeast"); - } - - llvm::Value *CallRes = - EmitNounwindRuntimeCall(CGM.IsOSVersionAtLeastFn, Args); - - return Builder.CreateICmpNE(CallRes, llvm::Constant::getNullValue(Int32Ty)); -} - -void CodeGenModule::emitAtAvailableLinkGuard() { - if (!IsOSVersionAtLeastFn) - return; - // @available requires CoreFoundation only on Darwin. - if (!Target.getTriple().isOSDarwin()) - return; - // Add -framework CoreFoundation to the linker commands. We still want to - // emit the core foundation reference down below because otherwise if - // CoreFoundation is not used in the code, the linker won't link the - // framework. - auto &Context = getLLVMContext(); - llvm::Metadata *Args[2] = {llvm::MDString::get(Context, "-framework"), - llvm::MDString::get(Context, "CoreFoundation")}; - LinkerOptionsMetadata.push_back(llvm::MDNode::get(Context, Args)); - // Emit a reference to a symbol from CoreFoundation to ensure that - // CoreFoundation is linked into the final binary. - llvm::FunctionType *FTy = - llvm::FunctionType::get(Int32Ty, {VoidPtrTy}, false); - llvm::Constant *CFFunc = - CreateRuntimeFunction(FTy, "CFBundleGetVersionNumber"); - - llvm::FunctionType *CheckFTy = llvm::FunctionType::get(VoidTy, {}, false); - llvm::Function *CFLinkCheckFunc = cast<llvm::Function>(CreateBuiltinFunction( - CheckFTy, "__clang_at_available_requires_core_foundation_framework")); - CFLinkCheckFunc->setLinkage(llvm::GlobalValue::LinkOnceAnyLinkage); - CFLinkCheckFunc->setVisibility(llvm::GlobalValue::HiddenVisibility); - CodeGenFunction CGF(*this); - CGF.Builder.SetInsertPoint(CGF.createBasicBlock("", CFLinkCheckFunc)); - CGF.EmitNounwindRuntimeCall(CFFunc, llvm::Constant::getNullValue(VoidPtrTy)); - CGF.Builder.CreateUnreachable(); - addCompilerUsedGlobal(CFLinkCheckFunc); -} - -CGObjCRuntime::~CGObjCRuntime() {} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp deleted file mode 100644 index 548bd6b3fd7..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp +++ /dev/null @@ -1,4022 +0,0 @@ -//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This provides Objective-C code generation targeting the GNU runtime. The -// class in this file generates structures used by the GNU Objective-C runtime -// library. These structures are defined in objc/objc.h and objc/objc-api.h in -// the GNU runtime distribution. -// -//===----------------------------------------------------------------------===// - -#include "CGObjCRuntime.h" -#include "CGCleanup.h" -#include "CodeGenFunction.h" -#include "CodeGenModule.h" -#include "CGCXXABI.h" -#include "clang/CodeGen/ConstantInitBuilder.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/RecordLayout.h" -#include "clang/AST/StmtObjC.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/SourceManager.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/ConvertUTF.h" -#include <cctype> - -using namespace clang; -using namespace CodeGen; - -namespace { - -std::string SymbolNameForMethod( StringRef ClassName, - StringRef CategoryName, const Selector MethodName, - bool isClassMethod) { - std::string MethodNameColonStripped = MethodName.getAsString(); - std::replace(MethodNameColonStripped.begin(), MethodNameColonStripped.end(), - ':', '_'); - return (Twine(isClassMethod ? "_c_" : "_i_") + ClassName + "_" + - CategoryName + "_" + MethodNameColonStripped).str(); -} - -/// Class that lazily initialises the runtime function. Avoids inserting the -/// types and the function declaration into a module if they're not used, and -/// avoids constructing the type more than once if it's used more than once. -class LazyRuntimeFunction { - CodeGenModule *CGM; - llvm::FunctionType *FTy; - const char *FunctionName; - llvm::Constant *Function; - -public: - /// Constructor leaves this class uninitialized, because it is intended to - /// be used as a field in another class and not all of the types that are - /// used as arguments will necessarily be available at construction time. - LazyRuntimeFunction() - : CGM(nullptr), FunctionName(nullptr), Function(nullptr) {} - - /// Initialises the lazy function with the name, return type, and the types - /// of the arguments. - template <typename... Tys> - void init(CodeGenModule *Mod, const char *name, llvm::Type *RetTy, - Tys *... Types) { - CGM = Mod; - FunctionName = name; - Function = nullptr; - if(sizeof...(Tys)) { - SmallVector<llvm::Type *, 8> ArgTys({Types...}); - FTy = llvm::FunctionType::get(RetTy, ArgTys, false); - } - else { - FTy = llvm::FunctionType::get(RetTy, None, false); - } - } - - llvm::FunctionType *getType() { return FTy; } - - /// Overloaded cast operator, allows the class to be implicitly cast to an - /// LLVM constant. - operator llvm::Constant *() { - if (!Function) { - if (!FunctionName) - return nullptr; - Function = CGM->CreateRuntimeFunction(FTy, FunctionName); - } - return Function; - } - operator llvm::Function *() { - return cast<llvm::Function>((llvm::Constant *)*this); - } -}; - - -/// GNU Objective-C runtime code generation. This class implements the parts of -/// Objective-C support that are specific to the GNU family of runtimes (GCC, -/// GNUstep and ObjFW). -class CGObjCGNU : public CGObjCRuntime { -protected: - /// The LLVM module into which output is inserted - llvm::Module &TheModule; - /// strut objc_super. Used for sending messages to super. This structure - /// contains the receiver (object) and the expected class. - llvm::StructType *ObjCSuperTy; - /// struct objc_super*. The type of the argument to the superclass message - /// lookup functions. - llvm::PointerType *PtrToObjCSuperTy; - /// LLVM type for selectors. Opaque pointer (i8*) unless a header declaring - /// SEL is included in a header somewhere, in which case it will be whatever - /// type is declared in that header, most likely {i8*, i8*}. - llvm::PointerType *SelectorTy; - /// LLVM i8 type. Cached here to avoid repeatedly getting it in all of the - /// places where it's used - llvm::IntegerType *Int8Ty; - /// Pointer to i8 - LLVM type of char*, for all of the places where the - /// runtime needs to deal with C strings. - llvm::PointerType *PtrToInt8Ty; - /// struct objc_protocol type - llvm::StructType *ProtocolTy; - /// Protocol * type. - llvm::PointerType *ProtocolPtrTy; - /// Instance Method Pointer type. This is a pointer to a function that takes, - /// at a minimum, an object and a selector, and is the generic type for - /// Objective-C methods. Due to differences between variadic / non-variadic - /// calling conventions, it must always be cast to the correct type before - /// actually being used. - llvm::PointerType *IMPTy; - /// Type of an untyped Objective-C object. Clang treats id as a built-in type - /// when compiling Objective-C code, so this may be an opaque pointer (i8*), - /// but if the runtime header declaring it is included then it may be a - /// pointer to a structure. - llvm::PointerType *IdTy; - /// Pointer to a pointer to an Objective-C object. Used in the new ABI - /// message lookup function and some GC-related functions. - llvm::PointerType *PtrToIdTy; - /// The clang type of id. Used when using the clang CGCall infrastructure to - /// call Objective-C methods. - CanQualType ASTIdTy; - /// LLVM type for C int type. - llvm::IntegerType *IntTy; - /// LLVM type for an opaque pointer. This is identical to PtrToInt8Ty, but is - /// used in the code to document the difference between i8* meaning a pointer - /// to a C string and i8* meaning a pointer to some opaque type. - llvm::PointerType *PtrTy; - /// LLVM type for C long type. The runtime uses this in a lot of places where - /// it should be using intptr_t, but we can't fix this without breaking - /// compatibility with GCC... - llvm::IntegerType *LongTy; - /// LLVM type for C size_t. Used in various runtime data structures. - llvm::IntegerType *SizeTy; - /// LLVM type for C intptr_t. - llvm::IntegerType *IntPtrTy; - /// LLVM type for C ptrdiff_t. Mainly used in property accessor functions. - llvm::IntegerType *PtrDiffTy; - /// LLVM type for C int*. Used for GCC-ABI-compatible non-fragile instance - /// variables. - llvm::PointerType *PtrToIntTy; - /// LLVM type for Objective-C BOOL type. - llvm::Type *BoolTy; - /// 32-bit integer type, to save us needing to look it up every time it's used. - llvm::IntegerType *Int32Ty; - /// 64-bit integer type, to save us needing to look it up every time it's used. - llvm::IntegerType *Int64Ty; - /// The type of struct objc_property. - llvm::StructType *PropertyMetadataTy; - /// Metadata kind used to tie method lookups to message sends. The GNUstep - /// runtime provides some LLVM passes that can use this to do things like - /// automatic IMP caching and speculative inlining. - unsigned msgSendMDKind; - /// Does the current target use SEH-based exceptions? False implies - /// Itanium-style DWARF unwinding. - bool usesSEHExceptions; - - /// Helper to check if we are targeting a specific runtime version or later. - bool isRuntime(ObjCRuntime::Kind kind, unsigned major, unsigned minor=0) { - const ObjCRuntime &R = CGM.getLangOpts().ObjCRuntime; - return (R.getKind() == kind) && - (R.getVersion() >= VersionTuple(major, minor)); - } - - std::string SymbolForProtocol(StringRef Name) { - return (StringRef("._OBJC_PROTOCOL_") + Name).str(); - } - - std::string SymbolForProtocolRef(StringRef Name) { - return (StringRef("._OBJC_REF_PROTOCOL_") + Name).str(); - } - - - /// Helper function that generates a constant string and returns a pointer to - /// the start of the string. The result of this function can be used anywhere - /// where the C code specifies const char*. - llvm::Constant *MakeConstantString(StringRef Str, const char *Name = "") { - ConstantAddress Array = CGM.GetAddrOfConstantCString(Str, Name); - return llvm::ConstantExpr::getGetElementPtr(Array.getElementType(), - Array.getPointer(), Zeros); - } - - /// Emits a linkonce_odr string, whose name is the prefix followed by the - /// string value. This allows the linker to combine the strings between - /// different modules. Used for EH typeinfo names, selector strings, and a - /// few other things. - llvm::Constant *ExportUniqueString(const std::string &Str, - const std::string &prefix, - bool Private=false) { - std::string name = prefix + Str; - auto *ConstStr = TheModule.getGlobalVariable(name); - if (!ConstStr) { - llvm::Constant *value = llvm::ConstantDataArray::getString(VMContext,Str); - auto *GV = new llvm::GlobalVariable(TheModule, value->getType(), true, - llvm::GlobalValue::LinkOnceODRLinkage, value, name); - GV->setComdat(TheModule.getOrInsertComdat(name)); - if (Private) - GV->setVisibility(llvm::GlobalValue::HiddenVisibility); - ConstStr = GV; - } - return llvm::ConstantExpr::getGetElementPtr(ConstStr->getValueType(), - ConstStr, Zeros); - } - - /// Returns a property name and encoding string. - llvm::Constant *MakePropertyEncodingString(const ObjCPropertyDecl *PD, - const Decl *Container) { - assert(!isRuntime(ObjCRuntime::GNUstep, 2)); - if (isRuntime(ObjCRuntime::GNUstep, 1, 6)) { - std::string NameAndAttributes; - std::string TypeStr = - CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container); - NameAndAttributes += '\0'; - NameAndAttributes += TypeStr.length() + 3; - NameAndAttributes += TypeStr; - NameAndAttributes += '\0'; - NameAndAttributes += PD->getNameAsString(); - return MakeConstantString(NameAndAttributes); - } - return MakeConstantString(PD->getNameAsString()); - } - - /// Push the property attributes into two structure fields. - void PushPropertyAttributes(ConstantStructBuilder &Fields, - const ObjCPropertyDecl *property, bool isSynthesized=true, bool - isDynamic=true) { - int attrs = property->getPropertyAttributes(); - // For read-only properties, clear the copy and retain flags - if (attrs & ObjCPropertyDecl::OBJC_PR_readonly) { - attrs &= ~ObjCPropertyDecl::OBJC_PR_copy; - attrs &= ~ObjCPropertyDecl::OBJC_PR_retain; - attrs &= ~ObjCPropertyDecl::OBJC_PR_weak; - attrs &= ~ObjCPropertyDecl::OBJC_PR_strong; - } - // The first flags field has the same attribute values as clang uses internally - Fields.addInt(Int8Ty, attrs & 0xff); - attrs >>= 8; - attrs <<= 2; - // For protocol properties, synthesized and dynamic have no meaning, so we - // reuse these flags to indicate that this is a protocol property (both set - // has no meaning, as a property can't be both synthesized and dynamic) - attrs |= isSynthesized ? (1<<0) : 0; - attrs |= isDynamic ? (1<<1) : 0; - // The second field is the next four fields left shifted by two, with the - // low bit set to indicate whether the field is synthesized or dynamic. - Fields.addInt(Int8Ty, attrs & 0xff); - // Two padding fields - Fields.addInt(Int8Ty, 0); - Fields.addInt(Int8Ty, 0); - } - - virtual llvm::Constant *GenerateCategoryProtocolList(const - ObjCCategoryDecl *OCD); - virtual ConstantArrayBuilder PushPropertyListHeader(ConstantStructBuilder &Fields, - int count) { - // int count; - Fields.addInt(IntTy, count); - // int size; (only in GNUstep v2 ABI. - if (isRuntime(ObjCRuntime::GNUstep, 2)) { - llvm::DataLayout td(&TheModule); - Fields.addInt(IntTy, td.getTypeSizeInBits(PropertyMetadataTy) / - CGM.getContext().getCharWidth()); - } - // struct objc_property_list *next; - Fields.add(NULLPtr); - // struct objc_property properties[] - return Fields.beginArray(PropertyMetadataTy); - } - virtual void PushProperty(ConstantArrayBuilder &PropertiesArray, - const ObjCPropertyDecl *property, - const Decl *OCD, - bool isSynthesized=true, bool - isDynamic=true) { - auto Fields = PropertiesArray.beginStruct(PropertyMetadataTy); - ASTContext &Context = CGM.getContext(); - Fields.add(MakePropertyEncodingString(property, OCD)); - PushPropertyAttributes(Fields, property, isSynthesized, isDynamic); - auto addPropertyMethod = [&](const ObjCMethodDecl *accessor) { - if (accessor) { - std::string TypeStr = Context.getObjCEncodingForMethodDecl(accessor); - llvm::Constant *TypeEncoding = MakeConstantString(TypeStr); - Fields.add(MakeConstantString(accessor->getSelector().getAsString())); - Fields.add(TypeEncoding); - } else { - Fields.add(NULLPtr); - Fields.add(NULLPtr); - } - }; - addPropertyMethod(property->getGetterMethodDecl()); - addPropertyMethod(property->getSetterMethodDecl()); - Fields.finishAndAddTo(PropertiesArray); - } - - /// Ensures that the value has the required type, by inserting a bitcast if - /// required. This function lets us avoid inserting bitcasts that are - /// redundant. - llvm::Value* EnforceType(CGBuilderTy &B, llvm::Value *V, llvm::Type *Ty) { - if (V->getType() == Ty) return V; - return B.CreateBitCast(V, Ty); - } - Address EnforceType(CGBuilderTy &B, Address V, llvm::Type *Ty) { - if (V.getType() == Ty) return V; - return B.CreateBitCast(V, Ty); - } - - // Some zeros used for GEPs in lots of places. - llvm::Constant *Zeros[2]; - /// Null pointer value. Mainly used as a terminator in various arrays. - llvm::Constant *NULLPtr; - /// LLVM context. - llvm::LLVMContext &VMContext; - -protected: - - /// Placeholder for the class. Lots of things refer to the class before we've - /// actually emitted it. We use this alias as a placeholder, and then replace - /// it with a pointer to the class structure before finally emitting the - /// module. - llvm::GlobalAlias *ClassPtrAlias; - /// Placeholder for the metaclass. Lots of things refer to the class before - /// we've / actually emitted it. We use this alias as a placeholder, and then - /// replace / it with a pointer to the metaclass structure before finally - /// emitting the / module. - llvm::GlobalAlias *MetaClassPtrAlias; - /// All of the classes that have been generated for this compilation units. - std::vector<llvm::Constant*> Classes; - /// All of the categories that have been generated for this compilation units. - std::vector<llvm::Constant*> Categories; - /// All of the Objective-C constant strings that have been generated for this - /// compilation units. - std::vector<llvm::Constant*> ConstantStrings; - /// Map from string values to Objective-C constant strings in the output. - /// Used to prevent emitting Objective-C strings more than once. This should - /// not be required at all - CodeGenModule should manage this list. - llvm::StringMap<llvm::Constant*> ObjCStrings; - /// All of the protocols that have been declared. - llvm::StringMap<llvm::Constant*> ExistingProtocols; - /// For each variant of a selector, we store the type encoding and a - /// placeholder value. For an untyped selector, the type will be the empty - /// string. Selector references are all done via the module's selector table, - /// so we create an alias as a placeholder and then replace it with the real - /// value later. - typedef std::pair<std::string, llvm::GlobalAlias*> TypedSelector; - /// Type of the selector map. This is roughly equivalent to the structure - /// used in the GNUstep runtime, which maintains a list of all of the valid - /// types for a selector in a table. - typedef llvm::DenseMap<Selector, SmallVector<TypedSelector, 2> > - SelectorMap; - /// A map from selectors to selector types. This allows us to emit all - /// selectors of the same name and type together. - SelectorMap SelectorTable; - - /// Selectors related to memory management. When compiling in GC mode, we - /// omit these. - Selector RetainSel, ReleaseSel, AutoreleaseSel; - /// Runtime functions used for memory management in GC mode. Note that clang - /// supports code generation for calling these functions, but neither GNU - /// runtime actually supports this API properly yet. - LazyRuntimeFunction IvarAssignFn, StrongCastAssignFn, MemMoveFn, WeakReadFn, - WeakAssignFn, GlobalAssignFn; - - typedef std::pair<std::string, std::string> ClassAliasPair; - /// All classes that have aliases set for them. - std::vector<ClassAliasPair> ClassAliases; - -protected: - /// Function used for throwing Objective-C exceptions. - LazyRuntimeFunction ExceptionThrowFn; - /// Function used for rethrowing exceptions, used at the end of \@finally or - /// \@synchronize blocks. - LazyRuntimeFunction ExceptionReThrowFn; - /// Function called when entering a catch function. This is required for - /// differentiating Objective-C exceptions and foreign exceptions. - LazyRuntimeFunction EnterCatchFn; - /// Function called when exiting from a catch block. Used to do exception - /// cleanup. - LazyRuntimeFunction ExitCatchFn; - /// Function called when entering an \@synchronize block. Acquires the lock. - LazyRuntimeFunction SyncEnterFn; - /// Function called when exiting an \@synchronize block. Releases the lock. - LazyRuntimeFunction SyncExitFn; - -private: - /// Function called if fast enumeration detects that the collection is - /// modified during the update. - LazyRuntimeFunction EnumerationMutationFn; - /// Function for implementing synthesized property getters that return an - /// object. - LazyRuntimeFunction GetPropertyFn; - /// Function for implementing synthesized property setters that return an - /// object. - LazyRuntimeFunction SetPropertyFn; - /// Function used for non-object declared property getters. - LazyRuntimeFunction GetStructPropertyFn; - /// Function used for non-object declared property setters. - LazyRuntimeFunction SetStructPropertyFn; - -protected: - /// The version of the runtime that this class targets. Must match the - /// version in the runtime. - int RuntimeVersion; - /// The version of the protocol class. Used to differentiate between ObjC1 - /// and ObjC2 protocols. Objective-C 1 protocols can not contain optional - /// components and can not contain declared properties. We always emit - /// Objective-C 2 property structures, but we have to pretend that they're - /// Objective-C 1 property structures when targeting the GCC runtime or it - /// will abort. - const int ProtocolVersion; - /// The version of the class ABI. This value is used in the class structure - /// and indicates how various fields should be interpreted. - const int ClassABIVersion; - /// Generates an instance variable list structure. This is a structure - /// containing a size and an array of structures containing instance variable - /// metadata. This is used purely for introspection in the fragile ABI. In - /// the non-fragile ABI, it's used for instance variable fixup. - virtual llvm::Constant *GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames, - ArrayRef<llvm::Constant *> IvarTypes, - ArrayRef<llvm::Constant *> IvarOffsets, - ArrayRef<llvm::Constant *> IvarAlign, - ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership); - - /// Generates a method list structure. This is a structure containing a size - /// and an array of structures containing method metadata. - /// - /// This structure is used by both classes and categories, and contains a next - /// pointer allowing them to be chained together in a linked list. - llvm::Constant *GenerateMethodList(StringRef ClassName, - StringRef CategoryName, - ArrayRef<const ObjCMethodDecl*> Methods, - bool isClassMethodList); - - /// Emits an empty protocol. This is used for \@protocol() where no protocol - /// is found. The runtime will (hopefully) fix up the pointer to refer to the - /// real protocol. - virtual llvm::Constant *GenerateEmptyProtocol(StringRef ProtocolName); - - /// Generates a list of property metadata structures. This follows the same - /// pattern as method and instance variable metadata lists. - llvm::Constant *GeneratePropertyList(const Decl *Container, - const ObjCContainerDecl *OCD, - bool isClassProperty=false, - bool protocolOptionalProperties=false); - - /// Generates a list of referenced protocols. Classes, categories, and - /// protocols all use this structure. - llvm::Constant *GenerateProtocolList(ArrayRef<std::string> Protocols); - - /// To ensure that all protocols are seen by the runtime, we add a category on - /// a class defined in the runtime, declaring no methods, but adopting the - /// protocols. This is a horribly ugly hack, but it allows us to collect all - /// of the protocols without changing the ABI. - void GenerateProtocolHolderCategory(); - - /// Generates a class structure. - llvm::Constant *GenerateClassStructure( - llvm::Constant *MetaClass, - llvm::Constant *SuperClass, - unsigned info, - const char *Name, - llvm::Constant *Version, - llvm::Constant *InstanceSize, - llvm::Constant *IVars, - llvm::Constant *Methods, - llvm::Constant *Protocols, - llvm::Constant *IvarOffsets, - llvm::Constant *Properties, - llvm::Constant *StrongIvarBitmap, - llvm::Constant *WeakIvarBitmap, - bool isMeta=false); - - /// Generates a method list. This is used by protocols to define the required - /// and optional methods. - virtual llvm::Constant *GenerateProtocolMethodList( - ArrayRef<const ObjCMethodDecl*> Methods); - /// Emits optional and required method lists. - template<class T> - void EmitProtocolMethodList(T &&Methods, llvm::Constant *&Required, - llvm::Constant *&Optional) { - SmallVector<const ObjCMethodDecl*, 16> RequiredMethods; - SmallVector<const ObjCMethodDecl*, 16> OptionalMethods; - for (const auto *I : Methods) - if (I->isOptional()) - OptionalMethods.push_back(I); - else - RequiredMethods.push_back(I); - Required = GenerateProtocolMethodList(RequiredMethods); - Optional = GenerateProtocolMethodList(OptionalMethods); - } - - /// Returns a selector with the specified type encoding. An empty string is - /// used to return an untyped selector (with the types field set to NULL). - virtual llvm::Value *GetTypedSelector(CodeGenFunction &CGF, Selector Sel, - const std::string &TypeEncoding); - - /// Returns the name of ivar offset variables. In the GNUstep v1 ABI, this - /// contains the class and ivar names, in the v2 ABI this contains the type - /// encoding as well. - virtual std::string GetIVarOffsetVariableName(const ObjCInterfaceDecl *ID, - const ObjCIvarDecl *Ivar) { - const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString() - + '.' + Ivar->getNameAsString(); - return Name; - } - /// Returns the variable used to store the offset of an instance variable. - llvm::GlobalVariable *ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID, - const ObjCIvarDecl *Ivar); - /// Emits a reference to a class. This allows the linker to object if there - /// is no class of the matching name. - void EmitClassRef(const std::string &className); - - /// Emits a pointer to the named class - virtual llvm::Value *GetClassNamed(CodeGenFunction &CGF, - const std::string &Name, bool isWeak); - - /// Looks up the method for sending a message to the specified object. This - /// mechanism differs between the GCC and GNU runtimes, so this method must be - /// overridden in subclasses. - virtual llvm::Value *LookupIMP(CodeGenFunction &CGF, - llvm::Value *&Receiver, - llvm::Value *cmd, - llvm::MDNode *node, - MessageSendInfo &MSI) = 0; - - /// Looks up the method for sending a message to a superclass. This - /// mechanism differs between the GCC and GNU runtimes, so this method must - /// be overridden in subclasses. - virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, - Address ObjCSuper, - llvm::Value *cmd, - MessageSendInfo &MSI) = 0; - - /// Libobjc2 uses a bitfield representation where small(ish) bitfields are - /// stored in a 64-bit value with the low bit set to 1 and the remaining 63 - /// bits set to their values, LSB first, while larger ones are stored in a - /// structure of this / form: - /// - /// struct { int32_t length; int32_t values[length]; }; - /// - /// The values in the array are stored in host-endian format, with the least - /// significant bit being assumed to come first in the bitfield. Therefore, - /// a bitfield with the 64th bit set will be (int64_t)&{ 2, [0, 1<<31] }, - /// while a bitfield / with the 63rd bit set will be 1<<64. - llvm::Constant *MakeBitField(ArrayRef<bool> bits); - -public: - CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion, - unsigned protocolClassVersion, unsigned classABI=1); - - ConstantAddress GenerateConstantString(const StringLiteral *) override; - - RValue - GenerateMessageSend(CodeGenFunction &CGF, ReturnValueSlot Return, - QualType ResultType, Selector Sel, - llvm::Value *Receiver, const CallArgList &CallArgs, - const ObjCInterfaceDecl *Class, - const ObjCMethodDecl *Method) override; - RValue - GenerateMessageSendSuper(CodeGenFunction &CGF, ReturnValueSlot Return, - QualType ResultType, Selector Sel, - const ObjCInterfaceDecl *Class, - bool isCategoryImpl, llvm::Value *Receiver, - bool IsClassMessage, const CallArgList &CallArgs, - const ObjCMethodDecl *Method) override; - llvm::Value *GetClass(CodeGenFunction &CGF, - const ObjCInterfaceDecl *OID) override; - llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override; - Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override; - llvm::Value *GetSelector(CodeGenFunction &CGF, - const ObjCMethodDecl *Method) override; - virtual llvm::Constant *GetConstantSelector(Selector Sel, - const std::string &TypeEncoding) { - llvm_unreachable("Runtime unable to generate constant selector"); - } - llvm::Constant *GetConstantSelector(const ObjCMethodDecl *M) { - return GetConstantSelector(M->getSelector(), - CGM.getContext().getObjCEncodingForMethodDecl(M)); - } - llvm::Constant *GetEHType(QualType T) override; - - llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, - const ObjCContainerDecl *CD) override; - void GenerateCategory(const ObjCCategoryImplDecl *CMD) override; - void GenerateClass(const ObjCImplementationDecl *ClassDecl) override; - void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override; - llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF, - const ObjCProtocolDecl *PD) override; - void GenerateProtocol(const ObjCProtocolDecl *PD) override; - llvm::Function *ModuleInitFunction() override; - llvm::Constant *GetPropertyGetFunction() override; - llvm::Constant *GetPropertySetFunction() override; - llvm::Constant *GetOptimizedPropertySetFunction(bool atomic, - bool copy) override; - llvm::Constant *GetSetStructFunction() override; - llvm::Constant *GetGetStructFunction() override; - llvm::Constant *GetCppAtomicObjectGetFunction() override; - llvm::Constant *GetCppAtomicObjectSetFunction() override; - llvm::Constant *EnumerationMutationFunction() override; - - void EmitTryStmt(CodeGenFunction &CGF, - const ObjCAtTryStmt &S) override; - void EmitSynchronizedStmt(CodeGenFunction &CGF, - const ObjCAtSynchronizedStmt &S) override; - void EmitThrowStmt(CodeGenFunction &CGF, - const ObjCAtThrowStmt &S, - bool ClearInsertionPoint=true) override; - llvm::Value * EmitObjCWeakRead(CodeGenFunction &CGF, - Address AddrWeakObj) override; - void EmitObjCWeakAssign(CodeGenFunction &CGF, - llvm::Value *src, Address dst) override; - void EmitObjCGlobalAssign(CodeGenFunction &CGF, - llvm::Value *src, Address dest, - bool threadlocal=false) override; - void EmitObjCIvarAssign(CodeGenFunction &CGF, llvm::Value *src, - Address dest, llvm::Value *ivarOffset) override; - void EmitObjCStrongCastAssign(CodeGenFunction &CGF, - llvm::Value *src, Address dest) override; - void EmitGCMemmoveCollectable(CodeGenFunction &CGF, Address DestPtr, - Address SrcPtr, - llvm::Value *Size) override; - LValue EmitObjCValueForIvar(CodeGenFunction &CGF, QualType ObjectTy, - llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, - unsigned CVRQualifiers) override; - llvm::Value *EmitIvarOffset(CodeGenFunction &CGF, - const ObjCInterfaceDecl *Interface, - const ObjCIvarDecl *Ivar) override; - llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override; - llvm::Constant *BuildGCBlockLayout(CodeGenModule &CGM, - const CGBlockInfo &blockInfo) override { - return NULLPtr; - } - llvm::Constant *BuildRCBlockLayout(CodeGenModule &CGM, - const CGBlockInfo &blockInfo) override { - return NULLPtr; - } - - llvm::Constant *BuildByrefLayout(CodeGenModule &CGM, QualType T) override { - return NULLPtr; - } -}; - -/// Class representing the legacy GCC Objective-C ABI. This is the default when -/// -fobjc-nonfragile-abi is not specified. -/// -/// The GCC ABI target actually generates code that is approximately compatible -/// with the new GNUstep runtime ABI, but refrains from using any features that -/// would not work with the GCC runtime. For example, clang always generates -/// the extended form of the class structure, and the extra fields are simply -/// ignored by GCC libobjc. -class CGObjCGCC : public CGObjCGNU { - /// The GCC ABI message lookup function. Returns an IMP pointing to the - /// method implementation for this message. - LazyRuntimeFunction MsgLookupFn; - /// The GCC ABI superclass message lookup function. Takes a pointer to a - /// structure describing the receiver and the class, and a selector as - /// arguments. Returns the IMP for the corresponding method. - LazyRuntimeFunction MsgLookupSuperFn; - -protected: - llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver, - llvm::Value *cmd, llvm::MDNode *node, - MessageSendInfo &MSI) override { - CGBuilderTy &Builder = CGF.Builder; - llvm::Value *args[] = { - EnforceType(Builder, Receiver, IdTy), - EnforceType(Builder, cmd, SelectorTy) }; - llvm::CallSite imp = CGF.EmitRuntimeCallOrInvoke(MsgLookupFn, args); - imp->setMetadata(msgSendMDKind, node); - return imp.getInstruction(); - } - - llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper, - llvm::Value *cmd, MessageSendInfo &MSI) override { - CGBuilderTy &Builder = CGF.Builder; - llvm::Value *lookupArgs[] = {EnforceType(Builder, ObjCSuper, - PtrToObjCSuperTy).getPointer(), cmd}; - return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs); - } - -public: - CGObjCGCC(CodeGenModule &Mod) : CGObjCGNU(Mod, 8, 2) { - // IMP objc_msg_lookup(id, SEL); - MsgLookupFn.init(&CGM, "objc_msg_lookup", IMPTy, IdTy, SelectorTy); - // IMP objc_msg_lookup_super(struct objc_super*, SEL); - MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy, - PtrToObjCSuperTy, SelectorTy); - } -}; - -/// Class used when targeting the new GNUstep runtime ABI. -class CGObjCGNUstep : public CGObjCGNU { - /// The slot lookup function. Returns a pointer to a cacheable structure - /// that contains (among other things) the IMP. - LazyRuntimeFunction SlotLookupFn; - /// The GNUstep ABI superclass message lookup function. Takes a pointer to - /// a structure describing the receiver and the class, and a selector as - /// arguments. Returns the slot for the corresponding method. Superclass - /// message lookup rarely changes, so this is a good caching opportunity. - LazyRuntimeFunction SlotLookupSuperFn; - /// Specialised function for setting atomic retain properties - LazyRuntimeFunction SetPropertyAtomic; - /// Specialised function for setting atomic copy properties - LazyRuntimeFunction SetPropertyAtomicCopy; - /// Specialised function for setting nonatomic retain properties - LazyRuntimeFunction SetPropertyNonAtomic; - /// Specialised function for setting nonatomic copy properties - LazyRuntimeFunction SetPropertyNonAtomicCopy; - /// Function to perform atomic copies of C++ objects with nontrivial copy - /// constructors from Objective-C ivars. - LazyRuntimeFunction CxxAtomicObjectGetFn; - /// Function to perform atomic copies of C++ objects with nontrivial copy - /// constructors to Objective-C ivars. - LazyRuntimeFunction CxxAtomicObjectSetFn; - /// Type of an slot structure pointer. This is returned by the various - /// lookup functions. - llvm::Type *SlotTy; - - public: - llvm::Constant *GetEHType(QualType T) override; - - protected: - llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver, - llvm::Value *cmd, llvm::MDNode *node, - MessageSendInfo &MSI) override { - CGBuilderTy &Builder = CGF.Builder; - llvm::Function *LookupFn = SlotLookupFn; - - // Store the receiver on the stack so that we can reload it later - Address ReceiverPtr = - CGF.CreateTempAlloca(Receiver->getType(), CGF.getPointerAlign()); - Builder.CreateStore(Receiver, ReceiverPtr); - - llvm::Value *self; - - if (isa<ObjCMethodDecl>(CGF.CurCodeDecl)) { - self = CGF.LoadObjCSelf(); - } else { - self = llvm::ConstantPointerNull::get(IdTy); - } - - // The lookup function is guaranteed not to capture the receiver pointer. - LookupFn->addParamAttr(0, llvm::Attribute::NoCapture); - - llvm::Value *args[] = { - EnforceType(Builder, ReceiverPtr.getPointer(), PtrToIdTy), - EnforceType(Builder, cmd, SelectorTy), - EnforceType(Builder, self, IdTy) }; - llvm::CallSite slot = CGF.EmitRuntimeCallOrInvoke(LookupFn, args); - slot.setOnlyReadsMemory(); - slot->setMetadata(msgSendMDKind, node); - - // Load the imp from the slot - llvm::Value *imp = Builder.CreateAlignedLoad( - Builder.CreateStructGEP(nullptr, slot.getInstruction(), 4), - CGF.getPointerAlign()); - - // The lookup function may have changed the receiver, so make sure we use - // the new one. - Receiver = Builder.CreateLoad(ReceiverPtr, true); - return imp; - } - - llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper, - llvm::Value *cmd, - MessageSendInfo &MSI) override { - CGBuilderTy &Builder = CGF.Builder; - llvm::Value *lookupArgs[] = {ObjCSuper.getPointer(), cmd}; - - llvm::CallInst *slot = - CGF.EmitNounwindRuntimeCall(SlotLookupSuperFn, lookupArgs); - slot->setOnlyReadsMemory(); - - return Builder.CreateAlignedLoad(Builder.CreateStructGEP(nullptr, slot, 4), - CGF.getPointerAlign()); - } - - public: - CGObjCGNUstep(CodeGenModule &Mod) : CGObjCGNUstep(Mod, 9, 3, 1) {} - CGObjCGNUstep(CodeGenModule &Mod, unsigned ABI, unsigned ProtocolABI, - unsigned ClassABI) : - CGObjCGNU(Mod, ABI, ProtocolABI, ClassABI) { - const ObjCRuntime &R = CGM.getLangOpts().ObjCRuntime; - - llvm::StructType *SlotStructTy = - llvm::StructType::get(PtrTy, PtrTy, PtrTy, IntTy, IMPTy); - SlotTy = llvm::PointerType::getUnqual(SlotStructTy); - // Slot_t objc_msg_lookup_sender(id *receiver, SEL selector, id sender); - SlotLookupFn.init(&CGM, "objc_msg_lookup_sender", SlotTy, PtrToIdTy, - SelectorTy, IdTy); - // Slot_t objc_slot_lookup_super(struct objc_super*, SEL); - SlotLookupSuperFn.init(&CGM, "objc_slot_lookup_super", SlotTy, - PtrToObjCSuperTy, SelectorTy); - // If we're in ObjC++ mode, then we want to make - if (usesSEHExceptions) { - llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); - // void objc_exception_rethrow(void) - ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy); - } else if (CGM.getLangOpts().CPlusPlus) { - llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); - // void *__cxa_begin_catch(void *e) - EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy); - // void __cxa_end_catch(void) - ExitCatchFn.init(&CGM, "__cxa_end_catch", VoidTy); - // void _Unwind_Resume_or_Rethrow(void*) - ExceptionReThrowFn.init(&CGM, "_Unwind_Resume_or_Rethrow", VoidTy, - PtrTy); - } else if (R.getVersion() >= VersionTuple(1, 7)) { - llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); - // id objc_begin_catch(void *e) - EnterCatchFn.init(&CGM, "objc_begin_catch", IdTy, PtrTy); - // void objc_end_catch(void) - ExitCatchFn.init(&CGM, "objc_end_catch", VoidTy); - // void _Unwind_Resume_or_Rethrow(void*) - ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy, PtrTy); - } - llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); - SetPropertyAtomic.init(&CGM, "objc_setProperty_atomic", VoidTy, IdTy, - SelectorTy, IdTy, PtrDiffTy); - SetPropertyAtomicCopy.init(&CGM, "objc_setProperty_atomic_copy", VoidTy, - IdTy, SelectorTy, IdTy, PtrDiffTy); - SetPropertyNonAtomic.init(&CGM, "objc_setProperty_nonatomic", VoidTy, - IdTy, SelectorTy, IdTy, PtrDiffTy); - SetPropertyNonAtomicCopy.init(&CGM, "objc_setProperty_nonatomic_copy", - VoidTy, IdTy, SelectorTy, IdTy, PtrDiffTy); - // void objc_setCppObjectAtomic(void *dest, const void *src, void - // *helper); - CxxAtomicObjectSetFn.init(&CGM, "objc_setCppObjectAtomic", VoidTy, PtrTy, - PtrTy, PtrTy); - // void objc_getCppObjectAtomic(void *dest, const void *src, void - // *helper); - CxxAtomicObjectGetFn.init(&CGM, "objc_getCppObjectAtomic", VoidTy, PtrTy, - PtrTy, PtrTy); - } - - llvm::Constant *GetCppAtomicObjectGetFunction() override { - // The optimised functions were added in version 1.7 of the GNUstep - // runtime. - assert (CGM.getLangOpts().ObjCRuntime.getVersion() >= - VersionTuple(1, 7)); - return CxxAtomicObjectGetFn; - } - - llvm::Constant *GetCppAtomicObjectSetFunction() override { - // The optimised functions were added in version 1.7 of the GNUstep - // runtime. - assert (CGM.getLangOpts().ObjCRuntime.getVersion() >= - VersionTuple(1, 7)); - return CxxAtomicObjectSetFn; - } - - llvm::Constant *GetOptimizedPropertySetFunction(bool atomic, - bool copy) override { - // The optimised property functions omit the GC check, and so are not - // safe to use in GC mode. The standard functions are fast in GC mode, - // so there is less advantage in using them. - assert ((CGM.getLangOpts().getGC() == LangOptions::NonGC)); - // The optimised functions were added in version 1.7 of the GNUstep - // runtime. - assert (CGM.getLangOpts().ObjCRuntime.getVersion() >= - VersionTuple(1, 7)); - - if (atomic) { - if (copy) return SetPropertyAtomicCopy; - return SetPropertyAtomic; - } - - return copy ? SetPropertyNonAtomicCopy : SetPropertyNonAtomic; - } -}; - -/// GNUstep Objective-C ABI version 2 implementation. -/// This is the ABI that provides a clean break with the legacy GCC ABI and -/// cleans up a number of things that were added to work around 1980s linkers. -class CGObjCGNUstep2 : public CGObjCGNUstep { - enum SectionKind - { - SelectorSection = 0, - ClassSection, - ClassReferenceSection, - CategorySection, - ProtocolSection, - ProtocolReferenceSection, - ClassAliasSection, - ConstantStringSection - }; - static const char *const SectionsBaseNames[8]; - template<SectionKind K> - std::string sectionName() { - std::string name(SectionsBaseNames[K]); - if (CGM.getTriple().isOSBinFormatCOFF()) - name += "$m"; - return name; - } - /// The GCC ABI superclass message lookup function. Takes a pointer to a - /// structure describing the receiver and the class, and a selector as - /// arguments. Returns the IMP for the corresponding method. - LazyRuntimeFunction MsgLookupSuperFn; - /// A flag indicating if we've emitted at least one protocol. - /// If we haven't, then we need to emit an empty protocol, to ensure that the - /// __start__objc_protocols and __stop__objc_protocols sections exist. - bool EmittedProtocol = false; - /// A flag indicating if we've emitted at least one protocol reference. - /// If we haven't, then we need to emit an empty protocol, to ensure that the - /// __start__objc_protocol_refs and __stop__objc_protocol_refs sections - /// exist. - bool EmittedProtocolRef = false; - /// A flag indicating if we've emitted at least one class. - /// If we haven't, then we need to emit an empty protocol, to ensure that the - /// __start__objc_classes and __stop__objc_classes sections / exist. - bool EmittedClass = false; - /// Generate the name of a symbol for a reference to a class. Accesses to - /// classes should be indirected via this. - std::string SymbolForClassRef(StringRef Name, bool isWeak) { - if (isWeak) - return (StringRef("._OBJC_WEAK_REF_CLASS_") + Name).str(); - else - return (StringRef("._OBJC_REF_CLASS_") + Name).str(); - } - /// Generate the name of a class symbol. - std::string SymbolForClass(StringRef Name) { - return (StringRef("._OBJC_CLASS_") + Name).str(); - } - void CallRuntimeFunction(CGBuilderTy &B, StringRef FunctionName, - ArrayRef<llvm::Value*> Args) { - SmallVector<llvm::Type *,8> Types; - for (auto *Arg : Args) - Types.push_back(Arg->getType()); - llvm::FunctionType *FT = llvm::FunctionType::get(B.getVoidTy(), Types, - false); - llvm::Value *Fn = CGM.CreateRuntimeFunction(FT, FunctionName); - B.CreateCall(Fn, Args); - } - - ConstantAddress GenerateConstantString(const StringLiteral *SL) override { - - auto Str = SL->getString(); - CharUnits Align = CGM.getPointerAlign(); - - // Look for an existing one - llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str); - if (old != ObjCStrings.end()) - return ConstantAddress(old->getValue(), Align); - - bool isNonASCII = SL->containsNonAscii(); - - auto LiteralLength = SL->getLength(); - - if ((CGM.getTarget().getPointerWidth(0) == 64) && - (LiteralLength < 9) && !isNonASCII) { - // Tiny strings are only used on 64-bit platforms. They store 8 7-bit - // ASCII characters in the high 56 bits, followed by a 4-bit length and a - // 3-bit tag (which is always 4). - uint64_t str = 0; - // Fill in the characters - for (unsigned i=0 ; i<LiteralLength ; i++) - str |= ((uint64_t)SL->getCodeUnit(i)) << ((64 - 4 - 3) - (i*7)); - // Fill in the length - str |= LiteralLength << 3; - // Set the tag - str |= 4; - auto *ObjCStr = llvm::ConstantExpr::getIntToPtr( - llvm::ConstantInt::get(Int64Ty, str), IdTy); - ObjCStrings[Str] = ObjCStr; - return ConstantAddress(ObjCStr, Align); - } - - StringRef StringClass = CGM.getLangOpts().ObjCConstantStringClass; - - if (StringClass.empty()) StringClass = "NSConstantString"; - - std::string Sym = SymbolForClass(StringClass); - - llvm::Constant *isa = TheModule.getNamedGlobal(Sym); - - if (!isa) - isa = new llvm::GlobalVariable(TheModule, IdTy, /* isConstant */false, - llvm::GlobalValue::ExternalLinkage, nullptr, Sym); - else if (isa->getType() != PtrToIdTy) - isa = llvm::ConstantExpr::getBitCast(isa, PtrToIdTy); - - // struct - // { - // Class isa; - // uint32_t flags; - // uint32_t length; // Number of codepoints - // uint32_t size; // Number of bytes - // uint32_t hash; - // const char *data; - // }; - - ConstantInitBuilder Builder(CGM); - auto Fields = Builder.beginStruct(); - Fields.add(isa); - // For now, all non-ASCII strings are represented as UTF-16. As such, the - // number of bytes is simply double the number of UTF-16 codepoints. In - // ASCII strings, the number of bytes is equal to the number of non-ASCII - // codepoints. - if (isNonASCII) { - unsigned NumU8CodeUnits = Str.size(); - // A UTF-16 representation of a unicode string contains at most the same - // number of code units as a UTF-8 representation. Allocate that much - // space, plus one for the final null character. - SmallVector<llvm::UTF16, 128> ToBuf(NumU8CodeUnits + 1); - const llvm::UTF8 *FromPtr = (const llvm::UTF8 *)Str.data(); - llvm::UTF16 *ToPtr = &ToBuf[0]; - (void)llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumU8CodeUnits, - &ToPtr, ToPtr + NumU8CodeUnits, llvm::strictConversion); - uint32_t StringLength = ToPtr - &ToBuf[0]; - // Add null terminator - *ToPtr = 0; - // Flags: 2 indicates UTF-16 encoding - Fields.addInt(Int32Ty, 2); - // Number of UTF-16 codepoints - Fields.addInt(Int32Ty, StringLength); - // Number of bytes - Fields.addInt(Int32Ty, StringLength * 2); - // Hash. Not currently initialised by the compiler. - Fields.addInt(Int32Ty, 0); - // pointer to the data string. - auto Arr = llvm::makeArrayRef(&ToBuf[0], ToPtr+1); - auto *C = llvm::ConstantDataArray::get(VMContext, Arr); - auto *Buffer = new llvm::GlobalVariable(TheModule, C->getType(), - /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, C, ".str"); - Buffer->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - Fields.add(Buffer); - } else { - // Flags: 0 indicates ASCII encoding - Fields.addInt(Int32Ty, 0); - // Number of UTF-16 codepoints, each ASCII byte is a UTF-16 codepoint - Fields.addInt(Int32Ty, Str.size()); - // Number of bytes - Fields.addInt(Int32Ty, Str.size()); - // Hash. Not currently initialised by the compiler. - Fields.addInt(Int32Ty, 0); - // Data pointer - Fields.add(MakeConstantString(Str)); - } - std::string StringName; - bool isNamed = !isNonASCII; - if (isNamed) { - StringName = ".objc_str_"; - for (int i=0,e=Str.size() ; i<e ; ++i) { - unsigned char c = Str[i]; - if (isalnum(c)) - StringName += c; - else if (c == ' ') - StringName += '_'; - else { - isNamed = false; - break; - } - } - } - auto *ObjCStrGV = - Fields.finishAndCreateGlobal( - isNamed ? StringRef(StringName) : ".objc_string", - Align, false, isNamed ? llvm::GlobalValue::LinkOnceODRLinkage - : llvm::GlobalValue::PrivateLinkage); - ObjCStrGV->setSection(sectionName<ConstantStringSection>()); - if (isNamed) { - ObjCStrGV->setComdat(TheModule.getOrInsertComdat(StringName)); - ObjCStrGV->setVisibility(llvm::GlobalValue::HiddenVisibility); - } - llvm::Constant *ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStrGV, IdTy); - ObjCStrings[Str] = ObjCStr; - ConstantStrings.push_back(ObjCStr); - return ConstantAddress(ObjCStr, Align); - } - - void PushProperty(ConstantArrayBuilder &PropertiesArray, - const ObjCPropertyDecl *property, - const Decl *OCD, - bool isSynthesized=true, bool - isDynamic=true) override { - // struct objc_property - // { - // const char *name; - // const char *attributes; - // const char *type; - // SEL getter; - // SEL setter; - // }; - auto Fields = PropertiesArray.beginStruct(PropertyMetadataTy); - ASTContext &Context = CGM.getContext(); - Fields.add(MakeConstantString(property->getNameAsString())); - std::string TypeStr = - CGM.getContext().getObjCEncodingForPropertyDecl(property, OCD); - Fields.add(MakeConstantString(TypeStr)); - std::string typeStr; - Context.getObjCEncodingForType(property->getType(), typeStr); - Fields.add(MakeConstantString(typeStr)); - auto addPropertyMethod = [&](const ObjCMethodDecl *accessor) { - if (accessor) { - std::string TypeStr = Context.getObjCEncodingForMethodDecl(accessor); - Fields.add(GetConstantSelector(accessor->getSelector(), TypeStr)); - } else { - Fields.add(NULLPtr); - } - }; - addPropertyMethod(property->getGetterMethodDecl()); - addPropertyMethod(property->getSetterMethodDecl()); - Fields.finishAndAddTo(PropertiesArray); - } - - llvm::Constant * - GenerateProtocolMethodList(ArrayRef<const ObjCMethodDecl*> Methods) override { - // struct objc_protocol_method_description - // { - // SEL selector; - // const char *types; - // }; - llvm::StructType *ObjCMethodDescTy = - llvm::StructType::get(CGM.getLLVMContext(), - { PtrToInt8Ty, PtrToInt8Ty }); - ASTContext &Context = CGM.getContext(); - ConstantInitBuilder Builder(CGM); - // struct objc_protocol_method_description_list - // { - // int count; - // int size; - // struct objc_protocol_method_description methods[]; - // }; - auto MethodList = Builder.beginStruct(); - // int count; - MethodList.addInt(IntTy, Methods.size()); - // int size; // sizeof(struct objc_method_description) - llvm::DataLayout td(&TheModule); - MethodList.addInt(IntTy, td.getTypeSizeInBits(ObjCMethodDescTy) / - CGM.getContext().getCharWidth()); - // struct objc_method_description[] - auto MethodArray = MethodList.beginArray(ObjCMethodDescTy); - for (auto *M : Methods) { - auto Method = MethodArray.beginStruct(ObjCMethodDescTy); - Method.add(CGObjCGNU::GetConstantSelector(M)); - Method.add(GetTypeString(Context.getObjCEncodingForMethodDecl(M, true))); - Method.finishAndAddTo(MethodArray); - } - MethodArray.finishAndAddTo(MethodList); - return MethodList.finishAndCreateGlobal(".objc_protocol_method_list", - CGM.getPointerAlign()); - } - llvm::Constant *GenerateCategoryProtocolList(const ObjCCategoryDecl *OCD) - override { - SmallVector<llvm::Constant*, 16> Protocols; - for (const auto *PI : OCD->getReferencedProtocols()) - Protocols.push_back( - llvm::ConstantExpr::getBitCast(GenerateProtocolRef(PI), - ProtocolPtrTy)); - return GenerateProtocolList(Protocols); - } - - llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper, - llvm::Value *cmd, MessageSendInfo &MSI) override { - // Don't access the slot unless we're trying to cache the result. - CGBuilderTy &Builder = CGF.Builder; - llvm::Value *lookupArgs[] = {CGObjCGNU::EnforceType(Builder, ObjCSuper, - PtrToObjCSuperTy).getPointer(), cmd}; - return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs); - } - - llvm::GlobalVariable *GetClassVar(StringRef Name, bool isWeak=false) { - std::string SymbolName = SymbolForClassRef(Name, isWeak); - auto *ClassSymbol = TheModule.getNamedGlobal(SymbolName); - if (ClassSymbol) - return ClassSymbol; - ClassSymbol = new llvm::GlobalVariable(TheModule, - IdTy, false, llvm::GlobalValue::ExternalLinkage, - nullptr, SymbolName); - // If this is a weak symbol, then we are creating a valid definition for - // the symbol, pointing to a weak definition of the real class pointer. If - // this is not a weak reference, then we are expecting another compilation - // unit to provide the real indirection symbol. - if (isWeak) - ClassSymbol->setInitializer(new llvm::GlobalVariable(TheModule, - Int8Ty, false, llvm::GlobalValue::ExternalWeakLinkage, - nullptr, SymbolForClass(Name))); - assert(ClassSymbol->getName() == SymbolName); - return ClassSymbol; - } - llvm::Value *GetClassNamed(CodeGenFunction &CGF, - const std::string &Name, - bool isWeak) override { - return CGF.Builder.CreateLoad(Address(GetClassVar(Name, isWeak), - CGM.getPointerAlign())); - } - int32_t FlagsForOwnership(Qualifiers::ObjCLifetime Ownership) { - // typedef enum { - // ownership_invalid = 0, - // ownership_strong = 1, - // ownership_weak = 2, - // ownership_unsafe = 3 - // } ivar_ownership; - int Flag; - switch (Ownership) { - case Qualifiers::OCL_Strong: - Flag = 1; - break; - case Qualifiers::OCL_Weak: - Flag = 2; - break; - case Qualifiers::OCL_ExplicitNone: - Flag = 3; - break; - case Qualifiers::OCL_None: - case Qualifiers::OCL_Autoreleasing: - assert(Ownership != Qualifiers::OCL_Autoreleasing); - Flag = 0; - } - return Flag; - } - llvm::Constant *GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames, - ArrayRef<llvm::Constant *> IvarTypes, - ArrayRef<llvm::Constant *> IvarOffsets, - ArrayRef<llvm::Constant *> IvarAlign, - ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership) override { - llvm_unreachable("Method should not be called!"); - } - - llvm::Constant *GenerateEmptyProtocol(StringRef ProtocolName) override { - std::string Name = SymbolForProtocol(ProtocolName); - auto *GV = TheModule.getGlobalVariable(Name); - if (!GV) { - // Emit a placeholder symbol. - GV = new llvm::GlobalVariable(TheModule, ProtocolTy, false, - llvm::GlobalValue::ExternalLinkage, nullptr, Name); - GV->setAlignment(CGM.getPointerAlign().getQuantity()); - } - return llvm::ConstantExpr::getBitCast(GV, ProtocolPtrTy); - } - - /// Existing protocol references. - llvm::StringMap<llvm::Constant*> ExistingProtocolRefs; - - llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF, - const ObjCProtocolDecl *PD) override { - auto Name = PD->getNameAsString(); - auto *&Ref = ExistingProtocolRefs[Name]; - if (!Ref) { - auto *&Protocol = ExistingProtocols[Name]; - if (!Protocol) - Protocol = GenerateProtocolRef(PD); - std::string RefName = SymbolForProtocolRef(Name); - assert(!TheModule.getGlobalVariable(RefName)); - // Emit a reference symbol. - auto GV = new llvm::GlobalVariable(TheModule, ProtocolPtrTy, - false, llvm::GlobalValue::LinkOnceODRLinkage, - llvm::ConstantExpr::getBitCast(Protocol, ProtocolPtrTy), RefName); - GV->setComdat(TheModule.getOrInsertComdat(RefName)); - GV->setSection(sectionName<ProtocolReferenceSection>()); - GV->setAlignment(CGM.getPointerAlign().getQuantity()); - Ref = GV; - } - EmittedProtocolRef = true; - return CGF.Builder.CreateAlignedLoad(Ref, CGM.getPointerAlign()); - } - - llvm::Constant *GenerateProtocolList(ArrayRef<llvm::Constant*> Protocols) { - llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(ProtocolPtrTy, - Protocols.size()); - llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy, - Protocols); - ConstantInitBuilder builder(CGM); - auto ProtocolBuilder = builder.beginStruct(); - ProtocolBuilder.addNullPointer(PtrTy); - ProtocolBuilder.addInt(SizeTy, Protocols.size()); - ProtocolBuilder.add(ProtocolArray); - return ProtocolBuilder.finishAndCreateGlobal(".objc_protocol_list", - CGM.getPointerAlign(), false, llvm::GlobalValue::InternalLinkage); - } - - void GenerateProtocol(const ObjCProtocolDecl *PD) override { - // Do nothing - we only emit referenced protocols. - } - llvm::Constant *GenerateProtocolRef(const ObjCProtocolDecl *PD) { - std::string ProtocolName = PD->getNameAsString(); - auto *&Protocol = ExistingProtocols[ProtocolName]; - if (Protocol) - return Protocol; - - EmittedProtocol = true; - - auto SymName = SymbolForProtocol(ProtocolName); - auto *OldGV = TheModule.getGlobalVariable(SymName); - - // Use the protocol definition, if there is one. - if (const ObjCProtocolDecl *Def = PD->getDefinition()) - PD = Def; - else { - // If there is no definition, then create an external linkage symbol and - // hope that someone else fills it in for us (and fail to link if they - // don't). - assert(!OldGV); - Protocol = new llvm::GlobalVariable(TheModule, ProtocolTy, - /*isConstant*/false, - llvm::GlobalValue::ExternalLinkage, nullptr, SymName); - return Protocol; - } - - SmallVector<llvm::Constant*, 16> Protocols; - for (const auto *PI : PD->protocols()) - Protocols.push_back( - llvm::ConstantExpr::getBitCast(GenerateProtocolRef(PI), - ProtocolPtrTy)); - llvm::Constant *ProtocolList = GenerateProtocolList(Protocols); - - // Collect information about methods - llvm::Constant *InstanceMethodList, *OptionalInstanceMethodList; - llvm::Constant *ClassMethodList, *OptionalClassMethodList; - EmitProtocolMethodList(PD->instance_methods(), InstanceMethodList, - OptionalInstanceMethodList); - EmitProtocolMethodList(PD->class_methods(), ClassMethodList, - OptionalClassMethodList); - - // The isa pointer must be set to a magic number so the runtime knows it's - // the correct layout. - ConstantInitBuilder builder(CGM); - auto ProtocolBuilder = builder.beginStruct(); - ProtocolBuilder.add(llvm::ConstantExpr::getIntToPtr( - llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy)); - ProtocolBuilder.add(MakeConstantString(ProtocolName)); - ProtocolBuilder.add(ProtocolList); - ProtocolBuilder.add(InstanceMethodList); - ProtocolBuilder.add(ClassMethodList); - ProtocolBuilder.add(OptionalInstanceMethodList); - ProtocolBuilder.add(OptionalClassMethodList); - // Required instance properties - ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, false, false)); - // Optional instance properties - ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, false, true)); - // Required class properties - ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, true, false)); - // Optional class properties - ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, true, true)); - - auto *GV = ProtocolBuilder.finishAndCreateGlobal(SymName, - CGM.getPointerAlign(), false, llvm::GlobalValue::ExternalLinkage); - GV->setSection(sectionName<ProtocolSection>()); - GV->setComdat(TheModule.getOrInsertComdat(SymName)); - if (OldGV) { - OldGV->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(GV, - OldGV->getType())); - OldGV->removeFromParent(); - GV->setName(SymName); - } - Protocol = GV; - return GV; - } - llvm::Constant *EnforceType(llvm::Constant *Val, llvm::Type *Ty) { - if (Val->getType() == Ty) - return Val; - return llvm::ConstantExpr::getBitCast(Val, Ty); - } - llvm::Value *GetTypedSelector(CodeGenFunction &CGF, Selector Sel, - const std::string &TypeEncoding) override { - return GetConstantSelector(Sel, TypeEncoding); - } - llvm::Constant *GetTypeString(llvm::StringRef TypeEncoding) { - if (TypeEncoding.empty()) - return NULLPtr; - std::string MangledTypes = TypeEncoding; - std::replace(MangledTypes.begin(), MangledTypes.end(), - '@', '\1'); - std::string TypesVarName = ".objc_sel_types_" + MangledTypes; - auto *TypesGlobal = TheModule.getGlobalVariable(TypesVarName); - if (!TypesGlobal) { - llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext, - TypeEncoding); - auto *GV = new llvm::GlobalVariable(TheModule, Init->getType(), - true, llvm::GlobalValue::LinkOnceODRLinkage, Init, TypesVarName); - GV->setComdat(TheModule.getOrInsertComdat(TypesVarName)); - GV->setVisibility(llvm::GlobalValue::HiddenVisibility); - TypesGlobal = GV; - } - return llvm::ConstantExpr::getGetElementPtr(TypesGlobal->getValueType(), - TypesGlobal, Zeros); - } - llvm::Constant *GetConstantSelector(Selector Sel, - const std::string &TypeEncoding) override { - // @ is used as a special character in symbol names (used for symbol - // versioning), so mangle the name to not include it. Replace it with a - // character that is not a valid type encoding character (and, being - // non-printable, never will be!) - std::string MangledTypes = TypeEncoding; - std::replace(MangledTypes.begin(), MangledTypes.end(), - '@', '\1'); - auto SelVarName = (StringRef(".objc_selector_") + Sel.getAsString() + "_" + - MangledTypes).str(); - if (auto *GV = TheModule.getNamedGlobal(SelVarName)) - return EnforceType(GV, SelectorTy); - ConstantInitBuilder builder(CGM); - auto SelBuilder = builder.beginStruct(); - SelBuilder.add(ExportUniqueString(Sel.getAsString(), ".objc_sel_name_", - true)); - SelBuilder.add(GetTypeString(TypeEncoding)); - auto *GV = SelBuilder.finishAndCreateGlobal(SelVarName, - CGM.getPointerAlign(), false, llvm::GlobalValue::LinkOnceODRLinkage); - GV->setComdat(TheModule.getOrInsertComdat(SelVarName)); - GV->setVisibility(llvm::GlobalValue::HiddenVisibility); - GV->setSection(sectionName<SelectorSection>()); - auto *SelVal = EnforceType(GV, SelectorTy); - return SelVal; - } - llvm::StructType *emptyStruct = nullptr; - - /// Return pointers to the start and end of a section. On ELF platforms, we - /// use the __start_ and __stop_ symbols that GNU-compatible linkers will set - /// to the start and end of section names, as long as those section names are - /// valid identifiers and the symbols are referenced but not defined. On - /// Windows, we use the fact that MSVC-compatible linkers will lexically sort - /// by subsections and place everything that we want to reference in a middle - /// subsection and then insert zero-sized symbols in subsections a and z. - std::pair<llvm::Constant*,llvm::Constant*> - GetSectionBounds(StringRef Section) { - if (CGM.getTriple().isOSBinFormatCOFF()) { - if (emptyStruct == nullptr) { - emptyStruct = llvm::StructType::create(VMContext, ".objc_section_sentinel"); - emptyStruct->setBody({}, /*isPacked*/true); - } - auto ZeroInit = llvm::Constant::getNullValue(emptyStruct); - auto Sym = [&](StringRef Prefix, StringRef SecSuffix) { - auto *Sym = new llvm::GlobalVariable(TheModule, emptyStruct, - /*isConstant*/false, - llvm::GlobalValue::LinkOnceODRLinkage, ZeroInit, Prefix + - Section); - Sym->setVisibility(llvm::GlobalValue::HiddenVisibility); - Sym->setSection((Section + SecSuffix).str()); - Sym->setComdat(TheModule.getOrInsertComdat((Prefix + - Section).str())); - Sym->setAlignment(1); - return Sym; - }; - return { Sym("__start_", "$a"), Sym("__stop", "$z") }; - } - auto *Start = new llvm::GlobalVariable(TheModule, PtrTy, - /*isConstant*/false, - llvm::GlobalValue::ExternalLinkage, nullptr, StringRef("__start_") + - Section); - Start->setVisibility(llvm::GlobalValue::HiddenVisibility); - auto *Stop = new llvm::GlobalVariable(TheModule, PtrTy, - /*isConstant*/false, - llvm::GlobalValue::ExternalLinkage, nullptr, StringRef("__stop_") + - Section); - Stop->setVisibility(llvm::GlobalValue::HiddenVisibility); - return { Start, Stop }; - } - CatchTypeInfo getCatchAllTypeInfo() override { - return CGM.getCXXABI().getCatchAllTypeInfo(); - } - llvm::Function *ModuleInitFunction() override { - llvm::Function *LoadFunction = llvm::Function::Create( - llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false), - llvm::GlobalValue::LinkOnceODRLinkage, ".objcv2_load_function", - &TheModule); - LoadFunction->setVisibility(llvm::GlobalValue::HiddenVisibility); - LoadFunction->setComdat(TheModule.getOrInsertComdat(".objcv2_load_function")); - - llvm::BasicBlock *EntryBB = - llvm::BasicBlock::Create(VMContext, "entry", LoadFunction); - CGBuilderTy B(CGM, VMContext); - B.SetInsertPoint(EntryBB); - ConstantInitBuilder builder(CGM); - auto InitStructBuilder = builder.beginStruct(); - InitStructBuilder.addInt(Int64Ty, 0); - for (auto *s : SectionsBaseNames) { - auto bounds = GetSectionBounds(s); - InitStructBuilder.add(bounds.first); - InitStructBuilder.add(bounds.second); - }; - auto *InitStruct = InitStructBuilder.finishAndCreateGlobal(".objc_init", - CGM.getPointerAlign(), false, llvm::GlobalValue::LinkOnceODRLinkage); - InitStruct->setVisibility(llvm::GlobalValue::HiddenVisibility); - InitStruct->setComdat(TheModule.getOrInsertComdat(".objc_init")); - - CallRuntimeFunction(B, "__objc_load", {InitStruct});; - B.CreateRetVoid(); - // Make sure that the optimisers don't delete this function. - CGM.addCompilerUsedGlobal(LoadFunction); - // FIXME: Currently ELF only! - // We have to do this by hand, rather than with @llvm.ctors, so that the - // linker can remove the duplicate invocations. - auto *InitVar = new llvm::GlobalVariable(TheModule, LoadFunction->getType(), - /*isConstant*/true, llvm::GlobalValue::LinkOnceAnyLinkage, - LoadFunction, ".objc_ctor"); - // Check that this hasn't been renamed. This shouldn't happen, because - // this function should be called precisely once. - assert(InitVar->getName() == ".objc_ctor"); - // In Windows, initialisers are sorted by the suffix. XCL is for library - // initialisers, which run before user initialisers. We are running - // Objective-C loads at the end of library load. This means +load methods - // will run before any other static constructors, but that static - // constructors can see a fully initialised Objective-C state. - if (CGM.getTriple().isOSBinFormatCOFF()) - InitVar->setSection(".CRT$XCLz"); - else - InitVar->setSection(".ctors"); - InitVar->setVisibility(llvm::GlobalValue::HiddenVisibility); - InitVar->setComdat(TheModule.getOrInsertComdat(".objc_ctor")); - CGM.addUsedGlobal(InitVar); - for (auto *C : Categories) { - auto *Cat = cast<llvm::GlobalVariable>(C->stripPointerCasts()); - Cat->setSection(sectionName<CategorySection>()); - CGM.addUsedGlobal(Cat); - } - auto createNullGlobal = [&](StringRef Name, ArrayRef<llvm::Constant*> Init, - StringRef Section) { - auto nullBuilder = builder.beginStruct(); - for (auto *F : Init) - nullBuilder.add(F); - auto GV = nullBuilder.finishAndCreateGlobal(Name, CGM.getPointerAlign(), - false, llvm::GlobalValue::LinkOnceODRLinkage); - GV->setSection(Section); - GV->setComdat(TheModule.getOrInsertComdat(Name)); - GV->setVisibility(llvm::GlobalValue::HiddenVisibility); - CGM.addUsedGlobal(GV); - return GV; - }; - for (auto clsAlias : ClassAliases) - createNullGlobal(std::string(".objc_class_alias") + - clsAlias.second, { MakeConstantString(clsAlias.second), - GetClassVar(clsAlias.first) }, sectionName<ClassAliasSection>()); - // On ELF platforms, add a null value for each special section so that we - // can always guarantee that the _start and _stop symbols will exist and be - // meaningful. This is not required on COFF platforms, where our start and - // stop symbols will create the section. - if (!CGM.getTriple().isOSBinFormatCOFF()) { - createNullGlobal(".objc_null_selector", {NULLPtr, NULLPtr}, - sectionName<SelectorSection>()); - if (Categories.empty()) - createNullGlobal(".objc_null_category", {NULLPtr, NULLPtr, - NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr}, - sectionName<CategorySection>()); - if (!EmittedClass) { - createNullGlobal(".objc_null_cls_init_ref", NULLPtr, - sectionName<ClassSection>()); - createNullGlobal(".objc_null_class_ref", { NULLPtr, NULLPtr }, - sectionName<ClassReferenceSection>()); - } - if (!EmittedProtocol) - createNullGlobal(".objc_null_protocol", {NULLPtr, NULLPtr, NULLPtr, - NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, - NULLPtr}, sectionName<ProtocolSection>()); - if (!EmittedProtocolRef) - createNullGlobal(".objc_null_protocol_ref", {NULLPtr}, - sectionName<ProtocolReferenceSection>()); - if (ClassAliases.empty()) - createNullGlobal(".objc_null_class_alias", { NULLPtr, NULLPtr }, - sectionName<ClassAliasSection>()); - if (ConstantStrings.empty()) { - auto i32Zero = llvm::ConstantInt::get(Int32Ty, 0); - createNullGlobal(".objc_null_constant_string", { NULLPtr, i32Zero, - i32Zero, i32Zero, i32Zero, NULLPtr }, - sectionName<ConstantStringSection>()); - } - } - ConstantStrings.clear(); - Categories.clear(); - Classes.clear(); - return nullptr; - } - /// In the v2 ABI, ivar offset variables use the type encoding in their name - /// to trigger linker failures if the types don't match. - std::string GetIVarOffsetVariableName(const ObjCInterfaceDecl *ID, - const ObjCIvarDecl *Ivar) override { - std::string TypeEncoding; - CGM.getContext().getObjCEncodingForType(Ivar->getType(), TypeEncoding); - // Prevent the @ from being interpreted as a symbol version. - std::replace(TypeEncoding.begin(), TypeEncoding.end(), - '@', '\1'); - const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString() - + '.' + Ivar->getNameAsString() + '.' + TypeEncoding; - return Name; - } - llvm::Value *EmitIvarOffset(CodeGenFunction &CGF, - const ObjCInterfaceDecl *Interface, - const ObjCIvarDecl *Ivar) override { - const std::string Name = GetIVarOffsetVariableName(Ivar->getContainingInterface(), Ivar); - llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name); - if (!IvarOffsetPointer) - IvarOffsetPointer = new llvm::GlobalVariable(TheModule, IntTy, false, - llvm::GlobalValue::ExternalLinkage, nullptr, Name); - CharUnits Align = CGM.getIntAlign(); - llvm::Value *Offset = CGF.Builder.CreateAlignedLoad(IvarOffsetPointer, Align); - if (Offset->getType() != PtrDiffTy) - Offset = CGF.Builder.CreateZExtOrBitCast(Offset, PtrDiffTy); - return Offset; - } - void GenerateClass(const ObjCImplementationDecl *OID) override { - ASTContext &Context = CGM.getContext(); - - // Get the class name - ObjCInterfaceDecl *classDecl = - const_cast<ObjCInterfaceDecl *>(OID->getClassInterface()); - std::string className = classDecl->getNameAsString(); - auto *classNameConstant = MakeConstantString(className); - - ConstantInitBuilder builder(CGM); - auto metaclassFields = builder.beginStruct(); - // struct objc_class *isa; - metaclassFields.addNullPointer(PtrTy); - // struct objc_class *super_class; - metaclassFields.addNullPointer(PtrTy); - // const char *name; - metaclassFields.add(classNameConstant); - // long version; - metaclassFields.addInt(LongTy, 0); - // unsigned long info; - // objc_class_flag_meta - metaclassFields.addInt(LongTy, 1); - // long instance_size; - // Setting this to zero is consistent with the older ABI, but it might be - // more sensible to set this to sizeof(struct objc_class) - metaclassFields.addInt(LongTy, 0); - // struct objc_ivar_list *ivars; - metaclassFields.addNullPointer(PtrTy); - // struct objc_method_list *methods - // FIXME: Almost identical code is copied and pasted below for the - // class, but refactoring it cleanly requires C++14 generic lambdas. - if (OID->classmeth_begin() == OID->classmeth_end()) - metaclassFields.addNullPointer(PtrTy); - else { - SmallVector<ObjCMethodDecl*, 16> ClassMethods; - ClassMethods.insert(ClassMethods.begin(), OID->classmeth_begin(), - OID->classmeth_end()); - metaclassFields.addBitCast( - GenerateMethodList(className, "", ClassMethods, true), - PtrTy); - } - // void *dtable; - metaclassFields.addNullPointer(PtrTy); - // IMP cxx_construct; - metaclassFields.addNullPointer(PtrTy); - // IMP cxx_destruct; - metaclassFields.addNullPointer(PtrTy); - // struct objc_class *subclass_list - metaclassFields.addNullPointer(PtrTy); - // struct objc_class *sibling_class - metaclassFields.addNullPointer(PtrTy); - // struct objc_protocol_list *protocols; - metaclassFields.addNullPointer(PtrTy); - // struct reference_list *extra_data; - metaclassFields.addNullPointer(PtrTy); - // long abi_version; - metaclassFields.addInt(LongTy, 0); - // struct objc_property_list *properties - metaclassFields.add(GeneratePropertyList(OID, classDecl, /*isClassProperty*/true)); - - auto *metaclass = metaclassFields.finishAndCreateGlobal("._OBJC_METACLASS_" - + className, CGM.getPointerAlign()); - - auto classFields = builder.beginStruct(); - // struct objc_class *isa; - classFields.add(metaclass); - // struct objc_class *super_class; - // Get the superclass name. - const ObjCInterfaceDecl * SuperClassDecl = - OID->getClassInterface()->getSuperClass(); - if (SuperClassDecl) { - auto SuperClassName = SymbolForClass(SuperClassDecl->getNameAsString()); - llvm::Constant *SuperClass = TheModule.getNamedGlobal(SuperClassName); - if (!SuperClass) - { - SuperClass = new llvm::GlobalVariable(TheModule, PtrTy, false, - llvm::GlobalValue::ExternalLinkage, nullptr, SuperClassName); - } - classFields.add(llvm::ConstantExpr::getBitCast(SuperClass, PtrTy)); - } else - classFields.addNullPointer(PtrTy); - // const char *name; - classFields.add(classNameConstant); - // long version; - classFields.addInt(LongTy, 0); - // unsigned long info; - // !objc_class_flag_meta - classFields.addInt(LongTy, 0); - // long instance_size; - int superInstanceSize = !SuperClassDecl ? 0 : - Context.getASTObjCInterfaceLayout(SuperClassDecl).getSize().getQuantity(); - // Instance size is negative for classes that have not yet had their ivar - // layout calculated. - classFields.addInt(LongTy, - 0 - (Context.getASTObjCImplementationLayout(OID).getSize().getQuantity() - - superInstanceSize)); - - if (classDecl->all_declared_ivar_begin() == nullptr) - classFields.addNullPointer(PtrTy); - else { - int ivar_count = 0; - for (const ObjCIvarDecl *IVD = classDecl->all_declared_ivar_begin(); IVD; - IVD = IVD->getNextIvar()) ivar_count++; - llvm::DataLayout td(&TheModule); - // struct objc_ivar_list *ivars; - ConstantInitBuilder b(CGM); - auto ivarListBuilder = b.beginStruct(); - // int count; - ivarListBuilder.addInt(IntTy, ivar_count); - // size_t size; - llvm::StructType *ObjCIvarTy = llvm::StructType::get( - PtrToInt8Ty, - PtrToInt8Ty, - PtrToInt8Ty, - Int32Ty, - Int32Ty); - ivarListBuilder.addInt(SizeTy, td.getTypeSizeInBits(ObjCIvarTy) / - CGM.getContext().getCharWidth()); - // struct objc_ivar ivars[] - auto ivarArrayBuilder = ivarListBuilder.beginArray(); - CodeGenTypes &Types = CGM.getTypes(); - for (const ObjCIvarDecl *IVD = classDecl->all_declared_ivar_begin(); IVD; - IVD = IVD->getNextIvar()) { - auto ivarTy = IVD->getType(); - auto ivarBuilder = ivarArrayBuilder.beginStruct(); - // const char *name; - ivarBuilder.add(MakeConstantString(IVD->getNameAsString())); - // const char *type; - std::string TypeStr; - //Context.getObjCEncodingForType(ivarTy, TypeStr, IVD, true); - Context.getObjCEncodingForMethodParameter(Decl::OBJC_TQ_None, ivarTy, TypeStr, true); - ivarBuilder.add(MakeConstantString(TypeStr)); - // int *offset; - uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD); - uint64_t Offset = BaseOffset - superInstanceSize; - llvm::Constant *OffsetValue = llvm::ConstantInt::get(IntTy, Offset); - std::string OffsetName = GetIVarOffsetVariableName(classDecl, IVD); - llvm::GlobalVariable *OffsetVar = TheModule.getGlobalVariable(OffsetName); - if (OffsetVar) - OffsetVar->setInitializer(OffsetValue); - else - OffsetVar = new llvm::GlobalVariable(TheModule, IntTy, - false, llvm::GlobalValue::ExternalLinkage, - OffsetValue, OffsetName); - auto ivarVisibility = - (IVD->getAccessControl() == ObjCIvarDecl::Private || - IVD->getAccessControl() == ObjCIvarDecl::Package || - classDecl->getVisibility() == HiddenVisibility) ? - llvm::GlobalValue::HiddenVisibility : - llvm::GlobalValue::DefaultVisibility; - OffsetVar->setVisibility(ivarVisibility); - ivarBuilder.add(OffsetVar); - // Ivar size - ivarBuilder.addInt(Int32Ty, - td.getTypeSizeInBits(Types.ConvertType(ivarTy)) / - CGM.getContext().getCharWidth()); - // Alignment will be stored as a base-2 log of the alignment. - int align = llvm::Log2_32(Context.getTypeAlignInChars(ivarTy).getQuantity()); - // Objects that require more than 2^64-byte alignment should be impossible! - assert(align < 64); - // uint32_t flags; - // Bits 0-1 are ownership. - // Bit 2 indicates an extended type encoding - // Bits 3-8 contain log2(aligment) - ivarBuilder.addInt(Int32Ty, - (align << 3) | (1<<2) | - FlagsForOwnership(ivarTy.getQualifiers().getObjCLifetime())); - ivarBuilder.finishAndAddTo(ivarArrayBuilder); - } - ivarArrayBuilder.finishAndAddTo(ivarListBuilder); - auto ivarList = ivarListBuilder.finishAndCreateGlobal(".objc_ivar_list", - CGM.getPointerAlign(), /*constant*/ false, - llvm::GlobalValue::PrivateLinkage); - classFields.add(ivarList); - } - // struct objc_method_list *methods - SmallVector<const ObjCMethodDecl*, 16> InstanceMethods; - InstanceMethods.insert(InstanceMethods.begin(), OID->instmeth_begin(), - OID->instmeth_end()); - for (auto *propImpl : OID->property_impls()) - if (propImpl->getPropertyImplementation() == - ObjCPropertyImplDecl::Synthesize) { - ObjCPropertyDecl *prop = propImpl->getPropertyDecl(); - auto addIfExists = [&](const ObjCMethodDecl* OMD) { - if (OMD) - InstanceMethods.push_back(OMD); - }; - addIfExists(prop->getGetterMethodDecl()); - addIfExists(prop->getSetterMethodDecl()); - } - - if (InstanceMethods.size() == 0) - classFields.addNullPointer(PtrTy); - else - classFields.addBitCast( - GenerateMethodList(className, "", InstanceMethods, false), - PtrTy); - // void *dtable; - classFields.addNullPointer(PtrTy); - // IMP cxx_construct; - classFields.addNullPointer(PtrTy); - // IMP cxx_destruct; - classFields.addNullPointer(PtrTy); - // struct objc_class *subclass_list - classFields.addNullPointer(PtrTy); - // struct objc_class *sibling_class - classFields.addNullPointer(PtrTy); - // struct objc_protocol_list *protocols; - SmallVector<llvm::Constant*, 16> Protocols; - for (const auto *I : classDecl->protocols()) - Protocols.push_back( - llvm::ConstantExpr::getBitCast(GenerateProtocolRef(I), - ProtocolPtrTy)); - if (Protocols.empty()) - classFields.addNullPointer(PtrTy); - else - classFields.add(GenerateProtocolList(Protocols)); - // struct reference_list *extra_data; - classFields.addNullPointer(PtrTy); - // long abi_version; - classFields.addInt(LongTy, 0); - // struct objc_property_list *properties - classFields.add(GeneratePropertyList(OID, classDecl)); - - auto *classStruct = - classFields.finishAndCreateGlobal(SymbolForClass(className), - CGM.getPointerAlign(), false, llvm::GlobalValue::ExternalLinkage); - - if (CGM.getTriple().isOSBinFormatCOFF()) { - auto Storage = llvm::GlobalValue::DefaultStorageClass; - if (OID->getClassInterface()->hasAttr<DLLImportAttr>()) - Storage = llvm::GlobalValue::DLLImportStorageClass; - else if (OID->getClassInterface()->hasAttr<DLLExportAttr>()) - Storage = llvm::GlobalValue::DLLExportStorageClass; - cast<llvm::GlobalValue>(classStruct)->setDLLStorageClass(Storage); - } - - auto *classRefSymbol = GetClassVar(className); - classRefSymbol->setSection(sectionName<ClassReferenceSection>()); - classRefSymbol->setInitializer(llvm::ConstantExpr::getBitCast(classStruct, IdTy)); - - - // Resolve the class aliases, if they exist. - // FIXME: Class pointer aliases shouldn't exist! - if (ClassPtrAlias) { - ClassPtrAlias->replaceAllUsesWith( - llvm::ConstantExpr::getBitCast(classStruct, IdTy)); - ClassPtrAlias->eraseFromParent(); - ClassPtrAlias = nullptr; - } - if (auto Placeholder = - TheModule.getNamedGlobal(SymbolForClass(className))) - if (Placeholder != classStruct) { - Placeholder->replaceAllUsesWith( - llvm::ConstantExpr::getBitCast(classStruct, Placeholder->getType())); - Placeholder->eraseFromParent(); - classStruct->setName(SymbolForClass(className)); - } - if (MetaClassPtrAlias) { - MetaClassPtrAlias->replaceAllUsesWith( - llvm::ConstantExpr::getBitCast(metaclass, IdTy)); - MetaClassPtrAlias->eraseFromParent(); - MetaClassPtrAlias = nullptr; - } - assert(classStruct->getName() == SymbolForClass(className)); - - auto classInitRef = new llvm::GlobalVariable(TheModule, - classStruct->getType(), false, llvm::GlobalValue::ExternalLinkage, - classStruct, "._OBJC_INIT_CLASS_" + className); - classInitRef->setSection(sectionName<ClassSection>()); - CGM.addUsedGlobal(classInitRef); - - EmittedClass = true; - } - public: - CGObjCGNUstep2(CodeGenModule &Mod) : CGObjCGNUstep(Mod, 10, 4, 2) { - MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy, - PtrToObjCSuperTy, SelectorTy); - // struct objc_property - // { - // const char *name; - // const char *attributes; - // const char *type; - // SEL getter; - // SEL setter; - // } - PropertyMetadataTy = - llvm::StructType::get(CGM.getLLVMContext(), - { PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty }); - } - -}; - -const char *const CGObjCGNUstep2::SectionsBaseNames[8] = -{ -"__objc_selectors", -"__objc_classes", -"__objc_class_refs", -"__objc_cats", -"__objc_protocols", -"__objc_protocol_refs", -"__objc_class_aliases", -"__objc_constant_string" -}; - -/// Support for the ObjFW runtime. -class CGObjCObjFW: public CGObjCGNU { -protected: - /// The GCC ABI message lookup function. Returns an IMP pointing to the - /// method implementation for this message. - LazyRuntimeFunction MsgLookupFn; - /// stret lookup function. While this does not seem to make sense at the - /// first look, this is required to call the correct forwarding function. - LazyRuntimeFunction MsgLookupFnSRet; - /// The GCC ABI superclass message lookup function. Takes a pointer to a - /// structure describing the receiver and the class, and a selector as - /// arguments. Returns the IMP for the corresponding method. - LazyRuntimeFunction MsgLookupSuperFn, MsgLookupSuperFnSRet; - - llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver, - llvm::Value *cmd, llvm::MDNode *node, - MessageSendInfo &MSI) override { - CGBuilderTy &Builder = CGF.Builder; - llvm::Value *args[] = { - EnforceType(Builder, Receiver, IdTy), - EnforceType(Builder, cmd, SelectorTy) }; - - llvm::CallSite imp; - if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) - imp = CGF.EmitRuntimeCallOrInvoke(MsgLookupFnSRet, args); - else - imp = CGF.EmitRuntimeCallOrInvoke(MsgLookupFn, args); - - imp->setMetadata(msgSendMDKind, node); - return imp.getInstruction(); - } - - llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper, - llvm::Value *cmd, MessageSendInfo &MSI) override { - CGBuilderTy &Builder = CGF.Builder; - llvm::Value *lookupArgs[] = { - EnforceType(Builder, ObjCSuper.getPointer(), PtrToObjCSuperTy), cmd, - }; - - if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) - return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFnSRet, lookupArgs); - else - return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs); - } - - llvm::Value *GetClassNamed(CodeGenFunction &CGF, const std::string &Name, - bool isWeak) override { - if (isWeak) - return CGObjCGNU::GetClassNamed(CGF, Name, isWeak); - - EmitClassRef(Name); - std::string SymbolName = "_OBJC_CLASS_" + Name; - llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(SymbolName); - if (!ClassSymbol) - ClassSymbol = new llvm::GlobalVariable(TheModule, LongTy, false, - llvm::GlobalValue::ExternalLinkage, - nullptr, SymbolName); - return ClassSymbol; - } - -public: - CGObjCObjFW(CodeGenModule &Mod): CGObjCGNU(Mod, 9, 3) { - // IMP objc_msg_lookup(id, SEL); - MsgLookupFn.init(&CGM, "objc_msg_lookup", IMPTy, IdTy, SelectorTy); - MsgLookupFnSRet.init(&CGM, "objc_msg_lookup_stret", IMPTy, IdTy, - SelectorTy); - // IMP objc_msg_lookup_super(struct objc_super*, SEL); - MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy, - PtrToObjCSuperTy, SelectorTy); - MsgLookupSuperFnSRet.init(&CGM, "objc_msg_lookup_super_stret", IMPTy, - PtrToObjCSuperTy, SelectorTy); - } -}; -} // end anonymous namespace - -/// Emits a reference to a dummy variable which is emitted with each class. -/// This ensures that a linker error will be generated when trying to link -/// together modules where a referenced class is not defined. -void CGObjCGNU::EmitClassRef(const std::string &className) { - std::string symbolRef = "__objc_class_ref_" + className; - // Don't emit two copies of the same symbol - if (TheModule.getGlobalVariable(symbolRef)) - return; - std::string symbolName = "__objc_class_name_" + className; - llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName); - if (!ClassSymbol) { - ClassSymbol = new llvm::GlobalVariable(TheModule, LongTy, false, - llvm::GlobalValue::ExternalLinkage, - nullptr, symbolName); - } - new llvm::GlobalVariable(TheModule, ClassSymbol->getType(), true, - llvm::GlobalValue::WeakAnyLinkage, ClassSymbol, symbolRef); -} - -CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion, - unsigned protocolClassVersion, unsigned classABI) - : CGObjCRuntime(cgm), TheModule(CGM.getModule()), - VMContext(cgm.getLLVMContext()), ClassPtrAlias(nullptr), - MetaClassPtrAlias(nullptr), RuntimeVersion(runtimeABIVersion), - ProtocolVersion(protocolClassVersion), ClassABIVersion(classABI) { - - msgSendMDKind = VMContext.getMDKindID("GNUObjCMessageSend"); - usesSEHExceptions = - cgm.getContext().getTargetInfo().getTriple().isWindowsMSVCEnvironment(); - - CodeGenTypes &Types = CGM.getTypes(); - IntTy = cast<llvm::IntegerType>( - Types.ConvertType(CGM.getContext().IntTy)); - LongTy = cast<llvm::IntegerType>( - Types.ConvertType(CGM.getContext().LongTy)); - SizeTy = cast<llvm::IntegerType>( - Types.ConvertType(CGM.getContext().getSizeType())); - PtrDiffTy = cast<llvm::IntegerType>( - Types.ConvertType(CGM.getContext().getPointerDiffType())); - BoolTy = CGM.getTypes().ConvertType(CGM.getContext().BoolTy); - - Int8Ty = llvm::Type::getInt8Ty(VMContext); - // C string type. Used in lots of places. - PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty); - ProtocolPtrTy = llvm::PointerType::getUnqual( - Types.ConvertType(CGM.getContext().getObjCProtoType())); - - Zeros[0] = llvm::ConstantInt::get(LongTy, 0); - Zeros[1] = Zeros[0]; - NULLPtr = llvm::ConstantPointerNull::get(PtrToInt8Ty); - // Get the selector Type. - QualType selTy = CGM.getContext().getObjCSelType(); - if (QualType() == selTy) { - SelectorTy = PtrToInt8Ty; - } else { - SelectorTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(selTy)); - } - - PtrToIntTy = llvm::PointerType::getUnqual(IntTy); - PtrTy = PtrToInt8Ty; - - Int32Ty = llvm::Type::getInt32Ty(VMContext); - Int64Ty = llvm::Type::getInt64Ty(VMContext); - - IntPtrTy = - CGM.getDataLayout().getPointerSizeInBits() == 32 ? Int32Ty : Int64Ty; - - // Object type - QualType UnqualIdTy = CGM.getContext().getObjCIdType(); - ASTIdTy = CanQualType(); - if (UnqualIdTy != QualType()) { - ASTIdTy = CGM.getContext().getCanonicalType(UnqualIdTy); - IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy)); - } else { - IdTy = PtrToInt8Ty; - } - PtrToIdTy = llvm::PointerType::getUnqual(IdTy); - ProtocolTy = llvm::StructType::get(IdTy, - PtrToInt8Ty, // name - PtrToInt8Ty, // protocols - PtrToInt8Ty, // instance methods - PtrToInt8Ty, // class methods - PtrToInt8Ty, // optional instance methods - PtrToInt8Ty, // optional class methods - PtrToInt8Ty, // properties - PtrToInt8Ty);// optional properties - - // struct objc_property_gsv1 - // { - // const char *name; - // char attributes; - // char attributes2; - // char unused1; - // char unused2; - // const char *getter_name; - // const char *getter_types; - // const char *setter_name; - // const char *setter_types; - // } - PropertyMetadataTy = llvm::StructType::get(CGM.getLLVMContext(), { - PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty, - PtrToInt8Ty, PtrToInt8Ty }); - - ObjCSuperTy = llvm::StructType::get(IdTy, IdTy); - PtrToObjCSuperTy = llvm::PointerType::getUnqual(ObjCSuperTy); - - llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); - - // void objc_exception_throw(id); - ExceptionThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy); - ExceptionReThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy); - // int objc_sync_enter(id); - SyncEnterFn.init(&CGM, "objc_sync_enter", IntTy, IdTy); - // int objc_sync_exit(id); - SyncExitFn.init(&CGM, "objc_sync_exit", IntTy, IdTy); - - // void objc_enumerationMutation (id) - EnumerationMutationFn.init(&CGM, "objc_enumerationMutation", VoidTy, IdTy); - - // id objc_getProperty(id, SEL, ptrdiff_t, BOOL) - GetPropertyFn.init(&CGM, "objc_getProperty", IdTy, IdTy, SelectorTy, - PtrDiffTy, BoolTy); - // void objc_setProperty(id, SEL, ptrdiff_t, id, BOOL, BOOL) - SetPropertyFn.init(&CGM, "objc_setProperty", VoidTy, IdTy, SelectorTy, - PtrDiffTy, IdTy, BoolTy, BoolTy); - // void objc_setPropertyStruct(void*, void*, ptrdiff_t, BOOL, BOOL) - GetStructPropertyFn.init(&CGM, "objc_getPropertyStruct", VoidTy, PtrTy, PtrTy, - PtrDiffTy, BoolTy, BoolTy); - // void objc_setPropertyStruct(void*, void*, ptrdiff_t, BOOL, BOOL) - SetStructPropertyFn.init(&CGM, "objc_setPropertyStruct", VoidTy, PtrTy, PtrTy, - PtrDiffTy, BoolTy, BoolTy); - - // IMP type - llvm::Type *IMPArgs[] = { IdTy, SelectorTy }; - IMPTy = llvm::PointerType::getUnqual(llvm::FunctionType::get(IdTy, IMPArgs, - true)); - - const LangOptions &Opts = CGM.getLangOpts(); - if ((Opts.getGC() != LangOptions::NonGC) || Opts.ObjCAutoRefCount) - RuntimeVersion = 10; - - // Don't bother initialising the GC stuff unless we're compiling in GC mode - if (Opts.getGC() != LangOptions::NonGC) { - // This is a bit of an hack. We should sort this out by having a proper - // CGObjCGNUstep subclass for GC, but we may want to really support the old - // ABI and GC added in ObjectiveC2.framework, so we fudge it a bit for now - // Get selectors needed in GC mode - RetainSel = GetNullarySelector("retain", CGM.getContext()); - ReleaseSel = GetNullarySelector("release", CGM.getContext()); - AutoreleaseSel = GetNullarySelector("autorelease", CGM.getContext()); - - // Get functions needed in GC mode - - // id objc_assign_ivar(id, id, ptrdiff_t); - IvarAssignFn.init(&CGM, "objc_assign_ivar", IdTy, IdTy, IdTy, PtrDiffTy); - // id objc_assign_strongCast (id, id*) - StrongCastAssignFn.init(&CGM, "objc_assign_strongCast", IdTy, IdTy, - PtrToIdTy); - // id objc_assign_global(id, id*); - GlobalAssignFn.init(&CGM, "objc_assign_global", IdTy, IdTy, PtrToIdTy); - // id objc_assign_weak(id, id*); - WeakAssignFn.init(&CGM, "objc_assign_weak", IdTy, IdTy, PtrToIdTy); - // id objc_read_weak(id*); - WeakReadFn.init(&CGM, "objc_read_weak", IdTy, PtrToIdTy); - // void *objc_memmove_collectable(void*, void *, size_t); - MemMoveFn.init(&CGM, "objc_memmove_collectable", PtrTy, PtrTy, PtrTy, - SizeTy); - } -} - -llvm::Value *CGObjCGNU::GetClassNamed(CodeGenFunction &CGF, - const std::string &Name, bool isWeak) { - llvm::Constant *ClassName = MakeConstantString(Name); - // With the incompatible ABI, this will need to be replaced with a direct - // reference to the class symbol. For the compatible nonfragile ABI we are - // still performing this lookup at run time but emitting the symbol for the - // class externally so that we can make the switch later. - // - // Libobjc2 contains an LLVM pass that replaces calls to objc_lookup_class - // with memoized versions or with static references if it's safe to do so. - if (!isWeak) - EmitClassRef(Name); - - llvm::Constant *ClassLookupFn = - CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, PtrToInt8Ty, true), - "objc_lookup_class"); - return CGF.EmitNounwindRuntimeCall(ClassLookupFn, ClassName); -} - -// This has to perform the lookup every time, since posing and related -// techniques can modify the name -> class mapping. -llvm::Value *CGObjCGNU::GetClass(CodeGenFunction &CGF, - const ObjCInterfaceDecl *OID) { - auto *Value = - GetClassNamed(CGF, OID->getNameAsString(), OID->isWeakImported()); - if (auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(Value)) - CGM.setGVProperties(ClassSymbol, OID); - return Value; -} - -llvm::Value *CGObjCGNU::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) { - auto *Value = GetClassNamed(CGF, "NSAutoreleasePool", false); - if (CGM.getTriple().isOSBinFormatCOFF()) { - if (auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(Value)) { - IdentifierInfo &II = CGF.CGM.getContext().Idents.get("NSAutoreleasePool"); - TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl(); - DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl); - - const VarDecl *VD = nullptr; - for (const auto &Result : DC->lookup(&II)) - if ((VD = dyn_cast<VarDecl>(Result))) - break; - - CGM.setGVProperties(ClassSymbol, VD); - } - } - return Value; -} - -llvm::Value *CGObjCGNU::GetTypedSelector(CodeGenFunction &CGF, Selector Sel, - const std::string &TypeEncoding) { - SmallVectorImpl<TypedSelector> &Types = SelectorTable[Sel]; - llvm::GlobalAlias *SelValue = nullptr; - - for (SmallVectorImpl<TypedSelector>::iterator i = Types.begin(), - e = Types.end() ; i!=e ; i++) { - if (i->first == TypeEncoding) { - SelValue = i->second; - break; - } - } - if (!SelValue) { - SelValue = llvm::GlobalAlias::create( - SelectorTy->getElementType(), 0, llvm::GlobalValue::PrivateLinkage, - ".objc_selector_" + Sel.getAsString(), &TheModule); - Types.emplace_back(TypeEncoding, SelValue); - } - - return SelValue; -} - -Address CGObjCGNU::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) { - llvm::Value *SelValue = GetSelector(CGF, Sel); - - // Store it to a temporary. Does this satisfy the semantics of - // GetAddrOfSelector? Hopefully. - Address tmp = CGF.CreateTempAlloca(SelValue->getType(), - CGF.getPointerAlign()); - CGF.Builder.CreateStore(SelValue, tmp); - return tmp; -} - -llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel) { - return GetTypedSelector(CGF, Sel, std::string()); -} - -llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, - const ObjCMethodDecl *Method) { - std::string SelTypes = CGM.getContext().getObjCEncodingForMethodDecl(Method); - return GetTypedSelector(CGF, Method->getSelector(), SelTypes); -} - -llvm::Constant *CGObjCGNU::GetEHType(QualType T) { - if (T->isObjCIdType() || T->isObjCQualifiedIdType()) { - // With the old ABI, there was only one kind of catchall, which broke - // foreign exceptions. With the new ABI, we use __objc_id_typeinfo as - // a pointer indicating object catchalls, and NULL to indicate real - // catchalls - if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) { - return MakeConstantString("@id"); - } else { - return nullptr; - } - } - - // All other types should be Objective-C interface pointer types. - const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>(); - assert(OPT && "Invalid @catch type."); - const ObjCInterfaceDecl *IDecl = OPT->getObjectType()->getInterface(); - assert(IDecl && "Invalid @catch type."); - return MakeConstantString(IDecl->getIdentifier()->getName()); -} - -llvm::Constant *CGObjCGNUstep::GetEHType(QualType T) { - if (usesSEHExceptions) - return CGM.getCXXABI().getAddrOfRTTIDescriptor(T); - - if (!CGM.getLangOpts().CPlusPlus) - return CGObjCGNU::GetEHType(T); - - // For Objective-C++, we want to provide the ability to catch both C++ and - // Objective-C objects in the same function. - - // There's a particular fixed type info for 'id'. - if (T->isObjCIdType() || - T->isObjCQualifiedIdType()) { - llvm::Constant *IDEHType = - CGM.getModule().getGlobalVariable("__objc_id_type_info"); - if (!IDEHType) - IDEHType = - new llvm::GlobalVariable(CGM.getModule(), PtrToInt8Ty, - false, - llvm::GlobalValue::ExternalLinkage, - nullptr, "__objc_id_type_info"); - return llvm::ConstantExpr::getBitCast(IDEHType, PtrToInt8Ty); - } - - const ObjCObjectPointerType *PT = - T->getAs<ObjCObjectPointerType>(); - assert(PT && "Invalid @catch type."); - const ObjCInterfaceType *IT = PT->getInterfaceType(); - assert(IT && "Invalid @catch type."); - std::string className = IT->getDecl()->getIdentifier()->getName(); - - std::string typeinfoName = "__objc_eh_typeinfo_" + className; - - // Return the existing typeinfo if it exists - llvm::Constant *typeinfo = TheModule.getGlobalVariable(typeinfoName); - if (typeinfo) - return llvm::ConstantExpr::getBitCast(typeinfo, PtrToInt8Ty); - - // Otherwise create it. - - // vtable for gnustep::libobjc::__objc_class_type_info - // It's quite ugly hard-coding this. Ideally we'd generate it using the host - // platform's name mangling. - const char *vtableName = "_ZTVN7gnustep7libobjc22__objc_class_type_infoE"; - auto *Vtable = TheModule.getGlobalVariable(vtableName); - if (!Vtable) { - Vtable = new llvm::GlobalVariable(TheModule, PtrToInt8Ty, true, - llvm::GlobalValue::ExternalLinkage, - nullptr, vtableName); - } - llvm::Constant *Two = llvm::ConstantInt::get(IntTy, 2); - auto *BVtable = llvm::ConstantExpr::getBitCast( - llvm::ConstantExpr::getGetElementPtr(Vtable->getValueType(), Vtable, Two), - PtrToInt8Ty); - - llvm::Constant *typeName = - ExportUniqueString(className, "__objc_eh_typename_"); - - ConstantInitBuilder builder(CGM); - auto fields = builder.beginStruct(); - fields.add(BVtable); - fields.add(typeName); - llvm::Constant *TI = - fields.finishAndCreateGlobal("__objc_eh_typeinfo_" + className, - CGM.getPointerAlign(), - /*constant*/ false, - llvm::GlobalValue::LinkOnceODRLinkage); - return llvm::ConstantExpr::getBitCast(TI, PtrToInt8Ty); -} - -/// Generate an NSConstantString object. -ConstantAddress CGObjCGNU::GenerateConstantString(const StringLiteral *SL) { - - std::string Str = SL->getString().str(); - CharUnits Align = CGM.getPointerAlign(); - - // Look for an existing one - llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str); - if (old != ObjCStrings.end()) - return ConstantAddress(old->getValue(), Align); - - StringRef StringClass = CGM.getLangOpts().ObjCConstantStringClass; - - if (StringClass.empty()) StringClass = "NSConstantString"; - - std::string Sym = "_OBJC_CLASS_"; - Sym += StringClass; - - llvm::Constant *isa = TheModule.getNamedGlobal(Sym); - - if (!isa) - isa = new llvm::GlobalVariable(TheModule, IdTy, /* isConstant */false, - llvm::GlobalValue::ExternalWeakLinkage, nullptr, Sym); - else if (isa->getType() != PtrToIdTy) - isa = llvm::ConstantExpr::getBitCast(isa, PtrToIdTy); - - ConstantInitBuilder Builder(CGM); - auto Fields = Builder.beginStruct(); - Fields.add(isa); - Fields.add(MakeConstantString(Str)); - Fields.addInt(IntTy, Str.size()); - llvm::Constant *ObjCStr = - Fields.finishAndCreateGlobal(".objc_str", Align); - ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty); - ObjCStrings[Str] = ObjCStr; - ConstantStrings.push_back(ObjCStr); - return ConstantAddress(ObjCStr, Align); -} - -///Generates a message send where the super is the receiver. This is a message -///send to self with special delivery semantics indicating which class's method -///should be called. -RValue -CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF, - ReturnValueSlot Return, - QualType ResultType, - Selector Sel, - const ObjCInterfaceDecl *Class, - bool isCategoryImpl, - llvm::Value *Receiver, - bool IsClassMessage, - const CallArgList &CallArgs, - const ObjCMethodDecl *Method) { - CGBuilderTy &Builder = CGF.Builder; - if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) { - if (Sel == RetainSel || Sel == AutoreleaseSel) { - return RValue::get(EnforceType(Builder, Receiver, - CGM.getTypes().ConvertType(ResultType))); - } - if (Sel == ReleaseSel) { - return RValue::get(nullptr); - } - } - - llvm::Value *cmd = GetSelector(CGF, Sel); - CallArgList ActualArgs; - - ActualArgs.add(RValue::get(EnforceType(Builder, Receiver, IdTy)), ASTIdTy); - ActualArgs.add(RValue::get(cmd), CGF.getContext().getObjCSelType()); - ActualArgs.addFrom(CallArgs); - - MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs); - - llvm::Value *ReceiverClass = nullptr; - bool isV2ABI = isRuntime(ObjCRuntime::GNUstep, 2); - if (isV2ABI) { - ReceiverClass = GetClassNamed(CGF, - Class->getSuperClass()->getNameAsString(), /*isWeak*/false); - if (IsClassMessage) { - // Load the isa pointer of the superclass is this is a class method. - ReceiverClass = Builder.CreateBitCast(ReceiverClass, - llvm::PointerType::getUnqual(IdTy)); - ReceiverClass = - Builder.CreateAlignedLoad(ReceiverClass, CGF.getPointerAlign()); - } - ReceiverClass = EnforceType(Builder, ReceiverClass, IdTy); - } else { - if (isCategoryImpl) { - llvm::Constant *classLookupFunction = nullptr; - if (IsClassMessage) { - classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get( - IdTy, PtrTy, true), "objc_get_meta_class"); - } else { - classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get( - IdTy, PtrTy, true), "objc_get_class"); - } - ReceiverClass = Builder.CreateCall(classLookupFunction, - MakeConstantString(Class->getNameAsString())); - } else { - // Set up global aliases for the metaclass or class pointer if they do not - // already exist. These will are forward-references which will be set to - // pointers to the class and metaclass structure created for the runtime - // load function. To send a message to super, we look up the value of the - // super_class pointer from either the class or metaclass structure. - if (IsClassMessage) { - if (!MetaClassPtrAlias) { - MetaClassPtrAlias = llvm::GlobalAlias::create( - IdTy->getElementType(), 0, llvm::GlobalValue::InternalLinkage, - ".objc_metaclass_ref" + Class->getNameAsString(), &TheModule); - } - ReceiverClass = MetaClassPtrAlias; - } else { - if (!ClassPtrAlias) { - ClassPtrAlias = llvm::GlobalAlias::create( - IdTy->getElementType(), 0, llvm::GlobalValue::InternalLinkage, - ".objc_class_ref" + Class->getNameAsString(), &TheModule); - } - ReceiverClass = ClassPtrAlias; - } - } - // Cast the pointer to a simplified version of the class structure - llvm::Type *CastTy = llvm::StructType::get(IdTy, IdTy); - ReceiverClass = Builder.CreateBitCast(ReceiverClass, - llvm::PointerType::getUnqual(CastTy)); - // Get the superclass pointer - ReceiverClass = Builder.CreateStructGEP(CastTy, ReceiverClass, 1); - // Load the superclass pointer - ReceiverClass = - Builder.CreateAlignedLoad(ReceiverClass, CGF.getPointerAlign()); - } - // Construct the structure used to look up the IMP - llvm::StructType *ObjCSuperTy = - llvm::StructType::get(Receiver->getType(), IdTy); - - Address ObjCSuper = CGF.CreateTempAlloca(ObjCSuperTy, - CGF.getPointerAlign()); - - Builder.CreateStore(Receiver, - Builder.CreateStructGEP(ObjCSuper, 0, CharUnits::Zero())); - Builder.CreateStore(ReceiverClass, - Builder.CreateStructGEP(ObjCSuper, 1, CGF.getPointerSize())); - - ObjCSuper = EnforceType(Builder, ObjCSuper, PtrToObjCSuperTy); - - // Get the IMP - llvm::Value *imp = LookupIMPSuper(CGF, ObjCSuper, cmd, MSI); - imp = EnforceType(Builder, imp, MSI.MessengerType); - - llvm::Metadata *impMD[] = { - llvm::MDString::get(VMContext, Sel.getAsString()), - llvm::MDString::get(VMContext, Class->getSuperClass()->getNameAsString()), - llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - llvm::Type::getInt1Ty(VMContext), IsClassMessage))}; - llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD); - - CGCallee callee(CGCalleeInfo(), imp); - - llvm::Instruction *call; - RValue msgRet = CGF.EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call); - call->setMetadata(msgSendMDKind, node); - return msgRet; -} - -/// Generate code for a message send expression. -RValue -CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF, - ReturnValueSlot Return, - QualType ResultType, - Selector Sel, - llvm::Value *Receiver, - const CallArgList &CallArgs, - const ObjCInterfaceDecl *Class, - const ObjCMethodDecl *Method) { - CGBuilderTy &Builder = CGF.Builder; - - // Strip out message sends to retain / release in GC mode - if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) { - if (Sel == RetainSel || Sel == AutoreleaseSel) { - return RValue::get(EnforceType(Builder, Receiver, - CGM.getTypes().ConvertType(ResultType))); - } - if (Sel == ReleaseSel) { - return RValue::get(nullptr); - } - } - - // If the return type is something that goes in an integer register, the - // runtime will handle 0 returns. For other cases, we fill in the 0 value - // ourselves. - // - // The language spec says the result of this kind of message send is - // undefined, but lots of people seem to have forgotten to read that - // paragraph and insist on sending messages to nil that have structure - // returns. With GCC, this generates a random return value (whatever happens - // to be on the stack / in those registers at the time) on most platforms, - // and generates an illegal instruction trap on SPARC. With LLVM it corrupts - // the stack. - bool isPointerSizedReturn = (ResultType->isAnyPointerType() || - ResultType->isIntegralOrEnumerationType() || ResultType->isVoidType()); - - llvm::BasicBlock *startBB = nullptr; - llvm::BasicBlock *messageBB = nullptr; - llvm::BasicBlock *continueBB = nullptr; - - if (!isPointerSizedReturn) { - startBB = Builder.GetInsertBlock(); - messageBB = CGF.createBasicBlock("msgSend"); - continueBB = CGF.createBasicBlock("continue"); - - llvm::Value *isNil = Builder.CreateICmpEQ(Receiver, - llvm::Constant::getNullValue(Receiver->getType())); - Builder.CreateCondBr(isNil, continueBB, messageBB); - CGF.EmitBlock(messageBB); - } - - IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy)); - llvm::Value *cmd; - if (Method) - cmd = GetSelector(CGF, Method); - else - cmd = GetSelector(CGF, Sel); - cmd = EnforceType(Builder, cmd, SelectorTy); - Receiver = EnforceType(Builder, Receiver, IdTy); - - llvm::Metadata *impMD[] = { - llvm::MDString::get(VMContext, Sel.getAsString()), - llvm::MDString::get(VMContext, Class ? Class->getNameAsString() : ""), - llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - llvm::Type::getInt1Ty(VMContext), Class != nullptr))}; - llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD); - - CallArgList ActualArgs; - ActualArgs.add(RValue::get(Receiver), ASTIdTy); - ActualArgs.add(RValue::get(cmd), CGF.getContext().getObjCSelType()); - ActualArgs.addFrom(CallArgs); - - MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs); - - // Get the IMP to call - llvm::Value *imp; - - // If we have non-legacy dispatch specified, we try using the objc_msgSend() - // functions. These are not supported on all platforms (or all runtimes on a - // given platform), so we - switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) { - case CodeGenOptions::Legacy: - imp = LookupIMP(CGF, Receiver, cmd, node, MSI); - break; - case CodeGenOptions::Mixed: - case CodeGenOptions::NonLegacy: - if (CGM.ReturnTypeUsesFPRet(ResultType)) { - imp = CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, IdTy, true), - "objc_msgSend_fpret"); - } else if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) { - // The actual types here don't matter - we're going to bitcast the - // function anyway - imp = CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, IdTy, true), - "objc_msgSend_stret"); - } else { - imp = CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, IdTy, true), - "objc_msgSend"); - } - } - - // Reset the receiver in case the lookup modified it - ActualArgs[0] = CallArg(RValue::get(Receiver), ASTIdTy); - - imp = EnforceType(Builder, imp, MSI.MessengerType); - - llvm::Instruction *call; - CGCallee callee(CGCalleeInfo(), imp); - RValue msgRet = CGF.EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call); - call->setMetadata(msgSendMDKind, node); - - - if (!isPointerSizedReturn) { - messageBB = CGF.Builder.GetInsertBlock(); - CGF.Builder.CreateBr(continueBB); - CGF.EmitBlock(continueBB); - if (msgRet.isScalar()) { - llvm::Value *v = msgRet.getScalarVal(); - llvm::PHINode *phi = Builder.CreatePHI(v->getType(), 2); - phi->addIncoming(v, messageBB); - phi->addIncoming(llvm::Constant::getNullValue(v->getType()), startBB); - msgRet = RValue::get(phi); - } else if (msgRet.isAggregate()) { - Address v = msgRet.getAggregateAddress(); - llvm::PHINode *phi = Builder.CreatePHI(v.getType(), 2); - llvm::Type *RetTy = v.getElementType(); - Address NullVal = CGF.CreateTempAlloca(RetTy, v.getAlignment(), "null"); - CGF.InitTempAlloca(NullVal, llvm::Constant::getNullValue(RetTy)); - phi->addIncoming(v.getPointer(), messageBB); - phi->addIncoming(NullVal.getPointer(), startBB); - msgRet = RValue::getAggregate(Address(phi, v.getAlignment())); - } else /* isComplex() */ { - std::pair<llvm::Value*,llvm::Value*> v = msgRet.getComplexVal(); - llvm::PHINode *phi = Builder.CreatePHI(v.first->getType(), 2); - phi->addIncoming(v.first, messageBB); - phi->addIncoming(llvm::Constant::getNullValue(v.first->getType()), - startBB); - llvm::PHINode *phi2 = Builder.CreatePHI(v.second->getType(), 2); - phi2->addIncoming(v.second, messageBB); - phi2->addIncoming(llvm::Constant::getNullValue(v.second->getType()), - startBB); - msgRet = RValue::getComplex(phi, phi2); - } - } - return msgRet; -} - -/// Generates a MethodList. Used in construction of a objc_class and -/// objc_category structures. -llvm::Constant *CGObjCGNU:: -GenerateMethodList(StringRef ClassName, - StringRef CategoryName, - ArrayRef<const ObjCMethodDecl*> Methods, - bool isClassMethodList) { - if (Methods.empty()) - return NULLPtr; - - ConstantInitBuilder Builder(CGM); - - auto MethodList = Builder.beginStruct(); - MethodList.addNullPointer(CGM.Int8PtrTy); - MethodList.addInt(Int32Ty, Methods.size()); - - // Get the method structure type. - llvm::StructType *ObjCMethodTy = - llvm::StructType::get(CGM.getLLVMContext(), { - PtrToInt8Ty, // Really a selector, but the runtime creates it us. - PtrToInt8Ty, // Method types - IMPTy // Method pointer - }); - bool isV2ABI = isRuntime(ObjCRuntime::GNUstep, 2); - if (isV2ABI) { - // size_t size; - llvm::DataLayout td(&TheModule); - MethodList.addInt(SizeTy, td.getTypeSizeInBits(ObjCMethodTy) / - CGM.getContext().getCharWidth()); - ObjCMethodTy = - llvm::StructType::get(CGM.getLLVMContext(), { - IMPTy, // Method pointer - PtrToInt8Ty, // Selector - PtrToInt8Ty // Extended type encoding - }); - } else { - ObjCMethodTy = - llvm::StructType::get(CGM.getLLVMContext(), { - PtrToInt8Ty, // Really a selector, but the runtime creates it us. - PtrToInt8Ty, // Method types - IMPTy // Method pointer - }); - } - auto MethodArray = MethodList.beginArray(); - ASTContext &Context = CGM.getContext(); - for (const auto *OMD : Methods) { - llvm::Constant *FnPtr = - TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName, - OMD->getSelector(), - isClassMethodList)); - assert(FnPtr && "Can't generate metadata for method that doesn't exist"); - auto Method = MethodArray.beginStruct(ObjCMethodTy); - if (isV2ABI) { - Method.addBitCast(FnPtr, IMPTy); - Method.add(GetConstantSelector(OMD->getSelector(), - Context.getObjCEncodingForMethodDecl(OMD))); - Method.add(MakeConstantString(Context.getObjCEncodingForMethodDecl(OMD, true))); - } else { - Method.add(MakeConstantString(OMD->getSelector().getAsString())); - Method.add(MakeConstantString(Context.getObjCEncodingForMethodDecl(OMD))); - Method.addBitCast(FnPtr, IMPTy); - } - Method.finishAndAddTo(MethodArray); - } - MethodArray.finishAndAddTo(MethodList); - - // Create an instance of the structure - return MethodList.finishAndCreateGlobal(".objc_method_list", - CGM.getPointerAlign()); -} - -/// Generates an IvarList. Used in construction of a objc_class. -llvm::Constant *CGObjCGNU:: -GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames, - ArrayRef<llvm::Constant *> IvarTypes, - ArrayRef<llvm::Constant *> IvarOffsets, - ArrayRef<llvm::Constant *> IvarAlign, - ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership) { - if (IvarNames.empty()) - return NULLPtr; - - ConstantInitBuilder Builder(CGM); - - // Structure containing array count followed by array. - auto IvarList = Builder.beginStruct(); - IvarList.addInt(IntTy, (int)IvarNames.size()); - - // Get the ivar structure type. - llvm::StructType *ObjCIvarTy = - llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy); - - // Array of ivar structures. - auto Ivars = IvarList.beginArray(ObjCIvarTy); - for (unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) { - auto Ivar = Ivars.beginStruct(ObjCIvarTy); - Ivar.add(IvarNames[i]); - Ivar.add(IvarTypes[i]); - Ivar.add(IvarOffsets[i]); - Ivar.finishAndAddTo(Ivars); - } - Ivars.finishAndAddTo(IvarList); - - // Create an instance of the structure - return IvarList.finishAndCreateGlobal(".objc_ivar_list", - CGM.getPointerAlign()); -} - -/// Generate a class structure -llvm::Constant *CGObjCGNU::GenerateClassStructure( - llvm::Constant *MetaClass, - llvm::Constant *SuperClass, - unsigned info, - const char *Name, - llvm::Constant *Version, - llvm::Constant *InstanceSize, - llvm::Constant *IVars, - llvm::Constant *Methods, - llvm::Constant *Protocols, - llvm::Constant *IvarOffsets, - llvm::Constant *Properties, - llvm::Constant *StrongIvarBitmap, - llvm::Constant *WeakIvarBitmap, - bool isMeta) { - // Set up the class structure - // Note: Several of these are char*s when they should be ids. This is - // because the runtime performs this translation on load. - // - // Fields marked New ABI are part of the GNUstep runtime. We emit them - // anyway; the classes will still work with the GNU runtime, they will just - // be ignored. - llvm::StructType *ClassTy = llvm::StructType::get( - PtrToInt8Ty, // isa - PtrToInt8Ty, // super_class - PtrToInt8Ty, // name - LongTy, // version - LongTy, // info - LongTy, // instance_size - IVars->getType(), // ivars - Methods->getType(), // methods - // These are all filled in by the runtime, so we pretend - PtrTy, // dtable - PtrTy, // subclass_list - PtrTy, // sibling_class - PtrTy, // protocols - PtrTy, // gc_object_type - // New ABI: - LongTy, // abi_version - IvarOffsets->getType(), // ivar_offsets - Properties->getType(), // properties - IntPtrTy, // strong_pointers - IntPtrTy // weak_pointers - ); - - ConstantInitBuilder Builder(CGM); - auto Elements = Builder.beginStruct(ClassTy); - - // Fill in the structure - - // isa - Elements.addBitCast(MetaClass, PtrToInt8Ty); - // super_class - Elements.add(SuperClass); - // name - Elements.add(MakeConstantString(Name, ".class_name")); - // version - Elements.addInt(LongTy, 0); - // info - Elements.addInt(LongTy, info); - // instance_size - if (isMeta) { - llvm::DataLayout td(&TheModule); - Elements.addInt(LongTy, - td.getTypeSizeInBits(ClassTy) / - CGM.getContext().getCharWidth()); - } else - Elements.add(InstanceSize); - // ivars - Elements.add(IVars); - // methods - Elements.add(Methods); - // These are all filled in by the runtime, so we pretend - // dtable - Elements.add(NULLPtr); - // subclass_list - Elements.add(NULLPtr); - // sibling_class - Elements.add(NULLPtr); - // protocols - Elements.addBitCast(Protocols, PtrTy); - // gc_object_type - Elements.add(NULLPtr); - // abi_version - Elements.addInt(LongTy, ClassABIVersion); - // ivar_offsets - Elements.add(IvarOffsets); - // properties - Elements.add(Properties); - // strong_pointers - Elements.add(StrongIvarBitmap); - // weak_pointers - Elements.add(WeakIvarBitmap); - // Create an instance of the structure - // This is now an externally visible symbol, so that we can speed up class - // messages in the next ABI. We may already have some weak references to - // this, so check and fix them properly. - std::string ClassSym((isMeta ? "_OBJC_METACLASS_": "_OBJC_CLASS_") + - std::string(Name)); - llvm::GlobalVariable *ClassRef = TheModule.getNamedGlobal(ClassSym); - llvm::Constant *Class = - Elements.finishAndCreateGlobal(ClassSym, CGM.getPointerAlign(), false, - llvm::GlobalValue::ExternalLinkage); - if (ClassRef) { - ClassRef->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(Class, - ClassRef->getType())); - ClassRef->removeFromParent(); - Class->setName(ClassSym); - } - return Class; -} - -llvm::Constant *CGObjCGNU:: -GenerateProtocolMethodList(ArrayRef<const ObjCMethodDecl*> Methods) { - // Get the method structure type. - llvm::StructType *ObjCMethodDescTy = - llvm::StructType::get(CGM.getLLVMContext(), { PtrToInt8Ty, PtrToInt8Ty }); - ASTContext &Context = CGM.getContext(); - ConstantInitBuilder Builder(CGM); - auto MethodList = Builder.beginStruct(); - MethodList.addInt(IntTy, Methods.size()); - auto MethodArray = MethodList.beginArray(ObjCMethodDescTy); - for (auto *M : Methods) { - auto Method = MethodArray.beginStruct(ObjCMethodDescTy); - Method.add(MakeConstantString(M->getSelector().getAsString())); - Method.add(MakeConstantString(Context.getObjCEncodingForMethodDecl(M))); - Method.finishAndAddTo(MethodArray); - } - MethodArray.finishAndAddTo(MethodList); - return MethodList.finishAndCreateGlobal(".objc_method_list", - CGM.getPointerAlign()); -} - -// Create the protocol list structure used in classes, categories and so on -llvm::Constant * -CGObjCGNU::GenerateProtocolList(ArrayRef<std::string> Protocols) { - - ConstantInitBuilder Builder(CGM); - auto ProtocolList = Builder.beginStruct(); - ProtocolList.add(NULLPtr); - ProtocolList.addInt(LongTy, Protocols.size()); - - auto Elements = ProtocolList.beginArray(PtrToInt8Ty); - for (const std::string *iter = Protocols.begin(), *endIter = Protocols.end(); - iter != endIter ; iter++) { - llvm::Constant *protocol = nullptr; - llvm::StringMap<llvm::Constant*>::iterator value = - ExistingProtocols.find(*iter); - if (value == ExistingProtocols.end()) { - protocol = GenerateEmptyProtocol(*iter); - } else { - protocol = value->getValue(); - } - Elements.addBitCast(protocol, PtrToInt8Ty); - } - Elements.finishAndAddTo(ProtocolList); - return ProtocolList.finishAndCreateGlobal(".objc_protocol_list", - CGM.getPointerAlign()); -} - -llvm::Value *CGObjCGNU::GenerateProtocolRef(CodeGenFunction &CGF, - const ObjCProtocolDecl *PD) { - llvm::Constant *&protocol = ExistingProtocols[PD->getNameAsString()]; - if (!protocol) - GenerateProtocol(PD); - llvm::Type *T = - CGM.getTypes().ConvertType(CGM.getContext().getObjCProtoType()); - return CGF.Builder.CreateBitCast(protocol, llvm::PointerType::getUnqual(T)); -} - -llvm::Constant * -CGObjCGNU::GenerateEmptyProtocol(StringRef ProtocolName) { - llvm::Constant *ProtocolList = GenerateProtocolList({}); - llvm::Constant *MethodList = GenerateProtocolMethodList({}); - MethodList = llvm::ConstantExpr::getBitCast(MethodList, PtrToInt8Ty); - // Protocols are objects containing lists of the methods implemented and - // protocols adopted. - ConstantInitBuilder Builder(CGM); - auto Elements = Builder.beginStruct(); - - // The isa pointer must be set to a magic number so the runtime knows it's - // the correct layout. - Elements.add(llvm::ConstantExpr::getIntToPtr( - llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy)); - - Elements.add(MakeConstantString(ProtocolName, ".objc_protocol_name")); - Elements.add(ProtocolList); /* .protocol_list */ - Elements.add(MethodList); /* .instance_methods */ - Elements.add(MethodList); /* .class_methods */ - Elements.add(MethodList); /* .optional_instance_methods */ - Elements.add(MethodList); /* .optional_class_methods */ - Elements.add(NULLPtr); /* .properties */ - Elements.add(NULLPtr); /* .optional_properties */ - return Elements.finishAndCreateGlobal(SymbolForProtocol(ProtocolName), - CGM.getPointerAlign()); -} - -void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) { - std::string ProtocolName = PD->getNameAsString(); - - // Use the protocol definition, if there is one. - if (const ObjCProtocolDecl *Def = PD->getDefinition()) - PD = Def; - - SmallVector<std::string, 16> Protocols; - for (const auto *PI : PD->protocols()) - Protocols.push_back(PI->getNameAsString()); - SmallVector<const ObjCMethodDecl*, 16> InstanceMethods; - SmallVector<const ObjCMethodDecl*, 16> OptionalInstanceMethods; - for (const auto *I : PD->instance_methods()) - if (I->isOptional()) - OptionalInstanceMethods.push_back(I); - else - InstanceMethods.push_back(I); - // Collect information about class methods: - SmallVector<const ObjCMethodDecl*, 16> ClassMethods; - SmallVector<const ObjCMethodDecl*, 16> OptionalClassMethods; - for (const auto *I : PD->class_methods()) - if (I->isOptional()) - OptionalClassMethods.push_back(I); - else - ClassMethods.push_back(I); - - llvm::Constant *ProtocolList = GenerateProtocolList(Protocols); - llvm::Constant *InstanceMethodList = - GenerateProtocolMethodList(InstanceMethods); - llvm::Constant *ClassMethodList = - GenerateProtocolMethodList(ClassMethods); - llvm::Constant *OptionalInstanceMethodList = - GenerateProtocolMethodList(OptionalInstanceMethods); - llvm::Constant *OptionalClassMethodList = - GenerateProtocolMethodList(OptionalClassMethods); - - // Property metadata: name, attributes, isSynthesized, setter name, setter - // types, getter name, getter types. - // The isSynthesized value is always set to 0 in a protocol. It exists to - // simplify the runtime library by allowing it to use the same data - // structures for protocol metadata everywhere. - - llvm::Constant *PropertyList = - GeneratePropertyList(nullptr, PD, false, false); - llvm::Constant *OptionalPropertyList = - GeneratePropertyList(nullptr, PD, false, true); - - // Protocols are objects containing lists of the methods implemented and - // protocols adopted. - // The isa pointer must be set to a magic number so the runtime knows it's - // the correct layout. - ConstantInitBuilder Builder(CGM); - auto Elements = Builder.beginStruct(); - Elements.add( - llvm::ConstantExpr::getIntToPtr( - llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy)); - Elements.add(MakeConstantString(ProtocolName)); - Elements.add(ProtocolList); - Elements.add(InstanceMethodList); - Elements.add(ClassMethodList); - Elements.add(OptionalInstanceMethodList); - Elements.add(OptionalClassMethodList); - Elements.add(PropertyList); - Elements.add(OptionalPropertyList); - ExistingProtocols[ProtocolName] = - llvm::ConstantExpr::getBitCast( - Elements.finishAndCreateGlobal(".objc_protocol", CGM.getPointerAlign()), - IdTy); -} -void CGObjCGNU::GenerateProtocolHolderCategory() { - // Collect information about instance methods - - ConstantInitBuilder Builder(CGM); - auto Elements = Builder.beginStruct(); - - const std::string ClassName = "__ObjC_Protocol_Holder_Ugly_Hack"; - const std::string CategoryName = "AnotherHack"; - Elements.add(MakeConstantString(CategoryName)); - Elements.add(MakeConstantString(ClassName)); - // Instance method list - Elements.addBitCast(GenerateMethodList( - ClassName, CategoryName, {}, false), PtrTy); - // Class method list - Elements.addBitCast(GenerateMethodList( - ClassName, CategoryName, {}, true), PtrTy); - - // Protocol list - ConstantInitBuilder ProtocolListBuilder(CGM); - auto ProtocolList = ProtocolListBuilder.beginStruct(); - ProtocolList.add(NULLPtr); - ProtocolList.addInt(LongTy, ExistingProtocols.size()); - auto ProtocolElements = ProtocolList.beginArray(PtrTy); - for (auto iter = ExistingProtocols.begin(), endIter = ExistingProtocols.end(); - iter != endIter ; iter++) { - ProtocolElements.addBitCast(iter->getValue(), PtrTy); - } - ProtocolElements.finishAndAddTo(ProtocolList); - Elements.addBitCast( - ProtocolList.finishAndCreateGlobal(".objc_protocol_list", - CGM.getPointerAlign()), - PtrTy); - Categories.push_back(llvm::ConstantExpr::getBitCast( - Elements.finishAndCreateGlobal("", CGM.getPointerAlign()), - PtrTy)); -} - -/// Libobjc2 uses a bitfield representation where small(ish) bitfields are -/// stored in a 64-bit value with the low bit set to 1 and the remaining 63 -/// bits set to their values, LSB first, while larger ones are stored in a -/// structure of this / form: -/// -/// struct { int32_t length; int32_t values[length]; }; -/// -/// The values in the array are stored in host-endian format, with the least -/// significant bit being assumed to come first in the bitfield. Therefore, a -/// bitfield with the 64th bit set will be (int64_t)&{ 2, [0, 1<<31] }, while a -/// bitfield / with the 63rd bit set will be 1<<64. -llvm::Constant *CGObjCGNU::MakeBitField(ArrayRef<bool> bits) { - int bitCount = bits.size(); - int ptrBits = CGM.getDataLayout().getPointerSizeInBits(); - if (bitCount < ptrBits) { - uint64_t val = 1; - for (int i=0 ; i<bitCount ; ++i) { - if (bits[i]) val |= 1ULL<<(i+1); - } - return llvm::ConstantInt::get(IntPtrTy, val); - } - SmallVector<llvm::Constant *, 8> values; - int v=0; - while (v < bitCount) { - int32_t word = 0; - for (int i=0 ; (i<32) && (v<bitCount) ; ++i) { - if (bits[v]) word |= 1<<i; - v++; - } - values.push_back(llvm::ConstantInt::get(Int32Ty, word)); - } - - ConstantInitBuilder builder(CGM); - auto fields = builder.beginStruct(); - fields.addInt(Int32Ty, values.size()); - auto array = fields.beginArray(); - for (auto v : values) array.add(v); - array.finishAndAddTo(fields); - - llvm::Constant *GS = - fields.finishAndCreateGlobal("", CharUnits::fromQuantity(4)); - llvm::Constant *ptr = llvm::ConstantExpr::getPtrToInt(GS, IntPtrTy); - return ptr; -} - -llvm::Constant *CGObjCGNU::GenerateCategoryProtocolList(const - ObjCCategoryDecl *OCD) { - SmallVector<std::string, 16> Protocols; - for (const auto *PD : OCD->getReferencedProtocols()) - Protocols.push_back(PD->getNameAsString()); - return GenerateProtocolList(Protocols); -} - -void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) { - const ObjCInterfaceDecl *Class = OCD->getClassInterface(); - std::string ClassName = Class->getNameAsString(); - std::string CategoryName = OCD->getNameAsString(); - - // Collect the names of referenced protocols - const ObjCCategoryDecl *CatDecl = OCD->getCategoryDecl(); - - ConstantInitBuilder Builder(CGM); - auto Elements = Builder.beginStruct(); - Elements.add(MakeConstantString(CategoryName)); - Elements.add(MakeConstantString(ClassName)); - // Instance method list - SmallVector<ObjCMethodDecl*, 16> InstanceMethods; - InstanceMethods.insert(InstanceMethods.begin(), OCD->instmeth_begin(), - OCD->instmeth_end()); - Elements.addBitCast( - GenerateMethodList(ClassName, CategoryName, InstanceMethods, false), - PtrTy); - // Class method list - - SmallVector<ObjCMethodDecl*, 16> ClassMethods; - ClassMethods.insert(ClassMethods.begin(), OCD->classmeth_begin(), - OCD->classmeth_end()); - Elements.addBitCast( - GenerateMethodList(ClassName, CategoryName, ClassMethods, true), - PtrTy); - // Protocol list - Elements.addBitCast(GenerateCategoryProtocolList(CatDecl), PtrTy); - if (isRuntime(ObjCRuntime::GNUstep, 2)) { - const ObjCCategoryDecl *Category = - Class->FindCategoryDeclaration(OCD->getIdentifier()); - if (Category) { - // Instance properties - Elements.addBitCast(GeneratePropertyList(OCD, Category, false), PtrTy); - // Class properties - Elements.addBitCast(GeneratePropertyList(OCD, Category, true), PtrTy); - } else { - Elements.addNullPointer(PtrTy); - Elements.addNullPointer(PtrTy); - } - } - - Categories.push_back(llvm::ConstantExpr::getBitCast( - Elements.finishAndCreateGlobal( - std::string(".objc_category_")+ClassName+CategoryName, - CGM.getPointerAlign()), - PtrTy)); -} - -llvm::Constant *CGObjCGNU::GeneratePropertyList(const Decl *Container, - const ObjCContainerDecl *OCD, - bool isClassProperty, - bool protocolOptionalProperties) { - - SmallVector<const ObjCPropertyDecl *, 16> Properties; - llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet; - bool isProtocol = isa<ObjCProtocolDecl>(OCD); - ASTContext &Context = CGM.getContext(); - - std::function<void(const ObjCProtocolDecl *Proto)> collectProtocolProperties - = [&](const ObjCProtocolDecl *Proto) { - for (const auto *P : Proto->protocols()) - collectProtocolProperties(P); - for (const auto *PD : Proto->properties()) { - if (isClassProperty != PD->isClassProperty()) - continue; - // Skip any properties that are declared in protocols that this class - // conforms to but are not actually implemented by this class. - if (!isProtocol && !Context.getObjCPropertyImplDeclForPropertyDecl(PD, Container)) - continue; - if (!PropertySet.insert(PD->getIdentifier()).second) - continue; - Properties.push_back(PD); - } - }; - - if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) - for (const ObjCCategoryDecl *ClassExt : OID->known_extensions()) - for (auto *PD : ClassExt->properties()) { - if (isClassProperty != PD->isClassProperty()) - continue; - PropertySet.insert(PD->getIdentifier()); - Properties.push_back(PD); - } - - for (const auto *PD : OCD->properties()) { - if (isClassProperty != PD->isClassProperty()) - continue; - // If we're generating a list for a protocol, skip optional / required ones - // when generating the other list. - if (isProtocol && (protocolOptionalProperties != PD->isOptional())) - continue; - // Don't emit duplicate metadata for properties that were already in a - // class extension. - if (!PropertySet.insert(PD->getIdentifier()).second) - continue; - - Properties.push_back(PD); - } - - if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) - for (const auto *P : OID->all_referenced_protocols()) - collectProtocolProperties(P); - else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) - for (const auto *P : CD->protocols()) - collectProtocolProperties(P); - - auto numProperties = Properties.size(); - - if (numProperties == 0) - return NULLPtr; - - ConstantInitBuilder builder(CGM); - auto propertyList = builder.beginStruct(); - auto properties = PushPropertyListHeader(propertyList, numProperties); - - // Add all of the property methods need adding to the method list and to the - // property metadata list. - for (auto *property : Properties) { - bool isSynthesized = false; - bool isDynamic = false; - if (!isProtocol) { - auto *propertyImpl = Context.getObjCPropertyImplDeclForPropertyDecl(property, Container); - if (propertyImpl) { - isSynthesized = (propertyImpl->getPropertyImplementation() == - ObjCPropertyImplDecl::Synthesize); - isDynamic = (propertyImpl->getPropertyImplementation() == - ObjCPropertyImplDecl::Dynamic); - } - } - PushProperty(properties, property, Container, isSynthesized, isDynamic); - } - properties.finishAndAddTo(propertyList); - - return propertyList.finishAndCreateGlobal(".objc_property_list", - CGM.getPointerAlign()); -} - -void CGObjCGNU::RegisterAlias(const ObjCCompatibleAliasDecl *OAD) { - // Get the class declaration for which the alias is specified. - ObjCInterfaceDecl *ClassDecl = - const_cast<ObjCInterfaceDecl *>(OAD->getClassInterface()); - ClassAliases.emplace_back(ClassDecl->getNameAsString(), - OAD->getNameAsString()); -} - -void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { - ASTContext &Context = CGM.getContext(); - - // Get the superclass name. - const ObjCInterfaceDecl * SuperClassDecl = - OID->getClassInterface()->getSuperClass(); - std::string SuperClassName; - if (SuperClassDecl) { - SuperClassName = SuperClassDecl->getNameAsString(); - EmitClassRef(SuperClassName); - } - - // Get the class name - ObjCInterfaceDecl *ClassDecl = - const_cast<ObjCInterfaceDecl *>(OID->getClassInterface()); - std::string ClassName = ClassDecl->getNameAsString(); - - // Emit the symbol that is used to generate linker errors if this class is - // referenced in other modules but not declared. - std::string classSymbolName = "__objc_class_name_" + ClassName; - if (auto *symbol = TheModule.getGlobalVariable(classSymbolName)) { - symbol->setInitializer(llvm::ConstantInt::get(LongTy, 0)); - } else { - new llvm::GlobalVariable(TheModule, LongTy, false, - llvm::GlobalValue::ExternalLinkage, - llvm::ConstantInt::get(LongTy, 0), - classSymbolName); - } - - // Get the size of instances. - int instanceSize = - Context.getASTObjCImplementationLayout(OID).getSize().getQuantity(); - - // Collect information about instance variables. - SmallVector<llvm::Constant*, 16> IvarNames; - SmallVector<llvm::Constant*, 16> IvarTypes; - SmallVector<llvm::Constant*, 16> IvarOffsets; - SmallVector<llvm::Constant*, 16> IvarAligns; - SmallVector<Qualifiers::ObjCLifetime, 16> IvarOwnership; - - ConstantInitBuilder IvarOffsetBuilder(CGM); - auto IvarOffsetValues = IvarOffsetBuilder.beginArray(PtrToIntTy); - SmallVector<bool, 16> WeakIvars; - SmallVector<bool, 16> StrongIvars; - - int superInstanceSize = !SuperClassDecl ? 0 : - Context.getASTObjCInterfaceLayout(SuperClassDecl).getSize().getQuantity(); - // For non-fragile ivars, set the instance size to 0 - {the size of just this - // class}. The runtime will then set this to the correct value on load. - if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) { - instanceSize = 0 - (instanceSize - superInstanceSize); - } - - for (const ObjCIvarDecl *IVD = ClassDecl->all_declared_ivar_begin(); IVD; - IVD = IVD->getNextIvar()) { - // Store the name - IvarNames.push_back(MakeConstantString(IVD->getNameAsString())); - // Get the type encoding for this ivar - std::string TypeStr; - Context.getObjCEncodingForType(IVD->getType(), TypeStr, IVD); - IvarTypes.push_back(MakeConstantString(TypeStr)); - IvarAligns.push_back(llvm::ConstantInt::get(IntTy, - Context.getTypeSize(IVD->getType()))); - // Get the offset - uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD); - uint64_t Offset = BaseOffset; - if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) { - Offset = BaseOffset - superInstanceSize; - } - llvm::Constant *OffsetValue = llvm::ConstantInt::get(IntTy, Offset); - // Create the direct offset value - std::string OffsetName = "__objc_ivar_offset_value_" + ClassName +"." + - IVD->getNameAsString(); - - llvm::GlobalVariable *OffsetVar = TheModule.getGlobalVariable(OffsetName); - if (OffsetVar) { - OffsetVar->setInitializer(OffsetValue); - // If this is the real definition, change its linkage type so that - // different modules will use this one, rather than their private - // copy. - OffsetVar->setLinkage(llvm::GlobalValue::ExternalLinkage); - } else - OffsetVar = new llvm::GlobalVariable(TheModule, Int32Ty, - false, llvm::GlobalValue::ExternalLinkage, - OffsetValue, OffsetName); - IvarOffsets.push_back(OffsetValue); - IvarOffsetValues.add(OffsetVar); - Qualifiers::ObjCLifetime lt = IVD->getType().getQualifiers().getObjCLifetime(); - IvarOwnership.push_back(lt); - switch (lt) { - case Qualifiers::OCL_Strong: - StrongIvars.push_back(true); - WeakIvars.push_back(false); - break; - case Qualifiers::OCL_Weak: - StrongIvars.push_back(false); - WeakIvars.push_back(true); - break; - default: - StrongIvars.push_back(false); - WeakIvars.push_back(false); - } - } - llvm::Constant *StrongIvarBitmap = MakeBitField(StrongIvars); - llvm::Constant *WeakIvarBitmap = MakeBitField(WeakIvars); - llvm::GlobalVariable *IvarOffsetArray = - IvarOffsetValues.finishAndCreateGlobal(".ivar.offsets", - CGM.getPointerAlign()); - - // Collect information about instance methods - SmallVector<const ObjCMethodDecl*, 16> InstanceMethods; - InstanceMethods.insert(InstanceMethods.begin(), OID->instmeth_begin(), - OID->instmeth_end()); - - SmallVector<const ObjCMethodDecl*, 16> ClassMethods; - ClassMethods.insert(ClassMethods.begin(), OID->classmeth_begin(), - OID->classmeth_end()); - - // Collect the same information about synthesized properties, which don't - // show up in the instance method lists. - for (auto *propertyImpl : OID->property_impls()) - if (propertyImpl->getPropertyImplementation() == - ObjCPropertyImplDecl::Synthesize) { - ObjCPropertyDecl *property = propertyImpl->getPropertyDecl(); - auto addPropertyMethod = [&](const ObjCMethodDecl *accessor) { - if (accessor) - InstanceMethods.push_back(accessor); - }; - addPropertyMethod(property->getGetterMethodDecl()); - addPropertyMethod(property->getSetterMethodDecl()); - } - - llvm::Constant *Properties = GeneratePropertyList(OID, ClassDecl); - - // Collect the names of referenced protocols - SmallVector<std::string, 16> Protocols; - for (const auto *I : ClassDecl->protocols()) - Protocols.push_back(I->getNameAsString()); - - // Get the superclass pointer. - llvm::Constant *SuperClass; - if (!SuperClassName.empty()) { - SuperClass = MakeConstantString(SuperClassName, ".super_class_name"); - } else { - SuperClass = llvm::ConstantPointerNull::get(PtrToInt8Ty); - } - // Empty vector used to construct empty method lists - SmallVector<llvm::Constant*, 1> empty; - // Generate the method and instance variable lists - llvm::Constant *MethodList = GenerateMethodList(ClassName, "", - InstanceMethods, false); - llvm::Constant *ClassMethodList = GenerateMethodList(ClassName, "", - ClassMethods, true); - llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes, - IvarOffsets, IvarAligns, IvarOwnership); - // Irrespective of whether we are compiling for a fragile or non-fragile ABI, - // we emit a symbol containing the offset for each ivar in the class. This - // allows code compiled for the non-Fragile ABI to inherit from code compiled - // for the legacy ABI, without causing problems. The converse is also - // possible, but causes all ivar accesses to be fragile. - - // Offset pointer for getting at the correct field in the ivar list when - // setting up the alias. These are: The base address for the global, the - // ivar array (second field), the ivar in this list (set for each ivar), and - // the offset (third field in ivar structure) - llvm::Type *IndexTy = Int32Ty; - llvm::Constant *offsetPointerIndexes[] = {Zeros[0], - llvm::ConstantInt::get(IndexTy, ClassABIVersion > 1 ? 2 : 1), nullptr, - llvm::ConstantInt::get(IndexTy, ClassABIVersion > 1 ? 3 : 2) }; - - unsigned ivarIndex = 0; - for (const ObjCIvarDecl *IVD = ClassDecl->all_declared_ivar_begin(); IVD; - IVD = IVD->getNextIvar()) { - const std::string Name = GetIVarOffsetVariableName(ClassDecl, IVD); - offsetPointerIndexes[2] = llvm::ConstantInt::get(IndexTy, ivarIndex); - // Get the correct ivar field - llvm::Constant *offsetValue = llvm::ConstantExpr::getGetElementPtr( - cast<llvm::GlobalVariable>(IvarList)->getValueType(), IvarList, - offsetPointerIndexes); - // Get the existing variable, if one exists. - llvm::GlobalVariable *offset = TheModule.getNamedGlobal(Name); - if (offset) { - offset->setInitializer(offsetValue); - // If this is the real definition, change its linkage type so that - // different modules will use this one, rather than their private - // copy. - offset->setLinkage(llvm::GlobalValue::ExternalLinkage); - } else - // Add a new alias if there isn't one already. - new llvm::GlobalVariable(TheModule, offsetValue->getType(), - false, llvm::GlobalValue::ExternalLinkage, offsetValue, Name); - ++ivarIndex; - } - llvm::Constant *ZeroPtr = llvm::ConstantInt::get(IntPtrTy, 0); - - //Generate metaclass for class methods - llvm::Constant *MetaClassStruct = GenerateClassStructure( - NULLPtr, NULLPtr, 0x12L, ClassName.c_str(), nullptr, Zeros[0], - NULLPtr, ClassMethodList, NULLPtr, NULLPtr, - GeneratePropertyList(OID, ClassDecl, true), ZeroPtr, ZeroPtr, true); - CGM.setGVProperties(cast<llvm::GlobalValue>(MetaClassStruct), - OID->getClassInterface()); - - // Generate the class structure - llvm::Constant *ClassStruct = GenerateClassStructure( - MetaClassStruct, SuperClass, 0x11L, ClassName.c_str(), nullptr, - llvm::ConstantInt::get(LongTy, instanceSize), IvarList, MethodList, - GenerateProtocolList(Protocols), IvarOffsetArray, Properties, - StrongIvarBitmap, WeakIvarBitmap); - CGM.setGVProperties(cast<llvm::GlobalValue>(ClassStruct), - OID->getClassInterface()); - - // Resolve the class aliases, if they exist. - if (ClassPtrAlias) { - ClassPtrAlias->replaceAllUsesWith( - llvm::ConstantExpr::getBitCast(ClassStruct, IdTy)); - ClassPtrAlias->eraseFromParent(); - ClassPtrAlias = nullptr; - } - if (MetaClassPtrAlias) { - MetaClassPtrAlias->replaceAllUsesWith( - llvm::ConstantExpr::getBitCast(MetaClassStruct, IdTy)); - MetaClassPtrAlias->eraseFromParent(); - MetaClassPtrAlias = nullptr; - } - - // Add class structure to list to be added to the symtab later - ClassStruct = llvm::ConstantExpr::getBitCast(ClassStruct, PtrToInt8Ty); - Classes.push_back(ClassStruct); -} - -llvm::Function *CGObjCGNU::ModuleInitFunction() { - // Only emit an ObjC load function if no Objective-C stuff has been called - if (Classes.empty() && Categories.empty() && ConstantStrings.empty() && - ExistingProtocols.empty() && SelectorTable.empty()) - return nullptr; - - // Add all referenced protocols to a category. - GenerateProtocolHolderCategory(); - - llvm::StructType *selStructTy = - dyn_cast<llvm::StructType>(SelectorTy->getElementType()); - llvm::Type *selStructPtrTy = SelectorTy; - if (!selStructTy) { - selStructTy = llvm::StructType::get(CGM.getLLVMContext(), - { PtrToInt8Ty, PtrToInt8Ty }); - selStructPtrTy = llvm::PointerType::getUnqual(selStructTy); - } - - // Generate statics list: - llvm::Constant *statics = NULLPtr; - if (!ConstantStrings.empty()) { - llvm::GlobalVariable *fileStatics = [&] { - ConstantInitBuilder builder(CGM); - auto staticsStruct = builder.beginStruct(); - - StringRef stringClass = CGM.getLangOpts().ObjCConstantStringClass; - if (stringClass.empty()) stringClass = "NXConstantString"; - staticsStruct.add(MakeConstantString(stringClass, - ".objc_static_class_name")); - - auto array = staticsStruct.beginArray(); - array.addAll(ConstantStrings); - array.add(NULLPtr); - array.finishAndAddTo(staticsStruct); - - return staticsStruct.finishAndCreateGlobal(".objc_statics", - CGM.getPointerAlign()); - }(); - - ConstantInitBuilder builder(CGM); - auto allStaticsArray = builder.beginArray(fileStatics->getType()); - allStaticsArray.add(fileStatics); - allStaticsArray.addNullPointer(fileStatics->getType()); - - statics = allStaticsArray.finishAndCreateGlobal(".objc_statics_ptr", - CGM.getPointerAlign()); - statics = llvm::ConstantExpr::getBitCast(statics, PtrTy); - } - - // Array of classes, categories, and constant objects. - - SmallVector<llvm::GlobalAlias*, 16> selectorAliases; - unsigned selectorCount; - - // Pointer to an array of selectors used in this module. - llvm::GlobalVariable *selectorList = [&] { - ConstantInitBuilder builder(CGM); - auto selectors = builder.beginArray(selStructTy); - auto &table = SelectorTable; // MSVC workaround - std::vector<Selector> allSelectors; - for (auto &entry : table) - allSelectors.push_back(entry.first); - llvm::sort(allSelectors); - - for (auto &untypedSel : allSelectors) { - std::string selNameStr = untypedSel.getAsString(); - llvm::Constant *selName = ExportUniqueString(selNameStr, ".objc_sel_name"); - - for (TypedSelector &sel : table[untypedSel]) { - llvm::Constant *selectorTypeEncoding = NULLPtr; - if (!sel.first.empty()) - selectorTypeEncoding = - MakeConstantString(sel.first, ".objc_sel_types"); - - auto selStruct = selectors.beginStruct(selStructTy); - selStruct.add(selName); - selStruct.add(selectorTypeEncoding); - selStruct.finishAndAddTo(selectors); - - // Store the selector alias for later replacement - selectorAliases.push_back(sel.second); - } - } - - // Remember the number of entries in the selector table. - selectorCount = selectors.size(); - - // NULL-terminate the selector list. This should not actually be required, - // because the selector list has a length field. Unfortunately, the GCC - // runtime decides to ignore the length field and expects a NULL terminator, - // and GCC cooperates with this by always setting the length to 0. - auto selStruct = selectors.beginStruct(selStructTy); - selStruct.add(NULLPtr); - selStruct.add(NULLPtr); - selStruct.finishAndAddTo(selectors); - - return selectors.finishAndCreateGlobal(".objc_selector_list", - CGM.getPointerAlign()); - }(); - - // Now that all of the static selectors exist, create pointers to them. - for (unsigned i = 0; i < selectorCount; ++i) { - llvm::Constant *idxs[] = { - Zeros[0], - llvm::ConstantInt::get(Int32Ty, i) - }; - // FIXME: We're generating redundant loads and stores here! - llvm::Constant *selPtr = llvm::ConstantExpr::getGetElementPtr( - selectorList->getValueType(), selectorList, idxs); - // If selectors are defined as an opaque type, cast the pointer to this - // type. - selPtr = llvm::ConstantExpr::getBitCast(selPtr, SelectorTy); - selectorAliases[i]->replaceAllUsesWith(selPtr); - selectorAliases[i]->eraseFromParent(); - } - - llvm::GlobalVariable *symtab = [&] { - ConstantInitBuilder builder(CGM); - auto symtab = builder.beginStruct(); - - // Number of static selectors - symtab.addInt(LongTy, selectorCount); - - symtab.addBitCast(selectorList, selStructPtrTy); - - // Number of classes defined. - symtab.addInt(CGM.Int16Ty, Classes.size()); - // Number of categories defined - symtab.addInt(CGM.Int16Ty, Categories.size()); - - // Create an array of classes, then categories, then static object instances - auto classList = symtab.beginArray(PtrToInt8Ty); - classList.addAll(Classes); - classList.addAll(Categories); - // NULL-terminated list of static object instances (mainly constant strings) - classList.add(statics); - classList.add(NULLPtr); - classList.finishAndAddTo(symtab); - - // Construct the symbol table. - return symtab.finishAndCreateGlobal("", CGM.getPointerAlign()); - }(); - - // The symbol table is contained in a module which has some version-checking - // constants - llvm::Constant *module = [&] { - llvm::Type *moduleEltTys[] = { - LongTy, LongTy, PtrToInt8Ty, symtab->getType(), IntTy - }; - llvm::StructType *moduleTy = - llvm::StructType::get(CGM.getLLVMContext(), - makeArrayRef(moduleEltTys).drop_back(unsigned(RuntimeVersion < 10))); - - ConstantInitBuilder builder(CGM); - auto module = builder.beginStruct(moduleTy); - // Runtime version, used for ABI compatibility checking. - module.addInt(LongTy, RuntimeVersion); - // sizeof(ModuleTy) - module.addInt(LongTy, CGM.getDataLayout().getTypeStoreSize(moduleTy)); - - // The path to the source file where this module was declared - SourceManager &SM = CGM.getContext().getSourceManager(); - const FileEntry *mainFile = SM.getFileEntryForID(SM.getMainFileID()); - std::string path = - (Twine(mainFile->getDir()->getName()) + "/" + mainFile->getName()).str(); - module.add(MakeConstantString(path, ".objc_source_file_name")); - module.add(symtab); - - if (RuntimeVersion >= 10) { - switch (CGM.getLangOpts().getGC()) { - case LangOptions::GCOnly: - module.addInt(IntTy, 2); - break; - case LangOptions::NonGC: - if (CGM.getLangOpts().ObjCAutoRefCount) - module.addInt(IntTy, 1); - else - module.addInt(IntTy, 0); - break; - case LangOptions::HybridGC: - module.addInt(IntTy, 1); - break; - } - } - - return module.finishAndCreateGlobal("", CGM.getPointerAlign()); - }(); - - // Create the load function calling the runtime entry point with the module - // structure - llvm::Function * LoadFunction = llvm::Function::Create( - llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false), - llvm::GlobalValue::InternalLinkage, ".objc_load_function", - &TheModule); - llvm::BasicBlock *EntryBB = - llvm::BasicBlock::Create(VMContext, "entry", LoadFunction); - CGBuilderTy Builder(CGM, VMContext); - Builder.SetInsertPoint(EntryBB); - - llvm::FunctionType *FT = - llvm::FunctionType::get(Builder.getVoidTy(), module->getType(), true); - llvm::Value *Register = CGM.CreateRuntimeFunction(FT, "__objc_exec_class"); - Builder.CreateCall(Register, module); - - if (!ClassAliases.empty()) { - llvm::Type *ArgTypes[2] = {PtrTy, PtrToInt8Ty}; - llvm::FunctionType *RegisterAliasTy = - llvm::FunctionType::get(Builder.getVoidTy(), - ArgTypes, false); - llvm::Function *RegisterAlias = llvm::Function::Create( - RegisterAliasTy, - llvm::GlobalValue::ExternalWeakLinkage, "class_registerAlias_np", - &TheModule); - llvm::BasicBlock *AliasBB = - llvm::BasicBlock::Create(VMContext, "alias", LoadFunction); - llvm::BasicBlock *NoAliasBB = - llvm::BasicBlock::Create(VMContext, "no_alias", LoadFunction); - - // Branch based on whether the runtime provided class_registerAlias_np() - llvm::Value *HasRegisterAlias = Builder.CreateICmpNE(RegisterAlias, - llvm::Constant::getNullValue(RegisterAlias->getType())); - Builder.CreateCondBr(HasRegisterAlias, AliasBB, NoAliasBB); - - // The true branch (has alias registration function): - Builder.SetInsertPoint(AliasBB); - // Emit alias registration calls: - for (std::vector<ClassAliasPair>::iterator iter = ClassAliases.begin(); - iter != ClassAliases.end(); ++iter) { - llvm::Constant *TheClass = - TheModule.getGlobalVariable("_OBJC_CLASS_" + iter->first, true); - if (TheClass) { - TheClass = llvm::ConstantExpr::getBitCast(TheClass, PtrTy); - Builder.CreateCall(RegisterAlias, - {TheClass, MakeConstantString(iter->second)}); - } - } - // Jump to end: - Builder.CreateBr(NoAliasBB); - - // Missing alias registration function, just return from the function: - Builder.SetInsertPoint(NoAliasBB); - } - Builder.CreateRetVoid(); - - return LoadFunction; -} - -llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD, - const ObjCContainerDecl *CD) { - const ObjCCategoryImplDecl *OCD = - dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext()); - StringRef CategoryName = OCD ? OCD->getName() : ""; - StringRef ClassName = CD->getName(); - Selector MethodName = OMD->getSelector(); - bool isClassMethod = !OMD->isInstanceMethod(); - - CodeGenTypes &Types = CGM.getTypes(); - llvm::FunctionType *MethodTy = - Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD)); - std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName, - MethodName, isClassMethod); - - llvm::Function *Method - = llvm::Function::Create(MethodTy, - llvm::GlobalValue::InternalLinkage, - FunctionName, - &TheModule); - return Method; -} - -llvm::Constant *CGObjCGNU::GetPropertyGetFunction() { - return GetPropertyFn; -} - -llvm::Constant *CGObjCGNU::GetPropertySetFunction() { - return SetPropertyFn; -} - -llvm::Constant *CGObjCGNU::GetOptimizedPropertySetFunction(bool atomic, - bool copy) { - return nullptr; -} - -llvm::Constant *CGObjCGNU::GetGetStructFunction() { - return GetStructPropertyFn; -} - -llvm::Constant *CGObjCGNU::GetSetStructFunction() { - return SetStructPropertyFn; -} - -llvm::Constant *CGObjCGNU::GetCppAtomicObjectGetFunction() { - return nullptr; -} - -llvm::Constant *CGObjCGNU::GetCppAtomicObjectSetFunction() { - return nullptr; -} - -llvm::Constant *CGObjCGNU::EnumerationMutationFunction() { - return EnumerationMutationFn; -} - -void CGObjCGNU::EmitSynchronizedStmt(CodeGenFunction &CGF, - const ObjCAtSynchronizedStmt &S) { - EmitAtSynchronizedStmt(CGF, S, SyncEnterFn, SyncExitFn); -} - - -void CGObjCGNU::EmitTryStmt(CodeGenFunction &CGF, - const ObjCAtTryStmt &S) { - // Unlike the Apple non-fragile runtimes, which also uses - // unwind-based zero cost exceptions, the GNU Objective C runtime's - // EH support isn't a veneer over C++ EH. Instead, exception - // objects are created by objc_exception_throw and destroyed by - // the personality function; this avoids the need for bracketing - // catch handlers with calls to __blah_begin_catch/__blah_end_catch - // (or even _Unwind_DeleteException), but probably doesn't - // interoperate very well with foreign exceptions. - // - // In Objective-C++ mode, we actually emit something equivalent to the C++ - // exception handler. - EmitTryCatchStmt(CGF, S, EnterCatchFn, ExitCatchFn, ExceptionReThrowFn); -} - -void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF, - const ObjCAtThrowStmt &S, - bool ClearInsertionPoint) { - llvm::Value *ExceptionAsObject; - bool isRethrow = false; - - if (const Expr *ThrowExpr = S.getThrowExpr()) { - llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr); - ExceptionAsObject = Exception; - } else { - assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) && - "Unexpected rethrow outside @catch block."); - ExceptionAsObject = CGF.ObjCEHValueStack.back(); - isRethrow = true; - } - if (isRethrow && usesSEHExceptions) { - // For SEH, ExceptionAsObject may be undef, because the catch handler is - // not passed it for catchalls and so it is not visible to the catch - // funclet. The real thrown object will still be live on the stack at this - // point and will be rethrown. If we are explicitly rethrowing the object - // that was passed into the `@catch` block, then this code path is not - // reached and we will instead call `objc_exception_throw` with an explicit - // argument. - CGF.EmitRuntimeCallOrInvoke(ExceptionReThrowFn).setDoesNotReturn(); - } - else { - ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy); - llvm::CallSite Throw = - CGF.EmitRuntimeCallOrInvoke(ExceptionThrowFn, ExceptionAsObject); - Throw.setDoesNotReturn(); - } - CGF.Builder.CreateUnreachable(); - if (ClearInsertionPoint) - CGF.Builder.ClearInsertionPoint(); -} - -llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGenFunction &CGF, - Address AddrWeakObj) { - CGBuilderTy &B = CGF.Builder; - AddrWeakObj = EnforceType(B, AddrWeakObj, PtrToIdTy); - return B.CreateCall(WeakReadFn.getType(), WeakReadFn, - AddrWeakObj.getPointer()); -} - -void CGObjCGNU::EmitObjCWeakAssign(CodeGenFunction &CGF, - llvm::Value *src, Address dst) { - CGBuilderTy &B = CGF.Builder; - src = EnforceType(B, src, IdTy); - dst = EnforceType(B, dst, PtrToIdTy); - B.CreateCall(WeakAssignFn.getType(), WeakAssignFn, - {src, dst.getPointer()}); -} - -void CGObjCGNU::EmitObjCGlobalAssign(CodeGenFunction &CGF, - llvm::Value *src, Address dst, - bool threadlocal) { - CGBuilderTy &B = CGF.Builder; - src = EnforceType(B, src, IdTy); - dst = EnforceType(B, dst, PtrToIdTy); - // FIXME. Add threadloca assign API - assert(!threadlocal && "EmitObjCGlobalAssign - Threal Local API NYI"); - B.CreateCall(GlobalAssignFn.getType(), GlobalAssignFn, - {src, dst.getPointer()}); -} - -void CGObjCGNU::EmitObjCIvarAssign(CodeGenFunction &CGF, - llvm::Value *src, Address dst, - llvm::Value *ivarOffset) { - CGBuilderTy &B = CGF.Builder; - src = EnforceType(B, src, IdTy); - dst = EnforceType(B, dst, IdTy); - B.CreateCall(IvarAssignFn.getType(), IvarAssignFn, - {src, dst.getPointer(), ivarOffset}); -} - -void CGObjCGNU::EmitObjCStrongCastAssign(CodeGenFunction &CGF, - llvm::Value *src, Address dst) { - CGBuilderTy &B = CGF.Builder; - src = EnforceType(B, src, IdTy); - dst = EnforceType(B, dst, PtrToIdTy); - B.CreateCall(StrongCastAssignFn.getType(), StrongCastAssignFn, - {src, dst.getPointer()}); -} - -void CGObjCGNU::EmitGCMemmoveCollectable(CodeGenFunction &CGF, - Address DestPtr, - Address SrcPtr, - llvm::Value *Size) { - CGBuilderTy &B = CGF.Builder; - DestPtr = EnforceType(B, DestPtr, PtrTy); - SrcPtr = EnforceType(B, SrcPtr, PtrTy); - - B.CreateCall(MemMoveFn.getType(), MemMoveFn, - {DestPtr.getPointer(), SrcPtr.getPointer(), Size}); -} - -llvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable( - const ObjCInterfaceDecl *ID, - const ObjCIvarDecl *Ivar) { - const std::string Name = GetIVarOffsetVariableName(ID, Ivar); - // Emit the variable and initialize it with what we think the correct value - // is. This allows code compiled with non-fragile ivars to work correctly - // when linked against code which isn't (most of the time). - llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name); - if (!IvarOffsetPointer) - IvarOffsetPointer = new llvm::GlobalVariable(TheModule, - llvm::Type::getInt32PtrTy(VMContext), false, - llvm::GlobalValue::ExternalLinkage, nullptr, Name); - return IvarOffsetPointer; -} - -LValue CGObjCGNU::EmitObjCValueForIvar(CodeGenFunction &CGF, - QualType ObjectTy, - llvm::Value *BaseValue, - const ObjCIvarDecl *Ivar, - unsigned CVRQualifiers) { - const ObjCInterfaceDecl *ID = - ObjectTy->getAs<ObjCObjectType>()->getInterface(); - return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, - EmitIvarOffset(CGF, ID, Ivar)); -} - -static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context, - const ObjCInterfaceDecl *OID, - const ObjCIvarDecl *OIVD) { - for (const ObjCIvarDecl *next = OID->all_declared_ivar_begin(); next; - next = next->getNextIvar()) { - if (OIVD == next) - return OID; - } - - // Otherwise check in the super class. - if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) - return FindIvarInterface(Context, Super, OIVD); - - return nullptr; -} - -llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF, - const ObjCInterfaceDecl *Interface, - const ObjCIvarDecl *Ivar) { - if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) { - Interface = FindIvarInterface(CGM.getContext(), Interface, Ivar); - - // The MSVC linker cannot have a single global defined as LinkOnceAnyLinkage - // and ExternalLinkage, so create a reference to the ivar global and rely on - // the definition being created as part of GenerateClass. - if (RuntimeVersion < 10 || - CGF.CGM.getTarget().getTriple().isKnownWindowsMSVCEnvironment()) - return CGF.Builder.CreateZExtOrBitCast( - CGF.Builder.CreateAlignedLoad( - Int32Ty, CGF.Builder.CreateAlignedLoad( - ObjCIvarOffsetVariable(Interface, Ivar), - CGF.getPointerAlign(), "ivar"), - CharUnits::fromQuantity(4)), - PtrDiffTy); - std::string name = "__objc_ivar_offset_value_" + - Interface->getNameAsString() +"." + Ivar->getNameAsString(); - CharUnits Align = CGM.getIntAlign(); - llvm::Value *Offset = TheModule.getGlobalVariable(name); - if (!Offset) { - auto GV = new llvm::GlobalVariable(TheModule, IntTy, - false, llvm::GlobalValue::LinkOnceAnyLinkage, - llvm::Constant::getNullValue(IntTy), name); - GV->setAlignment(Align.getQuantity()); - Offset = GV; - } - Offset = CGF.Builder.CreateAlignedLoad(Offset, Align); - if (Offset->getType() != PtrDiffTy) - Offset = CGF.Builder.CreateZExtOrBitCast(Offset, PtrDiffTy); - return Offset; - } - uint64_t Offset = ComputeIvarBaseOffset(CGF.CGM, Interface, Ivar); - return llvm::ConstantInt::get(PtrDiffTy, Offset, /*isSigned*/true); -} - -CGObjCRuntime * -clang::CodeGen::CreateGNUObjCRuntime(CodeGenModule &CGM) { - auto Runtime = CGM.getLangOpts().ObjCRuntime; - switch (Runtime.getKind()) { - case ObjCRuntime::GNUstep: - if (Runtime.getVersion() >= VersionTuple(2, 0)) - return new CGObjCGNUstep2(CGM); - return new CGObjCGNUstep(CGM); - - case ObjCRuntime::GCC: - return new CGObjCGCC(CGM); - - case ObjCRuntime::ObjFW: - return new CGObjCObjFW(CGM); - - case ObjCRuntime::FragileMacOSX: - case ObjCRuntime::MacOSX: - case ObjCRuntime::iOS: - case ObjCRuntime::WatchOS: - llvm_unreachable("these runtimes are not GNU runtimes"); - } - llvm_unreachable("bad runtime"); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp deleted file mode 100644 index d91eb43ca32..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp +++ /dev/null @@ -1,7663 +0,0 @@ -//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This provides Objective-C code generation targeting the Apple runtime. -// -//===----------------------------------------------------------------------===// - -#include "CGBlocks.h" -#include "CGCleanup.h" -#include "CGObjCRuntime.h" -#include "CGRecordLayout.h" -#include "CodeGenFunction.h" -#include "CodeGenModule.h" -#include "clang/CodeGen/ConstantInitBuilder.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/RecordLayout.h" -#include "clang/AST/StmtObjC.h" -#include "clang/Basic/CodeGenOptions.h" -#include "clang/Basic/LangOptions.h" -#include "clang/CodeGen/CGFunctionInfo.h" -#include "llvm/ADT/CachedHashString.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/ScopedPrinter.h" -#include "llvm/Support/raw_ostream.h" -#include <cstdio> - -using namespace clang; -using namespace CodeGen; - -namespace { - -// FIXME: We should find a nicer way to make the labels for metadata, string -// concatenation is lame. - -class ObjCCommonTypesHelper { -protected: - llvm::LLVMContext &VMContext; - -private: - // The types of these functions don't really matter because we - // should always bitcast before calling them. - - /// id objc_msgSend (id, SEL, ...) - /// - /// The default messenger, used for sends whose ABI is unchanged from - /// the all-integer/pointer case. - llvm::Constant *getMessageSendFn() const { - // Add the non-lazy-bind attribute, since objc_msgSend is likely to - // be called a lot. - llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; - return CGM.CreateRuntimeFunction( - llvm::FunctionType::get(ObjectPtrTy, params, true), "objc_msgSend", - llvm::AttributeList::get(CGM.getLLVMContext(), - llvm::AttributeList::FunctionIndex, - llvm::Attribute::NonLazyBind)); - } - - /// void objc_msgSend_stret (id, SEL, ...) - /// - /// The messenger used when the return value is an aggregate returned - /// by indirect reference in the first argument, and therefore the - /// self and selector parameters are shifted over by one. - llvm::Constant *getMessageSendStretFn() const { - llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, - params, true), - "objc_msgSend_stret"); - - } - - /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...) - /// - /// The messenger used when the return value is returned on the x87 - /// floating-point stack; without a special entrypoint, the nil case - /// would be unbalanced. - llvm::Constant *getMessageSendFpretFn() const { - llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy, - params, true), - "objc_msgSend_fpret"); - - } - - /// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...) - /// - /// The messenger used when the return value is returned in two values on the - /// x87 floating point stack; without a special entrypoint, the nil case - /// would be unbalanced. Only used on 64-bit X86. - llvm::Constant *getMessageSendFp2retFn() const { - llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; - llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext); - llvm::Type *resultType = - llvm::StructType::get(longDoubleType, longDoubleType); - - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(resultType, - params, true), - "objc_msgSend_fp2ret"); - } - - /// id objc_msgSendSuper(struct objc_super *super, SEL op, ...) - /// - /// The messenger used for super calls, which have different dispatch - /// semantics. The class passed is the superclass of the current - /// class. - llvm::Constant *getMessageSendSuperFn() const { - llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, - params, true), - "objc_msgSendSuper"); - } - - /// id objc_msgSendSuper2(struct objc_super *super, SEL op, ...) - /// - /// A slightly different messenger used for super calls. The class - /// passed is the current class. - llvm::Constant *getMessageSendSuperFn2() const { - llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, - params, true), - "objc_msgSendSuper2"); - } - - /// void objc_msgSendSuper_stret(void *stretAddr, struct objc_super *super, - /// SEL op, ...) - /// - /// The messenger used for super calls which return an aggregate indirectly. - llvm::Constant *getMessageSendSuperStretFn() const { - llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy }; - return CGM.CreateRuntimeFunction( - llvm::FunctionType::get(CGM.VoidTy, params, true), - "objc_msgSendSuper_stret"); - } - - /// void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super, - /// SEL op, ...) - /// - /// objc_msgSendSuper_stret with the super2 semantics. - llvm::Constant *getMessageSendSuperStretFn2() const { - llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy }; - return CGM.CreateRuntimeFunction( - llvm::FunctionType::get(CGM.VoidTy, params, true), - "objc_msgSendSuper2_stret"); - } - - llvm::Constant *getMessageSendSuperFpretFn() const { - // There is no objc_msgSendSuper_fpret? How can that work? - return getMessageSendSuperFn(); - } - - llvm::Constant *getMessageSendSuperFpretFn2() const { - // There is no objc_msgSendSuper_fpret? How can that work? - return getMessageSendSuperFn2(); - } - -protected: - CodeGen::CodeGenModule &CGM; - -public: - llvm::IntegerType *ShortTy, *IntTy, *LongTy; - llvm::PointerType *Int8PtrTy, *Int8PtrPtrTy; - llvm::Type *IvarOffsetVarTy; - - /// ObjectPtrTy - LLVM type for object handles (typeof(id)) - llvm::PointerType *ObjectPtrTy; - - /// PtrObjectPtrTy - LLVM type for id * - llvm::PointerType *PtrObjectPtrTy; - - /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL)) - llvm::PointerType *SelectorPtrTy; - -private: - /// ProtocolPtrTy - LLVM type for external protocol handles - /// (typeof(Protocol)) - llvm::Type *ExternalProtocolPtrTy; - -public: - llvm::Type *getExternalProtocolPtrTy() { - if (!ExternalProtocolPtrTy) { - // FIXME: It would be nice to unify this with the opaque type, so that the - // IR comes out a bit cleaner. - CodeGen::CodeGenTypes &Types = CGM.getTypes(); - ASTContext &Ctx = CGM.getContext(); - llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType()); - ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T); - } - - return ExternalProtocolPtrTy; - } - - // SuperCTy - clang type for struct objc_super. - QualType SuperCTy; - // SuperPtrCTy - clang type for struct objc_super *. - QualType SuperPtrCTy; - - /// SuperTy - LLVM type for struct objc_super. - llvm::StructType *SuperTy; - /// SuperPtrTy - LLVM type for struct objc_super *. - llvm::PointerType *SuperPtrTy; - - /// PropertyTy - LLVM type for struct objc_property (struct _prop_t - /// in GCC parlance). - llvm::StructType *PropertyTy; - - /// PropertyListTy - LLVM type for struct objc_property_list - /// (_prop_list_t in GCC parlance). - llvm::StructType *PropertyListTy; - /// PropertyListPtrTy - LLVM type for struct objc_property_list*. - llvm::PointerType *PropertyListPtrTy; - - // MethodTy - LLVM type for struct objc_method. - llvm::StructType *MethodTy; - - /// CacheTy - LLVM type for struct objc_cache. - llvm::Type *CacheTy; - /// CachePtrTy - LLVM type for struct objc_cache *. - llvm::PointerType *CachePtrTy; - - llvm::Constant *getGetPropertyFn() { - CodeGen::CodeGenTypes &Types = CGM.getTypes(); - ASTContext &Ctx = CGM.getContext(); - // id objc_getProperty (id, SEL, ptrdiff_t, bool) - CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType()); - CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType()); - CanQualType Params[] = { - IdType, SelType, - Ctx.getPointerDiffType()->getCanonicalTypeUnqualified(), Ctx.BoolTy}; - llvm::FunctionType *FTy = - Types.GetFunctionType( - Types.arrangeBuiltinFunctionDeclaration(IdType, Params)); - return CGM.CreateRuntimeFunction(FTy, "objc_getProperty"); - } - - llvm::Constant *getSetPropertyFn() { - CodeGen::CodeGenTypes &Types = CGM.getTypes(); - ASTContext &Ctx = CGM.getContext(); - // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool) - CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType()); - CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType()); - CanQualType Params[] = { - IdType, - SelType, - Ctx.getPointerDiffType()->getCanonicalTypeUnqualified(), - IdType, - Ctx.BoolTy, - Ctx.BoolTy}; - llvm::FunctionType *FTy = - Types.GetFunctionType( - Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); - return CGM.CreateRuntimeFunction(FTy, "objc_setProperty"); - } - - llvm::Constant *getOptimizedSetPropertyFn(bool atomic, bool copy) { - CodeGen::CodeGenTypes &Types = CGM.getTypes(); - ASTContext &Ctx = CGM.getContext(); - // void objc_setProperty_atomic(id self, SEL _cmd, - // id newValue, ptrdiff_t offset); - // void objc_setProperty_nonatomic(id self, SEL _cmd, - // id newValue, ptrdiff_t offset); - // void objc_setProperty_atomic_copy(id self, SEL _cmd, - // id newValue, ptrdiff_t offset); - // void objc_setProperty_nonatomic_copy(id self, SEL _cmd, - // id newValue, ptrdiff_t offset); - - SmallVector<CanQualType,4> Params; - CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType()); - CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType()); - Params.push_back(IdType); - Params.push_back(SelType); - Params.push_back(IdType); - Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified()); - llvm::FunctionType *FTy = - Types.GetFunctionType( - Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); - const char *name; - if (atomic && copy) - name = "objc_setProperty_atomic_copy"; - else if (atomic && !copy) - name = "objc_setProperty_atomic"; - else if (!atomic && copy) - name = "objc_setProperty_nonatomic_copy"; - else - name = "objc_setProperty_nonatomic"; - - return CGM.CreateRuntimeFunction(FTy, name); - } - - llvm::Constant *getCopyStructFn() { - CodeGen::CodeGenTypes &Types = CGM.getTypes(); - ASTContext &Ctx = CGM.getContext(); - // void objc_copyStruct (void *, const void *, size_t, bool, bool) - SmallVector<CanQualType,5> Params; - Params.push_back(Ctx.VoidPtrTy); - Params.push_back(Ctx.VoidPtrTy); - Params.push_back(Ctx.getSizeType()); - Params.push_back(Ctx.BoolTy); - Params.push_back(Ctx.BoolTy); - llvm::FunctionType *FTy = - Types.GetFunctionType( - Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); - return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct"); - } - - /// This routine declares and returns address of: - /// void objc_copyCppObjectAtomic( - /// void *dest, const void *src, - /// void (*copyHelper) (void *dest, const void *source)); - llvm::Constant *getCppAtomicObjectFunction() { - CodeGen::CodeGenTypes &Types = CGM.getTypes(); - ASTContext &Ctx = CGM.getContext(); - /// void objc_copyCppObjectAtomic(void *dest, const void *src, void *helper); - SmallVector<CanQualType,3> Params; - Params.push_back(Ctx.VoidPtrTy); - Params.push_back(Ctx.VoidPtrTy); - Params.push_back(Ctx.VoidPtrTy); - llvm::FunctionType *FTy = - Types.GetFunctionType( - Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); - return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic"); - } - - llvm::Constant *getEnumerationMutationFn() { - CodeGen::CodeGenTypes &Types = CGM.getTypes(); - ASTContext &Ctx = CGM.getContext(); - // void objc_enumerationMutation (id) - SmallVector<CanQualType,1> Params; - Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType())); - llvm::FunctionType *FTy = - Types.GetFunctionType( - Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); - return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation"); - } - - llvm::Constant *getLookUpClassFn() { - CodeGen::CodeGenTypes &Types = CGM.getTypes(); - ASTContext &Ctx = CGM.getContext(); - // Class objc_lookUpClass (const char *) - SmallVector<CanQualType,1> Params; - Params.push_back( - Ctx.getCanonicalType(Ctx.getPointerType(Ctx.CharTy.withConst()))); - llvm::FunctionType *FTy = - Types.GetFunctionType(Types.arrangeBuiltinFunctionDeclaration( - Ctx.getCanonicalType(Ctx.getObjCClassType()), - Params)); - return CGM.CreateRuntimeFunction(FTy, "objc_lookUpClass"); - } - - /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function. - llvm::Constant *getGcReadWeakFn() { - // id objc_read_weak (id *) - llvm::Type *args[] = { ObjectPtrTy->getPointerTo() }; - llvm::FunctionType *FTy = - llvm::FunctionType::get(ObjectPtrTy, args, false); - return CGM.CreateRuntimeFunction(FTy, "objc_read_weak"); - } - - /// GcAssignWeakFn -- LLVM objc_assign_weak function. - llvm::Constant *getGcAssignWeakFn() { - // id objc_assign_weak (id, id *) - llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; - llvm::FunctionType *FTy = - llvm::FunctionType::get(ObjectPtrTy, args, false); - return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak"); - } - - /// GcAssignGlobalFn -- LLVM objc_assign_global function. - llvm::Constant *getGcAssignGlobalFn() { - // id objc_assign_global(id, id *) - llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; - llvm::FunctionType *FTy = - llvm::FunctionType::get(ObjectPtrTy, args, false); - return CGM.CreateRuntimeFunction(FTy, "objc_assign_global"); - } - - /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function. - llvm::Constant *getGcAssignThreadLocalFn() { - // id objc_assign_threadlocal(id src, id * dest) - llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; - llvm::FunctionType *FTy = - llvm::FunctionType::get(ObjectPtrTy, args, false); - return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal"); - } - - /// GcAssignIvarFn -- LLVM objc_assign_ivar function. - llvm::Constant *getGcAssignIvarFn() { - // id objc_assign_ivar(id, id *, ptrdiff_t) - llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(), - CGM.PtrDiffTy }; - llvm::FunctionType *FTy = - llvm::FunctionType::get(ObjectPtrTy, args, false); - return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar"); - } - - /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function. - llvm::Constant *GcMemmoveCollectableFn() { - // void *objc_memmove_collectable(void *dst, const void *src, size_t size) - llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy }; - llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false); - return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable"); - } - - /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function. - llvm::Constant *getGcAssignStrongCastFn() { - // id objc_assign_strongCast(id, id *) - llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; - llvm::FunctionType *FTy = - llvm::FunctionType::get(ObjectPtrTy, args, false); - return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast"); - } - - /// ExceptionThrowFn - LLVM objc_exception_throw function. - llvm::Constant *getExceptionThrowFn() { - // void objc_exception_throw(id) - llvm::Type *args[] = { ObjectPtrTy }; - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, args, false); - return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw"); - } - - /// ExceptionRethrowFn - LLVM objc_exception_rethrow function. - llvm::Constant *getExceptionRethrowFn() { - // void objc_exception_rethrow(void) - llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false); - return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow"); - } - - /// SyncEnterFn - LLVM object_sync_enter function. - llvm::Constant *getSyncEnterFn() { - // int objc_sync_enter (id) - llvm::Type *args[] = { ObjectPtrTy }; - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.IntTy, args, false); - return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter"); - } - - /// SyncExitFn - LLVM object_sync_exit function. - llvm::Constant *getSyncExitFn() { - // int objc_sync_exit (id) - llvm::Type *args[] = { ObjectPtrTy }; - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.IntTy, args, false); - return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit"); - } - - llvm::Constant *getSendFn(bool IsSuper) const { - return IsSuper ? getMessageSendSuperFn() : getMessageSendFn(); - } - - llvm::Constant *getSendFn2(bool IsSuper) const { - return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn(); - } - - llvm::Constant *getSendStretFn(bool IsSuper) const { - return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn(); - } - - llvm::Constant *getSendStretFn2(bool IsSuper) const { - return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn(); - } - - llvm::Constant *getSendFpretFn(bool IsSuper) const { - return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn(); - } - - llvm::Constant *getSendFpretFn2(bool IsSuper) const { - return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn(); - } - - llvm::Constant *getSendFp2retFn(bool IsSuper) const { - return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn(); - } - - llvm::Constant *getSendFp2RetFn2(bool IsSuper) const { - return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn(); - } - - ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm); -}; - -/// ObjCTypesHelper - Helper class that encapsulates lazy -/// construction of varies types used during ObjC generation. -class ObjCTypesHelper : public ObjCCommonTypesHelper { -public: - /// SymtabTy - LLVM type for struct objc_symtab. - llvm::StructType *SymtabTy; - /// SymtabPtrTy - LLVM type for struct objc_symtab *. - llvm::PointerType *SymtabPtrTy; - /// ModuleTy - LLVM type for struct objc_module. - llvm::StructType *ModuleTy; - - /// ProtocolTy - LLVM type for struct objc_protocol. - llvm::StructType *ProtocolTy; - /// ProtocolPtrTy - LLVM type for struct objc_protocol *. - llvm::PointerType *ProtocolPtrTy; - /// ProtocolExtensionTy - LLVM type for struct - /// objc_protocol_extension. - llvm::StructType *ProtocolExtensionTy; - /// ProtocolExtensionTy - LLVM type for struct - /// objc_protocol_extension *. - llvm::PointerType *ProtocolExtensionPtrTy; - /// MethodDescriptionTy - LLVM type for struct - /// objc_method_description. - llvm::StructType *MethodDescriptionTy; - /// MethodDescriptionListTy - LLVM type for struct - /// objc_method_description_list. - llvm::StructType *MethodDescriptionListTy; - /// MethodDescriptionListPtrTy - LLVM type for struct - /// objc_method_description_list *. - llvm::PointerType *MethodDescriptionListPtrTy; - /// ProtocolListTy - LLVM type for struct objc_property_list. - llvm::StructType *ProtocolListTy; - /// ProtocolListPtrTy - LLVM type for struct objc_property_list*. - llvm::PointerType *ProtocolListPtrTy; - /// CategoryTy - LLVM type for struct objc_category. - llvm::StructType *CategoryTy; - /// ClassTy - LLVM type for struct objc_class. - llvm::StructType *ClassTy; - /// ClassPtrTy - LLVM type for struct objc_class *. - llvm::PointerType *ClassPtrTy; - /// ClassExtensionTy - LLVM type for struct objc_class_ext. - llvm::StructType *ClassExtensionTy; - /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *. - llvm::PointerType *ClassExtensionPtrTy; - // IvarTy - LLVM type for struct objc_ivar. - llvm::StructType *IvarTy; - /// IvarListTy - LLVM type for struct objc_ivar_list. - llvm::StructType *IvarListTy; - /// IvarListPtrTy - LLVM type for struct objc_ivar_list *. - llvm::PointerType *IvarListPtrTy; - /// MethodListTy - LLVM type for struct objc_method_list. - llvm::StructType *MethodListTy; - /// MethodListPtrTy - LLVM type for struct objc_method_list *. - llvm::PointerType *MethodListPtrTy; - - /// ExceptionDataTy - LLVM type for struct _objc_exception_data. - llvm::StructType *ExceptionDataTy; - - /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function. - llvm::Constant *getExceptionTryEnterFn() { - llvm::Type *params[] = { ExceptionDataTy->getPointerTo() }; - return CGM.CreateRuntimeFunction( - llvm::FunctionType::get(CGM.VoidTy, params, false), - "objc_exception_try_enter"); - } - - /// ExceptionTryExitFn - LLVM objc_exception_try_exit function. - llvm::Constant *getExceptionTryExitFn() { - llvm::Type *params[] = { ExceptionDataTy->getPointerTo() }; - return CGM.CreateRuntimeFunction( - llvm::FunctionType::get(CGM.VoidTy, params, false), - "objc_exception_try_exit"); - } - - /// ExceptionExtractFn - LLVM objc_exception_extract function. - llvm::Constant *getExceptionExtractFn() { - llvm::Type *params[] = { ExceptionDataTy->getPointerTo() }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, - params, false), - "objc_exception_extract"); - } - - /// ExceptionMatchFn - LLVM objc_exception_match function. - llvm::Constant *getExceptionMatchFn() { - llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy }; - return CGM.CreateRuntimeFunction( - llvm::FunctionType::get(CGM.Int32Ty, params, false), - "objc_exception_match"); - } - - /// SetJmpFn - LLVM _setjmp function. - llvm::Constant *getSetJmpFn() { - // This is specifically the prototype for x86. - llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() }; - return CGM.CreateRuntimeFunction( - llvm::FunctionType::get(CGM.Int32Ty, params, false), "_setjmp", - llvm::AttributeList::get(CGM.getLLVMContext(), - llvm::AttributeList::FunctionIndex, - llvm::Attribute::NonLazyBind)); - } - -public: - ObjCTypesHelper(CodeGen::CodeGenModule &cgm); -}; - -/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's -/// modern abi -class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper { -public: - // MethodListnfABITy - LLVM for struct _method_list_t - llvm::StructType *MethodListnfABITy; - - // MethodListnfABIPtrTy - LLVM for struct _method_list_t* - llvm::PointerType *MethodListnfABIPtrTy; - - // ProtocolnfABITy = LLVM for struct _protocol_t - llvm::StructType *ProtocolnfABITy; - - // ProtocolnfABIPtrTy = LLVM for struct _protocol_t* - llvm::PointerType *ProtocolnfABIPtrTy; - - // ProtocolListnfABITy - LLVM for struct _objc_protocol_list - llvm::StructType *ProtocolListnfABITy; - - // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list* - llvm::PointerType *ProtocolListnfABIPtrTy; - - // ClassnfABITy - LLVM for struct _class_t - llvm::StructType *ClassnfABITy; - - // ClassnfABIPtrTy - LLVM for struct _class_t* - llvm::PointerType *ClassnfABIPtrTy; - - // IvarnfABITy - LLVM for struct _ivar_t - llvm::StructType *IvarnfABITy; - - // IvarListnfABITy - LLVM for struct _ivar_list_t - llvm::StructType *IvarListnfABITy; - - // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t* - llvm::PointerType *IvarListnfABIPtrTy; - - // ClassRonfABITy - LLVM for struct _class_ro_t - llvm::StructType *ClassRonfABITy; - - // ImpnfABITy - LLVM for id (*)(id, SEL, ...) - llvm::PointerType *ImpnfABITy; - - // CategorynfABITy - LLVM for struct _category_t - llvm::StructType *CategorynfABITy; - - // New types for nonfragile abi messaging. - - // MessageRefTy - LLVM for: - // struct _message_ref_t { - // IMP messenger; - // SEL name; - // }; - llvm::StructType *MessageRefTy; - // MessageRefCTy - clang type for struct _message_ref_t - QualType MessageRefCTy; - - // MessageRefPtrTy - LLVM for struct _message_ref_t* - llvm::Type *MessageRefPtrTy; - // MessageRefCPtrTy - clang type for struct _message_ref_t* - QualType MessageRefCPtrTy; - - // SuperMessageRefTy - LLVM for: - // struct _super_message_ref_t { - // SUPER_IMP messenger; - // SEL name; - // }; - llvm::StructType *SuperMessageRefTy; - - // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t* - llvm::PointerType *SuperMessageRefPtrTy; - - llvm::Constant *getMessageSendFixupFn() { - // id objc_msgSend_fixup(id, struct message_ref_t*, ...) - llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, - params, true), - "objc_msgSend_fixup"); - } - - llvm::Constant *getMessageSendFpretFixupFn() { - // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...) - llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, - params, true), - "objc_msgSend_fpret_fixup"); - } - - llvm::Constant *getMessageSendStretFixupFn() { - // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...) - llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, - params, true), - "objc_msgSend_stret_fixup"); - } - - llvm::Constant *getMessageSendSuper2FixupFn() { - // id objc_msgSendSuper2_fixup (struct objc_super *, - // struct _super_message_ref_t*, ...) - llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, - params, true), - "objc_msgSendSuper2_fixup"); - } - - llvm::Constant *getMessageSendSuper2StretFixupFn() { - // id objc_msgSendSuper2_stret_fixup(struct objc_super *, - // struct _super_message_ref_t*, ...) - llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, - params, true), - "objc_msgSendSuper2_stret_fixup"); - } - - llvm::Constant *getObjCEndCatchFn() { - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false), - "objc_end_catch"); - - } - - llvm::Constant *getObjCBeginCatchFn() { - llvm::Type *params[] = { Int8PtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy, - params, false), - "objc_begin_catch"); - } - - llvm::StructType *EHTypeTy; - llvm::Type *EHTypePtrTy; - - ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm); -}; - -enum class ObjCLabelType { - ClassName, - MethodVarName, - MethodVarType, - PropertyName, -}; - -class CGObjCCommonMac : public CodeGen::CGObjCRuntime { -public: - class SKIP_SCAN { - public: - unsigned skip; - unsigned scan; - SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0) - : skip(_skip), scan(_scan) {} - }; - - /// opcode for captured block variables layout 'instructions'. - /// In the following descriptions, 'I' is the value of the immediate field. - /// (field following the opcode). - /// - enum BLOCK_LAYOUT_OPCODE { - /// An operator which affects how the following layout should be - /// interpreted. - /// I == 0: Halt interpretation and treat everything else as - /// a non-pointer. Note that this instruction is equal - /// to '\0'. - /// I != 0: Currently unused. - BLOCK_LAYOUT_OPERATOR = 0, - - /// The next I+1 bytes do not contain a value of object pointer type. - /// Note that this can leave the stream unaligned, meaning that - /// subsequent word-size instructions do not begin at a multiple of - /// the pointer size. - BLOCK_LAYOUT_NON_OBJECT_BYTES = 1, - - /// The next I+1 words do not contain a value of object pointer type. - /// This is simply an optimized version of BLOCK_LAYOUT_BYTES for - /// when the required skip quantity is a multiple of the pointer size. - BLOCK_LAYOUT_NON_OBJECT_WORDS = 2, - - /// The next I+1 words are __strong pointers to Objective-C - /// objects or blocks. - BLOCK_LAYOUT_STRONG = 3, - - /// The next I+1 words are pointers to __block variables. - BLOCK_LAYOUT_BYREF = 4, - - /// The next I+1 words are __weak pointers to Objective-C - /// objects or blocks. - BLOCK_LAYOUT_WEAK = 5, - - /// The next I+1 words are __unsafe_unretained pointers to - /// Objective-C objects or blocks. - BLOCK_LAYOUT_UNRETAINED = 6 - - /// The next I+1 words are block or object pointers with some - /// as-yet-unspecified ownership semantics. If we add more - /// flavors of ownership semantics, values will be taken from - /// this range. - /// - /// This is included so that older tools can at least continue - /// processing the layout past such things. - //BLOCK_LAYOUT_OWNERSHIP_UNKNOWN = 7..10, - - /// All other opcodes are reserved. Halt interpretation and - /// treat everything else as opaque. - }; - - class RUN_SKIP { - public: - enum BLOCK_LAYOUT_OPCODE opcode; - CharUnits block_var_bytepos; - CharUnits block_var_size; - RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR, - CharUnits BytePos = CharUnits::Zero(), - CharUnits Size = CharUnits::Zero()) - : opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {} - - // Allow sorting based on byte pos. - bool operator<(const RUN_SKIP &b) const { - return block_var_bytepos < b.block_var_bytepos; - } - }; - -protected: - llvm::LLVMContext &VMContext; - // FIXME! May not be needing this after all. - unsigned ObjCABI; - - // arc/mrr layout of captured block literal variables. - SmallVector<RUN_SKIP, 16> RunSkipBlockVars; - - /// LazySymbols - Symbols to generate a lazy reference for. See - /// DefinedSymbols and FinishModule(). - llvm::SetVector<IdentifierInfo*> LazySymbols; - - /// DefinedSymbols - External symbols which are defined by this - /// module. The symbols in this list and LazySymbols are used to add - /// special linker symbols which ensure that Objective-C modules are - /// linked properly. - llvm::SetVector<IdentifierInfo*> DefinedSymbols; - - /// ClassNames - uniqued class names. - llvm::StringMap<llvm::GlobalVariable*> ClassNames; - - /// MethodVarNames - uniqued method variable names. - llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames; - - /// DefinedCategoryNames - list of category names in form Class_Category. - llvm::SmallSetVector<llvm::CachedHashString, 16> DefinedCategoryNames; - - /// MethodVarTypes - uniqued method type signatures. We have to use - /// a StringMap here because have no other unique reference. - llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes; - - /// MethodDefinitions - map of methods which have been defined in - /// this translation unit. - llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions; - - /// PropertyNames - uniqued method variable names. - llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames; - - /// ClassReferences - uniqued class references. - llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences; - - /// SelectorReferences - uniqued selector references. - llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences; - - /// Protocols - Protocols for which an objc_protocol structure has - /// been emitted. Forward declarations are handled by creating an - /// empty structure whose initializer is filled in when/if defined. - llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols; - - /// DefinedProtocols - Protocols which have actually been - /// defined. We should not need this, see FIXME in GenerateProtocol. - llvm::DenseSet<IdentifierInfo*> DefinedProtocols; - - /// DefinedClasses - List of defined classes. - SmallVector<llvm::GlobalValue*, 16> DefinedClasses; - - /// ImplementedClasses - List of @implemented classes. - SmallVector<const ObjCInterfaceDecl*, 16> ImplementedClasses; - - /// DefinedNonLazyClasses - List of defined "non-lazy" classes. - SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyClasses; - - /// DefinedCategories - List of defined categories. - SmallVector<llvm::GlobalValue*, 16> DefinedCategories; - - /// DefinedNonLazyCategories - List of defined "non-lazy" categories. - SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories; - - /// Cached reference to the class for constant strings. This value has type - /// int * but is actually an Obj-C class pointer. - llvm::WeakTrackingVH ConstantStringClassRef; - - /// The LLVM type corresponding to NSConstantString. - llvm::StructType *NSConstantStringType = nullptr; - - llvm::StringMap<llvm::GlobalVariable *> NSConstantStringMap; - - /// GetNameForMethod - Return a name for the given method. - /// \param[out] NameOut - The return value. - void GetNameForMethod(const ObjCMethodDecl *OMD, - const ObjCContainerDecl *CD, - SmallVectorImpl<char> &NameOut); - - /// GetMethodVarName - Return a unique constant for the given - /// selector's name. The return value has type char *. - llvm::Constant *GetMethodVarName(Selector Sel); - llvm::Constant *GetMethodVarName(IdentifierInfo *Ident); - - /// GetMethodVarType - Return a unique constant for the given - /// method's type encoding string. The return value has type char *. - - // FIXME: This is a horrible name. - llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D, - bool Extended = false); - llvm::Constant *GetMethodVarType(const FieldDecl *D); - - /// GetPropertyName - Return a unique constant for the given - /// name. The return value has type char *. - llvm::Constant *GetPropertyName(IdentifierInfo *Ident); - - // FIXME: This can be dropped once string functions are unified. - llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD, - const Decl *Container); - - /// GetClassName - Return a unique constant for the given selector's - /// runtime name (which may change via use of objc_runtime_name attribute on - /// class or protocol definition. The return value has type char *. - llvm::Constant *GetClassName(StringRef RuntimeName); - - llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD); - - /// BuildIvarLayout - Builds ivar layout bitmap for the class - /// implementation for the __strong or __weak case. - /// - /// \param hasMRCWeakIvars - Whether we are compiling in MRC and there - /// are any weak ivars defined directly in the class. Meaningless unless - /// building a weak layout. Does not guarantee that the layout will - /// actually have any entries, because the ivar might be under-aligned. - llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI, - CharUnits beginOffset, - CharUnits endOffset, - bool forStrongLayout, - bool hasMRCWeakIvars); - - llvm::Constant *BuildStrongIvarLayout(const ObjCImplementationDecl *OI, - CharUnits beginOffset, - CharUnits endOffset) { - return BuildIvarLayout(OI, beginOffset, endOffset, true, false); - } - - llvm::Constant *BuildWeakIvarLayout(const ObjCImplementationDecl *OI, - CharUnits beginOffset, - CharUnits endOffset, - bool hasMRCWeakIvars) { - return BuildIvarLayout(OI, beginOffset, endOffset, false, hasMRCWeakIvars); - } - - Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout); - - void UpdateRunSkipBlockVars(bool IsByref, - Qualifiers::ObjCLifetime LifeTime, - CharUnits FieldOffset, - CharUnits FieldSize); - - void BuildRCBlockVarRecordLayout(const RecordType *RT, - CharUnits BytePos, bool &HasUnion, - bool ByrefLayout=false); - - void BuildRCRecordLayout(const llvm::StructLayout *RecLayout, - const RecordDecl *RD, - ArrayRef<const FieldDecl*> RecFields, - CharUnits BytePos, bool &HasUnion, - bool ByrefLayout); - - uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout); - - llvm::Constant *getBitmapBlockLayout(bool ComputeByrefLayout); - - /// GetIvarLayoutName - Returns a unique constant for the given - /// ivar layout bitmap. - llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident, - const ObjCCommonTypesHelper &ObjCTypes); - - /// EmitPropertyList - Emit the given property list. The return - /// value has type PropertyListPtrTy. - llvm::Constant *EmitPropertyList(Twine Name, - const Decl *Container, - const ObjCContainerDecl *OCD, - const ObjCCommonTypesHelper &ObjCTypes, - bool IsClassProperty); - - /// EmitProtocolMethodTypes - Generate the array of extended method type - /// strings. The return value has type Int8PtrPtrTy. - llvm::Constant *EmitProtocolMethodTypes(Twine Name, - ArrayRef<llvm::Constant*> MethodTypes, - const ObjCCommonTypesHelper &ObjCTypes); - - /// GetProtocolRef - Return a reference to the internal protocol - /// description, creating an empty one if it has not been - /// defined. The return value has type ProtocolPtrTy. - llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD); - - /// Return a reference to the given Class using runtime calls rather than - /// by a symbol reference. - llvm::Value *EmitClassRefViaRuntime(CodeGenFunction &CGF, - const ObjCInterfaceDecl *ID, - ObjCCommonTypesHelper &ObjCTypes); - - std::string GetSectionName(StringRef Section, StringRef MachOAttributes); - -public: - /// CreateMetadataVar - Create a global variable with internal - /// linkage for use by the Objective-C runtime. - /// - /// This is a convenience wrapper which not only creates the - /// variable, but also sets the section and alignment and adds the - /// global to the "llvm.used" list. - /// - /// \param Name - The variable name. - /// \param Init - The variable initializer; this is also used to - /// define the type of the variable. - /// \param Section - The section the variable should go into, or empty. - /// \param Align - The alignment for the variable, or 0. - /// \param AddToUsed - Whether the variable should be added to - /// "llvm.used". - llvm::GlobalVariable *CreateMetadataVar(Twine Name, - ConstantStructBuilder &Init, - StringRef Section, CharUnits Align, - bool AddToUsed); - llvm::GlobalVariable *CreateMetadataVar(Twine Name, - llvm::Constant *Init, - StringRef Section, CharUnits Align, - bool AddToUsed); - - llvm::GlobalVariable *CreateCStringLiteral(StringRef Name, - ObjCLabelType LabelType, - bool ForceNonFragileABI = false, - bool NullTerminate = true); - -protected: - CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, - QualType ResultType, - llvm::Value *Sel, - llvm::Value *Arg0, - QualType Arg0Ty, - bool IsSuper, - const CallArgList &CallArgs, - const ObjCMethodDecl *OMD, - const ObjCInterfaceDecl *ClassReceiver, - const ObjCCommonTypesHelper &ObjCTypes); - - /// EmitImageInfo - Emit the image info marker used to encode some module - /// level information. - void EmitImageInfo(); - -public: - CGObjCCommonMac(CodeGen::CodeGenModule &cgm) : - CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { } - - bool isNonFragileABI() const { - return ObjCABI == 2; - } - - ConstantAddress GenerateConstantString(const StringLiteral *SL) override; - ConstantAddress GenerateConstantNSString(const StringLiteral *SL); - - llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, - const ObjCContainerDecl *CD=nullptr) override; - - void GenerateProtocol(const ObjCProtocolDecl *PD) override; - - /// GetOrEmitProtocol - Get the protocol object for the given - /// declaration, emitting it if necessary. The return value has type - /// ProtocolPtrTy. - virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0; - - /// GetOrEmitProtocolRef - Get a forward reference to the protocol - /// object for the given declaration, emitting it if needed. These - /// forward references will be filled in with empty bodies if no - /// definition is seen. The return value has type ProtocolPtrTy. - virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0; - - virtual llvm::Constant *getNSConstantStringClassRef() = 0; - - llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM, - const CGBlockInfo &blockInfo) override; - llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM, - const CGBlockInfo &blockInfo) override; - std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM, - const CGBlockInfo &blockInfo) override; - - llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM, - QualType T) override; - -private: - void fillRunSkipBlockVars(CodeGenModule &CGM, const CGBlockInfo &blockInfo); -}; - -namespace { - -enum class MethodListType { - CategoryInstanceMethods, - CategoryClassMethods, - InstanceMethods, - ClassMethods, - ProtocolInstanceMethods, - ProtocolClassMethods, - OptionalProtocolInstanceMethods, - OptionalProtocolClassMethods, -}; - -/// A convenience class for splitting the methods of a protocol into -/// the four interesting groups. -class ProtocolMethodLists { -public: - enum Kind { - RequiredInstanceMethods, - RequiredClassMethods, - OptionalInstanceMethods, - OptionalClassMethods - }; - enum { - NumProtocolMethodLists = 4 - }; - - static MethodListType getMethodListKind(Kind kind) { - switch (kind) { - case RequiredInstanceMethods: - return MethodListType::ProtocolInstanceMethods; - case RequiredClassMethods: - return MethodListType::ProtocolClassMethods; - case OptionalInstanceMethods: - return MethodListType::OptionalProtocolInstanceMethods; - case OptionalClassMethods: - return MethodListType::OptionalProtocolClassMethods; - } - llvm_unreachable("bad kind"); - } - - SmallVector<const ObjCMethodDecl *, 4> Methods[NumProtocolMethodLists]; - - static ProtocolMethodLists get(const ObjCProtocolDecl *PD) { - ProtocolMethodLists result; - - for (auto MD : PD->methods()) { - size_t index = (2 * size_t(MD->isOptional())) - + (size_t(MD->isClassMethod())); - result.Methods[index].push_back(MD); - } - - return result; - } - - template <class Self> - SmallVector<llvm::Constant*, 8> emitExtendedTypesArray(Self *self) const { - // In both ABIs, the method types list is parallel with the - // concatenation of the methods arrays in the following order: - // instance methods - // class methods - // optional instance methods - // optional class methods - SmallVector<llvm::Constant*, 8> result; - - // Methods is already in the correct order for both ABIs. - for (auto &list : Methods) { - for (auto MD : list) { - result.push_back(self->GetMethodVarType(MD, true)); - } - } - - return result; - } - - template <class Self> - llvm::Constant *emitMethodList(Self *self, const ObjCProtocolDecl *PD, - Kind kind) const { - return self->emitMethodList(PD->getObjCRuntimeNameAsString(), - getMethodListKind(kind), Methods[kind]); - } -}; - -} // end anonymous namespace - -class CGObjCMac : public CGObjCCommonMac { -private: - friend ProtocolMethodLists; - - ObjCTypesHelper ObjCTypes; - - /// EmitModuleInfo - Another marker encoding module level - /// information. - void EmitModuleInfo(); - - /// EmitModuleSymols - Emit module symbols, the list of defined - /// classes and categories. The result has type SymtabPtrTy. - llvm::Constant *EmitModuleSymbols(); - - /// FinishModule - Write out global data structures at the end of - /// processing a translation unit. - void FinishModule(); - - /// EmitClassExtension - Generate the class extension structure used - /// to store the weak ivar layout and properties. The return value - /// has type ClassExtensionPtrTy. - llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID, - CharUnits instanceSize, - bool hasMRCWeakIvars, - bool isMetaclass); - - /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, - /// for the given class. - llvm::Value *EmitClassRef(CodeGenFunction &CGF, - const ObjCInterfaceDecl *ID); - - llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF, - IdentifierInfo *II); - - llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override; - - /// EmitSuperClassRef - Emits reference to class's main metadata class. - llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID); - - /// EmitIvarList - Emit the ivar list for the given - /// implementation. If ForClass is true the list of class ivars - /// (i.e. metaclass ivars) is emitted, otherwise the list of - /// interface ivars will be emitted. The return value has type - /// IvarListPtrTy. - llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID, - bool ForClass); - - /// EmitMetaClass - Emit a forward reference to the class structure - /// for the metaclass of the given interface. The return value has - /// type ClassPtrTy. - llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID); - - /// EmitMetaClass - Emit a class structure for the metaclass of the - /// given implementation. The return value has type ClassPtrTy. - llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID, - llvm::Constant *Protocols, - ArrayRef<const ObjCMethodDecl *> Methods); - - void emitMethodConstant(ConstantArrayBuilder &builder, - const ObjCMethodDecl *MD); - - void emitMethodDescriptionConstant(ConstantArrayBuilder &builder, - const ObjCMethodDecl *MD); - - /// EmitMethodList - Emit the method list for the given - /// implementation. The return value has type MethodListPtrTy. - llvm::Constant *emitMethodList(Twine Name, MethodListType MLT, - ArrayRef<const ObjCMethodDecl *> Methods); - - /// GetOrEmitProtocol - Get the protocol object for the given - /// declaration, emitting it if necessary. The return value has type - /// ProtocolPtrTy. - llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override; - - /// GetOrEmitProtocolRef - Get a forward reference to the protocol - /// object for the given declaration, emitting it if needed. These - /// forward references will be filled in with empty bodies if no - /// definition is seen. The return value has type ProtocolPtrTy. - llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override; - - /// EmitProtocolExtension - Generate the protocol extension - /// structure used to store optional instance and class methods, and - /// protocol properties. The return value has type - /// ProtocolExtensionPtrTy. - llvm::Constant * - EmitProtocolExtension(const ObjCProtocolDecl *PD, - const ProtocolMethodLists &methodLists); - - /// EmitProtocolList - Generate the list of referenced - /// protocols. The return value has type ProtocolListPtrTy. - llvm::Constant *EmitProtocolList(Twine Name, - ObjCProtocolDecl::protocol_iterator begin, - ObjCProtocolDecl::protocol_iterator end); - - /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, - /// for the given selector. - llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel); - Address EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel); - -public: - CGObjCMac(CodeGen::CodeGenModule &cgm); - - llvm::Constant *getNSConstantStringClassRef() override; - - llvm::Function *ModuleInitFunction() override; - - CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, - QualType ResultType, - Selector Sel, llvm::Value *Receiver, - const CallArgList &CallArgs, - const ObjCInterfaceDecl *Class, - const ObjCMethodDecl *Method) override; - - CodeGen::RValue - GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, QualType ResultType, - Selector Sel, const ObjCInterfaceDecl *Class, - bool isCategoryImpl, llvm::Value *Receiver, - bool IsClassMessage, const CallArgList &CallArgs, - const ObjCMethodDecl *Method) override; - - llvm::Value *GetClass(CodeGenFunction &CGF, - const ObjCInterfaceDecl *ID) override; - - llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override; - Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override; - - /// The NeXT/Apple runtimes do not support typed selectors; just emit an - /// untyped one. - llvm::Value *GetSelector(CodeGenFunction &CGF, - const ObjCMethodDecl *Method) override; - - llvm::Constant *GetEHType(QualType T) override; - - void GenerateCategory(const ObjCCategoryImplDecl *CMD) override; - - void GenerateClass(const ObjCImplementationDecl *ClassDecl) override; - - void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {} - - llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF, - const ObjCProtocolDecl *PD) override; - - llvm::Constant *GetPropertyGetFunction() override; - llvm::Constant *GetPropertySetFunction() override; - llvm::Constant *GetOptimizedPropertySetFunction(bool atomic, - bool copy) override; - llvm::Constant *GetGetStructFunction() override; - llvm::Constant *GetSetStructFunction() override; - llvm::Constant *GetCppAtomicObjectGetFunction() override; - llvm::Constant *GetCppAtomicObjectSetFunction() override; - llvm::Constant *EnumerationMutationFunction() override; - - void EmitTryStmt(CodeGen::CodeGenFunction &CGF, - const ObjCAtTryStmt &S) override; - void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, - const ObjCAtSynchronizedStmt &S) override; - void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S); - void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S, - bool ClearInsertionPoint=true) override; - llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, - Address AddrWeakObj) override; - void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dst) override; - void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dest, - bool threadlocal = false) override; - void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dest, - llvm::Value *ivarOffset) override; - void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dest) override; - void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, - Address dest, Address src, - llvm::Value *size) override; - - LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy, - llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, - unsigned CVRQualifiers) override; - llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, - const ObjCInterfaceDecl *Interface, - const ObjCIvarDecl *Ivar) override; -}; - -class CGObjCNonFragileABIMac : public CGObjCCommonMac { -private: - friend ProtocolMethodLists; - ObjCNonFragileABITypesHelper ObjCTypes; - llvm::GlobalVariable* ObjCEmptyCacheVar; - llvm::Constant* ObjCEmptyVtableVar; - - /// SuperClassReferences - uniqued super class references. - llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences; - - /// MetaClassReferences - uniqued meta class references. - llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences; - - /// EHTypeReferences - uniqued class ehtype references. - llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences; - - /// VTableDispatchMethods - List of methods for which we generate - /// vtable-based message dispatch. - llvm::DenseSet<Selector> VTableDispatchMethods; - - /// DefinedMetaClasses - List of defined meta-classes. - std::vector<llvm::GlobalValue*> DefinedMetaClasses; - - /// isVTableDispatchedSelector - Returns true if SEL is a - /// vtable-based selector. - bool isVTableDispatchedSelector(Selector Sel); - - /// FinishNonFragileABIModule - Write out global data structures at the end of - /// processing a translation unit. - void FinishNonFragileABIModule(); - - /// AddModuleClassList - Add the given list of class pointers to the - /// module with the provided symbol and section names. - void AddModuleClassList(ArrayRef<llvm::GlobalValue *> Container, - StringRef SymbolName, StringRef SectionName); - - llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags, - unsigned InstanceStart, - unsigned InstanceSize, - const ObjCImplementationDecl *ID); - llvm::GlobalVariable *BuildClassObject(const ObjCInterfaceDecl *CI, - bool isMetaclass, - llvm::Constant *IsAGV, - llvm::Constant *SuperClassGV, - llvm::Constant *ClassRoGV, - bool HiddenVisibility); - - void emitMethodConstant(ConstantArrayBuilder &builder, - const ObjCMethodDecl *MD, - bool forProtocol); - - /// Emit the method list for the given implementation. The return value - /// has type MethodListnfABITy. - llvm::Constant *emitMethodList(Twine Name, MethodListType MLT, - ArrayRef<const ObjCMethodDecl *> Methods); - - /// EmitIvarList - Emit the ivar list for the given - /// implementation. If ForClass is true the list of class ivars - /// (i.e. metaclass ivars) is emitted, otherwise the list of - /// interface ivars will be emitted. The return value has type - /// IvarListnfABIPtrTy. - llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID); - - llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID, - const ObjCIvarDecl *Ivar, - unsigned long int offset); - - /// GetOrEmitProtocol - Get the protocol object for the given - /// declaration, emitting it if necessary. The return value has type - /// ProtocolPtrTy. - llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override; - - /// GetOrEmitProtocolRef - Get a forward reference to the protocol - /// object for the given declaration, emitting it if needed. These - /// forward references will be filled in with empty bodies if no - /// definition is seen. The return value has type ProtocolPtrTy. - llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override; - - /// EmitProtocolList - Generate the list of referenced - /// protocols. The return value has type ProtocolListPtrTy. - llvm::Constant *EmitProtocolList(Twine Name, - ObjCProtocolDecl::protocol_iterator begin, - ObjCProtocolDecl::protocol_iterator end); - - CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, - QualType ResultType, - Selector Sel, - llvm::Value *Receiver, - QualType Arg0Ty, - bool IsSuper, - const CallArgList &CallArgs, - const ObjCMethodDecl *Method); - - /// GetClassGlobal - Return the global variable for the Objective-C - /// class of the given name. - llvm::Constant *GetClassGlobal(StringRef Name, - ForDefinition_t IsForDefinition, - bool Weak = false, bool DLLImport = false); - llvm::Constant *GetClassGlobal(const ObjCInterfaceDecl *ID, - bool isMetaclass, - ForDefinition_t isForDefinition); - - /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, - /// for the given class reference. - llvm::Value *EmitClassRef(CodeGenFunction &CGF, - const ObjCInterfaceDecl *ID); - - llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF, - IdentifierInfo *II, - const ObjCInterfaceDecl *ID); - - llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override; - - /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, - /// for the given super class reference. - llvm::Value *EmitSuperClassRef(CodeGenFunction &CGF, - const ObjCInterfaceDecl *ID); - - /// EmitMetaClassRef - Return a Value * of the address of _class_t - /// meta-data - llvm::Value *EmitMetaClassRef(CodeGenFunction &CGF, - const ObjCInterfaceDecl *ID, bool Weak); - - /// ObjCIvarOffsetVariable - Returns the ivar offset variable for - /// the given ivar. - /// - llvm::GlobalVariable * ObjCIvarOffsetVariable( - const ObjCInterfaceDecl *ID, - const ObjCIvarDecl *Ivar); - - /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, - /// for the given selector. - llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel); - Address EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel); - - /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C - /// interface. The return value has type EHTypePtrTy. - llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID, - ForDefinition_t IsForDefinition); - - StringRef getMetaclassSymbolPrefix() const { return "OBJC_METACLASS_$_"; } - - StringRef getClassSymbolPrefix() const { return "OBJC_CLASS_$_"; } - - void GetClassSizeInfo(const ObjCImplementationDecl *OID, - uint32_t &InstanceStart, - uint32_t &InstanceSize); - - // Shamelessly stolen from Analysis/CFRefCount.cpp - Selector GetNullarySelector(const char* name) const { - IdentifierInfo* II = &CGM.getContext().Idents.get(name); - return CGM.getContext().Selectors.getSelector(0, &II); - } - - Selector GetUnarySelector(const char* name) const { - IdentifierInfo* II = &CGM.getContext().Idents.get(name); - return CGM.getContext().Selectors.getSelector(1, &II); - } - - /// ImplementationIsNonLazy - Check whether the given category or - /// class implementation is "non-lazy". - bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const; - - bool IsIvarOffsetKnownIdempotent(const CodeGen::CodeGenFunction &CGF, - const ObjCIvarDecl *IV) { - // Annotate the load as an invariant load iff inside an instance method - // and ivar belongs to instance method's class and one of its super class. - // This check is needed because the ivar offset is a lazily - // initialised value that may depend on objc_msgSend to perform a fixup on - // the first message dispatch. - // - // An additional opportunity to mark the load as invariant arises when the - // base of the ivar access is a parameter to an Objective C method. - // However, because the parameters are not available in the current - // interface, we cannot perform this check. - if (const ObjCMethodDecl *MD = - dyn_cast_or_null<ObjCMethodDecl>(CGF.CurFuncDecl)) - if (MD->isInstanceMethod()) - if (const ObjCInterfaceDecl *ID = MD->getClassInterface()) - return IV->getContainingInterface()->isSuperClassOf(ID); - return false; - } - -public: - CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm); - - llvm::Constant *getNSConstantStringClassRef() override; - - llvm::Function *ModuleInitFunction() override; - - CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, - QualType ResultType, Selector Sel, - llvm::Value *Receiver, - const CallArgList &CallArgs, - const ObjCInterfaceDecl *Class, - const ObjCMethodDecl *Method) override; - - CodeGen::RValue - GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, QualType ResultType, - Selector Sel, const ObjCInterfaceDecl *Class, - bool isCategoryImpl, llvm::Value *Receiver, - bool IsClassMessage, const CallArgList &CallArgs, - const ObjCMethodDecl *Method) override; - - llvm::Value *GetClass(CodeGenFunction &CGF, - const ObjCInterfaceDecl *ID) override; - - llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override - { return EmitSelector(CGF, Sel); } - Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override - { return EmitSelectorAddr(CGF, Sel); } - - /// The NeXT/Apple runtimes do not support typed selectors; just emit an - /// untyped one. - llvm::Value *GetSelector(CodeGenFunction &CGF, - const ObjCMethodDecl *Method) override - { return EmitSelector(CGF, Method->getSelector()); } - - void GenerateCategory(const ObjCCategoryImplDecl *CMD) override; - - void GenerateClass(const ObjCImplementationDecl *ClassDecl) override; - - void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {} - - llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF, - const ObjCProtocolDecl *PD) override; - - llvm::Constant *GetEHType(QualType T) override; - - llvm::Constant *GetPropertyGetFunction() override { - return ObjCTypes.getGetPropertyFn(); - } - llvm::Constant *GetPropertySetFunction() override { - return ObjCTypes.getSetPropertyFn(); - } - - llvm::Constant *GetOptimizedPropertySetFunction(bool atomic, - bool copy) override { - return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy); - } - - llvm::Constant *GetSetStructFunction() override { - return ObjCTypes.getCopyStructFn(); - } - - llvm::Constant *GetGetStructFunction() override { - return ObjCTypes.getCopyStructFn(); - } - - llvm::Constant *GetCppAtomicObjectSetFunction() override { - return ObjCTypes.getCppAtomicObjectFunction(); - } - - llvm::Constant *GetCppAtomicObjectGetFunction() override { - return ObjCTypes.getCppAtomicObjectFunction(); - } - - llvm::Constant *EnumerationMutationFunction() override { - return ObjCTypes.getEnumerationMutationFn(); - } - - void EmitTryStmt(CodeGen::CodeGenFunction &CGF, - const ObjCAtTryStmt &S) override; - void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, - const ObjCAtSynchronizedStmt &S) override; - void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S, - bool ClearInsertionPoint=true) override; - llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, - Address AddrWeakObj) override; - void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address edst) override; - void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dest, - bool threadlocal = false) override; - void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dest, - llvm::Value *ivarOffset) override; - void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dest) override; - void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, - Address dest, Address src, - llvm::Value *size) override; - LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy, - llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, - unsigned CVRQualifiers) override; - llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, - const ObjCInterfaceDecl *Interface, - const ObjCIvarDecl *Ivar) override; -}; - -/// A helper class for performing the null-initialization of a return -/// value. -struct NullReturnState { - llvm::BasicBlock *NullBB; - NullReturnState() : NullBB(nullptr) {} - - /// Perform a null-check of the given receiver. - void init(CodeGenFunction &CGF, llvm::Value *receiver) { - // Make blocks for the null-receiver and call edges. - NullBB = CGF.createBasicBlock("msgSend.null-receiver"); - llvm::BasicBlock *callBB = CGF.createBasicBlock("msgSend.call"); - - // Check for a null receiver and, if there is one, jump to the - // null-receiver block. There's no point in trying to avoid it: - // we're always going to put *something* there, because otherwise - // we shouldn't have done this null-check in the first place. - llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver); - CGF.Builder.CreateCondBr(isNull, NullBB, callBB); - - // Otherwise, start performing the call. - CGF.EmitBlock(callBB); - } - - /// Complete the null-return operation. It is valid to call this - /// regardless of whether 'init' has been called. - RValue complete(CodeGenFunction &CGF, - ReturnValueSlot returnSlot, - RValue result, - QualType resultType, - const CallArgList &CallArgs, - const ObjCMethodDecl *Method) { - // If we never had to do a null-check, just use the raw result. - if (!NullBB) return result; - - // The continuation block. This will be left null if we don't have an - // IP, which can happen if the method we're calling is marked noreturn. - llvm::BasicBlock *contBB = nullptr; - - // Finish the call path. - llvm::BasicBlock *callBB = CGF.Builder.GetInsertBlock(); - if (callBB) { - contBB = CGF.createBasicBlock("msgSend.cont"); - CGF.Builder.CreateBr(contBB); - } - - // Okay, start emitting the null-receiver block. - CGF.EmitBlock(NullBB); - - // Release any consumed arguments we've got. - if (Method) { - CallArgList::const_iterator I = CallArgs.begin(); - for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(), - e = Method->param_end(); i != e; ++i, ++I) { - const ParmVarDecl *ParamDecl = (*i); - if (ParamDecl->hasAttr<NSConsumedAttr>()) { - RValue RV = I->getRValue(CGF); - assert(RV.isScalar() && - "NullReturnState::complete - arg not on object"); - CGF.EmitARCRelease(RV.getScalarVal(), ARCImpreciseLifetime); - } - } - } - - // The phi code below assumes that we haven't needed any control flow yet. - assert(CGF.Builder.GetInsertBlock() == NullBB); - - // If we've got a void return, just jump to the continuation block. - if (result.isScalar() && resultType->isVoidType()) { - // No jumps required if the message-send was noreturn. - if (contBB) CGF.EmitBlock(contBB); - return result; - } - - // If we've got a scalar return, build a phi. - if (result.isScalar()) { - // Derive the null-initialization value. - llvm::Constant *null = CGF.CGM.EmitNullConstant(resultType); - - // If no join is necessary, just flow out. - if (!contBB) return RValue::get(null); - - // Otherwise, build a phi. - CGF.EmitBlock(contBB); - llvm::PHINode *phi = CGF.Builder.CreatePHI(null->getType(), 2); - phi->addIncoming(result.getScalarVal(), callBB); - phi->addIncoming(null, NullBB); - return RValue::get(phi); - } - - // If we've got an aggregate return, null the buffer out. - // FIXME: maybe we should be doing things differently for all the - // cases where the ABI has us returning (1) non-agg values in - // memory or (2) agg values in registers. - if (result.isAggregate()) { - assert(result.isAggregate() && "null init of non-aggregate result?"); - if (!returnSlot.isUnused()) - CGF.EmitNullInitialization(result.getAggregateAddress(), resultType); - if (contBB) CGF.EmitBlock(contBB); - return result; - } - - // Complex types. - CGF.EmitBlock(contBB); - CodeGenFunction::ComplexPairTy callResult = result.getComplexVal(); - - // Find the scalar type and its zero value. - llvm::Type *scalarTy = callResult.first->getType(); - llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy); - - // Build phis for both coordinates. - llvm::PHINode *real = CGF.Builder.CreatePHI(scalarTy, 2); - real->addIncoming(callResult.first, callBB); - real->addIncoming(scalarZero, NullBB); - llvm::PHINode *imag = CGF.Builder.CreatePHI(scalarTy, 2); - imag->addIncoming(callResult.second, callBB); - imag->addIncoming(scalarZero, NullBB); - return RValue::getComplex(real, imag); - } -}; - -} // end anonymous namespace - -/* *** Helper Functions *** */ - -/// getConstantGEP() - Help routine to construct simple GEPs. -static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext, - llvm::GlobalVariable *C, unsigned idx0, - unsigned idx1) { - llvm::Value *Idxs[] = { - llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0), - llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1) - }; - return llvm::ConstantExpr::getGetElementPtr(C->getValueType(), C, Idxs); -} - -/// hasObjCExceptionAttribute - Return true if this class or any super -/// class has the __objc_exception__ attribute. -static bool hasObjCExceptionAttribute(ASTContext &Context, - const ObjCInterfaceDecl *OID) { - if (OID->hasAttr<ObjCExceptionAttr>()) - return true; - if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) - return hasObjCExceptionAttribute(Context, Super); - return false; -} - -/* *** CGObjCMac Public Interface *** */ - -CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm), - ObjCTypes(cgm) { - ObjCABI = 1; - EmitImageInfo(); -} - -/// GetClass - Return a reference to the class for the given interface -/// decl. -llvm::Value *CGObjCMac::GetClass(CodeGenFunction &CGF, - const ObjCInterfaceDecl *ID) { - return EmitClassRef(CGF, ID); -} - -/// GetSelector - Return the pointer to the unique'd string for this selector. -llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, Selector Sel) { - return EmitSelector(CGF, Sel); -} -Address CGObjCMac::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) { - return EmitSelectorAddr(CGF, Sel); -} -llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, const ObjCMethodDecl - *Method) { - return EmitSelector(CGF, Method->getSelector()); -} - -llvm::Constant *CGObjCMac::GetEHType(QualType T) { - if (T->isObjCIdType() || - T->isObjCQualifiedIdType()) { - return CGM.GetAddrOfRTTIDescriptor( - CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true); - } - if (T->isObjCClassType() || - T->isObjCQualifiedClassType()) { - return CGM.GetAddrOfRTTIDescriptor( - CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true); - } - if (T->isObjCObjectPointerType()) - return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true); - - llvm_unreachable("asking for catch type for ObjC type in fragile runtime"); -} - -/// Generate a constant CFString object. -/* - struct __builtin_CFString { - const int *isa; // point to __CFConstantStringClassReference - int flags; - const char *str; - long length; - }; -*/ - -/// or Generate a constant NSString object. -/* - struct __builtin_NSString { - const int *isa; // point to __NSConstantStringClassReference - const char *str; - unsigned int length; - }; -*/ - -ConstantAddress -CGObjCCommonMac::GenerateConstantString(const StringLiteral *SL) { - return (!CGM.getLangOpts().NoConstantCFStrings - ? CGM.GetAddrOfConstantCFString(SL) - : GenerateConstantNSString(SL)); -} - -static llvm::StringMapEntry<llvm::GlobalVariable *> & -GetConstantStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map, - const StringLiteral *Literal, unsigned &StringLength) { - StringRef String = Literal->getString(); - StringLength = String.size(); - return *Map.insert(std::make_pair(String, nullptr)).first; -} - -llvm::Constant *CGObjCMac::getNSConstantStringClassRef() { - if (llvm::Value *V = ConstantStringClassRef) - return cast<llvm::Constant>(V); - - auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass; - std::string str = - StringClass.empty() ? "_NSConstantStringClassReference" - : "_" + StringClass + "ClassReference"; - - llvm::Type *PTy = llvm::ArrayType::get(CGM.IntTy, 0); - auto GV = CGM.CreateRuntimeVariable(PTy, str); - auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo()); - ConstantStringClassRef = V; - return V; -} - -llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() { - if (llvm::Value *V = ConstantStringClassRef) - return cast<llvm::Constant>(V); - - auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass; - std::string str = - StringClass.empty() ? "OBJC_CLASS_$_NSConstantString" - : "OBJC_CLASS_$_" + StringClass; - auto GV = GetClassGlobal(str, NotForDefinition); - - // Make sure the result is of the correct type. - auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo()); - - ConstantStringClassRef = V; - return V; -} - -ConstantAddress -CGObjCCommonMac::GenerateConstantNSString(const StringLiteral *Literal) { - unsigned StringLength = 0; - llvm::StringMapEntry<llvm::GlobalVariable *> &Entry = - GetConstantStringEntry(NSConstantStringMap, Literal, StringLength); - - if (auto *C = Entry.second) - return ConstantAddress(C, CharUnits::fromQuantity(C->getAlignment())); - - // If we don't already have it, get _NSConstantStringClassReference. - llvm::Constant *Class = getNSConstantStringClassRef(); - - // If we don't already have it, construct the type for a constant NSString. - if (!NSConstantStringType) { - NSConstantStringType = - llvm::StructType::create({ - CGM.Int32Ty->getPointerTo(), - CGM.Int8PtrTy, - CGM.IntTy - }, "struct.__builtin_NSString"); - } - - ConstantInitBuilder Builder(CGM); - auto Fields = Builder.beginStruct(NSConstantStringType); - - // Class pointer. - Fields.add(Class); - - // String pointer. - llvm::Constant *C = - llvm::ConstantDataArray::getString(VMContext, Entry.first()); - - llvm::GlobalValue::LinkageTypes Linkage = llvm::GlobalValue::PrivateLinkage; - bool isConstant = !CGM.getLangOpts().WritableStrings; - - auto *GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), isConstant, - Linkage, C, ".str"); - GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - // Don't enforce the target's minimum global alignment, since the only use - // of the string is via this class initializer. - GV->setAlignment(1); - Fields.addBitCast(GV, CGM.Int8PtrTy); - - // String length. - Fields.addInt(CGM.IntTy, StringLength); - - // The struct. - CharUnits Alignment = CGM.getPointerAlign(); - GV = Fields.finishAndCreateGlobal("_unnamed_nsstring_", Alignment, - /*constant*/ true, - llvm::GlobalVariable::PrivateLinkage); - const char *NSStringSection = "__OBJC,__cstring_object,regular,no_dead_strip"; - const char *NSStringNonFragileABISection = - "__DATA,__objc_stringobj,regular,no_dead_strip"; - // FIXME. Fix section. - GV->setSection(CGM.getLangOpts().ObjCRuntime.isNonFragile() - ? NSStringNonFragileABISection - : NSStringSection); - Entry.second = GV; - - return ConstantAddress(GV, Alignment); -} - -enum { - kCFTaggedObjectID_Integer = (1 << 1) + 1 -}; - -/// Generates a message send where the super is the receiver. This is -/// a message send to self with special delivery semantics indicating -/// which class's method should be called. -CodeGen::RValue -CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, - QualType ResultType, - Selector Sel, - const ObjCInterfaceDecl *Class, - bool isCategoryImpl, - llvm::Value *Receiver, - bool IsClassMessage, - const CodeGen::CallArgList &CallArgs, - const ObjCMethodDecl *Method) { - // Create and init a super structure; this is a (receiver, class) - // pair we will pass to objc_msgSendSuper. - Address ObjCSuper = - CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(), - "objc_super"); - llvm::Value *ReceiverAsObject = - CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); - CGF.Builder.CreateStore( - ReceiverAsObject, - CGF.Builder.CreateStructGEP(ObjCSuper, 0, CharUnits::Zero())); - - // If this is a class message the metaclass is passed as the target. - llvm::Value *Target; - if (IsClassMessage) { - if (isCategoryImpl) { - // Message sent to 'super' in a class method defined in a category - // implementation requires an odd treatment. - // If we are in a class method, we must retrieve the - // _metaclass_ for the current class, pointed at by - // the class's "isa" pointer. The following assumes that - // isa" is the first ivar in a class (which it must be). - Target = EmitClassRef(CGF, Class->getSuperClass()); - Target = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, Target, 0); - Target = CGF.Builder.CreateAlignedLoad(Target, CGF.getPointerAlign()); - } else { - llvm::Constant *MetaClassPtr = EmitMetaClassRef(Class); - llvm::Value *SuperPtr = - CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, MetaClassPtr, 1); - llvm::Value *Super = - CGF.Builder.CreateAlignedLoad(SuperPtr, CGF.getPointerAlign()); - Target = Super; - } - } else if (isCategoryImpl) - Target = EmitClassRef(CGF, Class->getSuperClass()); - else { - llvm::Value *ClassPtr = EmitSuperClassRef(Class); - ClassPtr = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, ClassPtr, 1); - Target = CGF.Builder.CreateAlignedLoad(ClassPtr, CGF.getPointerAlign()); - } - // FIXME: We shouldn't need to do this cast, rectify the ASTContext and - // ObjCTypes types. - llvm::Type *ClassTy = - CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); - Target = CGF.Builder.CreateBitCast(Target, ClassTy); - CGF.Builder.CreateStore(Target, - CGF.Builder.CreateStructGEP(ObjCSuper, 1, CGF.getPointerSize())); - return EmitMessageSend(CGF, Return, ResultType, - EmitSelector(CGF, Sel), - ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy, - true, CallArgs, Method, Class, ObjCTypes); -} - -/// Generate code for a message send expression. -CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, - QualType ResultType, - Selector Sel, - llvm::Value *Receiver, - const CallArgList &CallArgs, - const ObjCInterfaceDecl *Class, - const ObjCMethodDecl *Method) { - return EmitMessageSend(CGF, Return, ResultType, - EmitSelector(CGF, Sel), - Receiver, CGF.getContext().getObjCIdType(), - false, CallArgs, Method, Class, ObjCTypes); -} - -static bool isWeakLinkedClass(const ObjCInterfaceDecl *ID) { - do { - if (ID->isWeakImported()) - return true; - } while ((ID = ID->getSuperClass())); - - return false; -} - -CodeGen::RValue -CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, - QualType ResultType, - llvm::Value *Sel, - llvm::Value *Arg0, - QualType Arg0Ty, - bool IsSuper, - const CallArgList &CallArgs, - const ObjCMethodDecl *Method, - const ObjCInterfaceDecl *ClassReceiver, - const ObjCCommonTypesHelper &ObjCTypes) { - CallArgList ActualArgs; - if (!IsSuper) - Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy); - ActualArgs.add(RValue::get(Arg0), Arg0Ty); - ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType()); - ActualArgs.addFrom(CallArgs); - - // If we're calling a method, use the formal signature. - MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs); - - if (Method) - assert(CGM.getContext().getCanonicalType(Method->getReturnType()) == - CGM.getContext().getCanonicalType(ResultType) && - "Result type mismatch!"); - - bool ReceiverCanBeNull = true; - - // Super dispatch assumes that self is non-null; even the messenger - // doesn't have a null check internally. - if (IsSuper) { - ReceiverCanBeNull = false; - - // If this is a direct dispatch of a class method, check whether the class, - // or anything in its hierarchy, was weak-linked. - } else if (ClassReceiver && Method && Method->isClassMethod()) { - ReceiverCanBeNull = isWeakLinkedClass(ClassReceiver); - - // If we're emitting a method, and self is const (meaning just ARC, for now), - // and the receiver is a load of self, then self is a valid object. - } else if (auto CurMethod = - dyn_cast_or_null<ObjCMethodDecl>(CGF.CurCodeDecl)) { - auto Self = CurMethod->getSelfDecl(); - if (Self->getType().isConstQualified()) { - if (auto LI = dyn_cast<llvm::LoadInst>(Arg0->stripPointerCasts())) { - llvm::Value *SelfAddr = CGF.GetAddrOfLocalVar(Self).getPointer(); - if (SelfAddr == LI->getPointerOperand()) { - ReceiverCanBeNull = false; - } - } - } - } - - bool RequiresNullCheck = false; - - llvm::Constant *Fn = nullptr; - if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) { - if (ReceiverCanBeNull) RequiresNullCheck = true; - Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper) - : ObjCTypes.getSendStretFn(IsSuper); - } else if (CGM.ReturnTypeUsesFPRet(ResultType)) { - Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper) - : ObjCTypes.getSendFpretFn(IsSuper); - } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) { - Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper) - : ObjCTypes.getSendFp2retFn(IsSuper); - } else { - // arm64 uses objc_msgSend for stret methods and yet null receiver check - // must be made for it. - if (ReceiverCanBeNull && CGM.ReturnTypeUsesSRet(MSI.CallInfo)) - RequiresNullCheck = true; - Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper) - : ObjCTypes.getSendFn(IsSuper); - } - - // We don't need to emit a null check to zero out an indirect result if the - // result is ignored. - if (Return.isUnused()) - RequiresNullCheck = false; - - // Emit a null-check if there's a consumed argument other than the receiver. - if (!RequiresNullCheck && CGM.getLangOpts().ObjCAutoRefCount && Method) { - for (const auto *ParamDecl : Method->parameters()) { - if (ParamDecl->hasAttr<NSConsumedAttr>()) { - RequiresNullCheck = true; - break; - } - } - } - - NullReturnState nullReturn; - if (RequiresNullCheck) { - nullReturn.init(CGF, Arg0); - } - - llvm::Instruction *CallSite; - Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType); - CGCallee Callee = CGCallee::forDirect(Fn); - RValue rvalue = CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs, - &CallSite); - - // Mark the call as noreturn if the method is marked noreturn and the - // receiver cannot be null. - if (Method && Method->hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) { - llvm::CallSite(CallSite).setDoesNotReturn(); - } - - return nullReturn.complete(CGF, Return, rvalue, ResultType, CallArgs, - RequiresNullCheck ? Method : nullptr); -} - -static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT, - bool pointee = false) { - // Note that GC qualification applies recursively to C pointer types - // that aren't otherwise decorated. This is weird, but it's probably - // an intentional workaround to the unreliable placement of GC qualifiers. - if (FQT.isObjCGCStrong()) - return Qualifiers::Strong; - - if (FQT.isObjCGCWeak()) - return Qualifiers::Weak; - - if (auto ownership = FQT.getObjCLifetime()) { - // Ownership does not apply recursively to C pointer types. - if (pointee) return Qualifiers::GCNone; - switch (ownership) { - case Qualifiers::OCL_Weak: return Qualifiers::Weak; - case Qualifiers::OCL_Strong: return Qualifiers::Strong; - case Qualifiers::OCL_ExplicitNone: return Qualifiers::GCNone; - case Qualifiers::OCL_Autoreleasing: llvm_unreachable("autoreleasing ivar?"); - case Qualifiers::OCL_None: llvm_unreachable("known nonzero"); - } - llvm_unreachable("bad objc ownership"); - } - - // Treat unqualified retainable pointers as strong. - if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType()) - return Qualifiers::Strong; - - // Walk into C pointer types, but only in GC. - if (Ctx.getLangOpts().getGC() != LangOptions::NonGC) { - if (const PointerType *PT = FQT->getAs<PointerType>()) - return GetGCAttrTypeForType(Ctx, PT->getPointeeType(), /*pointee*/ true); - } - - return Qualifiers::GCNone; -} - -namespace { - struct IvarInfo { - CharUnits Offset; - uint64_t SizeInWords; - IvarInfo(CharUnits offset, uint64_t sizeInWords) - : Offset(offset), SizeInWords(sizeInWords) {} - - // Allow sorting based on byte pos. - bool operator<(const IvarInfo &other) const { - return Offset < other.Offset; - } - }; - - /// A helper class for building GC layout strings. - class IvarLayoutBuilder { - CodeGenModule &CGM; - - /// The start of the layout. Offsets will be relative to this value, - /// and entries less than this value will be silently discarded. - CharUnits InstanceBegin; - - /// The end of the layout. Offsets will never exceed this value. - CharUnits InstanceEnd; - - /// Whether we're generating the strong layout or the weak layout. - bool ForStrongLayout; - - /// Whether the offsets in IvarsInfo might be out-of-order. - bool IsDisordered = false; - - llvm::SmallVector<IvarInfo, 8> IvarsInfo; - - public: - IvarLayoutBuilder(CodeGenModule &CGM, CharUnits instanceBegin, - CharUnits instanceEnd, bool forStrongLayout) - : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd), - ForStrongLayout(forStrongLayout) { - } - - void visitRecord(const RecordType *RT, CharUnits offset); - - template <class Iterator, class GetOffsetFn> - void visitAggregate(Iterator begin, Iterator end, - CharUnits aggrOffset, - const GetOffsetFn &getOffset); - - void visitField(const FieldDecl *field, CharUnits offset); - - /// Add the layout of a block implementation. - void visitBlock(const CGBlockInfo &blockInfo); - - /// Is there any information for an interesting bitmap? - bool hasBitmapData() const { return !IvarsInfo.empty(); } - - llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC, - llvm::SmallVectorImpl<unsigned char> &buffer); - - static void dump(ArrayRef<unsigned char> buffer) { - const unsigned char *s = buffer.data(); - for (unsigned i = 0, e = buffer.size(); i < e; i++) - if (!(s[i] & 0xf0)) - printf("0x0%x%s", s[i], s[i] != 0 ? ", " : ""); - else - printf("0x%x%s", s[i], s[i] != 0 ? ", " : ""); - printf("\n"); - } - }; -} // end anonymous namespace - -llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM, - const CGBlockInfo &blockInfo) { - - llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy); - if (CGM.getLangOpts().getGC() == LangOptions::NonGC) - return nullPtr; - - IvarLayoutBuilder builder(CGM, CharUnits::Zero(), blockInfo.BlockSize, - /*for strong layout*/ true); - - builder.visitBlock(blockInfo); - - if (!builder.hasBitmapData()) - return nullPtr; - - llvm::SmallVector<unsigned char, 32> buffer; - llvm::Constant *C = builder.buildBitmap(*this, buffer); - if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) { - printf("\n block variable layout for block: "); - builder.dump(buffer); - } - - return C; -} - -void IvarLayoutBuilder::visitBlock(const CGBlockInfo &blockInfo) { - // __isa is the first field in block descriptor and must assume by runtime's - // convention that it is GC'able. - IvarsInfo.push_back(IvarInfo(CharUnits::Zero(), 1)); - - const BlockDecl *blockDecl = blockInfo.getBlockDecl(); - - // Ignore the optional 'this' capture: C++ objects are not assumed - // to be GC'ed. - - CharUnits lastFieldOffset; - - // Walk the captured variables. - for (const auto &CI : blockDecl->captures()) { - const VarDecl *variable = CI.getVariable(); - QualType type = variable->getType(); - - const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); - - // Ignore constant captures. - if (capture.isConstant()) continue; - - CharUnits fieldOffset = capture.getOffset(); - - // Block fields are not necessarily ordered; if we detect that we're - // adding them out-of-order, make sure we sort later. - if (fieldOffset < lastFieldOffset) - IsDisordered = true; - lastFieldOffset = fieldOffset; - - // __block variables are passed by their descriptor address. - if (CI.isByRef()) { - IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1)); - continue; - } - - assert(!type->isArrayType() && "array variable should not be caught"); - if (const RecordType *record = type->getAs<RecordType>()) { - visitRecord(record, fieldOffset); - continue; - } - - Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type); - - if (GCAttr == Qualifiers::Strong) { - assert(CGM.getContext().getTypeSize(type) - == CGM.getTarget().getPointerWidth(0)); - IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1)); - } - } -} - -/// getBlockCaptureLifetime - This routine returns life time of the captured -/// block variable for the purpose of block layout meta-data generation. FQT is -/// the type of the variable captured in the block. -Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT, - bool ByrefLayout) { - // If it has an ownership qualifier, we're done. - if (auto lifetime = FQT.getObjCLifetime()) - return lifetime; - - // If it doesn't, and this is ARC, it has no ownership. - if (CGM.getLangOpts().ObjCAutoRefCount) - return Qualifiers::OCL_None; - - // In MRC, retainable pointers are owned by non-__block variables. - if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType()) - return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong; - - return Qualifiers::OCL_None; -} - -void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref, - Qualifiers::ObjCLifetime LifeTime, - CharUnits FieldOffset, - CharUnits FieldSize) { - // __block variables are passed by their descriptor address. - if (IsByref) - RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset, - FieldSize)); - else if (LifeTime == Qualifiers::OCL_Strong) - RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset, - FieldSize)); - else if (LifeTime == Qualifiers::OCL_Weak) - RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset, - FieldSize)); - else if (LifeTime == Qualifiers::OCL_ExplicitNone) - RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset, - FieldSize)); - else - RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES, - FieldOffset, - FieldSize)); -} - -void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, - const RecordDecl *RD, - ArrayRef<const FieldDecl*> RecFields, - CharUnits BytePos, bool &HasUnion, - bool ByrefLayout) { - bool IsUnion = (RD && RD->isUnion()); - CharUnits MaxUnionSize = CharUnits::Zero(); - const FieldDecl *MaxField = nullptr; - const FieldDecl *LastFieldBitfieldOrUnnamed = nullptr; - CharUnits MaxFieldOffset = CharUnits::Zero(); - CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero(); - - if (RecFields.empty()) - return; - unsigned ByteSizeInBits = CGM.getTarget().getCharWidth(); - - for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { - const FieldDecl *Field = RecFields[i]; - // Note that 'i' here is actually the field index inside RD of Field, - // although this dependency is hidden. - const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); - CharUnits FieldOffset = - CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i)); - - // Skip over unnamed or bitfields - if (!Field->getIdentifier() || Field->isBitField()) { - LastFieldBitfieldOrUnnamed = Field; - LastBitfieldOrUnnamedOffset = FieldOffset; - continue; - } - - LastFieldBitfieldOrUnnamed = nullptr; - QualType FQT = Field->getType(); - if (FQT->isRecordType() || FQT->isUnionType()) { - if (FQT->isUnionType()) - HasUnion = true; - - BuildRCBlockVarRecordLayout(FQT->getAs<RecordType>(), - BytePos + FieldOffset, HasUnion); - continue; - } - - if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { - const ConstantArrayType *CArray = - dyn_cast_or_null<ConstantArrayType>(Array); - uint64_t ElCount = CArray->getSize().getZExtValue(); - assert(CArray && "only array with known element size is supported"); - FQT = CArray->getElementType(); - while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { - const ConstantArrayType *CArray = - dyn_cast_or_null<ConstantArrayType>(Array); - ElCount *= CArray->getSize().getZExtValue(); - FQT = CArray->getElementType(); - } - if (FQT->isRecordType() && ElCount) { - int OldIndex = RunSkipBlockVars.size() - 1; - const RecordType *RT = FQT->getAs<RecordType>(); - BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset, - HasUnion); - - // Replicate layout information for each array element. Note that - // one element is already done. - uint64_t ElIx = 1; - for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) { - CharUnits Size = CGM.getContext().getTypeSizeInChars(RT); - for (int i = OldIndex+1; i <= FirstIndex; ++i) - RunSkipBlockVars.push_back( - RUN_SKIP(RunSkipBlockVars[i].opcode, - RunSkipBlockVars[i].block_var_bytepos + Size*ElIx, - RunSkipBlockVars[i].block_var_size)); - } - continue; - } - } - CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType()); - if (IsUnion) { - CharUnits UnionIvarSize = FieldSize; - if (UnionIvarSize > MaxUnionSize) { - MaxUnionSize = UnionIvarSize; - MaxField = Field; - MaxFieldOffset = FieldOffset; - } - } else { - UpdateRunSkipBlockVars(false, - getBlockCaptureLifetime(FQT, ByrefLayout), - BytePos + FieldOffset, - FieldSize); - } - } - - if (LastFieldBitfieldOrUnnamed) { - if (LastFieldBitfieldOrUnnamed->isBitField()) { - // Last field was a bitfield. Must update the info. - uint64_t BitFieldSize - = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext()); - unsigned UnsSize = (BitFieldSize / ByteSizeInBits) + - ((BitFieldSize % ByteSizeInBits) != 0); - CharUnits Size = CharUnits::fromQuantity(UnsSize); - Size += LastBitfieldOrUnnamedOffset; - UpdateRunSkipBlockVars(false, - getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(), - ByrefLayout), - BytePos + LastBitfieldOrUnnamedOffset, - Size); - } else { - assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed"); - // Last field was unnamed. Must update skip info. - CharUnits FieldSize - = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType()); - UpdateRunSkipBlockVars(false, - getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(), - ByrefLayout), - BytePos + LastBitfieldOrUnnamedOffset, - FieldSize); - } - } - - if (MaxField) - UpdateRunSkipBlockVars(false, - getBlockCaptureLifetime(MaxField->getType(), ByrefLayout), - BytePos + MaxFieldOffset, - MaxUnionSize); -} - -void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT, - CharUnits BytePos, - bool &HasUnion, - bool ByrefLayout) { - const RecordDecl *RD = RT->getDecl(); - SmallVector<const FieldDecl*, 16> Fields(RD->fields()); - llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0)); - const llvm::StructLayout *RecLayout = - CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty)); - - BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout); -} - -/// InlineLayoutInstruction - This routine produce an inline instruction for the -/// block variable layout if it can. If not, it returns 0. Rules are as follow: -/// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit world, -/// an inline layout of value 0x0000000000000xyz is interpreted as follows: -/// x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by -/// y captured object of BLOCK_LAYOUT_BYREF. Followed by -/// z captured object of BLOCK_LAYOUT_WEAK. If any of the above is missing, zero -/// replaces it. For example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no -/// BLOCK_LAYOUT_BYREF and no BLOCK_LAYOUT_WEAK objects are captured. -uint64_t CGObjCCommonMac::InlineLayoutInstruction( - SmallVectorImpl<unsigned char> &Layout) { - uint64_t Result = 0; - if (Layout.size() <= 3) { - unsigned size = Layout.size(); - unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0; - unsigned char inst; - enum BLOCK_LAYOUT_OPCODE opcode ; - switch (size) { - case 3: - inst = Layout[0]; - opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); - if (opcode == BLOCK_LAYOUT_STRONG) - strong_word_count = (inst & 0xF)+1; - else - return 0; - inst = Layout[1]; - opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); - if (opcode == BLOCK_LAYOUT_BYREF) - byref_word_count = (inst & 0xF)+1; - else - return 0; - inst = Layout[2]; - opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); - if (opcode == BLOCK_LAYOUT_WEAK) - weak_word_count = (inst & 0xF)+1; - else - return 0; - break; - - case 2: - inst = Layout[0]; - opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); - if (opcode == BLOCK_LAYOUT_STRONG) { - strong_word_count = (inst & 0xF)+1; - inst = Layout[1]; - opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); - if (opcode == BLOCK_LAYOUT_BYREF) - byref_word_count = (inst & 0xF)+1; - else if (opcode == BLOCK_LAYOUT_WEAK) - weak_word_count = (inst & 0xF)+1; - else - return 0; - } - else if (opcode == BLOCK_LAYOUT_BYREF) { - byref_word_count = (inst & 0xF)+1; - inst = Layout[1]; - opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); - if (opcode == BLOCK_LAYOUT_WEAK) - weak_word_count = (inst & 0xF)+1; - else - return 0; - } - else - return 0; - break; - - case 1: - inst = Layout[0]; - opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); - if (opcode == BLOCK_LAYOUT_STRONG) - strong_word_count = (inst & 0xF)+1; - else if (opcode == BLOCK_LAYOUT_BYREF) - byref_word_count = (inst & 0xF)+1; - else if (opcode == BLOCK_LAYOUT_WEAK) - weak_word_count = (inst & 0xF)+1; - else - return 0; - break; - - default: - return 0; - } - - // Cannot inline when any of the word counts is 15. Because this is one less - // than the actual work count (so 15 means 16 actual word counts), - // and we can only display 0 thru 15 word counts. - if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16) - return 0; - - unsigned count = - (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0); - - if (size == count) { - if (strong_word_count) - Result = strong_word_count; - Result <<= 4; - if (byref_word_count) - Result += byref_word_count; - Result <<= 4; - if (weak_word_count) - Result += weak_word_count; - } - } - return Result; -} - -llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) { - llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy); - if (RunSkipBlockVars.empty()) - return nullPtr; - unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0); - unsigned ByteSizeInBits = CGM.getTarget().getCharWidth(); - unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits; - - // Sort on byte position; captures might not be allocated in order, - // and unions can do funny things. - llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end()); - SmallVector<unsigned char, 16> Layout; - - unsigned size = RunSkipBlockVars.size(); - for (unsigned i = 0; i < size; i++) { - enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode; - CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos; - CharUnits end_byte_pos = start_byte_pos; - unsigned j = i+1; - while (j < size) { - if (opcode == RunSkipBlockVars[j].opcode) { - end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos; - i++; - } - else - break; - } - CharUnits size_in_bytes = - end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size; - if (j < size) { - CharUnits gap = - RunSkipBlockVars[j].block_var_bytepos - - RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size; - size_in_bytes += gap; - } - CharUnits residue_in_bytes = CharUnits::Zero(); - if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) { - residue_in_bytes = size_in_bytes % WordSizeInBytes; - size_in_bytes -= residue_in_bytes; - opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS; - } - - unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes; - while (size_in_words >= 16) { - // Note that value in imm. is one less that the actual - // value. So, 0xf means 16 words follow! - unsigned char inst = (opcode << 4) | 0xf; - Layout.push_back(inst); - size_in_words -= 16; - } - if (size_in_words > 0) { - // Note that value in imm. is one less that the actual - // value. So, we subtract 1 away! - unsigned char inst = (opcode << 4) | (size_in_words-1); - Layout.push_back(inst); - } - if (residue_in_bytes > CharUnits::Zero()) { - unsigned char inst = - (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.getQuantity()-1); - Layout.push_back(inst); - } - } - - while (!Layout.empty()) { - unsigned char inst = Layout.back(); - enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); - if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS) - Layout.pop_back(); - else - break; - } - - uint64_t Result = InlineLayoutInstruction(Layout); - if (Result != 0) { - // Block variable layout instruction has been inlined. - if (CGM.getLangOpts().ObjCGCBitmapPrint) { - if (ComputeByrefLayout) - printf("\n Inline BYREF variable layout: "); - else - printf("\n Inline block variable layout: "); - printf("0x0%" PRIx64 "", Result); - if (auto numStrong = (Result & 0xF00) >> 8) - printf(", BL_STRONG:%d", (int) numStrong); - if (auto numByref = (Result & 0x0F0) >> 4) - printf(", BL_BYREF:%d", (int) numByref); - if (auto numWeak = (Result & 0x00F) >> 0) - printf(", BL_WEAK:%d", (int) numWeak); - printf(", BL_OPERATOR:0\n"); - } - return llvm::ConstantInt::get(CGM.IntPtrTy, Result); - } - - unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0; - Layout.push_back(inst); - std::string BitMap; - for (unsigned i = 0, e = Layout.size(); i != e; i++) - BitMap += Layout[i]; - - if (CGM.getLangOpts().ObjCGCBitmapPrint) { - if (ComputeByrefLayout) - printf("\n Byref variable layout: "); - else - printf("\n Block variable layout: "); - for (unsigned i = 0, e = BitMap.size(); i != e; i++) { - unsigned char inst = BitMap[i]; - enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); - unsigned delta = 1; - switch (opcode) { - case BLOCK_LAYOUT_OPERATOR: - printf("BL_OPERATOR:"); - delta = 0; - break; - case BLOCK_LAYOUT_NON_OBJECT_BYTES: - printf("BL_NON_OBJECT_BYTES:"); - break; - case BLOCK_LAYOUT_NON_OBJECT_WORDS: - printf("BL_NON_OBJECT_WORD:"); - break; - case BLOCK_LAYOUT_STRONG: - printf("BL_STRONG:"); - break; - case BLOCK_LAYOUT_BYREF: - printf("BL_BYREF:"); - break; - case BLOCK_LAYOUT_WEAK: - printf("BL_WEAK:"); - break; - case BLOCK_LAYOUT_UNRETAINED: - printf("BL_UNRETAINED:"); - break; - } - // Actual value of word count is one more that what is in the imm. - // field of the instruction - printf("%d", (inst & 0xf) + delta); - if (i < e-1) - printf(", "); - else - printf("\n"); - } - } - - auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::ClassName, - /*ForceNonFragileABI=*/true, - /*NullTerminate=*/false); - return getConstantGEP(VMContext, Entry, 0, 0); -} - -static std::string getBlockLayoutInfoString( - const SmallVectorImpl<CGObjCCommonMac::RUN_SKIP> &RunSkipBlockVars, - bool HasCopyDisposeHelpers) { - std::string Str; - for (const CGObjCCommonMac::RUN_SKIP &R : RunSkipBlockVars) { - if (R.opcode == CGObjCCommonMac::BLOCK_LAYOUT_UNRETAINED) { - // Copy/dispose helpers don't have any information about - // __unsafe_unretained captures, so unconditionally concatenate a string. - Str += "u"; - } else if (HasCopyDisposeHelpers) { - // Information about __strong, __weak, or byref captures has already been - // encoded into the names of the copy/dispose helpers. We have to add a - // string here only when the copy/dispose helpers aren't generated (which - // happens when the block is non-escaping). - continue; - } else { - switch (R.opcode) { - case CGObjCCommonMac::BLOCK_LAYOUT_STRONG: - Str += "s"; - break; - case CGObjCCommonMac::BLOCK_LAYOUT_BYREF: - Str += "r"; - break; - case CGObjCCommonMac::BLOCK_LAYOUT_WEAK: - Str += "w"; - break; - default: - continue; - } - } - Str += llvm::to_string(R.block_var_bytepos.getQuantity()); - Str += "l" + llvm::to_string(R.block_var_size.getQuantity()); - } - return Str; -} - -void CGObjCCommonMac::fillRunSkipBlockVars(CodeGenModule &CGM, - const CGBlockInfo &blockInfo) { - assert(CGM.getLangOpts().getGC() == LangOptions::NonGC); - - RunSkipBlockVars.clear(); - bool hasUnion = false; - - unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0); - unsigned ByteSizeInBits = CGM.getTarget().getCharWidth(); - unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits; - - const BlockDecl *blockDecl = blockInfo.getBlockDecl(); - - // Calculate the basic layout of the block structure. - const llvm::StructLayout *layout = - CGM.getDataLayout().getStructLayout(blockInfo.StructureType); - - // Ignore the optional 'this' capture: C++ objects are not assumed - // to be GC'ed. - if (blockInfo.BlockHeaderForcedGapSize != CharUnits::Zero()) - UpdateRunSkipBlockVars(false, Qualifiers::OCL_None, - blockInfo.BlockHeaderForcedGapOffset, - blockInfo.BlockHeaderForcedGapSize); - // Walk the captured variables. - for (const auto &CI : blockDecl->captures()) { - const VarDecl *variable = CI.getVariable(); - QualType type = variable->getType(); - - const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); - - // Ignore constant captures. - if (capture.isConstant()) continue; - - CharUnits fieldOffset = - CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex())); - - assert(!type->isArrayType() && "array variable should not be caught"); - if (!CI.isByRef()) - if (const RecordType *record = type->getAs<RecordType>()) { - BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion); - continue; - } - CharUnits fieldSize; - if (CI.isByRef()) - fieldSize = CharUnits::fromQuantity(WordSizeInBytes); - else - fieldSize = CGM.getContext().getTypeSizeInChars(type); - UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(type, false), - fieldOffset, fieldSize); - } -} - -llvm::Constant * -CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM, - const CGBlockInfo &blockInfo) { - fillRunSkipBlockVars(CGM, blockInfo); - return getBitmapBlockLayout(false); -} - -std::string CGObjCCommonMac::getRCBlockLayoutStr(CodeGenModule &CGM, - const CGBlockInfo &blockInfo) { - fillRunSkipBlockVars(CGM, blockInfo); - return getBlockLayoutInfoString(RunSkipBlockVars, - blockInfo.needsCopyDisposeHelpers()); -} - -llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM, - QualType T) { - assert(CGM.getLangOpts().getGC() == LangOptions::NonGC); - assert(!T->isArrayType() && "__block array variable should not be caught"); - CharUnits fieldOffset; - RunSkipBlockVars.clear(); - bool hasUnion = false; - if (const RecordType *record = T->getAs<RecordType>()) { - BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */); - llvm::Constant *Result = getBitmapBlockLayout(true); - if (isa<llvm::ConstantInt>(Result)) - Result = llvm::ConstantExpr::getIntToPtr(Result, CGM.Int8PtrTy); - return Result; - } - llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy); - return nullPtr; -} - -llvm::Value *CGObjCMac::GenerateProtocolRef(CodeGenFunction &CGF, - const ObjCProtocolDecl *PD) { - // FIXME: I don't understand why gcc generates this, or where it is - // resolved. Investigate. Its also wasteful to look this up over and over. - LazySymbols.insert(&CGM.getContext().Idents.get("Protocol")); - - return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD), - ObjCTypes.getExternalProtocolPtrTy()); -} - -void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) { - // FIXME: We shouldn't need this, the protocol decl should contain enough - // information to tell us whether this was a declaration or a definition. - DefinedProtocols.insert(PD->getIdentifier()); - - // If we have generated a forward reference to this protocol, emit - // it now. Otherwise do nothing, the protocol objects are lazily - // emitted. - if (Protocols.count(PD->getIdentifier())) - GetOrEmitProtocol(PD); -} - -llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) { - if (DefinedProtocols.count(PD->getIdentifier())) - return GetOrEmitProtocol(PD); - - return GetOrEmitProtocolRef(PD); -} - -llvm::Value *CGObjCCommonMac::EmitClassRefViaRuntime( - CodeGenFunction &CGF, - const ObjCInterfaceDecl *ID, - ObjCCommonTypesHelper &ObjCTypes) { - llvm::Constant *lookUpClassFn = ObjCTypes.getLookUpClassFn(); - - llvm::Value *className = - CGF.CGM.GetAddrOfConstantCString(ID->getObjCRuntimeNameAsString()) - .getPointer(); - ASTContext &ctx = CGF.CGM.getContext(); - className = - CGF.Builder.CreateBitCast(className, - CGF.ConvertType( - ctx.getPointerType(ctx.CharTy.withConst()))); - llvm::CallInst *call = CGF.Builder.CreateCall(lookUpClassFn, className); - call->setDoesNotThrow(); - return call; -} - -/* -// Objective-C 1.0 extensions -struct _objc_protocol { -struct _objc_protocol_extension *isa; -char *protocol_name; -struct _objc_protocol_list *protocol_list; -struct _objc__method_prototype_list *instance_methods; -struct _objc__method_prototype_list *class_methods -}; - -See EmitProtocolExtension(). -*/ -llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) { - llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()]; - - // Early exit if a defining object has already been generated. - if (Entry && Entry->hasInitializer()) - return Entry; - - // Use the protocol definition, if there is one. - if (const ObjCProtocolDecl *Def = PD->getDefinition()) - PD = Def; - - // FIXME: I don't understand why gcc generates this, or where it is - // resolved. Investigate. Its also wasteful to look this up over and over. - LazySymbols.insert(&CGM.getContext().Idents.get("Protocol")); - - // Construct method lists. - auto methodLists = ProtocolMethodLists::get(PD); - - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(ObjCTypes.ProtocolTy); - values.add(EmitProtocolExtension(PD, methodLists)); - values.add(GetClassName(PD->getObjCRuntimeNameAsString())); - values.add(EmitProtocolList("OBJC_PROTOCOL_REFS_" + PD->getName(), - PD->protocol_begin(), PD->protocol_end())); - values.add(methodLists.emitMethodList(this, PD, - ProtocolMethodLists::RequiredInstanceMethods)); - values.add(methodLists.emitMethodList(this, PD, - ProtocolMethodLists::RequiredClassMethods)); - - if (Entry) { - // Already created, update the initializer. - assert(Entry->hasPrivateLinkage()); - values.finishAndSetAsInitializer(Entry); - } else { - Entry = values.finishAndCreateGlobal("OBJC_PROTOCOL_" + PD->getName(), - CGM.getPointerAlign(), - /*constant*/ false, - llvm::GlobalValue::PrivateLinkage); - Entry->setSection("__OBJC,__protocol,regular,no_dead_strip"); - - Protocols[PD->getIdentifier()] = Entry; - } - CGM.addCompilerUsedGlobal(Entry); - - return Entry; -} - -llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) { - llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; - - if (!Entry) { - // We use the initializer as a marker of whether this is a forward - // reference or not. At module finalization we add the empty - // contents for protocols which were referenced but never defined. - Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, - false, llvm::GlobalValue::PrivateLinkage, - nullptr, "OBJC_PROTOCOL_" + PD->getName()); - Entry->setSection("__OBJC,__protocol,regular,no_dead_strip"); - // FIXME: Is this necessary? Why only for protocol? - Entry->setAlignment(4); - } - - return Entry; -} - -/* - struct _objc_protocol_extension { - uint32_t size; - struct objc_method_description_list *optional_instance_methods; - struct objc_method_description_list *optional_class_methods; - struct objc_property_list *instance_properties; - const char ** extendedMethodTypes; - struct objc_property_list *class_properties; - }; -*/ -llvm::Constant * -CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD, - const ProtocolMethodLists &methodLists) { - auto optInstanceMethods = - methodLists.emitMethodList(this, PD, - ProtocolMethodLists::OptionalInstanceMethods); - auto optClassMethods = - methodLists.emitMethodList(this, PD, - ProtocolMethodLists::OptionalClassMethods); - - auto extendedMethodTypes = - EmitProtocolMethodTypes("OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(), - methodLists.emitExtendedTypesArray(this), - ObjCTypes); - - auto instanceProperties = - EmitPropertyList("OBJC_$_PROP_PROTO_LIST_" + PD->getName(), nullptr, PD, - ObjCTypes, false); - auto classProperties = - EmitPropertyList("OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->getName(), nullptr, - PD, ObjCTypes, true); - - // Return null if no extension bits are used. - if (optInstanceMethods->isNullValue() && - optClassMethods->isNullValue() && - extendedMethodTypes->isNullValue() && - instanceProperties->isNullValue() && - classProperties->isNullValue()) { - return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy); - } - - uint64_t size = - CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy); - - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy); - values.addInt(ObjCTypes.IntTy, size); - values.add(optInstanceMethods); - values.add(optClassMethods); - values.add(instanceProperties); - values.add(extendedMethodTypes); - values.add(classProperties); - - // No special section, but goes in llvm.used - return CreateMetadataVar("\01l_OBJC_PROTOCOLEXT_" + PD->getName(), values, - StringRef(), CGM.getPointerAlign(), true); -} - -/* - struct objc_protocol_list { - struct objc_protocol_list *next; - long count; - Protocol *list[]; - }; -*/ -llvm::Constant * -CGObjCMac::EmitProtocolList(Twine name, - ObjCProtocolDecl::protocol_iterator begin, - ObjCProtocolDecl::protocol_iterator end) { - // Just return null for empty protocol lists - if (begin == end) - return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); - - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(); - - // This field is only used by the runtime. - values.addNullPointer(ObjCTypes.ProtocolListPtrTy); - - // Reserve a slot for the count. - auto countSlot = values.addPlaceholder(); - - auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy); - for (; begin != end; ++begin) { - refsArray.add(GetProtocolRef(*begin)); - } - auto count = refsArray.size(); - - // This list is null terminated. - refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy); - - refsArray.finishAndAddTo(values); - values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count); - - StringRef section; - if (CGM.getTriple().isOSBinFormatMachO()) - section = "__OBJC,__cat_cls_meth,regular,no_dead_strip"; - - llvm::GlobalVariable *GV = - CreateMetadataVar(name, values, section, CGM.getPointerAlign(), false); - return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy); -} - -static void -PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet, - SmallVectorImpl<const ObjCPropertyDecl *> &Properties, - const ObjCProtocolDecl *Proto, - bool IsClassProperty) { - for (const auto *P : Proto->protocols()) - PushProtocolProperties(PropertySet, Properties, P, IsClassProperty); - - for (const auto *PD : Proto->properties()) { - if (IsClassProperty != PD->isClassProperty()) - continue; - if (!PropertySet.insert(PD->getIdentifier()).second) - continue; - Properties.push_back(PD); - } -} - -/* - struct _objc_property { - const char * const name; - const char * const attributes; - }; - - struct _objc_property_list { - uint32_t entsize; // sizeof (struct _objc_property) - uint32_t prop_count; - struct _objc_property[prop_count]; - }; -*/ -llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name, - const Decl *Container, - const ObjCContainerDecl *OCD, - const ObjCCommonTypesHelper &ObjCTypes, - bool IsClassProperty) { - if (IsClassProperty) { - // Make this entry NULL for OS X with deployment target < 10.11, for iOS - // with deployment target < 9.0. - const llvm::Triple &Triple = CGM.getTarget().getTriple(); - if ((Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 11)) || - (Triple.isiOS() && Triple.isOSVersionLT(9))) - return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); - } - - SmallVector<const ObjCPropertyDecl *, 16> Properties; - llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet; - - if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) - for (const ObjCCategoryDecl *ClassExt : OID->known_extensions()) - for (auto *PD : ClassExt->properties()) { - if (IsClassProperty != PD->isClassProperty()) - continue; - PropertySet.insert(PD->getIdentifier()); - Properties.push_back(PD); - } - - for (const auto *PD : OCD->properties()) { - if (IsClassProperty != PD->isClassProperty()) - continue; - // Don't emit duplicate metadata for properties that were already in a - // class extension. - if (!PropertySet.insert(PD->getIdentifier()).second) - continue; - Properties.push_back(PD); - } - - if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) { - for (const auto *P : OID->all_referenced_protocols()) - PushProtocolProperties(PropertySet, Properties, P, IsClassProperty); - } - else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) { - for (const auto *P : CD->protocols()) - PushProtocolProperties(PropertySet, Properties, P, IsClassProperty); - } - - // Return null for empty list. - if (Properties.empty()) - return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); - - unsigned propertySize = - CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy); - - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(); - values.addInt(ObjCTypes.IntTy, propertySize); - values.addInt(ObjCTypes.IntTy, Properties.size()); - auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy); - for (auto PD : Properties) { - auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy); - property.add(GetPropertyName(PD->getIdentifier())); - property.add(GetPropertyTypeString(PD, Container)); - property.finishAndAddTo(propertiesArray); - } - propertiesArray.finishAndAddTo(values); - - StringRef Section; - if (CGM.getTriple().isOSBinFormatMachO()) - Section = (ObjCABI == 2) ? "__DATA, __objc_const" - : "__OBJC,__property,regular,no_dead_strip"; - - llvm::GlobalVariable *GV = - CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true); - return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy); -} - -llvm::Constant * -CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name, - ArrayRef<llvm::Constant*> MethodTypes, - const ObjCCommonTypesHelper &ObjCTypes) { - // Return null for empty list. - if (MethodTypes.empty()) - return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy); - - llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy, - MethodTypes.size()); - llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes); - - StringRef Section; - if (CGM.getTriple().isOSBinFormatMachO() && ObjCABI == 2) - Section = "__DATA, __objc_const"; - - llvm::GlobalVariable *GV = - CreateMetadataVar(Name, Init, Section, CGM.getPointerAlign(), true); - return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy); -} - -/* - struct _objc_category { - char *category_name; - char *class_name; - struct _objc_method_list *instance_methods; - struct _objc_method_list *class_methods; - struct _objc_protocol_list *protocols; - uint32_t size; // <rdar://4585769> - struct _objc_property_list *instance_properties; - struct _objc_property_list *class_properties; - }; -*/ -void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { - unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy); - - // FIXME: This is poor design, the OCD should have a pointer to the category - // decl. Additionally, note that Category can be null for the @implementation - // w/o an @interface case. Sema should just create one for us as it does for - // @implementation so everyone else can live life under a clear blue sky. - const ObjCInterfaceDecl *Interface = OCD->getClassInterface(); - const ObjCCategoryDecl *Category = - Interface->FindCategoryDeclaration(OCD->getIdentifier()); - - SmallString<256> ExtName; - llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_' - << OCD->getName(); - - ConstantInitBuilder Builder(CGM); - auto Values = Builder.beginStruct(ObjCTypes.CategoryTy); - - enum { - InstanceMethods, - ClassMethods, - NumMethodLists - }; - SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists]; - for (const auto *MD : OCD->methods()) { - Methods[unsigned(MD->isClassMethod())].push_back(MD); - } - - Values.add(GetClassName(OCD->getName())); - Values.add(GetClassName(Interface->getObjCRuntimeNameAsString())); - LazySymbols.insert(Interface->getIdentifier()); - - Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods, - Methods[InstanceMethods])); - Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods, - Methods[ClassMethods])); - if (Category) { - Values.add( - EmitProtocolList("OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(), - Category->protocol_begin(), Category->protocol_end())); - } else { - Values.addNullPointer(ObjCTypes.ProtocolListPtrTy); - } - Values.addInt(ObjCTypes.IntTy, Size); - - // If there is no category @interface then there can be no properties. - if (Category) { - Values.add(EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(), - OCD, Category, ObjCTypes, false)); - Values.add(EmitPropertyList("\01l_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(), - OCD, Category, ObjCTypes, true)); - } else { - Values.addNullPointer(ObjCTypes.PropertyListPtrTy); - Values.addNullPointer(ObjCTypes.PropertyListPtrTy); - } - - llvm::GlobalVariable *GV = - CreateMetadataVar("OBJC_CATEGORY_" + ExtName.str(), Values, - "__OBJC,__category,regular,no_dead_strip", - CGM.getPointerAlign(), true); - DefinedCategories.push_back(GV); - DefinedCategoryNames.insert(llvm::CachedHashString(ExtName)); - // method definition entries must be clear for next implementation. - MethodDefinitions.clear(); -} - -enum FragileClassFlags { - /// Apparently: is not a meta-class. - FragileABI_Class_Factory = 0x00001, - - /// Is a meta-class. - FragileABI_Class_Meta = 0x00002, - - /// Has a non-trivial constructor or destructor. - FragileABI_Class_HasCXXStructors = 0x02000, - - /// Has hidden visibility. - FragileABI_Class_Hidden = 0x20000, - - /// Class implementation was compiled under ARC. - FragileABI_Class_CompiledByARC = 0x04000000, - - /// Class implementation was compiled under MRC and has MRC weak ivars. - /// Exclusive with CompiledByARC. - FragileABI_Class_HasMRCWeakIvars = 0x08000000, -}; - -enum NonFragileClassFlags { - /// Is a meta-class. - NonFragileABI_Class_Meta = 0x00001, - - /// Is a root class. - NonFragileABI_Class_Root = 0x00002, - - /// Has a non-trivial constructor or destructor. - NonFragileABI_Class_HasCXXStructors = 0x00004, - - /// Has hidden visibility. - NonFragileABI_Class_Hidden = 0x00010, - - /// Has the exception attribute. - NonFragileABI_Class_Exception = 0x00020, - - /// (Obsolete) ARC-specific: this class has a .release_ivars method - NonFragileABI_Class_HasIvarReleaser = 0x00040, - - /// Class implementation was compiled under ARC. - NonFragileABI_Class_CompiledByARC = 0x00080, - - /// Class has non-trivial destructors, but zero-initialization is okay. - NonFragileABI_Class_HasCXXDestructorOnly = 0x00100, - - /// Class implementation was compiled under MRC and has MRC weak ivars. - /// Exclusive with CompiledByARC. - NonFragileABI_Class_HasMRCWeakIvars = 0x00200, -}; - -static bool hasWeakMember(QualType type) { - if (type.getObjCLifetime() == Qualifiers::OCL_Weak) { - return true; - } - - if (auto recType = type->getAs<RecordType>()) { - for (auto field : recType->getDecl()->fields()) { - if (hasWeakMember(field->getType())) - return true; - } - } - - return false; -} - -/// For compatibility, we only want to set the "HasMRCWeakIvars" flag -/// (and actually fill in a layout string) if we really do have any -/// __weak ivars. -static bool hasMRCWeakIvars(CodeGenModule &CGM, - const ObjCImplementationDecl *ID) { - if (!CGM.getLangOpts().ObjCWeak) return false; - assert(CGM.getLangOpts().getGC() == LangOptions::NonGC); - - for (const ObjCIvarDecl *ivar = - ID->getClassInterface()->all_declared_ivar_begin(); - ivar; ivar = ivar->getNextIvar()) { - if (hasWeakMember(ivar->getType())) - return true; - } - - return false; -} - -/* - struct _objc_class { - Class isa; - Class super_class; - const char *name; - long version; - long info; - long instance_size; - struct _objc_ivar_list *ivars; - struct _objc_method_list *methods; - struct _objc_cache *cache; - struct _objc_protocol_list *protocols; - // Objective-C 1.0 extensions (<rdr://4585769>) - const char *ivar_layout; - struct _objc_class_ext *ext; - }; - - See EmitClassExtension(); -*/ -void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { - IdentifierInfo *RuntimeName = - &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString()); - DefinedSymbols.insert(RuntimeName); - - std::string ClassName = ID->getNameAsString(); - // FIXME: Gross - ObjCInterfaceDecl *Interface = - const_cast<ObjCInterfaceDecl*>(ID->getClassInterface()); - llvm::Constant *Protocols = - EmitProtocolList("OBJC_CLASS_PROTOCOLS_" + ID->getName(), - Interface->all_referenced_protocol_begin(), - Interface->all_referenced_protocol_end()); - unsigned Flags = FragileABI_Class_Factory; - if (ID->hasNonZeroConstructors() || ID->hasDestructors()) - Flags |= FragileABI_Class_HasCXXStructors; - - bool hasMRCWeak = false; - - if (CGM.getLangOpts().ObjCAutoRefCount) - Flags |= FragileABI_Class_CompiledByARC; - else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID))) - Flags |= FragileABI_Class_HasMRCWeakIvars; - - CharUnits Size = - CGM.getContext().getASTObjCImplementationLayout(ID).getSize(); - - // FIXME: Set CXX-structors flag. - if (ID->getClassInterface()->getVisibility() == HiddenVisibility) - Flags |= FragileABI_Class_Hidden; - - enum { - InstanceMethods, - ClassMethods, - NumMethodLists - }; - SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists]; - for (const auto *MD : ID->methods()) { - Methods[unsigned(MD->isClassMethod())].push_back(MD); - } - - for (const auto *PID : ID->property_impls()) { - if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) { - ObjCPropertyDecl *PD = PID->getPropertyDecl(); - - if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) - if (GetMethodDefinition(MD)) - Methods[InstanceMethods].push_back(MD); - if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) - if (GetMethodDefinition(MD)) - Methods[InstanceMethods].push_back(MD); - } - } - - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(ObjCTypes.ClassTy); - values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods])); - if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) { - // Record a reference to the super class. - LazySymbols.insert(Super->getIdentifier()); - - values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()), - ObjCTypes.ClassPtrTy); - } else { - values.addNullPointer(ObjCTypes.ClassPtrTy); - } - values.add(GetClassName(ID->getObjCRuntimeNameAsString())); - // Version is always 0. - values.addInt(ObjCTypes.LongTy, 0); - values.addInt(ObjCTypes.LongTy, Flags); - values.addInt(ObjCTypes.LongTy, Size.getQuantity()); - values.add(EmitIvarList(ID, false)); - values.add(emitMethodList(ID->getName(), MethodListType::InstanceMethods, - Methods[InstanceMethods])); - // cache is always NULL. - values.addNullPointer(ObjCTypes.CachePtrTy); - values.add(Protocols); - values.add(BuildStrongIvarLayout(ID, CharUnits::Zero(), Size)); - values.add(EmitClassExtension(ID, Size, hasMRCWeak, - /*isMetaclass*/ false)); - - std::string Name("OBJC_CLASS_"); - Name += ClassName; - const char *Section = "__OBJC,__class,regular,no_dead_strip"; - // Check for a forward reference. - llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true); - if (GV) { - assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && - "Forward metaclass reference has incorrect type."); - values.finishAndSetAsInitializer(GV); - GV->setSection(Section); - GV->setAlignment(CGM.getPointerAlign().getQuantity()); - CGM.addCompilerUsedGlobal(GV); - } else - GV = CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true); - DefinedClasses.push_back(GV); - ImplementedClasses.push_back(Interface); - // method definition entries must be clear for next implementation. - MethodDefinitions.clear(); -} - -llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID, - llvm::Constant *Protocols, - ArrayRef<const ObjCMethodDecl*> Methods) { - unsigned Flags = FragileABI_Class_Meta; - unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy); - - if (ID->getClassInterface()->getVisibility() == HiddenVisibility) - Flags |= FragileABI_Class_Hidden; - - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(ObjCTypes.ClassTy); - // The isa for the metaclass is the root of the hierarchy. - const ObjCInterfaceDecl *Root = ID->getClassInterface(); - while (const ObjCInterfaceDecl *Super = Root->getSuperClass()) - Root = Super; - values.addBitCast(GetClassName(Root->getObjCRuntimeNameAsString()), - ObjCTypes.ClassPtrTy); - // The super class for the metaclass is emitted as the name of the - // super class. The runtime fixes this up to point to the - // *metaclass* for the super class. - if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) { - values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()), - ObjCTypes.ClassPtrTy); - } else { - values.addNullPointer(ObjCTypes.ClassPtrTy); - } - values.add(GetClassName(ID->getObjCRuntimeNameAsString())); - // Version is always 0. - values.addInt(ObjCTypes.LongTy, 0); - values.addInt(ObjCTypes.LongTy, Flags); - values.addInt(ObjCTypes.LongTy, Size); - values.add(EmitIvarList(ID, true)); - values.add(emitMethodList(ID->getName(), MethodListType::ClassMethods, - Methods)); - // cache is always NULL. - values.addNullPointer(ObjCTypes.CachePtrTy); - values.add(Protocols); - // ivar_layout for metaclass is always NULL. - values.addNullPointer(ObjCTypes.Int8PtrTy); - // The class extension is used to store class properties for metaclasses. - values.add(EmitClassExtension(ID, CharUnits::Zero(), false/*hasMRCWeak*/, - /*isMetaclass*/true)); - - std::string Name("OBJC_METACLASS_"); - Name += ID->getName(); - - // Check for a forward reference. - llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true); - if (GV) { - assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && - "Forward metaclass reference has incorrect type."); - values.finishAndSetAsInitializer(GV); - } else { - GV = values.finishAndCreateGlobal(Name, CGM.getPointerAlign(), - /*constant*/ false, - llvm::GlobalValue::PrivateLinkage); - } - GV->setSection("__OBJC,__meta_class,regular,no_dead_strip"); - CGM.addCompilerUsedGlobal(GV); - - return GV; -} - -llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) { - std::string Name = "OBJC_METACLASS_" + ID->getNameAsString(); - - // FIXME: Should we look these up somewhere other than the module. Its a bit - // silly since we only generate these while processing an implementation, so - // exactly one pointer would work if know when we entered/exitted an - // implementation block. - - // Check for an existing forward reference. - // Previously, metaclass with internal linkage may have been defined. - // pass 'true' as 2nd argument so it is returned. - llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true); - if (!GV) - GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, - llvm::GlobalValue::PrivateLinkage, nullptr, - Name); - - assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && - "Forward metaclass reference has incorrect type."); - return GV; -} - -llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) { - std::string Name = "OBJC_CLASS_" + ID->getNameAsString(); - llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true); - - if (!GV) - GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, - llvm::GlobalValue::PrivateLinkage, nullptr, - Name); - - assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && - "Forward class metadata reference has incorrect type."); - return GV; -} - -/* - Emit a "class extension", which in this specific context means extra - data that doesn't fit in the normal fragile-ABI class structure, and - has nothing to do with the language concept of a class extension. - - struct objc_class_ext { - uint32_t size; - const char *weak_ivar_layout; - struct _objc_property_list *properties; - }; -*/ -llvm::Constant * -CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID, - CharUnits InstanceSize, bool hasMRCWeakIvars, - bool isMetaclass) { - // Weak ivar layout. - llvm::Constant *layout; - if (isMetaclass) { - layout = llvm::ConstantPointerNull::get(CGM.Int8PtrTy); - } else { - layout = BuildWeakIvarLayout(ID, CharUnits::Zero(), InstanceSize, - hasMRCWeakIvars); - } - - // Properties. - llvm::Constant *propertyList = - EmitPropertyList((isMetaclass ? Twine("\01l_OBJC_$_CLASS_PROP_LIST_") - : Twine("\01l_OBJC_$_PROP_LIST_")) - + ID->getName(), - ID, ID->getClassInterface(), ObjCTypes, isMetaclass); - - // Return null if no extension bits are used. - if (layout->isNullValue() && propertyList->isNullValue()) { - return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy); - } - - uint64_t size = - CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy); - - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy); - values.addInt(ObjCTypes.IntTy, size); - values.add(layout); - values.add(propertyList); - - return CreateMetadataVar("OBJC_CLASSEXT_" + ID->getName(), values, - "__OBJC,__class_ext,regular,no_dead_strip", - CGM.getPointerAlign(), true); -} - -/* - struct objc_ivar { - char *ivar_name; - char *ivar_type; - int ivar_offset; - }; - - struct objc_ivar_list { - int ivar_count; - struct objc_ivar list[count]; - }; -*/ -llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID, - bool ForClass) { - // When emitting the root class GCC emits ivar entries for the - // actual class structure. It is not clear if we need to follow this - // behavior; for now lets try and get away with not doing it. If so, - // the cleanest solution would be to make up an ObjCInterfaceDecl - // for the class. - if (ForClass) - return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy); - - const ObjCInterfaceDecl *OID = ID->getClassInterface(); - - ConstantInitBuilder builder(CGM); - auto ivarList = builder.beginStruct(); - auto countSlot = ivarList.addPlaceholder(); - auto ivars = ivarList.beginArray(ObjCTypes.IvarTy); - - for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin(); - IVD; IVD = IVD->getNextIvar()) { - // Ignore unnamed bit-fields. - if (!IVD->getDeclName()) - continue; - - auto ivar = ivars.beginStruct(ObjCTypes.IvarTy); - ivar.add(GetMethodVarName(IVD->getIdentifier())); - ivar.add(GetMethodVarType(IVD)); - ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD)); - ivar.finishAndAddTo(ivars); - } - - // Return null for empty list. - auto count = ivars.size(); - if (count == 0) { - ivars.abandon(); - ivarList.abandon(); - return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy); - } - - ivars.finishAndAddTo(ivarList); - ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count); - - llvm::GlobalVariable *GV; - if (ForClass) - GV = - CreateMetadataVar("OBJC_CLASS_VARIABLES_" + ID->getName(), ivarList, - "__OBJC,__class_vars,regular,no_dead_strip", - CGM.getPointerAlign(), true); - else - GV = CreateMetadataVar("OBJC_INSTANCE_VARIABLES_" + ID->getName(), ivarList, - "__OBJC,__instance_vars,regular,no_dead_strip", - CGM.getPointerAlign(), true); - return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy); -} - -/// Build a struct objc_method_description constant for the given method. -/// -/// struct objc_method_description { -/// SEL method_name; -/// char *method_types; -/// }; -void CGObjCMac::emitMethodDescriptionConstant(ConstantArrayBuilder &builder, - const ObjCMethodDecl *MD) { - auto description = builder.beginStruct(ObjCTypes.MethodDescriptionTy); - description.addBitCast(GetMethodVarName(MD->getSelector()), - ObjCTypes.SelectorPtrTy); - description.add(GetMethodVarType(MD)); - description.finishAndAddTo(builder); -} - -/// Build a struct objc_method constant for the given method. -/// -/// struct objc_method { -/// SEL method_name; -/// char *method_types; -/// void *method; -/// }; -void CGObjCMac::emitMethodConstant(ConstantArrayBuilder &builder, - const ObjCMethodDecl *MD) { - llvm::Function *fn = GetMethodDefinition(MD); - assert(fn && "no definition registered for method"); - - auto method = builder.beginStruct(ObjCTypes.MethodTy); - method.addBitCast(GetMethodVarName(MD->getSelector()), - ObjCTypes.SelectorPtrTy); - method.add(GetMethodVarType(MD)); - method.addBitCast(fn, ObjCTypes.Int8PtrTy); - method.finishAndAddTo(builder); -} - -/// Build a struct objc_method_list or struct objc_method_description_list, -/// as appropriate. -/// -/// struct objc_method_list { -/// struct objc_method_list *obsolete; -/// int count; -/// struct objc_method methods_list[count]; -/// }; -/// -/// struct objc_method_description_list { -/// int count; -/// struct objc_method_description list[count]; -/// }; -llvm::Constant *CGObjCMac::emitMethodList(Twine name, MethodListType MLT, - ArrayRef<const ObjCMethodDecl *> methods) { - StringRef prefix; - StringRef section; - bool forProtocol = false; - switch (MLT) { - case MethodListType::CategoryInstanceMethods: - prefix = "OBJC_CATEGORY_INSTANCE_METHODS_"; - section = "__OBJC,__cat_inst_meth,regular,no_dead_strip"; - forProtocol = false; - break; - case MethodListType::CategoryClassMethods: - prefix = "OBJC_CATEGORY_CLASS_METHODS_"; - section = "__OBJC,__cat_cls_meth,regular,no_dead_strip"; - forProtocol = false; - break; - case MethodListType::InstanceMethods: - prefix = "OBJC_INSTANCE_METHODS_"; - section = "__OBJC,__inst_meth,regular,no_dead_strip"; - forProtocol = false; - break; - case MethodListType::ClassMethods: - prefix = "OBJC_CLASS_METHODS_"; - section = "__OBJC,__cls_meth,regular,no_dead_strip"; - forProtocol = false; - break; - case MethodListType::ProtocolInstanceMethods: - prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_"; - section = "__OBJC,__cat_inst_meth,regular,no_dead_strip"; - forProtocol = true; - break; - case MethodListType::ProtocolClassMethods: - prefix = "OBJC_PROTOCOL_CLASS_METHODS_"; - section = "__OBJC,__cat_cls_meth,regular,no_dead_strip"; - forProtocol = true; - break; - case MethodListType::OptionalProtocolInstanceMethods: - prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"; - section = "__OBJC,__cat_inst_meth,regular,no_dead_strip"; - forProtocol = true; - break; - case MethodListType::OptionalProtocolClassMethods: - prefix = "OBJC_PROTOCOL_CLASS_METHODS_OPT_"; - section = "__OBJC,__cat_cls_meth,regular,no_dead_strip"; - forProtocol = true; - break; - } - - // Return null for empty list. - if (methods.empty()) - return llvm::Constant::getNullValue(forProtocol - ? ObjCTypes.MethodDescriptionListPtrTy - : ObjCTypes.MethodListPtrTy); - - // For protocols, this is an objc_method_description_list, which has - // a slightly different structure. - if (forProtocol) { - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(); - values.addInt(ObjCTypes.IntTy, methods.size()); - auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy); - for (auto MD : methods) { - emitMethodDescriptionConstant(methodArray, MD); - } - methodArray.finishAndAddTo(values); - - llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section, - CGM.getPointerAlign(), true); - return llvm::ConstantExpr::getBitCast(GV, - ObjCTypes.MethodDescriptionListPtrTy); - } - - // Otherwise, it's an objc_method_list. - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(); - values.addNullPointer(ObjCTypes.Int8PtrTy); - values.addInt(ObjCTypes.IntTy, methods.size()); - auto methodArray = values.beginArray(ObjCTypes.MethodTy); - for (auto MD : methods) { - emitMethodConstant(methodArray, MD); - } - methodArray.finishAndAddTo(values); - - llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section, - CGM.getPointerAlign(), true); - return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy); -} - -llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD, - const ObjCContainerDecl *CD) { - SmallString<256> Name; - GetNameForMethod(OMD, CD, Name); - - CodeGenTypes &Types = CGM.getTypes(); - llvm::FunctionType *MethodTy = - Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD)); - llvm::Function *Method = - llvm::Function::Create(MethodTy, - llvm::GlobalValue::InternalLinkage, - Name.str(), - &CGM.getModule()); - MethodDefinitions.insert(std::make_pair(OMD, Method)); - - return Method; -} - -llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name, - ConstantStructBuilder &Init, - StringRef Section, - CharUnits Align, - bool AddToUsed) { - llvm::GlobalVariable *GV = - Init.finishAndCreateGlobal(Name, Align, /*constant*/ false, - llvm::GlobalValue::PrivateLinkage); - if (!Section.empty()) - GV->setSection(Section); - if (AddToUsed) - CGM.addCompilerUsedGlobal(GV); - return GV; -} - -llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name, - llvm::Constant *Init, - StringRef Section, - CharUnits Align, - bool AddToUsed) { - llvm::Type *Ty = Init->getType(); - llvm::GlobalVariable *GV = - new llvm::GlobalVariable(CGM.getModule(), Ty, false, - llvm::GlobalValue::PrivateLinkage, Init, Name); - if (!Section.empty()) - GV->setSection(Section); - GV->setAlignment(Align.getQuantity()); - if (AddToUsed) - CGM.addCompilerUsedGlobal(GV); - return GV; -} - -llvm::GlobalVariable * -CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType Type, - bool ForceNonFragileABI, - bool NullTerminate) { - StringRef Label; - switch (Type) { - case ObjCLabelType::ClassName: Label = "OBJC_CLASS_NAME_"; break; - case ObjCLabelType::MethodVarName: Label = "OBJC_METH_VAR_NAME_"; break; - case ObjCLabelType::MethodVarType: Label = "OBJC_METH_VAR_TYPE_"; break; - case ObjCLabelType::PropertyName: Label = "OBJC_PROP_NAME_ATTR_"; break; - } - - bool NonFragile = ForceNonFragileABI || isNonFragileABI(); - - StringRef Section; - switch (Type) { - case ObjCLabelType::ClassName: - Section = NonFragile ? "__TEXT,__objc_classname,cstring_literals" - : "__TEXT,__cstring,cstring_literals"; - break; - case ObjCLabelType::MethodVarName: - Section = NonFragile ? "__TEXT,__objc_methname,cstring_literals" - : "__TEXT,__cstring,cstring_literals"; - break; - case ObjCLabelType::MethodVarType: - Section = NonFragile ? "__TEXT,__objc_methtype,cstring_literals" - : "__TEXT,__cstring,cstring_literals"; - break; - case ObjCLabelType::PropertyName: - Section = "__TEXT,__cstring,cstring_literals"; - break; - } - - llvm::Constant *Value = - llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate); - llvm::GlobalVariable *GV = - new llvm::GlobalVariable(CGM.getModule(), Value->getType(), - /*isConstant=*/true, - llvm::GlobalValue::PrivateLinkage, Value, Label); - if (CGM.getTriple().isOSBinFormatMachO()) - GV->setSection(Section); - GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - GV->setAlignment(CharUnits::One().getQuantity()); - CGM.addCompilerUsedGlobal(GV); - - return GV; -} - -llvm::Function *CGObjCMac::ModuleInitFunction() { - // Abuse this interface function as a place to finalize. - FinishModule(); - return nullptr; -} - -llvm::Constant *CGObjCMac::GetPropertyGetFunction() { - return ObjCTypes.getGetPropertyFn(); -} - -llvm::Constant *CGObjCMac::GetPropertySetFunction() { - return ObjCTypes.getSetPropertyFn(); -} - -llvm::Constant *CGObjCMac::GetOptimizedPropertySetFunction(bool atomic, - bool copy) { - return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy); -} - -llvm::Constant *CGObjCMac::GetGetStructFunction() { - return ObjCTypes.getCopyStructFn(); -} - -llvm::Constant *CGObjCMac::GetSetStructFunction() { - return ObjCTypes.getCopyStructFn(); -} - -llvm::Constant *CGObjCMac::GetCppAtomicObjectGetFunction() { - return ObjCTypes.getCppAtomicObjectFunction(); -} - -llvm::Constant *CGObjCMac::GetCppAtomicObjectSetFunction() { - return ObjCTypes.getCppAtomicObjectFunction(); -} - -llvm::Constant *CGObjCMac::EnumerationMutationFunction() { - return ObjCTypes.getEnumerationMutationFn(); -} - -void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) { - return EmitTryOrSynchronizedStmt(CGF, S); -} - -void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF, - const ObjCAtSynchronizedStmt &S) { - return EmitTryOrSynchronizedStmt(CGF, S); -} - -namespace { - struct PerformFragileFinally final : EHScopeStack::Cleanup { - const Stmt &S; - Address SyncArgSlot; - Address CallTryExitVar; - Address ExceptionData; - ObjCTypesHelper &ObjCTypes; - PerformFragileFinally(const Stmt *S, - Address SyncArgSlot, - Address CallTryExitVar, - Address ExceptionData, - ObjCTypesHelper *ObjCTypes) - : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar), - ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - // Check whether we need to call objc_exception_try_exit. - // In optimized code, this branch will always be folded. - llvm::BasicBlock *FinallyCallExit = - CGF.createBasicBlock("finally.call_exit"); - llvm::BasicBlock *FinallyNoCallExit = - CGF.createBasicBlock("finally.no_call_exit"); - CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar), - FinallyCallExit, FinallyNoCallExit); - - CGF.EmitBlock(FinallyCallExit); - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(), - ExceptionData.getPointer()); - - CGF.EmitBlock(FinallyNoCallExit); - - if (isa<ObjCAtTryStmt>(S)) { - if (const ObjCAtFinallyStmt* FinallyStmt = - cast<ObjCAtTryStmt>(S).getFinallyStmt()) { - // Don't try to do the @finally if this is an EH cleanup. - if (flags.isForEHCleanup()) return; - - // Save the current cleanup destination in case there's - // control flow inside the finally statement. - llvm::Value *CurCleanupDest = - CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot()); - - CGF.EmitStmt(FinallyStmt->getFinallyBody()); - - if (CGF.HaveInsertPoint()) { - CGF.Builder.CreateStore(CurCleanupDest, - CGF.getNormalCleanupDestSlot()); - } else { - // Currently, the end of the cleanup must always exist. - CGF.EnsureInsertPoint(); - } - } - } else { - // Emit objc_sync_exit(expr); as finally's sole statement for - // @synchronized. - llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot); - CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncExitFn(), SyncArg); - } - } - }; - - class FragileHazards { - CodeGenFunction &CGF; - SmallVector<llvm::Value*, 20> Locals; - llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry; - - llvm::InlineAsm *ReadHazard; - llvm::InlineAsm *WriteHazard; - - llvm::FunctionType *GetAsmFnType(); - - void collectLocals(); - void emitReadHazard(CGBuilderTy &Builder); - - public: - FragileHazards(CodeGenFunction &CGF); - - void emitWriteHazard(); - void emitHazardsInNewBlocks(); - }; -} // end anonymous namespace - -/// Create the fragile-ABI read and write hazards based on the current -/// state of the function, which is presumed to be immediately prior -/// to a @try block. These hazards are used to maintain correct -/// semantics in the face of optimization and the fragile ABI's -/// cavalier use of setjmp/longjmp. -FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) { - collectLocals(); - - if (Locals.empty()) return; - - // Collect all the blocks in the function. - for (llvm::Function::iterator - I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I) - BlocksBeforeTry.insert(&*I); - - llvm::FunctionType *AsmFnTy = GetAsmFnType(); - - // Create a read hazard for the allocas. This inhibits dead-store - // optimizations and forces the values to memory. This hazard is - // inserted before any 'throwing' calls in the protected scope to - // reflect the possibility that the variables might be read from the - // catch block if the call throws. - { - std::string Constraint; - for (unsigned I = 0, E = Locals.size(); I != E; ++I) { - if (I) Constraint += ','; - Constraint += "*m"; - } - - ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false); - } - - // Create a write hazard for the allocas. This inhibits folding - // loads across the hazard. This hazard is inserted at the - // beginning of the catch path to reflect the possibility that the - // variables might have been written within the protected scope. - { - std::string Constraint; - for (unsigned I = 0, E = Locals.size(); I != E; ++I) { - if (I) Constraint += ','; - Constraint += "=*m"; - } - - WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false); - } -} - -/// Emit a write hazard at the current location. -void FragileHazards::emitWriteHazard() { - if (Locals.empty()) return; - - CGF.EmitNounwindRuntimeCall(WriteHazard, Locals); -} - -void FragileHazards::emitReadHazard(CGBuilderTy &Builder) { - assert(!Locals.empty()); - llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals); - call->setDoesNotThrow(); - call->setCallingConv(CGF.getRuntimeCC()); -} - -/// Emit read hazards in all the protected blocks, i.e. all the blocks -/// which have been inserted since the beginning of the try. -void FragileHazards::emitHazardsInNewBlocks() { - if (Locals.empty()) return; - - CGBuilderTy Builder(CGF, CGF.getLLVMContext()); - - // Iterate through all blocks, skipping those prior to the try. - for (llvm::Function::iterator - FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) { - llvm::BasicBlock &BB = *FI; - if (BlocksBeforeTry.count(&BB)) continue; - - // Walk through all the calls in the block. - for (llvm::BasicBlock::iterator - BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) { - llvm::Instruction &I = *BI; - - // Ignore instructions that aren't non-intrinsic calls. - // These are the only calls that can possibly call longjmp. - if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue; - if (isa<llvm::IntrinsicInst>(I)) - continue; - - // Ignore call sites marked nounwind. This may be questionable, - // since 'nounwind' doesn't necessarily mean 'does not call longjmp'. - llvm::CallSite CS(&I); - if (CS.doesNotThrow()) continue; - - // Insert a read hazard before the call. This will ensure that - // any writes to the locals are performed before making the - // call. If the call throws, then this is sufficient to - // guarantee correctness as long as it doesn't also write to any - // locals. - Builder.SetInsertPoint(&BB, BI); - emitReadHazard(Builder); - } - } -} - -static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, Address V) { - if (V.isValid()) S.insert(V.getPointer()); -} - -void FragileHazards::collectLocals() { - // Compute a set of allocas to ignore. - llvm::DenseSet<llvm::Value*> AllocasToIgnore; - addIfPresent(AllocasToIgnore, CGF.ReturnValue); - addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest); - - // Collect all the allocas currently in the function. This is - // probably way too aggressive. - llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock(); - for (llvm::BasicBlock::iterator - I = Entry.begin(), E = Entry.end(); I != E; ++I) - if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I)) - Locals.push_back(&*I); -} - -llvm::FunctionType *FragileHazards::GetAsmFnType() { - SmallVector<llvm::Type *, 16> tys(Locals.size()); - for (unsigned i = 0, e = Locals.size(); i != e; ++i) - tys[i] = Locals[i]->getType(); - return llvm::FunctionType::get(CGF.VoidTy, tys, false); -} - -/* - - Objective-C setjmp-longjmp (sjlj) Exception Handling - -- - - A catch buffer is a setjmp buffer plus: - - a pointer to the exception that was caught - - a pointer to the previous exception data buffer - - two pointers of reserved storage - Therefore catch buffers form a stack, with a pointer to the top - of the stack kept in thread-local storage. - - objc_exception_try_enter pushes a catch buffer onto the EH stack. - objc_exception_try_exit pops the given catch buffer, which is - required to be the top of the EH stack. - objc_exception_throw pops the top of the EH stack, writes the - thrown exception into the appropriate field, and longjmps - to the setjmp buffer. It crashes the process (with a printf - and an abort()) if there are no catch buffers on the stack. - objc_exception_extract just reads the exception pointer out of the - catch buffer. - - There's no reason an implementation couldn't use a light-weight - setjmp here --- something like __builtin_setjmp, but API-compatible - with the heavyweight setjmp. This will be more important if we ever - want to implement correct ObjC/C++ exception interactions for the - fragile ABI. - - Note that for this use of setjmp/longjmp to be correct, we may need - to mark some local variables volatile: if a non-volatile local - variable is modified between the setjmp and the longjmp, it has - indeterminate value. For the purposes of LLVM IR, it may be - sufficient to make loads and stores within the @try (to variables - declared outside the @try) volatile. This is necessary for - optimized correctness, but is not currently being done; this is - being tracked as rdar://problem/8160285 - - The basic framework for a @try-catch-finally is as follows: - { - objc_exception_data d; - id _rethrow = null; - bool _call_try_exit = true; - - objc_exception_try_enter(&d); - if (!setjmp(d.jmp_buf)) { - ... try body ... - } else { - // exception path - id _caught = objc_exception_extract(&d); - - // enter new try scope for handlers - if (!setjmp(d.jmp_buf)) { - ... match exception and execute catch blocks ... - - // fell off end, rethrow. - _rethrow = _caught; - ... jump-through-finally to finally_rethrow ... - } else { - // exception in catch block - _rethrow = objc_exception_extract(&d); - _call_try_exit = false; - ... jump-through-finally to finally_rethrow ... - } - } - ... jump-through-finally to finally_end ... - - finally: - if (_call_try_exit) - objc_exception_try_exit(&d); - - ... finally block .... - ... dispatch to finally destination ... - - finally_rethrow: - objc_exception_throw(_rethrow); - - finally_end: - } - - This framework differs slightly from the one gcc uses, in that gcc - uses _rethrow to determine if objc_exception_try_exit should be called - and if the object should be rethrown. This breaks in the face of - throwing nil and introduces unnecessary branches. - - We specialize this framework for a few particular circumstances: - - - If there are no catch blocks, then we avoid emitting the second - exception handling context. - - - If there is a catch-all catch block (i.e. @catch(...) or @catch(id - e)) we avoid emitting the code to rethrow an uncaught exception. - - - FIXME: If there is no @finally block we can do a few more - simplifications. - - Rethrows and Jumps-Through-Finally - -- - - '@throw;' is supported by pushing the currently-caught exception - onto ObjCEHStack while the @catch blocks are emitted. - - Branches through the @finally block are handled with an ordinary - normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC - exceptions are not compatible with C++ exceptions, and this is - hardly the only place where this will go wrong. - - @synchronized(expr) { stmt; } is emitted as if it were: - id synch_value = expr; - objc_sync_enter(synch_value); - @try { stmt; } @finally { objc_sync_exit(synch_value); } -*/ - -void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, - const Stmt &S) { - bool isTry = isa<ObjCAtTryStmt>(S); - - // A destination for the fall-through edges of the catch handlers to - // jump to. - CodeGenFunction::JumpDest FinallyEnd = - CGF.getJumpDestInCurrentScope("finally.end"); - - // A destination for the rethrow edge of the catch handlers to jump - // to. - CodeGenFunction::JumpDest FinallyRethrow = - CGF.getJumpDestInCurrentScope("finally.rethrow"); - - // For @synchronized, call objc_sync_enter(sync.expr). The - // evaluation of the expression must occur before we enter the - // @synchronized. We can't avoid a temp here because we need the - // value to be preserved. If the backend ever does liveness - // correctly after setjmp, this will be unnecessary. - Address SyncArgSlot = Address::invalid(); - if (!isTry) { - llvm::Value *SyncArg = - CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr()); - SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy); - CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncEnterFn(), SyncArg); - - SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), - CGF.getPointerAlign(), "sync.arg"); - CGF.Builder.CreateStore(SyncArg, SyncArgSlot); - } - - // Allocate memory for the setjmp buffer. This needs to be kept - // live throughout the try and catch blocks. - Address ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy, - CGF.getPointerAlign(), - "exceptiondata.ptr"); - - // Create the fragile hazards. Note that this will not capture any - // of the allocas required for exception processing, but will - // capture the current basic block (which extends all the way to the - // setjmp call) as "before the @try". - FragileHazards Hazards(CGF); - - // Create a flag indicating whether the cleanup needs to call - // objc_exception_try_exit. This is true except when - // - no catches match and we're branching through the cleanup - // just to rethrow the exception, or - // - a catch matched and we're falling out of the catch handler. - // The setjmp-safety rule here is that we should always store to this - // variable in a place that dominates the branch through the cleanup - // without passing through any setjmps. - Address CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), - CharUnits::One(), - "_call_try_exit"); - - // A slot containing the exception to rethrow. Only needed when we - // have both a @catch and a @finally. - Address PropagatingExnVar = Address::invalid(); - - // Push a normal cleanup to leave the try scope. - CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalAndEHCleanup, &S, - SyncArgSlot, - CallTryExitVar, - ExceptionData, - &ObjCTypes); - - // Enter a try block: - // - Call objc_exception_try_enter to push ExceptionData on top of - // the EH stack. - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), - ExceptionData.getPointer()); - - // - Call setjmp on the exception data buffer. - llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0); - llvm::Value *GEPIndexes[] = { Zero, Zero, Zero }; - llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP( - ObjCTypes.ExceptionDataTy, ExceptionData.getPointer(), GEPIndexes, - "setjmp_buffer"); - llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall( - ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result"); - SetJmpResult->setCanReturnTwice(); - - // If setjmp returned 0, enter the protected block; otherwise, - // branch to the handler. - llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try"); - llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler"); - llvm::Value *DidCatch = - CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception"); - CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock); - - // Emit the protected block. - CGF.EmitBlock(TryBlock); - CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar); - CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody() - : cast<ObjCAtSynchronizedStmt>(S).getSynchBody()); - - CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP(); - - // Emit the exception handler block. - CGF.EmitBlock(TryHandler); - - // Don't optimize loads of the in-scope locals across this point. - Hazards.emitWriteHazard(); - - // For a @synchronized (or a @try with no catches), just branch - // through the cleanup to the rethrow block. - if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) { - // Tell the cleanup not to re-pop the exit. - CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar); - CGF.EmitBranchThroughCleanup(FinallyRethrow); - - // Otherwise, we have to match against the caught exceptions. - } else { - // Retrieve the exception object. We may emit multiple blocks but - // nothing can cross this so the value is already in SSA form. - llvm::CallInst *Caught = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), - ExceptionData.getPointer(), "caught"); - - // Push the exception to rethrow onto the EH value stack for the - // benefit of any @throws in the handlers. - CGF.ObjCEHValueStack.push_back(Caught); - - const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S); - - bool HasFinally = (AtTryStmt->getFinallyStmt() != nullptr); - - llvm::BasicBlock *CatchBlock = nullptr; - llvm::BasicBlock *CatchHandler = nullptr; - if (HasFinally) { - // Save the currently-propagating exception before - // objc_exception_try_enter clears the exception slot. - PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(), - CGF.getPointerAlign(), - "propagating_exception"); - CGF.Builder.CreateStore(Caught, PropagatingExnVar); - - // Enter a new exception try block (in case a @catch block - // throws an exception). - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), - ExceptionData.getPointer()); - - llvm::CallInst *SetJmpResult = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(), - SetJmpBuffer, "setjmp.result"); - SetJmpResult->setCanReturnTwice(); - - llvm::Value *Threw = - CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception"); - - CatchBlock = CGF.createBasicBlock("catch"); - CatchHandler = CGF.createBasicBlock("catch_for_catch"); - CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock); - - CGF.EmitBlock(CatchBlock); - } - - CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar); - - // Handle catch list. As a special case we check if everything is - // matched and avoid generating code for falling off the end if - // so. - bool AllMatched = false; - for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) { - const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I); - - const VarDecl *CatchParam = CatchStmt->getCatchParamDecl(); - const ObjCObjectPointerType *OPT = nullptr; - - // catch(...) always matches. - if (!CatchParam) { - AllMatched = true; - } else { - OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>(); - - // catch(id e) always matches under this ABI, since only - // ObjC exceptions end up here in the first place. - // FIXME: For the time being we also match id<X>; this should - // be rejected by Sema instead. - if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType())) - AllMatched = true; - } - - // If this is a catch-all, we don't need to test anything. - if (AllMatched) { - CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF); - - if (CatchParam) { - CGF.EmitAutoVarDecl(*CatchParam); - assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?"); - - // These types work out because ConvertType(id) == i8*. - EmitInitOfCatchParam(CGF, Caught, CatchParam); - } - - CGF.EmitStmt(CatchStmt->getCatchBody()); - - // The scope of the catch variable ends right here. - CatchVarCleanups.ForceCleanup(); - - CGF.EmitBranchThroughCleanup(FinallyEnd); - break; - } - - assert(OPT && "Unexpected non-object pointer type in @catch"); - const ObjCObjectType *ObjTy = OPT->getObjectType(); - - // FIXME: @catch (Class c) ? - ObjCInterfaceDecl *IDecl = ObjTy->getInterface(); - assert(IDecl && "Catch parameter must have Objective-C type!"); - - // Check if the @catch block matches the exception object. - llvm::Value *Class = EmitClassRef(CGF, IDecl); - - llvm::Value *matchArgs[] = { Class, Caught }; - llvm::CallInst *Match = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionMatchFn(), - matchArgs, "match"); - - llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match"); - llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next"); - - CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"), - MatchedBlock, NextCatchBlock); - - // Emit the @catch block. - CGF.EmitBlock(MatchedBlock); - - // Collect any cleanups for the catch variable. The scope lasts until - // the end of the catch body. - CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF); - - CGF.EmitAutoVarDecl(*CatchParam); - assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?"); - - // Initialize the catch variable. - llvm::Value *Tmp = - CGF.Builder.CreateBitCast(Caught, - CGF.ConvertType(CatchParam->getType())); - EmitInitOfCatchParam(CGF, Tmp, CatchParam); - - CGF.EmitStmt(CatchStmt->getCatchBody()); - - // We're done with the catch variable. - CatchVarCleanups.ForceCleanup(); - - CGF.EmitBranchThroughCleanup(FinallyEnd); - - CGF.EmitBlock(NextCatchBlock); - } - - CGF.ObjCEHValueStack.pop_back(); - - // If nothing wanted anything to do with the caught exception, - // kill the extract call. - if (Caught->use_empty()) - Caught->eraseFromParent(); - - if (!AllMatched) - CGF.EmitBranchThroughCleanup(FinallyRethrow); - - if (HasFinally) { - // Emit the exception handler for the @catch blocks. - CGF.EmitBlock(CatchHandler); - - // In theory we might now need a write hazard, but actually it's - // unnecessary because there's no local-accessing code between - // the try's write hazard and here. - //Hazards.emitWriteHazard(); - - // Extract the new exception and save it to the - // propagating-exception slot. - assert(PropagatingExnVar.isValid()); - llvm::CallInst *NewCaught = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), - ExceptionData.getPointer(), "caught"); - CGF.Builder.CreateStore(NewCaught, PropagatingExnVar); - - // Don't pop the catch handler; the throw already did. - CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar); - CGF.EmitBranchThroughCleanup(FinallyRethrow); - } - } - - // Insert read hazards as required in the new blocks. - Hazards.emitHazardsInNewBlocks(); - - // Pop the cleanup. - CGF.Builder.restoreIP(TryFallthroughIP); - if (CGF.HaveInsertPoint()) - CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar); - CGF.PopCleanupBlock(); - CGF.EmitBlock(FinallyEnd.getBlock(), true); - - // Emit the rethrow block. - CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP(); - CGF.EmitBlock(FinallyRethrow.getBlock(), true); - if (CGF.HaveInsertPoint()) { - // If we have a propagating-exception variable, check it. - llvm::Value *PropagatingExn; - if (PropagatingExnVar.isValid()) { - PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar); - - // Otherwise, just look in the buffer for the exception to throw. - } else { - llvm::CallInst *Caught = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), - ExceptionData.getPointer()); - PropagatingExn = Caught; - } - - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionThrowFn(), - PropagatingExn); - CGF.Builder.CreateUnreachable(); - } - - CGF.Builder.restoreIP(SavedIP); -} - -void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, - const ObjCAtThrowStmt &S, - bool ClearInsertionPoint) { - llvm::Value *ExceptionAsObject; - - if (const Expr *ThrowExpr = S.getThrowExpr()) { - llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr); - ExceptionAsObject = - CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy); - } else { - assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) && - "Unexpected rethrow outside @catch block."); - ExceptionAsObject = CGF.ObjCEHValueStack.back(); - } - - CGF.EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject) - ->setDoesNotReturn(); - CGF.Builder.CreateUnreachable(); - - // Clear the insertion point to indicate we are in unreachable code. - if (ClearInsertionPoint) - CGF.Builder.ClearInsertionPoint(); -} - -/// EmitObjCWeakRead - Code gen for loading value of a __weak -/// object: objc_read_weak (id *src) -/// -llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, - Address AddrWeakObj) { - llvm::Type* DestTy = AddrWeakObj.getElementType(); - AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, - ObjCTypes.PtrObjectPtrTy); - llvm::Value *read_weak = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(), - AddrWeakObj.getPointer(), "weakread"); - read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy); - return read_weak; -} - -/// EmitObjCWeakAssign - Code gen for assigning to a __weak object. -/// objc_assign_weak (id src, id *dst) -/// -void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dst) { - llvm::Type * SrcTy = src->getType(); - if (!isa<llvm::PointerType>(SrcTy)) { - unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); - assert(Size <= 8 && "does not support size > 8"); - src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty) - : CGF.Builder.CreateBitCast(src, CGM.Int64Ty); - src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); - } - src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); - llvm::Value *args[] = { src, dst.getPointer() }; - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), - args, "weakassign"); -} - -/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object. -/// objc_assign_global (id src, id *dst) -/// -void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dst, - bool threadlocal) { - llvm::Type * SrcTy = src->getType(); - if (!isa<llvm::PointerType>(SrcTy)) { - unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); - assert(Size <= 8 && "does not support size > 8"); - src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty) - : CGF.Builder.CreateBitCast(src, CGM.Int64Ty); - src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); - } - src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); - llvm::Value *args[] = { src, dst.getPointer() }; - if (!threadlocal) - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), - args, "globalassign"); - else - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(), - args, "threadlocalassign"); -} - -/// EmitObjCIvarAssign - Code gen for assigning to a __strong object. -/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset) -/// -void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dst, - llvm::Value *ivarOffset) { - assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL"); - llvm::Type * SrcTy = src->getType(); - if (!isa<llvm::PointerType>(SrcTy)) { - unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); - assert(Size <= 8 && "does not support size > 8"); - src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty) - : CGF.Builder.CreateBitCast(src, CGM.Int64Ty); - src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); - } - src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); - llvm::Value *args[] = { src, dst.getPointer(), ivarOffset }; - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args); -} - -/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object. -/// objc_assign_strongCast (id src, id *dst) -/// -void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dst) { - llvm::Type * SrcTy = src->getType(); - if (!isa<llvm::PointerType>(SrcTy)) { - unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); - assert(Size <= 8 && "does not support size > 8"); - src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty) - : CGF.Builder.CreateBitCast(src, CGM.Int64Ty); - src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); - } - src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); - llvm::Value *args[] = { src, dst.getPointer() }; - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), - args, "strongassign"); -} - -void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, - Address DestPtr, - Address SrcPtr, - llvm::Value *size) { - SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy); - DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy); - llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), size }; - CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args); -} - -/// EmitObjCValueForIvar - Code Gen for ivar reference. -/// -LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, - QualType ObjectTy, - llvm::Value *BaseValue, - const ObjCIvarDecl *Ivar, - unsigned CVRQualifiers) { - const ObjCInterfaceDecl *ID = - ObjectTy->getAs<ObjCObjectType>()->getInterface(); - return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, - EmitIvarOffset(CGF, ID, Ivar)); -} - -llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF, - const ObjCInterfaceDecl *Interface, - const ObjCIvarDecl *Ivar) { - uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar); - return llvm::ConstantInt::get( - CGM.getTypes().ConvertType(CGM.getContext().LongTy), - Offset); -} - -/* *** Private Interface *** */ - -std::string CGObjCCommonMac::GetSectionName(StringRef Section, - StringRef MachOAttributes) { - switch (CGM.getTriple().getObjectFormat()) { - default: - llvm_unreachable("unexpected object file format"); - case llvm::Triple::MachO: { - if (MachOAttributes.empty()) - return ("__DATA," + Section).str(); - return ("__DATA," + Section + "," + MachOAttributes).str(); - } - case llvm::Triple::ELF: - assert(Section.substr(0, 2) == "__" && - "expected the name to begin with __"); - return Section.substr(2).str(); - case llvm::Triple::COFF: - assert(Section.substr(0, 2) == "__" && - "expected the name to begin with __"); - return ("." + Section.substr(2) + "$B").str(); - } -} - -/// EmitImageInfo - Emit the image info marker used to encode some module -/// level information. -/// -/// See: <rdr://4810609&4810587&4810587> -/// struct IMAGE_INFO { -/// unsigned version; -/// unsigned flags; -/// }; -enum ImageInfoFlags { - eImageInfo_FixAndContinue = (1 << 0), // This flag is no longer set by clang. - eImageInfo_GarbageCollected = (1 << 1), - eImageInfo_GCOnly = (1 << 2), - eImageInfo_OptimizedByDyld = (1 << 3), // This flag is set by the dyld shared cache. - - // A flag indicating that the module has no instances of a @synthesize of a - // superclass variable. <rdar://problem/6803242> - eImageInfo_CorrectedSynthesize = (1 << 4), // This flag is no longer set by clang. - eImageInfo_ImageIsSimulated = (1 << 5), - eImageInfo_ClassProperties = (1 << 6) -}; - -void CGObjCCommonMac::EmitImageInfo() { - unsigned version = 0; // Version is unused? - std::string Section = - (ObjCABI == 1) - ? "__OBJC,__image_info,regular" - : GetSectionName("__objc_imageinfo", "regular,no_dead_strip"); - - // Generate module-level named metadata to convey this information to the - // linker and code-gen. - llvm::Module &Mod = CGM.getModule(); - - // Add the ObjC ABI version to the module flags. - Mod.addModuleFlag(llvm::Module::Error, "Objective-C Version", ObjCABI); - Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version", - version); - Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section", - llvm::MDString::get(VMContext, Section)); - - if (CGM.getLangOpts().getGC() == LangOptions::NonGC) { - // Non-GC overrides those files which specify GC. - Mod.addModuleFlag(llvm::Module::Override, - "Objective-C Garbage Collection", (uint32_t)0); - } else { - // Add the ObjC garbage collection value. - Mod.addModuleFlag(llvm::Module::Error, - "Objective-C Garbage Collection", - eImageInfo_GarbageCollected); - - if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) { - // Add the ObjC GC Only value. - Mod.addModuleFlag(llvm::Module::Error, "Objective-C GC Only", - eImageInfo_GCOnly); - - // Require that GC be specified and set to eImageInfo_GarbageCollected. - llvm::Metadata *Ops[2] = { - llvm::MDString::get(VMContext, "Objective-C Garbage Collection"), - llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - llvm::Type::getInt32Ty(VMContext), eImageInfo_GarbageCollected))}; - Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only", - llvm::MDNode::get(VMContext, Ops)); - } - } - - // Indicate whether we're compiling this to run on a simulator. - if (CGM.getTarget().getTriple().isSimulatorEnvironment()) - Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated", - eImageInfo_ImageIsSimulated); - - // Indicate whether we are generating class properties. - Mod.addModuleFlag(llvm::Module::Error, "Objective-C Class Properties", - eImageInfo_ClassProperties); -} - -// struct objc_module { -// unsigned long version; -// unsigned long size; -// const char *name; -// Symtab symtab; -// }; - -// FIXME: Get from somewhere -static const int ModuleVersion = 7; - -void CGObjCMac::EmitModuleInfo() { - uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy); - - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(ObjCTypes.ModuleTy); - values.addInt(ObjCTypes.LongTy, ModuleVersion); - values.addInt(ObjCTypes.LongTy, Size); - // This used to be the filename, now it is unused. <rdr://4327263> - values.add(GetClassName(StringRef(""))); - values.add(EmitModuleSymbols()); - CreateMetadataVar("OBJC_MODULES", values, - "__OBJC,__module_info,regular,no_dead_strip", - CGM.getPointerAlign(), true); -} - -llvm::Constant *CGObjCMac::EmitModuleSymbols() { - unsigned NumClasses = DefinedClasses.size(); - unsigned NumCategories = DefinedCategories.size(); - - // Return null if no symbols were defined. - if (!NumClasses && !NumCategories) - return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy); - - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(); - values.addInt(ObjCTypes.LongTy, 0); - values.addNullPointer(ObjCTypes.SelectorPtrTy); - values.addInt(ObjCTypes.ShortTy, NumClasses); - values.addInt(ObjCTypes.ShortTy, NumCategories); - - // The runtime expects exactly the list of defined classes followed - // by the list of defined categories, in a single array. - auto array = values.beginArray(ObjCTypes.Int8PtrTy); - for (unsigned i=0; i<NumClasses; i++) { - const ObjCInterfaceDecl *ID = ImplementedClasses[i]; - assert(ID); - if (ObjCImplementationDecl *IMP = ID->getImplementation()) - // We are implementing a weak imported interface. Give it external linkage - if (ID->isWeakImported() && !IMP->isWeakImported()) - DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage); - - array.addBitCast(DefinedClasses[i], ObjCTypes.Int8PtrTy); - } - for (unsigned i=0; i<NumCategories; i++) - array.addBitCast(DefinedCategories[i], ObjCTypes.Int8PtrTy); - - array.finishAndAddTo(values); - - llvm::GlobalVariable *GV = CreateMetadataVar( - "OBJC_SYMBOLS", values, "__OBJC,__symbols,regular,no_dead_strip", - CGM.getPointerAlign(), true); - return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy); -} - -llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF, - IdentifierInfo *II) { - LazySymbols.insert(II); - - llvm::GlobalVariable *&Entry = ClassReferences[II]; - - if (!Entry) { - llvm::Constant *Casted = - llvm::ConstantExpr::getBitCast(GetClassName(II->getName()), - ObjCTypes.ClassPtrTy); - Entry = CreateMetadataVar( - "OBJC_CLASS_REFERENCES_", Casted, - "__OBJC,__cls_refs,literal_pointers,no_dead_strip", - CGM.getPointerAlign(), true); - } - - return CGF.Builder.CreateAlignedLoad(Entry, CGF.getPointerAlign()); -} - -llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF, - const ObjCInterfaceDecl *ID) { - // If the class has the objc_runtime_visible attribute, we need to - // use the Objective-C runtime to get the class. - if (ID->hasAttr<ObjCRuntimeVisibleAttr>()) - return EmitClassRefViaRuntime(CGF, ID, ObjCTypes); - - IdentifierInfo *RuntimeName = - &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString()); - return EmitClassRefFromId(CGF, RuntimeName); -} - -llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) { - IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool"); - return EmitClassRefFromId(CGF, II); -} - -llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) { - return CGF.Builder.CreateLoad(EmitSelectorAddr(CGF, Sel)); -} - -Address CGObjCMac::EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel) { - CharUnits Align = CGF.getPointerAlign(); - - llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; - if (!Entry) { - llvm::Constant *Casted = - llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel), - ObjCTypes.SelectorPtrTy); - Entry = CreateMetadataVar( - "OBJC_SELECTOR_REFERENCES_", Casted, - "__OBJC,__message_refs,literal_pointers,no_dead_strip", Align, true); - Entry->setExternallyInitialized(true); - } - - return Address(Entry, Align); -} - -llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) { - llvm::GlobalVariable *&Entry = ClassNames[RuntimeName]; - if (!Entry) - Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName); - return getConstantGEP(VMContext, Entry, 0, 0); -} - -llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) { - llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator - I = MethodDefinitions.find(MD); - if (I != MethodDefinitions.end()) - return I->second; - - return nullptr; -} - -/// GetIvarLayoutName - Returns a unique constant for the given -/// ivar layout bitmap. -llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident, - const ObjCCommonTypesHelper &ObjCTypes) { - return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); -} - -void IvarLayoutBuilder::visitRecord(const RecordType *RT, - CharUnits offset) { - const RecordDecl *RD = RT->getDecl(); - - // If this is a union, remember that we had one, because it might mess - // up the ordering of layout entries. - if (RD->isUnion()) - IsDisordered = true; - - const ASTRecordLayout *recLayout = nullptr; - visitAggregate(RD->field_begin(), RD->field_end(), offset, - [&](const FieldDecl *field) -> CharUnits { - if (!recLayout) - recLayout = &CGM.getContext().getASTRecordLayout(RD); - auto offsetInBits = recLayout->getFieldOffset(field->getFieldIndex()); - return CGM.getContext().toCharUnitsFromBits(offsetInBits); - }); -} - -template <class Iterator, class GetOffsetFn> -void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end, - CharUnits aggregateOffset, - const GetOffsetFn &getOffset) { - for (; begin != end; ++begin) { - auto field = *begin; - - // Skip over bitfields. - if (field->isBitField()) { - continue; - } - - // Compute the offset of the field within the aggregate. - CharUnits fieldOffset = aggregateOffset + getOffset(field); - - visitField(field, fieldOffset); - } -} - -/// Collect layout information for the given fields into IvarsInfo. -void IvarLayoutBuilder::visitField(const FieldDecl *field, - CharUnits fieldOffset) { - QualType fieldType = field->getType(); - - // Drill down into arrays. - uint64_t numElts = 1; - if (auto arrayType = CGM.getContext().getAsIncompleteArrayType(fieldType)) { - numElts = 0; - fieldType = arrayType->getElementType(); - } - // Unlike incomplete arrays, constant arrays can be nested. - while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) { - numElts *= arrayType->getSize().getZExtValue(); - fieldType = arrayType->getElementType(); - } - - assert(!fieldType->isArrayType() && "ivar of non-constant array type?"); - - // If we ended up with a zero-sized array, we've done what we can do within - // the limits of this layout encoding. - if (numElts == 0) return; - - // Recurse if the base element type is a record type. - if (auto recType = fieldType->getAs<RecordType>()) { - size_t oldEnd = IvarsInfo.size(); - - visitRecord(recType, fieldOffset); - - // If we have an array, replicate the first entry's layout information. - auto numEltEntries = IvarsInfo.size() - oldEnd; - if (numElts != 1 && numEltEntries != 0) { - CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType); - for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) { - // Copy the last numEltEntries onto the end of the array, adjusting - // each for the element size. - for (size_t i = 0; i != numEltEntries; ++i) { - auto firstEntry = IvarsInfo[oldEnd + i]; - IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize, - firstEntry.SizeInWords)); - } - } - } - - return; - } - - // Classify the element type. - Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType); - - // If it matches what we're looking for, add an entry. - if ((ForStrongLayout && GCAttr == Qualifiers::Strong) - || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) { - assert(CGM.getContext().getTypeSizeInChars(fieldType) - == CGM.getPointerSize()); - IvarsInfo.push_back(IvarInfo(fieldOffset, numElts)); - } -} - -/// buildBitmap - This routine does the horsework of taking the offsets of -/// strong/weak references and creating a bitmap. The bitmap is also -/// returned in the given buffer, suitable for being passed to \c dump(). -llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC, - llvm::SmallVectorImpl<unsigned char> &buffer) { - // The bitmap is a series of skip/scan instructions, aligned to word - // boundaries. The skip is performed first. - const unsigned char MaxNibble = 0xF; - const unsigned char SkipMask = 0xF0, SkipShift = 4; - const unsigned char ScanMask = 0x0F, ScanShift = 0; - - assert(!IvarsInfo.empty() && "generating bitmap for no data"); - - // Sort the ivar info on byte position in case we encounterred a - // union nested in the ivar list. - if (IsDisordered) { - // This isn't a stable sort, but our algorithm should handle it fine. - llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end()); - } else { - assert(std::is_sorted(IvarsInfo.begin(), IvarsInfo.end())); - } - assert(IvarsInfo.back().Offset < InstanceEnd); - - assert(buffer.empty()); - - // Skip the next N words. - auto skip = [&](unsigned numWords) { - assert(numWords > 0); - - // Try to merge into the previous byte. Since scans happen second, we - // can't do this if it includes a scan. - if (!buffer.empty() && !(buffer.back() & ScanMask)) { - unsigned lastSkip = buffer.back() >> SkipShift; - if (lastSkip < MaxNibble) { - unsigned claimed = std::min(MaxNibble - lastSkip, numWords); - numWords -= claimed; - lastSkip += claimed; - buffer.back() = (lastSkip << SkipShift); - } - } - - while (numWords >= MaxNibble) { - buffer.push_back(MaxNibble << SkipShift); - numWords -= MaxNibble; - } - if (numWords) { - buffer.push_back(numWords << SkipShift); - } - }; - - // Scan the next N words. - auto scan = [&](unsigned numWords) { - assert(numWords > 0); - - // Try to merge into the previous byte. Since scans happen second, we can - // do this even if it includes a skip. - if (!buffer.empty()) { - unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift; - if (lastScan < MaxNibble) { - unsigned claimed = std::min(MaxNibble - lastScan, numWords); - numWords -= claimed; - lastScan += claimed; - buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift); - } - } - - while (numWords >= MaxNibble) { - buffer.push_back(MaxNibble << ScanShift); - numWords -= MaxNibble; - } - if (numWords) { - buffer.push_back(numWords << ScanShift); - } - }; - - // One past the end of the last scan. - unsigned endOfLastScanInWords = 0; - const CharUnits WordSize = CGM.getPointerSize(); - - // Consider all the scan requests. - for (auto &request : IvarsInfo) { - CharUnits beginOfScan = request.Offset - InstanceBegin; - - // Ignore scan requests that don't start at an even multiple of the - // word size. We can't encode them. - if ((beginOfScan % WordSize) != 0) continue; - - // Ignore scan requests that start before the instance start. - // This assumes that scans never span that boundary. The boundary - // isn't the true start of the ivars, because in the fragile-ARC case - // it's rounded up to word alignment, but the test above should leave - // us ignoring that possibility. - if (beginOfScan.isNegative()) { - assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin); - continue; - } - - unsigned beginOfScanInWords = beginOfScan / WordSize; - unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords; - - // If the scan starts some number of words after the last one ended, - // skip forward. - if (beginOfScanInWords > endOfLastScanInWords) { - skip(beginOfScanInWords - endOfLastScanInWords); - - // Otherwise, start scanning where the last left off. - } else { - beginOfScanInWords = endOfLastScanInWords; - - // If that leaves us with nothing to scan, ignore this request. - if (beginOfScanInWords >= endOfScanInWords) continue; - } - - // Scan to the end of the request. - assert(beginOfScanInWords < endOfScanInWords); - scan(endOfScanInWords - beginOfScanInWords); - endOfLastScanInWords = endOfScanInWords; - } - - if (buffer.empty()) - return llvm::ConstantPointerNull::get(CGM.Int8PtrTy); - - // For GC layouts, emit a skip to the end of the allocation so that we - // have precise information about the entire thing. This isn't useful - // or necessary for the ARC-style layout strings. - if (CGM.getLangOpts().getGC() != LangOptions::NonGC) { - unsigned lastOffsetInWords = - (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize; - if (lastOffsetInWords > endOfLastScanInWords) { - skip(lastOffsetInWords - endOfLastScanInWords); - } - } - - // Null terminate the string. - buffer.push_back(0); - - auto *Entry = CGObjC.CreateCStringLiteral( - reinterpret_cast<char *>(buffer.data()), ObjCLabelType::ClassName); - return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0); -} - -/// BuildIvarLayout - Builds ivar layout bitmap for the class -/// implementation for the __strong or __weak case. -/// The layout map displays which words in ivar list must be skipped -/// and which must be scanned by GC (see below). String is built of bytes. -/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count -/// of words to skip and right nibble is count of words to scan. So, each -/// nibble represents up to 15 workds to skip or scan. Skipping the rest is -/// represented by a 0x00 byte which also ends the string. -/// 1. when ForStrongLayout is true, following ivars are scanned: -/// - id, Class -/// - object * -/// - __strong anything -/// -/// 2. When ForStrongLayout is false, following ivars are scanned: -/// - __weak anything -/// -llvm::Constant * -CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD, - CharUnits beginOffset, CharUnits endOffset, - bool ForStrongLayout, bool HasMRCWeakIvars) { - // If this is MRC, and we're either building a strong layout or there - // are no weak ivars, bail out early. - llvm::Type *PtrTy = CGM.Int8PtrTy; - if (CGM.getLangOpts().getGC() == LangOptions::NonGC && - !CGM.getLangOpts().ObjCAutoRefCount && - (ForStrongLayout || !HasMRCWeakIvars)) - return llvm::Constant::getNullValue(PtrTy); - - const ObjCInterfaceDecl *OI = OMD->getClassInterface(); - SmallVector<const ObjCIvarDecl*, 32> ivars; - - // GC layout strings include the complete object layout, possibly - // inaccurately in the non-fragile ABI; the runtime knows how to fix this - // up. - // - // ARC layout strings only include the class's ivars. In non-fragile - // runtimes, that means starting at InstanceStart, rounded up to word - // alignment. In fragile runtimes, there's no InstanceStart, so it means - // starting at the offset of the first ivar, rounded up to word alignment. - // - // MRC weak layout strings follow the ARC style. - CharUnits baseOffset; - if (CGM.getLangOpts().getGC() == LangOptions::NonGC) { - for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin(); - IVD; IVD = IVD->getNextIvar()) - ivars.push_back(IVD); - - if (isNonFragileABI()) { - baseOffset = beginOffset; // InstanceStart - } else if (!ivars.empty()) { - baseOffset = - CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0])); - } else { - baseOffset = CharUnits::Zero(); - } - - baseOffset = baseOffset.alignTo(CGM.getPointerAlign()); - } - else { - CGM.getContext().DeepCollectObjCIvars(OI, true, ivars); - - baseOffset = CharUnits::Zero(); - } - - if (ivars.empty()) - return llvm::Constant::getNullValue(PtrTy); - - IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout); - - builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(), - [&](const ObjCIvarDecl *ivar) -> CharUnits { - return CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivar)); - }); - - if (!builder.hasBitmapData()) - return llvm::Constant::getNullValue(PtrTy); - - llvm::SmallVector<unsigned char, 4> buffer; - llvm::Constant *C = builder.buildBitmap(*this, buffer); - - if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) { - printf("\n%s ivar layout for class '%s': ", - ForStrongLayout ? "strong" : "weak", - OMD->getClassInterface()->getName().str().c_str()); - builder.dump(buffer); - } - return C; -} - -llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) { - llvm::GlobalVariable *&Entry = MethodVarNames[Sel]; - // FIXME: Avoid std::string in "Sel.getAsString()" - if (!Entry) - Entry = CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName); - return getConstantGEP(VMContext, Entry, 0, 0); -} - -// FIXME: Merge into a single cstring creation function. -llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) { - return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID)); -} - -llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) { - std::string TypeStr; - CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field); - - llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr]; - if (!Entry) - Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType); - return getConstantGEP(VMContext, Entry, 0, 0); -} - -llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D, - bool Extended) { - std::string TypeStr = - CGM.getContext().getObjCEncodingForMethodDecl(D, Extended); - - llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr]; - if (!Entry) - Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType); - return getConstantGEP(VMContext, Entry, 0, 0); -} - -// FIXME: Merge into a single cstring creation function. -llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) { - llvm::GlobalVariable *&Entry = PropertyNames[Ident]; - if (!Entry) - Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName); - return getConstantGEP(VMContext, Entry, 0, 0); -} - -// FIXME: Merge into a single cstring creation function. -// FIXME: This Decl should be more precise. -llvm::Constant * -CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD, - const Decl *Container) { - std::string TypeStr = - CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container); - return GetPropertyName(&CGM.getContext().Idents.get(TypeStr)); -} - -void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D, - const ObjCContainerDecl *CD, - SmallVectorImpl<char> &Name) { - llvm::raw_svector_ostream OS(Name); - assert (CD && "Missing container decl in GetNameForMethod"); - OS << '\01' << (D->isInstanceMethod() ? '-' : '+') - << '[' << CD->getName(); - if (const ObjCCategoryImplDecl *CID = - dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext())) - OS << '(' << *CID << ')'; - OS << ' ' << D->getSelector().getAsString() << ']'; -} - -void CGObjCMac::FinishModule() { - EmitModuleInfo(); - - // Emit the dummy bodies for any protocols which were referenced but - // never defined. - for (auto &entry : Protocols) { - llvm::GlobalVariable *global = entry.second; - if (global->hasInitializer()) - continue; - - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(ObjCTypes.ProtocolTy); - values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy); - values.add(GetClassName(entry.first->getName())); - values.addNullPointer(ObjCTypes.ProtocolListPtrTy); - values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy); - values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy); - values.finishAndSetAsInitializer(global); - CGM.addCompilerUsedGlobal(global); - } - - // Add assembler directives to add lazy undefined symbol references - // for classes which are referenced but not defined. This is - // important for correct linker interaction. - // - // FIXME: It would be nice if we had an LLVM construct for this. - if ((!LazySymbols.empty() || !DefinedSymbols.empty()) && - CGM.getTriple().isOSBinFormatMachO()) { - SmallString<256> Asm; - Asm += CGM.getModule().getModuleInlineAsm(); - if (!Asm.empty() && Asm.back() != '\n') - Asm += '\n'; - - llvm::raw_svector_ostream OS(Asm); - for (const auto *Sym : DefinedSymbols) - OS << "\t.objc_class_name_" << Sym->getName() << "=0\n" - << "\t.globl .objc_class_name_" << Sym->getName() << "\n"; - for (const auto *Sym : LazySymbols) - OS << "\t.lazy_reference .objc_class_name_" << Sym->getName() << "\n"; - for (const auto &Category : DefinedCategoryNames) - OS << "\t.objc_category_name_" << Category << "=0\n" - << "\t.globl .objc_category_name_" << Category << "\n"; - - CGM.getModule().setModuleInlineAsm(OS.str()); - } -} - -CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm) - : CGObjCCommonMac(cgm), ObjCTypes(cgm), ObjCEmptyCacheVar(nullptr), - ObjCEmptyVtableVar(nullptr) { - ObjCABI = 2; -} - -/* *** */ - -ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm) - : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(nullptr) -{ - CodeGen::CodeGenTypes &Types = CGM.getTypes(); - ASTContext &Ctx = CGM.getContext(); - - ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy)); - IntTy = CGM.IntTy; - LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy)); - Int8PtrTy = CGM.Int8PtrTy; - Int8PtrPtrTy = CGM.Int8PtrPtrTy; - - // arm64 targets use "int" ivar offset variables. All others, - // including OS X x86_64 and Windows x86_64, use "long" ivar offsets. - if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64) - IvarOffsetVarTy = IntTy; - else - IvarOffsetVarTy = LongTy; - - ObjectPtrTy = - cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType())); - PtrObjectPtrTy = - llvm::PointerType::getUnqual(ObjectPtrTy); - SelectorPtrTy = - cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType())); - - // I'm not sure I like this. The implicit coordination is a bit - // gross. We should solve this in a reasonable fashion because this - // is a pretty common task (match some runtime data structure with - // an LLVM data structure). - - // FIXME: This is leaked. - // FIXME: Merge with rewriter code? - - // struct _objc_super { - // id self; - // Class cls; - // } - RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct, - Ctx.getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Ctx.Idents.get("_objc_super")); - RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), - nullptr, Ctx.getObjCIdType(), nullptr, nullptr, - false, ICIS_NoInit)); - RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), - nullptr, Ctx.getObjCClassType(), nullptr, - nullptr, false, ICIS_NoInit)); - RD->completeDefinition(); - - SuperCTy = Ctx.getTagDeclType(RD); - SuperPtrCTy = Ctx.getPointerType(SuperCTy); - - SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy)); - SuperPtrTy = llvm::PointerType::getUnqual(SuperTy); - - // struct _prop_t { - // char *name; - // char *attributes; - // } - PropertyTy = llvm::StructType::create("struct._prop_t", Int8PtrTy, Int8PtrTy); - - // struct _prop_list_t { - // uint32_t entsize; // sizeof(struct _prop_t) - // uint32_t count_of_properties; - // struct _prop_t prop_list[count_of_properties]; - // } - PropertyListTy = llvm::StructType::create( - "struct._prop_list_t", IntTy, IntTy, llvm::ArrayType::get(PropertyTy, 0)); - // struct _prop_list_t * - PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy); - - // struct _objc_method { - // SEL _cmd; - // char *method_type; - // char *_imp; - // } - MethodTy = llvm::StructType::create("struct._objc_method", SelectorPtrTy, - Int8PtrTy, Int8PtrTy); - - // struct _objc_cache * - CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache"); - CachePtrTy = llvm::PointerType::getUnqual(CacheTy); -} - -ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) - : ObjCCommonTypesHelper(cgm) { - // struct _objc_method_description { - // SEL name; - // char *types; - // } - MethodDescriptionTy = llvm::StructType::create( - "struct._objc_method_description", SelectorPtrTy, Int8PtrTy); - - // struct _objc_method_description_list { - // int count; - // struct _objc_method_description[1]; - // } - MethodDescriptionListTy = - llvm::StructType::create("struct._objc_method_description_list", IntTy, - llvm::ArrayType::get(MethodDescriptionTy, 0)); - - // struct _objc_method_description_list * - MethodDescriptionListPtrTy = - llvm::PointerType::getUnqual(MethodDescriptionListTy); - - // Protocol description structures - - // struct _objc_protocol_extension { - // uint32_t size; // sizeof(struct _objc_protocol_extension) - // struct _objc_method_description_list *optional_instance_methods; - // struct _objc_method_description_list *optional_class_methods; - // struct _objc_property_list *instance_properties; - // const char ** extendedMethodTypes; - // struct _objc_property_list *class_properties; - // } - ProtocolExtensionTy = llvm::StructType::create( - "struct._objc_protocol_extension", IntTy, MethodDescriptionListPtrTy, - MethodDescriptionListPtrTy, PropertyListPtrTy, Int8PtrPtrTy, - PropertyListPtrTy); - - // struct _objc_protocol_extension * - ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy); - - // Handle recursive construction of Protocol and ProtocolList types - - ProtocolTy = - llvm::StructType::create(VMContext, "struct._objc_protocol"); - - ProtocolListTy = - llvm::StructType::create(VMContext, "struct._objc_protocol_list"); - ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy), LongTy, - llvm::ArrayType::get(ProtocolTy, 0)); - - // struct _objc_protocol { - // struct _objc_protocol_extension *isa; - // char *protocol_name; - // struct _objc_protocol **_objc_protocol_list; - // struct _objc_method_description_list *instance_methods; - // struct _objc_method_description_list *class_methods; - // } - ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy, - llvm::PointerType::getUnqual(ProtocolListTy), - MethodDescriptionListPtrTy, MethodDescriptionListPtrTy); - - // struct _objc_protocol_list * - ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy); - - ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy); - - // Class description structures - - // struct _objc_ivar { - // char *ivar_name; - // char *ivar_type; - // int ivar_offset; - // } - IvarTy = llvm::StructType::create("struct._objc_ivar", Int8PtrTy, Int8PtrTy, - IntTy); - - // struct _objc_ivar_list * - IvarListTy = - llvm::StructType::create(VMContext, "struct._objc_ivar_list"); - IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy); - - // struct _objc_method_list * - MethodListTy = - llvm::StructType::create(VMContext, "struct._objc_method_list"); - MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy); - - // struct _objc_class_extension * - ClassExtensionTy = llvm::StructType::create( - "struct._objc_class_extension", IntTy, Int8PtrTy, PropertyListPtrTy); - ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy); - - ClassTy = llvm::StructType::create(VMContext, "struct._objc_class"); - - // struct _objc_class { - // Class isa; - // Class super_class; - // char *name; - // long version; - // long info; - // long instance_size; - // struct _objc_ivar_list *ivars; - // struct _objc_method_list *methods; - // struct _objc_cache *cache; - // struct _objc_protocol_list *protocols; - // char *ivar_layout; - // struct _objc_class_ext *ext; - // }; - ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy), - llvm::PointerType::getUnqual(ClassTy), Int8PtrTy, LongTy, - LongTy, LongTy, IvarListPtrTy, MethodListPtrTy, CachePtrTy, - ProtocolListPtrTy, Int8PtrTy, ClassExtensionPtrTy); - - ClassPtrTy = llvm::PointerType::getUnqual(ClassTy); - - // struct _objc_category { - // char *category_name; - // char *class_name; - // struct _objc_method_list *instance_method; - // struct _objc_method_list *class_method; - // struct _objc_protocol_list *protocols; - // uint32_t size; // sizeof(struct _objc_category) - // struct _objc_property_list *instance_properties;// category's @property - // struct _objc_property_list *class_properties; - // } - CategoryTy = llvm::StructType::create( - "struct._objc_category", Int8PtrTy, Int8PtrTy, MethodListPtrTy, - MethodListPtrTy, ProtocolListPtrTy, IntTy, PropertyListPtrTy, - PropertyListPtrTy); - - // Global metadata structures - - // struct _objc_symtab { - // long sel_ref_cnt; - // SEL *refs; - // short cls_def_cnt; - // short cat_def_cnt; - // char *defs[cls_def_cnt + cat_def_cnt]; - // } - SymtabTy = llvm::StructType::create("struct._objc_symtab", LongTy, - SelectorPtrTy, ShortTy, ShortTy, - llvm::ArrayType::get(Int8PtrTy, 0)); - SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy); - - // struct _objc_module { - // long version; - // long size; // sizeof(struct _objc_module) - // char *name; - // struct _objc_symtab* symtab; - // } - ModuleTy = llvm::StructType::create("struct._objc_module", LongTy, LongTy, - Int8PtrTy, SymtabPtrTy); - - // FIXME: This is the size of the setjmp buffer and should be target - // specific. 18 is what's used on 32-bit X86. - uint64_t SetJmpBufferSize = 18; - - // Exceptions - llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4); - - ExceptionDataTy = llvm::StructType::create( - "struct._objc_exception_data", - llvm::ArrayType::get(CGM.Int32Ty, SetJmpBufferSize), StackPtrTy); -} - -ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm) - : ObjCCommonTypesHelper(cgm) { - // struct _method_list_t { - // uint32_t entsize; // sizeof(struct _objc_method) - // uint32_t method_count; - // struct _objc_method method_list[method_count]; - // } - MethodListnfABITy = - llvm::StructType::create("struct.__method_list_t", IntTy, IntTy, - llvm::ArrayType::get(MethodTy, 0)); - // struct method_list_t * - MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy); - - // struct _protocol_t { - // id isa; // NULL - // const char * const protocol_name; - // const struct _protocol_list_t * protocol_list; // super protocols - // const struct method_list_t * const instance_methods; - // const struct method_list_t * const class_methods; - // const struct method_list_t *optionalInstanceMethods; - // const struct method_list_t *optionalClassMethods; - // const struct _prop_list_t * properties; - // const uint32_t size; // sizeof(struct _protocol_t) - // const uint32_t flags; // = 0 - // const char ** extendedMethodTypes; - // const char *demangledName; - // const struct _prop_list_t * class_properties; - // } - - // Holder for struct _protocol_list_t * - ProtocolListnfABITy = - llvm::StructType::create(VMContext, "struct._objc_protocol_list"); - - ProtocolnfABITy = llvm::StructType::create( - "struct._protocol_t", ObjectPtrTy, Int8PtrTy, - llvm::PointerType::getUnqual(ProtocolListnfABITy), MethodListnfABIPtrTy, - MethodListnfABIPtrTy, MethodListnfABIPtrTy, MethodListnfABIPtrTy, - PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy, Int8PtrTy, - PropertyListPtrTy); - - // struct _protocol_t* - ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy); - - // struct _protocol_list_t { - // long protocol_count; // Note, this is 32/64 bit - // struct _protocol_t *[protocol_count]; - // } - ProtocolListnfABITy->setBody(LongTy, - llvm::ArrayType::get(ProtocolnfABIPtrTy, 0)); - - // struct _objc_protocol_list* - ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy); - - // struct _ivar_t { - // unsigned [long] int *offset; // pointer to ivar offset location - // char *name; - // char *type; - // uint32_t alignment; - // uint32_t size; - // } - IvarnfABITy = llvm::StructType::create( - "struct._ivar_t", llvm::PointerType::getUnqual(IvarOffsetVarTy), - Int8PtrTy, Int8PtrTy, IntTy, IntTy); - - // struct _ivar_list_t { - // uint32 entsize; // sizeof(struct _ivar_t) - // uint32 count; - // struct _iver_t list[count]; - // } - IvarListnfABITy = - llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy, - llvm::ArrayType::get(IvarnfABITy, 0)); - - IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy); - - // struct _class_ro_t { - // uint32_t const flags; - // uint32_t const instanceStart; - // uint32_t const instanceSize; - // uint32_t const reserved; // only when building for 64bit targets - // const uint8_t * const ivarLayout; - // const char *const name; - // const struct _method_list_t * const baseMethods; - // const struct _objc_protocol_list *const baseProtocols; - // const struct _ivar_list_t *const ivars; - // const uint8_t * const weakIvarLayout; - // const struct _prop_list_t * const properties; - // } - - // FIXME. Add 'reserved' field in 64bit abi mode! - ClassRonfABITy = llvm::StructType::create( - "struct._class_ro_t", IntTy, IntTy, IntTy, Int8PtrTy, Int8PtrTy, - MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, IvarListnfABIPtrTy, - Int8PtrTy, PropertyListPtrTy); - - // ImpnfABITy - LLVM for id (*)(id, SEL, ...) - llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; - ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false) - ->getPointerTo(); - - // struct _class_t { - // struct _class_t *isa; - // struct _class_t * const superclass; - // void *cache; - // IMP *vtable; - // struct class_ro_t *ro; - // } - - ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t"); - ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy), - llvm::PointerType::getUnqual(ClassnfABITy), CachePtrTy, - llvm::PointerType::getUnqual(ImpnfABITy), - llvm::PointerType::getUnqual(ClassRonfABITy)); - - // LLVM for struct _class_t * - ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy); - - // struct _category_t { - // const char * const name; - // struct _class_t *const cls; - // const struct _method_list_t * const instance_methods; - // const struct _method_list_t * const class_methods; - // const struct _protocol_list_t * const protocols; - // const struct _prop_list_t * const properties; - // const struct _prop_list_t * const class_properties; - // const uint32_t size; - // } - CategorynfABITy = llvm::StructType::create( - "struct._category_t", Int8PtrTy, ClassnfABIPtrTy, MethodListnfABIPtrTy, - MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, PropertyListPtrTy, - PropertyListPtrTy, IntTy); - - // New types for nonfragile abi messaging. - CodeGen::CodeGenTypes &Types = CGM.getTypes(); - ASTContext &Ctx = CGM.getContext(); - - // MessageRefTy - LLVM for: - // struct _message_ref_t { - // IMP messenger; - // SEL name; - // }; - - // First the clang type for struct _message_ref_t - RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct, - Ctx.getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Ctx.Idents.get("_message_ref_t")); - RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), - nullptr, Ctx.VoidPtrTy, nullptr, nullptr, false, - ICIS_NoInit)); - RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), - nullptr, Ctx.getObjCSelType(), nullptr, nullptr, - false, ICIS_NoInit)); - RD->completeDefinition(); - - MessageRefCTy = Ctx.getTagDeclType(RD); - MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy); - MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy)); - - // MessageRefPtrTy - LLVM for struct _message_ref_t* - MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy); - - // SuperMessageRefTy - LLVM for: - // struct _super_message_ref_t { - // SUPER_IMP messenger; - // SEL name; - // }; - SuperMessageRefTy = llvm::StructType::create("struct._super_message_ref_t", - ImpnfABITy, SelectorPtrTy); - - // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t* - SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy); - - - // struct objc_typeinfo { - // const void** vtable; // objc_ehtype_vtable + 2 - // const char* name; // c++ typeinfo string - // Class cls; - // }; - EHTypeTy = llvm::StructType::create("struct._objc_typeinfo", - llvm::PointerType::getUnqual(Int8PtrTy), - Int8PtrTy, ClassnfABIPtrTy); - EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy); -} - -llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() { - FinishNonFragileABIModule(); - - return nullptr; -} - -void CGObjCNonFragileABIMac::AddModuleClassList( - ArrayRef<llvm::GlobalValue *> Container, StringRef SymbolName, - StringRef SectionName) { - unsigned NumClasses = Container.size(); - - if (!NumClasses) - return; - - SmallVector<llvm::Constant*, 8> Symbols(NumClasses); - for (unsigned i=0; i<NumClasses; i++) - Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i], - ObjCTypes.Int8PtrTy); - llvm::Constant *Init = - llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy, - Symbols.size()), - Symbols); - - llvm::GlobalVariable *GV = - new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, - llvm::GlobalValue::PrivateLinkage, - Init, - SymbolName); - GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType())); - GV->setSection(SectionName); - CGM.addCompilerUsedGlobal(GV); -} - -void CGObjCNonFragileABIMac::FinishNonFragileABIModule() { - // nonfragile abi has no module definition. - - // Build list of all implemented class addresses in array - // L_OBJC_LABEL_CLASS_$. - - for (unsigned i=0, NumClasses=ImplementedClasses.size(); i<NumClasses; i++) { - const ObjCInterfaceDecl *ID = ImplementedClasses[i]; - assert(ID); - if (ObjCImplementationDecl *IMP = ID->getImplementation()) - // We are implementing a weak imported interface. Give it external linkage - if (ID->isWeakImported() && !IMP->isWeakImported()) { - DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage); - DefinedMetaClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage); - } - } - - AddModuleClassList(DefinedClasses, "OBJC_LABEL_CLASS_$", - GetSectionName("__objc_classlist", - "regular,no_dead_strip")); - - AddModuleClassList(DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$", - GetSectionName("__objc_nlclslist", - "regular,no_dead_strip")); - - // Build list of all implemented category addresses in array - // L_OBJC_LABEL_CATEGORY_$. - AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$", - GetSectionName("__objc_catlist", - "regular,no_dead_strip")); - AddModuleClassList(DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$", - GetSectionName("__objc_nlcatlist", - "regular,no_dead_strip")); - - EmitImageInfo(); -} - -/// isVTableDispatchedSelector - Returns true if SEL is not in the list of -/// VTableDispatchMethods; false otherwise. What this means is that -/// except for the 19 selectors in the list, we generate 32bit-style -/// message dispatch call for all the rest. -bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) { - // At various points we've experimented with using vtable-based - // dispatch for all methods. - switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) { - case CodeGenOptions::Legacy: - return false; - case CodeGenOptions::NonLegacy: - return true; - case CodeGenOptions::Mixed: - break; - } - - // If so, see whether this selector is in the white-list of things which must - // use the new dispatch convention. We lazily build a dense set for this. - if (VTableDispatchMethods.empty()) { - VTableDispatchMethods.insert(GetNullarySelector("alloc")); - VTableDispatchMethods.insert(GetNullarySelector("class")); - VTableDispatchMethods.insert(GetNullarySelector("self")); - VTableDispatchMethods.insert(GetNullarySelector("isFlipped")); - VTableDispatchMethods.insert(GetNullarySelector("length")); - VTableDispatchMethods.insert(GetNullarySelector("count")); - - // These are vtable-based if GC is disabled. - // Optimistically use vtable dispatch for hybrid compiles. - if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) { - VTableDispatchMethods.insert(GetNullarySelector("retain")); - VTableDispatchMethods.insert(GetNullarySelector("release")); - VTableDispatchMethods.insert(GetNullarySelector("autorelease")); - } - - VTableDispatchMethods.insert(GetUnarySelector("allocWithZone")); - VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass")); - VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector")); - VTableDispatchMethods.insert(GetUnarySelector("objectForKey")); - VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex")); - VTableDispatchMethods.insert(GetUnarySelector("isEqualToString")); - VTableDispatchMethods.insert(GetUnarySelector("isEqual")); - - // These are vtable-based if GC is enabled. - // Optimistically use vtable dispatch for hybrid compiles. - if (CGM.getLangOpts().getGC() != LangOptions::NonGC) { - VTableDispatchMethods.insert(GetNullarySelector("hash")); - VTableDispatchMethods.insert(GetUnarySelector("addObject")); - - // "countByEnumeratingWithState:objects:count" - IdentifierInfo *KeyIdents[] = { - &CGM.getContext().Idents.get("countByEnumeratingWithState"), - &CGM.getContext().Idents.get("objects"), - &CGM.getContext().Idents.get("count") - }; - VTableDispatchMethods.insert( - CGM.getContext().Selectors.getSelector(3, KeyIdents)); - } - } - - return VTableDispatchMethods.count(Sel); -} - -/// BuildClassRoTInitializer - generate meta-data for: -/// struct _class_ro_t { -/// uint32_t const flags; -/// uint32_t const instanceStart; -/// uint32_t const instanceSize; -/// uint32_t const reserved; // only when building for 64bit targets -/// const uint8_t * const ivarLayout; -/// const char *const name; -/// const struct _method_list_t * const baseMethods; -/// const struct _protocol_list_t *const baseProtocols; -/// const struct _ivar_list_t *const ivars; -/// const uint8_t * const weakIvarLayout; -/// const struct _prop_list_t * const properties; -/// } -/// -llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( - unsigned flags, - unsigned InstanceStart, - unsigned InstanceSize, - const ObjCImplementationDecl *ID) { - std::string ClassName = ID->getObjCRuntimeNameAsString(); - - CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart); - CharUnits endInstance = CharUnits::fromQuantity(InstanceSize); - - bool hasMRCWeak = false; - if (CGM.getLangOpts().ObjCAutoRefCount) - flags |= NonFragileABI_Class_CompiledByARC; - else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID))) - flags |= NonFragileABI_Class_HasMRCWeakIvars; - - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(ObjCTypes.ClassRonfABITy); - - values.addInt(ObjCTypes.IntTy, flags); - values.addInt(ObjCTypes.IntTy, InstanceStart); - values.addInt(ObjCTypes.IntTy, InstanceSize); - values.add((flags & NonFragileABI_Class_Meta) - ? GetIvarLayoutName(nullptr, ObjCTypes) - : BuildStrongIvarLayout(ID, beginInstance, endInstance)); - values.add(GetClassName(ID->getObjCRuntimeNameAsString())); - - // const struct _method_list_t * const baseMethods; - SmallVector<const ObjCMethodDecl*, 16> methods; - if (flags & NonFragileABI_Class_Meta) { - for (const auto *MD : ID->class_methods()) - methods.push_back(MD); - } else { - for (const auto *MD : ID->instance_methods()) - methods.push_back(MD); - - for (const auto *PID : ID->property_impls()) { - if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){ - ObjCPropertyDecl *PD = PID->getPropertyDecl(); - - if (auto MD = PD->getGetterMethodDecl()) - if (GetMethodDefinition(MD)) - methods.push_back(MD); - if (auto MD = PD->getSetterMethodDecl()) - if (GetMethodDefinition(MD)) - methods.push_back(MD); - } - } - } - - values.add(emitMethodList(ID->getObjCRuntimeNameAsString(), - (flags & NonFragileABI_Class_Meta) - ? MethodListType::ClassMethods - : MethodListType::InstanceMethods, - methods)); - - const ObjCInterfaceDecl *OID = ID->getClassInterface(); - assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer"); - values.add(EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_" - + OID->getObjCRuntimeNameAsString(), - OID->all_referenced_protocol_begin(), - OID->all_referenced_protocol_end())); - - if (flags & NonFragileABI_Class_Meta) { - values.addNullPointer(ObjCTypes.IvarListnfABIPtrTy); - values.add(GetIvarLayoutName(nullptr, ObjCTypes)); - values.add(EmitPropertyList( - "\01l_OBJC_$_CLASS_PROP_LIST_" + ID->getObjCRuntimeNameAsString(), - ID, ID->getClassInterface(), ObjCTypes, true)); - } else { - values.add(EmitIvarList(ID)); - values.add(BuildWeakIvarLayout(ID, beginInstance, endInstance, hasMRCWeak)); - values.add(EmitPropertyList( - "\01l_OBJC_$_PROP_LIST_" + ID->getObjCRuntimeNameAsString(), - ID, ID->getClassInterface(), ObjCTypes, false)); - } - - llvm::SmallString<64> roLabel; - llvm::raw_svector_ostream(roLabel) - << ((flags & NonFragileABI_Class_Meta) ? "\01l_OBJC_METACLASS_RO_$_" - : "\01l_OBJC_CLASS_RO_$_") - << ClassName; - - llvm::GlobalVariable *CLASS_RO_GV = - values.finishAndCreateGlobal(roLabel, CGM.getPointerAlign(), - /*constant*/ false, - llvm::GlobalValue::PrivateLinkage); - if (CGM.getTriple().isOSBinFormatMachO()) - CLASS_RO_GV->setSection("__DATA, __objc_const"); - return CLASS_RO_GV; -} - -/// Build the metaclass object for a class. -/// -/// struct _class_t { -/// struct _class_t *isa; -/// struct _class_t * const superclass; -/// void *cache; -/// IMP *vtable; -/// struct class_ro_t *ro; -/// } -/// -llvm::GlobalVariable * -CGObjCNonFragileABIMac::BuildClassObject(const ObjCInterfaceDecl *CI, - bool isMetaclass, - llvm::Constant *IsAGV, - llvm::Constant *SuperClassGV, - llvm::Constant *ClassRoGV, - bool HiddenVisibility) { - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(ObjCTypes.ClassnfABITy); - values.add(IsAGV); - if (SuperClassGV) { - values.add(SuperClassGV); - } else { - values.addNullPointer(ObjCTypes.ClassnfABIPtrTy); - } - values.add(ObjCEmptyCacheVar); - values.add(ObjCEmptyVtableVar); - values.add(ClassRoGV); - - llvm::GlobalVariable *GV = - cast<llvm::GlobalVariable>(GetClassGlobal(CI, isMetaclass, ForDefinition)); - values.finishAndSetAsInitializer(GV); - - if (CGM.getTriple().isOSBinFormatMachO()) - GV->setSection("__DATA, __objc_data"); - GV->setAlignment( - CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy)); - if (!CGM.getTriple().isOSBinFormatCOFF()) - if (HiddenVisibility) - GV->setVisibility(llvm::GlobalValue::HiddenVisibility); - return GV; -} - -bool -CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const { - return OD->getClassMethod(GetNullarySelector("load")) != nullptr; -} - -void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID, - uint32_t &InstanceStart, - uint32_t &InstanceSize) { - const ASTRecordLayout &RL = - CGM.getContext().getASTObjCImplementationLayout(OID); - - // InstanceSize is really instance end. - InstanceSize = RL.getDataSize().getQuantity(); - - // If there are no fields, the start is the same as the end. - if (!RL.getFieldCount()) - InstanceStart = InstanceSize; - else - InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth(); -} - -static llvm::GlobalValue::DLLStorageClassTypes getStorage(CodeGenModule &CGM, - StringRef Name) { - IdentifierInfo &II = CGM.getContext().Idents.get(Name); - TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl(); - DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl); - - const VarDecl *VD = nullptr; - for (const auto &Result : DC->lookup(&II)) - if ((VD = dyn_cast<VarDecl>(Result))) - break; - - if (!VD) - return llvm::GlobalValue::DLLImportStorageClass; - if (VD->hasAttr<DLLExportAttr>()) - return llvm::GlobalValue::DLLExportStorageClass; - if (VD->hasAttr<DLLImportAttr>()) - return llvm::GlobalValue::DLLImportStorageClass; - return llvm::GlobalValue::DefaultStorageClass; -} - -void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { - if (!ObjCEmptyCacheVar) { - ObjCEmptyCacheVar = - new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CacheTy, false, - llvm::GlobalValue::ExternalLinkage, nullptr, - "_objc_empty_cache"); - if (CGM.getTriple().isOSBinFormatCOFF()) - ObjCEmptyCacheVar->setDLLStorageClass(getStorage(CGM, "_objc_empty_cache")); - - // Only OS X with deployment version <10.9 use the empty vtable symbol - const llvm::Triple &Triple = CGM.getTarget().getTriple(); - if (Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 9)) - ObjCEmptyVtableVar = - new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ImpnfABITy, false, - llvm::GlobalValue::ExternalLinkage, nullptr, - "_objc_empty_vtable"); - else - ObjCEmptyVtableVar = - llvm::ConstantPointerNull::get(ObjCTypes.ImpnfABITy->getPointerTo()); - } - - // FIXME: Is this correct (that meta class size is never computed)? - uint32_t InstanceStart = - CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy); - uint32_t InstanceSize = InstanceStart; - uint32_t flags = NonFragileABI_Class_Meta; - - llvm::Constant *SuperClassGV, *IsAGV; - - const auto *CI = ID->getClassInterface(); - assert(CI && "CGObjCNonFragileABIMac::GenerateClass - class is 0"); - - // Build the flags for the metaclass. - bool classIsHidden = (CGM.getTriple().isOSBinFormatCOFF()) - ? !CI->hasAttr<DLLExportAttr>() - : CI->getVisibility() == HiddenVisibility; - if (classIsHidden) - flags |= NonFragileABI_Class_Hidden; - - // FIXME: why is this flag set on the metaclass? - // ObjC metaclasses have no fields and don't really get constructed. - if (ID->hasNonZeroConstructors() || ID->hasDestructors()) { - flags |= NonFragileABI_Class_HasCXXStructors; - if (!ID->hasNonZeroConstructors()) - flags |= NonFragileABI_Class_HasCXXDestructorOnly; - } - - if (!CI->getSuperClass()) { - // class is root - flags |= NonFragileABI_Class_Root; - - SuperClassGV = GetClassGlobal(CI, /*metaclass*/ false, NotForDefinition); - IsAGV = GetClassGlobal(CI, /*metaclass*/ true, NotForDefinition); - } else { - // Has a root. Current class is not a root. - const ObjCInterfaceDecl *Root = ID->getClassInterface(); - while (const ObjCInterfaceDecl *Super = Root->getSuperClass()) - Root = Super; - - const auto *Super = CI->getSuperClass(); - IsAGV = GetClassGlobal(Root, /*metaclass*/ true, NotForDefinition); - SuperClassGV = GetClassGlobal(Super, /*metaclass*/ true, NotForDefinition); - } - - llvm::GlobalVariable *CLASS_RO_GV = - BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID); - - llvm::GlobalVariable *MetaTClass = - BuildClassObject(CI, /*metaclass*/ true, - IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden); - CGM.setGVProperties(MetaTClass, CI); - DefinedMetaClasses.push_back(MetaTClass); - - // Metadata for the class - flags = 0; - if (classIsHidden) - flags |= NonFragileABI_Class_Hidden; - - if (ID->hasNonZeroConstructors() || ID->hasDestructors()) { - flags |= NonFragileABI_Class_HasCXXStructors; - - // Set a flag to enable a runtime optimization when a class has - // fields that require destruction but which don't require - // anything except zero-initialization during construction. This - // is most notably true of __strong and __weak types, but you can - // also imagine there being C++ types with non-trivial default - // constructors that merely set all fields to null. - if (!ID->hasNonZeroConstructors()) - flags |= NonFragileABI_Class_HasCXXDestructorOnly; - } - - if (hasObjCExceptionAttribute(CGM.getContext(), CI)) - flags |= NonFragileABI_Class_Exception; - - if (!CI->getSuperClass()) { - flags |= NonFragileABI_Class_Root; - SuperClassGV = nullptr; - } else { - // Has a root. Current class is not a root. - const auto *Super = CI->getSuperClass(); - SuperClassGV = GetClassGlobal(Super, /*metaclass*/ false, NotForDefinition); - } - - GetClassSizeInfo(ID, InstanceStart, InstanceSize); - CLASS_RO_GV = - BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID); - - llvm::GlobalVariable *ClassMD = - BuildClassObject(CI, /*metaclass*/ false, - MetaTClass, SuperClassGV, CLASS_RO_GV, classIsHidden); - CGM.setGVProperties(ClassMD, CI); - DefinedClasses.push_back(ClassMD); - ImplementedClasses.push_back(CI); - - // Determine if this class is also "non-lazy". - if (ImplementationIsNonLazy(ID)) - DefinedNonLazyClasses.push_back(ClassMD); - - // Force the definition of the EHType if necessary. - if (flags & NonFragileABI_Class_Exception) - (void) GetInterfaceEHType(CI, ForDefinition); - // Make sure method definition entries are all clear for next implementation. - MethodDefinitions.clear(); -} - -/// GenerateProtocolRef - This routine is called to generate code for -/// a protocol reference expression; as in: -/// @code -/// @protocol(Proto1); -/// @endcode -/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1 -/// which will hold address of the protocol meta-data. -/// -llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF, - const ObjCProtocolDecl *PD) { - - // This routine is called for @protocol only. So, we must build definition - // of protocol's meta-data (not a reference to it!) - // - llvm::Constant *Init = - llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD), - ObjCTypes.getExternalProtocolPtrTy()); - - std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_"); - ProtocolName += PD->getObjCRuntimeNameAsString(); - - CharUnits Align = CGF.getPointerAlign(); - - llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName); - if (PTGV) - return CGF.Builder.CreateAlignedLoad(PTGV, Align); - PTGV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, - llvm::GlobalValue::WeakAnyLinkage, Init, - ProtocolName); - PTGV->setSection(GetSectionName("__objc_protorefs", - "coalesced,no_dead_strip")); - PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); - PTGV->setAlignment(Align.getQuantity()); - if (!CGM.getTriple().isOSBinFormatMachO()) - PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolName)); - CGM.addUsedGlobal(PTGV); - return CGF.Builder.CreateAlignedLoad(PTGV, Align); -} - -/// GenerateCategory - Build metadata for a category implementation. -/// struct _category_t { -/// const char * const name; -/// struct _class_t *const cls; -/// const struct _method_list_t * const instance_methods; -/// const struct _method_list_t * const class_methods; -/// const struct _protocol_list_t * const protocols; -/// const struct _prop_list_t * const properties; -/// const struct _prop_list_t * const class_properties; -/// const uint32_t size; -/// } -/// -void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { - const ObjCInterfaceDecl *Interface = OCD->getClassInterface(); - const char *Prefix = "\01l_OBJC_$_CATEGORY_"; - - llvm::SmallString<64> ExtCatName(Prefix); - ExtCatName += Interface->getObjCRuntimeNameAsString(); - ExtCatName += "_$_"; - ExtCatName += OCD->getNameAsString(); - - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(ObjCTypes.CategorynfABITy); - values.add(GetClassName(OCD->getIdentifier()->getName())); - // meta-class entry symbol - values.add(GetClassGlobal(Interface, /*metaclass*/ false, NotForDefinition)); - std::string listName = - (Interface->getObjCRuntimeNameAsString() + "_$_" + OCD->getName()).str(); - - SmallVector<const ObjCMethodDecl *, 16> instanceMethods; - SmallVector<const ObjCMethodDecl *, 8> classMethods; - for (const auto *MD : OCD->methods()) { - if (MD->isInstanceMethod()) { - instanceMethods.push_back(MD); - } else { - classMethods.push_back(MD); - } - } - - values.add(emitMethodList(listName, MethodListType::CategoryInstanceMethods, - instanceMethods)); - values.add(emitMethodList(listName, MethodListType::CategoryClassMethods, - classMethods)); - - const ObjCCategoryDecl *Category = - Interface->FindCategoryDeclaration(OCD->getIdentifier()); - if (Category) { - SmallString<256> ExtName; - llvm::raw_svector_ostream(ExtName) << Interface->getObjCRuntimeNameAsString() << "_$_" - << OCD->getName(); - values.add(EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_" - + Interface->getObjCRuntimeNameAsString() + "_$_" - + Category->getName(), - Category->protocol_begin(), - Category->protocol_end())); - values.add(EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(), - OCD, Category, ObjCTypes, false)); - values.add(EmitPropertyList("\01l_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(), - OCD, Category, ObjCTypes, true)); - } else { - values.addNullPointer(ObjCTypes.ProtocolListnfABIPtrTy); - values.addNullPointer(ObjCTypes.PropertyListPtrTy); - values.addNullPointer(ObjCTypes.PropertyListPtrTy); - } - - unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategorynfABITy); - values.addInt(ObjCTypes.IntTy, Size); - - llvm::GlobalVariable *GCATV = - values.finishAndCreateGlobal(ExtCatName.str(), CGM.getPointerAlign(), - /*constant*/ false, - llvm::GlobalValue::PrivateLinkage); - if (CGM.getTriple().isOSBinFormatMachO()) - GCATV->setSection("__DATA, __objc_const"); - CGM.addCompilerUsedGlobal(GCATV); - DefinedCategories.push_back(GCATV); - - // Determine if this category is also "non-lazy". - if (ImplementationIsNonLazy(OCD)) - DefinedNonLazyCategories.push_back(GCATV); - // method definition entries must be clear for next implementation. - MethodDefinitions.clear(); -} - -/// emitMethodConstant - Return a struct objc_method constant. If -/// forProtocol is true, the implementation will be null; otherwise, -/// the method must have a definition registered with the runtime. -/// -/// struct _objc_method { -/// SEL _cmd; -/// char *method_type; -/// char *_imp; -/// } -void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder, - const ObjCMethodDecl *MD, - bool forProtocol) { - auto method = builder.beginStruct(ObjCTypes.MethodTy); - method.addBitCast(GetMethodVarName(MD->getSelector()), - ObjCTypes.SelectorPtrTy); - method.add(GetMethodVarType(MD)); - - if (forProtocol) { - // Protocol methods have no implementation. So, this entry is always NULL. - method.addNullPointer(ObjCTypes.Int8PtrTy); - } else { - llvm::Function *fn = GetMethodDefinition(MD); - assert(fn && "no definition for method?"); - method.addBitCast(fn, ObjCTypes.Int8PtrTy); - } - - method.finishAndAddTo(builder); -} - -/// Build meta-data for method declarations. -/// -/// struct _method_list_t { -/// uint32_t entsize; // sizeof(struct _objc_method) -/// uint32_t method_count; -/// struct _objc_method method_list[method_count]; -/// } -/// -llvm::Constant * -CGObjCNonFragileABIMac::emitMethodList(Twine name, MethodListType kind, - ArrayRef<const ObjCMethodDecl *> methods) { - // Return null for empty list. - if (methods.empty()) - return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy); - - StringRef prefix; - bool forProtocol; - switch (kind) { - case MethodListType::CategoryInstanceMethods: - prefix = "\01l_OBJC_$_CATEGORY_INSTANCE_METHODS_"; - forProtocol = false; - break; - case MethodListType::CategoryClassMethods: - prefix = "\01l_OBJC_$_CATEGORY_CLASS_METHODS_"; - forProtocol = false; - break; - case MethodListType::InstanceMethods: - prefix = "\01l_OBJC_$_INSTANCE_METHODS_"; - forProtocol = false; - break; - case MethodListType::ClassMethods: - prefix = "\01l_OBJC_$_CLASS_METHODS_"; - forProtocol = false; - break; - - case MethodListType::ProtocolInstanceMethods: - prefix = "\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"; - forProtocol = true; - break; - case MethodListType::ProtocolClassMethods: - prefix = "\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"; - forProtocol = true; - break; - case MethodListType::OptionalProtocolInstanceMethods: - prefix = "\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"; - forProtocol = true; - break; - case MethodListType::OptionalProtocolClassMethods: - prefix = "\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"; - forProtocol = true; - break; - } - - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(); - - // sizeof(struct _objc_method) - unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy); - values.addInt(ObjCTypes.IntTy, Size); - // method_count - values.addInt(ObjCTypes.IntTy, methods.size()); - auto methodArray = values.beginArray(ObjCTypes.MethodTy); - for (auto MD : methods) { - emitMethodConstant(methodArray, MD, forProtocol); - } - methodArray.finishAndAddTo(values); - - auto *GV = values.finishAndCreateGlobal(prefix + name, CGM.getPointerAlign(), - /*constant*/ false, - llvm::GlobalValue::PrivateLinkage); - if (CGM.getTriple().isOSBinFormatMachO()) - GV->setSection("__DATA, __objc_const"); - CGM.addCompilerUsedGlobal(GV); - return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy); -} - -/// ObjCIvarOffsetVariable - Returns the ivar offset variable for -/// the given ivar. -llvm::GlobalVariable * -CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID, - const ObjCIvarDecl *Ivar) { - const ObjCInterfaceDecl *Container = Ivar->getContainingInterface(); - llvm::SmallString<64> Name("OBJC_IVAR_$_"); - Name += Container->getObjCRuntimeNameAsString(); - Name += "."; - Name += Ivar->getName(); - llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name); - if (!IvarOffsetGV) { - IvarOffsetGV = - new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.IvarOffsetVarTy, - false, llvm::GlobalValue::ExternalLinkage, - nullptr, Name.str()); - if (CGM.getTriple().isOSBinFormatCOFF()) { - bool IsPrivateOrPackage = - Ivar->getAccessControl() == ObjCIvarDecl::Private || - Ivar->getAccessControl() == ObjCIvarDecl::Package; - - const ObjCInterfaceDecl *ContainingID = Ivar->getContainingInterface(); - - if (ContainingID->hasAttr<DLLImportAttr>()) - IvarOffsetGV - ->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); - else if (ContainingID->hasAttr<DLLExportAttr>() && !IsPrivateOrPackage) - IvarOffsetGV - ->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); - } - } - return IvarOffsetGV; -} - -llvm::Constant * -CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID, - const ObjCIvarDecl *Ivar, - unsigned long int Offset) { - llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar); - IvarOffsetGV->setInitializer( - llvm::ConstantInt::get(ObjCTypes.IvarOffsetVarTy, Offset)); - IvarOffsetGV->setAlignment( - CGM.getDataLayout().getABITypeAlignment(ObjCTypes.IvarOffsetVarTy)); - - if (!CGM.getTriple().isOSBinFormatCOFF()) { - // FIXME: This matches gcc, but shouldn't the visibility be set on the use - // as well (i.e., in ObjCIvarOffsetVariable). - if (Ivar->getAccessControl() == ObjCIvarDecl::Private || - Ivar->getAccessControl() == ObjCIvarDecl::Package || - ID->getVisibility() == HiddenVisibility) - IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility); - else - IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility); - } - - if (CGM.getTriple().isOSBinFormatMachO()) - IvarOffsetGV->setSection("__DATA, __objc_ivar"); - return IvarOffsetGV; -} - -/// EmitIvarList - Emit the ivar list for the given -/// implementation. The return value has type -/// IvarListnfABIPtrTy. -/// struct _ivar_t { -/// unsigned [long] int *offset; // pointer to ivar offset location -/// char *name; -/// char *type; -/// uint32_t alignment; -/// uint32_t size; -/// } -/// struct _ivar_list_t { -/// uint32 entsize; // sizeof(struct _ivar_t) -/// uint32 count; -/// struct _iver_t list[count]; -/// } -/// - -llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( - const ObjCImplementationDecl *ID) { - - ConstantInitBuilder builder(CGM); - auto ivarList = builder.beginStruct(); - ivarList.addInt(ObjCTypes.IntTy, - CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy)); - auto ivarCountSlot = ivarList.addPlaceholder(); - auto ivars = ivarList.beginArray(ObjCTypes.IvarnfABITy); - - const ObjCInterfaceDecl *OID = ID->getClassInterface(); - assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface"); - - // FIXME. Consolidate this with similar code in GenerateClass. - - for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin(); - IVD; IVD = IVD->getNextIvar()) { - // Ignore unnamed bit-fields. - if (!IVD->getDeclName()) - continue; - - auto ivar = ivars.beginStruct(ObjCTypes.IvarnfABITy); - ivar.add(EmitIvarOffsetVar(ID->getClassInterface(), IVD, - ComputeIvarBaseOffset(CGM, ID, IVD))); - ivar.add(GetMethodVarName(IVD->getIdentifier())); - ivar.add(GetMethodVarType(IVD)); - llvm::Type *FieldTy = - CGM.getTypes().ConvertTypeForMem(IVD->getType()); - unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy); - unsigned Align = CGM.getContext().getPreferredTypeAlign( - IVD->getType().getTypePtr()) >> 3; - Align = llvm::Log2_32(Align); - ivar.addInt(ObjCTypes.IntTy, Align); - // NOTE. Size of a bitfield does not match gcc's, because of the - // way bitfields are treated special in each. But I am told that - // 'size' for bitfield ivars is ignored by the runtime so it does - // not matter. If it matters, there is enough info to get the - // bitfield right! - ivar.addInt(ObjCTypes.IntTy, Size); - ivar.finishAndAddTo(ivars); - } - // Return null for empty list. - if (ivars.empty()) { - ivars.abandon(); - ivarList.abandon(); - return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy); - } - - auto ivarCount = ivars.size(); - ivars.finishAndAddTo(ivarList); - ivarList.fillPlaceholderWithInt(ivarCountSlot, ObjCTypes.IntTy, ivarCount); - - const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_"; - llvm::GlobalVariable *GV = - ivarList.finishAndCreateGlobal(Prefix + OID->getObjCRuntimeNameAsString(), - CGM.getPointerAlign(), /*constant*/ false, - llvm::GlobalValue::PrivateLinkage); - if (CGM.getTriple().isOSBinFormatMachO()) - GV->setSection("__DATA, __objc_const"); - CGM.addCompilerUsedGlobal(GV); - return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy); -} - -llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef( - const ObjCProtocolDecl *PD) { - llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; - - if (!Entry) { - // We use the initializer as a marker of whether this is a forward - // reference or not. At module finalization we add the empty - // contents for protocols which were referenced but never defined. - llvm::SmallString<64> Protocol; - llvm::raw_svector_ostream(Protocol) << "\01l_OBJC_PROTOCOL_$_" - << PD->getObjCRuntimeNameAsString(); - - Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, - false, llvm::GlobalValue::ExternalLinkage, - nullptr, Protocol); - if (!CGM.getTriple().isOSBinFormatMachO()) - Entry->setComdat(CGM.getModule().getOrInsertComdat(Protocol)); - } - - return Entry; -} - -/// GetOrEmitProtocol - Generate the protocol meta-data: -/// @code -/// struct _protocol_t { -/// id isa; // NULL -/// const char * const protocol_name; -/// const struct _protocol_list_t * protocol_list; // super protocols -/// const struct method_list_t * const instance_methods; -/// const struct method_list_t * const class_methods; -/// const struct method_list_t *optionalInstanceMethods; -/// const struct method_list_t *optionalClassMethods; -/// const struct _prop_list_t * properties; -/// const uint32_t size; // sizeof(struct _protocol_t) -/// const uint32_t flags; // = 0 -/// const char ** extendedMethodTypes; -/// const char *demangledName; -/// const struct _prop_list_t * class_properties; -/// } -/// @endcode -/// - -llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( - const ObjCProtocolDecl *PD) { - llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()]; - - // Early exit if a defining object has already been generated. - if (Entry && Entry->hasInitializer()) - return Entry; - - // Use the protocol definition, if there is one. - assert(PD->hasDefinition() && - "emitting protocol metadata without definition"); - PD = PD->getDefinition(); - - auto methodLists = ProtocolMethodLists::get(PD); - - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(ObjCTypes.ProtocolnfABITy); - - // isa is NULL - values.addNullPointer(ObjCTypes.ObjectPtrTy); - values.add(GetClassName(PD->getObjCRuntimeNameAsString())); - values.add(EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" - + PD->getObjCRuntimeNameAsString(), - PD->protocol_begin(), - PD->protocol_end())); - values.add(methodLists.emitMethodList(this, PD, - ProtocolMethodLists::RequiredInstanceMethods)); - values.add(methodLists.emitMethodList(this, PD, - ProtocolMethodLists::RequiredClassMethods)); - values.add(methodLists.emitMethodList(this, PD, - ProtocolMethodLists::OptionalInstanceMethods)); - values.add(methodLists.emitMethodList(this, PD, - ProtocolMethodLists::OptionalClassMethods)); - values.add(EmitPropertyList( - "\01l_OBJC_$_PROP_LIST_" + PD->getObjCRuntimeNameAsString(), - nullptr, PD, ObjCTypes, false)); - uint32_t Size = - CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy); - values.addInt(ObjCTypes.IntTy, Size); - values.addInt(ObjCTypes.IntTy, 0); - values.add(EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_" - + PD->getObjCRuntimeNameAsString(), - methodLists.emitExtendedTypesArray(this), - ObjCTypes)); - - // const char *demangledName; - values.addNullPointer(ObjCTypes.Int8PtrTy); - - values.add(EmitPropertyList( - "\01l_OBJC_$_CLASS_PROP_LIST_" + PD->getObjCRuntimeNameAsString(), - nullptr, PD, ObjCTypes, true)); - - if (Entry) { - // Already created, fix the linkage and update the initializer. - Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage); - values.finishAndSetAsInitializer(Entry); - } else { - llvm::SmallString<64> symbolName; - llvm::raw_svector_ostream(symbolName) - << "\01l_OBJC_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString(); - - Entry = values.finishAndCreateGlobal(symbolName, CGM.getPointerAlign(), - /*constant*/ false, - llvm::GlobalValue::WeakAnyLinkage); - if (!CGM.getTriple().isOSBinFormatMachO()) - Entry->setComdat(CGM.getModule().getOrInsertComdat(symbolName)); - - Protocols[PD->getIdentifier()] = Entry; - } - Entry->setVisibility(llvm::GlobalValue::HiddenVisibility); - CGM.addUsedGlobal(Entry); - - // Use this protocol meta-data to build protocol list table in section - // __DATA, __objc_protolist - llvm::SmallString<64> ProtocolRef; - llvm::raw_svector_ostream(ProtocolRef) << "\01l_OBJC_LABEL_PROTOCOL_$_" - << PD->getObjCRuntimeNameAsString(); - - llvm::GlobalVariable *PTGV = - new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy, - false, llvm::GlobalValue::WeakAnyLinkage, Entry, - ProtocolRef); - if (!CGM.getTriple().isOSBinFormatMachO()) - PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef)); - PTGV->setAlignment( - CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy)); - PTGV->setSection(GetSectionName("__objc_protolist", - "coalesced,no_dead_strip")); - PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); - CGM.addUsedGlobal(PTGV); - return Entry; -} - -/// EmitProtocolList - Generate protocol list meta-data: -/// @code -/// struct _protocol_list_t { -/// long protocol_count; // Note, this is 32/64 bit -/// struct _protocol_t[protocol_count]; -/// } -/// @endcode -/// -llvm::Constant * -CGObjCNonFragileABIMac::EmitProtocolList(Twine Name, - ObjCProtocolDecl::protocol_iterator begin, - ObjCProtocolDecl::protocol_iterator end) { - SmallVector<llvm::Constant *, 16> ProtocolRefs; - - // Just return null for empty protocol lists - if (begin == end) - return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy); - - // FIXME: We shouldn't need to do this lookup here, should we? - SmallString<256> TmpName; - Name.toVector(TmpName); - llvm::GlobalVariable *GV = - CGM.getModule().getGlobalVariable(TmpName.str(), true); - if (GV) - return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy); - - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(); - auto countSlot = values.addPlaceholder(); - - // A null-terminated array of protocols. - auto array = values.beginArray(ObjCTypes.ProtocolnfABIPtrTy); - for (; begin != end; ++begin) - array.add(GetProtocolRef(*begin)); // Implemented??? - auto count = array.size(); - array.addNullPointer(ObjCTypes.ProtocolnfABIPtrTy); - - array.finishAndAddTo(values); - values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count); - - GV = values.finishAndCreateGlobal(Name, CGM.getPointerAlign(), - /*constant*/ false, - llvm::GlobalValue::PrivateLinkage); - if (CGM.getTriple().isOSBinFormatMachO()) - GV->setSection("__DATA, __objc_const"); - CGM.addCompilerUsedGlobal(GV); - return llvm::ConstantExpr::getBitCast(GV, - ObjCTypes.ProtocolListnfABIPtrTy); -} - -/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference. -/// This code gen. amounts to generating code for: -/// @code -/// (type *)((char *)base + _OBJC_IVAR_$_.ivar; -/// @encode -/// -LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar( - CodeGen::CodeGenFunction &CGF, - QualType ObjectTy, - llvm::Value *BaseValue, - const ObjCIvarDecl *Ivar, - unsigned CVRQualifiers) { - ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface(); - llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar); - return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, - Offset); -} - -llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset( - CodeGen::CodeGenFunction &CGF, - const ObjCInterfaceDecl *Interface, - const ObjCIvarDecl *Ivar) { - llvm::Value *IvarOffsetValue = ObjCIvarOffsetVariable(Interface, Ivar); - IvarOffsetValue = CGF.Builder.CreateAlignedLoad(IvarOffsetValue, - CGF.getSizeAlign(), "ivar"); - if (IsIvarOffsetKnownIdempotent(CGF, Ivar)) - cast<llvm::LoadInst>(IvarOffsetValue) - ->setMetadata(CGM.getModule().getMDKindID("invariant.load"), - llvm::MDNode::get(VMContext, None)); - - // This could be 32bit int or 64bit integer depending on the architecture. - // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value - // as this is what caller always expects. - if (ObjCTypes.IvarOffsetVarTy == ObjCTypes.IntTy) - IvarOffsetValue = CGF.Builder.CreateIntCast( - IvarOffsetValue, ObjCTypes.LongTy, true, "ivar.conv"); - return IvarOffsetValue; -} - -static void appendSelectorForMessageRefTable(std::string &buffer, - Selector selector) { - if (selector.isUnarySelector()) { - buffer += selector.getNameForSlot(0); - return; - } - - for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) { - buffer += selector.getNameForSlot(i); - buffer += '_'; - } -} - -/// Emit a "vtable" message send. We emit a weak hidden-visibility -/// struct, initially containing the selector pointer and a pointer to -/// a "fixup" variant of the appropriate objc_msgSend. To call, we -/// load and call the function pointer, passing the address of the -/// struct as the second parameter. The runtime determines whether -/// the selector is currently emitted using vtable dispatch; if so, it -/// substitutes a stub function which simply tail-calls through the -/// appropriate vtable slot, and if not, it substitues a stub function -/// which tail-calls objc_msgSend. Both stubs adjust the selector -/// argument to correctly point to the selector. -RValue -CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, - ReturnValueSlot returnSlot, - QualType resultType, - Selector selector, - llvm::Value *arg0, - QualType arg0Type, - bool isSuper, - const CallArgList &formalArgs, - const ObjCMethodDecl *method) { - // Compute the actual arguments. - CallArgList args; - - // First argument: the receiver / super-call structure. - if (!isSuper) - arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy); - args.add(RValue::get(arg0), arg0Type); - - // Second argument: a pointer to the message ref structure. Leave - // the actual argument value blank for now. - args.add(RValue::get(nullptr), ObjCTypes.MessageRefCPtrTy); - - args.insert(args.end(), formalArgs.begin(), formalArgs.end()); - - MessageSendInfo MSI = getMessageSendInfo(method, resultType, args); - - NullReturnState nullReturn; - - // Find the function to call and the mangled name for the message - // ref structure. Using a different mangled name wouldn't actually - // be a problem; it would just be a waste. - // - // The runtime currently never uses vtable dispatch for anything - // except normal, non-super message-sends. - // FIXME: don't use this for that. - llvm::Constant *fn = nullptr; - std::string messageRefName("\01l_"); - if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) { - if (isSuper) { - fn = ObjCTypes.getMessageSendSuper2StretFixupFn(); - messageRefName += "objc_msgSendSuper2_stret_fixup"; - } else { - nullReturn.init(CGF, arg0); - fn = ObjCTypes.getMessageSendStretFixupFn(); - messageRefName += "objc_msgSend_stret_fixup"; - } - } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) { - fn = ObjCTypes.getMessageSendFpretFixupFn(); - messageRefName += "objc_msgSend_fpret_fixup"; - } else { - if (isSuper) { - fn = ObjCTypes.getMessageSendSuper2FixupFn(); - messageRefName += "objc_msgSendSuper2_fixup"; - } else { - fn = ObjCTypes.getMessageSendFixupFn(); - messageRefName += "objc_msgSend_fixup"; - } - } - assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend"); - messageRefName += '_'; - - // Append the selector name, except use underscores anywhere we - // would have used colons. - appendSelectorForMessageRefTable(messageRefName, selector); - - llvm::GlobalVariable *messageRef - = CGM.getModule().getGlobalVariable(messageRefName); - if (!messageRef) { - // Build the message ref structure. - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(); - values.add(fn); - values.add(GetMethodVarName(selector)); - messageRef = values.finishAndCreateGlobal(messageRefName, - CharUnits::fromQuantity(16), - /*constant*/ false, - llvm::GlobalValue::WeakAnyLinkage); - messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility); - messageRef->setSection(GetSectionName("__objc_msgrefs", "coalesced")); - } - - bool requiresnullCheck = false; - if (CGM.getLangOpts().ObjCAutoRefCount && method) - for (const auto *ParamDecl : method->parameters()) { - if (ParamDecl->hasAttr<NSConsumedAttr>()) { - if (!nullReturn.NullBB) - nullReturn.init(CGF, arg0); - requiresnullCheck = true; - break; - } - } - - Address mref = - Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy), - CGF.getPointerAlign()); - - // Update the message ref argument. - args[1].setRValue(RValue::get(mref.getPointer())); - - // Load the function to call from the message ref table. - Address calleeAddr = - CGF.Builder.CreateStructGEP(mref, 0, CharUnits::Zero()); - llvm::Value *calleePtr = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn"); - - calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType); - CGCallee callee(CGCalleeInfo(), calleePtr); - - RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args); - return nullReturn.complete(CGF, returnSlot, result, resultType, formalArgs, - requiresnullCheck ? method : nullptr); -} - -/// Generate code for a message send expression in the nonfragile abi. -CodeGen::RValue -CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, - QualType ResultType, - Selector Sel, - llvm::Value *Receiver, - const CallArgList &CallArgs, - const ObjCInterfaceDecl *Class, - const ObjCMethodDecl *Method) { - return isVTableDispatchedSelector(Sel) - ? EmitVTableMessageSend(CGF, Return, ResultType, Sel, - Receiver, CGF.getContext().getObjCIdType(), - false, CallArgs, Method) - : EmitMessageSend(CGF, Return, ResultType, - EmitSelector(CGF, Sel), - Receiver, CGF.getContext().getObjCIdType(), - false, CallArgs, Method, Class, ObjCTypes); -} - -llvm::Constant * -CGObjCNonFragileABIMac::GetClassGlobal(const ObjCInterfaceDecl *ID, - bool metaclass, - ForDefinition_t isForDefinition) { - auto prefix = - (metaclass ? getMetaclassSymbolPrefix() : getClassSymbolPrefix()); - return GetClassGlobal((prefix + ID->getObjCRuntimeNameAsString()).str(), - isForDefinition, - ID->isWeakImported(), - !isForDefinition - && CGM.getTriple().isOSBinFormatCOFF() - && ID->hasAttr<DLLImportAttr>()); -} - -llvm::Constant * -CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name, - ForDefinition_t IsForDefinition, - bool Weak, bool DLLImport) { - llvm::GlobalValue::LinkageTypes L = - Weak ? llvm::GlobalValue::ExternalWeakLinkage - : llvm::GlobalValue::ExternalLinkage; - - llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); - if (!GV || GV->getType() != ObjCTypes.ClassnfABITy->getPointerTo()) { - auto *NewGV = new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false, L, - nullptr, Name); - - if (DLLImport) - NewGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); - - if (GV) { - GV->replaceAllUsesWith( - llvm::ConstantExpr::getBitCast(NewGV, GV->getType())); - GV->eraseFromParent(); - } - GV = NewGV; - CGM.getModule().getGlobalList().push_back(GV); - } - - assert(GV->getLinkage() == L); - return GV; -} - -llvm::Value * -CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF, - IdentifierInfo *II, - const ObjCInterfaceDecl *ID) { - CharUnits Align = CGF.getPointerAlign(); - llvm::GlobalVariable *&Entry = ClassReferences[II]; - - if (!Entry) { - llvm::Constant *ClassGV; - if (ID) { - ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition); - } else { - ClassGV = GetClassGlobal((getClassSymbolPrefix() + II->getName()).str(), - NotForDefinition); - } - - Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, - false, llvm::GlobalValue::PrivateLinkage, - ClassGV, "OBJC_CLASSLIST_REFERENCES_$_"); - Entry->setAlignment(Align.getQuantity()); - Entry->setSection(GetSectionName("__objc_classrefs", - "regular,no_dead_strip")); - CGM.addCompilerUsedGlobal(Entry); - } - return CGF.Builder.CreateAlignedLoad(Entry, Align); -} - -llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF, - const ObjCInterfaceDecl *ID) { - // If the class has the objc_runtime_visible attribute, we need to - // use the Objective-C runtime to get the class. - if (ID->hasAttr<ObjCRuntimeVisibleAttr>()) - return EmitClassRefViaRuntime(CGF, ID, ObjCTypes); - - return EmitClassRefFromId(CGF, ID->getIdentifier(), ID); -} - -llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef( - CodeGenFunction &CGF) { - IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool"); - return EmitClassRefFromId(CGF, II, nullptr); -} - -llvm::Value * -CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF, - const ObjCInterfaceDecl *ID) { - CharUnits Align = CGF.getPointerAlign(); - llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()]; - - if (!Entry) { - auto ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition); - Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, - false, llvm::GlobalValue::PrivateLinkage, - ClassGV, "OBJC_CLASSLIST_SUP_REFS_$_"); - Entry->setAlignment(Align.getQuantity()); - Entry->setSection(GetSectionName("__objc_superrefs", - "regular,no_dead_strip")); - CGM.addCompilerUsedGlobal(Entry); - } - return CGF.Builder.CreateAlignedLoad(Entry, Align); -} - -/// EmitMetaClassRef - Return a Value * of the address of _class_t -/// meta-data -/// -llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF, - const ObjCInterfaceDecl *ID, - bool Weak) { - CharUnits Align = CGF.getPointerAlign(); - llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()]; - if (!Entry) { - auto MetaClassGV = GetClassGlobal(ID, /*metaclass*/ true, NotForDefinition); - - Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, - false, llvm::GlobalValue::PrivateLinkage, - MetaClassGV, "OBJC_CLASSLIST_SUP_REFS_$_"); - Entry->setAlignment(Align.getQuantity()); - - Entry->setSection(GetSectionName("__objc_superrefs", - "regular,no_dead_strip")); - CGM.addCompilerUsedGlobal(Entry); - } - - return CGF.Builder.CreateAlignedLoad(Entry, Align); -} - -/// GetClass - Return a reference to the class for the given interface -/// decl. -llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF, - const ObjCInterfaceDecl *ID) { - if (ID->isWeakImported()) { - auto ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition); - (void)ClassGV; - assert(!isa<llvm::GlobalVariable>(ClassGV) || - cast<llvm::GlobalVariable>(ClassGV)->hasExternalWeakLinkage()); - } - - return EmitClassRef(CGF, ID); -} - -/// Generates a message send where the super is the receiver. This is -/// a message send to self with special delivery semantics indicating -/// which class's method should be called. -CodeGen::RValue -CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, - QualType ResultType, - Selector Sel, - const ObjCInterfaceDecl *Class, - bool isCategoryImpl, - llvm::Value *Receiver, - bool IsClassMessage, - const CodeGen::CallArgList &CallArgs, - const ObjCMethodDecl *Method) { - // ... - // Create and init a super structure; this is a (receiver, class) - // pair we will pass to objc_msgSendSuper. - Address ObjCSuper = - CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(), - "objc_super"); - - llvm::Value *ReceiverAsObject = - CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); - CGF.Builder.CreateStore( - ReceiverAsObject, - CGF.Builder.CreateStructGEP(ObjCSuper, 0, CharUnits::Zero())); - - // If this is a class message the metaclass is passed as the target. - llvm::Value *Target; - if (IsClassMessage) - Target = EmitMetaClassRef(CGF, Class, Class->isWeakImported()); - else - Target = EmitSuperClassRef(CGF, Class); - - // FIXME: We shouldn't need to do this cast, rectify the ASTContext and - // ObjCTypes types. - llvm::Type *ClassTy = - CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); - Target = CGF.Builder.CreateBitCast(Target, ClassTy); - CGF.Builder.CreateStore( - Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1, CGF.getPointerSize())); - - return (isVTableDispatchedSelector(Sel)) - ? EmitVTableMessageSend(CGF, Return, ResultType, Sel, - ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy, - true, CallArgs, Method) - : EmitMessageSend(CGF, Return, ResultType, - EmitSelector(CGF, Sel), - ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy, - true, CallArgs, Method, Class, ObjCTypes); -} - -llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF, - Selector Sel) { - Address Addr = EmitSelectorAddr(CGF, Sel); - - llvm::LoadInst* LI = CGF.Builder.CreateLoad(Addr); - LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"), - llvm::MDNode::get(VMContext, None)); - return LI; -} - -Address CGObjCNonFragileABIMac::EmitSelectorAddr(CodeGenFunction &CGF, - Selector Sel) { - llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; - - CharUnits Align = CGF.getPointerAlign(); - if (!Entry) { - llvm::Constant *Casted = - llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel), - ObjCTypes.SelectorPtrTy); - Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, - false, llvm::GlobalValue::PrivateLinkage, - Casted, "OBJC_SELECTOR_REFERENCES_"); - Entry->setExternallyInitialized(true); - Entry->setSection(GetSectionName("__objc_selrefs", - "literal_pointers,no_dead_strip")); - Entry->setAlignment(Align.getQuantity()); - CGM.addCompilerUsedGlobal(Entry); - } - - return Address(Entry, Align); -} - -/// EmitObjCIvarAssign - Code gen for assigning to a __strong object. -/// objc_assign_ivar (id src, id *dst, ptrdiff_t) -/// -void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, - Address dst, - llvm::Value *ivarOffset) { - llvm::Type * SrcTy = src->getType(); - if (!isa<llvm::PointerType>(SrcTy)) { - unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); - assert(Size <= 8 && "does not support size > 8"); - src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) - : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); - src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); - } - src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); - llvm::Value *args[] = { src, dst.getPointer(), ivarOffset }; - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args); -} - -/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object. -/// objc_assign_strongCast (id src, id *dst) -/// -void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( - CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dst) { - llvm::Type * SrcTy = src->getType(); - if (!isa<llvm::PointerType>(SrcTy)) { - unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); - assert(Size <= 8 && "does not support size > 8"); - src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) - : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); - src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); - } - src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); - llvm::Value *args[] = { src, dst.getPointer() }; - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), - args, "weakassign"); -} - -void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable( - CodeGen::CodeGenFunction &CGF, - Address DestPtr, - Address SrcPtr, - llvm::Value *Size) { - SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy); - DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy); - llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), Size }; - CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args); -} - -/// EmitObjCWeakRead - Code gen for loading value of a __weak -/// object: objc_read_weak (id *src) -/// -llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead( - CodeGen::CodeGenFunction &CGF, - Address AddrWeakObj) { - llvm::Type *DestTy = AddrWeakObj.getElementType(); - AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy); - llvm::Value *read_weak = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(), - AddrWeakObj.getPointer(), "weakread"); - read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy); - return read_weak; -} - -/// EmitObjCWeakAssign - Code gen for assigning to a __weak object. -/// objc_assign_weak (id src, id *dst) -/// -void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dst) { - llvm::Type * SrcTy = src->getType(); - if (!isa<llvm::PointerType>(SrcTy)) { - unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); - assert(Size <= 8 && "does not support size > 8"); - src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) - : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); - src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); - } - src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); - llvm::Value *args[] = { src, dst.getPointer() }; - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), - args, "weakassign"); -} - -/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object. -/// objc_assign_global (id src, id *dst) -/// -void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dst, - bool threadlocal) { - llvm::Type * SrcTy = src->getType(); - if (!isa<llvm::PointerType>(SrcTy)) { - unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); - assert(Size <= 8 && "does not support size > 8"); - src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) - : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); - src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); - } - src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); - llvm::Value *args[] = { src, dst.getPointer() }; - if (!threadlocal) - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), - args, "globalassign"); - else - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(), - args, "threadlocalassign"); -} - -void -CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, - const ObjCAtSynchronizedStmt &S) { - EmitAtSynchronizedStmt(CGF, S, - cast<llvm::Function>(ObjCTypes.getSyncEnterFn()), - cast<llvm::Function>(ObjCTypes.getSyncExitFn())); -} - -llvm::Constant * -CGObjCNonFragileABIMac::GetEHType(QualType T) { - // There's a particular fixed type info for 'id'. - if (T->isObjCIdType() || T->isObjCQualifiedIdType()) { - auto *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id"); - if (!IDEHType) { - IDEHType = - new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, - llvm::GlobalValue::ExternalLinkage, nullptr, - "OBJC_EHTYPE_id"); - if (CGM.getTriple().isOSBinFormatCOFF()) - IDEHType->setDLLStorageClass(getStorage(CGM, "OBJC_EHTYPE_id")); - } - return IDEHType; - } - - // All other types should be Objective-C interface pointer types. - const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>(); - assert(PT && "Invalid @catch type."); - - const ObjCInterfaceType *IT = PT->getInterfaceType(); - assert(IT && "Invalid @catch type."); - - return GetInterfaceEHType(IT->getDecl(), NotForDefinition); -} - -void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF, - const ObjCAtTryStmt &S) { - EmitTryCatchStmt(CGF, S, - cast<llvm::Function>(ObjCTypes.getObjCBeginCatchFn()), - cast<llvm::Function>(ObjCTypes.getObjCEndCatchFn()), - cast<llvm::Function>(ObjCTypes.getExceptionRethrowFn())); -} - -/// EmitThrowStmt - Generate code for a throw statement. -void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, - const ObjCAtThrowStmt &S, - bool ClearInsertionPoint) { - if (const Expr *ThrowExpr = S.getThrowExpr()) { - llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr); - Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy); - CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception) - .setDoesNotReturn(); - } else { - CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn()) - .setDoesNotReturn(); - } - - CGF.Builder.CreateUnreachable(); - if (ClearInsertionPoint) - CGF.Builder.ClearInsertionPoint(); -} - -llvm::Constant * -CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, - ForDefinition_t IsForDefinition) { - llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()]; - StringRef ClassName = ID->getObjCRuntimeNameAsString(); - - // If we don't need a definition, return the entry if found or check - // if we use an external reference. - if (!IsForDefinition) { - if (Entry) - return Entry; - - // If this type (or a super class) has the __objc_exception__ - // attribute, emit an external reference. - if (hasObjCExceptionAttribute(CGM.getContext(), ID)) { - std::string EHTypeName = ("OBJC_EHTYPE_$_" + ClassName).str(); - Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, - false, llvm::GlobalValue::ExternalLinkage, - nullptr, EHTypeName); - CGM.setGVProperties(Entry, ID); - return Entry; - } - } - - // Otherwise we need to either make a new entry or fill in the initializer. - assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition"); - - std::string VTableName = "objc_ehtype_vtable"; - auto *VTableGV = CGM.getModule().getGlobalVariable(VTableName); - if (!VTableGV) { - VTableGV = - new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy, false, - llvm::GlobalValue::ExternalLinkage, nullptr, - VTableName); - if (CGM.getTriple().isOSBinFormatCOFF()) - VTableGV->setDLLStorageClass(getStorage(CGM, VTableName)); - } - - llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2); - ConstantInitBuilder builder(CGM); - auto values = builder.beginStruct(ObjCTypes.EHTypeTy); - values.add( - llvm::ConstantExpr::getInBoundsGetElementPtr(VTableGV->getValueType(), - VTableGV, VTableIdx)); - values.add(GetClassName(ClassName)); - values.add(GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition)); - - llvm::GlobalValue::LinkageTypes L = IsForDefinition - ? llvm::GlobalValue::ExternalLinkage - : llvm::GlobalValue::WeakAnyLinkage; - if (Entry) { - values.finishAndSetAsInitializer(Entry); - Entry->setAlignment(CGM.getPointerAlign().getQuantity()); - } else { - Entry = values.finishAndCreateGlobal("OBJC_EHTYPE_$_" + ClassName, - CGM.getPointerAlign(), - /*constant*/ false, - L); - if (hasObjCExceptionAttribute(CGM.getContext(), ID)) - CGM.setGVProperties(Entry, ID); - } - assert(Entry->getLinkage() == L); - - if (!CGM.getTriple().isOSBinFormatCOFF()) - if (ID->getVisibility() == HiddenVisibility) - Entry->setVisibility(llvm::GlobalValue::HiddenVisibility); - - if (IsForDefinition) - if (CGM.getTriple().isOSBinFormatMachO()) - Entry->setSection("__DATA,__objc_const"); - - return Entry; -} - -/* *** */ - -CodeGen::CGObjCRuntime * -CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) { - switch (CGM.getLangOpts().ObjCRuntime.getKind()) { - case ObjCRuntime::FragileMacOSX: - return new CGObjCMac(CGM); - - case ObjCRuntime::MacOSX: - case ObjCRuntime::iOS: - case ObjCRuntime::WatchOS: - return new CGObjCNonFragileABIMac(CGM); - - case ObjCRuntime::GNUstep: - case ObjCRuntime::GCC: - case ObjCRuntime::ObjFW: - llvm_unreachable("these runtimes are not Mac runtimes"); - } - llvm_unreachable("bad runtime"); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp deleted file mode 100644 index 4b6f24a03f2..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp +++ /dev/null @@ -1,388 +0,0 @@ -//==- CGObjCRuntime.cpp - Interface to Shared Objective-C Runtime Features ==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This abstract class defines the interface for Objective-C runtime-specific -// code generation. It provides some concrete helper methods for functionality -// shared between all (or most) of the Objective-C runtimes supported by clang. -// -//===----------------------------------------------------------------------===// - -#include "CGObjCRuntime.h" -#include "CGCleanup.h" -#include "CGCXXABI.h" -#include "CGRecordLayout.h" -#include "CodeGenFunction.h" -#include "CodeGenModule.h" -#include "clang/AST/RecordLayout.h" -#include "clang/AST/StmtObjC.h" -#include "clang/CodeGen/CGFunctionInfo.h" -#include "llvm/IR/CallSite.h" -#include "llvm/Support/SaveAndRestore.h" - -using namespace clang; -using namespace CodeGen; - -uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, - const ObjCInterfaceDecl *OID, - const ObjCIvarDecl *Ivar) { - return CGM.getContext().lookupFieldBitOffset(OID, nullptr, Ivar) / - CGM.getContext().getCharWidth(); -} - -uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, - const ObjCImplementationDecl *OID, - const ObjCIvarDecl *Ivar) { - return CGM.getContext().lookupFieldBitOffset(OID->getClassInterface(), OID, - Ivar) / - CGM.getContext().getCharWidth(); -} - -unsigned CGObjCRuntime::ComputeBitfieldBitOffset( - CodeGen::CodeGenModule &CGM, - const ObjCInterfaceDecl *ID, - const ObjCIvarDecl *Ivar) { - return CGM.getContext().lookupFieldBitOffset(ID, ID->getImplementation(), - Ivar); -} - -LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, - const ObjCInterfaceDecl *OID, - llvm::Value *BaseValue, - const ObjCIvarDecl *Ivar, - unsigned CVRQualifiers, - llvm::Value *Offset) { - // Compute (type*) ( (char *) BaseValue + Offset) - QualType InterfaceTy{OID->getTypeForDecl(), 0}; - QualType ObjectPtrTy = - CGF.CGM.getContext().getObjCObjectPointerType(InterfaceTy); - QualType IvarTy = - Ivar->getUsageType(ObjectPtrTy).withCVRQualifiers(CVRQualifiers); - llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy); - llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, CGF.Int8PtrTy); - V = CGF.Builder.CreateInBoundsGEP(V, Offset, "add.ptr"); - - if (!Ivar->isBitField()) { - V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy)); - LValue LV = CGF.MakeNaturalAlignAddrLValue(V, IvarTy); - return LV; - } - - // We need to compute an access strategy for this bit-field. We are given the - // offset to the first byte in the bit-field, the sub-byte offset is taken - // from the original layout. We reuse the normal bit-field access strategy by - // treating this as an access to a struct where the bit-field is in byte 0, - // and adjust the containing type size as appropriate. - // - // FIXME: Note that currently we make a very conservative estimate of the - // alignment of the bit-field, because (a) it is not clear what guarantees the - // runtime makes us, and (b) we don't have a way to specify that the struct is - // at an alignment plus offset. - // - // Note, there is a subtle invariant here: we can only call this routine on - // non-synthesized ivars but we may be called for synthesized ivars. However, - // a synthesized ivar can never be a bit-field, so this is safe. - uint64_t FieldBitOffset = - CGF.CGM.getContext().lookupFieldBitOffset(OID, nullptr, Ivar); - uint64_t BitOffset = FieldBitOffset % CGF.CGM.getContext().getCharWidth(); - uint64_t AlignmentBits = CGF.CGM.getTarget().getCharAlign(); - uint64_t BitFieldSize = Ivar->getBitWidthValue(CGF.getContext()); - CharUnits StorageSize = CGF.CGM.getContext().toCharUnitsFromBits( - llvm::alignTo(BitOffset + BitFieldSize, AlignmentBits)); - CharUnits Alignment = CGF.CGM.getContext().toCharUnitsFromBits(AlignmentBits); - - // Allocate a new CGBitFieldInfo object to describe this access. - // - // FIXME: This is incredibly wasteful, these should be uniqued or part of some - // layout object. However, this is blocked on other cleanups to the - // Objective-C code, so for now we just live with allocating a bunch of these - // objects. - CGBitFieldInfo *Info = new (CGF.CGM.getContext()) CGBitFieldInfo( - CGBitFieldInfo::MakeInfo(CGF.CGM.getTypes(), Ivar, BitOffset, BitFieldSize, - CGF.CGM.getContext().toBits(StorageSize), - CharUnits::fromQuantity(0))); - - Address Addr(V, Alignment); - Addr = CGF.Builder.CreateElementBitCast(Addr, - llvm::Type::getIntNTy(CGF.getLLVMContext(), - Info->StorageSize)); - return LValue::MakeBitfield(Addr, *Info, IvarTy, - LValueBaseInfo(AlignmentSource::Decl), - TBAAAccessInfo()); -} - -namespace { - struct CatchHandler { - const VarDecl *Variable; - const Stmt *Body; - llvm::BasicBlock *Block; - llvm::Constant *TypeInfo; - /// Flags used to differentiate cleanups and catchalls in Windows SEH - unsigned Flags; - }; - - struct CallObjCEndCatch final : EHScopeStack::Cleanup { - CallObjCEndCatch(bool MightThrow, llvm::Value *Fn) - : MightThrow(MightThrow), Fn(Fn) {} - bool MightThrow; - llvm::Value *Fn; - - void Emit(CodeGenFunction &CGF, Flags flags) override { - if (MightThrow) - CGF.EmitRuntimeCallOrInvoke(Fn); - else - CGF.EmitNounwindRuntimeCall(Fn); - } - }; -} - - -void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, - const ObjCAtTryStmt &S, - llvm::Constant *beginCatchFn, - llvm::Constant *endCatchFn, - llvm::Constant *exceptionRethrowFn) { - // Jump destination for falling out of catch bodies. - CodeGenFunction::JumpDest Cont; - if (S.getNumCatchStmts()) - Cont = CGF.getJumpDestInCurrentScope("eh.cont"); - - bool useFunclets = EHPersonality::get(CGF).usesFuncletPads(); - - CodeGenFunction::FinallyInfo FinallyInfo; - if (!useFunclets) - if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) - FinallyInfo.enter(CGF, Finally->getFinallyBody(), - beginCatchFn, endCatchFn, exceptionRethrowFn); - - SmallVector<CatchHandler, 8> Handlers; - - - // Enter the catch, if there is one. - if (S.getNumCatchStmts()) { - for (unsigned I = 0, N = S.getNumCatchStmts(); I != N; ++I) { - const ObjCAtCatchStmt *CatchStmt = S.getCatchStmt(I); - const VarDecl *CatchDecl = CatchStmt->getCatchParamDecl(); - - Handlers.push_back(CatchHandler()); - CatchHandler &Handler = Handlers.back(); - Handler.Variable = CatchDecl; - Handler.Body = CatchStmt->getCatchBody(); - Handler.Block = CGF.createBasicBlock("catch"); - Handler.Flags = 0; - - // @catch(...) always matches. - if (!CatchDecl) { - auto catchAll = getCatchAllTypeInfo(); - Handler.TypeInfo = catchAll.RTTI; - Handler.Flags = catchAll.Flags; - // Don't consider any other catches. - break; - } - - Handler.TypeInfo = GetEHType(CatchDecl->getType()); - } - - EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size()); - for (unsigned I = 0, E = Handlers.size(); I != E; ++I) - Catch->setHandler(I, { Handlers[I].TypeInfo, Handlers[I].Flags }, Handlers[I].Block); - } - - if (useFunclets) - if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) { - CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true); - if (!CGF.CurSEHParent) - CGF.CurSEHParent = cast<NamedDecl>(CGF.CurFuncDecl); - // Outline the finally block. - const Stmt *FinallyBlock = Finally->getFinallyBody(); - HelperCGF.startOutlinedSEHHelper(CGF, /*isFilter*/false, FinallyBlock); - - // Emit the original filter expression, convert to i32, and return. - HelperCGF.EmitStmt(FinallyBlock); - - HelperCGF.FinishFunction(FinallyBlock->getEndLoc()); - - llvm::Function *FinallyFunc = HelperCGF.CurFn; - - - // Push a cleanup for __finally blocks. - CGF.pushSEHCleanup(NormalAndEHCleanup, FinallyFunc); - } - - - // Emit the try body. - CGF.EmitStmt(S.getTryBody()); - - // Leave the try. - if (S.getNumCatchStmts()) - CGF.popCatchScope(); - - // Remember where we were. - CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP(); - - // Emit the handlers. - for (unsigned I = 0, E = Handlers.size(); I != E; ++I) { - CatchHandler &Handler = Handlers[I]; - - CGF.EmitBlock(Handler.Block); - llvm::CatchPadInst *CPI = nullptr; - SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(CGF.CurrentFuncletPad); - if (useFunclets) - if ((CPI = dyn_cast_or_null<llvm::CatchPadInst>(Handler.Block->getFirstNonPHI()))) { - CGF.CurrentFuncletPad = CPI; - CPI->setOperand(2, CGF.getExceptionSlot().getPointer()); - } - llvm::Value *RawExn = CGF.getExceptionFromSlot(); - - // Enter the catch. - llvm::Value *Exn = RawExn; - if (beginCatchFn) - Exn = CGF.EmitNounwindRuntimeCall(beginCatchFn, RawExn, "exn.adjusted"); - - CodeGenFunction::LexicalScope cleanups(CGF, Handler.Body->getSourceRange()); - - if (endCatchFn) { - // Add a cleanup to leave the catch. - bool EndCatchMightThrow = (Handler.Variable == nullptr); - - CGF.EHStack.pushCleanup<CallObjCEndCatch>(NormalAndEHCleanup, - EndCatchMightThrow, - endCatchFn); - } - - // Bind the catch parameter if it exists. - if (const VarDecl *CatchParam = Handler.Variable) { - llvm::Type *CatchType = CGF.ConvertType(CatchParam->getType()); - llvm::Value *CastExn = CGF.Builder.CreateBitCast(Exn, CatchType); - - CGF.EmitAutoVarDecl(*CatchParam); - EmitInitOfCatchParam(CGF, CastExn, CatchParam); - } - if (CPI) - CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI); - - CGF.ObjCEHValueStack.push_back(Exn); - CGF.EmitStmt(Handler.Body); - CGF.ObjCEHValueStack.pop_back(); - - // Leave any cleanups associated with the catch. - cleanups.ForceCleanup(); - - CGF.EmitBranchThroughCleanup(Cont); - } - - // Go back to the try-statement fallthrough. - CGF.Builder.restoreIP(SavedIP); - - // Pop out of the finally. - if (!useFunclets && S.getFinallyStmt()) - FinallyInfo.exit(CGF); - - if (Cont.isValid()) - CGF.EmitBlock(Cont.getBlock()); -} - -void CGObjCRuntime::EmitInitOfCatchParam(CodeGenFunction &CGF, - llvm::Value *exn, - const VarDecl *paramDecl) { - - Address paramAddr = CGF.GetAddrOfLocalVar(paramDecl); - - switch (paramDecl->getType().getQualifiers().getObjCLifetime()) { - case Qualifiers::OCL_Strong: - exn = CGF.EmitARCRetainNonBlock(exn); - LLVM_FALLTHROUGH; - - case Qualifiers::OCL_None: - case Qualifiers::OCL_ExplicitNone: - case Qualifiers::OCL_Autoreleasing: - CGF.Builder.CreateStore(exn, paramAddr); - return; - - case Qualifiers::OCL_Weak: - CGF.EmitARCInitWeak(paramAddr, exn); - return; - } - llvm_unreachable("invalid ownership qualifier"); -} - -namespace { - struct CallSyncExit final : EHScopeStack::Cleanup { - llvm::Value *SyncExitFn; - llvm::Value *SyncArg; - CallSyncExit(llvm::Value *SyncExitFn, llvm::Value *SyncArg) - : SyncExitFn(SyncExitFn), SyncArg(SyncArg) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - CGF.EmitNounwindRuntimeCall(SyncExitFn, SyncArg); - } - }; -} - -void CGObjCRuntime::EmitAtSynchronizedStmt(CodeGenFunction &CGF, - const ObjCAtSynchronizedStmt &S, - llvm::Function *syncEnterFn, - llvm::Function *syncExitFn) { - CodeGenFunction::RunCleanupsScope cleanups(CGF); - - // Evaluate the lock operand. This is guaranteed to dominate the - // ARC release and lock-release cleanups. - const Expr *lockExpr = S.getSynchExpr(); - llvm::Value *lock; - if (CGF.getLangOpts().ObjCAutoRefCount) { - lock = CGF.EmitARCRetainScalarExpr(lockExpr); - lock = CGF.EmitObjCConsumeObject(lockExpr->getType(), lock); - } else { - lock = CGF.EmitScalarExpr(lockExpr); - } - lock = CGF.Builder.CreateBitCast(lock, CGF.VoidPtrTy); - - // Acquire the lock. - CGF.Builder.CreateCall(syncEnterFn, lock)->setDoesNotThrow(); - - // Register an all-paths cleanup to release the lock. - CGF.EHStack.pushCleanup<CallSyncExit>(NormalAndEHCleanup, syncExitFn, lock); - - // Emit the body of the statement. - CGF.EmitStmt(S.getSynchBody()); -} - -/// Compute the pointer-to-function type to which a message send -/// should be casted in order to correctly call the given method -/// with the given arguments. -/// -/// \param method - may be null -/// \param resultType - the result type to use if there's no method -/// \param callArgs - the actual arguments, including implicit ones -CGObjCRuntime::MessageSendInfo -CGObjCRuntime::getMessageSendInfo(const ObjCMethodDecl *method, - QualType resultType, - CallArgList &callArgs) { - // If there's a method, use information from that. - if (method) { - const CGFunctionInfo &signature = - CGM.getTypes().arrangeObjCMessageSendSignature(method, callArgs[0].Ty); - - llvm::PointerType *signatureType = - CGM.getTypes().GetFunctionType(signature)->getPointerTo(); - - const CGFunctionInfo &signatureForCall = - CGM.getTypes().arrangeCall(signature, callArgs); - - return MessageSendInfo(signatureForCall, signatureType); - } - - // There's no method; just use a default CC. - const CGFunctionInfo &argsInfo = - CGM.getTypes().arrangeUnprototypedObjCMessageSend(resultType, callArgs); - - // Derive the signature to call from that. - llvm::PointerType *signatureType = - CGM.getTypes().GetFunctionType(argsInfo)->getPointerTo(); - return MessageSendInfo(argsInfo, signatureType); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h b/gnu/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h deleted file mode 100644 index fa16c198adb..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h +++ /dev/null @@ -1,316 +0,0 @@ -//===----- CGObjCRuntime.h - Interface to ObjC Runtimes ---------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This provides an abstract class for Objective-C code generation. Concrete -// subclasses of this implement code generation for specific Objective-C -// runtime libraries. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CGOBJCRUNTIME_H -#define LLVM_CLANG_LIB_CODEGEN_CGOBJCRUNTIME_H -#include "CGBuilder.h" -#include "CGCall.h" -#include "CGCleanup.h" -#include "CGValue.h" -#include "clang/AST/DeclObjC.h" -#include "clang/Basic/IdentifierTable.h" // Selector - -namespace llvm { - class Constant; - class Function; - class Module; - class StructLayout; - class StructType; - class Type; - class Value; -} - -namespace clang { -namespace CodeGen { - class CodeGenFunction; -} - - class FieldDecl; - class ObjCAtTryStmt; - class ObjCAtThrowStmt; - class ObjCAtSynchronizedStmt; - class ObjCContainerDecl; - class ObjCCategoryImplDecl; - class ObjCImplementationDecl; - class ObjCInterfaceDecl; - class ObjCMessageExpr; - class ObjCMethodDecl; - class ObjCProtocolDecl; - class Selector; - class ObjCIvarDecl; - class ObjCStringLiteral; - class BlockDeclRefExpr; - -namespace CodeGen { - class CodeGenModule; - class CGBlockInfo; - -// FIXME: Several methods should be pure virtual but aren't to avoid the -// partially-implemented subclass breaking. - -/// Implements runtime-specific code generation functions. -class CGObjCRuntime { -protected: - CodeGen::CodeGenModule &CGM; - CGObjCRuntime(CodeGen::CodeGenModule &CGM) : CGM(CGM) {} - - // Utility functions for unified ivar access. These need to - // eventually be folded into other places (the structure layout - // code). - - /// Compute an offset to the given ivar, suitable for passing to - /// EmitValueForIvarAtOffset. Note that the correct handling of - /// bit-fields is carefully coordinated by these two, use caution! - /// - /// The latter overload is suitable for computing the offset of a - /// sythesized ivar. - uint64_t ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, - const ObjCInterfaceDecl *OID, - const ObjCIvarDecl *Ivar); - uint64_t ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, - const ObjCImplementationDecl *OID, - const ObjCIvarDecl *Ivar); - - LValue EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, - const ObjCInterfaceDecl *OID, - llvm::Value *BaseValue, - const ObjCIvarDecl *Ivar, - unsigned CVRQualifiers, - llvm::Value *Offset); - /// Emits a try / catch statement. This function is intended to be called by - /// subclasses, and provides a generic mechanism for generating these, which - /// should be usable by all runtimes. The caller must provide the functions - /// to call when entering and exiting a \@catch() block, and the function - /// used to rethrow exceptions. If the begin and end catch functions are - /// NULL, then the function assumes that the EH personality function provides - /// the thrown object directly. - void EmitTryCatchStmt(CodeGenFunction &CGF, - const ObjCAtTryStmt &S, - llvm::Constant *beginCatchFn, - llvm::Constant *endCatchFn, - llvm::Constant *exceptionRethrowFn); - - void EmitInitOfCatchParam(CodeGenFunction &CGF, llvm::Value *exn, - const VarDecl *paramDecl); - - /// Emits an \@synchronize() statement, using the \p syncEnterFn and - /// \p syncExitFn arguments as the functions called to lock and unlock - /// the object. This function can be called by subclasses that use - /// zero-cost exception handling. - void EmitAtSynchronizedStmt(CodeGenFunction &CGF, - const ObjCAtSynchronizedStmt &S, - llvm::Function *syncEnterFn, - llvm::Function *syncExitFn); - -public: - virtual ~CGObjCRuntime(); - - /// Generate the function required to register all Objective-C components in - /// this compilation unit with the runtime library. - virtual llvm::Function *ModuleInitFunction() = 0; - - /// Get a selector for the specified name and type values. - /// The result should have the LLVM type for ASTContext::getObjCSelType(). - virtual llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) = 0; - - /// Get the address of a selector for the specified name and type values. - /// This is a rarely-used language extension, but sadly it exists. - /// - /// The result should have the LLVM type for a pointer to - /// ASTContext::getObjCSelType(). - virtual Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) = 0; - - /// Get a typed selector. - virtual llvm::Value *GetSelector(CodeGenFunction &CGF, - const ObjCMethodDecl *Method) = 0; - - /// Get the type constant to catch for the given ObjC pointer type. - /// This is used externally to implement catching ObjC types in C++. - /// Runtimes which don't support this should add the appropriate - /// error to Sema. - virtual llvm::Constant *GetEHType(QualType T) = 0; - - virtual CatchTypeInfo getCatchAllTypeInfo() { return { nullptr, 0 }; } - - /// Generate a constant string object. - virtual ConstantAddress GenerateConstantString(const StringLiteral *) = 0; - - /// Generate a category. A category contains a list of methods (and - /// accompanying metadata) and a list of protocols. - virtual void GenerateCategory(const ObjCCategoryImplDecl *OCD) = 0; - - /// Generate a class structure for this class. - virtual void GenerateClass(const ObjCImplementationDecl *OID) = 0; - - /// Register an class alias. - virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) = 0; - - /// Generate an Objective-C message send operation. - /// - /// \param Method - The method being called, this may be null if synthesizing - /// a property setter or getter. - virtual CodeGen::RValue - GenerateMessageSend(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot ReturnSlot, - QualType ResultType, - Selector Sel, - llvm::Value *Receiver, - const CallArgList &CallArgs, - const ObjCInterfaceDecl *Class = nullptr, - const ObjCMethodDecl *Method = nullptr) = 0; - - /// Generate an Objective-C message send operation to the super - /// class initiated in a method for Class and with the given Self - /// object. - /// - /// \param Method - The method being called, this may be null if synthesizing - /// a property setter or getter. - virtual CodeGen::RValue - GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot ReturnSlot, - QualType ResultType, - Selector Sel, - const ObjCInterfaceDecl *Class, - bool isCategoryImpl, - llvm::Value *Self, - bool IsClassMessage, - const CallArgList &CallArgs, - const ObjCMethodDecl *Method = nullptr) = 0; - - /// Emit the code to return the named protocol as an object, as in a - /// \@protocol expression. - virtual llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF, - const ObjCProtocolDecl *OPD) = 0; - - /// Generate the named protocol. Protocols contain method metadata but no - /// implementations. - virtual void GenerateProtocol(const ObjCProtocolDecl *OPD) = 0; - - /// Generate a function preamble for a method with the specified - /// types. - - // FIXME: Current this just generates the Function definition, but really this - // should also be generating the loads of the parameters, as the runtime - // should have full control over how parameters are passed. - virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, - const ObjCContainerDecl *CD) = 0; - - /// Return the runtime function for getting properties. - virtual llvm::Constant *GetPropertyGetFunction() = 0; - - /// Return the runtime function for setting properties. - virtual llvm::Constant *GetPropertySetFunction() = 0; - - /// Return the runtime function for optimized setting properties. - virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic, - bool copy) = 0; - - // API for atomic copying of qualified aggregates in getter. - virtual llvm::Constant *GetGetStructFunction() = 0; - // API for atomic copying of qualified aggregates in setter. - virtual llvm::Constant *GetSetStructFunction() = 0; - /// API for atomic copying of qualified aggregates with non-trivial copy - /// assignment (c++) in setter. - virtual llvm::Constant *GetCppAtomicObjectSetFunction() = 0; - /// API for atomic copying of qualified aggregates with non-trivial copy - /// assignment (c++) in getter. - virtual llvm::Constant *GetCppAtomicObjectGetFunction() = 0; - - /// GetClass - Return a reference to the class for the given - /// interface decl. - virtual llvm::Value *GetClass(CodeGenFunction &CGF, - const ObjCInterfaceDecl *OID) = 0; - - - virtual llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) { - llvm_unreachable("autoreleasepool unsupported in this ABI"); - } - - /// EnumerationMutationFunction - Return the function that's called by the - /// compiler when a mutation is detected during foreach iteration. - virtual llvm::Constant *EnumerationMutationFunction() = 0; - - virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, - const ObjCAtSynchronizedStmt &S) = 0; - virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF, - const ObjCAtTryStmt &S) = 0; - virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, - const ObjCAtThrowStmt &S, - bool ClearInsertionPoint=true) = 0; - virtual llvm::Value *EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, - Address AddrWeakObj) = 0; - virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dest) = 0; - virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dest, - bool threadlocal=false) = 0; - virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dest, - llvm::Value *ivarOffset) = 0; - virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dest) = 0; - - virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, - QualType ObjectTy, - llvm::Value *BaseValue, - const ObjCIvarDecl *Ivar, - unsigned CVRQualifiers) = 0; - virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, - const ObjCInterfaceDecl *Interface, - const ObjCIvarDecl *Ivar) = 0; - virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, - Address DestPtr, - Address SrcPtr, - llvm::Value *Size) = 0; - virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM, - const CodeGen::CGBlockInfo &blockInfo) = 0; - virtual llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM, - const CodeGen::CGBlockInfo &blockInfo) = 0; - virtual std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM, - const CGBlockInfo &blockInfo) { - return {}; - } - - /// Returns an i8* which points to the byref layout information. - virtual llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM, - QualType T) = 0; - - struct MessageSendInfo { - const CGFunctionInfo &CallInfo; - llvm::PointerType *MessengerType; - - MessageSendInfo(const CGFunctionInfo &callInfo, - llvm::PointerType *messengerType) - : CallInfo(callInfo), MessengerType(messengerType) {} - }; - - MessageSendInfo getMessageSendInfo(const ObjCMethodDecl *method, - QualType resultType, - CallArgList &callArgs); - - // FIXME: This probably shouldn't be here, but the code to compute - // it is here. - unsigned ComputeBitfieldBitOffset(CodeGen::CodeGenModule &CGM, - const ObjCInterfaceDecl *ID, - const ObjCIvarDecl *Ivar); -}; - -/// Creates an instance of an Objective-C runtime class. -//TODO: This should include some way of selecting which runtime to target. -CGObjCRuntime *CreateGNUObjCRuntime(CodeGenModule &CGM); -CGObjCRuntime *CreateMacObjCRuntime(CodeGenModule &CGM); -} -} -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.cpp deleted file mode 100644 index 7f6f595dd5d..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.cpp +++ /dev/null @@ -1,173 +0,0 @@ -//===----- CGOpenCLRuntime.cpp - Interface to OpenCL Runtimes -------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This provides an abstract class for OpenCL code generation. Concrete -// subclasses of this implement code generation for specific OpenCL -// runtime libraries. -// -//===----------------------------------------------------------------------===// - -#include "CGOpenCLRuntime.h" -#include "CodeGenFunction.h" -#include "TargetInfo.h" -#include "clang/CodeGen/ConstantInitBuilder.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/GlobalValue.h" -#include <assert.h> - -using namespace clang; -using namespace CodeGen; - -CGOpenCLRuntime::~CGOpenCLRuntime() {} - -void CGOpenCLRuntime::EmitWorkGroupLocalVarDecl(CodeGenFunction &CGF, - const VarDecl &D) { - return CGF.EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage); -} - -llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) { - assert(T->isOpenCLSpecificType() && - "Not an OpenCL specific type!"); - - llvm::LLVMContext& Ctx = CGM.getLLVMContext(); - uint32_t AddrSpc = CGM.getContext().getTargetAddressSpace( - CGM.getContext().getOpenCLTypeAddrSpace(T)); - switch (cast<BuiltinType>(T)->getKind()) { - default: - llvm_unreachable("Unexpected opencl builtin type!"); - return nullptr; -#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ - case BuiltinType::Id: \ - return llvm::PointerType::get( \ - llvm::StructType::create(Ctx, "opencl." #ImgType "_" #Suffix "_t"), \ - AddrSpc); -#include "clang/Basic/OpenCLImageTypes.def" - case BuiltinType::OCLSampler: - return getSamplerType(T); - case BuiltinType::OCLEvent: - return llvm::PointerType::get( - llvm::StructType::create(Ctx, "opencl.event_t"), AddrSpc); - case BuiltinType::OCLClkEvent: - return llvm::PointerType::get( - llvm::StructType::create(Ctx, "opencl.clk_event_t"), AddrSpc); - case BuiltinType::OCLQueue: - return llvm::PointerType::get( - llvm::StructType::create(Ctx, "opencl.queue_t"), AddrSpc); - case BuiltinType::OCLReserveID: - return llvm::PointerType::get( - llvm::StructType::create(Ctx, "opencl.reserve_id_t"), AddrSpc); -#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ - case BuiltinType::Id: \ - return llvm::PointerType::get( \ - llvm::StructType::create(Ctx, "opencl." #ExtType), AddrSpc); -#include "clang/Basic/OpenCLExtensionTypes.def" - } -} - -llvm::Type *CGOpenCLRuntime::getPipeType(const PipeType *T) { - if (T->isReadOnly()) - return getPipeType(T, "opencl.pipe_ro_t", PipeROTy); - else - return getPipeType(T, "opencl.pipe_wo_t", PipeWOTy); -} - -llvm::Type *CGOpenCLRuntime::getPipeType(const PipeType *T, StringRef Name, - llvm::Type *&PipeTy) { - if (!PipeTy) - PipeTy = llvm::PointerType::get(llvm::StructType::create( - CGM.getLLVMContext(), Name), - CGM.getContext().getTargetAddressSpace( - CGM.getContext().getOpenCLTypeAddrSpace(T))); - return PipeTy; -} - -llvm::PointerType *CGOpenCLRuntime::getSamplerType(const Type *T) { - if (!SamplerTy) - SamplerTy = llvm::PointerType::get(llvm::StructType::create( - CGM.getLLVMContext(), "opencl.sampler_t"), - CGM.getContext().getTargetAddressSpace( - CGM.getContext().getOpenCLTypeAddrSpace(T))); - return SamplerTy; -} - -llvm::Value *CGOpenCLRuntime::getPipeElemSize(const Expr *PipeArg) { - const PipeType *PipeTy = PipeArg->getType()->getAs<PipeType>(); - // The type of the last (implicit) argument to be passed. - llvm::Type *Int32Ty = llvm::IntegerType::getInt32Ty(CGM.getLLVMContext()); - unsigned TypeSize = CGM.getContext() - .getTypeSizeInChars(PipeTy->getElementType()) - .getQuantity(); - return llvm::ConstantInt::get(Int32Ty, TypeSize, false); -} - -llvm::Value *CGOpenCLRuntime::getPipeElemAlign(const Expr *PipeArg) { - const PipeType *PipeTy = PipeArg->getType()->getAs<PipeType>(); - // The type of the last (implicit) argument to be passed. - llvm::Type *Int32Ty = llvm::IntegerType::getInt32Ty(CGM.getLLVMContext()); - unsigned TypeSize = CGM.getContext() - .getTypeAlignInChars(PipeTy->getElementType()) - .getQuantity(); - return llvm::ConstantInt::get(Int32Ty, TypeSize, false); -} - -llvm::PointerType *CGOpenCLRuntime::getGenericVoidPointerType() { - assert(CGM.getLangOpts().OpenCL); - return llvm::IntegerType::getInt8PtrTy( - CGM.getLLVMContext(), - CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic)); -} - -/// Record emitted llvm invoke function and llvm block literal for the -/// corresponding block expression. -void CGOpenCLRuntime::recordBlockInfo(const BlockExpr *E, - llvm::Function *InvokeF, - llvm::Value *Block) { - assert(EnqueuedBlockMap.find(E) == EnqueuedBlockMap.end() && - "Block expression emitted twice"); - assert(isa<llvm::Function>(InvokeF) && "Invalid invoke function"); - assert(Block->getType()->isPointerTy() && "Invalid block literal type"); - EnqueuedBlockMap[E].InvokeFunc = InvokeF; - EnqueuedBlockMap[E].BlockArg = Block; - EnqueuedBlockMap[E].Kernel = nullptr; -} - -CGOpenCLRuntime::EnqueuedBlockInfo -CGOpenCLRuntime::emitOpenCLEnqueuedBlock(CodeGenFunction &CGF, const Expr *E) { - CGF.EmitScalarExpr(E); - - // The block literal may be assigned to a const variable. Chasing down - // to get the block literal. - if (auto DR = dyn_cast<DeclRefExpr>(E)) { - E = cast<VarDecl>(DR->getDecl())->getInit(); - } - E = E->IgnoreImplicit(); - if (auto Cast = dyn_cast<CastExpr>(E)) { - E = Cast->getSubExpr(); - } - auto *Block = cast<BlockExpr>(E); - - assert(EnqueuedBlockMap.find(Block) != EnqueuedBlockMap.end() && - "Block expression not emitted"); - - // Do not emit the block wrapper again if it has been emitted. - if (EnqueuedBlockMap[Block].Kernel) { - return EnqueuedBlockMap[Block]; - } - - auto *F = CGF.getTargetHooks().createEnqueuedBlockKernel( - CGF, EnqueuedBlockMap[Block].InvokeFunc, - EnqueuedBlockMap[Block].BlockArg->stripPointerCasts()); - - // The common part of the post-processing of the kernel goes here. - F->addFnAttr(llvm::Attribute::NoUnwind); - F->setCallingConv( - CGF.getTypes().ClangCallConvToLLVMCallConv(CallingConv::CC_OpenCLKernel)); - EnqueuedBlockMap[Block].Kernel = F; - return EnqueuedBlockMap[Block]; -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.h b/gnu/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.h deleted file mode 100644 index 750721f1b80..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.h +++ /dev/null @@ -1,100 +0,0 @@ -//===----- CGOpenCLRuntime.h - Interface to OpenCL Runtimes -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This provides an abstract class for OpenCL code generation. Concrete -// subclasses of this implement code generation for specific OpenCL -// runtime libraries. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CGOPENCLRUNTIME_H -#define LLVM_CLANG_LIB_CODEGEN_CGOPENCLRUNTIME_H - -#include "clang/AST/Expr.h" -#include "clang/AST/Type.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/Value.h" - -namespace clang { - -class BlockExpr; -class Expr; -class VarDecl; - -namespace CodeGen { - -class CodeGenFunction; -class CodeGenModule; - -class CGOpenCLRuntime { -protected: - CodeGenModule &CGM; - llvm::Type *PipeROTy; - llvm::Type *PipeWOTy; - llvm::PointerType *SamplerTy; - - /// Structure for enqueued block information. - struct EnqueuedBlockInfo { - llvm::Function *InvokeFunc; /// Block invoke function. - llvm::Function *Kernel; /// Enqueued block kernel. - llvm::Value *BlockArg; /// The first argument to enqueued block kernel. - }; - /// Maps block expression to block information. - llvm::DenseMap<const Expr *, EnqueuedBlockInfo> EnqueuedBlockMap; - - virtual llvm::Type *getPipeType(const PipeType *T, StringRef Name, - llvm::Type *&PipeTy); - -public: - CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM), - PipeROTy(nullptr), PipeWOTy(nullptr), SamplerTy(nullptr) {} - virtual ~CGOpenCLRuntime(); - - /// Emit the IR required for a work-group-local variable declaration, and add - /// an entry to CGF's LocalDeclMap for D. The base class does this using - /// CodeGenFunction::EmitStaticVarDecl to emit an internal global for D. - virtual void EmitWorkGroupLocalVarDecl(CodeGenFunction &CGF, - const VarDecl &D); - - virtual llvm::Type *convertOpenCLSpecificType(const Type *T); - - virtual llvm::Type *getPipeType(const PipeType *T); - - llvm::PointerType *getSamplerType(const Type *T); - - // Returns a value which indicates the size in bytes of the pipe - // element. - virtual llvm::Value *getPipeElemSize(const Expr *PipeArg); - - // Returns a value which indicates the alignment in bytes of the pipe - // element. - virtual llvm::Value *getPipeElemAlign(const Expr *PipeArg); - - /// \return __generic void* type. - llvm::PointerType *getGenericVoidPointerType(); - - /// \return enqueued block information for enqueued block. - EnqueuedBlockInfo emitOpenCLEnqueuedBlock(CodeGenFunction &CGF, - const Expr *E); - - /// Record invoke function and block literal emitted during normal - /// codegen for a block expression. The information is used by - /// emitOpenCLEnqueuedBlock to emit wrapper kernel. - /// - /// \param InvokeF invoke function emitted for the block expression. - /// \param Block block literal emitted for the block expression. - void recordBlockInfo(const BlockExpr *E, llvm::Function *InvokeF, - llvm::Value *Block); -}; - -} -} - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp deleted file mode 100644 index 20eb0b29f42..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ /dev/null @@ -1,9860 +0,0 @@ -//===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This provides a class for OpenMP runtime code generation. -// -//===----------------------------------------------------------------------===// - -#include "CGCXXABI.h" -#include "CGCleanup.h" -#include "CGOpenMPRuntime.h" -#include "CGRecordLayout.h" -#include "CodeGenFunction.h" -#include "clang/CodeGen/ConstantInitBuilder.h" -#include "clang/AST/Decl.h" -#include "clang/AST/StmtOpenMP.h" -#include "clang/Basic/BitmaskEnum.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/Bitcode/BitcodeReader.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> - -using namespace clang; -using namespace CodeGen; - -namespace { -/// Base class for handling code generation inside OpenMP regions. -class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { -public: - /// Kinds of OpenMP regions used in codegen. - enum CGOpenMPRegionKind { - /// Region with outlined function for standalone 'parallel' - /// directive. - ParallelOutlinedRegion, - /// Region with outlined function for standalone 'task' directive. - TaskOutlinedRegion, - /// Region for constructs that do not require function outlining, - /// like 'for', 'sections', 'atomic' etc. directives. - InlinedRegion, - /// Region with outlined function for standalone 'target' directive. - TargetRegion, - }; - - CGOpenMPRegionInfo(const CapturedStmt &CS, - const CGOpenMPRegionKind RegionKind, - const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, - bool HasCancel) - : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), - CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} - - CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, - const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, - bool HasCancel) - : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), - Kind(Kind), HasCancel(HasCancel) {} - - /// Get a variable or parameter for storing global thread id - /// inside OpenMP construct. - virtual const VarDecl *getThreadIDVariable() const = 0; - - /// Emit the captured statement body. - void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; - - /// Get an LValue for the current ThreadID variable. - /// \return LValue for thread id variable. This LValue always has type int32*. - virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); - - virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} - - CGOpenMPRegionKind getRegionKind() const { return RegionKind; } - - OpenMPDirectiveKind getDirectiveKind() const { return Kind; } - - bool hasCancel() const { return HasCancel; } - - static bool classof(const CGCapturedStmtInfo *Info) { - return Info->getKind() == CR_OpenMP; - } - - ~CGOpenMPRegionInfo() override = default; - -protected: - CGOpenMPRegionKind RegionKind; - RegionCodeGenTy CodeGen; - OpenMPDirectiveKind Kind; - bool HasCancel; -}; - -/// API for captured statement code generation in OpenMP constructs. -class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { -public: - CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, - const RegionCodeGenTy &CodeGen, - OpenMPDirectiveKind Kind, bool HasCancel, - StringRef HelperName) - : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, - HasCancel), - ThreadIDVar(ThreadIDVar), HelperName(HelperName) { - assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); - } - - /// Get a variable or parameter for storing global thread id - /// inside OpenMP construct. - const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } - - /// Get the name of the capture helper. - StringRef getHelperName() const override { return HelperName; } - - static bool classof(const CGCapturedStmtInfo *Info) { - return CGOpenMPRegionInfo::classof(Info) && - cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == - ParallelOutlinedRegion; - } - -private: - /// A variable or parameter storing global thread id for OpenMP - /// constructs. - const VarDecl *ThreadIDVar; - StringRef HelperName; -}; - -/// API for captured statement code generation in OpenMP constructs. -class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { -public: - class UntiedTaskActionTy final : public PrePostActionTy { - bool Untied; - const VarDecl *PartIDVar; - const RegionCodeGenTy UntiedCodeGen; - llvm::SwitchInst *UntiedSwitch = nullptr; - - public: - UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, - const RegionCodeGenTy &UntiedCodeGen) - : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} - void Enter(CodeGenFunction &CGF) override { - if (Untied) { - // Emit task switching point. - LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( - CGF.GetAddrOfLocalVar(PartIDVar), - PartIDVar->getType()->castAs<PointerType>()); - llvm::Value *Res = - CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation()); - llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done."); - UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); - CGF.EmitBlock(DoneBB); - CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); - CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); - UntiedSwitch->addCase(CGF.Builder.getInt32(0), - CGF.Builder.GetInsertBlock()); - emitUntiedSwitch(CGF); - } - } - void emitUntiedSwitch(CodeGenFunction &CGF) const { - if (Untied) { - LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( - CGF.GetAddrOfLocalVar(PartIDVar), - PartIDVar->getType()->castAs<PointerType>()); - CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), - PartIdLVal); - UntiedCodeGen(CGF); - CodeGenFunction::JumpDest CurPoint = - CGF.getJumpDestInCurrentScope(".untied.next."); - CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); - CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); - UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), - CGF.Builder.GetInsertBlock()); - CGF.EmitBranchThroughCleanup(CurPoint); - CGF.EmitBlock(CurPoint.getBlock()); - } - } - unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } - }; - CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, - const VarDecl *ThreadIDVar, - const RegionCodeGenTy &CodeGen, - OpenMPDirectiveKind Kind, bool HasCancel, - const UntiedTaskActionTy &Action) - : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), - ThreadIDVar(ThreadIDVar), Action(Action) { - assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); - } - - /// Get a variable or parameter for storing global thread id - /// inside OpenMP construct. - const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } - - /// Get an LValue for the current ThreadID variable. - LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; - - /// Get the name of the capture helper. - StringRef getHelperName() const override { return ".omp_outlined."; } - - void emitUntiedSwitch(CodeGenFunction &CGF) override { - Action.emitUntiedSwitch(CGF); - } - - static bool classof(const CGCapturedStmtInfo *Info) { - return CGOpenMPRegionInfo::classof(Info) && - cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == - TaskOutlinedRegion; - } - -private: - /// A variable or parameter storing global thread id for OpenMP - /// constructs. - const VarDecl *ThreadIDVar; - /// Action for emitting code for untied tasks. - const UntiedTaskActionTy &Action; -}; - -/// API for inlined captured statement code generation in OpenMP -/// constructs. -class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { -public: - CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, - const RegionCodeGenTy &CodeGen, - OpenMPDirectiveKind Kind, bool HasCancel) - : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), - OldCSI(OldCSI), - OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} - - // Retrieve the value of the context parameter. - llvm::Value *getContextValue() const override { - if (OuterRegionInfo) - return OuterRegionInfo->getContextValue(); - llvm_unreachable("No context value for inlined OpenMP region"); - } - - void setContextValue(llvm::Value *V) override { - if (OuterRegionInfo) { - OuterRegionInfo->setContextValue(V); - return; - } - llvm_unreachable("No context value for inlined OpenMP region"); - } - - /// Lookup the captured field decl for a variable. - const FieldDecl *lookup(const VarDecl *VD) const override { - if (OuterRegionInfo) - return OuterRegionInfo->lookup(VD); - // If there is no outer outlined region,no need to lookup in a list of - // captured variables, we can use the original one. - return nullptr; - } - - FieldDecl *getThisFieldDecl() const override { - if (OuterRegionInfo) - return OuterRegionInfo->getThisFieldDecl(); - return nullptr; - } - - /// Get a variable or parameter for storing global thread id - /// inside OpenMP construct. - const VarDecl *getThreadIDVariable() const override { - if (OuterRegionInfo) - return OuterRegionInfo->getThreadIDVariable(); - return nullptr; - } - - /// Get an LValue for the current ThreadID variable. - LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { - if (OuterRegionInfo) - return OuterRegionInfo->getThreadIDVariableLValue(CGF); - llvm_unreachable("No LValue for inlined OpenMP construct"); - } - - /// Get the name of the capture helper. - StringRef getHelperName() const override { - if (auto *OuterRegionInfo = getOldCSI()) - return OuterRegionInfo->getHelperName(); - llvm_unreachable("No helper name for inlined OpenMP construct"); - } - - void emitUntiedSwitch(CodeGenFunction &CGF) override { - if (OuterRegionInfo) - OuterRegionInfo->emitUntiedSwitch(CGF); - } - - CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } - - static bool classof(const CGCapturedStmtInfo *Info) { - return CGOpenMPRegionInfo::classof(Info) && - cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; - } - - ~CGOpenMPInlinedRegionInfo() override = default; - -private: - /// CodeGen info about outer OpenMP region. - CodeGenFunction::CGCapturedStmtInfo *OldCSI; - CGOpenMPRegionInfo *OuterRegionInfo; -}; - -/// API for captured statement code generation in OpenMP target -/// constructs. For this captures, implicit parameters are used instead of the -/// captured fields. The name of the target region has to be unique in a given -/// application so it is provided by the client, because only the client has -/// the information to generate that. -class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { -public: - CGOpenMPTargetRegionInfo(const CapturedStmt &CS, - const RegionCodeGenTy &CodeGen, StringRef HelperName) - : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, - /*HasCancel=*/false), - HelperName(HelperName) {} - - /// This is unused for target regions because each starts executing - /// with a single thread. - const VarDecl *getThreadIDVariable() const override { return nullptr; } - - /// Get the name of the capture helper. - StringRef getHelperName() const override { return HelperName; } - - static bool classof(const CGCapturedStmtInfo *Info) { - return CGOpenMPRegionInfo::classof(Info) && - cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; - } - -private: - StringRef HelperName; -}; - -static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { - llvm_unreachable("No codegen for expressions"); -} -/// API for generation of expressions captured in a innermost OpenMP -/// region. -class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { -public: - CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) - : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, - OMPD_unknown, - /*HasCancel=*/false), - PrivScope(CGF) { - // Make sure the globals captured in the provided statement are local by - // using the privatization logic. We assume the same variable is not - // captured more than once. - for (const auto &C : CS.captures()) { - if (!C.capturesVariable() && !C.capturesVariableByCopy()) - continue; - - const VarDecl *VD = C.getCapturedVar(); - if (VD->isLocalVarDeclOrParm()) - continue; - - DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), - /*RefersToEnclosingVariableOrCapture=*/false, - VD->getType().getNonReferenceType(), VK_LValue, - C.getLocation()); - PrivScope.addPrivate( - VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(); }); - } - (void)PrivScope.Privatize(); - } - - /// Lookup the captured field decl for a variable. - const FieldDecl *lookup(const VarDecl *VD) const override { - if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) - return FD; - return nullptr; - } - - /// Emit the captured statement body. - void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { - llvm_unreachable("No body for expressions"); - } - - /// Get a variable or parameter for storing global thread id - /// inside OpenMP construct. - const VarDecl *getThreadIDVariable() const override { - llvm_unreachable("No thread id for expressions"); - } - - /// Get the name of the capture helper. - StringRef getHelperName() const override { - llvm_unreachable("No helper name for expressions"); - } - - static bool classof(const CGCapturedStmtInfo *Info) { return false; } - -private: - /// Private scope to capture global variables. - CodeGenFunction::OMPPrivateScope PrivScope; -}; - -/// RAII for emitting code of OpenMP constructs. -class InlinedOpenMPRegionRAII { - CodeGenFunction &CGF; - llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; - FieldDecl *LambdaThisCaptureField = nullptr; - const CodeGen::CGBlockInfo *BlockInfo = nullptr; - -public: - /// Constructs region for combined constructs. - /// \param CodeGen Code generation sequence for combined directives. Includes - /// a list of functions used for code generation of implicitly inlined - /// regions. - InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, - OpenMPDirectiveKind Kind, bool HasCancel) - : CGF(CGF) { - // Start emission for the construct. - CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( - CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); - std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); - LambdaThisCaptureField = CGF.LambdaThisCaptureField; - CGF.LambdaThisCaptureField = nullptr; - BlockInfo = CGF.BlockInfo; - CGF.BlockInfo = nullptr; - } - - ~InlinedOpenMPRegionRAII() { - // Restore original CapturedStmtInfo only if we're done with code emission. - auto *OldCSI = - cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); - delete CGF.CapturedStmtInfo; - CGF.CapturedStmtInfo = OldCSI; - std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); - CGF.LambdaThisCaptureField = LambdaThisCaptureField; - CGF.BlockInfo = BlockInfo; - } -}; - -/// Values for bit flags used in the ident_t to describe the fields. -/// All enumeric elements are named and described in accordance with the code -/// from http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h -enum OpenMPLocationFlags : unsigned { - /// Use trampoline for internal microtask. - OMP_IDENT_IMD = 0x01, - /// Use c-style ident structure. - OMP_IDENT_KMPC = 0x02, - /// Atomic reduction option for kmpc_reduce. - OMP_ATOMIC_REDUCE = 0x10, - /// Explicit 'barrier' directive. - OMP_IDENT_BARRIER_EXPL = 0x20, - /// Implicit barrier in code. - OMP_IDENT_BARRIER_IMPL = 0x40, - /// Implicit barrier in 'for' directive. - OMP_IDENT_BARRIER_IMPL_FOR = 0x40, - /// Implicit barrier in 'sections' directive. - OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, - /// Implicit barrier in 'single' directive. - OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140, - /// Call of __kmp_for_static_init for static loop. - OMP_IDENT_WORK_LOOP = 0x200, - /// Call of __kmp_for_static_init for sections. - OMP_IDENT_WORK_SECTIONS = 0x400, - /// Call of __kmp_for_static_init for distribute. - OMP_IDENT_WORK_DISTRIBUTE = 0x800, - LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE) -}; - -/// Describes ident structure that describes a source location. -/// All descriptions are taken from -/// http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h -/// Original structure: -/// typedef struct ident { -/// kmp_int32 reserved_1; /**< might be used in Fortran; -/// see above */ -/// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; -/// KMP_IDENT_KMPC identifies this union -/// member */ -/// kmp_int32 reserved_2; /**< not really used in Fortran any more; -/// see above */ -///#if USE_ITT_BUILD -/// /* but currently used for storing -/// region-specific ITT */ -/// /* contextual information. */ -///#endif /* USE_ITT_BUILD */ -/// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for -/// C++ */ -/// char const *psource; /**< String describing the source location. -/// The string is composed of semi-colon separated -// fields which describe the source file, -/// the function and a pair of line numbers that -/// delimit the construct. -/// */ -/// } ident_t; -enum IdentFieldIndex { - /// might be used in Fortran - IdentField_Reserved_1, - /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. - IdentField_Flags, - /// Not really used in Fortran any more - IdentField_Reserved_2, - /// Source[4] in Fortran, do not use for C++ - IdentField_Reserved_3, - /// String describing the source location. The string is composed of - /// semi-colon separated fields which describe the source file, the function - /// and a pair of line numbers that delimit the construct. - IdentField_PSource -}; - -/// Schedule types for 'omp for' loops (these enumerators are taken from -/// the enum sched_type in kmp.h). -enum OpenMPSchedType { - /// Lower bound for default (unordered) versions. - OMP_sch_lower = 32, - OMP_sch_static_chunked = 33, - OMP_sch_static = 34, - OMP_sch_dynamic_chunked = 35, - OMP_sch_guided_chunked = 36, - OMP_sch_runtime = 37, - OMP_sch_auto = 38, - /// static with chunk adjustment (e.g., simd) - OMP_sch_static_balanced_chunked = 45, - /// Lower bound for 'ordered' versions. - OMP_ord_lower = 64, - OMP_ord_static_chunked = 65, - OMP_ord_static = 66, - OMP_ord_dynamic_chunked = 67, - OMP_ord_guided_chunked = 68, - OMP_ord_runtime = 69, - OMP_ord_auto = 70, - OMP_sch_default = OMP_sch_static, - /// dist_schedule types - OMP_dist_sch_static_chunked = 91, - OMP_dist_sch_static = 92, - /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. - /// Set if the monotonic schedule modifier was present. - OMP_sch_modifier_monotonic = (1 << 29), - /// Set if the nonmonotonic schedule modifier was present. - OMP_sch_modifier_nonmonotonic = (1 << 30), -}; - -enum OpenMPRTLFunction { - /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, - /// kmpc_micro microtask, ...); - OMPRTL__kmpc_fork_call, - /// Call to void *__kmpc_threadprivate_cached(ident_t *loc, - /// kmp_int32 global_tid, void *data, size_t size, void ***cache); - OMPRTL__kmpc_threadprivate_cached, - /// Call to void __kmpc_threadprivate_register( ident_t *, - /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); - OMPRTL__kmpc_threadprivate_register, - // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc); - OMPRTL__kmpc_global_thread_num, - // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, - // kmp_critical_name *crit); - OMPRTL__kmpc_critical, - // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 - // global_tid, kmp_critical_name *crit, uintptr_t hint); - OMPRTL__kmpc_critical_with_hint, - // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, - // kmp_critical_name *crit); - OMPRTL__kmpc_end_critical, - // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 - // global_tid); - OMPRTL__kmpc_cancel_barrier, - // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); - OMPRTL__kmpc_barrier, - // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); - OMPRTL__kmpc_for_static_fini, - // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 - // global_tid); - OMPRTL__kmpc_serialized_parallel, - // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 - // global_tid); - OMPRTL__kmpc_end_serialized_parallel, - // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, - // kmp_int32 num_threads); - OMPRTL__kmpc_push_num_threads, - // Call to void __kmpc_flush(ident_t *loc); - OMPRTL__kmpc_flush, - // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid); - OMPRTL__kmpc_master, - // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid); - OMPRTL__kmpc_end_master, - // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, - // int end_part); - OMPRTL__kmpc_omp_taskyield, - // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); - OMPRTL__kmpc_single, - // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid); - OMPRTL__kmpc_end_single, - // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, - // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, - // kmp_routine_entry_t *task_entry); - OMPRTL__kmpc_omp_task_alloc, - // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t * - // new_task); - OMPRTL__kmpc_omp_task, - // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, - // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), - // kmp_int32 didit); - OMPRTL__kmpc_copyprivate, - // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, - // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void - // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); - OMPRTL__kmpc_reduce, - // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 - // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, - // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name - // *lck); - OMPRTL__kmpc_reduce_nowait, - // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, - // kmp_critical_name *lck); - OMPRTL__kmpc_end_reduce, - // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, - // kmp_critical_name *lck); - OMPRTL__kmpc_end_reduce_nowait, - // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, - // kmp_task_t * new_task); - OMPRTL__kmpc_omp_task_begin_if0, - // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, - // kmp_task_t * new_task); - OMPRTL__kmpc_omp_task_complete_if0, - // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); - OMPRTL__kmpc_ordered, - // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); - OMPRTL__kmpc_end_ordered, - // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 - // global_tid); - OMPRTL__kmpc_omp_taskwait, - // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); - OMPRTL__kmpc_taskgroup, - // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); - OMPRTL__kmpc_end_taskgroup, - // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, - // int proc_bind); - OMPRTL__kmpc_push_proc_bind, - // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32 - // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t - // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); - OMPRTL__kmpc_omp_task_with_deps, - // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 - // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 - // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); - OMPRTL__kmpc_omp_wait_deps, - // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 - // global_tid, kmp_int32 cncl_kind); - OMPRTL__kmpc_cancellationpoint, - // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, - // kmp_int32 cncl_kind); - OMPRTL__kmpc_cancel, - // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, - // kmp_int32 num_teams, kmp_int32 thread_limit); - OMPRTL__kmpc_push_num_teams, - // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro - // microtask, ...); - OMPRTL__kmpc_fork_teams, - // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int - // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int - // sched, kmp_uint64 grainsize, void *task_dup); - OMPRTL__kmpc_taskloop, - // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 - // num_dims, struct kmp_dim *dims); - OMPRTL__kmpc_doacross_init, - // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); - OMPRTL__kmpc_doacross_fini, - // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 - // *vec); - OMPRTL__kmpc_doacross_post, - // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 - // *vec); - OMPRTL__kmpc_doacross_wait, - // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void - // *data); - OMPRTL__kmpc_task_reduction_init, - // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void - // *d); - OMPRTL__kmpc_task_reduction_get_th_data, - - // - // Offloading related calls - // - // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 - // size); - OMPRTL__kmpc_push_target_tripcount, - // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t - // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t - // *arg_types); - OMPRTL__tgt_target, - // Call to int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, - // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t - // *arg_types); - OMPRTL__tgt_target_nowait, - // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, - // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t - // *arg_types, int32_t num_teams, int32_t thread_limit); - OMPRTL__tgt_target_teams, - // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void - // *host_ptr, int32_t arg_num, void** args_base, void **args, size_t - // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); - OMPRTL__tgt_target_teams_nowait, - // Call to void __tgt_register_lib(__tgt_bin_desc *desc); - OMPRTL__tgt_register_lib, - // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc); - OMPRTL__tgt_unregister_lib, - // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, - // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); - OMPRTL__tgt_target_data_begin, - // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t - // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t - // *arg_types); - OMPRTL__tgt_target_data_begin_nowait, - // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num, - // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); - OMPRTL__tgt_target_data_end, - // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t - // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t - // *arg_types); - OMPRTL__tgt_target_data_end_nowait, - // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num, - // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); - OMPRTL__tgt_target_data_update, - // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t - // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t - // *arg_types); - OMPRTL__tgt_target_data_update_nowait, -}; - -/// A basic class for pre|post-action for advanced codegen sequence for OpenMP -/// region. -class CleanupTy final : public EHScopeStack::Cleanup { - PrePostActionTy *Action; - -public: - explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} - void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { - if (!CGF.HaveInsertPoint()) - return; - Action->Exit(CGF); - } -}; - -} // anonymous namespace - -void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { - CodeGenFunction::RunCleanupsScope Scope(CGF); - if (PrePostAction) { - CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); - Callback(CodeGen, CGF, *PrePostAction); - } else { - PrePostActionTy Action; - Callback(CodeGen, CGF, Action); - } -} - -/// Check if the combiner is a call to UDR combiner and if it is so return the -/// UDR decl used for reduction. -static const OMPDeclareReductionDecl * -getReductionInit(const Expr *ReductionOp) { - if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) - if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) - if (const auto *DRE = - dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) - if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) - return DRD; - return nullptr; -} - -static void emitInitWithReductionInitializer(CodeGenFunction &CGF, - const OMPDeclareReductionDecl *DRD, - const Expr *InitOp, - Address Private, Address Original, - QualType Ty) { - if (DRD->getInitializer()) { - std::pair<llvm::Function *, llvm::Function *> Reduction = - CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); - const auto *CE = cast<CallExpr>(InitOp); - const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); - const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); - const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); - const auto *LHSDRE = - cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); - const auto *RHSDRE = - cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); - CodeGenFunction::OMPPrivateScope PrivateScope(CGF); - PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), - [=]() { return Private; }); - PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), - [=]() { return Original; }); - (void)PrivateScope.Privatize(); - RValue Func = RValue::get(Reduction.second); - CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); - CGF.EmitIgnoredExpr(InitOp); - } else { - llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty); - std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"}); - auto *GV = new llvm::GlobalVariable( - CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, - llvm::GlobalValue::PrivateLinkage, Init, Name); - LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); - RValue InitRVal; - switch (CGF.getEvaluationKind(Ty)) { - case TEK_Scalar: - InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation()); - break; - case TEK_Complex: - InitRVal = - RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); - break; - case TEK_Aggregate: - InitRVal = RValue::getAggregate(LV.getAddress()); - break; - } - OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue); - CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); - CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), - /*IsInitializer=*/false); - } -} - -/// Emit initialization of arrays of complex types. -/// \param DestAddr Address of the array. -/// \param Type Type of array. -/// \param Init Initial expression of array. -/// \param SrcAddr Address of the original array. -static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, - QualType Type, bool EmitDeclareReductionInit, - const Expr *Init, - const OMPDeclareReductionDecl *DRD, - Address SrcAddr = Address::invalid()) { - // Perform element-by-element initialization. - QualType ElementTy; - - // Drill down to the base element type on both arrays. - const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); - llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr); - DestAddr = - CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType()); - if (DRD) - SrcAddr = - CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); - - llvm::Value *SrcBegin = nullptr; - if (DRD) - SrcBegin = SrcAddr.getPointer(); - llvm::Value *DestBegin = DestAddr.getPointer(); - // Cast from pointer to array type to pointer to single element. - llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements); - // The basic structure here is a while-do loop. - llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); - llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); - llvm::Value *IsEmpty = - CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); - CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); - - // Enter the loop body, making that address the current address. - llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); - CGF.EmitBlock(BodyBB); - - CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); - - llvm::PHINode *SrcElementPHI = nullptr; - Address SrcElementCurrent = Address::invalid(); - if (DRD) { - SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, - "omp.arraycpy.srcElementPast"); - SrcElementPHI->addIncoming(SrcBegin, EntryBB); - SrcElementCurrent = - Address(SrcElementPHI, - SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); - } - llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( - DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); - DestElementPHI->addIncoming(DestBegin, EntryBB); - Address DestElementCurrent = - Address(DestElementPHI, - DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); - - // Emit copy. - { - CodeGenFunction::RunCleanupsScope InitScope(CGF); - if (EmitDeclareReductionInit) { - emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, - SrcElementCurrent, ElementTy); - } else - CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), - /*IsInitializer=*/false); - } - - if (DRD) { - // Shift the address forward by one element. - llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( - SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); - SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); - } - - // Shift the address forward by one element. - llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( - DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); - // Check whether we've reached the end. - llvm::Value *Done = - CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); - CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); - DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); - - // Done. - CGF.EmitBlock(DoneBB, /*IsFinished=*/true); -} - -LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { - return CGF.EmitOMPSharedLValue(E); -} - -LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, - const Expr *E) { - if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) - return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); - return LValue(); -} - -void ReductionCodeGen::emitAggregateInitialization( - CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, - const OMPDeclareReductionDecl *DRD) { - // Emit VarDecl with copy init for arrays. - // Get the address of the original variable captured in current - // captured region. - const auto *PrivateVD = - cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); - bool EmitDeclareReductionInit = - DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); - EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), - EmitDeclareReductionInit, - EmitDeclareReductionInit ? ClausesData[N].ReductionOp - : PrivateVD->getInit(), - DRD, SharedLVal.getAddress()); -} - -ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, - ArrayRef<const Expr *> Privates, - ArrayRef<const Expr *> ReductionOps) { - ClausesData.reserve(Shareds.size()); - SharedAddresses.reserve(Shareds.size()); - Sizes.reserve(Shareds.size()); - BaseDecls.reserve(Shareds.size()); - auto IPriv = Privates.begin(); - auto IRed = ReductionOps.begin(); - for (const Expr *Ref : Shareds) { - ClausesData.emplace_back(Ref, *IPriv, *IRed); - std::advance(IPriv, 1); - std::advance(IRed, 1); - } -} - -void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) { - assert(SharedAddresses.size() == N && - "Number of generated lvalues must be exactly N."); - LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); - LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); - SharedAddresses.emplace_back(First, Second); -} - -void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { - const auto *PrivateVD = - cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); - QualType PrivateType = PrivateVD->getType(); - bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); - if (!PrivateType->isVariablyModifiedType()) { - Sizes.emplace_back( - CGF.getTypeSize( - SharedAddresses[N].first.getType().getNonReferenceType()), - nullptr); - return; - } - llvm::Value *Size; - llvm::Value *SizeInChars; - auto *ElemType = - cast<llvm::PointerType>(SharedAddresses[N].first.getPointer()->getType()) - ->getElementType(); - auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); - if (AsArraySection) { - Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(), - SharedAddresses[N].first.getPointer()); - Size = CGF.Builder.CreateNUWAdd( - Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); - SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); - } else { - SizeInChars = CGF.getTypeSize( - SharedAddresses[N].first.getType().getNonReferenceType()); - Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); - } - Sizes.emplace_back(SizeInChars, Size); - CodeGenFunction::OpaqueValueMapping OpaqueMap( - CGF, - cast<OpaqueValueExpr>( - CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), - RValue::get(Size)); - CGF.EmitVariablyModifiedType(PrivateType); -} - -void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, - llvm::Value *Size) { - const auto *PrivateVD = - cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); - QualType PrivateType = PrivateVD->getType(); - if (!PrivateType->isVariablyModifiedType()) { - assert(!Size && !Sizes[N].second && - "Size should be nullptr for non-variably modified reduction " - "items."); - return; - } - CodeGenFunction::OpaqueValueMapping OpaqueMap( - CGF, - cast<OpaqueValueExpr>( - CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), - RValue::get(Size)); - CGF.EmitVariablyModifiedType(PrivateType); -} - -void ReductionCodeGen::emitInitialization( - CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, - llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { - assert(SharedAddresses.size() > N && "No variable was generated"); - const auto *PrivateVD = - cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); - const OMPDeclareReductionDecl *DRD = - getReductionInit(ClausesData[N].ReductionOp); - QualType PrivateType = PrivateVD->getType(); - PrivateAddr = CGF.Builder.CreateElementBitCast( - PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); - QualType SharedType = SharedAddresses[N].first.getType(); - SharedLVal = CGF.MakeAddrLValue( - CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(), - CGF.ConvertTypeForMem(SharedType)), - SharedType, SharedAddresses[N].first.getBaseInfo(), - CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); - if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { - emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); - } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { - emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, - PrivateAddr, SharedLVal.getAddress(), - SharedLVal.getType()); - } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && - !CGF.isTrivialInitializer(PrivateVD->getInit())) { - CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, - PrivateVD->getType().getQualifiers(), - /*IsInitializer=*/false); - } -} - -bool ReductionCodeGen::needCleanups(unsigned N) { - const auto *PrivateVD = - cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); - QualType PrivateType = PrivateVD->getType(); - QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); - return DTorKind != QualType::DK_none; -} - -void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, - Address PrivateAddr) { - const auto *PrivateVD = - cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); - QualType PrivateType = PrivateVD->getType(); - QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); - if (needCleanups(N)) { - PrivateAddr = CGF.Builder.CreateElementBitCast( - PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); - CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); - } -} - -static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, - LValue BaseLV) { - BaseTy = BaseTy.getNonReferenceType(); - while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && - !CGF.getContext().hasSameType(BaseTy, ElTy)) { - if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { - BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(), PtrTy); - } else { - LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(), BaseTy); - BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); - } - BaseTy = BaseTy->getPointeeType(); - } - return CGF.MakeAddrLValue( - CGF.Builder.CreateElementBitCast(BaseLV.getAddress(), - CGF.ConvertTypeForMem(ElTy)), - BaseLV.getType(), BaseLV.getBaseInfo(), - CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); -} - -static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, - llvm::Type *BaseLVType, CharUnits BaseLVAlignment, - llvm::Value *Addr) { - Address Tmp = Address::invalid(); - Address TopTmp = Address::invalid(); - Address MostTopTmp = Address::invalid(); - BaseTy = BaseTy.getNonReferenceType(); - while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && - !CGF.getContext().hasSameType(BaseTy, ElTy)) { - Tmp = CGF.CreateMemTemp(BaseTy); - if (TopTmp.isValid()) - CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); - else - MostTopTmp = Tmp; - TopTmp = Tmp; - BaseTy = BaseTy->getPointeeType(); - } - llvm::Type *Ty = BaseLVType; - if (Tmp.isValid()) - Ty = Tmp.getElementType(); - Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); - if (Tmp.isValid()) { - CGF.Builder.CreateStore(Addr, Tmp); - return MostTopTmp; - } - return Address(Addr, BaseLVAlignment); -} - -static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { - const VarDecl *OrigVD = nullptr; - if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { - const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); - while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) - Base = TempOASE->getBase()->IgnoreParenImpCasts(); - while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) - Base = TempASE->getBase()->IgnoreParenImpCasts(); - DE = cast<DeclRefExpr>(Base); - OrigVD = cast<VarDecl>(DE->getDecl()); - } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { - const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); - while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) - Base = TempASE->getBase()->IgnoreParenImpCasts(); - DE = cast<DeclRefExpr>(Base); - OrigVD = cast<VarDecl>(DE->getDecl()); - } - return OrigVD; -} - -Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, - Address PrivateAddr) { - const DeclRefExpr *DE; - if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { - BaseDecls.emplace_back(OrigVD); - LValue OriginalBaseLValue = CGF.EmitLValue(DE); - LValue BaseLValue = - loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), - OriginalBaseLValue); - llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( - BaseLValue.getPointer(), SharedAddresses[N].first.getPointer()); - llvm::Value *PrivatePointer = - CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - PrivateAddr.getPointer(), - SharedAddresses[N].first.getAddress().getType()); - llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); - return castToBase(CGF, OrigVD->getType(), - SharedAddresses[N].first.getType(), - OriginalBaseLValue.getAddress().getType(), - OriginalBaseLValue.getAlignment(), Ptr); - } - BaseDecls.emplace_back( - cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); - return PrivateAddr; -} - -bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { - const OMPDeclareReductionDecl *DRD = - getReductionInit(ClausesData[N].ReductionOp); - return DRD && DRD->getInitializer(); -} - -LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { - return CGF.EmitLoadOfPointerLValue( - CGF.GetAddrOfLocalVar(getThreadIDVariable()), - getThreadIDVariable()->getType()->castAs<PointerType>()); -} - -void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { - if (!CGF.HaveInsertPoint()) - return; - // 1.2.2 OpenMP Language Terminology - // Structured block - An executable statement with a single entry at the - // top and a single exit at the bottom. - // The point of exit cannot be a branch out of the structured block. - // longjmp() and throw() must not violate the entry/exit criteria. - CGF.EHStack.pushTerminate(); - CodeGen(CGF); - CGF.EHStack.popTerminate(); -} - -LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( - CodeGenFunction &CGF) { - return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), - getThreadIDVariable()->getType(), - AlignmentSource::Decl); -} - -static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, - QualType FieldTy) { - auto *Field = FieldDecl::Create( - C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, - C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), - /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); - Field->setAccess(AS_public); - DC->addDecl(Field); - return Field; -} - -CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, - StringRef Separator) - : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), - OffloadEntriesInfoManager(CGM) { - ASTContext &C = CGM.getContext(); - RecordDecl *RD = C.buildImplicitRecord("ident_t"); - QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); - RD->startDefinition(); - // reserved_1 - addFieldToRecordDecl(C, RD, KmpInt32Ty); - // flags - addFieldToRecordDecl(C, RD, KmpInt32Ty); - // reserved_2 - addFieldToRecordDecl(C, RD, KmpInt32Ty); - // reserved_3 - addFieldToRecordDecl(C, RD, KmpInt32Ty); - // psource - addFieldToRecordDecl(C, RD, C.VoidPtrTy); - RD->completeDefinition(); - IdentQTy = C.getRecordType(RD); - IdentTy = CGM.getTypes().ConvertRecordDeclType(RD); - KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); - - loadOffloadInfoMetadata(); -} - -void CGOpenMPRuntime::clear() { - InternalVars.clear(); - // Clean non-target variable declarations possibly used only in debug info. - for (const auto &Data : EmittedNonTargetVariables) { - if (!Data.getValue().pointsToAliveValue()) - continue; - auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); - if (!GV) - continue; - if (!GV->isDeclaration() || GV->getNumUses() > 0) - continue; - GV->eraseFromParent(); - } -} - -std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { - SmallString<128> Buffer; - llvm::raw_svector_ostream OS(Buffer); - StringRef Sep = FirstSeparator; - for (StringRef Part : Parts) { - OS << Sep << Part; - Sep = Separator; - } - return OS.str(); -} - -static llvm::Function * -emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, - const Expr *CombinerInitializer, const VarDecl *In, - const VarDecl *Out, bool IsCombiner) { - // void .omp_combiner.(Ty *in, Ty *out); - ASTContext &C = CGM.getContext(); - QualType PtrTy = C.getPointerType(Ty).withRestrict(); - FunctionArgList Args; - ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), - /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); - ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), - /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); - Args.push_back(&OmpOutParm); - Args.push_back(&OmpInParm); - const CGFunctionInfo &FnInfo = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); - llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); - std::string Name = CGM.getOpenMPRuntime().getName( - {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); - auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, - Name, &CGM.getModule()); - CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); - Fn->removeFnAttr(llvm::Attribute::NoInline); - Fn->removeFnAttr(llvm::Attribute::OptimizeNone); - Fn->addFnAttr(llvm::Attribute::AlwaysInline); - CodeGenFunction CGF(CGM); - // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. - // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. - CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), - Out->getLocation()); - CodeGenFunction::OMPPrivateScope Scope(CGF); - Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); - Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { - return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) - .getAddress(); - }); - Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); - Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { - return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) - .getAddress(); - }); - (void)Scope.Privatize(); - if (!IsCombiner && Out->hasInit() && - !CGF.isTrivialInitializer(Out->getInit())) { - CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), - Out->getType().getQualifiers(), - /*IsInitializer=*/true); - } - if (CombinerInitializer) - CGF.EmitIgnoredExpr(CombinerInitializer); - Scope.ForceCleanup(); - CGF.FinishFunction(); - return Fn; -} - -void CGOpenMPRuntime::emitUserDefinedReduction( - CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { - if (UDRMap.count(D) > 0) - return; - llvm::Function *Combiner = emitCombinerOrInitializer( - CGM, D->getType(), D->getCombiner(), - cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), - cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), - /*IsCombiner=*/true); - llvm::Function *Initializer = nullptr; - if (const Expr *Init = D->getInitializer()) { - Initializer = emitCombinerOrInitializer( - CGM, D->getType(), - D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init - : nullptr, - cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), - cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), - /*IsCombiner=*/false); - } - UDRMap.try_emplace(D, Combiner, Initializer); - if (CGF) { - auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); - Decls.second.push_back(D); - } -} - -std::pair<llvm::Function *, llvm::Function *> -CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { - auto I = UDRMap.find(D); - if (I != UDRMap.end()) - return I->second; - emitUserDefinedReduction(/*CGF=*/nullptr, D); - return UDRMap.lookup(D); -} - -static llvm::Value *emitParallelOrTeamsOutlinedFunction( - CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, - const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, - const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { - assert(ThreadIDVar->getType()->isPointerType() && - "thread id variable must be of type kmp_int32 *"); - CodeGenFunction CGF(CGM, true); - bool HasCancel = false; - if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) - HasCancel = OPD->hasCancel(); - else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) - HasCancel = OPSD->hasCancel(); - else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) - HasCancel = OPFD->hasCancel(); - else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) - HasCancel = OPFD->hasCancel(); - else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) - HasCancel = OPFD->hasCancel(); - else if (const auto *OPFD = - dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) - HasCancel = OPFD->hasCancel(); - else if (const auto *OPFD = - dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) - HasCancel = OPFD->hasCancel(); - CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, - HasCancel, OutlinedHelperName); - CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); - return CGF.GenerateOpenMPCapturedStmtFunction(*CS); -} - -llvm::Value *CGOpenMPRuntime::emitParallelOutlinedFunction( - const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, - OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { - const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); - return emitParallelOrTeamsOutlinedFunction( - CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); -} - -llvm::Value *CGOpenMPRuntime::emitTeamsOutlinedFunction( - const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, - OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { - const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); - return emitParallelOrTeamsOutlinedFunction( - CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); -} - -llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction( - const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, - const VarDecl *PartIDVar, const VarDecl *TaskTVar, - OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, - bool Tied, unsigned &NumberOfParts) { - auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, - PrePostActionTy &) { - llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); - llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); - llvm::Value *TaskArgs[] = { - UpLoc, ThreadID, - CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), - TaskTVar->getType()->castAs<PointerType>()) - .getPointer()}; - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs); - }; - CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, - UntiedCodeGen); - CodeGen.setAction(Action); - assert(!ThreadIDVar->getType()->isPointerType() && - "thread id variable must be of type kmp_int32 for tasks"); - const OpenMPDirectiveKind Region = - isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop - : OMPD_task; - const CapturedStmt *CS = D.getCapturedStmt(Region); - const auto *TD = dyn_cast<OMPTaskDirective>(&D); - CodeGenFunction CGF(CGM, true); - CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, - InnermostKind, - TD ? TD->hasCancel() : false, Action); - CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); - llvm::Value *Res = CGF.GenerateCapturedStmtFunction(*CS); - if (!Tied) - NumberOfParts = Action.getNumberOfParts(); - return Res; -} - -static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, - const RecordDecl *RD, const CGRecordLayout &RL, - ArrayRef<llvm::Constant *> Data) { - llvm::StructType *StructTy = RL.getLLVMType(); - unsigned PrevIdx = 0; - ConstantInitBuilder CIBuilder(CGM); - auto DI = Data.begin(); - for (const FieldDecl *FD : RD->fields()) { - unsigned Idx = RL.getLLVMFieldNo(FD); - // Fill the alignment. - for (unsigned I = PrevIdx; I < Idx; ++I) - Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); - PrevIdx = Idx + 1; - Fields.add(*DI); - ++DI; - } -} - -template <class... As> -static llvm::GlobalVariable * -createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, - ArrayRef<llvm::Constant *> Data, const Twine &Name, - As &&... Args) { - const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); - const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); - ConstantInitBuilder CIBuilder(CGM); - ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); - buildStructValue(Fields, CGM, RD, RL, Data); - return Fields.finishAndCreateGlobal( - Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, - std::forward<As>(Args)...); -} - -template <typename T> -static void -createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, - ArrayRef<llvm::Constant *> Data, - T &Parent) { - const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); - const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); - ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); - buildStructValue(Fields, CGM, RD, RL, Data); - Fields.finishAndAddTo(Parent); -} - -Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) { - CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); - unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); - FlagsTy FlagsKey(Flags, Reserved2Flags); - llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey); - if (!Entry) { - if (!DefaultOpenMPPSource) { - // Initialize default location for psource field of ident_t structure of - // all ident_t objects. Format is ";file;function;line;column;;". - // Taken from - // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c - DefaultOpenMPPSource = - CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer(); - DefaultOpenMPPSource = - llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); - } - - llvm::Constant *Data[] = { - llvm::ConstantInt::getNullValue(CGM.Int32Ty), - llvm::ConstantInt::get(CGM.Int32Ty, Flags), - llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags), - llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource}; - llvm::GlobalValue *DefaultOpenMPLocation = - createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "", - llvm::GlobalValue::PrivateLinkage); - DefaultOpenMPLocation->setUnnamedAddr( - llvm::GlobalValue::UnnamedAddr::Global); - - OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation; - } - return Address(Entry, Align); -} - -void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, - bool AtCurrentPoint) { - auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); - assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); - - llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); - if (AtCurrentPoint) { - Elem.second.ServiceInsertPt = new llvm::BitCastInst( - Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); - } else { - Elem.second.ServiceInsertPt = - new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); - Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); - } -} - -void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { - auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); - if (Elem.second.ServiceInsertPt) { - llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; - Elem.second.ServiceInsertPt = nullptr; - Ptr->eraseFromParent(); - } -} - -llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, - SourceLocation Loc, - unsigned Flags) { - Flags |= OMP_IDENT_KMPC; - // If no debug info is generated - return global default location. - if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || - Loc.isInvalid()) - return getOrCreateDefaultLocation(Flags).getPointer(); - - assert(CGF.CurFn && "No function in current CodeGenFunction."); - - CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); - Address LocValue = Address::invalid(); - auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); - if (I != OpenMPLocThreadIDMap.end()) - LocValue = Address(I->second.DebugLoc, Align); - - // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if - // GetOpenMPThreadID was called before this routine. - if (!LocValue.isValid()) { - // Generate "ident_t .kmpc_loc.addr;" - Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr"); - auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); - Elem.second.DebugLoc = AI.getPointer(); - LocValue = AI; - - if (!Elem.second.ServiceInsertPt) - setLocThreadIdInsertPt(CGF); - CGBuilderTy::InsertPointGuard IPG(CGF.Builder); - CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); - CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), - CGF.getTypeSize(IdentQTy)); - } - - // char **psource = &.kmpc_loc_<flags>.addr.psource; - LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy); - auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin(); - LValue PSource = - CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource)); - - llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); - if (OMPDebugLoc == nullptr) { - SmallString<128> Buffer2; - llvm::raw_svector_ostream OS2(Buffer2); - // Build debug location - PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); - OS2 << ";" << PLoc.getFilename() << ";"; - if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) - OS2 << FD->getQualifiedNameAsString(); - OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; - OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); - OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; - } - // *psource = ";<File>;<Function>;<Line>;<Column>;;"; - CGF.EmitStoreOfScalar(OMPDebugLoc, PSource); - - // Our callers always pass this to a runtime function, so for - // convenience, go ahead and return a naked pointer. - return LocValue.getPointer(); -} - -llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, - SourceLocation Loc) { - assert(CGF.CurFn && "No function in current CodeGenFunction."); - - llvm::Value *ThreadID = nullptr; - // Check whether we've already cached a load of the thread id in this - // function. - auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); - if (I != OpenMPLocThreadIDMap.end()) { - ThreadID = I->second.ThreadID; - if (ThreadID != nullptr) - return ThreadID; - } - // If exceptions are enabled, do not use parameter to avoid possible crash. - if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || - !CGF.getLangOpts().CXXExceptions || - CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) { - if (auto *OMPRegionInfo = - dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { - if (OMPRegionInfo->getThreadIDVariable()) { - // Check if this an outlined function with thread id passed as argument. - LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); - ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); - // If value loaded in entry block, cache it and use it everywhere in - // function. - if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) { - auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); - Elem.second.ThreadID = ThreadID; - } - return ThreadID; - } - } - } - - // This is not an outlined function region - need to call __kmpc_int32 - // kmpc_global_thread_num(ident_t *loc). - // Generate thread id value and cache this value for use across the - // function. - auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); - if (!Elem.second.ServiceInsertPt) - setLocThreadIdInsertPt(CGF); - CGBuilderTy::InsertPointGuard IPG(CGF.Builder); - CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); - llvm::CallInst *Call = CGF.Builder.CreateCall( - createRuntimeFunction(OMPRTL__kmpc_global_thread_num), - emitUpdateLocation(CGF, Loc)); - Call->setCallingConv(CGF.getRuntimeCC()); - Elem.second.ThreadID = Call; - return Call; -} - -void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { - assert(CGF.CurFn && "No function in current CodeGenFunction."); - if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { - clearLocThreadIdInsertPt(CGF); - OpenMPLocThreadIDMap.erase(CGF.CurFn); - } - if (FunctionUDRMap.count(CGF.CurFn) > 0) { - for(auto *D : FunctionUDRMap[CGF.CurFn]) - UDRMap.erase(D); - FunctionUDRMap.erase(CGF.CurFn); - } -} - -llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { - return IdentTy->getPointerTo(); -} - -llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { - if (!Kmpc_MicroTy) { - // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) - llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), - llvm::PointerType::getUnqual(CGM.Int32Ty)}; - Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); - } - return llvm::PointerType::getUnqual(Kmpc_MicroTy); -} - -llvm::Constant * -CGOpenMPRuntime::createRuntimeFunction(unsigned Function) { - llvm::Constant *RTLFn = nullptr; - switch (static_cast<OpenMPRTLFunction>(Function)) { - case OMPRTL__kmpc_fork_call: { - // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro - // microtask, ...); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, - getKmpc_MicroPointerTy()}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); - break; - } - case OMPRTL__kmpc_global_thread_num: { - // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); - llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); - break; - } - case OMPRTL__kmpc_threadprivate_cached: { - // Build void *__kmpc_threadprivate_cached(ident_t *loc, - // kmp_int32 global_tid, void *data, size_t size, void ***cache); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, - CGM.VoidPtrTy, CGM.SizeTy, - CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); - break; - } - case OMPRTL__kmpc_critical: { - // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, - // kmp_critical_name *crit); - llvm::Type *TypeParams[] = { - getIdentTyPointerTy(), CGM.Int32Ty, - llvm::PointerType::getUnqual(KmpCriticalNameTy)}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); - break; - } - case OMPRTL__kmpc_critical_with_hint: { - // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, - // kmp_critical_name *crit, uintptr_t hint); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, - llvm::PointerType::getUnqual(KmpCriticalNameTy), - CGM.IntPtrTy}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint"); - break; - } - case OMPRTL__kmpc_threadprivate_register: { - // Build void __kmpc_threadprivate_register(ident_t *, void *data, - // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); - // typedef void *(*kmpc_ctor)(void *); - auto *KmpcCtorTy = - llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, - /*isVarArg*/ false)->getPointerTo(); - // typedef void *(*kmpc_cctor)(void *, void *); - llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; - auto *KmpcCopyCtorTy = - llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, - /*isVarArg*/ false) - ->getPointerTo(); - // typedef void (*kmpc_dtor)(void *); - auto *KmpcDtorTy = - llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) - ->getPointerTo(); - llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, - KmpcCopyCtorTy, KmpcDtorTy}; - auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, - /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); - break; - } - case OMPRTL__kmpc_end_critical: { - // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, - // kmp_critical_name *crit); - llvm::Type *TypeParams[] = { - getIdentTyPointerTy(), CGM.Int32Ty, - llvm::PointerType::getUnqual(KmpCriticalNameTy)}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); - break; - } - case OMPRTL__kmpc_cancel_barrier: { - // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 - // global_tid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); - break; - } - case OMPRTL__kmpc_barrier: { - // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); - break; - } - case OMPRTL__kmpc_for_static_fini: { - // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); - break; - } - case OMPRTL__kmpc_push_num_threads: { - // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, - // kmp_int32 num_threads) - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, - CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); - break; - } - case OMPRTL__kmpc_serialized_parallel: { - // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 - // global_tid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); - break; - } - case OMPRTL__kmpc_end_serialized_parallel: { - // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 - // global_tid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); - break; - } - case OMPRTL__kmpc_flush: { - // Build void __kmpc_flush(ident_t *loc); - llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); - break; - } - case OMPRTL__kmpc_master: { - // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master"); - break; - } - case OMPRTL__kmpc_end_master: { - // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); - break; - } - case OMPRTL__kmpc_omp_taskyield: { - // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, - // int end_part); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); - break; - } - case OMPRTL__kmpc_single: { - // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); - break; - } - case OMPRTL__kmpc_end_single: { - // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); - break; - } - case OMPRTL__kmpc_omp_task_alloc: { - // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, - // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, - // kmp_routine_entry_t *task_entry); - assert(KmpRoutineEntryPtrTy != nullptr && - "Type kmp_routine_entry_t must be created."); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, - CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; - // Return void * and then cast to particular kmp_task_t type. - auto *FnTy = - llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); - break; - } - case OMPRTL__kmpc_omp_task: { - // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t - // *new_task); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, - CGM.VoidPtrTy}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); - break; - } - case OMPRTL__kmpc_copyprivate: { - // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, - // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), - // kmp_int32 didit); - llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; - auto *CpyFnTy = - llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy, - CGM.VoidPtrTy, CpyFnTy->getPointerTo(), - CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); - break; - } - case OMPRTL__kmpc_reduce: { - // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, - // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void - // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); - llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; - auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, - /*isVarArg=*/false); - llvm::Type *TypeParams[] = { - getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, - CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), - llvm::PointerType::getUnqual(KmpCriticalNameTy)}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce"); - break; - } - case OMPRTL__kmpc_reduce_nowait: { - // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 - // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, - // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name - // *lck); - llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; - auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, - /*isVarArg=*/false); - llvm::Type *TypeParams[] = { - getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, - CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), - llvm::PointerType::getUnqual(KmpCriticalNameTy)}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait"); - break; - } - case OMPRTL__kmpc_end_reduce: { - // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, - // kmp_critical_name *lck); - llvm::Type *TypeParams[] = { - getIdentTyPointerTy(), CGM.Int32Ty, - llvm::PointerType::getUnqual(KmpCriticalNameTy)}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce"); - break; - } - case OMPRTL__kmpc_end_reduce_nowait: { - // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, - // kmp_critical_name *lck); - llvm::Type *TypeParams[] = { - getIdentTyPointerTy(), CGM.Int32Ty, - llvm::PointerType::getUnqual(KmpCriticalNameTy)}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = - CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait"); - break; - } - case OMPRTL__kmpc_omp_task_begin_if0: { - // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t - // *new_task); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, - CGM.VoidPtrTy}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = - CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0"); - break; - } - case OMPRTL__kmpc_omp_task_complete_if0: { - // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t - // *new_task); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, - CGM.VoidPtrTy}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, - /*Name=*/"__kmpc_omp_task_complete_if0"); - break; - } - case OMPRTL__kmpc_ordered: { - // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered"); - break; - } - case OMPRTL__kmpc_end_ordered: { - // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered"); - break; - } - case OMPRTL__kmpc_omp_taskwait: { - // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); - break; - } - case OMPRTL__kmpc_taskgroup: { - // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); - break; - } - case OMPRTL__kmpc_end_taskgroup: { - // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); - break; - } - case OMPRTL__kmpc_push_proc_bind: { - // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, - // int proc_bind) - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); - break; - } - case OMPRTL__kmpc_omp_task_with_deps: { - // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, - // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, - // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); - llvm::Type *TypeParams[] = { - getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, - CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); - RTLFn = - CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); - break; - } - case OMPRTL__kmpc_omp_wait_deps: { - // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, - // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, - // kmp_depend_info_t *noalias_dep_list); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, - CGM.Int32Ty, CGM.VoidPtrTy, - CGM.Int32Ty, CGM.VoidPtrTy}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); - break; - } - case OMPRTL__kmpc_cancellationpoint: { - // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 - // global_tid, kmp_int32 cncl_kind) - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); - break; - } - case OMPRTL__kmpc_cancel: { - // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, - // kmp_int32 cncl_kind) - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); - break; - } - case OMPRTL__kmpc_push_num_teams: { - // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid, - // kmp_int32 num_teams, kmp_int32 num_threads) - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, - CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams"); - break; - } - case OMPRTL__kmpc_fork_teams: { - // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro - // microtask, ...); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, - getKmpc_MicroPointerTy()}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams"); - break; - } - case OMPRTL__kmpc_taskloop: { - // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int - // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int - // sched, kmp_uint64 grainsize, void *task_dup); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), - CGM.IntTy, - CGM.VoidPtrTy, - CGM.IntTy, - CGM.Int64Ty->getPointerTo(), - CGM.Int64Ty->getPointerTo(), - CGM.Int64Ty, - CGM.IntTy, - CGM.IntTy, - CGM.Int64Ty, - CGM.VoidPtrTy}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop"); - break; - } - case OMPRTL__kmpc_doacross_init: { - // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 - // num_dims, struct kmp_dim *dims); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), - CGM.Int32Ty, - CGM.Int32Ty, - CGM.VoidPtrTy}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init"); - break; - } - case OMPRTL__kmpc_doacross_fini: { - // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini"); - break; - } - case OMPRTL__kmpc_doacross_post: { - // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 - // *vec); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, - CGM.Int64Ty->getPointerTo()}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post"); - break; - } - case OMPRTL__kmpc_doacross_wait: { - // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 - // *vec); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, - CGM.Int64Ty->getPointerTo()}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait"); - break; - } - case OMPRTL__kmpc_task_reduction_init: { - // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void - // *data); - llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); - RTLFn = - CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init"); - break; - } - case OMPRTL__kmpc_task_reduction_get_th_data: { - // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void - // *d); - llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction( - FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data"); - break; - } - case OMPRTL__kmpc_push_target_tripcount: { - // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 - // size); - llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty}; - llvm::FunctionType *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount"); - break; - } - case OMPRTL__tgt_target: { - // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t - // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t - // *arg_types); - llvm::Type *TypeParams[] = {CGM.Int64Ty, - CGM.VoidPtrTy, - CGM.Int32Ty, - CGM.VoidPtrPtrTy, - CGM.VoidPtrPtrTy, - CGM.SizeTy->getPointerTo(), - CGM.Int64Ty->getPointerTo()}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target"); - break; - } - case OMPRTL__tgt_target_nowait: { - // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, - // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes, - // int64_t *arg_types); - llvm::Type *TypeParams[] = {CGM.Int64Ty, - CGM.VoidPtrTy, - CGM.Int32Ty, - CGM.VoidPtrPtrTy, - CGM.VoidPtrPtrTy, - CGM.SizeTy->getPointerTo(), - CGM.Int64Ty->getPointerTo()}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait"); - break; - } - case OMPRTL__tgt_target_teams: { - // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, - // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes, - // int64_t *arg_types, int32_t num_teams, int32_t thread_limit); - llvm::Type *TypeParams[] = {CGM.Int64Ty, - CGM.VoidPtrTy, - CGM.Int32Ty, - CGM.VoidPtrPtrTy, - CGM.VoidPtrPtrTy, - CGM.SizeTy->getPointerTo(), - CGM.Int64Ty->getPointerTo(), - CGM.Int32Ty, - CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams"); - break; - } - case OMPRTL__tgt_target_teams_nowait: { - // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void - // *host_ptr, int32_t arg_num, void** args_base, void **args, size_t - // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); - llvm::Type *TypeParams[] = {CGM.Int64Ty, - CGM.VoidPtrTy, - CGM.Int32Ty, - CGM.VoidPtrPtrTy, - CGM.VoidPtrPtrTy, - CGM.SizeTy->getPointerTo(), - CGM.Int64Ty->getPointerTo(), - CGM.Int32Ty, - CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait"); - break; - } - case OMPRTL__tgt_register_lib: { - // Build void __tgt_register_lib(__tgt_bin_desc *desc); - QualType ParamTy = - CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); - llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib"); - break; - } - case OMPRTL__tgt_unregister_lib: { - // Build void __tgt_unregister_lib(__tgt_bin_desc *desc); - QualType ParamTy = - CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); - llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib"); - break; - } - case OMPRTL__tgt_target_data_begin: { - // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, - // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); - llvm::Type *TypeParams[] = {CGM.Int64Ty, - CGM.Int32Ty, - CGM.VoidPtrPtrTy, - CGM.VoidPtrPtrTy, - CGM.SizeTy->getPointerTo(), - CGM.Int64Ty->getPointerTo()}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin"); - break; - } - case OMPRTL__tgt_target_data_begin_nowait: { - // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t - // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t - // *arg_types); - llvm::Type *TypeParams[] = {CGM.Int64Ty, - CGM.Int32Ty, - CGM.VoidPtrPtrTy, - CGM.VoidPtrPtrTy, - CGM.SizeTy->getPointerTo(), - CGM.Int64Ty->getPointerTo()}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait"); - break; - } - case OMPRTL__tgt_target_data_end: { - // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num, - // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); - llvm::Type *TypeParams[] = {CGM.Int64Ty, - CGM.Int32Ty, - CGM.VoidPtrPtrTy, - CGM.VoidPtrPtrTy, - CGM.SizeTy->getPointerTo(), - CGM.Int64Ty->getPointerTo()}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end"); - break; - } - case OMPRTL__tgt_target_data_end_nowait: { - // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t - // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t - // *arg_types); - llvm::Type *TypeParams[] = {CGM.Int64Ty, - CGM.Int32Ty, - CGM.VoidPtrPtrTy, - CGM.VoidPtrPtrTy, - CGM.SizeTy->getPointerTo(), - CGM.Int64Ty->getPointerTo()}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait"); - break; - } - case OMPRTL__tgt_target_data_update: { - // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num, - // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); - llvm::Type *TypeParams[] = {CGM.Int64Ty, - CGM.Int32Ty, - CGM.VoidPtrPtrTy, - CGM.VoidPtrPtrTy, - CGM.SizeTy->getPointerTo(), - CGM.Int64Ty->getPointerTo()}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update"); - break; - } - case OMPRTL__tgt_target_data_update_nowait: { - // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t - // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t - // *arg_types); - llvm::Type *TypeParams[] = {CGM.Int64Ty, - CGM.Int32Ty, - CGM.VoidPtrPtrTy, - CGM.VoidPtrPtrTy, - CGM.SizeTy->getPointerTo(), - CGM.Int64Ty->getPointerTo()}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait"); - break; - } - } - assert(RTLFn && "Unable to find OpenMP runtime function"); - return RTLFn; -} - -llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, - bool IVSigned) { - assert((IVSize == 32 || IVSize == 64) && - "IV size is not compatible with the omp runtime"); - StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" - : "__kmpc_for_static_init_4u") - : (IVSigned ? "__kmpc_for_static_init_8" - : "__kmpc_for_static_init_8u"); - llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; - auto *PtrTy = llvm::PointerType::getUnqual(ITy); - llvm::Type *TypeParams[] = { - getIdentTyPointerTy(), // loc - CGM.Int32Ty, // tid - CGM.Int32Ty, // schedtype - llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter - PtrTy, // p_lower - PtrTy, // p_upper - PtrTy, // p_stride - ITy, // incr - ITy // chunk - }; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - return CGM.CreateRuntimeFunction(FnTy, Name); -} - -llvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, - bool IVSigned) { - assert((IVSize == 32 || IVSize == 64) && - "IV size is not compatible with the omp runtime"); - StringRef Name = - IVSize == 32 - ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") - : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); - llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; - llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc - CGM.Int32Ty, // tid - CGM.Int32Ty, // schedtype - ITy, // lower - ITy, // upper - ITy, // stride - ITy // chunk - }; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - return CGM.CreateRuntimeFunction(FnTy, Name); -} - -llvm::Constant *CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, - bool IVSigned) { - assert((IVSize == 32 || IVSize == 64) && - "IV size is not compatible with the omp runtime"); - StringRef Name = - IVSize == 32 - ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") - : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); - llvm::Type *TypeParams[] = { - getIdentTyPointerTy(), // loc - CGM.Int32Ty, // tid - }; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - return CGM.CreateRuntimeFunction(FnTy, Name); -} - -llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, - bool IVSigned) { - assert((IVSize == 32 || IVSize == 64) && - "IV size is not compatible with the omp runtime"); - StringRef Name = - IVSize == 32 - ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") - : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); - llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; - auto *PtrTy = llvm::PointerType::getUnqual(ITy); - llvm::Type *TypeParams[] = { - getIdentTyPointerTy(), // loc - CGM.Int32Ty, // tid - llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter - PtrTy, // p_lower - PtrTy, // p_upper - PtrTy // p_stride - }; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); - return CGM.CreateRuntimeFunction(FnTy, Name); -} - -Address CGOpenMPRuntime::getAddrOfDeclareTargetLink(const VarDecl *VD) { - if (CGM.getLangOpts().OpenMPSimd) - return Address::invalid(); - llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); - if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) { - SmallString<64> PtrName; - { - llvm::raw_svector_ostream OS(PtrName); - OS << CGM.getMangledName(GlobalDecl(VD)) << "_decl_tgt_link_ptr"; - } - llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); - if (!Ptr) { - QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); - Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), - PtrName); - if (!CGM.getLangOpts().OpenMPIsDevice) { - auto *GV = cast<llvm::GlobalVariable>(Ptr); - GV->setLinkage(llvm::GlobalValue::ExternalLinkage); - GV->setInitializer(CGM.GetAddrOfGlobal(VD)); - } - CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ptr)); - registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); - } - return Address(Ptr, CGM.getContext().getDeclAlign(VD)); - } - return Address::invalid(); -} - -llvm::Constant * -CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { - assert(!CGM.getLangOpts().OpenMPUseTLS || - !CGM.getContext().getTargetInfo().isTLSSupported()); - // Lookup the entry, lazily creating it if necessary. - std::string Suffix = getName({"cache", ""}); - return getOrCreateInternalVariable( - CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); -} - -Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, - const VarDecl *VD, - Address VDAddr, - SourceLocation Loc) { - if (CGM.getLangOpts().OpenMPUseTLS && - CGM.getContext().getTargetInfo().isTLSSupported()) - return VDAddr; - - llvm::Type *VarTy = VDAddr.getElementType(); - llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), - CGF.Builder.CreatePointerCast(VDAddr.getPointer(), - CGM.Int8PtrTy), - CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), - getOrCreateThreadPrivateCache(VD)}; - return Address(CGF.EmitRuntimeCall( - createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), - VDAddr.getAlignment()); -} - -void CGOpenMPRuntime::emitThreadPrivateVarInit( - CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, - llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { - // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime - // library. - llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), - OMPLoc); - // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) - // to register constructor/destructor for variable. - llvm::Value *Args[] = { - OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), - Ctor, CopyCtor, Dtor}; - CGF.EmitRuntimeCall( - createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); -} - -llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( - const VarDecl *VD, Address VDAddr, SourceLocation Loc, - bool PerformInit, CodeGenFunction *CGF) { - if (CGM.getLangOpts().OpenMPUseTLS && - CGM.getContext().getTargetInfo().isTLSSupported()) - return nullptr; - - VD = VD->getDefinition(CGM.getContext()); - if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { - QualType ASTTy = VD->getType(); - - llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; - const Expr *Init = VD->getAnyInitializer(); - if (CGM.getLangOpts().CPlusPlus && PerformInit) { - // Generate function that re-emits the declaration's initializer into the - // threadprivate copy of the variable VD - CodeGenFunction CtorCGF(CGM); - FunctionArgList Args; - ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, - /*Id=*/nullptr, CGM.getContext().VoidPtrTy, - ImplicitParamDecl::Other); - Args.push_back(&Dst); - - const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( - CGM.getContext().VoidPtrTy, Args); - llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); - std::string Name = getName({"__kmpc_global_ctor_", ""}); - llvm::Function *Fn = - CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); - CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, - Args, Loc, Loc); - llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( - CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, - CGM.getContext().VoidPtrTy, Dst.getLocation()); - Address Arg = Address(ArgVal, VDAddr.getAlignment()); - Arg = CtorCGF.Builder.CreateElementBitCast( - Arg, CtorCGF.ConvertTypeForMem(ASTTy)); - CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), - /*IsInitializer=*/true); - ArgVal = CtorCGF.EmitLoadOfScalar( - CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, - CGM.getContext().VoidPtrTy, Dst.getLocation()); - CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); - CtorCGF.FinishFunction(); - Ctor = Fn; - } - if (VD->getType().isDestructedType() != QualType::DK_none) { - // Generate function that emits destructor call for the threadprivate copy - // of the variable VD - CodeGenFunction DtorCGF(CGM); - FunctionArgList Args; - ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, - /*Id=*/nullptr, CGM.getContext().VoidPtrTy, - ImplicitParamDecl::Other); - Args.push_back(&Dst); - - const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( - CGM.getContext().VoidTy, Args); - llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); - std::string Name = getName({"__kmpc_global_dtor_", ""}); - llvm::Function *Fn = - CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); - auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); - DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, - Loc, Loc); - // Create a scope with an artificial location for the body of this function. - auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); - llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( - DtorCGF.GetAddrOfLocalVar(&Dst), - /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); - DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, - DtorCGF.getDestroyer(ASTTy.isDestructedType()), - DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); - DtorCGF.FinishFunction(); - Dtor = Fn; - } - // Do not emit init function if it is not required. - if (!Ctor && !Dtor) - return nullptr; - - llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; - auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, - /*isVarArg=*/false) - ->getPointerTo(); - // Copying constructor for the threadprivate variable. - // Must be NULL - reserved by runtime, but currently it requires that this - // parameter is always NULL. Otherwise it fires assertion. - CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); - if (Ctor == nullptr) { - auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, - /*isVarArg=*/false) - ->getPointerTo(); - Ctor = llvm::Constant::getNullValue(CtorTy); - } - if (Dtor == nullptr) { - auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, - /*isVarArg=*/false) - ->getPointerTo(); - Dtor = llvm::Constant::getNullValue(DtorTy); - } - if (!CGF) { - auto *InitFunctionTy = - llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); - std::string Name = getName({"__omp_threadprivate_init_", ""}); - llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction( - InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); - CodeGenFunction InitCGF(CGM); - FunctionArgList ArgList; - InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, - CGM.getTypes().arrangeNullaryFunction(), ArgList, - Loc, Loc); - emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); - InitCGF.FinishFunction(); - return InitFunction; - } - emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); - } - return nullptr; -} - -/// Obtain information that uniquely identifies a target entry. This -/// consists of the file and device IDs as well as line number associated with -/// the relevant entry source location. -static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, - unsigned &DeviceID, unsigned &FileID, - unsigned &LineNum) { - SourceManager &SM = C.getSourceManager(); - - // The loc should be always valid and have a file ID (the user cannot use - // #pragma directives in macros) - - assert(Loc.isValid() && "Source location is expected to be always valid."); - - PresumedLoc PLoc = SM.getPresumedLoc(Loc); - assert(PLoc.isValid() && "Source location is expected to be always valid."); - - llvm::sys::fs::UniqueID ID; - if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) - SM.getDiagnostics().Report(diag::err_cannot_open_file) - << PLoc.getFilename() << EC.message(); - - DeviceID = ID.getDevice(); - FileID = ID.getFile(); - LineNum = PLoc.getLine(); -} - -bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, - llvm::GlobalVariable *Addr, - bool PerformInit) { - Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); - if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link) - return CGM.getLangOpts().OpenMPIsDevice; - VD = VD->getDefinition(CGM.getContext()); - if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) - return CGM.getLangOpts().OpenMPIsDevice; - - QualType ASTTy = VD->getType(); - - SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); - // Produce the unique prefix to identify the new target regions. We use - // the source location of the variable declaration which we know to not - // conflict with any target region. - unsigned DeviceID; - unsigned FileID; - unsigned Line; - getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); - SmallString<128> Buffer, Out; - { - llvm::raw_svector_ostream OS(Buffer); - OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) - << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; - } - - const Expr *Init = VD->getAnyInitializer(); - if (CGM.getLangOpts().CPlusPlus && PerformInit) { - llvm::Constant *Ctor; - llvm::Constant *ID; - if (CGM.getLangOpts().OpenMPIsDevice) { - // Generate function that re-emits the declaration's initializer into - // the threadprivate copy of the variable VD - CodeGenFunction CtorCGF(CGM); - - const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); - llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); - llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( - FTy, Twine(Buffer, "_ctor"), FI, Loc); - auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); - CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, - FunctionArgList(), Loc, Loc); - auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); - CtorCGF.EmitAnyExprToMem(Init, - Address(Addr, CGM.getContext().getDeclAlign(VD)), - Init->getType().getQualifiers(), - /*IsInitializer=*/true); - CtorCGF.FinishFunction(); - Ctor = Fn; - ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); - CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); - } else { - Ctor = new llvm::GlobalVariable( - CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, - llvm::GlobalValue::PrivateLinkage, - llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); - ID = Ctor; - } - - // Register the information for the entry associated with the constructor. - Out.clear(); - OffloadEntriesInfoManager.registerTargetRegionEntryInfo( - DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, - ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); - } - if (VD->getType().isDestructedType() != QualType::DK_none) { - llvm::Constant *Dtor; - llvm::Constant *ID; - if (CGM.getLangOpts().OpenMPIsDevice) { - // Generate function that emits destructor call for the threadprivate - // copy of the variable VD - CodeGenFunction DtorCGF(CGM); - - const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); - llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); - llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( - FTy, Twine(Buffer, "_dtor"), FI, Loc); - auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); - DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, - FunctionArgList(), Loc, Loc); - // Create a scope with an artificial location for the body of this - // function. - auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); - DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), - ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), - DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); - DtorCGF.FinishFunction(); - Dtor = Fn; - ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); - CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); - } else { - Dtor = new llvm::GlobalVariable( - CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, - llvm::GlobalValue::PrivateLinkage, - llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); - ID = Dtor; - } - // Register the information for the entry associated with the destructor. - Out.clear(); - OffloadEntriesInfoManager.registerTargetRegionEntryInfo( - DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, - ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); - } - return CGM.getLangOpts().OpenMPIsDevice; -} - -Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, - QualType VarType, - StringRef Name) { - std::string Suffix = getName({"artificial", ""}); - std::string CacheSuffix = getName({"cache", ""}); - llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); - llvm::Value *GAddr = - getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); - llvm::Value *Args[] = { - emitUpdateLocation(CGF, SourceLocation()), - getThreadID(CGF, SourceLocation()), - CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), - CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, - /*IsSigned=*/false), - getOrCreateInternalVariable( - CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; - return Address( - CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - CGF.EmitRuntimeCall( - createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), - VarLVType->getPointerTo(/*AddrSpace=*/0)), - CGM.getPointerAlign()); -} - -void CGOpenMPRuntime::emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond, - const RegionCodeGenTy &ThenGen, - const RegionCodeGenTy &ElseGen) { - CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); - - // If the condition constant folds and can be elided, try to avoid emitting - // the condition and the dead arm of the if/else. - bool CondConstant; - if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { - if (CondConstant) - ThenGen(CGF); - else - ElseGen(CGF); - return; - } - - // Otherwise, the condition did not fold, or we couldn't elide it. Just - // emit the conditional branch. - llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); - llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); - llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); - CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); - - // Emit the 'then' code. - CGF.EmitBlock(ThenBlock); - ThenGen(CGF); - CGF.EmitBranch(ContBlock); - // Emit the 'else' code if present. - // There is no need to emit line number for unconditional branch. - (void)ApplyDebugLocation::CreateEmpty(CGF); - CGF.EmitBlock(ElseBlock); - ElseGen(CGF); - // There is no need to emit line number for unconditional branch. - (void)ApplyDebugLocation::CreateEmpty(CGF); - CGF.EmitBranch(ContBlock); - // Emit the continuation block for code after the if. - CGF.EmitBlock(ContBlock, /*IsFinished=*/true); -} - -void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, - llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> CapturedVars, - const Expr *IfCond) { - if (!CGF.HaveInsertPoint()) - return; - llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); - auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF, - PrePostActionTy &) { - // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); - CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); - llvm::Value *Args[] = { - RTLoc, - CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars - CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; - llvm::SmallVector<llvm::Value *, 16> RealArgs; - RealArgs.append(std::begin(Args), std::end(Args)); - RealArgs.append(CapturedVars.begin(), CapturedVars.end()); - - llvm::Value *RTLFn = RT.createRuntimeFunction(OMPRTL__kmpc_fork_call); - CGF.EmitRuntimeCall(RTLFn, RealArgs); - }; - auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF, - PrePostActionTy &) { - CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); - llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); - // Build calls: - // __kmpc_serialized_parallel(&Loc, GTid); - llvm::Value *Args[] = {RTLoc, ThreadID}; - CGF.EmitRuntimeCall( - RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args); - - // OutlinedFn(>id, &zero, CapturedStruct); - Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, - /*Name*/ ".zero.addr"); - CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0)); - llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; - // ThreadId for serialized parallels is 0. - OutlinedFnArgs.push_back(ZeroAddr.getPointer()); - OutlinedFnArgs.push_back(ZeroAddr.getPointer()); - OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); - RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); - - // __kmpc_end_serialized_parallel(&Loc, GTid); - llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; - CGF.EmitRuntimeCall( - RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), - EndArgs); - }; - if (IfCond) { - emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen); - } else { - RegionCodeGenTy ThenRCG(ThenGen); - ThenRCG(CGF); - } -} - -// If we're inside an (outlined) parallel region, use the region info's -// thread-ID variable (it is passed in a first argument of the outlined function -// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in -// regular serial code region, get thread ID by calling kmp_int32 -// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and -// return the address of that temp. -Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, - SourceLocation Loc) { - if (auto *OMPRegionInfo = - dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) - if (OMPRegionInfo->getThreadIDVariable()) - return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(); - - llvm::Value *ThreadID = getThreadID(CGF, Loc); - QualType Int32Ty = - CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); - Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); - CGF.EmitStoreOfScalar(ThreadID, - CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); - - return ThreadIDTemp; -} - -llvm::Constant * -CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty, - const llvm::Twine &Name) { - SmallString<256> Buffer; - llvm::raw_svector_ostream Out(Buffer); - Out << Name; - StringRef RuntimeName = Out.str(); - auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; - if (Elem.second) { - assert(Elem.second->getType()->getPointerElementType() == Ty && - "OMP internal variable has different type than requested"); - return &*Elem.second; - } - - return Elem.second = new llvm::GlobalVariable( - CGM.getModule(), Ty, /*IsConstant*/ false, - llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), - Elem.first()); -} - -llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { - std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); - std::string Name = getName({Prefix, "var"}); - return getOrCreateInternalVariable(KmpCriticalNameTy, Name); -} - -namespace { -/// Common pre(post)-action for different OpenMP constructs. -class CommonActionTy final : public PrePostActionTy { - llvm::Value *EnterCallee; - ArrayRef<llvm::Value *> EnterArgs; - llvm::Value *ExitCallee; - ArrayRef<llvm::Value *> ExitArgs; - bool Conditional; - llvm::BasicBlock *ContBlock = nullptr; - -public: - CommonActionTy(llvm::Value *EnterCallee, ArrayRef<llvm::Value *> EnterArgs, - llvm::Value *ExitCallee, ArrayRef<llvm::Value *> ExitArgs, - bool Conditional = false) - : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), - ExitArgs(ExitArgs), Conditional(Conditional) {} - void Enter(CodeGenFunction &CGF) override { - llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); - if (Conditional) { - llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); - auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); - ContBlock = CGF.createBasicBlock("omp_if.end"); - // Generate the branch (If-stmt) - CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); - CGF.EmitBlock(ThenBlock); - } - } - void Done(CodeGenFunction &CGF) { - // Emit the rest of blocks/branches - CGF.EmitBranch(ContBlock); - CGF.EmitBlock(ContBlock, true); - } - void Exit(CodeGenFunction &CGF) override { - CGF.EmitRuntimeCall(ExitCallee, ExitArgs); - } -}; -} // anonymous namespace - -void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, - StringRef CriticalName, - const RegionCodeGenTy &CriticalOpGen, - SourceLocation Loc, const Expr *Hint) { - // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); - // CriticalOpGen(); - // __kmpc_end_critical(ident_t *, gtid, Lock); - // Prepare arguments and build a call to __kmpc_critical - if (!CGF.HaveInsertPoint()) - return; - llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), - getCriticalRegionLock(CriticalName)}; - llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), - std::end(Args)); - if (Hint) { - EnterArgs.push_back(CGF.Builder.CreateIntCast( - CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false)); - } - CommonActionTy Action( - createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint - : OMPRTL__kmpc_critical), - EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args); - CriticalOpGen.setAction(Action); - emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); -} - -void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, - const RegionCodeGenTy &MasterOpGen, - SourceLocation Loc) { - if (!CGF.HaveInsertPoint()) - return; - // if(__kmpc_master(ident_t *, gtid)) { - // MasterOpGen(); - // __kmpc_end_master(ident_t *, gtid); - // } - // Prepare arguments and build a call to __kmpc_master - llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; - CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args, - createRuntimeFunction(OMPRTL__kmpc_end_master), Args, - /*Conditional=*/true); - MasterOpGen.setAction(Action); - emitInlinedDirective(CGF, OMPD_master, MasterOpGen); - Action.Done(CGF); -} - -void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, - SourceLocation Loc) { - if (!CGF.HaveInsertPoint()) - return; - // Build call __kmpc_omp_taskyield(loc, thread_id, 0); - llvm::Value *Args[] = { - emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), - llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args); - if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) - Region->emitUntiedSwitch(CGF); -} - -void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, - const RegionCodeGenTy &TaskgroupOpGen, - SourceLocation Loc) { - if (!CGF.HaveInsertPoint()) - return; - // __kmpc_taskgroup(ident_t *, gtid); - // TaskgroupOpGen(); - // __kmpc_end_taskgroup(ident_t *, gtid); - // Prepare arguments and build a call to __kmpc_taskgroup - llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; - CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args, - createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), - Args); - TaskgroupOpGen.setAction(Action); - emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); -} - -/// Given an array of pointers to variables, project the address of a -/// given variable. -static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, - unsigned Index, const VarDecl *Var) { - // Pull out the pointer to the variable. - Address PtrAddr = - CGF.Builder.CreateConstArrayGEP(Array, Index, CGF.getPointerSize()); - llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); - - Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); - Addr = CGF.Builder.CreateElementBitCast( - Addr, CGF.ConvertTypeForMem(Var->getType())); - return Addr; -} - -static llvm::Value *emitCopyprivateCopyFunction( - CodeGenModule &CGM, llvm::Type *ArgsType, - ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, - ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, - SourceLocation Loc) { - ASTContext &C = CGM.getContext(); - // void copy_func(void *LHSArg, void *RHSArg); - FunctionArgList Args; - ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, - ImplicitParamDecl::Other); - ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, - ImplicitParamDecl::Other); - Args.push_back(&LHSArg); - Args.push_back(&RHSArg); - const auto &CGFI = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); - std::string Name = - CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); - auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), - llvm::GlobalValue::InternalLinkage, Name, - &CGM.getModule()); - CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); - Fn->setDoesNotRecurse(); - CodeGenFunction CGF(CGM); - CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); - // Dest = (void*[n])(LHSArg); - // Src = (void*[n])(RHSArg); - Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), - ArgsType), CGF.getPointerAlign()); - Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), - ArgsType), CGF.getPointerAlign()); - // *(Type0*)Dst[0] = *(Type0*)Src[0]; - // *(Type1*)Dst[1] = *(Type1*)Src[1]; - // ... - // *(Typen*)Dst[n] = *(Typen*)Src[n]; - for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { - const auto *DestVar = - cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); - Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); - - const auto *SrcVar = - cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); - Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); - - const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); - QualType Type = VD->getType(); - CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); - } - CGF.FinishFunction(); - return Fn; -} - -void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, - const RegionCodeGenTy &SingleOpGen, - SourceLocation Loc, - ArrayRef<const Expr *> CopyprivateVars, - ArrayRef<const Expr *> SrcExprs, - ArrayRef<const Expr *> DstExprs, - ArrayRef<const Expr *> AssignmentOps) { - if (!CGF.HaveInsertPoint()) - return; - assert(CopyprivateVars.size() == SrcExprs.size() && - CopyprivateVars.size() == DstExprs.size() && - CopyprivateVars.size() == AssignmentOps.size()); - ASTContext &C = CGM.getContext(); - // int32 did_it = 0; - // if(__kmpc_single(ident_t *, gtid)) { - // SingleOpGen(); - // __kmpc_end_single(ident_t *, gtid); - // did_it = 1; - // } - // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, - // <copy_func>, did_it); - - Address DidIt = Address::invalid(); - if (!CopyprivateVars.empty()) { - // int32 did_it = 0; - QualType KmpInt32Ty = - C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); - DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); - CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); - } - // Prepare arguments and build a call to __kmpc_single - llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; - CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args, - createRuntimeFunction(OMPRTL__kmpc_end_single), Args, - /*Conditional=*/true); - SingleOpGen.setAction(Action); - emitInlinedDirective(CGF, OMPD_single, SingleOpGen); - if (DidIt.isValid()) { - // did_it = 1; - CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); - } - Action.Done(CGF); - // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, - // <copy_func>, did_it); - if (DidIt.isValid()) { - llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); - QualType CopyprivateArrayTy = - C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal, - /*IndexTypeQuals=*/0); - // Create a list of all private variables for copyprivate. - Address CopyprivateList = - CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); - for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { - Address Elem = CGF.Builder.CreateConstArrayGEP( - CopyprivateList, I, CGF.getPointerSize()); - CGF.Builder.CreateStore( - CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy), - Elem); - } - // Build function that copies private values from single region to all other - // threads in the corresponding parallel region. - llvm::Value *CpyFn = emitCopyprivateCopyFunction( - CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), - CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); - llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); - Address CL = - CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, - CGF.VoidPtrTy); - llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); - llvm::Value *Args[] = { - emitUpdateLocation(CGF, Loc), // ident_t *<loc> - getThreadID(CGF, Loc), // i32 <gtid> - BufSize, // size_t <buf_size> - CL.getPointer(), // void *<copyprivate list> - CpyFn, // void (*) (void *, void *) <copy_func> - DidItVal // i32 did_it - }; - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); - } -} - -void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, - const RegionCodeGenTy &OrderedOpGen, - SourceLocation Loc, bool IsThreads) { - if (!CGF.HaveInsertPoint()) - return; - // __kmpc_ordered(ident_t *, gtid); - // OrderedOpGen(); - // __kmpc_end_ordered(ident_t *, gtid); - // Prepare arguments and build a call to __kmpc_ordered - if (IsThreads) { - llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; - CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args, - createRuntimeFunction(OMPRTL__kmpc_end_ordered), - Args); - OrderedOpGen.setAction(Action); - emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); - return; - } - emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); -} - -unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { - unsigned Flags; - if (Kind == OMPD_for) - Flags = OMP_IDENT_BARRIER_IMPL_FOR; - else if (Kind == OMPD_sections) - Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; - else if (Kind == OMPD_single) - Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; - else if (Kind == OMPD_barrier) - Flags = OMP_IDENT_BARRIER_EXPL; - else - Flags = OMP_IDENT_BARRIER_IMPL; - return Flags; -} - -void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDirectiveKind Kind, bool EmitChecks, - bool ForceSimpleCall) { - if (!CGF.HaveInsertPoint()) - return; - // Build call __kmpc_cancel_barrier(loc, thread_id); - // Build call __kmpc_barrier(loc, thread_id); - unsigned Flags = getDefaultFlagsForBarriers(Kind); - // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, - // thread_id); - llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), - getThreadID(CGF, Loc)}; - if (auto *OMPRegionInfo = - dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { - if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { - llvm::Value *Result = CGF.EmitRuntimeCall( - createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); - if (EmitChecks) { - // if (__kmpc_cancel_barrier()) { - // exit from construct; - // } - llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); - llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); - llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); - CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); - CGF.EmitBlock(ExitBB); - // exit from construct; - CodeGenFunction::JumpDest CancelDestination = - CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); - CGF.EmitBranchThroughCleanup(CancelDestination); - CGF.EmitBlock(ContBB, /*IsFinished=*/true); - } - return; - } - } - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); -} - -/// Map the OpenMP loop schedule to the runtime enumeration. -static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, - bool Chunked, bool Ordered) { - switch (ScheduleKind) { - case OMPC_SCHEDULE_static: - return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) - : (Ordered ? OMP_ord_static : OMP_sch_static); - case OMPC_SCHEDULE_dynamic: - return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; - case OMPC_SCHEDULE_guided: - return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; - case OMPC_SCHEDULE_runtime: - return Ordered ? OMP_ord_runtime : OMP_sch_runtime; - case OMPC_SCHEDULE_auto: - return Ordered ? OMP_ord_auto : OMP_sch_auto; - case OMPC_SCHEDULE_unknown: - assert(!Chunked && "chunk was specified but schedule kind not known"); - return Ordered ? OMP_ord_static : OMP_sch_static; - } - llvm_unreachable("Unexpected runtime schedule"); -} - -/// Map the OpenMP distribute schedule to the runtime enumeration. -static OpenMPSchedType -getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { - // only static is allowed for dist_schedule - return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; -} - -bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, - bool Chunked) const { - OpenMPSchedType Schedule = - getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); - return Schedule == OMP_sch_static; -} - -bool CGOpenMPRuntime::isStaticNonchunked( - OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { - OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); - return Schedule == OMP_dist_sch_static; -} - -bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, - bool Chunked) const { - OpenMPSchedType Schedule = - getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); - return Schedule == OMP_sch_static_chunked; -} - -bool CGOpenMPRuntime::isStaticChunked( - OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { - OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); - return Schedule == OMP_dist_sch_static_chunked; -} - -bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { - OpenMPSchedType Schedule = - getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); - assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); - return Schedule != OMP_sch_static; -} - -static int addMonoNonMonoModifier(OpenMPSchedType Schedule, - OpenMPScheduleClauseModifier M1, - OpenMPScheduleClauseModifier M2) { - int Modifier = 0; - switch (M1) { - case OMPC_SCHEDULE_MODIFIER_monotonic: - Modifier = OMP_sch_modifier_monotonic; - break; - case OMPC_SCHEDULE_MODIFIER_nonmonotonic: - Modifier = OMP_sch_modifier_nonmonotonic; - break; - case OMPC_SCHEDULE_MODIFIER_simd: - if (Schedule == OMP_sch_static_chunked) - Schedule = OMP_sch_static_balanced_chunked; - break; - case OMPC_SCHEDULE_MODIFIER_last: - case OMPC_SCHEDULE_MODIFIER_unknown: - break; - } - switch (M2) { - case OMPC_SCHEDULE_MODIFIER_monotonic: - Modifier = OMP_sch_modifier_monotonic; - break; - case OMPC_SCHEDULE_MODIFIER_nonmonotonic: - Modifier = OMP_sch_modifier_nonmonotonic; - break; - case OMPC_SCHEDULE_MODIFIER_simd: - if (Schedule == OMP_sch_static_chunked) - Schedule = OMP_sch_static_balanced_chunked; - break; - case OMPC_SCHEDULE_MODIFIER_last: - case OMPC_SCHEDULE_MODIFIER_unknown: - break; - } - return Schedule | Modifier; -} - -void CGOpenMPRuntime::emitForDispatchInit( - CodeGenFunction &CGF, SourceLocation Loc, - const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, - bool Ordered, const DispatchRTInput &DispatchValues) { - if (!CGF.HaveInsertPoint()) - return; - OpenMPSchedType Schedule = getRuntimeSchedule( - ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); - assert(Ordered || - (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && - Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && - Schedule != OMP_sch_static_balanced_chunked)); - // Call __kmpc_dispatch_init( - // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, - // kmp_int[32|64] lower, kmp_int[32|64] upper, - // kmp_int[32|64] stride, kmp_int[32|64] chunk); - - // If the Chunk was not specified in the clause - use default value 1. - llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk - : CGF.Builder.getIntN(IVSize, 1); - llvm::Value *Args[] = { - emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), - CGF.Builder.getInt32(addMonoNonMonoModifier( - Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type - DispatchValues.LB, // Lower - DispatchValues.UB, // Upper - CGF.Builder.getIntN(IVSize, 1), // Stride - Chunk // Chunk - }; - CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); -} - -static void emitForStaticInitCall( - CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, - llvm::Constant *ForStaticInitFunction, OpenMPSchedType Schedule, - OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, - const CGOpenMPRuntime::StaticRTInput &Values) { - if (!CGF.HaveInsertPoint()) - return; - - assert(!Values.Ordered); - assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || - Schedule == OMP_sch_static_balanced_chunked || - Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || - Schedule == OMP_dist_sch_static || - Schedule == OMP_dist_sch_static_chunked); - - // Call __kmpc_for_static_init( - // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, - // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, - // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, - // kmp_int[32|64] incr, kmp_int[32|64] chunk); - llvm::Value *Chunk = Values.Chunk; - if (Chunk == nullptr) { - assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || - Schedule == OMP_dist_sch_static) && - "expected static non-chunked schedule"); - // If the Chunk was not specified in the clause - use default value 1. - Chunk = CGF.Builder.getIntN(Values.IVSize, 1); - } else { - assert((Schedule == OMP_sch_static_chunked || - Schedule == OMP_sch_static_balanced_chunked || - Schedule == OMP_ord_static_chunked || - Schedule == OMP_dist_sch_static_chunked) && - "expected static chunked schedule"); - } - llvm::Value *Args[] = { - UpdateLocation, - ThreadId, - CGF.Builder.getInt32(addMonoNonMonoModifier(Schedule, M1, - M2)), // Schedule type - Values.IL.getPointer(), // &isLastIter - Values.LB.getPointer(), // &LB - Values.UB.getPointer(), // &UB - Values.ST.getPointer(), // &Stride - CGF.Builder.getIntN(Values.IVSize, 1), // Incr - Chunk // Chunk - }; - CGF.EmitRuntimeCall(ForStaticInitFunction, Args); -} - -void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, - SourceLocation Loc, - OpenMPDirectiveKind DKind, - const OpenMPScheduleTy &ScheduleKind, - const StaticRTInput &Values) { - OpenMPSchedType ScheduleNum = getRuntimeSchedule( - ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); - assert(isOpenMPWorksharingDirective(DKind) && - "Expected loop-based or sections-based directive."); - llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, - isOpenMPLoopDirective(DKind) - ? OMP_IDENT_WORK_LOOP - : OMP_IDENT_WORK_SECTIONS); - llvm::Value *ThreadId = getThreadID(CGF, Loc); - llvm::Constant *StaticInitFunction = - createForStaticInitFunction(Values.IVSize, Values.IVSigned); - emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, - ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); -} - -void CGOpenMPRuntime::emitDistributeStaticInit( - CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDistScheduleClauseKind SchedKind, - const CGOpenMPRuntime::StaticRTInput &Values) { - OpenMPSchedType ScheduleNum = - getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); - llvm::Value *UpdatedLocation = - emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); - llvm::Value *ThreadId = getThreadID(CGF, Loc); - llvm::Constant *StaticInitFunction = - createForStaticInitFunction(Values.IVSize, Values.IVSigned); - emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, - ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, - OMPC_SCHEDULE_MODIFIER_unknown, Values); -} - -void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, - SourceLocation Loc, - OpenMPDirectiveKind DKind) { - if (!CGF.HaveInsertPoint()) - return; - // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); - llvm::Value *Args[] = { - emitUpdateLocation(CGF, Loc, - isOpenMPDistributeDirective(DKind) - ? OMP_IDENT_WORK_DISTRIBUTE - : isOpenMPLoopDirective(DKind) - ? OMP_IDENT_WORK_LOOP - : OMP_IDENT_WORK_SECTIONS), - getThreadID(CGF, Loc)}; - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), - Args); -} - -void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, - SourceLocation Loc, - unsigned IVSize, - bool IVSigned) { - if (!CGF.HaveInsertPoint()) - return; - // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); - llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; - CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); -} - -llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, - SourceLocation Loc, unsigned IVSize, - bool IVSigned, Address IL, - Address LB, Address UB, - Address ST) { - // Call __kmpc_dispatch_next( - // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, - // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, - // kmp_int[32|64] *p_stride); - llvm::Value *Args[] = { - emitUpdateLocation(CGF, Loc), - getThreadID(CGF, Loc), - IL.getPointer(), // &isLastIter - LB.getPointer(), // &Lower - UB.getPointer(), // &Upper - ST.getPointer() // &Stride - }; - llvm::Value *Call = - CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); - return CGF.EmitScalarConversion( - Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), - CGF.getContext().BoolTy, Loc); -} - -void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, - llvm::Value *NumThreads, - SourceLocation Loc) { - if (!CGF.HaveInsertPoint()) - return; - // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) - llvm::Value *Args[] = { - emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), - CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), - Args); -} - -void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, - OpenMPProcBindClauseKind ProcBind, - SourceLocation Loc) { - if (!CGF.HaveInsertPoint()) - return; - // Constants for proc bind value accepted by the runtime. - enum ProcBindTy { - ProcBindFalse = 0, - ProcBindTrue, - ProcBindMaster, - ProcBindClose, - ProcBindSpread, - ProcBindIntel, - ProcBindDefault - } RuntimeProcBind; - switch (ProcBind) { - case OMPC_PROC_BIND_master: - RuntimeProcBind = ProcBindMaster; - break; - case OMPC_PROC_BIND_close: - RuntimeProcBind = ProcBindClose; - break; - case OMPC_PROC_BIND_spread: - RuntimeProcBind = ProcBindSpread; - break; - case OMPC_PROC_BIND_unknown: - llvm_unreachable("Unsupported proc_bind value."); - } - // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) - llvm::Value *Args[] = { - emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), - llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)}; - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args); -} - -void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, - SourceLocation Loc) { - if (!CGF.HaveInsertPoint()) - return; - // Build call void __kmpc_flush(ident_t *loc) - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), - emitUpdateLocation(CGF, Loc)); -} - -namespace { -/// Indexes of fields for type kmp_task_t. -enum KmpTaskTFields { - /// List of shared variables. - KmpTaskTShareds, - /// Task routine. - KmpTaskTRoutine, - /// Partition id for the untied tasks. - KmpTaskTPartId, - /// Function with call of destructors for private variables. - Data1, - /// Task priority. - Data2, - /// (Taskloops only) Lower bound. - KmpTaskTLowerBound, - /// (Taskloops only) Upper bound. - KmpTaskTUpperBound, - /// (Taskloops only) Stride. - KmpTaskTStride, - /// (Taskloops only) Is last iteration flag. - KmpTaskTLastIter, - /// (Taskloops only) Reduction data. - KmpTaskTReductions, -}; -} // anonymous namespace - -bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { - return OffloadEntriesTargetRegion.empty() && - OffloadEntriesDeviceGlobalVar.empty(); -} - -/// Initialize target region entry. -void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: - initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, - StringRef ParentName, unsigned LineNum, - unsigned Order) { - assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " - "only required for the device " - "code generation."); - OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = - OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, - OMPTargetRegionEntryTargetRegion); - ++OffloadingEntriesNum; -} - -void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: - registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, - StringRef ParentName, unsigned LineNum, - llvm::Constant *Addr, llvm::Constant *ID, - OMPTargetRegionEntryKind Flags) { - // If we are emitting code for a target, the entry is already initialized, - // only has to be registered. - if (CGM.getLangOpts().OpenMPIsDevice) { - if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) { - unsigned DiagID = CGM.getDiags().getCustomDiagID( - DiagnosticsEngine::Error, - "Unable to find target region on line '%0' in the device code."); - CGM.getDiags().Report(DiagID) << LineNum; - return; - } - auto &Entry = - OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; - assert(Entry.isValid() && "Entry not initialized!"); - Entry.setAddress(Addr); - Entry.setID(ID); - Entry.setFlags(Flags); - } else { - OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); - OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; - ++OffloadingEntriesNum; - } -} - -bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( - unsigned DeviceID, unsigned FileID, StringRef ParentName, - unsigned LineNum) const { - auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); - if (PerDevice == OffloadEntriesTargetRegion.end()) - return false; - auto PerFile = PerDevice->second.find(FileID); - if (PerFile == PerDevice->second.end()) - return false; - auto PerParentName = PerFile->second.find(ParentName); - if (PerParentName == PerFile->second.end()) - return false; - auto PerLine = PerParentName->second.find(LineNum); - if (PerLine == PerParentName->second.end()) - return false; - // Fail if this entry is already registered. - if (PerLine->second.getAddress() || PerLine->second.getID()) - return false; - return true; -} - -void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( - const OffloadTargetRegionEntryInfoActTy &Action) { - // Scan all target region entries and perform the provided action. - for (const auto &D : OffloadEntriesTargetRegion) - for (const auto &F : D.second) - for (const auto &P : F.second) - for (const auto &L : P.second) - Action(D.first, F.first, P.first(), L.first, L.second); -} - -void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: - initializeDeviceGlobalVarEntryInfo(StringRef Name, - OMPTargetGlobalVarEntryKind Flags, - unsigned Order) { - assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " - "only required for the device " - "code generation."); - OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); - ++OffloadingEntriesNum; -} - -void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: - registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, - CharUnits VarSize, - OMPTargetGlobalVarEntryKind Flags, - llvm::GlobalValue::LinkageTypes Linkage) { - if (CGM.getLangOpts().OpenMPIsDevice) { - auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; - assert(Entry.isValid() && Entry.getFlags() == Flags && - "Entry not initialized!"); - assert((!Entry.getAddress() || Entry.getAddress() == Addr) && - "Resetting with the new address."); - if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) - return; - Entry.setAddress(Addr); - Entry.setVarSize(VarSize); - Entry.setLinkage(Linkage); - } else { - if (hasDeviceGlobalVarEntryInfo(VarName)) - return; - OffloadEntriesDeviceGlobalVar.try_emplace( - VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); - ++OffloadingEntriesNum; - } -} - -void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: - actOnDeviceGlobalVarEntriesInfo( - const OffloadDeviceGlobalVarEntryInfoActTy &Action) { - // Scan all target region entries and perform the provided action. - for (const auto &E : OffloadEntriesDeviceGlobalVar) - Action(E.getKey(), E.getValue()); -} - -llvm::Function * -CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() { - // If we don't have entries or if we are emitting code for the device, we - // don't need to do anything. - if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty()) - return nullptr; - - llvm::Module &M = CGM.getModule(); - ASTContext &C = CGM.getContext(); - - // Get list of devices we care about - const std::vector<llvm::Triple> &Devices = CGM.getLangOpts().OMPTargetTriples; - - // We should be creating an offloading descriptor only if there are devices - // specified. - assert(!Devices.empty() && "No OpenMP offloading devices??"); - - // Create the external variables that will point to the begin and end of the - // host entries section. These will be defined by the linker. - llvm::Type *OffloadEntryTy = - CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy()); - std::string EntriesBeginName = getName({"omp_offloading", "entries_begin"}); - auto *HostEntriesBegin = new llvm::GlobalVariable( - M, OffloadEntryTy, /*isConstant=*/true, - llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr, - EntriesBeginName); - std::string EntriesEndName = getName({"omp_offloading", "entries_end"}); - auto *HostEntriesEnd = - new llvm::GlobalVariable(M, OffloadEntryTy, /*isConstant=*/true, - llvm::GlobalValue::ExternalLinkage, - /*Initializer=*/nullptr, EntriesEndName); - - // Create all device images - auto *DeviceImageTy = cast<llvm::StructType>( - CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy())); - ConstantInitBuilder DeviceImagesBuilder(CGM); - ConstantArrayBuilder DeviceImagesEntries = - DeviceImagesBuilder.beginArray(DeviceImageTy); - - for (const llvm::Triple &Device : Devices) { - StringRef T = Device.getTriple(); - std::string BeginName = getName({"omp_offloading", "img_start", ""}); - auto *ImgBegin = new llvm::GlobalVariable( - M, CGM.Int8Ty, /*isConstant=*/true, - llvm::GlobalValue::ExternalWeakLinkage, - /*Initializer=*/nullptr, Twine(BeginName).concat(T)); - std::string EndName = getName({"omp_offloading", "img_end", ""}); - auto *ImgEnd = new llvm::GlobalVariable( - M, CGM.Int8Ty, /*isConstant=*/true, - llvm::GlobalValue::ExternalWeakLinkage, - /*Initializer=*/nullptr, Twine(EndName).concat(T)); - - llvm::Constant *Data[] = {ImgBegin, ImgEnd, HostEntriesBegin, - HostEntriesEnd}; - createConstantGlobalStructAndAddToParent(CGM, getTgtDeviceImageQTy(), Data, - DeviceImagesEntries); - } - - // Create device images global array. - std::string ImagesName = getName({"omp_offloading", "device_images"}); - llvm::GlobalVariable *DeviceImages = - DeviceImagesEntries.finishAndCreateGlobal(ImagesName, - CGM.getPointerAlign(), - /*isConstant=*/true); - DeviceImages->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - - // This is a Zero array to be used in the creation of the constant expressions - llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty), - llvm::Constant::getNullValue(CGM.Int32Ty)}; - - // Create the target region descriptor. - llvm::Constant *Data[] = { - llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()), - llvm::ConstantExpr::getGetElementPtr(DeviceImages->getValueType(), - DeviceImages, Index), - HostEntriesBegin, HostEntriesEnd}; - std::string Descriptor = getName({"omp_offloading", "descriptor"}); - llvm::GlobalVariable *Desc = createGlobalStruct( - CGM, getTgtBinaryDescriptorQTy(), /*IsConstant=*/true, Data, Descriptor); - - // Emit code to register or unregister the descriptor at execution - // startup or closing, respectively. - - llvm::Function *UnRegFn; - { - FunctionArgList Args; - ImplicitParamDecl DummyPtr(C, C.VoidPtrTy, ImplicitParamDecl::Other); - Args.push_back(&DummyPtr); - - CodeGenFunction CGF(CGM); - // Disable debug info for global (de-)initializer because they are not part - // of some particular construct. - CGF.disableDebugInfo(); - const auto &FI = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); - llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); - std::string UnregName = getName({"omp_offloading", "descriptor_unreg"}); - UnRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, UnregName, FI); - CGF.StartFunction(GlobalDecl(), C.VoidTy, UnRegFn, FI, Args); - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_unregister_lib), - Desc); - CGF.FinishFunction(); - } - llvm::Function *RegFn; - { - CodeGenFunction CGF(CGM); - // Disable debug info for global (de-)initializer because they are not part - // of some particular construct. - CGF.disableDebugInfo(); - const auto &FI = CGM.getTypes().arrangeNullaryFunction(); - llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); - - // Encode offload target triples into the registration function name. It - // will serve as a comdat key for the registration/unregistration code for - // this particular combination of offloading targets. - SmallVector<StringRef, 4U> RegFnNameParts(Devices.size() + 2U); - RegFnNameParts[0] = "omp_offloading"; - RegFnNameParts[1] = "descriptor_reg"; - llvm::transform(Devices, std::next(RegFnNameParts.begin(), 2), - [](const llvm::Triple &T) -> const std::string& { - return T.getTriple(); - }); - llvm::sort(std::next(RegFnNameParts.begin(), 2), RegFnNameParts.end()); - std::string Descriptor = getName(RegFnNameParts); - RegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, Descriptor, FI); - CGF.StartFunction(GlobalDecl(), C.VoidTy, RegFn, FI, FunctionArgList()); - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_lib), Desc); - // Create a variable to drive the registration and unregistration of the - // descriptor, so we can reuse the logic that emits Ctors and Dtors. - ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(), - SourceLocation(), nullptr, C.CharTy, - ImplicitParamDecl::Other); - CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc); - CGF.FinishFunction(); - } - if (CGM.supportsCOMDAT()) { - // It is sufficient to call registration function only once, so create a - // COMDAT group for registration/unregistration functions and associated - // data. That would reduce startup time and code size. Registration - // function serves as a COMDAT group key. - llvm::Comdat *ComdatKey = M.getOrInsertComdat(RegFn->getName()); - RegFn->setLinkage(llvm::GlobalValue::LinkOnceAnyLinkage); - RegFn->setVisibility(llvm::GlobalValue::HiddenVisibility); - RegFn->setComdat(ComdatKey); - UnRegFn->setComdat(ComdatKey); - DeviceImages->setComdat(ComdatKey); - Desc->setComdat(ComdatKey); - } - return RegFn; -} - -void CGOpenMPRuntime::createOffloadEntry( - llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, - llvm::GlobalValue::LinkageTypes Linkage) { - StringRef Name = Addr->getName(); - llvm::Module &M = CGM.getModule(); - llvm::LLVMContext &C = M.getContext(); - - // Create constant string with the name. - llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); - - std::string StringName = getName({"omp_offloading", "entry_name"}); - auto *Str = new llvm::GlobalVariable( - M, StrPtrInit->getType(), /*isConstant=*/true, - llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); - Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - - llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy), - llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy), - llvm::ConstantInt::get(CGM.SizeTy, Size), - llvm::ConstantInt::get(CGM.Int32Ty, Flags), - llvm::ConstantInt::get(CGM.Int32Ty, 0)}; - std::string EntryName = getName({"omp_offloading", "entry", ""}); - llvm::GlobalVariable *Entry = createGlobalStruct( - CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, - Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); - - // The entry has to be created in the section the linker expects it to be. - std::string Section = getName({"omp_offloading", "entries"}); - Entry->setSection(Section); -} - -void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { - // Emit the offloading entries and metadata so that the device codegen side - // can easily figure out what to emit. The produced metadata looks like - // this: - // - // !omp_offload.info = !{!1, ...} - // - // Right now we only generate metadata for function that contain target - // regions. - - // If we do not have entries, we don't need to do anything. - if (OffloadEntriesInfoManager.empty()) - return; - - llvm::Module &M = CGM.getModule(); - llvm::LLVMContext &C = M.getContext(); - SmallVector<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16> - OrderedEntries(OffloadEntriesInfoManager.size()); - llvm::SmallVector<StringRef, 16> ParentFunctions( - OffloadEntriesInfoManager.size()); - - // Auxiliary methods to create metadata values and strings. - auto &&GetMDInt = [this](unsigned V) { - return llvm::ConstantAsMetadata::get( - llvm::ConstantInt::get(CGM.Int32Ty, V)); - }; - - auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; - - // Create the offloading info metadata node. - llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); - - // Create function that emits metadata for each target region entry; - auto &&TargetRegionMetadataEmitter = - [&C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, &GetMDString]( - unsigned DeviceID, unsigned FileID, StringRef ParentName, - unsigned Line, - const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { - // Generate metadata for target regions. Each entry of this metadata - // contains: - // - Entry 0 -> Kind of this type of metadata (0). - // - Entry 1 -> Device ID of the file where the entry was identified. - // - Entry 2 -> File ID of the file where the entry was identified. - // - Entry 3 -> Mangled name of the function where the entry was - // identified. - // - Entry 4 -> Line in the file where the entry was identified. - // - Entry 5 -> Order the entry was created. - // The first element of the metadata node is the kind. - llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), - GetMDInt(FileID), GetMDString(ParentName), - GetMDInt(Line), GetMDInt(E.getOrder())}; - - // Save this entry in the right position of the ordered entries array. - OrderedEntries[E.getOrder()] = &E; - ParentFunctions[E.getOrder()] = ParentName; - - // Add metadata to the named metadata node. - MD->addOperand(llvm::MDNode::get(C, Ops)); - }; - - OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( - TargetRegionMetadataEmitter); - - // Create function that emits metadata for each device global variable entry; - auto &&DeviceGlobalVarMetadataEmitter = - [&C, &OrderedEntries, &GetMDInt, &GetMDString, - MD](StringRef MangledName, - const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar - &E) { - // Generate metadata for global variables. Each entry of this metadata - // contains: - // - Entry 0 -> Kind of this type of metadata (1). - // - Entry 1 -> Mangled name of the variable. - // - Entry 2 -> Declare target kind. - // - Entry 3 -> Order the entry was created. - // The first element of the metadata node is the kind. - llvm::Metadata *Ops[] = { - GetMDInt(E.getKind()), GetMDString(MangledName), - GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; - - // Save this entry in the right position of the ordered entries array. - OrderedEntries[E.getOrder()] = &E; - - // Add metadata to the named metadata node. - MD->addOperand(llvm::MDNode::get(C, Ops)); - }; - - OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( - DeviceGlobalVarMetadataEmitter); - - for (const auto *E : OrderedEntries) { - assert(E && "All ordered entries must exist!"); - if (const auto *CE = - dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( - E)) { - if (!CE->getID() || !CE->getAddress()) { - // Do not blame the entry if the parent funtion is not emitted. - StringRef FnName = ParentFunctions[CE->getOrder()]; - if (!CGM.GetGlobalValue(FnName)) - continue; - unsigned DiagID = CGM.getDiags().getCustomDiagID( - DiagnosticsEngine::Error, - "Offloading entry for target region is incorrect: either the " - "address or the ID is invalid."); - CGM.getDiags().Report(DiagID); - continue; - } - createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, - CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); - } else if (const auto *CE = - dyn_cast<OffloadEntriesInfoManagerTy:: - OffloadEntryInfoDeviceGlobalVar>(E)) { - OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = - static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( - CE->getFlags()); - switch (Flags) { - case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { - if (!CE->getAddress()) { - unsigned DiagID = CGM.getDiags().getCustomDiagID( - DiagnosticsEngine::Error, - "Offloading entry for declare target variable is incorrect: the " - "address is invalid."); - CGM.getDiags().Report(DiagID); - continue; - } - // The vaiable has no definition - no need to add the entry. - if (CE->getVarSize().isZero()) - continue; - break; - } - case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: - assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || - (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && - "Declaret target link address is set."); - if (CGM.getLangOpts().OpenMPIsDevice) - continue; - if (!CE->getAddress()) { - unsigned DiagID = CGM.getDiags().getCustomDiagID( - DiagnosticsEngine::Error, - "Offloading entry for declare target variable is incorrect: the " - "address is invalid."); - CGM.getDiags().Report(DiagID); - continue; - } - break; - } - createOffloadEntry(CE->getAddress(), CE->getAddress(), - CE->getVarSize().getQuantity(), Flags, - CE->getLinkage()); - } else { - llvm_unreachable("Unsupported entry kind."); - } - } -} - -/// Loads all the offload entries information from the host IR -/// metadata. -void CGOpenMPRuntime::loadOffloadInfoMetadata() { - // If we are in target mode, load the metadata from the host IR. This code has - // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). - - if (!CGM.getLangOpts().OpenMPIsDevice) - return; - - if (CGM.getLangOpts().OMPHostIRFile.empty()) - return; - - auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); - if (auto EC = Buf.getError()) { - CGM.getDiags().Report(diag::err_cannot_open_file) - << CGM.getLangOpts().OMPHostIRFile << EC.message(); - return; - } - - llvm::LLVMContext C; - auto ME = expectedToErrorOrAndEmitErrors( - C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); - - if (auto EC = ME.getError()) { - unsigned DiagID = CGM.getDiags().getCustomDiagID( - DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); - CGM.getDiags().Report(DiagID) - << CGM.getLangOpts().OMPHostIRFile << EC.message(); - return; - } - - llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); - if (!MD) - return; - - for (llvm::MDNode *MN : MD->operands()) { - auto &&GetMDInt = [MN](unsigned Idx) { - auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); - return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); - }; - - auto &&GetMDString = [MN](unsigned Idx) { - auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); - return V->getString(); - }; - - switch (GetMDInt(0)) { - default: - llvm_unreachable("Unexpected metadata!"); - break; - case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: - OffloadingEntryInfoTargetRegion: - OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( - /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), - /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), - /*Order=*/GetMDInt(5)); - break; - case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: - OffloadingEntryInfoDeviceGlobalVar: - OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( - /*MangledName=*/GetMDString(1), - static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( - /*Flags=*/GetMDInt(2)), - /*Order=*/GetMDInt(3)); - break; - } - } -} - -void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { - if (!KmpRoutineEntryPtrTy) { - // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. - ASTContext &C = CGM.getContext(); - QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; - FunctionProtoType::ExtProtoInfo EPI; - KmpRoutineEntryPtrQTy = C.getPointerType( - C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); - KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); - } -} - -QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { - // Make sure the type of the entry is already created. This is the type we - // have to create: - // struct __tgt_offload_entry{ - // void *addr; // Pointer to the offload entry info. - // // (function or global) - // char *name; // Name of the function or global. - // size_t size; // Size of the entry info (0 if it a function). - // int32_t flags; // Flags associated with the entry, e.g. 'link'. - // int32_t reserved; // Reserved, to use by the runtime library. - // }; - if (TgtOffloadEntryQTy.isNull()) { - ASTContext &C = CGM.getContext(); - RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); - RD->startDefinition(); - addFieldToRecordDecl(C, RD, C.VoidPtrTy); - addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); - addFieldToRecordDecl(C, RD, C.getSizeType()); - addFieldToRecordDecl( - C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); - addFieldToRecordDecl( - C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); - RD->completeDefinition(); - RD->addAttr(PackedAttr::CreateImplicit(C)); - TgtOffloadEntryQTy = C.getRecordType(RD); - } - return TgtOffloadEntryQTy; -} - -QualType CGOpenMPRuntime::getTgtDeviceImageQTy() { - // These are the types we need to build: - // struct __tgt_device_image{ - // void *ImageStart; // Pointer to the target code start. - // void *ImageEnd; // Pointer to the target code end. - // // We also add the host entries to the device image, as it may be useful - // // for the target runtime to have access to that information. - // __tgt_offload_entry *EntriesBegin; // Begin of the table with all - // // the entries. - // __tgt_offload_entry *EntriesEnd; // End of the table with all the - // // entries (non inclusive). - // }; - if (TgtDeviceImageQTy.isNull()) { - ASTContext &C = CGM.getContext(); - RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image"); - RD->startDefinition(); - addFieldToRecordDecl(C, RD, C.VoidPtrTy); - addFieldToRecordDecl(C, RD, C.VoidPtrTy); - addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); - addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); - RD->completeDefinition(); - TgtDeviceImageQTy = C.getRecordType(RD); - } - return TgtDeviceImageQTy; -} - -QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() { - // struct __tgt_bin_desc{ - // int32_t NumDevices; // Number of devices supported. - // __tgt_device_image *DeviceImages; // Arrays of device images - // // (one per device). - // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the - // // entries. - // __tgt_offload_entry *EntriesEnd; // End of the table with all the - // // entries (non inclusive). - // }; - if (TgtBinaryDescriptorQTy.isNull()) { - ASTContext &C = CGM.getContext(); - RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc"); - RD->startDefinition(); - addFieldToRecordDecl( - C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); - addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy())); - addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); - addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); - RD->completeDefinition(); - TgtBinaryDescriptorQTy = C.getRecordType(RD); - } - return TgtBinaryDescriptorQTy; -} - -namespace { -struct PrivateHelpersTy { - PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy, - const VarDecl *PrivateElemInit) - : Original(Original), PrivateCopy(PrivateCopy), - PrivateElemInit(PrivateElemInit) {} - const VarDecl *Original; - const VarDecl *PrivateCopy; - const VarDecl *PrivateElemInit; -}; -typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; -} // anonymous namespace - -static RecordDecl * -createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { - if (!Privates.empty()) { - ASTContext &C = CGM.getContext(); - // Build struct .kmp_privates_t. { - // /* private vars */ - // }; - RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); - RD->startDefinition(); - for (const auto &Pair : Privates) { - const VarDecl *VD = Pair.second.Original; - QualType Type = VD->getType().getNonReferenceType(); - FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); - if (VD->hasAttrs()) { - for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), - E(VD->getAttrs().end()); - I != E; ++I) - FD->addAttr(*I); - } - } - RD->completeDefinition(); - return RD; - } - return nullptr; -} - -static RecordDecl * -createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, - QualType KmpInt32Ty, - QualType KmpRoutineEntryPointerQTy) { - ASTContext &C = CGM.getContext(); - // Build struct kmp_task_t { - // void * shareds; - // kmp_routine_entry_t routine; - // kmp_int32 part_id; - // kmp_cmplrdata_t data1; - // kmp_cmplrdata_t data2; - // For taskloops additional fields: - // kmp_uint64 lb; - // kmp_uint64 ub; - // kmp_int64 st; - // kmp_int32 liter; - // void * reductions; - // }; - RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); - UD->startDefinition(); - addFieldToRecordDecl(C, UD, KmpInt32Ty); - addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); - UD->completeDefinition(); - QualType KmpCmplrdataTy = C.getRecordType(UD); - RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); - RD->startDefinition(); - addFieldToRecordDecl(C, RD, C.VoidPtrTy); - addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); - addFieldToRecordDecl(C, RD, KmpInt32Ty); - addFieldToRecordDecl(C, RD, KmpCmplrdataTy); - addFieldToRecordDecl(C, RD, KmpCmplrdataTy); - if (isOpenMPTaskLoopDirective(Kind)) { - QualType KmpUInt64Ty = - CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); - QualType KmpInt64Ty = - CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); - addFieldToRecordDecl(C, RD, KmpUInt64Ty); - addFieldToRecordDecl(C, RD, KmpUInt64Ty); - addFieldToRecordDecl(C, RD, KmpInt64Ty); - addFieldToRecordDecl(C, RD, KmpInt32Ty); - addFieldToRecordDecl(C, RD, C.VoidPtrTy); - } - RD->completeDefinition(); - return RD; -} - -static RecordDecl * -createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, - ArrayRef<PrivateDataTy> Privates) { - ASTContext &C = CGM.getContext(); - // Build struct kmp_task_t_with_privates { - // kmp_task_t task_data; - // .kmp_privates_t. privates; - // }; - RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); - RD->startDefinition(); - addFieldToRecordDecl(C, RD, KmpTaskTQTy); - if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) - addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); - RD->completeDefinition(); - return RD; -} - -/// Emit a proxy function which accepts kmp_task_t as the second -/// argument. -/// \code -/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { -/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, -/// For taskloops: -/// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, -/// tt->reductions, tt->shareds); -/// return 0; -/// } -/// \endcode -static llvm::Value * -emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, - OpenMPDirectiveKind Kind, QualType KmpInt32Ty, - QualType KmpTaskTWithPrivatesPtrQTy, - QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, - QualType SharedsPtrTy, llvm::Value *TaskFunction, - llvm::Value *TaskPrivatesMap) { - ASTContext &C = CGM.getContext(); - FunctionArgList Args; - ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, - ImplicitParamDecl::Other); - ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, - KmpTaskTWithPrivatesPtrQTy.withRestrict(), - ImplicitParamDecl::Other); - Args.push_back(&GtidArg); - Args.push_back(&TaskTypeArg); - const auto &TaskEntryFnInfo = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); - llvm::FunctionType *TaskEntryTy = - CGM.getTypes().GetFunctionType(TaskEntryFnInfo); - std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); - auto *TaskEntry = llvm::Function::Create( - TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); - CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); - TaskEntry->setDoesNotRecurse(); - CodeGenFunction CGF(CGM); - CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, - Loc, Loc); - - // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, - // tt, - // For taskloops: - // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, - // tt->task_data.shareds); - llvm::Value *GtidParam = CGF.EmitLoadOfScalar( - CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); - LValue TDBase = CGF.EmitLoadOfPointerLValue( - CGF.GetAddrOfLocalVar(&TaskTypeArg), - KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); - const auto *KmpTaskTWithPrivatesQTyRD = - cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); - LValue Base = - CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); - const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); - auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); - LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); - llvm::Value *PartidParam = PartIdLVal.getPointer(); - - auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); - LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); - llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - CGF.EmitLoadOfScalar(SharedsLVal, Loc), - CGF.ConvertTypeForMem(SharedsPtrTy)); - - auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); - llvm::Value *PrivatesParam; - if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { - LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); - PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - PrivatesLVal.getPointer(), CGF.VoidPtrTy); - } else { - PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); - } - - llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, - TaskPrivatesMap, - CGF.Builder - .CreatePointerBitCastOrAddrSpaceCast( - TDBase.getAddress(), CGF.VoidPtrTy) - .getPointer()}; - SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), - std::end(CommonArgs)); - if (isOpenMPTaskLoopDirective(Kind)) { - auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); - LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); - llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); - auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); - LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); - llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); - auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); - LValue StLVal = CGF.EmitLValueForField(Base, *StFI); - llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); - auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); - LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); - llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); - auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); - LValue RLVal = CGF.EmitLValueForField(Base, *RFI); - llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); - CallArgs.push_back(LBParam); - CallArgs.push_back(UBParam); - CallArgs.push_back(StParam); - CallArgs.push_back(LIParam); - CallArgs.push_back(RParam); - } - CallArgs.push_back(SharedsParam); - - CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, - CallArgs); - CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), - CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); - CGF.FinishFunction(); - return TaskEntry; -} - -static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, - SourceLocation Loc, - QualType KmpInt32Ty, - QualType KmpTaskTWithPrivatesPtrQTy, - QualType KmpTaskTWithPrivatesQTy) { - ASTContext &C = CGM.getContext(); - FunctionArgList Args; - ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, - ImplicitParamDecl::Other); - ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, - KmpTaskTWithPrivatesPtrQTy.withRestrict(), - ImplicitParamDecl::Other); - Args.push_back(&GtidArg); - Args.push_back(&TaskTypeArg); - const auto &DestructorFnInfo = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); - llvm::FunctionType *DestructorFnTy = - CGM.getTypes().GetFunctionType(DestructorFnInfo); - std::string Name = - CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); - auto *DestructorFn = - llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, - Name, &CGM.getModule()); - CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, - DestructorFnInfo); - DestructorFn->setDoesNotRecurse(); - CodeGenFunction CGF(CGM); - CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, - Args, Loc, Loc); - - LValue Base = CGF.EmitLoadOfPointerLValue( - CGF.GetAddrOfLocalVar(&TaskTypeArg), - KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); - const auto *KmpTaskTWithPrivatesQTyRD = - cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); - auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); - Base = CGF.EmitLValueForField(Base, *FI); - for (const auto *Field : - cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { - if (QualType::DestructionKind DtorKind = - Field->getType().isDestructedType()) { - LValue FieldLValue = CGF.EmitLValueForField(Base, Field); - CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType()); - } - } - CGF.FinishFunction(); - return DestructorFn; -} - -/// Emit a privates mapping function for correct handling of private and -/// firstprivate variables. -/// \code -/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> -/// **noalias priv1,..., <tyn> **noalias privn) { -/// *priv1 = &.privates.priv1; -/// ...; -/// *privn = &.privates.privn; -/// } -/// \endcode -static llvm::Value * -emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, - ArrayRef<const Expr *> PrivateVars, - ArrayRef<const Expr *> FirstprivateVars, - ArrayRef<const Expr *> LastprivateVars, - QualType PrivatesQTy, - ArrayRef<PrivateDataTy> Privates) { - ASTContext &C = CGM.getContext(); - FunctionArgList Args; - ImplicitParamDecl TaskPrivatesArg( - C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, - C.getPointerType(PrivatesQTy).withConst().withRestrict(), - ImplicitParamDecl::Other); - Args.push_back(&TaskPrivatesArg); - llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; - unsigned Counter = 1; - for (const Expr *E : PrivateVars) { - Args.push_back(ImplicitParamDecl::Create( - C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, - C.getPointerType(C.getPointerType(E->getType())) - .withConst() - .withRestrict(), - ImplicitParamDecl::Other)); - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - PrivateVarsPos[VD] = Counter; - ++Counter; - } - for (const Expr *E : FirstprivateVars) { - Args.push_back(ImplicitParamDecl::Create( - C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, - C.getPointerType(C.getPointerType(E->getType())) - .withConst() - .withRestrict(), - ImplicitParamDecl::Other)); - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - PrivateVarsPos[VD] = Counter; - ++Counter; - } - for (const Expr *E : LastprivateVars) { - Args.push_back(ImplicitParamDecl::Create( - C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, - C.getPointerType(C.getPointerType(E->getType())) - .withConst() - .withRestrict(), - ImplicitParamDecl::Other)); - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - PrivateVarsPos[VD] = Counter; - ++Counter; - } - const auto &TaskPrivatesMapFnInfo = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); - llvm::FunctionType *TaskPrivatesMapTy = - CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); - std::string Name = - CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); - auto *TaskPrivatesMap = llvm::Function::Create( - TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, - &CGM.getModule()); - CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, - TaskPrivatesMapFnInfo); - TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); - TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); - TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); - CodeGenFunction CGF(CGM); - CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, - TaskPrivatesMapFnInfo, Args, Loc, Loc); - - // *privi = &.privates.privi; - LValue Base = CGF.EmitLoadOfPointerLValue( - CGF.GetAddrOfLocalVar(&TaskPrivatesArg), - TaskPrivatesArg.getType()->castAs<PointerType>()); - const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); - Counter = 0; - for (const FieldDecl *Field : PrivatesQTyRD->fields()) { - LValue FieldLVal = CGF.EmitLValueForField(Base, Field); - const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; - LValue RefLVal = - CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); - LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( - RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>()); - CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal); - ++Counter; - } - CGF.FinishFunction(); - return TaskPrivatesMap; -} - -static bool stable_sort_comparator(const PrivateDataTy P1, - const PrivateDataTy P2) { - return P1.first > P2.first; -} - -/// Emit initialization for private variables in task-based directives. -static void emitPrivatesInit(CodeGenFunction &CGF, - const OMPExecutableDirective &D, - Address KmpTaskSharedsPtr, LValue TDBase, - const RecordDecl *KmpTaskTWithPrivatesQTyRD, - QualType SharedsTy, QualType SharedsPtrTy, - const OMPTaskDataTy &Data, - ArrayRef<PrivateDataTy> Privates, bool ForDup) { - ASTContext &C = CGF.getContext(); - auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); - LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); - OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) - ? OMPD_taskloop - : OMPD_task; - const CapturedStmt &CS = *D.getCapturedStmt(Kind); - CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); - LValue SrcBase; - bool IsTargetTask = - isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || - isOpenMPTargetExecutionDirective(D.getDirectiveKind()); - // For target-based directives skip 3 firstprivate arrays BasePointersArray, - // PointersArray and SizesArray. The original variables for these arrays are - // not captured and we get their addresses explicitly. - if ((!IsTargetTask && !Data.FirstprivateVars.empty()) || - (IsTargetTask && KmpTaskSharedsPtr.isValid())) { - SrcBase = CGF.MakeAddrLValue( - CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), - SharedsTy); - } - FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); - for (const PrivateDataTy &Pair : Privates) { - const VarDecl *VD = Pair.second.PrivateCopy; - const Expr *Init = VD->getAnyInitializer(); - if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && - !CGF.isTrivialInitializer(Init)))) { - LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); - if (const VarDecl *Elem = Pair.second.PrivateElemInit) { - const VarDecl *OriginalVD = Pair.second.Original; - // Check if the variable is the target-based BasePointersArray, - // PointersArray or SizesArray. - LValue SharedRefLValue; - QualType Type = OriginalVD->getType(); - const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); - if (IsTargetTask && !SharedField) { - assert(isa<ImplicitParamDecl>(OriginalVD) && - isa<CapturedDecl>(OriginalVD->getDeclContext()) && - cast<CapturedDecl>(OriginalVD->getDeclContext()) - ->getNumParams() == 0 && - isa<TranslationUnitDecl>( - cast<CapturedDecl>(OriginalVD->getDeclContext()) - ->getDeclContext()) && - "Expected artificial target data variable."); - SharedRefLValue = - CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); - } else { - SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); - SharedRefLValue = CGF.MakeAddrLValue( - Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)), - SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), - SharedRefLValue.getTBAAInfo()); - } - if (Type->isArrayType()) { - // Initialize firstprivate array. - if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { - // Perform simple memcpy. - CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); - } else { - // Initialize firstprivate array using element-by-element - // initialization. - CGF.EmitOMPAggregateAssign( - PrivateLValue.getAddress(), SharedRefLValue.getAddress(), Type, - [&CGF, Elem, Init, &CapturesInfo](Address DestElement, - Address SrcElement) { - // Clean up any temporaries needed by the initialization. - CodeGenFunction::OMPPrivateScope InitScope(CGF); - InitScope.addPrivate( - Elem, [SrcElement]() -> Address { return SrcElement; }); - (void)InitScope.Privatize(); - // Emit initialization for single element. - CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( - CGF, &CapturesInfo); - CGF.EmitAnyExprToMem(Init, DestElement, - Init->getType().getQualifiers(), - /*IsInitializer=*/false); - }); - } - } else { - CodeGenFunction::OMPPrivateScope InitScope(CGF); - InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address { - return SharedRefLValue.getAddress(); - }); - (void)InitScope.Privatize(); - CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); - CGF.EmitExprAsInit(Init, VD, PrivateLValue, - /*capturedByInit=*/false); - } - } else { - CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); - } - } - ++FI; - } -} - -/// Check if duplication function is required for taskloops. -static bool checkInitIsRequired(CodeGenFunction &CGF, - ArrayRef<PrivateDataTy> Privates) { - bool InitRequired = false; - for (const PrivateDataTy &Pair : Privates) { - const VarDecl *VD = Pair.second.PrivateCopy; - const Expr *Init = VD->getAnyInitializer(); - InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && - !CGF.isTrivialInitializer(Init)); - if (InitRequired) - break; - } - return InitRequired; -} - - -/// Emit task_dup function (for initialization of -/// private/firstprivate/lastprivate vars and last_iter flag) -/// \code -/// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int -/// lastpriv) { -/// // setup lastprivate flag -/// task_dst->last = lastpriv; -/// // could be constructor calls here... -/// } -/// \endcode -static llvm::Value * -emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, - const OMPExecutableDirective &D, - QualType KmpTaskTWithPrivatesPtrQTy, - const RecordDecl *KmpTaskTWithPrivatesQTyRD, - const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, - QualType SharedsPtrTy, const OMPTaskDataTy &Data, - ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { - ASTContext &C = CGM.getContext(); - FunctionArgList Args; - ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, - KmpTaskTWithPrivatesPtrQTy, - ImplicitParamDecl::Other); - ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, - KmpTaskTWithPrivatesPtrQTy, - ImplicitParamDecl::Other); - ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, - ImplicitParamDecl::Other); - Args.push_back(&DstArg); - Args.push_back(&SrcArg); - Args.push_back(&LastprivArg); - const auto &TaskDupFnInfo = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); - llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); - std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); - auto *TaskDup = llvm::Function::Create( - TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); - CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); - TaskDup->setDoesNotRecurse(); - CodeGenFunction CGF(CGM); - CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, - Loc); - - LValue TDBase = CGF.EmitLoadOfPointerLValue( - CGF.GetAddrOfLocalVar(&DstArg), - KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); - // task_dst->liter = lastpriv; - if (WithLastIter) { - auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); - LValue Base = CGF.EmitLValueForField( - TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); - LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); - llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( - CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); - CGF.EmitStoreOfScalar(Lastpriv, LILVal); - } - - // Emit initial values for private copies (if any). - assert(!Privates.empty()); - Address KmpTaskSharedsPtr = Address::invalid(); - if (!Data.FirstprivateVars.empty()) { - LValue TDBase = CGF.EmitLoadOfPointerLValue( - CGF.GetAddrOfLocalVar(&SrcArg), - KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); - LValue Base = CGF.EmitLValueForField( - TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); - KmpTaskSharedsPtr = Address( - CGF.EmitLoadOfScalar(CGF.EmitLValueForField( - Base, *std::next(KmpTaskTQTyRD->field_begin(), - KmpTaskTShareds)), - Loc), - CGF.getNaturalTypeAlignment(SharedsTy)); - } - emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, - SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); - CGF.FinishFunction(); - return TaskDup; -} - -/// Checks if destructor function is required to be generated. -/// \return true if cleanups are required, false otherwise. -static bool -checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) { - bool NeedsCleanup = false; - auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); - const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl()); - for (const FieldDecl *FD : PrivateRD->fields()) { - NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType(); - if (NeedsCleanup) - break; - } - return NeedsCleanup; -} - -CGOpenMPRuntime::TaskResultTy -CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, - const OMPExecutableDirective &D, - llvm::Value *TaskFunction, QualType SharedsTy, - Address Shareds, const OMPTaskDataTy &Data) { - ASTContext &C = CGM.getContext(); - llvm::SmallVector<PrivateDataTy, 4> Privates; - // Aggregate privates and sort them by the alignment. - auto I = Data.PrivateCopies.begin(); - for (const Expr *E : Data.PrivateVars) { - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - Privates.emplace_back( - C.getDeclAlign(VD), - PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), - /*PrivateElemInit=*/nullptr)); - ++I; - } - I = Data.FirstprivateCopies.begin(); - auto IElemInitRef = Data.FirstprivateInits.begin(); - for (const Expr *E : Data.FirstprivateVars) { - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - Privates.emplace_back( - C.getDeclAlign(VD), - PrivateHelpersTy( - VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), - cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); - ++I; - ++IElemInitRef; - } - I = Data.LastprivateCopies.begin(); - for (const Expr *E : Data.LastprivateVars) { - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - Privates.emplace_back( - C.getDeclAlign(VD), - PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), - /*PrivateElemInit=*/nullptr)); - ++I; - } - std::stable_sort(Privates.begin(), Privates.end(), stable_sort_comparator); - QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); - // Build type kmp_routine_entry_t (if not built yet). - emitKmpRoutineEntryT(KmpInt32Ty); - // Build type kmp_task_t (if not built yet). - if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { - if (SavedKmpTaskloopTQTy.isNull()) { - SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( - CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); - } - KmpTaskTQTy = SavedKmpTaskloopTQTy; - } else { - assert((D.getDirectiveKind() == OMPD_task || - isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || - isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && - "Expected taskloop, task or target directive"); - if (SavedKmpTaskTQTy.isNull()) { - SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( - CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); - } - KmpTaskTQTy = SavedKmpTaskTQTy; - } - const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); - // Build particular struct kmp_task_t for the given task. - const RecordDecl *KmpTaskTWithPrivatesQTyRD = - createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); - QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); - QualType KmpTaskTWithPrivatesPtrQTy = - C.getPointerType(KmpTaskTWithPrivatesQTy); - llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); - llvm::Type *KmpTaskTWithPrivatesPtrTy = - KmpTaskTWithPrivatesTy->getPointerTo(); - llvm::Value *KmpTaskTWithPrivatesTySize = - CGF.getTypeSize(KmpTaskTWithPrivatesQTy); - QualType SharedsPtrTy = C.getPointerType(SharedsTy); - - // Emit initial values for private copies (if any). - llvm::Value *TaskPrivatesMap = nullptr; - llvm::Type *TaskPrivatesMapTy = - std::next(cast<llvm::Function>(TaskFunction)->arg_begin(), 3)->getType(); - if (!Privates.empty()) { - auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); - TaskPrivatesMap = emitTaskPrivateMappingFunction( - CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars, - FI->getType(), Privates); - TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - TaskPrivatesMap, TaskPrivatesMapTy); - } else { - TaskPrivatesMap = llvm::ConstantPointerNull::get( - cast<llvm::PointerType>(TaskPrivatesMapTy)); - } - // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, - // kmp_task_t *tt); - llvm::Value *TaskEntry = emitProxyTaskFunction( - CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, - KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, - TaskPrivatesMap); - - // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, - // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, - // kmp_routine_entry_t *task_entry); - // Task flags. Format is taken from - // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h, - // description of kmp_tasking_flags struct. - enum { - TiedFlag = 0x1, - FinalFlag = 0x2, - DestructorsFlag = 0x8, - PriorityFlag = 0x20 - }; - unsigned Flags = Data.Tied ? TiedFlag : 0; - bool NeedsCleanup = false; - if (!Privates.empty()) { - NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD); - if (NeedsCleanup) - Flags = Flags | DestructorsFlag; - } - if (Data.Priority.getInt()) - Flags = Flags | PriorityFlag; - llvm::Value *TaskFlags = - Data.Final.getPointer() - ? CGF.Builder.CreateSelect(Data.Final.getPointer(), - CGF.Builder.getInt32(FinalFlag), - CGF.Builder.getInt32(/*C=*/0)) - : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); - TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); - llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); - llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc), - getThreadID(CGF, Loc), TaskFlags, - KmpTaskTWithPrivatesTySize, SharedsSize, - CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - TaskEntry, KmpRoutineEntryPtrTy)}; - llvm::Value *NewTask = CGF.EmitRuntimeCall( - createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); - llvm::Value *NewTaskNewTaskTTy = - CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - NewTask, KmpTaskTWithPrivatesPtrTy); - LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, - KmpTaskTWithPrivatesQTy); - LValue TDBase = - CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); - // Fill the data in the resulting kmp_task_t record. - // Copy shareds if there are any. - Address KmpTaskSharedsPtr = Address::invalid(); - if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { - KmpTaskSharedsPtr = - Address(CGF.EmitLoadOfScalar( - CGF.EmitLValueForField( - TDBase, *std::next(KmpTaskTQTyRD->field_begin(), - KmpTaskTShareds)), - Loc), - CGF.getNaturalTypeAlignment(SharedsTy)); - LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); - LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); - CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); - } - // Emit initial values for private copies (if any). - TaskResultTy Result; - if (!Privates.empty()) { - emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, - SharedsTy, SharedsPtrTy, Data, Privates, - /*ForDup=*/false); - if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && - (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { - Result.TaskDupFn = emitTaskDupFunction( - CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, - KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, - /*WithLastIter=*/!Data.LastprivateVars.empty()); - } - } - // Fields of union "kmp_cmplrdata_t" for destructors and priority. - enum { Priority = 0, Destructors = 1 }; - // Provide pointer to function with destructors for privates. - auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); - const RecordDecl *KmpCmplrdataUD = - (*FI)->getType()->getAsUnionType()->getDecl(); - if (NeedsCleanup) { - llvm::Value *DestructorFn = emitDestructorsFunction( - CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, - KmpTaskTWithPrivatesQTy); - LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); - LValue DestructorsLV = CGF.EmitLValueForField( - Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); - CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - DestructorFn, KmpRoutineEntryPtrTy), - DestructorsLV); - } - // Set priority. - if (Data.Priority.getInt()) { - LValue Data2LV = CGF.EmitLValueForField( - TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); - LValue PriorityLV = CGF.EmitLValueForField( - Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); - CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); - } - Result.NewTask = NewTask; - Result.TaskEntry = TaskEntry; - Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; - Result.TDBase = TDBase; - Result.KmpTaskTQTyRD = KmpTaskTQTyRD; - return Result; -} - -void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, - const OMPExecutableDirective &D, - llvm::Value *TaskFunction, - QualType SharedsTy, Address Shareds, - const Expr *IfCond, - const OMPTaskDataTy &Data) { - if (!CGF.HaveInsertPoint()) - return; - - TaskResultTy Result = - emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); - llvm::Value *NewTask = Result.NewTask; - llvm::Value *TaskEntry = Result.TaskEntry; - llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; - LValue TDBase = Result.TDBase; - const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; - ASTContext &C = CGM.getContext(); - // Process list of dependences. - Address DependenciesArray = Address::invalid(); - unsigned NumDependencies = Data.Dependences.size(); - if (NumDependencies) { - // Dependence kind for RTL. - enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3 }; - enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; - RecordDecl *KmpDependInfoRD; - QualType FlagsTy = - C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); - llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); - if (KmpDependInfoTy.isNull()) { - KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); - KmpDependInfoRD->startDefinition(); - addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); - addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); - addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); - KmpDependInfoRD->completeDefinition(); - KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); - } else { - KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); - } - CharUnits DependencySize = C.getTypeSizeInChars(KmpDependInfoTy); - // Define type kmp_depend_info[<Dependences.size()>]; - QualType KmpDependInfoArrayTy = C.getConstantArrayType( - KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), - ArrayType::Normal, /*IndexTypeQuals=*/0); - // kmp_depend_info[<Dependences.size()>] deps; - DependenciesArray = - CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); - for (unsigned I = 0; I < NumDependencies; ++I) { - const Expr *E = Data.Dependences[I].second; - LValue Addr = CGF.EmitLValue(E); - llvm::Value *Size; - QualType Ty = E->getType(); - if (const auto *ASE = - dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { - LValue UpAddrLVal = - CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false); - llvm::Value *UpAddr = - CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1); - llvm::Value *LowIntPtr = - CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy); - llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); - Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); - } else { - Size = CGF.getTypeSize(Ty); - } - LValue Base = CGF.MakeAddrLValue( - CGF.Builder.CreateConstArrayGEP(DependenciesArray, I, DependencySize), - KmpDependInfoTy); - // deps[i].base_addr = &<Dependences[i].second>; - LValue BaseAddrLVal = CGF.EmitLValueForField( - Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); - CGF.EmitStoreOfScalar( - CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy), - BaseAddrLVal); - // deps[i].len = sizeof(<Dependences[i].second>); - LValue LenLVal = CGF.EmitLValueForField( - Base, *std::next(KmpDependInfoRD->field_begin(), Len)); - CGF.EmitStoreOfScalar(Size, LenLVal); - // deps[i].flags = <Dependences[i].first>; - RTLDependenceKindTy DepKind; - switch (Data.Dependences[I].first) { - case OMPC_DEPEND_in: - DepKind = DepIn; - break; - // Out and InOut dependencies must use the same code. - case OMPC_DEPEND_out: - case OMPC_DEPEND_inout: - DepKind = DepInOut; - break; - case OMPC_DEPEND_source: - case OMPC_DEPEND_sink: - case OMPC_DEPEND_unknown: - llvm_unreachable("Unknown task dependence type"); - } - LValue FlagsLVal = CGF.EmitLValueForField( - Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); - CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), - FlagsLVal); - } - DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - CGF.Builder.CreateStructGEP(DependenciesArray, 0, CharUnits::Zero()), - CGF.VoidPtrTy); - } - - // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() - // libcall. - // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, - // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, - // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence - // list is not empty - llvm::Value *ThreadID = getThreadID(CGF, Loc); - llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); - llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; - llvm::Value *DepTaskArgs[7]; - if (NumDependencies) { - DepTaskArgs[0] = UpLoc; - DepTaskArgs[1] = ThreadID; - DepTaskArgs[2] = NewTask; - DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies); - DepTaskArgs[4] = DependenciesArray.getPointer(); - DepTaskArgs[5] = CGF.Builder.getInt32(0); - DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); - } - auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies, - &TaskArgs, - &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { - if (!Data.Tied) { - auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); - LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); - CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); - } - if (NumDependencies) { - CGF.EmitRuntimeCall( - createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs); - } else { - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), - TaskArgs); - } - // Check if parent region is untied and build return for untied task; - if (auto *Region = - dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) - Region->emitUntiedSwitch(CGF); - }; - - llvm::Value *DepWaitTaskArgs[6]; - if (NumDependencies) { - DepWaitTaskArgs[0] = UpLoc; - DepWaitTaskArgs[1] = ThreadID; - DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies); - DepWaitTaskArgs[3] = DependenciesArray.getPointer(); - DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); - DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); - } - auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, - NumDependencies, &DepWaitTaskArgs, - Loc](CodeGenFunction &CGF, PrePostActionTy &) { - CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); - CodeGenFunction::RunCleanupsScope LocalScope(CGF); - // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, - // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 - // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info - // is specified. - if (NumDependencies) - CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), - DepWaitTaskArgs); - // Call proxy_task_entry(gtid, new_task); - auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, - Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { - Action.Enter(CGF); - llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; - CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, - OutlinedFnArgs); - }; - - // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, - // kmp_task_t *new_task); - // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, - // kmp_task_t *new_task); - RegionCodeGenTy RCG(CodeGen); - CommonActionTy Action( - RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs, - RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs); - RCG.setAction(Action); - RCG(CGF); - }; - - if (IfCond) { - emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); - } else { - RegionCodeGenTy ThenRCG(ThenCodeGen); - ThenRCG(CGF); - } -} - -void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, - const OMPLoopDirective &D, - llvm::Value *TaskFunction, - QualType SharedsTy, Address Shareds, - const Expr *IfCond, - const OMPTaskDataTy &Data) { - if (!CGF.HaveInsertPoint()) - return; - TaskResultTy Result = - emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); - // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() - // libcall. - // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int - // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int - // sched, kmp_uint64 grainsize, void *task_dup); - llvm::Value *ThreadID = getThreadID(CGF, Loc); - llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); - llvm::Value *IfVal; - if (IfCond) { - IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, - /*isSigned=*/true); - } else { - IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); - } - - LValue LBLVal = CGF.EmitLValueForField( - Result.TDBase, - *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); - const auto *LBVar = - cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); - CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(), - /*IsInitializer=*/true); - LValue UBLVal = CGF.EmitLValueForField( - Result.TDBase, - *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); - const auto *UBVar = - cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); - CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(), - /*IsInitializer=*/true); - LValue StLVal = CGF.EmitLValueForField( - Result.TDBase, - *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); - const auto *StVar = - cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); - CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(), - /*IsInitializer=*/true); - // Store reductions address. - LValue RedLVal = CGF.EmitLValueForField( - Result.TDBase, - *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); - if (Data.Reductions) { - CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); - } else { - CGF.EmitNullInitialization(RedLVal.getAddress(), - CGF.getContext().VoidPtrTy); - } - enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; - llvm::Value *TaskArgs[] = { - UpLoc, - ThreadID, - Result.NewTask, - IfVal, - LBLVal.getPointer(), - UBLVal.getPointer(), - CGF.EmitLoadOfScalar(StLVal, Loc), - llvm::ConstantInt::getSigned( - CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler - llvm::ConstantInt::getSigned( - CGF.IntTy, Data.Schedule.getPointer() - ? Data.Schedule.getInt() ? NumTasks : Grainsize - : NoSchedule), - Data.Schedule.getPointer() - ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, - /*isSigned=*/false) - : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), - Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - Result.TaskDupFn, CGF.VoidPtrTy) - : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs); -} - -/// Emit reduction operation for each element of array (required for -/// array sections) LHS op = RHS. -/// \param Type Type of array. -/// \param LHSVar Variable on the left side of the reduction operation -/// (references element of array in original variable). -/// \param RHSVar Variable on the right side of the reduction operation -/// (references element of array in original variable). -/// \param RedOpGen Generator of reduction operation with use of LHSVar and -/// RHSVar. -static void EmitOMPAggregateReduction( - CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, - const VarDecl *RHSVar, - const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, - const Expr *, const Expr *)> &RedOpGen, - const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, - const Expr *UpExpr = nullptr) { - // Perform element-by-element initialization. - QualType ElementTy; - Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); - Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); - - // Drill down to the base element type on both arrays. - const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); - llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); - - llvm::Value *RHSBegin = RHSAddr.getPointer(); - llvm::Value *LHSBegin = LHSAddr.getPointer(); - // Cast from pointer to array type to pointer to single element. - llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); - // The basic structure here is a while-do loop. - llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); - llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); - llvm::Value *IsEmpty = - CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); - CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); - - // Enter the loop body, making that address the current address. - llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); - CGF.EmitBlock(BodyBB); - - CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); - - llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( - RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); - RHSElementPHI->addIncoming(RHSBegin, EntryBB); - Address RHSElementCurrent = - Address(RHSElementPHI, - RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); - - llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( - LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); - LHSElementPHI->addIncoming(LHSBegin, EntryBB); - Address LHSElementCurrent = - Address(LHSElementPHI, - LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); - - // Emit copy. - CodeGenFunction::OMPPrivateScope Scope(CGF); - Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); - Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); - Scope.Privatize(); - RedOpGen(CGF, XExpr, EExpr, UpExpr); - Scope.ForceCleanup(); - - // Shift the address forward by one element. - llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( - LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); - llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( - RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); - // Check whether we've reached the end. - llvm::Value *Done = - CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); - CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); - LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); - RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); - - // Done. - CGF.EmitBlock(DoneBB, /*IsFinished=*/true); -} - -/// Emit reduction combiner. If the combiner is a simple expression emit it as -/// is, otherwise consider it as combiner of UDR decl and emit it as a call of -/// UDR combiner function. -static void emitReductionCombiner(CodeGenFunction &CGF, - const Expr *ReductionOp) { - if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) - if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) - if (const auto *DRE = - dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) - if (const auto *DRD = - dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { - std::pair<llvm::Function *, llvm::Function *> Reduction = - CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); - RValue Func = RValue::get(Reduction.first); - CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); - CGF.EmitIgnoredExpr(ReductionOp); - return; - } - CGF.EmitIgnoredExpr(ReductionOp); -} - -llvm::Value *CGOpenMPRuntime::emitReductionFunction( - CodeGenModule &CGM, SourceLocation Loc, llvm::Type *ArgsType, - ArrayRef<const Expr *> Privates, ArrayRef<const Expr *> LHSExprs, - ArrayRef<const Expr *> RHSExprs, ArrayRef<const Expr *> ReductionOps) { - ASTContext &C = CGM.getContext(); - - // void reduction_func(void *LHSArg, void *RHSArg); - FunctionArgList Args; - ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, - ImplicitParamDecl::Other); - ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, - ImplicitParamDecl::Other); - Args.push_back(&LHSArg); - Args.push_back(&RHSArg); - const auto &CGFI = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); - std::string Name = getName({"omp", "reduction", "reduction_func"}); - auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), - llvm::GlobalValue::InternalLinkage, Name, - &CGM.getModule()); - CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); - Fn->setDoesNotRecurse(); - CodeGenFunction CGF(CGM); - CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); - - // Dst = (void*[n])(LHSArg); - // Src = (void*[n])(RHSArg); - Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), - ArgsType), CGF.getPointerAlign()); - Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), - ArgsType), CGF.getPointerAlign()); - - // ... - // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); - // ... - CodeGenFunction::OMPPrivateScope Scope(CGF); - auto IPriv = Privates.begin(); - unsigned Idx = 0; - for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { - const auto *RHSVar = - cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); - Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { - return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); - }); - const auto *LHSVar = - cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); - Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { - return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); - }); - QualType PrivTy = (*IPriv)->getType(); - if (PrivTy->isVariablyModifiedType()) { - // Get array size and emit VLA type. - ++Idx; - Address Elem = - CGF.Builder.CreateConstArrayGEP(LHS, Idx, CGF.getPointerSize()); - llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); - const VariableArrayType *VLA = - CGF.getContext().getAsVariableArrayType(PrivTy); - const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); - CodeGenFunction::OpaqueValueMapping OpaqueMap( - CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); - CGF.EmitVariablyModifiedType(PrivTy); - } - } - Scope.Privatize(); - IPriv = Privates.begin(); - auto ILHS = LHSExprs.begin(); - auto IRHS = RHSExprs.begin(); - for (const Expr *E : ReductionOps) { - if ((*IPriv)->getType()->isArrayType()) { - // Emit reduction for array section. - const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); - const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); - EmitOMPAggregateReduction( - CGF, (*IPriv)->getType(), LHSVar, RHSVar, - [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { - emitReductionCombiner(CGF, E); - }); - } else { - // Emit reduction for array subscript or single variable. - emitReductionCombiner(CGF, E); - } - ++IPriv; - ++ILHS; - ++IRHS; - } - Scope.ForceCleanup(); - CGF.FinishFunction(); - return Fn; -} - -void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, - const Expr *ReductionOp, - const Expr *PrivateRef, - const DeclRefExpr *LHS, - const DeclRefExpr *RHS) { - if (PrivateRef->getType()->isArrayType()) { - // Emit reduction for array section. - const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); - const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); - EmitOMPAggregateReduction( - CGF, PrivateRef->getType(), LHSVar, RHSVar, - [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { - emitReductionCombiner(CGF, ReductionOp); - }); - } else { - // Emit reduction for array subscript or single variable. - emitReductionCombiner(CGF, ReductionOp); - } -} - -void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, - ArrayRef<const Expr *> Privates, - ArrayRef<const Expr *> LHSExprs, - ArrayRef<const Expr *> RHSExprs, - ArrayRef<const Expr *> ReductionOps, - ReductionOptionsTy Options) { - if (!CGF.HaveInsertPoint()) - return; - - bool WithNowait = Options.WithNowait; - bool SimpleReduction = Options.SimpleReduction; - - // Next code should be emitted for reduction: - // - // static kmp_critical_name lock = { 0 }; - // - // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { - // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); - // ... - // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], - // *(Type<n>-1*)rhs[<n>-1]); - // } - // - // ... - // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; - // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), - // RedList, reduce_func, &<lock>)) { - // case 1: - // ... - // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); - // ... - // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); - // break; - // case 2: - // ... - // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); - // ... - // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] - // break; - // default:; - // } - // - // if SimpleReduction is true, only the next code is generated: - // ... - // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); - // ... - - ASTContext &C = CGM.getContext(); - - if (SimpleReduction) { - CodeGenFunction::RunCleanupsScope Scope(CGF); - auto IPriv = Privates.begin(); - auto ILHS = LHSExprs.begin(); - auto IRHS = RHSExprs.begin(); - for (const Expr *E : ReductionOps) { - emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), - cast<DeclRefExpr>(*IRHS)); - ++IPriv; - ++ILHS; - ++IRHS; - } - return; - } - - // 1. Build a list of reduction variables. - // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; - auto Size = RHSExprs.size(); - for (const Expr *E : Privates) { - if (E->getType()->isVariablyModifiedType()) - // Reserve place for array size. - ++Size; - } - llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); - QualType ReductionArrayTy = - C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal, - /*IndexTypeQuals=*/0); - Address ReductionList = - CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); - auto IPriv = Privates.begin(); - unsigned Idx = 0; - for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { - Address Elem = - CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, CGF.getPointerSize()); - CGF.Builder.CreateStore( - CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy), - Elem); - if ((*IPriv)->getType()->isVariablyModifiedType()) { - // Store array size. - ++Idx; - Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, - CGF.getPointerSize()); - llvm::Value *Size = CGF.Builder.CreateIntCast( - CGF.getVLASize( - CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) - .NumElts, - CGF.SizeTy, /*isSigned=*/false); - CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), - Elem); - } - } - - // 2. Emit reduce_func(). - llvm::Value *ReductionFn = emitReductionFunction( - CGM, Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), - Privates, LHSExprs, RHSExprs, ReductionOps); - - // 3. Create static kmp_critical_name lock = { 0 }; - std::string Name = getName({"reduction"}); - llvm::Value *Lock = getCriticalRegionLock(Name); - - // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), - // RedList, reduce_func, &<lock>); - llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); - llvm::Value *ThreadId = getThreadID(CGF, Loc); - llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); - llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - ReductionList.getPointer(), CGF.VoidPtrTy); - llvm::Value *Args[] = { - IdentTLoc, // ident_t *<loc> - ThreadId, // i32 <gtid> - CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> - ReductionArrayTySize, // size_type sizeof(RedList) - RL, // void *RedList - ReductionFn, // void (*) (void *, void *) <reduce_func> - Lock // kmp_critical_name *&<lock> - }; - llvm::Value *Res = CGF.EmitRuntimeCall( - createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait - : OMPRTL__kmpc_reduce), - Args); - - // 5. Build switch(res) - llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); - llvm::SwitchInst *SwInst = - CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); - - // 6. Build case 1: - // ... - // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); - // ... - // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); - // break; - llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); - SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); - CGF.EmitBlock(Case1BB); - - // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); - llvm::Value *EndArgs[] = { - IdentTLoc, // ident_t *<loc> - ThreadId, // i32 <gtid> - Lock // kmp_critical_name *&<lock> - }; - auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( - CodeGenFunction &CGF, PrePostActionTy &Action) { - CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); - auto IPriv = Privates.begin(); - auto ILHS = LHSExprs.begin(); - auto IRHS = RHSExprs.begin(); - for (const Expr *E : ReductionOps) { - RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), - cast<DeclRefExpr>(*IRHS)); - ++IPriv; - ++ILHS; - ++IRHS; - } - }; - RegionCodeGenTy RCG(CodeGen); - CommonActionTy Action( - nullptr, llvm::None, - createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait - : OMPRTL__kmpc_end_reduce), - EndArgs); - RCG.setAction(Action); - RCG(CGF); - - CGF.EmitBranch(DefaultBB); - - // 7. Build case 2: - // ... - // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); - // ... - // break; - llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); - SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); - CGF.EmitBlock(Case2BB); - - auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( - CodeGenFunction &CGF, PrePostActionTy &Action) { - auto ILHS = LHSExprs.begin(); - auto IRHS = RHSExprs.begin(); - auto IPriv = Privates.begin(); - for (const Expr *E : ReductionOps) { - const Expr *XExpr = nullptr; - const Expr *EExpr = nullptr; - const Expr *UpExpr = nullptr; - BinaryOperatorKind BO = BO_Comma; - if (const auto *BO = dyn_cast<BinaryOperator>(E)) { - if (BO->getOpcode() == BO_Assign) { - XExpr = BO->getLHS(); - UpExpr = BO->getRHS(); - } - } - // Try to emit update expression as a simple atomic. - const Expr *RHSExpr = UpExpr; - if (RHSExpr) { - // Analyze RHS part of the whole expression. - if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( - RHSExpr->IgnoreParenImpCasts())) { - // If this is a conditional operator, analyze its condition for - // min/max reduction operator. - RHSExpr = ACO->getCond(); - } - if (const auto *BORHS = - dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { - EExpr = BORHS->getRHS(); - BO = BORHS->getOpcode(); - } - } - if (XExpr) { - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); - auto &&AtomicRedGen = [BO, VD, - Loc](CodeGenFunction &CGF, const Expr *XExpr, - const Expr *EExpr, const Expr *UpExpr) { - LValue X = CGF.EmitLValue(XExpr); - RValue E; - if (EExpr) - E = CGF.EmitAnyExpr(EExpr); - CGF.EmitOMPAtomicSimpleUpdateExpr( - X, E, BO, /*IsXLHSInRHSPart=*/true, - llvm::AtomicOrdering::Monotonic, Loc, - [&CGF, UpExpr, VD, Loc](RValue XRValue) { - CodeGenFunction::OMPPrivateScope PrivateScope(CGF); - PrivateScope.addPrivate( - VD, [&CGF, VD, XRValue, Loc]() { - Address LHSTemp = CGF.CreateMemTemp(VD->getType()); - CGF.emitOMPSimpleStore( - CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, - VD->getType().getNonReferenceType(), Loc); - return LHSTemp; - }); - (void)PrivateScope.Privatize(); - return CGF.EmitAnyExpr(UpExpr); - }); - }; - if ((*IPriv)->getType()->isArrayType()) { - // Emit atomic reduction for array section. - const auto *RHSVar = - cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); - EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, - AtomicRedGen, XExpr, EExpr, UpExpr); - } else { - // Emit atomic reduction for array subscript or single variable. - AtomicRedGen(CGF, XExpr, EExpr, UpExpr); - } - } else { - // Emit as a critical region. - auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, - const Expr *, const Expr *) { - CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); - std::string Name = RT.getName({"atomic_reduction"}); - RT.emitCriticalRegion( - CGF, Name, - [=](CodeGenFunction &CGF, PrePostActionTy &Action) { - Action.Enter(CGF); - emitReductionCombiner(CGF, E); - }, - Loc); - }; - if ((*IPriv)->getType()->isArrayType()) { - const auto *LHSVar = - cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); - const auto *RHSVar = - cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); - EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, - CritRedGen); - } else { - CritRedGen(CGF, nullptr, nullptr, nullptr); - } - } - ++ILHS; - ++IRHS; - ++IPriv; - } - }; - RegionCodeGenTy AtomicRCG(AtomicCodeGen); - if (!WithNowait) { - // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); - llvm::Value *EndArgs[] = { - IdentTLoc, // ident_t *<loc> - ThreadId, // i32 <gtid> - Lock // kmp_critical_name *&<lock> - }; - CommonActionTy Action(nullptr, llvm::None, - createRuntimeFunction(OMPRTL__kmpc_end_reduce), - EndArgs); - AtomicRCG.setAction(Action); - AtomicRCG(CGF); - } else { - AtomicRCG(CGF); - } - - CGF.EmitBranch(DefaultBB); - CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); -} - -/// Generates unique name for artificial threadprivate variables. -/// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" -static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, - const Expr *Ref) { - SmallString<256> Buffer; - llvm::raw_svector_ostream Out(Buffer); - const clang::DeclRefExpr *DE; - const VarDecl *D = ::getBaseDecl(Ref, DE); - if (!D) - D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); - D = D->getCanonicalDecl(); - std::string Name = CGM.getOpenMPRuntime().getName( - {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); - Out << Prefix << Name << "_" - << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); - return Out.str(); -} - -/// Emits reduction initializer function: -/// \code -/// void @.red_init(void* %arg) { -/// %0 = bitcast void* %arg to <type>* -/// store <type> <init>, <type>* %0 -/// ret void -/// } -/// \endcode -static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, - SourceLocation Loc, - ReductionCodeGen &RCG, unsigned N) { - ASTContext &C = CGM.getContext(); - FunctionArgList Args; - ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, - ImplicitParamDecl::Other); - Args.emplace_back(&Param); - const auto &FnInfo = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); - llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); - std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); - auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, - Name, &CGM.getModule()); - CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); - Fn->setDoesNotRecurse(); - CodeGenFunction CGF(CGM); - CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); - Address PrivateAddr = CGF.EmitLoadOfPointer( - CGF.GetAddrOfLocalVar(&Param), - C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); - llvm::Value *Size = nullptr; - // If the size of the reduction item is non-constant, load it from global - // threadprivate variable. - if (RCG.getSizes(N).second) { - Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( - CGF, CGM.getContext().getSizeType(), - generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); - Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, - CGM.getContext().getSizeType(), Loc); - } - RCG.emitAggregateType(CGF, N, Size); - LValue SharedLVal; - // If initializer uses initializer from declare reduction construct, emit a - // pointer to the address of the original reduction item (reuired by reduction - // initializer) - if (RCG.usesReductionInitializer(N)) { - Address SharedAddr = - CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( - CGF, CGM.getContext().VoidPtrTy, - generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); - SharedAddr = CGF.EmitLoadOfPointer( - SharedAddr, - CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); - SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); - } else { - SharedLVal = CGF.MakeNaturalAlignAddrLValue( - llvm::ConstantPointerNull::get(CGM.VoidPtrTy), - CGM.getContext().VoidPtrTy); - } - // Emit the initializer: - // %0 = bitcast void* %arg to <type>* - // store <type> <init>, <type>* %0 - RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal, - [](CodeGenFunction &) { return false; }); - CGF.FinishFunction(); - return Fn; -} - -/// Emits reduction combiner function: -/// \code -/// void @.red_comb(void* %arg0, void* %arg1) { -/// %lhs = bitcast void* %arg0 to <type>* -/// %rhs = bitcast void* %arg1 to <type>* -/// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) -/// store <type> %2, <type>* %lhs -/// ret void -/// } -/// \endcode -static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, - SourceLocation Loc, - ReductionCodeGen &RCG, unsigned N, - const Expr *ReductionOp, - const Expr *LHS, const Expr *RHS, - const Expr *PrivateRef) { - ASTContext &C = CGM.getContext(); - const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); - const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); - FunctionArgList Args; - ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, - C.VoidPtrTy, ImplicitParamDecl::Other); - ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, - ImplicitParamDecl::Other); - Args.emplace_back(&ParamInOut); - Args.emplace_back(&ParamIn); - const auto &FnInfo = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); - llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); - std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); - auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, - Name, &CGM.getModule()); - CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); - Fn->setDoesNotRecurse(); - CodeGenFunction CGF(CGM); - CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); - llvm::Value *Size = nullptr; - // If the size of the reduction item is non-constant, load it from global - // threadprivate variable. - if (RCG.getSizes(N).second) { - Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( - CGF, CGM.getContext().getSizeType(), - generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); - Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, - CGM.getContext().getSizeType(), Loc); - } - RCG.emitAggregateType(CGF, N, Size); - // Remap lhs and rhs variables to the addresses of the function arguments. - // %lhs = bitcast void* %arg0 to <type>* - // %rhs = bitcast void* %arg1 to <type>* - CodeGenFunction::OMPPrivateScope PrivateScope(CGF); - PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { - // Pull out the pointer to the variable. - Address PtrAddr = CGF.EmitLoadOfPointer( - CGF.GetAddrOfLocalVar(&ParamInOut), - C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); - return CGF.Builder.CreateElementBitCast( - PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); - }); - PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { - // Pull out the pointer to the variable. - Address PtrAddr = CGF.EmitLoadOfPointer( - CGF.GetAddrOfLocalVar(&ParamIn), - C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); - return CGF.Builder.CreateElementBitCast( - PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); - }); - PrivateScope.Privatize(); - // Emit the combiner body: - // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) - // store <type> %2, <type>* %lhs - CGM.getOpenMPRuntime().emitSingleReductionCombiner( - CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), - cast<DeclRefExpr>(RHS)); - CGF.FinishFunction(); - return Fn; -} - -/// Emits reduction finalizer function: -/// \code -/// void @.red_fini(void* %arg) { -/// %0 = bitcast void* %arg to <type>* -/// <destroy>(<type>* %0) -/// ret void -/// } -/// \endcode -static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, - SourceLocation Loc, - ReductionCodeGen &RCG, unsigned N) { - if (!RCG.needCleanups(N)) - return nullptr; - ASTContext &C = CGM.getContext(); - FunctionArgList Args; - ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, - ImplicitParamDecl::Other); - Args.emplace_back(&Param); - const auto &FnInfo = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); - llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); - std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); - auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, - Name, &CGM.getModule()); - CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); - Fn->setDoesNotRecurse(); - CodeGenFunction CGF(CGM); - CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); - Address PrivateAddr = CGF.EmitLoadOfPointer( - CGF.GetAddrOfLocalVar(&Param), - C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); - llvm::Value *Size = nullptr; - // If the size of the reduction item is non-constant, load it from global - // threadprivate variable. - if (RCG.getSizes(N).second) { - Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( - CGF, CGM.getContext().getSizeType(), - generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); - Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, - CGM.getContext().getSizeType(), Loc); - } - RCG.emitAggregateType(CGF, N, Size); - // Emit the finalizer body: - // <destroy>(<type>* %0) - RCG.emitCleanups(CGF, N, PrivateAddr); - CGF.FinishFunction(); - return Fn; -} - -llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( - CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, - ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { - if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) - return nullptr; - - // Build typedef struct: - // kmp_task_red_input { - // void *reduce_shar; // shared reduction item - // size_t reduce_size; // size of data item - // void *reduce_init; // data initialization routine - // void *reduce_fini; // data finalization routine - // void *reduce_comb; // data combiner routine - // kmp_task_red_flags_t flags; // flags for additional info from compiler - // } kmp_task_red_input_t; - ASTContext &C = CGM.getContext(); - RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t"); - RD->startDefinition(); - const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); - const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); - const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); - const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); - const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); - const FieldDecl *FlagsFD = addFieldToRecordDecl( - C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); - RD->completeDefinition(); - QualType RDType = C.getRecordType(RD); - unsigned Size = Data.ReductionVars.size(); - llvm::APInt ArraySize(/*numBits=*/64, Size); - QualType ArrayRDType = C.getConstantArrayType( - RDType, ArraySize, ArrayType::Normal, /*IndexTypeQuals=*/0); - // kmp_task_red_input_t .rd_input.[Size]; - Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); - ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies, - Data.ReductionOps); - for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { - // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; - llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), - llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; - llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( - TaskRedInput.getPointer(), Idxs, - /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, - ".rd_input.gep."); - LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); - // ElemLVal.reduce_shar = &Shareds[Cnt]; - LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); - RCG.emitSharedLValue(CGF, Cnt); - llvm::Value *CastedShared = - CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer()); - CGF.EmitStoreOfScalar(CastedShared, SharedLVal); - RCG.emitAggregateType(CGF, Cnt); - llvm::Value *SizeValInChars; - llvm::Value *SizeVal; - std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); - // We use delayed creation/initialization for VLAs, array sections and - // custom reduction initializations. It is required because runtime does not - // provide the way to pass the sizes of VLAs/array sections to - // initializer/combiner/finalizer functions and does not pass the pointer to - // original reduction item to the initializer. Instead threadprivate global - // variables are used to store these values and use them in the functions. - bool DelayedCreation = !!SizeVal; - SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, - /*isSigned=*/false); - LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); - CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); - // ElemLVal.reduce_init = init; - LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); - llvm::Value *InitAddr = - CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); - CGF.EmitStoreOfScalar(InitAddr, InitLVal); - DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt); - // ElemLVal.reduce_fini = fini; - LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); - llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); - llvm::Value *FiniAddr = Fini - ? CGF.EmitCastToVoidPtr(Fini) - : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); - CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); - // ElemLVal.reduce_comb = comb; - LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); - llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( - CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], - RHSExprs[Cnt], Data.ReductionCopies[Cnt])); - CGF.EmitStoreOfScalar(CombAddr, CombLVal); - // ElemLVal.flags = 0; - LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); - if (DelayedCreation) { - CGF.EmitStoreOfScalar( - llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*IsSigned=*/true), - FlagsLVal); - } else - CGF.EmitNullInitialization(FlagsLVal.getAddress(), FlagsLVal.getType()); - } - // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void - // *data); - llvm::Value *Args[] = { - CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, - /*isSigned=*/true), - llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), - CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), - CGM.VoidPtrTy)}; - return CGF.EmitRuntimeCall( - createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args); -} - -void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, - SourceLocation Loc, - ReductionCodeGen &RCG, - unsigned N) { - auto Sizes = RCG.getSizes(N); - // Emit threadprivate global variable if the type is non-constant - // (Sizes.second = nullptr). - if (Sizes.second) { - llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, - /*isSigned=*/false); - Address SizeAddr = getAddrOfArtificialThreadPrivate( - CGF, CGM.getContext().getSizeType(), - generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); - CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); - } - // Store address of the original reduction item if custom initializer is used. - if (RCG.usesReductionInitializer(N)) { - Address SharedAddr = getAddrOfArtificialThreadPrivate( - CGF, CGM.getContext().VoidPtrTy, - generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); - CGF.Builder.CreateStore( - CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - RCG.getSharedLValue(N).getPointer(), CGM.VoidPtrTy), - SharedAddr, /*IsVolatile=*/false); - } -} - -Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, - SourceLocation Loc, - llvm::Value *ReductionsPtr, - LValue SharedLVal) { - // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void - // *d); - llvm::Value *Args[] = { - CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, - /*isSigned=*/true), - ReductionsPtr, - CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(SharedLVal.getPointer(), - CGM.VoidPtrTy)}; - return Address( - CGF.EmitRuntimeCall( - createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args), - SharedLVal.getAlignment()); -} - -void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, - SourceLocation Loc) { - if (!CGF.HaveInsertPoint()) - return; - // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 - // global_tid); - llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; - // Ignore return result until untied tasks are supported. - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); - if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) - Region->emitUntiedSwitch(CGF); -} - -void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, - OpenMPDirectiveKind InnerKind, - const RegionCodeGenTy &CodeGen, - bool HasCancel) { - if (!CGF.HaveInsertPoint()) - return; - InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); - CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); -} - -namespace { -enum RTCancelKind { - CancelNoreq = 0, - CancelParallel = 1, - CancelLoop = 2, - CancelSections = 3, - CancelTaskgroup = 4 -}; -} // anonymous namespace - -static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { - RTCancelKind CancelKind = CancelNoreq; - if (CancelRegion == OMPD_parallel) - CancelKind = CancelParallel; - else if (CancelRegion == OMPD_for) - CancelKind = CancelLoop; - else if (CancelRegion == OMPD_sections) - CancelKind = CancelSections; - else { - assert(CancelRegion == OMPD_taskgroup); - CancelKind = CancelTaskgroup; - } - return CancelKind; -} - -void CGOpenMPRuntime::emitCancellationPointCall( - CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDirectiveKind CancelRegion) { - if (!CGF.HaveInsertPoint()) - return; - // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 - // global_tid, kmp_int32 cncl_kind); - if (auto *OMPRegionInfo = - dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { - // For 'cancellation point taskgroup', the task region info may not have a - // cancel. This may instead happen in another adjacent task. - if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { - llvm::Value *Args[] = { - emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), - CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; - // Ignore return result until untied tasks are supported. - llvm::Value *Result = CGF.EmitRuntimeCall( - createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); - // if (__kmpc_cancellationpoint()) { - // exit from construct; - // } - llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); - llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); - llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); - CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); - CGF.EmitBlock(ExitBB); - // exit from construct; - CodeGenFunction::JumpDest CancelDest = - CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); - CGF.EmitBranchThroughCleanup(CancelDest); - CGF.EmitBlock(ContBB, /*IsFinished=*/true); - } - } -} - -void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, - const Expr *IfCond, - OpenMPDirectiveKind CancelRegion) { - if (!CGF.HaveInsertPoint()) - return; - // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, - // kmp_int32 cncl_kind); - if (auto *OMPRegionInfo = - dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { - auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF, - PrePostActionTy &) { - CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); - llvm::Value *Args[] = { - RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), - CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; - // Ignore return result until untied tasks are supported. - llvm::Value *Result = CGF.EmitRuntimeCall( - RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args); - // if (__kmpc_cancel()) { - // exit from construct; - // } - llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); - llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); - llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); - CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); - CGF.EmitBlock(ExitBB); - // exit from construct; - CodeGenFunction::JumpDest CancelDest = - CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); - CGF.EmitBranchThroughCleanup(CancelDest); - CGF.EmitBlock(ContBB, /*IsFinished=*/true); - }; - if (IfCond) { - emitOMPIfClause(CGF, IfCond, ThenGen, - [](CodeGenFunction &, PrePostActionTy &) {}); - } else { - RegionCodeGenTy ThenRCG(ThenGen); - ThenRCG(CGF); - } - } -} - -void CGOpenMPRuntime::emitTargetOutlinedFunction( - const OMPExecutableDirective &D, StringRef ParentName, - llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, - bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { - assert(!ParentName.empty() && "Invalid target region parent name!"); - emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, - IsOffloadEntry, CodeGen); -} - -void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( - const OMPExecutableDirective &D, StringRef ParentName, - llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, - bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { - // Create a unique name for the entry function using the source location - // information of the current target region. The name will be something like: - // - // __omp_offloading_DD_FFFF_PP_lBB - // - // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the - // mangled name of the function that encloses the target region and BB is the - // line number of the target region. - - unsigned DeviceID; - unsigned FileID; - unsigned Line; - getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, - Line); - SmallString<64> EntryFnName; - { - llvm::raw_svector_ostream OS(EntryFnName); - OS << "__omp_offloading" << llvm::format("_%x", DeviceID) - << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; - } - - const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); - - CodeGenFunction CGF(CGM, true); - CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); - CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); - - OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS); - - // If this target outline function is not an offload entry, we don't need to - // register it. - if (!IsOffloadEntry) - return; - - // The target region ID is used by the runtime library to identify the current - // target region, so it only has to be unique and not necessarily point to - // anything. It could be the pointer to the outlined function that implements - // the target region, but we aren't using that so that the compiler doesn't - // need to keep that, and could therefore inline the host function if proven - // worthwhile during optimization. In the other hand, if emitting code for the - // device, the ID has to be the function address so that it can retrieved from - // the offloading entry and launched by the runtime library. We also mark the - // outlined function to have external linkage in case we are emitting code for - // the device, because these functions will be entry points to the device. - - if (CGM.getLangOpts().OpenMPIsDevice) { - OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); - OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); - OutlinedFn->setDSOLocal(false); - } else { - std::string Name = getName({EntryFnName, "region_id"}); - OutlinedFnID = new llvm::GlobalVariable( - CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, - llvm::GlobalValue::WeakAnyLinkage, - llvm::Constant::getNullValue(CGM.Int8Ty), Name); - } - - // Register the information for the entry associated with this target region. - OffloadEntriesInfoManager.registerTargetRegionEntryInfo( - DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, - OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); -} - -/// discard all CompoundStmts intervening between two constructs -static const Stmt *ignoreCompoundStmts(const Stmt *Body) { - while (const auto *CS = dyn_cast_or_null<CompoundStmt>(Body)) - Body = CS->body_front(); - - return Body; -} - -/// Emit the number of teams for a target directive. Inspect the num_teams -/// clause associated with a teams construct combined or closely nested -/// with the target directive. -/// -/// Emit a team of size one for directives such as 'target parallel' that -/// have no associated teams construct. -/// -/// Otherwise, return nullptr. -static llvm::Value * -emitNumTeamsForTargetDirective(CGOpenMPRuntime &OMPRuntime, - CodeGenFunction &CGF, - const OMPExecutableDirective &D) { - assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the " - "teams directive expected to be " - "emitted only for the host!"); - - CGBuilderTy &Bld = CGF.Builder; - - // If the target directive is combined with a teams directive: - // Return the value in the num_teams clause, if any. - // Otherwise, return 0 to denote the runtime default. - if (isOpenMPTeamsDirective(D.getDirectiveKind())) { - if (const auto *NumTeamsClause = D.getSingleClause<OMPNumTeamsClause>()) { - CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); - llvm::Value *NumTeams = CGF.EmitScalarExpr(NumTeamsClause->getNumTeams(), - /*IgnoreResultAssign*/ true); - return Bld.CreateIntCast(NumTeams, CGF.Int32Ty, - /*IsSigned=*/true); - } - - // The default value is 0. - return Bld.getInt32(0); - } - - // If the target directive is combined with a parallel directive but not a - // teams directive, start one team. - if (isOpenMPParallelDirective(D.getDirectiveKind())) - return Bld.getInt32(1); - - // If the current target region has a teams region enclosed, we need to get - // the number of teams to pass to the runtime function call. This is done - // by generating the expression in a inlined region. This is required because - // the expression is captured in the enclosing target environment when the - // teams directive is not combined with target. - - const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); - - if (const auto *TeamsDir = dyn_cast_or_null<OMPExecutableDirective>( - ignoreCompoundStmts(CS.getCapturedStmt()))) { - if (isOpenMPTeamsDirective(TeamsDir->getDirectiveKind())) { - if (const auto *NTE = TeamsDir->getSingleClause<OMPNumTeamsClause>()) { - CGOpenMPInnerExprInfo CGInfo(CGF, CS); - CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); - llvm::Value *NumTeams = CGF.EmitScalarExpr(NTE->getNumTeams()); - return Bld.CreateIntCast(NumTeams, CGF.Int32Ty, - /*IsSigned=*/true); - } - - // If we have an enclosed teams directive but no num_teams clause we use - // the default value 0. - return Bld.getInt32(0); - } - } - - // No teams associated with the directive. - return nullptr; -} - -/// Emit the number of threads for a target directive. Inspect the -/// thread_limit clause associated with a teams construct combined or closely -/// nested with the target directive. -/// -/// Emit the num_threads clause for directives such as 'target parallel' that -/// have no associated teams construct. -/// -/// Otherwise, return nullptr. -static llvm::Value * -emitNumThreadsForTargetDirective(CGOpenMPRuntime &OMPRuntime, - CodeGenFunction &CGF, - const OMPExecutableDirective &D) { - assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the " - "teams directive expected to be " - "emitted only for the host!"); - - CGBuilderTy &Bld = CGF.Builder; - - // - // If the target directive is combined with a teams directive: - // Return the value in the thread_limit clause, if any. - // - // If the target directive is combined with a parallel directive: - // Return the value in the num_threads clause, if any. - // - // If both clauses are set, select the minimum of the two. - // - // If neither teams or parallel combined directives set the number of threads - // in a team, return 0 to denote the runtime default. - // - // If this is not a teams directive return nullptr. - - if (isOpenMPTeamsDirective(D.getDirectiveKind()) || - isOpenMPParallelDirective(D.getDirectiveKind())) { - llvm::Value *DefaultThreadLimitVal = Bld.getInt32(0); - llvm::Value *NumThreadsVal = nullptr; - llvm::Value *ThreadLimitVal = nullptr; - - if (const auto *ThreadLimitClause = - D.getSingleClause<OMPThreadLimitClause>()) { - CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); - llvm::Value *ThreadLimit = - CGF.EmitScalarExpr(ThreadLimitClause->getThreadLimit(), - /*IgnoreResultAssign*/ true); - ThreadLimitVal = Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, - /*IsSigned=*/true); - } - - if (const auto *NumThreadsClause = - D.getSingleClause<OMPNumThreadsClause>()) { - CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); - llvm::Value *NumThreads = - CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(), - /*IgnoreResultAssign*/ true); - NumThreadsVal = - Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*IsSigned=*/true); - } - - // Select the lesser of thread_limit and num_threads. - if (NumThreadsVal) - ThreadLimitVal = ThreadLimitVal - ? Bld.CreateSelect(Bld.CreateICmpSLT(NumThreadsVal, - ThreadLimitVal), - NumThreadsVal, ThreadLimitVal) - : NumThreadsVal; - - // Set default value passed to the runtime if either teams or a target - // parallel type directive is found but no clause is specified. - if (!ThreadLimitVal) - ThreadLimitVal = DefaultThreadLimitVal; - - return ThreadLimitVal; - } - - // If the current target region has a teams region enclosed, we need to get - // the thread limit to pass to the runtime function call. This is done - // by generating the expression in a inlined region. This is required because - // the expression is captured in the enclosing target environment when the - // teams directive is not combined with target. - - const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); - - if (const auto *TeamsDir = dyn_cast_or_null<OMPExecutableDirective>( - ignoreCompoundStmts(CS.getCapturedStmt()))) { - if (isOpenMPTeamsDirective(TeamsDir->getDirectiveKind())) { - if (const auto *TLE = TeamsDir->getSingleClause<OMPThreadLimitClause>()) { - CGOpenMPInnerExprInfo CGInfo(CGF, CS); - CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); - llvm::Value *ThreadLimit = CGF.EmitScalarExpr(TLE->getThreadLimit()); - return CGF.Builder.CreateIntCast(ThreadLimit, CGF.Int32Ty, - /*IsSigned=*/true); - } - - // If we have an enclosed teams directive but no thread_limit clause we - // use the default value 0. - return CGF.Builder.getInt32(0); - } - } - - // No teams associated with the directive. - return nullptr; -} - -namespace { -LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); - -// Utility to handle information from clauses associated with a given -// construct that use mappable expressions (e.g. 'map' clause, 'to' clause). -// It provides a convenient interface to obtain the information and generate -// code for that information. -class MappableExprsHandler { -public: - /// Values for bit flags used to specify the mapping type for - /// offloading. - enum OpenMPOffloadMappingFlags : uint64_t { - /// No flags - OMP_MAP_NONE = 0x0, - /// Allocate memory on the device and move data from host to device. - OMP_MAP_TO = 0x01, - /// Allocate memory on the device and move data from device to host. - OMP_MAP_FROM = 0x02, - /// Always perform the requested mapping action on the element, even - /// if it was already mapped before. - OMP_MAP_ALWAYS = 0x04, - /// Delete the element from the device environment, ignoring the - /// current reference count associated with the element. - OMP_MAP_DELETE = 0x08, - /// The element being mapped is a pointer-pointee pair; both the - /// pointer and the pointee should be mapped. - OMP_MAP_PTR_AND_OBJ = 0x10, - /// This flags signals that the base address of an entry should be - /// passed to the target kernel as an argument. - OMP_MAP_TARGET_PARAM = 0x20, - /// Signal that the runtime library has to return the device pointer - /// in the current position for the data being mapped. Used when we have the - /// use_device_ptr clause. - OMP_MAP_RETURN_PARAM = 0x40, - /// This flag signals that the reference being passed is a pointer to - /// private data. - OMP_MAP_PRIVATE = 0x80, - /// Pass the element to the device by value. - OMP_MAP_LITERAL = 0x100, - /// Implicit map - OMP_MAP_IMPLICIT = 0x200, - /// The 16 MSBs of the flags indicate whether the entry is member of some - /// struct/class. - OMP_MAP_MEMBER_OF = 0xffff000000000000, - LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), - }; - - /// Class that associates information with a base pointer to be passed to the - /// runtime library. - class BasePointerInfo { - /// The base pointer. - llvm::Value *Ptr = nullptr; - /// The base declaration that refers to this device pointer, or null if - /// there is none. - const ValueDecl *DevPtrDecl = nullptr; - - public: - BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) - : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} - llvm::Value *operator*() const { return Ptr; } - const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } - void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } - }; - - using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; - using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; - using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; - - /// Map between a struct and the its lowest & highest elements which have been - /// mapped. - /// [ValueDecl *] --> {LE(FieldIndex, Pointer), - /// HE(FieldIndex, Pointer)} - struct StructRangeInfoTy { - std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { - 0, Address::invalid()}; - std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { - 0, Address::invalid()}; - Address Base = Address::invalid(); - }; - -private: - /// Kind that defines how a device pointer has to be returned. - struct MapInfo { - OMPClauseMappableExprCommon::MappableExprComponentListRef Components; - OpenMPMapClauseKind MapType = OMPC_MAP_unknown; - ArrayRef<OpenMPMapModifierKind> MapModifiers; - bool ReturnDevicePointer = false; - bool IsImplicit = false; - - MapInfo() = default; - MapInfo( - OMPClauseMappableExprCommon::MappableExprComponentListRef Components, - OpenMPMapClauseKind MapType, - ArrayRef<OpenMPMapModifierKind> MapModifiers, - bool ReturnDevicePointer, bool IsImplicit) - : Components(Components), MapType(MapType), MapModifiers(MapModifiers), - ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {} - }; - - /// If use_device_ptr is used on a pointer which is a struct member and there - /// is no map information about it, then emission of that entry is deferred - /// until the whole struct has been processed. - struct DeferredDevicePtrEntryTy { - const Expr *IE = nullptr; - const ValueDecl *VD = nullptr; - - DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD) - : IE(IE), VD(VD) {} - }; - - /// Directive from where the map clauses were extracted. - const OMPExecutableDirective &CurDir; - - /// Function the directive is being generated for. - CodeGenFunction &CGF; - - /// Set of all first private variables in the current directive. - llvm::SmallPtrSet<const VarDecl *, 8> FirstPrivateDecls; - - /// Map between device pointer declarations and their expression components. - /// The key value for declarations in 'this' is null. - llvm::DenseMap< - const ValueDecl *, - SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> - DevPointersMap; - - llvm::Value *getExprTypeSize(const Expr *E) const { - QualType ExprTy = E->getType().getCanonicalType(); - - // Reference types are ignored for mapping purposes. - if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) - ExprTy = RefTy->getPointeeType().getCanonicalType(); - - // Given that an array section is considered a built-in type, we need to - // do the calculation based on the length of the section instead of relying - // on CGF.getTypeSize(E->getType()). - if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { - QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( - OAE->getBase()->IgnoreParenImpCasts()) - .getCanonicalType(); - - // If there is no length associated with the expression, that means we - // are using the whole length of the base. - if (!OAE->getLength() && OAE->getColonLoc().isValid()) - return CGF.getTypeSize(BaseTy); - - llvm::Value *ElemSize; - if (const auto *PTy = BaseTy->getAs<PointerType>()) { - ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); - } else { - const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); - assert(ATy && "Expecting array type if not a pointer type."); - ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); - } - - // If we don't have a length at this point, that is because we have an - // array section with a single element. - if (!OAE->getLength()) - return ElemSize; - - llvm::Value *LengthVal = CGF.EmitScalarExpr(OAE->getLength()); - LengthVal = - CGF.Builder.CreateIntCast(LengthVal, CGF.SizeTy, /*isSigned=*/false); - return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); - } - return CGF.getTypeSize(ExprTy); - } - - /// Return the corresponding bits for a given map clause modifier. Add - /// a flag marking the map as a pointer if requested. Add a flag marking the - /// map as the first one of a series of maps that relate to the same map - /// expression. - OpenMPOffloadMappingFlags getMapTypeBits( - OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, - bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const { - OpenMPOffloadMappingFlags Bits = - IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; - switch (MapType) { - case OMPC_MAP_alloc: - case OMPC_MAP_release: - // alloc and release is the default behavior in the runtime library, i.e. - // if we don't pass any bits alloc/release that is what the runtime is - // going to do. Therefore, we don't need to signal anything for these two - // type modifiers. - break; - case OMPC_MAP_to: - Bits |= OMP_MAP_TO; - break; - case OMPC_MAP_from: - Bits |= OMP_MAP_FROM; - break; - case OMPC_MAP_tofrom: - Bits |= OMP_MAP_TO | OMP_MAP_FROM; - break; - case OMPC_MAP_delete: - Bits |= OMP_MAP_DELETE; - break; - case OMPC_MAP_unknown: - llvm_unreachable("Unexpected map type!"); - } - if (AddPtrFlag) - Bits |= OMP_MAP_PTR_AND_OBJ; - if (AddIsTargetParamFlag) - Bits |= OMP_MAP_TARGET_PARAM; - if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) - != MapModifiers.end()) - Bits |= OMP_MAP_ALWAYS; - return Bits; - } - - /// Return true if the provided expression is a final array section. A - /// final array section, is one whose length can't be proved to be one. - bool isFinalArraySectionExpression(const Expr *E) const { - const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); - - // It is not an array section and therefore not a unity-size one. - if (!OASE) - return false; - - // An array section with no colon always refer to a single element. - if (OASE->getColonLoc().isInvalid()) - return false; - - const Expr *Length = OASE->getLength(); - - // If we don't have a length we have to check if the array has size 1 - // for this dimension. Also, we should always expect a length if the - // base type is pointer. - if (!Length) { - QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( - OASE->getBase()->IgnoreParenImpCasts()) - .getCanonicalType(); - if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) - return ATy->getSize().getSExtValue() != 1; - // If we don't have a constant dimension length, we have to consider - // the current section as having any size, so it is not necessarily - // unitary. If it happen to be unity size, that's user fault. - return true; - } - - // Check if the length evaluates to 1. - Expr::EvalResult Result; - if (!Length->EvaluateAsInt(Result, CGF.getContext())) - return true; // Can have more that size 1. - - llvm::APSInt ConstLength = Result.Val.getInt(); - return ConstLength.getSExtValue() != 1; - } - - /// Generate the base pointers, section pointers, sizes and map type - /// bits for the provided map type, map modifier, and expression components. - /// \a IsFirstComponent should be set to true if the provided set of - /// components is the first associated with a capture. - void generateInfoForComponentList( - OpenMPMapClauseKind MapType, - ArrayRef<OpenMPMapModifierKind> MapModifiers, - OMPClauseMappableExprCommon::MappableExprComponentListRef Components, - MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, - MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, - StructRangeInfoTy &PartialStruct, bool IsFirstComponentList, - bool IsImplicit, - ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> - OverlappedElements = llvm::None) const { - // The following summarizes what has to be generated for each map and the - // types below. The generated information is expressed in this order: - // base pointer, section pointer, size, flags - // (to add to the ones that come from the map type and modifier). - // - // double d; - // int i[100]; - // float *p; - // - // struct S1 { - // int i; - // float f[50]; - // } - // struct S2 { - // int i; - // float f[50]; - // S1 s; - // double *p; - // struct S2 *ps; - // } - // S2 s; - // S2 *ps; - // - // map(d) - // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM - // - // map(i) - // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM - // - // map(i[1:23]) - // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM - // - // map(p) - // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM - // - // map(p[1:24]) - // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM - // - // map(s) - // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM - // - // map(s.i) - // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM - // - // map(s.s.f) - // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM - // - // map(s.p) - // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM - // - // map(to: s.p[:22]) - // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) - // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) - // &(s.p), &(s.p[0]), 22*sizeof(double), - // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) - // (*) alloc space for struct members, only this is a target parameter - // (**) map the pointer (nothing to be mapped in this example) (the compiler - // optimizes this entry out, same in the examples below) - // (***) map the pointee (map: to) - // - // map(s.ps) - // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM - // - // map(from: s.ps->s.i) - // &s, &(s.ps), sizeof(S2*), TARGET_PARAM - // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) - // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM - // - // map(to: s.ps->ps) - // &s, &(s.ps), sizeof(S2*), TARGET_PARAM - // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) - // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO - // - // map(s.ps->ps->ps) - // &s, &(s.ps), sizeof(S2*), TARGET_PARAM - // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) - // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ - // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM - // - // map(to: s.ps->ps->s.f[:22]) - // &s, &(s.ps), sizeof(S2*), TARGET_PARAM - // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) - // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ - // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO - // - // map(ps) - // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM - // - // map(ps->i) - // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM - // - // map(ps->s.f) - // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM - // - // map(from: ps->p) - // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM - // - // map(to: ps->p[:22]) - // ps, &(ps->p), sizeof(double*), TARGET_PARAM - // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) - // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO - // - // map(ps->ps) - // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM - // - // map(from: ps->ps->s.i) - // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM - // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) - // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM - // - // map(from: ps->ps->ps) - // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM - // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) - // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM - // - // map(ps->ps->ps->ps) - // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM - // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) - // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ - // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM - // - // map(to: ps->ps->ps->s.f[:22]) - // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM - // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) - // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ - // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO - // - // map(to: s.f[:22]) map(from: s.p[:33]) - // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + - // sizeof(double*) (**), TARGET_PARAM - // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO - // &s, &(s.p), sizeof(double*), MEMBER_OF(1) - // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM - // (*) allocate contiguous space needed to fit all mapped members even if - // we allocate space for members not mapped (in this example, - // s.f[22..49] and s.s are not mapped, yet we must allocate space for - // them as well because they fall between &s.f[0] and &s.p) - // - // map(from: s.f[:22]) map(to: ps->p[:33]) - // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM - // ps, &(ps->p), sizeof(S2*), TARGET_PARAM - // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) - // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO - // (*) the struct this entry pertains to is the 2nd element in the list of - // arguments, hence MEMBER_OF(2) - // - // map(from: s.f[:22], s.s) map(to: ps->p[:33]) - // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM - // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM - // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM - // ps, &(ps->p), sizeof(S2*), TARGET_PARAM - // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) - // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO - // (*) the struct this entry pertains to is the 4th element in the list - // of arguments, hence MEMBER_OF(4) - - // Track if the map information being generated is the first for a capture. - bool IsCaptureFirstInfo = IsFirstComponentList; - bool IsLink = false; // Is this variable a "declare target link"? - - // Scan the components from the base to the complete expression. - auto CI = Components.rbegin(); - auto CE = Components.rend(); - auto I = CI; - - // Track if the map information being generated is the first for a list of - // components. - bool IsExpressionFirstInfo = true; - Address BP = Address::invalid(); - const Expr *AssocExpr = I->getAssociatedExpression(); - const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); - const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); - - if (isa<MemberExpr>(AssocExpr)) { - // The base is the 'this' pointer. The content of the pointer is going - // to be the base of the field being mapped. - BP = CGF.LoadCXXThisAddress(); - } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || - (OASE && - isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { - BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(); - } else { - // The base is the reference to the variable. - // BP = &Var. - BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(); - if (const auto *VD = - dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { - if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) - if (*Res == OMPDeclareTargetDeclAttr::MT_Link) { - IsLink = true; - BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD); - } - } - - // If the variable is a pointer and is being dereferenced (i.e. is not - // the last component), the base has to be the pointer itself, not its - // reference. References are ignored for mapping purposes. - QualType Ty = - I->getAssociatedDeclaration()->getType().getNonReferenceType(); - if (Ty->isAnyPointerType() && std::next(I) != CE) { - BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); - - // We do not need to generate individual map information for the - // pointer, it can be associated with the combined storage. - ++I; - } - } - - // Track whether a component of the list should be marked as MEMBER_OF some - // combined entry (for partial structs). Only the first PTR_AND_OBJ entry - // in a component list should be marked as MEMBER_OF, all subsequent entries - // do not belong to the base struct. E.g. - // struct S2 s; - // s.ps->ps->ps->f[:] - // (1) (2) (3) (4) - // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a - // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) - // is the pointee of ps(2) which is not member of struct s, so it should not - // be marked as such (it is still PTR_AND_OBJ). - // The variable is initialized to false so that PTR_AND_OBJ entries which - // are not struct members are not considered (e.g. array of pointers to - // data). - bool ShouldBeMemberOf = false; - - // Variable keeping track of whether or not we have encountered a component - // in the component list which is a member expression. Useful when we have a - // pointer or a final array section, in which case it is the previous - // component in the list which tells us whether we have a member expression. - // E.g. X.f[:] - // While processing the final array section "[:]" it is "f" which tells us - // whether we are dealing with a member of a declared struct. - const MemberExpr *EncounteredME = nullptr; - - for (; I != CE; ++I) { - // If the current component is member of a struct (parent struct) mark it. - if (!EncounteredME) { - EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); - // If we encounter a PTR_AND_OBJ entry from now on it should be marked - // as MEMBER_OF the parent struct. - if (EncounteredME) - ShouldBeMemberOf = true; - } - - auto Next = std::next(I); - - // We need to generate the addresses and sizes if this is the last - // component, if the component is a pointer or if it is an array section - // whose length can't be proved to be one. If this is a pointer, it - // becomes the base address for the following components. - - // A final array section, is one whose length can't be proved to be one. - bool IsFinalArraySection = - isFinalArraySectionExpression(I->getAssociatedExpression()); - - // Get information on whether the element is a pointer. Have to do a - // special treatment for array sections given that they are built-in - // types. - const auto *OASE = - dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); - bool IsPointer = - (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) - .getCanonicalType() - ->isAnyPointerType()) || - I->getAssociatedExpression()->getType()->isAnyPointerType(); - - if (Next == CE || IsPointer || IsFinalArraySection) { - // If this is not the last component, we expect the pointer to be - // associated with an array expression or member expression. - assert((Next == CE || - isa<MemberExpr>(Next->getAssociatedExpression()) || - isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || - isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) && - "Unexpected expression"); - - Address LB = - CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress(); - - // If this component is a pointer inside the base struct then we don't - // need to create any entry for it - it will be combined with the object - // it is pointing to into a single PTR_AND_OBJ entry. - bool IsMemberPointer = - IsPointer && EncounteredME && - (dyn_cast<MemberExpr>(I->getAssociatedExpression()) == - EncounteredME); - if (!OverlappedElements.empty()) { - // Handle base element with the info for overlapped elements. - assert(!PartialStruct.Base.isValid() && "The base element is set."); - assert(Next == CE && - "Expected last element for the overlapped elements."); - assert(!IsPointer && - "Unexpected base element with the pointer type."); - // Mark the whole struct as the struct that requires allocation on the - // device. - PartialStruct.LowestElem = {0, LB}; - CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( - I->getAssociatedExpression()->getType()); - Address HB = CGF.Builder.CreateConstGEP( - CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB, - CGF.VoidPtrTy), - TypeSize.getQuantity() - 1, CharUnits::One()); - PartialStruct.HighestElem = { - std::numeric_limits<decltype( - PartialStruct.HighestElem.first)>::max(), - HB}; - PartialStruct.Base = BP; - // Emit data for non-overlapped data. - OpenMPOffloadMappingFlags Flags = - OMP_MAP_MEMBER_OF | - getMapTypeBits(MapType, MapModifiers, IsImplicit, - /*AddPtrFlag=*/false, - /*AddIsTargetParamFlag=*/false); - LB = BP; - llvm::Value *Size = nullptr; - // Do bitcopy of all non-overlapped structure elements. - for (OMPClauseMappableExprCommon::MappableExprComponentListRef - Component : OverlappedElements) { - Address ComponentLB = Address::invalid(); - for (const OMPClauseMappableExprCommon::MappableComponent &MC : - Component) { - if (MC.getAssociatedDeclaration()) { - ComponentLB = - CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) - .getAddress(); - Size = CGF.Builder.CreatePtrDiff( - CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), - CGF.EmitCastToVoidPtr(LB.getPointer())); - break; - } - } - BasePointers.push_back(BP.getPointer()); - Pointers.push_back(LB.getPointer()); - Sizes.push_back(Size); - Types.push_back(Flags); - LB = CGF.Builder.CreateConstGEP(ComponentLB, 1, - CGF.getPointerSize()); - } - BasePointers.push_back(BP.getPointer()); - Pointers.push_back(LB.getPointer()); - Size = CGF.Builder.CreatePtrDiff( - CGF.EmitCastToVoidPtr( - CGF.Builder.CreateConstGEP(HB, 1, CharUnits::One()) - .getPointer()), - CGF.EmitCastToVoidPtr(LB.getPointer())); - Sizes.push_back(Size); - Types.push_back(Flags); - break; - } - llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); - if (!IsMemberPointer) { - BasePointers.push_back(BP.getPointer()); - Pointers.push_back(LB.getPointer()); - Sizes.push_back(Size); - - // We need to add a pointer flag for each map that comes from the - // same expression except for the first one. We also need to signal - // this map is the first one that relates with the current capture - // (there is a set of entries for each capture). - OpenMPOffloadMappingFlags Flags = getMapTypeBits( - MapType, MapModifiers, IsImplicit, - !IsExpressionFirstInfo || IsLink, IsCaptureFirstInfo && !IsLink); - - if (!IsExpressionFirstInfo) { - // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, - // then we reset the TO/FROM/ALWAYS/DELETE flags. - if (IsPointer) - Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | - OMP_MAP_DELETE); - - if (ShouldBeMemberOf) { - // Set placeholder value MEMBER_OF=FFFF to indicate that the flag - // should be later updated with the correct value of MEMBER_OF. - Flags |= OMP_MAP_MEMBER_OF; - // From now on, all subsequent PTR_AND_OBJ entries should not be - // marked as MEMBER_OF. - ShouldBeMemberOf = false; - } - } - - Types.push_back(Flags); - } - - // If we have encountered a member expression so far, keep track of the - // mapped member. If the parent is "*this", then the value declaration - // is nullptr. - if (EncounteredME) { - const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl()); - unsigned FieldIndex = FD->getFieldIndex(); - - // Update info about the lowest and highest elements for this struct - if (!PartialStruct.Base.isValid()) { - PartialStruct.LowestElem = {FieldIndex, LB}; - PartialStruct.HighestElem = {FieldIndex, LB}; - PartialStruct.Base = BP; - } else if (FieldIndex < PartialStruct.LowestElem.first) { - PartialStruct.LowestElem = {FieldIndex, LB}; - } else if (FieldIndex > PartialStruct.HighestElem.first) { - PartialStruct.HighestElem = {FieldIndex, LB}; - } - } - - // If we have a final array section, we are done with this expression. - if (IsFinalArraySection) - break; - - // The pointer becomes the base for the next element. - if (Next != CE) - BP = LB; - - IsExpressionFirstInfo = false; - IsCaptureFirstInfo = false; - } - } - } - - /// Return the adjusted map modifiers if the declaration a capture refers to - /// appears in a first-private clause. This is expected to be used only with - /// directives that start with 'target'. - MappableExprsHandler::OpenMPOffloadMappingFlags - getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { - assert(Cap.capturesVariable() && "Expected capture by reference only!"); - - // A first private variable captured by reference will use only the - // 'private ptr' and 'map to' flag. Return the right flags if the captured - // declaration is known as first-private in this handler. - if (FirstPrivateDecls.count(Cap.getCapturedVar())) - return MappableExprsHandler::OMP_MAP_PRIVATE | - MappableExprsHandler::OMP_MAP_TO; - return MappableExprsHandler::OMP_MAP_TO | - MappableExprsHandler::OMP_MAP_FROM; - } - - static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { - // Member of is given by the 16 MSB of the flag, so rotate by 48 bits. - return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) - << 48); - } - - static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, - OpenMPOffloadMappingFlags MemberOfFlag) { - // If the entry is PTR_AND_OBJ but has not been marked with the special - // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be - // marked as MEMBER_OF. - if ((Flags & OMP_MAP_PTR_AND_OBJ) && - ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) - return; - - // Reset the placeholder value to prepare the flag for the assignment of the - // proper MEMBER_OF value. - Flags &= ~OMP_MAP_MEMBER_OF; - Flags |= MemberOfFlag; - } - - void getPlainLayout(const CXXRecordDecl *RD, - llvm::SmallVectorImpl<const FieldDecl *> &Layout, - bool AsBase) const { - const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); - - llvm::StructType *St = - AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); - - unsigned NumElements = St->getNumElements(); - llvm::SmallVector< - llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> - RecordLayout(NumElements); - - // Fill bases. - for (const auto &I : RD->bases()) { - if (I.isVirtual()) - continue; - const auto *Base = I.getType()->getAsCXXRecordDecl(); - // Ignore empty bases. - if (Base->isEmpty() || CGF.getContext() - .getASTRecordLayout(Base) - .getNonVirtualSize() - .isZero()) - continue; - - unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); - RecordLayout[FieldIndex] = Base; - } - // Fill in virtual bases. - for (const auto &I : RD->vbases()) { - const auto *Base = I.getType()->getAsCXXRecordDecl(); - // Ignore empty bases. - if (Base->isEmpty()) - continue; - unsigned FieldIndex = RL.getVirtualBaseIndex(Base); - if (RecordLayout[FieldIndex]) - continue; - RecordLayout[FieldIndex] = Base; - } - // Fill in all the fields. - assert(!RD->isUnion() && "Unexpected union."); - for (const auto *Field : RD->fields()) { - // Fill in non-bitfields. (Bitfields always use a zero pattern, which we - // will fill in later.) - if (!Field->isBitField()) { - unsigned FieldIndex = RL.getLLVMFieldNo(Field); - RecordLayout[FieldIndex] = Field; - } - } - for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> - &Data : RecordLayout) { - if (Data.isNull()) - continue; - if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) - getPlainLayout(Base, Layout, /*AsBase=*/true); - else - Layout.push_back(Data.get<const FieldDecl *>()); - } - } - -public: - MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) - : CurDir(Dir), CGF(CGF) { - // Extract firstprivate clause information. - for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) - for (const auto *D : C->varlists()) - FirstPrivateDecls.insert( - cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl()); - // Extract device pointer clause information. - for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) - for (auto L : C->component_lists()) - DevPointersMap[L.first].push_back(L.second); - } - - /// Generate code for the combined entry if we have a partially mapped struct - /// and take care of the mapping flags of the arguments corresponding to - /// individual struct members. - void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers, - MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, - MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes, - const StructRangeInfoTy &PartialStruct) const { - // Base is the base of the struct - BasePointers.push_back(PartialStruct.Base.getPointer()); - // Pointer is the address of the lowest element - llvm::Value *LB = PartialStruct.LowestElem.second.getPointer(); - Pointers.push_back(LB); - // Size is (addr of {highest+1} element) - (addr of lowest element) - llvm::Value *HB = PartialStruct.HighestElem.second.getPointer(); - llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); - llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); - llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); - llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); - llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.SizeTy, - /*isSinged=*/false); - Sizes.push_back(Size); - // Map type is always TARGET_PARAM - Types.push_back(OMP_MAP_TARGET_PARAM); - // Remove TARGET_PARAM flag from the first element - (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; - - // All other current entries will be MEMBER_OF the combined entry - // (except for PTR_AND_OBJ entries which do not have a placeholder value - // 0xFFFF in the MEMBER_OF field). - OpenMPOffloadMappingFlags MemberOfFlag = - getMemberOfFlag(BasePointers.size() - 1); - for (auto &M : CurTypes) - setCorrectMemberOfFlag(M, MemberOfFlag); - } - - /// Generate all the base pointers, section pointers, sizes and map - /// types for the extracted mappable expressions. Also, for each item that - /// relates with a device pointer, a pair of the relevant declaration and - /// index where it occurs is appended to the device pointers info array. - void generateAllInfo(MapBaseValuesArrayTy &BasePointers, - MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, - MapFlagsArrayTy &Types) const { - // We have to process the component lists that relate with the same - // declaration in a single chunk so that we can generate the map flags - // correctly. Therefore, we organize all lists in a map. - llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; - - // Helper function to fill the information map for the different supported - // clauses. - auto &&InfoGen = [&Info]( - const ValueDecl *D, - OMPClauseMappableExprCommon::MappableExprComponentListRef L, - OpenMPMapClauseKind MapType, - ArrayRef<OpenMPMapModifierKind> MapModifiers, - bool ReturnDevicePointer, bool IsImplicit) { - const ValueDecl *VD = - D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; - Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, - IsImplicit); - }; - - // FIXME: MSVC 2013 seems to require this-> to find member CurDir. - for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>()) - for (const auto &L : C->component_lists()) { - InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(), - /*ReturnDevicePointer=*/false, C->isImplicit()); - } - for (const auto *C : this->CurDir.getClausesOfKind<OMPToClause>()) - for (const auto &L : C->component_lists()) { - InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None, - /*ReturnDevicePointer=*/false, C->isImplicit()); - } - for (const auto *C : this->CurDir.getClausesOfKind<OMPFromClause>()) - for (const auto &L : C->component_lists()) { - InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None, - /*ReturnDevicePointer=*/false, C->isImplicit()); - } - - // Look at the use_device_ptr clause information and mark the existing map - // entries as such. If there is no map information for an entry in the - // use_device_ptr list, we create one with map type 'alloc' and zero size - // section. It is the user fault if that was not mapped before. If there is - // no map information and the pointer is a struct member, then we defer the - // emission of that entry until the whole struct has been processed. - llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>> - DeferredInfo; - - // FIXME: MSVC 2013 seems to require this-> to find member CurDir. - for (const auto *C : - this->CurDir.getClausesOfKind<OMPUseDevicePtrClause>()) { - for (const auto &L : C->component_lists()) { - assert(!L.second.empty() && "Not expecting empty list of components!"); - const ValueDecl *VD = L.second.back().getAssociatedDeclaration(); - VD = cast<ValueDecl>(VD->getCanonicalDecl()); - const Expr *IE = L.second.back().getAssociatedExpression(); - // If the first component is a member expression, we have to look into - // 'this', which maps to null in the map of map information. Otherwise - // look directly for the information. - auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); - - // We potentially have map information for this declaration already. - // Look for the first set of components that refer to it. - if (It != Info.end()) { - auto CI = std::find_if( - It->second.begin(), It->second.end(), [VD](const MapInfo &MI) { - return MI.Components.back().getAssociatedDeclaration() == VD; - }); - // If we found a map entry, signal that the pointer has to be returned - // and move on to the next declaration. - if (CI != It->second.end()) { - CI->ReturnDevicePointer = true; - continue; - } - } - - // We didn't find any match in our map information - generate a zero - // size array section - if the pointer is a struct member we defer this - // action until the whole struct has been processed. - // FIXME: MSVC 2013 seems to require this-> to find member CGF. - if (isa<MemberExpr>(IE)) { - // Insert the pointer into Info to be processed by - // generateInfoForComponentList. Because it is a member pointer - // without a pointee, no entry will be generated for it, therefore - // we need to generate one after the whole struct has been processed. - // Nonetheless, generateInfoForComponentList must be called to take - // the pointer into account for the calculation of the range of the - // partial struct. - InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None, - /*ReturnDevicePointer=*/false, C->isImplicit()); - DeferredInfo[nullptr].emplace_back(IE, VD); - } else { - llvm::Value *Ptr = this->CGF.EmitLoadOfScalar( - this->CGF.EmitLValue(IE), IE->getExprLoc()); - BasePointers.emplace_back(Ptr, VD); - Pointers.push_back(Ptr); - Sizes.push_back(llvm::Constant::getNullValue(this->CGF.SizeTy)); - Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM); - } - } - } - - for (const auto &M : Info) { - // We need to know when we generate information for the first component - // associated with a capture, because the mapping flags depend on it. - bool IsFirstComponentList = true; - - // Temporary versions of arrays - MapBaseValuesArrayTy CurBasePointers; - MapValuesArrayTy CurPointers; - MapValuesArrayTy CurSizes; - MapFlagsArrayTy CurTypes; - StructRangeInfoTy PartialStruct; - - for (const MapInfo &L : M.second) { - assert(!L.Components.empty() && - "Not expecting declaration with no component lists."); - - // Remember the current base pointer index. - unsigned CurrentBasePointersIdx = CurBasePointers.size(); - // FIXME: MSVC 2013 seems to require this-> to find the member method. - this->generateInfoForComponentList( - L.MapType, L.MapModifiers, L.Components, CurBasePointers, - CurPointers, CurSizes, CurTypes, PartialStruct, - IsFirstComponentList, L.IsImplicit); - - // If this entry relates with a device pointer, set the relevant - // declaration and add the 'return pointer' flag. - if (L.ReturnDevicePointer) { - assert(CurBasePointers.size() > CurrentBasePointersIdx && - "Unexpected number of mapped base pointers."); - - const ValueDecl *RelevantVD = - L.Components.back().getAssociatedDeclaration(); - assert(RelevantVD && - "No relevant declaration related with device pointer??"); - - CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD); - CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; - } - IsFirstComponentList = false; - } - - // Append any pending zero-length pointers which are struct members and - // used with use_device_ptr. - auto CI = DeferredInfo.find(M.first); - if (CI != DeferredInfo.end()) { - for (const DeferredDevicePtrEntryTy &L : CI->second) { - llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(); - llvm::Value *Ptr = this->CGF.EmitLoadOfScalar( - this->CGF.EmitLValue(L.IE), L.IE->getExprLoc()); - CurBasePointers.emplace_back(BasePtr, L.VD); - CurPointers.push_back(Ptr); - CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.SizeTy)); - // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder - // value MEMBER_OF=FFFF so that the entry is later updated with the - // correct value of MEMBER_OF. - CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | - OMP_MAP_MEMBER_OF); - } - } - - // If there is an entry in PartialStruct it means we have a struct with - // individual members mapped. Emit an extra combined entry. - if (PartialStruct.Base.isValid()) - emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, - PartialStruct); - - // We need to append the results of this capture to what we already have. - BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); - Pointers.append(CurPointers.begin(), CurPointers.end()); - Sizes.append(CurSizes.begin(), CurSizes.end()); - Types.append(CurTypes.begin(), CurTypes.end()); - } - } - - /// Emit capture info for lambdas for variables captured by reference. - void generateInfoForLambdaCaptures( - const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers, - MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, - MapFlagsArrayTy &Types, - llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { - const auto *RD = VD->getType() - .getCanonicalType() - .getNonReferenceType() - ->getAsCXXRecordDecl(); - if (!RD || !RD->isLambda()) - return; - Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); - LValue VDLVal = CGF.MakeAddrLValue( - VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); - llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; - FieldDecl *ThisCapture = nullptr; - RD->getCaptureFields(Captures, ThisCapture); - if (ThisCapture) { - LValue ThisLVal = - CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); - LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); - LambdaPointers.try_emplace(ThisLVal.getPointer(), VDLVal.getPointer()); - BasePointers.push_back(ThisLVal.getPointer()); - Pointers.push_back(ThisLValVal.getPointer()); - Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy)); - Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | - OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); - } - for (const LambdaCapture &LC : RD->captures()) { - if (LC.getCaptureKind() != LCK_ByRef) - continue; - const VarDecl *VD = LC.getCapturedVar(); - auto It = Captures.find(VD); - assert(It != Captures.end() && "Found lambda capture without field."); - LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); - LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); - LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer()); - BasePointers.push_back(VarLVal.getPointer()); - Pointers.push_back(VarLValVal.getPointer()); - Sizes.push_back(CGF.getTypeSize( - VD->getType().getCanonicalType().getNonReferenceType())); - Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | - OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); - } - } - - /// Set correct indices for lambdas captures. - void adjustMemberOfForLambdaCaptures( - const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, - MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, - MapFlagsArrayTy &Types) const { - for (unsigned I = 0, E = Types.size(); I < E; ++I) { - // Set correct member_of idx for all implicit lambda captures. - if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | - OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) - continue; - llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); - assert(BasePtr && "Unable to find base lambda address."); - int TgtIdx = -1; - for (unsigned J = I; J > 0; --J) { - unsigned Idx = J - 1; - if (Pointers[Idx] != BasePtr) - continue; - TgtIdx = Idx; - break; - } - assert(TgtIdx != -1 && "Unable to find parent lambda."); - // All other current entries will be MEMBER_OF the combined entry - // (except for PTR_AND_OBJ entries which do not have a placeholder value - // 0xFFFF in the MEMBER_OF field). - OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); - setCorrectMemberOfFlag(Types[I], MemberOfFlag); - } - } - - /// Generate the base pointers, section pointers, sizes and map types - /// associated to a given capture. - void generateInfoForCapture(const CapturedStmt::Capture *Cap, - llvm::Value *Arg, - MapBaseValuesArrayTy &BasePointers, - MapValuesArrayTy &Pointers, - MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, - StructRangeInfoTy &PartialStruct) const { - assert(!Cap->capturesVariableArrayType() && - "Not expecting to generate map info for a variable array type!"); - - // We need to know when we generating information for the first component - const ValueDecl *VD = Cap->capturesThis() - ? nullptr - : Cap->getCapturedVar()->getCanonicalDecl(); - - // If this declaration appears in a is_device_ptr clause we just have to - // pass the pointer by value. If it is a reference to a declaration, we just - // pass its value. - if (DevPointersMap.count(VD)) { - BasePointers.emplace_back(Arg, VD); - Pointers.push_back(Arg); - Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy)); - Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM); - return; - } - - using MapData = - std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, - OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>; - SmallVector<MapData, 4> DeclComponentLists; - // FIXME: MSVC 2013 seems to require this-> to find member CurDir. - for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>()) { - for (const auto &L : C->decl_component_lists(VD)) { - assert(L.first == VD && - "We got information for the wrong declaration??"); - assert(!L.second.empty() && - "Not expecting declaration with no component lists."); - DeclComponentLists.emplace_back(L.second, C->getMapType(), - C->getMapTypeModifiers(), - C->isImplicit()); - } - } - - // Find overlapping elements (including the offset from the base element). - llvm::SmallDenseMap< - const MapData *, - llvm::SmallVector< - OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, - 4> - OverlappedData; - size_t Count = 0; - for (const MapData &L : DeclComponentLists) { - OMPClauseMappableExprCommon::MappableExprComponentListRef Components; - OpenMPMapClauseKind MapType; - ArrayRef<OpenMPMapModifierKind> MapModifiers; - bool IsImplicit; - std::tie(Components, MapType, MapModifiers, IsImplicit) = L; - ++Count; - for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { - OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; - std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1; - auto CI = Components.rbegin(); - auto CE = Components.rend(); - auto SI = Components1.rbegin(); - auto SE = Components1.rend(); - for (; CI != CE && SI != SE; ++CI, ++SI) { - if (CI->getAssociatedExpression()->getStmtClass() != - SI->getAssociatedExpression()->getStmtClass()) - break; - // Are we dealing with different variables/fields? - if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) - break; - } - // Found overlapping if, at least for one component, reached the head of - // the components list. - if (CI == CE || SI == SE) { - assert((CI != CE || SI != SE) && - "Unexpected full match of the mapping components."); - const MapData &BaseData = CI == CE ? L : L1; - OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = - SI == SE ? Components : Components1; - auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); - OverlappedElements.getSecond().push_back(SubData); - } - } - } - // Sort the overlapped elements for each item. - llvm::SmallVector<const FieldDecl *, 4> Layout; - if (!OverlappedData.empty()) { - if (const auto *CRD = - VD->getType().getCanonicalType()->getAsCXXRecordDecl()) - getPlainLayout(CRD, Layout, /*AsBase=*/false); - else { - const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl(); - Layout.append(RD->field_begin(), RD->field_end()); - } - } - for (auto &Pair : OverlappedData) { - llvm::sort( - Pair.getSecond(), - [&Layout]( - OMPClauseMappableExprCommon::MappableExprComponentListRef First, - OMPClauseMappableExprCommon::MappableExprComponentListRef - Second) { - auto CI = First.rbegin(); - auto CE = First.rend(); - auto SI = Second.rbegin(); - auto SE = Second.rend(); - for (; CI != CE && SI != SE; ++CI, ++SI) { - if (CI->getAssociatedExpression()->getStmtClass() != - SI->getAssociatedExpression()->getStmtClass()) - break; - // Are we dealing with different variables/fields? - if (CI->getAssociatedDeclaration() != - SI->getAssociatedDeclaration()) - break; - } - - // Lists contain the same elements. - if (CI == CE && SI == SE) - return false; - - // List with less elements is less than list with more elements. - if (CI == CE || SI == SE) - return CI == CE; - - const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); - const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); - if (FD1->getParent() == FD2->getParent()) - return FD1->getFieldIndex() < FD2->getFieldIndex(); - const auto It = - llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { - return FD == FD1 || FD == FD2; - }); - return *It == FD1; - }); - } - - // Associated with a capture, because the mapping flags depend on it. - // Go through all of the elements with the overlapped elements. - for (const auto &Pair : OverlappedData) { - const MapData &L = *Pair.getFirst(); - OMPClauseMappableExprCommon::MappableExprComponentListRef Components; - OpenMPMapClauseKind MapType; - ArrayRef<OpenMPMapModifierKind> MapModifiers; - bool IsImplicit; - std::tie(Components, MapType, MapModifiers, IsImplicit) = L; - ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> - OverlappedComponents = Pair.getSecond(); - bool IsFirstComponentList = true; - generateInfoForComponentList(MapType, MapModifiers, Components, - BasePointers, Pointers, Sizes, Types, - PartialStruct, IsFirstComponentList, - IsImplicit, OverlappedComponents); - } - // Go through other elements without overlapped elements. - bool IsFirstComponentList = OverlappedData.empty(); - for (const MapData &L : DeclComponentLists) { - OMPClauseMappableExprCommon::MappableExprComponentListRef Components; - OpenMPMapClauseKind MapType; - ArrayRef<OpenMPMapModifierKind> MapModifiers; - bool IsImplicit; - std::tie(Components, MapType, MapModifiers, IsImplicit) = L; - auto It = OverlappedData.find(&L); - if (It == OverlappedData.end()) - generateInfoForComponentList(MapType, MapModifiers, Components, - BasePointers, Pointers, Sizes, Types, - PartialStruct, IsFirstComponentList, - IsImplicit); - IsFirstComponentList = false; - } - } - - /// Generate the base pointers, section pointers, sizes and map types - /// associated with the declare target link variables. - void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers, - MapValuesArrayTy &Pointers, - MapValuesArrayTy &Sizes, - MapFlagsArrayTy &Types) const { - // Map other list items in the map clause which are not captured variables - // but "declare target link" global variables., - for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>()) { - for (const auto &L : C->component_lists()) { - if (!L.first) - continue; - const auto *VD = dyn_cast<VarDecl>(L.first); - if (!VD) - continue; - llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); - if (!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) - continue; - StructRangeInfoTy PartialStruct; - generateInfoForComponentList( - C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers, - Pointers, Sizes, Types, PartialStruct, - /*IsFirstComponentList=*/true, C->isImplicit()); - assert(!PartialStruct.Base.isValid() && - "No partial structs for declare target link expected."); - } - } - } - - /// Generate the default map information for a given capture \a CI, - /// record field declaration \a RI and captured value \a CV. - void generateDefaultMapInfo(const CapturedStmt::Capture &CI, - const FieldDecl &RI, llvm::Value *CV, - MapBaseValuesArrayTy &CurBasePointers, - MapValuesArrayTy &CurPointers, - MapValuesArrayTy &CurSizes, - MapFlagsArrayTy &CurMapTypes) const { - // Do the default mapping. - if (CI.capturesThis()) { - CurBasePointers.push_back(CV); - CurPointers.push_back(CV); - const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); - CurSizes.push_back(CGF.getTypeSize(PtrTy->getPointeeType())); - // Default map type. - CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM); - } else if (CI.capturesVariableByCopy()) { - CurBasePointers.push_back(CV); - CurPointers.push_back(CV); - if (!RI.getType()->isAnyPointerType()) { - // We have to signal to the runtime captures passed by value that are - // not pointers. - CurMapTypes.push_back(OMP_MAP_LITERAL); - CurSizes.push_back(CGF.getTypeSize(RI.getType())); - } else { - // Pointers are implicitly mapped with a zero size and no flags - // (other than first map that is added for all implicit maps). - CurMapTypes.push_back(OMP_MAP_NONE); - CurSizes.push_back(llvm::Constant::getNullValue(CGF.SizeTy)); - } - } else { - assert(CI.capturesVariable() && "Expected captured reference."); - CurBasePointers.push_back(CV); - CurPointers.push_back(CV); - - const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); - QualType ElementType = PtrTy->getPointeeType(); - CurSizes.push_back(CGF.getTypeSize(ElementType)); - // The default map type for a scalar/complex type is 'to' because by - // default the value doesn't have to be retrieved. For an aggregate - // type, the default is 'tofrom'. - CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI)); - } - // Every default map produces a single argument which is a target parameter. - CurMapTypes.back() |= OMP_MAP_TARGET_PARAM; - - // Add flag stating this is an implicit map. - CurMapTypes.back() |= OMP_MAP_IMPLICIT; - } -}; - -enum OpenMPOffloadingReservedDeviceIDs { - /// Device ID if the device was not defined, runtime should get it - /// from environment variables in the spec. - OMP_DEVICEID_UNDEF = -1, -}; -} // anonymous namespace - -/// Emit the arrays used to pass the captures and map information to the -/// offloading runtime library. If there is no map or capture information, -/// return nullptr by reference. -static void -emitOffloadingArrays(CodeGenFunction &CGF, - MappableExprsHandler::MapBaseValuesArrayTy &BasePointers, - MappableExprsHandler::MapValuesArrayTy &Pointers, - MappableExprsHandler::MapValuesArrayTy &Sizes, - MappableExprsHandler::MapFlagsArrayTy &MapTypes, - CGOpenMPRuntime::TargetDataInfo &Info) { - CodeGenModule &CGM = CGF.CGM; - ASTContext &Ctx = CGF.getContext(); - - // Reset the array information. - Info.clearArrayInfo(); - Info.NumberOfPtrs = BasePointers.size(); - - if (Info.NumberOfPtrs) { - // Detect if we have any capture size requiring runtime evaluation of the - // size so that a constant array could be eventually used. - bool hasRuntimeEvaluationCaptureSize = false; - for (llvm::Value *S : Sizes) - if (!isa<llvm::Constant>(S)) { - hasRuntimeEvaluationCaptureSize = true; - break; - } - - llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); - QualType PointerArrayType = - Ctx.getConstantArrayType(Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal, - /*IndexTypeQuals=*/0); - - Info.BasePointersArray = - CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); - Info.PointersArray = - CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); - - // If we don't have any VLA types or other types that require runtime - // evaluation, we can use a constant array for the map sizes, otherwise we - // need to fill up the arrays as we do for the pointers. - if (hasRuntimeEvaluationCaptureSize) { - QualType SizeArrayType = Ctx.getConstantArrayType( - Ctx.getSizeType(), PointerNumAP, ArrayType::Normal, - /*IndexTypeQuals=*/0); - Info.SizesArray = - CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); - } else { - // We expect all the sizes to be constant, so we collect them to create - // a constant array. - SmallVector<llvm::Constant *, 16> ConstSizes; - for (llvm::Value *S : Sizes) - ConstSizes.push_back(cast<llvm::Constant>(S)); - - auto *SizesArrayInit = llvm::ConstantArray::get( - llvm::ArrayType::get(CGM.SizeTy, ConstSizes.size()), ConstSizes); - std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); - auto *SizesArrayGbl = new llvm::GlobalVariable( - CGM.getModule(), SizesArrayInit->getType(), - /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, - SizesArrayInit, Name); - SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - Info.SizesArray = SizesArrayGbl; - } - - // The map types are always constant so we don't need to generate code to - // fill arrays. Instead, we create an array constant. - SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0); - llvm::copy(MapTypes, Mapping.begin()); - llvm::Constant *MapTypesArrayInit = - llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); - std::string MaptypesName = - CGM.getOpenMPRuntime().getName({"offload_maptypes"}); - auto *MapTypesArrayGbl = new llvm::GlobalVariable( - CGM.getModule(), MapTypesArrayInit->getType(), - /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, - MapTypesArrayInit, MaptypesName); - MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - Info.MapTypesArray = MapTypesArrayGbl; - - for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { - llvm::Value *BPVal = *BasePointers[I]; - llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( - llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), - Info.BasePointersArray, 0, I); - BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); - Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); - CGF.Builder.CreateStore(BPVal, BPAddr); - - if (Info.requiresDevicePointerInfo()) - if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl()) - Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); - - llvm::Value *PVal = Pointers[I]; - llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( - llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), - Info.PointersArray, 0, I); - P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); - Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); - CGF.Builder.CreateStore(PVal, PAddr); - - if (hasRuntimeEvaluationCaptureSize) { - llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( - llvm::ArrayType::get(CGM.SizeTy, Info.NumberOfPtrs), - Info.SizesArray, - /*Idx0=*/0, - /*Idx1=*/I); - Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType())); - CGF.Builder.CreateStore( - CGF.Builder.CreateIntCast(Sizes[I], CGM.SizeTy, /*isSigned=*/true), - SAddr); - } - } - } -} -/// Emit the arguments to be passed to the runtime library based on the -/// arrays of pointers, sizes and map types. -static void emitOffloadingArraysArgument( - CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, - llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, - llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) { - CodeGenModule &CGM = CGF.CGM; - if (Info.NumberOfPtrs) { - BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( - llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), - Info.BasePointersArray, - /*Idx0=*/0, /*Idx1=*/0); - PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( - llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), - Info.PointersArray, - /*Idx0=*/0, - /*Idx1=*/0); - SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( - llvm::ArrayType::get(CGM.SizeTy, Info.NumberOfPtrs), Info.SizesArray, - /*Idx0=*/0, /*Idx1=*/0); - MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( - llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), - Info.MapTypesArray, - /*Idx0=*/0, - /*Idx1=*/0); - } else { - BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); - PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); - SizesArrayArg = llvm::ConstantPointerNull::get(CGM.SizeTy->getPointerTo()); - MapTypesArrayArg = - llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); - } -} - -/// Checks if the expression is constant or does not have non-trivial function -/// calls. -static bool isTrivial(ASTContext &Ctx, const Expr * E) { - // We can skip constant expressions. - // We can skip expressions with trivial calls or simple expressions. - return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || - !E->hasNonTrivialCall(Ctx)) && - !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); -} - -/// Checks if the \p Body is the \a CompoundStmt and returns its child statement -/// iff there is only one that is not evaluatable at the compile time. -static const Stmt *getSingleCompoundChild(ASTContext &Ctx, const Stmt *Body) { - if (const auto *C = dyn_cast<CompoundStmt>(Body)) { - const Stmt *Child = nullptr; - for (const Stmt *S : C->body()) { - if (const auto *E = dyn_cast<Expr>(S)) { - if (isTrivial(Ctx, E)) - continue; - } - // Some of the statements can be ignored. - if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || - isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) - continue; - // Analyze declarations. - if (const auto *DS = dyn_cast<DeclStmt>(S)) { - if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) { - if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || - isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || - isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || - isa<UsingDirectiveDecl>(D) || - isa<OMPDeclareReductionDecl>(D) || - isa<OMPThreadPrivateDecl>(D)) - return true; - const auto *VD = dyn_cast<VarDecl>(D); - if (!VD) - return false; - return VD->isConstexpr() || - ((VD->getType().isTrivialType(Ctx) || - VD->getType()->isReferenceType()) && - (!VD->hasInit() || isTrivial(Ctx, VD->getInit()))); - })) - continue; - } - // Found multiple children - cannot get the one child only. - if (Child) - return Body; - Child = S; - } - if (Child) - return Child; - } - return Body; -} - -/// Check for inner distribute directive. -static const OMPExecutableDirective * -getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { - const auto *CS = D.getInnermostCapturedStmt(); - const auto *Body = - CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); - const Stmt *ChildStmt = getSingleCompoundChild(Ctx, Body); - - if (const auto *NestedDir = dyn_cast<OMPExecutableDirective>(ChildStmt)) { - OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); - switch (D.getDirectiveKind()) { - case OMPD_target: - if (isOpenMPDistributeDirective(DKind)) - return NestedDir; - if (DKind == OMPD_teams) { - Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( - /*IgnoreCaptured=*/true); - if (!Body) - return nullptr; - ChildStmt = getSingleCompoundChild(Ctx, Body); - if (const auto *NND = dyn_cast<OMPExecutableDirective>(ChildStmt)) { - DKind = NND->getDirectiveKind(); - if (isOpenMPDistributeDirective(DKind)) - return NND; - } - } - return nullptr; - case OMPD_target_teams: - if (isOpenMPDistributeDirective(DKind)) - return NestedDir; - return nullptr; - case OMPD_target_parallel: - case OMPD_target_simd: - case OMPD_target_parallel_for: - case OMPD_target_parallel_for_simd: - return nullptr; - case OMPD_target_teams_distribute: - case OMPD_target_teams_distribute_simd: - case OMPD_target_teams_distribute_parallel_for: - case OMPD_target_teams_distribute_parallel_for_simd: - case OMPD_parallel: - case OMPD_for: - case OMPD_parallel_for: - case OMPD_parallel_sections: - case OMPD_for_simd: - case OMPD_parallel_for_simd: - case OMPD_cancel: - case OMPD_cancellation_point: - case OMPD_ordered: - case OMPD_threadprivate: - case OMPD_task: - case OMPD_simd: - case OMPD_sections: - case OMPD_section: - case OMPD_single: - case OMPD_master: - case OMPD_critical: - case OMPD_taskyield: - case OMPD_barrier: - case OMPD_taskwait: - case OMPD_taskgroup: - case OMPD_atomic: - case OMPD_flush: - case OMPD_teams: - case OMPD_target_data: - case OMPD_target_exit_data: - case OMPD_target_enter_data: - case OMPD_distribute: - case OMPD_distribute_simd: - case OMPD_distribute_parallel_for: - case OMPD_distribute_parallel_for_simd: - case OMPD_teams_distribute: - case OMPD_teams_distribute_simd: - case OMPD_teams_distribute_parallel_for: - case OMPD_teams_distribute_parallel_for_simd: - case OMPD_target_update: - case OMPD_declare_simd: - case OMPD_declare_target: - case OMPD_end_declare_target: - case OMPD_declare_reduction: - case OMPD_taskloop: - case OMPD_taskloop_simd: - case OMPD_requires: - case OMPD_unknown: - llvm_unreachable("Unexpected directive."); - } - } - - return nullptr; -} - -void CGOpenMPRuntime::emitTargetNumIterationsCall( - CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *Device, - const llvm::function_ref<llvm::Value *( - CodeGenFunction &CGF, const OMPLoopDirective &D)> &SizeEmitter) { - OpenMPDirectiveKind Kind = D.getDirectiveKind(); - const OMPExecutableDirective *TD = &D; - // Get nested teams distribute kind directive, if any. - if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) - TD = getNestedDistributeDirective(CGM.getContext(), D); - if (!TD) - return; - const auto *LD = cast<OMPLoopDirective>(TD); - auto &&CodeGen = [LD, &Device, &SizeEmitter, this](CodeGenFunction &CGF, - PrePostActionTy &) { - llvm::Value *NumIterations = SizeEmitter(CGF, *LD); - - // Emit device ID if any. - llvm::Value *DeviceID; - if (Device) - DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), - CGF.Int64Ty, /*isSigned=*/true); - else - DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); - - llvm::Value *Args[] = {DeviceID, NumIterations}; - CGF.EmitRuntimeCall( - createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args); - }; - emitInlinedDirective(CGF, OMPD_unknown, CodeGen); -} - -void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF, - const OMPExecutableDirective &D, - llvm::Value *OutlinedFn, - llvm::Value *OutlinedFnID, - const Expr *IfCond, const Expr *Device) { - if (!CGF.HaveInsertPoint()) - return; - - assert(OutlinedFn && "Invalid outlined function!"); - - const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>(); - llvm::SmallVector<llvm::Value *, 16> CapturedVars; - const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); - auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, - PrePostActionTy &) { - CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); - }; - emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); - - CodeGenFunction::OMPTargetDataInfo InputInfo; - llvm::Value *MapTypesArray = nullptr; - // Fill up the pointer arrays and transfer execution to the device. - auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, - &MapTypesArray, &CS, RequiresOuterTask, - &CapturedVars](CodeGenFunction &CGF, PrePostActionTy &) { - // On top of the arrays that were filled up, the target offloading call - // takes as arguments the device id as well as the host pointer. The host - // pointer is used by the runtime library to identify the current target - // region, so it only has to be unique and not necessarily point to - // anything. It could be the pointer to the outlined function that - // implements the target region, but we aren't using that so that the - // compiler doesn't need to keep that, and could therefore inline the host - // function if proven worthwhile during optimization. - - // From this point on, we need to have an ID of the target region defined. - assert(OutlinedFnID && "Invalid outlined function ID!"); - - // Emit device ID if any. - llvm::Value *DeviceID; - if (Device) { - DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), - CGF.Int64Ty, /*isSigned=*/true); - } else { - DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); - } - - // Emit the number of elements in the offloading arrays. - llvm::Value *PointerNum = - CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); - - // Return value of the runtime offloading call. - llvm::Value *Return; - - llvm::Value *NumTeams = emitNumTeamsForTargetDirective(*this, CGF, D); - llvm::Value *NumThreads = emitNumThreadsForTargetDirective(*this, CGF, D); - - bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); - // The target region is an outlined function launched by the runtime - // via calls __tgt_target() or __tgt_target_teams(). - // - // __tgt_target() launches a target region with one team and one thread, - // executing a serial region. This master thread may in turn launch - // more threads within its team upon encountering a parallel region, - // however, no additional teams can be launched on the device. - // - // __tgt_target_teams() launches a target region with one or more teams, - // each with one or more threads. This call is required for target - // constructs such as: - // 'target teams' - // 'target' / 'teams' - // 'target teams distribute parallel for' - // 'target parallel' - // and so on. - // - // Note that on the host and CPU targets, the runtime implementation of - // these calls simply call the outlined function without forking threads. - // The outlined functions themselves have runtime calls to - // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by - // the compiler in emitTeamsCall() and emitParallelCall(). - // - // In contrast, on the NVPTX target, the implementation of - // __tgt_target_teams() launches a GPU kernel with the requested number - // of teams and threads so no additional calls to the runtime are required. - if (NumTeams) { - // If we have NumTeams defined this means that we have an enclosed teams - // region. Therefore we also expect to have NumThreads defined. These two - // values should be defined in the presence of a teams directive, - // regardless of having any clauses associated. If the user is using teams - // but no clauses, these two values will be the default that should be - // passed to the runtime library - a 32-bit integer with the value zero. - assert(NumThreads && "Thread limit expression should be available along " - "with number of teams."); - llvm::Value *OffloadingArgs[] = {DeviceID, - OutlinedFnID, - PointerNum, - InputInfo.BasePointersArray.getPointer(), - InputInfo.PointersArray.getPointer(), - InputInfo.SizesArray.getPointer(), - MapTypesArray, - NumTeams, - NumThreads}; - Return = CGF.EmitRuntimeCall( - createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait - : OMPRTL__tgt_target_teams), - OffloadingArgs); - } else { - llvm::Value *OffloadingArgs[] = {DeviceID, - OutlinedFnID, - PointerNum, - InputInfo.BasePointersArray.getPointer(), - InputInfo.PointersArray.getPointer(), - InputInfo.SizesArray.getPointer(), - MapTypesArray}; - Return = CGF.EmitRuntimeCall( - createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait - : OMPRTL__tgt_target), - OffloadingArgs); - } - - // Check the error code and execute the host version if required. - llvm::BasicBlock *OffloadFailedBlock = - CGF.createBasicBlock("omp_offload.failed"); - llvm::BasicBlock *OffloadContBlock = - CGF.createBasicBlock("omp_offload.cont"); - llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); - CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); - - CGF.EmitBlock(OffloadFailedBlock); - if (RequiresOuterTask) { - CapturedVars.clear(); - CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); - } - emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); - CGF.EmitBranch(OffloadContBlock); - - CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); - }; - - // Notify that the host version must be executed. - auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, - RequiresOuterTask](CodeGenFunction &CGF, - PrePostActionTy &) { - if (RequiresOuterTask) { - CapturedVars.clear(); - CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); - } - emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); - }; - - auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, - &CapturedVars, RequiresOuterTask, - &CS](CodeGenFunction &CGF, PrePostActionTy &) { - // Fill up the arrays with all the captured variables. - MappableExprsHandler::MapBaseValuesArrayTy BasePointers; - MappableExprsHandler::MapValuesArrayTy Pointers; - MappableExprsHandler::MapValuesArrayTy Sizes; - MappableExprsHandler::MapFlagsArrayTy MapTypes; - - // Get mappable expression information. - MappableExprsHandler MEHandler(D, CGF); - llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; - - auto RI = CS.getCapturedRecordDecl()->field_begin(); - auto CV = CapturedVars.begin(); - for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), - CE = CS.capture_end(); - CI != CE; ++CI, ++RI, ++CV) { - MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; - MappableExprsHandler::MapValuesArrayTy CurPointers; - MappableExprsHandler::MapValuesArrayTy CurSizes; - MappableExprsHandler::MapFlagsArrayTy CurMapTypes; - MappableExprsHandler::StructRangeInfoTy PartialStruct; - - // VLA sizes are passed to the outlined region by copy and do not have map - // information associated. - if (CI->capturesVariableArrayType()) { - CurBasePointers.push_back(*CV); - CurPointers.push_back(*CV); - CurSizes.push_back(CGF.getTypeSize(RI->getType())); - // Copy to the device as an argument. No need to retrieve it. - CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL | - MappableExprsHandler::OMP_MAP_TARGET_PARAM); - } else { - // If we have any information in the map clause, we use it, otherwise we - // just do a default mapping. - MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers, - CurSizes, CurMapTypes, PartialStruct); - if (CurBasePointers.empty()) - MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers, - CurPointers, CurSizes, CurMapTypes); - // Generate correct mapping for variables captured by reference in - // lambdas. - if (CI->capturesVariable()) - MEHandler.generateInfoForLambdaCaptures( - CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes, - CurMapTypes, LambdaPointers); - } - // We expect to have at least an element of information for this capture. - assert(!CurBasePointers.empty() && - "Non-existing map pointer for capture!"); - assert(CurBasePointers.size() == CurPointers.size() && - CurBasePointers.size() == CurSizes.size() && - CurBasePointers.size() == CurMapTypes.size() && - "Inconsistent map information sizes!"); - - // If there is an entry in PartialStruct it means we have a struct with - // individual members mapped. Emit an extra combined entry. - if (PartialStruct.Base.isValid()) - MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes, - CurMapTypes, PartialStruct); - - // We need to append the results of this capture to what we already have. - BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); - Pointers.append(CurPointers.begin(), CurPointers.end()); - Sizes.append(CurSizes.begin(), CurSizes.end()); - MapTypes.append(CurMapTypes.begin(), CurMapTypes.end()); - } - // Adjust MEMBER_OF flags for the lambdas captures. - MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers, - Pointers, MapTypes); - // Map other list items in the map clause which are not captured variables - // but "declare target link" global variables. - MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes, - MapTypes); - - TargetDataInfo Info; - // Fill up the arrays and create the arguments. - emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); - emitOffloadingArraysArgument(CGF, Info.BasePointersArray, - Info.PointersArray, Info.SizesArray, - Info.MapTypesArray, Info); - InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; - InputInfo.BasePointersArray = - Address(Info.BasePointersArray, CGM.getPointerAlign()); - InputInfo.PointersArray = - Address(Info.PointersArray, CGM.getPointerAlign()); - InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); - MapTypesArray = Info.MapTypesArray; - if (RequiresOuterTask) - CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); - else - emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); - }; - - auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( - CodeGenFunction &CGF, PrePostActionTy &) { - if (RequiresOuterTask) { - CodeGenFunction::OMPTargetDataInfo InputInfo; - CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); - } else { - emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); - } - }; - - // If we have a target function ID it means that we need to support - // offloading, otherwise, just execute on the host. We need to execute on host - // regardless of the conditional in the if clause if, e.g., the user do not - // specify target triples. - if (OutlinedFnID) { - if (IfCond) { - emitOMPIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); - } else { - RegionCodeGenTy ThenRCG(TargetThenGen); - ThenRCG(CGF); - } - } else { - RegionCodeGenTy ElseRCG(TargetElseGen); - ElseRCG(CGF); - } -} - -void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, - StringRef ParentName) { - if (!S) - return; - - // Codegen OMP target directives that offload compute to the device. - bool RequiresDeviceCodegen = - isa<OMPExecutableDirective>(S) && - isOpenMPTargetExecutionDirective( - cast<OMPExecutableDirective>(S)->getDirectiveKind()); - - if (RequiresDeviceCodegen) { - const auto &E = *cast<OMPExecutableDirective>(S); - unsigned DeviceID; - unsigned FileID; - unsigned Line; - getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, - FileID, Line); - - // Is this a target region that should not be emitted as an entry point? If - // so just signal we are done with this target region. - if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, - ParentName, Line)) - return; - - switch (E.getDirectiveKind()) { - case OMPD_target: - CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, - cast<OMPTargetDirective>(E)); - break; - case OMPD_target_parallel: - CodeGenFunction::EmitOMPTargetParallelDeviceFunction( - CGM, ParentName, cast<OMPTargetParallelDirective>(E)); - break; - case OMPD_target_teams: - CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( - CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); - break; - case OMPD_target_teams_distribute: - CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( - CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); - break; - case OMPD_target_teams_distribute_simd: - CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( - CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); - break; - case OMPD_target_parallel_for: - CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( - CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); - break; - case OMPD_target_parallel_for_simd: - CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( - CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); - break; - case OMPD_target_simd: - CodeGenFunction::EmitOMPTargetSimdDeviceFunction( - CGM, ParentName, cast<OMPTargetSimdDirective>(E)); - break; - case OMPD_target_teams_distribute_parallel_for: - CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( - CGM, ParentName, - cast<OMPTargetTeamsDistributeParallelForDirective>(E)); - break; - case OMPD_target_teams_distribute_parallel_for_simd: - CodeGenFunction:: - EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( - CGM, ParentName, - cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); - break; - case OMPD_parallel: - case OMPD_for: - case OMPD_parallel_for: - case OMPD_parallel_sections: - case OMPD_for_simd: - case OMPD_parallel_for_simd: - case OMPD_cancel: - case OMPD_cancellation_point: - case OMPD_ordered: - case OMPD_threadprivate: - case OMPD_task: - case OMPD_simd: - case OMPD_sections: - case OMPD_section: - case OMPD_single: - case OMPD_master: - case OMPD_critical: - case OMPD_taskyield: - case OMPD_barrier: - case OMPD_taskwait: - case OMPD_taskgroup: - case OMPD_atomic: - case OMPD_flush: - case OMPD_teams: - case OMPD_target_data: - case OMPD_target_exit_data: - case OMPD_target_enter_data: - case OMPD_distribute: - case OMPD_distribute_simd: - case OMPD_distribute_parallel_for: - case OMPD_distribute_parallel_for_simd: - case OMPD_teams_distribute: - case OMPD_teams_distribute_simd: - case OMPD_teams_distribute_parallel_for: - case OMPD_teams_distribute_parallel_for_simd: - case OMPD_target_update: - case OMPD_declare_simd: - case OMPD_declare_target: - case OMPD_end_declare_target: - case OMPD_declare_reduction: - case OMPD_taskloop: - case OMPD_taskloop_simd: - case OMPD_requires: - case OMPD_unknown: - llvm_unreachable("Unknown target directive for OpenMP device codegen."); - } - return; - } - - if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { - if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) - return; - - scanForTargetRegionsFunctions( - E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName); - return; - } - - // If this is a lambda function, look into its body. - if (const auto *L = dyn_cast<LambdaExpr>(S)) - S = L->getBody(); - - // Keep looking for target regions recursively. - for (const Stmt *II : S->children()) - scanForTargetRegionsFunctions(II, ParentName); -} - -bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { - // If emitting code for the host, we do not process FD here. Instead we do - // the normal code generation. - if (!CGM.getLangOpts().OpenMPIsDevice) - return false; - - const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); - StringRef Name = CGM.getMangledName(GD); - // Try to detect target regions in the function. - if (const auto *FD = dyn_cast<FunctionDecl>(VD)) - scanForTargetRegionsFunctions(FD->getBody(), Name); - - // Do not to emit function if it is not marked as declare target. - return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && - AlreadyEmittedTargetFunctions.count(Name) == 0; -} - -bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { - if (!CGM.getLangOpts().OpenMPIsDevice) - return false; - - // Check if there are Ctors/Dtors in this declaration and look for target - // regions in it. We use the complete variant to produce the kernel name - // mangling. - QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); - if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { - for (const CXXConstructorDecl *Ctor : RD->ctors()) { - StringRef ParentName = - CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); - scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); - } - if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { - StringRef ParentName = - CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); - scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); - } - } - - // Do not to emit variable if it is not marked as declare target. - llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( - cast<VarDecl>(GD.getDecl())); - if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link) { - DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); - return true; - } - return false; -} - -void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, - llvm::Constant *Addr) { - llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); - if (!Res) { - if (CGM.getLangOpts().OpenMPIsDevice) { - // Register non-target variables being emitted in device code (debug info - // may cause this). - StringRef VarName = CGM.getMangledName(VD); - EmittedNonTargetVariables.try_emplace(VarName, Addr); - } - return; - } - // Register declare target variables. - OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; - StringRef VarName; - CharUnits VarSize; - llvm::GlobalValue::LinkageTypes Linkage; - switch (*Res) { - case OMPDeclareTargetDeclAttr::MT_To: - Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; - VarName = CGM.getMangledName(VD); - if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { - VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); - assert(!VarSize.isZero() && "Expected non-zero size of the variable"); - } else { - VarSize = CharUnits::Zero(); - } - Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); - // Temp solution to prevent optimizations of the internal variables. - if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { - std::string RefName = getName({VarName, "ref"}); - if (!CGM.GetGlobalValue(RefName)) { - llvm::Constant *AddrRef = - getOrCreateInternalVariable(Addr->getType(), RefName); - auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); - GVAddrRef->setConstant(/*Val=*/true); - GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); - GVAddrRef->setInitializer(Addr); - CGM.addCompilerUsedGlobal(GVAddrRef); - } - } - break; - case OMPDeclareTargetDeclAttr::MT_Link: - Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; - if (CGM.getLangOpts().OpenMPIsDevice) { - VarName = Addr->getName(); - Addr = nullptr; - } else { - VarName = getAddrOfDeclareTargetLink(VD).getName(); - Addr = cast<llvm::Constant>(getAddrOfDeclareTargetLink(VD).getPointer()); - } - VarSize = CGM.getPointerSize(); - Linkage = llvm::GlobalValue::WeakAnyLinkage; - break; - } - OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( - VarName, Addr, VarSize, Flags, Linkage); -} - -bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { - if (isa<FunctionDecl>(GD.getDecl()) || - isa<OMPDeclareReductionDecl>(GD.getDecl())) - return emitTargetFunctions(GD); - - return emitTargetGlobalVariable(GD); -} - -void CGOpenMPRuntime::emitDeferredTargetDecls() const { - for (const VarDecl *VD : DeferredGlobalVariables) { - llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); - if (!Res) - continue; - if (*Res == OMPDeclareTargetDeclAttr::MT_To) { - CGM.EmitGlobal(VD); - } else { - assert(*Res == OMPDeclareTargetDeclAttr::MT_Link && - "Expected to or link clauses."); - (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD); - } - } -} - -void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( - CodeGenFunction &CGF, const OMPExecutableDirective &D) const { - assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && - " Expected target-based directive."); -} - -CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( - CodeGenModule &CGM) - : CGM(CGM) { - if (CGM.getLangOpts().OpenMPIsDevice) { - SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; - CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; - } -} - -CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { - if (CGM.getLangOpts().OpenMPIsDevice) - CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; -} - -bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { - if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) - return true; - - StringRef Name = CGM.getMangledName(GD); - const auto *D = cast<FunctionDecl>(GD.getDecl()); - // Do not to emit function if it is marked as declare target as it was already - // emitted. - if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { - if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) { - if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name))) - return !F->isDeclaration(); - return false; - } - return true; - } - - return !AlreadyEmittedTargetFunctions.insert(Name).second; -} - -llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() { - // If we have offloading in the current module, we need to emit the entries - // now and register the offloading descriptor. - createOffloadEntriesAndInfoMetadata(); - - // Create and register the offloading binary descriptors. This is the main - // entity that captures all the information about offloading in the current - // compilation unit. - return createOffloadingBinaryDescriptorRegistration(); -} - -void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, - const OMPExecutableDirective &D, - SourceLocation Loc, - llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> CapturedVars) { - if (!CGF.HaveInsertPoint()) - return; - - llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); - CodeGenFunction::RunCleanupsScope Scope(CGF); - - // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); - llvm::Value *Args[] = { - RTLoc, - CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars - CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; - llvm::SmallVector<llvm::Value *, 16> RealArgs; - RealArgs.append(std::begin(Args), std::end(Args)); - RealArgs.append(CapturedVars.begin(), CapturedVars.end()); - - llvm::Value *RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams); - CGF.EmitRuntimeCall(RTLFn, RealArgs); -} - -void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, - const Expr *NumTeams, - const Expr *ThreadLimit, - SourceLocation Loc) { - if (!CGF.HaveInsertPoint()) - return; - - llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); - - llvm::Value *NumTeamsVal = - NumTeams - ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), - CGF.CGM.Int32Ty, /* isSigned = */ true) - : CGF.Builder.getInt32(0); - - llvm::Value *ThreadLimitVal = - ThreadLimit - ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), - CGF.CGM.Int32Ty, /* isSigned = */ true) - : CGF.Builder.getInt32(0); - - // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) - llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, - ThreadLimitVal}; - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams), - PushNumTeamsArgs); -} - -void CGOpenMPRuntime::emitTargetDataCalls( - CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, - const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { - if (!CGF.HaveInsertPoint()) - return; - - // Action used to replace the default codegen action and turn privatization - // off. - PrePostActionTy NoPrivAction; - - // Generate the code for the opening of the data environment. Capture all the - // arguments of the runtime call by reference because they are used in the - // closing of the region. - auto &&BeginThenGen = [this, &D, Device, &Info, - &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { - // Fill up the arrays with all the mapped variables. - MappableExprsHandler::MapBaseValuesArrayTy BasePointers; - MappableExprsHandler::MapValuesArrayTy Pointers; - MappableExprsHandler::MapValuesArrayTy Sizes; - MappableExprsHandler::MapFlagsArrayTy MapTypes; - - // Get map clause information. - MappableExprsHandler MCHandler(D, CGF); - MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); - - // Fill up the arrays and create the arguments. - emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); - - llvm::Value *BasePointersArrayArg = nullptr; - llvm::Value *PointersArrayArg = nullptr; - llvm::Value *SizesArrayArg = nullptr; - llvm::Value *MapTypesArrayArg = nullptr; - emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, - SizesArrayArg, MapTypesArrayArg, Info); - - // Emit device ID if any. - llvm::Value *DeviceID = nullptr; - if (Device) { - DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), - CGF.Int64Ty, /*isSigned=*/true); - } else { - DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); - } - - // Emit the number of elements in the offloading arrays. - llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); - - llvm::Value *OffloadingArgs[] = { - DeviceID, PointerNum, BasePointersArrayArg, - PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin), - OffloadingArgs); - - // If device pointer privatization is required, emit the body of the region - // here. It will have to be duplicated: with and without privatization. - if (!Info.CaptureDeviceAddrMap.empty()) - CodeGen(CGF); - }; - - // Generate code for the closing of the data region. - auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF, - PrePostActionTy &) { - assert(Info.isValid() && "Invalid data environment closing arguments."); - - llvm::Value *BasePointersArrayArg = nullptr; - llvm::Value *PointersArrayArg = nullptr; - llvm::Value *SizesArrayArg = nullptr; - llvm::Value *MapTypesArrayArg = nullptr; - emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, - SizesArrayArg, MapTypesArrayArg, Info); - - // Emit device ID if any. - llvm::Value *DeviceID = nullptr; - if (Device) { - DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), - CGF.Int64Ty, /*isSigned=*/true); - } else { - DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); - } - - // Emit the number of elements in the offloading arrays. - llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); - - llvm::Value *OffloadingArgs[] = { - DeviceID, PointerNum, BasePointersArrayArg, - PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end), - OffloadingArgs); - }; - - // If we need device pointer privatization, we need to emit the body of the - // region with no privatization in the 'else' branch of the conditional. - // Otherwise, we don't have to do anything. - auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, - PrePostActionTy &) { - if (!Info.CaptureDeviceAddrMap.empty()) { - CodeGen.setAction(NoPrivAction); - CodeGen(CGF); - } - }; - - // We don't have to do anything to close the region if the if clause evaluates - // to false. - auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; - - if (IfCond) { - emitOMPIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); - } else { - RegionCodeGenTy RCG(BeginThenGen); - RCG(CGF); - } - - // If we don't require privatization of device pointers, we emit the body in - // between the runtime calls. This avoids duplicating the body code. - if (Info.CaptureDeviceAddrMap.empty()) { - CodeGen.setAction(NoPrivAction); - CodeGen(CGF); - } - - if (IfCond) { - emitOMPIfClause(CGF, IfCond, EndThenGen, EndElseGen); - } else { - RegionCodeGenTy RCG(EndThenGen); - RCG(CGF); - } -} - -void CGOpenMPRuntime::emitTargetDataStandAloneCall( - CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, - const Expr *Device) { - if (!CGF.HaveInsertPoint()) - return; - - assert((isa<OMPTargetEnterDataDirective>(D) || - isa<OMPTargetExitDataDirective>(D) || - isa<OMPTargetUpdateDirective>(D)) && - "Expecting either target enter, exit data, or update directives."); - - CodeGenFunction::OMPTargetDataInfo InputInfo; - llvm::Value *MapTypesArray = nullptr; - // Generate the code for the opening of the data environment. - auto &&ThenGen = [this, &D, Device, &InputInfo, - &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) { - // Emit device ID if any. - llvm::Value *DeviceID = nullptr; - if (Device) { - DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), - CGF.Int64Ty, /*isSigned=*/true); - } else { - DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); - } - - // Emit the number of elements in the offloading arrays. - llvm::Constant *PointerNum = - CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); - - llvm::Value *OffloadingArgs[] = {DeviceID, - PointerNum, - InputInfo.BasePointersArray.getPointer(), - InputInfo.PointersArray.getPointer(), - InputInfo.SizesArray.getPointer(), - MapTypesArray}; - - // Select the right runtime function call for each expected standalone - // directive. - const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); - OpenMPRTLFunction RTLFn; - switch (D.getDirectiveKind()) { - case OMPD_target_enter_data: - RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait - : OMPRTL__tgt_target_data_begin; - break; - case OMPD_target_exit_data: - RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait - : OMPRTL__tgt_target_data_end; - break; - case OMPD_target_update: - RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait - : OMPRTL__tgt_target_data_update; - break; - case OMPD_parallel: - case OMPD_for: - case OMPD_parallel_for: - case OMPD_parallel_sections: - case OMPD_for_simd: - case OMPD_parallel_for_simd: - case OMPD_cancel: - case OMPD_cancellation_point: - case OMPD_ordered: - case OMPD_threadprivate: - case OMPD_task: - case OMPD_simd: - case OMPD_sections: - case OMPD_section: - case OMPD_single: - case OMPD_master: - case OMPD_critical: - case OMPD_taskyield: - case OMPD_barrier: - case OMPD_taskwait: - case OMPD_taskgroup: - case OMPD_atomic: - case OMPD_flush: - case OMPD_teams: - case OMPD_target_data: - case OMPD_distribute: - case OMPD_distribute_simd: - case OMPD_distribute_parallel_for: - case OMPD_distribute_parallel_for_simd: - case OMPD_teams_distribute: - case OMPD_teams_distribute_simd: - case OMPD_teams_distribute_parallel_for: - case OMPD_teams_distribute_parallel_for_simd: - case OMPD_declare_simd: - case OMPD_declare_target: - case OMPD_end_declare_target: - case OMPD_declare_reduction: - case OMPD_taskloop: - case OMPD_taskloop_simd: - case OMPD_target: - case OMPD_target_simd: - case OMPD_target_teams_distribute: - case OMPD_target_teams_distribute_simd: - case OMPD_target_teams_distribute_parallel_for: - case OMPD_target_teams_distribute_parallel_for_simd: - case OMPD_target_teams: - case OMPD_target_parallel: - case OMPD_target_parallel_for: - case OMPD_target_parallel_for_simd: - case OMPD_requires: - case OMPD_unknown: - llvm_unreachable("Unexpected standalone target data directive."); - break; - } - CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs); - }; - - auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray]( - CodeGenFunction &CGF, PrePostActionTy &) { - // Fill up the arrays with all the mapped variables. - MappableExprsHandler::MapBaseValuesArrayTy BasePointers; - MappableExprsHandler::MapValuesArrayTy Pointers; - MappableExprsHandler::MapValuesArrayTy Sizes; - MappableExprsHandler::MapFlagsArrayTy MapTypes; - - // Get map clause information. - MappableExprsHandler MEHandler(D, CGF); - MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); - - TargetDataInfo Info; - // Fill up the arrays and create the arguments. - emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); - emitOffloadingArraysArgument(CGF, Info.BasePointersArray, - Info.PointersArray, Info.SizesArray, - Info.MapTypesArray, Info); - InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; - InputInfo.BasePointersArray = - Address(Info.BasePointersArray, CGM.getPointerAlign()); - InputInfo.PointersArray = - Address(Info.PointersArray, CGM.getPointerAlign()); - InputInfo.SizesArray = - Address(Info.SizesArray, CGM.getPointerAlign()); - MapTypesArray = Info.MapTypesArray; - if (D.hasClausesOfKind<OMPDependClause>()) - CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); - else - emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); - }; - - if (IfCond) { - emitOMPIfClause(CGF, IfCond, TargetThenGen, - [](CodeGenFunction &CGF, PrePostActionTy &) {}); - } else { - RegionCodeGenTy ThenRCG(TargetThenGen); - ThenRCG(CGF); - } -} - -namespace { - /// Kind of parameter in a function with 'declare simd' directive. - enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; - /// Attribute set of the parameter. - struct ParamAttrTy { - ParamKindTy Kind = Vector; - llvm::APSInt StrideOrArg; - llvm::APSInt Alignment; - }; -} // namespace - -static unsigned evaluateCDTSize(const FunctionDecl *FD, - ArrayRef<ParamAttrTy> ParamAttrs) { - // Every vector variant of a SIMD-enabled function has a vector length (VLEN). - // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument - // of that clause. The VLEN value must be power of 2. - // In other case the notion of the function`s "characteristic data type" (CDT) - // is used to compute the vector length. - // CDT is defined in the following order: - // a) For non-void function, the CDT is the return type. - // b) If the function has any non-uniform, non-linear parameters, then the - // CDT is the type of the first such parameter. - // c) If the CDT determined by a) or b) above is struct, union, or class - // type which is pass-by-value (except for the type that maps to the - // built-in complex data type), the characteristic data type is int. - // d) If none of the above three cases is applicable, the CDT is int. - // The VLEN is then determined based on the CDT and the size of vector - // register of that ISA for which current vector version is generated. The - // VLEN is computed using the formula below: - // VLEN = sizeof(vector_register) / sizeof(CDT), - // where vector register size specified in section 3.2.1 Registers and the - // Stack Frame of original AMD64 ABI document. - QualType RetType = FD->getReturnType(); - if (RetType.isNull()) - return 0; - ASTContext &C = FD->getASTContext(); - QualType CDT; - if (!RetType.isNull() && !RetType->isVoidType()) { - CDT = RetType; - } else { - unsigned Offset = 0; - if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { - if (ParamAttrs[Offset].Kind == Vector) - CDT = C.getPointerType(C.getRecordType(MD->getParent())); - ++Offset; - } - if (CDT.isNull()) { - for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { - if (ParamAttrs[I + Offset].Kind == Vector) { - CDT = FD->getParamDecl(I)->getType(); - break; - } - } - } - } - if (CDT.isNull()) - CDT = C.IntTy; - CDT = CDT->getCanonicalTypeUnqualified(); - if (CDT->isRecordType() || CDT->isUnionType()) - CDT = C.IntTy; - return C.getTypeSize(CDT); -} - -static void -emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, - const llvm::APSInt &VLENVal, - ArrayRef<ParamAttrTy> ParamAttrs, - OMPDeclareSimdDeclAttr::BranchStateTy State) { - struct ISADataTy { - char ISA; - unsigned VecRegSize; - }; - ISADataTy ISAData[] = { - { - 'b', 128 - }, // SSE - { - 'c', 256 - }, // AVX - { - 'd', 256 - }, // AVX2 - { - 'e', 512 - }, // AVX512 - }; - llvm::SmallVector<char, 2> Masked; - switch (State) { - case OMPDeclareSimdDeclAttr::BS_Undefined: - Masked.push_back('N'); - Masked.push_back('M'); - break; - case OMPDeclareSimdDeclAttr::BS_Notinbranch: - Masked.push_back('N'); - break; - case OMPDeclareSimdDeclAttr::BS_Inbranch: - Masked.push_back('M'); - break; - } - for (char Mask : Masked) { - for (const ISADataTy &Data : ISAData) { - SmallString<256> Buffer; - llvm::raw_svector_ostream Out(Buffer); - Out << "_ZGV" << Data.ISA << Mask; - if (!VLENVal) { - Out << llvm::APSInt::getUnsigned(Data.VecRegSize / - evaluateCDTSize(FD, ParamAttrs)); - } else { - Out << VLENVal; - } - for (const ParamAttrTy &ParamAttr : ParamAttrs) { - switch (ParamAttr.Kind){ - case LinearWithVarStride: - Out << 's' << ParamAttr.StrideOrArg; - break; - case Linear: - Out << 'l'; - if (!!ParamAttr.StrideOrArg) - Out << ParamAttr.StrideOrArg; - break; - case Uniform: - Out << 'u'; - break; - case Vector: - Out << 'v'; - break; - } - if (!!ParamAttr.Alignment) - Out << 'a' << ParamAttr.Alignment; - } - Out << '_' << Fn->getName(); - Fn->addFnAttr(Out.str()); - } - } -} - -void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, - llvm::Function *Fn) { - ASTContext &C = CGM.getContext(); - FD = FD->getMostRecentDecl(); - // Map params to their positions in function decl. - llvm::DenseMap<const Decl *, unsigned> ParamPositions; - if (isa<CXXMethodDecl>(FD)) - ParamPositions.try_emplace(FD, 0); - unsigned ParamPos = ParamPositions.size(); - for (const ParmVarDecl *P : FD->parameters()) { - ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); - ++ParamPos; - } - while (FD) { - for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { - llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); - // Mark uniform parameters. - for (const Expr *E : Attr->uniforms()) { - E = E->IgnoreParenImpCasts(); - unsigned Pos; - if (isa<CXXThisExpr>(E)) { - Pos = ParamPositions[FD]; - } else { - const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) - ->getCanonicalDecl(); - Pos = ParamPositions[PVD]; - } - ParamAttrs[Pos].Kind = Uniform; - } - // Get alignment info. - auto NI = Attr->alignments_begin(); - for (const Expr *E : Attr->aligneds()) { - E = E->IgnoreParenImpCasts(); - unsigned Pos; - QualType ParmTy; - if (isa<CXXThisExpr>(E)) { - Pos = ParamPositions[FD]; - ParmTy = E->getType(); - } else { - const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) - ->getCanonicalDecl(); - Pos = ParamPositions[PVD]; - ParmTy = PVD->getType(); - } - ParamAttrs[Pos].Alignment = - (*NI) - ? (*NI)->EvaluateKnownConstInt(C) - : llvm::APSInt::getUnsigned( - C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) - .getQuantity()); - ++NI; - } - // Mark linear parameters. - auto SI = Attr->steps_begin(); - auto MI = Attr->modifiers_begin(); - for (const Expr *E : Attr->linears()) { - E = E->IgnoreParenImpCasts(); - unsigned Pos; - if (isa<CXXThisExpr>(E)) { - Pos = ParamPositions[FD]; - } else { - const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) - ->getCanonicalDecl(); - Pos = ParamPositions[PVD]; - } - ParamAttrTy &ParamAttr = ParamAttrs[Pos]; - ParamAttr.Kind = Linear; - if (*SI) { - Expr::EvalResult Result; - if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { - if (const auto *DRE = - cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { - if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { - ParamAttr.Kind = LinearWithVarStride; - ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( - ParamPositions[StridePVD->getCanonicalDecl()]); - } - } - } else { - ParamAttr.StrideOrArg = Result.Val.getInt(); - } - } - ++SI; - ++MI; - } - llvm::APSInt VLENVal; - if (const Expr *VLEN = Attr->getSimdlen()) - VLENVal = VLEN->EvaluateKnownConstInt(C); - OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); - if (CGM.getTriple().getArch() == llvm::Triple::x86 || - CGM.getTriple().getArch() == llvm::Triple::x86_64) - emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); - } - FD = FD->getPreviousDecl(); - } -} - -namespace { -/// Cleanup action for doacross support. -class DoacrossCleanupTy final : public EHScopeStack::Cleanup { -public: - static const int DoacrossFinArgs = 2; - -private: - llvm::Value *RTLFn; - llvm::Value *Args[DoacrossFinArgs]; - -public: - DoacrossCleanupTy(llvm::Value *RTLFn, ArrayRef<llvm::Value *> CallArgs) - : RTLFn(RTLFn) { - assert(CallArgs.size() == DoacrossFinArgs); - std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); - } - void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { - if (!CGF.HaveInsertPoint()) - return; - CGF.EmitRuntimeCall(RTLFn, Args); - } -}; -} // namespace - -void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, - const OMPLoopDirective &D, - ArrayRef<Expr *> NumIterations) { - if (!CGF.HaveInsertPoint()) - return; - - ASTContext &C = CGM.getContext(); - QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); - RecordDecl *RD; - if (KmpDimTy.isNull()) { - // Build struct kmp_dim { // loop bounds info casted to kmp_int64 - // kmp_int64 lo; // lower - // kmp_int64 up; // upper - // kmp_int64 st; // stride - // }; - RD = C.buildImplicitRecord("kmp_dim"); - RD->startDefinition(); - addFieldToRecordDecl(C, RD, Int64Ty); - addFieldToRecordDecl(C, RD, Int64Ty); - addFieldToRecordDecl(C, RD, Int64Ty); - RD->completeDefinition(); - KmpDimTy = C.getRecordType(RD); - } else { - RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); - } - llvm::APInt Size(/*numBits=*/32, NumIterations.size()); - QualType ArrayTy = - C.getConstantArrayType(KmpDimTy, Size, ArrayType::Normal, 0); - - Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); - CGF.EmitNullInitialization(DimsAddr, ArrayTy); - enum { LowerFD = 0, UpperFD, StrideFD }; - // Fill dims with data. - for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { - LValue DimsLVal = - CGF.MakeAddrLValue(CGF.Builder.CreateConstArrayGEP( - DimsAddr, I, C.getTypeSizeInChars(KmpDimTy)), - KmpDimTy); - // dims.upper = num_iterations; - LValue UpperLVal = CGF.EmitLValueForField( - DimsLVal, *std::next(RD->field_begin(), UpperFD)); - llvm::Value *NumIterVal = - CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]), - D.getNumIterations()->getType(), Int64Ty, - D.getNumIterations()->getExprLoc()); - CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); - // dims.stride = 1; - LValue StrideLVal = CGF.EmitLValueForField( - DimsLVal, *std::next(RD->field_begin(), StrideFD)); - CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), - StrideLVal); - } - - // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, - // kmp_int32 num_dims, struct kmp_dim * dims); - llvm::Value *Args[] = { - emitUpdateLocation(CGF, D.getBeginLoc()), - getThreadID(CGF, D.getBeginLoc()), - llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), - CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - CGF.Builder - .CreateConstArrayGEP(DimsAddr, 0, C.getTypeSizeInChars(KmpDimTy)) - .getPointer(), - CGM.VoidPtrTy)}; - - llvm::Value *RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_init); - CGF.EmitRuntimeCall(RTLFn, Args); - llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { - emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; - llvm::Value *FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_fini); - CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, - llvm::makeArrayRef(FiniArgs)); -} - -void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, - const OMPDependClause *C) { - QualType Int64Ty = - CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); - llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); - QualType ArrayTy = CGM.getContext().getConstantArrayType( - Int64Ty, Size, ArrayType::Normal, 0); - Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); - for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { - const Expr *CounterVal = C->getLoopData(I); - assert(CounterVal); - llvm::Value *CntVal = CGF.EmitScalarConversion( - CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, - CounterVal->getExprLoc()); - CGF.EmitStoreOfScalar( - CntVal, - CGF.Builder.CreateConstArrayGEP( - CntAddr, I, CGM.getContext().getTypeSizeInChars(Int64Ty)), - /*Volatile=*/false, Int64Ty); - } - llvm::Value *Args[] = { - emitUpdateLocation(CGF, C->getBeginLoc()), - getThreadID(CGF, C->getBeginLoc()), - CGF.Builder - .CreateConstArrayGEP(CntAddr, 0, - CGM.getContext().getTypeSizeInChars(Int64Ty)) - .getPointer()}; - llvm::Value *RTLFn; - if (C->getDependencyKind() == OMPC_DEPEND_source) { - RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post); - } else { - assert(C->getDependencyKind() == OMPC_DEPEND_sink); - RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait); - } - CGF.EmitRuntimeCall(RTLFn, Args); -} - -void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, - llvm::Value *Callee, - ArrayRef<llvm::Value *> Args) const { - assert(Loc.isValid() && "Outlined function call location must be valid."); - auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); - - if (auto *Fn = dyn_cast<llvm::Function>(Callee)) { - if (Fn->doesNotThrow()) { - CGF.EmitNounwindRuntimeCall(Fn, Args); - return; - } - } - CGF.EmitRuntimeCall(Callee, Args); -} - -void CGOpenMPRuntime::emitOutlinedFunctionCall( - CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> Args) const { - emitCall(CGF, Loc, OutlinedFn, Args); -} - -Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, - const VarDecl *NativeParam, - const VarDecl *TargetParam) const { - return CGF.GetAddrOfLocalVar(NativeParam); -} - -Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, - const VarDecl *VD) { - return Address::invalid(); -} - -llvm::Value *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( - const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, - OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -llvm::Value *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( - const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, - OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -llvm::Value *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( - const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, - const VarDecl *PartIDVar, const VarDecl *TaskTVar, - OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, - bool Tied, unsigned &NumberOfParts) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, - SourceLocation Loc, - llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> CapturedVars, - const Expr *IfCond) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitCriticalRegion( - CodeGenFunction &CGF, StringRef CriticalName, - const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, - const Expr *Hint) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, - const RegionCodeGenTy &MasterOpGen, - SourceLocation Loc) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, - SourceLocation Loc) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitTaskgroupRegion( - CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, - SourceLocation Loc) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitSingleRegion( - CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, - SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, - ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, - ArrayRef<const Expr *> AssignmentOps) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, - const RegionCodeGenTy &OrderedOpGen, - SourceLocation Loc, - bool IsThreads) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, - SourceLocation Loc, - OpenMPDirectiveKind Kind, - bool EmitChecks, - bool ForceSimpleCall) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitForDispatchInit( - CodeGenFunction &CGF, SourceLocation Loc, - const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, - bool Ordered, const DispatchRTInput &DispatchValues) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitForStaticInit( - CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, - const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitDistributeStaticInit( - CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, - SourceLocation Loc, - unsigned IVSize, - bool IVSigned) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, - SourceLocation Loc, - OpenMPDirectiveKind DKind) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, - SourceLocation Loc, - unsigned IVSize, bool IVSigned, - Address IL, Address LB, - Address UB, Address ST) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, - llvm::Value *NumThreads, - SourceLocation Loc) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, - OpenMPProcBindClauseKind ProcBind, - SourceLocation Loc) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, - const VarDecl *VD, - Address VDAddr, - SourceLocation Loc) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( - const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, - CodeGenFunction *CGF) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( - CodeGenFunction &CGF, QualType VarType, StringRef Name) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, - ArrayRef<const Expr *> Vars, - SourceLocation Loc) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, - const OMPExecutableDirective &D, - llvm::Value *TaskFunction, - QualType SharedsTy, Address Shareds, - const Expr *IfCond, - const OMPTaskDataTy &Data) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitTaskLoopCall( - CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, - llvm::Value *TaskFunction, QualType SharedsTy, Address Shareds, - const Expr *IfCond, const OMPTaskDataTy &Data) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitReduction( - CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, - ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, - ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { - assert(Options.SimpleReduction && "Only simple reduction is expected."); - CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, - ReductionOps, Options); -} - -llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( - CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, - ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, - SourceLocation Loc, - ReductionCodeGen &RCG, - unsigned N) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, - SourceLocation Loc, - llvm::Value *ReductionsPtr, - LValue SharedLVal) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, - SourceLocation Loc) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitCancellationPointCall( - CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDirectiveKind CancelRegion) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, - SourceLocation Loc, const Expr *IfCond, - OpenMPDirectiveKind CancelRegion) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( - const OMPExecutableDirective &D, StringRef ParentName, - llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, - bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitTargetCall(CodeGenFunction &CGF, - const OMPExecutableDirective &D, - llvm::Value *OutlinedFn, - llvm::Value *OutlinedFnID, - const Expr *IfCond, const Expr *Device) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { - return false; -} - -llvm::Function *CGOpenMPSIMDRuntime::emitRegistrationFunction() { - return nullptr; -} - -void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, - const OMPExecutableDirective &D, - SourceLocation Loc, - llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> CapturedVars) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, - const Expr *NumTeams, - const Expr *ThreadLimit, - SourceLocation Loc) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitTargetDataCalls( - CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, - const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( - CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, - const Expr *Device) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, - const OMPLoopDirective &D, - ArrayRef<Expr *> NumIterations) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, - const OMPDependClause *C) { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -const VarDecl * -CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, - const VarDecl *NativeParam) const { - llvm_unreachable("Not supported in SIMD-only mode"); -} - -Address -CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, - const VarDecl *NativeParam, - const VarDecl *TargetParam) const { - llvm_unreachable("Not supported in SIMD-only mode"); -} - diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h b/gnu/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h deleted file mode 100644 index 1822a6fd197..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h +++ /dev/null @@ -1,2155 +0,0 @@ -//===----- CGOpenMPRuntime.h - Interface to OpenMP Runtimes -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This provides a class for OpenMP runtime code generation. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CGOPENMPRUNTIME_H -#define LLVM_CLANG_LIB_CODEGEN_CGOPENMPRUNTIME_H - -#include "CGValue.h" -#include "clang/AST/DeclOpenMP.h" -#include "clang/AST/Type.h" -#include "clang/Basic/OpenMPKinds.h" -#include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringSet.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/ValueHandle.h" - -namespace llvm { -class ArrayType; -class Constant; -class FunctionType; -class GlobalVariable; -class StructType; -class Type; -class Value; -} // namespace llvm - -namespace clang { -class Expr; -class GlobalDecl; -class OMPDependClause; -class OMPExecutableDirective; -class OMPLoopDirective; -class VarDecl; -class OMPDeclareReductionDecl; -class IdentifierInfo; - -namespace CodeGen { -class Address; -class CodeGenFunction; -class CodeGenModule; - -/// A basic class for pre|post-action for advanced codegen sequence for OpenMP -/// region. -class PrePostActionTy { -public: - explicit PrePostActionTy() {} - virtual void Enter(CodeGenFunction &CGF) {} - virtual void Exit(CodeGenFunction &CGF) {} - virtual ~PrePostActionTy() {} -}; - -/// Class provides a way to call simple version of codegen for OpenMP region, or -/// an advanced with possible pre|post-actions in codegen. -class RegionCodeGenTy final { - intptr_t CodeGen; - typedef void (*CodeGenTy)(intptr_t, CodeGenFunction &, PrePostActionTy &); - CodeGenTy Callback; - mutable PrePostActionTy *PrePostAction; - RegionCodeGenTy() = delete; - RegionCodeGenTy &operator=(const RegionCodeGenTy &) = delete; - template <typename Callable> - static void CallbackFn(intptr_t CodeGen, CodeGenFunction &CGF, - PrePostActionTy &Action) { - return (*reinterpret_cast<Callable *>(CodeGen))(CGF, Action); - } - -public: - template <typename Callable> - RegionCodeGenTy( - Callable &&CodeGen, - typename std::enable_if< - !std::is_same<typename std::remove_reference<Callable>::type, - RegionCodeGenTy>::value>::type * = nullptr) - : CodeGen(reinterpret_cast<intptr_t>(&CodeGen)), - Callback(CallbackFn<typename std::remove_reference<Callable>::type>), - PrePostAction(nullptr) {} - void setAction(PrePostActionTy &Action) const { PrePostAction = &Action; } - void operator()(CodeGenFunction &CGF) const; -}; - -struct OMPTaskDataTy final { - SmallVector<const Expr *, 4> PrivateVars; - SmallVector<const Expr *, 4> PrivateCopies; - SmallVector<const Expr *, 4> FirstprivateVars; - SmallVector<const Expr *, 4> FirstprivateCopies; - SmallVector<const Expr *, 4> FirstprivateInits; - SmallVector<const Expr *, 4> LastprivateVars; - SmallVector<const Expr *, 4> LastprivateCopies; - SmallVector<const Expr *, 4> ReductionVars; - SmallVector<const Expr *, 4> ReductionCopies; - SmallVector<const Expr *, 4> ReductionOps; - SmallVector<std::pair<OpenMPDependClauseKind, const Expr *>, 4> Dependences; - llvm::PointerIntPair<llvm::Value *, 1, bool> Final; - llvm::PointerIntPair<llvm::Value *, 1, bool> Schedule; - llvm::PointerIntPair<llvm::Value *, 1, bool> Priority; - llvm::Value *Reductions = nullptr; - unsigned NumberOfParts = 0; - bool Tied = true; - bool Nogroup = false; -}; - -/// Class intended to support codegen of all kind of the reduction clauses. -class ReductionCodeGen { -private: - /// Data required for codegen of reduction clauses. - struct ReductionData { - /// Reference to the original shared item. - const Expr *Ref = nullptr; - /// Helper expression for generation of private copy. - const Expr *Private = nullptr; - /// Helper expression for generation reduction operation. - const Expr *ReductionOp = nullptr; - ReductionData(const Expr *Ref, const Expr *Private, const Expr *ReductionOp) - : Ref(Ref), Private(Private), ReductionOp(ReductionOp) {} - }; - /// List of reduction-based clauses. - SmallVector<ReductionData, 4> ClausesData; - - /// List of addresses of original shared variables/expressions. - SmallVector<std::pair<LValue, LValue>, 4> SharedAddresses; - /// Sizes of the reduction items in chars. - SmallVector<std::pair<llvm::Value *, llvm::Value *>, 4> Sizes; - /// Base declarations for the reduction items. - SmallVector<const VarDecl *, 4> BaseDecls; - - /// Emits lvalue for shared expression. - LValue emitSharedLValue(CodeGenFunction &CGF, const Expr *E); - /// Emits upper bound for shared expression (if array section). - LValue emitSharedLValueUB(CodeGenFunction &CGF, const Expr *E); - /// Performs aggregate initialization. - /// \param N Number of reduction item in the common list. - /// \param PrivateAddr Address of the corresponding private item. - /// \param SharedLVal Address of the original shared variable. - /// \param DRD Declare reduction construct used for reduction item. - void emitAggregateInitialization(CodeGenFunction &CGF, unsigned N, - Address PrivateAddr, LValue SharedLVal, - const OMPDeclareReductionDecl *DRD); - -public: - ReductionCodeGen(ArrayRef<const Expr *> Shareds, - ArrayRef<const Expr *> Privates, - ArrayRef<const Expr *> ReductionOps); - /// Emits lvalue for a reduction item. - /// \param N Number of the reduction item. - void emitSharedLValue(CodeGenFunction &CGF, unsigned N); - /// Emits the code for the variable-modified type, if required. - /// \param N Number of the reduction item. - void emitAggregateType(CodeGenFunction &CGF, unsigned N); - /// Emits the code for the variable-modified type, if required. - /// \param N Number of the reduction item. - /// \param Size Size of the type in chars. - void emitAggregateType(CodeGenFunction &CGF, unsigned N, llvm::Value *Size); - /// Performs initialization of the private copy for the reduction item. - /// \param N Number of the reduction item. - /// \param PrivateAddr Address of the corresponding private item. - /// \param DefaultInit Default initialization sequence that should be - /// performed if no reduction specific initialization is found. - /// \param SharedLVal Address of the original shared variable. - void - emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr, - LValue SharedLVal, - llvm::function_ref<bool(CodeGenFunction &)> DefaultInit); - /// Returns true if the private copy requires cleanups. - bool needCleanups(unsigned N); - /// Emits cleanup code for the reduction item. - /// \param N Number of the reduction item. - /// \param PrivateAddr Address of the corresponding private item. - void emitCleanups(CodeGenFunction &CGF, unsigned N, Address PrivateAddr); - /// Adjusts \p PrivatedAddr for using instead of the original variable - /// address in normal operations. - /// \param N Number of the reduction item. - /// \param PrivateAddr Address of the corresponding private item. - Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, - Address PrivateAddr); - /// Returns LValue for the reduction item. - LValue getSharedLValue(unsigned N) const { return SharedAddresses[N].first; } - /// Returns the size of the reduction item (in chars and total number of - /// elements in the item), or nullptr, if the size is a constant. - std::pair<llvm::Value *, llvm::Value *> getSizes(unsigned N) const { - return Sizes[N]; - } - /// Returns the base declaration of the reduction item. - const VarDecl *getBaseDecl(unsigned N) const { return BaseDecls[N]; } - /// Returns the base declaration of the reduction item. - const Expr *getRefExpr(unsigned N) const { return ClausesData[N].Ref; } - /// Returns true if the initialization of the reduction item uses initializer - /// from declare reduction construct. - bool usesReductionInitializer(unsigned N) const; -}; - -class CGOpenMPRuntime { -public: - /// Allows to disable automatic handling of functions used in target regions - /// as those marked as `omp declare target`. - class DisableAutoDeclareTargetRAII { - CodeGenModule &CGM; - bool SavedShouldMarkAsGlobal; - - public: - DisableAutoDeclareTargetRAII(CodeGenModule &CGM); - ~DisableAutoDeclareTargetRAII(); - }; - -protected: - CodeGenModule &CGM; - StringRef FirstSeparator, Separator; - - /// Constructor allowing to redefine the name separator for the variables. - explicit CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, - StringRef Separator); - - /// Creates offloading entry for the provided entry ID \a ID, - /// address \a Addr, size \a Size, and flags \a Flags. - virtual void createOffloadEntry(llvm::Constant *ID, llvm::Constant *Addr, - uint64_t Size, int32_t Flags, - llvm::GlobalValue::LinkageTypes Linkage); - - /// Helper to emit outlined function for 'target' directive. - /// \param D Directive to emit. - /// \param ParentName Name of the function that encloses the target region. - /// \param OutlinedFn Outlined function value to be defined by this call. - /// \param OutlinedFnID Outlined function ID value to be defined by this call. - /// \param IsOffloadEntry True if the outlined function is an offload entry. - /// \param CodeGen Lambda codegen specific to an accelerator device. - /// An outlined function may not be an entry if, e.g. the if clause always - /// evaluates to false. - virtual void emitTargetOutlinedFunctionHelper(const OMPExecutableDirective &D, - StringRef ParentName, - llvm::Function *&OutlinedFn, - llvm::Constant *&OutlinedFnID, - bool IsOffloadEntry, - const RegionCodeGenTy &CodeGen); - - /// Emits code for OpenMP 'if' clause using specified \a CodeGen - /// function. Here is the logic: - /// if (Cond) { - /// ThenGen(); - /// } else { - /// ElseGen(); - /// } - void emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond, - const RegionCodeGenTy &ThenGen, - const RegionCodeGenTy &ElseGen); - - /// Emits object of ident_t type with info for source location. - /// \param Flags Flags for OpenMP location. - /// - llvm::Value *emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc, - unsigned Flags = 0); - - /// Returns pointer to ident_t type. - llvm::Type *getIdentTyPointerTy(); - - /// Gets thread id value for the current thread. - /// - llvm::Value *getThreadID(CodeGenFunction &CGF, SourceLocation Loc); - - /// Get the function name of an outlined region. - // The name can be customized depending on the target. - // - virtual StringRef getOutlinedHelperName() const { return ".omp_outlined."; } - - /// Emits \p Callee function call with arguments \p Args with location \p Loc. - void emitCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *Callee, - ArrayRef<llvm::Value *> Args = llvm::None) const; - - /// Emits address of the word in a memory where current thread id is - /// stored. - virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc); - - void setLocThreadIdInsertPt(CodeGenFunction &CGF, - bool AtCurrentPoint = false); - void clearLocThreadIdInsertPt(CodeGenFunction &CGF); - - /// Check if the default location must be constant. - /// Default is false to support OMPT/OMPD. - virtual bool isDefaultLocationConstant() const { return false; } - - /// Returns additional flags that can be stored in reserved_2 field of the - /// default location. - virtual unsigned getDefaultLocationReserved2Flags() const { return 0; } - - /// Returns default flags for the barriers depending on the directive, for - /// which this barier is going to be emitted. - static unsigned getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind); - - /// Get the LLVM type for the critical name. - llvm::ArrayType *getKmpCriticalNameTy() const {return KmpCriticalNameTy;} - - /// Returns corresponding lock object for the specified critical region - /// name. If the lock object does not exist it is created, otherwise the - /// reference to the existing copy is returned. - /// \param CriticalName Name of the critical region. - /// - llvm::Value *getCriticalRegionLock(StringRef CriticalName); - -private: - /// Default const ident_t object used for initialization of all other - /// ident_t objects. - llvm::Constant *DefaultOpenMPPSource = nullptr; - using FlagsTy = std::pair<unsigned, unsigned>; - /// Map of flags and corresponding default locations. - using OpenMPDefaultLocMapTy = llvm::DenseMap<FlagsTy, llvm::Value *>; - OpenMPDefaultLocMapTy OpenMPDefaultLocMap; - Address getOrCreateDefaultLocation(unsigned Flags); - - QualType IdentQTy; - llvm::StructType *IdentTy = nullptr; - /// Map for SourceLocation and OpenMP runtime library debug locations. - typedef llvm::DenseMap<unsigned, llvm::Value *> OpenMPDebugLocMapTy; - OpenMPDebugLocMapTy OpenMPDebugLocMap; - /// The type for a microtask which gets passed to __kmpc_fork_call(). - /// Original representation is: - /// typedef void (kmpc_micro)(kmp_int32 global_tid, kmp_int32 bound_tid,...); - llvm::FunctionType *Kmpc_MicroTy = nullptr; - /// Stores debug location and ThreadID for the function. - struct DebugLocThreadIdTy { - llvm::Value *DebugLoc; - llvm::Value *ThreadID; - /// Insert point for the service instructions. - llvm::AssertingVH<llvm::Instruction> ServiceInsertPt = nullptr; - }; - /// Map of local debug location, ThreadId and functions. - typedef llvm::DenseMap<llvm::Function *, DebugLocThreadIdTy> - OpenMPLocThreadIDMapTy; - OpenMPLocThreadIDMapTy OpenMPLocThreadIDMap; - /// Map of UDRs and corresponding combiner/initializer. - typedef llvm::DenseMap<const OMPDeclareReductionDecl *, - std::pair<llvm::Function *, llvm::Function *>> - UDRMapTy; - UDRMapTy UDRMap; - /// Map of functions and locally defined UDRs. - typedef llvm::DenseMap<llvm::Function *, - SmallVector<const OMPDeclareReductionDecl *, 4>> - FunctionUDRMapTy; - FunctionUDRMapTy FunctionUDRMap; - /// Type kmp_critical_name, originally defined as typedef kmp_int32 - /// kmp_critical_name[8]; - llvm::ArrayType *KmpCriticalNameTy; - /// An ordered map of auto-generated variables to their unique names. - /// It stores variables with the following names: 1) ".gomp_critical_user_" + - /// <critical_section_name> + ".var" for "omp critical" directives; 2) - /// <mangled_name_for_global_var> + ".cache." for cache for threadprivate - /// variables. - llvm::StringMap<llvm::AssertingVH<llvm::Constant>, llvm::BumpPtrAllocator> - InternalVars; - /// Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); - llvm::Type *KmpRoutineEntryPtrTy = nullptr; - QualType KmpRoutineEntryPtrQTy; - /// Type typedef struct kmp_task { - /// void * shareds; /**< pointer to block of pointers to - /// shared vars */ - /// kmp_routine_entry_t routine; /**< pointer to routine to call for - /// executing task */ - /// kmp_int32 part_id; /**< part id for the task */ - /// kmp_routine_entry_t destructors; /* pointer to function to invoke - /// deconstructors of firstprivate C++ objects */ - /// } kmp_task_t; - QualType KmpTaskTQTy; - /// Saved kmp_task_t for task directive. - QualType SavedKmpTaskTQTy; - /// Saved kmp_task_t for taskloop-based directive. - QualType SavedKmpTaskloopTQTy; - /// Type typedef struct kmp_depend_info { - /// kmp_intptr_t base_addr; - /// size_t len; - /// struct { - /// bool in:1; - /// bool out:1; - /// } flags; - /// } kmp_depend_info_t; - QualType KmpDependInfoTy; - /// struct kmp_dim { // loop bounds info casted to kmp_int64 - /// kmp_int64 lo; // lower - /// kmp_int64 up; // upper - /// kmp_int64 st; // stride - /// }; - QualType KmpDimTy; - /// Type struct __tgt_offload_entry{ - /// void *addr; // Pointer to the offload entry info. - /// // (function or global) - /// char *name; // Name of the function or global. - /// size_t size; // Size of the entry info (0 if it a function). - /// }; - QualType TgtOffloadEntryQTy; - /// struct __tgt_device_image{ - /// void *ImageStart; // Pointer to the target code start. - /// void *ImageEnd; // Pointer to the target code end. - /// // We also add the host entries to the device image, as it may be useful - /// // for the target runtime to have access to that information. - /// __tgt_offload_entry *EntriesBegin; // Begin of the table with all - /// // the entries. - /// __tgt_offload_entry *EntriesEnd; // End of the table with all the - /// // entries (non inclusive). - /// }; - QualType TgtDeviceImageQTy; - /// struct __tgt_bin_desc{ - /// int32_t NumDevices; // Number of devices supported. - /// __tgt_device_image *DeviceImages; // Arrays of device images - /// // (one per device). - /// __tgt_offload_entry *EntriesBegin; // Begin of the table with all the - /// // entries. - /// __tgt_offload_entry *EntriesEnd; // End of the table with all the - /// // entries (non inclusive). - /// }; - QualType TgtBinaryDescriptorQTy; - /// Entity that registers the offloading constants that were emitted so - /// far. - class OffloadEntriesInfoManagerTy { - CodeGenModule &CGM; - - /// Number of entries registered so far. - unsigned OffloadingEntriesNum = 0; - - public: - /// Base class of the entries info. - class OffloadEntryInfo { - public: - /// Kind of a given entry. - enum OffloadingEntryInfoKinds : unsigned { - /// Entry is a target region. - OffloadingEntryInfoTargetRegion = 0, - /// Entry is a declare target variable. - OffloadingEntryInfoDeviceGlobalVar = 1, - /// Invalid entry info. - OffloadingEntryInfoInvalid = ~0u - }; - - protected: - OffloadEntryInfo() = delete; - explicit OffloadEntryInfo(OffloadingEntryInfoKinds Kind) : Kind(Kind) {} - explicit OffloadEntryInfo(OffloadingEntryInfoKinds Kind, unsigned Order, - uint32_t Flags) - : Flags(Flags), Order(Order), Kind(Kind) {} - ~OffloadEntryInfo() = default; - - public: - bool isValid() const { return Order != ~0u; } - unsigned getOrder() const { return Order; } - OffloadingEntryInfoKinds getKind() const { return Kind; } - uint32_t getFlags() const { return Flags; } - void setFlags(uint32_t NewFlags) { Flags = NewFlags; } - llvm::Constant *getAddress() const { - return cast_or_null<llvm::Constant>(Addr); - } - void setAddress(llvm::Constant *V) { - assert(!Addr.pointsToAliveValue() && "Address has been set before!"); - Addr = V; - } - static bool classof(const OffloadEntryInfo *Info) { return true; } - - private: - /// Address of the entity that has to be mapped for offloading. - llvm::WeakTrackingVH Addr; - - /// Flags associated with the device global. - uint32_t Flags = 0u; - - /// Order this entry was emitted. - unsigned Order = ~0u; - - OffloadingEntryInfoKinds Kind = OffloadingEntryInfoInvalid; - }; - - /// Return true if a there are no entries defined. - bool empty() const; - /// Return number of entries defined so far. - unsigned size() const { return OffloadingEntriesNum; } - OffloadEntriesInfoManagerTy(CodeGenModule &CGM) : CGM(CGM) {} - - // - // Target region entries related. - // - - /// Kind of the target registry entry. - enum OMPTargetRegionEntryKind : uint32_t { - /// Mark the entry as target region. - OMPTargetRegionEntryTargetRegion = 0x0, - /// Mark the entry as a global constructor. - OMPTargetRegionEntryCtor = 0x02, - /// Mark the entry as a global destructor. - OMPTargetRegionEntryDtor = 0x04, - }; - - /// Target region entries info. - class OffloadEntryInfoTargetRegion final : public OffloadEntryInfo { - /// Address that can be used as the ID of the entry. - llvm::Constant *ID = nullptr; - - public: - OffloadEntryInfoTargetRegion() - : OffloadEntryInfo(OffloadingEntryInfoTargetRegion) {} - explicit OffloadEntryInfoTargetRegion(unsigned Order, - llvm::Constant *Addr, - llvm::Constant *ID, - OMPTargetRegionEntryKind Flags) - : OffloadEntryInfo(OffloadingEntryInfoTargetRegion, Order, Flags), - ID(ID) { - setAddress(Addr); - } - - llvm::Constant *getID() const { return ID; } - void setID(llvm::Constant *V) { - assert(!ID && "ID has been set before!"); - ID = V; - } - static bool classof(const OffloadEntryInfo *Info) { - return Info->getKind() == OffloadingEntryInfoTargetRegion; - } - }; - - /// Initialize target region entry. - void initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, - StringRef ParentName, unsigned LineNum, - unsigned Order); - /// Register target region entry. - void registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, - StringRef ParentName, unsigned LineNum, - llvm::Constant *Addr, llvm::Constant *ID, - OMPTargetRegionEntryKind Flags); - /// Return true if a target region entry with the provided information - /// exists. - bool hasTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, - StringRef ParentName, unsigned LineNum) const; - /// brief Applies action \a Action on all registered entries. - typedef llvm::function_ref<void(unsigned, unsigned, StringRef, unsigned, - const OffloadEntryInfoTargetRegion &)> - OffloadTargetRegionEntryInfoActTy; - void actOnTargetRegionEntriesInfo( - const OffloadTargetRegionEntryInfoActTy &Action); - - // - // Device global variable entries related. - // - - /// Kind of the global variable entry.. - enum OMPTargetGlobalVarEntryKind : uint32_t { - /// Mark the entry as a to declare target. - OMPTargetGlobalVarEntryTo = 0x0, - /// Mark the entry as a to declare target link. - OMPTargetGlobalVarEntryLink = 0x1, - }; - - /// Device global variable entries info. - class OffloadEntryInfoDeviceGlobalVar final : public OffloadEntryInfo { - /// Type of the global variable. - CharUnits VarSize; - llvm::GlobalValue::LinkageTypes Linkage; - - public: - OffloadEntryInfoDeviceGlobalVar() - : OffloadEntryInfo(OffloadingEntryInfoDeviceGlobalVar) {} - explicit OffloadEntryInfoDeviceGlobalVar(unsigned Order, - OMPTargetGlobalVarEntryKind Flags) - : OffloadEntryInfo(OffloadingEntryInfoDeviceGlobalVar, Order, Flags) {} - explicit OffloadEntryInfoDeviceGlobalVar( - unsigned Order, llvm::Constant *Addr, CharUnits VarSize, - OMPTargetGlobalVarEntryKind Flags, - llvm::GlobalValue::LinkageTypes Linkage) - : OffloadEntryInfo(OffloadingEntryInfoDeviceGlobalVar, Order, Flags), - VarSize(VarSize), Linkage(Linkage) { - setAddress(Addr); - } - - CharUnits getVarSize() const { return VarSize; } - void setVarSize(CharUnits Size) { VarSize = Size; } - llvm::GlobalValue::LinkageTypes getLinkage() const { return Linkage; } - void setLinkage(llvm::GlobalValue::LinkageTypes LT) { Linkage = LT; } - static bool classof(const OffloadEntryInfo *Info) { - return Info->getKind() == OffloadingEntryInfoDeviceGlobalVar; - } - }; - - /// Initialize device global variable entry. - void initializeDeviceGlobalVarEntryInfo(StringRef Name, - OMPTargetGlobalVarEntryKind Flags, - unsigned Order); - - /// Register device global variable entry. - void - registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, - CharUnits VarSize, - OMPTargetGlobalVarEntryKind Flags, - llvm::GlobalValue::LinkageTypes Linkage); - /// Checks if the variable with the given name has been registered already. - bool hasDeviceGlobalVarEntryInfo(StringRef VarName) const { - return OffloadEntriesDeviceGlobalVar.count(VarName) > 0; - } - /// Applies action \a Action on all registered entries. - typedef llvm::function_ref<void(StringRef, - const OffloadEntryInfoDeviceGlobalVar &)> - OffloadDeviceGlobalVarEntryInfoActTy; - void actOnDeviceGlobalVarEntriesInfo( - const OffloadDeviceGlobalVarEntryInfoActTy &Action); - - private: - // Storage for target region entries kind. The storage is to be indexed by - // file ID, device ID, parent function name and line number. - typedef llvm::DenseMap<unsigned, OffloadEntryInfoTargetRegion> - OffloadEntriesTargetRegionPerLine; - typedef llvm::StringMap<OffloadEntriesTargetRegionPerLine> - OffloadEntriesTargetRegionPerParentName; - typedef llvm::DenseMap<unsigned, OffloadEntriesTargetRegionPerParentName> - OffloadEntriesTargetRegionPerFile; - typedef llvm::DenseMap<unsigned, OffloadEntriesTargetRegionPerFile> - OffloadEntriesTargetRegionPerDevice; - typedef OffloadEntriesTargetRegionPerDevice OffloadEntriesTargetRegionTy; - OffloadEntriesTargetRegionTy OffloadEntriesTargetRegion; - /// Storage for device global variable entries kind. The storage is to be - /// indexed by mangled name. - typedef llvm::StringMap<OffloadEntryInfoDeviceGlobalVar> - OffloadEntriesDeviceGlobalVarTy; - OffloadEntriesDeviceGlobalVarTy OffloadEntriesDeviceGlobalVar; - }; - OffloadEntriesInfoManagerTy OffloadEntriesInfoManager; - - bool ShouldMarkAsGlobal = true; - /// List of the emitted functions. - llvm::StringSet<> AlreadyEmittedTargetFunctions; - /// List of the global variables with their addresses that should not be - /// emitted for the target. - llvm::StringMap<llvm::WeakTrackingVH> EmittedNonTargetVariables; - - /// List of variables that can become declare target implicitly and, thus, - /// must be emitted. - llvm::SmallDenseSet<const VarDecl *> DeferredGlobalVariables; - - /// Creates and registers offloading binary descriptor for the current - /// compilation unit. The function that does the registration is returned. - llvm::Function *createOffloadingBinaryDescriptorRegistration(); - - /// Creates all the offload entries in the current compilation unit - /// along with the associated metadata. - void createOffloadEntriesAndInfoMetadata(); - - /// Loads all the offload entries information from the host IR - /// metadata. - void loadOffloadInfoMetadata(); - - /// Returns __tgt_offload_entry type. - QualType getTgtOffloadEntryQTy(); - - /// Returns __tgt_device_image type. - QualType getTgtDeviceImageQTy(); - - /// Returns __tgt_bin_desc type. - QualType getTgtBinaryDescriptorQTy(); - - /// Start scanning from statement \a S and and emit all target regions - /// found along the way. - /// \param S Starting statement. - /// \param ParentName Name of the function declaration that is being scanned. - void scanForTargetRegionsFunctions(const Stmt *S, StringRef ParentName); - - /// Build type kmp_routine_entry_t (if not built yet). - void emitKmpRoutineEntryT(QualType KmpInt32Ty); - - /// Returns pointer to kmpc_micro type. - llvm::Type *getKmpc_MicroPointerTy(); - - /// Returns specified OpenMP runtime function. - /// \param Function OpenMP runtime function. - /// \return Specified function. - llvm::Constant *createRuntimeFunction(unsigned Function); - - /// Returns __kmpc_for_static_init_* runtime function for the specified - /// size \a IVSize and sign \a IVSigned. - llvm::Constant *createForStaticInitFunction(unsigned IVSize, bool IVSigned); - - /// Returns __kmpc_dispatch_init_* runtime function for the specified - /// size \a IVSize and sign \a IVSigned. - llvm::Constant *createDispatchInitFunction(unsigned IVSize, bool IVSigned); - - /// Returns __kmpc_dispatch_next_* runtime function for the specified - /// size \a IVSize and sign \a IVSigned. - llvm::Constant *createDispatchNextFunction(unsigned IVSize, bool IVSigned); - - /// Returns __kmpc_dispatch_fini_* runtime function for the specified - /// size \a IVSize and sign \a IVSigned. - llvm::Constant *createDispatchFiniFunction(unsigned IVSize, bool IVSigned); - - /// If the specified mangled name is not in the module, create and - /// return threadprivate cache object. This object is a pointer's worth of - /// storage that's reserved for use by the OpenMP runtime. - /// \param VD Threadprivate variable. - /// \return Cache variable for the specified threadprivate. - llvm::Constant *getOrCreateThreadPrivateCache(const VarDecl *VD); - - /// Gets (if variable with the given name already exist) or creates - /// internal global variable with the specified Name. The created variable has - /// linkage CommonLinkage by default and is initialized by null value. - /// \param Ty Type of the global variable. If it is exist already the type - /// must be the same. - /// \param Name Name of the variable. - llvm::Constant *getOrCreateInternalVariable(llvm::Type *Ty, - const llvm::Twine &Name); - - /// Set of threadprivate variables with the generated initializer. - llvm::StringSet<> ThreadPrivateWithDefinition; - - /// Set of declare target variables with the generated initializer. - llvm::StringSet<> DeclareTargetWithDefinition; - - /// Emits initialization code for the threadprivate variables. - /// \param VDAddr Address of the global variable \a VD. - /// \param Ctor Pointer to a global init function for \a VD. - /// \param CopyCtor Pointer to a global copy function for \a VD. - /// \param Dtor Pointer to a global destructor function for \a VD. - /// \param Loc Location of threadprivate declaration. - void emitThreadPrivateVarInit(CodeGenFunction &CGF, Address VDAddr, - llvm::Value *Ctor, llvm::Value *CopyCtor, - llvm::Value *Dtor, SourceLocation Loc); - - struct TaskResultTy { - llvm::Value *NewTask = nullptr; - llvm::Value *TaskEntry = nullptr; - llvm::Value *NewTaskNewTaskTTy = nullptr; - LValue TDBase; - const RecordDecl *KmpTaskTQTyRD = nullptr; - llvm::Value *TaskDupFn = nullptr; - }; - /// Emit task region for the task directive. The task region is emitted in - /// several steps: - /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 - /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, - /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the - /// function: - /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { - /// TaskFunction(gtid, tt->part_id, tt->shareds); - /// return 0; - /// } - /// 2. Copy a list of shared variables to field shareds of the resulting - /// structure kmp_task_t returned by the previous call (if any). - /// 3. Copy a pointer to destructions function to field destructions of the - /// resulting structure kmp_task_t. - /// \param D Current task directive. - /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32 - /// /*part_id*/, captured_struct */*__context*/); - /// \param SharedsTy A type which contains references the shared variables. - /// \param Shareds Context with the list of shared variables from the \p - /// TaskFunction. - /// \param Data Additional data for task generation like tiednsee, final - /// state, list of privates etc. - TaskResultTy emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, - const OMPExecutableDirective &D, - llvm::Value *TaskFunction, QualType SharedsTy, - Address Shareds, const OMPTaskDataTy &Data); - -public: - explicit CGOpenMPRuntime(CodeGenModule &CGM) - : CGOpenMPRuntime(CGM, ".", ".") {} - virtual ~CGOpenMPRuntime() {} - virtual void clear(); - - /// Get the platform-specific name separator. - std::string getName(ArrayRef<StringRef> Parts) const; - - /// Emit code for the specified user defined reduction construct. - virtual void emitUserDefinedReduction(CodeGenFunction *CGF, - const OMPDeclareReductionDecl *D); - /// Get combiner/initializer for the specified user-defined reduction, if any. - virtual std::pair<llvm::Function *, llvm::Function *> - getUserDefinedReduction(const OMPDeclareReductionDecl *D); - - /// Emits outlined function for the specified OpenMP parallel directive - /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID, - /// kmp_int32 BoundID, struct context_vars*). - /// \param D OpenMP directive. - /// \param ThreadIDVar Variable for thread id in the current OpenMP region. - /// \param InnermostKind Kind of innermost directive (for simple directives it - /// is a directive itself, for combined - its innermost directive). - /// \param CodeGen Code generation sequence for the \a D directive. - virtual llvm::Value *emitParallelOutlinedFunction( - const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, - OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen); - - /// Emits outlined function for the specified OpenMP teams directive - /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID, - /// kmp_int32 BoundID, struct context_vars*). - /// \param D OpenMP directive. - /// \param ThreadIDVar Variable for thread id in the current OpenMP region. - /// \param InnermostKind Kind of innermost directive (for simple directives it - /// is a directive itself, for combined - its innermost directive). - /// \param CodeGen Code generation sequence for the \a D directive. - virtual llvm::Value *emitTeamsOutlinedFunction( - const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, - OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen); - - /// Emits outlined function for the OpenMP task directive \a D. This - /// outlined function has type void(*)(kmp_int32 ThreadID, struct task_t* - /// TaskT). - /// \param D OpenMP directive. - /// \param ThreadIDVar Variable for thread id in the current OpenMP region. - /// \param PartIDVar Variable for partition id in the current OpenMP untied - /// task region. - /// \param TaskTVar Variable for task_t argument. - /// \param InnermostKind Kind of innermost directive (for simple directives it - /// is a directive itself, for combined - its innermost directive). - /// \param CodeGen Code generation sequence for the \a D directive. - /// \param Tied true if task is generated for tied task, false otherwise. - /// \param NumberOfParts Number of parts in untied task. Ignored for tied - /// tasks. - /// - virtual llvm::Value *emitTaskOutlinedFunction( - const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, - const VarDecl *PartIDVar, const VarDecl *TaskTVar, - OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, - bool Tied, unsigned &NumberOfParts); - - /// Cleans up references to the objects in finished function. - /// - virtual void functionFinished(CodeGenFunction &CGF); - - /// Emits code for parallel or serial call of the \a OutlinedFn with - /// variables captured in a record which address is stored in \a - /// CapturedStruct. - /// \param OutlinedFn Outlined function to be run in parallel threads. Type of - /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*). - /// \param CapturedVars A pointer to the record with the references to - /// variables used in \a OutlinedFn function. - /// \param IfCond Condition in the associated 'if' clause, if it was - /// specified, nullptr otherwise. - /// - virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, - llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> CapturedVars, - const Expr *IfCond); - - /// Emits a critical region. - /// \param CriticalName Name of the critical region. - /// \param CriticalOpGen Generator for the statement associated with the given - /// critical region. - /// \param Hint Value of the 'hint' clause (optional). - virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, - const RegionCodeGenTy &CriticalOpGen, - SourceLocation Loc, - const Expr *Hint = nullptr); - - /// Emits a master region. - /// \param MasterOpGen Generator for the statement associated with the given - /// master region. - virtual void emitMasterRegion(CodeGenFunction &CGF, - const RegionCodeGenTy &MasterOpGen, - SourceLocation Loc); - - /// Emits code for a taskyield directive. - virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc); - - /// Emit a taskgroup region. - /// \param TaskgroupOpGen Generator for the statement associated with the - /// given taskgroup region. - virtual void emitTaskgroupRegion(CodeGenFunction &CGF, - const RegionCodeGenTy &TaskgroupOpGen, - SourceLocation Loc); - - /// Emits a single region. - /// \param SingleOpGen Generator for the statement associated with the given - /// single region. - virtual void emitSingleRegion(CodeGenFunction &CGF, - const RegionCodeGenTy &SingleOpGen, - SourceLocation Loc, - ArrayRef<const Expr *> CopyprivateVars, - ArrayRef<const Expr *> DestExprs, - ArrayRef<const Expr *> SrcExprs, - ArrayRef<const Expr *> AssignmentOps); - - /// Emit an ordered region. - /// \param OrderedOpGen Generator for the statement associated with the given - /// ordered region. - virtual void emitOrderedRegion(CodeGenFunction &CGF, - const RegionCodeGenTy &OrderedOpGen, - SourceLocation Loc, bool IsThreads); - - /// Emit an implicit/explicit barrier for OpenMP threads. - /// \param Kind Directive for which this implicit barrier call must be - /// generated. Must be OMPD_barrier for explicit barrier generation. - /// \param EmitChecks true if need to emit checks for cancellation barriers. - /// \param ForceSimpleCall true simple barrier call must be emitted, false if - /// runtime class decides which one to emit (simple or with cancellation - /// checks). - /// - virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDirectiveKind Kind, - bool EmitChecks = true, - bool ForceSimpleCall = false); - - /// Check if the specified \a ScheduleKind is static non-chunked. - /// This kind of worksharing directive is emitted without outer loop. - /// \param ScheduleKind Schedule kind specified in the 'schedule' clause. - /// \param Chunked True if chunk is specified in the clause. - /// - virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, - bool Chunked) const; - - /// Check if the specified \a ScheduleKind is static non-chunked. - /// This kind of distribute directive is emitted without outer loop. - /// \param ScheduleKind Schedule kind specified in the 'dist_schedule' clause. - /// \param Chunked True if chunk is specified in the clause. - /// - virtual bool isStaticNonchunked(OpenMPDistScheduleClauseKind ScheduleKind, - bool Chunked) const; - - /// Check if the specified \a ScheduleKind is static chunked. - /// \param ScheduleKind Schedule kind specified in the 'schedule' clause. - /// \param Chunked True if chunk is specified in the clause. - /// - virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, - bool Chunked) const; - - /// Check if the specified \a ScheduleKind is static non-chunked. - /// \param ScheduleKind Schedule kind specified in the 'dist_schedule' clause. - /// \param Chunked True if chunk is specified in the clause. - /// - virtual bool isStaticChunked(OpenMPDistScheduleClauseKind ScheduleKind, - bool Chunked) const; - - /// Check if the specified \a ScheduleKind is dynamic. - /// This kind of worksharing directive is emitted without outer loop. - /// \param ScheduleKind Schedule Kind specified in the 'schedule' clause. - /// - virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const; - - /// struct with the values to be passed to the dispatch runtime function - struct DispatchRTInput { - /// Loop lower bound - llvm::Value *LB = nullptr; - /// Loop upper bound - llvm::Value *UB = nullptr; - /// Chunk size specified using 'schedule' clause (nullptr if chunk - /// was not specified) - llvm::Value *Chunk = nullptr; - DispatchRTInput() = default; - DispatchRTInput(llvm::Value *LB, llvm::Value *UB, llvm::Value *Chunk) - : LB(LB), UB(UB), Chunk(Chunk) {} - }; - - /// Call the appropriate runtime routine to initialize it before start - /// of loop. - - /// This is used for non static scheduled types and when the ordered - /// clause is present on the loop construct. - /// Depending on the loop schedule, it is necessary to call some runtime - /// routine before start of the OpenMP loop to get the loop upper / lower - /// bounds \a LB and \a UB and stride \a ST. - /// - /// \param CGF Reference to current CodeGenFunction. - /// \param Loc Clang source location. - /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause. - /// \param IVSize Size of the iteration variable in bits. - /// \param IVSigned Sign of the iteration variable. - /// \param Ordered true if loop is ordered, false otherwise. - /// \param DispatchValues struct containing llvm values for lower bound, upper - /// bound, and chunk expression. - /// For the default (nullptr) value, the chunk 1 will be used. - /// - virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, - const OpenMPScheduleTy &ScheduleKind, - unsigned IVSize, bool IVSigned, bool Ordered, - const DispatchRTInput &DispatchValues); - - /// Struct with the values to be passed to the static runtime function - struct StaticRTInput { - /// Size of the iteration variable in bits. - unsigned IVSize = 0; - /// Sign of the iteration variable. - bool IVSigned = false; - /// true if loop is ordered, false otherwise. - bool Ordered = false; - /// Address of the output variable in which the flag of the last iteration - /// is returned. - Address IL = Address::invalid(); - /// Address of the output variable in which the lower iteration number is - /// returned. - Address LB = Address::invalid(); - /// Address of the output variable in which the upper iteration number is - /// returned. - Address UB = Address::invalid(); - /// Address of the output variable in which the stride value is returned - /// necessary to generated the static_chunked scheduled loop. - Address ST = Address::invalid(); - /// Value of the chunk for the static_chunked scheduled loop. For the - /// default (nullptr) value, the chunk 1 will be used. - llvm::Value *Chunk = nullptr; - StaticRTInput(unsigned IVSize, bool IVSigned, bool Ordered, Address IL, - Address LB, Address UB, Address ST, - llvm::Value *Chunk = nullptr) - : IVSize(IVSize), IVSigned(IVSigned), Ordered(Ordered), IL(IL), LB(LB), - UB(UB), ST(ST), Chunk(Chunk) {} - }; - /// Call the appropriate runtime routine to initialize it before start - /// of loop. - /// - /// This is used only in case of static schedule, when the user did not - /// specify a ordered clause on the loop construct. - /// Depending on the loop schedule, it is necessary to call some runtime - /// routine before start of the OpenMP loop to get the loop upper / lower - /// bounds LB and UB and stride ST. - /// - /// \param CGF Reference to current CodeGenFunction. - /// \param Loc Clang source location. - /// \param DKind Kind of the directive. - /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause. - /// \param Values Input arguments for the construct. - /// - virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDirectiveKind DKind, - const OpenMPScheduleTy &ScheduleKind, - const StaticRTInput &Values); - - /// - /// \param CGF Reference to current CodeGenFunction. - /// \param Loc Clang source location. - /// \param SchedKind Schedule kind, specified by the 'dist_schedule' clause. - /// \param Values Input arguments for the construct. - /// - virtual void emitDistributeStaticInit(CodeGenFunction &CGF, - SourceLocation Loc, - OpenMPDistScheduleClauseKind SchedKind, - const StaticRTInput &Values); - - /// Call the appropriate runtime routine to notify that we finished - /// iteration of the ordered loop with the dynamic scheduling. - /// - /// \param CGF Reference to current CodeGenFunction. - /// \param Loc Clang source location. - /// \param IVSize Size of the iteration variable in bits. - /// \param IVSigned Sign of the iteration variable. - /// - virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF, - SourceLocation Loc, unsigned IVSize, - bool IVSigned); - - /// Call the appropriate runtime routine to notify that we finished - /// all the work with current loop. - /// - /// \param CGF Reference to current CodeGenFunction. - /// \param Loc Clang source location. - /// \param DKind Kind of the directive for which the static finish is emitted. - /// - virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDirectiveKind DKind); - - /// Call __kmpc_dispatch_next( - /// ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, - /// kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, - /// kmp_int[32|64] *p_stride); - /// \param IVSize Size of the iteration variable in bits. - /// \param IVSigned Sign of the iteration variable. - /// \param IL Address of the output variable in which the flag of the - /// last iteration is returned. - /// \param LB Address of the output variable in which the lower iteration - /// number is returned. - /// \param UB Address of the output variable in which the upper iteration - /// number is returned. - /// \param ST Address of the output variable in which the stride value is - /// returned. - virtual llvm::Value *emitForNext(CodeGenFunction &CGF, SourceLocation Loc, - unsigned IVSize, bool IVSigned, - Address IL, Address LB, - Address UB, Address ST); - - /// Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 - /// global_tid, kmp_int32 num_threads) to generate code for 'num_threads' - /// clause. - /// \param NumThreads An integer value of threads. - virtual void emitNumThreadsClause(CodeGenFunction &CGF, - llvm::Value *NumThreads, - SourceLocation Loc); - - /// Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 - /// global_tid, int proc_bind) to generate code for 'proc_bind' clause. - virtual void emitProcBindClause(CodeGenFunction &CGF, - OpenMPProcBindClauseKind ProcBind, - SourceLocation Loc); - - /// Returns address of the threadprivate variable for the current - /// thread. - /// \param VD Threadprivate variable. - /// \param VDAddr Address of the global variable \a VD. - /// \param Loc Location of the reference to threadprivate var. - /// \return Address of the threadprivate variable for the current thread. - virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF, - const VarDecl *VD, - Address VDAddr, - SourceLocation Loc); - - /// Returns the address of the variable marked as declare target with link - /// clause. - virtual Address getAddrOfDeclareTargetLink(const VarDecl *VD); - - /// Emit a code for initialization of threadprivate variable. It emits - /// a call to runtime library which adds initial value to the newly created - /// threadprivate variable (if it is not constant) and registers destructor - /// for the variable (if any). - /// \param VD Threadprivate variable. - /// \param VDAddr Address of the global variable \a VD. - /// \param Loc Location of threadprivate declaration. - /// \param PerformInit true if initialization expression is not constant. - virtual llvm::Function * - emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, - SourceLocation Loc, bool PerformInit, - CodeGenFunction *CGF = nullptr); - - /// Emit a code for initialization of declare target variable. - /// \param VD Declare target variable. - /// \param Addr Address of the global variable \a VD. - /// \param PerformInit true if initialization expression is not constant. - virtual bool emitDeclareTargetVarDefinition(const VarDecl *VD, - llvm::GlobalVariable *Addr, - bool PerformInit); - - /// Creates artificial threadprivate variable with name \p Name and type \p - /// VarType. - /// \param VarType Type of the artificial threadprivate variable. - /// \param Name Name of the artificial threadprivate variable. - virtual Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, - QualType VarType, - StringRef Name); - - /// Emit flush of the variables specified in 'omp flush' directive. - /// \param Vars List of variables to flush. - virtual void emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *> Vars, - SourceLocation Loc); - - /// Emit task region for the task directive. The task region is - /// emitted in several steps: - /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 - /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, - /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the - /// function: - /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { - /// TaskFunction(gtid, tt->part_id, tt->shareds); - /// return 0; - /// } - /// 2. Copy a list of shared variables to field shareds of the resulting - /// structure kmp_task_t returned by the previous call (if any). - /// 3. Copy a pointer to destructions function to field destructions of the - /// resulting structure kmp_task_t. - /// 4. Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, - /// kmp_task_t *new_task), where new_task is a resulting structure from - /// previous items. - /// \param D Current task directive. - /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32 - /// /*part_id*/, captured_struct */*__context*/); - /// \param SharedsTy A type which contains references the shared variables. - /// \param Shareds Context with the list of shared variables from the \p - /// TaskFunction. - /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr - /// otherwise. - /// \param Data Additional data for task generation like tiednsee, final - /// state, list of privates etc. - virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, - const OMPExecutableDirective &D, - llvm::Value *TaskFunction, QualType SharedsTy, - Address Shareds, const Expr *IfCond, - const OMPTaskDataTy &Data); - - /// Emit task region for the taskloop directive. The taskloop region is - /// emitted in several steps: - /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 - /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, - /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the - /// function: - /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { - /// TaskFunction(gtid, tt->part_id, tt->shareds); - /// return 0; - /// } - /// 2. Copy a list of shared variables to field shareds of the resulting - /// structure kmp_task_t returned by the previous call (if any). - /// 3. Copy a pointer to destructions function to field destructions of the - /// resulting structure kmp_task_t. - /// 4. Emit a call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t - /// *task, int if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int - /// nogroup, int sched, kmp_uint64 grainsize, void *task_dup ), where new_task - /// is a resulting structure from - /// previous items. - /// \param D Current task directive. - /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32 - /// /*part_id*/, captured_struct */*__context*/); - /// \param SharedsTy A type which contains references the shared variables. - /// \param Shareds Context with the list of shared variables from the \p - /// TaskFunction. - /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr - /// otherwise. - /// \param Data Additional data for task generation like tiednsee, final - /// state, list of privates etc. - virtual void emitTaskLoopCall( - CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, - llvm::Value *TaskFunction, QualType SharedsTy, Address Shareds, - const Expr *IfCond, const OMPTaskDataTy &Data); - - /// Emit code for the directive that does not require outlining. - /// - /// \param InnermostKind Kind of innermost directive (for simple directives it - /// is a directive itself, for combined - its innermost directive). - /// \param CodeGen Code generation sequence for the \a D directive. - /// \param HasCancel true if region has inner cancel directive, false - /// otherwise. - virtual void emitInlinedDirective(CodeGenFunction &CGF, - OpenMPDirectiveKind InnermostKind, - const RegionCodeGenTy &CodeGen, - bool HasCancel = false); - - /// Emits reduction function. - /// \param ArgsType Array type containing pointers to reduction variables. - /// \param Privates List of private copies for original reduction arguments. - /// \param LHSExprs List of LHS in \a ReductionOps reduction operations. - /// \param RHSExprs List of RHS in \a ReductionOps reduction operations. - /// \param ReductionOps List of reduction operations in form 'LHS binop RHS' - /// or 'operator binop(LHS, RHS)'. - llvm::Value *emitReductionFunction(CodeGenModule &CGM, SourceLocation Loc, - llvm::Type *ArgsType, - ArrayRef<const Expr *> Privates, - ArrayRef<const Expr *> LHSExprs, - ArrayRef<const Expr *> RHSExprs, - ArrayRef<const Expr *> ReductionOps); - - /// Emits single reduction combiner - void emitSingleReductionCombiner(CodeGenFunction &CGF, - const Expr *ReductionOp, - const Expr *PrivateRef, - const DeclRefExpr *LHS, - const DeclRefExpr *RHS); - - struct ReductionOptionsTy { - bool WithNowait; - bool SimpleReduction; - OpenMPDirectiveKind ReductionKind; - }; - /// Emit a code for reduction clause. Next code should be emitted for - /// reduction: - /// \code - /// - /// static kmp_critical_name lock = { 0 }; - /// - /// void reduce_func(void *lhs[<n>], void *rhs[<n>]) { - /// ... - /// *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); - /// ... - /// } - /// - /// ... - /// void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; - /// switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), - /// RedList, reduce_func, &<lock>)) { - /// case 1: - /// ... - /// <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); - /// ... - /// __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); - /// break; - /// case 2: - /// ... - /// Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); - /// ... - /// break; - /// default:; - /// } - /// \endcode - /// - /// \param Privates List of private copies for original reduction arguments. - /// \param LHSExprs List of LHS in \a ReductionOps reduction operations. - /// \param RHSExprs List of RHS in \a ReductionOps reduction operations. - /// \param ReductionOps List of reduction operations in form 'LHS binop RHS' - /// or 'operator binop(LHS, RHS)'. - /// \param Options List of options for reduction codegen: - /// WithNowait true if parent directive has also nowait clause, false - /// otherwise. - /// SimpleReduction Emit reduction operation only. Used for omp simd - /// directive on the host. - /// ReductionKind The kind of reduction to perform. - virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, - ArrayRef<const Expr *> Privates, - ArrayRef<const Expr *> LHSExprs, - ArrayRef<const Expr *> RHSExprs, - ArrayRef<const Expr *> ReductionOps, - ReductionOptionsTy Options); - - /// Emit a code for initialization of task reduction clause. Next code - /// should be emitted for reduction: - /// \code - /// - /// _task_red_item_t red_data[n]; - /// ... - /// red_data[i].shar = &origs[i]; - /// red_data[i].size = sizeof(origs[i]); - /// red_data[i].f_init = (void*)RedInit<i>; - /// red_data[i].f_fini = (void*)RedDest<i>; - /// red_data[i].f_comb = (void*)RedOp<i>; - /// red_data[i].flags = <Flag_i>; - /// ... - /// void* tg1 = __kmpc_task_reduction_init(gtid, n, red_data); - /// \endcode - /// - /// \param LHSExprs List of LHS in \a Data.ReductionOps reduction operations. - /// \param RHSExprs List of RHS in \a Data.ReductionOps reduction operations. - /// \param Data Additional data for task generation like tiedness, final - /// state, list of privates, reductions etc. - virtual llvm::Value *emitTaskReductionInit(CodeGenFunction &CGF, - SourceLocation Loc, - ArrayRef<const Expr *> LHSExprs, - ArrayRef<const Expr *> RHSExprs, - const OMPTaskDataTy &Data); - - /// Required to resolve existing problems in the runtime. Emits threadprivate - /// variables to store the size of the VLAs/array sections for - /// initializer/combiner/finalizer functions + emits threadprivate variable to - /// store the pointer to the original reduction item for the custom - /// initializer defined by declare reduction construct. - /// \param RCG Allows to reuse an existing data for the reductions. - /// \param N Reduction item for which fixups must be emitted. - virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, - ReductionCodeGen &RCG, unsigned N); - - /// Get the address of `void *` type of the privatue copy of the reduction - /// item specified by the \p SharedLVal. - /// \param ReductionsPtr Pointer to the reduction data returned by the - /// emitTaskReductionInit function. - /// \param SharedLVal Address of the original reduction item. - virtual Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, - llvm::Value *ReductionsPtr, - LValue SharedLVal); - - /// Emit code for 'taskwait' directive. - virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc); - - /// Emit code for 'cancellation point' construct. - /// \param CancelRegion Region kind for which the cancellation point must be - /// emitted. - /// - virtual void emitCancellationPointCall(CodeGenFunction &CGF, - SourceLocation Loc, - OpenMPDirectiveKind CancelRegion); - - /// Emit code for 'cancel' construct. - /// \param IfCond Condition in the associated 'if' clause, if it was - /// specified, nullptr otherwise. - /// \param CancelRegion Region kind for which the cancel must be emitted. - /// - virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, - const Expr *IfCond, - OpenMPDirectiveKind CancelRegion); - - /// Emit outilined function for 'target' directive. - /// \param D Directive to emit. - /// \param ParentName Name of the function that encloses the target region. - /// \param OutlinedFn Outlined function value to be defined by this call. - /// \param OutlinedFnID Outlined function ID value to be defined by this call. - /// \param IsOffloadEntry True if the outlined function is an offload entry. - /// \param CodeGen Code generation sequence for the \a D directive. - /// An outlined function may not be an entry if, e.g. the if clause always - /// evaluates to false. - virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, - StringRef ParentName, - llvm::Function *&OutlinedFn, - llvm::Constant *&OutlinedFnID, - bool IsOffloadEntry, - const RegionCodeGenTy &CodeGen); - - /// Emit code that pushes the trip count of loops associated with constructs - /// 'target teams distribute' and 'teams distribute parallel for'. - /// \param SizeEmitter Emits the int64 value for the number of iterations of - /// the associated loop. - virtual void emitTargetNumIterationsCall( - CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *Device, - const llvm::function_ref<llvm::Value *( - CodeGenFunction &CGF, const OMPLoopDirective &D)> &SizeEmitter); - - /// Emit the target offloading code associated with \a D. The emitted - /// code attempts offloading the execution to the device, an the event of - /// a failure it executes the host version outlined in \a OutlinedFn. - /// \param D Directive to emit. - /// \param OutlinedFn Host version of the code to be offloaded. - /// \param OutlinedFnID ID of host version of the code to be offloaded. - /// \param IfCond Expression evaluated in if clause associated with the target - /// directive, or null if no if clause is used. - /// \param Device Expression evaluated in device clause associated with the - /// target directive, or null if no device clause is used. - virtual void emitTargetCall(CodeGenFunction &CGF, - const OMPExecutableDirective &D, - llvm::Value *OutlinedFn, - llvm::Value *OutlinedFnID, const Expr *IfCond, - const Expr *Device); - - /// Emit the target regions enclosed in \a GD function definition or - /// the function itself in case it is a valid device function. Returns true if - /// \a GD was dealt with successfully. - /// \param GD Function to scan. - virtual bool emitTargetFunctions(GlobalDecl GD); - - /// Emit the global variable if it is a valid device global variable. - /// Returns true if \a GD was dealt with successfully. - /// \param GD Variable declaration to emit. - virtual bool emitTargetGlobalVariable(GlobalDecl GD); - - /// Checks if the provided global decl \a GD is a declare target variable and - /// registers it when emitting code for the host. - virtual void registerTargetGlobalVariable(const VarDecl *VD, - llvm::Constant *Addr); - - /// Emit the global \a GD if it is meaningful for the target. Returns - /// if it was emitted successfully. - /// \param GD Global to scan. - virtual bool emitTargetGlobal(GlobalDecl GD); - - /// Creates the offloading descriptor in the event any target region - /// was emitted in the current module and return the function that registers - /// it. - virtual llvm::Function *emitRegistrationFunction(); - - /// Emits code for teams call of the \a OutlinedFn with - /// variables captured in a record which address is stored in \a - /// CapturedStruct. - /// \param OutlinedFn Outlined function to be run by team masters. Type of - /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*). - /// \param CapturedVars A pointer to the record with the references to - /// variables used in \a OutlinedFn function. - /// - virtual void emitTeamsCall(CodeGenFunction &CGF, - const OMPExecutableDirective &D, - SourceLocation Loc, llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> CapturedVars); - - /// Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 - /// global_tid, kmp_int32 num_teams, kmp_int32 thread_limit) to generate code - /// for num_teams clause. - /// \param NumTeams An integer expression of teams. - /// \param ThreadLimit An integer expression of threads. - virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, - const Expr *ThreadLimit, SourceLocation Loc); - - /// Struct that keeps all the relevant information that should be kept - /// throughout a 'target data' region. - class TargetDataInfo { - /// Set to true if device pointer information have to be obtained. - bool RequiresDevicePointerInfo = false; - - public: - /// The array of base pointer passed to the runtime library. - llvm::Value *BasePointersArray = nullptr; - /// The array of section pointers passed to the runtime library. - llvm::Value *PointersArray = nullptr; - /// The array of sizes passed to the runtime library. - llvm::Value *SizesArray = nullptr; - /// The array of map types passed to the runtime library. - llvm::Value *MapTypesArray = nullptr; - /// The total number of pointers passed to the runtime library. - unsigned NumberOfPtrs = 0u; - /// Map between the a declaration of a capture and the corresponding base - /// pointer address where the runtime returns the device pointers. - llvm::DenseMap<const ValueDecl *, Address> CaptureDeviceAddrMap; - - explicit TargetDataInfo() {} - explicit TargetDataInfo(bool RequiresDevicePointerInfo) - : RequiresDevicePointerInfo(RequiresDevicePointerInfo) {} - /// Clear information about the data arrays. - void clearArrayInfo() { - BasePointersArray = nullptr; - PointersArray = nullptr; - SizesArray = nullptr; - MapTypesArray = nullptr; - NumberOfPtrs = 0u; - } - /// Return true if the current target data information has valid arrays. - bool isValid() { - return BasePointersArray && PointersArray && SizesArray && - MapTypesArray && NumberOfPtrs; - } - bool requiresDevicePointerInfo() { return RequiresDevicePointerInfo; } - }; - - /// Emit the target data mapping code associated with \a D. - /// \param D Directive to emit. - /// \param IfCond Expression evaluated in if clause associated with the - /// target directive, or null if no device clause is used. - /// \param Device Expression evaluated in device clause associated with the - /// target directive, or null if no device clause is used. - /// \param Info A record used to store information that needs to be preserved - /// until the region is closed. - virtual void emitTargetDataCalls(CodeGenFunction &CGF, - const OMPExecutableDirective &D, - const Expr *IfCond, const Expr *Device, - const RegionCodeGenTy &CodeGen, - TargetDataInfo &Info); - - /// Emit the data mapping/movement code associated with the directive - /// \a D that should be of the form 'target [{enter|exit} data | update]'. - /// \param D Directive to emit. - /// \param IfCond Expression evaluated in if clause associated with the target - /// directive, or null if no if clause is used. - /// \param Device Expression evaluated in device clause associated with the - /// target directive, or null if no device clause is used. - virtual void emitTargetDataStandAloneCall(CodeGenFunction &CGF, - const OMPExecutableDirective &D, - const Expr *IfCond, - const Expr *Device); - - /// Marks function \a Fn with properly mangled versions of vector functions. - /// \param FD Function marked as 'declare simd'. - /// \param Fn LLVM function that must be marked with 'declare simd' - /// attributes. - virtual void emitDeclareSimdFunction(const FunctionDecl *FD, - llvm::Function *Fn); - - /// Emit initialization for doacross loop nesting support. - /// \param D Loop-based construct used in doacross nesting construct. - virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, - ArrayRef<Expr *> NumIterations); - - /// Emit code for doacross ordered directive with 'depend' clause. - /// \param C 'depend' clause with 'sink|source' dependency kind. - virtual void emitDoacrossOrdered(CodeGenFunction &CGF, - const OMPDependClause *C); - - /// Translates the native parameter of outlined function if this is required - /// for target. - /// \param FD Field decl from captured record for the parameter. - /// \param NativeParam Parameter itself. - virtual const VarDecl *translateParameter(const FieldDecl *FD, - const VarDecl *NativeParam) const { - return NativeParam; - } - - /// Gets the address of the native argument basing on the address of the - /// target-specific parameter. - /// \param NativeParam Parameter itself. - /// \param TargetParam Corresponding target-specific parameter. - virtual Address getParameterAddress(CodeGenFunction &CGF, - const VarDecl *NativeParam, - const VarDecl *TargetParam) const; - - /// Choose default schedule type and chunk value for the - /// dist_schedule clause. - virtual void getDefaultDistScheduleAndChunk(CodeGenFunction &CGF, - const OMPLoopDirective &S, OpenMPDistScheduleClauseKind &ScheduleKind, - llvm::Value *&Chunk) const {} - - /// Choose default schedule type and chunk value for the - /// schedule clause. - virtual void getDefaultScheduleAndChunk(CodeGenFunction &CGF, - const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind, - const Expr *&ChunkExpr) const {} - - /// Emits call of the outlined function with the provided arguments, - /// translating these arguments to correct target-specific arguments. - virtual void - emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc, - llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> Args = llvm::None) const; - - /// Emits OpenMP-specific function prolog. - /// Required for device constructs. - virtual void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) {} - - /// Gets the OpenMP-specific address of the local variable. - virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF, - const VarDecl *VD); - - /// Marks the declaration as already emitted for the device code and returns - /// true, if it was marked already, and false, otherwise. - bool markAsGlobalTarget(GlobalDecl GD); - - /// Emit deferred declare target variables marked for deferred emission. - void emitDeferredTargetDecls() const; - - /// Adjust some parameters for the target-based directives, like addresses of - /// the variables captured by reference in lambdas. - virtual void - adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF, - const OMPExecutableDirective &D) const; - - /// Perform check on requires decl to ensure that target architecture - /// supports unified addressing - virtual void checkArchForUnifiedAddressing(CodeGenModule &CGM, - const OMPRequiresDecl *D) const {} -}; - -/// Class supports emissionof SIMD-only code. -class CGOpenMPSIMDRuntime final : public CGOpenMPRuntime { -public: - explicit CGOpenMPSIMDRuntime(CodeGenModule &CGM) : CGOpenMPRuntime(CGM) {} - ~CGOpenMPSIMDRuntime() override {} - - /// Emits outlined function for the specified OpenMP parallel directive - /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID, - /// kmp_int32 BoundID, struct context_vars*). - /// \param D OpenMP directive. - /// \param ThreadIDVar Variable for thread id in the current OpenMP region. - /// \param InnermostKind Kind of innermost directive (for simple directives it - /// is a directive itself, for combined - its innermost directive). - /// \param CodeGen Code generation sequence for the \a D directive. - llvm::Value * - emitParallelOutlinedFunction(const OMPExecutableDirective &D, - const VarDecl *ThreadIDVar, - OpenMPDirectiveKind InnermostKind, - const RegionCodeGenTy &CodeGen) override; - - /// Emits outlined function for the specified OpenMP teams directive - /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID, - /// kmp_int32 BoundID, struct context_vars*). - /// \param D OpenMP directive. - /// \param ThreadIDVar Variable for thread id in the current OpenMP region. - /// \param InnermostKind Kind of innermost directive (for simple directives it - /// is a directive itself, for combined - its innermost directive). - /// \param CodeGen Code generation sequence for the \a D directive. - llvm::Value * - emitTeamsOutlinedFunction(const OMPExecutableDirective &D, - const VarDecl *ThreadIDVar, - OpenMPDirectiveKind InnermostKind, - const RegionCodeGenTy &CodeGen) override; - - /// Emits outlined function for the OpenMP task directive \a D. This - /// outlined function has type void(*)(kmp_int32 ThreadID, struct task_t* - /// TaskT). - /// \param D OpenMP directive. - /// \param ThreadIDVar Variable for thread id in the current OpenMP region. - /// \param PartIDVar Variable for partition id in the current OpenMP untied - /// task region. - /// \param TaskTVar Variable for task_t argument. - /// \param InnermostKind Kind of innermost directive (for simple directives it - /// is a directive itself, for combined - its innermost directive). - /// \param CodeGen Code generation sequence for the \a D directive. - /// \param Tied true if task is generated for tied task, false otherwise. - /// \param NumberOfParts Number of parts in untied task. Ignored for tied - /// tasks. - /// - llvm::Value *emitTaskOutlinedFunction( - const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, - const VarDecl *PartIDVar, const VarDecl *TaskTVar, - OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, - bool Tied, unsigned &NumberOfParts) override; - - /// Emits code for parallel or serial call of the \a OutlinedFn with - /// variables captured in a record which address is stored in \a - /// CapturedStruct. - /// \param OutlinedFn Outlined function to be run in parallel threads. Type of - /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*). - /// \param CapturedVars A pointer to the record with the references to - /// variables used in \a OutlinedFn function. - /// \param IfCond Condition in the associated 'if' clause, if it was - /// specified, nullptr otherwise. - /// - void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, - llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> CapturedVars, - const Expr *IfCond) override; - - /// Emits a critical region. - /// \param CriticalName Name of the critical region. - /// \param CriticalOpGen Generator for the statement associated with the given - /// critical region. - /// \param Hint Value of the 'hint' clause (optional). - void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, - const RegionCodeGenTy &CriticalOpGen, - SourceLocation Loc, - const Expr *Hint = nullptr) override; - - /// Emits a master region. - /// \param MasterOpGen Generator for the statement associated with the given - /// master region. - void emitMasterRegion(CodeGenFunction &CGF, - const RegionCodeGenTy &MasterOpGen, - SourceLocation Loc) override; - - /// Emits code for a taskyield directive. - void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override; - - /// Emit a taskgroup region. - /// \param TaskgroupOpGen Generator for the statement associated with the - /// given taskgroup region. - void emitTaskgroupRegion(CodeGenFunction &CGF, - const RegionCodeGenTy &TaskgroupOpGen, - SourceLocation Loc) override; - - /// Emits a single region. - /// \param SingleOpGen Generator for the statement associated with the given - /// single region. - void emitSingleRegion(CodeGenFunction &CGF, - const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, - ArrayRef<const Expr *> CopyprivateVars, - ArrayRef<const Expr *> DestExprs, - ArrayRef<const Expr *> SrcExprs, - ArrayRef<const Expr *> AssignmentOps) override; - - /// Emit an ordered region. - /// \param OrderedOpGen Generator for the statement associated with the given - /// ordered region. - void emitOrderedRegion(CodeGenFunction &CGF, - const RegionCodeGenTy &OrderedOpGen, - SourceLocation Loc, bool IsThreads) override; - - /// Emit an implicit/explicit barrier for OpenMP threads. - /// \param Kind Directive for which this implicit barrier call must be - /// generated. Must be OMPD_barrier for explicit barrier generation. - /// \param EmitChecks true if need to emit checks for cancellation barriers. - /// \param ForceSimpleCall true simple barrier call must be emitted, false if - /// runtime class decides which one to emit (simple or with cancellation - /// checks). - /// - void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDirectiveKind Kind, bool EmitChecks = true, - bool ForceSimpleCall = false) override; - - /// This is used for non static scheduled types and when the ordered - /// clause is present on the loop construct. - /// Depending on the loop schedule, it is necessary to call some runtime - /// routine before start of the OpenMP loop to get the loop upper / lower - /// bounds \a LB and \a UB and stride \a ST. - /// - /// \param CGF Reference to current CodeGenFunction. - /// \param Loc Clang source location. - /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause. - /// \param IVSize Size of the iteration variable in bits. - /// \param IVSigned Sign of the iteration variable. - /// \param Ordered true if loop is ordered, false otherwise. - /// \param DispatchValues struct containing llvm values for lower bound, upper - /// bound, and chunk expression. - /// For the default (nullptr) value, the chunk 1 will be used. - /// - void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, - const OpenMPScheduleTy &ScheduleKind, - unsigned IVSize, bool IVSigned, bool Ordered, - const DispatchRTInput &DispatchValues) override; - - /// Call the appropriate runtime routine to initialize it before start - /// of loop. - /// - /// This is used only in case of static schedule, when the user did not - /// specify a ordered clause on the loop construct. - /// Depending on the loop schedule, it is necessary to call some runtime - /// routine before start of the OpenMP loop to get the loop upper / lower - /// bounds LB and UB and stride ST. - /// - /// \param CGF Reference to current CodeGenFunction. - /// \param Loc Clang source location. - /// \param DKind Kind of the directive. - /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause. - /// \param Values Input arguments for the construct. - /// - void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDirectiveKind DKind, - const OpenMPScheduleTy &ScheduleKind, - const StaticRTInput &Values) override; - - /// - /// \param CGF Reference to current CodeGenFunction. - /// \param Loc Clang source location. - /// \param SchedKind Schedule kind, specified by the 'dist_schedule' clause. - /// \param Values Input arguments for the construct. - /// - void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDistScheduleClauseKind SchedKind, - const StaticRTInput &Values) override; - - /// Call the appropriate runtime routine to notify that we finished - /// iteration of the ordered loop with the dynamic scheduling. - /// - /// \param CGF Reference to current CodeGenFunction. - /// \param Loc Clang source location. - /// \param IVSize Size of the iteration variable in bits. - /// \param IVSigned Sign of the iteration variable. - /// - void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, - unsigned IVSize, bool IVSigned) override; - - /// Call the appropriate runtime routine to notify that we finished - /// all the work with current loop. - /// - /// \param CGF Reference to current CodeGenFunction. - /// \param Loc Clang source location. - /// \param DKind Kind of the directive for which the static finish is emitted. - /// - void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDirectiveKind DKind) override; - - /// Call __kmpc_dispatch_next( - /// ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, - /// kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, - /// kmp_int[32|64] *p_stride); - /// \param IVSize Size of the iteration variable in bits. - /// \param IVSigned Sign of the iteration variable. - /// \param IL Address of the output variable in which the flag of the - /// last iteration is returned. - /// \param LB Address of the output variable in which the lower iteration - /// number is returned. - /// \param UB Address of the output variable in which the upper iteration - /// number is returned. - /// \param ST Address of the output variable in which the stride value is - /// returned. - llvm::Value *emitForNext(CodeGenFunction &CGF, SourceLocation Loc, - unsigned IVSize, bool IVSigned, Address IL, - Address LB, Address UB, Address ST) override; - - /// Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 - /// global_tid, kmp_int32 num_threads) to generate code for 'num_threads' - /// clause. - /// \param NumThreads An integer value of threads. - void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, - SourceLocation Loc) override; - - /// Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 - /// global_tid, int proc_bind) to generate code for 'proc_bind' clause. - void emitProcBindClause(CodeGenFunction &CGF, - OpenMPProcBindClauseKind ProcBind, - SourceLocation Loc) override; - - /// Returns address of the threadprivate variable for the current - /// thread. - /// \param VD Threadprivate variable. - /// \param VDAddr Address of the global variable \a VD. - /// \param Loc Location of the reference to threadprivate var. - /// \return Address of the threadprivate variable for the current thread. - Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, - Address VDAddr, SourceLocation Loc) override; - - /// Emit a code for initialization of threadprivate variable. It emits - /// a call to runtime library which adds initial value to the newly created - /// threadprivate variable (if it is not constant) and registers destructor - /// for the variable (if any). - /// \param VD Threadprivate variable. - /// \param VDAddr Address of the global variable \a VD. - /// \param Loc Location of threadprivate declaration. - /// \param PerformInit true if initialization expression is not constant. - llvm::Function * - emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, - SourceLocation Loc, bool PerformInit, - CodeGenFunction *CGF = nullptr) override; - - /// Creates artificial threadprivate variable with name \p Name and type \p - /// VarType. - /// \param VarType Type of the artificial threadprivate variable. - /// \param Name Name of the artificial threadprivate variable. - Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, - QualType VarType, - StringRef Name) override; - - /// Emit flush of the variables specified in 'omp flush' directive. - /// \param Vars List of variables to flush. - void emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *> Vars, - SourceLocation Loc) override; - - /// Emit task region for the task directive. The task region is - /// emitted in several steps: - /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 - /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, - /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the - /// function: - /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { - /// TaskFunction(gtid, tt->part_id, tt->shareds); - /// return 0; - /// } - /// 2. Copy a list of shared variables to field shareds of the resulting - /// structure kmp_task_t returned by the previous call (if any). - /// 3. Copy a pointer to destructions function to field destructions of the - /// resulting structure kmp_task_t. - /// 4. Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, - /// kmp_task_t *new_task), where new_task is a resulting structure from - /// previous items. - /// \param D Current task directive. - /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32 - /// /*part_id*/, captured_struct */*__context*/); - /// \param SharedsTy A type which contains references the shared variables. - /// \param Shareds Context with the list of shared variables from the \p - /// TaskFunction. - /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr - /// otherwise. - /// \param Data Additional data for task generation like tiednsee, final - /// state, list of privates etc. - void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, - const OMPExecutableDirective &D, llvm::Value *TaskFunction, - QualType SharedsTy, Address Shareds, const Expr *IfCond, - const OMPTaskDataTy &Data) override; - - /// Emit task region for the taskloop directive. The taskloop region is - /// emitted in several steps: - /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 - /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, - /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the - /// function: - /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { - /// TaskFunction(gtid, tt->part_id, tt->shareds); - /// return 0; - /// } - /// 2. Copy a list of shared variables to field shareds of the resulting - /// structure kmp_task_t returned by the previous call (if any). - /// 3. Copy a pointer to destructions function to field destructions of the - /// resulting structure kmp_task_t. - /// 4. Emit a call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t - /// *task, int if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int - /// nogroup, int sched, kmp_uint64 grainsize, void *task_dup ), where new_task - /// is a resulting structure from - /// previous items. - /// \param D Current task directive. - /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32 - /// /*part_id*/, captured_struct */*__context*/); - /// \param SharedsTy A type which contains references the shared variables. - /// \param Shareds Context with the list of shared variables from the \p - /// TaskFunction. - /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr - /// otherwise. - /// \param Data Additional data for task generation like tiednsee, final - /// state, list of privates etc. - void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, - const OMPLoopDirective &D, llvm::Value *TaskFunction, - QualType SharedsTy, Address Shareds, const Expr *IfCond, - const OMPTaskDataTy &Data) override; - - /// Emit a code for reduction clause. Next code should be emitted for - /// reduction: - /// \code - /// - /// static kmp_critical_name lock = { 0 }; - /// - /// void reduce_func(void *lhs[<n>], void *rhs[<n>]) { - /// ... - /// *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); - /// ... - /// } - /// - /// ... - /// void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; - /// switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), - /// RedList, reduce_func, &<lock>)) { - /// case 1: - /// ... - /// <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); - /// ... - /// __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); - /// break; - /// case 2: - /// ... - /// Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); - /// ... - /// break; - /// default:; - /// } - /// \endcode - /// - /// \param Privates List of private copies for original reduction arguments. - /// \param LHSExprs List of LHS in \a ReductionOps reduction operations. - /// \param RHSExprs List of RHS in \a ReductionOps reduction operations. - /// \param ReductionOps List of reduction operations in form 'LHS binop RHS' - /// or 'operator binop(LHS, RHS)'. - /// \param Options List of options for reduction codegen: - /// WithNowait true if parent directive has also nowait clause, false - /// otherwise. - /// SimpleReduction Emit reduction operation only. Used for omp simd - /// directive on the host. - /// ReductionKind The kind of reduction to perform. - void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, - ArrayRef<const Expr *> Privates, - ArrayRef<const Expr *> LHSExprs, - ArrayRef<const Expr *> RHSExprs, - ArrayRef<const Expr *> ReductionOps, - ReductionOptionsTy Options) override; - - /// Emit a code for initialization of task reduction clause. Next code - /// should be emitted for reduction: - /// \code - /// - /// _task_red_item_t red_data[n]; - /// ... - /// red_data[i].shar = &origs[i]; - /// red_data[i].size = sizeof(origs[i]); - /// red_data[i].f_init = (void*)RedInit<i>; - /// red_data[i].f_fini = (void*)RedDest<i>; - /// red_data[i].f_comb = (void*)RedOp<i>; - /// red_data[i].flags = <Flag_i>; - /// ... - /// void* tg1 = __kmpc_task_reduction_init(gtid, n, red_data); - /// \endcode - /// - /// \param LHSExprs List of LHS in \a Data.ReductionOps reduction operations. - /// \param RHSExprs List of RHS in \a Data.ReductionOps reduction operations. - /// \param Data Additional data for task generation like tiedness, final - /// state, list of privates, reductions etc. - llvm::Value *emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, - ArrayRef<const Expr *> LHSExprs, - ArrayRef<const Expr *> RHSExprs, - const OMPTaskDataTy &Data) override; - - /// Required to resolve existing problems in the runtime. Emits threadprivate - /// variables to store the size of the VLAs/array sections for - /// initializer/combiner/finalizer functions + emits threadprivate variable to - /// store the pointer to the original reduction item for the custom - /// initializer defined by declare reduction construct. - /// \param RCG Allows to reuse an existing data for the reductions. - /// \param N Reduction item for which fixups must be emitted. - void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, - ReductionCodeGen &RCG, unsigned N) override; - - /// Get the address of `void *` type of the privatue copy of the reduction - /// item specified by the \p SharedLVal. - /// \param ReductionsPtr Pointer to the reduction data returned by the - /// emitTaskReductionInit function. - /// \param SharedLVal Address of the original reduction item. - Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, - llvm::Value *ReductionsPtr, - LValue SharedLVal) override; - - /// Emit code for 'taskwait' directive. - void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc) override; - - /// Emit code for 'cancellation point' construct. - /// \param CancelRegion Region kind for which the cancellation point must be - /// emitted. - /// - void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDirectiveKind CancelRegion) override; - - /// Emit code for 'cancel' construct. - /// \param IfCond Condition in the associated 'if' clause, if it was - /// specified, nullptr otherwise. - /// \param CancelRegion Region kind for which the cancel must be emitted. - /// - void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, - const Expr *IfCond, - OpenMPDirectiveKind CancelRegion) override; - - /// Emit outilined function for 'target' directive. - /// \param D Directive to emit. - /// \param ParentName Name of the function that encloses the target region. - /// \param OutlinedFn Outlined function value to be defined by this call. - /// \param OutlinedFnID Outlined function ID value to be defined by this call. - /// \param IsOffloadEntry True if the outlined function is an offload entry. - /// \param CodeGen Code generation sequence for the \a D directive. - /// An outlined function may not be an entry if, e.g. the if clause always - /// evaluates to false. - void emitTargetOutlinedFunction(const OMPExecutableDirective &D, - StringRef ParentName, - llvm::Function *&OutlinedFn, - llvm::Constant *&OutlinedFnID, - bool IsOffloadEntry, - const RegionCodeGenTy &CodeGen) override; - - /// Emit the target offloading code associated with \a D. The emitted - /// code attempts offloading the execution to the device, an the event of - /// a failure it executes the host version outlined in \a OutlinedFn. - /// \param D Directive to emit. - /// \param OutlinedFn Host version of the code to be offloaded. - /// \param OutlinedFnID ID of host version of the code to be offloaded. - /// \param IfCond Expression evaluated in if clause associated with the target - /// directive, or null if no if clause is used. - /// \param Device Expression evaluated in device clause associated with the - /// target directive, or null if no device clause is used. - void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, - llvm::Value *OutlinedFn, llvm::Value *OutlinedFnID, - const Expr *IfCond, const Expr *Device) override; - - /// Emit the target regions enclosed in \a GD function definition or - /// the function itself in case it is a valid device function. Returns true if - /// \a GD was dealt with successfully. - /// \param GD Function to scan. - bool emitTargetFunctions(GlobalDecl GD) override; - - /// Emit the global variable if it is a valid device global variable. - /// Returns true if \a GD was dealt with successfully. - /// \param GD Variable declaration to emit. - bool emitTargetGlobalVariable(GlobalDecl GD) override; - - /// Emit the global \a GD if it is meaningful for the target. Returns - /// if it was emitted successfully. - /// \param GD Global to scan. - bool emitTargetGlobal(GlobalDecl GD) override; - - /// Creates the offloading descriptor in the event any target region - /// was emitted in the current module and return the function that registers - /// it. - llvm::Function *emitRegistrationFunction() override; - - /// Emits code for teams call of the \a OutlinedFn with - /// variables captured in a record which address is stored in \a - /// CapturedStruct. - /// \param OutlinedFn Outlined function to be run by team masters. Type of - /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*). - /// \param CapturedVars A pointer to the record with the references to - /// variables used in \a OutlinedFn function. - /// - void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, - SourceLocation Loc, llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> CapturedVars) override; - - /// Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 - /// global_tid, kmp_int32 num_teams, kmp_int32 thread_limit) to generate code - /// for num_teams clause. - /// \param NumTeams An integer expression of teams. - /// \param ThreadLimit An integer expression of threads. - void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, - const Expr *ThreadLimit, SourceLocation Loc) override; - - /// Emit the target data mapping code associated with \a D. - /// \param D Directive to emit. - /// \param IfCond Expression evaluated in if clause associated with the - /// target directive, or null if no device clause is used. - /// \param Device Expression evaluated in device clause associated with the - /// target directive, or null if no device clause is used. - /// \param Info A record used to store information that needs to be preserved - /// until the region is closed. - void emitTargetDataCalls(CodeGenFunction &CGF, - const OMPExecutableDirective &D, const Expr *IfCond, - const Expr *Device, const RegionCodeGenTy &CodeGen, - TargetDataInfo &Info) override; - - /// Emit the data mapping/movement code associated with the directive - /// \a D that should be of the form 'target [{enter|exit} data | update]'. - /// \param D Directive to emit. - /// \param IfCond Expression evaluated in if clause associated with the target - /// directive, or null if no if clause is used. - /// \param Device Expression evaluated in device clause associated with the - /// target directive, or null if no device clause is used. - void emitTargetDataStandAloneCall(CodeGenFunction &CGF, - const OMPExecutableDirective &D, - const Expr *IfCond, - const Expr *Device) override; - - /// Emit initialization for doacross loop nesting support. - /// \param D Loop-based construct used in doacross nesting construct. - void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, - ArrayRef<Expr *> NumIterations) override; - - /// Emit code for doacross ordered directive with 'depend' clause. - /// \param C 'depend' clause with 'sink|source' dependency kind. - void emitDoacrossOrdered(CodeGenFunction &CGF, - const OMPDependClause *C) override; - - /// Translates the native parameter of outlined function if this is required - /// for target. - /// \param FD Field decl from captured record for the parameter. - /// \param NativeParam Parameter itself. - const VarDecl *translateParameter(const FieldDecl *FD, - const VarDecl *NativeParam) const override; - - /// Gets the address of the native argument basing on the address of the - /// target-specific parameter. - /// \param NativeParam Parameter itself. - /// \param TargetParam Corresponding target-specific parameter. - Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, - const VarDecl *TargetParam) const override; -}; - -} // namespace CodeGen -} // namespace clang - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp deleted file mode 100644 index 7046ab3aa35..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp +++ /dev/null @@ -1,4604 +0,0 @@ -//===---- CGOpenMPRuntimeNVPTX.cpp - Interface to OpenMP NVPTX Runtimes ---===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This provides a class for OpenMP runtime code generation specialized to NVPTX -// targets. -// -//===----------------------------------------------------------------------===// - -#include "CGOpenMPRuntimeNVPTX.h" -#include "CodeGenFunction.h" -#include "clang/AST/DeclOpenMP.h" -#include "clang/AST/StmtOpenMP.h" -#include "clang/AST/StmtVisitor.h" -#include "clang/Basic/Cuda.h" -#include "llvm/ADT/SmallPtrSet.h" - -using namespace clang; -using namespace CodeGen; - -namespace { -enum OpenMPRTLFunctionNVPTX { - /// Call to void __kmpc_kernel_init(kmp_int32 thread_limit, - /// int16_t RequiresOMPRuntime); - OMPRTL_NVPTX__kmpc_kernel_init, - /// Call to void __kmpc_kernel_deinit(int16_t IsOMPRuntimeInitialized); - OMPRTL_NVPTX__kmpc_kernel_deinit, - /// Call to void __kmpc_spmd_kernel_init(kmp_int32 thread_limit, - /// int16_t RequiresOMPRuntime, int16_t RequiresDataSharing); - OMPRTL_NVPTX__kmpc_spmd_kernel_init, - /// Call to void __kmpc_spmd_kernel_deinit_v2(int16_t RequiresOMPRuntime); - OMPRTL_NVPTX__kmpc_spmd_kernel_deinit_v2, - /// Call to void __kmpc_kernel_prepare_parallel(void - /// *outlined_function, int16_t - /// IsOMPRuntimeInitialized); - OMPRTL_NVPTX__kmpc_kernel_prepare_parallel, - /// Call to bool __kmpc_kernel_parallel(void **outlined_function, - /// int16_t IsOMPRuntimeInitialized); - OMPRTL_NVPTX__kmpc_kernel_parallel, - /// Call to void __kmpc_kernel_end_parallel(); - OMPRTL_NVPTX__kmpc_kernel_end_parallel, - /// Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 - /// global_tid); - OMPRTL_NVPTX__kmpc_serialized_parallel, - /// Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 - /// global_tid); - OMPRTL_NVPTX__kmpc_end_serialized_parallel, - /// Call to int32_t __kmpc_shuffle_int32(int32_t element, - /// int16_t lane_offset, int16_t warp_size); - OMPRTL_NVPTX__kmpc_shuffle_int32, - /// Call to int64_t __kmpc_shuffle_int64(int64_t element, - /// int16_t lane_offset, int16_t warp_size); - OMPRTL_NVPTX__kmpc_shuffle_int64, - /// Call to __kmpc_nvptx_parallel_reduce_nowait_v2(ident_t *loc, kmp_int32 - /// global_tid, kmp_int32 num_vars, size_t reduce_size, void* reduce_data, - /// void (*kmp_ShuffleReductFctPtr)(void *rhsData, int16_t lane_id, int16_t - /// lane_offset, int16_t shortCircuit), - /// void (*kmp_InterWarpCopyFctPtr)(void* src, int32_t warp_num)); - OMPRTL_NVPTX__kmpc_parallel_reduce_nowait_v2, - /// Call to __kmpc_nvptx_teams_reduce_nowait_simple(ident_t *loc, kmp_int32 - /// global_tid, kmp_critical_name *lck) - OMPRTL_NVPTX__kmpc_nvptx_teams_reduce_nowait_simple, - /// Call to __kmpc_nvptx_teams_end_reduce_nowait_simple(ident_t *loc, - /// kmp_int32 global_tid, kmp_critical_name *lck) - OMPRTL_NVPTX__kmpc_nvptx_teams_end_reduce_nowait_simple, - /// Call to __kmpc_nvptx_end_reduce_nowait(int32_t global_tid); - OMPRTL_NVPTX__kmpc_end_reduce_nowait, - /// Call to void __kmpc_data_sharing_init_stack(); - OMPRTL_NVPTX__kmpc_data_sharing_init_stack, - /// Call to void __kmpc_data_sharing_init_stack_spmd(); - OMPRTL_NVPTX__kmpc_data_sharing_init_stack_spmd, - /// Call to void* __kmpc_data_sharing_coalesced_push_stack(size_t size, - /// int16_t UseSharedMemory); - OMPRTL_NVPTX__kmpc_data_sharing_coalesced_push_stack, - /// Call to void __kmpc_data_sharing_pop_stack(void *a); - OMPRTL_NVPTX__kmpc_data_sharing_pop_stack, - /// Call to void __kmpc_begin_sharing_variables(void ***args, - /// size_t n_args); - OMPRTL_NVPTX__kmpc_begin_sharing_variables, - /// Call to void __kmpc_end_sharing_variables(); - OMPRTL_NVPTX__kmpc_end_sharing_variables, - /// Call to void __kmpc_get_shared_variables(void ***GlobalArgs) - OMPRTL_NVPTX__kmpc_get_shared_variables, - /// Call to uint16_t __kmpc_parallel_level(ident_t *loc, kmp_int32 - /// global_tid); - OMPRTL_NVPTX__kmpc_parallel_level, - /// Call to int8_t __kmpc_is_spmd_exec_mode(); - OMPRTL_NVPTX__kmpc_is_spmd_exec_mode, - /// Call to void __kmpc_get_team_static_memory(int16_t isSPMDExecutionMode, - /// const void *buf, size_t size, int16_t is_shared, const void **res); - OMPRTL_NVPTX__kmpc_get_team_static_memory, - /// Call to void __kmpc_restore_team_static_memory(int16_t - /// isSPMDExecutionMode, int16_t is_shared); - OMPRTL_NVPTX__kmpc_restore_team_static_memory, - /// Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); - OMPRTL__kmpc_barrier, - /// Call to void __kmpc_barrier_simple_spmd(ident_t *loc, kmp_int32 - /// global_tid); - OMPRTL__kmpc_barrier_simple_spmd, -}; - -/// Pre(post)-action for different OpenMP constructs specialized for NVPTX. -class NVPTXActionTy final : public PrePostActionTy { - llvm::Value *EnterCallee = nullptr; - ArrayRef<llvm::Value *> EnterArgs; - llvm::Value *ExitCallee = nullptr; - ArrayRef<llvm::Value *> ExitArgs; - bool Conditional = false; - llvm::BasicBlock *ContBlock = nullptr; - -public: - NVPTXActionTy(llvm::Value *EnterCallee, ArrayRef<llvm::Value *> EnterArgs, - llvm::Value *ExitCallee, ArrayRef<llvm::Value *> ExitArgs, - bool Conditional = false) - : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), - ExitArgs(ExitArgs), Conditional(Conditional) {} - void Enter(CodeGenFunction &CGF) override { - llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); - if (Conditional) { - llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); - auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); - ContBlock = CGF.createBasicBlock("omp_if.end"); - // Generate the branch (If-stmt) - CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); - CGF.EmitBlock(ThenBlock); - } - } - void Done(CodeGenFunction &CGF) { - // Emit the rest of blocks/branches - CGF.EmitBranch(ContBlock); - CGF.EmitBlock(ContBlock, true); - } - void Exit(CodeGenFunction &CGF) override { - CGF.EmitRuntimeCall(ExitCallee, ExitArgs); - } -}; - -/// A class to track the execution mode when codegening directives within -/// a target region. The appropriate mode (SPMD|NON-SPMD) is set on entry -/// to the target region and used by containing directives such as 'parallel' -/// to emit optimized code. -class ExecutionRuntimeModesRAII { -private: - CGOpenMPRuntimeNVPTX::ExecutionMode SavedExecMode = - CGOpenMPRuntimeNVPTX::EM_Unknown; - CGOpenMPRuntimeNVPTX::ExecutionMode &ExecMode; - bool SavedRuntimeMode = false; - bool *RuntimeMode = nullptr; - -public: - /// Constructor for Non-SPMD mode. - ExecutionRuntimeModesRAII(CGOpenMPRuntimeNVPTX::ExecutionMode &ExecMode) - : ExecMode(ExecMode) { - SavedExecMode = ExecMode; - ExecMode = CGOpenMPRuntimeNVPTX::EM_NonSPMD; - } - /// Constructor for SPMD mode. - ExecutionRuntimeModesRAII(CGOpenMPRuntimeNVPTX::ExecutionMode &ExecMode, - bool &RuntimeMode, bool FullRuntimeMode) - : ExecMode(ExecMode), RuntimeMode(&RuntimeMode) { - SavedExecMode = ExecMode; - SavedRuntimeMode = RuntimeMode; - ExecMode = CGOpenMPRuntimeNVPTX::EM_SPMD; - RuntimeMode = FullRuntimeMode; - } - ~ExecutionRuntimeModesRAII() { - ExecMode = SavedExecMode; - if (RuntimeMode) - *RuntimeMode = SavedRuntimeMode; - } -}; - -/// GPU Configuration: This information can be derived from cuda registers, -/// however, providing compile time constants helps generate more efficient -/// code. For all practical purposes this is fine because the configuration -/// is the same for all known NVPTX architectures. -enum MachineConfiguration : unsigned { - WarpSize = 32, - /// Number of bits required to represent a lane identifier, which is - /// computed as log_2(WarpSize). - LaneIDBits = 5, - LaneIDMask = WarpSize - 1, - - /// Global memory alignment for performance. - GlobalMemoryAlignment = 128, - - /// Maximal size of the shared memory buffer. - SharedMemorySize = 128, -}; - -static const ValueDecl *getPrivateItem(const Expr *RefExpr) { - RefExpr = RefExpr->IgnoreParens(); - if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr)) { - const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); - while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) - Base = TempASE->getBase()->IgnoreParenImpCasts(); - RefExpr = Base; - } else if (auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr)) { - const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); - while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) - Base = TempOASE->getBase()->IgnoreParenImpCasts(); - while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) - Base = TempASE->getBase()->IgnoreParenImpCasts(); - RefExpr = Base; - } - RefExpr = RefExpr->IgnoreParenImpCasts(); - if (const auto *DE = dyn_cast<DeclRefExpr>(RefExpr)) - return cast<ValueDecl>(DE->getDecl()->getCanonicalDecl()); - const auto *ME = cast<MemberExpr>(RefExpr); - return cast<ValueDecl>(ME->getMemberDecl()->getCanonicalDecl()); -} - -typedef std::pair<CharUnits /*Align*/, const ValueDecl *> VarsDataTy; -static bool stable_sort_comparator(const VarsDataTy P1, const VarsDataTy P2) { - return P1.first > P2.first; -} - -static RecordDecl *buildRecordForGlobalizedVars( - ASTContext &C, ArrayRef<const ValueDecl *> EscapedDecls, - ArrayRef<const ValueDecl *> EscapedDeclsForTeams, - llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *> - &MappedDeclsFields) { - if (EscapedDecls.empty() && EscapedDeclsForTeams.empty()) - return nullptr; - SmallVector<VarsDataTy, 4> GlobalizedVars; - for (const ValueDecl *D : EscapedDecls) - GlobalizedVars.emplace_back( - CharUnits::fromQuantity(std::max( - C.getDeclAlign(D).getQuantity(), - static_cast<CharUnits::QuantityType>(GlobalMemoryAlignment))), - D); - for (const ValueDecl *D : EscapedDeclsForTeams) - GlobalizedVars.emplace_back(C.getDeclAlign(D), D); - std::stable_sort(GlobalizedVars.begin(), GlobalizedVars.end(), - stable_sort_comparator); - // Build struct _globalized_locals_ty { - // /* globalized vars */[WarSize] align (max(decl_align, - // GlobalMemoryAlignment)) - // /* globalized vars */ for EscapedDeclsForTeams - // }; - RecordDecl *GlobalizedRD = C.buildImplicitRecord("_globalized_locals_ty"); - GlobalizedRD->startDefinition(); - llvm::SmallPtrSet<const ValueDecl *, 16> SingleEscaped( - EscapedDeclsForTeams.begin(), EscapedDeclsForTeams.end()); - for (const auto &Pair : GlobalizedVars) { - const ValueDecl *VD = Pair.second; - QualType Type = VD->getType(); - if (Type->isLValueReferenceType()) - Type = C.getPointerType(Type.getNonReferenceType()); - else - Type = Type.getNonReferenceType(); - SourceLocation Loc = VD->getLocation(); - FieldDecl *Field; - if (SingleEscaped.count(VD)) { - Field = FieldDecl::Create( - C, GlobalizedRD, Loc, Loc, VD->getIdentifier(), Type, - C.getTrivialTypeSourceInfo(Type, SourceLocation()), - /*BW=*/nullptr, /*Mutable=*/false, - /*InitStyle=*/ICIS_NoInit); - Field->setAccess(AS_public); - if (VD->hasAttrs()) { - for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), - E(VD->getAttrs().end()); - I != E; ++I) - Field->addAttr(*I); - } - } else { - llvm::APInt ArraySize(32, WarpSize); - Type = C.getConstantArrayType(Type, ArraySize, ArrayType::Normal, 0); - Field = FieldDecl::Create( - C, GlobalizedRD, Loc, Loc, VD->getIdentifier(), Type, - C.getTrivialTypeSourceInfo(Type, SourceLocation()), - /*BW=*/nullptr, /*Mutable=*/false, - /*InitStyle=*/ICIS_NoInit); - Field->setAccess(AS_public); - llvm::APInt Align(32, std::max(C.getDeclAlign(VD).getQuantity(), - static_cast<CharUnits::QuantityType>( - GlobalMemoryAlignment))); - Field->addAttr(AlignedAttr::CreateImplicit( - C, AlignedAttr::GNU_aligned, /*IsAlignmentExpr=*/true, - IntegerLiteral::Create(C, Align, - C.getIntTypeForBitwidth(32, /*Signed=*/0), - SourceLocation()))); - } - GlobalizedRD->addDecl(Field); - MappedDeclsFields.try_emplace(VD, Field); - } - GlobalizedRD->completeDefinition(); - return GlobalizedRD; -} - -/// Get the list of variables that can escape their declaration context. -class CheckVarsEscapingDeclContext final - : public ConstStmtVisitor<CheckVarsEscapingDeclContext> { - CodeGenFunction &CGF; - llvm::SetVector<const ValueDecl *> EscapedDecls; - llvm::SetVector<const ValueDecl *> EscapedVariableLengthDecls; - llvm::SmallPtrSet<const Decl *, 4> EscapedParameters; - RecordDecl *GlobalizedRD = nullptr; - llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *> MappedDeclsFields; - bool AllEscaped = false; - bool IsForCombinedParallelRegion = false; - - void markAsEscaped(const ValueDecl *VD) { - // Do not globalize declare target variables. - if (!isa<VarDecl>(VD) || - OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) - return; - VD = cast<ValueDecl>(VD->getCanonicalDecl()); - // Variables captured by value must be globalized. - if (auto *CSI = CGF.CapturedStmtInfo) { - if (const FieldDecl *FD = CSI->lookup(cast<VarDecl>(VD))) { - // Check if need to capture the variable that was already captured by - // value in the outer region. - if (!IsForCombinedParallelRegion) { - if (!FD->hasAttrs()) - return; - const auto *Attr = FD->getAttr<OMPCaptureKindAttr>(); - if (!Attr) - return; - if (((Attr->getCaptureKind() != OMPC_map) && - !isOpenMPPrivate( - static_cast<OpenMPClauseKind>(Attr->getCaptureKind()))) || - ((Attr->getCaptureKind() == OMPC_map) && - !FD->getType()->isAnyPointerType())) - return; - } - if (!FD->getType()->isReferenceType()) { - assert(!VD->getType()->isVariablyModifiedType() && - "Parameter captured by value with variably modified type"); - EscapedParameters.insert(VD); - } else if (!IsForCombinedParallelRegion) { - return; - } - } - } - if ((!CGF.CapturedStmtInfo || - (IsForCombinedParallelRegion && CGF.CapturedStmtInfo)) && - VD->getType()->isReferenceType()) - // Do not globalize variables with reference type. - return; - if (VD->getType()->isVariablyModifiedType()) - EscapedVariableLengthDecls.insert(VD); - else - EscapedDecls.insert(VD); - } - - void VisitValueDecl(const ValueDecl *VD) { - if (VD->getType()->isLValueReferenceType()) - markAsEscaped(VD); - if (const auto *VarD = dyn_cast<VarDecl>(VD)) { - if (!isa<ParmVarDecl>(VarD) && VarD->hasInit()) { - const bool SavedAllEscaped = AllEscaped; - AllEscaped = VD->getType()->isLValueReferenceType(); - Visit(VarD->getInit()); - AllEscaped = SavedAllEscaped; - } - } - } - void VisitOpenMPCapturedStmt(const CapturedStmt *S, - ArrayRef<OMPClause *> Clauses, - bool IsCombinedParallelRegion) { - if (!S) - return; - for (const CapturedStmt::Capture &C : S->captures()) { - if (C.capturesVariable() && !C.capturesVariableByCopy()) { - const ValueDecl *VD = C.getCapturedVar(); - bool SavedIsForCombinedParallelRegion = IsForCombinedParallelRegion; - if (IsCombinedParallelRegion) { - // Check if the variable is privatized in the combined construct and - // those private copies must be shared in the inner parallel - // directive. - IsForCombinedParallelRegion = false; - for (const OMPClause *C : Clauses) { - if (!isOpenMPPrivate(C->getClauseKind()) || - C->getClauseKind() == OMPC_reduction || - C->getClauseKind() == OMPC_linear || - C->getClauseKind() == OMPC_private) - continue; - ArrayRef<const Expr *> Vars; - if (const auto *PC = dyn_cast<OMPFirstprivateClause>(C)) - Vars = PC->getVarRefs(); - else if (const auto *PC = dyn_cast<OMPLastprivateClause>(C)) - Vars = PC->getVarRefs(); - else - llvm_unreachable("Unexpected clause."); - for (const auto *E : Vars) { - const Decl *D = - cast<DeclRefExpr>(E)->getDecl()->getCanonicalDecl(); - if (D == VD->getCanonicalDecl()) { - IsForCombinedParallelRegion = true; - break; - } - } - if (IsForCombinedParallelRegion) - break; - } - } - markAsEscaped(VD); - if (isa<OMPCapturedExprDecl>(VD)) - VisitValueDecl(VD); - IsForCombinedParallelRegion = SavedIsForCombinedParallelRegion; - } - } - } - - void buildRecordForGlobalizedVars(bool IsInTTDRegion) { - assert(!GlobalizedRD && - "Record for globalized variables is built already."); - ArrayRef<const ValueDecl *> EscapedDeclsForParallel, EscapedDeclsForTeams; - if (IsInTTDRegion) - EscapedDeclsForTeams = EscapedDecls.getArrayRef(); - else - EscapedDeclsForParallel = EscapedDecls.getArrayRef(); - GlobalizedRD = ::buildRecordForGlobalizedVars( - CGF.getContext(), EscapedDeclsForParallel, EscapedDeclsForTeams, - MappedDeclsFields); - } - -public: - CheckVarsEscapingDeclContext(CodeGenFunction &CGF, - ArrayRef<const ValueDecl *> TeamsReductions) - : CGF(CGF), EscapedDecls(TeamsReductions.begin(), TeamsReductions.end()) { - } - virtual ~CheckVarsEscapingDeclContext() = default; - void VisitDeclStmt(const DeclStmt *S) { - if (!S) - return; - for (const Decl *D : S->decls()) - if (const auto *VD = dyn_cast_or_null<ValueDecl>(D)) - VisitValueDecl(VD); - } - void VisitOMPExecutableDirective(const OMPExecutableDirective *D) { - if (!D) - return; - if (!D->hasAssociatedStmt()) - return; - if (const auto *S = - dyn_cast_or_null<CapturedStmt>(D->getAssociatedStmt())) { - // Do not analyze directives that do not actually require capturing, - // like `omp for` or `omp simd` directives. - llvm::SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; - getOpenMPCaptureRegions(CaptureRegions, D->getDirectiveKind()); - if (CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown) { - VisitStmt(S->getCapturedStmt()); - return; - } - VisitOpenMPCapturedStmt( - S, D->clauses(), - CaptureRegions.back() == OMPD_parallel && - isOpenMPDistributeDirective(D->getDirectiveKind())); - } - } - void VisitCapturedStmt(const CapturedStmt *S) { - if (!S) - return; - for (const CapturedStmt::Capture &C : S->captures()) { - if (C.capturesVariable() && !C.capturesVariableByCopy()) { - const ValueDecl *VD = C.getCapturedVar(); - markAsEscaped(VD); - if (isa<OMPCapturedExprDecl>(VD)) - VisitValueDecl(VD); - } - } - } - void VisitLambdaExpr(const LambdaExpr *E) { - if (!E) - return; - for (const LambdaCapture &C : E->captures()) { - if (C.capturesVariable()) { - if (C.getCaptureKind() == LCK_ByRef) { - const ValueDecl *VD = C.getCapturedVar(); - markAsEscaped(VD); - if (E->isInitCapture(&C) || isa<OMPCapturedExprDecl>(VD)) - VisitValueDecl(VD); - } - } - } - } - void VisitBlockExpr(const BlockExpr *E) { - if (!E) - return; - for (const BlockDecl::Capture &C : E->getBlockDecl()->captures()) { - if (C.isByRef()) { - const VarDecl *VD = C.getVariable(); - markAsEscaped(VD); - if (isa<OMPCapturedExprDecl>(VD) || VD->isInitCapture()) - VisitValueDecl(VD); - } - } - } - void VisitCallExpr(const CallExpr *E) { - if (!E) - return; - for (const Expr *Arg : E->arguments()) { - if (!Arg) - continue; - if (Arg->isLValue()) { - const bool SavedAllEscaped = AllEscaped; - AllEscaped = true; - Visit(Arg); - AllEscaped = SavedAllEscaped; - } else { - Visit(Arg); - } - } - Visit(E->getCallee()); - } - void VisitDeclRefExpr(const DeclRefExpr *E) { - if (!E) - return; - const ValueDecl *VD = E->getDecl(); - if (AllEscaped) - markAsEscaped(VD); - if (isa<OMPCapturedExprDecl>(VD)) - VisitValueDecl(VD); - else if (const auto *VarD = dyn_cast<VarDecl>(VD)) - if (VarD->isInitCapture()) - VisitValueDecl(VD); - } - void VisitUnaryOperator(const UnaryOperator *E) { - if (!E) - return; - if (E->getOpcode() == UO_AddrOf) { - const bool SavedAllEscaped = AllEscaped; - AllEscaped = true; - Visit(E->getSubExpr()); - AllEscaped = SavedAllEscaped; - } else { - Visit(E->getSubExpr()); - } - } - void VisitImplicitCastExpr(const ImplicitCastExpr *E) { - if (!E) - return; - if (E->getCastKind() == CK_ArrayToPointerDecay) { - const bool SavedAllEscaped = AllEscaped; - AllEscaped = true; - Visit(E->getSubExpr()); - AllEscaped = SavedAllEscaped; - } else { - Visit(E->getSubExpr()); - } - } - void VisitExpr(const Expr *E) { - if (!E) - return; - bool SavedAllEscaped = AllEscaped; - if (!E->isLValue()) - AllEscaped = false; - for (const Stmt *Child : E->children()) - if (Child) - Visit(Child); - AllEscaped = SavedAllEscaped; - } - void VisitStmt(const Stmt *S) { - if (!S) - return; - for (const Stmt *Child : S->children()) - if (Child) - Visit(Child); - } - - /// Returns the record that handles all the escaped local variables and used - /// instead of their original storage. - const RecordDecl *getGlobalizedRecord(bool IsInTTDRegion) { - if (!GlobalizedRD) - buildRecordForGlobalizedVars(IsInTTDRegion); - return GlobalizedRD; - } - - /// Returns the field in the globalized record for the escaped variable. - const FieldDecl *getFieldForGlobalizedVar(const ValueDecl *VD) const { - assert(GlobalizedRD && - "Record for globalized variables must be generated already."); - auto I = MappedDeclsFields.find(VD); - if (I == MappedDeclsFields.end()) - return nullptr; - return I->getSecond(); - } - - /// Returns the list of the escaped local variables/parameters. - ArrayRef<const ValueDecl *> getEscapedDecls() const { - return EscapedDecls.getArrayRef(); - } - - /// Checks if the escaped local variable is actually a parameter passed by - /// value. - const llvm::SmallPtrSetImpl<const Decl *> &getEscapedParameters() const { - return EscapedParameters; - } - - /// Returns the list of the escaped variables with the variably modified - /// types. - ArrayRef<const ValueDecl *> getEscapedVariableLengthDecls() const { - return EscapedVariableLengthDecls.getArrayRef(); - } -}; -} // anonymous namespace - -/// Get the GPU warp size. -static llvm::Value *getNVPTXWarpSize(CodeGenFunction &CGF) { - return CGF.EmitRuntimeCall( - llvm::Intrinsic::getDeclaration( - &CGF.CGM.getModule(), llvm::Intrinsic::nvvm_read_ptx_sreg_warpsize), - "nvptx_warp_size"); -} - -/// Get the id of the current thread on the GPU. -static llvm::Value *getNVPTXThreadID(CodeGenFunction &CGF) { - return CGF.EmitRuntimeCall( - llvm::Intrinsic::getDeclaration( - &CGF.CGM.getModule(), llvm::Intrinsic::nvvm_read_ptx_sreg_tid_x), - "nvptx_tid"); -} - -/// Get the id of the warp in the block. -/// We assume that the warp size is 32, which is always the case -/// on the NVPTX device, to generate more efficient code. -static llvm::Value *getNVPTXWarpID(CodeGenFunction &CGF) { - CGBuilderTy &Bld = CGF.Builder; - return Bld.CreateAShr(getNVPTXThreadID(CGF), LaneIDBits, "nvptx_warp_id"); -} - -/// Get the id of the current lane in the Warp. -/// We assume that the warp size is 32, which is always the case -/// on the NVPTX device, to generate more efficient code. -static llvm::Value *getNVPTXLaneID(CodeGenFunction &CGF) { - CGBuilderTy &Bld = CGF.Builder; - return Bld.CreateAnd(getNVPTXThreadID(CGF), Bld.getInt32(LaneIDMask), - "nvptx_lane_id"); -} - -/// Get the maximum number of threads in a block of the GPU. -static llvm::Value *getNVPTXNumThreads(CodeGenFunction &CGF) { - return CGF.EmitRuntimeCall( - llvm::Intrinsic::getDeclaration( - &CGF.CGM.getModule(), llvm::Intrinsic::nvvm_read_ptx_sreg_ntid_x), - "nvptx_num_threads"); -} - -/// Get the value of the thread_limit clause in the teams directive. -/// For the 'generic' execution mode, the runtime encodes thread_limit in -/// the launch parameters, always starting thread_limit+warpSize threads per -/// CTA. The threads in the last warp are reserved for master execution. -/// For the 'spmd' execution mode, all threads in a CTA are part of the team. -static llvm::Value *getThreadLimit(CodeGenFunction &CGF, - bool IsInSPMDExecutionMode = false) { - CGBuilderTy &Bld = CGF.Builder; - return IsInSPMDExecutionMode - ? getNVPTXNumThreads(CGF) - : Bld.CreateNUWSub(getNVPTXNumThreads(CGF), getNVPTXWarpSize(CGF), - "thread_limit"); -} - -/// Get the thread id of the OMP master thread. -/// The master thread id is the first thread (lane) of the last warp in the -/// GPU block. Warp size is assumed to be some power of 2. -/// Thread id is 0 indexed. -/// E.g: If NumThreads is 33, master id is 32. -/// If NumThreads is 64, master id is 32. -/// If NumThreads is 1024, master id is 992. -static llvm::Value *getMasterThreadID(CodeGenFunction &CGF) { - CGBuilderTy &Bld = CGF.Builder; - llvm::Value *NumThreads = getNVPTXNumThreads(CGF); - - // We assume that the warp size is a power of 2. - llvm::Value *Mask = Bld.CreateNUWSub(getNVPTXWarpSize(CGF), Bld.getInt32(1)); - - return Bld.CreateAnd(Bld.CreateNUWSub(NumThreads, Bld.getInt32(1)), - Bld.CreateNot(Mask), "master_tid"); -} - -CGOpenMPRuntimeNVPTX::WorkerFunctionState::WorkerFunctionState( - CodeGenModule &CGM, SourceLocation Loc) - : WorkerFn(nullptr), CGFI(CGM.getTypes().arrangeNullaryFunction()), - Loc(Loc) { - createWorkerFunction(CGM); -} - -void CGOpenMPRuntimeNVPTX::WorkerFunctionState::createWorkerFunction( - CodeGenModule &CGM) { - // Create an worker function with no arguments. - - WorkerFn = llvm::Function::Create( - CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage, - /*placeholder=*/"_worker", &CGM.getModule()); - CGM.SetInternalFunctionAttributes(GlobalDecl(), WorkerFn, CGFI); - WorkerFn->setDoesNotRecurse(); -} - -CGOpenMPRuntimeNVPTX::ExecutionMode -CGOpenMPRuntimeNVPTX::getExecutionMode() const { - return CurrentExecutionMode; -} - -static CGOpenMPRuntimeNVPTX::DataSharingMode -getDataSharingMode(CodeGenModule &CGM) { - return CGM.getLangOpts().OpenMPCUDAMode ? CGOpenMPRuntimeNVPTX::CUDA - : CGOpenMPRuntimeNVPTX::Generic; -} - -/// Checks if the expression is constant or does not have non-trivial function -/// calls. -static bool isTrivial(ASTContext &Ctx, const Expr * E) { - // We can skip constant expressions. - // We can skip expressions with trivial calls or simple expressions. - return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || - !E->hasNonTrivialCall(Ctx)) && - !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); -} - -/// Checks if the \p Body is the \a CompoundStmt and returns its child statement -/// iff there is only one that is not evaluatable at the compile time. -static const Stmt *getSingleCompoundChild(ASTContext &Ctx, const Stmt *Body) { - if (const auto *C = dyn_cast<CompoundStmt>(Body)) { - const Stmt *Child = nullptr; - for (const Stmt *S : C->body()) { - if (const auto *E = dyn_cast<Expr>(S)) { - if (isTrivial(Ctx, E)) - continue; - } - // Some of the statements can be ignored. - if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || - isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) - continue; - // Analyze declarations. - if (const auto *DS = dyn_cast<DeclStmt>(S)) { - if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) { - if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || - isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || - isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || - isa<UsingDirectiveDecl>(D) || - isa<OMPDeclareReductionDecl>(D) || - isa<OMPThreadPrivateDecl>(D)) - return true; - const auto *VD = dyn_cast<VarDecl>(D); - if (!VD) - return false; - return VD->isConstexpr() || - ((VD->getType().isTrivialType(Ctx) || - VD->getType()->isReferenceType()) && - (!VD->hasInit() || isTrivial(Ctx, VD->getInit()))); - })) - continue; - } - // Found multiple children - cannot get the one child only. - if (Child) - return Body; - Child = S; - } - if (Child) - return Child; - } - return Body; -} - -/// Check if the parallel directive has an 'if' clause with non-constant or -/// false condition. Also, check if the number of threads is strictly specified -/// and run those directives in non-SPMD mode. -static bool hasParallelIfNumThreadsClause(ASTContext &Ctx, - const OMPExecutableDirective &D) { - if (D.hasClausesOfKind<OMPNumThreadsClause>()) - return true; - for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { - OpenMPDirectiveKind NameModifier = C->getNameModifier(); - if (NameModifier != OMPD_parallel && NameModifier != OMPD_unknown) - continue; - const Expr *Cond = C->getCondition(); - bool Result; - if (!Cond->EvaluateAsBooleanCondition(Result, Ctx) || !Result) - return true; - } - return false; -} - -/// Check for inner (nested) SPMD construct, if any -static bool hasNestedSPMDDirective(ASTContext &Ctx, - const OMPExecutableDirective &D) { - const auto *CS = D.getInnermostCapturedStmt(); - const auto *Body = - CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); - const Stmt *ChildStmt = getSingleCompoundChild(Ctx, Body); - - if (const auto *NestedDir = dyn_cast<OMPExecutableDirective>(ChildStmt)) { - OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); - switch (D.getDirectiveKind()) { - case OMPD_target: - if (isOpenMPParallelDirective(DKind) && - !hasParallelIfNumThreadsClause(Ctx, *NestedDir)) - return true; - if (DKind == OMPD_teams) { - Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( - /*IgnoreCaptured=*/true); - if (!Body) - return false; - ChildStmt = getSingleCompoundChild(Ctx, Body); - if (const auto *NND = dyn_cast<OMPExecutableDirective>(ChildStmt)) { - DKind = NND->getDirectiveKind(); - if (isOpenMPParallelDirective(DKind) && - !hasParallelIfNumThreadsClause(Ctx, *NND)) - return true; - } - } - return false; - case OMPD_target_teams: - return isOpenMPParallelDirective(DKind) && - !hasParallelIfNumThreadsClause(Ctx, *NestedDir); - case OMPD_target_simd: - case OMPD_target_parallel: - case OMPD_target_parallel_for: - case OMPD_target_parallel_for_simd: - case OMPD_target_teams_distribute: - case OMPD_target_teams_distribute_simd: - case OMPD_target_teams_distribute_parallel_for: - case OMPD_target_teams_distribute_parallel_for_simd: - case OMPD_parallel: - case OMPD_for: - case OMPD_parallel_for: - case OMPD_parallel_sections: - case OMPD_for_simd: - case OMPD_parallel_for_simd: - case OMPD_cancel: - case OMPD_cancellation_point: - case OMPD_ordered: - case OMPD_threadprivate: - case OMPD_task: - case OMPD_simd: - case OMPD_sections: - case OMPD_section: - case OMPD_single: - case OMPD_master: - case OMPD_critical: - case OMPD_taskyield: - case OMPD_barrier: - case OMPD_taskwait: - case OMPD_taskgroup: - case OMPD_atomic: - case OMPD_flush: - case OMPD_teams: - case OMPD_target_data: - case OMPD_target_exit_data: - case OMPD_target_enter_data: - case OMPD_distribute: - case OMPD_distribute_simd: - case OMPD_distribute_parallel_for: - case OMPD_distribute_parallel_for_simd: - case OMPD_teams_distribute: - case OMPD_teams_distribute_simd: - case OMPD_teams_distribute_parallel_for: - case OMPD_teams_distribute_parallel_for_simd: - case OMPD_target_update: - case OMPD_declare_simd: - case OMPD_declare_target: - case OMPD_end_declare_target: - case OMPD_declare_reduction: - case OMPD_taskloop: - case OMPD_taskloop_simd: - case OMPD_requires: - case OMPD_unknown: - llvm_unreachable("Unexpected directive."); - } - } - - return false; -} - -static bool supportsSPMDExecutionMode(ASTContext &Ctx, - const OMPExecutableDirective &D) { - OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); - switch (DirectiveKind) { - case OMPD_target: - case OMPD_target_teams: - return hasNestedSPMDDirective(Ctx, D); - case OMPD_target_parallel: - case OMPD_target_parallel_for: - case OMPD_target_parallel_for_simd: - case OMPD_target_teams_distribute_parallel_for: - case OMPD_target_teams_distribute_parallel_for_simd: - return !hasParallelIfNumThreadsClause(Ctx, D); - case OMPD_target_simd: - case OMPD_target_teams_distribute: - case OMPD_target_teams_distribute_simd: - return false; - case OMPD_parallel: - case OMPD_for: - case OMPD_parallel_for: - case OMPD_parallel_sections: - case OMPD_for_simd: - case OMPD_parallel_for_simd: - case OMPD_cancel: - case OMPD_cancellation_point: - case OMPD_ordered: - case OMPD_threadprivate: - case OMPD_task: - case OMPD_simd: - case OMPD_sections: - case OMPD_section: - case OMPD_single: - case OMPD_master: - case OMPD_critical: - case OMPD_taskyield: - case OMPD_barrier: - case OMPD_taskwait: - case OMPD_taskgroup: - case OMPD_atomic: - case OMPD_flush: - case OMPD_teams: - case OMPD_target_data: - case OMPD_target_exit_data: - case OMPD_target_enter_data: - case OMPD_distribute: - case OMPD_distribute_simd: - case OMPD_distribute_parallel_for: - case OMPD_distribute_parallel_for_simd: - case OMPD_teams_distribute: - case OMPD_teams_distribute_simd: - case OMPD_teams_distribute_parallel_for: - case OMPD_teams_distribute_parallel_for_simd: - case OMPD_target_update: - case OMPD_declare_simd: - case OMPD_declare_target: - case OMPD_end_declare_target: - case OMPD_declare_reduction: - case OMPD_taskloop: - case OMPD_taskloop_simd: - case OMPD_requires: - case OMPD_unknown: - break; - } - llvm_unreachable( - "Unknown programming model for OpenMP directive on NVPTX target."); -} - -/// Check if the directive is loops based and has schedule clause at all or has -/// static scheduling. -static bool hasStaticScheduling(const OMPExecutableDirective &D) { - assert(isOpenMPWorksharingDirective(D.getDirectiveKind()) && - isOpenMPLoopDirective(D.getDirectiveKind()) && - "Expected loop-based directive."); - return !D.hasClausesOfKind<OMPOrderedClause>() && - (!D.hasClausesOfKind<OMPScheduleClause>() || - llvm::any_of(D.getClausesOfKind<OMPScheduleClause>(), - [](const OMPScheduleClause *C) { - return C->getScheduleKind() == OMPC_SCHEDULE_static; - })); -} - -/// Check for inner (nested) lightweight runtime construct, if any -static bool hasNestedLightweightDirective(ASTContext &Ctx, - const OMPExecutableDirective &D) { - assert(supportsSPMDExecutionMode(Ctx, D) && "Expected SPMD mode directive."); - const auto *CS = D.getInnermostCapturedStmt(); - const auto *Body = - CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); - const Stmt *ChildStmt = getSingleCompoundChild(Ctx, Body); - - if (const auto *NestedDir = dyn_cast<OMPExecutableDirective>(ChildStmt)) { - OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); - switch (D.getDirectiveKind()) { - case OMPD_target: - if (isOpenMPParallelDirective(DKind) && - isOpenMPWorksharingDirective(DKind) && isOpenMPLoopDirective(DKind) && - hasStaticScheduling(*NestedDir)) - return true; - if (DKind == OMPD_parallel) { - Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( - /*IgnoreCaptured=*/true); - if (!Body) - return false; - ChildStmt = getSingleCompoundChild(Ctx, Body); - if (const auto *NND = dyn_cast<OMPExecutableDirective>(ChildStmt)) { - DKind = NND->getDirectiveKind(); - if (isOpenMPWorksharingDirective(DKind) && - isOpenMPLoopDirective(DKind) && hasStaticScheduling(*NND)) - return true; - } - } else if (DKind == OMPD_teams) { - Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( - /*IgnoreCaptured=*/true); - if (!Body) - return false; - ChildStmt = getSingleCompoundChild(Ctx, Body); - if (const auto *NND = dyn_cast<OMPExecutableDirective>(ChildStmt)) { - DKind = NND->getDirectiveKind(); - if (isOpenMPParallelDirective(DKind) && - isOpenMPWorksharingDirective(DKind) && - isOpenMPLoopDirective(DKind) && hasStaticScheduling(*NND)) - return true; - if (DKind == OMPD_parallel) { - Body = NND->getInnermostCapturedStmt()->IgnoreContainers( - /*IgnoreCaptured=*/true); - if (!Body) - return false; - ChildStmt = getSingleCompoundChild(Ctx, Body); - if (const auto *NND = dyn_cast<OMPExecutableDirective>(ChildStmt)) { - DKind = NND->getDirectiveKind(); - if (isOpenMPWorksharingDirective(DKind) && - isOpenMPLoopDirective(DKind) && hasStaticScheduling(*NND)) - return true; - } - } - } - } - return false; - case OMPD_target_teams: - if (isOpenMPParallelDirective(DKind) && - isOpenMPWorksharingDirective(DKind) && isOpenMPLoopDirective(DKind) && - hasStaticScheduling(*NestedDir)) - return true; - if (DKind == OMPD_parallel) { - Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( - /*IgnoreCaptured=*/true); - if (!Body) - return false; - ChildStmt = getSingleCompoundChild(Ctx, Body); - if (const auto *NND = dyn_cast<OMPExecutableDirective>(ChildStmt)) { - DKind = NND->getDirectiveKind(); - if (isOpenMPWorksharingDirective(DKind) && - isOpenMPLoopDirective(DKind) && hasStaticScheduling(*NND)) - return true; - } - } - return false; - case OMPD_target_parallel: - return isOpenMPWorksharingDirective(DKind) && - isOpenMPLoopDirective(DKind) && hasStaticScheduling(*NestedDir); - case OMPD_target_teams_distribute: - case OMPD_target_simd: - case OMPD_target_parallel_for: - case OMPD_target_parallel_for_simd: - case OMPD_target_teams_distribute_simd: - case OMPD_target_teams_distribute_parallel_for: - case OMPD_target_teams_distribute_parallel_for_simd: - case OMPD_parallel: - case OMPD_for: - case OMPD_parallel_for: - case OMPD_parallel_sections: - case OMPD_for_simd: - case OMPD_parallel_for_simd: - case OMPD_cancel: - case OMPD_cancellation_point: - case OMPD_ordered: - case OMPD_threadprivate: - case OMPD_task: - case OMPD_simd: - case OMPD_sections: - case OMPD_section: - case OMPD_single: - case OMPD_master: - case OMPD_critical: - case OMPD_taskyield: - case OMPD_barrier: - case OMPD_taskwait: - case OMPD_taskgroup: - case OMPD_atomic: - case OMPD_flush: - case OMPD_teams: - case OMPD_target_data: - case OMPD_target_exit_data: - case OMPD_target_enter_data: - case OMPD_distribute: - case OMPD_distribute_simd: - case OMPD_distribute_parallel_for: - case OMPD_distribute_parallel_for_simd: - case OMPD_teams_distribute: - case OMPD_teams_distribute_simd: - case OMPD_teams_distribute_parallel_for: - case OMPD_teams_distribute_parallel_for_simd: - case OMPD_target_update: - case OMPD_declare_simd: - case OMPD_declare_target: - case OMPD_end_declare_target: - case OMPD_declare_reduction: - case OMPD_taskloop: - case OMPD_taskloop_simd: - case OMPD_requires: - case OMPD_unknown: - llvm_unreachable("Unexpected directive."); - } - } - - return false; -} - -/// Checks if the construct supports lightweight runtime. It must be SPMD -/// construct + inner loop-based construct with static scheduling. -static bool supportsLightweightRuntime(ASTContext &Ctx, - const OMPExecutableDirective &D) { - if (!supportsSPMDExecutionMode(Ctx, D)) - return false; - OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); - switch (DirectiveKind) { - case OMPD_target: - case OMPD_target_teams: - case OMPD_target_parallel: - return hasNestedLightweightDirective(Ctx, D); - case OMPD_target_parallel_for: - case OMPD_target_parallel_for_simd: - case OMPD_target_teams_distribute_parallel_for: - case OMPD_target_teams_distribute_parallel_for_simd: - // (Last|First)-privates must be shared in parallel region. - return hasStaticScheduling(D); - case OMPD_target_simd: - case OMPD_target_teams_distribute: - case OMPD_target_teams_distribute_simd: - return false; - case OMPD_parallel: - case OMPD_for: - case OMPD_parallel_for: - case OMPD_parallel_sections: - case OMPD_for_simd: - case OMPD_parallel_for_simd: - case OMPD_cancel: - case OMPD_cancellation_point: - case OMPD_ordered: - case OMPD_threadprivate: - case OMPD_task: - case OMPD_simd: - case OMPD_sections: - case OMPD_section: - case OMPD_single: - case OMPD_master: - case OMPD_critical: - case OMPD_taskyield: - case OMPD_barrier: - case OMPD_taskwait: - case OMPD_taskgroup: - case OMPD_atomic: - case OMPD_flush: - case OMPD_teams: - case OMPD_target_data: - case OMPD_target_exit_data: - case OMPD_target_enter_data: - case OMPD_distribute: - case OMPD_distribute_simd: - case OMPD_distribute_parallel_for: - case OMPD_distribute_parallel_for_simd: - case OMPD_teams_distribute: - case OMPD_teams_distribute_simd: - case OMPD_teams_distribute_parallel_for: - case OMPD_teams_distribute_parallel_for_simd: - case OMPD_target_update: - case OMPD_declare_simd: - case OMPD_declare_target: - case OMPD_end_declare_target: - case OMPD_declare_reduction: - case OMPD_taskloop: - case OMPD_taskloop_simd: - case OMPD_requires: - case OMPD_unknown: - break; - } - llvm_unreachable( - "Unknown programming model for OpenMP directive on NVPTX target."); -} - -void CGOpenMPRuntimeNVPTX::emitNonSPMDKernel(const OMPExecutableDirective &D, - StringRef ParentName, - llvm::Function *&OutlinedFn, - llvm::Constant *&OutlinedFnID, - bool IsOffloadEntry, - const RegionCodeGenTy &CodeGen) { - ExecutionRuntimeModesRAII ModeRAII(CurrentExecutionMode); - EntryFunctionState EST; - WorkerFunctionState WST(CGM, D.getBeginLoc()); - Work.clear(); - WrapperFunctionsMap.clear(); - - // Emit target region as a standalone region. - class NVPTXPrePostActionTy : public PrePostActionTy { - CGOpenMPRuntimeNVPTX::EntryFunctionState &EST; - CGOpenMPRuntimeNVPTX::WorkerFunctionState &WST; - - public: - NVPTXPrePostActionTy(CGOpenMPRuntimeNVPTX::EntryFunctionState &EST, - CGOpenMPRuntimeNVPTX::WorkerFunctionState &WST) - : EST(EST), WST(WST) {} - void Enter(CodeGenFunction &CGF) override { - auto &RT = - static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime()); - RT.emitNonSPMDEntryHeader(CGF, EST, WST); - // Skip target region initialization. - RT.setLocThreadIdInsertPt(CGF, /*AtCurrentPoint=*/true); - } - void Exit(CodeGenFunction &CGF) override { - auto &RT = - static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime()); - RT.clearLocThreadIdInsertPt(CGF); - RT.emitNonSPMDEntryFooter(CGF, EST); - } - } Action(EST, WST); - CodeGen.setAction(Action); - IsInTTDRegion = true; - // Reserve place for the globalized memory. - GlobalizedRecords.emplace_back(); - if (!KernelStaticGlobalized) { - KernelStaticGlobalized = new llvm::GlobalVariable( - CGM.getModule(), CGM.VoidPtrTy, /*isConstant=*/false, - llvm::GlobalValue::InternalLinkage, - llvm::ConstantPointerNull::get(CGM.VoidPtrTy), - "_openmp_kernel_static_glob_rd$ptr", /*InsertBefore=*/nullptr, - llvm::GlobalValue::NotThreadLocal, - CGM.getContext().getTargetAddressSpace(LangAS::cuda_shared)); - } - emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, - IsOffloadEntry, CodeGen); - IsInTTDRegion = false; - - // Now change the name of the worker function to correspond to this target - // region's entry function. - WST.WorkerFn->setName(Twine(OutlinedFn->getName(), "_worker")); - - // Create the worker function - emitWorkerFunction(WST); -} - -// Setup NVPTX threads for master-worker OpenMP scheme. -void CGOpenMPRuntimeNVPTX::emitNonSPMDEntryHeader(CodeGenFunction &CGF, - EntryFunctionState &EST, - WorkerFunctionState &WST) { - CGBuilderTy &Bld = CGF.Builder; - - llvm::BasicBlock *WorkerBB = CGF.createBasicBlock(".worker"); - llvm::BasicBlock *MasterCheckBB = CGF.createBasicBlock(".mastercheck"); - llvm::BasicBlock *MasterBB = CGF.createBasicBlock(".master"); - EST.ExitBB = CGF.createBasicBlock(".exit"); - - llvm::Value *IsWorker = - Bld.CreateICmpULT(getNVPTXThreadID(CGF), getThreadLimit(CGF)); - Bld.CreateCondBr(IsWorker, WorkerBB, MasterCheckBB); - - CGF.EmitBlock(WorkerBB); - emitCall(CGF, WST.Loc, WST.WorkerFn); - CGF.EmitBranch(EST.ExitBB); - - CGF.EmitBlock(MasterCheckBB); - llvm::Value *IsMaster = - Bld.CreateICmpEQ(getNVPTXThreadID(CGF), getMasterThreadID(CGF)); - Bld.CreateCondBr(IsMaster, MasterBB, EST.ExitBB); - - CGF.EmitBlock(MasterBB); - IsInTargetMasterThreadRegion = true; - // SEQUENTIAL (MASTER) REGION START - // First action in sequential region: - // Initialize the state of the OpenMP runtime library on the GPU. - // TODO: Optimize runtime initialization and pass in correct value. - llvm::Value *Args[] = {getThreadLimit(CGF), - Bld.getInt16(/*RequiresOMPRuntime=*/1)}; - CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_init), Args); - - // For data sharing, we need to initialize the stack. - CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction( - OMPRTL_NVPTX__kmpc_data_sharing_init_stack)); - - emitGenericVarsProlog(CGF, WST.Loc); -} - -void CGOpenMPRuntimeNVPTX::emitNonSPMDEntryFooter(CodeGenFunction &CGF, - EntryFunctionState &EST) { - IsInTargetMasterThreadRegion = false; - if (!CGF.HaveInsertPoint()) - return; - - emitGenericVarsEpilog(CGF); - - if (!EST.ExitBB) - EST.ExitBB = CGF.createBasicBlock(".exit"); - - llvm::BasicBlock *TerminateBB = CGF.createBasicBlock(".termination.notifier"); - CGF.EmitBranch(TerminateBB); - - CGF.EmitBlock(TerminateBB); - // Signal termination condition. - // TODO: Optimize runtime initialization and pass in correct value. - llvm::Value *Args[] = {CGF.Builder.getInt16(/*IsOMPRuntimeInitialized=*/1)}; - CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_deinit), Args); - // Barrier to terminate worker threads. - syncCTAThreads(CGF); - // Master thread jumps to exit point. - CGF.EmitBranch(EST.ExitBB); - - CGF.EmitBlock(EST.ExitBB); - EST.ExitBB = nullptr; -} - -void CGOpenMPRuntimeNVPTX::emitSPMDKernel(const OMPExecutableDirective &D, - StringRef ParentName, - llvm::Function *&OutlinedFn, - llvm::Constant *&OutlinedFnID, - bool IsOffloadEntry, - const RegionCodeGenTy &CodeGen) { - ExecutionRuntimeModesRAII ModeRAII( - CurrentExecutionMode, RequiresFullRuntime, - CGM.getLangOpts().OpenMPCUDAForceFullRuntime || - !supportsLightweightRuntime(CGM.getContext(), D)); - EntryFunctionState EST; - - // Emit target region as a standalone region. - class NVPTXPrePostActionTy : public PrePostActionTy { - CGOpenMPRuntimeNVPTX &RT; - CGOpenMPRuntimeNVPTX::EntryFunctionState &EST; - const OMPExecutableDirective &D; - - public: - NVPTXPrePostActionTy(CGOpenMPRuntimeNVPTX &RT, - CGOpenMPRuntimeNVPTX::EntryFunctionState &EST, - const OMPExecutableDirective &D) - : RT(RT), EST(EST), D(D) {} - void Enter(CodeGenFunction &CGF) override { - RT.emitSPMDEntryHeader(CGF, EST, D); - // Skip target region initialization. - RT.setLocThreadIdInsertPt(CGF, /*AtCurrentPoint=*/true); - } - void Exit(CodeGenFunction &CGF) override { - RT.clearLocThreadIdInsertPt(CGF); - RT.emitSPMDEntryFooter(CGF, EST); - } - } Action(*this, EST, D); - CodeGen.setAction(Action); - IsInTTDRegion = true; - // Reserve place for the globalized memory. - GlobalizedRecords.emplace_back(); - if (!KernelStaticGlobalized) { - KernelStaticGlobalized = new llvm::GlobalVariable( - CGM.getModule(), CGM.VoidPtrTy, /*isConstant=*/false, - llvm::GlobalValue::InternalLinkage, - llvm::ConstantPointerNull::get(CGM.VoidPtrTy), - "_openmp_kernel_static_glob_rd$ptr", /*InsertBefore=*/nullptr, - llvm::GlobalValue::NotThreadLocal, - CGM.getContext().getTargetAddressSpace(LangAS::cuda_shared)); - } - emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, - IsOffloadEntry, CodeGen); - IsInTTDRegion = false; -} - -void CGOpenMPRuntimeNVPTX::emitSPMDEntryHeader( - CodeGenFunction &CGF, EntryFunctionState &EST, - const OMPExecutableDirective &D) { - CGBuilderTy &Bld = CGF.Builder; - - // Setup BBs in entry function. - llvm::BasicBlock *ExecuteBB = CGF.createBasicBlock(".execute"); - EST.ExitBB = CGF.createBasicBlock(".exit"); - - llvm::Value *Args[] = {getThreadLimit(CGF, /*IsInSPMDExecutionMode=*/true), - /*RequiresOMPRuntime=*/ - Bld.getInt16(RequiresFullRuntime ? 1 : 0), - /*RequiresDataSharing=*/Bld.getInt16(0)}; - CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_spmd_kernel_init), Args); - - if (RequiresFullRuntime) { - // For data sharing, we need to initialize the stack. - CGF.EmitRuntimeCall(createNVPTXRuntimeFunction( - OMPRTL_NVPTX__kmpc_data_sharing_init_stack_spmd)); - } - - CGF.EmitBranch(ExecuteBB); - - CGF.EmitBlock(ExecuteBB); - - IsInTargetMasterThreadRegion = true; -} - -void CGOpenMPRuntimeNVPTX::emitSPMDEntryFooter(CodeGenFunction &CGF, - EntryFunctionState &EST) { - IsInTargetMasterThreadRegion = false; - if (!CGF.HaveInsertPoint()) - return; - - if (!EST.ExitBB) - EST.ExitBB = CGF.createBasicBlock(".exit"); - - llvm::BasicBlock *OMPDeInitBB = CGF.createBasicBlock(".omp.deinit"); - CGF.EmitBranch(OMPDeInitBB); - - CGF.EmitBlock(OMPDeInitBB); - // DeInitialize the OMP state in the runtime; called by all active threads. - llvm::Value *Args[] = {/*RequiresOMPRuntime=*/ - CGF.Builder.getInt16(RequiresFullRuntime ? 1 : 0)}; - CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction( - OMPRTL_NVPTX__kmpc_spmd_kernel_deinit_v2), Args); - CGF.EmitBranch(EST.ExitBB); - - CGF.EmitBlock(EST.ExitBB); - EST.ExitBB = nullptr; -} - -// Create a unique global variable to indicate the execution mode of this target -// region. The execution mode is either 'generic', or 'spmd' depending on the -// target directive. This variable is picked up by the offload library to setup -// the device appropriately before kernel launch. If the execution mode is -// 'generic', the runtime reserves one warp for the master, otherwise, all -// warps participate in parallel work. -static void setPropertyExecutionMode(CodeGenModule &CGM, StringRef Name, - bool Mode) { - auto *GVMode = - new llvm::GlobalVariable(CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, - llvm::GlobalValue::WeakAnyLinkage, - llvm::ConstantInt::get(CGM.Int8Ty, Mode ? 0 : 1), - Twine(Name, "_exec_mode")); - CGM.addCompilerUsedGlobal(GVMode); -} - -void CGOpenMPRuntimeNVPTX::emitWorkerFunction(WorkerFunctionState &WST) { - ASTContext &Ctx = CGM.getContext(); - - CodeGenFunction CGF(CGM, /*suppressNewContext=*/true); - CGF.StartFunction(GlobalDecl(), Ctx.VoidTy, WST.WorkerFn, WST.CGFI, {}, - WST.Loc, WST.Loc); - emitWorkerLoop(CGF, WST); - CGF.FinishFunction(); -} - -void CGOpenMPRuntimeNVPTX::emitWorkerLoop(CodeGenFunction &CGF, - WorkerFunctionState &WST) { - // - // The workers enter this loop and wait for parallel work from the master. - // When the master encounters a parallel region it sets up the work + variable - // arguments, and wakes up the workers. The workers first check to see if - // they are required for the parallel region, i.e., within the # of requested - // parallel threads. The activated workers load the variable arguments and - // execute the parallel work. - // - - CGBuilderTy &Bld = CGF.Builder; - - llvm::BasicBlock *AwaitBB = CGF.createBasicBlock(".await.work"); - llvm::BasicBlock *SelectWorkersBB = CGF.createBasicBlock(".select.workers"); - llvm::BasicBlock *ExecuteBB = CGF.createBasicBlock(".execute.parallel"); - llvm::BasicBlock *TerminateBB = CGF.createBasicBlock(".terminate.parallel"); - llvm::BasicBlock *BarrierBB = CGF.createBasicBlock(".barrier.parallel"); - llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".exit"); - - CGF.EmitBranch(AwaitBB); - - // Workers wait for work from master. - CGF.EmitBlock(AwaitBB); - // Wait for parallel work - syncCTAThreads(CGF); - - Address WorkFn = - CGF.CreateDefaultAlignTempAlloca(CGF.Int8PtrTy, /*Name=*/"work_fn"); - Address ExecStatus = - CGF.CreateDefaultAlignTempAlloca(CGF.Int8Ty, /*Name=*/"exec_status"); - CGF.InitTempAlloca(ExecStatus, Bld.getInt8(/*C=*/0)); - CGF.InitTempAlloca(WorkFn, llvm::Constant::getNullValue(CGF.Int8PtrTy)); - - // TODO: Optimize runtime initialization and pass in correct value. - llvm::Value *Args[] = {WorkFn.getPointer(), - /*RequiresOMPRuntime=*/Bld.getInt16(1)}; - llvm::Value *Ret = CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_parallel), Args); - Bld.CreateStore(Bld.CreateZExt(Ret, CGF.Int8Ty), ExecStatus); - - // On termination condition (workid == 0), exit loop. - llvm::Value *WorkID = Bld.CreateLoad(WorkFn); - llvm::Value *ShouldTerminate = Bld.CreateIsNull(WorkID, "should_terminate"); - Bld.CreateCondBr(ShouldTerminate, ExitBB, SelectWorkersBB); - - // Activate requested workers. - CGF.EmitBlock(SelectWorkersBB); - llvm::Value *IsActive = - Bld.CreateIsNotNull(Bld.CreateLoad(ExecStatus), "is_active"); - Bld.CreateCondBr(IsActive, ExecuteBB, BarrierBB); - - // Signal start of parallel region. - CGF.EmitBlock(ExecuteBB); - // Skip initialization. - setLocThreadIdInsertPt(CGF, /*AtCurrentPoint=*/true); - - // Process work items: outlined parallel functions. - for (llvm::Function *W : Work) { - // Try to match this outlined function. - llvm::Value *ID = Bld.CreatePointerBitCastOrAddrSpaceCast(W, CGM.Int8PtrTy); - - llvm::Value *WorkFnMatch = - Bld.CreateICmpEQ(Bld.CreateLoad(WorkFn), ID, "work_match"); - - llvm::BasicBlock *ExecuteFNBB = CGF.createBasicBlock(".execute.fn"); - llvm::BasicBlock *CheckNextBB = CGF.createBasicBlock(".check.next"); - Bld.CreateCondBr(WorkFnMatch, ExecuteFNBB, CheckNextBB); - - // Execute this outlined function. - CGF.EmitBlock(ExecuteFNBB); - - // Insert call to work function via shared wrapper. The shared - // wrapper takes two arguments: - // - the parallelism level; - // - the thread ID; - emitCall(CGF, WST.Loc, W, - {Bld.getInt16(/*ParallelLevel=*/0), getThreadID(CGF, WST.Loc)}); - - // Go to end of parallel region. - CGF.EmitBranch(TerminateBB); - - CGF.EmitBlock(CheckNextBB); - } - // Default case: call to outlined function through pointer if the target - // region makes a declare target call that may contain an orphaned parallel - // directive. - auto *ParallelFnTy = - llvm::FunctionType::get(CGM.VoidTy, {CGM.Int16Ty, CGM.Int32Ty}, - /*isVarArg=*/false) - ->getPointerTo(); - llvm::Value *WorkFnCast = Bld.CreateBitCast(WorkID, ParallelFnTy); - // Insert call to work function via shared wrapper. The shared - // wrapper takes two arguments: - // - the parallelism level; - // - the thread ID; - emitCall(CGF, WST.Loc, WorkFnCast, - {Bld.getInt16(/*ParallelLevel=*/0), getThreadID(CGF, WST.Loc)}); - // Go to end of parallel region. - CGF.EmitBranch(TerminateBB); - - // Signal end of parallel region. - CGF.EmitBlock(TerminateBB); - CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_end_parallel), - llvm::None); - CGF.EmitBranch(BarrierBB); - - // All active and inactive workers wait at a barrier after parallel region. - CGF.EmitBlock(BarrierBB); - // Barrier after parallel region. - syncCTAThreads(CGF); - CGF.EmitBranch(AwaitBB); - - // Exit target region. - CGF.EmitBlock(ExitBB); - // Skip initialization. - clearLocThreadIdInsertPt(CGF); -} - -/// Returns specified OpenMP runtime function for the current OpenMP -/// implementation. Specialized for the NVPTX device. -/// \param Function OpenMP runtime function. -/// \return Specified function. -llvm::Constant * -CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) { - llvm::Constant *RTLFn = nullptr; - switch (static_cast<OpenMPRTLFunctionNVPTX>(Function)) { - case OMPRTL_NVPTX__kmpc_kernel_init: { - // Build void __kmpc_kernel_init(kmp_int32 thread_limit, int16_t - // RequiresOMPRuntime); - llvm::Type *TypeParams[] = {CGM.Int32Ty, CGM.Int16Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_kernel_init"); - break; - } - case OMPRTL_NVPTX__kmpc_kernel_deinit: { - // Build void __kmpc_kernel_deinit(int16_t IsOMPRuntimeInitialized); - llvm::Type *TypeParams[] = {CGM.Int16Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_kernel_deinit"); - break; - } - case OMPRTL_NVPTX__kmpc_spmd_kernel_init: { - // Build void __kmpc_spmd_kernel_init(kmp_int32 thread_limit, - // int16_t RequiresOMPRuntime, int16_t RequiresDataSharing); - llvm::Type *TypeParams[] = {CGM.Int32Ty, CGM.Int16Ty, CGM.Int16Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_spmd_kernel_init"); - break; - } - case OMPRTL_NVPTX__kmpc_spmd_kernel_deinit_v2: { - // Build void __kmpc_spmd_kernel_deinit_v2(int16_t RequiresOMPRuntime); - llvm::Type *TypeParams[] = {CGM.Int16Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_spmd_kernel_deinit_v2"); - break; - } - case OMPRTL_NVPTX__kmpc_kernel_prepare_parallel: { - /// Build void __kmpc_kernel_prepare_parallel( - /// void *outlined_function, int16_t IsOMPRuntimeInitialized); - llvm::Type *TypeParams[] = {CGM.Int8PtrTy, CGM.Int16Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_kernel_prepare_parallel"); - break; - } - case OMPRTL_NVPTX__kmpc_kernel_parallel: { - /// Build bool __kmpc_kernel_parallel(void **outlined_function, - /// int16_t IsOMPRuntimeInitialized); - llvm::Type *TypeParams[] = {CGM.Int8PtrPtrTy, CGM.Int16Ty}; - llvm::Type *RetTy = CGM.getTypes().ConvertType(CGM.getContext().BoolTy); - auto *FnTy = - llvm::FunctionType::get(RetTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_kernel_parallel"); - break; - } - case OMPRTL_NVPTX__kmpc_kernel_end_parallel: { - /// Build void __kmpc_kernel_end_parallel(); - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, llvm::None, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_kernel_end_parallel"); - break; - } - case OMPRTL_NVPTX__kmpc_serialized_parallel: { - // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 - // global_tid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); - break; - } - case OMPRTL_NVPTX__kmpc_end_serialized_parallel: { - // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 - // global_tid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); - break; - } - case OMPRTL_NVPTX__kmpc_shuffle_int32: { - // Build int32_t __kmpc_shuffle_int32(int32_t element, - // int16_t lane_offset, int16_t warp_size); - llvm::Type *TypeParams[] = {CGM.Int32Ty, CGM.Int16Ty, CGM.Int16Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_shuffle_int32"); - break; - } - case OMPRTL_NVPTX__kmpc_shuffle_int64: { - // Build int64_t __kmpc_shuffle_int64(int64_t element, - // int16_t lane_offset, int16_t warp_size); - llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int16Ty, CGM.Int16Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_shuffle_int64"); - break; - } - case OMPRTL_NVPTX__kmpc_parallel_reduce_nowait_v2: { - // Build int32_t kmpc_nvptx_parallel_reduce_nowait_v2(ident_t *loc, - // kmp_int32 global_tid, kmp_int32 num_vars, size_t reduce_size, void* - // reduce_data, void (*kmp_ShuffleReductFctPtr)(void *rhsData, int16_t - // lane_id, int16_t lane_offset, int16_t Algorithm Version), void - // (*kmp_InterWarpCopyFctPtr)(void* src, int warp_num)); - llvm::Type *ShuffleReduceTypeParams[] = {CGM.VoidPtrTy, CGM.Int16Ty, - CGM.Int16Ty, CGM.Int16Ty}; - auto *ShuffleReduceFnTy = - llvm::FunctionType::get(CGM.VoidTy, ShuffleReduceTypeParams, - /*isVarArg=*/false); - llvm::Type *InterWarpCopyTypeParams[] = {CGM.VoidPtrTy, CGM.Int32Ty}; - auto *InterWarpCopyFnTy = - llvm::FunctionType::get(CGM.VoidTy, InterWarpCopyTypeParams, - /*isVarArg=*/false); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), - CGM.Int32Ty, - CGM.Int32Ty, - CGM.SizeTy, - CGM.VoidPtrTy, - ShuffleReduceFnTy->getPointerTo(), - InterWarpCopyFnTy->getPointerTo()}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction( - FnTy, /*Name=*/"__kmpc_nvptx_parallel_reduce_nowait_v2"); - break; - } - case OMPRTL_NVPTX__kmpc_end_reduce_nowait: { - // Build __kmpc_end_reduce_nowait(kmp_int32 global_tid); - llvm::Type *TypeParams[] = {CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction( - FnTy, /*Name=*/"__kmpc_nvptx_end_reduce_nowait"); - break; - } - case OMPRTL_NVPTX__kmpc_nvptx_teams_reduce_nowait_simple: { - // Build __kmpc_nvptx_teams_reduce_nowait_simple(ident_t *loc, kmp_int32 - // global_tid, kmp_critical_name *lck) - llvm::Type *TypeParams[] = { - getIdentTyPointerTy(), CGM.Int32Ty, - llvm::PointerType::getUnqual(getKmpCriticalNameTy())}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction( - FnTy, /*Name=*/"__kmpc_nvptx_teams_reduce_nowait_simple"); - break; - } - case OMPRTL_NVPTX__kmpc_nvptx_teams_end_reduce_nowait_simple: { - // Build __kmpc_nvptx_teams_end_reduce_nowait_simple(ident_t *loc, kmp_int32 - // global_tid, kmp_critical_name *lck) - llvm::Type *TypeParams[] = { - getIdentTyPointerTy(), CGM.Int32Ty, - llvm::PointerType::getUnqual(getKmpCriticalNameTy())}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction( - FnTy, /*Name=*/"__kmpc_nvptx_teams_end_reduce_nowait_simple"); - break; - } - case OMPRTL_NVPTX__kmpc_data_sharing_init_stack: { - /// Build void __kmpc_data_sharing_init_stack(); - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, llvm::None, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_data_sharing_init_stack"); - break; - } - case OMPRTL_NVPTX__kmpc_data_sharing_init_stack_spmd: { - /// Build void __kmpc_data_sharing_init_stack_spmd(); - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, llvm::None, /*isVarArg*/ false); - RTLFn = - CGM.CreateRuntimeFunction(FnTy, "__kmpc_data_sharing_init_stack_spmd"); - break; - } - case OMPRTL_NVPTX__kmpc_data_sharing_coalesced_push_stack: { - // Build void *__kmpc_data_sharing_coalesced_push_stack(size_t size, - // int16_t UseSharedMemory); - llvm::Type *TypeParams[] = {CGM.SizeTy, CGM.Int16Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction( - FnTy, /*Name=*/"__kmpc_data_sharing_coalesced_push_stack"); - break; - } - case OMPRTL_NVPTX__kmpc_data_sharing_pop_stack: { - // Build void __kmpc_data_sharing_pop_stack(void *a); - llvm::Type *TypeParams[] = {CGM.VoidPtrTy}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, - /*Name=*/"__kmpc_data_sharing_pop_stack"); - break; - } - case OMPRTL_NVPTX__kmpc_begin_sharing_variables: { - /// Build void __kmpc_begin_sharing_variables(void ***args, - /// size_t n_args); - llvm::Type *TypeParams[] = {CGM.Int8PtrPtrTy->getPointerTo(), CGM.SizeTy}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_begin_sharing_variables"); - break; - } - case OMPRTL_NVPTX__kmpc_end_sharing_variables: { - /// Build void __kmpc_end_sharing_variables(); - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, llvm::None, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_sharing_variables"); - break; - } - case OMPRTL_NVPTX__kmpc_get_shared_variables: { - /// Build void __kmpc_get_shared_variables(void ***GlobalArgs); - llvm::Type *TypeParams[] = {CGM.Int8PtrPtrTy->getPointerTo()}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_get_shared_variables"); - break; - } - case OMPRTL_NVPTX__kmpc_parallel_level: { - // Build uint16_t __kmpc_parallel_level(ident_t *loc, kmp_int32 global_tid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.Int16Ty, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_parallel_level"); - break; - } - case OMPRTL_NVPTX__kmpc_is_spmd_exec_mode: { - // Build int8_t __kmpc_is_spmd_exec_mode(); - auto *FnTy = llvm::FunctionType::get(CGM.Int8Ty, /*isVarArg=*/false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_is_spmd_exec_mode"); - break; - } - case OMPRTL_NVPTX__kmpc_get_team_static_memory: { - // Build void __kmpc_get_team_static_memory(int16_t isSPMDExecutionMode, - // const void *buf, size_t size, int16_t is_shared, const void **res); - llvm::Type *TypeParams[] = {CGM.Int16Ty, CGM.VoidPtrTy, CGM.SizeTy, - CGM.Int16Ty, CGM.VoidPtrPtrTy}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_get_team_static_memory"); - break; - } - case OMPRTL_NVPTX__kmpc_restore_team_static_memory: { - // Build void __kmpc_restore_team_static_memory(int16_t isSPMDExecutionMode, - // int16_t is_shared); - llvm::Type *TypeParams[] = {CGM.Int16Ty, CGM.Int16Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); - RTLFn = - CGM.CreateRuntimeFunction(FnTy, "__kmpc_restore_team_static_memory"); - break; - } - case OMPRTL__kmpc_barrier: { - // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); - cast<llvm::Function>(RTLFn)->addFnAttr(llvm::Attribute::Convergent); - break; - } - case OMPRTL__kmpc_barrier_simple_spmd: { - // Build void __kmpc_barrier_simple_spmd(ident_t *loc, kmp_int32 - // global_tid); - llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; - auto *FnTy = - llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); - RTLFn = - CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier_simple_spmd"); - cast<llvm::Function>(RTLFn)->addFnAttr(llvm::Attribute::Convergent); - break; - } - } - return RTLFn; -} - -void CGOpenMPRuntimeNVPTX::createOffloadEntry(llvm::Constant *ID, - llvm::Constant *Addr, - uint64_t Size, int32_t, - llvm::GlobalValue::LinkageTypes) { - // TODO: Add support for global variables on the device after declare target - // support. - if (!isa<llvm::Function>(Addr)) - return; - llvm::Module &M = CGM.getModule(); - llvm::LLVMContext &Ctx = CGM.getLLVMContext(); - - // Get "nvvm.annotations" metadata node - llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("nvvm.annotations"); - - llvm::Metadata *MDVals[] = { - llvm::ConstantAsMetadata::get(Addr), llvm::MDString::get(Ctx, "kernel"), - llvm::ConstantAsMetadata::get( - llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx), 1))}; - // Append metadata to nvvm.annotations - MD->addOperand(llvm::MDNode::get(Ctx, MDVals)); -} - -void CGOpenMPRuntimeNVPTX::emitTargetOutlinedFunction( - const OMPExecutableDirective &D, StringRef ParentName, - llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, - bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { - if (!IsOffloadEntry) // Nothing to do. - return; - - assert(!ParentName.empty() && "Invalid target region parent name!"); - - bool Mode = supportsSPMDExecutionMode(CGM.getContext(), D); - if (Mode) - emitSPMDKernel(D, ParentName, OutlinedFn, OutlinedFnID, IsOffloadEntry, - CodeGen); - else - emitNonSPMDKernel(D, ParentName, OutlinedFn, OutlinedFnID, IsOffloadEntry, - CodeGen); - - setPropertyExecutionMode(CGM, OutlinedFn->getName(), Mode); -} - -namespace { -LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); -/// Enum for accesseing the reserved_2 field of the ident_t struct. -enum ModeFlagsTy : unsigned { - /// Bit set to 1 when in SPMD mode. - KMP_IDENT_SPMD_MODE = 0x01, - /// Bit set to 1 when a simplified runtime is used. - KMP_IDENT_SIMPLE_RT_MODE = 0x02, - LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/KMP_IDENT_SIMPLE_RT_MODE) -}; - -/// Special mode Undefined. Is the combination of Non-SPMD mode + SimpleRuntime. -static const ModeFlagsTy UndefinedMode = - (~KMP_IDENT_SPMD_MODE) & KMP_IDENT_SIMPLE_RT_MODE; -} // anonymous namespace - -unsigned CGOpenMPRuntimeNVPTX::getDefaultLocationReserved2Flags() const { - switch (getExecutionMode()) { - case EM_SPMD: - if (requiresFullRuntime()) - return KMP_IDENT_SPMD_MODE & (~KMP_IDENT_SIMPLE_RT_MODE); - return KMP_IDENT_SPMD_MODE | KMP_IDENT_SIMPLE_RT_MODE; - case EM_NonSPMD: - assert(requiresFullRuntime() && "Expected full runtime."); - return (~KMP_IDENT_SPMD_MODE) & (~KMP_IDENT_SIMPLE_RT_MODE); - case EM_Unknown: - return UndefinedMode; - } - llvm_unreachable("Unknown flags are requested."); -} - -CGOpenMPRuntimeNVPTX::CGOpenMPRuntimeNVPTX(CodeGenModule &CGM) - : CGOpenMPRuntime(CGM, "_", "$") { - if (!CGM.getLangOpts().OpenMPIsDevice) - llvm_unreachable("OpenMP NVPTX can only handle device code."); -} - -void CGOpenMPRuntimeNVPTX::emitProcBindClause(CodeGenFunction &CGF, - OpenMPProcBindClauseKind ProcBind, - SourceLocation Loc) { - // Do nothing in case of SPMD mode and L0 parallel. - if (getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_SPMD) - return; - - CGOpenMPRuntime::emitProcBindClause(CGF, ProcBind, Loc); -} - -void CGOpenMPRuntimeNVPTX::emitNumThreadsClause(CodeGenFunction &CGF, - llvm::Value *NumThreads, - SourceLocation Loc) { - // Do nothing in case of SPMD mode and L0 parallel. - if (getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_SPMD) - return; - - CGOpenMPRuntime::emitNumThreadsClause(CGF, NumThreads, Loc); -} - -void CGOpenMPRuntimeNVPTX::emitNumTeamsClause(CodeGenFunction &CGF, - const Expr *NumTeams, - const Expr *ThreadLimit, - SourceLocation Loc) {} - -llvm::Value *CGOpenMPRuntimeNVPTX::emitParallelOutlinedFunction( - const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, - OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { - // Emit target region as a standalone region. - class NVPTXPrePostActionTy : public PrePostActionTy { - bool &IsInParallelRegion; - bool PrevIsInParallelRegion; - - public: - NVPTXPrePostActionTy(bool &IsInParallelRegion) - : IsInParallelRegion(IsInParallelRegion) {} - void Enter(CodeGenFunction &CGF) override { - PrevIsInParallelRegion = IsInParallelRegion; - IsInParallelRegion = true; - } - void Exit(CodeGenFunction &CGF) override { - IsInParallelRegion = PrevIsInParallelRegion; - } - } Action(IsInParallelRegion); - CodeGen.setAction(Action); - bool PrevIsInTTDRegion = IsInTTDRegion; - IsInTTDRegion = false; - bool PrevIsInTargetMasterThreadRegion = IsInTargetMasterThreadRegion; - IsInTargetMasterThreadRegion = false; - auto *OutlinedFun = - cast<llvm::Function>(CGOpenMPRuntime::emitParallelOutlinedFunction( - D, ThreadIDVar, InnermostKind, CodeGen)); - IsInTargetMasterThreadRegion = PrevIsInTargetMasterThreadRegion; - IsInTTDRegion = PrevIsInTTDRegion; - if (getExecutionMode() != CGOpenMPRuntimeNVPTX::EM_SPMD && - !IsInParallelRegion) { - llvm::Function *WrapperFun = - createParallelDataSharingWrapper(OutlinedFun, D); - WrapperFunctionsMap[OutlinedFun] = WrapperFun; - } - - return OutlinedFun; -} - -/// Get list of lastprivate variables from the teams distribute ... or -/// teams {distribute ...} directives. -static void -getDistributeLastprivateVars(ASTContext &Ctx, const OMPExecutableDirective &D, - llvm::SmallVectorImpl<const ValueDecl *> &Vars) { - assert(isOpenMPTeamsDirective(D.getDirectiveKind()) && - "expected teams directive."); - const OMPExecutableDirective *Dir = &D; - if (!isOpenMPDistributeDirective(D.getDirectiveKind())) { - if (const Stmt *S = getSingleCompoundChild( - Ctx, - D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers( - /*IgnoreCaptured=*/true))) { - Dir = dyn_cast<OMPExecutableDirective>(S); - if (Dir && !isOpenMPDistributeDirective(Dir->getDirectiveKind())) - Dir = nullptr; - } - } - if (!Dir) - return; - for (const auto *C : Dir->getClausesOfKind<OMPLastprivateClause>()) { - for (const Expr *E : C->getVarRefs()) - Vars.push_back(getPrivateItem(E)); - } -} - -/// Get list of reduction variables from the teams ... directives. -static void -getTeamsReductionVars(ASTContext &Ctx, const OMPExecutableDirective &D, - llvm::SmallVectorImpl<const ValueDecl *> &Vars) { - assert(isOpenMPTeamsDirective(D.getDirectiveKind()) && - "expected teams directive."); - for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) { - for (const Expr *E : C->privates()) - Vars.push_back(getPrivateItem(E)); - } -} - -llvm::Value *CGOpenMPRuntimeNVPTX::emitTeamsOutlinedFunction( - const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, - OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { - SourceLocation Loc = D.getBeginLoc(); - - const RecordDecl *GlobalizedRD = nullptr; - llvm::SmallVector<const ValueDecl *, 4> LastPrivatesReductions; - llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *> MappedDeclsFields; - // Globalize team reductions variable unconditionally in all modes. - getTeamsReductionVars(CGM.getContext(), D, LastPrivatesReductions); - if (getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_SPMD) { - getDistributeLastprivateVars(CGM.getContext(), D, LastPrivatesReductions); - if (!LastPrivatesReductions.empty()) { - GlobalizedRD = ::buildRecordForGlobalizedVars( - CGM.getContext(), llvm::None, LastPrivatesReductions, - MappedDeclsFields); - } - } else if (!LastPrivatesReductions.empty()) { - assert(!TeamAndReductions.first && - "Previous team declaration is not expected."); - TeamAndReductions.first = D.getCapturedStmt(OMPD_teams)->getCapturedDecl(); - std::swap(TeamAndReductions.second, LastPrivatesReductions); - } - - // Emit target region as a standalone region. - class NVPTXPrePostActionTy : public PrePostActionTy { - SourceLocation &Loc; - const RecordDecl *GlobalizedRD; - llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *> - &MappedDeclsFields; - - public: - NVPTXPrePostActionTy( - SourceLocation &Loc, const RecordDecl *GlobalizedRD, - llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *> - &MappedDeclsFields) - : Loc(Loc), GlobalizedRD(GlobalizedRD), - MappedDeclsFields(MappedDeclsFields) {} - void Enter(CodeGenFunction &CGF) override { - auto &Rt = - static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime()); - if (GlobalizedRD) { - auto I = Rt.FunctionGlobalizedDecls.try_emplace(CGF.CurFn).first; - I->getSecond().GlobalRecord = GlobalizedRD; - I->getSecond().MappedParams = - llvm::make_unique<CodeGenFunction::OMPMapVars>(); - DeclToAddrMapTy &Data = I->getSecond().LocalVarData; - for (const auto &Pair : MappedDeclsFields) { - assert(Pair.getFirst()->isCanonicalDecl() && - "Expected canonical declaration"); - Data.insert(std::make_pair(Pair.getFirst(), - MappedVarData(Pair.getSecond(), - /*IsOnePerTeam=*/true))); - } - } - Rt.emitGenericVarsProlog(CGF, Loc); - } - void Exit(CodeGenFunction &CGF) override { - static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime()) - .emitGenericVarsEpilog(CGF); - } - } Action(Loc, GlobalizedRD, MappedDeclsFields); - CodeGen.setAction(Action); - llvm::Value *OutlinedFunVal = CGOpenMPRuntime::emitTeamsOutlinedFunction( - D, ThreadIDVar, InnermostKind, CodeGen); - llvm::Function *OutlinedFun = cast<llvm::Function>(OutlinedFunVal); - OutlinedFun->removeFnAttr(llvm::Attribute::NoInline); - OutlinedFun->removeFnAttr(llvm::Attribute::OptimizeNone); - OutlinedFun->addFnAttr(llvm::Attribute::AlwaysInline); - - return OutlinedFun; -} - -void CGOpenMPRuntimeNVPTX::emitGenericVarsProlog(CodeGenFunction &CGF, - SourceLocation Loc, - bool WithSPMDCheck) { - if (getDataSharingMode(CGM) != CGOpenMPRuntimeNVPTX::Generic && - getExecutionMode() != CGOpenMPRuntimeNVPTX::EM_SPMD) - return; - - CGBuilderTy &Bld = CGF.Builder; - - const auto I = FunctionGlobalizedDecls.find(CGF.CurFn); - if (I == FunctionGlobalizedDecls.end()) - return; - if (const RecordDecl *GlobalizedVarsRecord = I->getSecond().GlobalRecord) { - QualType GlobalRecTy = CGM.getContext().getRecordType(GlobalizedVarsRecord); - QualType SecGlobalRecTy; - - // Recover pointer to this function's global record. The runtime will - // handle the specifics of the allocation of the memory. - // Use actual memory size of the record including the padding - // for alignment purposes. - unsigned Alignment = - CGM.getContext().getTypeAlignInChars(GlobalRecTy).getQuantity(); - unsigned GlobalRecordSize = - CGM.getContext().getTypeSizeInChars(GlobalRecTy).getQuantity(); - GlobalRecordSize = llvm::alignTo(GlobalRecordSize, Alignment); - - llvm::PointerType *GlobalRecPtrTy = - CGF.ConvertTypeForMem(GlobalRecTy)->getPointerTo(); - llvm::Value *GlobalRecCastAddr; - llvm::Value *IsTTD = nullptr; - if (!IsInTTDRegion && - (WithSPMDCheck || - getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_Unknown)) { - llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".exit"); - llvm::BasicBlock *SPMDBB = CGF.createBasicBlock(".spmd"); - llvm::BasicBlock *NonSPMDBB = CGF.createBasicBlock(".non-spmd"); - if (I->getSecond().SecondaryGlobalRecord.hasValue()) { - llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); - llvm::Value *ThreadID = getThreadID(CGF, Loc); - llvm::Value *PL = CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_parallel_level), - {RTLoc, ThreadID}); - IsTTD = Bld.CreateIsNull(PL); - } - llvm::Value *IsSPMD = Bld.CreateIsNotNull(CGF.EmitNounwindRuntimeCall( - createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_is_spmd_exec_mode))); - Bld.CreateCondBr(IsSPMD, SPMDBB, NonSPMDBB); - // There is no need to emit line number for unconditional branch. - (void)ApplyDebugLocation::CreateEmpty(CGF); - CGF.EmitBlock(SPMDBB); - Address RecPtr = Address(llvm::ConstantPointerNull::get(GlobalRecPtrTy), - CharUnits::fromQuantity(Alignment)); - CGF.EmitBranch(ExitBB); - // There is no need to emit line number for unconditional branch. - (void)ApplyDebugLocation::CreateEmpty(CGF); - CGF.EmitBlock(NonSPMDBB); - llvm::Value *Size = llvm::ConstantInt::get(CGM.SizeTy, GlobalRecordSize); - if (const RecordDecl *SecGlobalizedVarsRecord = - I->getSecond().SecondaryGlobalRecord.getValueOr(nullptr)) { - SecGlobalRecTy = - CGM.getContext().getRecordType(SecGlobalizedVarsRecord); - - // Recover pointer to this function's global record. The runtime will - // handle the specifics of the allocation of the memory. - // Use actual memory size of the record including the padding - // for alignment purposes. - unsigned Alignment = - CGM.getContext().getTypeAlignInChars(SecGlobalRecTy).getQuantity(); - unsigned GlobalRecordSize = - CGM.getContext().getTypeSizeInChars(SecGlobalRecTy).getQuantity(); - GlobalRecordSize = llvm::alignTo(GlobalRecordSize, Alignment); - Size = Bld.CreateSelect( - IsTTD, llvm::ConstantInt::get(CGM.SizeTy, GlobalRecordSize), Size); - } - // TODO: allow the usage of shared memory to be controlled by - // the user, for now, default to global. - llvm::Value *GlobalRecordSizeArg[] = { - Size, CGF.Builder.getInt16(/*UseSharedMemory=*/0)}; - llvm::Value *GlobalRecValue = CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction( - OMPRTL_NVPTX__kmpc_data_sharing_coalesced_push_stack), - GlobalRecordSizeArg); - GlobalRecCastAddr = Bld.CreatePointerBitCastOrAddrSpaceCast( - GlobalRecValue, GlobalRecPtrTy); - CGF.EmitBlock(ExitBB); - auto *Phi = Bld.CreatePHI(GlobalRecPtrTy, - /*NumReservedValues=*/2, "_select_stack"); - Phi->addIncoming(RecPtr.getPointer(), SPMDBB); - Phi->addIncoming(GlobalRecCastAddr, NonSPMDBB); - GlobalRecCastAddr = Phi; - I->getSecond().GlobalRecordAddr = Phi; - I->getSecond().IsInSPMDModeFlag = IsSPMD; - } else if (IsInTTDRegion) { - assert(GlobalizedRecords.back().Records.size() < 2 && - "Expected less than 2 globalized records: one for target and one " - "for teams."); - unsigned Offset = 0; - for (const RecordDecl *RD : GlobalizedRecords.back().Records) { - QualType RDTy = CGM.getContext().getRecordType(RD); - unsigned Alignment = - CGM.getContext().getTypeAlignInChars(RDTy).getQuantity(); - unsigned Size = CGM.getContext().getTypeSizeInChars(RDTy).getQuantity(); - Offset = - llvm::alignTo(llvm::alignTo(Offset, Alignment) + Size, Alignment); - } - unsigned Alignment = - CGM.getContext().getTypeAlignInChars(GlobalRecTy).getQuantity(); - Offset = llvm::alignTo(Offset, Alignment); - GlobalizedRecords.back().Records.push_back(GlobalizedVarsRecord); - ++GlobalizedRecords.back().RegionCounter; - if (GlobalizedRecords.back().Records.size() == 1) { - assert(KernelStaticGlobalized && - "Kernel static pointer must be initialized already."); - auto *UseSharedMemory = new llvm::GlobalVariable( - CGM.getModule(), CGM.Int16Ty, /*isConstant=*/true, - llvm::GlobalValue::InternalLinkage, nullptr, - "_openmp_static_kernel$is_shared"); - UseSharedMemory->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - QualType Int16Ty = CGM.getContext().getIntTypeForBitwidth( - /*DestWidth=*/16, /*Signed=*/0); - llvm::Value *IsInSharedMemory = CGF.EmitLoadOfScalar( - Address(UseSharedMemory, - CGM.getContext().getTypeAlignInChars(Int16Ty)), - /*Volatile=*/false, Int16Ty, Loc); - auto *StaticGlobalized = new llvm::GlobalVariable( - CGM.getModule(), CGM.Int8Ty, /*isConstant=*/false, - llvm::GlobalValue::CommonLinkage, nullptr); - auto *RecSize = new llvm::GlobalVariable( - CGM.getModule(), CGM.SizeTy, /*isConstant=*/true, - llvm::GlobalValue::InternalLinkage, nullptr, - "_openmp_static_kernel$size"); - RecSize->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - llvm::Value *Ld = CGF.EmitLoadOfScalar( - Address(RecSize, CGM.getSizeAlign()), /*Volatile=*/false, - CGM.getContext().getSizeType(), Loc); - llvm::Value *ResAddr = Bld.CreatePointerBitCastOrAddrSpaceCast( - KernelStaticGlobalized, CGM.VoidPtrPtrTy); - llvm::Value *GlobalRecordSizeArg[] = { - llvm::ConstantInt::get( - CGM.Int16Ty, - getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_SPMD ? 1 : 0), - StaticGlobalized, Ld, IsInSharedMemory, ResAddr}; - CGF.EmitRuntimeCall(createNVPTXRuntimeFunction( - OMPRTL_NVPTX__kmpc_get_team_static_memory), - GlobalRecordSizeArg); - GlobalizedRecords.back().Buffer = StaticGlobalized; - GlobalizedRecords.back().RecSize = RecSize; - GlobalizedRecords.back().UseSharedMemory = UseSharedMemory; - GlobalizedRecords.back().Loc = Loc; - } - assert(KernelStaticGlobalized && "Global address must be set already."); - Address FrameAddr = CGF.EmitLoadOfPointer( - Address(KernelStaticGlobalized, CGM.getPointerAlign()), - CGM.getContext() - .getPointerType(CGM.getContext().VoidPtrTy) - .castAs<PointerType>()); - llvm::Value *GlobalRecValue = - Bld.CreateConstInBoundsGEP(FrameAddr, Offset, CharUnits::One()) - .getPointer(); - I->getSecond().GlobalRecordAddr = GlobalRecValue; - I->getSecond().IsInSPMDModeFlag = nullptr; - GlobalRecCastAddr = Bld.CreatePointerBitCastOrAddrSpaceCast( - GlobalRecValue, CGF.ConvertTypeForMem(GlobalRecTy)->getPointerTo()); - } else { - // TODO: allow the usage of shared memory to be controlled by - // the user, for now, default to global. - llvm::Value *GlobalRecordSizeArg[] = { - llvm::ConstantInt::get(CGM.SizeTy, GlobalRecordSize), - CGF.Builder.getInt16(/*UseSharedMemory=*/0)}; - llvm::Value *GlobalRecValue = CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction( - OMPRTL_NVPTX__kmpc_data_sharing_coalesced_push_stack), - GlobalRecordSizeArg); - GlobalRecCastAddr = Bld.CreatePointerBitCastOrAddrSpaceCast( - GlobalRecValue, GlobalRecPtrTy); - I->getSecond().GlobalRecordAddr = GlobalRecValue; - I->getSecond().IsInSPMDModeFlag = nullptr; - } - LValue Base = - CGF.MakeNaturalAlignPointeeAddrLValue(GlobalRecCastAddr, GlobalRecTy); - - // Emit the "global alloca" which is a GEP from the global declaration - // record using the pointer returned by the runtime. - LValue SecBase; - decltype(I->getSecond().LocalVarData)::const_iterator SecIt; - if (IsTTD) { - SecIt = I->getSecond().SecondaryLocalVarData->begin(); - llvm::PointerType *SecGlobalRecPtrTy = - CGF.ConvertTypeForMem(SecGlobalRecTy)->getPointerTo(); - SecBase = CGF.MakeNaturalAlignPointeeAddrLValue( - Bld.CreatePointerBitCastOrAddrSpaceCast( - I->getSecond().GlobalRecordAddr, SecGlobalRecPtrTy), - SecGlobalRecTy); - } - for (auto &Rec : I->getSecond().LocalVarData) { - bool EscapedParam = I->getSecond().EscapedParameters.count(Rec.first); - llvm::Value *ParValue; - if (EscapedParam) { - const auto *VD = cast<VarDecl>(Rec.first); - LValue ParLVal = - CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); - ParValue = CGF.EmitLoadOfScalar(ParLVal, Loc); - } - LValue VarAddr = CGF.EmitLValueForField(Base, Rec.second.FD); - // Emit VarAddr basing on lane-id if required. - QualType VarTy; - if (Rec.second.IsOnePerTeam) { - VarTy = Rec.second.FD->getType(); - } else { - llvm::Value *Ptr = CGF.Builder.CreateInBoundsGEP( - VarAddr.getAddress().getPointer(), - {Bld.getInt32(0), getNVPTXLaneID(CGF)}); - VarTy = - Rec.second.FD->getType()->castAsArrayTypeUnsafe()->getElementType(); - VarAddr = CGF.MakeAddrLValue( - Address(Ptr, CGM.getContext().getDeclAlign(Rec.first)), VarTy, - AlignmentSource::Decl); - } - Rec.second.PrivateAddr = VarAddr.getAddress(); - if (!IsInTTDRegion && - (WithSPMDCheck || - getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_Unknown)) { - assert(I->getSecond().IsInSPMDModeFlag && - "Expected unknown execution mode or required SPMD check."); - if (IsTTD) { - assert(SecIt->second.IsOnePerTeam && - "Secondary glob data must be one per team."); - LValue SecVarAddr = CGF.EmitLValueForField(SecBase, SecIt->second.FD); - VarAddr.setAddress( - Address(Bld.CreateSelect(IsTTD, SecVarAddr.getPointer(), - VarAddr.getPointer()), - VarAddr.getAlignment())); - Rec.second.PrivateAddr = VarAddr.getAddress(); - } - Address GlobalPtr = Rec.second.PrivateAddr; - Address LocalAddr = CGF.CreateMemTemp(VarTy, Rec.second.FD->getName()); - Rec.second.PrivateAddr = Address( - Bld.CreateSelect(I->getSecond().IsInSPMDModeFlag, - LocalAddr.getPointer(), GlobalPtr.getPointer()), - LocalAddr.getAlignment()); - } - if (EscapedParam) { - const auto *VD = cast<VarDecl>(Rec.first); - CGF.EmitStoreOfScalar(ParValue, VarAddr); - I->getSecond().MappedParams->setVarAddr(CGF, VD, VarAddr.getAddress()); - } - if (IsTTD) - ++SecIt; - } - } - for (const ValueDecl *VD : I->getSecond().EscapedVariableLengthDecls) { - // Recover pointer to this function's global record. The runtime will - // handle the specifics of the allocation of the memory. - // Use actual memory size of the record including the padding - // for alignment purposes. - CGBuilderTy &Bld = CGF.Builder; - llvm::Value *Size = CGF.getTypeSize(VD->getType()); - CharUnits Align = CGM.getContext().getDeclAlign(VD); - Size = Bld.CreateNUWAdd( - Size, llvm::ConstantInt::get(CGF.SizeTy, Align.getQuantity() - 1)); - llvm::Value *AlignVal = - llvm::ConstantInt::get(CGF.SizeTy, Align.getQuantity()); - Size = Bld.CreateUDiv(Size, AlignVal); - Size = Bld.CreateNUWMul(Size, AlignVal); - // TODO: allow the usage of shared memory to be controlled by - // the user, for now, default to global. - llvm::Value *GlobalRecordSizeArg[] = { - Size, CGF.Builder.getInt16(/*UseSharedMemory=*/0)}; - llvm::Value *GlobalRecValue = CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction( - OMPRTL_NVPTX__kmpc_data_sharing_coalesced_push_stack), - GlobalRecordSizeArg); - llvm::Value *GlobalRecCastAddr = Bld.CreatePointerBitCastOrAddrSpaceCast( - GlobalRecValue, CGF.ConvertTypeForMem(VD->getType())->getPointerTo()); - LValue Base = CGF.MakeAddrLValue(GlobalRecCastAddr, VD->getType(), - CGM.getContext().getDeclAlign(VD), - AlignmentSource::Decl); - I->getSecond().MappedParams->setVarAddr(CGF, cast<VarDecl>(VD), - Base.getAddress()); - I->getSecond().EscapedVariableLengthDeclsAddrs.emplace_back(GlobalRecValue); - } - I->getSecond().MappedParams->apply(CGF); -} - -void CGOpenMPRuntimeNVPTX::emitGenericVarsEpilog(CodeGenFunction &CGF, - bool WithSPMDCheck) { - if (getDataSharingMode(CGM) != CGOpenMPRuntimeNVPTX::Generic && - getExecutionMode() != CGOpenMPRuntimeNVPTX::EM_SPMD) - return; - - const auto I = FunctionGlobalizedDecls.find(CGF.CurFn); - if (I != FunctionGlobalizedDecls.end()) { - I->getSecond().MappedParams->restore(CGF); - if (!CGF.HaveInsertPoint()) - return; - for (llvm::Value *Addr : - llvm::reverse(I->getSecond().EscapedVariableLengthDeclsAddrs)) { - CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_data_sharing_pop_stack), - Addr); - } - if (I->getSecond().GlobalRecordAddr) { - if (!IsInTTDRegion && - (WithSPMDCheck || - getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_Unknown)) { - CGBuilderTy &Bld = CGF.Builder; - llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".exit"); - llvm::BasicBlock *NonSPMDBB = CGF.createBasicBlock(".non-spmd"); - Bld.CreateCondBr(I->getSecond().IsInSPMDModeFlag, ExitBB, NonSPMDBB); - // There is no need to emit line number for unconditional branch. - (void)ApplyDebugLocation::CreateEmpty(CGF); - CGF.EmitBlock(NonSPMDBB); - CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction( - OMPRTL_NVPTX__kmpc_data_sharing_pop_stack), - CGF.EmitCastToVoidPtr(I->getSecond().GlobalRecordAddr)); - CGF.EmitBlock(ExitBB); - } else if (IsInTTDRegion) { - assert(GlobalizedRecords.back().RegionCounter > 0 && - "region counter must be > 0."); - --GlobalizedRecords.back().RegionCounter; - // Emit the restore function only in the target region. - if (GlobalizedRecords.back().RegionCounter == 0) { - QualType Int16Ty = CGM.getContext().getIntTypeForBitwidth( - /*DestWidth=*/16, /*Signed=*/0); - llvm::Value *IsInSharedMemory = CGF.EmitLoadOfScalar( - Address(GlobalizedRecords.back().UseSharedMemory, - CGM.getContext().getTypeAlignInChars(Int16Ty)), - /*Volatile=*/false, Int16Ty, GlobalizedRecords.back().Loc); - llvm::Value *Args[] = { - llvm::ConstantInt::get( - CGM.Int16Ty, - getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_SPMD ? 1 : 0), - IsInSharedMemory}; - CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction( - OMPRTL_NVPTX__kmpc_restore_team_static_memory), - Args); - } - } else { - CGF.EmitRuntimeCall(createNVPTXRuntimeFunction( - OMPRTL_NVPTX__kmpc_data_sharing_pop_stack), - I->getSecond().GlobalRecordAddr); - } - } - } -} - -void CGOpenMPRuntimeNVPTX::emitTeamsCall(CodeGenFunction &CGF, - const OMPExecutableDirective &D, - SourceLocation Loc, - llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> CapturedVars) { - if (!CGF.HaveInsertPoint()) - return; - - Address ZeroAddr = CGF.CreateMemTemp( - CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1), - /*Name*/ ".zero.addr"); - CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0)); - llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; - OutlinedFnArgs.push_back(emitThreadIDAddress(CGF, Loc).getPointer()); - OutlinedFnArgs.push_back(ZeroAddr.getPointer()); - OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); - emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); -} - -void CGOpenMPRuntimeNVPTX::emitParallelCall( - CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> CapturedVars, const Expr *IfCond) { - if (!CGF.HaveInsertPoint()) - return; - - if (getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_SPMD) - emitSPMDParallelCall(CGF, Loc, OutlinedFn, CapturedVars, IfCond); - else - emitNonSPMDParallelCall(CGF, Loc, OutlinedFn, CapturedVars, IfCond); -} - -void CGOpenMPRuntimeNVPTX::emitNonSPMDParallelCall( - CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> CapturedVars, const Expr *IfCond) { - llvm::Function *Fn = cast<llvm::Function>(OutlinedFn); - - // Force inline this outlined function at its call site. - Fn->setLinkage(llvm::GlobalValue::InternalLinkage); - - Address ZeroAddr = CGF.CreateMemTemp(CGF.getContext().getIntTypeForBitwidth( - /*DestWidth=*/32, /*Signed=*/1), - ".zero.addr"); - CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0)); - // ThreadId for serialized parallels is 0. - Address ThreadIDAddr = ZeroAddr; - auto &&CodeGen = [this, Fn, CapturedVars, Loc, ZeroAddr, &ThreadIDAddr]( - CodeGenFunction &CGF, PrePostActionTy &Action) { - Action.Enter(CGF); - - llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; - OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); - OutlinedFnArgs.push_back(ZeroAddr.getPointer()); - OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); - emitOutlinedFunctionCall(CGF, Loc, Fn, OutlinedFnArgs); - }; - auto &&SeqGen = [this, &CodeGen, Loc](CodeGenFunction &CGF, - PrePostActionTy &) { - - RegionCodeGenTy RCG(CodeGen); - llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); - llvm::Value *ThreadID = getThreadID(CGF, Loc); - llvm::Value *Args[] = {RTLoc, ThreadID}; - - NVPTXActionTy Action( - createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_serialized_parallel), - Args, - createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_end_serialized_parallel), - Args); - RCG.setAction(Action); - RCG(CGF); - }; - - auto &&L0ParallelGen = [this, CapturedVars, Fn](CodeGenFunction &CGF, - PrePostActionTy &Action) { - CGBuilderTy &Bld = CGF.Builder; - llvm::Function *WFn = WrapperFunctionsMap[Fn]; - assert(WFn && "Wrapper function does not exist!"); - llvm::Value *ID = Bld.CreateBitOrPointerCast(WFn, CGM.Int8PtrTy); - - // Prepare for parallel region. Indicate the outlined function. - llvm::Value *Args[] = {ID, /*RequiresOMPRuntime=*/Bld.getInt16(1)}; - CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_prepare_parallel), - Args); - - // Create a private scope that will globalize the arguments - // passed from the outside of the target region. - CodeGenFunction::OMPPrivateScope PrivateArgScope(CGF); - - // There's something to share. - if (!CapturedVars.empty()) { - // Prepare for parallel region. Indicate the outlined function. - Address SharedArgs = - CGF.CreateDefaultAlignTempAlloca(CGF.VoidPtrPtrTy, "shared_arg_refs"); - llvm::Value *SharedArgsPtr = SharedArgs.getPointer(); - - llvm::Value *DataSharingArgs[] = { - SharedArgsPtr, - llvm::ConstantInt::get(CGM.SizeTy, CapturedVars.size())}; - CGF.EmitRuntimeCall(createNVPTXRuntimeFunction( - OMPRTL_NVPTX__kmpc_begin_sharing_variables), - DataSharingArgs); - - // Store variable address in a list of references to pass to workers. - unsigned Idx = 0; - ASTContext &Ctx = CGF.getContext(); - Address SharedArgListAddress = CGF.EmitLoadOfPointer( - SharedArgs, Ctx.getPointerType(Ctx.getPointerType(Ctx.VoidPtrTy)) - .castAs<PointerType>()); - for (llvm::Value *V : CapturedVars) { - Address Dst = Bld.CreateConstInBoundsGEP(SharedArgListAddress, Idx, - CGF.getPointerSize()); - llvm::Value *PtrV; - if (V->getType()->isIntegerTy()) - PtrV = Bld.CreateIntToPtr(V, CGF.VoidPtrTy); - else - PtrV = Bld.CreatePointerBitCastOrAddrSpaceCast(V, CGF.VoidPtrTy); - CGF.EmitStoreOfScalar(PtrV, Dst, /*Volatile=*/false, - Ctx.getPointerType(Ctx.VoidPtrTy)); - ++Idx; - } - } - - // Activate workers. This barrier is used by the master to signal - // work for the workers. - syncCTAThreads(CGF); - - // OpenMP [2.5, Parallel Construct, p.49] - // There is an implied barrier at the end of a parallel region. After the - // end of a parallel region, only the master thread of the team resumes - // execution of the enclosing task region. - // - // The master waits at this barrier until all workers are done. - syncCTAThreads(CGF); - - if (!CapturedVars.empty()) - CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_end_sharing_variables)); - - // Remember for post-processing in worker loop. - Work.emplace_back(WFn); - }; - - auto &&LNParallelGen = [this, Loc, &SeqGen, &L0ParallelGen]( - CodeGenFunction &CGF, PrePostActionTy &Action) { - if (IsInParallelRegion) { - SeqGen(CGF, Action); - } else if (IsInTargetMasterThreadRegion) { - L0ParallelGen(CGF, Action); - } else { - // Check for master and then parallelism: - // if (__kmpc_is_spmd_exec_mode() || __kmpc_parallel_level(loc, gtid)) { - // Serialized execution. - // } else { - // Worker call. - // } - CGBuilderTy &Bld = CGF.Builder; - llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".exit"); - llvm::BasicBlock *SeqBB = CGF.createBasicBlock(".sequential"); - llvm::BasicBlock *ParallelCheckBB = CGF.createBasicBlock(".parcheck"); - llvm::BasicBlock *MasterBB = CGF.createBasicBlock(".master"); - llvm::Value *IsSPMD = Bld.CreateIsNotNull(CGF.EmitNounwindRuntimeCall( - createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_is_spmd_exec_mode))); - Bld.CreateCondBr(IsSPMD, SeqBB, ParallelCheckBB); - // There is no need to emit line number for unconditional branch. - (void)ApplyDebugLocation::CreateEmpty(CGF); - CGF.EmitBlock(ParallelCheckBB); - llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); - llvm::Value *ThreadID = getThreadID(CGF, Loc); - llvm::Value *PL = CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_parallel_level), - {RTLoc, ThreadID}); - llvm::Value *Res = Bld.CreateIsNotNull(PL); - Bld.CreateCondBr(Res, SeqBB, MasterBB); - CGF.EmitBlock(SeqBB); - SeqGen(CGF, Action); - CGF.EmitBranch(ExitBB); - // There is no need to emit line number for unconditional branch. - (void)ApplyDebugLocation::CreateEmpty(CGF); - CGF.EmitBlock(MasterBB); - L0ParallelGen(CGF, Action); - CGF.EmitBranch(ExitBB); - // There is no need to emit line number for unconditional branch. - (void)ApplyDebugLocation::CreateEmpty(CGF); - // Emit the continuation block for code after the if. - CGF.EmitBlock(ExitBB, /*IsFinished=*/true); - } - }; - - if (IfCond) { - emitOMPIfClause(CGF, IfCond, LNParallelGen, SeqGen); - } else { - CodeGenFunction::RunCleanupsScope Scope(CGF); - RegionCodeGenTy ThenRCG(LNParallelGen); - ThenRCG(CGF); - } -} - -void CGOpenMPRuntimeNVPTX::emitSPMDParallelCall( - CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> CapturedVars, const Expr *IfCond) { - // Just call the outlined function to execute the parallel region. - // OutlinedFn(>id, &zero, CapturedStruct); - // - llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; - - Address ZeroAddr = CGF.CreateMemTemp(CGF.getContext().getIntTypeForBitwidth( - /*DestWidth=*/32, /*Signed=*/1), - ".zero.addr"); - CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0)); - // ThreadId for serialized parallels is 0. - Address ThreadIDAddr = ZeroAddr; - auto &&CodeGen = [this, OutlinedFn, CapturedVars, Loc, ZeroAddr, - &ThreadIDAddr](CodeGenFunction &CGF, - PrePostActionTy &Action) { - Action.Enter(CGF); - - llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; - OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); - OutlinedFnArgs.push_back(ZeroAddr.getPointer()); - OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); - emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); - }; - auto &&SeqGen = [this, &CodeGen, Loc](CodeGenFunction &CGF, - PrePostActionTy &) { - - RegionCodeGenTy RCG(CodeGen); - llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); - llvm::Value *ThreadID = getThreadID(CGF, Loc); - llvm::Value *Args[] = {RTLoc, ThreadID}; - - NVPTXActionTy Action( - createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_serialized_parallel), - Args, - createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_end_serialized_parallel), - Args); - RCG.setAction(Action); - RCG(CGF); - }; - - if (IsInTargetMasterThreadRegion) { - // In the worker need to use the real thread id. - ThreadIDAddr = emitThreadIDAddress(CGF, Loc); - RegionCodeGenTy RCG(CodeGen); - RCG(CGF); - } else { - // If we are not in the target region, it is definitely L2 parallelism or - // more, because for SPMD mode we always has L1 parallel level, sowe don't - // need to check for orphaned directives. - RegionCodeGenTy RCG(SeqGen); - RCG(CGF); - } -} - -void CGOpenMPRuntimeNVPTX::syncCTAThreads(CodeGenFunction &CGF) { - // Always emit simple barriers! - if (!CGF.HaveInsertPoint()) - return; - // Build call __kmpc_barrier_simple_spmd(nullptr, 0); - // This function does not use parameters, so we can emit just default values. - llvm::Value *Args[] = { - llvm::ConstantPointerNull::get( - cast<llvm::PointerType>(getIdentTyPointerTy())), - llvm::ConstantInt::get(CGF.Int32Ty, /*V=*/0, /*isSigned=*/true)}; - CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction(OMPRTL__kmpc_barrier_simple_spmd), Args); -} - -void CGOpenMPRuntimeNVPTX::emitBarrierCall(CodeGenFunction &CGF, - SourceLocation Loc, - OpenMPDirectiveKind Kind, bool, - bool) { - // Always emit simple barriers! - if (!CGF.HaveInsertPoint()) - return; - // Build call __kmpc_cancel_barrier(loc, thread_id); - unsigned Flags = getDefaultFlagsForBarriers(Kind); - llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), - getThreadID(CGF, Loc)}; - CGF.EmitRuntimeCall(createNVPTXRuntimeFunction(OMPRTL__kmpc_barrier), Args); -} - -void CGOpenMPRuntimeNVPTX::emitCriticalRegion( - CodeGenFunction &CGF, StringRef CriticalName, - const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, - const Expr *Hint) { - llvm::BasicBlock *LoopBB = CGF.createBasicBlock("omp.critical.loop"); - llvm::BasicBlock *TestBB = CGF.createBasicBlock("omp.critical.test"); - llvm::BasicBlock *SyncBB = CGF.createBasicBlock("omp.critical.sync"); - llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.critical.body"); - llvm::BasicBlock *ExitBB = CGF.createBasicBlock("omp.critical.exit"); - - // Fetch team-local id of the thread. - llvm::Value *ThreadID = getNVPTXThreadID(CGF); - - // Get the width of the team. - llvm::Value *TeamWidth = getNVPTXNumThreads(CGF); - - // Initialize the counter variable for the loop. - QualType Int32Ty = - CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/0); - Address Counter = CGF.CreateMemTemp(Int32Ty, "critical_counter"); - LValue CounterLVal = CGF.MakeAddrLValue(Counter, Int32Ty); - CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.Int32Ty), CounterLVal, - /*isInit=*/true); - - // Block checks if loop counter exceeds upper bound. - CGF.EmitBlock(LoopBB); - llvm::Value *CounterVal = CGF.EmitLoadOfScalar(CounterLVal, Loc); - llvm::Value *CmpLoopBound = CGF.Builder.CreateICmpSLT(CounterVal, TeamWidth); - CGF.Builder.CreateCondBr(CmpLoopBound, TestBB, ExitBB); - - // Block tests which single thread should execute region, and which threads - // should go straight to synchronisation point. - CGF.EmitBlock(TestBB); - CounterVal = CGF.EmitLoadOfScalar(CounterLVal, Loc); - llvm::Value *CmpThreadToCounter = - CGF.Builder.CreateICmpEQ(ThreadID, CounterVal); - CGF.Builder.CreateCondBr(CmpThreadToCounter, BodyBB, SyncBB); - - // Block emits the body of the critical region. - CGF.EmitBlock(BodyBB); - - // Output the critical statement. - CGOpenMPRuntime::emitCriticalRegion(CGF, CriticalName, CriticalOpGen, Loc, - Hint); - - // After the body surrounded by the critical region, the single executing - // thread will jump to the synchronisation point. - // Block waits for all threads in current team to finish then increments the - // counter variable and returns to the loop. - CGF.EmitBlock(SyncBB); - emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false, - /*ForceSimpleCall=*/true); - - llvm::Value *IncCounterVal = - CGF.Builder.CreateNSWAdd(CounterVal, CGF.Builder.getInt32(1)); - CGF.EmitStoreOfScalar(IncCounterVal, CounterLVal); - CGF.EmitBranch(LoopBB); - - // Block that is reached when all threads in the team complete the region. - CGF.EmitBlock(ExitBB, /*IsFinished=*/true); -} - -/// Cast value to the specified type. -static llvm::Value *castValueToType(CodeGenFunction &CGF, llvm::Value *Val, - QualType ValTy, QualType CastTy, - SourceLocation Loc) { - assert(!CGF.getContext().getTypeSizeInChars(CastTy).isZero() && - "Cast type must sized."); - assert(!CGF.getContext().getTypeSizeInChars(ValTy).isZero() && - "Val type must sized."); - llvm::Type *LLVMCastTy = CGF.ConvertTypeForMem(CastTy); - if (ValTy == CastTy) - return Val; - if (CGF.getContext().getTypeSizeInChars(ValTy) == - CGF.getContext().getTypeSizeInChars(CastTy)) - return CGF.Builder.CreateBitCast(Val, LLVMCastTy); - if (CastTy->isIntegerType() && ValTy->isIntegerType()) - return CGF.Builder.CreateIntCast(Val, LLVMCastTy, - CastTy->hasSignedIntegerRepresentation()); - Address CastItem = CGF.CreateMemTemp(CastTy); - Address ValCastItem = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - CastItem, Val->getType()->getPointerTo(CastItem.getAddressSpace())); - CGF.EmitStoreOfScalar(Val, ValCastItem, /*Volatile=*/false, ValTy); - return CGF.EmitLoadOfScalar(CastItem, /*Volatile=*/false, CastTy, Loc); -} - -/// This function creates calls to one of two shuffle functions to copy -/// variables between lanes in a warp. -static llvm::Value *createRuntimeShuffleFunction(CodeGenFunction &CGF, - llvm::Value *Elem, - QualType ElemType, - llvm::Value *Offset, - SourceLocation Loc) { - CodeGenModule &CGM = CGF.CGM; - CGBuilderTy &Bld = CGF.Builder; - CGOpenMPRuntimeNVPTX &RT = - *(static_cast<CGOpenMPRuntimeNVPTX *>(&CGM.getOpenMPRuntime())); - - CharUnits Size = CGF.getContext().getTypeSizeInChars(ElemType); - assert(Size.getQuantity() <= 8 && - "Unsupported bitwidth in shuffle instruction."); - - OpenMPRTLFunctionNVPTX ShuffleFn = Size.getQuantity() <= 4 - ? OMPRTL_NVPTX__kmpc_shuffle_int32 - : OMPRTL_NVPTX__kmpc_shuffle_int64; - - // Cast all types to 32- or 64-bit values before calling shuffle routines. - QualType CastTy = CGF.getContext().getIntTypeForBitwidth( - Size.getQuantity() <= 4 ? 32 : 64, /*Signed=*/1); - llvm::Value *ElemCast = castValueToType(CGF, Elem, ElemType, CastTy, Loc); - llvm::Value *WarpSize = - Bld.CreateIntCast(getNVPTXWarpSize(CGF), CGM.Int16Ty, /*isSigned=*/true); - - llvm::Value *ShuffledVal = CGF.EmitRuntimeCall( - RT.createNVPTXRuntimeFunction(ShuffleFn), {ElemCast, Offset, WarpSize}); - - return castValueToType(CGF, ShuffledVal, CastTy, ElemType, Loc); -} - -static void shuffleAndStore(CodeGenFunction &CGF, Address SrcAddr, - Address DestAddr, QualType ElemType, - llvm::Value *Offset, SourceLocation Loc) { - CGBuilderTy &Bld = CGF.Builder; - - CharUnits Size = CGF.getContext().getTypeSizeInChars(ElemType); - // Create the loop over the big sized data. - // ptr = (void*)Elem; - // ptrEnd = (void*) Elem + 1; - // Step = 8; - // while (ptr + Step < ptrEnd) - // shuffle((int64_t)*ptr); - // Step = 4; - // while (ptr + Step < ptrEnd) - // shuffle((int32_t)*ptr); - // ... - Address ElemPtr = DestAddr; - Address Ptr = SrcAddr; - Address PtrEnd = Bld.CreatePointerBitCastOrAddrSpaceCast( - Bld.CreateConstGEP(SrcAddr, 1, Size), CGF.VoidPtrTy); - for (int IntSize = 8; IntSize >= 1; IntSize /= 2) { - if (Size < CharUnits::fromQuantity(IntSize)) - continue; - QualType IntType = CGF.getContext().getIntTypeForBitwidth( - CGF.getContext().toBits(CharUnits::fromQuantity(IntSize)), - /*Signed=*/1); - llvm::Type *IntTy = CGF.ConvertTypeForMem(IntType); - Ptr = Bld.CreatePointerBitCastOrAddrSpaceCast(Ptr, IntTy->getPointerTo()); - ElemPtr = - Bld.CreatePointerBitCastOrAddrSpaceCast(ElemPtr, IntTy->getPointerTo()); - if (Size.getQuantity() / IntSize > 1) { - llvm::BasicBlock *PreCondBB = CGF.createBasicBlock(".shuffle.pre_cond"); - llvm::BasicBlock *ThenBB = CGF.createBasicBlock(".shuffle.then"); - llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".shuffle.exit"); - llvm::BasicBlock *CurrentBB = Bld.GetInsertBlock(); - CGF.EmitBlock(PreCondBB); - llvm::PHINode *PhiSrc = - Bld.CreatePHI(Ptr.getType(), /*NumReservedValues=*/2); - PhiSrc->addIncoming(Ptr.getPointer(), CurrentBB); - llvm::PHINode *PhiDest = - Bld.CreatePHI(ElemPtr.getType(), /*NumReservedValues=*/2); - PhiDest->addIncoming(ElemPtr.getPointer(), CurrentBB); - Ptr = Address(PhiSrc, Ptr.getAlignment()); - ElemPtr = Address(PhiDest, ElemPtr.getAlignment()); - llvm::Value *PtrDiff = Bld.CreatePtrDiff( - PtrEnd.getPointer(), Bld.CreatePointerBitCastOrAddrSpaceCast( - Ptr.getPointer(), CGF.VoidPtrTy)); - Bld.CreateCondBr(Bld.CreateICmpSGT(PtrDiff, Bld.getInt64(IntSize - 1)), - ThenBB, ExitBB); - CGF.EmitBlock(ThenBB); - llvm::Value *Res = createRuntimeShuffleFunction( - CGF, CGF.EmitLoadOfScalar(Ptr, /*Volatile=*/false, IntType, Loc), - IntType, Offset, Loc); - CGF.EmitStoreOfScalar(Res, ElemPtr, /*Volatile=*/false, IntType); - Address LocalPtr = - Bld.CreateConstGEP(Ptr, 1, CharUnits::fromQuantity(IntSize)); - Address LocalElemPtr = - Bld.CreateConstGEP(ElemPtr, 1, CharUnits::fromQuantity(IntSize)); - PhiSrc->addIncoming(LocalPtr.getPointer(), ThenBB); - PhiDest->addIncoming(LocalElemPtr.getPointer(), ThenBB); - CGF.EmitBranch(PreCondBB); - CGF.EmitBlock(ExitBB); - } else { - llvm::Value *Res = createRuntimeShuffleFunction( - CGF, CGF.EmitLoadOfScalar(Ptr, /*Volatile=*/false, IntType, Loc), - IntType, Offset, Loc); - CGF.EmitStoreOfScalar(Res, ElemPtr, /*Volatile=*/false, IntType); - Ptr = Bld.CreateConstGEP(Ptr, 1, CharUnits::fromQuantity(IntSize)); - ElemPtr = - Bld.CreateConstGEP(ElemPtr, 1, CharUnits::fromQuantity(IntSize)); - } - Size = Size % IntSize; - } -} - -namespace { -enum CopyAction : unsigned { - // RemoteLaneToThread: Copy over a Reduce list from a remote lane in - // the warp using shuffle instructions. - RemoteLaneToThread, - // ThreadCopy: Make a copy of a Reduce list on the thread's stack. - ThreadCopy, - // ThreadToScratchpad: Copy a team-reduced array to the scratchpad. - ThreadToScratchpad, - // ScratchpadToThread: Copy from a scratchpad array in global memory - // containing team-reduced data to a thread's stack. - ScratchpadToThread, -}; -} // namespace - -struct CopyOptionsTy { - llvm::Value *RemoteLaneOffset; - llvm::Value *ScratchpadIndex; - llvm::Value *ScratchpadWidth; -}; - -/// Emit instructions to copy a Reduce list, which contains partially -/// aggregated values, in the specified direction. -static void emitReductionListCopy( - CopyAction Action, CodeGenFunction &CGF, QualType ReductionArrayTy, - ArrayRef<const Expr *> Privates, Address SrcBase, Address DestBase, - CopyOptionsTy CopyOptions = {nullptr, nullptr, nullptr}) { - - CodeGenModule &CGM = CGF.CGM; - ASTContext &C = CGM.getContext(); - CGBuilderTy &Bld = CGF.Builder; - - llvm::Value *RemoteLaneOffset = CopyOptions.RemoteLaneOffset; - llvm::Value *ScratchpadIndex = CopyOptions.ScratchpadIndex; - llvm::Value *ScratchpadWidth = CopyOptions.ScratchpadWidth; - - // Iterates, element-by-element, through the source Reduce list and - // make a copy. - unsigned Idx = 0; - unsigned Size = Privates.size(); - for (const Expr *Private : Privates) { - Address SrcElementAddr = Address::invalid(); - Address DestElementAddr = Address::invalid(); - Address DestElementPtrAddr = Address::invalid(); - // Should we shuffle in an element from a remote lane? - bool ShuffleInElement = false; - // Set to true to update the pointer in the dest Reduce list to a - // newly created element. - bool UpdateDestListPtr = false; - // Increment the src or dest pointer to the scratchpad, for each - // new element. - bool IncrScratchpadSrc = false; - bool IncrScratchpadDest = false; - - switch (Action) { - case RemoteLaneToThread: { - // Step 1.1: Get the address for the src element in the Reduce list. - Address SrcElementPtrAddr = - Bld.CreateConstArrayGEP(SrcBase, Idx, CGF.getPointerSize()); - SrcElementAddr = CGF.EmitLoadOfPointer( - SrcElementPtrAddr, - C.getPointerType(Private->getType())->castAs<PointerType>()); - - // Step 1.2: Create a temporary to store the element in the destination - // Reduce list. - DestElementPtrAddr = - Bld.CreateConstArrayGEP(DestBase, Idx, CGF.getPointerSize()); - DestElementAddr = - CGF.CreateMemTemp(Private->getType(), ".omp.reduction.element"); - ShuffleInElement = true; - UpdateDestListPtr = true; - break; - } - case ThreadCopy: { - // Step 1.1: Get the address for the src element in the Reduce list. - Address SrcElementPtrAddr = - Bld.CreateConstArrayGEP(SrcBase, Idx, CGF.getPointerSize()); - SrcElementAddr = CGF.EmitLoadOfPointer( - SrcElementPtrAddr, - C.getPointerType(Private->getType())->castAs<PointerType>()); - - // Step 1.2: Get the address for dest element. The destination - // element has already been created on the thread's stack. - DestElementPtrAddr = - Bld.CreateConstArrayGEP(DestBase, Idx, CGF.getPointerSize()); - DestElementAddr = CGF.EmitLoadOfPointer( - DestElementPtrAddr, - C.getPointerType(Private->getType())->castAs<PointerType>()); - break; - } - case ThreadToScratchpad: { - // Step 1.1: Get the address for the src element in the Reduce list. - Address SrcElementPtrAddr = - Bld.CreateConstArrayGEP(SrcBase, Idx, CGF.getPointerSize()); - SrcElementAddr = CGF.EmitLoadOfPointer( - SrcElementPtrAddr, - C.getPointerType(Private->getType())->castAs<PointerType>()); - - // Step 1.2: Get the address for dest element: - // address = base + index * ElementSizeInChars. - llvm::Value *ElementSizeInChars = CGF.getTypeSize(Private->getType()); - llvm::Value *CurrentOffset = - Bld.CreateNUWMul(ElementSizeInChars, ScratchpadIndex); - llvm::Value *ScratchPadElemAbsolutePtrVal = - Bld.CreateNUWAdd(DestBase.getPointer(), CurrentOffset); - ScratchPadElemAbsolutePtrVal = - Bld.CreateIntToPtr(ScratchPadElemAbsolutePtrVal, CGF.VoidPtrTy); - DestElementAddr = Address(ScratchPadElemAbsolutePtrVal, - C.getTypeAlignInChars(Private->getType())); - IncrScratchpadDest = true; - break; - } - case ScratchpadToThread: { - // Step 1.1: Get the address for the src element in the scratchpad. - // address = base + index * ElementSizeInChars. - llvm::Value *ElementSizeInChars = CGF.getTypeSize(Private->getType()); - llvm::Value *CurrentOffset = - Bld.CreateNUWMul(ElementSizeInChars, ScratchpadIndex); - llvm::Value *ScratchPadElemAbsolutePtrVal = - Bld.CreateNUWAdd(SrcBase.getPointer(), CurrentOffset); - ScratchPadElemAbsolutePtrVal = - Bld.CreateIntToPtr(ScratchPadElemAbsolutePtrVal, CGF.VoidPtrTy); - SrcElementAddr = Address(ScratchPadElemAbsolutePtrVal, - C.getTypeAlignInChars(Private->getType())); - IncrScratchpadSrc = true; - - // Step 1.2: Create a temporary to store the element in the destination - // Reduce list. - DestElementPtrAddr = - Bld.CreateConstArrayGEP(DestBase, Idx, CGF.getPointerSize()); - DestElementAddr = - CGF.CreateMemTemp(Private->getType(), ".omp.reduction.element"); - UpdateDestListPtr = true; - break; - } - } - - // Regardless of src and dest of copy, we emit the load of src - // element as this is required in all directions - SrcElementAddr = Bld.CreateElementBitCast( - SrcElementAddr, CGF.ConvertTypeForMem(Private->getType())); - DestElementAddr = Bld.CreateElementBitCast(DestElementAddr, - SrcElementAddr.getElementType()); - - // Now that all active lanes have read the element in the - // Reduce list, shuffle over the value from the remote lane. - if (ShuffleInElement) { - shuffleAndStore(CGF, SrcElementAddr, DestElementAddr, Private->getType(), - RemoteLaneOffset, Private->getExprLoc()); - } else { - if (Private->getType()->isScalarType()) { - llvm::Value *Elem = - CGF.EmitLoadOfScalar(SrcElementAddr, /*Volatile=*/false, - Private->getType(), Private->getExprLoc()); - // Store the source element value to the dest element address. - CGF.EmitStoreOfScalar(Elem, DestElementAddr, /*Volatile=*/false, - Private->getType()); - } else { - CGF.EmitAggregateCopy( - CGF.MakeAddrLValue(DestElementAddr, Private->getType()), - CGF.MakeAddrLValue(SrcElementAddr, Private->getType()), - Private->getType(), AggValueSlot::DoesNotOverlap); - } - } - - // Step 3.1: Modify reference in dest Reduce list as needed. - // Modifying the reference in Reduce list to point to the newly - // created element. The element is live in the current function - // scope and that of functions it invokes (i.e., reduce_function). - // RemoteReduceData[i] = (void*)&RemoteElem - if (UpdateDestListPtr) { - CGF.EmitStoreOfScalar(Bld.CreatePointerBitCastOrAddrSpaceCast( - DestElementAddr.getPointer(), CGF.VoidPtrTy), - DestElementPtrAddr, /*Volatile=*/false, - C.VoidPtrTy); - } - - // Step 4.1: Increment SrcBase/DestBase so that it points to the starting - // address of the next element in scratchpad memory, unless we're currently - // processing the last one. Memory alignment is also taken care of here. - if ((IncrScratchpadDest || IncrScratchpadSrc) && (Idx + 1 < Size)) { - llvm::Value *ScratchpadBasePtr = - IncrScratchpadDest ? DestBase.getPointer() : SrcBase.getPointer(); - llvm::Value *ElementSizeInChars = CGF.getTypeSize(Private->getType()); - ScratchpadBasePtr = Bld.CreateNUWAdd( - ScratchpadBasePtr, - Bld.CreateNUWMul(ScratchpadWidth, ElementSizeInChars)); - - // Take care of global memory alignment for performance - ScratchpadBasePtr = Bld.CreateNUWSub( - ScratchpadBasePtr, llvm::ConstantInt::get(CGM.SizeTy, 1)); - ScratchpadBasePtr = Bld.CreateUDiv( - ScratchpadBasePtr, - llvm::ConstantInt::get(CGM.SizeTy, GlobalMemoryAlignment)); - ScratchpadBasePtr = Bld.CreateNUWAdd( - ScratchpadBasePtr, llvm::ConstantInt::get(CGM.SizeTy, 1)); - ScratchpadBasePtr = Bld.CreateNUWMul( - ScratchpadBasePtr, - llvm::ConstantInt::get(CGM.SizeTy, GlobalMemoryAlignment)); - - if (IncrScratchpadDest) - DestBase = Address(ScratchpadBasePtr, CGF.getPointerAlign()); - else /* IncrScratchpadSrc = true */ - SrcBase = Address(ScratchpadBasePtr, CGF.getPointerAlign()); - } - - ++Idx; - } -} - -/// This function emits a helper that gathers Reduce lists from the first -/// lane of every active warp to lanes in the first warp. -/// -/// void inter_warp_copy_func(void* reduce_data, num_warps) -/// shared smem[warp_size]; -/// For all data entries D in reduce_data: -/// sync -/// If (I am the first lane in each warp) -/// Copy my local D to smem[warp_id] -/// sync -/// if (I am the first warp) -/// Copy smem[thread_id] to my local D -static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM, - ArrayRef<const Expr *> Privates, - QualType ReductionArrayTy, - SourceLocation Loc) { - ASTContext &C = CGM.getContext(); - llvm::Module &M = CGM.getModule(); - - // ReduceList: thread local Reduce list. - // At the stage of the computation when this function is called, partially - // aggregated values reside in the first lane of every active warp. - ImplicitParamDecl ReduceListArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, - C.VoidPtrTy, ImplicitParamDecl::Other); - // NumWarps: number of warps active in the parallel region. This could - // be smaller than 32 (max warps in a CTA) for partial block reduction. - ImplicitParamDecl NumWarpsArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, - C.getIntTypeForBitwidth(32, /* Signed */ true), - ImplicitParamDecl::Other); - FunctionArgList Args; - Args.push_back(&ReduceListArg); - Args.push_back(&NumWarpsArg); - - const CGFunctionInfo &CGFI = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); - auto *Fn = llvm::Function::Create( - CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage, - "_omp_reduction_inter_warp_copy_func", &CGM.getModule()); - CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); - Fn->setDoesNotRecurse(); - CodeGenFunction CGF(CGM); - CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); - - CGBuilderTy &Bld = CGF.Builder; - - // This array is used as a medium to transfer, one reduce element at a time, - // the data from the first lane of every warp to lanes in the first warp - // in order to perform the final step of a reduction in a parallel region - // (reduction across warps). The array is placed in NVPTX __shared__ memory - // for reduced latency, as well as to have a distinct copy for concurrently - // executing target regions. The array is declared with common linkage so - // as to be shared across compilation units. - StringRef TransferMediumName = - "__openmp_nvptx_data_transfer_temporary_storage"; - llvm::GlobalVariable *TransferMedium = - M.getGlobalVariable(TransferMediumName); - if (!TransferMedium) { - auto *Ty = llvm::ArrayType::get(CGM.Int32Ty, WarpSize); - unsigned SharedAddressSpace = C.getTargetAddressSpace(LangAS::cuda_shared); - TransferMedium = new llvm::GlobalVariable( - M, Ty, /*isConstant=*/false, llvm::GlobalVariable::CommonLinkage, - llvm::Constant::getNullValue(Ty), TransferMediumName, - /*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal, - SharedAddressSpace); - CGM.addCompilerUsedGlobal(TransferMedium); - } - - // Get the CUDA thread id of the current OpenMP thread on the GPU. - llvm::Value *ThreadID = getNVPTXThreadID(CGF); - // nvptx_lane_id = nvptx_id % warpsize - llvm::Value *LaneID = getNVPTXLaneID(CGF); - // nvptx_warp_id = nvptx_id / warpsize - llvm::Value *WarpID = getNVPTXWarpID(CGF); - - Address AddrReduceListArg = CGF.GetAddrOfLocalVar(&ReduceListArg); - Address LocalReduceList( - Bld.CreatePointerBitCastOrAddrSpaceCast( - CGF.EmitLoadOfScalar(AddrReduceListArg, /*Volatile=*/false, - C.VoidPtrTy, Loc), - CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo()), - CGF.getPointerAlign()); - - unsigned Idx = 0; - for (const Expr *Private : Privates) { - // - // Warp master copies reduce element to transfer medium in __shared__ - // memory. - // - unsigned RealTySize = - C.getTypeSizeInChars(Private->getType()) - .alignTo(C.getTypeAlignInChars(Private->getType())) - .getQuantity(); - for (unsigned TySize = 4; TySize > 0 && RealTySize > 0; TySize /=2) { - unsigned NumIters = RealTySize / TySize; - if (NumIters == 0) - continue; - QualType CType = C.getIntTypeForBitwidth( - C.toBits(CharUnits::fromQuantity(TySize)), /*Signed=*/1); - llvm::Type *CopyType = CGF.ConvertTypeForMem(CType); - CharUnits Align = CharUnits::fromQuantity(TySize); - llvm::Value *Cnt = nullptr; - Address CntAddr = Address::invalid(); - llvm::BasicBlock *PrecondBB = nullptr; - llvm::BasicBlock *ExitBB = nullptr; - if (NumIters > 1) { - CntAddr = CGF.CreateMemTemp(C.IntTy, ".cnt.addr"); - CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.IntTy), CntAddr, - /*Volatile=*/false, C.IntTy); - PrecondBB = CGF.createBasicBlock("precond"); - ExitBB = CGF.createBasicBlock("exit"); - llvm::BasicBlock *BodyBB = CGF.createBasicBlock("body"); - // There is no need to emit line number for unconditional branch. - (void)ApplyDebugLocation::CreateEmpty(CGF); - CGF.EmitBlock(PrecondBB); - Cnt = CGF.EmitLoadOfScalar(CntAddr, /*Volatile=*/false, C.IntTy, Loc); - llvm::Value *Cmp = - Bld.CreateICmpULT(Cnt, llvm::ConstantInt::get(CGM.IntTy, NumIters)); - Bld.CreateCondBr(Cmp, BodyBB, ExitBB); - CGF.EmitBlock(BodyBB); - } - // kmpc_barrier. - CGM.getOpenMPRuntime().emitBarrierCall(CGF, Loc, OMPD_unknown, - /*EmitChecks=*/false, - /*ForceSimpleCall=*/true); - llvm::BasicBlock *ThenBB = CGF.createBasicBlock("then"); - llvm::BasicBlock *ElseBB = CGF.createBasicBlock("else"); - llvm::BasicBlock *MergeBB = CGF.createBasicBlock("ifcont"); - - // if (lane_id == 0) - llvm::Value *IsWarpMaster = Bld.CreateIsNull(LaneID, "warp_master"); - Bld.CreateCondBr(IsWarpMaster, ThenBB, ElseBB); - CGF.EmitBlock(ThenBB); - - // Reduce element = LocalReduceList[i] - Address ElemPtrPtrAddr = - Bld.CreateConstArrayGEP(LocalReduceList, Idx, CGF.getPointerSize()); - llvm::Value *ElemPtrPtr = CGF.EmitLoadOfScalar( - ElemPtrPtrAddr, /*Volatile=*/false, C.VoidPtrTy, SourceLocation()); - // elemptr = ((CopyType*)(elemptrptr)) + I - Address ElemPtr = Address(ElemPtrPtr, Align); - ElemPtr = Bld.CreateElementBitCast(ElemPtr, CopyType); - if (NumIters > 1) { - ElemPtr = Address(Bld.CreateGEP(ElemPtr.getPointer(), Cnt), - ElemPtr.getAlignment()); - } - - // Get pointer to location in transfer medium. - // MediumPtr = &medium[warp_id] - llvm::Value *MediumPtrVal = Bld.CreateInBoundsGEP( - TransferMedium, {llvm::Constant::getNullValue(CGM.Int64Ty), WarpID}); - Address MediumPtr(MediumPtrVal, Align); - // Casting to actual data type. - // MediumPtr = (CopyType*)MediumPtrAddr; - MediumPtr = Bld.CreateElementBitCast(MediumPtr, CopyType); - - // elem = *elemptr - //*MediumPtr = elem - llvm::Value *Elem = - CGF.EmitLoadOfScalar(ElemPtr, /*Volatile=*/false, CType, Loc); - // Store the source element value to the dest element address. - CGF.EmitStoreOfScalar(Elem, MediumPtr, /*Volatile=*/true, CType); - - Bld.CreateBr(MergeBB); - - CGF.EmitBlock(ElseBB); - Bld.CreateBr(MergeBB); - - CGF.EmitBlock(MergeBB); - - // kmpc_barrier. - CGM.getOpenMPRuntime().emitBarrierCall(CGF, Loc, OMPD_unknown, - /*EmitChecks=*/false, - /*ForceSimpleCall=*/true); - - // - // Warp 0 copies reduce element from transfer medium. - // - llvm::BasicBlock *W0ThenBB = CGF.createBasicBlock("then"); - llvm::BasicBlock *W0ElseBB = CGF.createBasicBlock("else"); - llvm::BasicBlock *W0MergeBB = CGF.createBasicBlock("ifcont"); - - Address AddrNumWarpsArg = CGF.GetAddrOfLocalVar(&NumWarpsArg); - llvm::Value *NumWarpsVal = CGF.EmitLoadOfScalar( - AddrNumWarpsArg, /*Volatile=*/false, C.IntTy, Loc); - - // Up to 32 threads in warp 0 are active. - llvm::Value *IsActiveThread = - Bld.CreateICmpULT(ThreadID, NumWarpsVal, "is_active_thread"); - Bld.CreateCondBr(IsActiveThread, W0ThenBB, W0ElseBB); - - CGF.EmitBlock(W0ThenBB); - - // SrcMediumPtr = &medium[tid] - llvm::Value *SrcMediumPtrVal = Bld.CreateInBoundsGEP( - TransferMedium, - {llvm::Constant::getNullValue(CGM.Int64Ty), ThreadID}); - Address SrcMediumPtr(SrcMediumPtrVal, Align); - // SrcMediumVal = *SrcMediumPtr; - SrcMediumPtr = Bld.CreateElementBitCast(SrcMediumPtr, CopyType); - - // TargetElemPtr = (CopyType*)(SrcDataAddr[i]) + I - Address TargetElemPtrPtr = - Bld.CreateConstArrayGEP(LocalReduceList, Idx, CGF.getPointerSize()); - llvm::Value *TargetElemPtrVal = CGF.EmitLoadOfScalar( - TargetElemPtrPtr, /*Volatile=*/false, C.VoidPtrTy, Loc); - Address TargetElemPtr = Address(TargetElemPtrVal, Align); - TargetElemPtr = Bld.CreateElementBitCast(TargetElemPtr, CopyType); - if (NumIters > 1) { - TargetElemPtr = Address(Bld.CreateGEP(TargetElemPtr.getPointer(), Cnt), - TargetElemPtr.getAlignment()); - } - - // *TargetElemPtr = SrcMediumVal; - llvm::Value *SrcMediumValue = - CGF.EmitLoadOfScalar(SrcMediumPtr, /*Volatile=*/true, CType, Loc); - CGF.EmitStoreOfScalar(SrcMediumValue, TargetElemPtr, /*Volatile=*/false, - CType); - Bld.CreateBr(W0MergeBB); - - CGF.EmitBlock(W0ElseBB); - Bld.CreateBr(W0MergeBB); - - CGF.EmitBlock(W0MergeBB); - - if (NumIters > 1) { - Cnt = Bld.CreateNSWAdd(Cnt, llvm::ConstantInt::get(CGM.IntTy, /*V=*/1)); - CGF.EmitStoreOfScalar(Cnt, CntAddr, /*Volatile=*/false, C.IntTy); - CGF.EmitBranch(PrecondBB); - (void)ApplyDebugLocation::CreateEmpty(CGF); - CGF.EmitBlock(ExitBB); - } - RealTySize %= TySize; - } - ++Idx; - } - - CGF.FinishFunction(); - return Fn; -} - -/// Emit a helper that reduces data across two OpenMP threads (lanes) -/// in the same warp. It uses shuffle instructions to copy over data from -/// a remote lane's stack. The reduction algorithm performed is specified -/// by the fourth parameter. -/// -/// Algorithm Versions. -/// Full Warp Reduce (argument value 0): -/// This algorithm assumes that all 32 lanes are active and gathers -/// data from these 32 lanes, producing a single resultant value. -/// Contiguous Partial Warp Reduce (argument value 1): -/// This algorithm assumes that only a *contiguous* subset of lanes -/// are active. This happens for the last warp in a parallel region -/// when the user specified num_threads is not an integer multiple of -/// 32. This contiguous subset always starts with the zeroth lane. -/// Partial Warp Reduce (argument value 2): -/// This algorithm gathers data from any number of lanes at any position. -/// All reduced values are stored in the lowest possible lane. The set -/// of problems every algorithm addresses is a super set of those -/// addressable by algorithms with a lower version number. Overhead -/// increases as algorithm version increases. -/// -/// Terminology -/// Reduce element: -/// Reduce element refers to the individual data field with primitive -/// data types to be combined and reduced across threads. -/// Reduce list: -/// Reduce list refers to a collection of local, thread-private -/// reduce elements. -/// Remote Reduce list: -/// Remote Reduce list refers to a collection of remote (relative to -/// the current thread) reduce elements. -/// -/// We distinguish between three states of threads that are important to -/// the implementation of this function. -/// Alive threads: -/// Threads in a warp executing the SIMT instruction, as distinguished from -/// threads that are inactive due to divergent control flow. -/// Active threads: -/// The minimal set of threads that has to be alive upon entry to this -/// function. The computation is correct iff active threads are alive. -/// Some threads are alive but they are not active because they do not -/// contribute to the computation in any useful manner. Turning them off -/// may introduce control flow overheads without any tangible benefits. -/// Effective threads: -/// In order to comply with the argument requirements of the shuffle -/// function, we must keep all lanes holding data alive. But at most -/// half of them perform value aggregation; we refer to this half of -/// threads as effective. The other half is simply handing off their -/// data. -/// -/// Procedure -/// Value shuffle: -/// In this step active threads transfer data from higher lane positions -/// in the warp to lower lane positions, creating Remote Reduce list. -/// Value aggregation: -/// In this step, effective threads combine their thread local Reduce list -/// with Remote Reduce list and store the result in the thread local -/// Reduce list. -/// Value copy: -/// In this step, we deal with the assumption made by algorithm 2 -/// (i.e. contiguity assumption). When we have an odd number of lanes -/// active, say 2k+1, only k threads will be effective and therefore k -/// new values will be produced. However, the Reduce list owned by the -/// (2k+1)th thread is ignored in the value aggregation. Therefore -/// we copy the Reduce list from the (2k+1)th lane to (k+1)th lane so -/// that the contiguity assumption still holds. -static llvm::Value *emitShuffleAndReduceFunction( - CodeGenModule &CGM, ArrayRef<const Expr *> Privates, - QualType ReductionArrayTy, llvm::Value *ReduceFn, SourceLocation Loc) { - ASTContext &C = CGM.getContext(); - - // Thread local Reduce list used to host the values of data to be reduced. - ImplicitParamDecl ReduceListArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, - C.VoidPtrTy, ImplicitParamDecl::Other); - // Current lane id; could be logical. - ImplicitParamDecl LaneIDArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.ShortTy, - ImplicitParamDecl::Other); - // Offset of the remote source lane relative to the current lane. - ImplicitParamDecl RemoteLaneOffsetArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, - C.ShortTy, ImplicitParamDecl::Other); - // Algorithm version. This is expected to be known at compile time. - ImplicitParamDecl AlgoVerArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, - C.ShortTy, ImplicitParamDecl::Other); - FunctionArgList Args; - Args.push_back(&ReduceListArg); - Args.push_back(&LaneIDArg); - Args.push_back(&RemoteLaneOffsetArg); - Args.push_back(&AlgoVerArg); - - const CGFunctionInfo &CGFI = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); - auto *Fn = llvm::Function::Create( - CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage, - "_omp_reduction_shuffle_and_reduce_func", &CGM.getModule()); - CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); - Fn->setDoesNotRecurse(); - CodeGenFunction CGF(CGM); - CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); - - CGBuilderTy &Bld = CGF.Builder; - - Address AddrReduceListArg = CGF.GetAddrOfLocalVar(&ReduceListArg); - Address LocalReduceList( - Bld.CreatePointerBitCastOrAddrSpaceCast( - CGF.EmitLoadOfScalar(AddrReduceListArg, /*Volatile=*/false, - C.VoidPtrTy, SourceLocation()), - CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo()), - CGF.getPointerAlign()); - - Address AddrLaneIDArg = CGF.GetAddrOfLocalVar(&LaneIDArg); - llvm::Value *LaneIDArgVal = CGF.EmitLoadOfScalar( - AddrLaneIDArg, /*Volatile=*/false, C.ShortTy, SourceLocation()); - - Address AddrRemoteLaneOffsetArg = CGF.GetAddrOfLocalVar(&RemoteLaneOffsetArg); - llvm::Value *RemoteLaneOffsetArgVal = CGF.EmitLoadOfScalar( - AddrRemoteLaneOffsetArg, /*Volatile=*/false, C.ShortTy, SourceLocation()); - - Address AddrAlgoVerArg = CGF.GetAddrOfLocalVar(&AlgoVerArg); - llvm::Value *AlgoVerArgVal = CGF.EmitLoadOfScalar( - AddrAlgoVerArg, /*Volatile=*/false, C.ShortTy, SourceLocation()); - - // Create a local thread-private variable to host the Reduce list - // from a remote lane. - Address RemoteReduceList = - CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.remote_reduce_list"); - - // This loop iterates through the list of reduce elements and copies, - // element by element, from a remote lane in the warp to RemoteReduceList, - // hosted on the thread's stack. - emitReductionListCopy(RemoteLaneToThread, CGF, ReductionArrayTy, Privates, - LocalReduceList, RemoteReduceList, - {/*RemoteLaneOffset=*/RemoteLaneOffsetArgVal, - /*ScratchpadIndex=*/nullptr, - /*ScratchpadWidth=*/nullptr}); - - // The actions to be performed on the Remote Reduce list is dependent - // on the algorithm version. - // - // if (AlgoVer==0) || (AlgoVer==1 && (LaneId < Offset)) || (AlgoVer==2 && - // LaneId % 2 == 0 && Offset > 0): - // do the reduction value aggregation - // - // The thread local variable Reduce list is mutated in place to host the - // reduced data, which is the aggregated value produced from local and - // remote lanes. - // - // Note that AlgoVer is expected to be a constant integer known at compile - // time. - // When AlgoVer==0, the first conjunction evaluates to true, making - // the entire predicate true during compile time. - // When AlgoVer==1, the second conjunction has only the second part to be - // evaluated during runtime. Other conjunctions evaluates to false - // during compile time. - // When AlgoVer==2, the third conjunction has only the second part to be - // evaluated during runtime. Other conjunctions evaluates to false - // during compile time. - llvm::Value *CondAlgo0 = Bld.CreateIsNull(AlgoVerArgVal); - - llvm::Value *Algo1 = Bld.CreateICmpEQ(AlgoVerArgVal, Bld.getInt16(1)); - llvm::Value *CondAlgo1 = Bld.CreateAnd( - Algo1, Bld.CreateICmpULT(LaneIDArgVal, RemoteLaneOffsetArgVal)); - - llvm::Value *Algo2 = Bld.CreateICmpEQ(AlgoVerArgVal, Bld.getInt16(2)); - llvm::Value *CondAlgo2 = Bld.CreateAnd( - Algo2, Bld.CreateIsNull(Bld.CreateAnd(LaneIDArgVal, Bld.getInt16(1)))); - CondAlgo2 = Bld.CreateAnd( - CondAlgo2, Bld.CreateICmpSGT(RemoteLaneOffsetArgVal, Bld.getInt16(0))); - - llvm::Value *CondReduce = Bld.CreateOr(CondAlgo0, CondAlgo1); - CondReduce = Bld.CreateOr(CondReduce, CondAlgo2); - - llvm::BasicBlock *ThenBB = CGF.createBasicBlock("then"); - llvm::BasicBlock *ElseBB = CGF.createBasicBlock("else"); - llvm::BasicBlock *MergeBB = CGF.createBasicBlock("ifcont"); - Bld.CreateCondBr(CondReduce, ThenBB, ElseBB); - - CGF.EmitBlock(ThenBB); - // reduce_function(LocalReduceList, RemoteReduceList) - llvm::Value *LocalReduceListPtr = Bld.CreatePointerBitCastOrAddrSpaceCast( - LocalReduceList.getPointer(), CGF.VoidPtrTy); - llvm::Value *RemoteReduceListPtr = Bld.CreatePointerBitCastOrAddrSpaceCast( - RemoteReduceList.getPointer(), CGF.VoidPtrTy); - CGM.getOpenMPRuntime().emitOutlinedFunctionCall( - CGF, Loc, ReduceFn, {LocalReduceListPtr, RemoteReduceListPtr}); - Bld.CreateBr(MergeBB); - - CGF.EmitBlock(ElseBB); - Bld.CreateBr(MergeBB); - - CGF.EmitBlock(MergeBB); - - // if (AlgoVer==1 && (LaneId >= Offset)) copy Remote Reduce list to local - // Reduce list. - Algo1 = Bld.CreateICmpEQ(AlgoVerArgVal, Bld.getInt16(1)); - llvm::Value *CondCopy = Bld.CreateAnd( - Algo1, Bld.CreateICmpUGE(LaneIDArgVal, RemoteLaneOffsetArgVal)); - - llvm::BasicBlock *CpyThenBB = CGF.createBasicBlock("then"); - llvm::BasicBlock *CpyElseBB = CGF.createBasicBlock("else"); - llvm::BasicBlock *CpyMergeBB = CGF.createBasicBlock("ifcont"); - Bld.CreateCondBr(CondCopy, CpyThenBB, CpyElseBB); - - CGF.EmitBlock(CpyThenBB); - emitReductionListCopy(ThreadCopy, CGF, ReductionArrayTy, Privates, - RemoteReduceList, LocalReduceList); - Bld.CreateBr(CpyMergeBB); - - CGF.EmitBlock(CpyElseBB); - Bld.CreateBr(CpyMergeBB); - - CGF.EmitBlock(CpyMergeBB); - - CGF.FinishFunction(); - return Fn; -} - -/// -/// Design of OpenMP reductions on the GPU -/// -/// Consider a typical OpenMP program with one or more reduction -/// clauses: -/// -/// float foo; -/// double bar; -/// #pragma omp target teams distribute parallel for \ -/// reduction(+:foo) reduction(*:bar) -/// for (int i = 0; i < N; i++) { -/// foo += A[i]; bar *= B[i]; -/// } -/// -/// where 'foo' and 'bar' are reduced across all OpenMP threads in -/// all teams. In our OpenMP implementation on the NVPTX device an -/// OpenMP team is mapped to a CUDA threadblock and OpenMP threads -/// within a team are mapped to CUDA threads within a threadblock. -/// Our goal is to efficiently aggregate values across all OpenMP -/// threads such that: -/// -/// - the compiler and runtime are logically concise, and -/// - the reduction is performed efficiently in a hierarchical -/// manner as follows: within OpenMP threads in the same warp, -/// across warps in a threadblock, and finally across teams on -/// the NVPTX device. -/// -/// Introduction to Decoupling -/// -/// We would like to decouple the compiler and the runtime so that the -/// latter is ignorant of the reduction variables (number, data types) -/// and the reduction operators. This allows a simpler interface -/// and implementation while still attaining good performance. -/// -/// Pseudocode for the aforementioned OpenMP program generated by the -/// compiler is as follows: -/// -/// 1. Create private copies of reduction variables on each OpenMP -/// thread: 'foo_private', 'bar_private' -/// 2. Each OpenMP thread reduces the chunk of 'A' and 'B' assigned -/// to it and writes the result in 'foo_private' and 'bar_private' -/// respectively. -/// 3. Call the OpenMP runtime on the GPU to reduce within a team -/// and store the result on the team master: -/// -/// __kmpc_nvptx_parallel_reduce_nowait_v2(..., -/// reduceData, shuffleReduceFn, interWarpCpyFn) -/// -/// where: -/// struct ReduceData { -/// double *foo; -/// double *bar; -/// } reduceData -/// reduceData.foo = &foo_private -/// reduceData.bar = &bar_private -/// -/// 'shuffleReduceFn' and 'interWarpCpyFn' are pointers to two -/// auxiliary functions generated by the compiler that operate on -/// variables of type 'ReduceData'. They aid the runtime perform -/// algorithmic steps in a data agnostic manner. -/// -/// 'shuffleReduceFn' is a pointer to a function that reduces data -/// of type 'ReduceData' across two OpenMP threads (lanes) in the -/// same warp. It takes the following arguments as input: -/// -/// a. variable of type 'ReduceData' on the calling lane, -/// b. its lane_id, -/// c. an offset relative to the current lane_id to generate a -/// remote_lane_id. The remote lane contains the second -/// variable of type 'ReduceData' that is to be reduced. -/// d. an algorithm version parameter determining which reduction -/// algorithm to use. -/// -/// 'shuffleReduceFn' retrieves data from the remote lane using -/// efficient GPU shuffle intrinsics and reduces, using the -/// algorithm specified by the 4th parameter, the two operands -/// element-wise. The result is written to the first operand. -/// -/// Different reduction algorithms are implemented in different -/// runtime functions, all calling 'shuffleReduceFn' to perform -/// the essential reduction step. Therefore, based on the 4th -/// parameter, this function behaves slightly differently to -/// cooperate with the runtime to ensure correctness under -/// different circumstances. -/// -/// 'InterWarpCpyFn' is a pointer to a function that transfers -/// reduced variables across warps. It tunnels, through CUDA -/// shared memory, the thread-private data of type 'ReduceData' -/// from lane 0 of each warp to a lane in the first warp. -/// 4. Call the OpenMP runtime on the GPU to reduce across teams. -/// The last team writes the global reduced value to memory. -/// -/// ret = __kmpc_nvptx_teams_reduce_nowait(..., -/// reduceData, shuffleReduceFn, interWarpCpyFn, -/// scratchpadCopyFn, loadAndReduceFn) -/// -/// 'scratchpadCopyFn' is a helper that stores reduced -/// data from the team master to a scratchpad array in -/// global memory. -/// -/// 'loadAndReduceFn' is a helper that loads data from -/// the scratchpad array and reduces it with the input -/// operand. -/// -/// These compiler generated functions hide address -/// calculation and alignment information from the runtime. -/// 5. if ret == 1: -/// The team master of the last team stores the reduced -/// result to the globals in memory. -/// foo += reduceData.foo; bar *= reduceData.bar -/// -/// -/// Warp Reduction Algorithms -/// -/// On the warp level, we have three algorithms implemented in the -/// OpenMP runtime depending on the number of active lanes: -/// -/// Full Warp Reduction -/// -/// The reduce algorithm within a warp where all lanes are active -/// is implemented in the runtime as follows: -/// -/// full_warp_reduce(void *reduce_data, -/// kmp_ShuffleReductFctPtr ShuffleReduceFn) { -/// for (int offset = WARPSIZE/2; offset > 0; offset /= 2) -/// ShuffleReduceFn(reduce_data, 0, offset, 0); -/// } -/// -/// The algorithm completes in log(2, WARPSIZE) steps. -/// -/// 'ShuffleReduceFn' is used here with lane_id set to 0 because it is -/// not used therefore we save instructions by not retrieving lane_id -/// from the corresponding special registers. The 4th parameter, which -/// represents the version of the algorithm being used, is set to 0 to -/// signify full warp reduction. -/// -/// In this version, 'ShuffleReduceFn' behaves, per element, as follows: -/// -/// #reduce_elem refers to an element in the local lane's data structure -/// #remote_elem is retrieved from a remote lane -/// remote_elem = shuffle_down(reduce_elem, offset, WARPSIZE); -/// reduce_elem = reduce_elem REDUCE_OP remote_elem; -/// -/// Contiguous Partial Warp Reduction -/// -/// This reduce algorithm is used within a warp where only the first -/// 'n' (n <= WARPSIZE) lanes are active. It is typically used when the -/// number of OpenMP threads in a parallel region is not a multiple of -/// WARPSIZE. The algorithm is implemented in the runtime as follows: -/// -/// void -/// contiguous_partial_reduce(void *reduce_data, -/// kmp_ShuffleReductFctPtr ShuffleReduceFn, -/// int size, int lane_id) { -/// int curr_size; -/// int offset; -/// curr_size = size; -/// mask = curr_size/2; -/// while (offset>0) { -/// ShuffleReduceFn(reduce_data, lane_id, offset, 1); -/// curr_size = (curr_size+1)/2; -/// offset = curr_size/2; -/// } -/// } -/// -/// In this version, 'ShuffleReduceFn' behaves, per element, as follows: -/// -/// remote_elem = shuffle_down(reduce_elem, offset, WARPSIZE); -/// if (lane_id < offset) -/// reduce_elem = reduce_elem REDUCE_OP remote_elem -/// else -/// reduce_elem = remote_elem -/// -/// This algorithm assumes that the data to be reduced are located in a -/// contiguous subset of lanes starting from the first. When there is -/// an odd number of active lanes, the data in the last lane is not -/// aggregated with any other lane's dat but is instead copied over. -/// -/// Dispersed Partial Warp Reduction -/// -/// This algorithm is used within a warp when any discontiguous subset of -/// lanes are active. It is used to implement the reduction operation -/// across lanes in an OpenMP simd region or in a nested parallel region. -/// -/// void -/// dispersed_partial_reduce(void *reduce_data, -/// kmp_ShuffleReductFctPtr ShuffleReduceFn) { -/// int size, remote_id; -/// int logical_lane_id = number_of_active_lanes_before_me() * 2; -/// do { -/// remote_id = next_active_lane_id_right_after_me(); -/// # the above function returns 0 of no active lane -/// # is present right after the current lane. -/// size = number_of_active_lanes_in_this_warp(); -/// logical_lane_id /= 2; -/// ShuffleReduceFn(reduce_data, logical_lane_id, -/// remote_id-1-threadIdx.x, 2); -/// } while (logical_lane_id % 2 == 0 && size > 1); -/// } -/// -/// There is no assumption made about the initial state of the reduction. -/// Any number of lanes (>=1) could be active at any position. The reduction -/// result is returned in the first active lane. -/// -/// In this version, 'ShuffleReduceFn' behaves, per element, as follows: -/// -/// remote_elem = shuffle_down(reduce_elem, offset, WARPSIZE); -/// if (lane_id % 2 == 0 && offset > 0) -/// reduce_elem = reduce_elem REDUCE_OP remote_elem -/// else -/// reduce_elem = remote_elem -/// -/// -/// Intra-Team Reduction -/// -/// This function, as implemented in the runtime call -/// '__kmpc_nvptx_parallel_reduce_nowait_v2', aggregates data across OpenMP -/// threads in a team. It first reduces within a warp using the -/// aforementioned algorithms. We then proceed to gather all such -/// reduced values at the first warp. -/// -/// The runtime makes use of the function 'InterWarpCpyFn', which copies -/// data from each of the "warp master" (zeroth lane of each warp, where -/// warp-reduced data is held) to the zeroth warp. This step reduces (in -/// a mathematical sense) the problem of reduction across warp masters in -/// a block to the problem of warp reduction. -/// -/// -/// Inter-Team Reduction -/// -/// Once a team has reduced its data to a single value, it is stored in -/// a global scratchpad array. Since each team has a distinct slot, this -/// can be done without locking. -/// -/// The last team to write to the scratchpad array proceeds to reduce the -/// scratchpad array. One or more workers in the last team use the helper -/// 'loadAndReduceDataFn' to load and reduce values from the array, i.e., -/// the k'th worker reduces every k'th element. -/// -/// Finally, a call is made to '__kmpc_nvptx_parallel_reduce_nowait_v2' to -/// reduce across workers and compute a globally reduced value. -/// -void CGOpenMPRuntimeNVPTX::emitReduction( - CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, - ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, - ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { - if (!CGF.HaveInsertPoint()) - return; - - bool ParallelReduction = isOpenMPParallelDirective(Options.ReductionKind); -#ifndef NDEBUG - bool TeamsReduction = isOpenMPTeamsDirective(Options.ReductionKind); -#endif - - if (Options.SimpleReduction) { - assert(!TeamsReduction && !ParallelReduction && - "Invalid reduction selection in emitReduction."); - CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, - ReductionOps, Options); - return; - } - - assert((TeamsReduction || ParallelReduction) && - "Invalid reduction selection in emitReduction."); - - // Build res = __kmpc_reduce{_nowait}(<gtid>, <n>, sizeof(RedList), - // RedList, shuffle_reduce_func, interwarp_copy_func); - // or - // Build res = __kmpc_reduce_teams_nowait_simple(<loc>, <gtid>, <lck>); - llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); - llvm::Value *ThreadId = getThreadID(CGF, Loc); - - llvm::Value *Res; - if (ParallelReduction) { - ASTContext &C = CGM.getContext(); - // 1. Build a list of reduction variables. - // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; - auto Size = RHSExprs.size(); - for (const Expr *E : Privates) { - if (E->getType()->isVariablyModifiedType()) - // Reserve place for array size. - ++Size; - } - llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); - QualType ReductionArrayTy = - C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal, - /*IndexTypeQuals=*/0); - Address ReductionList = - CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); - auto IPriv = Privates.begin(); - unsigned Idx = 0; - for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { - Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, - CGF.getPointerSize()); - CGF.Builder.CreateStore( - CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy), - Elem); - if ((*IPriv)->getType()->isVariablyModifiedType()) { - // Store array size. - ++Idx; - Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, - CGF.getPointerSize()); - llvm::Value *Size = CGF.Builder.CreateIntCast( - CGF.getVLASize( - CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) - .NumElts, - CGF.SizeTy, /*isSigned=*/false); - CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), - Elem); - } - } - - llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); - llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - ReductionList.getPointer(), CGF.VoidPtrTy); - llvm::Value *ReductionFn = emitReductionFunction( - CGM, Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), - Privates, LHSExprs, RHSExprs, ReductionOps); - llvm::Value *ShuffleAndReduceFn = emitShuffleAndReduceFunction( - CGM, Privates, ReductionArrayTy, ReductionFn, Loc); - llvm::Value *InterWarpCopyFn = - emitInterWarpCopyFunction(CGM, Privates, ReductionArrayTy, Loc); - - llvm::Value *Args[] = {RTLoc, - ThreadId, - CGF.Builder.getInt32(RHSExprs.size()), - ReductionArrayTySize, - RL, - ShuffleAndReduceFn, - InterWarpCopyFn}; - - Res = CGF.EmitRuntimeCall(createNVPTXRuntimeFunction( - OMPRTL_NVPTX__kmpc_parallel_reduce_nowait_v2), - Args); - } else { - assert(TeamsReduction && "expected teams reduction."); - std::string Name = getName({"reduction"}); - llvm::Value *Lock = getCriticalRegionLock(Name); - llvm::Value *Args[] = {RTLoc, ThreadId, Lock}; - Res = CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction( - OMPRTL_NVPTX__kmpc_nvptx_teams_reduce_nowait_simple), - Args); - } - - // 5. Build if (res == 1) - llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".omp.reduction.done"); - llvm::BasicBlock *ThenBB = CGF.createBasicBlock(".omp.reduction.then"); - llvm::Value *Cond = CGF.Builder.CreateICmpEQ( - Res, llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1)); - CGF.Builder.CreateCondBr(Cond, ThenBB, ExitBB); - - // 6. Build then branch: where we have reduced values in the master - // thread in each team. - // __kmpc_end_reduce{_nowait}(<gtid>); - // break; - CGF.EmitBlock(ThenBB); - - // Add emission of __kmpc_end_reduce{_nowait}(<gtid>); - auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps, - this](CodeGenFunction &CGF, PrePostActionTy &Action) { - auto IPriv = Privates.begin(); - auto ILHS = LHSExprs.begin(); - auto IRHS = RHSExprs.begin(); - for (const Expr *E : ReductionOps) { - emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), - cast<DeclRefExpr>(*IRHS)); - ++IPriv; - ++ILHS; - ++IRHS; - } - }; - if (ParallelReduction) { - llvm::Value *EndArgs[] = {ThreadId}; - RegionCodeGenTy RCG(CodeGen); - NVPTXActionTy Action( - nullptr, llvm::None, - createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_end_reduce_nowait), - EndArgs); - RCG.setAction(Action); - RCG(CGF); - } else { - assert(TeamsReduction && "expected teams reduction."); - llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); - std::string Name = getName({"reduction"}); - llvm::Value *Lock = getCriticalRegionLock(Name); - llvm::Value *EndArgs[] = {RTLoc, ThreadId, Lock}; - RegionCodeGenTy RCG(CodeGen); - NVPTXActionTy Action( - nullptr, llvm::None, - createNVPTXRuntimeFunction( - OMPRTL_NVPTX__kmpc_nvptx_teams_end_reduce_nowait_simple), - EndArgs); - RCG.setAction(Action); - RCG(CGF); - } - // There is no need to emit line number for unconditional branch. - (void)ApplyDebugLocation::CreateEmpty(CGF); - CGF.EmitBlock(ExitBB, /*IsFinished=*/true); -} - -const VarDecl * -CGOpenMPRuntimeNVPTX::translateParameter(const FieldDecl *FD, - const VarDecl *NativeParam) const { - if (!NativeParam->getType()->isReferenceType()) - return NativeParam; - QualType ArgType = NativeParam->getType(); - QualifierCollector QC; - const Type *NonQualTy = QC.strip(ArgType); - QualType PointeeTy = cast<ReferenceType>(NonQualTy)->getPointeeType(); - if (const auto *Attr = FD->getAttr<OMPCaptureKindAttr>()) { - if (Attr->getCaptureKind() == OMPC_map) { - PointeeTy = CGM.getContext().getAddrSpaceQualType(PointeeTy, - LangAS::opencl_global); - } - } - ArgType = CGM.getContext().getPointerType(PointeeTy); - QC.addRestrict(); - enum { NVPTX_local_addr = 5 }; - QC.addAddressSpace(getLangASFromTargetAS(NVPTX_local_addr)); - ArgType = QC.apply(CGM.getContext(), ArgType); - if (isa<ImplicitParamDecl>(NativeParam)) - return ImplicitParamDecl::Create( - CGM.getContext(), /*DC=*/nullptr, NativeParam->getLocation(), - NativeParam->getIdentifier(), ArgType, ImplicitParamDecl::Other); - return ParmVarDecl::Create( - CGM.getContext(), - const_cast<DeclContext *>(NativeParam->getDeclContext()), - NativeParam->getBeginLoc(), NativeParam->getLocation(), - NativeParam->getIdentifier(), ArgType, - /*TInfo=*/nullptr, SC_None, /*DefArg=*/nullptr); -} - -Address -CGOpenMPRuntimeNVPTX::getParameterAddress(CodeGenFunction &CGF, - const VarDecl *NativeParam, - const VarDecl *TargetParam) const { - assert(NativeParam != TargetParam && - NativeParam->getType()->isReferenceType() && - "Native arg must not be the same as target arg."); - Address LocalAddr = CGF.GetAddrOfLocalVar(TargetParam); - QualType NativeParamType = NativeParam->getType(); - QualifierCollector QC; - const Type *NonQualTy = QC.strip(NativeParamType); - QualType NativePointeeTy = cast<ReferenceType>(NonQualTy)->getPointeeType(); - unsigned NativePointeeAddrSpace = - CGF.getContext().getTargetAddressSpace(NativePointeeTy); - QualType TargetTy = TargetParam->getType(); - llvm::Value *TargetAddr = CGF.EmitLoadOfScalar( - LocalAddr, /*Volatile=*/false, TargetTy, SourceLocation()); - // First cast to generic. - TargetAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - TargetAddr, TargetAddr->getType()->getPointerElementType()->getPointerTo( - /*AddrSpace=*/0)); - // Cast from generic to native address space. - TargetAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - TargetAddr, TargetAddr->getType()->getPointerElementType()->getPointerTo( - NativePointeeAddrSpace)); - Address NativeParamAddr = CGF.CreateMemTemp(NativeParamType); - CGF.EmitStoreOfScalar(TargetAddr, NativeParamAddr, /*Volatile=*/false, - NativeParamType); - return NativeParamAddr; -} - -void CGOpenMPRuntimeNVPTX::emitOutlinedFunctionCall( - CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> Args) const { - SmallVector<llvm::Value *, 4> TargetArgs; - TargetArgs.reserve(Args.size()); - auto *FnType = - cast<llvm::FunctionType>(OutlinedFn->getType()->getPointerElementType()); - for (unsigned I = 0, E = Args.size(); I < E; ++I) { - if (FnType->isVarArg() && FnType->getNumParams() <= I) { - TargetArgs.append(std::next(Args.begin(), I), Args.end()); - break; - } - llvm::Type *TargetType = FnType->getParamType(I); - llvm::Value *NativeArg = Args[I]; - if (!TargetType->isPointerTy()) { - TargetArgs.emplace_back(NativeArg); - continue; - } - llvm::Value *TargetArg = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - NativeArg, - NativeArg->getType()->getPointerElementType()->getPointerTo()); - TargetArgs.emplace_back( - CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TargetArg, TargetType)); - } - CGOpenMPRuntime::emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, TargetArgs); -} - -/// Emit function which wraps the outline parallel region -/// and controls the arguments which are passed to this function. -/// The wrapper ensures that the outlined function is called -/// with the correct arguments when data is shared. -llvm::Function *CGOpenMPRuntimeNVPTX::createParallelDataSharingWrapper( - llvm::Function *OutlinedParallelFn, const OMPExecutableDirective &D) { - ASTContext &Ctx = CGM.getContext(); - const auto &CS = *D.getCapturedStmt(OMPD_parallel); - - // Create a function that takes as argument the source thread. - FunctionArgList WrapperArgs; - QualType Int16QTy = - Ctx.getIntTypeForBitwidth(/*DestWidth=*/16, /*Signed=*/false); - QualType Int32QTy = - Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false); - ImplicitParamDecl ParallelLevelArg(Ctx, /*DC=*/nullptr, D.getBeginLoc(), - /*Id=*/nullptr, Int16QTy, - ImplicitParamDecl::Other); - ImplicitParamDecl WrapperArg(Ctx, /*DC=*/nullptr, D.getBeginLoc(), - /*Id=*/nullptr, Int32QTy, - ImplicitParamDecl::Other); - WrapperArgs.emplace_back(&ParallelLevelArg); - WrapperArgs.emplace_back(&WrapperArg); - - const CGFunctionInfo &CGFI = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, WrapperArgs); - - auto *Fn = llvm::Function::Create( - CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage, - Twine(OutlinedParallelFn->getName(), "_wrapper"), &CGM.getModule()); - CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); - Fn->setLinkage(llvm::GlobalValue::InternalLinkage); - Fn->setDoesNotRecurse(); - - CodeGenFunction CGF(CGM, /*suppressNewContext=*/true); - CGF.StartFunction(GlobalDecl(), Ctx.VoidTy, Fn, CGFI, WrapperArgs, - D.getBeginLoc(), D.getBeginLoc()); - - const auto *RD = CS.getCapturedRecordDecl(); - auto CurField = RD->field_begin(); - - Address ZeroAddr = CGF.CreateMemTemp( - CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1), - /*Name*/ ".zero.addr"); - CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0)); - // Get the array of arguments. - SmallVector<llvm::Value *, 8> Args; - - Args.emplace_back(CGF.GetAddrOfLocalVar(&WrapperArg).getPointer()); - Args.emplace_back(ZeroAddr.getPointer()); - - CGBuilderTy &Bld = CGF.Builder; - auto CI = CS.capture_begin(); - - // Use global memory for data sharing. - // Handle passing of global args to workers. - Address GlobalArgs = - CGF.CreateDefaultAlignTempAlloca(CGF.VoidPtrPtrTy, "global_args"); - llvm::Value *GlobalArgsPtr = GlobalArgs.getPointer(); - llvm::Value *DataSharingArgs[] = {GlobalArgsPtr}; - CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_get_shared_variables), - DataSharingArgs); - - // Retrieve the shared variables from the list of references returned - // by the runtime. Pass the variables to the outlined function. - Address SharedArgListAddress = Address::invalid(); - if (CS.capture_size() > 0 || - isOpenMPLoopBoundSharingDirective(D.getDirectiveKind())) { - SharedArgListAddress = CGF.EmitLoadOfPointer( - GlobalArgs, CGF.getContext() - .getPointerType(CGF.getContext().getPointerType( - CGF.getContext().VoidPtrTy)) - .castAs<PointerType>()); - } - unsigned Idx = 0; - if (isOpenMPLoopBoundSharingDirective(D.getDirectiveKind())) { - Address Src = Bld.CreateConstInBoundsGEP(SharedArgListAddress, Idx, - CGF.getPointerSize()); - Address TypedAddress = Bld.CreatePointerBitCastOrAddrSpaceCast( - Src, CGF.SizeTy->getPointerTo()); - llvm::Value *LB = CGF.EmitLoadOfScalar( - TypedAddress, - /*Volatile=*/false, - CGF.getContext().getPointerType(CGF.getContext().getSizeType()), - cast<OMPLoopDirective>(D).getLowerBoundVariable()->getExprLoc()); - Args.emplace_back(LB); - ++Idx; - Src = Bld.CreateConstInBoundsGEP(SharedArgListAddress, Idx, - CGF.getPointerSize()); - TypedAddress = Bld.CreatePointerBitCastOrAddrSpaceCast( - Src, CGF.SizeTy->getPointerTo()); - llvm::Value *UB = CGF.EmitLoadOfScalar( - TypedAddress, - /*Volatile=*/false, - CGF.getContext().getPointerType(CGF.getContext().getSizeType()), - cast<OMPLoopDirective>(D).getUpperBoundVariable()->getExprLoc()); - Args.emplace_back(UB); - ++Idx; - } - if (CS.capture_size() > 0) { - ASTContext &CGFContext = CGF.getContext(); - for (unsigned I = 0, E = CS.capture_size(); I < E; ++I, ++CI, ++CurField) { - QualType ElemTy = CurField->getType(); - Address Src = Bld.CreateConstInBoundsGEP(SharedArgListAddress, I + Idx, - CGF.getPointerSize()); - Address TypedAddress = Bld.CreatePointerBitCastOrAddrSpaceCast( - Src, CGF.ConvertTypeForMem(CGFContext.getPointerType(ElemTy))); - llvm::Value *Arg = CGF.EmitLoadOfScalar(TypedAddress, - /*Volatile=*/false, - CGFContext.getPointerType(ElemTy), - CI->getLocation()); - if (CI->capturesVariableByCopy() && - !CI->getCapturedVar()->getType()->isAnyPointerType()) { - Arg = castValueToType(CGF, Arg, ElemTy, CGFContext.getUIntPtrType(), - CI->getLocation()); - } - Args.emplace_back(Arg); - } - } - - emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedParallelFn, Args); - CGF.FinishFunction(); - return Fn; -} - -void CGOpenMPRuntimeNVPTX::emitFunctionProlog(CodeGenFunction &CGF, - const Decl *D) { - if (getDataSharingMode(CGM) != CGOpenMPRuntimeNVPTX::Generic) - return; - - assert(D && "Expected function or captured|block decl."); - assert(FunctionGlobalizedDecls.count(CGF.CurFn) == 0 && - "Function is registered already."); - assert((!TeamAndReductions.first || TeamAndReductions.first == D) && - "Team is set but not processed."); - const Stmt *Body = nullptr; - bool NeedToDelayGlobalization = false; - if (const auto *FD = dyn_cast<FunctionDecl>(D)) { - Body = FD->getBody(); - } else if (const auto *BD = dyn_cast<BlockDecl>(D)) { - Body = BD->getBody(); - } else if (const auto *CD = dyn_cast<CapturedDecl>(D)) { - Body = CD->getBody(); - NeedToDelayGlobalization = CGF.CapturedStmtInfo->getKind() == CR_OpenMP; - if (NeedToDelayGlobalization && - getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_SPMD) - return; - } - if (!Body) - return; - CheckVarsEscapingDeclContext VarChecker(CGF, TeamAndReductions.second); - VarChecker.Visit(Body); - const RecordDecl *GlobalizedVarsRecord = - VarChecker.getGlobalizedRecord(IsInTTDRegion); - TeamAndReductions.first = nullptr; - TeamAndReductions.second.clear(); - ArrayRef<const ValueDecl *> EscapedVariableLengthDecls = - VarChecker.getEscapedVariableLengthDecls(); - if (!GlobalizedVarsRecord && EscapedVariableLengthDecls.empty()) - return; - auto I = FunctionGlobalizedDecls.try_emplace(CGF.CurFn).first; - I->getSecond().MappedParams = - llvm::make_unique<CodeGenFunction::OMPMapVars>(); - I->getSecond().GlobalRecord = GlobalizedVarsRecord; - I->getSecond().EscapedParameters.insert( - VarChecker.getEscapedParameters().begin(), - VarChecker.getEscapedParameters().end()); - I->getSecond().EscapedVariableLengthDecls.append( - EscapedVariableLengthDecls.begin(), EscapedVariableLengthDecls.end()); - DeclToAddrMapTy &Data = I->getSecond().LocalVarData; - for (const ValueDecl *VD : VarChecker.getEscapedDecls()) { - assert(VD->isCanonicalDecl() && "Expected canonical declaration"); - const FieldDecl *FD = VarChecker.getFieldForGlobalizedVar(VD); - Data.insert(std::make_pair(VD, MappedVarData(FD, IsInTTDRegion))); - } - if (!IsInTTDRegion && !NeedToDelayGlobalization && !IsInParallelRegion) { - CheckVarsEscapingDeclContext VarChecker(CGF, llvm::None); - VarChecker.Visit(Body); - I->getSecond().SecondaryGlobalRecord = - VarChecker.getGlobalizedRecord(/*IsInTTDRegion=*/true); - I->getSecond().SecondaryLocalVarData.emplace(); - DeclToAddrMapTy &Data = I->getSecond().SecondaryLocalVarData.getValue(); - for (const ValueDecl *VD : VarChecker.getEscapedDecls()) { - assert(VD->isCanonicalDecl() && "Expected canonical declaration"); - const FieldDecl *FD = VarChecker.getFieldForGlobalizedVar(VD); - Data.insert( - std::make_pair(VD, MappedVarData(FD, /*IsInTTDRegion=*/true))); - } - } - if (!NeedToDelayGlobalization) { - emitGenericVarsProlog(CGF, D->getBeginLoc(), /*WithSPMDCheck=*/true); - struct GlobalizationScope final : EHScopeStack::Cleanup { - GlobalizationScope() = default; - - void Emit(CodeGenFunction &CGF, Flags flags) override { - static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime()) - .emitGenericVarsEpilog(CGF, /*WithSPMDCheck=*/true); - } - }; - CGF.EHStack.pushCleanup<GlobalizationScope>(NormalAndEHCleanup); - } -} - -Address CGOpenMPRuntimeNVPTX::getAddressOfLocalVariable(CodeGenFunction &CGF, - const VarDecl *VD) { - if (getDataSharingMode(CGM) != CGOpenMPRuntimeNVPTX::Generic) - return Address::invalid(); - - VD = VD->getCanonicalDecl(); - auto I = FunctionGlobalizedDecls.find(CGF.CurFn); - if (I == FunctionGlobalizedDecls.end()) - return Address::invalid(); - auto VDI = I->getSecond().LocalVarData.find(VD); - if (VDI != I->getSecond().LocalVarData.end()) - return VDI->second.PrivateAddr; - if (VD->hasAttrs()) { - for (specific_attr_iterator<OMPReferencedVarAttr> IT(VD->attr_begin()), - E(VD->attr_end()); - IT != E; ++IT) { - auto VDI = I->getSecond().LocalVarData.find( - cast<VarDecl>(cast<DeclRefExpr>(IT->getRef())->getDecl()) - ->getCanonicalDecl()); - if (VDI != I->getSecond().LocalVarData.end()) - return VDI->second.PrivateAddr; - } - } - return Address::invalid(); -} - -void CGOpenMPRuntimeNVPTX::functionFinished(CodeGenFunction &CGF) { - FunctionGlobalizedDecls.erase(CGF.CurFn); - CGOpenMPRuntime::functionFinished(CGF); -} - -void CGOpenMPRuntimeNVPTX::getDefaultDistScheduleAndChunk( - CodeGenFunction &CGF, const OMPLoopDirective &S, - OpenMPDistScheduleClauseKind &ScheduleKind, - llvm::Value *&Chunk) const { - if (getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_SPMD) { - ScheduleKind = OMPC_DIST_SCHEDULE_static; - Chunk = CGF.EmitScalarConversion(getNVPTXNumThreads(CGF), - CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), - S.getIterationVariable()->getType(), S.getBeginLoc()); - return; - } - CGOpenMPRuntime::getDefaultDistScheduleAndChunk( - CGF, S, ScheduleKind, Chunk); -} - -void CGOpenMPRuntimeNVPTX::getDefaultScheduleAndChunk( - CodeGenFunction &CGF, const OMPLoopDirective &S, - OpenMPScheduleClauseKind &ScheduleKind, - const Expr *&ChunkExpr) const { - ScheduleKind = OMPC_SCHEDULE_static; - // Chunk size is 1 in this case. - llvm::APInt ChunkSize(32, 1); - ChunkExpr = IntegerLiteral::Create(CGF.getContext(), ChunkSize, - CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), - SourceLocation()); -} - -void CGOpenMPRuntimeNVPTX::adjustTargetSpecificDataForLambdas( - CodeGenFunction &CGF, const OMPExecutableDirective &D) const { - assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && - " Expected target-based directive."); - const CapturedStmt *CS = D.getCapturedStmt(OMPD_target); - for (const CapturedStmt::Capture &C : CS->captures()) { - // Capture variables captured by reference in lambdas for target-based - // directives. - if (!C.capturesVariable()) - continue; - const VarDecl *VD = C.getCapturedVar(); - const auto *RD = VD->getType() - .getCanonicalType() - .getNonReferenceType() - ->getAsCXXRecordDecl(); - if (!RD || !RD->isLambda()) - continue; - Address VDAddr = CGF.GetAddrOfLocalVar(VD); - LValue VDLVal; - if (VD->getType().getCanonicalType()->isReferenceType()) - VDLVal = CGF.EmitLoadOfReferenceLValue(VDAddr, VD->getType()); - else - VDLVal = CGF.MakeAddrLValue( - VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); - llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; - FieldDecl *ThisCapture = nullptr; - RD->getCaptureFields(Captures, ThisCapture); - if (ThisCapture && CGF.CapturedStmtInfo->isCXXThisExprCaptured()) { - LValue ThisLVal = - CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); - llvm::Value *CXXThis = CGF.LoadCXXThis(); - CGF.EmitStoreOfScalar(CXXThis, ThisLVal); - } - for (const LambdaCapture &LC : RD->captures()) { - if (LC.getCaptureKind() != LCK_ByRef) - continue; - const VarDecl *VD = LC.getCapturedVar(); - if (!CS->capturesVariable(VD)) - continue; - auto It = Captures.find(VD); - assert(It != Captures.end() && "Found lambda capture without field."); - LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); - Address VDAddr = CGF.GetAddrOfLocalVar(VD); - if (VD->getType().getCanonicalType()->isReferenceType()) - VDAddr = CGF.EmitLoadOfReferenceLValue(VDAddr, - VD->getType().getCanonicalType()) - .getAddress(); - CGF.EmitStoreOfScalar(VDAddr.getPointer(), VarLVal); - } - } -} - -// Get current CudaArch and ignore any unknown values -static CudaArch getCudaArch(CodeGenModule &CGM) { - if (!CGM.getTarget().hasFeature("ptx")) - return CudaArch::UNKNOWN; - llvm::StringMap<bool> Features; - CGM.getTarget().initFeatureMap(Features, CGM.getDiags(), - CGM.getTarget().getTargetOpts().CPU, - CGM.getTarget().getTargetOpts().Features); - for (const auto &Feature : Features) { - if (Feature.getValue()) { - CudaArch Arch = StringToCudaArch(Feature.getKey()); - if (Arch != CudaArch::UNKNOWN) - return Arch; - } - } - return CudaArch::UNKNOWN; -} - -/// Check to see if target architecture supports unified addressing which is -/// a restriction for OpenMP requires clause "unified_shared_memory". -void CGOpenMPRuntimeNVPTX::checkArchForUnifiedAddressing( - CodeGenModule &CGM, const OMPRequiresDecl *D) const { - for (const OMPClause *Clause : D->clauselists()) { - if (Clause->getClauseKind() == OMPC_unified_shared_memory) { - switch (getCudaArch(CGM)) { - case CudaArch::SM_20: - case CudaArch::SM_21: - case CudaArch::SM_30: - case CudaArch::SM_32: - case CudaArch::SM_35: - case CudaArch::SM_37: - case CudaArch::SM_50: - case CudaArch::SM_52: - case CudaArch::SM_53: - case CudaArch::SM_60: - case CudaArch::SM_61: - case CudaArch::SM_62: - CGM.Error(Clause->getBeginLoc(), - "Target architecture does not support unified addressing"); - return; - case CudaArch::SM_70: - case CudaArch::SM_72: - case CudaArch::SM_75: - case CudaArch::GFX600: - case CudaArch::GFX601: - case CudaArch::GFX700: - case CudaArch::GFX701: - case CudaArch::GFX702: - case CudaArch::GFX703: - case CudaArch::GFX704: - case CudaArch::GFX801: - case CudaArch::GFX802: - case CudaArch::GFX803: - case CudaArch::GFX810: - case CudaArch::GFX900: - case CudaArch::GFX902: - case CudaArch::GFX904: - case CudaArch::GFX906: - case CudaArch::GFX909: - case CudaArch::UNKNOWN: - break; - case CudaArch::LAST: - llvm_unreachable("Unexpected Cuda arch."); - } - } - } -} - -/// Get number of SMs and number of blocks per SM. -static std::pair<unsigned, unsigned> getSMsBlocksPerSM(CodeGenModule &CGM) { - std::pair<unsigned, unsigned> Data; - if (CGM.getLangOpts().OpenMPCUDANumSMs) - Data.first = CGM.getLangOpts().OpenMPCUDANumSMs; - if (CGM.getLangOpts().OpenMPCUDABlocksPerSM) - Data.second = CGM.getLangOpts().OpenMPCUDABlocksPerSM; - if (Data.first && Data.second) - return Data; - switch (getCudaArch(CGM)) { - case CudaArch::SM_20: - case CudaArch::SM_21: - case CudaArch::SM_30: - case CudaArch::SM_32: - case CudaArch::SM_35: - case CudaArch::SM_37: - case CudaArch::SM_50: - case CudaArch::SM_52: - case CudaArch::SM_53: - return {16, 16}; - case CudaArch::SM_60: - case CudaArch::SM_61: - case CudaArch::SM_62: - return {56, 32}; - case CudaArch::SM_70: - case CudaArch::SM_72: - case CudaArch::SM_75: - return {84, 32}; - case CudaArch::GFX600: - case CudaArch::GFX601: - case CudaArch::GFX700: - case CudaArch::GFX701: - case CudaArch::GFX702: - case CudaArch::GFX703: - case CudaArch::GFX704: - case CudaArch::GFX801: - case CudaArch::GFX802: - case CudaArch::GFX803: - case CudaArch::GFX810: - case CudaArch::GFX900: - case CudaArch::GFX902: - case CudaArch::GFX904: - case CudaArch::GFX906: - case CudaArch::GFX909: - case CudaArch::UNKNOWN: - break; - case CudaArch::LAST: - llvm_unreachable("Unexpected Cuda arch."); - } - llvm_unreachable("Unexpected NVPTX target without ptx feature."); -} - -void CGOpenMPRuntimeNVPTX::clear() { - if (!GlobalizedRecords.empty()) { - ASTContext &C = CGM.getContext(); - llvm::SmallVector<const GlobalPtrSizeRecsTy *, 4> GlobalRecs; - llvm::SmallVector<const GlobalPtrSizeRecsTy *, 4> SharedRecs; - RecordDecl *StaticRD = C.buildImplicitRecord( - "_openmp_static_memory_type_$_", RecordDecl::TagKind::TTK_Union); - StaticRD->startDefinition(); - RecordDecl *SharedStaticRD = C.buildImplicitRecord( - "_shared_openmp_static_memory_type_$_", RecordDecl::TagKind::TTK_Union); - SharedStaticRD->startDefinition(); - for (const GlobalPtrSizeRecsTy &Records : GlobalizedRecords) { - if (Records.Records.empty()) - continue; - unsigned Size = 0; - unsigned RecAlignment = 0; - for (const RecordDecl *RD : Records.Records) { - QualType RDTy = C.getRecordType(RD); - unsigned Alignment = C.getTypeAlignInChars(RDTy).getQuantity(); - RecAlignment = std::max(RecAlignment, Alignment); - unsigned RecSize = C.getTypeSizeInChars(RDTy).getQuantity(); - Size = - llvm::alignTo(llvm::alignTo(Size, Alignment) + RecSize, Alignment); - } - Size = llvm::alignTo(Size, RecAlignment); - llvm::APInt ArySize(/*numBits=*/64, Size); - QualType SubTy = C.getConstantArrayType( - C.CharTy, ArySize, ArrayType::Normal, /*IndexTypeQuals=*/0); - const bool UseSharedMemory = Size <= SharedMemorySize; - auto *Field = - FieldDecl::Create(C, UseSharedMemory ? SharedStaticRD : StaticRD, - SourceLocation(), SourceLocation(), nullptr, SubTy, - C.getTrivialTypeSourceInfo(SubTy, SourceLocation()), - /*BW=*/nullptr, /*Mutable=*/false, - /*InitStyle=*/ICIS_NoInit); - Field->setAccess(AS_public); - if (UseSharedMemory) { - SharedStaticRD->addDecl(Field); - SharedRecs.push_back(&Records); - } else { - StaticRD->addDecl(Field); - GlobalRecs.push_back(&Records); - } - Records.RecSize->setInitializer(llvm::ConstantInt::get(CGM.SizeTy, Size)); - Records.UseSharedMemory->setInitializer( - llvm::ConstantInt::get(CGM.Int16Ty, UseSharedMemory ? 1 : 0)); - } - // Allocate SharedMemorySize buffer for the shared memory. - // FIXME: nvlink does not handle weak linkage correctly (object with the - // different size are reported as erroneous). - // Restore this code as sson as nvlink is fixed. - if (!SharedStaticRD->field_empty()) { - llvm::APInt ArySize(/*numBits=*/64, SharedMemorySize); - QualType SubTy = C.getConstantArrayType( - C.CharTy, ArySize, ArrayType::Normal, /*IndexTypeQuals=*/0); - auto *Field = FieldDecl::Create( - C, SharedStaticRD, SourceLocation(), SourceLocation(), nullptr, SubTy, - C.getTrivialTypeSourceInfo(SubTy, SourceLocation()), - /*BW=*/nullptr, /*Mutable=*/false, - /*InitStyle=*/ICIS_NoInit); - Field->setAccess(AS_public); - SharedStaticRD->addDecl(Field); - } - SharedStaticRD->completeDefinition(); - if (!SharedStaticRD->field_empty()) { - QualType StaticTy = C.getRecordType(SharedStaticRD); - llvm::Type *LLVMStaticTy = CGM.getTypes().ConvertTypeForMem(StaticTy); - auto *GV = new llvm::GlobalVariable( - CGM.getModule(), LLVMStaticTy, - /*isConstant=*/false, llvm::GlobalValue::CommonLinkage, - llvm::Constant::getNullValue(LLVMStaticTy), - "_openmp_shared_static_glob_rd_$_", /*InsertBefore=*/nullptr, - llvm::GlobalValue::NotThreadLocal, - C.getTargetAddressSpace(LangAS::cuda_shared)); - auto *Replacement = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast( - GV, CGM.VoidPtrTy); - for (const GlobalPtrSizeRecsTy *Rec : SharedRecs) { - Rec->Buffer->replaceAllUsesWith(Replacement); - Rec->Buffer->eraseFromParent(); - } - } - StaticRD->completeDefinition(); - if (!StaticRD->field_empty()) { - QualType StaticTy = C.getRecordType(StaticRD); - std::pair<unsigned, unsigned> SMsBlockPerSM = getSMsBlocksPerSM(CGM); - llvm::APInt Size1(32, SMsBlockPerSM.second); - QualType Arr1Ty = - C.getConstantArrayType(StaticTy, Size1, ArrayType::Normal, - /*IndexTypeQuals=*/0); - llvm::APInt Size2(32, SMsBlockPerSM.first); - QualType Arr2Ty = C.getConstantArrayType(Arr1Ty, Size2, ArrayType::Normal, - /*IndexTypeQuals=*/0); - llvm::Type *LLVMArr2Ty = CGM.getTypes().ConvertTypeForMem(Arr2Ty); - auto *GV = new llvm::GlobalVariable( - CGM.getModule(), LLVMArr2Ty, - /*isConstant=*/false, llvm::GlobalValue::CommonLinkage, - llvm::Constant::getNullValue(LLVMArr2Ty), - "_openmp_static_glob_rd_$_"); - auto *Replacement = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast( - GV, CGM.VoidPtrTy); - for (const GlobalPtrSizeRecsTy *Rec : GlobalRecs) { - Rec->Buffer->replaceAllUsesWith(Replacement); - Rec->Buffer->eraseFromParent(); - } - } - } - CGOpenMPRuntime::clear(); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.h b/gnu/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.h deleted file mode 100644 index 6091610c37e..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.h +++ /dev/null @@ -1,478 +0,0 @@ -//===----- CGOpenMPRuntimeNVPTX.h - Interface to OpenMP NVPTX Runtimes ----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This provides a class for OpenMP runtime code generation specialized to NVPTX -// targets. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CGOPENMPRUNTIMENVPTX_H -#define LLVM_CLANG_LIB_CODEGEN_CGOPENMPRUNTIMENVPTX_H - -#include "CGOpenMPRuntime.h" -#include "CodeGenFunction.h" -#include "clang/AST/StmtOpenMP.h" -#include "llvm/IR/CallSite.h" - -namespace clang { -namespace CodeGen { - -class CGOpenMPRuntimeNVPTX : public CGOpenMPRuntime { -public: - /// Defines the execution mode. - enum ExecutionMode { - /// SPMD execution mode (all threads are worker threads). - EM_SPMD, - /// Non-SPMD execution mode (1 master thread, others are workers). - EM_NonSPMD, - /// Unknown execution mode (orphaned directive). - EM_Unknown, - }; -private: - /// Parallel outlined function work for workers to execute. - llvm::SmallVector<llvm::Function *, 16> Work; - - struct EntryFunctionState { - llvm::BasicBlock *ExitBB = nullptr; - }; - - class WorkerFunctionState { - public: - llvm::Function *WorkerFn; - const CGFunctionInfo &CGFI; - SourceLocation Loc; - - WorkerFunctionState(CodeGenModule &CGM, SourceLocation Loc); - - private: - void createWorkerFunction(CodeGenModule &CGM); - }; - - ExecutionMode getExecutionMode() const; - - bool requiresFullRuntime() const { return RequiresFullRuntime; } - - /// Get barrier to synchronize all threads in a block. - void syncCTAThreads(CodeGenFunction &CGF); - - /// Emit the worker function for the current target region. - void emitWorkerFunction(WorkerFunctionState &WST); - - /// Helper for worker function. Emit body of worker loop. - void emitWorkerLoop(CodeGenFunction &CGF, WorkerFunctionState &WST); - - /// Helper for non-SPMD target entry function. Guide the master and - /// worker threads to their respective locations. - void emitNonSPMDEntryHeader(CodeGenFunction &CGF, EntryFunctionState &EST, - WorkerFunctionState &WST); - - /// Signal termination of OMP execution for non-SPMD target entry - /// function. - void emitNonSPMDEntryFooter(CodeGenFunction &CGF, EntryFunctionState &EST); - - /// Helper for generic variables globalization prolog. - void emitGenericVarsProlog(CodeGenFunction &CGF, SourceLocation Loc, - bool WithSPMDCheck = false); - - /// Helper for generic variables globalization epilog. - void emitGenericVarsEpilog(CodeGenFunction &CGF, bool WithSPMDCheck = false); - - /// Helper for SPMD mode target directive's entry function. - void emitSPMDEntryHeader(CodeGenFunction &CGF, EntryFunctionState &EST, - const OMPExecutableDirective &D); - - /// Signal termination of SPMD mode execution. - void emitSPMDEntryFooter(CodeGenFunction &CGF, EntryFunctionState &EST); - - // - // Base class overrides. - // - - /// Creates offloading entry for the provided entry ID \a ID, - /// address \a Addr, size \a Size, and flags \a Flags. - void createOffloadEntry(llvm::Constant *ID, llvm::Constant *Addr, - uint64_t Size, int32_t Flags, - llvm::GlobalValue::LinkageTypes Linkage) override; - - /// Emit outlined function specialized for the Fork-Join - /// programming model for applicable target directives on the NVPTX device. - /// \param D Directive to emit. - /// \param ParentName Name of the function that encloses the target region. - /// \param OutlinedFn Outlined function value to be defined by this call. - /// \param OutlinedFnID Outlined function ID value to be defined by this call. - /// \param IsOffloadEntry True if the outlined function is an offload entry. - /// An outlined function may not be an entry if, e.g. the if clause always - /// evaluates to false. - void emitNonSPMDKernel(const OMPExecutableDirective &D, StringRef ParentName, - llvm::Function *&OutlinedFn, - llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, - const RegionCodeGenTy &CodeGen); - - /// Emit outlined function specialized for the Single Program - /// Multiple Data programming model for applicable target directives on the - /// NVPTX device. - /// \param D Directive to emit. - /// \param ParentName Name of the function that encloses the target region. - /// \param OutlinedFn Outlined function value to be defined by this call. - /// \param OutlinedFnID Outlined function ID value to be defined by this call. - /// \param IsOffloadEntry True if the outlined function is an offload entry. - /// \param CodeGen Object containing the target statements. - /// An outlined function may not be an entry if, e.g. the if clause always - /// evaluates to false. - void emitSPMDKernel(const OMPExecutableDirective &D, StringRef ParentName, - llvm::Function *&OutlinedFn, - llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, - const RegionCodeGenTy &CodeGen); - - /// Emit outlined function for 'target' directive on the NVPTX - /// device. - /// \param D Directive to emit. - /// \param ParentName Name of the function that encloses the target region. - /// \param OutlinedFn Outlined function value to be defined by this call. - /// \param OutlinedFnID Outlined function ID value to be defined by this call. - /// \param IsOffloadEntry True if the outlined function is an offload entry. - /// An outlined function may not be an entry if, e.g. the if clause always - /// evaluates to false. - void emitTargetOutlinedFunction(const OMPExecutableDirective &D, - StringRef ParentName, - llvm::Function *&OutlinedFn, - llvm::Constant *&OutlinedFnID, - bool IsOffloadEntry, - const RegionCodeGenTy &CodeGen) override; - - /// Emits code for parallel or serial call of the \a OutlinedFn with - /// variables captured in a record which address is stored in \a - /// CapturedStruct. - /// This call is for the Non-SPMD Execution Mode. - /// \param OutlinedFn Outlined function to be run in parallel threads. Type of - /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*). - /// \param CapturedVars A pointer to the record with the references to - /// variables used in \a OutlinedFn function. - /// \param IfCond Condition in the associated 'if' clause, if it was - /// specified, nullptr otherwise. - void emitNonSPMDParallelCall(CodeGenFunction &CGF, SourceLocation Loc, - llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> CapturedVars, - const Expr *IfCond); - - /// Emits code for parallel or serial call of the \a OutlinedFn with - /// variables captured in a record which address is stored in \a - /// CapturedStruct. - /// This call is for a parallel directive within an SPMD target directive. - /// \param OutlinedFn Outlined function to be run in parallel threads. Type of - /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*). - /// \param CapturedVars A pointer to the record with the references to - /// variables used in \a OutlinedFn function. - /// \param IfCond Condition in the associated 'if' clause, if it was - /// specified, nullptr otherwise. - /// - void emitSPMDParallelCall(CodeGenFunction &CGF, SourceLocation Loc, - llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> CapturedVars, - const Expr *IfCond); - -protected: - /// Get the function name of an outlined region. - // The name can be customized depending on the target. - // - StringRef getOutlinedHelperName() const override { - return "__omp_outlined__"; - } - - /// Check if the default location must be constant. - /// Constant for NVPTX for better optimization. - bool isDefaultLocationConstant() const override { return true; } - - /// Returns additional flags that can be stored in reserved_2 field of the - /// default location. - /// For NVPTX target contains data about SPMD/Non-SPMD execution mode + - /// Full/Lightweight runtime mode. Used for better optimization. - unsigned getDefaultLocationReserved2Flags() const override; - -public: - explicit CGOpenMPRuntimeNVPTX(CodeGenModule &CGM); - void clear() override; - - /// Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 - /// global_tid, int proc_bind) to generate code for 'proc_bind' clause. - virtual void emitProcBindClause(CodeGenFunction &CGF, - OpenMPProcBindClauseKind ProcBind, - SourceLocation Loc) override; - - /// Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 - /// global_tid, kmp_int32 num_threads) to generate code for 'num_threads' - /// clause. - /// \param NumThreads An integer value of threads. - virtual void emitNumThreadsClause(CodeGenFunction &CGF, - llvm::Value *NumThreads, - SourceLocation Loc) override; - - /// This function ought to emit, in the general case, a call to - // the openmp runtime kmpc_push_num_teams. In NVPTX backend it is not needed - // as these numbers are obtained through the PTX grid and block configuration. - /// \param NumTeams An integer expression of teams. - /// \param ThreadLimit An integer expression of threads. - void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, - const Expr *ThreadLimit, SourceLocation Loc) override; - - /// Emits inlined function for the specified OpenMP parallel - // directive. - /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID, - /// kmp_int32 BoundID, struct context_vars*). - /// \param D OpenMP directive. - /// \param ThreadIDVar Variable for thread id in the current OpenMP region. - /// \param InnermostKind Kind of innermost directive (for simple directives it - /// is a directive itself, for combined - its innermost directive). - /// \param CodeGen Code generation sequence for the \a D directive. - llvm::Value * - emitParallelOutlinedFunction(const OMPExecutableDirective &D, - const VarDecl *ThreadIDVar, - OpenMPDirectiveKind InnermostKind, - const RegionCodeGenTy &CodeGen) override; - - /// Emits inlined function for the specified OpenMP teams - // directive. - /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID, - /// kmp_int32 BoundID, struct context_vars*). - /// \param D OpenMP directive. - /// \param ThreadIDVar Variable for thread id in the current OpenMP region. - /// \param InnermostKind Kind of innermost directive (for simple directives it - /// is a directive itself, for combined - its innermost directive). - /// \param CodeGen Code generation sequence for the \a D directive. - llvm::Value * - emitTeamsOutlinedFunction(const OMPExecutableDirective &D, - const VarDecl *ThreadIDVar, - OpenMPDirectiveKind InnermostKind, - const RegionCodeGenTy &CodeGen) override; - - /// Emits code for teams call of the \a OutlinedFn with - /// variables captured in a record which address is stored in \a - /// CapturedStruct. - /// \param OutlinedFn Outlined function to be run by team masters. Type of - /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*). - /// \param CapturedVars A pointer to the record with the references to - /// variables used in \a OutlinedFn function. - /// - void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, - SourceLocation Loc, llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> CapturedVars) override; - - /// Emits code for parallel or serial call of the \a OutlinedFn with - /// variables captured in a record which address is stored in \a - /// CapturedStruct. - /// \param OutlinedFn Outlined function to be run in parallel threads. Type of - /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*). - /// \param CapturedVars A pointer to the record with the references to - /// variables used in \a OutlinedFn function. - /// \param IfCond Condition in the associated 'if' clause, if it was - /// specified, nullptr otherwise. - void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, - llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> CapturedVars, - const Expr *IfCond) override; - - /// Emit an implicit/explicit barrier for OpenMP threads. - /// \param Kind Directive for which this implicit barrier call must be - /// generated. Must be OMPD_barrier for explicit barrier generation. - /// \param EmitChecks true if need to emit checks for cancellation barriers. - /// \param ForceSimpleCall true simple barrier call must be emitted, false if - /// runtime class decides which one to emit (simple or with cancellation - /// checks). - /// - void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDirectiveKind Kind, bool EmitChecks = true, - bool ForceSimpleCall = false) override; - - /// Emits a critical region. - /// \param CriticalName Name of the critical region. - /// \param CriticalOpGen Generator for the statement associated with the given - /// critical region. - /// \param Hint Value of the 'hint' clause (optional). - void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, - const RegionCodeGenTy &CriticalOpGen, - SourceLocation Loc, - const Expr *Hint = nullptr) override; - - /// Emit a code for reduction clause. - /// - /// \param Privates List of private copies for original reduction arguments. - /// \param LHSExprs List of LHS in \a ReductionOps reduction operations. - /// \param RHSExprs List of RHS in \a ReductionOps reduction operations. - /// \param ReductionOps List of reduction operations in form 'LHS binop RHS' - /// or 'operator binop(LHS, RHS)'. - /// \param Options List of options for reduction codegen: - /// WithNowait true if parent directive has also nowait clause, false - /// otherwise. - /// SimpleReduction Emit reduction operation only. Used for omp simd - /// directive on the host. - /// ReductionKind The kind of reduction to perform. - virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, - ArrayRef<const Expr *> Privates, - ArrayRef<const Expr *> LHSExprs, - ArrayRef<const Expr *> RHSExprs, - ArrayRef<const Expr *> ReductionOps, - ReductionOptionsTy Options) override; - - /// Returns specified OpenMP runtime function for the current OpenMP - /// implementation. Specialized for the NVPTX device. - /// \param Function OpenMP runtime function. - /// \return Specified function. - llvm::Constant *createNVPTXRuntimeFunction(unsigned Function); - - /// Translates the native parameter of outlined function if this is required - /// for target. - /// \param FD Field decl from captured record for the parameter. - /// \param NativeParam Parameter itself. - const VarDecl *translateParameter(const FieldDecl *FD, - const VarDecl *NativeParam) const override; - - /// Gets the address of the native argument basing on the address of the - /// target-specific parameter. - /// \param NativeParam Parameter itself. - /// \param TargetParam Corresponding target-specific parameter. - Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, - const VarDecl *TargetParam) const override; - - /// Emits call of the outlined function with the provided arguments, - /// translating these arguments to correct target-specific arguments. - void emitOutlinedFunctionCall( - CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *OutlinedFn, - ArrayRef<llvm::Value *> Args = llvm::None) const override; - - /// Emits OpenMP-specific function prolog. - /// Required for device constructs. - void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) override; - - /// Gets the OpenMP-specific address of the local variable. - Address getAddressOfLocalVariable(CodeGenFunction &CGF, - const VarDecl *VD) override; - - /// Target codegen is specialized based on two data-sharing modes: CUDA, in - /// which the local variables are actually global threadlocal, and Generic, in - /// which the local variables are placed in global memory if they may escape - /// their declaration context. - enum DataSharingMode { - /// CUDA data sharing mode. - CUDA, - /// Generic data-sharing mode. - Generic, - }; - - /// Cleans up references to the objects in finished function. - /// - void functionFinished(CodeGenFunction &CGF) override; - - /// Choose a default value for the dist_schedule clause. - void getDefaultDistScheduleAndChunk(CodeGenFunction &CGF, - const OMPLoopDirective &S, OpenMPDistScheduleClauseKind &ScheduleKind, - llvm::Value *&Chunk) const override; - - /// Choose a default value for the schedule clause. - void getDefaultScheduleAndChunk(CodeGenFunction &CGF, - const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind, - const Expr *&ChunkExpr) const override; - - /// Adjust some parameters for the target-based directives, like addresses of - /// the variables captured by reference in lambdas. - void adjustTargetSpecificDataForLambdas( - CodeGenFunction &CGF, const OMPExecutableDirective &D) const override; - - /// Perform check on requires decl to ensure that target architecture - /// supports unified addressing - void checkArchForUnifiedAddressing(CodeGenModule &CGM, - const OMPRequiresDecl *D) const override; - -private: - /// Track the execution mode when codegening directives within a target - /// region. The appropriate mode (SPMD/NON-SPMD) is set on entry to the - /// target region and used by containing directives such as 'parallel' - /// to emit optimized code. - ExecutionMode CurrentExecutionMode = EM_Unknown; - - /// Check if the full runtime is required (default - yes). - bool RequiresFullRuntime = true; - - /// true if we're emitting the code for the target region and next parallel - /// region is L0 for sure. - bool IsInTargetMasterThreadRegion = false; - /// true if currently emitting code for target/teams/distribute region, false - /// - otherwise. - bool IsInTTDRegion = false; - /// true if we're definitely in the parallel region. - bool IsInParallelRegion = false; - - /// Map between an outlined function and its wrapper. - llvm::DenseMap<llvm::Function *, llvm::Function *> WrapperFunctionsMap; - - /// Emit function which wraps the outline parallel region - /// and controls the parameters which are passed to this function. - /// The wrapper ensures that the outlined function is called - /// with the correct arguments when data is shared. - llvm::Function *createParallelDataSharingWrapper( - llvm::Function *OutlinedParallelFn, const OMPExecutableDirective &D); - - /// The data for the single globalized variable. - struct MappedVarData { - /// Corresponding field in the global record. - const FieldDecl *FD = nullptr; - /// Corresponding address. - Address PrivateAddr = Address::invalid(); - /// true, if only one element is required (for latprivates in SPMD mode), - /// false, if need to create based on the warp-size. - bool IsOnePerTeam = false; - MappedVarData() = delete; - MappedVarData(const FieldDecl *FD, bool IsOnePerTeam = false) - : FD(FD), IsOnePerTeam(IsOnePerTeam) {} - }; - /// The map of local variables to their addresses in the global memory. - using DeclToAddrMapTy = llvm::MapVector<const Decl *, MappedVarData>; - /// Set of the parameters passed by value escaping OpenMP context. - using EscapedParamsTy = llvm::SmallPtrSet<const Decl *, 4>; - struct FunctionData { - DeclToAddrMapTy LocalVarData; - llvm::Optional<DeclToAddrMapTy> SecondaryLocalVarData = llvm::None; - EscapedParamsTy EscapedParameters; - llvm::SmallVector<const ValueDecl*, 4> EscapedVariableLengthDecls; - llvm::SmallVector<llvm::Value *, 4> EscapedVariableLengthDeclsAddrs; - const RecordDecl *GlobalRecord = nullptr; - llvm::Optional<const RecordDecl *> SecondaryGlobalRecord = llvm::None; - llvm::Value *GlobalRecordAddr = nullptr; - llvm::Value *IsInSPMDModeFlag = nullptr; - std::unique_ptr<CodeGenFunction::OMPMapVars> MappedParams; - }; - /// Maps the function to the list of the globalized variables with their - /// addresses. - llvm::SmallDenseMap<llvm::Function *, FunctionData> FunctionGlobalizedDecls; - /// List of records for the globalized variables in target/teams/distribute - /// contexts. Inner records are going to be joined into the single record, - /// while those resulting records are going to be joined into the single - /// union. This resulting union (one per CU) is the entry point for the static - /// memory management runtime functions. - struct GlobalPtrSizeRecsTy { - llvm::GlobalVariable *UseSharedMemory = nullptr; - llvm::GlobalVariable *RecSize = nullptr; - llvm::GlobalVariable *Buffer = nullptr; - SourceLocation Loc; - llvm::SmallVector<const RecordDecl *, 2> Records; - unsigned RegionCounter = 0; - }; - llvm::SmallVector<GlobalPtrSizeRecsTy, 8> GlobalizedRecords; - /// Shared pointer for the global memory in the global memory buffer used for - /// the given kernel. - llvm::GlobalVariable *KernelStaticGlobalized = nullptr; - /// Pair of the Non-SPMD team and all reductions variables in this team - /// region. - std::pair<const Decl *, llvm::SmallVector<const ValueDecl *, 4>> - TeamAndReductions; -}; - -} // CodeGen namespace. -} // clang namespace. - -#endif // LLVM_CLANG_LIB_CODEGEN_CGOPENMPRUNTIMENVPTX_H diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h b/gnu/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h deleted file mode 100644 index 41084294ab9..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h +++ /dev/null @@ -1,220 +0,0 @@ -//===--- CGRecordLayout.h - LLVM Record Layout Information ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CGRECORDLAYOUT_H -#define LLVM_CLANG_LIB_CODEGEN_CGRECORDLAYOUT_H - -#include "clang/AST/CharUnits.h" -#include "clang/AST/DeclCXX.h" -#include "clang/Basic/LLVM.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/IR/DerivedTypes.h" - -namespace llvm { - class StructType; -} - -namespace clang { -namespace CodeGen { - -/// Structure with information about how a bitfield should be accessed. -/// -/// Often we layout a sequence of bitfields as a contiguous sequence of bits. -/// When the AST record layout does this, we represent it in the LLVM IR's type -/// as either a sequence of i8 members or a byte array to reserve the number of -/// bytes touched without forcing any particular alignment beyond the basic -/// character alignment. -/// -/// Then accessing a particular bitfield involves converting this byte array -/// into a single integer of that size (i24 or i40 -- may not be power-of-two -/// size), loading it, and shifting and masking to extract the particular -/// subsequence of bits which make up that particular bitfield. This structure -/// encodes the information used to construct the extraction code sequences. -/// The CGRecordLayout also has a field index which encodes which byte-sequence -/// this bitfield falls within. Let's assume the following C struct: -/// -/// struct S { -/// char a, b, c; -/// unsigned bits : 3; -/// unsigned more_bits : 4; -/// unsigned still_more_bits : 7; -/// }; -/// -/// This will end up as the following LLVM type. The first array is the -/// bitfield, and the second is the padding out to a 4-byte alignmnet. -/// -/// %t = type { i8, i8, i8, i8, i8, [3 x i8] } -/// -/// When generating code to access more_bits, we'll generate something -/// essentially like this: -/// -/// define i32 @foo(%t* %base) { -/// %0 = gep %t* %base, i32 0, i32 3 -/// %2 = load i8* %1 -/// %3 = lshr i8 %2, 3 -/// %4 = and i8 %3, 15 -/// %5 = zext i8 %4 to i32 -/// ret i32 %i -/// } -/// -struct CGBitFieldInfo { - /// The offset within a contiguous run of bitfields that are represented as - /// a single "field" within the LLVM struct type. This offset is in bits. - unsigned Offset : 16; - - /// The total size of the bit-field, in bits. - unsigned Size : 15; - - /// Whether the bit-field is signed. - unsigned IsSigned : 1; - - /// The storage size in bits which should be used when accessing this - /// bitfield. - unsigned StorageSize; - - /// The offset of the bitfield storage from the start of the struct. - CharUnits StorageOffset; - - CGBitFieldInfo() - : Offset(), Size(), IsSigned(), StorageSize(), StorageOffset() {} - - CGBitFieldInfo(unsigned Offset, unsigned Size, bool IsSigned, - unsigned StorageSize, CharUnits StorageOffset) - : Offset(Offset), Size(Size), IsSigned(IsSigned), - StorageSize(StorageSize), StorageOffset(StorageOffset) {} - - void print(raw_ostream &OS) const; - void dump() const; - - /// Given a bit-field decl, build an appropriate helper object for - /// accessing that field (which is expected to have the given offset and - /// size). - static CGBitFieldInfo MakeInfo(class CodeGenTypes &Types, - const FieldDecl *FD, - uint64_t Offset, uint64_t Size, - uint64_t StorageSize, - CharUnits StorageOffset); -}; - -/// CGRecordLayout - This class handles struct and union layout info while -/// lowering AST types to LLVM types. -/// -/// These layout objects are only created on demand as IR generation requires. -class CGRecordLayout { - friend class CodeGenTypes; - - CGRecordLayout(const CGRecordLayout &) = delete; - void operator=(const CGRecordLayout &) = delete; - -private: - /// The LLVM type corresponding to this record layout; used when - /// laying it out as a complete object. - llvm::StructType *CompleteObjectType; - - /// The LLVM type for the non-virtual part of this record layout; - /// used when laying it out as a base subobject. - llvm::StructType *BaseSubobjectType; - - /// Map from (non-bit-field) struct field to the corresponding llvm struct - /// type field no. This info is populated by record builder. - llvm::DenseMap<const FieldDecl *, unsigned> FieldInfo; - - /// Map from (bit-field) struct field to the corresponding llvm struct type - /// field no. This info is populated by record builder. - llvm::DenseMap<const FieldDecl *, CGBitFieldInfo> BitFields; - - // FIXME: Maybe we could use a CXXBaseSpecifier as the key and use a single - // map for both virtual and non-virtual bases. - llvm::DenseMap<const CXXRecordDecl *, unsigned> NonVirtualBases; - - /// Map from virtual bases to their field index in the complete object. - llvm::DenseMap<const CXXRecordDecl *, unsigned> CompleteObjectVirtualBases; - - /// False if any direct or indirect subobject of this class, when - /// considered as a complete object, requires a non-zero bitpattern - /// when zero-initialized. - bool IsZeroInitializable : 1; - - /// False if any direct or indirect subobject of this class, when - /// considered as a base subobject, requires a non-zero bitpattern - /// when zero-initialized. - bool IsZeroInitializableAsBase : 1; - -public: - CGRecordLayout(llvm::StructType *CompleteObjectType, - llvm::StructType *BaseSubobjectType, - bool IsZeroInitializable, - bool IsZeroInitializableAsBase) - : CompleteObjectType(CompleteObjectType), - BaseSubobjectType(BaseSubobjectType), - IsZeroInitializable(IsZeroInitializable), - IsZeroInitializableAsBase(IsZeroInitializableAsBase) {} - - /// Return the "complete object" LLVM type associated with - /// this record. - llvm::StructType *getLLVMType() const { - return CompleteObjectType; - } - - /// Return the "base subobject" LLVM type associated with - /// this record. - llvm::StructType *getBaseSubobjectLLVMType() const { - return BaseSubobjectType; - } - - /// Check whether this struct can be C++ zero-initialized - /// with a zeroinitializer. - bool isZeroInitializable() const { - return IsZeroInitializable; - } - - /// Check whether this struct can be C++ zero-initialized - /// with a zeroinitializer when considered as a base subobject. - bool isZeroInitializableAsBase() const { - return IsZeroInitializableAsBase; - } - - /// Return llvm::StructType element number that corresponds to the - /// field FD. - unsigned getLLVMFieldNo(const FieldDecl *FD) const { - FD = FD->getCanonicalDecl(); - assert(FieldInfo.count(FD) && "Invalid field for record!"); - return FieldInfo.lookup(FD); - } - - unsigned getNonVirtualBaseLLVMFieldNo(const CXXRecordDecl *RD) const { - assert(NonVirtualBases.count(RD) && "Invalid non-virtual base!"); - return NonVirtualBases.lookup(RD); - } - - /// Return the LLVM field index corresponding to the given - /// virtual base. Only valid when operating on the complete object. - unsigned getVirtualBaseIndex(const CXXRecordDecl *base) const { - assert(CompleteObjectVirtualBases.count(base) && "Invalid virtual base!"); - return CompleteObjectVirtualBases.lookup(base); - } - - /// Return the BitFieldInfo that corresponds to the field FD. - const CGBitFieldInfo &getBitFieldInfo(const FieldDecl *FD) const { - FD = FD->getCanonicalDecl(); - assert(FD->isBitField() && "Invalid call for non-bit-field decl!"); - llvm::DenseMap<const FieldDecl *, CGBitFieldInfo>::const_iterator - it = BitFields.find(FD); - assert(it != BitFields.end() && "Unable to find bitfield info"); - return it->second; - } - - void print(raw_ostream &OS) const; - void dump() const; -}; - -} // end namespace CodeGen -} // end namespace clang - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp deleted file mode 100644 index c754541ac12..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ /dev/null @@ -1,897 +0,0 @@ -//===--- CGRecordLayoutBuilder.cpp - CGRecordLayout builder ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Builder implementation for CGRecordLayout objects. -// -//===----------------------------------------------------------------------===// - -#include "CGRecordLayout.h" -#include "CGCXXABI.h" -#include "CodeGenTypes.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Attr.h" -#include "clang/AST/CXXInheritance.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/Expr.h" -#include "clang/AST/RecordLayout.h" -#include "clang/Basic/CodeGenOptions.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Type.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" -using namespace clang; -using namespace CodeGen; - -namespace { -/// The CGRecordLowering is responsible for lowering an ASTRecordLayout to an -/// llvm::Type. Some of the lowering is straightforward, some is not. Here we -/// detail some of the complexities and weirdnesses here. -/// * LLVM does not have unions - Unions can, in theory be represented by any -/// llvm::Type with correct size. We choose a field via a specific heuristic -/// and add padding if necessary. -/// * LLVM does not have bitfields - Bitfields are collected into contiguous -/// runs and allocated as a single storage type for the run. ASTRecordLayout -/// contains enough information to determine where the runs break. Microsoft -/// and Itanium follow different rules and use different codepaths. -/// * It is desired that, when possible, bitfields use the appropriate iN type -/// when lowered to llvm types. For example unsigned x : 24 gets lowered to -/// i24. This isn't always possible because i24 has storage size of 32 bit -/// and if it is possible to use that extra byte of padding we must use -/// [i8 x 3] instead of i24. The function clipTailPadding does this. -/// C++ examples that require clipping: -/// struct { int a : 24; char b; }; // a must be clipped, b goes at offset 3 -/// struct A { int a : 24; }; // a must be clipped because a struct like B -// could exist: struct B : A { char b; }; // b goes at offset 3 -/// * Clang ignores 0 sized bitfields and 0 sized bases but *not* zero sized -/// fields. The existing asserts suggest that LLVM assumes that *every* field -/// has an underlying storage type. Therefore empty structures containing -/// zero sized subobjects such as empty records or zero sized arrays still get -/// a zero sized (empty struct) storage type. -/// * Clang reads the complete type rather than the base type when generating -/// code to access fields. Bitfields in tail position with tail padding may -/// be clipped in the base class but not the complete class (we may discover -/// that the tail padding is not used in the complete class.) However, -/// because LLVM reads from the complete type it can generate incorrect code -/// if we do not clip the tail padding off of the bitfield in the complete -/// layout. This introduces a somewhat awkward extra unnecessary clip stage. -/// The location of the clip is stored internally as a sentinel of type -/// SCISSOR. If LLVM were updated to read base types (which it probably -/// should because locations of things such as VBases are bogus in the llvm -/// type anyway) then we could eliminate the SCISSOR. -/// * Itanium allows nearly empty primary virtual bases. These bases don't get -/// get their own storage because they're laid out as part of another base -/// or at the beginning of the structure. Determining if a VBase actually -/// gets storage awkwardly involves a walk of all bases. -/// * VFPtrs and VBPtrs do *not* make a record NotZeroInitializable. -struct CGRecordLowering { - // MemberInfo is a helper structure that contains information about a record - // member. In additional to the standard member types, there exists a - // sentinel member type that ensures correct rounding. - struct MemberInfo { - CharUnits Offset; - enum InfoKind { VFPtr, VBPtr, Field, Base, VBase, Scissor } Kind; - llvm::Type *Data; - union { - const FieldDecl *FD; - const CXXRecordDecl *RD; - }; - MemberInfo(CharUnits Offset, InfoKind Kind, llvm::Type *Data, - const FieldDecl *FD = nullptr) - : Offset(Offset), Kind(Kind), Data(Data), FD(FD) {} - MemberInfo(CharUnits Offset, InfoKind Kind, llvm::Type *Data, - const CXXRecordDecl *RD) - : Offset(Offset), Kind(Kind), Data(Data), RD(RD) {} - // MemberInfos are sorted so we define a < operator. - bool operator <(const MemberInfo& a) const { return Offset < a.Offset; } - }; - // The constructor. - CGRecordLowering(CodeGenTypes &Types, const RecordDecl *D, bool Packed); - // Short helper routines. - /// Constructs a MemberInfo instance from an offset and llvm::Type *. - MemberInfo StorageInfo(CharUnits Offset, llvm::Type *Data) { - return MemberInfo(Offset, MemberInfo::Field, Data); - } - - /// The Microsoft bitfield layout rule allocates discrete storage - /// units of the field's formal type and only combines adjacent - /// fields of the same formal type. We want to emit a layout with - /// these discrete storage units instead of combining them into a - /// continuous run. - bool isDiscreteBitFieldABI() { - return Context.getTargetInfo().getCXXABI().isMicrosoft() || - D->isMsStruct(Context); - } - - /// The Itanium base layout rule allows virtual bases to overlap - /// other bases, which complicates layout in specific ways. - /// - /// Note specifically that the ms_struct attribute doesn't change this. - bool isOverlappingVBaseABI() { - return !Context.getTargetInfo().getCXXABI().isMicrosoft(); - } - - /// Wraps llvm::Type::getIntNTy with some implicit arguments. - llvm::Type *getIntNType(uint64_t NumBits) { - return llvm::Type::getIntNTy(Types.getLLVMContext(), - (unsigned)llvm::alignTo(NumBits, 8)); - } - /// Gets an llvm type of size NumBytes and alignment 1. - llvm::Type *getByteArrayType(CharUnits NumBytes) { - assert(!NumBytes.isZero() && "Empty byte arrays aren't allowed."); - llvm::Type *Type = llvm::Type::getInt8Ty(Types.getLLVMContext()); - return NumBytes == CharUnits::One() ? Type : - (llvm::Type *)llvm::ArrayType::get(Type, NumBytes.getQuantity()); - } - /// Gets the storage type for a field decl and handles storage - /// for itanium bitfields that are smaller than their declared type. - llvm::Type *getStorageType(const FieldDecl *FD) { - llvm::Type *Type = Types.ConvertTypeForMem(FD->getType()); - if (!FD->isBitField()) return Type; - if (isDiscreteBitFieldABI()) return Type; - return getIntNType(std::min(FD->getBitWidthValue(Context), - (unsigned)Context.toBits(getSize(Type)))); - } - /// Gets the llvm Basesubobject type from a CXXRecordDecl. - llvm::Type *getStorageType(const CXXRecordDecl *RD) { - return Types.getCGRecordLayout(RD).getBaseSubobjectLLVMType(); - } - CharUnits bitsToCharUnits(uint64_t BitOffset) { - return Context.toCharUnitsFromBits(BitOffset); - } - CharUnits getSize(llvm::Type *Type) { - return CharUnits::fromQuantity(DataLayout.getTypeAllocSize(Type)); - } - CharUnits getAlignment(llvm::Type *Type) { - return CharUnits::fromQuantity(DataLayout.getABITypeAlignment(Type)); - } - bool isZeroInitializable(const FieldDecl *FD) { - return Types.isZeroInitializable(FD->getType()); - } - bool isZeroInitializable(const RecordDecl *RD) { - return Types.isZeroInitializable(RD); - } - void appendPaddingBytes(CharUnits Size) { - if (!Size.isZero()) - FieldTypes.push_back(getByteArrayType(Size)); - } - uint64_t getFieldBitOffset(const FieldDecl *FD) { - return Layout.getFieldOffset(FD->getFieldIndex()); - } - // Layout routines. - void setBitFieldInfo(const FieldDecl *FD, CharUnits StartOffset, - llvm::Type *StorageType); - /// Lowers an ASTRecordLayout to a llvm type. - void lower(bool NonVirtualBaseType); - void lowerUnion(); - void accumulateFields(); - void accumulateBitFields(RecordDecl::field_iterator Field, - RecordDecl::field_iterator FieldEnd); - void accumulateBases(); - void accumulateVPtrs(); - void accumulateVBases(); - /// Recursively searches all of the bases to find out if a vbase is - /// not the primary vbase of some base class. - bool hasOwnStorage(const CXXRecordDecl *Decl, const CXXRecordDecl *Query); - void calculateZeroInit(); - /// Lowers bitfield storage types to I8 arrays for bitfields with tail - /// padding that is or can potentially be used. - void clipTailPadding(); - /// Determines if we need a packed llvm struct. - void determinePacked(bool NVBaseType); - /// Inserts padding everywhere it's needed. - void insertPadding(); - /// Fills out the structures that are ultimately consumed. - void fillOutputFields(); - // Input memoization fields. - CodeGenTypes &Types; - const ASTContext &Context; - const RecordDecl *D; - const CXXRecordDecl *RD; - const ASTRecordLayout &Layout; - const llvm::DataLayout &DataLayout; - // Helpful intermediate data-structures. - std::vector<MemberInfo> Members; - // Output fields, consumed by CodeGenTypes::ComputeRecordLayout. - SmallVector<llvm::Type *, 16> FieldTypes; - llvm::DenseMap<const FieldDecl *, unsigned> Fields; - llvm::DenseMap<const FieldDecl *, CGBitFieldInfo> BitFields; - llvm::DenseMap<const CXXRecordDecl *, unsigned> NonVirtualBases; - llvm::DenseMap<const CXXRecordDecl *, unsigned> VirtualBases; - bool IsZeroInitializable : 1; - bool IsZeroInitializableAsBase : 1; - bool Packed : 1; -private: - CGRecordLowering(const CGRecordLowering &) = delete; - void operator =(const CGRecordLowering &) = delete; -}; -} // namespace { - -CGRecordLowering::CGRecordLowering(CodeGenTypes &Types, const RecordDecl *D, - bool Packed) - : Types(Types), Context(Types.getContext()), D(D), - RD(dyn_cast<CXXRecordDecl>(D)), - Layout(Types.getContext().getASTRecordLayout(D)), - DataLayout(Types.getDataLayout()), IsZeroInitializable(true), - IsZeroInitializableAsBase(true), Packed(Packed) {} - -void CGRecordLowering::setBitFieldInfo( - const FieldDecl *FD, CharUnits StartOffset, llvm::Type *StorageType) { - CGBitFieldInfo &Info = BitFields[FD->getCanonicalDecl()]; - Info.IsSigned = FD->getType()->isSignedIntegerOrEnumerationType(); - Info.Offset = (unsigned)(getFieldBitOffset(FD) - Context.toBits(StartOffset)); - Info.Size = FD->getBitWidthValue(Context); - Info.StorageSize = (unsigned)DataLayout.getTypeAllocSizeInBits(StorageType); - Info.StorageOffset = StartOffset; - if (Info.Size > Info.StorageSize) - Info.Size = Info.StorageSize; - // Reverse the bit offsets for big endian machines. Because we represent - // a bitfield as a single large integer load, we can imagine the bits - // counting from the most-significant-bit instead of the - // least-significant-bit. - if (DataLayout.isBigEndian()) - Info.Offset = Info.StorageSize - (Info.Offset + Info.Size); -} - -void CGRecordLowering::lower(bool NVBaseType) { - // The lowering process implemented in this function takes a variety of - // carefully ordered phases. - // 1) Store all members (fields and bases) in a list and sort them by offset. - // 2) Add a 1-byte capstone member at the Size of the structure. - // 3) Clip bitfield storages members if their tail padding is or might be - // used by another field or base. The clipping process uses the capstone - // by treating it as another object that occurs after the record. - // 4) Determine if the llvm-struct requires packing. It's important that this - // phase occur after clipping, because clipping changes the llvm type. - // This phase reads the offset of the capstone when determining packedness - // and updates the alignment of the capstone to be equal of the alignment - // of the record after doing so. - // 5) Insert padding everywhere it is needed. This phase requires 'Packed' to - // have been computed and needs to know the alignment of the record in - // order to understand if explicit tail padding is needed. - // 6) Remove the capstone, we don't need it anymore. - // 7) Determine if this record can be zero-initialized. This phase could have - // been placed anywhere after phase 1. - // 8) Format the complete list of members in a way that can be consumed by - // CodeGenTypes::ComputeRecordLayout. - CharUnits Size = NVBaseType ? Layout.getNonVirtualSize() : Layout.getSize(); - if (D->isUnion()) - return lowerUnion(); - accumulateFields(); - // RD implies C++. - if (RD) { - accumulateVPtrs(); - accumulateBases(); - if (Members.empty()) - return appendPaddingBytes(Size); - if (!NVBaseType) - accumulateVBases(); - } - std::stable_sort(Members.begin(), Members.end()); - Members.push_back(StorageInfo(Size, getIntNType(8))); - clipTailPadding(); - determinePacked(NVBaseType); - insertPadding(); - Members.pop_back(); - calculateZeroInit(); - fillOutputFields(); -} - -void CGRecordLowering::lowerUnion() { - CharUnits LayoutSize = Layout.getSize(); - llvm::Type *StorageType = nullptr; - bool SeenNamedMember = false; - // Iterate through the fields setting bitFieldInfo and the Fields array. Also - // locate the "most appropriate" storage type. The heuristic for finding the - // storage type isn't necessary, the first (non-0-length-bitfield) field's - // type would work fine and be simpler but would be different than what we've - // been doing and cause lit tests to change. - for (const auto *Field : D->fields()) { - if (Field->isBitField()) { - if (Field->isZeroLengthBitField(Context)) - continue; - llvm::Type *FieldType = getStorageType(Field); - if (LayoutSize < getSize(FieldType)) - FieldType = getByteArrayType(LayoutSize); - setBitFieldInfo(Field, CharUnits::Zero(), FieldType); - } - Fields[Field->getCanonicalDecl()] = 0; - llvm::Type *FieldType = getStorageType(Field); - // Compute zero-initializable status. - // This union might not be zero initialized: it may contain a pointer to - // data member which might have some exotic initialization sequence. - // If this is the case, then we aught not to try and come up with a "better" - // type, it might not be very easy to come up with a Constant which - // correctly initializes it. - if (!SeenNamedMember) { - SeenNamedMember = Field->getIdentifier(); - if (!SeenNamedMember) - if (const auto *FieldRD = Field->getType()->getAsRecordDecl()) - SeenNamedMember = FieldRD->findFirstNamedDataMember(); - if (SeenNamedMember && !isZeroInitializable(Field)) { - IsZeroInitializable = IsZeroInitializableAsBase = false; - StorageType = FieldType; - } - } - // Because our union isn't zero initializable, we won't be getting a better - // storage type. - if (!IsZeroInitializable) - continue; - // Conditionally update our storage type if we've got a new "better" one. - if (!StorageType || - getAlignment(FieldType) > getAlignment(StorageType) || - (getAlignment(FieldType) == getAlignment(StorageType) && - getSize(FieldType) > getSize(StorageType))) - StorageType = FieldType; - } - // If we have no storage type just pad to the appropriate size and return. - if (!StorageType) - return appendPaddingBytes(LayoutSize); - // If our storage size was bigger than our required size (can happen in the - // case of packed bitfields on Itanium) then just use an I8 array. - if (LayoutSize < getSize(StorageType)) - StorageType = getByteArrayType(LayoutSize); - FieldTypes.push_back(StorageType); - appendPaddingBytes(LayoutSize - getSize(StorageType)); - // Set packed if we need it. - if (LayoutSize % getAlignment(StorageType)) - Packed = true; -} - -void CGRecordLowering::accumulateFields() { - for (RecordDecl::field_iterator Field = D->field_begin(), - FieldEnd = D->field_end(); - Field != FieldEnd;) - if (Field->isBitField()) { - RecordDecl::field_iterator Start = Field; - // Iterate to gather the list of bitfields. - for (++Field; Field != FieldEnd && Field->isBitField(); ++Field); - accumulateBitFields(Start, Field); - } else { - Members.push_back(MemberInfo( - bitsToCharUnits(getFieldBitOffset(*Field)), MemberInfo::Field, - getStorageType(*Field), *Field)); - ++Field; - } -} - -void -CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field, - RecordDecl::field_iterator FieldEnd) { - // Run stores the first element of the current run of bitfields. FieldEnd is - // used as a special value to note that we don't have a current run. A - // bitfield run is a contiguous collection of bitfields that can be stored in - // the same storage block. Zero-sized bitfields and bitfields that would - // cross an alignment boundary break a run and start a new one. - RecordDecl::field_iterator Run = FieldEnd; - // Tail is the offset of the first bit off the end of the current run. It's - // used to determine if the ASTRecordLayout is treating these two bitfields as - // contiguous. StartBitOffset is offset of the beginning of the Run. - uint64_t StartBitOffset, Tail = 0; - if (isDiscreteBitFieldABI()) { - for (; Field != FieldEnd; ++Field) { - uint64_t BitOffset = getFieldBitOffset(*Field); - // Zero-width bitfields end runs. - if (Field->isZeroLengthBitField(Context)) { - Run = FieldEnd; - continue; - } - llvm::Type *Type = Types.ConvertTypeForMem(Field->getType()); - // If we don't have a run yet, or don't live within the previous run's - // allocated storage then we allocate some storage and start a new run. - if (Run == FieldEnd || BitOffset >= Tail) { - Run = Field; - StartBitOffset = BitOffset; - Tail = StartBitOffset + DataLayout.getTypeAllocSizeInBits(Type); - // Add the storage member to the record. This must be added to the - // record before the bitfield members so that it gets laid out before - // the bitfields it contains get laid out. - Members.push_back(StorageInfo(bitsToCharUnits(StartBitOffset), Type)); - } - // Bitfields get the offset of their storage but come afterward and remain - // there after a stable sort. - Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset), - MemberInfo::Field, nullptr, *Field)); - } - return; - } - - // Check if OffsetInRecord is better as a single field run. When OffsetInRecord - // has legal integer width, and its bitfield offset is naturally aligned, it - // is better to make the bitfield a separate storage component so as it can be - // accessed directly with lower cost. - auto IsBetterAsSingleFieldRun = [&](uint64_t OffsetInRecord, - uint64_t StartBitOffset) { - if (!Types.getCodeGenOpts().FineGrainedBitfieldAccesses) - return false; - if (!DataLayout.isLegalInteger(OffsetInRecord)) - return false; - // Make sure StartBitOffset is natually aligned if it is treated as an - // IType integer. - if (StartBitOffset % - Context.toBits(getAlignment(getIntNType(OffsetInRecord))) != - 0) - return false; - return true; - }; - - // The start field is better as a single field run. - bool StartFieldAsSingleRun = false; - for (;;) { - // Check to see if we need to start a new run. - if (Run == FieldEnd) { - // If we're out of fields, return. - if (Field == FieldEnd) - break; - // Any non-zero-length bitfield can start a new run. - if (!Field->isZeroLengthBitField(Context)) { - Run = Field; - StartBitOffset = getFieldBitOffset(*Field); - Tail = StartBitOffset + Field->getBitWidthValue(Context); - StartFieldAsSingleRun = IsBetterAsSingleFieldRun(Tail - StartBitOffset, - StartBitOffset); - } - ++Field; - continue; - } - - // If the start field of a new run is better as a single run, or - // if current field (or consecutive fields) is better as a single run, or - // if current field has zero width bitfield and either - // UseZeroLengthBitfieldAlignment or UseBitFieldTypeAlignment is set to - // true, or - // if the offset of current field is inconsistent with the offset of - // previous field plus its offset, - // skip the block below and go ahead to emit the storage. - // Otherwise, try to add bitfields to the run. - if (!StartFieldAsSingleRun && Field != FieldEnd && - !IsBetterAsSingleFieldRun(Tail - StartBitOffset, StartBitOffset) && - (!Field->isZeroLengthBitField(Context) || - (!Context.getTargetInfo().useZeroLengthBitfieldAlignment() && - !Context.getTargetInfo().useBitFieldTypeAlignment())) && - Tail == getFieldBitOffset(*Field)) { - Tail += Field->getBitWidthValue(Context); - ++Field; - continue; - } - - // We've hit a break-point in the run and need to emit a storage field. - llvm::Type *Type = getIntNType(Tail - StartBitOffset); - // Add the storage member to the record and set the bitfield info for all of - // the bitfields in the run. Bitfields get the offset of their storage but - // come afterward and remain there after a stable sort. - Members.push_back(StorageInfo(bitsToCharUnits(StartBitOffset), Type)); - for (; Run != Field; ++Run) - Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset), - MemberInfo::Field, nullptr, *Run)); - Run = FieldEnd; - StartFieldAsSingleRun = false; - } -} - -void CGRecordLowering::accumulateBases() { - // If we've got a primary virtual base, we need to add it with the bases. - if (Layout.isPrimaryBaseVirtual()) { - const CXXRecordDecl *BaseDecl = Layout.getPrimaryBase(); - Members.push_back(MemberInfo(CharUnits::Zero(), MemberInfo::Base, - getStorageType(BaseDecl), BaseDecl)); - } - // Accumulate the non-virtual bases. - for (const auto &Base : RD->bases()) { - if (Base.isVirtual()) - continue; - - // Bases can be zero-sized even if not technically empty if they - // contain only a trailing array member. - const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); - if (!BaseDecl->isEmpty() && - !Context.getASTRecordLayout(BaseDecl).getNonVirtualSize().isZero()) - Members.push_back(MemberInfo(Layout.getBaseClassOffset(BaseDecl), - MemberInfo::Base, getStorageType(BaseDecl), BaseDecl)); - } -} - -void CGRecordLowering::accumulateVPtrs() { - if (Layout.hasOwnVFPtr()) - Members.push_back(MemberInfo(CharUnits::Zero(), MemberInfo::VFPtr, - llvm::FunctionType::get(getIntNType(32), /*isVarArg=*/true)-> - getPointerTo()->getPointerTo())); - if (Layout.hasOwnVBPtr()) - Members.push_back(MemberInfo(Layout.getVBPtrOffset(), MemberInfo::VBPtr, - llvm::Type::getInt32PtrTy(Types.getLLVMContext()))); -} - -void CGRecordLowering::accumulateVBases() { - CharUnits ScissorOffset = Layout.getNonVirtualSize(); - // In the itanium ABI, it's possible to place a vbase at a dsize that is - // smaller than the nvsize. Here we check to see if such a base is placed - // before the nvsize and set the scissor offset to that, instead of the - // nvsize. - if (isOverlappingVBaseABI()) - for (const auto &Base : RD->vbases()) { - const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); - if (BaseDecl->isEmpty()) - continue; - // If the vbase is a primary virtual base of some base, then it doesn't - // get its own storage location but instead lives inside of that base. - if (Context.isNearlyEmpty(BaseDecl) && !hasOwnStorage(RD, BaseDecl)) - continue; - ScissorOffset = std::min(ScissorOffset, - Layout.getVBaseClassOffset(BaseDecl)); - } - Members.push_back(MemberInfo(ScissorOffset, MemberInfo::Scissor, nullptr, - RD)); - for (const auto &Base : RD->vbases()) { - const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); - if (BaseDecl->isEmpty()) - continue; - CharUnits Offset = Layout.getVBaseClassOffset(BaseDecl); - // If the vbase is a primary virtual base of some base, then it doesn't - // get its own storage location but instead lives inside of that base. - if (isOverlappingVBaseABI() && - Context.isNearlyEmpty(BaseDecl) && - !hasOwnStorage(RD, BaseDecl)) { - Members.push_back(MemberInfo(Offset, MemberInfo::VBase, nullptr, - BaseDecl)); - continue; - } - // If we've got a vtordisp, add it as a storage type. - if (Layout.getVBaseOffsetsMap().find(BaseDecl)->second.hasVtorDisp()) - Members.push_back(StorageInfo(Offset - CharUnits::fromQuantity(4), - getIntNType(32))); - Members.push_back(MemberInfo(Offset, MemberInfo::VBase, - getStorageType(BaseDecl), BaseDecl)); - } -} - -bool CGRecordLowering::hasOwnStorage(const CXXRecordDecl *Decl, - const CXXRecordDecl *Query) { - const ASTRecordLayout &DeclLayout = Context.getASTRecordLayout(Decl); - if (DeclLayout.isPrimaryBaseVirtual() && DeclLayout.getPrimaryBase() == Query) - return false; - for (const auto &Base : Decl->bases()) - if (!hasOwnStorage(Base.getType()->getAsCXXRecordDecl(), Query)) - return false; - return true; -} - -void CGRecordLowering::calculateZeroInit() { - for (std::vector<MemberInfo>::const_iterator Member = Members.begin(), - MemberEnd = Members.end(); - IsZeroInitializableAsBase && Member != MemberEnd; ++Member) { - if (Member->Kind == MemberInfo::Field) { - if (!Member->FD || isZeroInitializable(Member->FD)) - continue; - IsZeroInitializable = IsZeroInitializableAsBase = false; - } else if (Member->Kind == MemberInfo::Base || - Member->Kind == MemberInfo::VBase) { - if (isZeroInitializable(Member->RD)) - continue; - IsZeroInitializable = false; - if (Member->Kind == MemberInfo::Base) - IsZeroInitializableAsBase = false; - } - } -} - -void CGRecordLowering::clipTailPadding() { - std::vector<MemberInfo>::iterator Prior = Members.begin(); - CharUnits Tail = getSize(Prior->Data); - for (std::vector<MemberInfo>::iterator Member = Prior + 1, - MemberEnd = Members.end(); - Member != MemberEnd; ++Member) { - // Only members with data and the scissor can cut into tail padding. - if (!Member->Data && Member->Kind != MemberInfo::Scissor) - continue; - if (Member->Offset < Tail) { - assert(Prior->Kind == MemberInfo::Field && !Prior->FD && - "Only storage fields have tail padding!"); - Prior->Data = getByteArrayType(bitsToCharUnits(llvm::alignTo( - cast<llvm::IntegerType>(Prior->Data)->getIntegerBitWidth(), 8))); - } - if (Member->Data) - Prior = Member; - Tail = Prior->Offset + getSize(Prior->Data); - } -} - -void CGRecordLowering::determinePacked(bool NVBaseType) { - if (Packed) - return; - CharUnits Alignment = CharUnits::One(); - CharUnits NVAlignment = CharUnits::One(); - CharUnits NVSize = - !NVBaseType && RD ? Layout.getNonVirtualSize() : CharUnits::Zero(); - for (std::vector<MemberInfo>::const_iterator Member = Members.begin(), - MemberEnd = Members.end(); - Member != MemberEnd; ++Member) { - if (!Member->Data) - continue; - // If any member falls at an offset that it not a multiple of its alignment, - // then the entire record must be packed. - if (Member->Offset % getAlignment(Member->Data)) - Packed = true; - if (Member->Offset < NVSize) - NVAlignment = std::max(NVAlignment, getAlignment(Member->Data)); - Alignment = std::max(Alignment, getAlignment(Member->Data)); - } - // If the size of the record (the capstone's offset) is not a multiple of the - // record's alignment, it must be packed. - if (Members.back().Offset % Alignment) - Packed = true; - // If the non-virtual sub-object is not a multiple of the non-virtual - // sub-object's alignment, it must be packed. We cannot have a packed - // non-virtual sub-object and an unpacked complete object or vise versa. - if (NVSize % NVAlignment) - Packed = true; - // Update the alignment of the sentinel. - if (!Packed) - Members.back().Data = getIntNType(Context.toBits(Alignment)); -} - -void CGRecordLowering::insertPadding() { - std::vector<std::pair<CharUnits, CharUnits> > Padding; - CharUnits Size = CharUnits::Zero(); - for (std::vector<MemberInfo>::const_iterator Member = Members.begin(), - MemberEnd = Members.end(); - Member != MemberEnd; ++Member) { - if (!Member->Data) - continue; - CharUnits Offset = Member->Offset; - assert(Offset >= Size); - // Insert padding if we need to. - if (Offset != - Size.alignTo(Packed ? CharUnits::One() : getAlignment(Member->Data))) - Padding.push_back(std::make_pair(Size, Offset - Size)); - Size = Offset + getSize(Member->Data); - } - if (Padding.empty()) - return; - // Add the padding to the Members list and sort it. - for (std::vector<std::pair<CharUnits, CharUnits> >::const_iterator - Pad = Padding.begin(), PadEnd = Padding.end(); - Pad != PadEnd; ++Pad) - Members.push_back(StorageInfo(Pad->first, getByteArrayType(Pad->second))); - std::stable_sort(Members.begin(), Members.end()); -} - -void CGRecordLowering::fillOutputFields() { - for (std::vector<MemberInfo>::const_iterator Member = Members.begin(), - MemberEnd = Members.end(); - Member != MemberEnd; ++Member) { - if (Member->Data) - FieldTypes.push_back(Member->Data); - if (Member->Kind == MemberInfo::Field) { - if (Member->FD) - Fields[Member->FD->getCanonicalDecl()] = FieldTypes.size() - 1; - // A field without storage must be a bitfield. - if (!Member->Data) - setBitFieldInfo(Member->FD, Member->Offset, FieldTypes.back()); - } else if (Member->Kind == MemberInfo::Base) - NonVirtualBases[Member->RD] = FieldTypes.size() - 1; - else if (Member->Kind == MemberInfo::VBase) - VirtualBases[Member->RD] = FieldTypes.size() - 1; - } -} - -CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types, - const FieldDecl *FD, - uint64_t Offset, uint64_t Size, - uint64_t StorageSize, - CharUnits StorageOffset) { - // This function is vestigial from CGRecordLayoutBuilder days but is still - // used in GCObjCRuntime.cpp. That usage has a "fixme" attached to it that - // when addressed will allow for the removal of this function. - llvm::Type *Ty = Types.ConvertTypeForMem(FD->getType()); - CharUnits TypeSizeInBytes = - CharUnits::fromQuantity(Types.getDataLayout().getTypeAllocSize(Ty)); - uint64_t TypeSizeInBits = Types.getContext().toBits(TypeSizeInBytes); - - bool IsSigned = FD->getType()->isSignedIntegerOrEnumerationType(); - - if (Size > TypeSizeInBits) { - // We have a wide bit-field. The extra bits are only used for padding, so - // if we have a bitfield of type T, with size N: - // - // T t : N; - // - // We can just assume that it's: - // - // T t : sizeof(T); - // - Size = TypeSizeInBits; - } - - // Reverse the bit offsets for big endian machines. Because we represent - // a bitfield as a single large integer load, we can imagine the bits - // counting from the most-significant-bit instead of the - // least-significant-bit. - if (Types.getDataLayout().isBigEndian()) { - Offset = StorageSize - (Offset + Size); - } - - return CGBitFieldInfo(Offset, Size, IsSigned, StorageSize, StorageOffset); -} - -CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D, - llvm::StructType *Ty) { - CGRecordLowering Builder(*this, D, /*Packed=*/false); - - Builder.lower(/*NonVirtualBaseType=*/false); - - // If we're in C++, compute the base subobject type. - llvm::StructType *BaseTy = nullptr; - if (isa<CXXRecordDecl>(D) && !D->isUnion() && !D->hasAttr<FinalAttr>()) { - BaseTy = Ty; - if (Builder.Layout.getNonVirtualSize() != Builder.Layout.getSize()) { - CGRecordLowering BaseBuilder(*this, D, /*Packed=*/Builder.Packed); - BaseBuilder.lower(/*NonVirtualBaseType=*/true); - BaseTy = llvm::StructType::create( - getLLVMContext(), BaseBuilder.FieldTypes, "", BaseBuilder.Packed); - addRecordTypeName(D, BaseTy, ".base"); - // BaseTy and Ty must agree on their packedness for getLLVMFieldNo to work - // on both of them with the same index. - assert(Builder.Packed == BaseBuilder.Packed && - "Non-virtual and complete types must agree on packedness"); - } - } - - // Fill in the struct *after* computing the base type. Filling in the body - // signifies that the type is no longer opaque and record layout is complete, - // but we may need to recursively layout D while laying D out as a base type. - Ty->setBody(Builder.FieldTypes, Builder.Packed); - - CGRecordLayout *RL = - new CGRecordLayout(Ty, BaseTy, Builder.IsZeroInitializable, - Builder.IsZeroInitializableAsBase); - - RL->NonVirtualBases.swap(Builder.NonVirtualBases); - RL->CompleteObjectVirtualBases.swap(Builder.VirtualBases); - - // Add all the field numbers. - RL->FieldInfo.swap(Builder.Fields); - - // Add bitfield info. - RL->BitFields.swap(Builder.BitFields); - - // Dump the layout, if requested. - if (getContext().getLangOpts().DumpRecordLayouts) { - llvm::outs() << "\n*** Dumping IRgen Record Layout\n"; - llvm::outs() << "Record: "; - D->dump(llvm::outs()); - llvm::outs() << "\nLayout: "; - RL->print(llvm::outs()); - } - -#ifndef NDEBUG - // Verify that the computed LLVM struct size matches the AST layout size. - const ASTRecordLayout &Layout = getContext().getASTRecordLayout(D); - - uint64_t TypeSizeInBits = getContext().toBits(Layout.getSize()); - assert(TypeSizeInBits == getDataLayout().getTypeAllocSizeInBits(Ty) && - "Type size mismatch!"); - - if (BaseTy) { - CharUnits NonVirtualSize = Layout.getNonVirtualSize(); - - uint64_t AlignedNonVirtualTypeSizeInBits = - getContext().toBits(NonVirtualSize); - - assert(AlignedNonVirtualTypeSizeInBits == - getDataLayout().getTypeAllocSizeInBits(BaseTy) && - "Type size mismatch!"); - } - - // Verify that the LLVM and AST field offsets agree. - llvm::StructType *ST = RL->getLLVMType(); - const llvm::StructLayout *SL = getDataLayout().getStructLayout(ST); - - const ASTRecordLayout &AST_RL = getContext().getASTRecordLayout(D); - RecordDecl::field_iterator it = D->field_begin(); - for (unsigned i = 0, e = AST_RL.getFieldCount(); i != e; ++i, ++it) { - const FieldDecl *FD = *it; - - // For non-bit-fields, just check that the LLVM struct offset matches the - // AST offset. - if (!FD->isBitField()) { - unsigned FieldNo = RL->getLLVMFieldNo(FD); - assert(AST_RL.getFieldOffset(i) == SL->getElementOffsetInBits(FieldNo) && - "Invalid field offset!"); - continue; - } - - // Ignore unnamed bit-fields. - if (!FD->getDeclName()) - continue; - - // Don't inspect zero-length bitfields. - if (FD->isZeroLengthBitField(getContext())) - continue; - - const CGBitFieldInfo &Info = RL->getBitFieldInfo(FD); - llvm::Type *ElementTy = ST->getTypeAtIndex(RL->getLLVMFieldNo(FD)); - - // Unions have overlapping elements dictating their layout, but for - // non-unions we can verify that this section of the layout is the exact - // expected size. - if (D->isUnion()) { - // For unions we verify that the start is zero and the size - // is in-bounds. However, on BE systems, the offset may be non-zero, but - // the size + offset should match the storage size in that case as it - // "starts" at the back. - if (getDataLayout().isBigEndian()) - assert(static_cast<unsigned>(Info.Offset + Info.Size) == - Info.StorageSize && - "Big endian union bitfield does not end at the back"); - else - assert(Info.Offset == 0 && - "Little endian union bitfield with a non-zero offset"); - assert(Info.StorageSize <= SL->getSizeInBits() && - "Union not large enough for bitfield storage"); - } else { - assert(Info.StorageSize == - getDataLayout().getTypeAllocSizeInBits(ElementTy) && - "Storage size does not match the element type size"); - } - assert(Info.Size > 0 && "Empty bitfield!"); - assert(static_cast<unsigned>(Info.Offset) + Info.Size <= Info.StorageSize && - "Bitfield outside of its allocated storage"); - } -#endif - - return RL; -} - -void CGRecordLayout::print(raw_ostream &OS) const { - OS << "<CGRecordLayout\n"; - OS << " LLVMType:" << *CompleteObjectType << "\n"; - if (BaseSubobjectType) - OS << " NonVirtualBaseLLVMType:" << *BaseSubobjectType << "\n"; - OS << " IsZeroInitializable:" << IsZeroInitializable << "\n"; - OS << " BitFields:[\n"; - - // Print bit-field infos in declaration order. - std::vector<std::pair<unsigned, const CGBitFieldInfo*> > BFIs; - for (llvm::DenseMap<const FieldDecl*, CGBitFieldInfo>::const_iterator - it = BitFields.begin(), ie = BitFields.end(); - it != ie; ++it) { - const RecordDecl *RD = it->first->getParent(); - unsigned Index = 0; - for (RecordDecl::field_iterator - it2 = RD->field_begin(); *it2 != it->first; ++it2) - ++Index; - BFIs.push_back(std::make_pair(Index, &it->second)); - } - llvm::array_pod_sort(BFIs.begin(), BFIs.end()); - for (unsigned i = 0, e = BFIs.size(); i != e; ++i) { - OS.indent(4); - BFIs[i].second->print(OS); - OS << "\n"; - } - - OS << "]>\n"; -} - -LLVM_DUMP_METHOD void CGRecordLayout::dump() const { - print(llvm::errs()); -} - -void CGBitFieldInfo::print(raw_ostream &OS) const { - OS << "<CGBitFieldInfo" - << " Offset:" << Offset - << " Size:" << Size - << " IsSigned:" << IsSigned - << " StorageSize:" << StorageSize - << " StorageOffset:" << StorageOffset.getQuantity() << ">"; -} - -LLVM_DUMP_METHOD void CGBitFieldInfo::dump() const { - print(llvm::errs()); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGStmt.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGStmt.cpp deleted file mode 100644 index b2b32759b6f..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGStmt.cpp +++ /dev/null @@ -1,2350 +0,0 @@ -//===--- CGStmt.cpp - Emit LLVM Code from Statements ----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code to emit Stmt nodes as LLVM code. -// -//===----------------------------------------------------------------------===// - -#include "CodeGenFunction.h" -#include "CGDebugInfo.h" -#include "CodeGenModule.h" -#include "TargetInfo.h" -#include "clang/AST/StmtVisitor.h" -#include "clang/Basic/Builtins.h" -#include "clang/Basic/PrettyStackTrace.h" -#include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/MDBuilder.h" - -using namespace clang; -using namespace CodeGen; - -//===----------------------------------------------------------------------===// -// Statement Emission -//===----------------------------------------------------------------------===// - -void CodeGenFunction::EmitStopPoint(const Stmt *S) { - if (CGDebugInfo *DI = getDebugInfo()) { - SourceLocation Loc; - Loc = S->getBeginLoc(); - DI->EmitLocation(Builder, Loc); - - LastStopPoint = Loc; - } -} - -void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) { - assert(S && "Null statement?"); - PGO.setCurrentStmt(S); - - // These statements have their own debug info handling. - if (EmitSimpleStmt(S)) - return; - - // Check if we are generating unreachable code. - if (!HaveInsertPoint()) { - // If so, and the statement doesn't contain a label, then we do not need to - // generate actual code. This is safe because (1) the current point is - // unreachable, so we don't need to execute the code, and (2) we've already - // handled the statements which update internal data structures (like the - // local variable map) which could be used by subsequent statements. - if (!ContainsLabel(S)) { - // Verify that any decl statements were handled as simple, they may be in - // scope of subsequent reachable statements. - assert(!isa<DeclStmt>(*S) && "Unexpected DeclStmt!"); - return; - } - - // Otherwise, make a new block to hold the code. - EnsureInsertPoint(); - } - - // Generate a stoppoint if we are emitting debug info. - EmitStopPoint(S); - - // Ignore all OpenMP directives except for simd if OpenMP with Simd is - // enabled. - if (getLangOpts().OpenMP && getLangOpts().OpenMPSimd) { - if (const auto *D = dyn_cast<OMPExecutableDirective>(S)) { - EmitSimpleOMPExecutableDirective(*D); - return; - } - } - - switch (S->getStmtClass()) { - case Stmt::NoStmtClass: - case Stmt::CXXCatchStmtClass: - case Stmt::SEHExceptStmtClass: - case Stmt::SEHFinallyStmtClass: - case Stmt::MSDependentExistsStmtClass: - llvm_unreachable("invalid statement class to emit generically"); - case Stmt::NullStmtClass: - case Stmt::CompoundStmtClass: - case Stmt::DeclStmtClass: - case Stmt::LabelStmtClass: - case Stmt::AttributedStmtClass: - case Stmt::GotoStmtClass: - case Stmt::BreakStmtClass: - case Stmt::ContinueStmtClass: - case Stmt::DefaultStmtClass: - case Stmt::CaseStmtClass: - case Stmt::SEHLeaveStmtClass: - llvm_unreachable("should have emitted these statements as simple"); - -#define STMT(Type, Base) -#define ABSTRACT_STMT(Op) -#define EXPR(Type, Base) \ - case Stmt::Type##Class: -#include "clang/AST/StmtNodes.inc" - { - // Remember the block we came in on. - llvm::BasicBlock *incoming = Builder.GetInsertBlock(); - assert(incoming && "expression emission must have an insertion point"); - - EmitIgnoredExpr(cast<Expr>(S)); - - llvm::BasicBlock *outgoing = Builder.GetInsertBlock(); - assert(outgoing && "expression emission cleared block!"); - - // The expression emitters assume (reasonably!) that the insertion - // point is always set. To maintain that, the call-emission code - // for noreturn functions has to enter a new block with no - // predecessors. We want to kill that block and mark the current - // insertion point unreachable in the common case of a call like - // "exit();". Since expression emission doesn't otherwise create - // blocks with no predecessors, we can just test for that. - // However, we must be careful not to do this to our incoming - // block, because *statement* emission does sometimes create - // reachable blocks which will have no predecessors until later in - // the function. This occurs with, e.g., labels that are not - // reachable by fallthrough. - if (incoming != outgoing && outgoing->use_empty()) { - outgoing->eraseFromParent(); - Builder.ClearInsertionPoint(); - } - break; - } - - case Stmt::IndirectGotoStmtClass: - EmitIndirectGotoStmt(cast<IndirectGotoStmt>(*S)); break; - - case Stmt::IfStmtClass: EmitIfStmt(cast<IfStmt>(*S)); break; - case Stmt::WhileStmtClass: EmitWhileStmt(cast<WhileStmt>(*S), Attrs); break; - case Stmt::DoStmtClass: EmitDoStmt(cast<DoStmt>(*S), Attrs); break; - case Stmt::ForStmtClass: EmitForStmt(cast<ForStmt>(*S), Attrs); break; - - case Stmt::ReturnStmtClass: EmitReturnStmt(cast<ReturnStmt>(*S)); break; - - case Stmt::SwitchStmtClass: EmitSwitchStmt(cast<SwitchStmt>(*S)); break; - case Stmt::GCCAsmStmtClass: // Intentional fall-through. - case Stmt::MSAsmStmtClass: EmitAsmStmt(cast<AsmStmt>(*S)); break; - case Stmt::CoroutineBodyStmtClass: - EmitCoroutineBody(cast<CoroutineBodyStmt>(*S)); - break; - case Stmt::CoreturnStmtClass: - EmitCoreturnStmt(cast<CoreturnStmt>(*S)); - break; - case Stmt::CapturedStmtClass: { - const CapturedStmt *CS = cast<CapturedStmt>(S); - EmitCapturedStmt(*CS, CS->getCapturedRegionKind()); - } - break; - case Stmt::ObjCAtTryStmtClass: - EmitObjCAtTryStmt(cast<ObjCAtTryStmt>(*S)); - break; - case Stmt::ObjCAtCatchStmtClass: - llvm_unreachable( - "@catch statements should be handled by EmitObjCAtTryStmt"); - case Stmt::ObjCAtFinallyStmtClass: - llvm_unreachable( - "@finally statements should be handled by EmitObjCAtTryStmt"); - case Stmt::ObjCAtThrowStmtClass: - EmitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(*S)); - break; - case Stmt::ObjCAtSynchronizedStmtClass: - EmitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(*S)); - break; - case Stmt::ObjCForCollectionStmtClass: - EmitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(*S)); - break; - case Stmt::ObjCAutoreleasePoolStmtClass: - EmitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(*S)); - break; - - case Stmt::CXXTryStmtClass: - EmitCXXTryStmt(cast<CXXTryStmt>(*S)); - break; - case Stmt::CXXForRangeStmtClass: - EmitCXXForRangeStmt(cast<CXXForRangeStmt>(*S), Attrs); - break; - case Stmt::SEHTryStmtClass: - EmitSEHTryStmt(cast<SEHTryStmt>(*S)); - break; - case Stmt::OMPParallelDirectiveClass: - EmitOMPParallelDirective(cast<OMPParallelDirective>(*S)); - break; - case Stmt::OMPSimdDirectiveClass: - EmitOMPSimdDirective(cast<OMPSimdDirective>(*S)); - break; - case Stmt::OMPForDirectiveClass: - EmitOMPForDirective(cast<OMPForDirective>(*S)); - break; - case Stmt::OMPForSimdDirectiveClass: - EmitOMPForSimdDirective(cast<OMPForSimdDirective>(*S)); - break; - case Stmt::OMPSectionsDirectiveClass: - EmitOMPSectionsDirective(cast<OMPSectionsDirective>(*S)); - break; - case Stmt::OMPSectionDirectiveClass: - EmitOMPSectionDirective(cast<OMPSectionDirective>(*S)); - break; - case Stmt::OMPSingleDirectiveClass: - EmitOMPSingleDirective(cast<OMPSingleDirective>(*S)); - break; - case Stmt::OMPMasterDirectiveClass: - EmitOMPMasterDirective(cast<OMPMasterDirective>(*S)); - break; - case Stmt::OMPCriticalDirectiveClass: - EmitOMPCriticalDirective(cast<OMPCriticalDirective>(*S)); - break; - case Stmt::OMPParallelForDirectiveClass: - EmitOMPParallelForDirective(cast<OMPParallelForDirective>(*S)); - break; - case Stmt::OMPParallelForSimdDirectiveClass: - EmitOMPParallelForSimdDirective(cast<OMPParallelForSimdDirective>(*S)); - break; - case Stmt::OMPParallelSectionsDirectiveClass: - EmitOMPParallelSectionsDirective(cast<OMPParallelSectionsDirective>(*S)); - break; - case Stmt::OMPTaskDirectiveClass: - EmitOMPTaskDirective(cast<OMPTaskDirective>(*S)); - break; - case Stmt::OMPTaskyieldDirectiveClass: - EmitOMPTaskyieldDirective(cast<OMPTaskyieldDirective>(*S)); - break; - case Stmt::OMPBarrierDirectiveClass: - EmitOMPBarrierDirective(cast<OMPBarrierDirective>(*S)); - break; - case Stmt::OMPTaskwaitDirectiveClass: - EmitOMPTaskwaitDirective(cast<OMPTaskwaitDirective>(*S)); - break; - case Stmt::OMPTaskgroupDirectiveClass: - EmitOMPTaskgroupDirective(cast<OMPTaskgroupDirective>(*S)); - break; - case Stmt::OMPFlushDirectiveClass: - EmitOMPFlushDirective(cast<OMPFlushDirective>(*S)); - break; - case Stmt::OMPOrderedDirectiveClass: - EmitOMPOrderedDirective(cast<OMPOrderedDirective>(*S)); - break; - case Stmt::OMPAtomicDirectiveClass: - EmitOMPAtomicDirective(cast<OMPAtomicDirective>(*S)); - break; - case Stmt::OMPTargetDirectiveClass: - EmitOMPTargetDirective(cast<OMPTargetDirective>(*S)); - break; - case Stmt::OMPTeamsDirectiveClass: - EmitOMPTeamsDirective(cast<OMPTeamsDirective>(*S)); - break; - case Stmt::OMPCancellationPointDirectiveClass: - EmitOMPCancellationPointDirective(cast<OMPCancellationPointDirective>(*S)); - break; - case Stmt::OMPCancelDirectiveClass: - EmitOMPCancelDirective(cast<OMPCancelDirective>(*S)); - break; - case Stmt::OMPTargetDataDirectiveClass: - EmitOMPTargetDataDirective(cast<OMPTargetDataDirective>(*S)); - break; - case Stmt::OMPTargetEnterDataDirectiveClass: - EmitOMPTargetEnterDataDirective(cast<OMPTargetEnterDataDirective>(*S)); - break; - case Stmt::OMPTargetExitDataDirectiveClass: - EmitOMPTargetExitDataDirective(cast<OMPTargetExitDataDirective>(*S)); - break; - case Stmt::OMPTargetParallelDirectiveClass: - EmitOMPTargetParallelDirective(cast<OMPTargetParallelDirective>(*S)); - break; - case Stmt::OMPTargetParallelForDirectiveClass: - EmitOMPTargetParallelForDirective(cast<OMPTargetParallelForDirective>(*S)); - break; - case Stmt::OMPTaskLoopDirectiveClass: - EmitOMPTaskLoopDirective(cast<OMPTaskLoopDirective>(*S)); - break; - case Stmt::OMPTaskLoopSimdDirectiveClass: - EmitOMPTaskLoopSimdDirective(cast<OMPTaskLoopSimdDirective>(*S)); - break; - case Stmt::OMPDistributeDirectiveClass: - EmitOMPDistributeDirective(cast<OMPDistributeDirective>(*S)); - break; - case Stmt::OMPTargetUpdateDirectiveClass: - EmitOMPTargetUpdateDirective(cast<OMPTargetUpdateDirective>(*S)); - break; - case Stmt::OMPDistributeParallelForDirectiveClass: - EmitOMPDistributeParallelForDirective( - cast<OMPDistributeParallelForDirective>(*S)); - break; - case Stmt::OMPDistributeParallelForSimdDirectiveClass: - EmitOMPDistributeParallelForSimdDirective( - cast<OMPDistributeParallelForSimdDirective>(*S)); - break; - case Stmt::OMPDistributeSimdDirectiveClass: - EmitOMPDistributeSimdDirective(cast<OMPDistributeSimdDirective>(*S)); - break; - case Stmt::OMPTargetParallelForSimdDirectiveClass: - EmitOMPTargetParallelForSimdDirective( - cast<OMPTargetParallelForSimdDirective>(*S)); - break; - case Stmt::OMPTargetSimdDirectiveClass: - EmitOMPTargetSimdDirective(cast<OMPTargetSimdDirective>(*S)); - break; - case Stmt::OMPTeamsDistributeDirectiveClass: - EmitOMPTeamsDistributeDirective(cast<OMPTeamsDistributeDirective>(*S)); - break; - case Stmt::OMPTeamsDistributeSimdDirectiveClass: - EmitOMPTeamsDistributeSimdDirective( - cast<OMPTeamsDistributeSimdDirective>(*S)); - break; - case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass: - EmitOMPTeamsDistributeParallelForSimdDirective( - cast<OMPTeamsDistributeParallelForSimdDirective>(*S)); - break; - case Stmt::OMPTeamsDistributeParallelForDirectiveClass: - EmitOMPTeamsDistributeParallelForDirective( - cast<OMPTeamsDistributeParallelForDirective>(*S)); - break; - case Stmt::OMPTargetTeamsDirectiveClass: - EmitOMPTargetTeamsDirective(cast<OMPTargetTeamsDirective>(*S)); - break; - case Stmt::OMPTargetTeamsDistributeDirectiveClass: - EmitOMPTargetTeamsDistributeDirective( - cast<OMPTargetTeamsDistributeDirective>(*S)); - break; - case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass: - EmitOMPTargetTeamsDistributeParallelForDirective( - cast<OMPTargetTeamsDistributeParallelForDirective>(*S)); - break; - case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass: - EmitOMPTargetTeamsDistributeParallelForSimdDirective( - cast<OMPTargetTeamsDistributeParallelForSimdDirective>(*S)); - break; - case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass: - EmitOMPTargetTeamsDistributeSimdDirective( - cast<OMPTargetTeamsDistributeSimdDirective>(*S)); - break; - } -} - -bool CodeGenFunction::EmitSimpleStmt(const Stmt *S) { - switch (S->getStmtClass()) { - default: return false; - case Stmt::NullStmtClass: break; - case Stmt::CompoundStmtClass: EmitCompoundStmt(cast<CompoundStmt>(*S)); break; - case Stmt::DeclStmtClass: EmitDeclStmt(cast<DeclStmt>(*S)); break; - case Stmt::LabelStmtClass: EmitLabelStmt(cast<LabelStmt>(*S)); break; - case Stmt::AttributedStmtClass: - EmitAttributedStmt(cast<AttributedStmt>(*S)); break; - case Stmt::GotoStmtClass: EmitGotoStmt(cast<GotoStmt>(*S)); break; - case Stmt::BreakStmtClass: EmitBreakStmt(cast<BreakStmt>(*S)); break; - case Stmt::ContinueStmtClass: EmitContinueStmt(cast<ContinueStmt>(*S)); break; - case Stmt::DefaultStmtClass: EmitDefaultStmt(cast<DefaultStmt>(*S)); break; - case Stmt::CaseStmtClass: EmitCaseStmt(cast<CaseStmt>(*S)); break; - case Stmt::SEHLeaveStmtClass: EmitSEHLeaveStmt(cast<SEHLeaveStmt>(*S)); break; - } - - return true; -} - -/// EmitCompoundStmt - Emit a compound statement {..} node. If GetLast is true, -/// this captures the expression result of the last sub-statement and returns it -/// (for use by the statement expression extension). -Address CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast, - AggValueSlot AggSlot) { - PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),S.getLBracLoc(), - "LLVM IR generation of compound statement ('{}')"); - - // Keep track of the current cleanup stack depth, including debug scopes. - LexicalScope Scope(*this, S.getSourceRange()); - - return EmitCompoundStmtWithoutScope(S, GetLast, AggSlot); -} - -Address -CodeGenFunction::EmitCompoundStmtWithoutScope(const CompoundStmt &S, - bool GetLast, - AggValueSlot AggSlot) { - - for (CompoundStmt::const_body_iterator I = S.body_begin(), - E = S.body_end()-GetLast; I != E; ++I) - EmitStmt(*I); - - Address RetAlloca = Address::invalid(); - if (GetLast) { - // We have to special case labels here. They are statements, but when put - // at the end of a statement expression, they yield the value of their - // subexpression. Handle this by walking through all labels we encounter, - // emitting them before we evaluate the subexpr. - const Stmt *LastStmt = S.body_back(); - while (const LabelStmt *LS = dyn_cast<LabelStmt>(LastStmt)) { - EmitLabel(LS->getDecl()); - LastStmt = LS->getSubStmt(); - } - - EnsureInsertPoint(); - - QualType ExprTy = cast<Expr>(LastStmt)->getType(); - if (hasAggregateEvaluationKind(ExprTy)) { - EmitAggExpr(cast<Expr>(LastStmt), AggSlot); - } else { - // We can't return an RValue here because there might be cleanups at - // the end of the StmtExpr. Because of that, we have to emit the result - // here into a temporary alloca. - RetAlloca = CreateMemTemp(ExprTy); - EmitAnyExprToMem(cast<Expr>(LastStmt), RetAlloca, Qualifiers(), - /*IsInit*/false); - } - - } - - return RetAlloca; -} - -void CodeGenFunction::SimplifyForwardingBlocks(llvm::BasicBlock *BB) { - llvm::BranchInst *BI = dyn_cast<llvm::BranchInst>(BB->getTerminator()); - - // If there is a cleanup stack, then we it isn't worth trying to - // simplify this block (we would need to remove it from the scope map - // and cleanup entry). - if (!EHStack.empty()) - return; - - // Can only simplify direct branches. - if (!BI || !BI->isUnconditional()) - return; - - // Can only simplify empty blocks. - if (BI->getIterator() != BB->begin()) - return; - - BB->replaceAllUsesWith(BI->getSuccessor(0)); - BI->eraseFromParent(); - BB->eraseFromParent(); -} - -void CodeGenFunction::EmitBlock(llvm::BasicBlock *BB, bool IsFinished) { - llvm::BasicBlock *CurBB = Builder.GetInsertBlock(); - - // Fall out of the current block (if necessary). - EmitBranch(BB); - - if (IsFinished && BB->use_empty()) { - delete BB; - return; - } - - // Place the block after the current block, if possible, or else at - // the end of the function. - if (CurBB && CurBB->getParent()) - CurFn->getBasicBlockList().insertAfter(CurBB->getIterator(), BB); - else - CurFn->getBasicBlockList().push_back(BB); - Builder.SetInsertPoint(BB); -} - -void CodeGenFunction::EmitBranch(llvm::BasicBlock *Target) { - // Emit a branch from the current block to the target one if this - // was a real block. If this was just a fall-through block after a - // terminator, don't emit it. - llvm::BasicBlock *CurBB = Builder.GetInsertBlock(); - - if (!CurBB || CurBB->getTerminator()) { - // If there is no insert point or the previous block is already - // terminated, don't touch it. - } else { - // Otherwise, create a fall-through branch. - Builder.CreateBr(Target); - } - - Builder.ClearInsertionPoint(); -} - -void CodeGenFunction::EmitBlockAfterUses(llvm::BasicBlock *block) { - bool inserted = false; - for (llvm::User *u : block->users()) { - if (llvm::Instruction *insn = dyn_cast<llvm::Instruction>(u)) { - CurFn->getBasicBlockList().insertAfter(insn->getParent()->getIterator(), - block); - inserted = true; - break; - } - } - - if (!inserted) - CurFn->getBasicBlockList().push_back(block); - - Builder.SetInsertPoint(block); -} - -CodeGenFunction::JumpDest -CodeGenFunction::getJumpDestForLabel(const LabelDecl *D) { - JumpDest &Dest = LabelMap[D]; - if (Dest.isValid()) return Dest; - - // Create, but don't insert, the new block. - Dest = JumpDest(createBasicBlock(D->getName()), - EHScopeStack::stable_iterator::invalid(), - NextCleanupDestIndex++); - return Dest; -} - -void CodeGenFunction::EmitLabel(const LabelDecl *D) { - // Add this label to the current lexical scope if we're within any - // normal cleanups. Jumps "in" to this label --- when permitted by - // the language --- may need to be routed around such cleanups. - if (EHStack.hasNormalCleanups() && CurLexicalScope) - CurLexicalScope->addLabel(D); - - JumpDest &Dest = LabelMap[D]; - - // If we didn't need a forward reference to this label, just go - // ahead and create a destination at the current scope. - if (!Dest.isValid()) { - Dest = getJumpDestInCurrentScope(D->getName()); - - // Otherwise, we need to give this label a target depth and remove - // it from the branch-fixups list. - } else { - assert(!Dest.getScopeDepth().isValid() && "already emitted label!"); - Dest.setScopeDepth(EHStack.stable_begin()); - ResolveBranchFixups(Dest.getBlock()); - } - - EmitBlock(Dest.getBlock()); - incrementProfileCounter(D->getStmt()); -} - -/// Change the cleanup scope of the labels in this lexical scope to -/// match the scope of the enclosing context. -void CodeGenFunction::LexicalScope::rescopeLabels() { - assert(!Labels.empty()); - EHScopeStack::stable_iterator innermostScope - = CGF.EHStack.getInnermostNormalCleanup(); - - // Change the scope depth of all the labels. - for (SmallVectorImpl<const LabelDecl*>::const_iterator - i = Labels.begin(), e = Labels.end(); i != e; ++i) { - assert(CGF.LabelMap.count(*i)); - JumpDest &dest = CGF.LabelMap.find(*i)->second; - assert(dest.getScopeDepth().isValid()); - assert(innermostScope.encloses(dest.getScopeDepth())); - dest.setScopeDepth(innermostScope); - } - - // Reparent the labels if the new scope also has cleanups. - if (innermostScope != EHScopeStack::stable_end() && ParentScope) { - ParentScope->Labels.append(Labels.begin(), Labels.end()); - } -} - - -void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) { - EmitLabel(S.getDecl()); - EmitStmt(S.getSubStmt()); -} - -void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) { - EmitStmt(S.getSubStmt(), S.getAttrs()); -} - -void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) { - // If this code is reachable then emit a stop point (if generating - // debug info). We have to do this ourselves because we are on the - // "simple" statement path. - if (HaveInsertPoint()) - EmitStopPoint(&S); - - EmitBranchThroughCleanup(getJumpDestForLabel(S.getLabel())); -} - - -void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) { - if (const LabelDecl *Target = S.getConstantTarget()) { - EmitBranchThroughCleanup(getJumpDestForLabel(Target)); - return; - } - - // Ensure that we have an i8* for our PHI node. - llvm::Value *V = Builder.CreateBitCast(EmitScalarExpr(S.getTarget()), - Int8PtrTy, "addr"); - llvm::BasicBlock *CurBB = Builder.GetInsertBlock(); - - // Get the basic block for the indirect goto. - llvm::BasicBlock *IndGotoBB = GetIndirectGotoBlock(); - - // The first instruction in the block has to be the PHI for the switch dest, - // add an entry for this branch. - cast<llvm::PHINode>(IndGotoBB->begin())->addIncoming(V, CurBB); - - EmitBranch(IndGotoBB); -} - -void CodeGenFunction::EmitIfStmt(const IfStmt &S) { - // C99 6.8.4.1: The first substatement is executed if the expression compares - // unequal to 0. The condition must be a scalar type. - LexicalScope ConditionScope(*this, S.getCond()->getSourceRange()); - - if (S.getInit()) - EmitStmt(S.getInit()); - - if (S.getConditionVariable()) - EmitDecl(*S.getConditionVariable()); - - // If the condition constant folds and can be elided, try to avoid emitting - // the condition and the dead arm of the if/else. - bool CondConstant; - if (ConstantFoldsToSimpleInteger(S.getCond(), CondConstant, - S.isConstexpr())) { - // Figure out which block (then or else) is executed. - const Stmt *Executed = S.getThen(); - const Stmt *Skipped = S.getElse(); - if (!CondConstant) // Condition false? - std::swap(Executed, Skipped); - - // If the skipped block has no labels in it, just emit the executed block. - // This avoids emitting dead code and simplifies the CFG substantially. - if (S.isConstexpr() || !ContainsLabel(Skipped)) { - if (CondConstant) - incrementProfileCounter(&S); - if (Executed) { - RunCleanupsScope ExecutedScope(*this); - EmitStmt(Executed); - } - return; - } - } - - // Otherwise, the condition did not fold, or we couldn't elide it. Just emit - // the conditional branch. - llvm::BasicBlock *ThenBlock = createBasicBlock("if.then"); - llvm::BasicBlock *ContBlock = createBasicBlock("if.end"); - llvm::BasicBlock *ElseBlock = ContBlock; - if (S.getElse()) - ElseBlock = createBasicBlock("if.else"); - - EmitBranchOnBoolExpr(S.getCond(), ThenBlock, ElseBlock, - getProfileCount(S.getThen())); - - // Emit the 'then' code. - EmitBlock(ThenBlock); - incrementProfileCounter(&S); - { - RunCleanupsScope ThenScope(*this); - EmitStmt(S.getThen()); - } - EmitBranch(ContBlock); - - // Emit the 'else' code if present. - if (const Stmt *Else = S.getElse()) { - { - // There is no need to emit line number for an unconditional branch. - auto NL = ApplyDebugLocation::CreateEmpty(*this); - EmitBlock(ElseBlock); - } - { - RunCleanupsScope ElseScope(*this); - EmitStmt(Else); - } - { - // There is no need to emit line number for an unconditional branch. - auto NL = ApplyDebugLocation::CreateEmpty(*this); - EmitBranch(ContBlock); - } - } - - // Emit the continuation block for code after the if. - EmitBlock(ContBlock, true); -} - -void CodeGenFunction::EmitWhileStmt(const WhileStmt &S, - ArrayRef<const Attr *> WhileAttrs) { - // Emit the header for the loop, which will also become - // the continue target. - JumpDest LoopHeader = getJumpDestInCurrentScope("while.cond"); - EmitBlock(LoopHeader.getBlock()); - - const SourceRange &R = S.getSourceRange(); - LoopStack.push(LoopHeader.getBlock(), CGM.getContext(), WhileAttrs, - SourceLocToDebugLoc(R.getBegin()), - SourceLocToDebugLoc(R.getEnd())); - - // Create an exit block for when the condition fails, which will - // also become the break target. - JumpDest LoopExit = getJumpDestInCurrentScope("while.end"); - - // Store the blocks to use for break and continue. - BreakContinueStack.push_back(BreakContinue(LoopExit, LoopHeader)); - - // C++ [stmt.while]p2: - // When the condition of a while statement is a declaration, the - // scope of the variable that is declared extends from its point - // of declaration (3.3.2) to the end of the while statement. - // [...] - // The object created in a condition is destroyed and created - // with each iteration of the loop. - RunCleanupsScope ConditionScope(*this); - - if (S.getConditionVariable()) - EmitDecl(*S.getConditionVariable()); - - // Evaluate the conditional in the while header. C99 6.8.5.1: The - // evaluation of the controlling expression takes place before each - // execution of the loop body. - llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond()); - - // while(1) is common, avoid extra exit blocks. Be sure - // to correctly handle break/continue though. - bool EmitBoolCondBranch = true; - if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) - if (C->isOne()) - EmitBoolCondBranch = false; - - // As long as the condition is true, go to the loop body. - llvm::BasicBlock *LoopBody = createBasicBlock("while.body"); - if (EmitBoolCondBranch) { - llvm::BasicBlock *ExitBlock = LoopExit.getBlock(); - if (ConditionScope.requiresCleanups()) - ExitBlock = createBasicBlock("while.exit"); - Builder.CreateCondBr( - BoolCondVal, LoopBody, ExitBlock, - createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody()))); - - if (ExitBlock != LoopExit.getBlock()) { - EmitBlock(ExitBlock); - EmitBranchThroughCleanup(LoopExit); - } - } - - // Emit the loop body. We have to emit this in a cleanup scope - // because it might be a singleton DeclStmt. - { - RunCleanupsScope BodyScope(*this); - EmitBlock(LoopBody); - incrementProfileCounter(&S); - EmitStmt(S.getBody()); - } - - BreakContinueStack.pop_back(); - - // Immediately force cleanup. - ConditionScope.ForceCleanup(); - - EmitStopPoint(&S); - // Branch to the loop header again. - EmitBranch(LoopHeader.getBlock()); - - LoopStack.pop(); - - // Emit the exit block. - EmitBlock(LoopExit.getBlock(), true); - - // The LoopHeader typically is just a branch if we skipped emitting - // a branch, try to erase it. - if (!EmitBoolCondBranch) - SimplifyForwardingBlocks(LoopHeader.getBlock()); -} - -void CodeGenFunction::EmitDoStmt(const DoStmt &S, - ArrayRef<const Attr *> DoAttrs) { - JumpDest LoopExit = getJumpDestInCurrentScope("do.end"); - JumpDest LoopCond = getJumpDestInCurrentScope("do.cond"); - - uint64_t ParentCount = getCurrentProfileCount(); - - // Store the blocks to use for break and continue. - BreakContinueStack.push_back(BreakContinue(LoopExit, LoopCond)); - - // Emit the body of the loop. - llvm::BasicBlock *LoopBody = createBasicBlock("do.body"); - - EmitBlockWithFallThrough(LoopBody, &S); - { - RunCleanupsScope BodyScope(*this); - EmitStmt(S.getBody()); - } - - EmitBlock(LoopCond.getBlock()); - - const SourceRange &R = S.getSourceRange(); - LoopStack.push(LoopBody, CGM.getContext(), DoAttrs, - SourceLocToDebugLoc(R.getBegin()), - SourceLocToDebugLoc(R.getEnd())); - - // C99 6.8.5.2: "The evaluation of the controlling expression takes place - // after each execution of the loop body." - - // Evaluate the conditional in the while header. - // C99 6.8.5p2/p4: The first substatement is executed if the expression - // compares unequal to 0. The condition must be a scalar type. - llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond()); - - BreakContinueStack.pop_back(); - - // "do {} while (0)" is common in macros, avoid extra blocks. Be sure - // to correctly handle break/continue though. - bool EmitBoolCondBranch = true; - if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) - if (C->isZero()) - EmitBoolCondBranch = false; - - // As long as the condition is true, iterate the loop. - if (EmitBoolCondBranch) { - uint64_t BackedgeCount = getProfileCount(S.getBody()) - ParentCount; - Builder.CreateCondBr( - BoolCondVal, LoopBody, LoopExit.getBlock(), - createProfileWeightsForLoop(S.getCond(), BackedgeCount)); - } - - LoopStack.pop(); - - // Emit the exit block. - EmitBlock(LoopExit.getBlock()); - - // The DoCond block typically is just a branch if we skipped - // emitting a branch, try to erase it. - if (!EmitBoolCondBranch) - SimplifyForwardingBlocks(LoopCond.getBlock()); -} - -void CodeGenFunction::EmitForStmt(const ForStmt &S, - ArrayRef<const Attr *> ForAttrs) { - JumpDest LoopExit = getJumpDestInCurrentScope("for.end"); - - LexicalScope ForScope(*this, S.getSourceRange()); - - // Evaluate the first part before the loop. - if (S.getInit()) - EmitStmt(S.getInit()); - - // Start the loop with a block that tests the condition. - // If there's an increment, the continue scope will be overwritten - // later. - JumpDest Continue = getJumpDestInCurrentScope("for.cond"); - llvm::BasicBlock *CondBlock = Continue.getBlock(); - EmitBlock(CondBlock); - - const SourceRange &R = S.getSourceRange(); - LoopStack.push(CondBlock, CGM.getContext(), ForAttrs, - SourceLocToDebugLoc(R.getBegin()), - SourceLocToDebugLoc(R.getEnd())); - - // If the for loop doesn't have an increment we can just use the - // condition as the continue block. Otherwise we'll need to create - // a block for it (in the current scope, i.e. in the scope of the - // condition), and that we will become our continue block. - if (S.getInc()) - Continue = getJumpDestInCurrentScope("for.inc"); - - // Store the blocks to use for break and continue. - BreakContinueStack.push_back(BreakContinue(LoopExit, Continue)); - - // Create a cleanup scope for the condition variable cleanups. - LexicalScope ConditionScope(*this, S.getSourceRange()); - - if (S.getCond()) { - // If the for statement has a condition scope, emit the local variable - // declaration. - if (S.getConditionVariable()) { - EmitDecl(*S.getConditionVariable()); - } - - llvm::BasicBlock *ExitBlock = LoopExit.getBlock(); - // If there are any cleanups between here and the loop-exit scope, - // create a block to stage a loop exit along. - if (ForScope.requiresCleanups()) - ExitBlock = createBasicBlock("for.cond.cleanup"); - - // As long as the condition is true, iterate the loop. - llvm::BasicBlock *ForBody = createBasicBlock("for.body"); - - // C99 6.8.5p2/p4: The first substatement is executed if the expression - // compares unequal to 0. The condition must be a scalar type. - llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond()); - Builder.CreateCondBr( - BoolCondVal, ForBody, ExitBlock, - createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody()))); - - if (ExitBlock != LoopExit.getBlock()) { - EmitBlock(ExitBlock); - EmitBranchThroughCleanup(LoopExit); - } - - EmitBlock(ForBody); - } else { - // Treat it as a non-zero constant. Don't even create a new block for the - // body, just fall into it. - } - incrementProfileCounter(&S); - - { - // Create a separate cleanup scope for the body, in case it is not - // a compound statement. - RunCleanupsScope BodyScope(*this); - EmitStmt(S.getBody()); - } - - // If there is an increment, emit it next. - if (S.getInc()) { - EmitBlock(Continue.getBlock()); - EmitStmt(S.getInc()); - } - - BreakContinueStack.pop_back(); - - ConditionScope.ForceCleanup(); - - EmitStopPoint(&S); - EmitBranch(CondBlock); - - ForScope.ForceCleanup(); - - LoopStack.pop(); - - // Emit the fall-through block. - EmitBlock(LoopExit.getBlock(), true); -} - -void -CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S, - ArrayRef<const Attr *> ForAttrs) { - JumpDest LoopExit = getJumpDestInCurrentScope("for.end"); - - LexicalScope ForScope(*this, S.getSourceRange()); - - // Evaluate the first pieces before the loop. - if (S.getInit()) - EmitStmt(S.getInit()); - EmitStmt(S.getRangeStmt()); - EmitStmt(S.getBeginStmt()); - EmitStmt(S.getEndStmt()); - - // Start the loop with a block that tests the condition. - // If there's an increment, the continue scope will be overwritten - // later. - llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); - EmitBlock(CondBlock); - - const SourceRange &R = S.getSourceRange(); - LoopStack.push(CondBlock, CGM.getContext(), ForAttrs, - SourceLocToDebugLoc(R.getBegin()), - SourceLocToDebugLoc(R.getEnd())); - - // If there are any cleanups between here and the loop-exit scope, - // create a block to stage a loop exit along. - llvm::BasicBlock *ExitBlock = LoopExit.getBlock(); - if (ForScope.requiresCleanups()) - ExitBlock = createBasicBlock("for.cond.cleanup"); - - // The loop body, consisting of the specified body and the loop variable. - llvm::BasicBlock *ForBody = createBasicBlock("for.body"); - - // The body is executed if the expression, contextually converted - // to bool, is true. - llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond()); - Builder.CreateCondBr( - BoolCondVal, ForBody, ExitBlock, - createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody()))); - - if (ExitBlock != LoopExit.getBlock()) { - EmitBlock(ExitBlock); - EmitBranchThroughCleanup(LoopExit); - } - - EmitBlock(ForBody); - incrementProfileCounter(&S); - - // Create a block for the increment. In case of a 'continue', we jump there. - JumpDest Continue = getJumpDestInCurrentScope("for.inc"); - - // Store the blocks to use for break and continue. - BreakContinueStack.push_back(BreakContinue(LoopExit, Continue)); - - { - // Create a separate cleanup scope for the loop variable and body. - LexicalScope BodyScope(*this, S.getSourceRange()); - EmitStmt(S.getLoopVarStmt()); - EmitStmt(S.getBody()); - } - - EmitStopPoint(&S); - // If there is an increment, emit it next. - EmitBlock(Continue.getBlock()); - EmitStmt(S.getInc()); - - BreakContinueStack.pop_back(); - - EmitBranch(CondBlock); - - ForScope.ForceCleanup(); - - LoopStack.pop(); - - // Emit the fall-through block. - EmitBlock(LoopExit.getBlock(), true); -} - -void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) { - if (RV.isScalar()) { - Builder.CreateStore(RV.getScalarVal(), ReturnValue); - } else if (RV.isAggregate()) { - LValue Dest = MakeAddrLValue(ReturnValue, Ty); - LValue Src = MakeAddrLValue(RV.getAggregateAddress(), Ty); - EmitAggregateCopy(Dest, Src, Ty, overlapForReturnValue()); - } else { - EmitStoreOfComplex(RV.getComplexVal(), MakeAddrLValue(ReturnValue, Ty), - /*init*/ true); - } - EmitBranchThroughCleanup(ReturnBlock); -} - -/// EmitReturnStmt - Note that due to GCC extensions, this can have an operand -/// if the function returns void, or may be missing one if the function returns -/// non-void. Fun stuff :). -void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { - if (requiresReturnValueCheck()) { - llvm::Constant *SLoc = EmitCheckSourceLocation(S.getBeginLoc()); - auto *SLocPtr = - new llvm::GlobalVariable(CGM.getModule(), SLoc->getType(), false, - llvm::GlobalVariable::PrivateLinkage, SLoc); - SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - CGM.getSanitizerMetadata()->disableSanitizerForGlobal(SLocPtr); - assert(ReturnLocation.isValid() && "No valid return location"); - Builder.CreateStore(Builder.CreateBitCast(SLocPtr, Int8PtrTy), - ReturnLocation); - } - - // Returning from an outlined SEH helper is UB, and we already warn on it. - if (IsOutlinedSEHHelper) { - Builder.CreateUnreachable(); - Builder.ClearInsertionPoint(); - } - - // Emit the result value, even if unused, to evaluate the side effects. - const Expr *RV = S.getRetValue(); - - // Treat block literals in a return expression as if they appeared - // in their own scope. This permits a small, easily-implemented - // exception to our over-conservative rules about not jumping to - // statements following block literals with non-trivial cleanups. - RunCleanupsScope cleanupScope(*this); - if (const FullExpr *fe = dyn_cast_or_null<FullExpr>(RV)) { - enterFullExpression(fe); - RV = fe->getSubExpr(); - } - - // FIXME: Clean this up by using an LValue for ReturnTemp, - // EmitStoreThroughLValue, and EmitAnyExpr. - if (getLangOpts().ElideConstructors && - S.getNRVOCandidate() && S.getNRVOCandidate()->isNRVOVariable()) { - // Apply the named return value optimization for this return statement, - // which means doing nothing: the appropriate result has already been - // constructed into the NRVO variable. - - // If there is an NRVO flag for this variable, set it to 1 into indicate - // that the cleanup code should not destroy the variable. - if (llvm::Value *NRVOFlag = NRVOFlags[S.getNRVOCandidate()]) - Builder.CreateFlagStore(Builder.getTrue(), NRVOFlag); - } else if (!ReturnValue.isValid() || (RV && RV->getType()->isVoidType())) { - // Make sure not to return anything, but evaluate the expression - // for side effects. - if (RV) - EmitAnyExpr(RV); - } else if (!RV) { - // Do nothing (return value is left uninitialized) - } else if (FnRetTy->isReferenceType()) { - // If this function returns a reference, take the address of the expression - // rather than the value. - RValue Result = EmitReferenceBindingToExpr(RV); - Builder.CreateStore(Result.getScalarVal(), ReturnValue); - } else { - switch (getEvaluationKind(RV->getType())) { - case TEK_Scalar: - Builder.CreateStore(EmitScalarExpr(RV), ReturnValue); - break; - case TEK_Complex: - EmitComplexExprIntoLValue(RV, MakeAddrLValue(ReturnValue, RV->getType()), - /*isInit*/ true); - break; - case TEK_Aggregate: - EmitAggExpr(RV, AggValueSlot::forAddr( - ReturnValue, Qualifiers(), - AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - overlapForReturnValue())); - break; - } - } - - ++NumReturnExprs; - if (!RV || RV->isEvaluatable(getContext())) - ++NumSimpleReturnExprs; - - cleanupScope.ForceCleanup(); - EmitBranchThroughCleanup(ReturnBlock); -} - -void CodeGenFunction::EmitDeclStmt(const DeclStmt &S) { - // As long as debug info is modeled with instructions, we have to ensure we - // have a place to insert here and write the stop point here. - if (HaveInsertPoint()) - EmitStopPoint(&S); - - for (const auto *I : S.decls()) - EmitDecl(*I); -} - -void CodeGenFunction::EmitBreakStmt(const BreakStmt &S) { - assert(!BreakContinueStack.empty() && "break stmt not in a loop or switch!"); - - // If this code is reachable then emit a stop point (if generating - // debug info). We have to do this ourselves because we are on the - // "simple" statement path. - if (HaveInsertPoint()) - EmitStopPoint(&S); - - EmitBranchThroughCleanup(BreakContinueStack.back().BreakBlock); -} - -void CodeGenFunction::EmitContinueStmt(const ContinueStmt &S) { - assert(!BreakContinueStack.empty() && "continue stmt not in a loop!"); - - // If this code is reachable then emit a stop point (if generating - // debug info). We have to do this ourselves because we are on the - // "simple" statement path. - if (HaveInsertPoint()) - EmitStopPoint(&S); - - EmitBranchThroughCleanup(BreakContinueStack.back().ContinueBlock); -} - -/// EmitCaseStmtRange - If case statement range is not too big then -/// add multiple cases to switch instruction, one for each value within -/// the range. If range is too big then emit "if" condition check. -void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) { - assert(S.getRHS() && "Expected RHS value in CaseStmt"); - - llvm::APSInt LHS = S.getLHS()->EvaluateKnownConstInt(getContext()); - llvm::APSInt RHS = S.getRHS()->EvaluateKnownConstInt(getContext()); - - // Emit the code for this case. We do this first to make sure it is - // properly chained from our predecessor before generating the - // switch machinery to enter this block. - llvm::BasicBlock *CaseDest = createBasicBlock("sw.bb"); - EmitBlockWithFallThrough(CaseDest, &S); - EmitStmt(S.getSubStmt()); - - // If range is empty, do nothing. - if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS)) - return; - - llvm::APInt Range = RHS - LHS; - // FIXME: parameters such as this should not be hardcoded. - if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) { - // Range is small enough to add multiple switch instruction cases. - uint64_t Total = getProfileCount(&S); - unsigned NCases = Range.getZExtValue() + 1; - // We only have one region counter for the entire set of cases here, so we - // need to divide the weights evenly between the generated cases, ensuring - // that the total weight is preserved. E.g., a weight of 5 over three cases - // will be distributed as weights of 2, 2, and 1. - uint64_t Weight = Total / NCases, Rem = Total % NCases; - for (unsigned I = 0; I != NCases; ++I) { - if (SwitchWeights) - SwitchWeights->push_back(Weight + (Rem ? 1 : 0)); - if (Rem) - Rem--; - SwitchInsn->addCase(Builder.getInt(LHS), CaseDest); - ++LHS; - } - return; - } - - // The range is too big. Emit "if" condition into a new block, - // making sure to save and restore the current insertion point. - llvm::BasicBlock *RestoreBB = Builder.GetInsertBlock(); - - // Push this test onto the chain of range checks (which terminates - // in the default basic block). The switch's default will be changed - // to the top of this chain after switch emission is complete. - llvm::BasicBlock *FalseDest = CaseRangeBlock; - CaseRangeBlock = createBasicBlock("sw.caserange"); - - CurFn->getBasicBlockList().push_back(CaseRangeBlock); - Builder.SetInsertPoint(CaseRangeBlock); - - // Emit range check. - llvm::Value *Diff = - Builder.CreateSub(SwitchInsn->getCondition(), Builder.getInt(LHS)); - llvm::Value *Cond = - Builder.CreateICmpULE(Diff, Builder.getInt(Range), "inbounds"); - - llvm::MDNode *Weights = nullptr; - if (SwitchWeights) { - uint64_t ThisCount = getProfileCount(&S); - uint64_t DefaultCount = (*SwitchWeights)[0]; - Weights = createProfileWeights(ThisCount, DefaultCount); - - // Since we're chaining the switch default through each large case range, we - // need to update the weight for the default, ie, the first case, to include - // this case. - (*SwitchWeights)[0] += ThisCount; - } - Builder.CreateCondBr(Cond, CaseDest, FalseDest, Weights); - - // Restore the appropriate insertion point. - if (RestoreBB) - Builder.SetInsertPoint(RestoreBB); - else - Builder.ClearInsertionPoint(); -} - -void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) { - // If there is no enclosing switch instance that we're aware of, then this - // case statement and its block can be elided. This situation only happens - // when we've constant-folded the switch, are emitting the constant case, - // and part of the constant case includes another case statement. For - // instance: switch (4) { case 4: do { case 5: } while (1); } - if (!SwitchInsn) { - EmitStmt(S.getSubStmt()); - return; - } - - // Handle case ranges. - if (S.getRHS()) { - EmitCaseStmtRange(S); - return; - } - - llvm::ConstantInt *CaseVal = - Builder.getInt(S.getLHS()->EvaluateKnownConstInt(getContext())); - - // If the body of the case is just a 'break', try to not emit an empty block. - // If we're profiling or we're not optimizing, leave the block in for better - // debug and coverage analysis. - if (!CGM.getCodeGenOpts().hasProfileClangInstr() && - CGM.getCodeGenOpts().OptimizationLevel > 0 && - isa<BreakStmt>(S.getSubStmt())) { - JumpDest Block = BreakContinueStack.back().BreakBlock; - - // Only do this optimization if there are no cleanups that need emitting. - if (isObviouslyBranchWithoutCleanups(Block)) { - if (SwitchWeights) - SwitchWeights->push_back(getProfileCount(&S)); - SwitchInsn->addCase(CaseVal, Block.getBlock()); - - // If there was a fallthrough into this case, make sure to redirect it to - // the end of the switch as well. - if (Builder.GetInsertBlock()) { - Builder.CreateBr(Block.getBlock()); - Builder.ClearInsertionPoint(); - } - return; - } - } - - llvm::BasicBlock *CaseDest = createBasicBlock("sw.bb"); - EmitBlockWithFallThrough(CaseDest, &S); - if (SwitchWeights) - SwitchWeights->push_back(getProfileCount(&S)); - SwitchInsn->addCase(CaseVal, CaseDest); - - // Recursively emitting the statement is acceptable, but is not wonderful for - // code where we have many case statements nested together, i.e.: - // case 1: - // case 2: - // case 3: etc. - // Handling this recursively will create a new block for each case statement - // that falls through to the next case which is IR intensive. It also causes - // deep recursion which can run into stack depth limitations. Handle - // sequential non-range case statements specially. - const CaseStmt *CurCase = &S; - const CaseStmt *NextCase = dyn_cast<CaseStmt>(S.getSubStmt()); - - // Otherwise, iteratively add consecutive cases to this switch stmt. - while (NextCase && NextCase->getRHS() == nullptr) { - CurCase = NextCase; - llvm::ConstantInt *CaseVal = - Builder.getInt(CurCase->getLHS()->EvaluateKnownConstInt(getContext())); - - if (SwitchWeights) - SwitchWeights->push_back(getProfileCount(NextCase)); - if (CGM.getCodeGenOpts().hasProfileClangInstr()) { - CaseDest = createBasicBlock("sw.bb"); - EmitBlockWithFallThrough(CaseDest, &S); - } - - SwitchInsn->addCase(CaseVal, CaseDest); - NextCase = dyn_cast<CaseStmt>(CurCase->getSubStmt()); - } - - // Normal default recursion for non-cases. - EmitStmt(CurCase->getSubStmt()); -} - -void CodeGenFunction::EmitDefaultStmt(const DefaultStmt &S) { - // If there is no enclosing switch instance that we're aware of, then this - // default statement can be elided. This situation only happens when we've - // constant-folded the switch. - if (!SwitchInsn) { - EmitStmt(S.getSubStmt()); - return; - } - - llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest(); - assert(DefaultBlock->empty() && - "EmitDefaultStmt: Default block already defined?"); - - EmitBlockWithFallThrough(DefaultBlock, &S); - - EmitStmt(S.getSubStmt()); -} - -/// CollectStatementsForCase - Given the body of a 'switch' statement and a -/// constant value that is being switched on, see if we can dead code eliminate -/// the body of the switch to a simple series of statements to emit. Basically, -/// on a switch (5) we want to find these statements: -/// case 5: -/// printf(...); <-- -/// ++i; <-- -/// break; -/// -/// and add them to the ResultStmts vector. If it is unsafe to do this -/// transformation (for example, one of the elided statements contains a label -/// that might be jumped to), return CSFC_Failure. If we handled it and 'S' -/// should include statements after it (e.g. the printf() line is a substmt of -/// the case) then return CSFC_FallThrough. If we handled it and found a break -/// statement, then return CSFC_Success. -/// -/// If Case is non-null, then we are looking for the specified case, checking -/// that nothing we jump over contains labels. If Case is null, then we found -/// the case and are looking for the break. -/// -/// If the recursive walk actually finds our Case, then we set FoundCase to -/// true. -/// -enum CSFC_Result { CSFC_Failure, CSFC_FallThrough, CSFC_Success }; -static CSFC_Result CollectStatementsForCase(const Stmt *S, - const SwitchCase *Case, - bool &FoundCase, - SmallVectorImpl<const Stmt*> &ResultStmts) { - // If this is a null statement, just succeed. - if (!S) - return Case ? CSFC_Success : CSFC_FallThrough; - - // If this is the switchcase (case 4: or default) that we're looking for, then - // we're in business. Just add the substatement. - if (const SwitchCase *SC = dyn_cast<SwitchCase>(S)) { - if (S == Case) { - FoundCase = true; - return CollectStatementsForCase(SC->getSubStmt(), nullptr, FoundCase, - ResultStmts); - } - - // Otherwise, this is some other case or default statement, just ignore it. - return CollectStatementsForCase(SC->getSubStmt(), Case, FoundCase, - ResultStmts); - } - - // If we are in the live part of the code and we found our break statement, - // return a success! - if (!Case && isa<BreakStmt>(S)) - return CSFC_Success; - - // If this is a switch statement, then it might contain the SwitchCase, the - // break, or neither. - if (const CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) { - // Handle this as two cases: we might be looking for the SwitchCase (if so - // the skipped statements must be skippable) or we might already have it. - CompoundStmt::const_body_iterator I = CS->body_begin(), E = CS->body_end(); - bool StartedInLiveCode = FoundCase; - unsigned StartSize = ResultStmts.size(); - - // If we've not found the case yet, scan through looking for it. - if (Case) { - // Keep track of whether we see a skipped declaration. The code could be - // using the declaration even if it is skipped, so we can't optimize out - // the decl if the kept statements might refer to it. - bool HadSkippedDecl = false; - - // If we're looking for the case, just see if we can skip each of the - // substatements. - for (; Case && I != E; ++I) { - HadSkippedDecl |= CodeGenFunction::mightAddDeclToScope(*I); - - switch (CollectStatementsForCase(*I, Case, FoundCase, ResultStmts)) { - case CSFC_Failure: return CSFC_Failure; - case CSFC_Success: - // A successful result means that either 1) that the statement doesn't - // have the case and is skippable, or 2) does contain the case value - // and also contains the break to exit the switch. In the later case, - // we just verify the rest of the statements are elidable. - if (FoundCase) { - // If we found the case and skipped declarations, we can't do the - // optimization. - if (HadSkippedDecl) - return CSFC_Failure; - - for (++I; I != E; ++I) - if (CodeGenFunction::ContainsLabel(*I, true)) - return CSFC_Failure; - return CSFC_Success; - } - break; - case CSFC_FallThrough: - // If we have a fallthrough condition, then we must have found the - // case started to include statements. Consider the rest of the - // statements in the compound statement as candidates for inclusion. - assert(FoundCase && "Didn't find case but returned fallthrough?"); - // We recursively found Case, so we're not looking for it anymore. - Case = nullptr; - - // If we found the case and skipped declarations, we can't do the - // optimization. - if (HadSkippedDecl) - return CSFC_Failure; - break; - } - } - - if (!FoundCase) - return CSFC_Success; - - assert(!HadSkippedDecl && "fallthrough after skipping decl"); - } - - // If we have statements in our range, then we know that the statements are - // live and need to be added to the set of statements we're tracking. - bool AnyDecls = false; - for (; I != E; ++I) { - AnyDecls |= CodeGenFunction::mightAddDeclToScope(*I); - - switch (CollectStatementsForCase(*I, nullptr, FoundCase, ResultStmts)) { - case CSFC_Failure: return CSFC_Failure; - case CSFC_FallThrough: - // A fallthrough result means that the statement was simple and just - // included in ResultStmt, keep adding them afterwards. - break; - case CSFC_Success: - // A successful result means that we found the break statement and - // stopped statement inclusion. We just ensure that any leftover stmts - // are skippable and return success ourselves. - for (++I; I != E; ++I) - if (CodeGenFunction::ContainsLabel(*I, true)) - return CSFC_Failure; - return CSFC_Success; - } - } - - // If we're about to fall out of a scope without hitting a 'break;', we - // can't perform the optimization if there were any decls in that scope - // (we'd lose their end-of-lifetime). - if (AnyDecls) { - // If the entire compound statement was live, there's one more thing we - // can try before giving up: emit the whole thing as a single statement. - // We can do that unless the statement contains a 'break;'. - // FIXME: Such a break must be at the end of a construct within this one. - // We could emit this by just ignoring the BreakStmts entirely. - if (StartedInLiveCode && !CodeGenFunction::containsBreak(S)) { - ResultStmts.resize(StartSize); - ResultStmts.push_back(S); - } else { - return CSFC_Failure; - } - } - - return CSFC_FallThrough; - } - - // Okay, this is some other statement that we don't handle explicitly, like a - // for statement or increment etc. If we are skipping over this statement, - // just verify it doesn't have labels, which would make it invalid to elide. - if (Case) { - if (CodeGenFunction::ContainsLabel(S, true)) - return CSFC_Failure; - return CSFC_Success; - } - - // Otherwise, we want to include this statement. Everything is cool with that - // so long as it doesn't contain a break out of the switch we're in. - if (CodeGenFunction::containsBreak(S)) return CSFC_Failure; - - // Otherwise, everything is great. Include the statement and tell the caller - // that we fall through and include the next statement as well. - ResultStmts.push_back(S); - return CSFC_FallThrough; -} - -/// FindCaseStatementsForValue - Find the case statement being jumped to and -/// then invoke CollectStatementsForCase to find the list of statements to emit -/// for a switch on constant. See the comment above CollectStatementsForCase -/// for more details. -static bool FindCaseStatementsForValue(const SwitchStmt &S, - const llvm::APSInt &ConstantCondValue, - SmallVectorImpl<const Stmt*> &ResultStmts, - ASTContext &C, - const SwitchCase *&ResultCase) { - // First step, find the switch case that is being branched to. We can do this - // efficiently by scanning the SwitchCase list. - const SwitchCase *Case = S.getSwitchCaseList(); - const DefaultStmt *DefaultCase = nullptr; - - for (; Case; Case = Case->getNextSwitchCase()) { - // It's either a default or case. Just remember the default statement in - // case we're not jumping to any numbered cases. - if (const DefaultStmt *DS = dyn_cast<DefaultStmt>(Case)) { - DefaultCase = DS; - continue; - } - - // Check to see if this case is the one we're looking for. - const CaseStmt *CS = cast<CaseStmt>(Case); - // Don't handle case ranges yet. - if (CS->getRHS()) return false; - - // If we found our case, remember it as 'case'. - if (CS->getLHS()->EvaluateKnownConstInt(C) == ConstantCondValue) - break; - } - - // If we didn't find a matching case, we use a default if it exists, or we - // elide the whole switch body! - if (!Case) { - // It is safe to elide the body of the switch if it doesn't contain labels - // etc. If it is safe, return successfully with an empty ResultStmts list. - if (!DefaultCase) - return !CodeGenFunction::ContainsLabel(&S); - Case = DefaultCase; - } - - // Ok, we know which case is being jumped to, try to collect all the - // statements that follow it. This can fail for a variety of reasons. Also, - // check to see that the recursive walk actually found our case statement. - // Insane cases like this can fail to find it in the recursive walk since we - // don't handle every stmt kind: - // switch (4) { - // while (1) { - // case 4: ... - bool FoundCase = false; - ResultCase = Case; - return CollectStatementsForCase(S.getBody(), Case, FoundCase, - ResultStmts) != CSFC_Failure && - FoundCase; -} - -void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) { - // Handle nested switch statements. - llvm::SwitchInst *SavedSwitchInsn = SwitchInsn; - SmallVector<uint64_t, 16> *SavedSwitchWeights = SwitchWeights; - llvm::BasicBlock *SavedCRBlock = CaseRangeBlock; - - // See if we can constant fold the condition of the switch and therefore only - // emit the live case statement (if any) of the switch. - llvm::APSInt ConstantCondValue; - if (ConstantFoldsToSimpleInteger(S.getCond(), ConstantCondValue)) { - SmallVector<const Stmt*, 4> CaseStmts; - const SwitchCase *Case = nullptr; - if (FindCaseStatementsForValue(S, ConstantCondValue, CaseStmts, - getContext(), Case)) { - if (Case) - incrementProfileCounter(Case); - RunCleanupsScope ExecutedScope(*this); - - if (S.getInit()) - EmitStmt(S.getInit()); - - // Emit the condition variable if needed inside the entire cleanup scope - // used by this special case for constant folded switches. - if (S.getConditionVariable()) - EmitDecl(*S.getConditionVariable()); - - // At this point, we are no longer "within" a switch instance, so - // we can temporarily enforce this to ensure that any embedded case - // statements are not emitted. - SwitchInsn = nullptr; - - // Okay, we can dead code eliminate everything except this case. Emit the - // specified series of statements and we're good. - for (unsigned i = 0, e = CaseStmts.size(); i != e; ++i) - EmitStmt(CaseStmts[i]); - incrementProfileCounter(&S); - - // Now we want to restore the saved switch instance so that nested - // switches continue to function properly - SwitchInsn = SavedSwitchInsn; - - return; - } - } - - JumpDest SwitchExit = getJumpDestInCurrentScope("sw.epilog"); - - RunCleanupsScope ConditionScope(*this); - - if (S.getInit()) - EmitStmt(S.getInit()); - - if (S.getConditionVariable()) - EmitDecl(*S.getConditionVariable()); - llvm::Value *CondV = EmitScalarExpr(S.getCond()); - - // Create basic block to hold stuff that comes after switch - // statement. We also need to create a default block now so that - // explicit case ranges tests can have a place to jump to on - // failure. - llvm::BasicBlock *DefaultBlock = createBasicBlock("sw.default"); - SwitchInsn = Builder.CreateSwitch(CondV, DefaultBlock); - if (PGO.haveRegionCounts()) { - // Walk the SwitchCase list to find how many there are. - uint64_t DefaultCount = 0; - unsigned NumCases = 0; - for (const SwitchCase *Case = S.getSwitchCaseList(); - Case; - Case = Case->getNextSwitchCase()) { - if (isa<DefaultStmt>(Case)) - DefaultCount = getProfileCount(Case); - NumCases += 1; - } - SwitchWeights = new SmallVector<uint64_t, 16>(); - SwitchWeights->reserve(NumCases); - // The default needs to be first. We store the edge count, so we already - // know the right weight. - SwitchWeights->push_back(DefaultCount); - } - CaseRangeBlock = DefaultBlock; - - // Clear the insertion point to indicate we are in unreachable code. - Builder.ClearInsertionPoint(); - - // All break statements jump to NextBlock. If BreakContinueStack is non-empty - // then reuse last ContinueBlock. - JumpDest OuterContinue; - if (!BreakContinueStack.empty()) - OuterContinue = BreakContinueStack.back().ContinueBlock; - - BreakContinueStack.push_back(BreakContinue(SwitchExit, OuterContinue)); - - // Emit switch body. - EmitStmt(S.getBody()); - - BreakContinueStack.pop_back(); - - // Update the default block in case explicit case range tests have - // been chained on top. - SwitchInsn->setDefaultDest(CaseRangeBlock); - - // If a default was never emitted: - if (!DefaultBlock->getParent()) { - // If we have cleanups, emit the default block so that there's a - // place to jump through the cleanups from. - if (ConditionScope.requiresCleanups()) { - EmitBlock(DefaultBlock); - - // Otherwise, just forward the default block to the switch end. - } else { - DefaultBlock->replaceAllUsesWith(SwitchExit.getBlock()); - delete DefaultBlock; - } - } - - ConditionScope.ForceCleanup(); - - // Emit continuation. - EmitBlock(SwitchExit.getBlock(), true); - incrementProfileCounter(&S); - - // If the switch has a condition wrapped by __builtin_unpredictable, - // create metadata that specifies that the switch is unpredictable. - // Don't bother if not optimizing because that metadata would not be used. - auto *Call = dyn_cast<CallExpr>(S.getCond()); - if (Call && CGM.getCodeGenOpts().OptimizationLevel != 0) { - auto *FD = dyn_cast_or_null<FunctionDecl>(Call->getCalleeDecl()); - if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) { - llvm::MDBuilder MDHelper(getLLVMContext()); - SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable, - MDHelper.createUnpredictable()); - } - } - - if (SwitchWeights) { - assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() && - "switch weights do not match switch cases"); - // If there's only one jump destination there's no sense weighting it. - if (SwitchWeights->size() > 1) - SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof, - createProfileWeights(*SwitchWeights)); - delete SwitchWeights; - } - SwitchInsn = SavedSwitchInsn; - SwitchWeights = SavedSwitchWeights; - CaseRangeBlock = SavedCRBlock; -} - -static std::string -SimplifyConstraint(const char *Constraint, const TargetInfo &Target, - SmallVectorImpl<TargetInfo::ConstraintInfo> *OutCons=nullptr) { - std::string Result; - - while (*Constraint) { - switch (*Constraint) { - default: - Result += Target.convertConstraint(Constraint); - break; - // Ignore these - case '*': - case '?': - case '!': - case '=': // Will see this and the following in mult-alt constraints. - case '+': - break; - case '#': // Ignore the rest of the constraint alternative. - while (Constraint[1] && Constraint[1] != ',') - Constraint++; - break; - case '&': - case '%': - Result += *Constraint; - while (Constraint[1] && Constraint[1] == *Constraint) - Constraint++; - break; - case ',': - Result += "|"; - break; - case 'g': - Result += "imr"; - break; - case '[': { - assert(OutCons && - "Must pass output names to constraints with a symbolic name"); - unsigned Index; - bool result = Target.resolveSymbolicName(Constraint, *OutCons, Index); - assert(result && "Could not resolve symbolic name"); (void)result; - Result += llvm::utostr(Index); - break; - } - } - - Constraint++; - } - - return Result; -} - -/// AddVariableConstraints - Look at AsmExpr and if it is a variable declared -/// as using a particular register add that as a constraint that will be used -/// in this asm stmt. -static std::string -AddVariableConstraints(const std::string &Constraint, const Expr &AsmExpr, - const TargetInfo &Target, CodeGenModule &CGM, - const AsmStmt &Stmt, const bool EarlyClobber) { - const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(&AsmExpr); - if (!AsmDeclRef) - return Constraint; - const ValueDecl &Value = *AsmDeclRef->getDecl(); - const VarDecl *Variable = dyn_cast<VarDecl>(&Value); - if (!Variable) - return Constraint; - if (Variable->getStorageClass() != SC_Register) - return Constraint; - AsmLabelAttr *Attr = Variable->getAttr<AsmLabelAttr>(); - if (!Attr) - return Constraint; - StringRef Register = Attr->getLabel(); - assert(Target.isValidGCCRegisterName(Register)); - // We're using validateOutputConstraint here because we only care if - // this is a register constraint. - TargetInfo::ConstraintInfo Info(Constraint, ""); - if (Target.validateOutputConstraint(Info) && - !Info.allowsRegister()) { - CGM.ErrorUnsupported(&Stmt, "__asm__"); - return Constraint; - } - // Canonicalize the register here before returning it. - Register = Target.getNormalizedGCCRegisterName(Register); - return (EarlyClobber ? "&{" : "{") + Register.str() + "}"; -} - -llvm::Value* -CodeGenFunction::EmitAsmInputLValue(const TargetInfo::ConstraintInfo &Info, - LValue InputValue, QualType InputType, - std::string &ConstraintStr, - SourceLocation Loc) { - llvm::Value *Arg; - if (Info.allowsRegister() || !Info.allowsMemory()) { - if (CodeGenFunction::hasScalarEvaluationKind(InputType)) { - Arg = EmitLoadOfLValue(InputValue, Loc).getScalarVal(); - } else { - llvm::Type *Ty = ConvertType(InputType); - uint64_t Size = CGM.getDataLayout().getTypeSizeInBits(Ty); - if (Size <= 64 && llvm::isPowerOf2_64(Size)) { - Ty = llvm::IntegerType::get(getLLVMContext(), Size); - Ty = llvm::PointerType::getUnqual(Ty); - - Arg = Builder.CreateLoad(Builder.CreateBitCast(InputValue.getAddress(), - Ty)); - } else { - Arg = InputValue.getPointer(); - ConstraintStr += '*'; - } - } - } else { - Arg = InputValue.getPointer(); - ConstraintStr += '*'; - } - - return Arg; -} - -llvm::Value* CodeGenFunction::EmitAsmInput( - const TargetInfo::ConstraintInfo &Info, - const Expr *InputExpr, - std::string &ConstraintStr) { - // If this can't be a register or memory, i.e., has to be a constant - // (immediate or symbolic), try to emit it as such. - if (!Info.allowsRegister() && !Info.allowsMemory()) { - if (Info.requiresImmediateConstant()) { - Expr::EvalResult EVResult; - InputExpr->EvaluateAsRValue(EVResult, getContext(), true); - - llvm::APSInt IntResult; - if (!EVResult.Val.toIntegralConstant(IntResult, InputExpr->getType(), - getContext())) - llvm_unreachable("Invalid immediate constant!"); - - return llvm::ConstantInt::get(getLLVMContext(), IntResult); - } - - Expr::EvalResult Result; - if (InputExpr->EvaluateAsInt(Result, getContext())) - return llvm::ConstantInt::get(getLLVMContext(), Result.Val.getInt()); - } - - if (Info.allowsRegister() || !Info.allowsMemory()) - if (CodeGenFunction::hasScalarEvaluationKind(InputExpr->getType())) - return EmitScalarExpr(InputExpr); - if (InputExpr->getStmtClass() == Expr::CXXThisExprClass) - return EmitScalarExpr(InputExpr); - InputExpr = InputExpr->IgnoreParenNoopCasts(getContext()); - LValue Dest = EmitLValue(InputExpr); - return EmitAsmInputLValue(Info, Dest, InputExpr->getType(), ConstraintStr, - InputExpr->getExprLoc()); -} - -/// getAsmSrcLocInfo - Return the !srcloc metadata node to attach to an inline -/// asm call instruction. The !srcloc MDNode contains a list of constant -/// integers which are the source locations of the start of each line in the -/// asm. -static llvm::MDNode *getAsmSrcLocInfo(const StringLiteral *Str, - CodeGenFunction &CGF) { - SmallVector<llvm::Metadata *, 8> Locs; - // Add the location of the first line to the MDNode. - Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - CGF.Int32Ty, Str->getBeginLoc().getRawEncoding()))); - StringRef StrVal = Str->getString(); - if (!StrVal.empty()) { - const SourceManager &SM = CGF.CGM.getContext().getSourceManager(); - const LangOptions &LangOpts = CGF.CGM.getLangOpts(); - unsigned StartToken = 0; - unsigned ByteOffset = 0; - - // Add the location of the start of each subsequent line of the asm to the - // MDNode. - for (unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) { - if (StrVal[i] != '\n') continue; - SourceLocation LineLoc = Str->getLocationOfByte( - i + 1, SM, LangOpts, CGF.getTarget(), &StartToken, &ByteOffset); - Locs.push_back(llvm::ConstantAsMetadata::get( - llvm::ConstantInt::get(CGF.Int32Ty, LineLoc.getRawEncoding()))); - } - } - - return llvm::MDNode::get(CGF.getLLVMContext(), Locs); -} - -void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { - // Assemble the final asm string. - std::string AsmString = S.generateAsmString(getContext()); - - // Get all the output and input constraints together. - SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos; - SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos; - - for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) { - StringRef Name; - if (const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S)) - Name = GAS->getOutputName(i); - TargetInfo::ConstraintInfo Info(S.getOutputConstraint(i), Name); - bool IsValid = getTarget().validateOutputConstraint(Info); (void)IsValid; - assert(IsValid && "Failed to parse output constraint"); - OutputConstraintInfos.push_back(Info); - } - - for (unsigned i = 0, e = S.getNumInputs(); i != e; i++) { - StringRef Name; - if (const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S)) - Name = GAS->getInputName(i); - TargetInfo::ConstraintInfo Info(S.getInputConstraint(i), Name); - bool IsValid = - getTarget().validateInputConstraint(OutputConstraintInfos, Info); - assert(IsValid && "Failed to parse input constraint"); (void)IsValid; - InputConstraintInfos.push_back(Info); - } - - std::string Constraints; - - std::vector<LValue> ResultRegDests; - std::vector<QualType> ResultRegQualTys; - std::vector<llvm::Type *> ResultRegTypes; - std::vector<llvm::Type *> ResultTruncRegTypes; - std::vector<llvm::Type *> ArgTypes; - std::vector<llvm::Value*> Args; - - // Keep track of inout constraints. - std::string InOutConstraints; - std::vector<llvm::Value*> InOutArgs; - std::vector<llvm::Type*> InOutArgTypes; - - // An inline asm can be marked readonly if it meets the following conditions: - // - it doesn't have any sideeffects - // - it doesn't clobber memory - // - it doesn't return a value by-reference - // It can be marked readnone if it doesn't have any input memory constraints - // in addition to meeting the conditions listed above. - bool ReadOnly = true, ReadNone = true; - - for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) { - TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i]; - - // Simplify the output constraint. - std::string OutputConstraint(S.getOutputConstraint(i)); - OutputConstraint = SimplifyConstraint(OutputConstraint.c_str() + 1, - getTarget(), &OutputConstraintInfos); - - const Expr *OutExpr = S.getOutputExpr(i); - OutExpr = OutExpr->IgnoreParenNoopCasts(getContext()); - - OutputConstraint = AddVariableConstraints(OutputConstraint, *OutExpr, - getTarget(), CGM, S, - Info.earlyClobber()); - - LValue Dest = EmitLValue(OutExpr); - if (!Constraints.empty()) - Constraints += ','; - - // If this is a register output, then make the inline asm return it - // by-value. If this is a memory result, return the value by-reference. - if (!Info.allowsMemory() && hasScalarEvaluationKind(OutExpr->getType())) { - Constraints += "=" + OutputConstraint; - ResultRegQualTys.push_back(OutExpr->getType()); - ResultRegDests.push_back(Dest); - ResultRegTypes.push_back(ConvertTypeForMem(OutExpr->getType())); - ResultTruncRegTypes.push_back(ResultRegTypes.back()); - - // If this output is tied to an input, and if the input is larger, then - // we need to set the actual result type of the inline asm node to be the - // same as the input type. - if (Info.hasMatchingInput()) { - unsigned InputNo; - for (InputNo = 0; InputNo != S.getNumInputs(); ++InputNo) { - TargetInfo::ConstraintInfo &Input = InputConstraintInfos[InputNo]; - if (Input.hasTiedOperand() && Input.getTiedOperand() == i) - break; - } - assert(InputNo != S.getNumInputs() && "Didn't find matching input!"); - - QualType InputTy = S.getInputExpr(InputNo)->getType(); - QualType OutputType = OutExpr->getType(); - - uint64_t InputSize = getContext().getTypeSize(InputTy); - if (getContext().getTypeSize(OutputType) < InputSize) { - // Form the asm to return the value as a larger integer or fp type. - ResultRegTypes.back() = ConvertType(InputTy); - } - } - if (llvm::Type* AdjTy = - getTargetHooks().adjustInlineAsmType(*this, OutputConstraint, - ResultRegTypes.back())) - ResultRegTypes.back() = AdjTy; - else { - CGM.getDiags().Report(S.getAsmLoc(), - diag::err_asm_invalid_type_in_input) - << OutExpr->getType() << OutputConstraint; - } - - // Update largest vector width for any vector types. - if (auto *VT = dyn_cast<llvm::VectorType>(ResultRegTypes.back())) - LargestVectorWidth = std::max(LargestVectorWidth, - VT->getPrimitiveSizeInBits()); - } else { - ArgTypes.push_back(Dest.getAddress().getType()); - Args.push_back(Dest.getPointer()); - Constraints += "=*"; - Constraints += OutputConstraint; - ReadOnly = ReadNone = false; - } - - if (Info.isReadWrite()) { - InOutConstraints += ','; - - const Expr *InputExpr = S.getOutputExpr(i); - llvm::Value *Arg = EmitAsmInputLValue(Info, Dest, InputExpr->getType(), - InOutConstraints, - InputExpr->getExprLoc()); - - if (llvm::Type* AdjTy = - getTargetHooks().adjustInlineAsmType(*this, OutputConstraint, - Arg->getType())) - Arg = Builder.CreateBitCast(Arg, AdjTy); - - // Update largest vector width for any vector types. - if (auto *VT = dyn_cast<llvm::VectorType>(Arg->getType())) - LargestVectorWidth = std::max(LargestVectorWidth, - VT->getPrimitiveSizeInBits()); - if (Info.allowsRegister()) - InOutConstraints += llvm::utostr(i); - else - InOutConstraints += OutputConstraint; - - InOutArgTypes.push_back(Arg->getType()); - InOutArgs.push_back(Arg); - } - } - - // If this is a Microsoft-style asm blob, store the return registers (EAX:EDX) - // to the return value slot. Only do this when returning in registers. - if (isa<MSAsmStmt>(&S)) { - const ABIArgInfo &RetAI = CurFnInfo->getReturnInfo(); - if (RetAI.isDirect() || RetAI.isExtend()) { - // Make a fake lvalue for the return value slot. - LValue ReturnSlot = MakeAddrLValue(ReturnValue, FnRetTy); - CGM.getTargetCodeGenInfo().addReturnRegisterOutputs( - *this, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes, - ResultRegDests, AsmString, S.getNumOutputs()); - SawAsmBlock = true; - } - } - - for (unsigned i = 0, e = S.getNumInputs(); i != e; i++) { - const Expr *InputExpr = S.getInputExpr(i); - - TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; - - if (Info.allowsMemory()) - ReadNone = false; - - if (!Constraints.empty()) - Constraints += ','; - - // Simplify the input constraint. - std::string InputConstraint(S.getInputConstraint(i)); - InputConstraint = SimplifyConstraint(InputConstraint.c_str(), getTarget(), - &OutputConstraintInfos); - - InputConstraint = AddVariableConstraints( - InputConstraint, *InputExpr->IgnoreParenNoopCasts(getContext()), - getTarget(), CGM, S, false /* No EarlyClobber */); - - llvm::Value *Arg = EmitAsmInput(Info, InputExpr, Constraints); - - // If this input argument is tied to a larger output result, extend the - // input to be the same size as the output. The LLVM backend wants to see - // the input and output of a matching constraint be the same size. Note - // that GCC does not define what the top bits are here. We use zext because - // that is usually cheaper, but LLVM IR should really get an anyext someday. - if (Info.hasTiedOperand()) { - unsigned Output = Info.getTiedOperand(); - QualType OutputType = S.getOutputExpr(Output)->getType(); - QualType InputTy = InputExpr->getType(); - - if (getContext().getTypeSize(OutputType) > - getContext().getTypeSize(InputTy)) { - // Use ptrtoint as appropriate so that we can do our extension. - if (isa<llvm::PointerType>(Arg->getType())) - Arg = Builder.CreatePtrToInt(Arg, IntPtrTy); - llvm::Type *OutputTy = ConvertType(OutputType); - if (isa<llvm::IntegerType>(OutputTy)) - Arg = Builder.CreateZExt(Arg, OutputTy); - else if (isa<llvm::PointerType>(OutputTy)) - Arg = Builder.CreateZExt(Arg, IntPtrTy); - else { - assert(OutputTy->isFloatingPointTy() && "Unexpected output type"); - Arg = Builder.CreateFPExt(Arg, OutputTy); - } - } - } - if (llvm::Type* AdjTy = - getTargetHooks().adjustInlineAsmType(*this, InputConstraint, - Arg->getType())) - Arg = Builder.CreateBitCast(Arg, AdjTy); - else - CGM.getDiags().Report(S.getAsmLoc(), diag::err_asm_invalid_type_in_input) - << InputExpr->getType() << InputConstraint; - - // Update largest vector width for any vector types. - if (auto *VT = dyn_cast<llvm::VectorType>(Arg->getType())) - LargestVectorWidth = std::max(LargestVectorWidth, - VT->getPrimitiveSizeInBits()); - - ArgTypes.push_back(Arg->getType()); - Args.push_back(Arg); - Constraints += InputConstraint; - } - - // Append the "input" part of inout constraints last. - for (unsigned i = 0, e = InOutArgs.size(); i != e; i++) { - ArgTypes.push_back(InOutArgTypes[i]); - Args.push_back(InOutArgs[i]); - } - Constraints += InOutConstraints; - - // Clobbers - for (unsigned i = 0, e = S.getNumClobbers(); i != e; i++) { - StringRef Clobber = S.getClobber(i); - - if (Clobber == "memory") - ReadOnly = ReadNone = false; - else if (Clobber != "cc") - Clobber = getTarget().getNormalizedGCCRegisterName(Clobber); - - if (!Constraints.empty()) - Constraints += ','; - - Constraints += "~{"; - Constraints += Clobber; - Constraints += '}'; - } - - // Add machine specific clobbers - std::string MachineClobbers = getTarget().getClobbers(); - if (!MachineClobbers.empty()) { - if (!Constraints.empty()) - Constraints += ','; - Constraints += MachineClobbers; - } - - llvm::Type *ResultType; - if (ResultRegTypes.empty()) - ResultType = VoidTy; - else if (ResultRegTypes.size() == 1) - ResultType = ResultRegTypes[0]; - else - ResultType = llvm::StructType::get(getLLVMContext(), ResultRegTypes); - - llvm::FunctionType *FTy = - llvm::FunctionType::get(ResultType, ArgTypes, false); - - bool HasSideEffect = S.isVolatile() || S.getNumOutputs() == 0; - llvm::InlineAsm::AsmDialect AsmDialect = isa<MSAsmStmt>(&S) ? - llvm::InlineAsm::AD_Intel : llvm::InlineAsm::AD_ATT; - llvm::InlineAsm *IA = - llvm::InlineAsm::get(FTy, AsmString, Constraints, HasSideEffect, - /* IsAlignStack */ false, AsmDialect); - llvm::CallInst *Result = - Builder.CreateCall(IA, Args, getBundlesForFunclet(IA)); - Result->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind); - - // Attach readnone and readonly attributes. - if (!HasSideEffect) { - if (ReadNone) - Result->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::ReadNone); - else if (ReadOnly) - Result->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::ReadOnly); - } - - // Slap the source location of the inline asm into a !srcloc metadata on the - // call. - if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S)) { - Result->setMetadata("srcloc", getAsmSrcLocInfo(gccAsmStmt->getAsmString(), - *this)); - } else { - // At least put the line number on MS inline asm blobs. - auto Loc = llvm::ConstantInt::get(Int32Ty, S.getAsmLoc().getRawEncoding()); - Result->setMetadata("srcloc", - llvm::MDNode::get(getLLVMContext(), - llvm::ConstantAsMetadata::get(Loc))); - } - - if (getLangOpts().assumeFunctionsAreConvergent()) { - // Conservatively, mark all inline asm blocks in CUDA or OpenCL as - // convergent (meaning, they may call an intrinsically convergent op, such - // as bar.sync, and so can't have certain optimizations applied around - // them). - Result->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::Convergent); - } - - // Extract all of the register value results from the asm. - std::vector<llvm::Value*> RegResults; - if (ResultRegTypes.size() == 1) { - RegResults.push_back(Result); - } else { - for (unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) { - llvm::Value *Tmp = Builder.CreateExtractValue(Result, i, "asmresult"); - RegResults.push_back(Tmp); - } - } - - assert(RegResults.size() == ResultRegTypes.size()); - assert(RegResults.size() == ResultTruncRegTypes.size()); - assert(RegResults.size() == ResultRegDests.size()); - for (unsigned i = 0, e = RegResults.size(); i != e; ++i) { - llvm::Value *Tmp = RegResults[i]; - - // If the result type of the LLVM IR asm doesn't match the result type of - // the expression, do the conversion. - if (ResultRegTypes[i] != ResultTruncRegTypes[i]) { - llvm::Type *TruncTy = ResultTruncRegTypes[i]; - - // Truncate the integer result to the right size, note that TruncTy can be - // a pointer. - if (TruncTy->isFloatingPointTy()) - Tmp = Builder.CreateFPTrunc(Tmp, TruncTy); - else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) { - uint64_t ResSize = CGM.getDataLayout().getTypeSizeInBits(TruncTy); - Tmp = Builder.CreateTrunc(Tmp, - llvm::IntegerType::get(getLLVMContext(), (unsigned)ResSize)); - Tmp = Builder.CreateIntToPtr(Tmp, TruncTy); - } else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) { - uint64_t TmpSize =CGM.getDataLayout().getTypeSizeInBits(Tmp->getType()); - Tmp = Builder.CreatePtrToInt(Tmp, - llvm::IntegerType::get(getLLVMContext(), (unsigned)TmpSize)); - Tmp = Builder.CreateTrunc(Tmp, TruncTy); - } else if (TruncTy->isIntegerTy()) { - Tmp = Builder.CreateZExtOrTrunc(Tmp, TruncTy); - } else if (TruncTy->isVectorTy()) { - Tmp = Builder.CreateBitCast(Tmp, TruncTy); - } - } - - EmitStoreThroughLValue(RValue::get(Tmp), ResultRegDests[i]); - } -} - -LValue CodeGenFunction::InitCapturedStruct(const CapturedStmt &S) { - const RecordDecl *RD = S.getCapturedRecordDecl(); - QualType RecordTy = getContext().getRecordType(RD); - - // Initialize the captured struct. - LValue SlotLV = - MakeAddrLValue(CreateMemTemp(RecordTy, "agg.captured"), RecordTy); - - RecordDecl::field_iterator CurField = RD->field_begin(); - for (CapturedStmt::const_capture_init_iterator I = S.capture_init_begin(), - E = S.capture_init_end(); - I != E; ++I, ++CurField) { - LValue LV = EmitLValueForFieldInitialization(SlotLV, *CurField); - if (CurField->hasCapturedVLAType()) { - auto VAT = CurField->getCapturedVLAType(); - EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV); - } else { - EmitInitializerForField(*CurField, LV, *I); - } - } - - return SlotLV; -} - -/// Generate an outlined function for the body of a CapturedStmt, store any -/// captured variables into the captured struct, and call the outlined function. -llvm::Function * -CodeGenFunction::EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K) { - LValue CapStruct = InitCapturedStruct(S); - - // Emit the CapturedDecl - CodeGenFunction CGF(CGM, true); - CGCapturedStmtRAII CapInfoRAII(CGF, new CGCapturedStmtInfo(S, K)); - llvm::Function *F = CGF.GenerateCapturedStmtFunction(S); - delete CGF.CapturedStmtInfo; - - // Emit call to the helper function. - EmitCallOrInvoke(F, CapStruct.getPointer()); - - return F; -} - -Address CodeGenFunction::GenerateCapturedStmtArgument(const CapturedStmt &S) { - LValue CapStruct = InitCapturedStruct(S); - return CapStruct.getAddress(); -} - -/// Creates the outlined function for a CapturedStmt. -llvm::Function * -CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) { - assert(CapturedStmtInfo && - "CapturedStmtInfo should be set when generating the captured function"); - const CapturedDecl *CD = S.getCapturedDecl(); - const RecordDecl *RD = S.getCapturedRecordDecl(); - SourceLocation Loc = S.getBeginLoc(); - assert(CD->hasBody() && "missing CapturedDecl body"); - - // Build the argument list. - ASTContext &Ctx = CGM.getContext(); - FunctionArgList Args; - Args.append(CD->param_begin(), CD->param_end()); - - // Create the function declaration. - const CGFunctionInfo &FuncInfo = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args); - llvm::FunctionType *FuncLLVMTy = CGM.getTypes().GetFunctionType(FuncInfo); - - llvm::Function *F = - llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage, - CapturedStmtInfo->getHelperName(), &CGM.getModule()); - CGM.SetInternalFunctionAttributes(CD, F, FuncInfo); - if (CD->isNothrow()) - F->addFnAttr(llvm::Attribute::NoUnwind); - - // Generate the function. - StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args, CD->getLocation(), - CD->getBody()->getBeginLoc()); - // Set the context parameter in CapturedStmtInfo. - Address DeclPtr = GetAddrOfLocalVar(CD->getContextParam()); - CapturedStmtInfo->setContextValue(Builder.CreateLoad(DeclPtr)); - - // Initialize variable-length arrays. - LValue Base = MakeNaturalAlignAddrLValue(CapturedStmtInfo->getContextValue(), - Ctx.getTagDeclType(RD)); - for (auto *FD : RD->fields()) { - if (FD->hasCapturedVLAType()) { - auto *ExprArg = - EmitLoadOfLValue(EmitLValueForField(Base, FD), S.getBeginLoc()) - .getScalarVal(); - auto VAT = FD->getCapturedVLAType(); - VLASizeMap[VAT->getSizeExpr()] = ExprArg; - } - } - - // If 'this' is captured, load it into CXXThisValue. - if (CapturedStmtInfo->isCXXThisExprCaptured()) { - FieldDecl *FD = CapturedStmtInfo->getThisFieldDecl(); - LValue ThisLValue = EmitLValueForField(Base, FD); - CXXThisValue = EmitLoadOfLValue(ThisLValue, Loc).getScalarVal(); - } - - PGO.assignRegionCounters(GlobalDecl(CD), F); - CapturedStmtInfo->EmitBody(*this, CD->getBody()); - FinishFunction(CD->getBodyRBrace()); - - return F; -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp deleted file mode 100644 index 44dc1cdee0b..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ /dev/null @@ -1,5081 +0,0 @@ -//===--- CGStmtOpenMP.cpp - Emit LLVM Code from Statements ----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code to emit OpenMP nodes as LLVM code. -// -//===----------------------------------------------------------------------===// - -#include "CGCleanup.h" -#include "CGOpenMPRuntime.h" -#include "CodeGenFunction.h" -#include "CodeGenModule.h" -#include "TargetInfo.h" -#include "clang/AST/Stmt.h" -#include "clang/AST/StmtOpenMP.h" -#include "clang/AST/DeclOpenMP.h" -#include "llvm/IR/CallSite.h" -using namespace clang; -using namespace CodeGen; - -namespace { -/// Lexical scope for OpenMP executable constructs, that handles correct codegen -/// for captured expressions. -class OMPLexicalScope : public CodeGenFunction::LexicalScope { - void emitPreInitStmt(CodeGenFunction &CGF, const OMPExecutableDirective &S) { - for (const auto *C : S.clauses()) { - if (const auto *CPI = OMPClauseWithPreInit::get(C)) { - if (const auto *PreInit = - cast_or_null<DeclStmt>(CPI->getPreInitStmt())) { - for (const auto *I : PreInit->decls()) { - if (!I->hasAttr<OMPCaptureNoInitAttr>()) { - CGF.EmitVarDecl(cast<VarDecl>(*I)); - } else { - CodeGenFunction::AutoVarEmission Emission = - CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); - CGF.EmitAutoVarCleanups(Emission); - } - } - } - } - } - } - CodeGenFunction::OMPPrivateScope InlinedShareds; - - static bool isCapturedVar(CodeGenFunction &CGF, const VarDecl *VD) { - return CGF.LambdaCaptureFields.lookup(VD) || - (CGF.CapturedStmtInfo && CGF.CapturedStmtInfo->lookup(VD)) || - (CGF.CurCodeDecl && isa<BlockDecl>(CGF.CurCodeDecl)); - } - -public: - OMPLexicalScope( - CodeGenFunction &CGF, const OMPExecutableDirective &S, - const llvm::Optional<OpenMPDirectiveKind> CapturedRegion = llvm::None, - const bool EmitPreInitStmt = true) - : CodeGenFunction::LexicalScope(CGF, S.getSourceRange()), - InlinedShareds(CGF) { - if (EmitPreInitStmt) - emitPreInitStmt(CGF, S); - if (!CapturedRegion.hasValue()) - return; - assert(S.hasAssociatedStmt() && - "Expected associated statement for inlined directive."); - const CapturedStmt *CS = S.getCapturedStmt(*CapturedRegion); - for (const auto &C : CS->captures()) { - if (C.capturesVariable() || C.capturesVariableByCopy()) { - auto *VD = C.getCapturedVar(); - assert(VD == VD->getCanonicalDecl() && - "Canonical decl must be captured."); - DeclRefExpr DRE( - CGF.getContext(), const_cast<VarDecl *>(VD), - isCapturedVar(CGF, VD) || (CGF.CapturedStmtInfo && - InlinedShareds.isGlobalVarCaptured(VD)), - VD->getType().getNonReferenceType(), VK_LValue, C.getLocation()); - InlinedShareds.addPrivate(VD, [&CGF, &DRE]() -> Address { - return CGF.EmitLValue(&DRE).getAddress(); - }); - } - } - (void)InlinedShareds.Privatize(); - } -}; - -/// Lexical scope for OpenMP parallel construct, that handles correct codegen -/// for captured expressions. -class OMPParallelScope final : public OMPLexicalScope { - bool EmitPreInitStmt(const OMPExecutableDirective &S) { - OpenMPDirectiveKind Kind = S.getDirectiveKind(); - return !(isOpenMPTargetExecutionDirective(Kind) || - isOpenMPLoopBoundSharingDirective(Kind)) && - isOpenMPParallelDirective(Kind); - } - -public: - OMPParallelScope(CodeGenFunction &CGF, const OMPExecutableDirective &S) - : OMPLexicalScope(CGF, S, /*CapturedRegion=*/llvm::None, - EmitPreInitStmt(S)) {} -}; - -/// Lexical scope for OpenMP teams construct, that handles correct codegen -/// for captured expressions. -class OMPTeamsScope final : public OMPLexicalScope { - bool EmitPreInitStmt(const OMPExecutableDirective &S) { - OpenMPDirectiveKind Kind = S.getDirectiveKind(); - return !isOpenMPTargetExecutionDirective(Kind) && - isOpenMPTeamsDirective(Kind); - } - -public: - OMPTeamsScope(CodeGenFunction &CGF, const OMPExecutableDirective &S) - : OMPLexicalScope(CGF, S, /*CapturedRegion=*/llvm::None, - EmitPreInitStmt(S)) {} -}; - -/// Private scope for OpenMP loop-based directives, that supports capturing -/// of used expression from loop statement. -class OMPLoopScope : public CodeGenFunction::RunCleanupsScope { - void emitPreInitStmt(CodeGenFunction &CGF, const OMPLoopDirective &S) { - CodeGenFunction::OMPMapVars PreCondVars; - for (const auto *E : S.counters()) { - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - (void)PreCondVars.setVarAddr( - CGF, VD, CGF.CreateMemTemp(VD->getType().getNonReferenceType())); - } - (void)PreCondVars.apply(CGF); - if (const auto *PreInits = cast_or_null<DeclStmt>(S.getPreInits())) { - for (const auto *I : PreInits->decls()) - CGF.EmitVarDecl(cast<VarDecl>(*I)); - } - PreCondVars.restore(CGF); - } - -public: - OMPLoopScope(CodeGenFunction &CGF, const OMPLoopDirective &S) - : CodeGenFunction::RunCleanupsScope(CGF) { - emitPreInitStmt(CGF, S); - } -}; - -class OMPSimdLexicalScope : public CodeGenFunction::LexicalScope { - CodeGenFunction::OMPPrivateScope InlinedShareds; - - static bool isCapturedVar(CodeGenFunction &CGF, const VarDecl *VD) { - return CGF.LambdaCaptureFields.lookup(VD) || - (CGF.CapturedStmtInfo && CGF.CapturedStmtInfo->lookup(VD)) || - (CGF.CurCodeDecl && isa<BlockDecl>(CGF.CurCodeDecl) && - cast<BlockDecl>(CGF.CurCodeDecl)->capturesVariable(VD)); - } - -public: - OMPSimdLexicalScope(CodeGenFunction &CGF, const OMPExecutableDirective &S) - : CodeGenFunction::LexicalScope(CGF, S.getSourceRange()), - InlinedShareds(CGF) { - for (const auto *C : S.clauses()) { - if (const auto *CPI = OMPClauseWithPreInit::get(C)) { - if (const auto *PreInit = - cast_or_null<DeclStmt>(CPI->getPreInitStmt())) { - for (const auto *I : PreInit->decls()) { - if (!I->hasAttr<OMPCaptureNoInitAttr>()) { - CGF.EmitVarDecl(cast<VarDecl>(*I)); - } else { - CodeGenFunction::AutoVarEmission Emission = - CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); - CGF.EmitAutoVarCleanups(Emission); - } - } - } - } else if (const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(C)) { - for (const Expr *E : UDP->varlists()) { - const Decl *D = cast<DeclRefExpr>(E)->getDecl(); - if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(D)) - CGF.EmitVarDecl(*OED); - } - } - } - if (!isOpenMPSimdDirective(S.getDirectiveKind())) - CGF.EmitOMPPrivateClause(S, InlinedShareds); - if (const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) { - if (const Expr *E = TG->getReductionRef()) - CGF.EmitVarDecl(*cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl())); - } - const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt()); - while (CS) { - for (auto &C : CS->captures()) { - if (C.capturesVariable() || C.capturesVariableByCopy()) { - auto *VD = C.getCapturedVar(); - assert(VD == VD->getCanonicalDecl() && - "Canonical decl must be captured."); - DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), - isCapturedVar(CGF, VD) || - (CGF.CapturedStmtInfo && - InlinedShareds.isGlobalVarCaptured(VD)), - VD->getType().getNonReferenceType(), VK_LValue, - C.getLocation()); - InlinedShareds.addPrivate(VD, [&CGF, &DRE]() -> Address { - return CGF.EmitLValue(&DRE).getAddress(); - }); - } - } - CS = dyn_cast<CapturedStmt>(CS->getCapturedStmt()); - } - (void)InlinedShareds.Privatize(); - } -}; - -} // namespace - -static void emitCommonOMPTargetDirective(CodeGenFunction &CGF, - const OMPExecutableDirective &S, - const RegionCodeGenTy &CodeGen); - -LValue CodeGenFunction::EmitOMPSharedLValue(const Expr *E) { - if (const auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) { - if (const auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) { - OrigVD = OrigVD->getCanonicalDecl(); - bool IsCaptured = - LambdaCaptureFields.lookup(OrigVD) || - (CapturedStmtInfo && CapturedStmtInfo->lookup(OrigVD)) || - (CurCodeDecl && isa<BlockDecl>(CurCodeDecl)); - DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD), IsCaptured, - OrigDRE->getType(), VK_LValue, OrigDRE->getExprLoc()); - return EmitLValue(&DRE); - } - } - return EmitLValue(E); -} - -llvm::Value *CodeGenFunction::getTypeSize(QualType Ty) { - ASTContext &C = getContext(); - llvm::Value *Size = nullptr; - auto SizeInChars = C.getTypeSizeInChars(Ty); - if (SizeInChars.isZero()) { - // getTypeSizeInChars() returns 0 for a VLA. - while (const VariableArrayType *VAT = C.getAsVariableArrayType(Ty)) { - VlaSizePair VlaSize = getVLASize(VAT); - Ty = VlaSize.Type; - Size = Size ? Builder.CreateNUWMul(Size, VlaSize.NumElts) - : VlaSize.NumElts; - } - SizeInChars = C.getTypeSizeInChars(Ty); - if (SizeInChars.isZero()) - return llvm::ConstantInt::get(SizeTy, /*V=*/0); - return Builder.CreateNUWMul(Size, CGM.getSize(SizeInChars)); - } - return CGM.getSize(SizeInChars); -} - -void CodeGenFunction::GenerateOpenMPCapturedVars( - const CapturedStmt &S, SmallVectorImpl<llvm::Value *> &CapturedVars) { - const RecordDecl *RD = S.getCapturedRecordDecl(); - auto CurField = RD->field_begin(); - auto CurCap = S.captures().begin(); - for (CapturedStmt::const_capture_init_iterator I = S.capture_init_begin(), - E = S.capture_init_end(); - I != E; ++I, ++CurField, ++CurCap) { - if (CurField->hasCapturedVLAType()) { - const VariableArrayType *VAT = CurField->getCapturedVLAType(); - llvm::Value *Val = VLASizeMap[VAT->getSizeExpr()]; - CapturedVars.push_back(Val); - } else if (CurCap->capturesThis()) { - CapturedVars.push_back(CXXThisValue); - } else if (CurCap->capturesVariableByCopy()) { - llvm::Value *CV = EmitLoadOfScalar(EmitLValue(*I), CurCap->getLocation()); - - // If the field is not a pointer, we need to save the actual value - // and load it as a void pointer. - if (!CurField->getType()->isAnyPointerType()) { - ASTContext &Ctx = getContext(); - Address DstAddr = CreateMemTemp( - Ctx.getUIntPtrType(), - Twine(CurCap->getCapturedVar()->getName(), ".casted")); - LValue DstLV = MakeAddrLValue(DstAddr, Ctx.getUIntPtrType()); - - llvm::Value *SrcAddrVal = EmitScalarConversion( - DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()), - Ctx.getPointerType(CurField->getType()), CurCap->getLocation()); - LValue SrcLV = - MakeNaturalAlignAddrLValue(SrcAddrVal, CurField->getType()); - - // Store the value using the source type pointer. - EmitStoreThroughLValue(RValue::get(CV), SrcLV); - - // Load the value using the destination type pointer. - CV = EmitLoadOfScalar(DstLV, CurCap->getLocation()); - } - CapturedVars.push_back(CV); - } else { - assert(CurCap->capturesVariable() && "Expected capture by reference."); - CapturedVars.push_back(EmitLValue(*I).getAddress().getPointer()); - } - } -} - -static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc, - QualType DstType, StringRef Name, - LValue AddrLV, - bool isReferenceType = false) { - ASTContext &Ctx = CGF.getContext(); - - llvm::Value *CastedPtr = CGF.EmitScalarConversion( - AddrLV.getAddress().getPointer(), Ctx.getUIntPtrType(), - Ctx.getPointerType(DstType), Loc); - Address TmpAddr = - CGF.MakeNaturalAlignAddrLValue(CastedPtr, Ctx.getPointerType(DstType)) - .getAddress(); - - // If we are dealing with references we need to return the address of the - // reference instead of the reference of the value. - if (isReferenceType) { - QualType RefType = Ctx.getLValueReferenceType(DstType); - llvm::Value *RefVal = TmpAddr.getPointer(); - TmpAddr = CGF.CreateMemTemp(RefType, Twine(Name, ".ref")); - LValue TmpLVal = CGF.MakeAddrLValue(TmpAddr, RefType); - CGF.EmitStoreThroughLValue(RValue::get(RefVal), TmpLVal, /*isInit=*/true); - } - - return TmpAddr; -} - -static QualType getCanonicalParamType(ASTContext &C, QualType T) { - if (T->isLValueReferenceType()) - return C.getLValueReferenceType( - getCanonicalParamType(C, T.getNonReferenceType()), - /*SpelledAsLValue=*/false); - if (T->isPointerType()) - return C.getPointerType(getCanonicalParamType(C, T->getPointeeType())); - if (const ArrayType *A = T->getAsArrayTypeUnsafe()) { - if (const auto *VLA = dyn_cast<VariableArrayType>(A)) - return getCanonicalParamType(C, VLA->getElementType()); - if (!A->isVariablyModifiedType()) - return C.getCanonicalType(T); - } - return C.getCanonicalParamType(T); -} - -namespace { - /// Contains required data for proper outlined function codegen. - struct FunctionOptions { - /// Captured statement for which the function is generated. - const CapturedStmt *S = nullptr; - /// true if cast to/from UIntPtr is required for variables captured by - /// value. - const bool UIntPtrCastRequired = true; - /// true if only casted arguments must be registered as local args or VLA - /// sizes. - const bool RegisterCastedArgsOnly = false; - /// Name of the generated function. - const StringRef FunctionName; - explicit FunctionOptions(const CapturedStmt *S, bool UIntPtrCastRequired, - bool RegisterCastedArgsOnly, - StringRef FunctionName) - : S(S), UIntPtrCastRequired(UIntPtrCastRequired), - RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly), - FunctionName(FunctionName) {} - }; -} - -static llvm::Function *emitOutlinedFunctionPrologue( - CodeGenFunction &CGF, FunctionArgList &Args, - llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> - &LocalAddrs, - llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> - &VLASizes, - llvm::Value *&CXXThisValue, const FunctionOptions &FO) { - const CapturedDecl *CD = FO.S->getCapturedDecl(); - const RecordDecl *RD = FO.S->getCapturedRecordDecl(); - assert(CD->hasBody() && "missing CapturedDecl body"); - - CXXThisValue = nullptr; - // Build the argument list. - CodeGenModule &CGM = CGF.CGM; - ASTContext &Ctx = CGM.getContext(); - FunctionArgList TargetArgs; - Args.append(CD->param_begin(), - std::next(CD->param_begin(), CD->getContextParamPosition())); - TargetArgs.append( - CD->param_begin(), - std::next(CD->param_begin(), CD->getContextParamPosition())); - auto I = FO.S->captures().begin(); - FunctionDecl *DebugFunctionDecl = nullptr; - if (!FO.UIntPtrCastRequired) { - FunctionProtoType::ExtProtoInfo EPI; - QualType FunctionTy = Ctx.getFunctionType(Ctx.VoidTy, llvm::None, EPI); - DebugFunctionDecl = FunctionDecl::Create( - Ctx, Ctx.getTranslationUnitDecl(), FO.S->getBeginLoc(), - SourceLocation(), DeclarationName(), FunctionTy, - Ctx.getTrivialTypeSourceInfo(FunctionTy), SC_Static, - /*isInlineSpecified=*/false, /*hasWrittenPrototype=*/false); - } - for (const FieldDecl *FD : RD->fields()) { - QualType ArgType = FD->getType(); - IdentifierInfo *II = nullptr; - VarDecl *CapVar = nullptr; - - // If this is a capture by copy and the type is not a pointer, the outlined - // function argument type should be uintptr and the value properly casted to - // uintptr. This is necessary given that the runtime library is only able to - // deal with pointers. We can pass in the same way the VLA type sizes to the - // outlined function. - if (FO.UIntPtrCastRequired && - ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) || - I->capturesVariableArrayType())) - ArgType = Ctx.getUIntPtrType(); - - if (I->capturesVariable() || I->capturesVariableByCopy()) { - CapVar = I->getCapturedVar(); - II = CapVar->getIdentifier(); - } else if (I->capturesThis()) { - II = &Ctx.Idents.get("this"); - } else { - assert(I->capturesVariableArrayType()); - II = &Ctx.Idents.get("vla"); - } - if (ArgType->isVariablyModifiedType()) - ArgType = getCanonicalParamType(Ctx, ArgType); - VarDecl *Arg; - if (DebugFunctionDecl && (CapVar || I->capturesThis())) { - Arg = ParmVarDecl::Create( - Ctx, DebugFunctionDecl, - CapVar ? CapVar->getBeginLoc() : FD->getBeginLoc(), - CapVar ? CapVar->getLocation() : FD->getLocation(), II, ArgType, - /*TInfo=*/nullptr, SC_None, /*DefArg=*/nullptr); - } else { - Arg = ImplicitParamDecl::Create(Ctx, /*DC=*/nullptr, FD->getLocation(), - II, ArgType, ImplicitParamDecl::Other); - } - Args.emplace_back(Arg); - // Do not cast arguments if we emit function with non-original types. - TargetArgs.emplace_back( - FO.UIntPtrCastRequired - ? Arg - : CGM.getOpenMPRuntime().translateParameter(FD, Arg)); - ++I; - } - Args.append( - std::next(CD->param_begin(), CD->getContextParamPosition() + 1), - CD->param_end()); - TargetArgs.append( - std::next(CD->param_begin(), CD->getContextParamPosition() + 1), - CD->param_end()); - - // Create the function declaration. - const CGFunctionInfo &FuncInfo = - CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, TargetArgs); - llvm::FunctionType *FuncLLVMTy = CGM.getTypes().GetFunctionType(FuncInfo); - - auto *F = - llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage, - FO.FunctionName, &CGM.getModule()); - CGM.SetInternalFunctionAttributes(CD, F, FuncInfo); - if (CD->isNothrow()) - F->setDoesNotThrow(); - F->setDoesNotRecurse(); - - // Generate the function. - CGF.StartFunction(CD, Ctx.VoidTy, F, FuncInfo, TargetArgs, - FO.S->getBeginLoc(), CD->getBody()->getBeginLoc()); - unsigned Cnt = CD->getContextParamPosition(); - I = FO.S->captures().begin(); - for (const FieldDecl *FD : RD->fields()) { - // Do not map arguments if we emit function with non-original types. - Address LocalAddr(Address::invalid()); - if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) { - LocalAddr = CGM.getOpenMPRuntime().getParameterAddress(CGF, Args[Cnt], - TargetArgs[Cnt]); - } else { - LocalAddr = CGF.GetAddrOfLocalVar(Args[Cnt]); - } - // If we are capturing a pointer by copy we don't need to do anything, just - // use the value that we get from the arguments. - if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) { - const VarDecl *CurVD = I->getCapturedVar(); - // If the variable is a reference we need to materialize it here. - if (CurVD->getType()->isReferenceType()) { - Address RefAddr = CGF.CreateMemTemp( - CurVD->getType(), CGM.getPointerAlign(), ".materialized_ref"); - CGF.EmitStoreOfScalar(LocalAddr.getPointer(), RefAddr, - /*Volatile=*/false, CurVD->getType()); - LocalAddr = RefAddr; - } - if (!FO.RegisterCastedArgsOnly) - LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}}); - ++Cnt; - ++I; - continue; - } - - LValue ArgLVal = CGF.MakeAddrLValue(LocalAddr, Args[Cnt]->getType(), - AlignmentSource::Decl); - if (FD->hasCapturedVLAType()) { - if (FO.UIntPtrCastRequired) { - ArgLVal = CGF.MakeAddrLValue( - castValueFromUintptr(CGF, I->getLocation(), FD->getType(), - Args[Cnt]->getName(), ArgLVal), - FD->getType(), AlignmentSource::Decl); - } - llvm::Value *ExprArg = CGF.EmitLoadOfScalar(ArgLVal, I->getLocation()); - const VariableArrayType *VAT = FD->getCapturedVLAType(); - VLASizes.try_emplace(Args[Cnt], VAT->getSizeExpr(), ExprArg); - } else if (I->capturesVariable()) { - const VarDecl *Var = I->getCapturedVar(); - QualType VarTy = Var->getType(); - Address ArgAddr = ArgLVal.getAddress(); - if (!VarTy->isReferenceType()) { - if (ArgLVal.getType()->isLValueReferenceType()) { - ArgAddr = CGF.EmitLoadOfReference(ArgLVal); - } else if (!VarTy->isVariablyModifiedType() || - !VarTy->isPointerType()) { - assert(ArgLVal.getType()->isPointerType()); - ArgAddr = CGF.EmitLoadOfPointer( - ArgAddr, ArgLVal.getType()->castAs<PointerType>()); - } - } - if (!FO.RegisterCastedArgsOnly) { - LocalAddrs.insert( - {Args[Cnt], - {Var, Address(ArgAddr.getPointer(), Ctx.getDeclAlign(Var))}}); - } - } else if (I->capturesVariableByCopy()) { - assert(!FD->getType()->isAnyPointerType() && - "Not expecting a captured pointer."); - const VarDecl *Var = I->getCapturedVar(); - QualType VarTy = Var->getType(); - LocalAddrs.insert( - {Args[Cnt], - {Var, FO.UIntPtrCastRequired - ? castValueFromUintptr(CGF, I->getLocation(), - FD->getType(), Args[Cnt]->getName(), - ArgLVal, VarTy->isReferenceType()) - : ArgLVal.getAddress()}}); - } else { - // If 'this' is captured, load it into CXXThisValue. - assert(I->capturesThis()); - CXXThisValue = CGF.EmitLoadOfScalar(ArgLVal, I->getLocation()); - LocalAddrs.insert({Args[Cnt], {nullptr, ArgLVal.getAddress()}}); - } - ++Cnt; - ++I; - } - - return F; -} - -llvm::Function * -CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) { - assert( - CapturedStmtInfo && - "CapturedStmtInfo should be set when generating the captured function"); - const CapturedDecl *CD = S.getCapturedDecl(); - // Build the argument list. - bool NeedWrapperFunction = - getDebugInfo() && - CGM.getCodeGenOpts().getDebugInfo() >= codegenoptions::LimitedDebugInfo; - FunctionArgList Args; - llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs; - llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes; - SmallString<256> Buffer; - llvm::raw_svector_ostream Out(Buffer); - Out << CapturedStmtInfo->getHelperName(); - if (NeedWrapperFunction) - Out << "_debug__"; - FunctionOptions FO(&S, !NeedWrapperFunction, /*RegisterCastedArgsOnly=*/false, - Out.str()); - llvm::Function *F = emitOutlinedFunctionPrologue(*this, Args, LocalAddrs, - VLASizes, CXXThisValue, FO); - for (const auto &LocalAddrPair : LocalAddrs) { - if (LocalAddrPair.second.first) { - setAddrOfLocalVar(LocalAddrPair.second.first, - LocalAddrPair.second.second); - } - } - for (const auto &VLASizePair : VLASizes) - VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second; - PGO.assignRegionCounters(GlobalDecl(CD), F); - CapturedStmtInfo->EmitBody(*this, CD->getBody()); - FinishFunction(CD->getBodyRBrace()); - if (!NeedWrapperFunction) - return F; - - FunctionOptions WrapperFO(&S, /*UIntPtrCastRequired=*/true, - /*RegisterCastedArgsOnly=*/true, - CapturedStmtInfo->getHelperName()); - CodeGenFunction WrapperCGF(CGM, /*suppressNewContext=*/true); - WrapperCGF.CapturedStmtInfo = CapturedStmtInfo; - Args.clear(); - LocalAddrs.clear(); - VLASizes.clear(); - llvm::Function *WrapperF = - emitOutlinedFunctionPrologue(WrapperCGF, Args, LocalAddrs, VLASizes, - WrapperCGF.CXXThisValue, WrapperFO); - llvm::SmallVector<llvm::Value *, 4> CallArgs; - for (const auto *Arg : Args) { - llvm::Value *CallArg; - auto I = LocalAddrs.find(Arg); - if (I != LocalAddrs.end()) { - LValue LV = WrapperCGF.MakeAddrLValue( - I->second.second, - I->second.first ? I->second.first->getType() : Arg->getType(), - AlignmentSource::Decl); - CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getBeginLoc()); - } else { - auto EI = VLASizes.find(Arg); - if (EI != VLASizes.end()) { - CallArg = EI->second.second; - } else { - LValue LV = WrapperCGF.MakeAddrLValue(WrapperCGF.GetAddrOfLocalVar(Arg), - Arg->getType(), - AlignmentSource::Decl); - CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getBeginLoc()); - } - } - CallArgs.emplace_back(WrapperCGF.EmitFromMemory(CallArg, Arg->getType())); - } - CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, S.getBeginLoc(), - F, CallArgs); - WrapperCGF.FinishFunction(); - return WrapperF; -} - -//===----------------------------------------------------------------------===// -// OpenMP Directive Emission -//===----------------------------------------------------------------------===// -void CodeGenFunction::EmitOMPAggregateAssign( - Address DestAddr, Address SrcAddr, QualType OriginalType, - const llvm::function_ref<void(Address, Address)> CopyGen) { - // Perform element-by-element initialization. - QualType ElementTy; - - // Drill down to the base element type on both arrays. - const ArrayType *ArrayTy = OriginalType->getAsArrayTypeUnsafe(); - llvm::Value *NumElements = emitArrayLength(ArrayTy, ElementTy, DestAddr); - SrcAddr = Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); - - llvm::Value *SrcBegin = SrcAddr.getPointer(); - llvm::Value *DestBegin = DestAddr.getPointer(); - // Cast from pointer to array type to pointer to single element. - llvm::Value *DestEnd = Builder.CreateGEP(DestBegin, NumElements); - // The basic structure here is a while-do loop. - llvm::BasicBlock *BodyBB = createBasicBlock("omp.arraycpy.body"); - llvm::BasicBlock *DoneBB = createBasicBlock("omp.arraycpy.done"); - llvm::Value *IsEmpty = - Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arraycpy.isempty"); - Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); - - // Enter the loop body, making that address the current address. - llvm::BasicBlock *EntryBB = Builder.GetInsertBlock(); - EmitBlock(BodyBB); - - CharUnits ElementSize = getContext().getTypeSizeInChars(ElementTy); - - llvm::PHINode *SrcElementPHI = - Builder.CreatePHI(SrcBegin->getType(), 2, "omp.arraycpy.srcElementPast"); - SrcElementPHI->addIncoming(SrcBegin, EntryBB); - Address SrcElementCurrent = - Address(SrcElementPHI, - SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); - - llvm::PHINode *DestElementPHI = - Builder.CreatePHI(DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); - DestElementPHI->addIncoming(DestBegin, EntryBB); - Address DestElementCurrent = - Address(DestElementPHI, - DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); - - // Emit copy. - CopyGen(DestElementCurrent, SrcElementCurrent); - - // Shift the address forward by one element. - llvm::Value *DestElementNext = Builder.CreateConstGEP1_32( - DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); - llvm::Value *SrcElementNext = Builder.CreateConstGEP1_32( - SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); - // Check whether we've reached the end. - llvm::Value *Done = - Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); - Builder.CreateCondBr(Done, DoneBB, BodyBB); - DestElementPHI->addIncoming(DestElementNext, Builder.GetInsertBlock()); - SrcElementPHI->addIncoming(SrcElementNext, Builder.GetInsertBlock()); - - // Done. - EmitBlock(DoneBB, /*IsFinished=*/true); -} - -void CodeGenFunction::EmitOMPCopy(QualType OriginalType, Address DestAddr, - Address SrcAddr, const VarDecl *DestVD, - const VarDecl *SrcVD, const Expr *Copy) { - if (OriginalType->isArrayType()) { - const auto *BO = dyn_cast<BinaryOperator>(Copy); - if (BO && BO->getOpcode() == BO_Assign) { - // Perform simple memcpy for simple copying. - LValue Dest = MakeAddrLValue(DestAddr, OriginalType); - LValue Src = MakeAddrLValue(SrcAddr, OriginalType); - EmitAggregateAssign(Dest, Src, OriginalType); - } else { - // For arrays with complex element types perform element by element - // copying. - EmitOMPAggregateAssign( - DestAddr, SrcAddr, OriginalType, - [this, Copy, SrcVD, DestVD](Address DestElement, Address SrcElement) { - // Working with the single array element, so have to remap - // destination and source variables to corresponding array - // elements. - CodeGenFunction::OMPPrivateScope Remap(*this); - Remap.addPrivate(DestVD, [DestElement]() { return DestElement; }); - Remap.addPrivate(SrcVD, [SrcElement]() { return SrcElement; }); - (void)Remap.Privatize(); - EmitIgnoredExpr(Copy); - }); - } - } else { - // Remap pseudo source variable to private copy. - CodeGenFunction::OMPPrivateScope Remap(*this); - Remap.addPrivate(SrcVD, [SrcAddr]() { return SrcAddr; }); - Remap.addPrivate(DestVD, [DestAddr]() { return DestAddr; }); - (void)Remap.Privatize(); - // Emit copying of the whole variable. - EmitIgnoredExpr(Copy); - } -} - -bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D, - OMPPrivateScope &PrivateScope) { - if (!HaveInsertPoint()) - return false; - bool FirstprivateIsLastprivate = false; - llvm::DenseSet<const VarDecl *> Lastprivates; - for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) { - for (const auto *D : C->varlists()) - Lastprivates.insert( - cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl()); - } - llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate; - llvm::SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; - getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind()); - // Force emission of the firstprivate copy if the directive does not emit - // outlined function, like omp for, omp simd, omp distribute etc. - bool MustEmitFirstprivateCopy = - CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown; - for (const auto *C : D.getClausesOfKind<OMPFirstprivateClause>()) { - auto IRef = C->varlist_begin(); - auto InitsRef = C->inits().begin(); - for (const Expr *IInit : C->private_copies()) { - const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); - bool ThisFirstprivateIsLastprivate = - Lastprivates.count(OrigVD->getCanonicalDecl()) > 0; - const FieldDecl *FD = CapturedStmtInfo->lookup(OrigVD); - if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD && - !FD->getType()->isReferenceType()) { - EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()); - ++IRef; - ++InitsRef; - continue; - } - FirstprivateIsLastprivate = - FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate; - if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) { - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl()); - const auto *VDInit = - cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl()); - bool IsRegistered; - DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD), - /*RefersToEnclosingVariableOrCapture=*/FD != nullptr, - (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc()); - LValue OriginalLVal = EmitLValue(&DRE); - QualType Type = VD->getType(); - if (Type->isArrayType()) { - // Emit VarDecl with copy init for arrays. - // Get the address of the original variable captured in current - // captured region. - IsRegistered = PrivateScope.addPrivate( - OrigVD, [this, VD, Type, OriginalLVal, VDInit]() { - AutoVarEmission Emission = EmitAutoVarAlloca(*VD); - const Expr *Init = VD->getInit(); - if (!isa<CXXConstructExpr>(Init) || - isTrivialInitializer(Init)) { - // Perform simple memcpy. - LValue Dest = - MakeAddrLValue(Emission.getAllocatedAddress(), Type); - EmitAggregateAssign(Dest, OriginalLVal, Type); - } else { - EmitOMPAggregateAssign( - Emission.getAllocatedAddress(), OriginalLVal.getAddress(), - Type, - [this, VDInit, Init](Address DestElement, - Address SrcElement) { - // Clean up any temporaries needed by the - // initialization. - RunCleanupsScope InitScope(*this); - // Emit initialization for single element. - setAddrOfLocalVar(VDInit, SrcElement); - EmitAnyExprToMem(Init, DestElement, - Init->getType().getQualifiers(), - /*IsInitializer*/ false); - LocalDeclMap.erase(VDInit); - }); - } - EmitAutoVarCleanups(Emission); - return Emission.getAllocatedAddress(); - }); - } else { - Address OriginalAddr = OriginalLVal.getAddress(); - IsRegistered = PrivateScope.addPrivate( - OrigVD, [this, VDInit, OriginalAddr, VD]() { - // Emit private VarDecl with copy init. - // Remap temp VDInit variable to the address of the original - // variable (for proper handling of captured global variables). - setAddrOfLocalVar(VDInit, OriginalAddr); - EmitDecl(*VD); - LocalDeclMap.erase(VDInit); - return GetAddrOfLocalVar(VD); - }); - } - assert(IsRegistered && - "firstprivate var already registered as private"); - // Silence the warning about unused variable. - (void)IsRegistered; - } - ++IRef; - ++InitsRef; - } - } - return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty(); -} - -void CodeGenFunction::EmitOMPPrivateClause( - const OMPExecutableDirective &D, - CodeGenFunction::OMPPrivateScope &PrivateScope) { - if (!HaveInsertPoint()) - return; - llvm::DenseSet<const VarDecl *> EmittedAsPrivate; - for (const auto *C : D.getClausesOfKind<OMPPrivateClause>()) { - auto IRef = C->varlist_begin(); - for (const Expr *IInit : C->private_copies()) { - const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); - if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) { - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl()); - bool IsRegistered = PrivateScope.addPrivate(OrigVD, [this, VD]() { - // Emit private VarDecl with copy init. - EmitDecl(*VD); - return GetAddrOfLocalVar(VD); - }); - assert(IsRegistered && "private var already registered as private"); - // Silence the warning about unused variable. - (void)IsRegistered; - } - ++IRef; - } - } -} - -bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) { - if (!HaveInsertPoint()) - return false; - // threadprivate_var1 = master_threadprivate_var1; - // operator=(threadprivate_var2, master_threadprivate_var2); - // ... - // __kmpc_barrier(&loc, global_tid); - llvm::DenseSet<const VarDecl *> CopiedVars; - llvm::BasicBlock *CopyBegin = nullptr, *CopyEnd = nullptr; - for (const auto *C : D.getClausesOfKind<OMPCopyinClause>()) { - auto IRef = C->varlist_begin(); - auto ISrcRef = C->source_exprs().begin(); - auto IDestRef = C->destination_exprs().begin(); - for (const Expr *AssignOp : C->assignment_ops()) { - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); - QualType Type = VD->getType(); - if (CopiedVars.insert(VD->getCanonicalDecl()).second) { - // Get the address of the master variable. If we are emitting code with - // TLS support, the address is passed from the master as field in the - // captured declaration. - Address MasterAddr = Address::invalid(); - if (getLangOpts().OpenMPUseTLS && - getContext().getTargetInfo().isTLSSupported()) { - assert(CapturedStmtInfo->lookup(VD) && - "Copyin threadprivates should have been captured!"); - DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(VD), true, - (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc()); - MasterAddr = EmitLValue(&DRE).getAddress(); - LocalDeclMap.erase(VD); - } else { - MasterAddr = - Address(VD->isStaticLocal() ? CGM.getStaticLocalDeclAddress(VD) - : CGM.GetAddrOfGlobal(VD), - getContext().getDeclAlign(VD)); - } - // Get the address of the threadprivate variable. - Address PrivateAddr = EmitLValue(*IRef).getAddress(); - if (CopiedVars.size() == 1) { - // At first check if current thread is a master thread. If it is, no - // need to copy data. - CopyBegin = createBasicBlock("copyin.not.master"); - CopyEnd = createBasicBlock("copyin.not.master.end"); - Builder.CreateCondBr( - Builder.CreateICmpNE( - Builder.CreatePtrToInt(MasterAddr.getPointer(), CGM.IntPtrTy), - Builder.CreatePtrToInt(PrivateAddr.getPointer(), - CGM.IntPtrTy)), - CopyBegin, CopyEnd); - EmitBlock(CopyBegin); - } - const auto *SrcVD = - cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl()); - const auto *DestVD = - cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl()); - EmitOMPCopy(Type, PrivateAddr, MasterAddr, DestVD, SrcVD, AssignOp); - } - ++IRef; - ++ISrcRef; - ++IDestRef; - } - } - if (CopyEnd) { - // Exit out of copying procedure for non-master thread. - EmitBlock(CopyEnd, /*IsFinished=*/true); - return true; - } - return false; -} - -bool CodeGenFunction::EmitOMPLastprivateClauseInit( - const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope) { - if (!HaveInsertPoint()) - return false; - bool HasAtLeastOneLastprivate = false; - llvm::DenseSet<const VarDecl *> SIMDLCVs; - if (isOpenMPSimdDirective(D.getDirectiveKind())) { - const auto *LoopDirective = cast<OMPLoopDirective>(&D); - for (const Expr *C : LoopDirective->counters()) { - SIMDLCVs.insert( - cast<VarDecl>(cast<DeclRefExpr>(C)->getDecl())->getCanonicalDecl()); - } - } - llvm::DenseSet<const VarDecl *> AlreadyEmittedVars; - for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) { - HasAtLeastOneLastprivate = true; - if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && - !getLangOpts().OpenMPSimd) - break; - auto IRef = C->varlist_begin(); - auto IDestRef = C->destination_exprs().begin(); - for (const Expr *IInit : C->private_copies()) { - // Keep the address of the original variable for future update at the end - // of the loop. - const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); - // Taskloops do not require additional initialization, it is done in - // runtime support library. - if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) { - const auto *DestVD = - cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl()); - PrivateScope.addPrivate(DestVD, [this, OrigVD, IRef]() { - DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD), - /*RefersToEnclosingVariableOrCapture=*/ - CapturedStmtInfo->lookup(OrigVD) != nullptr, - (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc()); - return EmitLValue(&DRE).getAddress(); - }); - // Check if the variable is also a firstprivate: in this case IInit is - // not generated. Initialization of this variable will happen in codegen - // for 'firstprivate' clause. - if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) { - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl()); - bool IsRegistered = PrivateScope.addPrivate(OrigVD, [this, VD]() { - // Emit private VarDecl with copy init. - EmitDecl(*VD); - return GetAddrOfLocalVar(VD); - }); - assert(IsRegistered && - "lastprivate var already registered as private"); - (void)IsRegistered; - } - } - ++IRef; - ++IDestRef; - } - } - return HasAtLeastOneLastprivate; -} - -void CodeGenFunction::EmitOMPLastprivateClauseFinal( - const OMPExecutableDirective &D, bool NoFinals, - llvm::Value *IsLastIterCond) { - if (!HaveInsertPoint()) - return; - // Emit following code: - // if (<IsLastIterCond>) { - // orig_var1 = private_orig_var1; - // ... - // orig_varn = private_orig_varn; - // } - llvm::BasicBlock *ThenBB = nullptr; - llvm::BasicBlock *DoneBB = nullptr; - if (IsLastIterCond) { - ThenBB = createBasicBlock(".omp.lastprivate.then"); - DoneBB = createBasicBlock(".omp.lastprivate.done"); - Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB); - EmitBlock(ThenBB); - } - llvm::DenseSet<const VarDecl *> AlreadyEmittedVars; - llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates; - if (const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) { - auto IC = LoopDirective->counters().begin(); - for (const Expr *F : LoopDirective->finals()) { - const auto *D = - cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl())->getCanonicalDecl(); - if (NoFinals) - AlreadyEmittedVars.insert(D); - else - LoopCountersAndUpdates[D] = F; - ++IC; - } - } - for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) { - auto IRef = C->varlist_begin(); - auto ISrcRef = C->source_exprs().begin(); - auto IDestRef = C->destination_exprs().begin(); - for (const Expr *AssignOp : C->assignment_ops()) { - const auto *PrivateVD = - cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); - QualType Type = PrivateVD->getType(); - const auto *CanonicalVD = PrivateVD->getCanonicalDecl(); - if (AlreadyEmittedVars.insert(CanonicalVD).second) { - // If lastprivate variable is a loop control variable for loop-based - // directive, update its value before copyin back to original - // variable. - if (const Expr *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD)) - EmitIgnoredExpr(FinalExpr); - const auto *SrcVD = - cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl()); - const auto *DestVD = - cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl()); - // Get the address of the original variable. - Address OriginalAddr = GetAddrOfLocalVar(DestVD); - // Get the address of the private variable. - Address PrivateAddr = GetAddrOfLocalVar(PrivateVD); - if (const auto *RefTy = PrivateVD->getType()->getAs<ReferenceType>()) - PrivateAddr = - Address(Builder.CreateLoad(PrivateAddr), - getNaturalTypeAlignment(RefTy->getPointeeType())); - EmitOMPCopy(Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp); - } - ++IRef; - ++ISrcRef; - ++IDestRef; - } - if (const Expr *PostUpdate = C->getPostUpdateExpr()) - EmitIgnoredExpr(PostUpdate); - } - if (IsLastIterCond) - EmitBlock(DoneBB, /*IsFinished=*/true); -} - -void CodeGenFunction::EmitOMPReductionClauseInit( - const OMPExecutableDirective &D, - CodeGenFunction::OMPPrivateScope &PrivateScope) { - if (!HaveInsertPoint()) - return; - SmallVector<const Expr *, 4> Shareds; - SmallVector<const Expr *, 4> Privates; - SmallVector<const Expr *, 4> ReductionOps; - SmallVector<const Expr *, 4> LHSs; - SmallVector<const Expr *, 4> RHSs; - for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) { - auto IPriv = C->privates().begin(); - auto IRed = C->reduction_ops().begin(); - auto ILHS = C->lhs_exprs().begin(); - auto IRHS = C->rhs_exprs().begin(); - for (const Expr *Ref : C->varlists()) { - Shareds.emplace_back(Ref); - Privates.emplace_back(*IPriv); - ReductionOps.emplace_back(*IRed); - LHSs.emplace_back(*ILHS); - RHSs.emplace_back(*IRHS); - std::advance(IPriv, 1); - std::advance(IRed, 1); - std::advance(ILHS, 1); - std::advance(IRHS, 1); - } - } - ReductionCodeGen RedCG(Shareds, Privates, ReductionOps); - unsigned Count = 0; - auto ILHS = LHSs.begin(); - auto IRHS = RHSs.begin(); - auto IPriv = Privates.begin(); - for (const Expr *IRef : Shareds) { - const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IPriv)->getDecl()); - // Emit private VarDecl with reduction init. - RedCG.emitSharedLValue(*this, Count); - RedCG.emitAggregateType(*this, Count); - AutoVarEmission Emission = EmitAutoVarAlloca(*PrivateVD); - RedCG.emitInitialization(*this, Count, Emission.getAllocatedAddress(), - RedCG.getSharedLValue(Count), - [&Emission](CodeGenFunction &CGF) { - CGF.EmitAutoVarInit(Emission); - return true; - }); - EmitAutoVarCleanups(Emission); - Address BaseAddr = RedCG.adjustPrivateAddress( - *this, Count, Emission.getAllocatedAddress()); - bool IsRegistered = PrivateScope.addPrivate( - RedCG.getBaseDecl(Count), [BaseAddr]() { return BaseAddr; }); - assert(IsRegistered && "private var already registered as private"); - // Silence the warning about unused variable. - (void)IsRegistered; - - const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); - const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); - QualType Type = PrivateVD->getType(); - bool isaOMPArraySectionExpr = isa<OMPArraySectionExpr>(IRef); - if (isaOMPArraySectionExpr && Type->isVariablyModifiedType()) { - // Store the address of the original variable associated with the LHS - // implicit variable. - PrivateScope.addPrivate(LHSVD, [&RedCG, Count]() { - return RedCG.getSharedLValue(Count).getAddress(); - }); - PrivateScope.addPrivate( - RHSVD, [this, PrivateVD]() { return GetAddrOfLocalVar(PrivateVD); }); - } else if ((isaOMPArraySectionExpr && Type->isScalarType()) || - isa<ArraySubscriptExpr>(IRef)) { - // Store the address of the original variable associated with the LHS - // implicit variable. - PrivateScope.addPrivate(LHSVD, [&RedCG, Count]() { - return RedCG.getSharedLValue(Count).getAddress(); - }); - PrivateScope.addPrivate(RHSVD, [this, PrivateVD, RHSVD]() { - return Builder.CreateElementBitCast(GetAddrOfLocalVar(PrivateVD), - ConvertTypeForMem(RHSVD->getType()), - "rhs.begin"); - }); - } else { - QualType Type = PrivateVD->getType(); - bool IsArray = getContext().getAsArrayType(Type) != nullptr; - Address OriginalAddr = RedCG.getSharedLValue(Count).getAddress(); - // Store the address of the original variable associated with the LHS - // implicit variable. - if (IsArray) { - OriginalAddr = Builder.CreateElementBitCast( - OriginalAddr, ConvertTypeForMem(LHSVD->getType()), "lhs.begin"); - } - PrivateScope.addPrivate(LHSVD, [OriginalAddr]() { return OriginalAddr; }); - PrivateScope.addPrivate( - RHSVD, [this, PrivateVD, RHSVD, IsArray]() { - return IsArray - ? Builder.CreateElementBitCast( - GetAddrOfLocalVar(PrivateVD), - ConvertTypeForMem(RHSVD->getType()), "rhs.begin") - : GetAddrOfLocalVar(PrivateVD); - }); - } - ++ILHS; - ++IRHS; - ++IPriv; - ++Count; - } -} - -void CodeGenFunction::EmitOMPReductionClauseFinal( - const OMPExecutableDirective &D, const OpenMPDirectiveKind ReductionKind) { - if (!HaveInsertPoint()) - return; - llvm::SmallVector<const Expr *, 8> Privates; - llvm::SmallVector<const Expr *, 8> LHSExprs; - llvm::SmallVector<const Expr *, 8> RHSExprs; - llvm::SmallVector<const Expr *, 8> ReductionOps; - bool HasAtLeastOneReduction = false; - for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) { - HasAtLeastOneReduction = true; - Privates.append(C->privates().begin(), C->privates().end()); - LHSExprs.append(C->lhs_exprs().begin(), C->lhs_exprs().end()); - RHSExprs.append(C->rhs_exprs().begin(), C->rhs_exprs().end()); - ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end()); - } - if (HasAtLeastOneReduction) { - bool WithNowait = D.getSingleClause<OMPNowaitClause>() || - isOpenMPParallelDirective(D.getDirectiveKind()) || - ReductionKind == OMPD_simd; - bool SimpleReduction = ReductionKind == OMPD_simd; - // Emit nowait reduction if nowait clause is present or directive is a - // parallel directive (it always has implicit barrier). - CGM.getOpenMPRuntime().emitReduction( - *this, D.getEndLoc(), Privates, LHSExprs, RHSExprs, ReductionOps, - {WithNowait, SimpleReduction, ReductionKind}); - } -} - -static void emitPostUpdateForReductionClause( - CodeGenFunction &CGF, const OMPExecutableDirective &D, - const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) { - if (!CGF.HaveInsertPoint()) - return; - llvm::BasicBlock *DoneBB = nullptr; - for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) { - if (const Expr *PostUpdate = C->getPostUpdateExpr()) { - if (!DoneBB) { - if (llvm::Value *Cond = CondGen(CGF)) { - // If the first post-update expression is found, emit conditional - // block if it was requested. - llvm::BasicBlock *ThenBB = CGF.createBasicBlock(".omp.reduction.pu"); - DoneBB = CGF.createBasicBlock(".omp.reduction.pu.done"); - CGF.Builder.CreateCondBr(Cond, ThenBB, DoneBB); - CGF.EmitBlock(ThenBB); - } - } - CGF.EmitIgnoredExpr(PostUpdate); - } - } - if (DoneBB) - CGF.EmitBlock(DoneBB, /*IsFinished=*/true); -} - -namespace { -/// Codegen lambda for appending distribute lower and upper bounds to outlined -/// parallel function. This is necessary for combined constructs such as -/// 'distribute parallel for' -typedef llvm::function_ref<void(CodeGenFunction &, - const OMPExecutableDirective &, - llvm::SmallVectorImpl<llvm::Value *> &)> - CodeGenBoundParametersTy; -} // anonymous namespace - -static void emitCommonOMPParallelDirective( - CodeGenFunction &CGF, const OMPExecutableDirective &S, - OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, - const CodeGenBoundParametersTy &CodeGenBoundParameters) { - const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel); - llvm::Value *OutlinedFn = - CGF.CGM.getOpenMPRuntime().emitParallelOutlinedFunction( - S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen); - if (const auto *NumThreadsClause = S.getSingleClause<OMPNumThreadsClause>()) { - CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); - llvm::Value *NumThreads = - CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(), - /*IgnoreResultAssign=*/true); - CGF.CGM.getOpenMPRuntime().emitNumThreadsClause( - CGF, NumThreads, NumThreadsClause->getBeginLoc()); - } - if (const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) { - CodeGenFunction::RunCleanupsScope ProcBindScope(CGF); - CGF.CGM.getOpenMPRuntime().emitProcBindClause( - CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc()); - } - const Expr *IfCond = nullptr; - for (const auto *C : S.getClausesOfKind<OMPIfClause>()) { - if (C->getNameModifier() == OMPD_unknown || - C->getNameModifier() == OMPD_parallel) { - IfCond = C->getCondition(); - break; - } - } - - OMPParallelScope Scope(CGF, S); - llvm::SmallVector<llvm::Value *, 16> CapturedVars; - // Combining 'distribute' with 'for' requires sharing each 'distribute' chunk - // lower and upper bounds with the pragma 'for' chunking mechanism. - // The following lambda takes care of appending the lower and upper bound - // parameters when necessary - CodeGenBoundParameters(CGF, S, CapturedVars); - CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars); - CGF.CGM.getOpenMPRuntime().emitParallelCall(CGF, S.getBeginLoc(), OutlinedFn, - CapturedVars, IfCond); -} - -static void emitEmptyBoundParameters(CodeGenFunction &, - const OMPExecutableDirective &, - llvm::SmallVectorImpl<llvm::Value *> &) {} - -void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) { - // Emit parallel region as a standalone region. - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - Action.Enter(CGF); - OMPPrivateScope PrivateScope(CGF); - bool Copyins = CGF.EmitOMPCopyinClause(S); - (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope); - if (Copyins) { - // Emit implicit barrier to synchronize threads and avoid data races on - // propagation master's thread values of threadprivate variables to local - // instances of that variables of all other implicit threads. - CGF.CGM.getOpenMPRuntime().emitBarrierCall( - CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false, - /*ForceSimpleCall=*/true); - } - CGF.EmitOMPPrivateClause(S, PrivateScope); - CGF.EmitOMPReductionClauseInit(S, PrivateScope); - (void)PrivateScope.Privatize(); - CGF.EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt()); - CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel); - }; - emitCommonOMPParallelDirective(*this, S, OMPD_parallel, CodeGen, - emitEmptyBoundParameters); - emitPostUpdateForReductionClause(*this, S, - [](CodeGenFunction &) { return nullptr; }); -} - -void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D, - JumpDest LoopExit) { - RunCleanupsScope BodyScope(*this); - // Update counters values on current iteration. - for (const Expr *UE : D.updates()) - EmitIgnoredExpr(UE); - // Update the linear variables. - // In distribute directives only loop counters may be marked as linear, no - // need to generate the code for them. - if (!isOpenMPDistributeDirective(D.getDirectiveKind())) { - for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) { - for (const Expr *UE : C->updates()) - EmitIgnoredExpr(UE); - } - } - - // On a continue in the body, jump to the end. - JumpDest Continue = getJumpDestInCurrentScope("omp.body.continue"); - BreakContinueStack.push_back(BreakContinue(LoopExit, Continue)); - // Emit loop body. - EmitStmt(D.getBody()); - // The end (updates/cleanups). - EmitBlock(Continue.getBlock()); - BreakContinueStack.pop_back(); -} - -void CodeGenFunction::EmitOMPInnerLoop( - const Stmt &S, bool RequiresCleanup, const Expr *LoopCond, - const Expr *IncExpr, - const llvm::function_ref<void(CodeGenFunction &)> BodyGen, - const llvm::function_ref<void(CodeGenFunction &)> PostIncGen) { - auto LoopExit = getJumpDestInCurrentScope("omp.inner.for.end"); - - // Start the loop with a block that tests the condition. - auto CondBlock = createBasicBlock("omp.inner.for.cond"); - EmitBlock(CondBlock); - const SourceRange R = S.getSourceRange(); - LoopStack.push(CondBlock, SourceLocToDebugLoc(R.getBegin()), - SourceLocToDebugLoc(R.getEnd())); - - // If there are any cleanups between here and the loop-exit scope, - // create a block to stage a loop exit along. - llvm::BasicBlock *ExitBlock = LoopExit.getBlock(); - if (RequiresCleanup) - ExitBlock = createBasicBlock("omp.inner.for.cond.cleanup"); - - llvm::BasicBlock *LoopBody = createBasicBlock("omp.inner.for.body"); - - // Emit condition. - EmitBranchOnBoolExpr(LoopCond, LoopBody, ExitBlock, getProfileCount(&S)); - if (ExitBlock != LoopExit.getBlock()) { - EmitBlock(ExitBlock); - EmitBranchThroughCleanup(LoopExit); - } - - EmitBlock(LoopBody); - incrementProfileCounter(&S); - - // Create a block for the increment. - JumpDest Continue = getJumpDestInCurrentScope("omp.inner.for.inc"); - BreakContinueStack.push_back(BreakContinue(LoopExit, Continue)); - - BodyGen(*this); - - // Emit "IV = IV + 1" and a back-edge to the condition block. - EmitBlock(Continue.getBlock()); - EmitIgnoredExpr(IncExpr); - PostIncGen(*this); - BreakContinueStack.pop_back(); - EmitBranch(CondBlock); - LoopStack.pop(); - // Emit the fall-through block. - EmitBlock(LoopExit.getBlock()); -} - -bool CodeGenFunction::EmitOMPLinearClauseInit(const OMPLoopDirective &D) { - if (!HaveInsertPoint()) - return false; - // Emit inits for the linear variables. - bool HasLinears = false; - for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) { - for (const Expr *Init : C->inits()) { - HasLinears = true; - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(Init)->getDecl()); - if (const auto *Ref = - dyn_cast<DeclRefExpr>(VD->getInit()->IgnoreImpCasts())) { - AutoVarEmission Emission = EmitAutoVarAlloca(*VD); - const auto *OrigVD = cast<VarDecl>(Ref->getDecl()); - DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD), - CapturedStmtInfo->lookup(OrigVD) != nullptr, - VD->getInit()->getType(), VK_LValue, - VD->getInit()->getExprLoc()); - EmitExprAsInit(&DRE, VD, MakeAddrLValue(Emission.getAllocatedAddress(), - VD->getType()), - /*capturedByInit=*/false); - EmitAutoVarCleanups(Emission); - } else { - EmitVarDecl(*VD); - } - } - // Emit the linear steps for the linear clauses. - // If a step is not constant, it is pre-calculated before the loop. - if (const auto *CS = cast_or_null<BinaryOperator>(C->getCalcStep())) - if (const auto *SaveRef = cast<DeclRefExpr>(CS->getLHS())) { - EmitVarDecl(*cast<VarDecl>(SaveRef->getDecl())); - // Emit calculation of the linear step. - EmitIgnoredExpr(CS); - } - } - return HasLinears; -} - -void CodeGenFunction::EmitOMPLinearClauseFinal( - const OMPLoopDirective &D, - const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) { - if (!HaveInsertPoint()) - return; - llvm::BasicBlock *DoneBB = nullptr; - // Emit the final values of the linear variables. - for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) { - auto IC = C->varlist_begin(); - for (const Expr *F : C->finals()) { - if (!DoneBB) { - if (llvm::Value *Cond = CondGen(*this)) { - // If the first post-update expression is found, emit conditional - // block if it was requested. - llvm::BasicBlock *ThenBB = createBasicBlock(".omp.linear.pu"); - DoneBB = createBasicBlock(".omp.linear.pu.done"); - Builder.CreateCondBr(Cond, ThenBB, DoneBB); - EmitBlock(ThenBB); - } - } - const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl()); - DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD), - CapturedStmtInfo->lookup(OrigVD) != nullptr, - (*IC)->getType(), VK_LValue, (*IC)->getExprLoc()); - Address OrigAddr = EmitLValue(&DRE).getAddress(); - CodeGenFunction::OMPPrivateScope VarScope(*this); - VarScope.addPrivate(OrigVD, [OrigAddr]() { return OrigAddr; }); - (void)VarScope.Privatize(); - EmitIgnoredExpr(F); - ++IC; - } - if (const Expr *PostUpdate = C->getPostUpdateExpr()) - EmitIgnoredExpr(PostUpdate); - } - if (DoneBB) - EmitBlock(DoneBB, /*IsFinished=*/true); -} - -static void emitAlignedClause(CodeGenFunction &CGF, - const OMPExecutableDirective &D) { - if (!CGF.HaveInsertPoint()) - return; - for (const auto *Clause : D.getClausesOfKind<OMPAlignedClause>()) { - unsigned ClauseAlignment = 0; - if (const Expr *AlignmentExpr = Clause->getAlignment()) { - auto *AlignmentCI = - cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr)); - ClauseAlignment = static_cast<unsigned>(AlignmentCI->getZExtValue()); - } - for (const Expr *E : Clause->varlists()) { - unsigned Alignment = ClauseAlignment; - if (Alignment == 0) { - // OpenMP [2.8.1, Description] - // If no optional parameter is specified, implementation-defined default - // alignments for SIMD instructions on the target platforms are assumed. - Alignment = - CGF.getContext() - .toCharUnitsFromBits(CGF.getContext().getOpenMPDefaultSimdAlign( - E->getType()->getPointeeType())) - .getQuantity(); - } - assert((Alignment == 0 || llvm::isPowerOf2_32(Alignment)) && - "alignment is not power of 2"); - if (Alignment != 0) { - llvm::Value *PtrValue = CGF.EmitScalarExpr(E); - CGF.EmitAlignmentAssumption( - PtrValue, E, /*No second loc needed*/ SourceLocation(), Alignment); - } - } - } -} - -void CodeGenFunction::EmitOMPPrivateLoopCounters( - const OMPLoopDirective &S, CodeGenFunction::OMPPrivateScope &LoopScope) { - if (!HaveInsertPoint()) - return; - auto I = S.private_counters().begin(); - for (const Expr *E : S.counters()) { - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()); - // Emit var without initialization. - AutoVarEmission VarEmission = EmitAutoVarAlloca(*PrivateVD); - EmitAutoVarCleanups(VarEmission); - LocalDeclMap.erase(PrivateVD); - (void)LoopScope.addPrivate(VD, [&VarEmission]() { - return VarEmission.getAllocatedAddress(); - }); - if (LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD) || - VD->hasGlobalStorage()) { - (void)LoopScope.addPrivate(PrivateVD, [this, VD, E]() { - DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(VD), - LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD), - E->getType(), VK_LValue, E->getExprLoc()); - return EmitLValue(&DRE).getAddress(); - }); - } else { - (void)LoopScope.addPrivate(PrivateVD, [&VarEmission]() { - return VarEmission.getAllocatedAddress(); - }); - } - ++I; - } - // Privatize extra loop counters used in loops for ordered(n) clauses. - for (const auto *C : S.getClausesOfKind<OMPOrderedClause>()) { - if (!C->getNumForLoops()) - continue; - for (unsigned I = S.getCollapsedNumber(), - E = C->getLoopNumIterations().size(); - I < E; ++I) { - const auto *DRE = cast<DeclRefExpr>(C->getLoopCounter(I)); - const auto *VD = cast<VarDecl>(DRE->getDecl()); - // Override only those variables that can be captured to avoid re-emission - // of the variables declared within the loops. - if (DRE->refersToEnclosingVariableOrCapture()) { - (void)LoopScope.addPrivate(VD, [this, DRE, VD]() { - return CreateMemTemp(DRE->getType(), VD->getName()); - }); - } - } - } -} - -static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S, - const Expr *Cond, llvm::BasicBlock *TrueBlock, - llvm::BasicBlock *FalseBlock, uint64_t TrueCount) { - if (!CGF.HaveInsertPoint()) - return; - { - CodeGenFunction::OMPPrivateScope PreCondScope(CGF); - CGF.EmitOMPPrivateLoopCounters(S, PreCondScope); - (void)PreCondScope.Privatize(); - // Get initial values of real counters. - for (const Expr *I : S.inits()) { - CGF.EmitIgnoredExpr(I); - } - } - // Check that loop is executed at least one time. - CGF.EmitBranchOnBoolExpr(Cond, TrueBlock, FalseBlock, TrueCount); -} - -void CodeGenFunction::EmitOMPLinearClause( - const OMPLoopDirective &D, CodeGenFunction::OMPPrivateScope &PrivateScope) { - if (!HaveInsertPoint()) - return; - llvm::DenseSet<const VarDecl *> SIMDLCVs; - if (isOpenMPSimdDirective(D.getDirectiveKind())) { - const auto *LoopDirective = cast<OMPLoopDirective>(&D); - for (const Expr *C : LoopDirective->counters()) { - SIMDLCVs.insert( - cast<VarDecl>(cast<DeclRefExpr>(C)->getDecl())->getCanonicalDecl()); - } - } - for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) { - auto CurPrivate = C->privates().begin(); - for (const Expr *E : C->varlists()) { - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - const auto *PrivateVD = - cast<VarDecl>(cast<DeclRefExpr>(*CurPrivate)->getDecl()); - if (!SIMDLCVs.count(VD->getCanonicalDecl())) { - bool IsRegistered = PrivateScope.addPrivate(VD, [this, PrivateVD]() { - // Emit private VarDecl with copy init. - EmitVarDecl(*PrivateVD); - return GetAddrOfLocalVar(PrivateVD); - }); - assert(IsRegistered && "linear var already registered as private"); - // Silence the warning about unused variable. - (void)IsRegistered; - } else { - EmitVarDecl(*PrivateVD); - } - ++CurPrivate; - } - } -} - -static void emitSimdlenSafelenClause(CodeGenFunction &CGF, - const OMPExecutableDirective &D, - bool IsMonotonic) { - if (!CGF.HaveInsertPoint()) - return; - if (const auto *C = D.getSingleClause<OMPSimdlenClause>()) { - RValue Len = CGF.EmitAnyExpr(C->getSimdlen(), AggValueSlot::ignored(), - /*ignoreResult=*/true); - auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal()); - CGF.LoopStack.setVectorizeWidth(Val->getZExtValue()); - // In presence of finite 'safelen', it may be unsafe to mark all - // the memory instructions parallel, because loop-carried - // dependences of 'safelen' iterations are possible. - if (!IsMonotonic) - CGF.LoopStack.setParallel(!D.getSingleClause<OMPSafelenClause>()); - } else if (const auto *C = D.getSingleClause<OMPSafelenClause>()) { - RValue Len = CGF.EmitAnyExpr(C->getSafelen(), AggValueSlot::ignored(), - /*ignoreResult=*/true); - auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal()); - CGF.LoopStack.setVectorizeWidth(Val->getZExtValue()); - // In presence of finite 'safelen', it may be unsafe to mark all - // the memory instructions parallel, because loop-carried - // dependences of 'safelen' iterations are possible. - CGF.LoopStack.setParallel(/*Enable=*/false); - } -} - -void CodeGenFunction::EmitOMPSimdInit(const OMPLoopDirective &D, - bool IsMonotonic) { - // Walk clauses and process safelen/lastprivate. - LoopStack.setParallel(!IsMonotonic); - LoopStack.setVectorizeEnable(); - emitSimdlenSafelenClause(*this, D, IsMonotonic); -} - -void CodeGenFunction::EmitOMPSimdFinal( - const OMPLoopDirective &D, - const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) { - if (!HaveInsertPoint()) - return; - llvm::BasicBlock *DoneBB = nullptr; - auto IC = D.counters().begin(); - auto IPC = D.private_counters().begin(); - for (const Expr *F : D.finals()) { - const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>((*IC))->getDecl()); - const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>((*IPC))->getDecl()); - const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD); - if (LocalDeclMap.count(OrigVD) || CapturedStmtInfo->lookup(OrigVD) || - OrigVD->hasGlobalStorage() || CED) { - if (!DoneBB) { - if (llvm::Value *Cond = CondGen(*this)) { - // If the first post-update expression is found, emit conditional - // block if it was requested. - llvm::BasicBlock *ThenBB = createBasicBlock(".omp.final.then"); - DoneBB = createBasicBlock(".omp.final.done"); - Builder.CreateCondBr(Cond, ThenBB, DoneBB); - EmitBlock(ThenBB); - } - } - Address OrigAddr = Address::invalid(); - if (CED) { - OrigAddr = EmitLValue(CED->getInit()->IgnoreImpCasts()).getAddress(); - } else { - DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(PrivateVD), - /*RefersToEnclosingVariableOrCapture=*/false, - (*IPC)->getType(), VK_LValue, (*IPC)->getExprLoc()); - OrigAddr = EmitLValue(&DRE).getAddress(); - } - OMPPrivateScope VarScope(*this); - VarScope.addPrivate(OrigVD, [OrigAddr]() { return OrigAddr; }); - (void)VarScope.Privatize(); - EmitIgnoredExpr(F); - } - ++IC; - ++IPC; - } - if (DoneBB) - EmitBlock(DoneBB, /*IsFinished=*/true); -} - -static void emitOMPLoopBodyWithStopPoint(CodeGenFunction &CGF, - const OMPLoopDirective &S, - CodeGenFunction::JumpDest LoopExit) { - CGF.EmitOMPLoopBody(S, LoopExit); - CGF.EmitStopPoint(&S); -} - -/// Emit a helper variable and return corresponding lvalue. -static LValue EmitOMPHelperVar(CodeGenFunction &CGF, - const DeclRefExpr *Helper) { - auto VDecl = cast<VarDecl>(Helper->getDecl()); - CGF.EmitVarDecl(*VDecl); - return CGF.EmitLValue(Helper); -} - -static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S, - PrePostActionTy &Action) { - Action.Enter(CGF); - assert(isOpenMPSimdDirective(S.getDirectiveKind()) && - "Expected simd directive"); - OMPLoopScope PreInitScope(CGF, S); - // if (PreCond) { - // for (IV in 0..LastIteration) BODY; - // <Final counter/linear vars updates>; - // } - // - if (isOpenMPDistributeDirective(S.getDirectiveKind()) || - isOpenMPWorksharingDirective(S.getDirectiveKind()) || - isOpenMPTaskLoopDirective(S.getDirectiveKind())) { - (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable())); - (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable())); - } - - // Emit: if (PreCond) - begin. - // If the condition constant folds and can be elided, avoid emitting the - // whole loop. - bool CondConstant; - llvm::BasicBlock *ContBlock = nullptr; - if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) { - if (!CondConstant) - return; - } else { - llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("simd.if.then"); - ContBlock = CGF.createBasicBlock("simd.if.end"); - emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock, - CGF.getProfileCount(&S)); - CGF.EmitBlock(ThenBlock); - CGF.incrementProfileCounter(&S); - } - - // Emit the loop iteration variable. - const Expr *IVExpr = S.getIterationVariable(); - const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl()); - CGF.EmitVarDecl(*IVDecl); - CGF.EmitIgnoredExpr(S.getInit()); - - // Emit the iterations count variable. - // If it is not a variable, Sema decided to calculate iterations count on - // each iteration (e.g., it is foldable into a constant). - if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) { - CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl())); - // Emit calculation of the iterations count. - CGF.EmitIgnoredExpr(S.getCalcLastIteration()); - } - - CGF.EmitOMPSimdInit(S); - - emitAlignedClause(CGF, S); - (void)CGF.EmitOMPLinearClauseInit(S); - { - CodeGenFunction::OMPPrivateScope LoopScope(CGF); - CGF.EmitOMPPrivateLoopCounters(S, LoopScope); - CGF.EmitOMPLinearClause(S, LoopScope); - CGF.EmitOMPPrivateClause(S, LoopScope); - CGF.EmitOMPReductionClauseInit(S, LoopScope); - bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope); - (void)LoopScope.Privatize(); - if (isOpenMPTargetExecutionDirective(S.getDirectiveKind())) - CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S); - CGF.EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(), - S.getInc(), - [&S](CodeGenFunction &CGF) { - CGF.EmitOMPLoopBody(S, CodeGenFunction::JumpDest()); - CGF.EmitStopPoint(&S); - }, - [](CodeGenFunction &) {}); - CGF.EmitOMPSimdFinal(S, [](CodeGenFunction &) { return nullptr; }); - // Emit final copy of the lastprivate variables at the end of loops. - if (HasLastprivateClause) - CGF.EmitOMPLastprivateClauseFinal(S, /*NoFinals=*/true); - CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_simd); - emitPostUpdateForReductionClause(CGF, S, - [](CodeGenFunction &) { return nullptr; }); - } - CGF.EmitOMPLinearClauseFinal(S, [](CodeGenFunction &) { return nullptr; }); - // Emit: if (PreCond) - end. - if (ContBlock) { - CGF.EmitBranch(ContBlock); - CGF.EmitBlock(ContBlock, true); - } -} - -void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitOMPSimdRegion(CGF, S, Action); - }; - OMPLexicalScope Scope(*this, S, OMPD_unknown); - CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen); -} - -void CodeGenFunction::EmitOMPOuterLoop( - bool DynamicOrOrdered, bool IsMonotonic, const OMPLoopDirective &S, - CodeGenFunction::OMPPrivateScope &LoopScope, - const CodeGenFunction::OMPLoopArguments &LoopArgs, - const CodeGenFunction::CodeGenLoopTy &CodeGenLoop, - const CodeGenFunction::CodeGenOrderedTy &CodeGenOrdered) { - CGOpenMPRuntime &RT = CGM.getOpenMPRuntime(); - - const Expr *IVExpr = S.getIterationVariable(); - const unsigned IVSize = getContext().getTypeSize(IVExpr->getType()); - const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation(); - - JumpDest LoopExit = getJumpDestInCurrentScope("omp.dispatch.end"); - - // Start the loop with a block that tests the condition. - llvm::BasicBlock *CondBlock = createBasicBlock("omp.dispatch.cond"); - EmitBlock(CondBlock); - const SourceRange R = S.getSourceRange(); - LoopStack.push(CondBlock, SourceLocToDebugLoc(R.getBegin()), - SourceLocToDebugLoc(R.getEnd())); - - llvm::Value *BoolCondVal = nullptr; - if (!DynamicOrOrdered) { - // UB = min(UB, GlobalUB) or - // UB = min(UB, PrevUB) for combined loop sharing constructs (e.g. - // 'distribute parallel for') - EmitIgnoredExpr(LoopArgs.EUB); - // IV = LB - EmitIgnoredExpr(LoopArgs.Init); - // IV < UB - BoolCondVal = EvaluateExprAsBool(LoopArgs.Cond); - } else { - BoolCondVal = - RT.emitForNext(*this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL, - LoopArgs.LB, LoopArgs.UB, LoopArgs.ST); - } - - // If there are any cleanups between here and the loop-exit scope, - // create a block to stage a loop exit along. - llvm::BasicBlock *ExitBlock = LoopExit.getBlock(); - if (LoopScope.requiresCleanups()) - ExitBlock = createBasicBlock("omp.dispatch.cleanup"); - - llvm::BasicBlock *LoopBody = createBasicBlock("omp.dispatch.body"); - Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock); - if (ExitBlock != LoopExit.getBlock()) { - EmitBlock(ExitBlock); - EmitBranchThroughCleanup(LoopExit); - } - EmitBlock(LoopBody); - - // Emit "IV = LB" (in case of static schedule, we have already calculated new - // LB for loop condition and emitted it above). - if (DynamicOrOrdered) - EmitIgnoredExpr(LoopArgs.Init); - - // Create a block for the increment. - JumpDest Continue = getJumpDestInCurrentScope("omp.dispatch.inc"); - BreakContinueStack.push_back(BreakContinue(LoopExit, Continue)); - - // Generate !llvm.loop.parallel metadata for loads and stores for loops - // with dynamic/guided scheduling and without ordered clause. - if (!isOpenMPSimdDirective(S.getDirectiveKind())) - LoopStack.setParallel(!IsMonotonic); - else - EmitOMPSimdInit(S, IsMonotonic); - - SourceLocation Loc = S.getBeginLoc(); - - // when 'distribute' is not combined with a 'for': - // while (idx <= UB) { BODY; ++idx; } - // when 'distribute' is combined with a 'for' - // (e.g. 'distribute parallel for') - // while (idx <= UB) { <CodeGen rest of pragma>; idx += ST; } - EmitOMPInnerLoop( - S, LoopScope.requiresCleanups(), LoopArgs.Cond, LoopArgs.IncExpr, - [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) { - CodeGenLoop(CGF, S, LoopExit); - }, - [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) { - CodeGenOrdered(CGF, Loc, IVSize, IVSigned); - }); - - EmitBlock(Continue.getBlock()); - BreakContinueStack.pop_back(); - if (!DynamicOrOrdered) { - // Emit "LB = LB + Stride", "UB = UB + Stride". - EmitIgnoredExpr(LoopArgs.NextLB); - EmitIgnoredExpr(LoopArgs.NextUB); - } - - EmitBranch(CondBlock); - LoopStack.pop(); - // Emit the fall-through block. - EmitBlock(LoopExit.getBlock()); - - // Tell the runtime we are done. - auto &&CodeGen = [DynamicOrOrdered, &S](CodeGenFunction &CGF) { - if (!DynamicOrOrdered) - CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(), - S.getDirectiveKind()); - }; - OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen); -} - -void CodeGenFunction::EmitOMPForOuterLoop( - const OpenMPScheduleTy &ScheduleKind, bool IsMonotonic, - const OMPLoopDirective &S, OMPPrivateScope &LoopScope, bool Ordered, - const OMPLoopArguments &LoopArgs, - const CodeGenDispatchBoundsTy &CGDispatchBounds) { - CGOpenMPRuntime &RT = CGM.getOpenMPRuntime(); - - // Dynamic scheduling of the outer loop (dynamic, guided, auto, runtime). - const bool DynamicOrOrdered = - Ordered || RT.isDynamic(ScheduleKind.Schedule); - - assert((Ordered || - !RT.isStaticNonchunked(ScheduleKind.Schedule, - LoopArgs.Chunk != nullptr)) && - "static non-chunked schedule does not need outer loop"); - - // Emit outer loop. - // - // OpenMP [2.7.1, Loop Construct, Description, table 2-1] - // When schedule(dynamic,chunk_size) is specified, the iterations are - // distributed to threads in the team in chunks as the threads request them. - // Each thread executes a chunk of iterations, then requests another chunk, - // until no chunks remain to be distributed. Each chunk contains chunk_size - // iterations, except for the last chunk to be distributed, which may have - // fewer iterations. When no chunk_size is specified, it defaults to 1. - // - // When schedule(guided,chunk_size) is specified, the iterations are assigned - // to threads in the team in chunks as the executing threads request them. - // Each thread executes a chunk of iterations, then requests another chunk, - // until no chunks remain to be assigned. For a chunk_size of 1, the size of - // each chunk is proportional to the number of unassigned iterations divided - // by the number of threads in the team, decreasing to 1. For a chunk_size - // with value k (greater than 1), the size of each chunk is determined in the - // same way, with the restriction that the chunks do not contain fewer than k - // iterations (except for the last chunk to be assigned, which may have fewer - // than k iterations). - // - // When schedule(auto) is specified, the decision regarding scheduling is - // delegated to the compiler and/or runtime system. The programmer gives the - // implementation the freedom to choose any possible mapping of iterations to - // threads in the team. - // - // When schedule(runtime) is specified, the decision regarding scheduling is - // deferred until run time, and the schedule and chunk size are taken from the - // run-sched-var ICV. If the ICV is set to auto, the schedule is - // implementation defined - // - // while(__kmpc_dispatch_next(&LB, &UB)) { - // idx = LB; - // while (idx <= UB) { BODY; ++idx; - // __kmpc_dispatch_fini_(4|8)[u](); // For ordered loops only. - // } // inner loop - // } - // - // OpenMP [2.7.1, Loop Construct, Description, table 2-1] - // When schedule(static, chunk_size) is specified, iterations are divided into - // chunks of size chunk_size, and the chunks are assigned to the threads in - // the team in a round-robin fashion in the order of the thread number. - // - // while(UB = min(UB, GlobalUB), idx = LB, idx < UB) { - // while (idx <= UB) { BODY; ++idx; } // inner loop - // LB = LB + ST; - // UB = UB + ST; - // } - // - - const Expr *IVExpr = S.getIterationVariable(); - const unsigned IVSize = getContext().getTypeSize(IVExpr->getType()); - const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation(); - - if (DynamicOrOrdered) { - const std::pair<llvm::Value *, llvm::Value *> DispatchBounds = - CGDispatchBounds(*this, S, LoopArgs.LB, LoopArgs.UB); - llvm::Value *LBVal = DispatchBounds.first; - llvm::Value *UBVal = DispatchBounds.second; - CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal, - LoopArgs.Chunk}; - RT.emitForDispatchInit(*this, S.getBeginLoc(), ScheduleKind, IVSize, - IVSigned, Ordered, DipatchRTInputValues); - } else { - CGOpenMPRuntime::StaticRTInput StaticInit( - IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB, - LoopArgs.ST, LoopArgs.Chunk); - RT.emitForStaticInit(*this, S.getBeginLoc(), S.getDirectiveKind(), - ScheduleKind, StaticInit); - } - - auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc, - const unsigned IVSize, - const bool IVSigned) { - if (Ordered) { - CGF.CGM.getOpenMPRuntime().emitForOrderedIterationEnd(CGF, Loc, IVSize, - IVSigned); - } - }; - - OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST, - LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB); - OuterLoopArgs.IncExpr = S.getInc(); - OuterLoopArgs.Init = S.getInit(); - OuterLoopArgs.Cond = S.getCond(); - OuterLoopArgs.NextLB = S.getNextLowerBound(); - OuterLoopArgs.NextUB = S.getNextUpperBound(); - EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs, - emitOMPLoopBodyWithStopPoint, CodeGenOrdered); -} - -static void emitEmptyOrdered(CodeGenFunction &, SourceLocation Loc, - const unsigned IVSize, const bool IVSigned) {} - -void CodeGenFunction::EmitOMPDistributeOuterLoop( - OpenMPDistScheduleClauseKind ScheduleKind, const OMPLoopDirective &S, - OMPPrivateScope &LoopScope, const OMPLoopArguments &LoopArgs, - const CodeGenLoopTy &CodeGenLoopContent) { - - CGOpenMPRuntime &RT = CGM.getOpenMPRuntime(); - - // Emit outer loop. - // Same behavior as a OMPForOuterLoop, except that schedule cannot be - // dynamic - // - - const Expr *IVExpr = S.getIterationVariable(); - const unsigned IVSize = getContext().getTypeSize(IVExpr->getType()); - const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation(); - - CGOpenMPRuntime::StaticRTInput StaticInit( - IVSize, IVSigned, /* Ordered = */ false, LoopArgs.IL, LoopArgs.LB, - LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk); - RT.emitDistributeStaticInit(*this, S.getBeginLoc(), ScheduleKind, StaticInit); - - // for combined 'distribute' and 'for' the increment expression of distribute - // is stored in DistInc. For 'distribute' alone, it is in Inc. - Expr *IncExpr; - if (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())) - IncExpr = S.getDistInc(); - else - IncExpr = S.getInc(); - - // this routine is shared by 'omp distribute parallel for' and - // 'omp distribute': select the right EUB expression depending on the - // directive - OMPLoopArguments OuterLoopArgs; - OuterLoopArgs.LB = LoopArgs.LB; - OuterLoopArgs.UB = LoopArgs.UB; - OuterLoopArgs.ST = LoopArgs.ST; - OuterLoopArgs.IL = LoopArgs.IL; - OuterLoopArgs.Chunk = LoopArgs.Chunk; - OuterLoopArgs.EUB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) - ? S.getCombinedEnsureUpperBound() - : S.getEnsureUpperBound(); - OuterLoopArgs.IncExpr = IncExpr; - OuterLoopArgs.Init = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) - ? S.getCombinedInit() - : S.getInit(); - OuterLoopArgs.Cond = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) - ? S.getCombinedCond() - : S.getCond(); - OuterLoopArgs.NextLB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) - ? S.getCombinedNextLowerBound() - : S.getNextLowerBound(); - OuterLoopArgs.NextUB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) - ? S.getCombinedNextUpperBound() - : S.getNextUpperBound(); - - EmitOMPOuterLoop(/* DynamicOrOrdered = */ false, /* IsMonotonic = */ false, S, - LoopScope, OuterLoopArgs, CodeGenLoopContent, - emitEmptyOrdered); -} - -static std::pair<LValue, LValue> -emitDistributeParallelForInnerBounds(CodeGenFunction &CGF, - const OMPExecutableDirective &S) { - const OMPLoopDirective &LS = cast<OMPLoopDirective>(S); - LValue LB = - EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getLowerBoundVariable())); - LValue UB = - EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getUpperBoundVariable())); - - // When composing 'distribute' with 'for' (e.g. as in 'distribute - // parallel for') we need to use the 'distribute' - // chunk lower and upper bounds rather than the whole loop iteration - // space. These are parameters to the outlined function for 'parallel' - // and we copy the bounds of the previous schedule into the - // the current ones. - LValue PrevLB = CGF.EmitLValue(LS.getPrevLowerBoundVariable()); - LValue PrevUB = CGF.EmitLValue(LS.getPrevUpperBoundVariable()); - llvm::Value *PrevLBVal = CGF.EmitLoadOfScalar( - PrevLB, LS.getPrevLowerBoundVariable()->getExprLoc()); - PrevLBVal = CGF.EmitScalarConversion( - PrevLBVal, LS.getPrevLowerBoundVariable()->getType(), - LS.getIterationVariable()->getType(), - LS.getPrevLowerBoundVariable()->getExprLoc()); - llvm::Value *PrevUBVal = CGF.EmitLoadOfScalar( - PrevUB, LS.getPrevUpperBoundVariable()->getExprLoc()); - PrevUBVal = CGF.EmitScalarConversion( - PrevUBVal, LS.getPrevUpperBoundVariable()->getType(), - LS.getIterationVariable()->getType(), - LS.getPrevUpperBoundVariable()->getExprLoc()); - - CGF.EmitStoreOfScalar(PrevLBVal, LB); - CGF.EmitStoreOfScalar(PrevUBVal, UB); - - return {LB, UB}; -} - -/// if the 'for' loop has a dispatch schedule (e.g. dynamic, guided) then -/// we need to use the LB and UB expressions generated by the worksharing -/// code generation support, whereas in non combined situations we would -/// just emit 0 and the LastIteration expression -/// This function is necessary due to the difference of the LB and UB -/// types for the RT emission routines for 'for_static_init' and -/// 'for_dispatch_init' -static std::pair<llvm::Value *, llvm::Value *> -emitDistributeParallelForDispatchBounds(CodeGenFunction &CGF, - const OMPExecutableDirective &S, - Address LB, Address UB) { - const OMPLoopDirective &LS = cast<OMPLoopDirective>(S); - const Expr *IVExpr = LS.getIterationVariable(); - // when implementing a dynamic schedule for a 'for' combined with a - // 'distribute' (e.g. 'distribute parallel for'), the 'for' loop - // is not normalized as each team only executes its own assigned - // distribute chunk - QualType IteratorTy = IVExpr->getType(); - llvm::Value *LBVal = - CGF.EmitLoadOfScalar(LB, /*Volatile=*/false, IteratorTy, S.getBeginLoc()); - llvm::Value *UBVal = - CGF.EmitLoadOfScalar(UB, /*Volatile=*/false, IteratorTy, S.getBeginLoc()); - return {LBVal, UBVal}; -} - -static void emitDistributeParallelForDistributeInnerBoundParams( - CodeGenFunction &CGF, const OMPExecutableDirective &S, - llvm::SmallVectorImpl<llvm::Value *> &CapturedVars) { - const auto &Dir = cast<OMPLoopDirective>(S); - LValue LB = - CGF.EmitLValue(cast<DeclRefExpr>(Dir.getCombinedLowerBoundVariable())); - llvm::Value *LBCast = CGF.Builder.CreateIntCast( - CGF.Builder.CreateLoad(LB.getAddress()), CGF.SizeTy, /*isSigned=*/false); - CapturedVars.push_back(LBCast); - LValue UB = - CGF.EmitLValue(cast<DeclRefExpr>(Dir.getCombinedUpperBoundVariable())); - - llvm::Value *UBCast = CGF.Builder.CreateIntCast( - CGF.Builder.CreateLoad(UB.getAddress()), CGF.SizeTy, /*isSigned=*/false); - CapturedVars.push_back(UBCast); -} - -static void -emitInnerParallelForWhenCombined(CodeGenFunction &CGF, - const OMPLoopDirective &S, - CodeGenFunction::JumpDest LoopExit) { - auto &&CGInlinedWorksharingLoop = [&S](CodeGenFunction &CGF, - PrePostActionTy &Action) { - Action.Enter(CGF); - bool HasCancel = false; - if (!isOpenMPSimdDirective(S.getDirectiveKind())) { - if (const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S)) - HasCancel = D->hasCancel(); - else if (const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S)) - HasCancel = D->hasCancel(); - else if (const auto *D = - dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S)) - HasCancel = D->hasCancel(); - } - CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, S.getDirectiveKind(), - HasCancel); - CGF.EmitOMPWorksharingLoop(S, S.getPrevEnsureUpperBound(), - emitDistributeParallelForInnerBounds, - emitDistributeParallelForDispatchBounds); - }; - - emitCommonOMPParallelDirective( - CGF, S, - isOpenMPSimdDirective(S.getDirectiveKind()) ? OMPD_for_simd : OMPD_for, - CGInlinedWorksharingLoop, - emitDistributeParallelForDistributeInnerBoundParams); -} - -void CodeGenFunction::EmitOMPDistributeParallelForDirective( - const OMPDistributeParallelForDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { - CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined, - S.getDistInc()); - }; - OMPLexicalScope Scope(*this, S, OMPD_parallel); - CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen); -} - -void CodeGenFunction::EmitOMPDistributeParallelForSimdDirective( - const OMPDistributeParallelForSimdDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { - CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined, - S.getDistInc()); - }; - OMPLexicalScope Scope(*this, S, OMPD_parallel); - CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen); -} - -void CodeGenFunction::EmitOMPDistributeSimdDirective( - const OMPDistributeSimdDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { - CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc()); - }; - OMPLexicalScope Scope(*this, S, OMPD_unknown); - CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen); -} - -void CodeGenFunction::EmitOMPTargetSimdDeviceFunction( - CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S) { - // Emit SPMD target parallel for region as a standalone region. - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitOMPSimdRegion(CGF, S, Action); - }; - llvm::Function *Fn; - llvm::Constant *Addr; - // Emit target region as a standalone region. - CGM.getOpenMPRuntime().emitTargetOutlinedFunction( - S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); - assert(Fn && Addr && "Target device function emission failed."); -} - -void CodeGenFunction::EmitOMPTargetSimdDirective( - const OMPTargetSimdDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitOMPSimdRegion(CGF, S, Action); - }; - emitCommonOMPTargetDirective(*this, S, CodeGen); -} - -namespace { - struct ScheduleKindModifiersTy { - OpenMPScheduleClauseKind Kind; - OpenMPScheduleClauseModifier M1; - OpenMPScheduleClauseModifier M2; - ScheduleKindModifiersTy(OpenMPScheduleClauseKind Kind, - OpenMPScheduleClauseModifier M1, - OpenMPScheduleClauseModifier M2) - : Kind(Kind), M1(M1), M2(M2) {} - }; -} // namespace - -bool CodeGenFunction::EmitOMPWorksharingLoop( - const OMPLoopDirective &S, Expr *EUB, - const CodeGenLoopBoundsTy &CodeGenLoopBounds, - const CodeGenDispatchBoundsTy &CGDispatchBounds) { - // Emit the loop iteration variable. - const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable()); - const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl()); - EmitVarDecl(*IVDecl); - - // Emit the iterations count variable. - // If it is not a variable, Sema decided to calculate iterations count on each - // iteration (e.g., it is foldable into a constant). - if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) { - EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl())); - // Emit calculation of the iterations count. - EmitIgnoredExpr(S.getCalcLastIteration()); - } - - CGOpenMPRuntime &RT = CGM.getOpenMPRuntime(); - - bool HasLastprivateClause; - // Check pre-condition. - { - OMPLoopScope PreInitScope(*this, S); - // Skip the entire loop if we don't meet the precondition. - // If the condition constant folds and can be elided, avoid emitting the - // whole loop. - bool CondConstant; - llvm::BasicBlock *ContBlock = nullptr; - if (ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) { - if (!CondConstant) - return false; - } else { - llvm::BasicBlock *ThenBlock = createBasicBlock("omp.precond.then"); - ContBlock = createBasicBlock("omp.precond.end"); - emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock, - getProfileCount(&S)); - EmitBlock(ThenBlock); - incrementProfileCounter(&S); - } - - RunCleanupsScope DoacrossCleanupScope(*this); - bool Ordered = false; - if (const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) { - if (OrderedClause->getNumForLoops()) - RT.emitDoacrossInit(*this, S, OrderedClause->getLoopNumIterations()); - else - Ordered = true; - } - - llvm::DenseSet<const Expr *> EmittedFinals; - emitAlignedClause(*this, S); - bool HasLinears = EmitOMPLinearClauseInit(S); - // Emit helper vars inits. - - std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*this, S); - LValue LB = Bounds.first; - LValue UB = Bounds.second; - LValue ST = - EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable())); - LValue IL = - EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable())); - - // Emit 'then' code. - { - OMPPrivateScope LoopScope(*this); - if (EmitOMPFirstprivateClause(S, LoopScope) || HasLinears) { - // Emit implicit barrier to synchronize threads and avoid data races on - // initialization of firstprivate variables and post-update of - // lastprivate variables. - CGM.getOpenMPRuntime().emitBarrierCall( - *this, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false, - /*ForceSimpleCall=*/true); - } - EmitOMPPrivateClause(S, LoopScope); - HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope); - EmitOMPReductionClauseInit(S, LoopScope); - EmitOMPPrivateLoopCounters(S, LoopScope); - EmitOMPLinearClause(S, LoopScope); - (void)LoopScope.Privatize(); - if (isOpenMPTargetExecutionDirective(S.getDirectiveKind())) - CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*this, S); - - // Detect the loop schedule kind and chunk. - const Expr *ChunkExpr = nullptr; - OpenMPScheduleTy ScheduleKind; - if (const auto *C = S.getSingleClause<OMPScheduleClause>()) { - ScheduleKind.Schedule = C->getScheduleKind(); - ScheduleKind.M1 = C->getFirstScheduleModifier(); - ScheduleKind.M2 = C->getSecondScheduleModifier(); - ChunkExpr = C->getChunkSize(); - } else { - // Default behaviour for schedule clause. - CGM.getOpenMPRuntime().getDefaultScheduleAndChunk( - *this, S, ScheduleKind.Schedule, ChunkExpr); - } - bool HasChunkSizeOne = false; - llvm::Value *Chunk = nullptr; - if (ChunkExpr) { - Chunk = EmitScalarExpr(ChunkExpr); - Chunk = EmitScalarConversion(Chunk, ChunkExpr->getType(), - S.getIterationVariable()->getType(), - S.getBeginLoc()); - Expr::EvalResult Result; - if (ChunkExpr->EvaluateAsInt(Result, getContext())) { - llvm::APSInt EvaluatedChunk = Result.Val.getInt(); - HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1); - } - } - const unsigned IVSize = getContext().getTypeSize(IVExpr->getType()); - const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation(); - // OpenMP 4.5, 2.7.1 Loop Construct, Description. - // If the static schedule kind is specified or if the ordered clause is - // specified, and if no monotonic modifier is specified, the effect will - // be as if the monotonic modifier was specified. - bool StaticChunkedOne = RT.isStaticChunked(ScheduleKind.Schedule, - /* Chunked */ Chunk != nullptr) && HasChunkSizeOne && - isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()); - if ((RT.isStaticNonchunked(ScheduleKind.Schedule, - /* Chunked */ Chunk != nullptr) || - StaticChunkedOne) && - !Ordered) { - if (isOpenMPSimdDirective(S.getDirectiveKind())) - EmitOMPSimdInit(S, /*IsMonotonic=*/true); - // OpenMP [2.7.1, Loop Construct, Description, table 2-1] - // When no chunk_size is specified, the iteration space is divided into - // chunks that are approximately equal in size, and at most one chunk is - // distributed to each thread. Note that the size of the chunks is - // unspecified in this case. - CGOpenMPRuntime::StaticRTInput StaticInit( - IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(), - UB.getAddress(), ST.getAddress(), - StaticChunkedOne ? Chunk : nullptr); - RT.emitForStaticInit(*this, S.getBeginLoc(), S.getDirectiveKind(), - ScheduleKind, StaticInit); - JumpDest LoopExit = - getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit")); - // UB = min(UB, GlobalUB); - if (!StaticChunkedOne) - EmitIgnoredExpr(S.getEnsureUpperBound()); - // IV = LB; - EmitIgnoredExpr(S.getInit()); - // For unchunked static schedule generate: - // - // while (idx <= UB) { - // BODY; - // ++idx; - // } - // - // For static schedule with chunk one: - // - // while (IV <= PrevUB) { - // BODY; - // IV += ST; - // } - EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), - StaticChunkedOne ? S.getCombinedParForInDistCond() : S.getCond(), - StaticChunkedOne ? S.getDistInc() : S.getInc(), - [&S, LoopExit](CodeGenFunction &CGF) { - CGF.EmitOMPLoopBody(S, LoopExit); - CGF.EmitStopPoint(&S); - }, - [](CodeGenFunction &) {}); - EmitBlock(LoopExit.getBlock()); - // Tell the runtime we are done. - auto &&CodeGen = [&S](CodeGenFunction &CGF) { - CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(), - S.getDirectiveKind()); - }; - OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen); - } else { - const bool IsMonotonic = - Ordered || ScheduleKind.Schedule == OMPC_SCHEDULE_static || - ScheduleKind.Schedule == OMPC_SCHEDULE_unknown || - ScheduleKind.M1 == OMPC_SCHEDULE_MODIFIER_monotonic || - ScheduleKind.M2 == OMPC_SCHEDULE_MODIFIER_monotonic; - // Emit the outer loop, which requests its work chunk [LB..UB] from - // runtime and runs the inner loop to process it. - const OMPLoopArguments LoopArguments(LB.getAddress(), UB.getAddress(), - ST.getAddress(), IL.getAddress(), - Chunk, EUB); - EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered, - LoopArguments, CGDispatchBounds); - } - if (isOpenMPSimdDirective(S.getDirectiveKind())) { - EmitOMPSimdFinal(S, [IL, &S](CodeGenFunction &CGF) { - return CGF.Builder.CreateIsNotNull( - CGF.EmitLoadOfScalar(IL, S.getBeginLoc())); - }); - } - EmitOMPReductionClauseFinal( - S, /*ReductionKind=*/isOpenMPSimdDirective(S.getDirectiveKind()) - ? /*Parallel and Simd*/ OMPD_parallel_for_simd - : /*Parallel only*/ OMPD_parallel); - // Emit post-update of the reduction variables if IsLastIter != 0. - emitPostUpdateForReductionClause( - *this, S, [IL, &S](CodeGenFunction &CGF) { - return CGF.Builder.CreateIsNotNull( - CGF.EmitLoadOfScalar(IL, S.getBeginLoc())); - }); - // Emit final copy of the lastprivate variables if IsLastIter != 0. - if (HasLastprivateClause) - EmitOMPLastprivateClauseFinal( - S, isOpenMPSimdDirective(S.getDirectiveKind()), - Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getBeginLoc()))); - } - EmitOMPLinearClauseFinal(S, [IL, &S](CodeGenFunction &CGF) { - return CGF.Builder.CreateIsNotNull( - CGF.EmitLoadOfScalar(IL, S.getBeginLoc())); - }); - DoacrossCleanupScope.ForceCleanup(); - // We're now done with the loop, so jump to the continuation block. - if (ContBlock) { - EmitBranch(ContBlock); - EmitBlock(ContBlock, /*IsFinished=*/true); - } - } - return HasLastprivateClause; -} - -/// The following two functions generate expressions for the loop lower -/// and upper bounds in case of static and dynamic (dispatch) schedule -/// of the associated 'for' or 'distribute' loop. -static std::pair<LValue, LValue> -emitForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S) { - const auto &LS = cast<OMPLoopDirective>(S); - LValue LB = - EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getLowerBoundVariable())); - LValue UB = - EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getUpperBoundVariable())); - return {LB, UB}; -} - -/// When dealing with dispatch schedules (e.g. dynamic, guided) we do not -/// consider the lower and upper bound expressions generated by the -/// worksharing loop support, but we use 0 and the iteration space size as -/// constants -static std::pair<llvm::Value *, llvm::Value *> -emitDispatchForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, - Address LB, Address UB) { - const auto &LS = cast<OMPLoopDirective>(S); - const Expr *IVExpr = LS.getIterationVariable(); - const unsigned IVSize = CGF.getContext().getTypeSize(IVExpr->getType()); - llvm::Value *LBVal = CGF.Builder.getIntN(IVSize, 0); - llvm::Value *UBVal = CGF.EmitScalarExpr(LS.getLastIteration()); - return {LBVal, UBVal}; -} - -void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) { - bool HasLastprivates = false; - auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF, - PrePostActionTy &) { - OMPCancelStackRAII CancelRegion(CGF, OMPD_for, S.hasCancel()); - HasLastprivates = CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), - emitForLoopBounds, - emitDispatchForLoopBounds); - }; - { - OMPLexicalScope Scope(*this, S, OMPD_unknown); - CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen, - S.hasCancel()); - } - - // Emit an implicit barrier at the end. - if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates) - CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for); -} - -void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) { - bool HasLastprivates = false; - auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF, - PrePostActionTy &) { - HasLastprivates = CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), - emitForLoopBounds, - emitDispatchForLoopBounds); - }; - { - OMPLexicalScope Scope(*this, S, OMPD_unknown); - CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen); - } - - // Emit an implicit barrier at the end. - if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates) - CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for); -} - -static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty, - const Twine &Name, - llvm::Value *Init = nullptr) { - LValue LVal = CGF.MakeAddrLValue(CGF.CreateMemTemp(Ty, Name), Ty); - if (Init) - CGF.EmitStoreThroughLValue(RValue::get(Init), LVal, /*isInit*/ true); - return LVal; -} - -void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) { - const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt(); - const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt); - bool HasLastprivates = false; - auto &&CodeGen = [&S, CapturedStmt, CS, - &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) { - ASTContext &C = CGF.getContext(); - QualType KmpInt32Ty = - C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); - // Emit helper vars inits. - LValue LB = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.lb.", - CGF.Builder.getInt32(0)); - llvm::ConstantInt *GlobalUBVal = CS != nullptr - ? CGF.Builder.getInt32(CS->size() - 1) - : CGF.Builder.getInt32(0); - LValue UB = - createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.ub.", GlobalUBVal); - LValue ST = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.st.", - CGF.Builder.getInt32(1)); - LValue IL = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.il.", - CGF.Builder.getInt32(0)); - // Loop counter. - LValue IV = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.iv."); - OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty, VK_LValue); - CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV); - OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty, VK_LValue); - CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB); - // Generate condition for loop. - BinaryOperator Cond(&IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue, - OK_Ordinary, S.getBeginLoc(), FPOptions()); - // Increment for loop counter. - UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary, - S.getBeginLoc(), true); - auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) { - // Iterate through all sections and emit a switch construct: - // switch (IV) { - // case 0: - // <SectionStmt[0]>; - // break; - // ... - // case <NumSection> - 1: - // <SectionStmt[<NumSection> - 1]>; - // break; - // } - // .omp.sections.exit: - llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".omp.sections.exit"); - llvm::SwitchInst *SwitchStmt = - CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.getBeginLoc()), - ExitBB, CS == nullptr ? 1 : CS->size()); - if (CS) { - unsigned CaseNumber = 0; - for (const Stmt *SubStmt : CS->children()) { - auto CaseBB = CGF.createBasicBlock(".omp.sections.case"); - CGF.EmitBlock(CaseBB); - SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB); - CGF.EmitStmt(SubStmt); - CGF.EmitBranch(ExitBB); - ++CaseNumber; - } - } else { - llvm::BasicBlock *CaseBB = CGF.createBasicBlock(".omp.sections.case"); - CGF.EmitBlock(CaseBB); - SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB); - CGF.EmitStmt(CapturedStmt); - CGF.EmitBranch(ExitBB); - } - CGF.EmitBlock(ExitBB, /*IsFinished=*/true); - }; - - CodeGenFunction::OMPPrivateScope LoopScope(CGF); - if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) { - // Emit implicit barrier to synchronize threads and avoid data races on - // initialization of firstprivate variables and post-update of lastprivate - // variables. - CGF.CGM.getOpenMPRuntime().emitBarrierCall( - CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false, - /*ForceSimpleCall=*/true); - } - CGF.EmitOMPPrivateClause(S, LoopScope); - HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope); - CGF.EmitOMPReductionClauseInit(S, LoopScope); - (void)LoopScope.Privatize(); - if (isOpenMPTargetExecutionDirective(S.getDirectiveKind())) - CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S); - - // Emit static non-chunked loop. - OpenMPScheduleTy ScheduleKind; - ScheduleKind.Schedule = OMPC_SCHEDULE_static; - CGOpenMPRuntime::StaticRTInput StaticInit( - /*IVSize=*/32, /*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(), - LB.getAddress(), UB.getAddress(), ST.getAddress()); - CGF.CGM.getOpenMPRuntime().emitForStaticInit( - CGF, S.getBeginLoc(), S.getDirectiveKind(), ScheduleKind, StaticInit); - // UB = min(UB, GlobalUB); - llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.getBeginLoc()); - llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect( - CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal); - CGF.EmitStoreOfScalar(MinUBGlobalUB, UB); - // IV = LB; - CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getBeginLoc()), IV); - // while (idx <= UB) { BODY; ++idx; } - CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, &Cond, &Inc, BodyGen, - [](CodeGenFunction &) {}); - // Tell the runtime we are done. - auto &&CodeGen = [&S](CodeGenFunction &CGF) { - CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(), - S.getDirectiveKind()); - }; - CGF.OMPCancelStack.emitExit(CGF, S.getDirectiveKind(), CodeGen); - CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel); - // Emit post-update of the reduction variables if IsLastIter != 0. - emitPostUpdateForReductionClause(CGF, S, [IL, &S](CodeGenFunction &CGF) { - return CGF.Builder.CreateIsNotNull( - CGF.EmitLoadOfScalar(IL, S.getBeginLoc())); - }); - - // Emit final copy of the lastprivate variables if IsLastIter != 0. - if (HasLastprivates) - CGF.EmitOMPLastprivateClauseFinal( - S, /*NoFinals=*/false, - CGF.Builder.CreateIsNotNull( - CGF.EmitLoadOfScalar(IL, S.getBeginLoc()))); - }; - - bool HasCancel = false; - if (auto *OSD = dyn_cast<OMPSectionsDirective>(&S)) - HasCancel = OSD->hasCancel(); - else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S)) - HasCancel = OPSD->hasCancel(); - OMPCancelStackRAII CancelRegion(*this, S.getDirectiveKind(), HasCancel); - CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen, - HasCancel); - // Emit barrier for lastprivates only if 'sections' directive has 'nowait' - // clause. Otherwise the barrier will be generated by the codegen for the - // directive. - if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) { - // Emit implicit barrier to synchronize threads and avoid data races on - // initialization of firstprivate variables. - CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), - OMPD_unknown); - } -} - -void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) { - { - OMPLexicalScope Scope(*this, S, OMPD_unknown); - EmitSections(S); - } - // Emit an implicit barrier at the end. - if (!S.getSingleClause<OMPNowaitClause>()) { - CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), - OMPD_sections); - } -} - -void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { - CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt()); - }; - OMPLexicalScope Scope(*this, S, OMPD_unknown); - CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_section, CodeGen, - S.hasCancel()); -} - -void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) { - llvm::SmallVector<const Expr *, 8> CopyprivateVars; - llvm::SmallVector<const Expr *, 8> DestExprs; - llvm::SmallVector<const Expr *, 8> SrcExprs; - llvm::SmallVector<const Expr *, 8> AssignmentOps; - // Check if there are any 'copyprivate' clauses associated with this - // 'single' construct. - // Build a list of copyprivate variables along with helper expressions - // (<source>, <destination>, <destination>=<source> expressions) - for (const auto *C : S.getClausesOfKind<OMPCopyprivateClause>()) { - CopyprivateVars.append(C->varlists().begin(), C->varlists().end()); - DestExprs.append(C->destination_exprs().begin(), - C->destination_exprs().end()); - SrcExprs.append(C->source_exprs().begin(), C->source_exprs().end()); - AssignmentOps.append(C->assignment_ops().begin(), - C->assignment_ops().end()); - } - // Emit code for 'single' region along with 'copyprivate' clauses - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - Action.Enter(CGF); - OMPPrivateScope SingleScope(CGF); - (void)CGF.EmitOMPFirstprivateClause(S, SingleScope); - CGF.EmitOMPPrivateClause(S, SingleScope); - (void)SingleScope.Privatize(); - CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt()); - }; - { - OMPLexicalScope Scope(*this, S, OMPD_unknown); - CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getBeginLoc(), - CopyprivateVars, DestExprs, - SrcExprs, AssignmentOps); - } - // Emit an implicit barrier at the end (to avoid data race on firstprivate - // init or if no 'nowait' clause was specified and no 'copyprivate' clause). - if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) { - CGM.getOpenMPRuntime().emitBarrierCall( - *this, S.getBeginLoc(), - S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single); - } -} - -void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - Action.Enter(CGF); - CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt()); - }; - OMPLexicalScope Scope(*this, S, OMPD_unknown); - CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getBeginLoc()); -} - -void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - Action.Enter(CGF); - CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt()); - }; - const Expr *Hint = nullptr; - if (const auto *HintClause = S.getSingleClause<OMPHintClause>()) - Hint = HintClause->getHint(); - OMPLexicalScope Scope(*this, S, OMPD_unknown); - CGM.getOpenMPRuntime().emitCriticalRegion(*this, - S.getDirectiveName().getAsString(), - CodeGen, S.getBeginLoc(), Hint); -} - -void CodeGenFunction::EmitOMPParallelForDirective( - const OMPParallelForDirective &S) { - // Emit directive as a combined directive that consists of two implicit - // directives: 'parallel' with 'for' directive. - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - Action.Enter(CGF); - OMPCancelStackRAII CancelRegion(CGF, OMPD_parallel_for, S.hasCancel()); - CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds, - emitDispatchForLoopBounds); - }; - emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen, - emitEmptyBoundParameters); -} - -void CodeGenFunction::EmitOMPParallelForSimdDirective( - const OMPParallelForSimdDirective &S) { - // Emit directive as a combined directive that consists of two implicit - // directives: 'parallel' with 'for' directive. - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - Action.Enter(CGF); - CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds, - emitDispatchForLoopBounds); - }; - emitCommonOMPParallelDirective(*this, S, OMPD_simd, CodeGen, - emitEmptyBoundParameters); -} - -void CodeGenFunction::EmitOMPParallelSectionsDirective( - const OMPParallelSectionsDirective &S) { - // Emit directive as a combined directive that consists of two implicit - // directives: 'parallel' with 'sections' directive. - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - Action.Enter(CGF); - CGF.EmitSections(S); - }; - emitCommonOMPParallelDirective(*this, S, OMPD_sections, CodeGen, - emitEmptyBoundParameters); -} - -void CodeGenFunction::EmitOMPTaskBasedDirective( - const OMPExecutableDirective &S, const OpenMPDirectiveKind CapturedRegion, - const RegionCodeGenTy &BodyGen, const TaskGenTy &TaskGen, - OMPTaskDataTy &Data) { - // Emit outlined function for task construct. - const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion); - auto I = CS->getCapturedDecl()->param_begin(); - auto PartId = std::next(I); - auto TaskT = std::next(I, 4); - // Check if the task is final - if (const auto *Clause = S.getSingleClause<OMPFinalClause>()) { - // If the condition constant folds and can be elided, try to avoid emitting - // the condition and the dead arm of the if/else. - const Expr *Cond = Clause->getCondition(); - bool CondConstant; - if (ConstantFoldsToSimpleInteger(Cond, CondConstant)) - Data.Final.setInt(CondConstant); - else - Data.Final.setPointer(EvaluateExprAsBool(Cond)); - } else { - // By default the task is not final. - Data.Final.setInt(/*IntVal=*/false); - } - // Check if the task has 'priority' clause. - if (const auto *Clause = S.getSingleClause<OMPPriorityClause>()) { - const Expr *Prio = Clause->getPriority(); - Data.Priority.setInt(/*IntVal=*/true); - Data.Priority.setPointer(EmitScalarConversion( - EmitScalarExpr(Prio), Prio->getType(), - getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1), - Prio->getExprLoc())); - } - // The first function argument for tasks is a thread id, the second one is a - // part id (0 for tied tasks, >=0 for untied task). - llvm::DenseSet<const VarDecl *> EmittedAsPrivate; - // Get list of private variables. - for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) { - auto IRef = C->varlist_begin(); - for (const Expr *IInit : C->private_copies()) { - const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); - if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) { - Data.PrivateVars.push_back(*IRef); - Data.PrivateCopies.push_back(IInit); - } - ++IRef; - } - } - EmittedAsPrivate.clear(); - // Get list of firstprivate variables. - for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) { - auto IRef = C->varlist_begin(); - auto IElemInitRef = C->inits().begin(); - for (const Expr *IInit : C->private_copies()) { - const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); - if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) { - Data.FirstprivateVars.push_back(*IRef); - Data.FirstprivateCopies.push_back(IInit); - Data.FirstprivateInits.push_back(*IElemInitRef); - } - ++IRef; - ++IElemInitRef; - } - } - // Get list of lastprivate variables (for taskloops). - llvm::DenseMap<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs; - for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { - auto IRef = C->varlist_begin(); - auto ID = C->destination_exprs().begin(); - for (const Expr *IInit : C->private_copies()) { - const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); - if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) { - Data.LastprivateVars.push_back(*IRef); - Data.LastprivateCopies.push_back(IInit); - } - LastprivateDstsOrigs.insert( - {cast<VarDecl>(cast<DeclRefExpr>(*ID)->getDecl()), - cast<DeclRefExpr>(*IRef)}); - ++IRef; - ++ID; - } - } - SmallVector<const Expr *, 4> LHSs; - SmallVector<const Expr *, 4> RHSs; - for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) { - auto IPriv = C->privates().begin(); - auto IRed = C->reduction_ops().begin(); - auto ILHS = C->lhs_exprs().begin(); - auto IRHS = C->rhs_exprs().begin(); - for (const Expr *Ref : C->varlists()) { - Data.ReductionVars.emplace_back(Ref); - Data.ReductionCopies.emplace_back(*IPriv); - Data.ReductionOps.emplace_back(*IRed); - LHSs.emplace_back(*ILHS); - RHSs.emplace_back(*IRHS); - std::advance(IPriv, 1); - std::advance(IRed, 1); - std::advance(ILHS, 1); - std::advance(IRHS, 1); - } - } - Data.Reductions = CGM.getOpenMPRuntime().emitTaskReductionInit( - *this, S.getBeginLoc(), LHSs, RHSs, Data); - // Build list of dependences. - for (const auto *C : S.getClausesOfKind<OMPDependClause>()) - for (const Expr *IRef : C->varlists()) - Data.Dependences.emplace_back(C->getDependencyKind(), IRef); - auto &&CodeGen = [&Data, &S, CS, &BodyGen, &LastprivateDstsOrigs, - CapturedRegion](CodeGenFunction &CGF, - PrePostActionTy &Action) { - // Set proper addresses for generated private copies. - OMPPrivateScope Scope(CGF); - if (!Data.PrivateVars.empty() || !Data.FirstprivateVars.empty() || - !Data.LastprivateVars.empty()) { - enum { PrivatesParam = 2, CopyFnParam = 3 }; - llvm::Value *CopyFn = CGF.Builder.CreateLoad( - CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam))); - llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar( - CS->getCapturedDecl()->getParam(PrivatesParam))); - // Map privates. - llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> PrivatePtrs; - llvm::SmallVector<llvm::Value *, 16> CallArgs; - CallArgs.push_back(PrivatesPtr); - for (const Expr *E : Data.PrivateVars) { - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - Address PrivatePtr = CGF.CreateMemTemp( - CGF.getContext().getPointerType(E->getType()), ".priv.ptr.addr"); - PrivatePtrs.emplace_back(VD, PrivatePtr); - CallArgs.push_back(PrivatePtr.getPointer()); - } - for (const Expr *E : Data.FirstprivateVars) { - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - Address PrivatePtr = - CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), - ".firstpriv.ptr.addr"); - PrivatePtrs.emplace_back(VD, PrivatePtr); - CallArgs.push_back(PrivatePtr.getPointer()); - } - for (const Expr *E : Data.LastprivateVars) { - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - Address PrivatePtr = - CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), - ".lastpriv.ptr.addr"); - PrivatePtrs.emplace_back(VD, PrivatePtr); - CallArgs.push_back(PrivatePtr.getPointer()); - } - CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(), - CopyFn, CallArgs); - for (const auto &Pair : LastprivateDstsOrigs) { - const auto *OrigVD = cast<VarDecl>(Pair.second->getDecl()); - DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(OrigVD), - /*RefersToEnclosingVariableOrCapture=*/ - CGF.CapturedStmtInfo->lookup(OrigVD) != nullptr, - Pair.second->getType(), VK_LValue, - Pair.second->getExprLoc()); - Scope.addPrivate(Pair.first, [&CGF, &DRE]() { - return CGF.EmitLValue(&DRE).getAddress(); - }); - } - for (const auto &Pair : PrivatePtrs) { - Address Replacement(CGF.Builder.CreateLoad(Pair.second), - CGF.getContext().getDeclAlign(Pair.first)); - Scope.addPrivate(Pair.first, [Replacement]() { return Replacement; }); - } - } - if (Data.Reductions) { - OMPLexicalScope LexScope(CGF, S, CapturedRegion); - ReductionCodeGen RedCG(Data.ReductionVars, Data.ReductionCopies, - Data.ReductionOps); - llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad( - CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(9))); - for (unsigned Cnt = 0, E = Data.ReductionVars.size(); Cnt < E; ++Cnt) { - RedCG.emitSharedLValue(CGF, Cnt); - RedCG.emitAggregateType(CGF, Cnt); - // FIXME: This must removed once the runtime library is fixed. - // Emit required threadprivate variables for - // initializer/combiner/finalizer. - CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(), - RedCG, Cnt); - Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem( - CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); - Replacement = - Address(CGF.EmitScalarConversion( - Replacement.getPointer(), CGF.getContext().VoidPtrTy, - CGF.getContext().getPointerType( - Data.ReductionCopies[Cnt]->getType()), - Data.ReductionCopies[Cnt]->getExprLoc()), - Replacement.getAlignment()); - Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement); - Scope.addPrivate(RedCG.getBaseDecl(Cnt), - [Replacement]() { return Replacement; }); - } - } - // Privatize all private variables except for in_reduction items. - (void)Scope.Privatize(); - SmallVector<const Expr *, 4> InRedVars; - SmallVector<const Expr *, 4> InRedPrivs; - SmallVector<const Expr *, 4> InRedOps; - SmallVector<const Expr *, 4> TaskgroupDescriptors; - for (const auto *C : S.getClausesOfKind<OMPInReductionClause>()) { - auto IPriv = C->privates().begin(); - auto IRed = C->reduction_ops().begin(); - auto ITD = C->taskgroup_descriptors().begin(); - for (const Expr *Ref : C->varlists()) { - InRedVars.emplace_back(Ref); - InRedPrivs.emplace_back(*IPriv); - InRedOps.emplace_back(*IRed); - TaskgroupDescriptors.emplace_back(*ITD); - std::advance(IPriv, 1); - std::advance(IRed, 1); - std::advance(ITD, 1); - } - } - // Privatize in_reduction items here, because taskgroup descriptors must be - // privatized earlier. - OMPPrivateScope InRedScope(CGF); - if (!InRedVars.empty()) { - ReductionCodeGen RedCG(InRedVars, InRedPrivs, InRedOps); - for (unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) { - RedCG.emitSharedLValue(CGF, Cnt); - RedCG.emitAggregateType(CGF, Cnt); - // The taskgroup descriptor variable is always implicit firstprivate and - // privatized already during processing of the firstprivates. - // FIXME: This must removed once the runtime library is fixed. - // Emit required threadprivate variables for - // initializer/combiner/finalizer. - CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(), - RedCG, Cnt); - llvm::Value *ReductionsPtr = - CGF.EmitLoadOfScalar(CGF.EmitLValue(TaskgroupDescriptors[Cnt]), - TaskgroupDescriptors[Cnt]->getExprLoc()); - Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem( - CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); - Replacement = Address( - CGF.EmitScalarConversion( - Replacement.getPointer(), CGF.getContext().VoidPtrTy, - CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()), - InRedPrivs[Cnt]->getExprLoc()), - Replacement.getAlignment()); - Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement); - InRedScope.addPrivate(RedCG.getBaseDecl(Cnt), - [Replacement]() { return Replacement; }); - } - } - (void)InRedScope.Privatize(); - - Action.Enter(CGF); - BodyGen(CGF); - }; - llvm::Value *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction( - S, *I, *PartId, *TaskT, S.getDirectiveKind(), CodeGen, Data.Tied, - Data.NumberOfParts); - OMPLexicalScope Scope(*this, S); - TaskGen(*this, OutlinedFn, Data); -} - -static ImplicitParamDecl * -createImplicitFirstprivateForType(ASTContext &C, OMPTaskDataTy &Data, - QualType Ty, CapturedDecl *CD, - SourceLocation Loc) { - auto *OrigVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, Ty, - ImplicitParamDecl::Other); - auto *OrigRef = DeclRefExpr::Create( - C, NestedNameSpecifierLoc(), SourceLocation(), OrigVD, - /*RefersToEnclosingVariableOrCapture=*/false, Loc, Ty, VK_LValue); - auto *PrivateVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, Ty, - ImplicitParamDecl::Other); - auto *PrivateRef = DeclRefExpr::Create( - C, NestedNameSpecifierLoc(), SourceLocation(), PrivateVD, - /*RefersToEnclosingVariableOrCapture=*/false, Loc, Ty, VK_LValue); - QualType ElemType = C.getBaseElementType(Ty); - auto *InitVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, ElemType, - ImplicitParamDecl::Other); - auto *InitRef = DeclRefExpr::Create( - C, NestedNameSpecifierLoc(), SourceLocation(), InitVD, - /*RefersToEnclosingVariableOrCapture=*/false, Loc, ElemType, VK_LValue); - PrivateVD->setInitStyle(VarDecl::CInit); - PrivateVD->setInit(ImplicitCastExpr::Create(C, ElemType, CK_LValueToRValue, - InitRef, /*BasePath=*/nullptr, - VK_RValue)); - Data.FirstprivateVars.emplace_back(OrigRef); - Data.FirstprivateCopies.emplace_back(PrivateRef); - Data.FirstprivateInits.emplace_back(InitRef); - return OrigVD; -} - -void CodeGenFunction::EmitOMPTargetTaskBasedDirective( - const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, - OMPTargetDataInfo &InputInfo) { - // Emit outlined function for task construct. - const CapturedStmt *CS = S.getCapturedStmt(OMPD_task); - Address CapturedStruct = GenerateCapturedStmtArgument(*CS); - QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl()); - auto I = CS->getCapturedDecl()->param_begin(); - auto PartId = std::next(I); - auto TaskT = std::next(I, 4); - OMPTaskDataTy Data; - // The task is not final. - Data.Final.setInt(/*IntVal=*/false); - // Get list of firstprivate variables. - for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) { - auto IRef = C->varlist_begin(); - auto IElemInitRef = C->inits().begin(); - for (auto *IInit : C->private_copies()) { - Data.FirstprivateVars.push_back(*IRef); - Data.FirstprivateCopies.push_back(IInit); - Data.FirstprivateInits.push_back(*IElemInitRef); - ++IRef; - ++IElemInitRef; - } - } - OMPPrivateScope TargetScope(*this); - VarDecl *BPVD = nullptr; - VarDecl *PVD = nullptr; - VarDecl *SVD = nullptr; - if (InputInfo.NumberOfTargetItems > 0) { - auto *CD = CapturedDecl::Create( - getContext(), getContext().getTranslationUnitDecl(), /*NumParams=*/0); - llvm::APInt ArrSize(/*numBits=*/32, InputInfo.NumberOfTargetItems); - QualType BaseAndPointersType = getContext().getConstantArrayType( - getContext().VoidPtrTy, ArrSize, ArrayType::Normal, - /*IndexTypeQuals=*/0); - BPVD = createImplicitFirstprivateForType( - getContext(), Data, BaseAndPointersType, CD, S.getBeginLoc()); - PVD = createImplicitFirstprivateForType( - getContext(), Data, BaseAndPointersType, CD, S.getBeginLoc()); - QualType SizesType = getContext().getConstantArrayType( - getContext().getSizeType(), ArrSize, ArrayType::Normal, - /*IndexTypeQuals=*/0); - SVD = createImplicitFirstprivateForType(getContext(), Data, SizesType, CD, - S.getBeginLoc()); - TargetScope.addPrivate( - BPVD, [&InputInfo]() { return InputInfo.BasePointersArray; }); - TargetScope.addPrivate(PVD, - [&InputInfo]() { return InputInfo.PointersArray; }); - TargetScope.addPrivate(SVD, - [&InputInfo]() { return InputInfo.SizesArray; }); - } - (void)TargetScope.Privatize(); - // Build list of dependences. - for (const auto *C : S.getClausesOfKind<OMPDependClause>()) - for (const Expr *IRef : C->varlists()) - Data.Dependences.emplace_back(C->getDependencyKind(), IRef); - auto &&CodeGen = [&Data, &S, CS, &BodyGen, BPVD, PVD, SVD, - &InputInfo](CodeGenFunction &CGF, PrePostActionTy &Action) { - // Set proper addresses for generated private copies. - OMPPrivateScope Scope(CGF); - if (!Data.FirstprivateVars.empty()) { - enum { PrivatesParam = 2, CopyFnParam = 3 }; - llvm::Value *CopyFn = CGF.Builder.CreateLoad( - CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam))); - llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar( - CS->getCapturedDecl()->getParam(PrivatesParam))); - // Map privates. - llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> PrivatePtrs; - llvm::SmallVector<llvm::Value *, 16> CallArgs; - CallArgs.push_back(PrivatesPtr); - for (const Expr *E : Data.FirstprivateVars) { - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - Address PrivatePtr = - CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), - ".firstpriv.ptr.addr"); - PrivatePtrs.emplace_back(VD, PrivatePtr); - CallArgs.push_back(PrivatePtr.getPointer()); - } - CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(), - CopyFn, CallArgs); - for (const auto &Pair : PrivatePtrs) { - Address Replacement(CGF.Builder.CreateLoad(Pair.second), - CGF.getContext().getDeclAlign(Pair.first)); - Scope.addPrivate(Pair.first, [Replacement]() { return Replacement; }); - } - } - // Privatize all private variables except for in_reduction items. - (void)Scope.Privatize(); - if (InputInfo.NumberOfTargetItems > 0) { - InputInfo.BasePointersArray = CGF.Builder.CreateConstArrayGEP( - CGF.GetAddrOfLocalVar(BPVD), /*Index=*/0, CGF.getPointerSize()); - InputInfo.PointersArray = CGF.Builder.CreateConstArrayGEP( - CGF.GetAddrOfLocalVar(PVD), /*Index=*/0, CGF.getPointerSize()); - InputInfo.SizesArray = CGF.Builder.CreateConstArrayGEP( - CGF.GetAddrOfLocalVar(SVD), /*Index=*/0, CGF.getSizeSize()); - } - - Action.Enter(CGF); - OMPLexicalScope LexScope(CGF, S, OMPD_task, /*EmitPreInitStmt=*/false); - BodyGen(CGF); - }; - llvm::Value *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction( - S, *I, *PartId, *TaskT, S.getDirectiveKind(), CodeGen, /*Tied=*/true, - Data.NumberOfParts); - llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0); - IntegerLiteral IfCond(getContext(), TrueOrFalse, - getContext().getIntTypeForBitwidth(32, /*Signed=*/0), - SourceLocation()); - - CGM.getOpenMPRuntime().emitTaskCall(*this, S.getBeginLoc(), S, OutlinedFn, - SharedsTy, CapturedStruct, &IfCond, Data); -} - -void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) { - // Emit outlined function for task construct. - const CapturedStmt *CS = S.getCapturedStmt(OMPD_task); - Address CapturedStruct = GenerateCapturedStmtArgument(*CS); - QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl()); - const Expr *IfCond = nullptr; - for (const auto *C : S.getClausesOfKind<OMPIfClause>()) { - if (C->getNameModifier() == OMPD_unknown || - C->getNameModifier() == OMPD_task) { - IfCond = C->getCondition(); - break; - } - } - - OMPTaskDataTy Data; - // Check if we should emit tied or untied task. - Data.Tied = !S.getSingleClause<OMPUntiedClause>(); - auto &&BodyGen = [CS](CodeGenFunction &CGF, PrePostActionTy &) { - CGF.EmitStmt(CS->getCapturedStmt()); - }; - auto &&TaskGen = [&S, SharedsTy, CapturedStruct, - IfCond](CodeGenFunction &CGF, llvm::Value *OutlinedFn, - const OMPTaskDataTy &Data) { - CGF.CGM.getOpenMPRuntime().emitTaskCall(CGF, S.getBeginLoc(), S, OutlinedFn, - SharedsTy, CapturedStruct, IfCond, - Data); - }; - EmitOMPTaskBasedDirective(S, OMPD_task, BodyGen, TaskGen, Data); -} - -void CodeGenFunction::EmitOMPTaskyieldDirective( - const OMPTaskyieldDirective &S) { - CGM.getOpenMPRuntime().emitTaskyieldCall(*this, S.getBeginLoc()); -} - -void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) { - CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_barrier); -} - -void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) { - CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc()); -} - -void CodeGenFunction::EmitOMPTaskgroupDirective( - const OMPTaskgroupDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - Action.Enter(CGF); - if (const Expr *E = S.getReductionRef()) { - SmallVector<const Expr *, 4> LHSs; - SmallVector<const Expr *, 4> RHSs; - OMPTaskDataTy Data; - for (const auto *C : S.getClausesOfKind<OMPTaskReductionClause>()) { - auto IPriv = C->privates().begin(); - auto IRed = C->reduction_ops().begin(); - auto ILHS = C->lhs_exprs().begin(); - auto IRHS = C->rhs_exprs().begin(); - for (const Expr *Ref : C->varlists()) { - Data.ReductionVars.emplace_back(Ref); - Data.ReductionCopies.emplace_back(*IPriv); - Data.ReductionOps.emplace_back(*IRed); - LHSs.emplace_back(*ILHS); - RHSs.emplace_back(*IRHS); - std::advance(IPriv, 1); - std::advance(IRed, 1); - std::advance(ILHS, 1); - std::advance(IRHS, 1); - } - } - llvm::Value *ReductionDesc = - CGF.CGM.getOpenMPRuntime().emitTaskReductionInit(CGF, S.getBeginLoc(), - LHSs, RHSs, Data); - const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - CGF.EmitVarDecl(*VD); - CGF.EmitStoreOfScalar(ReductionDesc, CGF.GetAddrOfLocalVar(VD), - /*Volatile=*/false, E->getType()); - } - CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt()); - }; - OMPLexicalScope Scope(*this, S, OMPD_unknown); - CGM.getOpenMPRuntime().emitTaskgroupRegion(*this, CodeGen, S.getBeginLoc()); -} - -void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) { - CGM.getOpenMPRuntime().emitFlush( - *this, - [&S]() -> ArrayRef<const Expr *> { - if (const auto *FlushClause = S.getSingleClause<OMPFlushClause>()) - return llvm::makeArrayRef(FlushClause->varlist_begin(), - FlushClause->varlist_end()); - return llvm::None; - }(), - S.getBeginLoc()); -} - -void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S, - const CodeGenLoopTy &CodeGenLoop, - Expr *IncExpr) { - // Emit the loop iteration variable. - const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable()); - const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl()); - EmitVarDecl(*IVDecl); - - // Emit the iterations count variable. - // If it is not a variable, Sema decided to calculate iterations count on each - // iteration (e.g., it is foldable into a constant). - if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) { - EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl())); - // Emit calculation of the iterations count. - EmitIgnoredExpr(S.getCalcLastIteration()); - } - - CGOpenMPRuntime &RT = CGM.getOpenMPRuntime(); - - bool HasLastprivateClause = false; - // Check pre-condition. - { - OMPLoopScope PreInitScope(*this, S); - // Skip the entire loop if we don't meet the precondition. - // If the condition constant folds and can be elided, avoid emitting the - // whole loop. - bool CondConstant; - llvm::BasicBlock *ContBlock = nullptr; - if (ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) { - if (!CondConstant) - return; - } else { - llvm::BasicBlock *ThenBlock = createBasicBlock("omp.precond.then"); - ContBlock = createBasicBlock("omp.precond.end"); - emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock, - getProfileCount(&S)); - EmitBlock(ThenBlock); - incrementProfileCounter(&S); - } - - emitAlignedClause(*this, S); - // Emit 'then' code. - { - // Emit helper vars inits. - - LValue LB = EmitOMPHelperVar( - *this, cast<DeclRefExpr>( - (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) - ? S.getCombinedLowerBoundVariable() - : S.getLowerBoundVariable()))); - LValue UB = EmitOMPHelperVar( - *this, cast<DeclRefExpr>( - (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) - ? S.getCombinedUpperBoundVariable() - : S.getUpperBoundVariable()))); - LValue ST = - EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable())); - LValue IL = - EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable())); - - OMPPrivateScope LoopScope(*this); - if (EmitOMPFirstprivateClause(S, LoopScope)) { - // Emit implicit barrier to synchronize threads and avoid data races - // on initialization of firstprivate variables and post-update of - // lastprivate variables. - CGM.getOpenMPRuntime().emitBarrierCall( - *this, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false, - /*ForceSimpleCall=*/true); - } - EmitOMPPrivateClause(S, LoopScope); - if (isOpenMPSimdDirective(S.getDirectiveKind()) && - !isOpenMPParallelDirective(S.getDirectiveKind()) && - !isOpenMPTeamsDirective(S.getDirectiveKind())) - EmitOMPReductionClauseInit(S, LoopScope); - HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope); - EmitOMPPrivateLoopCounters(S, LoopScope); - (void)LoopScope.Privatize(); - if (isOpenMPTargetExecutionDirective(S.getDirectiveKind())) - CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*this, S); - - // Detect the distribute schedule kind and chunk. - llvm::Value *Chunk = nullptr; - OpenMPDistScheduleClauseKind ScheduleKind = OMPC_DIST_SCHEDULE_unknown; - if (const auto *C = S.getSingleClause<OMPDistScheduleClause>()) { - ScheduleKind = C->getDistScheduleKind(); - if (const Expr *Ch = C->getChunkSize()) { - Chunk = EmitScalarExpr(Ch); - Chunk = EmitScalarConversion(Chunk, Ch->getType(), - S.getIterationVariable()->getType(), - S.getBeginLoc()); - } - } else { - // Default behaviour for dist_schedule clause. - CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk( - *this, S, ScheduleKind, Chunk); - } - const unsigned IVSize = getContext().getTypeSize(IVExpr->getType()); - const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation(); - - // OpenMP [2.10.8, distribute Construct, Description] - // If dist_schedule is specified, kind must be static. If specified, - // iterations are divided into chunks of size chunk_size, chunks are - // assigned to the teams of the league in a round-robin fashion in the - // order of the team number. When no chunk_size is specified, the - // iteration space is divided into chunks that are approximately equal - // in size, and at most one chunk is distributed to each team of the - // league. The size of the chunks is unspecified in this case. - bool StaticChunked = RT.isStaticChunked( - ScheduleKind, /* Chunked */ Chunk != nullptr) && - isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()); - if (RT.isStaticNonchunked(ScheduleKind, - /* Chunked */ Chunk != nullptr) || - StaticChunked) { - if (isOpenMPSimdDirective(S.getDirectiveKind())) - EmitOMPSimdInit(S, /*IsMonotonic=*/true); - CGOpenMPRuntime::StaticRTInput StaticInit( - IVSize, IVSigned, /* Ordered = */ false, IL.getAddress(), - LB.getAddress(), UB.getAddress(), ST.getAddress(), - StaticChunked ? Chunk : nullptr); - RT.emitDistributeStaticInit(*this, S.getBeginLoc(), ScheduleKind, - StaticInit); - JumpDest LoopExit = - getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit")); - // UB = min(UB, GlobalUB); - EmitIgnoredExpr(isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) - ? S.getCombinedEnsureUpperBound() - : S.getEnsureUpperBound()); - // IV = LB; - EmitIgnoredExpr(isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) - ? S.getCombinedInit() - : S.getInit()); - - const Expr *Cond = - isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) - ? S.getCombinedCond() - : S.getCond(); - - if (StaticChunked) - Cond = S.getCombinedDistCond(); - - // For static unchunked schedules generate: - // - // 1. For distribute alone, codegen - // while (idx <= UB) { - // BODY; - // ++idx; - // } - // - // 2. When combined with 'for' (e.g. as in 'distribute parallel for') - // while (idx <= UB) { - // <CodeGen rest of pragma>(LB, UB); - // idx += ST; - // } - // - // For static chunk one schedule generate: - // - // while (IV <= GlobalUB) { - // <CodeGen rest of pragma>(LB, UB); - // LB += ST; - // UB += ST; - // UB = min(UB, GlobalUB); - // IV = LB; - // } - // - EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), Cond, IncExpr, - [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) { - CodeGenLoop(CGF, S, LoopExit); - }, - [&S, StaticChunked](CodeGenFunction &CGF) { - if (StaticChunked) { - CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound()); - CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound()); - CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound()); - CGF.EmitIgnoredExpr(S.getCombinedInit()); - } - }); - EmitBlock(LoopExit.getBlock()); - // Tell the runtime we are done. - RT.emitForStaticFinish(*this, S.getBeginLoc(), S.getDirectiveKind()); - } else { - // Emit the outer loop, which requests its work chunk [LB..UB] from - // runtime and runs the inner loop to process it. - const OMPLoopArguments LoopArguments = { - LB.getAddress(), UB.getAddress(), ST.getAddress(), IL.getAddress(), - Chunk}; - EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments, - CodeGenLoop); - } - if (isOpenMPSimdDirective(S.getDirectiveKind())) { - EmitOMPSimdFinal(S, [IL, &S](CodeGenFunction &CGF) { - return CGF.Builder.CreateIsNotNull( - CGF.EmitLoadOfScalar(IL, S.getBeginLoc())); - }); - } - if (isOpenMPSimdDirective(S.getDirectiveKind()) && - !isOpenMPParallelDirective(S.getDirectiveKind()) && - !isOpenMPTeamsDirective(S.getDirectiveKind())) { - EmitOMPReductionClauseFinal(S, OMPD_simd); - // Emit post-update of the reduction variables if IsLastIter != 0. - emitPostUpdateForReductionClause( - *this, S, [IL, &S](CodeGenFunction &CGF) { - return CGF.Builder.CreateIsNotNull( - CGF.EmitLoadOfScalar(IL, S.getBeginLoc())); - }); - } - // Emit final copy of the lastprivate variables if IsLastIter != 0. - if (HasLastprivateClause) { - EmitOMPLastprivateClauseFinal( - S, /*NoFinals=*/false, - Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getBeginLoc()))); - } - } - - // We're now done with the loop, so jump to the continuation block. - if (ContBlock) { - EmitBranch(ContBlock); - EmitBlock(ContBlock, true); - } - } -} - -void CodeGenFunction::EmitOMPDistributeDirective( - const OMPDistributeDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { - CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc()); - }; - OMPLexicalScope Scope(*this, S, OMPD_unknown); - CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen); -} - -static llvm::Function *emitOutlinedOrderedFunction(CodeGenModule &CGM, - const CapturedStmt *S) { - CodeGenFunction CGF(CGM, /*suppressNewContext=*/true); - CodeGenFunction::CGCapturedStmtInfo CapStmtInfo; - CGF.CapturedStmtInfo = &CapStmtInfo; - llvm::Function *Fn = CGF.GenerateOpenMPCapturedStmtFunction(*S); - Fn->setDoesNotRecurse(); - return Fn; -} - -void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &S) { - if (S.hasClausesOfKind<OMPDependClause>()) { - assert(!S.getAssociatedStmt() && - "No associated statement must be in ordered depend construct."); - for (const auto *DC : S.getClausesOfKind<OMPDependClause>()) - CGM.getOpenMPRuntime().emitDoacrossOrdered(*this, DC); - return; - } - const auto *C = S.getSingleClause<OMPSIMDClause>(); - auto &&CodeGen = [&S, C, this](CodeGenFunction &CGF, - PrePostActionTy &Action) { - const CapturedStmt *CS = S.getInnermostCapturedStmt(); - if (C) { - llvm::SmallVector<llvm::Value *, 16> CapturedVars; - CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars); - llvm::Function *OutlinedFn = emitOutlinedOrderedFunction(CGM, CS); - CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(), - OutlinedFn, CapturedVars); - } else { - Action.Enter(CGF); - CGF.EmitStmt(CS->getCapturedStmt()); - } - }; - OMPLexicalScope Scope(*this, S, OMPD_unknown); - CGM.getOpenMPRuntime().emitOrderedRegion(*this, CodeGen, S.getBeginLoc(), !C); -} - -static llvm::Value *convertToScalarValue(CodeGenFunction &CGF, RValue Val, - QualType SrcType, QualType DestType, - SourceLocation Loc) { - assert(CGF.hasScalarEvaluationKind(DestType) && - "DestType must have scalar evaluation kind."); - assert(!Val.isAggregate() && "Must be a scalar or complex."); - return Val.isScalar() ? CGF.EmitScalarConversion(Val.getScalarVal(), SrcType, - DestType, Loc) - : CGF.EmitComplexToScalarConversion( - Val.getComplexVal(), SrcType, DestType, Loc); -} - -static CodeGenFunction::ComplexPairTy -convertToComplexValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, - QualType DestType, SourceLocation Loc) { - assert(CGF.getEvaluationKind(DestType) == TEK_Complex && - "DestType must have complex evaluation kind."); - CodeGenFunction::ComplexPairTy ComplexVal; - if (Val.isScalar()) { - // Convert the input element to the element type of the complex. - QualType DestElementType = - DestType->castAs<ComplexType>()->getElementType(); - llvm::Value *ScalarVal = CGF.EmitScalarConversion( - Val.getScalarVal(), SrcType, DestElementType, Loc); - ComplexVal = CodeGenFunction::ComplexPairTy( - ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType())); - } else { - assert(Val.isComplex() && "Must be a scalar or complex."); - QualType SrcElementType = SrcType->castAs<ComplexType>()->getElementType(); - QualType DestElementType = - DestType->castAs<ComplexType>()->getElementType(); - ComplexVal.first = CGF.EmitScalarConversion( - Val.getComplexVal().first, SrcElementType, DestElementType, Loc); - ComplexVal.second = CGF.EmitScalarConversion( - Val.getComplexVal().second, SrcElementType, DestElementType, Loc); - } - return ComplexVal; -} - -static void emitSimpleAtomicStore(CodeGenFunction &CGF, bool IsSeqCst, - LValue LVal, RValue RVal) { - if (LVal.isGlobalReg()) { - CGF.EmitStoreThroughGlobalRegLValue(RVal, LVal); - } else { - CGF.EmitAtomicStore(RVal, LVal, - IsSeqCst ? llvm::AtomicOrdering::SequentiallyConsistent - : llvm::AtomicOrdering::Monotonic, - LVal.isVolatile(), /*IsInit=*/false); - } -} - -void CodeGenFunction::emitOMPSimpleStore(LValue LVal, RValue RVal, - QualType RValTy, SourceLocation Loc) { - switch (getEvaluationKind(LVal.getType())) { - case TEK_Scalar: - EmitStoreThroughLValue(RValue::get(convertToScalarValue( - *this, RVal, RValTy, LVal.getType(), Loc)), - LVal); - break; - case TEK_Complex: - EmitStoreOfComplex( - convertToComplexValue(*this, RVal, RValTy, LVal.getType(), Loc), LVal, - /*isInit=*/false); - break; - case TEK_Aggregate: - llvm_unreachable("Must be a scalar or complex."); - } -} - -static void emitOMPAtomicReadExpr(CodeGenFunction &CGF, bool IsSeqCst, - const Expr *X, const Expr *V, - SourceLocation Loc) { - // v = x; - assert(V->isLValue() && "V of 'omp atomic read' is not lvalue"); - assert(X->isLValue() && "X of 'omp atomic read' is not lvalue"); - LValue XLValue = CGF.EmitLValue(X); - LValue VLValue = CGF.EmitLValue(V); - RValue Res = XLValue.isGlobalReg() - ? CGF.EmitLoadOfLValue(XLValue, Loc) - : CGF.EmitAtomicLoad( - XLValue, Loc, - IsSeqCst ? llvm::AtomicOrdering::SequentiallyConsistent - : llvm::AtomicOrdering::Monotonic, - XLValue.isVolatile()); - // OpenMP, 2.12.6, atomic Construct - // Any atomic construct with a seq_cst clause forces the atomically - // performed operation to include an implicit flush operation without a - // list. - if (IsSeqCst) - CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc); - CGF.emitOMPSimpleStore(VLValue, Res, X->getType().getNonReferenceType(), Loc); -} - -static void emitOMPAtomicWriteExpr(CodeGenFunction &CGF, bool IsSeqCst, - const Expr *X, const Expr *E, - SourceLocation Loc) { - // x = expr; - assert(X->isLValue() && "X of 'omp atomic write' is not lvalue"); - emitSimpleAtomicStore(CGF, IsSeqCst, CGF.EmitLValue(X), CGF.EmitAnyExpr(E)); - // OpenMP, 2.12.6, atomic Construct - // Any atomic construct with a seq_cst clause forces the atomically - // performed operation to include an implicit flush operation without a - // list. - if (IsSeqCst) - CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc); -} - -static std::pair<bool, RValue> emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X, - RValue Update, - BinaryOperatorKind BO, - llvm::AtomicOrdering AO, - bool IsXLHSInRHSPart) { - ASTContext &Context = CGF.getContext(); - // Allow atomicrmw only if 'x' and 'update' are integer values, lvalue for 'x' - // expression is simple and atomic is allowed for the given type for the - // target platform. - if (BO == BO_Comma || !Update.isScalar() || - !Update.getScalarVal()->getType()->isIntegerTy() || - !X.isSimple() || (!isa<llvm::ConstantInt>(Update.getScalarVal()) && - (Update.getScalarVal()->getType() != - X.getAddress().getElementType())) || - !X.getAddress().getElementType()->isIntegerTy() || - !Context.getTargetInfo().hasBuiltinAtomic( - Context.getTypeSize(X.getType()), Context.toBits(X.getAlignment()))) - return std::make_pair(false, RValue::get(nullptr)); - - llvm::AtomicRMWInst::BinOp RMWOp; - switch (BO) { - case BO_Add: - RMWOp = llvm::AtomicRMWInst::Add; - break; - case BO_Sub: - if (!IsXLHSInRHSPart) - return std::make_pair(false, RValue::get(nullptr)); - RMWOp = llvm::AtomicRMWInst::Sub; - break; - case BO_And: - RMWOp = llvm::AtomicRMWInst::And; - break; - case BO_Or: - RMWOp = llvm::AtomicRMWInst::Or; - break; - case BO_Xor: - RMWOp = llvm::AtomicRMWInst::Xor; - break; - case BO_LT: - RMWOp = X.getType()->hasSignedIntegerRepresentation() - ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min - : llvm::AtomicRMWInst::Max) - : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin - : llvm::AtomicRMWInst::UMax); - break; - case BO_GT: - RMWOp = X.getType()->hasSignedIntegerRepresentation() - ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max - : llvm::AtomicRMWInst::Min) - : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax - : llvm::AtomicRMWInst::UMin); - break; - case BO_Assign: - RMWOp = llvm::AtomicRMWInst::Xchg; - break; - case BO_Mul: - case BO_Div: - case BO_Rem: - case BO_Shl: - case BO_Shr: - case BO_LAnd: - case BO_LOr: - return std::make_pair(false, RValue::get(nullptr)); - case BO_PtrMemD: - case BO_PtrMemI: - case BO_LE: - case BO_GE: - case BO_EQ: - case BO_NE: - case BO_Cmp: - case BO_AddAssign: - case BO_SubAssign: - case BO_AndAssign: - case BO_OrAssign: - case BO_XorAssign: - case BO_MulAssign: - case BO_DivAssign: - case BO_RemAssign: - case BO_ShlAssign: - case BO_ShrAssign: - case BO_Comma: - llvm_unreachable("Unsupported atomic update operation"); - } - llvm::Value *UpdateVal = Update.getScalarVal(); - if (auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) { - UpdateVal = CGF.Builder.CreateIntCast( - IC, X.getAddress().getElementType(), - X.getType()->hasSignedIntegerRepresentation()); - } - llvm::Value *Res = - CGF.Builder.CreateAtomicRMW(RMWOp, X.getPointer(), UpdateVal, AO); - return std::make_pair(true, RValue::get(Res)); -} - -std::pair<bool, RValue> CodeGenFunction::EmitOMPAtomicSimpleUpdateExpr( - LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart, - llvm::AtomicOrdering AO, SourceLocation Loc, - const llvm::function_ref<RValue(RValue)> CommonGen) { - // Update expressions are allowed to have the following forms: - // x binop= expr; -> xrval + expr; - // x++, ++x -> xrval + 1; - // x--, --x -> xrval - 1; - // x = x binop expr; -> xrval binop expr - // x = expr Op x; - > expr binop xrval; - auto Res = emitOMPAtomicRMW(*this, X, E, BO, AO, IsXLHSInRHSPart); - if (!Res.first) { - if (X.isGlobalReg()) { - // Emit an update expression: 'xrval' binop 'expr' or 'expr' binop - // 'xrval'. - EmitStoreThroughLValue(CommonGen(EmitLoadOfLValue(X, Loc)), X); - } else { - // Perform compare-and-swap procedure. - EmitAtomicUpdate(X, AO, CommonGen, X.getType().isVolatileQualified()); - } - } - return Res; -} - -static void emitOMPAtomicUpdateExpr(CodeGenFunction &CGF, bool IsSeqCst, - const Expr *X, const Expr *E, - const Expr *UE, bool IsXLHSInRHSPart, - SourceLocation Loc) { - assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) && - "Update expr in 'atomic update' must be a binary operator."); - const auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts()); - // Update expressions are allowed to have the following forms: - // x binop= expr; -> xrval + expr; - // x++, ++x -> xrval + 1; - // x--, --x -> xrval - 1; - // x = x binop expr; -> xrval binop expr - // x = expr Op x; - > expr binop xrval; - assert(X->isLValue() && "X of 'omp atomic update' is not lvalue"); - LValue XLValue = CGF.EmitLValue(X); - RValue ExprRValue = CGF.EmitAnyExpr(E); - llvm::AtomicOrdering AO = IsSeqCst - ? llvm::AtomicOrdering::SequentiallyConsistent - : llvm::AtomicOrdering::Monotonic; - const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts()); - const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts()); - const OpaqueValueExpr *XRValExpr = IsXLHSInRHSPart ? LHS : RHS; - const OpaqueValueExpr *ERValExpr = IsXLHSInRHSPart ? RHS : LHS; - auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](RValue XRValue) { - CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue); - CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue); - return CGF.EmitAnyExpr(UE); - }; - (void)CGF.EmitOMPAtomicSimpleUpdateExpr( - XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen); - // OpenMP, 2.12.6, atomic Construct - // Any atomic construct with a seq_cst clause forces the atomically - // performed operation to include an implicit flush operation without a - // list. - if (IsSeqCst) - CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc); -} - -static RValue convertToType(CodeGenFunction &CGF, RValue Value, - QualType SourceType, QualType ResType, - SourceLocation Loc) { - switch (CGF.getEvaluationKind(ResType)) { - case TEK_Scalar: - return RValue::get( - convertToScalarValue(CGF, Value, SourceType, ResType, Loc)); - case TEK_Complex: { - auto Res = convertToComplexValue(CGF, Value, SourceType, ResType, Loc); - return RValue::getComplex(Res.first, Res.second); - } - case TEK_Aggregate: - break; - } - llvm_unreachable("Must be a scalar or complex."); -} - -static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF, bool IsSeqCst, - bool IsPostfixUpdate, const Expr *V, - const Expr *X, const Expr *E, - const Expr *UE, bool IsXLHSInRHSPart, - SourceLocation Loc) { - assert(X->isLValue() && "X of 'omp atomic capture' is not lvalue"); - assert(V->isLValue() && "V of 'omp atomic capture' is not lvalue"); - RValue NewVVal; - LValue VLValue = CGF.EmitLValue(V); - LValue XLValue = CGF.EmitLValue(X); - RValue ExprRValue = CGF.EmitAnyExpr(E); - llvm::AtomicOrdering AO = IsSeqCst - ? llvm::AtomicOrdering::SequentiallyConsistent - : llvm::AtomicOrdering::Monotonic; - QualType NewVValType; - if (UE) { - // 'x' is updated with some additional value. - assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) && - "Update expr in 'atomic capture' must be a binary operator."); - const auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts()); - // Update expressions are allowed to have the following forms: - // x binop= expr; -> xrval + expr; - // x++, ++x -> xrval + 1; - // x--, --x -> xrval - 1; - // x = x binop expr; -> xrval binop expr - // x = expr Op x; - > expr binop xrval; - const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts()); - const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts()); - const OpaqueValueExpr *XRValExpr = IsXLHSInRHSPart ? LHS : RHS; - NewVValType = XRValExpr->getType(); - const OpaqueValueExpr *ERValExpr = IsXLHSInRHSPart ? RHS : LHS; - auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr, - IsPostfixUpdate](RValue XRValue) { - CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue); - CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue); - RValue Res = CGF.EmitAnyExpr(UE); - NewVVal = IsPostfixUpdate ? XRValue : Res; - return Res; - }; - auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr( - XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen); - if (Res.first) { - // 'atomicrmw' instruction was generated. - if (IsPostfixUpdate) { - // Use old value from 'atomicrmw'. - NewVVal = Res.second; - } else { - // 'atomicrmw' does not provide new value, so evaluate it using old - // value of 'x'. - CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue); - CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, Res.second); - NewVVal = CGF.EmitAnyExpr(UE); - } - } - } else { - // 'x' is simply rewritten with some 'expr'. - NewVValType = X->getType().getNonReferenceType(); - ExprRValue = convertToType(CGF, ExprRValue, E->getType(), - X->getType().getNonReferenceType(), Loc); - auto &&Gen = [&NewVVal, ExprRValue](RValue XRValue) { - NewVVal = XRValue; - return ExprRValue; - }; - // Try to perform atomicrmw xchg, otherwise simple exchange. - auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr( - XLValue, ExprRValue, /*BO=*/BO_Assign, /*IsXLHSInRHSPart=*/false, AO, - Loc, Gen); - if (Res.first) { - // 'atomicrmw' instruction was generated. - NewVVal = IsPostfixUpdate ? Res.second : ExprRValue; - } - } - // Emit post-update store to 'v' of old/new 'x' value. - CGF.emitOMPSimpleStore(VLValue, NewVVal, NewVValType, Loc); - // OpenMP, 2.12.6, atomic Construct - // Any atomic construct with a seq_cst clause forces the atomically - // performed operation to include an implicit flush operation without a - // list. - if (IsSeqCst) - CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc); -} - -static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, - bool IsSeqCst, bool IsPostfixUpdate, - const Expr *X, const Expr *V, const Expr *E, - const Expr *UE, bool IsXLHSInRHSPart, - SourceLocation Loc) { - switch (Kind) { - case OMPC_read: - emitOMPAtomicReadExpr(CGF, IsSeqCst, X, V, Loc); - break; - case OMPC_write: - emitOMPAtomicWriteExpr(CGF, IsSeqCst, X, E, Loc); - break; - case OMPC_unknown: - case OMPC_update: - emitOMPAtomicUpdateExpr(CGF, IsSeqCst, X, E, UE, IsXLHSInRHSPart, Loc); - break; - case OMPC_capture: - emitOMPAtomicCaptureExpr(CGF, IsSeqCst, IsPostfixUpdate, V, X, E, UE, - IsXLHSInRHSPart, Loc); - break; - case OMPC_if: - case OMPC_final: - case OMPC_num_threads: - case OMPC_private: - case OMPC_firstprivate: - case OMPC_lastprivate: - case OMPC_reduction: - case OMPC_task_reduction: - case OMPC_in_reduction: - case OMPC_safelen: - case OMPC_simdlen: - case OMPC_collapse: - case OMPC_default: - case OMPC_seq_cst: - case OMPC_shared: - case OMPC_linear: - case OMPC_aligned: - case OMPC_copyin: - case OMPC_copyprivate: - case OMPC_flush: - case OMPC_proc_bind: - case OMPC_schedule: - case OMPC_ordered: - case OMPC_nowait: - case OMPC_untied: - case OMPC_threadprivate: - case OMPC_depend: - case OMPC_mergeable: - case OMPC_device: - case OMPC_threads: - case OMPC_simd: - case OMPC_map: - case OMPC_num_teams: - case OMPC_thread_limit: - case OMPC_priority: - case OMPC_grainsize: - case OMPC_nogroup: - case OMPC_num_tasks: - case OMPC_hint: - case OMPC_dist_schedule: - case OMPC_defaultmap: - case OMPC_uniform: - case OMPC_to: - case OMPC_from: - case OMPC_use_device_ptr: - case OMPC_is_device_ptr: - case OMPC_unified_address: - case OMPC_unified_shared_memory: - case OMPC_reverse_offload: - case OMPC_dynamic_allocators: - case OMPC_atomic_default_mem_order: - llvm_unreachable("Clause is not allowed in 'omp atomic'."); - } -} - -void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) { - bool IsSeqCst = S.getSingleClause<OMPSeqCstClause>(); - OpenMPClauseKind Kind = OMPC_unknown; - for (const OMPClause *C : S.clauses()) { - // Find first clause (skip seq_cst clause, if it is first). - if (C->getClauseKind() != OMPC_seq_cst) { - Kind = C->getClauseKind(); - break; - } - } - - const Stmt *CS = S.getInnermostCapturedStmt()->IgnoreContainers(); - if (const auto *FE = dyn_cast<FullExpr>(CS)) - enterFullExpression(FE); - // Processing for statements under 'atomic capture'. - if (const auto *Compound = dyn_cast<CompoundStmt>(CS)) { - for (const Stmt *C : Compound->body()) { - if (const auto *FE = dyn_cast<FullExpr>(C)) - enterFullExpression(FE); - } - } - - auto &&CodeGen = [&S, Kind, IsSeqCst, CS](CodeGenFunction &CGF, - PrePostActionTy &) { - CGF.EmitStopPoint(CS); - emitOMPAtomicExpr(CGF, Kind, IsSeqCst, S.isPostfixUpdate(), S.getX(), - S.getV(), S.getExpr(), S.getUpdateExpr(), - S.isXLHSInRHSPart(), S.getBeginLoc()); - }; - OMPLexicalScope Scope(*this, S, OMPD_unknown); - CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_atomic, CodeGen); -} - -static void emitCommonOMPTargetDirective(CodeGenFunction &CGF, - const OMPExecutableDirective &S, - const RegionCodeGenTy &CodeGen) { - assert(isOpenMPTargetExecutionDirective(S.getDirectiveKind())); - CodeGenModule &CGM = CGF.CGM; - - // On device emit this construct as inlined code. - if (CGM.getLangOpts().OpenMPIsDevice) { - OMPLexicalScope Scope(CGF, S, OMPD_target); - CGM.getOpenMPRuntime().emitInlinedDirective( - CGF, OMPD_target, [&S](CodeGenFunction &CGF, PrePostActionTy &) { - CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt()); - }); - return; - } - - llvm::Function *Fn = nullptr; - llvm::Constant *FnID = nullptr; - - const Expr *IfCond = nullptr; - // Check for the at most one if clause associated with the target region. - for (const auto *C : S.getClausesOfKind<OMPIfClause>()) { - if (C->getNameModifier() == OMPD_unknown || - C->getNameModifier() == OMPD_target) { - IfCond = C->getCondition(); - break; - } - } - - // Check if we have any device clause associated with the directive. - const Expr *Device = nullptr; - if (auto *C = S.getSingleClause<OMPDeviceClause>()) - Device = C->getDevice(); - - // Check if we have an if clause whose conditional always evaluates to false - // or if we do not have any targets specified. If so the target region is not - // an offload entry point. - bool IsOffloadEntry = true; - if (IfCond) { - bool Val; - if (CGF.ConstantFoldsToSimpleInteger(IfCond, Val) && !Val) - IsOffloadEntry = false; - } - if (CGM.getLangOpts().OMPTargetTriples.empty()) - IsOffloadEntry = false; - - assert(CGF.CurFuncDecl && "No parent declaration for target region!"); - StringRef ParentName; - // In case we have Ctors/Dtors we use the complete type variant to produce - // the mangling of the device outlined kernel. - if (const auto *D = dyn_cast<CXXConstructorDecl>(CGF.CurFuncDecl)) - ParentName = CGM.getMangledName(GlobalDecl(D, Ctor_Complete)); - else if (const auto *D = dyn_cast<CXXDestructorDecl>(CGF.CurFuncDecl)) - ParentName = CGM.getMangledName(GlobalDecl(D, Dtor_Complete)); - else - ParentName = - CGM.getMangledName(GlobalDecl(cast<FunctionDecl>(CGF.CurFuncDecl))); - - // Emit target region as a standalone region. - CGM.getOpenMPRuntime().emitTargetOutlinedFunction(S, ParentName, Fn, FnID, - IsOffloadEntry, CodeGen); - OMPLexicalScope Scope(CGF, S, OMPD_task); - auto &&SizeEmitter = [](CodeGenFunction &CGF, const OMPLoopDirective &D) { - OMPLoopScope(CGF, D); - // Emit calculation of the iterations count. - llvm::Value *NumIterations = CGF.EmitScalarExpr(D.getNumIterations()); - NumIterations = CGF.Builder.CreateIntCast(NumIterations, CGF.Int64Ty, - /*IsSigned=*/false); - return NumIterations; - }; - CGM.getOpenMPRuntime().emitTargetNumIterationsCall(CGF, S, Device, - SizeEmitter); - CGM.getOpenMPRuntime().emitTargetCall(CGF, S, Fn, FnID, IfCond, Device); -} - -static void emitTargetRegion(CodeGenFunction &CGF, const OMPTargetDirective &S, - PrePostActionTy &Action) { - Action.Enter(CGF); - CodeGenFunction::OMPPrivateScope PrivateScope(CGF); - (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope); - CGF.EmitOMPPrivateClause(S, PrivateScope); - (void)PrivateScope.Privatize(); - if (isOpenMPTargetExecutionDirective(S.getDirectiveKind())) - CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S); - - CGF.EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt()); -} - -void CodeGenFunction::EmitOMPTargetDeviceFunction(CodeGenModule &CGM, - StringRef ParentName, - const OMPTargetDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitTargetRegion(CGF, S, Action); - }; - llvm::Function *Fn; - llvm::Constant *Addr; - // Emit target region as a standalone region. - CGM.getOpenMPRuntime().emitTargetOutlinedFunction( - S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); - assert(Fn && Addr && "Target device function emission failed."); -} - -void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitTargetRegion(CGF, S, Action); - }; - emitCommonOMPTargetDirective(*this, S, CodeGen); -} - -static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF, - const OMPExecutableDirective &S, - OpenMPDirectiveKind InnermostKind, - const RegionCodeGenTy &CodeGen) { - const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams); - llvm::Value *OutlinedFn = - CGF.CGM.getOpenMPRuntime().emitTeamsOutlinedFunction( - S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen); - - const auto *NT = S.getSingleClause<OMPNumTeamsClause>(); - const auto *TL = S.getSingleClause<OMPThreadLimitClause>(); - if (NT || TL) { - const Expr *NumTeams = NT ? NT->getNumTeams() : nullptr; - const Expr *ThreadLimit = TL ? TL->getThreadLimit() : nullptr; - - CGF.CGM.getOpenMPRuntime().emitNumTeamsClause(CGF, NumTeams, ThreadLimit, - S.getBeginLoc()); - } - - OMPTeamsScope Scope(CGF, S); - llvm::SmallVector<llvm::Value *, 16> CapturedVars; - CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars); - CGF.CGM.getOpenMPRuntime().emitTeamsCall(CGF, S, S.getBeginLoc(), OutlinedFn, - CapturedVars); -} - -void CodeGenFunction::EmitOMPTeamsDirective(const OMPTeamsDirective &S) { - // Emit teams region as a standalone region. - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - Action.Enter(CGF); - OMPPrivateScope PrivateScope(CGF); - (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope); - CGF.EmitOMPPrivateClause(S, PrivateScope); - CGF.EmitOMPReductionClauseInit(S, PrivateScope); - (void)PrivateScope.Privatize(); - CGF.EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt()); - CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); - }; - emitCommonOMPTeamsDirective(*this, S, OMPD_distribute, CodeGen); - emitPostUpdateForReductionClause(*this, S, - [](CodeGenFunction &) { return nullptr; }); -} - -static void emitTargetTeamsRegion(CodeGenFunction &CGF, PrePostActionTy &Action, - const OMPTargetTeamsDirective &S) { - auto *CS = S.getCapturedStmt(OMPD_teams); - Action.Enter(CGF); - // Emit teams region as a standalone region. - auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &Action) { - Action.Enter(CGF); - CodeGenFunction::OMPPrivateScope PrivateScope(CGF); - (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope); - CGF.EmitOMPPrivateClause(S, PrivateScope); - CGF.EmitOMPReductionClauseInit(S, PrivateScope); - (void)PrivateScope.Privatize(); - if (isOpenMPTargetExecutionDirective(S.getDirectiveKind())) - CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S); - CGF.EmitStmt(CS->getCapturedStmt()); - CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); - }; - emitCommonOMPTeamsDirective(CGF, S, OMPD_teams, CodeGen); - emitPostUpdateForReductionClause(CGF, S, - [](CodeGenFunction &) { return nullptr; }); -} - -void CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( - CodeGenModule &CGM, StringRef ParentName, - const OMPTargetTeamsDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitTargetTeamsRegion(CGF, Action, S); - }; - llvm::Function *Fn; - llvm::Constant *Addr; - // Emit target region as a standalone region. - CGM.getOpenMPRuntime().emitTargetOutlinedFunction( - S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); - assert(Fn && Addr && "Target device function emission failed."); -} - -void CodeGenFunction::EmitOMPTargetTeamsDirective( - const OMPTargetTeamsDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitTargetTeamsRegion(CGF, Action, S); - }; - emitCommonOMPTargetDirective(*this, S, CodeGen); -} - -static void -emitTargetTeamsDistributeRegion(CodeGenFunction &CGF, PrePostActionTy &Action, - const OMPTargetTeamsDistributeDirective &S) { - Action.Enter(CGF); - auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) { - CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc()); - }; - - // Emit teams region as a standalone region. - auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF, - PrePostActionTy &Action) { - Action.Enter(CGF); - CodeGenFunction::OMPPrivateScope PrivateScope(CGF); - CGF.EmitOMPReductionClauseInit(S, PrivateScope); - (void)PrivateScope.Privatize(); - CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute, - CodeGenDistribute); - CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); - }; - emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute, CodeGen); - emitPostUpdateForReductionClause(CGF, S, - [](CodeGenFunction &) { return nullptr; }); -} - -void CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( - CodeGenModule &CGM, StringRef ParentName, - const OMPTargetTeamsDistributeDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitTargetTeamsDistributeRegion(CGF, Action, S); - }; - llvm::Function *Fn; - llvm::Constant *Addr; - // Emit target region as a standalone region. - CGM.getOpenMPRuntime().emitTargetOutlinedFunction( - S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); - assert(Fn && Addr && "Target device function emission failed."); -} - -void CodeGenFunction::EmitOMPTargetTeamsDistributeDirective( - const OMPTargetTeamsDistributeDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitTargetTeamsDistributeRegion(CGF, Action, S); - }; - emitCommonOMPTargetDirective(*this, S, CodeGen); -} - -static void emitTargetTeamsDistributeSimdRegion( - CodeGenFunction &CGF, PrePostActionTy &Action, - const OMPTargetTeamsDistributeSimdDirective &S) { - Action.Enter(CGF); - auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) { - CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc()); - }; - - // Emit teams region as a standalone region. - auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF, - PrePostActionTy &Action) { - Action.Enter(CGF); - CodeGenFunction::OMPPrivateScope PrivateScope(CGF); - CGF.EmitOMPReductionClauseInit(S, PrivateScope); - (void)PrivateScope.Privatize(); - CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute, - CodeGenDistribute); - CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); - }; - emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_simd, CodeGen); - emitPostUpdateForReductionClause(CGF, S, - [](CodeGenFunction &) { return nullptr; }); -} - -void CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( - CodeGenModule &CGM, StringRef ParentName, - const OMPTargetTeamsDistributeSimdDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitTargetTeamsDistributeSimdRegion(CGF, Action, S); - }; - llvm::Function *Fn; - llvm::Constant *Addr; - // Emit target region as a standalone region. - CGM.getOpenMPRuntime().emitTargetOutlinedFunction( - S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); - assert(Fn && Addr && "Target device function emission failed."); -} - -void CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDirective( - const OMPTargetTeamsDistributeSimdDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitTargetTeamsDistributeSimdRegion(CGF, Action, S); - }; - emitCommonOMPTargetDirective(*this, S, CodeGen); -} - -void CodeGenFunction::EmitOMPTeamsDistributeDirective( - const OMPTeamsDistributeDirective &S) { - - auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) { - CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc()); - }; - - // Emit teams region as a standalone region. - auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF, - PrePostActionTy &Action) { - Action.Enter(CGF); - OMPPrivateScope PrivateScope(CGF); - CGF.EmitOMPReductionClauseInit(S, PrivateScope); - (void)PrivateScope.Privatize(); - CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute, - CodeGenDistribute); - CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); - }; - emitCommonOMPTeamsDirective(*this, S, OMPD_distribute, CodeGen); - emitPostUpdateForReductionClause(*this, S, - [](CodeGenFunction &) { return nullptr; }); -} - -void CodeGenFunction::EmitOMPTeamsDistributeSimdDirective( - const OMPTeamsDistributeSimdDirective &S) { - auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) { - CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc()); - }; - - // Emit teams region as a standalone region. - auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF, - PrePostActionTy &Action) { - Action.Enter(CGF); - OMPPrivateScope PrivateScope(CGF); - CGF.EmitOMPReductionClauseInit(S, PrivateScope); - (void)PrivateScope.Privatize(); - CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_simd, - CodeGenDistribute); - CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); - }; - emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_simd, CodeGen); - emitPostUpdateForReductionClause(*this, S, - [](CodeGenFunction &) { return nullptr; }); -} - -void CodeGenFunction::EmitOMPTeamsDistributeParallelForDirective( - const OMPTeamsDistributeParallelForDirective &S) { - auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) { - CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined, - S.getDistInc()); - }; - - // Emit teams region as a standalone region. - auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF, - PrePostActionTy &Action) { - Action.Enter(CGF); - OMPPrivateScope PrivateScope(CGF); - CGF.EmitOMPReductionClauseInit(S, PrivateScope); - (void)PrivateScope.Privatize(); - CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute, - CodeGenDistribute); - CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); - }; - emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_parallel_for, CodeGen); - emitPostUpdateForReductionClause(*this, S, - [](CodeGenFunction &) { return nullptr; }); -} - -void CodeGenFunction::EmitOMPTeamsDistributeParallelForSimdDirective( - const OMPTeamsDistributeParallelForSimdDirective &S) { - auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) { - CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined, - S.getDistInc()); - }; - - // Emit teams region as a standalone region. - auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF, - PrePostActionTy &Action) { - Action.Enter(CGF); - OMPPrivateScope PrivateScope(CGF); - CGF.EmitOMPReductionClauseInit(S, PrivateScope); - (void)PrivateScope.Privatize(); - CGF.CGM.getOpenMPRuntime().emitInlinedDirective( - CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false); - CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); - }; - emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_parallel_for, CodeGen); - emitPostUpdateForReductionClause(*this, S, - [](CodeGenFunction &) { return nullptr; }); -} - -static void emitTargetTeamsDistributeParallelForRegion( - CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForDirective &S, - PrePostActionTy &Action) { - Action.Enter(CGF); - auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) { - CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined, - S.getDistInc()); - }; - - // Emit teams region as a standalone region. - auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF, - PrePostActionTy &Action) { - Action.Enter(CGF); - CodeGenFunction::OMPPrivateScope PrivateScope(CGF); - CGF.EmitOMPReductionClauseInit(S, PrivateScope); - (void)PrivateScope.Privatize(); - CGF.CGM.getOpenMPRuntime().emitInlinedDirective( - CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false); - CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); - }; - - emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_parallel_for, - CodeGenTeams); - emitPostUpdateForReductionClause(CGF, S, - [](CodeGenFunction &) { return nullptr; }); -} - -void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( - CodeGenModule &CGM, StringRef ParentName, - const OMPTargetTeamsDistributeParallelForDirective &S) { - // Emit SPMD target teams distribute parallel for region as a standalone - // region. - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitTargetTeamsDistributeParallelForRegion(CGF, S, Action); - }; - llvm::Function *Fn; - llvm::Constant *Addr; - // Emit target region as a standalone region. - CGM.getOpenMPRuntime().emitTargetOutlinedFunction( - S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); - assert(Fn && Addr && "Target device function emission failed."); -} - -void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDirective( - const OMPTargetTeamsDistributeParallelForDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitTargetTeamsDistributeParallelForRegion(CGF, S, Action); - }; - emitCommonOMPTargetDirective(*this, S, CodeGen); -} - -static void emitTargetTeamsDistributeParallelForSimdRegion( - CodeGenFunction &CGF, - const OMPTargetTeamsDistributeParallelForSimdDirective &S, - PrePostActionTy &Action) { - Action.Enter(CGF); - auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) { - CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined, - S.getDistInc()); - }; - - // Emit teams region as a standalone region. - auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF, - PrePostActionTy &Action) { - Action.Enter(CGF); - CodeGenFunction::OMPPrivateScope PrivateScope(CGF); - CGF.EmitOMPReductionClauseInit(S, PrivateScope); - (void)PrivateScope.Privatize(); - CGF.CGM.getOpenMPRuntime().emitInlinedDirective( - CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false); - CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); - }; - - emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_parallel_for_simd, - CodeGenTeams); - emitPostUpdateForReductionClause(CGF, S, - [](CodeGenFunction &) { return nullptr; }); -} - -void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( - CodeGenModule &CGM, StringRef ParentName, - const OMPTargetTeamsDistributeParallelForSimdDirective &S) { - // Emit SPMD target teams distribute parallel for simd region as a standalone - // region. - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitTargetTeamsDistributeParallelForSimdRegion(CGF, S, Action); - }; - llvm::Function *Fn; - llvm::Constant *Addr; - // Emit target region as a standalone region. - CGM.getOpenMPRuntime().emitTargetOutlinedFunction( - S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); - assert(Fn && Addr && "Target device function emission failed."); -} - -void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForSimdDirective( - const OMPTargetTeamsDistributeParallelForSimdDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitTargetTeamsDistributeParallelForSimdRegion(CGF, S, Action); - }; - emitCommonOMPTargetDirective(*this, S, CodeGen); -} - -void CodeGenFunction::EmitOMPCancellationPointDirective( - const OMPCancellationPointDirective &S) { - CGM.getOpenMPRuntime().emitCancellationPointCall(*this, S.getBeginLoc(), - S.getCancelRegion()); -} - -void CodeGenFunction::EmitOMPCancelDirective(const OMPCancelDirective &S) { - const Expr *IfCond = nullptr; - for (const auto *C : S.getClausesOfKind<OMPIfClause>()) { - if (C->getNameModifier() == OMPD_unknown || - C->getNameModifier() == OMPD_cancel) { - IfCond = C->getCondition(); - break; - } - } - CGM.getOpenMPRuntime().emitCancelCall(*this, S.getBeginLoc(), IfCond, - S.getCancelRegion()); -} - -CodeGenFunction::JumpDest -CodeGenFunction::getOMPCancelDestination(OpenMPDirectiveKind Kind) { - if (Kind == OMPD_parallel || Kind == OMPD_task || - Kind == OMPD_target_parallel) - return ReturnBlock; - assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections || - Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for || - Kind == OMPD_distribute_parallel_for || - Kind == OMPD_target_parallel_for || - Kind == OMPD_teams_distribute_parallel_for || - Kind == OMPD_target_teams_distribute_parallel_for); - return OMPCancelStack.getExitBlock(); -} - -void CodeGenFunction::EmitOMPUseDevicePtrClause( - const OMPClause &NC, OMPPrivateScope &PrivateScope, - const llvm::DenseMap<const ValueDecl *, Address> &CaptureDeviceAddrMap) { - const auto &C = cast<OMPUseDevicePtrClause>(NC); - auto OrigVarIt = C.varlist_begin(); - auto InitIt = C.inits().begin(); - for (const Expr *PvtVarIt : C.private_copies()) { - const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*OrigVarIt)->getDecl()); - const auto *InitVD = cast<VarDecl>(cast<DeclRefExpr>(*InitIt)->getDecl()); - const auto *PvtVD = cast<VarDecl>(cast<DeclRefExpr>(PvtVarIt)->getDecl()); - - // In order to identify the right initializer we need to match the - // declaration used by the mapping logic. In some cases we may get - // OMPCapturedExprDecl that refers to the original declaration. - const ValueDecl *MatchingVD = OrigVD; - if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) { - // OMPCapturedExprDecl are used to privative fields of the current - // structure. - const auto *ME = cast<MemberExpr>(OED->getInit()); - assert(isa<CXXThisExpr>(ME->getBase()) && - "Base should be the current struct!"); - MatchingVD = ME->getMemberDecl(); - } - - // If we don't have information about the current list item, move on to - // the next one. - auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD); - if (InitAddrIt == CaptureDeviceAddrMap.end()) - continue; - - bool IsRegistered = PrivateScope.addPrivate(OrigVD, [this, OrigVD, - InitAddrIt, InitVD, - PvtVD]() { - // Initialize the temporary initialization variable with the address we - // get from the runtime library. We have to cast the source address - // because it is always a void *. References are materialized in the - // privatization scope, so the initialization here disregards the fact - // the original variable is a reference. - QualType AddrQTy = - getContext().getPointerType(OrigVD->getType().getNonReferenceType()); - llvm::Type *AddrTy = ConvertTypeForMem(AddrQTy); - Address InitAddr = Builder.CreateBitCast(InitAddrIt->second, AddrTy); - setAddrOfLocalVar(InitVD, InitAddr); - - // Emit private declaration, it will be initialized by the value we - // declaration we just added to the local declarations map. - EmitDecl(*PvtVD); - - // The initialization variables reached its purpose in the emission - // of the previous declaration, so we don't need it anymore. - LocalDeclMap.erase(InitVD); - - // Return the address of the private variable. - return GetAddrOfLocalVar(PvtVD); - }); - assert(IsRegistered && "firstprivate var already registered as private"); - // Silence the warning about unused variable. - (void)IsRegistered; - - ++OrigVarIt; - ++InitIt; - } -} - -// Generate the instructions for '#pragma omp target data' directive. -void CodeGenFunction::EmitOMPTargetDataDirective( - const OMPTargetDataDirective &S) { - CGOpenMPRuntime::TargetDataInfo Info(/*RequiresDevicePointerInfo=*/true); - - // Create a pre/post action to signal the privatization of the device pointer. - // This action can be replaced by the OpenMP runtime code generation to - // deactivate privatization. - bool PrivatizeDevicePointers = false; - class DevicePointerPrivActionTy : public PrePostActionTy { - bool &PrivatizeDevicePointers; - - public: - explicit DevicePointerPrivActionTy(bool &PrivatizeDevicePointers) - : PrePostActionTy(), PrivatizeDevicePointers(PrivatizeDevicePointers) {} - void Enter(CodeGenFunction &CGF) override { - PrivatizeDevicePointers = true; - } - }; - DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers); - - auto &&CodeGen = [&S, &Info, &PrivatizeDevicePointers]( - CodeGenFunction &CGF, PrePostActionTy &Action) { - auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { - CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt()); - }; - - // Codegen that selects whether to generate the privatization code or not. - auto &&PrivCodeGen = [&S, &Info, &PrivatizeDevicePointers, - &InnermostCodeGen](CodeGenFunction &CGF, - PrePostActionTy &Action) { - RegionCodeGenTy RCG(InnermostCodeGen); - PrivatizeDevicePointers = false; - - // Call the pre-action to change the status of PrivatizeDevicePointers if - // needed. - Action.Enter(CGF); - - if (PrivatizeDevicePointers) { - OMPPrivateScope PrivateScope(CGF); - // Emit all instances of the use_device_ptr clause. - for (const auto *C : S.getClausesOfKind<OMPUseDevicePtrClause>()) - CGF.EmitOMPUseDevicePtrClause(*C, PrivateScope, - Info.CaptureDeviceAddrMap); - (void)PrivateScope.Privatize(); - RCG(CGF); - } else { - RCG(CGF); - } - }; - - // Forward the provided action to the privatization codegen. - RegionCodeGenTy PrivRCG(PrivCodeGen); - PrivRCG.setAction(Action); - - // Notwithstanding the body of the region is emitted as inlined directive, - // we don't use an inline scope as changes in the references inside the - // region are expected to be visible outside, so we do not privative them. - OMPLexicalScope Scope(CGF, S); - CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_target_data, - PrivRCG); - }; - - RegionCodeGenTy RCG(CodeGen); - - // If we don't have target devices, don't bother emitting the data mapping - // code. - if (CGM.getLangOpts().OMPTargetTriples.empty()) { - RCG(*this); - return; - } - - // Check if we have any if clause associated with the directive. - const Expr *IfCond = nullptr; - if (const auto *C = S.getSingleClause<OMPIfClause>()) - IfCond = C->getCondition(); - - // Check if we have any device clause associated with the directive. - const Expr *Device = nullptr; - if (const auto *C = S.getSingleClause<OMPDeviceClause>()) - Device = C->getDevice(); - - // Set the action to signal privatization of device pointers. - RCG.setAction(PrivAction); - - // Emit region code. - CGM.getOpenMPRuntime().emitTargetDataCalls(*this, S, IfCond, Device, RCG, - Info); -} - -void CodeGenFunction::EmitOMPTargetEnterDataDirective( - const OMPTargetEnterDataDirective &S) { - // If we don't have target devices, don't bother emitting the data mapping - // code. - if (CGM.getLangOpts().OMPTargetTriples.empty()) - return; - - // Check if we have any if clause associated with the directive. - const Expr *IfCond = nullptr; - if (const auto *C = S.getSingleClause<OMPIfClause>()) - IfCond = C->getCondition(); - - // Check if we have any device clause associated with the directive. - const Expr *Device = nullptr; - if (const auto *C = S.getSingleClause<OMPDeviceClause>()) - Device = C->getDevice(); - - OMPLexicalScope Scope(*this, S, OMPD_task); - CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device); -} - -void CodeGenFunction::EmitOMPTargetExitDataDirective( - const OMPTargetExitDataDirective &S) { - // If we don't have target devices, don't bother emitting the data mapping - // code. - if (CGM.getLangOpts().OMPTargetTriples.empty()) - return; - - // Check if we have any if clause associated with the directive. - const Expr *IfCond = nullptr; - if (const auto *C = S.getSingleClause<OMPIfClause>()) - IfCond = C->getCondition(); - - // Check if we have any device clause associated with the directive. - const Expr *Device = nullptr; - if (const auto *C = S.getSingleClause<OMPDeviceClause>()) - Device = C->getDevice(); - - OMPLexicalScope Scope(*this, S, OMPD_task); - CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device); -} - -static void emitTargetParallelRegion(CodeGenFunction &CGF, - const OMPTargetParallelDirective &S, - PrePostActionTy &Action) { - // Get the captured statement associated with the 'parallel' region. - const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel); - Action.Enter(CGF); - auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &Action) { - Action.Enter(CGF); - CodeGenFunction::OMPPrivateScope PrivateScope(CGF); - (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope); - CGF.EmitOMPPrivateClause(S, PrivateScope); - CGF.EmitOMPReductionClauseInit(S, PrivateScope); - (void)PrivateScope.Privatize(); - if (isOpenMPTargetExecutionDirective(S.getDirectiveKind())) - CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S); - // TODO: Add support for clauses. - CGF.EmitStmt(CS->getCapturedStmt()); - CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel); - }; - emitCommonOMPParallelDirective(CGF, S, OMPD_parallel, CodeGen, - emitEmptyBoundParameters); - emitPostUpdateForReductionClause(CGF, S, - [](CodeGenFunction &) { return nullptr; }); -} - -void CodeGenFunction::EmitOMPTargetParallelDeviceFunction( - CodeGenModule &CGM, StringRef ParentName, - const OMPTargetParallelDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitTargetParallelRegion(CGF, S, Action); - }; - llvm::Function *Fn; - llvm::Constant *Addr; - // Emit target region as a standalone region. - CGM.getOpenMPRuntime().emitTargetOutlinedFunction( - S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); - assert(Fn && Addr && "Target device function emission failed."); -} - -void CodeGenFunction::EmitOMPTargetParallelDirective( - const OMPTargetParallelDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitTargetParallelRegion(CGF, S, Action); - }; - emitCommonOMPTargetDirective(*this, S, CodeGen); -} - -static void emitTargetParallelForRegion(CodeGenFunction &CGF, - const OMPTargetParallelForDirective &S, - PrePostActionTy &Action) { - Action.Enter(CGF); - // Emit directive as a combined directive that consists of two implicit - // directives: 'parallel' with 'for' directive. - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - Action.Enter(CGF); - CodeGenFunction::OMPCancelStackRAII CancelRegion( - CGF, OMPD_target_parallel_for, S.hasCancel()); - CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds, - emitDispatchForLoopBounds); - }; - emitCommonOMPParallelDirective(CGF, S, OMPD_for, CodeGen, - emitEmptyBoundParameters); -} - -void CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( - CodeGenModule &CGM, StringRef ParentName, - const OMPTargetParallelForDirective &S) { - // Emit SPMD target parallel for region as a standalone region. - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitTargetParallelForRegion(CGF, S, Action); - }; - llvm::Function *Fn; - llvm::Constant *Addr; - // Emit target region as a standalone region. - CGM.getOpenMPRuntime().emitTargetOutlinedFunction( - S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); - assert(Fn && Addr && "Target device function emission failed."); -} - -void CodeGenFunction::EmitOMPTargetParallelForDirective( - const OMPTargetParallelForDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitTargetParallelForRegion(CGF, S, Action); - }; - emitCommonOMPTargetDirective(*this, S, CodeGen); -} - -static void -emitTargetParallelForSimdRegion(CodeGenFunction &CGF, - const OMPTargetParallelForSimdDirective &S, - PrePostActionTy &Action) { - Action.Enter(CGF); - // Emit directive as a combined directive that consists of two implicit - // directives: 'parallel' with 'for' directive. - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - Action.Enter(CGF); - CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds, - emitDispatchForLoopBounds); - }; - emitCommonOMPParallelDirective(CGF, S, OMPD_simd, CodeGen, - emitEmptyBoundParameters); -} - -void CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( - CodeGenModule &CGM, StringRef ParentName, - const OMPTargetParallelForSimdDirective &S) { - // Emit SPMD target parallel for region as a standalone region. - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitTargetParallelForSimdRegion(CGF, S, Action); - }; - llvm::Function *Fn; - llvm::Constant *Addr; - // Emit target region as a standalone region. - CGM.getOpenMPRuntime().emitTargetOutlinedFunction( - S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); - assert(Fn && Addr && "Target device function emission failed."); -} - -void CodeGenFunction::EmitOMPTargetParallelForSimdDirective( - const OMPTargetParallelForSimdDirective &S) { - auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { - emitTargetParallelForSimdRegion(CGF, S, Action); - }; - emitCommonOMPTargetDirective(*this, S, CodeGen); -} - -/// Emit a helper variable and return corresponding lvalue. -static void mapParam(CodeGenFunction &CGF, const DeclRefExpr *Helper, - const ImplicitParamDecl *PVD, - CodeGenFunction::OMPPrivateScope &Privates) { - const auto *VDecl = cast<VarDecl>(Helper->getDecl()); - Privates.addPrivate(VDecl, - [&CGF, PVD]() { return CGF.GetAddrOfLocalVar(PVD); }); -} - -void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) { - assert(isOpenMPTaskLoopDirective(S.getDirectiveKind())); - // Emit outlined function for task construct. - const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop); - Address CapturedStruct = GenerateCapturedStmtArgument(*CS); - QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl()); - const Expr *IfCond = nullptr; - for (const auto *C : S.getClausesOfKind<OMPIfClause>()) { - if (C->getNameModifier() == OMPD_unknown || - C->getNameModifier() == OMPD_taskloop) { - IfCond = C->getCondition(); - break; - } - } - - OMPTaskDataTy Data; - // Check if taskloop must be emitted without taskgroup. - Data.Nogroup = S.getSingleClause<OMPNogroupClause>(); - // TODO: Check if we should emit tied or untied task. - Data.Tied = true; - // Set scheduling for taskloop - if (const auto* Clause = S.getSingleClause<OMPGrainsizeClause>()) { - // grainsize clause - Data.Schedule.setInt(/*IntVal=*/false); - Data.Schedule.setPointer(EmitScalarExpr(Clause->getGrainsize())); - } else if (const auto* Clause = S.getSingleClause<OMPNumTasksClause>()) { - // num_tasks clause - Data.Schedule.setInt(/*IntVal=*/true); - Data.Schedule.setPointer(EmitScalarExpr(Clause->getNumTasks())); - } - - auto &&BodyGen = [CS, &S](CodeGenFunction &CGF, PrePostActionTy &) { - // if (PreCond) { - // for (IV in 0..LastIteration) BODY; - // <Final counter/linear vars updates>; - // } - // - - // Emit: if (PreCond) - begin. - // If the condition constant folds and can be elided, avoid emitting the - // whole loop. - bool CondConstant; - llvm::BasicBlock *ContBlock = nullptr; - OMPLoopScope PreInitScope(CGF, S); - if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) { - if (!CondConstant) - return; - } else { - llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("taskloop.if.then"); - ContBlock = CGF.createBasicBlock("taskloop.if.end"); - emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock, - CGF.getProfileCount(&S)); - CGF.EmitBlock(ThenBlock); - CGF.incrementProfileCounter(&S); - } - - if (isOpenMPSimdDirective(S.getDirectiveKind())) - CGF.EmitOMPSimdInit(S); - - OMPPrivateScope LoopScope(CGF); - // Emit helper vars inits. - enum { LowerBound = 5, UpperBound, Stride, LastIter }; - auto *I = CS->getCapturedDecl()->param_begin(); - auto *LBP = std::next(I, LowerBound); - auto *UBP = std::next(I, UpperBound); - auto *STP = std::next(I, Stride); - auto *LIP = std::next(I, LastIter); - mapParam(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable()), *LBP, - LoopScope); - mapParam(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable()), *UBP, - LoopScope); - mapParam(CGF, cast<DeclRefExpr>(S.getStrideVariable()), *STP, LoopScope); - mapParam(CGF, cast<DeclRefExpr>(S.getIsLastIterVariable()), *LIP, - LoopScope); - CGF.EmitOMPPrivateLoopCounters(S, LoopScope); - bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope); - (void)LoopScope.Privatize(); - // Emit the loop iteration variable. - const Expr *IVExpr = S.getIterationVariable(); - const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl()); - CGF.EmitVarDecl(*IVDecl); - CGF.EmitIgnoredExpr(S.getInit()); - - // Emit the iterations count variable. - // If it is not a variable, Sema decided to calculate iterations count on - // each iteration (e.g., it is foldable into a constant). - if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) { - CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl())); - // Emit calculation of the iterations count. - CGF.EmitIgnoredExpr(S.getCalcLastIteration()); - } - - CGF.EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(), - S.getInc(), - [&S](CodeGenFunction &CGF) { - CGF.EmitOMPLoopBody(S, JumpDest()); - CGF.EmitStopPoint(&S); - }, - [](CodeGenFunction &) {}); - // Emit: if (PreCond) - end. - if (ContBlock) { - CGF.EmitBranch(ContBlock); - CGF.EmitBlock(ContBlock, true); - } - // Emit final copy of the lastprivate variables if IsLastIter != 0. - if (HasLastprivateClause) { - CGF.EmitOMPLastprivateClauseFinal( - S, isOpenMPSimdDirective(S.getDirectiveKind()), - CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar( - CGF.GetAddrOfLocalVar(*LIP), /*Volatile=*/false, - (*LIP)->getType(), S.getBeginLoc()))); - } - }; - auto &&TaskGen = [&S, SharedsTy, CapturedStruct, - IfCond](CodeGenFunction &CGF, llvm::Value *OutlinedFn, - const OMPTaskDataTy &Data) { - auto &&CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond, - &Data](CodeGenFunction &CGF, PrePostActionTy &) { - OMPLoopScope PreInitScope(CGF, S); - CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S, - OutlinedFn, SharedsTy, - CapturedStruct, IfCond, Data); - }; - CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop, - CodeGen); - }; - if (Data.Nogroup) { - EmitOMPTaskBasedDirective(S, OMPD_taskloop, BodyGen, TaskGen, Data); - } else { - CGM.getOpenMPRuntime().emitTaskgroupRegion( - *this, - [&S, &BodyGen, &TaskGen, &Data](CodeGenFunction &CGF, - PrePostActionTy &Action) { - Action.Enter(CGF); - CGF.EmitOMPTaskBasedDirective(S, OMPD_taskloop, BodyGen, TaskGen, - Data); - }, - S.getBeginLoc()); - } -} - -void CodeGenFunction::EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S) { - EmitOMPTaskLoopBasedDirective(S); -} - -void CodeGenFunction::EmitOMPTaskLoopSimdDirective( - const OMPTaskLoopSimdDirective &S) { - EmitOMPTaskLoopBasedDirective(S); -} - -// Generate the instructions for '#pragma omp target update' directive. -void CodeGenFunction::EmitOMPTargetUpdateDirective( - const OMPTargetUpdateDirective &S) { - // If we don't have target devices, don't bother emitting the data mapping - // code. - if (CGM.getLangOpts().OMPTargetTriples.empty()) - return; - - // Check if we have any if clause associated with the directive. - const Expr *IfCond = nullptr; - if (const auto *C = S.getSingleClause<OMPIfClause>()) - IfCond = C->getCondition(); - - // Check if we have any device clause associated with the directive. - const Expr *Device = nullptr; - if (const auto *C = S.getSingleClause<OMPDeviceClause>()) - Device = C->getDevice(); - - OMPLexicalScope Scope(*this, S, OMPD_task); - CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device); -} - -void CodeGenFunction::EmitSimpleOMPExecutableDirective( - const OMPExecutableDirective &D) { - if (!D.hasAssociatedStmt() || !D.getAssociatedStmt()) - return; - auto &&CodeGen = [&D](CodeGenFunction &CGF, PrePostActionTy &Action) { - if (isOpenMPSimdDirective(D.getDirectiveKind())) { - emitOMPSimdRegion(CGF, cast<OMPLoopDirective>(D), Action); - } else { - OMPPrivateScope LoopGlobals(CGF); - if (const auto *LD = dyn_cast<OMPLoopDirective>(&D)) { - for (const Expr *E : LD->counters()) { - const auto *VD = dyn_cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - if (!VD->hasLocalStorage() && !CGF.LocalDeclMap.count(VD)) { - LValue GlobLVal = CGF.EmitLValue(E); - LoopGlobals.addPrivate( - VD, [&GlobLVal]() { return GlobLVal.getAddress(); }); - } - if (isa<OMPCapturedExprDecl>(VD)) { - // Emit only those that were not explicitly referenced in clauses. - if (!CGF.LocalDeclMap.count(VD)) - CGF.EmitVarDecl(*VD); - } - } - for (const auto *C : D.getClausesOfKind<OMPOrderedClause>()) { - if (!C->getNumForLoops()) - continue; - for (unsigned I = LD->getCollapsedNumber(), - E = C->getLoopNumIterations().size(); - I < E; ++I) { - if (const auto *VD = dyn_cast<OMPCapturedExprDecl>( - cast<DeclRefExpr>(C->getLoopCounter(I))->getDecl())) { - // Emit only those that were not explicitly referenced in clauses. - if (!CGF.LocalDeclMap.count(VD)) - CGF.EmitVarDecl(*VD); - } - } - } - } - LoopGlobals.Privatize(); - CGF.EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt()); - } - }; - OMPSimdLexicalScope Scope(*this, D); - CGM.getOpenMPRuntime().emitInlinedDirective( - *this, - isOpenMPSimdDirective(D.getDirectiveKind()) ? OMPD_simd - : D.getDirectiveKind(), - CodeGen); -} - diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGVTT.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGVTT.cpp deleted file mode 100644 index fbd8146702a..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGVTT.cpp +++ /dev/null @@ -1,180 +0,0 @@ -//===--- CGVTT.cpp - Emit LLVM Code for C++ VTTs --------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code dealing with C++ code generation of VTTs (vtable tables). -// -//===----------------------------------------------------------------------===// - -#include "CodeGenModule.h" -#include "CGCXXABI.h" -#include "clang/AST/RecordLayout.h" -#include "clang/AST/VTTBuilder.h" -using namespace clang; -using namespace CodeGen; - -static llvm::GlobalVariable * -GetAddrOfVTTVTable(CodeGenVTables &CGVT, CodeGenModule &CGM, - const CXXRecordDecl *MostDerivedClass, - const VTTVTable &VTable, - llvm::GlobalVariable::LinkageTypes Linkage, - VTableLayout::AddressPointsMapTy &AddressPoints) { - if (VTable.getBase() == MostDerivedClass) { - assert(VTable.getBaseOffset().isZero() && - "Most derived class vtable must have a zero offset!"); - // This is a regular vtable. - return CGM.getCXXABI().getAddrOfVTable(MostDerivedClass, CharUnits()); - } - - return CGVT.GenerateConstructionVTable(MostDerivedClass, - VTable.getBaseSubobject(), - VTable.isVirtual(), - Linkage, - AddressPoints); -} - -void -CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT, - llvm::GlobalVariable::LinkageTypes Linkage, - const CXXRecordDecl *RD) { - VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/true); - - llvm::Type *Int8PtrTy = CGM.Int8PtrTy, *Int32Ty = CGM.Int32Ty; - llvm::ArrayType *ArrayType = - llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size()); - - SmallVector<llvm::GlobalVariable *, 8> VTables; - SmallVector<VTableAddressPointsMapTy, 8> VTableAddressPoints; - for (const VTTVTable *i = Builder.getVTTVTables().begin(), - *e = Builder.getVTTVTables().end(); i != e; ++i) { - VTableAddressPoints.push_back(VTableAddressPointsMapTy()); - VTables.push_back(GetAddrOfVTTVTable(*this, CGM, RD, *i, Linkage, - VTableAddressPoints.back())); - } - - SmallVector<llvm::Constant *, 8> VTTComponents; - for (const VTTComponent *i = Builder.getVTTComponents().begin(), - *e = Builder.getVTTComponents().end(); i != e; ++i) { - const VTTVTable &VTTVT = Builder.getVTTVTables()[i->VTableIndex]; - llvm::GlobalVariable *VTable = VTables[i->VTableIndex]; - VTableLayout::AddressPointLocation AddressPoint; - if (VTTVT.getBase() == RD) { - // Just get the address point for the regular vtable. - AddressPoint = - getItaniumVTableContext().getVTableLayout(RD).getAddressPoint( - i->VTableBase); - } else { - AddressPoint = VTableAddressPoints[i->VTableIndex].lookup(i->VTableBase); - assert(AddressPoint.AddressPointIndex != 0 && - "Did not find ctor vtable address point!"); - } - - llvm::Value *Idxs[] = { - llvm::ConstantInt::get(Int32Ty, 0), - llvm::ConstantInt::get(Int32Ty, AddressPoint.VTableIndex), - llvm::ConstantInt::get(Int32Ty, AddressPoint.AddressPointIndex), - }; - - llvm::Constant *Init = llvm::ConstantExpr::getGetElementPtr( - VTable->getValueType(), VTable, Idxs, /*InBounds=*/true, - /*InRangeIndex=*/1); - - Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy); - - VTTComponents.push_back(Init); - } - - llvm::Constant *Init = llvm::ConstantArray::get(ArrayType, VTTComponents); - - VTT->setInitializer(Init); - - // Set the correct linkage. - VTT->setLinkage(Linkage); - - if (CGM.supportsCOMDAT() && VTT->isWeakForLinker()) - VTT->setComdat(CGM.getModule().getOrInsertComdat(VTT->getName())); - - // Set the right visibility. - CGM.setGVProperties(VTT, RD); -} - -llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) { - assert(RD->getNumVBases() && "Only classes with virtual bases need a VTT"); - - SmallString<256> OutName; - llvm::raw_svector_ostream Out(OutName); - cast<ItaniumMangleContext>(CGM.getCXXABI().getMangleContext()) - .mangleCXXVTT(RD, Out); - StringRef Name = OutName.str(); - - // This will also defer the definition of the VTT. - (void) CGM.getCXXABI().getAddrOfVTable(RD, CharUnits()); - - VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false); - - llvm::ArrayType *ArrayType = - llvm::ArrayType::get(CGM.Int8PtrTy, Builder.getVTTComponents().size()); - unsigned Align = CGM.getDataLayout().getABITypeAlignment(CGM.Int8PtrTy); - - llvm::GlobalVariable *GV = CGM.CreateOrReplaceCXXRuntimeVariable( - Name, ArrayType, llvm::GlobalValue::ExternalLinkage, Align); - GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - return GV; -} - -uint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD, - BaseSubobject Base) { - BaseSubobjectPairTy ClassSubobjectPair(RD, Base); - - SubVTTIndiciesMapTy::iterator I = SubVTTIndicies.find(ClassSubobjectPair); - if (I != SubVTTIndicies.end()) - return I->second; - - VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false); - - for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I = - Builder.getSubVTTIndicies().begin(), - E = Builder.getSubVTTIndicies().end(); I != E; ++I) { - // Insert all indices. - BaseSubobjectPairTy ClassSubobjectPair(RD, I->first); - - SubVTTIndicies.insert(std::make_pair(ClassSubobjectPair, I->second)); - } - - I = SubVTTIndicies.find(ClassSubobjectPair); - assert(I != SubVTTIndicies.end() && "Did not find index!"); - - return I->second; -} - -uint64_t -CodeGenVTables::getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD, - BaseSubobject Base) { - SecondaryVirtualPointerIndicesMapTy::iterator I = - SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base)); - - if (I != SecondaryVirtualPointerIndices.end()) - return I->second; - - VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false); - - // Insert all secondary vpointer indices. - for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I = - Builder.getSecondaryVirtualPointerIndices().begin(), - E = Builder.getSecondaryVirtualPointerIndices().end(); I != E; ++I) { - std::pair<const CXXRecordDecl *, BaseSubobject> Pair = - std::make_pair(RD, I->first); - - SecondaryVirtualPointerIndices.insert(std::make_pair(Pair, I->second)); - } - - I = SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base)); - assert(I != SecondaryVirtualPointerIndices.end() && "Did not find index!"); - - return I->second; -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGVTables.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGVTables.cpp deleted file mode 100644 index bfb089ff908..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGVTables.cpp +++ /dev/null @@ -1,1068 +0,0 @@ -//===--- CGVTables.cpp - Emit LLVM Code for C++ vtables -------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code dealing with C++ code generation of virtual tables. -// -//===----------------------------------------------------------------------===// - -#include "CGCXXABI.h" -#include "CodeGenFunction.h" -#include "CodeGenModule.h" -#include "clang/AST/CXXInheritance.h" -#include "clang/AST/RecordLayout.h" -#include "clang/Basic/CodeGenOptions.h" -#include "clang/CodeGen/CGFunctionInfo.h" -#include "clang/CodeGen/ConstantInitBuilder.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/Support/Format.h" -#include "llvm/Transforms/Utils/Cloning.h" -#include <algorithm> -#include <cstdio> - -using namespace clang; -using namespace CodeGen; - -CodeGenVTables::CodeGenVTables(CodeGenModule &CGM) - : CGM(CGM), VTContext(CGM.getContext().getVTableContext()) {} - -llvm::Constant *CodeGenModule::GetAddrOfThunk(StringRef Name, llvm::Type *FnTy, - GlobalDecl GD) { - return GetOrCreateLLVMFunction(Name, FnTy, GD, /*ForVTable=*/true, - /*DontDefer=*/true, /*IsThunk=*/true); -} - -static void setThunkProperties(CodeGenModule &CGM, const ThunkInfo &Thunk, - llvm::Function *ThunkFn, bool ForVTable, - GlobalDecl GD) { - CGM.setFunctionLinkage(GD, ThunkFn); - CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD, - !Thunk.Return.isEmpty()); - - // Set the right visibility. - CGM.setGVProperties(ThunkFn, GD); - - if (!CGM.getCXXABI().exportThunk()) { - ThunkFn->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); - ThunkFn->setDSOLocal(true); - } - - if (CGM.supportsCOMDAT() && ThunkFn->isWeakForLinker()) - ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName())); -} - -#ifndef NDEBUG -static bool similar(const ABIArgInfo &infoL, CanQualType typeL, - const ABIArgInfo &infoR, CanQualType typeR) { - return (infoL.getKind() == infoR.getKind() && - (typeL == typeR || - (isa<PointerType>(typeL) && isa<PointerType>(typeR)) || - (isa<ReferenceType>(typeL) && isa<ReferenceType>(typeR)))); -} -#endif - -static RValue PerformReturnAdjustment(CodeGenFunction &CGF, - QualType ResultType, RValue RV, - const ThunkInfo &Thunk) { - // Emit the return adjustment. - bool NullCheckValue = !ResultType->isReferenceType(); - - llvm::BasicBlock *AdjustNull = nullptr; - llvm::BasicBlock *AdjustNotNull = nullptr; - llvm::BasicBlock *AdjustEnd = nullptr; - - llvm::Value *ReturnValue = RV.getScalarVal(); - - if (NullCheckValue) { - AdjustNull = CGF.createBasicBlock("adjust.null"); - AdjustNotNull = CGF.createBasicBlock("adjust.notnull"); - AdjustEnd = CGF.createBasicBlock("adjust.end"); - - llvm::Value *IsNull = CGF.Builder.CreateIsNull(ReturnValue); - CGF.Builder.CreateCondBr(IsNull, AdjustNull, AdjustNotNull); - CGF.EmitBlock(AdjustNotNull); - } - - auto ClassDecl = ResultType->getPointeeType()->getAsCXXRecordDecl(); - auto ClassAlign = CGF.CGM.getClassPointerAlignment(ClassDecl); - ReturnValue = CGF.CGM.getCXXABI().performReturnAdjustment(CGF, - Address(ReturnValue, ClassAlign), - Thunk.Return); - - if (NullCheckValue) { - CGF.Builder.CreateBr(AdjustEnd); - CGF.EmitBlock(AdjustNull); - CGF.Builder.CreateBr(AdjustEnd); - CGF.EmitBlock(AdjustEnd); - - llvm::PHINode *PHI = CGF.Builder.CreatePHI(ReturnValue->getType(), 2); - PHI->addIncoming(ReturnValue, AdjustNotNull); - PHI->addIncoming(llvm::Constant::getNullValue(ReturnValue->getType()), - AdjustNull); - ReturnValue = PHI; - } - - return RValue::get(ReturnValue); -} - -/// This function clones a function's DISubprogram node and enters it into -/// a value map with the intent that the map can be utilized by the cloner -/// to short-circuit Metadata node mapping. -/// Furthermore, the function resolves any DILocalVariable nodes referenced -/// by dbg.value intrinsics so they can be properly mapped during cloning. -static void resolveTopLevelMetadata(llvm::Function *Fn, - llvm::ValueToValueMapTy &VMap) { - // Clone the DISubprogram node and put it into the Value map. - auto *DIS = Fn->getSubprogram(); - if (!DIS) - return; - auto *NewDIS = DIS->replaceWithDistinct(DIS->clone()); - VMap.MD()[DIS].reset(NewDIS); - - // Find all llvm.dbg.declare intrinsics and resolve the DILocalVariable nodes - // they are referencing. - for (auto &BB : Fn->getBasicBlockList()) { - for (auto &I : BB) { - if (auto *DII = dyn_cast<llvm::DbgVariableIntrinsic>(&I)) { - auto *DILocal = DII->getVariable(); - if (!DILocal->isResolved()) - DILocal->resolve(); - } - } - } -} - -// This function does roughly the same thing as GenerateThunk, but in a -// very different way, so that va_start and va_end work correctly. -// FIXME: This function assumes "this" is the first non-sret LLVM argument of -// a function, and that there is an alloca built in the entry block -// for all accesses to "this". -// FIXME: This function assumes there is only one "ret" statement per function. -// FIXME: Cloning isn't correct in the presence of indirect goto! -// FIXME: This implementation of thunks bloats codesize by duplicating the -// function definition. There are alternatives: -// 1. Add some sort of stub support to LLVM for cases where we can -// do a this adjustment, then a sibcall. -// 2. We could transform the definition to take a va_list instead of an -// actual variable argument list, then have the thunks (including a -// no-op thunk for the regular definition) call va_start/va_end. -// There's a bit of per-call overhead for this solution, but it's -// better for codesize if the definition is long. -llvm::Function * -CodeGenFunction::GenerateVarArgsThunk(llvm::Function *Fn, - const CGFunctionInfo &FnInfo, - GlobalDecl GD, const ThunkInfo &Thunk) { - const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); - const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); - QualType ResultType = FPT->getReturnType(); - - // Get the original function - assert(FnInfo.isVariadic()); - llvm::Type *Ty = CGM.getTypes().GetFunctionType(FnInfo); - llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true); - llvm::Function *BaseFn = cast<llvm::Function>(Callee); - - // Clone to thunk. - llvm::ValueToValueMapTy VMap; - - // We are cloning a function while some Metadata nodes are still unresolved. - // Ensure that the value mapper does not encounter any of them. - resolveTopLevelMetadata(BaseFn, VMap); - llvm::Function *NewFn = llvm::CloneFunction(BaseFn, VMap); - Fn->replaceAllUsesWith(NewFn); - NewFn->takeName(Fn); - Fn->eraseFromParent(); - Fn = NewFn; - - // "Initialize" CGF (minimally). - CurFn = Fn; - - // Get the "this" value - llvm::Function::arg_iterator AI = Fn->arg_begin(); - if (CGM.ReturnTypeUsesSRet(FnInfo)) - ++AI; - - // Find the first store of "this", which will be to the alloca associated - // with "this". - Address ThisPtr(&*AI, CGM.getClassPointerAlignment(MD->getParent())); - llvm::BasicBlock *EntryBB = &Fn->front(); - llvm::BasicBlock::iterator ThisStore = - std::find_if(EntryBB->begin(), EntryBB->end(), [&](llvm::Instruction &I) { - return isa<llvm::StoreInst>(I) && - I.getOperand(0) == ThisPtr.getPointer(); - }); - assert(ThisStore != EntryBB->end() && - "Store of this should be in entry block?"); - // Adjust "this", if necessary. - Builder.SetInsertPoint(&*ThisStore); - llvm::Value *AdjustedThisPtr = - CGM.getCXXABI().performThisAdjustment(*this, ThisPtr, Thunk.This); - ThisStore->setOperand(0, AdjustedThisPtr); - - if (!Thunk.Return.isEmpty()) { - // Fix up the returned value, if necessary. - for (llvm::BasicBlock &BB : *Fn) { - llvm::Instruction *T = BB.getTerminator(); - if (isa<llvm::ReturnInst>(T)) { - RValue RV = RValue::get(T->getOperand(0)); - T->eraseFromParent(); - Builder.SetInsertPoint(&BB); - RV = PerformReturnAdjustment(*this, ResultType, RV, Thunk); - Builder.CreateRet(RV.getScalarVal()); - break; - } - } - } - - return Fn; -} - -void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD, - const CGFunctionInfo &FnInfo, - bool IsUnprototyped) { - assert(!CurGD.getDecl() && "CurGD was already set!"); - CurGD = GD; - CurFuncIsThunk = true; - - // Build FunctionArgs. - const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); - QualType ThisType = MD->getThisType(); - const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); - QualType ResultType; - if (IsUnprototyped) - ResultType = CGM.getContext().VoidTy; - else if (CGM.getCXXABI().HasThisReturn(GD)) - ResultType = ThisType; - else if (CGM.getCXXABI().hasMostDerivedReturn(GD)) - ResultType = CGM.getContext().VoidPtrTy; - else - ResultType = FPT->getReturnType(); - FunctionArgList FunctionArgs; - - // Create the implicit 'this' parameter declaration. - CGM.getCXXABI().buildThisParam(*this, FunctionArgs); - - // Add the rest of the parameters, if we have a prototype to work with. - if (!IsUnprototyped) { - FunctionArgs.append(MD->param_begin(), MD->param_end()); - - if (isa<CXXDestructorDecl>(MD)) - CGM.getCXXABI().addImplicitStructorParams(*this, ResultType, - FunctionArgs); - } - - // Start defining the function. - auto NL = ApplyDebugLocation::CreateEmpty(*this); - StartFunction(GlobalDecl(), ResultType, Fn, FnInfo, FunctionArgs, - MD->getLocation()); - // Create a scope with an artificial location for the body of this function. - auto AL = ApplyDebugLocation::CreateArtificial(*this); - - // Since we didn't pass a GlobalDecl to StartFunction, do this ourselves. - CGM.getCXXABI().EmitInstanceFunctionProlog(*this); - CXXThisValue = CXXABIThisValue; - CurCodeDecl = MD; - CurFuncDecl = MD; -} - -void CodeGenFunction::FinishThunk() { - // Clear these to restore the invariants expected by - // StartFunction/FinishFunction. - CurCodeDecl = nullptr; - CurFuncDecl = nullptr; - - FinishFunction(); -} - -void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Constant *CalleePtr, - const ThunkInfo *Thunk, - bool IsUnprototyped) { - assert(isa<CXXMethodDecl>(CurGD.getDecl()) && - "Please use a new CGF for this thunk"); - const CXXMethodDecl *MD = cast<CXXMethodDecl>(CurGD.getDecl()); - - // Adjust the 'this' pointer if necessary - llvm::Value *AdjustedThisPtr = - Thunk ? CGM.getCXXABI().performThisAdjustment( - *this, LoadCXXThisAddress(), Thunk->This) - : LoadCXXThis(); - - if (CurFnInfo->usesInAlloca() || IsUnprototyped) { - // We don't handle return adjusting thunks, because they require us to call - // the copy constructor. For now, fall through and pretend the return - // adjustment was empty so we don't crash. - if (Thunk && !Thunk->Return.isEmpty()) { - if (IsUnprototyped) - CGM.ErrorUnsupported( - MD, "return-adjusting thunk with incomplete parameter type"); - else - CGM.ErrorUnsupported( - MD, "non-trivial argument copy for return-adjusting thunk"); - } - EmitMustTailThunk(CurGD, AdjustedThisPtr, CalleePtr); - return; - } - - // Start building CallArgs. - CallArgList CallArgs; - QualType ThisType = MD->getThisType(); - CallArgs.add(RValue::get(AdjustedThisPtr), ThisType); - - if (isa<CXXDestructorDecl>(MD)) - CGM.getCXXABI().adjustCallArgsForDestructorThunk(*this, CurGD, CallArgs); - -#ifndef NDEBUG - unsigned PrefixArgs = CallArgs.size() - 1; -#endif - // Add the rest of the arguments. - for (const ParmVarDecl *PD : MD->parameters()) - EmitDelegateCallArg(CallArgs, PD, SourceLocation()); - - const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); - -#ifndef NDEBUG - const CGFunctionInfo &CallFnInfo = CGM.getTypes().arrangeCXXMethodCall( - CallArgs, FPT, RequiredArgs::forPrototypePlus(FPT, 1, MD), PrefixArgs); - assert(CallFnInfo.getRegParm() == CurFnInfo->getRegParm() && - CallFnInfo.isNoReturn() == CurFnInfo->isNoReturn() && - CallFnInfo.getCallingConvention() == CurFnInfo->getCallingConvention()); - assert(isa<CXXDestructorDecl>(MD) || // ignore dtor return types - similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(), - CurFnInfo->getReturnInfo(), CurFnInfo->getReturnType())); - assert(CallFnInfo.arg_size() == CurFnInfo->arg_size()); - for (unsigned i = 0, e = CurFnInfo->arg_size(); i != e; ++i) - assert(similar(CallFnInfo.arg_begin()[i].info, - CallFnInfo.arg_begin()[i].type, - CurFnInfo->arg_begin()[i].info, - CurFnInfo->arg_begin()[i].type)); -#endif - - // Determine whether we have a return value slot to use. - QualType ResultType = CGM.getCXXABI().HasThisReturn(CurGD) - ? ThisType - : CGM.getCXXABI().hasMostDerivedReturn(CurGD) - ? CGM.getContext().VoidPtrTy - : FPT->getReturnType(); - ReturnValueSlot Slot; - if (!ResultType->isVoidType() && - CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect) - Slot = ReturnValueSlot(ReturnValue, ResultType.isVolatileQualified()); - - // Now emit our call. - llvm::Instruction *CallOrInvoke; - CGCallee Callee = CGCallee::forDirect(CalleePtr, CurGD); - RValue RV = EmitCall(*CurFnInfo, Callee, Slot, CallArgs, &CallOrInvoke); - - // Consider return adjustment if we have ThunkInfo. - if (Thunk && !Thunk->Return.isEmpty()) - RV = PerformReturnAdjustment(*this, ResultType, RV, *Thunk); - else if (llvm::CallInst* Call = dyn_cast<llvm::CallInst>(CallOrInvoke)) - Call->setTailCallKind(llvm::CallInst::TCK_Tail); - - // Emit return. - if (!ResultType->isVoidType() && Slot.isNull()) - CGM.getCXXABI().EmitReturnFromThunk(*this, RV, ResultType); - - // Disable the final ARC autorelease. - AutoreleaseResult = false; - - FinishThunk(); -} - -void CodeGenFunction::EmitMustTailThunk(GlobalDecl GD, - llvm::Value *AdjustedThisPtr, - llvm::Value *CalleePtr) { - // Emitting a musttail call thunk doesn't use any of the CGCall.cpp machinery - // to translate AST arguments into LLVM IR arguments. For thunks, we know - // that the caller prototype more or less matches the callee prototype with - // the exception of 'this'. - SmallVector<llvm::Value *, 8> Args; - for (llvm::Argument &A : CurFn->args()) - Args.push_back(&A); - - // Set the adjusted 'this' pointer. - const ABIArgInfo &ThisAI = CurFnInfo->arg_begin()->info; - if (ThisAI.isDirect()) { - const ABIArgInfo &RetAI = CurFnInfo->getReturnInfo(); - int ThisArgNo = RetAI.isIndirect() && !RetAI.isSRetAfterThis() ? 1 : 0; - llvm::Type *ThisType = Args[ThisArgNo]->getType(); - if (ThisType != AdjustedThisPtr->getType()) - AdjustedThisPtr = Builder.CreateBitCast(AdjustedThisPtr, ThisType); - Args[ThisArgNo] = AdjustedThisPtr; - } else { - assert(ThisAI.isInAlloca() && "this is passed directly or inalloca"); - Address ThisAddr = GetAddrOfLocalVar(CXXABIThisDecl); - llvm::Type *ThisType = ThisAddr.getElementType(); - if (ThisType != AdjustedThisPtr->getType()) - AdjustedThisPtr = Builder.CreateBitCast(AdjustedThisPtr, ThisType); - Builder.CreateStore(AdjustedThisPtr, ThisAddr); - } - - // Emit the musttail call manually. Even if the prologue pushed cleanups, we - // don't actually want to run them. - llvm::CallInst *Call = Builder.CreateCall(CalleePtr, Args); - Call->setTailCallKind(llvm::CallInst::TCK_MustTail); - - // Apply the standard set of call attributes. - unsigned CallingConv; - llvm::AttributeList Attrs; - CGM.ConstructAttributeList(CalleePtr->getName(), *CurFnInfo, GD, Attrs, - CallingConv, /*AttrOnCallSite=*/true); - Call->setAttributes(Attrs); - Call->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv)); - - if (Call->getType()->isVoidTy()) - Builder.CreateRetVoid(); - else - Builder.CreateRet(Call); - - // Finish the function to maintain CodeGenFunction invariants. - // FIXME: Don't emit unreachable code. - EmitBlock(createBasicBlock()); - FinishFunction(); -} - -void CodeGenFunction::generateThunk(llvm::Function *Fn, - const CGFunctionInfo &FnInfo, GlobalDecl GD, - const ThunkInfo &Thunk, - bool IsUnprototyped) { - StartThunk(Fn, GD, FnInfo, IsUnprototyped); - // Create a scope with an artificial location for the body of this function. - auto AL = ApplyDebugLocation::CreateArtificial(*this); - - // Get our callee. Use a placeholder type if this method is unprototyped so - // that CodeGenModule doesn't try to set attributes. - llvm::Type *Ty; - if (IsUnprototyped) - Ty = llvm::StructType::get(getLLVMContext()); - else - Ty = CGM.getTypes().GetFunctionType(FnInfo); - - llvm::Constant *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true); - - // Fix up the function type for an unprototyped musttail call. - if (IsUnprototyped) - Callee = llvm::ConstantExpr::getBitCast(Callee, Fn->getType()); - - // Make the call and return the result. - EmitCallAndReturnForThunk(Callee, &Thunk, IsUnprototyped); -} - -static bool shouldEmitVTableThunk(CodeGenModule &CGM, const CXXMethodDecl *MD, - bool IsUnprototyped, bool ForVTable) { - // Always emit thunks in the MS C++ ABI. We cannot rely on other TUs to - // provide thunks for us. - if (CGM.getTarget().getCXXABI().isMicrosoft()) - return true; - - // In the Itanium C++ ABI, vtable thunks are provided by TUs that provide - // definitions of the main method. Therefore, emitting thunks with the vtable - // is purely an optimization. Emit the thunk if optimizations are enabled and - // all of the parameter types are complete. - if (ForVTable) - return CGM.getCodeGenOpts().OptimizationLevel && !IsUnprototyped; - - // Always emit thunks along with the method definition. - return true; -} - -llvm::Constant *CodeGenVTables::maybeEmitThunk(GlobalDecl GD, - const ThunkInfo &TI, - bool ForVTable) { - const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); - - // First, get a declaration. Compute the mangled name. Don't worry about - // getting the function prototype right, since we may only need this - // declaration to fill in a vtable slot. - SmallString<256> Name; - MangleContext &MCtx = CGM.getCXXABI().getMangleContext(); - llvm::raw_svector_ostream Out(Name); - if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) - MCtx.mangleCXXDtorThunk(DD, GD.getDtorType(), TI.This, Out); - else - MCtx.mangleThunk(MD, TI, Out); - llvm::Type *ThunkVTableTy = CGM.getTypes().GetFunctionTypeForVTable(GD); - llvm::Constant *Thunk = CGM.GetAddrOfThunk(Name, ThunkVTableTy, GD); - - // If we don't need to emit a definition, return this declaration as is. - bool IsUnprototyped = !CGM.getTypes().isFuncTypeConvertible( - MD->getType()->castAs<FunctionType>()); - if (!shouldEmitVTableThunk(CGM, MD, IsUnprototyped, ForVTable)) - return Thunk; - - // Arrange a function prototype appropriate for a function definition. In some - // cases in the MS ABI, we may need to build an unprototyped musttail thunk. - const CGFunctionInfo &FnInfo = - IsUnprototyped ? CGM.getTypes().arrangeUnprototypedMustTailThunk(MD) - : CGM.getTypes().arrangeGlobalDeclaration(GD); - llvm::FunctionType *ThunkFnTy = CGM.getTypes().GetFunctionType(FnInfo); - - // If the type of the underlying GlobalValue is wrong, we'll have to replace - // it. It should be a declaration. - llvm::Function *ThunkFn = cast<llvm::Function>(Thunk->stripPointerCasts()); - if (ThunkFn->getFunctionType() != ThunkFnTy) { - llvm::GlobalValue *OldThunkFn = ThunkFn; - - assert(OldThunkFn->isDeclaration() && "Shouldn't replace non-declaration"); - - // Remove the name from the old thunk function and get a new thunk. - OldThunkFn->setName(StringRef()); - ThunkFn = llvm::Function::Create(ThunkFnTy, llvm::Function::ExternalLinkage, - Name.str(), &CGM.getModule()); - CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn); - - // If needed, replace the old thunk with a bitcast. - if (!OldThunkFn->use_empty()) { - llvm::Constant *NewPtrForOldDecl = - llvm::ConstantExpr::getBitCast(ThunkFn, OldThunkFn->getType()); - OldThunkFn->replaceAllUsesWith(NewPtrForOldDecl); - } - - // Remove the old thunk. - OldThunkFn->eraseFromParent(); - } - - bool ABIHasKeyFunctions = CGM.getTarget().getCXXABI().hasKeyFunctions(); - bool UseAvailableExternallyLinkage = ForVTable && ABIHasKeyFunctions; - - if (!ThunkFn->isDeclaration()) { - if (!ABIHasKeyFunctions || UseAvailableExternallyLinkage) { - // There is already a thunk emitted for this function, do nothing. - return ThunkFn; - } - - setThunkProperties(CGM, TI, ThunkFn, ForVTable, GD); - return ThunkFn; - } - - // If this will be unprototyped, add the "thunk" attribute so that LLVM knows - // that the return type is meaningless. These thunks can be used to call - // functions with differing return types, and the caller is required to cast - // the prototype appropriately to extract the correct value. - if (IsUnprototyped) - ThunkFn->addFnAttr("thunk"); - - CGM.SetLLVMFunctionAttributesForDefinition(GD.getDecl(), ThunkFn); - - if (!IsUnprototyped && ThunkFn->isVarArg()) { - // Varargs thunks are special; we can't just generate a call because - // we can't copy the varargs. Our implementation is rather - // expensive/sucky at the moment, so don't generate the thunk unless - // we have to. - // FIXME: Do something better here; GenerateVarArgsThunk is extremely ugly. - if (UseAvailableExternallyLinkage) - return ThunkFn; - ThunkFn = CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, - TI); - } else { - // Normal thunk body generation. - CodeGenFunction(CGM).generateThunk(ThunkFn, FnInfo, GD, TI, IsUnprototyped); - } - - setThunkProperties(CGM, TI, ThunkFn, ForVTable, GD); - return ThunkFn; -} - -void CodeGenVTables::EmitThunks(GlobalDecl GD) { - const CXXMethodDecl *MD = - cast<CXXMethodDecl>(GD.getDecl())->getCanonicalDecl(); - - // We don't need to generate thunks for the base destructor. - if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base) - return; - - const VTableContextBase::ThunkInfoVectorTy *ThunkInfoVector = - VTContext->getThunkInfo(GD); - - if (!ThunkInfoVector) - return; - - for (const ThunkInfo& Thunk : *ThunkInfoVector) - maybeEmitThunk(GD, Thunk, /*ForVTable=*/false); -} - -void CodeGenVTables::addVTableComponent( - ConstantArrayBuilder &builder, const VTableLayout &layout, - unsigned idx, llvm::Constant *rtti, unsigned &nextVTableThunkIndex) { - auto &component = layout.vtable_components()[idx]; - - auto addOffsetConstant = [&](CharUnits offset) { - builder.add(llvm::ConstantExpr::getIntToPtr( - llvm::ConstantInt::get(CGM.PtrDiffTy, offset.getQuantity()), - CGM.Int8PtrTy)); - }; - - switch (component.getKind()) { - case VTableComponent::CK_VCallOffset: - return addOffsetConstant(component.getVCallOffset()); - - case VTableComponent::CK_VBaseOffset: - return addOffsetConstant(component.getVBaseOffset()); - - case VTableComponent::CK_OffsetToTop: - return addOffsetConstant(component.getOffsetToTop()); - - case VTableComponent::CK_RTTI: - return builder.add(llvm::ConstantExpr::getBitCast(rtti, CGM.Int8PtrTy)); - - case VTableComponent::CK_FunctionPointer: - case VTableComponent::CK_CompleteDtorPointer: - case VTableComponent::CK_DeletingDtorPointer: { - GlobalDecl GD; - - // Get the right global decl. - switch (component.getKind()) { - default: - llvm_unreachable("Unexpected vtable component kind"); - case VTableComponent::CK_FunctionPointer: - GD = component.getFunctionDecl(); - break; - case VTableComponent::CK_CompleteDtorPointer: - GD = GlobalDecl(component.getDestructorDecl(), Dtor_Complete); - break; - case VTableComponent::CK_DeletingDtorPointer: - GD = GlobalDecl(component.getDestructorDecl(), Dtor_Deleting); - break; - } - - if (CGM.getLangOpts().CUDA) { - // Emit NULL for methods we can't codegen on this - // side. Otherwise we'd end up with vtable with unresolved - // references. - const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); - // OK on device side: functions w/ __device__ attribute - // OK on host side: anything except __device__-only functions. - bool CanEmitMethod = - CGM.getLangOpts().CUDAIsDevice - ? MD->hasAttr<CUDADeviceAttr>() - : (MD->hasAttr<CUDAHostAttr>() || !MD->hasAttr<CUDADeviceAttr>()); - if (!CanEmitMethod) - return builder.addNullPointer(CGM.Int8PtrTy); - // Method is acceptable, continue processing as usual. - } - - auto getSpecialVirtualFn = [&](StringRef name) { - llvm::FunctionType *fnTy = - llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); - llvm::Constant *fn = CGM.CreateRuntimeFunction(fnTy, name); - if (auto f = dyn_cast<llvm::Function>(fn)) - f->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - return llvm::ConstantExpr::getBitCast(fn, CGM.Int8PtrTy); - }; - - llvm::Constant *fnPtr; - - // Pure virtual member functions. - if (cast<CXXMethodDecl>(GD.getDecl())->isPure()) { - if (!PureVirtualFn) - PureVirtualFn = - getSpecialVirtualFn(CGM.getCXXABI().GetPureVirtualCallName()); - fnPtr = PureVirtualFn; - - // Deleted virtual member functions. - } else if (cast<CXXMethodDecl>(GD.getDecl())->isDeleted()) { - if (!DeletedVirtualFn) - DeletedVirtualFn = - getSpecialVirtualFn(CGM.getCXXABI().GetDeletedVirtualCallName()); - fnPtr = DeletedVirtualFn; - - // Thunks. - } else if (nextVTableThunkIndex < layout.vtable_thunks().size() && - layout.vtable_thunks()[nextVTableThunkIndex].first == idx) { - auto &thunkInfo = layout.vtable_thunks()[nextVTableThunkIndex].second; - - nextVTableThunkIndex++; - fnPtr = maybeEmitThunk(GD, thunkInfo, /*ForVTable=*/true); - - // Otherwise we can use the method definition directly. - } else { - llvm::Type *fnTy = CGM.getTypes().GetFunctionTypeForVTable(GD); - fnPtr = CGM.GetAddrOfFunction(GD, fnTy, /*ForVTable=*/true); - } - - fnPtr = llvm::ConstantExpr::getBitCast(fnPtr, CGM.Int8PtrTy); - builder.add(fnPtr); - return; - } - - case VTableComponent::CK_UnusedFunctionPointer: - return builder.addNullPointer(CGM.Int8PtrTy); - } - - llvm_unreachable("Unexpected vtable component kind"); -} - -llvm::Type *CodeGenVTables::getVTableType(const VTableLayout &layout) { - SmallVector<llvm::Type *, 4> tys; - for (unsigned i = 0, e = layout.getNumVTables(); i != e; ++i) { - tys.push_back(llvm::ArrayType::get(CGM.Int8PtrTy, layout.getVTableSize(i))); - } - - return llvm::StructType::get(CGM.getLLVMContext(), tys); -} - -void CodeGenVTables::createVTableInitializer(ConstantStructBuilder &builder, - const VTableLayout &layout, - llvm::Constant *rtti) { - unsigned nextVTableThunkIndex = 0; - for (unsigned i = 0, e = layout.getNumVTables(); i != e; ++i) { - auto vtableElem = builder.beginArray(CGM.Int8PtrTy); - size_t thisIndex = layout.getVTableOffset(i); - size_t nextIndex = thisIndex + layout.getVTableSize(i); - for (unsigned i = thisIndex; i != nextIndex; ++i) { - addVTableComponent(vtableElem, layout, i, rtti, nextVTableThunkIndex); - } - vtableElem.finishAndAddTo(builder); - } -} - -llvm::GlobalVariable * -CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD, - const BaseSubobject &Base, - bool BaseIsVirtual, - llvm::GlobalVariable::LinkageTypes Linkage, - VTableAddressPointsMapTy& AddressPoints) { - if (CGDebugInfo *DI = CGM.getModuleDebugInfo()) - DI->completeClassData(Base.getBase()); - - std::unique_ptr<VTableLayout> VTLayout( - getItaniumVTableContext().createConstructionVTableLayout( - Base.getBase(), Base.getBaseOffset(), BaseIsVirtual, RD)); - - // Add the address points. - AddressPoints = VTLayout->getAddressPoints(); - - // Get the mangled construction vtable name. - SmallString<256> OutName; - llvm::raw_svector_ostream Out(OutName); - cast<ItaniumMangleContext>(CGM.getCXXABI().getMangleContext()) - .mangleCXXCtorVTable(RD, Base.getBaseOffset().getQuantity(), - Base.getBase(), Out); - StringRef Name = OutName.str(); - - llvm::Type *VTType = getVTableType(*VTLayout); - - // Construction vtable symbols are not part of the Itanium ABI, so we cannot - // guarantee that they actually will be available externally. Instead, when - // emitting an available_externally VTT, we provide references to an internal - // linkage construction vtable. The ABI only requires complete-object vtables - // to be the same for all instances of a type, not construction vtables. - if (Linkage == llvm::GlobalVariable::AvailableExternallyLinkage) - Linkage = llvm::GlobalVariable::InternalLinkage; - - unsigned Align = CGM.getDataLayout().getABITypeAlignment(VTType); - - // Create the variable that will hold the construction vtable. - llvm::GlobalVariable *VTable = - CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType, Linkage, Align); - CGM.setGVProperties(VTable, RD); - - // V-tables are always unnamed_addr. - VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - - llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor( - CGM.getContext().getTagDeclType(Base.getBase())); - - // Create and set the initializer. - ConstantInitBuilder builder(CGM); - auto components = builder.beginStruct(); - createVTableInitializer(components, *VTLayout, RTTI); - components.finishAndSetAsInitializer(VTable); - - CGM.EmitVTableTypeMetadata(VTable, *VTLayout.get()); - - return VTable; -} - -static bool shouldEmitAvailableExternallyVTable(const CodeGenModule &CGM, - const CXXRecordDecl *RD) { - return CGM.getCodeGenOpts().OptimizationLevel > 0 && - CGM.getCXXABI().canSpeculativelyEmitVTable(RD); -} - -/// Compute the required linkage of the vtable for the given class. -/// -/// Note that we only call this at the end of the translation unit. -llvm::GlobalVariable::LinkageTypes -CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) { - if (!RD->isExternallyVisible()) - return llvm::GlobalVariable::InternalLinkage; - - // We're at the end of the translation unit, so the current key - // function is fully correct. - const CXXMethodDecl *keyFunction = Context.getCurrentKeyFunction(RD); - if (keyFunction && !RD->hasAttr<DLLImportAttr>()) { - // If this class has a key function, use that to determine the - // linkage of the vtable. - const FunctionDecl *def = nullptr; - if (keyFunction->hasBody(def)) - keyFunction = cast<CXXMethodDecl>(def); - - switch (keyFunction->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ExplicitSpecialization: - assert((def || CodeGenOpts.OptimizationLevel > 0 || - CodeGenOpts.getDebugInfo() != codegenoptions::NoDebugInfo) && - "Shouldn't query vtable linkage without key function, " - "optimizations, or debug info"); - if (!def && CodeGenOpts.OptimizationLevel > 0) - return llvm::GlobalVariable::AvailableExternallyLinkage; - - if (keyFunction->isInlined()) - return !Context.getLangOpts().AppleKext ? - llvm::GlobalVariable::LinkOnceODRLinkage : - llvm::Function::InternalLinkage; - - return llvm::GlobalVariable::ExternalLinkage; - - case TSK_ImplicitInstantiation: - return !Context.getLangOpts().AppleKext ? - llvm::GlobalVariable::LinkOnceODRLinkage : - llvm::Function::InternalLinkage; - - case TSK_ExplicitInstantiationDefinition: - return !Context.getLangOpts().AppleKext ? - llvm::GlobalVariable::WeakODRLinkage : - llvm::Function::InternalLinkage; - - case TSK_ExplicitInstantiationDeclaration: - llvm_unreachable("Should not have been asked to emit this"); - } - } - - // -fapple-kext mode does not support weak linkage, so we must use - // internal linkage. - if (Context.getLangOpts().AppleKext) - return llvm::Function::InternalLinkage; - - llvm::GlobalVariable::LinkageTypes DiscardableODRLinkage = - llvm::GlobalValue::LinkOnceODRLinkage; - llvm::GlobalVariable::LinkageTypes NonDiscardableODRLinkage = - llvm::GlobalValue::WeakODRLinkage; - if (RD->hasAttr<DLLExportAttr>()) { - // Cannot discard exported vtables. - DiscardableODRLinkage = NonDiscardableODRLinkage; - } else if (RD->hasAttr<DLLImportAttr>()) { - // Imported vtables are available externally. - DiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage; - NonDiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage; - } - - switch (RD->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ExplicitSpecialization: - case TSK_ImplicitInstantiation: - return DiscardableODRLinkage; - - case TSK_ExplicitInstantiationDeclaration: - // Explicit instantiations in MSVC do not provide vtables, so we must emit - // our own. - if (getTarget().getCXXABI().isMicrosoft()) - return DiscardableODRLinkage; - return shouldEmitAvailableExternallyVTable(*this, RD) - ? llvm::GlobalVariable::AvailableExternallyLinkage - : llvm::GlobalVariable::ExternalLinkage; - - case TSK_ExplicitInstantiationDefinition: - return NonDiscardableODRLinkage; - } - - llvm_unreachable("Invalid TemplateSpecializationKind!"); -} - -/// This is a callback from Sema to tell us that a particular vtable is -/// required to be emitted in this translation unit. -/// -/// This is only called for vtables that _must_ be emitted (mainly due to key -/// functions). For weak vtables, CodeGen tracks when they are needed and -/// emits them as-needed. -void CodeGenModule::EmitVTable(CXXRecordDecl *theClass) { - VTables.GenerateClassData(theClass); -} - -void -CodeGenVTables::GenerateClassData(const CXXRecordDecl *RD) { - if (CGDebugInfo *DI = CGM.getModuleDebugInfo()) - DI->completeClassData(RD); - - if (RD->getNumVBases()) - CGM.getCXXABI().emitVirtualInheritanceTables(RD); - - CGM.getCXXABI().emitVTableDefinitions(*this, RD); -} - -/// At this point in the translation unit, does it appear that can we -/// rely on the vtable being defined elsewhere in the program? -/// -/// The response is really only definitive when called at the end of -/// the translation unit. -/// -/// The only semantic restriction here is that the object file should -/// not contain a vtable definition when that vtable is defined -/// strongly elsewhere. Otherwise, we'd just like to avoid emitting -/// vtables when unnecessary. -bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) { - assert(RD->isDynamicClass() && "Non-dynamic classes have no VTable."); - - // We always synthesize vtables if they are needed in the MS ABI. MSVC doesn't - // emit them even if there is an explicit template instantiation. - if (CGM.getTarget().getCXXABI().isMicrosoft()) - return false; - - // If we have an explicit instantiation declaration (and not a - // definition), the vtable is defined elsewhere. - TemplateSpecializationKind TSK = RD->getTemplateSpecializationKind(); - if (TSK == TSK_ExplicitInstantiationDeclaration) - return true; - - // Otherwise, if the class is an instantiated template, the - // vtable must be defined here. - if (TSK == TSK_ImplicitInstantiation || - TSK == TSK_ExplicitInstantiationDefinition) - return false; - - // Otherwise, if the class doesn't have a key function (possibly - // anymore), the vtable must be defined here. - const CXXMethodDecl *keyFunction = CGM.getContext().getCurrentKeyFunction(RD); - if (!keyFunction) - return false; - - // Otherwise, if we don't have a definition of the key function, the - // vtable must be defined somewhere else. - return !keyFunction->hasBody(); -} - -/// Given that we're currently at the end of the translation unit, and -/// we've emitted a reference to the vtable for this class, should -/// we define that vtable? -static bool shouldEmitVTableAtEndOfTranslationUnit(CodeGenModule &CGM, - const CXXRecordDecl *RD) { - // If vtable is internal then it has to be done. - if (!CGM.getVTables().isVTableExternal(RD)) - return true; - - // If it's external then maybe we will need it as available_externally. - return shouldEmitAvailableExternallyVTable(CGM, RD); -} - -/// Given that at some point we emitted a reference to one or more -/// vtables, and that we are now at the end of the translation unit, -/// decide whether we should emit them. -void CodeGenModule::EmitDeferredVTables() { -#ifndef NDEBUG - // Remember the size of DeferredVTables, because we're going to assume - // that this entire operation doesn't modify it. - size_t savedSize = DeferredVTables.size(); -#endif - - for (const CXXRecordDecl *RD : DeferredVTables) - if (shouldEmitVTableAtEndOfTranslationUnit(*this, RD)) - VTables.GenerateClassData(RD); - else if (shouldOpportunisticallyEmitVTables()) - OpportunisticVTables.push_back(RD); - - assert(savedSize == DeferredVTables.size() && - "deferred extra vtables during vtable emission?"); - DeferredVTables.clear(); -} - -bool CodeGenModule::HasHiddenLTOVisibility(const CXXRecordDecl *RD) { - LinkageInfo LV = RD->getLinkageAndVisibility(); - if (!isExternallyVisible(LV.getLinkage())) - return true; - - if (RD->hasAttr<LTOVisibilityPublicAttr>() || RD->hasAttr<UuidAttr>()) - return false; - - if (getTriple().isOSBinFormatCOFF()) { - if (RD->hasAttr<DLLExportAttr>() || RD->hasAttr<DLLImportAttr>()) - return false; - } else { - if (LV.getVisibility() != HiddenVisibility) - return false; - } - - if (getCodeGenOpts().LTOVisibilityPublicStd) { - const DeclContext *DC = RD; - while (1) { - auto *D = cast<Decl>(DC); - DC = DC->getParent(); - if (isa<TranslationUnitDecl>(DC->getRedeclContext())) { - if (auto *ND = dyn_cast<NamespaceDecl>(D)) - if (const IdentifierInfo *II = ND->getIdentifier()) - if (II->isStr("std") || II->isStr("stdext")) - return false; - break; - } - } - } - - return true; -} - -void CodeGenModule::EmitVTableTypeMetadata(llvm::GlobalVariable *VTable, - const VTableLayout &VTLayout) { - if (!getCodeGenOpts().LTOUnit) - return; - - CharUnits PointerWidth = - Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); - - typedef std::pair<const CXXRecordDecl *, unsigned> AddressPoint; - std::vector<AddressPoint> AddressPoints; - for (auto &&AP : VTLayout.getAddressPoints()) - AddressPoints.push_back(std::make_pair( - AP.first.getBase(), VTLayout.getVTableOffset(AP.second.VTableIndex) + - AP.second.AddressPointIndex)); - - // Sort the address points for determinism. - llvm::sort(AddressPoints, [this](const AddressPoint &AP1, - const AddressPoint &AP2) { - if (&AP1 == &AP2) - return false; - - std::string S1; - llvm::raw_string_ostream O1(S1); - getCXXABI().getMangleContext().mangleTypeName( - QualType(AP1.first->getTypeForDecl(), 0), O1); - O1.flush(); - - std::string S2; - llvm::raw_string_ostream O2(S2); - getCXXABI().getMangleContext().mangleTypeName( - QualType(AP2.first->getTypeForDecl(), 0), O2); - O2.flush(); - - if (S1 < S2) - return true; - if (S1 != S2) - return false; - - return AP1.second < AP2.second; - }); - - ArrayRef<VTableComponent> Comps = VTLayout.vtable_components(); - for (auto AP : AddressPoints) { - // Create type metadata for the address point. - AddVTableTypeMetadata(VTable, PointerWidth * AP.second, AP.first); - - // The class associated with each address point could also potentially be - // used for indirect calls via a member function pointer, so we need to - // annotate the address of each function pointer with the appropriate member - // function pointer type. - for (unsigned I = 0; I != Comps.size(); ++I) { - if (Comps[I].getKind() != VTableComponent::CK_FunctionPointer) - continue; - llvm::Metadata *MD = CreateMetadataIdentifierForVirtualMemPtrType( - Context.getMemberPointerType( - Comps[I].getFunctionDecl()->getType(), - Context.getRecordType(AP.first).getTypePtr())); - VTable->addTypeMetadata((PointerWidth * I).getQuantity(), MD); - } - } -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGVTables.h b/gnu/llvm/tools/clang/lib/CodeGen/CGVTables.h deleted file mode 100644 index 6377659e4cb..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGVTables.h +++ /dev/null @@ -1,132 +0,0 @@ -//===--- CGVTables.h - Emit LLVM Code for C++ vtables -----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This contains code dealing with C++ code generation of virtual tables. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CGVTABLES_H -#define LLVM_CLANG_LIB_CODEGEN_CGVTABLES_H - -#include "clang/AST/BaseSubobject.h" -#include "clang/AST/CharUnits.h" -#include "clang/AST/GlobalDecl.h" -#include "clang/AST/VTableBuilder.h" -#include "clang/Basic/ABI.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/IR/GlobalVariable.h" - -namespace clang { - class CXXRecordDecl; - -namespace CodeGen { - class CodeGenModule; - class ConstantArrayBuilder; - class ConstantStructBuilder; - -class CodeGenVTables { - CodeGenModule &CGM; - - VTableContextBase *VTContext; - - /// VTableAddressPointsMapTy - Address points for a single vtable. - typedef VTableLayout::AddressPointsMapTy VTableAddressPointsMapTy; - - typedef std::pair<const CXXRecordDecl *, BaseSubobject> BaseSubobjectPairTy; - typedef llvm::DenseMap<BaseSubobjectPairTy, uint64_t> SubVTTIndiciesMapTy; - - /// SubVTTIndicies - Contains indices into the various sub-VTTs. - SubVTTIndiciesMapTy SubVTTIndicies; - - typedef llvm::DenseMap<BaseSubobjectPairTy, uint64_t> - SecondaryVirtualPointerIndicesMapTy; - - /// SecondaryVirtualPointerIndices - Contains the secondary virtual pointer - /// indices. - SecondaryVirtualPointerIndicesMapTy SecondaryVirtualPointerIndices; - - /// Cache for the pure virtual member call function. - llvm::Constant *PureVirtualFn = nullptr; - - /// Cache for the deleted virtual member call function. - llvm::Constant *DeletedVirtualFn = nullptr; - - /// Get the address of a thunk and emit it if necessary. - llvm::Constant *maybeEmitThunk(GlobalDecl GD, - const ThunkInfo &ThunkAdjustments, - bool ForVTable); - - void addVTableComponent(ConstantArrayBuilder &builder, - const VTableLayout &layout, unsigned idx, - llvm::Constant *rtti, - unsigned &nextVTableThunkIndex); - -public: - /// Add vtable components for the given vtable layout to the given - /// global initializer. - void createVTableInitializer(ConstantStructBuilder &builder, - const VTableLayout &layout, - llvm::Constant *rtti); - - CodeGenVTables(CodeGenModule &CGM); - - ItaniumVTableContext &getItaniumVTableContext() { - return *cast<ItaniumVTableContext>(VTContext); - } - - MicrosoftVTableContext &getMicrosoftVTableContext() { - return *cast<MicrosoftVTableContext>(VTContext); - } - - /// getSubVTTIndex - Return the index of the sub-VTT for the base class of the - /// given record decl. - uint64_t getSubVTTIndex(const CXXRecordDecl *RD, BaseSubobject Base); - - /// getSecondaryVirtualPointerIndex - Return the index in the VTT where the - /// virtual pointer for the given subobject is located. - uint64_t getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD, - BaseSubobject Base); - - /// GenerateConstructionVTable - Generate a construction vtable for the given - /// base subobject. - llvm::GlobalVariable * - GenerateConstructionVTable(const CXXRecordDecl *RD, const BaseSubobject &Base, - bool BaseIsVirtual, - llvm::GlobalVariable::LinkageTypes Linkage, - VTableAddressPointsMapTy& AddressPoints); - - - /// GetAddrOfVTT - Get the address of the VTT for the given record decl. - llvm::GlobalVariable *GetAddrOfVTT(const CXXRecordDecl *RD); - - /// EmitVTTDefinition - Emit the definition of the given vtable. - void EmitVTTDefinition(llvm::GlobalVariable *VTT, - llvm::GlobalVariable::LinkageTypes Linkage, - const CXXRecordDecl *RD); - - /// EmitThunks - Emit the associated thunks for the given global decl. - void EmitThunks(GlobalDecl GD); - - /// GenerateClassData - Generate all the class data required to be - /// generated upon definition of a KeyFunction. This includes the - /// vtable, the RTTI data structure (if RTTI is enabled) and the VTT - /// (if the class has virtual bases). - void GenerateClassData(const CXXRecordDecl *RD); - - bool isVTableExternal(const CXXRecordDecl *RD); - - /// Returns the type of a vtable with the given layout. Normally a struct of - /// arrays of pointers, with one struct element for each vtable in the vtable - /// group. - llvm::Type *getVTableType(const VTableLayout &layout); -}; - -} // end namespace CodeGen -} // end namespace clang -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGValue.h b/gnu/llvm/tools/clang/lib/CodeGen/CGValue.h deleted file mode 100644 index da8a8efb840..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGValue.h +++ /dev/null @@ -1,632 +0,0 @@ -//===-- CGValue.h - LLVM CodeGen wrappers for llvm::Value* ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// These classes implement wrappers around llvm::Value in order to -// fully represent the range of values for C L- and R- values. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CGVALUE_H -#define LLVM_CLANG_LIB_CODEGEN_CGVALUE_H - -#include "clang/AST/ASTContext.h" -#include "clang/AST/Type.h" -#include "llvm/IR/Value.h" -#include "llvm/IR/Type.h" -#include "Address.h" -#include "CodeGenTBAA.h" - -namespace llvm { - class Constant; - class MDNode; -} - -namespace clang { -namespace CodeGen { - class AggValueSlot; - struct CGBitFieldInfo; - -/// RValue - This trivial value class is used to represent the result of an -/// expression that is evaluated. It can be one of three things: either a -/// simple LLVM SSA value, a pair of SSA values for complex numbers, or the -/// address of an aggregate value in memory. -class RValue { - enum Flavor { Scalar, Complex, Aggregate }; - - // The shift to make to an aggregate's alignment to make it look - // like a pointer. - enum { AggAlignShift = 4 }; - - // Stores first value and flavor. - llvm::PointerIntPair<llvm::Value *, 2, Flavor> V1; - // Stores second value and volatility. - llvm::PointerIntPair<llvm::Value *, 1, bool> V2; - -public: - bool isScalar() const { return V1.getInt() == Scalar; } - bool isComplex() const { return V1.getInt() == Complex; } - bool isAggregate() const { return V1.getInt() == Aggregate; } - - bool isVolatileQualified() const { return V2.getInt(); } - - /// getScalarVal() - Return the Value* of this scalar value. - llvm::Value *getScalarVal() const { - assert(isScalar() && "Not a scalar!"); - return V1.getPointer(); - } - - /// getComplexVal - Return the real/imag components of this complex value. - /// - std::pair<llvm::Value *, llvm::Value *> getComplexVal() const { - return std::make_pair(V1.getPointer(), V2.getPointer()); - } - - /// getAggregateAddr() - Return the Value* of the address of the aggregate. - Address getAggregateAddress() const { - assert(isAggregate() && "Not an aggregate!"); - auto align = reinterpret_cast<uintptr_t>(V2.getPointer()) >> AggAlignShift; - return Address(V1.getPointer(), CharUnits::fromQuantity(align)); - } - llvm::Value *getAggregatePointer() const { - assert(isAggregate() && "Not an aggregate!"); - return V1.getPointer(); - } - - static RValue getIgnored() { - // FIXME: should we make this a more explicit state? - return get(nullptr); - } - - static RValue get(llvm::Value *V) { - RValue ER; - ER.V1.setPointer(V); - ER.V1.setInt(Scalar); - ER.V2.setInt(false); - return ER; - } - static RValue getComplex(llvm::Value *V1, llvm::Value *V2) { - RValue ER; - ER.V1.setPointer(V1); - ER.V2.setPointer(V2); - ER.V1.setInt(Complex); - ER.V2.setInt(false); - return ER; - } - static RValue getComplex(const std::pair<llvm::Value *, llvm::Value *> &C) { - return getComplex(C.first, C.second); - } - // FIXME: Aggregate rvalues need to retain information about whether they are - // volatile or not. Remove default to find all places that probably get this - // wrong. - static RValue getAggregate(Address addr, bool isVolatile = false) { - RValue ER; - ER.V1.setPointer(addr.getPointer()); - ER.V1.setInt(Aggregate); - - auto align = static_cast<uintptr_t>(addr.getAlignment().getQuantity()); - ER.V2.setPointer(reinterpret_cast<llvm::Value*>(align << AggAlignShift)); - ER.V2.setInt(isVolatile); - return ER; - } -}; - -/// Does an ARC strong l-value have precise lifetime? -enum ARCPreciseLifetime_t { - ARCImpreciseLifetime, ARCPreciseLifetime -}; - -/// The source of the alignment of an l-value; an expression of -/// confidence in the alignment actually matching the estimate. -enum class AlignmentSource { - /// The l-value was an access to a declared entity or something - /// equivalently strong, like the address of an array allocated by a - /// language runtime. - Decl, - - /// The l-value was considered opaque, so the alignment was - /// determined from a type, but that type was an explicitly-aligned - /// typedef. - AttributedType, - - /// The l-value was considered opaque, so the alignment was - /// determined from a type. - Type -}; - -/// Given that the base address has the given alignment source, what's -/// our confidence in the alignment of the field? -static inline AlignmentSource getFieldAlignmentSource(AlignmentSource Source) { - // For now, we don't distinguish fields of opaque pointers from - // top-level declarations, but maybe we should. - return AlignmentSource::Decl; -} - -class LValueBaseInfo { - AlignmentSource AlignSource; - -public: - explicit LValueBaseInfo(AlignmentSource Source = AlignmentSource::Type) - : AlignSource(Source) {} - AlignmentSource getAlignmentSource() const { return AlignSource; } - void setAlignmentSource(AlignmentSource Source) { AlignSource = Source; } - - void mergeForCast(const LValueBaseInfo &Info) { - setAlignmentSource(Info.getAlignmentSource()); - } -}; - -/// LValue - This represents an lvalue references. Because C/C++ allow -/// bitfields, this is not a simple LLVM pointer, it may be a pointer plus a -/// bitrange. -class LValue { - enum { - Simple, // This is a normal l-value, use getAddress(). - VectorElt, // This is a vector element l-value (V[i]), use getVector* - BitField, // This is a bitfield l-value, use getBitfield*. - ExtVectorElt, // This is an extended vector subset, use getExtVectorComp - GlobalReg // This is a register l-value, use getGlobalReg() - } LVType; - - llvm::Value *V; - - union { - // Index into a vector subscript: V[i] - llvm::Value *VectorIdx; - - // ExtVector element subset: V.xyx - llvm::Constant *VectorElts; - - // BitField start bit and size - const CGBitFieldInfo *BitFieldInfo; - }; - - QualType Type; - - // 'const' is unused here - Qualifiers Quals; - - // The alignment to use when accessing this lvalue. (For vector elements, - // this is the alignment of the whole vector.) - unsigned Alignment; - - // objective-c's ivar - bool Ivar:1; - - // objective-c's ivar is an array - bool ObjIsArray:1; - - // LValue is non-gc'able for any reason, including being a parameter or local - // variable. - bool NonGC: 1; - - // Lvalue is a global reference of an objective-c object - bool GlobalObjCRef : 1; - - // Lvalue is a thread local reference - bool ThreadLocalRef : 1; - - // Lvalue has ARC imprecise lifetime. We store this inverted to try - // to make the default bitfield pattern all-zeroes. - bool ImpreciseLifetime : 1; - - // This flag shows if a nontemporal load/stores should be used when accessing - // this lvalue. - bool Nontemporal : 1; - - LValueBaseInfo BaseInfo; - TBAAAccessInfo TBAAInfo; - - Expr *BaseIvarExp; - -private: - void Initialize(QualType Type, Qualifiers Quals, CharUnits Alignment, - LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { - assert((!Alignment.isZero() || Type->isIncompleteType()) && - "initializing l-value with zero alignment!"); - this->Type = Type; - this->Quals = Quals; - const unsigned MaxAlign = 1U << 31; - this->Alignment = Alignment.getQuantity() <= MaxAlign - ? Alignment.getQuantity() - : MaxAlign; - assert(this->Alignment == Alignment.getQuantity() && - "Alignment exceeds allowed max!"); - this->BaseInfo = BaseInfo; - this->TBAAInfo = TBAAInfo; - - // Initialize Objective-C flags. - this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false; - this->ImpreciseLifetime = false; - this->Nontemporal = false; - this->ThreadLocalRef = false; - this->BaseIvarExp = nullptr; - } - -public: - bool isSimple() const { return LVType == Simple; } - bool isVectorElt() const { return LVType == VectorElt; } - bool isBitField() const { return LVType == BitField; } - bool isExtVectorElt() const { return LVType == ExtVectorElt; } - bool isGlobalReg() const { return LVType == GlobalReg; } - - bool isVolatileQualified() const { return Quals.hasVolatile(); } - bool isRestrictQualified() const { return Quals.hasRestrict(); } - unsigned getVRQualifiers() const { - return Quals.getCVRQualifiers() & ~Qualifiers::Const; - } - - QualType getType() const { return Type; } - - Qualifiers::ObjCLifetime getObjCLifetime() const { - return Quals.getObjCLifetime(); - } - - bool isObjCIvar() const { return Ivar; } - void setObjCIvar(bool Value) { Ivar = Value; } - - bool isObjCArray() const { return ObjIsArray; } - void setObjCArray(bool Value) { ObjIsArray = Value; } - - bool isNonGC () const { return NonGC; } - void setNonGC(bool Value) { NonGC = Value; } - - bool isGlobalObjCRef() const { return GlobalObjCRef; } - void setGlobalObjCRef(bool Value) { GlobalObjCRef = Value; } - - bool isThreadLocalRef() const { return ThreadLocalRef; } - void setThreadLocalRef(bool Value) { ThreadLocalRef = Value;} - - ARCPreciseLifetime_t isARCPreciseLifetime() const { - return ARCPreciseLifetime_t(!ImpreciseLifetime); - } - void setARCPreciseLifetime(ARCPreciseLifetime_t value) { - ImpreciseLifetime = (value == ARCImpreciseLifetime); - } - bool isNontemporal() const { return Nontemporal; } - void setNontemporal(bool Value) { Nontemporal = Value; } - - bool isObjCWeak() const { - return Quals.getObjCGCAttr() == Qualifiers::Weak; - } - bool isObjCStrong() const { - return Quals.getObjCGCAttr() == Qualifiers::Strong; - } - - bool isVolatile() const { - return Quals.hasVolatile(); - } - - Expr *getBaseIvarExp() const { return BaseIvarExp; } - void setBaseIvarExp(Expr *V) { BaseIvarExp = V; } - - TBAAAccessInfo getTBAAInfo() const { return TBAAInfo; } - void setTBAAInfo(TBAAAccessInfo Info) { TBAAInfo = Info; } - - const Qualifiers &getQuals() const { return Quals; } - Qualifiers &getQuals() { return Quals; } - - LangAS getAddressSpace() const { return Quals.getAddressSpace(); } - - CharUnits getAlignment() const { return CharUnits::fromQuantity(Alignment); } - void setAlignment(CharUnits A) { Alignment = A.getQuantity(); } - - LValueBaseInfo getBaseInfo() const { return BaseInfo; } - void setBaseInfo(LValueBaseInfo Info) { BaseInfo = Info; } - - // simple lvalue - llvm::Value *getPointer() const { - assert(isSimple()); - return V; - } - Address getAddress() const { return Address(getPointer(), getAlignment()); } - void setAddress(Address address) { - assert(isSimple()); - V = address.getPointer(); - Alignment = address.getAlignment().getQuantity(); - } - - // vector elt lvalue - Address getVectorAddress() const { - return Address(getVectorPointer(), getAlignment()); - } - llvm::Value *getVectorPointer() const { assert(isVectorElt()); return V; } - llvm::Value *getVectorIdx() const { assert(isVectorElt()); return VectorIdx; } - - // extended vector elements. - Address getExtVectorAddress() const { - return Address(getExtVectorPointer(), getAlignment()); - } - llvm::Value *getExtVectorPointer() const { - assert(isExtVectorElt()); - return V; - } - llvm::Constant *getExtVectorElts() const { - assert(isExtVectorElt()); - return VectorElts; - } - - // bitfield lvalue - Address getBitFieldAddress() const { - return Address(getBitFieldPointer(), getAlignment()); - } - llvm::Value *getBitFieldPointer() const { assert(isBitField()); return V; } - const CGBitFieldInfo &getBitFieldInfo() const { - assert(isBitField()); - return *BitFieldInfo; - } - - // global register lvalue - llvm::Value *getGlobalReg() const { assert(isGlobalReg()); return V; } - - static LValue MakeAddr(Address address, QualType type, ASTContext &Context, - LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { - Qualifiers qs = type.getQualifiers(); - qs.setObjCGCAttr(Context.getObjCGCAttrKind(type)); - - LValue R; - R.LVType = Simple; - assert(address.getPointer()->getType()->isPointerTy()); - R.V = address.getPointer(); - R.Initialize(type, qs, address.getAlignment(), BaseInfo, TBAAInfo); - return R; - } - - static LValue MakeVectorElt(Address vecAddress, llvm::Value *Idx, - QualType type, LValueBaseInfo BaseInfo, - TBAAAccessInfo TBAAInfo) { - LValue R; - R.LVType = VectorElt; - R.V = vecAddress.getPointer(); - R.VectorIdx = Idx; - R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(), - BaseInfo, TBAAInfo); - return R; - } - - static LValue MakeExtVectorElt(Address vecAddress, llvm::Constant *Elts, - QualType type, LValueBaseInfo BaseInfo, - TBAAAccessInfo TBAAInfo) { - LValue R; - R.LVType = ExtVectorElt; - R.V = vecAddress.getPointer(); - R.VectorElts = Elts; - R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(), - BaseInfo, TBAAInfo); - return R; - } - - /// Create a new object to represent a bit-field access. - /// - /// \param Addr - The base address of the bit-field sequence this - /// bit-field refers to. - /// \param Info - The information describing how to perform the bit-field - /// access. - static LValue MakeBitfield(Address Addr, const CGBitFieldInfo &Info, - QualType type, LValueBaseInfo BaseInfo, - TBAAAccessInfo TBAAInfo) { - LValue R; - R.LVType = BitField; - R.V = Addr.getPointer(); - R.BitFieldInfo = &Info; - R.Initialize(type, type.getQualifiers(), Addr.getAlignment(), BaseInfo, - TBAAInfo); - return R; - } - - static LValue MakeGlobalReg(Address Reg, QualType type) { - LValue R; - R.LVType = GlobalReg; - R.V = Reg.getPointer(); - R.Initialize(type, type.getQualifiers(), Reg.getAlignment(), - LValueBaseInfo(AlignmentSource::Decl), TBAAAccessInfo()); - return R; - } - - RValue asAggregateRValue() const { - return RValue::getAggregate(getAddress(), isVolatileQualified()); - } -}; - -/// An aggregate value slot. -class AggValueSlot { - /// The address. - llvm::Value *Addr; - - // Qualifiers - Qualifiers Quals; - - unsigned Alignment; - - /// DestructedFlag - This is set to true if some external code is - /// responsible for setting up a destructor for the slot. Otherwise - /// the code which constructs it should push the appropriate cleanup. - bool DestructedFlag : 1; - - /// ObjCGCFlag - This is set to true if writing to the memory in the - /// slot might require calling an appropriate Objective-C GC - /// barrier. The exact interaction here is unnecessarily mysterious. - bool ObjCGCFlag : 1; - - /// ZeroedFlag - This is set to true if the memory in the slot is - /// known to be zero before the assignment into it. This means that - /// zero fields don't need to be set. - bool ZeroedFlag : 1; - - /// AliasedFlag - This is set to true if the slot might be aliased - /// and it's not undefined behavior to access it through such an - /// alias. Note that it's always undefined behavior to access a C++ - /// object that's under construction through an alias derived from - /// outside the construction process. - /// - /// This flag controls whether calls that produce the aggregate - /// value may be evaluated directly into the slot, or whether they - /// must be evaluated into an unaliased temporary and then memcpy'ed - /// over. Since it's invalid in general to memcpy a non-POD C++ - /// object, it's important that this flag never be set when - /// evaluating an expression which constructs such an object. - bool AliasedFlag : 1; - - /// This is set to true if the tail padding of this slot might overlap - /// another object that may have already been initialized (and whose - /// value must be preserved by this initialization). If so, we may only - /// store up to the dsize of the type. Otherwise we can widen stores to - /// the size of the type. - bool OverlapFlag : 1; - - /// If is set to true, sanitizer checks are already generated for this address - /// or not required. For instance, if this address represents an object - /// created in 'new' expression, sanitizer checks for memory is made as a part - /// of 'operator new' emission and object constructor should not generate - /// them. - bool SanitizerCheckedFlag : 1; - -public: - enum IsAliased_t { IsNotAliased, IsAliased }; - enum IsDestructed_t { IsNotDestructed, IsDestructed }; - enum IsZeroed_t { IsNotZeroed, IsZeroed }; - enum Overlap_t { DoesNotOverlap, MayOverlap }; - enum NeedsGCBarriers_t { DoesNotNeedGCBarriers, NeedsGCBarriers }; - enum IsSanitizerChecked_t { IsNotSanitizerChecked, IsSanitizerChecked }; - - /// ignored - Returns an aggregate value slot indicating that the - /// aggregate value is being ignored. - static AggValueSlot ignored() { - return forAddr(Address::invalid(), Qualifiers(), IsNotDestructed, - DoesNotNeedGCBarriers, IsNotAliased, DoesNotOverlap); - } - - /// forAddr - Make a slot for an aggregate value. - /// - /// \param quals - The qualifiers that dictate how the slot should - /// be initialied. Only 'volatile' and the Objective-C lifetime - /// qualifiers matter. - /// - /// \param isDestructed - true if something else is responsible - /// for calling destructors on this object - /// \param needsGC - true if the slot is potentially located - /// somewhere that ObjC GC calls should be emitted for - static AggValueSlot forAddr(Address addr, - Qualifiers quals, - IsDestructed_t isDestructed, - NeedsGCBarriers_t needsGC, - IsAliased_t isAliased, - Overlap_t mayOverlap, - IsZeroed_t isZeroed = IsNotZeroed, - IsSanitizerChecked_t isChecked = IsNotSanitizerChecked) { - AggValueSlot AV; - if (addr.isValid()) { - AV.Addr = addr.getPointer(); - AV.Alignment = addr.getAlignment().getQuantity(); - } else { - AV.Addr = nullptr; - AV.Alignment = 0; - } - AV.Quals = quals; - AV.DestructedFlag = isDestructed; - AV.ObjCGCFlag = needsGC; - AV.ZeroedFlag = isZeroed; - AV.AliasedFlag = isAliased; - AV.OverlapFlag = mayOverlap; - AV.SanitizerCheckedFlag = isChecked; - return AV; - } - - static AggValueSlot forLValue(const LValue &LV, - IsDestructed_t isDestructed, - NeedsGCBarriers_t needsGC, - IsAliased_t isAliased, - Overlap_t mayOverlap, - IsZeroed_t isZeroed = IsNotZeroed, - IsSanitizerChecked_t isChecked = IsNotSanitizerChecked) { - return forAddr(LV.getAddress(), LV.getQuals(), isDestructed, needsGC, - isAliased, mayOverlap, isZeroed, isChecked); - } - - IsDestructed_t isExternallyDestructed() const { - return IsDestructed_t(DestructedFlag); - } - void setExternallyDestructed(bool destructed = true) { - DestructedFlag = destructed; - } - - Qualifiers getQualifiers() const { return Quals; } - - bool isVolatile() const { - return Quals.hasVolatile(); - } - - void setVolatile(bool flag) { - if (flag) - Quals.addVolatile(); - else - Quals.removeVolatile(); - } - - Qualifiers::ObjCLifetime getObjCLifetime() const { - return Quals.getObjCLifetime(); - } - - NeedsGCBarriers_t requiresGCollection() const { - return NeedsGCBarriers_t(ObjCGCFlag); - } - - llvm::Value *getPointer() const { - return Addr; - } - - Address getAddress() const { - return Address(Addr, getAlignment()); - } - - bool isIgnored() const { - return Addr == nullptr; - } - - CharUnits getAlignment() const { - return CharUnits::fromQuantity(Alignment); - } - - IsAliased_t isPotentiallyAliased() const { - return IsAliased_t(AliasedFlag); - } - - Overlap_t mayOverlap() const { - return Overlap_t(OverlapFlag); - } - - bool isSanitizerChecked() const { - return SanitizerCheckedFlag; - } - - RValue asRValue() const { - if (isIgnored()) { - return RValue::getIgnored(); - } else { - return RValue::getAggregate(getAddress(), isVolatile()); - } - } - - void setZeroed(bool V = true) { ZeroedFlag = V; } - IsZeroed_t isZeroed() const { - return IsZeroed_t(ZeroedFlag); - } - - /// Get the preferred size to use when storing a value to this slot. This - /// is the type size unless that might overlap another object, in which - /// case it's the dsize. - CharUnits getPreferredSize(ASTContext &Ctx, QualType Type) const { - return mayOverlap() ? Ctx.getTypeInfoDataSizeInChars(Type).first - : Ctx.getTypeSizeInChars(Type); - } -}; - -} // end namespace CodeGen -} // end namespace clang - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CMakeLists.txt b/gnu/llvm/tools/clang/lib/CodeGen/CMakeLists.txt deleted file mode 100644 index 29c6793c601..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CMakeLists.txt +++ /dev/null @@ -1,106 +0,0 @@ -set(LLVM_LINK_COMPONENTS - Analysis - BitReader - BitWriter - Core - Coroutines - Coverage - IPO - IRReader - AggressiveInstCombine - InstCombine - Instrumentation - LTO - Linker - MC - ObjCARCOpts - Object - Passes - ProfileData - ScalarOpts - Support - Target - TransformUtils - ) - -# In a standard Clang+LLVM build, we need to generate intrinsics before -# building codegen. In a standalone build, LLVM is already built and we don't -# need this dependency. Furthermore, LLVM doesn't export it so we can't have -# this dependency. -set(codegen_deps intrinsics_gen) -if (CLANG_BUILT_STANDALONE) - set(codegen_deps) -endif() - -if (MSVC) - set_source_files_properties(CodeGenModule.cpp PROPERTIES COMPILE_FLAGS /bigobj) -endif() - -add_clang_library(clangCodeGen - BackendUtil.cpp - CGAtomic.cpp - CGBlocks.cpp - CGBuiltin.cpp - CGCUDANV.cpp - CGCUDARuntime.cpp - CGCXX.cpp - CGCXXABI.cpp - CGCall.cpp - CGClass.cpp - CGCleanup.cpp - CGCoroutine.cpp - CGDebugInfo.cpp - CGDecl.cpp - CGDeclCXX.cpp - CGException.cpp - CGExpr.cpp - CGExprAgg.cpp - CGExprCXX.cpp - CGExprComplex.cpp - CGExprConstant.cpp - CGExprScalar.cpp - CGGPUBuiltin.cpp - CGLoopInfo.cpp - CGNonTrivialStruct.cpp - CGObjC.cpp - CGObjCGNU.cpp - CGObjCMac.cpp - CGObjCRuntime.cpp - CGOpenCLRuntime.cpp - CGOpenMPRuntime.cpp - CGOpenMPRuntimeNVPTX.cpp - CGRecordLayoutBuilder.cpp - CGStmt.cpp - CGStmtOpenMP.cpp - CGVTT.cpp - CGVTables.cpp - CodeGenABITypes.cpp - CodeGenAction.cpp - CodeGenFunction.cpp - CodeGenModule.cpp - CodeGenPGO.cpp - CodeGenTBAA.cpp - CodeGenTypes.cpp - ConstantInitBuilder.cpp - CoverageMappingGen.cpp - ItaniumCXXABI.cpp - MacroPPCallbacks.cpp - MicrosoftCXXABI.cpp - ModuleBuilder.cpp - ObjectFilePCHContainerOperations.cpp - SanitizerMetadata.cpp - SwiftCallingConv.cpp - TargetInfo.cpp - VarBypassDetector.cpp - - DEPENDS - ${codegen_deps} - - LINK_LIBS - clangAnalysis - clangAST - clangBasic - clangFrontend - clangLex - clangSerialization - ) diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp deleted file mode 100644 index 27f5d53ffe1..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp +++ /dev/null @@ -1,88 +0,0 @@ -//==--- CodeGenABITypes.cpp - Convert Clang types to LLVM types for ABI ----==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// - -#include "clang/CodeGen/CodeGenABITypes.h" -#include "CGRecordLayout.h" -#include "CodeGenModule.h" -#include "clang/CodeGen/CGFunctionInfo.h" -#include "clang/Lex/HeaderSearchOptions.h" -#include "clang/Lex/PreprocessorOptions.h" - -using namespace clang; -using namespace CodeGen; - -const CGFunctionInfo & -CodeGen::arrangeObjCMessageSendSignature(CodeGenModule &CGM, - const ObjCMethodDecl *MD, - QualType receiverType) { - return CGM.getTypes().arrangeObjCMessageSendSignature(MD, receiverType); -} - -const CGFunctionInfo & -CodeGen::arrangeFreeFunctionType(CodeGenModule &CGM, - CanQual<FunctionProtoType> Ty, - const FunctionDecl *FD) { - return CGM.getTypes().arrangeFreeFunctionType(Ty, FD); -} - -const CGFunctionInfo & -CodeGen::arrangeFreeFunctionType(CodeGenModule &CGM, - CanQual<FunctionNoProtoType> Ty) { - return CGM.getTypes().arrangeFreeFunctionType(Ty); -} - -const CGFunctionInfo & -CodeGen::arrangeCXXMethodType(CodeGenModule &CGM, - const CXXRecordDecl *RD, - const FunctionProtoType *FTP, - const CXXMethodDecl *MD) { - return CGM.getTypes().arrangeCXXMethodType(RD, FTP, MD); -} - -const CGFunctionInfo & -CodeGen::arrangeFreeFunctionCall(CodeGenModule &CGM, - CanQualType returnType, - ArrayRef<CanQualType> argTypes, - FunctionType::ExtInfo info, - RequiredArgs args) { - return CGM.getTypes().arrangeLLVMFunctionInfo( - returnType, /*IsInstanceMethod=*/false, /*IsChainCall=*/false, argTypes, - info, {}, args); -} - -llvm::FunctionType * -CodeGen::convertFreeFunctionType(CodeGenModule &CGM, const FunctionDecl *FD) { - assert(FD != nullptr && "Expected a non-null function declaration!"); - llvm::Type *T = CGM.getTypes().ConvertFunctionType(FD->getType(), FD); - - if (auto FT = dyn_cast<llvm::FunctionType>(T)) - return FT; - - return nullptr; -} - -llvm::Type * -CodeGen::convertTypeForMemory(CodeGenModule &CGM, QualType T) { - return CGM.getTypes().ConvertTypeForMem(T); -} - -unsigned CodeGen::getLLVMFieldNumber(CodeGenModule &CGM, - const RecordDecl *RD, - const FieldDecl *FD) { - return CGM.getTypes().getCGRecordLayout(RD).getLLVMFieldNo(FD); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp deleted file mode 100644 index fd4506f2d19..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp +++ /dev/null @@ -1,1075 +0,0 @@ -//===--- CodeGenAction.cpp - LLVM Code Generation Frontend Action ---------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "clang/CodeGen/CodeGenAction.h" -#include "CodeGenModule.h" -#include "CoverageMappingGen.h" -#include "MacroPPCallbacks.h" -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclGroup.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/CodeGen/BackendUtil.h" -#include "clang/CodeGen/ModuleBuilder.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/FrontendDiagnostic.h" -#include "clang/Lex/Preprocessor.h" -#include "llvm/Bitcode/BitcodeReader.h" -#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/DiagnosticInfo.h" -#include "llvm/IR/DiagnosticPrinter.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/IRReader/IRReader.h" -#include "llvm/Linker/Linker.h" -#include "llvm/Pass.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/Timer.h" -#include "llvm/Support/ToolOutputFile.h" -#include "llvm/Support/YAMLTraits.h" -#include "llvm/Transforms/IPO/Internalize.h" - -#include <memory> -using namespace clang; -using namespace llvm; - -namespace clang { - class BackendConsumer; - class ClangDiagnosticHandler final : public DiagnosticHandler { - public: - ClangDiagnosticHandler(const CodeGenOptions &CGOpts, BackendConsumer *BCon) - : CodeGenOpts(CGOpts), BackendCon(BCon) {} - - bool handleDiagnostics(const DiagnosticInfo &DI) override; - - bool isAnalysisRemarkEnabled(StringRef PassName) const override { - return (CodeGenOpts.OptimizationRemarkAnalysisPattern && - CodeGenOpts.OptimizationRemarkAnalysisPattern->match(PassName)); - } - bool isMissedOptRemarkEnabled(StringRef PassName) const override { - return (CodeGenOpts.OptimizationRemarkMissedPattern && - CodeGenOpts.OptimizationRemarkMissedPattern->match(PassName)); - } - bool isPassedOptRemarkEnabled(StringRef PassName) const override { - return (CodeGenOpts.OptimizationRemarkPattern && - CodeGenOpts.OptimizationRemarkPattern->match(PassName)); - } - - bool isAnyRemarkEnabled() const override { - return (CodeGenOpts.OptimizationRemarkAnalysisPattern || - CodeGenOpts.OptimizationRemarkMissedPattern || - CodeGenOpts.OptimizationRemarkPattern); - } - - private: - const CodeGenOptions &CodeGenOpts; - BackendConsumer *BackendCon; - }; - - class BackendConsumer : public ASTConsumer { - using LinkModule = CodeGenAction::LinkModule; - - virtual void anchor(); - DiagnosticsEngine &Diags; - BackendAction Action; - const HeaderSearchOptions &HeaderSearchOpts; - const CodeGenOptions &CodeGenOpts; - const TargetOptions &TargetOpts; - const LangOptions &LangOpts; - std::unique_ptr<raw_pwrite_stream> AsmOutStream; - ASTContext *Context; - - Timer LLVMIRGeneration; - unsigned LLVMIRGenerationRefCount; - - /// True if we've finished generating IR. This prevents us from generating - /// additional LLVM IR after emitting output in HandleTranslationUnit. This - /// can happen when Clang plugins trigger additional AST deserialization. - bool IRGenFinished = false; - - std::unique_ptr<CodeGenerator> Gen; - - SmallVector<LinkModule, 4> LinkModules; - - // This is here so that the diagnostic printer knows the module a diagnostic - // refers to. - llvm::Module *CurLinkModule = nullptr; - - public: - BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, - const HeaderSearchOptions &HeaderSearchOpts, - const PreprocessorOptions &PPOpts, - const CodeGenOptions &CodeGenOpts, - const TargetOptions &TargetOpts, - const LangOptions &LangOpts, bool TimePasses, - const std::string &InFile, - SmallVector<LinkModule, 4> LinkModules, - std::unique_ptr<raw_pwrite_stream> OS, LLVMContext &C, - CoverageSourceInfo *CoverageInfo = nullptr) - : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts), - CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts), - AsmOutStream(std::move(OS)), Context(nullptr), - LLVMIRGeneration("irgen", "LLVM IR Generation Time"), - LLVMIRGenerationRefCount(0), - Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts, - CodeGenOpts, C, CoverageInfo)), - LinkModules(std::move(LinkModules)) { - FrontendTimesIsEnabled = TimePasses; - llvm::TimePassesIsEnabled = TimePasses; - } - llvm::Module *getModule() const { return Gen->GetModule(); } - std::unique_ptr<llvm::Module> takeModule() { - return std::unique_ptr<llvm::Module>(Gen->ReleaseModule()); - } - - CodeGenerator *getCodeGenerator() { return Gen.get(); } - - void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override { - Gen->HandleCXXStaticMemberVarInstantiation(VD); - } - - void Initialize(ASTContext &Ctx) override { - assert(!Context && "initialized multiple times"); - - Context = &Ctx; - - if (FrontendTimesIsEnabled) - LLVMIRGeneration.startTimer(); - - Gen->Initialize(Ctx); - - if (FrontendTimesIsEnabled) - LLVMIRGeneration.stopTimer(); - } - - bool HandleTopLevelDecl(DeclGroupRef D) override { - PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(), - Context->getSourceManager(), - "LLVM IR generation of declaration"); - - // Recurse. - if (FrontendTimesIsEnabled) { - LLVMIRGenerationRefCount += 1; - if (LLVMIRGenerationRefCount == 1) - LLVMIRGeneration.startTimer(); - } - - Gen->HandleTopLevelDecl(D); - - if (FrontendTimesIsEnabled) { - LLVMIRGenerationRefCount -= 1; - if (LLVMIRGenerationRefCount == 0) - LLVMIRGeneration.stopTimer(); - } - - return true; - } - - void HandleInlineFunctionDefinition(FunctionDecl *D) override { - PrettyStackTraceDecl CrashInfo(D, SourceLocation(), - Context->getSourceManager(), - "LLVM IR generation of inline function"); - if (FrontendTimesIsEnabled) - LLVMIRGeneration.startTimer(); - - Gen->HandleInlineFunctionDefinition(D); - - if (FrontendTimesIsEnabled) - LLVMIRGeneration.stopTimer(); - } - - void HandleInterestingDecl(DeclGroupRef D) override { - // Ignore interesting decls from the AST reader after IRGen is finished. - if (!IRGenFinished) - HandleTopLevelDecl(D); - } - - // Links each entry in LinkModules into our module. Returns true on error. - bool LinkInModules() { - for (auto &LM : LinkModules) { - if (LM.PropagateAttrs) - for (Function &F : *LM.Module) - Gen->CGM().AddDefaultFnAttrs(F); - - CurLinkModule = LM.Module.get(); - - bool Err; - if (LM.Internalize) { - Err = Linker::linkModules( - *getModule(), std::move(LM.Module), LM.LinkFlags, - [](llvm::Module &M, const llvm::StringSet<> &GVS) { - internalizeModule(M, [&GVS](const llvm::GlobalValue &GV) { - return !GV.hasName() || (GVS.count(GV.getName()) == 0); - }); - }); - } else { - Err = Linker::linkModules(*getModule(), std::move(LM.Module), - LM.LinkFlags); - } - - if (Err) - return true; - } - return false; // success - } - - void HandleTranslationUnit(ASTContext &C) override { - { - PrettyStackTraceString CrashInfo("Per-file LLVM IR generation"); - if (FrontendTimesIsEnabled) { - LLVMIRGenerationRefCount += 1; - if (LLVMIRGenerationRefCount == 1) - LLVMIRGeneration.startTimer(); - } - - Gen->HandleTranslationUnit(C); - - if (FrontendTimesIsEnabled) { - LLVMIRGenerationRefCount -= 1; - if (LLVMIRGenerationRefCount == 0) - LLVMIRGeneration.stopTimer(); - } - - IRGenFinished = true; - } - - // Silently ignore if we weren't initialized for some reason. - if (!getModule()) - return; - - // Install an inline asm handler so that diagnostics get printed through - // our diagnostics hooks. - LLVMContext &Ctx = getModule()->getContext(); - LLVMContext::InlineAsmDiagHandlerTy OldHandler = - Ctx.getInlineAsmDiagnosticHandler(); - void *OldContext = Ctx.getInlineAsmDiagnosticContext(); - Ctx.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, this); - - std::unique_ptr<DiagnosticHandler> OldDiagnosticHandler = - Ctx.getDiagnosticHandler(); - Ctx.setDiagnosticHandler(llvm::make_unique<ClangDiagnosticHandler>( - CodeGenOpts, this)); - Ctx.setDiagnosticsHotnessRequested(CodeGenOpts.DiagnosticsWithHotness); - if (CodeGenOpts.DiagnosticsHotnessThreshold != 0) - Ctx.setDiagnosticsHotnessThreshold( - CodeGenOpts.DiagnosticsHotnessThreshold); - - std::unique_ptr<llvm::ToolOutputFile> OptRecordFile; - if (!CodeGenOpts.OptRecordFile.empty()) { - std::error_code EC; - OptRecordFile = llvm::make_unique<llvm::ToolOutputFile>( - CodeGenOpts.OptRecordFile, EC, sys::fs::F_None); - if (EC) { - Diags.Report(diag::err_cannot_open_file) << - CodeGenOpts.OptRecordFile << EC.message(); - return; - } - - Ctx.setDiagnosticsOutputFile( - llvm::make_unique<yaml::Output>(OptRecordFile->os())); - - if (CodeGenOpts.getProfileUse() != CodeGenOptions::ProfileNone) - Ctx.setDiagnosticsHotnessRequested(true); - } - - // Link each LinkModule into our module. - if (LinkInModules()) - return; - - EmbedBitcode(getModule(), CodeGenOpts, llvm::MemoryBufferRef()); - - EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, - LangOpts, C.getTargetInfo().getDataLayout(), - getModule(), Action, std::move(AsmOutStream)); - - Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext); - - Ctx.setDiagnosticHandler(std::move(OldDiagnosticHandler)); - - if (OptRecordFile) - OptRecordFile->keep(); - } - - void HandleTagDeclDefinition(TagDecl *D) override { - PrettyStackTraceDecl CrashInfo(D, SourceLocation(), - Context->getSourceManager(), - "LLVM IR generation of declaration"); - Gen->HandleTagDeclDefinition(D); - } - - void HandleTagDeclRequiredDefinition(const TagDecl *D) override { - Gen->HandleTagDeclRequiredDefinition(D); - } - - void CompleteTentativeDefinition(VarDecl *D) override { - Gen->CompleteTentativeDefinition(D); - } - - void AssignInheritanceModel(CXXRecordDecl *RD) override { - Gen->AssignInheritanceModel(RD); - } - - void HandleVTable(CXXRecordDecl *RD) override { - Gen->HandleVTable(RD); - } - - static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context, - unsigned LocCookie) { - SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie); - ((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc); - } - - /// Get the best possible source location to represent a diagnostic that - /// may have associated debug info. - const FullSourceLoc - getBestLocationFromDebugLoc(const llvm::DiagnosticInfoWithLocationBase &D, - bool &BadDebugInfo, StringRef &Filename, - unsigned &Line, unsigned &Column) const; - - void InlineAsmDiagHandler2(const llvm::SMDiagnostic &, - SourceLocation LocCookie); - - void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI); - /// Specialized handler for InlineAsm diagnostic. - /// \return True if the diagnostic has been successfully reported, false - /// otherwise. - bool InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D); - /// Specialized handler for StackSize diagnostic. - /// \return True if the diagnostic has been successfully reported, false - /// otherwise. - bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D); - /// Specialized handler for unsupported backend feature diagnostic. - void UnsupportedDiagHandler(const llvm::DiagnosticInfoUnsupported &D); - /// Specialized handlers for optimization remarks. - /// Note that these handlers only accept remarks and they always handle - /// them. - void EmitOptimizationMessage(const llvm::DiagnosticInfoOptimizationBase &D, - unsigned DiagID); - void - OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationBase &D); - void OptimizationRemarkHandler( - const llvm::OptimizationRemarkAnalysisFPCommute &D); - void OptimizationRemarkHandler( - const llvm::OptimizationRemarkAnalysisAliasing &D); - void OptimizationFailureHandler( - const llvm::DiagnosticInfoOptimizationFailure &D); - }; - - void BackendConsumer::anchor() {} -} - -bool ClangDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) { - BackendCon->DiagnosticHandlerImpl(DI); - return true; -} - -/// ConvertBackendLocation - Convert a location in a temporary llvm::SourceMgr -/// buffer to be a valid FullSourceLoc. -static FullSourceLoc ConvertBackendLocation(const llvm::SMDiagnostic &D, - SourceManager &CSM) { - // Get both the clang and llvm source managers. The location is relative to - // a memory buffer that the LLVM Source Manager is handling, we need to add - // a copy to the Clang source manager. - const llvm::SourceMgr &LSM = *D.getSourceMgr(); - - // We need to copy the underlying LLVM memory buffer because llvm::SourceMgr - // already owns its one and clang::SourceManager wants to own its one. - const MemoryBuffer *LBuf = - LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); - - // Create the copy and transfer ownership to clang::SourceManager. - // TODO: Avoid copying files into memory. - std::unique_ptr<llvm::MemoryBuffer> CBuf = - llvm::MemoryBuffer::getMemBufferCopy(LBuf->getBuffer(), - LBuf->getBufferIdentifier()); - // FIXME: Keep a file ID map instead of creating new IDs for each location. - FileID FID = CSM.createFileID(std::move(CBuf)); - - // Translate the offset into the file. - unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); - SourceLocation NewLoc = - CSM.getLocForStartOfFile(FID).getLocWithOffset(Offset); - return FullSourceLoc(NewLoc, CSM); -} - - -/// InlineAsmDiagHandler2 - This function is invoked when the backend hits an -/// error parsing inline asm. The SMDiagnostic indicates the error relative to -/// the temporary memory buffer that the inline asm parser has set up. -void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D, - SourceLocation LocCookie) { - // There are a couple of different kinds of errors we could get here. First, - // we re-format the SMDiagnostic in terms of a clang diagnostic. - - // Strip "error: " off the start of the message string. - StringRef Message = D.getMessage(); - if (Message.startswith("error: ")) - Message = Message.substr(7); - - // If the SMDiagnostic has an inline asm source location, translate it. - FullSourceLoc Loc; - if (D.getLoc() != SMLoc()) - Loc = ConvertBackendLocation(D, Context->getSourceManager()); - - unsigned DiagID; - switch (D.getKind()) { - case llvm::SourceMgr::DK_Error: - DiagID = diag::err_fe_inline_asm; - break; - case llvm::SourceMgr::DK_Warning: - DiagID = diag::warn_fe_inline_asm; - break; - case llvm::SourceMgr::DK_Note: - DiagID = diag::note_fe_inline_asm; - break; - case llvm::SourceMgr::DK_Remark: - llvm_unreachable("remarks unexpected"); - } - // If this problem has clang-level source location information, report the - // issue in the source with a note showing the instantiated - // code. - if (LocCookie.isValid()) { - Diags.Report(LocCookie, DiagID).AddString(Message); - - if (D.getLoc().isValid()) { - DiagnosticBuilder B = Diags.Report(Loc, diag::note_fe_inline_asm_here); - // Convert the SMDiagnostic ranges into SourceRange and attach them - // to the diagnostic. - for (const std::pair<unsigned, unsigned> &Range : D.getRanges()) { - unsigned Column = D.getColumnNo(); - B << SourceRange(Loc.getLocWithOffset(Range.first - Column), - Loc.getLocWithOffset(Range.second - Column)); - } - } - return; - } - - // Otherwise, report the backend issue as occurring in the generated .s file. - // If Loc is invalid, we still need to report the issue, it just gets no - // location info. - Diags.Report(Loc, DiagID).AddString(Message); -} - -#define ComputeDiagID(Severity, GroupName, DiagID) \ - do { \ - switch (Severity) { \ - case llvm::DS_Error: \ - DiagID = diag::err_fe_##GroupName; \ - break; \ - case llvm::DS_Warning: \ - DiagID = diag::warn_fe_##GroupName; \ - break; \ - case llvm::DS_Remark: \ - llvm_unreachable("'remark' severity not expected"); \ - break; \ - case llvm::DS_Note: \ - DiagID = diag::note_fe_##GroupName; \ - break; \ - } \ - } while (false) - -#define ComputeDiagRemarkID(Severity, GroupName, DiagID) \ - do { \ - switch (Severity) { \ - case llvm::DS_Error: \ - DiagID = diag::err_fe_##GroupName; \ - break; \ - case llvm::DS_Warning: \ - DiagID = diag::warn_fe_##GroupName; \ - break; \ - case llvm::DS_Remark: \ - DiagID = diag::remark_fe_##GroupName; \ - break; \ - case llvm::DS_Note: \ - DiagID = diag::note_fe_##GroupName; \ - break; \ - } \ - } while (false) - -bool -BackendConsumer::InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D) { - unsigned DiagID; - ComputeDiagID(D.getSeverity(), inline_asm, DiagID); - std::string Message = D.getMsgStr().str(); - - // If this problem has clang-level source location information, report the - // issue as being a problem in the source with a note showing the instantiated - // code. - SourceLocation LocCookie = - SourceLocation::getFromRawEncoding(D.getLocCookie()); - if (LocCookie.isValid()) - Diags.Report(LocCookie, DiagID).AddString(Message); - else { - // Otherwise, report the backend diagnostic as occurring in the generated - // .s file. - // If Loc is invalid, we still need to report the diagnostic, it just gets - // no location info. - FullSourceLoc Loc; - Diags.Report(Loc, DiagID).AddString(Message); - } - // We handled all the possible severities. - return true; -} - -bool -BackendConsumer::StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D) { - if (D.getSeverity() != llvm::DS_Warning) - // For now, the only support we have for StackSize diagnostic is warning. - // We do not know how to format other severities. - return false; - - if (const Decl *ND = Gen->GetDeclForMangledName(D.getFunction().getName())) { - // FIXME: Shouldn't need to truncate to uint32_t - Diags.Report(ND->getASTContext().getFullLoc(ND->getLocation()), - diag::warn_fe_frame_larger_than) - << static_cast<uint32_t>(D.getStackSize()) << Decl::castToDeclContext(ND); - return true; - } - - return false; -} - -const FullSourceLoc BackendConsumer::getBestLocationFromDebugLoc( - const llvm::DiagnosticInfoWithLocationBase &D, bool &BadDebugInfo, - StringRef &Filename, unsigned &Line, unsigned &Column) const { - SourceManager &SourceMgr = Context->getSourceManager(); - FileManager &FileMgr = SourceMgr.getFileManager(); - SourceLocation DILoc; - - if (D.isLocationAvailable()) { - D.getLocation(Filename, Line, Column); - if (Line > 0) { - const FileEntry *FE = FileMgr.getFile(Filename); - if (!FE) - FE = FileMgr.getFile(D.getAbsolutePath()); - if (FE) { - // If -gcolumn-info was not used, Column will be 0. This upsets the - // source manager, so pass 1 if Column is not set. - DILoc = SourceMgr.translateFileLineCol(FE, Line, Column ? Column : 1); - } - } - BadDebugInfo = DILoc.isInvalid(); - } - - // If a location isn't available, try to approximate it using the associated - // function definition. We use the definition's right brace to differentiate - // from diagnostics that genuinely relate to the function itself. - FullSourceLoc Loc(DILoc, SourceMgr); - if (Loc.isInvalid()) - if (const Decl *FD = Gen->GetDeclForMangledName(D.getFunction().getName())) - Loc = FD->getASTContext().getFullLoc(FD->getLocation()); - - if (DILoc.isInvalid() && D.isLocationAvailable()) - // If we were not able to translate the file:line:col information - // back to a SourceLocation, at least emit a note stating that - // we could not translate this location. This can happen in the - // case of #line directives. - Diags.Report(Loc, diag::note_fe_backend_invalid_loc) - << Filename << Line << Column; - - return Loc; -} - -void BackendConsumer::UnsupportedDiagHandler( - const llvm::DiagnosticInfoUnsupported &D) { - // We only support errors. - assert(D.getSeverity() == llvm::DS_Error); - - StringRef Filename; - unsigned Line, Column; - bool BadDebugInfo = false; - FullSourceLoc Loc = - getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column); - - Diags.Report(Loc, diag::err_fe_backend_unsupported) << D.getMessage().str(); - - if (BadDebugInfo) - // If we were not able to translate the file:line:col information - // back to a SourceLocation, at least emit a note stating that - // we could not translate this location. This can happen in the - // case of #line directives. - Diags.Report(Loc, diag::note_fe_backend_invalid_loc) - << Filename << Line << Column; -} - -void BackendConsumer::EmitOptimizationMessage( - const llvm::DiagnosticInfoOptimizationBase &D, unsigned DiagID) { - // We only support warnings and remarks. - assert(D.getSeverity() == llvm::DS_Remark || - D.getSeverity() == llvm::DS_Warning); - - StringRef Filename; - unsigned Line, Column; - bool BadDebugInfo = false; - FullSourceLoc Loc = - getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column); - - std::string Msg; - raw_string_ostream MsgStream(Msg); - MsgStream << D.getMsg(); - - if (D.getHotness()) - MsgStream << " (hotness: " << *D.getHotness() << ")"; - - Diags.Report(Loc, DiagID) - << AddFlagValue(D.getPassName()) - << MsgStream.str(); - - if (BadDebugInfo) - // If we were not able to translate the file:line:col information - // back to a SourceLocation, at least emit a note stating that - // we could not translate this location. This can happen in the - // case of #line directives. - Diags.Report(Loc, diag::note_fe_backend_invalid_loc) - << Filename << Line << Column; -} - -void BackendConsumer::OptimizationRemarkHandler( - const llvm::DiagnosticInfoOptimizationBase &D) { - // Without hotness information, don't show noisy remarks. - if (D.isVerbose() && !D.getHotness()) - return; - - if (D.isPassed()) { - // Optimization remarks are active only if the -Rpass flag has a regular - // expression that matches the name of the pass name in \p D. - if (CodeGenOpts.OptimizationRemarkPattern && - CodeGenOpts.OptimizationRemarkPattern->match(D.getPassName())) - EmitOptimizationMessage(D, diag::remark_fe_backend_optimization_remark); - } else if (D.isMissed()) { - // Missed optimization remarks are active only if the -Rpass-missed - // flag has a regular expression that matches the name of the pass - // name in \p D. - if (CodeGenOpts.OptimizationRemarkMissedPattern && - CodeGenOpts.OptimizationRemarkMissedPattern->match(D.getPassName())) - EmitOptimizationMessage( - D, diag::remark_fe_backend_optimization_remark_missed); - } else { - assert(D.isAnalysis() && "Unknown remark type"); - - bool ShouldAlwaysPrint = false; - if (auto *ORA = dyn_cast<llvm::OptimizationRemarkAnalysis>(&D)) - ShouldAlwaysPrint = ORA->shouldAlwaysPrint(); - - if (ShouldAlwaysPrint || - (CodeGenOpts.OptimizationRemarkAnalysisPattern && - CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName()))) - EmitOptimizationMessage( - D, diag::remark_fe_backend_optimization_remark_analysis); - } -} - -void BackendConsumer::OptimizationRemarkHandler( - const llvm::OptimizationRemarkAnalysisFPCommute &D) { - // Optimization analysis remarks are active if the pass name is set to - // llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a - // regular expression that matches the name of the pass name in \p D. - - if (D.shouldAlwaysPrint() || - (CodeGenOpts.OptimizationRemarkAnalysisPattern && - CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName()))) - EmitOptimizationMessage( - D, diag::remark_fe_backend_optimization_remark_analysis_fpcommute); -} - -void BackendConsumer::OptimizationRemarkHandler( - const llvm::OptimizationRemarkAnalysisAliasing &D) { - // Optimization analysis remarks are active if the pass name is set to - // llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a - // regular expression that matches the name of the pass name in \p D. - - if (D.shouldAlwaysPrint() || - (CodeGenOpts.OptimizationRemarkAnalysisPattern && - CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName()))) - EmitOptimizationMessage( - D, diag::remark_fe_backend_optimization_remark_analysis_aliasing); -} - -void BackendConsumer::OptimizationFailureHandler( - const llvm::DiagnosticInfoOptimizationFailure &D) { - EmitOptimizationMessage(D, diag::warn_fe_backend_optimization_failure); -} - -/// This function is invoked when the backend needs -/// to report something to the user. -void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) { - unsigned DiagID = diag::err_fe_inline_asm; - llvm::DiagnosticSeverity Severity = DI.getSeverity(); - // Get the diagnostic ID based. - switch (DI.getKind()) { - case llvm::DK_InlineAsm: - if (InlineAsmDiagHandler(cast<DiagnosticInfoInlineAsm>(DI))) - return; - ComputeDiagID(Severity, inline_asm, DiagID); - break; - case llvm::DK_StackSize: - if (StackSizeDiagHandler(cast<DiagnosticInfoStackSize>(DI))) - return; - ComputeDiagID(Severity, backend_frame_larger_than, DiagID); - break; - case DK_Linker: - assert(CurLinkModule); - // FIXME: stop eating the warnings and notes. - if (Severity != DS_Error) - return; - DiagID = diag::err_fe_cannot_link_module; - break; - case llvm::DK_OptimizationRemark: - // Optimization remarks are always handled completely by this - // handler. There is no generic way of emitting them. - OptimizationRemarkHandler(cast<OptimizationRemark>(DI)); - return; - case llvm::DK_OptimizationRemarkMissed: - // Optimization remarks are always handled completely by this - // handler. There is no generic way of emitting them. - OptimizationRemarkHandler(cast<OptimizationRemarkMissed>(DI)); - return; - case llvm::DK_OptimizationRemarkAnalysis: - // Optimization remarks are always handled completely by this - // handler. There is no generic way of emitting them. - OptimizationRemarkHandler(cast<OptimizationRemarkAnalysis>(DI)); - return; - case llvm::DK_OptimizationRemarkAnalysisFPCommute: - // Optimization remarks are always handled completely by this - // handler. There is no generic way of emitting them. - OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisFPCommute>(DI)); - return; - case llvm::DK_OptimizationRemarkAnalysisAliasing: - // Optimization remarks are always handled completely by this - // handler. There is no generic way of emitting them. - OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisAliasing>(DI)); - return; - case llvm::DK_MachineOptimizationRemark: - // Optimization remarks are always handled completely by this - // handler. There is no generic way of emitting them. - OptimizationRemarkHandler(cast<MachineOptimizationRemark>(DI)); - return; - case llvm::DK_MachineOptimizationRemarkMissed: - // Optimization remarks are always handled completely by this - // handler. There is no generic way of emitting them. - OptimizationRemarkHandler(cast<MachineOptimizationRemarkMissed>(DI)); - return; - case llvm::DK_MachineOptimizationRemarkAnalysis: - // Optimization remarks are always handled completely by this - // handler. There is no generic way of emitting them. - OptimizationRemarkHandler(cast<MachineOptimizationRemarkAnalysis>(DI)); - return; - case llvm::DK_OptimizationFailure: - // Optimization failures are always handled completely by this - // handler. - OptimizationFailureHandler(cast<DiagnosticInfoOptimizationFailure>(DI)); - return; - case llvm::DK_Unsupported: - UnsupportedDiagHandler(cast<DiagnosticInfoUnsupported>(DI)); - return; - default: - // Plugin IDs are not bound to any value as they are set dynamically. - ComputeDiagRemarkID(Severity, backend_plugin, DiagID); - break; - } - std::string MsgStorage; - { - raw_string_ostream Stream(MsgStorage); - DiagnosticPrinterRawOStream DP(Stream); - DI.print(DP); - } - - if (DiagID == diag::err_fe_cannot_link_module) { - Diags.Report(diag::err_fe_cannot_link_module) - << CurLinkModule->getModuleIdentifier() << MsgStorage; - return; - } - - // Report the backend message using the usual diagnostic mechanism. - FullSourceLoc Loc; - Diags.Report(Loc, DiagID).AddString(MsgStorage); -} -#undef ComputeDiagID - -CodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext) - : Act(_Act), VMContext(_VMContext ? _VMContext : new LLVMContext), - OwnsVMContext(!_VMContext) {} - -CodeGenAction::~CodeGenAction() { - TheModule.reset(); - if (OwnsVMContext) - delete VMContext; -} - -bool CodeGenAction::hasIRSupport() const { return true; } - -void CodeGenAction::EndSourceFileAction() { - // If the consumer creation failed, do nothing. - if (!getCompilerInstance().hasASTConsumer()) - return; - - // Steal the module from the consumer. - TheModule = BEConsumer->takeModule(); -} - -std::unique_ptr<llvm::Module> CodeGenAction::takeModule() { - return std::move(TheModule); -} - -llvm::LLVMContext *CodeGenAction::takeLLVMContext() { - OwnsVMContext = false; - return VMContext; -} - -static std::unique_ptr<raw_pwrite_stream> -GetOutputStream(CompilerInstance &CI, StringRef InFile, BackendAction Action) { - switch (Action) { - case Backend_EmitAssembly: - return CI.createDefaultOutputFile(false, InFile, "s"); - case Backend_EmitLL: - return CI.createDefaultOutputFile(false, InFile, "ll"); - case Backend_EmitBC: - return CI.createDefaultOutputFile(true, InFile, "bc"); - case Backend_EmitNothing: - return nullptr; - case Backend_EmitMCNull: - return CI.createNullOutputFile(); - case Backend_EmitObj: - return CI.createDefaultOutputFile(true, InFile, "o"); - } - - llvm_unreachable("Invalid action!"); -} - -std::unique_ptr<ASTConsumer> -CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - BackendAction BA = static_cast<BackendAction>(Act); - std::unique_ptr<raw_pwrite_stream> OS = CI.takeOutputStream(); - if (!OS) - OS = GetOutputStream(CI, InFile, BA); - - if (BA != Backend_EmitNothing && !OS) - return nullptr; - - // Load bitcode modules to link with, if we need to. - if (LinkModules.empty()) - for (const CodeGenOptions::BitcodeFileToLink &F : - CI.getCodeGenOpts().LinkBitcodeFiles) { - auto BCBuf = CI.getFileManager().getBufferForFile(F.Filename); - if (!BCBuf) { - CI.getDiagnostics().Report(diag::err_cannot_open_file) - << F.Filename << BCBuf.getError().message(); - LinkModules.clear(); - return nullptr; - } - - Expected<std::unique_ptr<llvm::Module>> ModuleOrErr = - getOwningLazyBitcodeModule(std::move(*BCBuf), *VMContext); - if (!ModuleOrErr) { - handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) { - CI.getDiagnostics().Report(diag::err_cannot_open_file) - << F.Filename << EIB.message(); - }); - LinkModules.clear(); - return nullptr; - } - LinkModules.push_back({std::move(ModuleOrErr.get()), F.PropagateAttrs, - F.Internalize, F.LinkFlags}); - } - - CoverageSourceInfo *CoverageInfo = nullptr; - // Add the preprocessor callback only when the coverage mapping is generated. - if (CI.getCodeGenOpts().CoverageMapping) { - CoverageInfo = new CoverageSourceInfo; - CI.getPreprocessor().addPPCallbacks( - std::unique_ptr<PPCallbacks>(CoverageInfo)); - } - - std::unique_ptr<BackendConsumer> Result(new BackendConsumer( - BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), - CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(), - CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, InFile, - std::move(LinkModules), std::move(OS), *VMContext, CoverageInfo)); - BEConsumer = Result.get(); - - // Enable generating macro debug info only when debug info is not disabled and - // also macro debug info is enabled. - if (CI.getCodeGenOpts().getDebugInfo() != codegenoptions::NoDebugInfo && - CI.getCodeGenOpts().MacroDebugInfo) { - std::unique_ptr<PPCallbacks> Callbacks = - llvm::make_unique<MacroPPCallbacks>(BEConsumer->getCodeGenerator(), - CI.getPreprocessor()); - CI.getPreprocessor().addPPCallbacks(std::move(Callbacks)); - } - - return std::move(Result); -} - -static void BitcodeInlineAsmDiagHandler(const llvm::SMDiagnostic &SM, - void *Context, - unsigned LocCookie) { - SM.print(nullptr, llvm::errs()); - - auto Diags = static_cast<DiagnosticsEngine *>(Context); - unsigned DiagID; - switch (SM.getKind()) { - case llvm::SourceMgr::DK_Error: - DiagID = diag::err_fe_inline_asm; - break; - case llvm::SourceMgr::DK_Warning: - DiagID = diag::warn_fe_inline_asm; - break; - case llvm::SourceMgr::DK_Note: - DiagID = diag::note_fe_inline_asm; - break; - case llvm::SourceMgr::DK_Remark: - llvm_unreachable("remarks unexpected"); - } - - Diags->Report(DiagID).AddString("cannot compile inline asm"); -} - -std::unique_ptr<llvm::Module> CodeGenAction::loadModule(MemoryBufferRef MBRef) { - CompilerInstance &CI = getCompilerInstance(); - SourceManager &SM = CI.getSourceManager(); - - // For ThinLTO backend invocations, ensure that the context - // merges types based on ODR identifiers. We also need to read - // the correct module out of a multi-module bitcode file. - if (!CI.getCodeGenOpts().ThinLTOIndexFile.empty()) { - VMContext->enableDebugTypeODRUniquing(); - - auto DiagErrors = [&](Error E) -> std::unique_ptr<llvm::Module> { - unsigned DiagID = - CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0"); - handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) { - CI.getDiagnostics().Report(DiagID) << EIB.message(); - }); - return {}; - }; - - Expected<std::vector<BitcodeModule>> BMsOrErr = getBitcodeModuleList(MBRef); - if (!BMsOrErr) - return DiagErrors(BMsOrErr.takeError()); - BitcodeModule *Bm = FindThinLTOModule(*BMsOrErr); - // We have nothing to do if the file contains no ThinLTO module. This is - // possible if ThinLTO compilation was not able to split module. Content of - // the file was already processed by indexing and will be passed to the - // linker using merged object file. - if (!Bm) { - auto M = llvm::make_unique<llvm::Module>("empty", *VMContext); - M->setTargetTriple(CI.getTargetOpts().Triple); - return M; - } - Expected<std::unique_ptr<llvm::Module>> MOrErr = - Bm->parseModule(*VMContext); - if (!MOrErr) - return DiagErrors(MOrErr.takeError()); - return std::move(*MOrErr); - } - - llvm::SMDiagnostic Err; - if (std::unique_ptr<llvm::Module> M = parseIR(MBRef, Err, *VMContext)) - return M; - - // Translate from the diagnostic info to the SourceManager location if - // available. - // TODO: Unify this with ConvertBackendLocation() - SourceLocation Loc; - if (Err.getLineNo() > 0) { - assert(Err.getColumnNo() >= 0); - Loc = SM.translateFileLineCol(SM.getFileEntryForID(SM.getMainFileID()), - Err.getLineNo(), Err.getColumnNo() + 1); - } - - // Strip off a leading diagnostic code if there is one. - StringRef Msg = Err.getMessage(); - if (Msg.startswith("error: ")) - Msg = Msg.substr(7); - - unsigned DiagID = - CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0"); - - CI.getDiagnostics().Report(Loc, DiagID) << Msg; - return {}; -} - -void CodeGenAction::ExecuteAction() { - // If this is an IR file, we have to treat it specially. - if (getCurrentFileKind().getLanguage() == InputKind::LLVM_IR) { - BackendAction BA = static_cast<BackendAction>(Act); - CompilerInstance &CI = getCompilerInstance(); - std::unique_ptr<raw_pwrite_stream> OS = - GetOutputStream(CI, getCurrentFile(), BA); - if (BA != Backend_EmitNothing && !OS) - return; - - bool Invalid; - SourceManager &SM = CI.getSourceManager(); - FileID FID = SM.getMainFileID(); - llvm::MemoryBuffer *MainFile = SM.getBuffer(FID, &Invalid); - if (Invalid) - return; - - TheModule = loadModule(*MainFile); - if (!TheModule) - return; - - const TargetOptions &TargetOpts = CI.getTargetOpts(); - if (TheModule->getTargetTriple() != TargetOpts.Triple) { - CI.getDiagnostics().Report(SourceLocation(), - diag::warn_fe_override_module) - << TargetOpts.Triple; - TheModule->setTargetTriple(TargetOpts.Triple); - } - - EmbedBitcode(TheModule.get(), CI.getCodeGenOpts(), - MainFile->getMemBufferRef()); - - LLVMContext &Ctx = TheModule->getContext(); - Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler, - &CI.getDiagnostics()); - - EmitBackendOutput(CI.getDiagnostics(), CI.getHeaderSearchOpts(), - CI.getCodeGenOpts(), TargetOpts, CI.getLangOpts(), - CI.getTarget().getDataLayout(), TheModule.get(), BA, - std::move(OS)); - return; - } - - // Otherwise follow the normal AST path. - this->ASTFrontendAction::ExecuteAction(); -} - -// - -void EmitAssemblyAction::anchor() { } -EmitAssemblyAction::EmitAssemblyAction(llvm::LLVMContext *_VMContext) - : CodeGenAction(Backend_EmitAssembly, _VMContext) {} - -void EmitBCAction::anchor() { } -EmitBCAction::EmitBCAction(llvm::LLVMContext *_VMContext) - : CodeGenAction(Backend_EmitBC, _VMContext) {} - -void EmitLLVMAction::anchor() { } -EmitLLVMAction::EmitLLVMAction(llvm::LLVMContext *_VMContext) - : CodeGenAction(Backend_EmitLL, _VMContext) {} - -void EmitLLVMOnlyAction::anchor() { } -EmitLLVMOnlyAction::EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext) - : CodeGenAction(Backend_EmitNothing, _VMContext) {} - -void EmitCodeGenOnlyAction::anchor() { } -EmitCodeGenOnlyAction::EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext) - : CodeGenAction(Backend_EmitMCNull, _VMContext) {} - -void EmitObjAction::anchor() { } -EmitObjAction::EmitObjAction(llvm::LLVMContext *_VMContext) - : CodeGenAction(Backend_EmitObj, _VMContext) {} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp deleted file mode 100644 index 1713e40c312..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp +++ /dev/null @@ -1,2565 +0,0 @@ -//===--- CodeGenFunction.cpp - Emit LLVM Code from ASTs for a Function ----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This coordinates the per-function state used while generating code. -// -//===----------------------------------------------------------------------===// - -#include "CodeGenFunction.h" -#include "CGBlocks.h" -#include "CGCleanup.h" -#include "CGCUDARuntime.h" -#include "CGCXXABI.h" -#include "CGDebugInfo.h" -#include "CGOpenMPRuntime.h" -#include "CodeGenModule.h" -#include "CodeGenPGO.h" -#include "TargetInfo.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/ASTLambda.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/StmtCXX.h" -#include "clang/AST/StmtObjC.h" -#include "clang/Basic/Builtins.h" -#include "clang/Basic/CodeGenOptions.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/CodeGen/CGFunctionInfo.h" -#include "clang/Frontend/FrontendDiagnostic.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/Dominators.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/MDBuilder.h" -#include "llvm/IR/Operator.h" -#include "llvm/Transforms/Utils/PromoteMemToReg.h" -using namespace clang; -using namespace CodeGen; - -/// shouldEmitLifetimeMarkers - Decide whether we need emit the life-time -/// markers. -static bool shouldEmitLifetimeMarkers(const CodeGenOptions &CGOpts, - const LangOptions &LangOpts) { - if (CGOpts.DisableLifetimeMarkers) - return false; - - // Disable lifetime markers in msan builds. - // FIXME: Remove this when msan works with lifetime markers. - if (LangOpts.Sanitize.has(SanitizerKind::Memory)) - return false; - - // Asan uses markers for use-after-scope checks. - if (CGOpts.SanitizeAddressUseAfterScope) - return true; - - // For now, only in optimized builds. - return CGOpts.OptimizationLevel != 0; -} - -CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) - : CodeGenTypeCache(cgm), CGM(cgm), Target(cgm.getTarget()), - Builder(cgm, cgm.getModule().getContext(), llvm::ConstantFolder(), - CGBuilderInserterTy(this)), - SanOpts(CGM.getLangOpts().Sanitize), DebugInfo(CGM.getModuleDebugInfo()), - PGO(cgm), ShouldEmitLifetimeMarkers(shouldEmitLifetimeMarkers( - CGM.getCodeGenOpts(), CGM.getLangOpts())) { - if (!suppressNewContext) - CGM.getCXXABI().getMangleContext().startNewFunction(); - - llvm::FastMathFlags FMF; - if (CGM.getLangOpts().FastMath) - FMF.setFast(); - if (CGM.getLangOpts().FiniteMathOnly) { - FMF.setNoNaNs(); - FMF.setNoInfs(); - } - if (CGM.getCodeGenOpts().NoNaNsFPMath) { - FMF.setNoNaNs(); - } - if (CGM.getCodeGenOpts().NoSignedZeros) { - FMF.setNoSignedZeros(); - } - if (CGM.getCodeGenOpts().ReciprocalMath) { - FMF.setAllowReciprocal(); - } - if (CGM.getCodeGenOpts().Reassociate) { - FMF.setAllowReassoc(); - } - Builder.setFastMathFlags(FMF); -} - -CodeGenFunction::~CodeGenFunction() { - assert(LifetimeExtendedCleanupStack.empty() && "failed to emit a cleanup"); - - // If there are any unclaimed block infos, go ahead and destroy them - // now. This can happen if IR-gen gets clever and skips evaluating - // something. - if (FirstBlockInfo) - destroyBlockInfos(FirstBlockInfo); - - if (getLangOpts().OpenMP && CurFn) - CGM.getOpenMPRuntime().functionFinished(*this); -} - -CharUnits CodeGenFunction::getNaturalPointeeTypeAlignment(QualType T, - LValueBaseInfo *BaseInfo, - TBAAAccessInfo *TBAAInfo) { - return getNaturalTypeAlignment(T->getPointeeType(), BaseInfo, TBAAInfo, - /* forPointeeType= */ true); -} - -CharUnits CodeGenFunction::getNaturalTypeAlignment(QualType T, - LValueBaseInfo *BaseInfo, - TBAAAccessInfo *TBAAInfo, - bool forPointeeType) { - if (TBAAInfo) - *TBAAInfo = CGM.getTBAAAccessInfo(T); - - // Honor alignment typedef attributes even on incomplete types. - // We also honor them straight for C++ class types, even as pointees; - // there's an expressivity gap here. - if (auto TT = T->getAs<TypedefType>()) { - if (auto Align = TT->getDecl()->getMaxAlignment()) { - if (BaseInfo) - *BaseInfo = LValueBaseInfo(AlignmentSource::AttributedType); - return getContext().toCharUnitsFromBits(Align); - } - } - - if (BaseInfo) - *BaseInfo = LValueBaseInfo(AlignmentSource::Type); - - CharUnits Alignment; - if (T->isIncompleteType()) { - Alignment = CharUnits::One(); // Shouldn't be used, but pessimistic is best. - } else { - // For C++ class pointees, we don't know whether we're pointing at a - // base or a complete object, so we generally need to use the - // non-virtual alignment. - const CXXRecordDecl *RD; - if (forPointeeType && (RD = T->getAsCXXRecordDecl())) { - Alignment = CGM.getClassPointerAlignment(RD); - } else { - Alignment = getContext().getTypeAlignInChars(T); - if (T.getQualifiers().hasUnaligned()) - Alignment = CharUnits::One(); - } - - // Cap to the global maximum type alignment unless the alignment - // was somehow explicit on the type. - if (unsigned MaxAlign = getLangOpts().MaxTypeAlign) { - if (Alignment.getQuantity() > MaxAlign && - !getContext().isAlignmentRequired(T)) - Alignment = CharUnits::fromQuantity(MaxAlign); - } - } - return Alignment; -} - -LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) { - LValueBaseInfo BaseInfo; - TBAAAccessInfo TBAAInfo; - CharUnits Alignment = getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo); - return LValue::MakeAddr(Address(V, Alignment), T, getContext(), BaseInfo, - TBAAInfo); -} - -/// Given a value of type T* that may not be to a complete object, -/// construct an l-value with the natural pointee alignment of T. -LValue -CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T) { - LValueBaseInfo BaseInfo; - TBAAAccessInfo TBAAInfo; - CharUnits Align = getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo, - /* forPointeeType= */ true); - return MakeAddrLValue(Address(V, Align), T, BaseInfo, TBAAInfo); -} - - -llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) { - return CGM.getTypes().ConvertTypeForMem(T); -} - -llvm::Type *CodeGenFunction::ConvertType(QualType T) { - return CGM.getTypes().ConvertType(T); -} - -TypeEvaluationKind CodeGenFunction::getEvaluationKind(QualType type) { - type = type.getCanonicalType(); - while (true) { - switch (type->getTypeClass()) { -#define TYPE(name, parent) -#define ABSTRACT_TYPE(name, parent) -#define NON_CANONICAL_TYPE(name, parent) case Type::name: -#define DEPENDENT_TYPE(name, parent) case Type::name: -#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(name, parent) case Type::name: -#include "clang/AST/TypeNodes.def" - llvm_unreachable("non-canonical or dependent type in IR-generation"); - - case Type::Auto: - case Type::DeducedTemplateSpecialization: - llvm_unreachable("undeduced type in IR-generation"); - - // Various scalar types. - case Type::Builtin: - case Type::Pointer: - case Type::BlockPointer: - case Type::LValueReference: - case Type::RValueReference: - case Type::MemberPointer: - case Type::Vector: - case Type::ExtVector: - case Type::FunctionProto: - case Type::FunctionNoProto: - case Type::Enum: - case Type::ObjCObjectPointer: - case Type::Pipe: - return TEK_Scalar; - - // Complexes. - case Type::Complex: - return TEK_Complex; - - // Arrays, records, and Objective-C objects. - case Type::ConstantArray: - case Type::IncompleteArray: - case Type::VariableArray: - case Type::Record: - case Type::ObjCObject: - case Type::ObjCInterface: - return TEK_Aggregate; - - // We operate on atomic values according to their underlying type. - case Type::Atomic: - type = cast<AtomicType>(type)->getValueType(); - continue; - } - llvm_unreachable("unknown type kind!"); - } -} - -llvm::DebugLoc CodeGenFunction::EmitReturnBlock() { - // For cleanliness, we try to avoid emitting the return block for - // simple cases. - llvm::BasicBlock *CurBB = Builder.GetInsertBlock(); - - if (CurBB) { - assert(!CurBB->getTerminator() && "Unexpected terminated block."); - - // We have a valid insert point, reuse it if it is empty or there are no - // explicit jumps to the return block. - if (CurBB->empty() || ReturnBlock.getBlock()->use_empty()) { - ReturnBlock.getBlock()->replaceAllUsesWith(CurBB); - delete ReturnBlock.getBlock(); - } else - EmitBlock(ReturnBlock.getBlock()); - return llvm::DebugLoc(); - } - - // Otherwise, if the return block is the target of a single direct - // branch then we can just put the code in that block instead. This - // cleans up functions which started with a unified return block. - if (ReturnBlock.getBlock()->hasOneUse()) { - llvm::BranchInst *BI = - dyn_cast<llvm::BranchInst>(*ReturnBlock.getBlock()->user_begin()); - if (BI && BI->isUnconditional() && - BI->getSuccessor(0) == ReturnBlock.getBlock()) { - // Record/return the DebugLoc of the simple 'return' expression to be used - // later by the actual 'ret' instruction. - llvm::DebugLoc Loc = BI->getDebugLoc(); - Builder.SetInsertPoint(BI->getParent()); - BI->eraseFromParent(); - delete ReturnBlock.getBlock(); - return Loc; - } - } - - // FIXME: We are at an unreachable point, there is no reason to emit the block - // unless it has uses. However, we still need a place to put the debug - // region.end for now. - - EmitBlock(ReturnBlock.getBlock()); - return llvm::DebugLoc(); -} - -static void EmitIfUsed(CodeGenFunction &CGF, llvm::BasicBlock *BB) { - if (!BB) return; - if (!BB->use_empty()) - return CGF.CurFn->getBasicBlockList().push_back(BB); - delete BB; -} - -void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { - assert(BreakContinueStack.empty() && - "mismatched push/pop in break/continue stack!"); - - bool OnlySimpleReturnStmts = NumSimpleReturnExprs > 0 - && NumSimpleReturnExprs == NumReturnExprs - && ReturnBlock.getBlock()->use_empty(); - // Usually the return expression is evaluated before the cleanup - // code. If the function contains only a simple return statement, - // such as a constant, the location before the cleanup code becomes - // the last useful breakpoint in the function, because the simple - // return expression will be evaluated after the cleanup code. To be - // safe, set the debug location for cleanup code to the location of - // the return statement. Otherwise the cleanup code should be at the - // end of the function's lexical scope. - // - // If there are multiple branches to the return block, the branch - // instructions will get the location of the return statements and - // all will be fine. - if (CGDebugInfo *DI = getDebugInfo()) { - if (OnlySimpleReturnStmts) - DI->EmitLocation(Builder, LastStopPoint); - else - DI->EmitLocation(Builder, EndLoc); - } - - // Pop any cleanups that might have been associated with the - // parameters. Do this in whatever block we're currently in; it's - // important to do this before we enter the return block or return - // edges will be *really* confused. - bool HasCleanups = EHStack.stable_begin() != PrologueCleanupDepth; - bool HasOnlyLifetimeMarkers = - HasCleanups && EHStack.containsOnlyLifetimeMarkers(PrologueCleanupDepth); - bool EmitRetDbgLoc = !HasCleanups || HasOnlyLifetimeMarkers; - if (HasCleanups) { - // Make sure the line table doesn't jump back into the body for - // the ret after it's been at EndLoc. - if (CGDebugInfo *DI = getDebugInfo()) - if (OnlySimpleReturnStmts) - DI->EmitLocation(Builder, EndLoc); - - PopCleanupBlocks(PrologueCleanupDepth); - } - - // Emit function epilog (to return). - llvm::DebugLoc Loc = EmitReturnBlock(); - - if (ShouldInstrumentFunction()) { - if (CGM.getCodeGenOpts().InstrumentFunctions) - CurFn->addFnAttr("instrument-function-exit", "__cyg_profile_func_exit"); - if (CGM.getCodeGenOpts().InstrumentFunctionsAfterInlining) - CurFn->addFnAttr("instrument-function-exit-inlined", - "__cyg_profile_func_exit"); - } - - // Emit debug descriptor for function end. - if (CGDebugInfo *DI = getDebugInfo()) - DI->EmitFunctionEnd(Builder, CurFn); - - // Reset the debug location to that of the simple 'return' expression, if any - // rather than that of the end of the function's scope '}'. - ApplyDebugLocation AL(*this, Loc); - EmitFunctionEpilog(*CurFnInfo, EmitRetDbgLoc, EndLoc); - EmitEndEHSpec(CurCodeDecl); - - assert(EHStack.empty() && - "did not remove all scopes from cleanup stack!"); - - // If someone did an indirect goto, emit the indirect goto block at the end of - // the function. - if (IndirectBranch) { - EmitBlock(IndirectBranch->getParent()); - Builder.ClearInsertionPoint(); - } - - // If some of our locals escaped, insert a call to llvm.localescape in the - // entry block. - if (!EscapedLocals.empty()) { - // Invert the map from local to index into a simple vector. There should be - // no holes. - SmallVector<llvm::Value *, 4> EscapeArgs; - EscapeArgs.resize(EscapedLocals.size()); - for (auto &Pair : EscapedLocals) - EscapeArgs[Pair.second] = Pair.first; - llvm::Function *FrameEscapeFn = llvm::Intrinsic::getDeclaration( - &CGM.getModule(), llvm::Intrinsic::localescape); - CGBuilderTy(*this, AllocaInsertPt).CreateCall(FrameEscapeFn, EscapeArgs); - } - - // Remove the AllocaInsertPt instruction, which is just a convenience for us. - llvm::Instruction *Ptr = AllocaInsertPt; - AllocaInsertPt = nullptr; - Ptr->eraseFromParent(); - - // If someone took the address of a label but never did an indirect goto, we - // made a zero entry PHI node, which is illegal, zap it now. - if (IndirectBranch) { - llvm::PHINode *PN = cast<llvm::PHINode>(IndirectBranch->getAddress()); - if (PN->getNumIncomingValues() == 0) { - PN->replaceAllUsesWith(llvm::UndefValue::get(PN->getType())); - PN->eraseFromParent(); - } - } - - EmitIfUsed(*this, EHResumeBlock); - EmitIfUsed(*this, TerminateLandingPad); - EmitIfUsed(*this, TerminateHandler); - EmitIfUsed(*this, UnreachableBlock); - - for (const auto &FuncletAndParent : TerminateFunclets) - EmitIfUsed(*this, FuncletAndParent.second); - - if (CGM.getCodeGenOpts().EmitDeclMetadata) - EmitDeclMetadata(); - - for (SmallVectorImpl<std::pair<llvm::Instruction *, llvm::Value *> >::iterator - I = DeferredReplacements.begin(), - E = DeferredReplacements.end(); - I != E; ++I) { - I->first->replaceAllUsesWith(I->second); - I->first->eraseFromParent(); - } - - // Eliminate CleanupDestSlot alloca by replacing it with SSA values and - // PHIs if the current function is a coroutine. We don't do it for all - // functions as it may result in slight increase in numbers of instructions - // if compiled with no optimizations. We do it for coroutine as the lifetime - // of CleanupDestSlot alloca make correct coroutine frame building very - // difficult. - if (NormalCleanupDest.isValid() && isCoroutine()) { - llvm::DominatorTree DT(*CurFn); - llvm::PromoteMemToReg( - cast<llvm::AllocaInst>(NormalCleanupDest.getPointer()), DT); - NormalCleanupDest = Address::invalid(); - } - - // Scan function arguments for vector width. - for (llvm::Argument &A : CurFn->args()) - if (auto *VT = dyn_cast<llvm::VectorType>(A.getType())) - LargestVectorWidth = std::max(LargestVectorWidth, - VT->getPrimitiveSizeInBits()); - - // Update vector width based on return type. - if (auto *VT = dyn_cast<llvm::VectorType>(CurFn->getReturnType())) - LargestVectorWidth = std::max(LargestVectorWidth, - VT->getPrimitiveSizeInBits()); - - // Add the required-vector-width attribute. This contains the max width from: - // 1. min-vector-width attribute used in the source program. - // 2. Any builtins used that have a vector width specified. - // 3. Values passed in and out of inline assembly. - // 4. Width of vector arguments and return types for this function. - // 5. Width of vector aguments and return types for functions called by this - // function. - CurFn->addFnAttr("min-legal-vector-width", llvm::utostr(LargestVectorWidth)); -} - -/// ShouldInstrumentFunction - Return true if the current function should be -/// instrumented with __cyg_profile_func_* calls -bool CodeGenFunction::ShouldInstrumentFunction() { - if (!CGM.getCodeGenOpts().InstrumentFunctions && - !CGM.getCodeGenOpts().InstrumentFunctionsAfterInlining && - !CGM.getCodeGenOpts().InstrumentFunctionEntryBare) - return false; - if (!CurFuncDecl || CurFuncDecl->hasAttr<NoInstrumentFunctionAttr>()) - return false; - return true; -} - -/// ShouldXRayInstrument - Return true if the current function should be -/// instrumented with XRay nop sleds. -bool CodeGenFunction::ShouldXRayInstrumentFunction() const { - return CGM.getCodeGenOpts().XRayInstrumentFunctions; -} - -/// AlwaysEmitXRayCustomEvents - Return true if we should emit IR for calls to -/// the __xray_customevent(...) builtin calls, when doing XRay instrumentation. -bool CodeGenFunction::AlwaysEmitXRayCustomEvents() const { - return CGM.getCodeGenOpts().XRayInstrumentFunctions && - (CGM.getCodeGenOpts().XRayAlwaysEmitCustomEvents || - CGM.getCodeGenOpts().XRayInstrumentationBundle.Mask == - XRayInstrKind::Custom); -} - -bool CodeGenFunction::AlwaysEmitXRayTypedEvents() const { - return CGM.getCodeGenOpts().XRayInstrumentFunctions && - (CGM.getCodeGenOpts().XRayAlwaysEmitTypedEvents || - CGM.getCodeGenOpts().XRayInstrumentationBundle.Mask == - XRayInstrKind::Typed); -} - -llvm::Constant * -CodeGenFunction::EncodeAddrForUseInPrologue(llvm::Function *F, - llvm::Constant *Addr) { - // Addresses stored in prologue data can't require run-time fixups and must - // be PC-relative. Run-time fixups are undesirable because they necessitate - // writable text segments, which are unsafe. And absolute addresses are - // undesirable because they break PIE mode. - - // Add a layer of indirection through a private global. Taking its address - // won't result in a run-time fixup, even if Addr has linkonce_odr linkage. - auto *GV = new llvm::GlobalVariable(CGM.getModule(), Addr->getType(), - /*isConstant=*/true, - llvm::GlobalValue::PrivateLinkage, Addr); - - // Create a PC-relative address. - auto *GOTAsInt = llvm::ConstantExpr::getPtrToInt(GV, IntPtrTy); - auto *FuncAsInt = llvm::ConstantExpr::getPtrToInt(F, IntPtrTy); - auto *PCRelAsInt = llvm::ConstantExpr::getSub(GOTAsInt, FuncAsInt); - return (IntPtrTy == Int32Ty) - ? PCRelAsInt - : llvm::ConstantExpr::getTrunc(PCRelAsInt, Int32Ty); -} - -llvm::Value * -CodeGenFunction::DecodeAddrUsedInPrologue(llvm::Value *F, - llvm::Value *EncodedAddr) { - // Reconstruct the address of the global. - auto *PCRelAsInt = Builder.CreateSExt(EncodedAddr, IntPtrTy); - auto *FuncAsInt = Builder.CreatePtrToInt(F, IntPtrTy, "func_addr.int"); - auto *GOTAsInt = Builder.CreateAdd(PCRelAsInt, FuncAsInt, "global_addr.int"); - auto *GOTAddr = Builder.CreateIntToPtr(GOTAsInt, Int8PtrPtrTy, "global_addr"); - - // Load the original pointer through the global. - return Builder.CreateLoad(Address(GOTAddr, getPointerAlign()), - "decoded_addr"); -} - -static void removeImageAccessQualifier(std::string& TyName) { - std::string ReadOnlyQual("__read_only"); - std::string::size_type ReadOnlyPos = TyName.find(ReadOnlyQual); - if (ReadOnlyPos != std::string::npos) - // "+ 1" for the space after access qualifier. - TyName.erase(ReadOnlyPos, ReadOnlyQual.size() + 1); - else { - std::string WriteOnlyQual("__write_only"); - std::string::size_type WriteOnlyPos = TyName.find(WriteOnlyQual); - if (WriteOnlyPos != std::string::npos) - TyName.erase(WriteOnlyPos, WriteOnlyQual.size() + 1); - else { - std::string ReadWriteQual("__read_write"); - std::string::size_type ReadWritePos = TyName.find(ReadWriteQual); - if (ReadWritePos != std::string::npos) - TyName.erase(ReadWritePos, ReadWriteQual.size() + 1); - } - } -} - -// Returns the address space id that should be produced to the -// kernel_arg_addr_space metadata. This is always fixed to the ids -// as specified in the SPIR 2.0 specification in order to differentiate -// for example in clGetKernelArgInfo() implementation between the address -// spaces with targets without unique mapping to the OpenCL address spaces -// (basically all single AS CPUs). -static unsigned ArgInfoAddressSpace(LangAS AS) { - switch (AS) { - case LangAS::opencl_global: return 1; - case LangAS::opencl_constant: return 2; - case LangAS::opencl_local: return 3; - case LangAS::opencl_generic: return 4; // Not in SPIR 2.0 specs. - default: - return 0; // Assume private. - } -} - -// OpenCL v1.2 s5.6.4.6 allows the compiler to store kernel argument -// information in the program executable. The argument information stored -// includes the argument name, its type, the address and access qualifiers used. -static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn, - CodeGenModule &CGM, llvm::LLVMContext &Context, - CGBuilderTy &Builder, ASTContext &ASTCtx) { - // Create MDNodes that represent the kernel arg metadata. - // Each MDNode is a list in the form of "key", N number of values which is - // the same number of values as their are kernel arguments. - - const PrintingPolicy &Policy = ASTCtx.getPrintingPolicy(); - - // MDNode for the kernel argument address space qualifiers. - SmallVector<llvm::Metadata *, 8> addressQuals; - - // MDNode for the kernel argument access qualifiers (images only). - SmallVector<llvm::Metadata *, 8> accessQuals; - - // MDNode for the kernel argument type names. - SmallVector<llvm::Metadata *, 8> argTypeNames; - - // MDNode for the kernel argument base type names. - SmallVector<llvm::Metadata *, 8> argBaseTypeNames; - - // MDNode for the kernel argument type qualifiers. - SmallVector<llvm::Metadata *, 8> argTypeQuals; - - // MDNode for the kernel argument names. - SmallVector<llvm::Metadata *, 8> argNames; - - for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) { - const ParmVarDecl *parm = FD->getParamDecl(i); - QualType ty = parm->getType(); - std::string typeQuals; - - if (ty->isPointerType()) { - QualType pointeeTy = ty->getPointeeType(); - - // Get address qualifier. - addressQuals.push_back(llvm::ConstantAsMetadata::get(Builder.getInt32( - ArgInfoAddressSpace(pointeeTy.getAddressSpace())))); - - // Get argument type name. - std::string typeName = - pointeeTy.getUnqualifiedType().getAsString(Policy) + "*"; - - // Turn "unsigned type" to "utype" - std::string::size_type pos = typeName.find("unsigned"); - if (pointeeTy.isCanonical() && pos != std::string::npos) - typeName.erase(pos+1, 8); - - argTypeNames.push_back(llvm::MDString::get(Context, typeName)); - - std::string baseTypeName = - pointeeTy.getUnqualifiedType().getCanonicalType().getAsString( - Policy) + - "*"; - - // Turn "unsigned type" to "utype" - pos = baseTypeName.find("unsigned"); - if (pos != std::string::npos) - baseTypeName.erase(pos+1, 8); - - argBaseTypeNames.push_back(llvm::MDString::get(Context, baseTypeName)); - - // Get argument type qualifiers: - if (ty.isRestrictQualified()) - typeQuals = "restrict"; - if (pointeeTy.isConstQualified() || - (pointeeTy.getAddressSpace() == LangAS::opencl_constant)) - typeQuals += typeQuals.empty() ? "const" : " const"; - if (pointeeTy.isVolatileQualified()) - typeQuals += typeQuals.empty() ? "volatile" : " volatile"; - } else { - uint32_t AddrSpc = 0; - bool isPipe = ty->isPipeType(); - if (ty->isImageType() || isPipe) - AddrSpc = ArgInfoAddressSpace(LangAS::opencl_global); - - addressQuals.push_back( - llvm::ConstantAsMetadata::get(Builder.getInt32(AddrSpc))); - - // Get argument type name. - std::string typeName; - if (isPipe) - typeName = ty.getCanonicalType()->getAs<PipeType>()->getElementType() - .getAsString(Policy); - else - typeName = ty.getUnqualifiedType().getAsString(Policy); - - // Turn "unsigned type" to "utype" - std::string::size_type pos = typeName.find("unsigned"); - if (ty.isCanonical() && pos != std::string::npos) - typeName.erase(pos+1, 8); - - std::string baseTypeName; - if (isPipe) - baseTypeName = ty.getCanonicalType()->getAs<PipeType>() - ->getElementType().getCanonicalType() - .getAsString(Policy); - else - baseTypeName = - ty.getUnqualifiedType().getCanonicalType().getAsString(Policy); - - // Remove access qualifiers on images - // (as they are inseparable from type in clang implementation, - // but OpenCL spec provides a special query to get access qualifier - // via clGetKernelArgInfo with CL_KERNEL_ARG_ACCESS_QUALIFIER): - if (ty->isImageType()) { - removeImageAccessQualifier(typeName); - removeImageAccessQualifier(baseTypeName); - } - - argTypeNames.push_back(llvm::MDString::get(Context, typeName)); - - // Turn "unsigned type" to "utype" - pos = baseTypeName.find("unsigned"); - if (pos != std::string::npos) - baseTypeName.erase(pos+1, 8); - - argBaseTypeNames.push_back(llvm::MDString::get(Context, baseTypeName)); - - if (isPipe) - typeQuals = "pipe"; - } - - argTypeQuals.push_back(llvm::MDString::get(Context, typeQuals)); - - // Get image and pipe access qualifier: - if (ty->isImageType()|| ty->isPipeType()) { - const Decl *PDecl = parm; - if (auto *TD = dyn_cast<TypedefType>(ty)) - PDecl = TD->getDecl(); - const OpenCLAccessAttr *A = PDecl->getAttr<OpenCLAccessAttr>(); - if (A && A->isWriteOnly()) - accessQuals.push_back(llvm::MDString::get(Context, "write_only")); - else if (A && A->isReadWrite()) - accessQuals.push_back(llvm::MDString::get(Context, "read_write")); - else - accessQuals.push_back(llvm::MDString::get(Context, "read_only")); - } else - accessQuals.push_back(llvm::MDString::get(Context, "none")); - - // Get argument name. - argNames.push_back(llvm::MDString::get(Context, parm->getName())); - } - - Fn->setMetadata("kernel_arg_addr_space", - llvm::MDNode::get(Context, addressQuals)); - Fn->setMetadata("kernel_arg_access_qual", - llvm::MDNode::get(Context, accessQuals)); - Fn->setMetadata("kernel_arg_type", - llvm::MDNode::get(Context, argTypeNames)); - Fn->setMetadata("kernel_arg_base_type", - llvm::MDNode::get(Context, argBaseTypeNames)); - Fn->setMetadata("kernel_arg_type_qual", - llvm::MDNode::get(Context, argTypeQuals)); - if (CGM.getCodeGenOpts().EmitOpenCLArgMetadata) - Fn->setMetadata("kernel_arg_name", - llvm::MDNode::get(Context, argNames)); -} - -void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD, - llvm::Function *Fn) -{ - if (!FD->hasAttr<OpenCLKernelAttr>()) - return; - - llvm::LLVMContext &Context = getLLVMContext(); - - GenOpenCLArgMetadata(FD, Fn, CGM, Context, Builder, getContext()); - - if (const VecTypeHintAttr *A = FD->getAttr<VecTypeHintAttr>()) { - QualType HintQTy = A->getTypeHint(); - const ExtVectorType *HintEltQTy = HintQTy->getAs<ExtVectorType>(); - bool IsSignedInteger = - HintQTy->isSignedIntegerType() || - (HintEltQTy && HintEltQTy->getElementType()->isSignedIntegerType()); - llvm::Metadata *AttrMDArgs[] = { - llvm::ConstantAsMetadata::get(llvm::UndefValue::get( - CGM.getTypes().ConvertType(A->getTypeHint()))), - llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - llvm::IntegerType::get(Context, 32), - llvm::APInt(32, (uint64_t)(IsSignedInteger ? 1 : 0))))}; - Fn->setMetadata("vec_type_hint", llvm::MDNode::get(Context, AttrMDArgs)); - } - - if (const WorkGroupSizeHintAttr *A = FD->getAttr<WorkGroupSizeHintAttr>()) { - llvm::Metadata *AttrMDArgs[] = { - llvm::ConstantAsMetadata::get(Builder.getInt32(A->getXDim())), - llvm::ConstantAsMetadata::get(Builder.getInt32(A->getYDim())), - llvm::ConstantAsMetadata::get(Builder.getInt32(A->getZDim()))}; - Fn->setMetadata("work_group_size_hint", llvm::MDNode::get(Context, AttrMDArgs)); - } - - if (const ReqdWorkGroupSizeAttr *A = FD->getAttr<ReqdWorkGroupSizeAttr>()) { - llvm::Metadata *AttrMDArgs[] = { - llvm::ConstantAsMetadata::get(Builder.getInt32(A->getXDim())), - llvm::ConstantAsMetadata::get(Builder.getInt32(A->getYDim())), - llvm::ConstantAsMetadata::get(Builder.getInt32(A->getZDim()))}; - Fn->setMetadata("reqd_work_group_size", llvm::MDNode::get(Context, AttrMDArgs)); - } - - if (const OpenCLIntelReqdSubGroupSizeAttr *A = - FD->getAttr<OpenCLIntelReqdSubGroupSizeAttr>()) { - llvm::Metadata *AttrMDArgs[] = { - llvm::ConstantAsMetadata::get(Builder.getInt32(A->getSubGroupSize()))}; - Fn->setMetadata("intel_reqd_sub_group_size", - llvm::MDNode::get(Context, AttrMDArgs)); - } -} - -/// Determine whether the function F ends with a return stmt. -static bool endsWithReturn(const Decl* F) { - const Stmt *Body = nullptr; - if (auto *FD = dyn_cast_or_null<FunctionDecl>(F)) - Body = FD->getBody(); - else if (auto *OMD = dyn_cast_or_null<ObjCMethodDecl>(F)) - Body = OMD->getBody(); - - if (auto *CS = dyn_cast_or_null<CompoundStmt>(Body)) { - auto LastStmt = CS->body_rbegin(); - if (LastStmt != CS->body_rend()) - return isa<ReturnStmt>(*LastStmt); - } - return false; -} - -void CodeGenFunction::markAsIgnoreThreadCheckingAtRuntime(llvm::Function *Fn) { - if (SanOpts.has(SanitizerKind::Thread)) { - Fn->addFnAttr("sanitize_thread_no_checking_at_run_time"); - Fn->removeFnAttr(llvm::Attribute::SanitizeThread); - } -} - -static bool matchesStlAllocatorFn(const Decl *D, const ASTContext &Ctx) { - auto *MD = dyn_cast_or_null<CXXMethodDecl>(D); - if (!MD || !MD->getDeclName().getAsIdentifierInfo() || - !MD->getDeclName().getAsIdentifierInfo()->isStr("allocate") || - (MD->getNumParams() != 1 && MD->getNumParams() != 2)) - return false; - - if (MD->parameters()[0]->getType().getCanonicalType() != Ctx.getSizeType()) - return false; - - if (MD->getNumParams() == 2) { - auto *PT = MD->parameters()[1]->getType()->getAs<PointerType>(); - if (!PT || !PT->isVoidPointerType() || - !PT->getPointeeType().isConstQualified()) - return false; - } - - return true; -} - -/// Return the UBSan prologue signature for \p FD if one is available. -static llvm::Constant *getPrologueSignature(CodeGenModule &CGM, - const FunctionDecl *FD) { - if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) - if (!MD->isStatic()) - return nullptr; - return CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM); -} - -void CodeGenFunction::StartFunction(GlobalDecl GD, - QualType RetTy, - llvm::Function *Fn, - const CGFunctionInfo &FnInfo, - const FunctionArgList &Args, - SourceLocation Loc, - SourceLocation StartLoc) { - assert(!CurFn && - "Do not use a CodeGenFunction object for more than one function"); - - const Decl *D = GD.getDecl(); - - DidCallStackSave = false; - CurCodeDecl = D; - if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D)) - if (FD->usesSEHTry()) - CurSEHParent = FD; - CurFuncDecl = (D ? D->getNonClosureContext() : nullptr); - FnRetTy = RetTy; - CurFn = Fn; - CurFnInfo = &FnInfo; - assert(CurFn->isDeclaration() && "Function already has body?"); - - // If this function has been blacklisted for any of the enabled sanitizers, - // disable the sanitizer for the function. - do { -#define SANITIZER(NAME, ID) \ - if (SanOpts.empty()) \ - break; \ - if (SanOpts.has(SanitizerKind::ID)) \ - if (CGM.isInSanitizerBlacklist(SanitizerKind::ID, Fn, Loc)) \ - SanOpts.set(SanitizerKind::ID, false); - -#include "clang/Basic/Sanitizers.def" -#undef SANITIZER - } while (0); - - if (D) { - // Apply the no_sanitize* attributes to SanOpts. - for (auto Attr : D->specific_attrs<NoSanitizeAttr>()) { - SanitizerMask mask = Attr->getMask(); - SanOpts.Mask &= ~mask; - if (mask & SanitizerKind::Address) - SanOpts.set(SanitizerKind::KernelAddress, false); - if (mask & SanitizerKind::KernelAddress) - SanOpts.set(SanitizerKind::Address, false); - if (mask & SanitizerKind::HWAddress) - SanOpts.set(SanitizerKind::KernelHWAddress, false); - if (mask & SanitizerKind::KernelHWAddress) - SanOpts.set(SanitizerKind::HWAddress, false); - } - } - - // Apply sanitizer attributes to the function. - if (SanOpts.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress)) - Fn->addFnAttr(llvm::Attribute::SanitizeAddress); - if (SanOpts.hasOneOf(SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress)) - Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress); - if (SanOpts.has(SanitizerKind::Thread)) - Fn->addFnAttr(llvm::Attribute::SanitizeThread); - if (SanOpts.hasOneOf(SanitizerKind::Memory | SanitizerKind::KernelMemory)) - Fn->addFnAttr(llvm::Attribute::SanitizeMemory); - if (SanOpts.has(SanitizerKind::SafeStack)) - Fn->addFnAttr(llvm::Attribute::SafeStack); - if (SanOpts.has(SanitizerKind::ShadowCallStack)) - Fn->addFnAttr(llvm::Attribute::ShadowCallStack); - - // Apply fuzzing attribute to the function. - if (SanOpts.hasOneOf(SanitizerKind::Fuzzer | SanitizerKind::FuzzerNoLink)) - Fn->addFnAttr(llvm::Attribute::OptForFuzzing); - - // Ignore TSan memory acesses from within ObjC/ObjC++ dealloc, initialize, - // .cxx_destruct, __destroy_helper_block_ and all of their calees at run time. - if (SanOpts.has(SanitizerKind::Thread)) { - if (const auto *OMD = dyn_cast_or_null<ObjCMethodDecl>(D)) { - IdentifierInfo *II = OMD->getSelector().getIdentifierInfoForSlot(0); - if (OMD->getMethodFamily() == OMF_dealloc || - OMD->getMethodFamily() == OMF_initialize || - (OMD->getSelector().isUnarySelector() && II->isStr(".cxx_destruct"))) { - markAsIgnoreThreadCheckingAtRuntime(Fn); - } - } - } - - // Ignore unrelated casts in STL allocate() since the allocator must cast - // from void* to T* before object initialization completes. Don't match on the - // namespace because not all allocators are in std:: - if (D && SanOpts.has(SanitizerKind::CFIUnrelatedCast)) { - if (matchesStlAllocatorFn(D, getContext())) - SanOpts.Mask &= ~SanitizerKind::CFIUnrelatedCast; - } - - // Apply xray attributes to the function (as a string, for now) - if (D) { - if (const auto *XRayAttr = D->getAttr<XRayInstrumentAttr>()) { - if (CGM.getCodeGenOpts().XRayInstrumentationBundle.has( - XRayInstrKind::Function)) { - if (XRayAttr->alwaysXRayInstrument() && ShouldXRayInstrumentFunction()) - Fn->addFnAttr("function-instrument", "xray-always"); - if (XRayAttr->neverXRayInstrument()) - Fn->addFnAttr("function-instrument", "xray-never"); - if (const auto *LogArgs = D->getAttr<XRayLogArgsAttr>()) - if (ShouldXRayInstrumentFunction()) - Fn->addFnAttr("xray-log-args", - llvm::utostr(LogArgs->getArgumentCount())); - } - } else { - if (ShouldXRayInstrumentFunction() && !CGM.imbueXRayAttrs(Fn, Loc)) - Fn->addFnAttr( - "xray-instruction-threshold", - llvm::itostr(CGM.getCodeGenOpts().XRayInstructionThreshold)); - } - } - - // Add no-jump-tables value. - Fn->addFnAttr("no-jump-tables", - llvm::toStringRef(CGM.getCodeGenOpts().NoUseJumpTables)); - - // Add profile-sample-accurate value. - if (CGM.getCodeGenOpts().ProfileSampleAccurate) - Fn->addFnAttr("profile-sample-accurate"); - - if (getLangOpts().OpenCL) { - // Add metadata for a kernel function. - if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) - EmitOpenCLKernelMetadata(FD, Fn); - } - - // If we are checking function types, emit a function type signature as - // prologue data. - if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function)) { - if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) { - if (llvm::Constant *PrologueSig = getPrologueSignature(CGM, FD)) { - // Remove any (C++17) exception specifications, to allow calling e.g. a - // noexcept function through a non-noexcept pointer. - auto ProtoTy = - getContext().getFunctionTypeWithExceptionSpec(FD->getType(), - EST_None); - llvm::Constant *FTRTTIConst = - CGM.GetAddrOfRTTIDescriptor(ProtoTy, /*ForEH=*/true); - llvm::Constant *FTRTTIConstEncoded = - EncodeAddrForUseInPrologue(Fn, FTRTTIConst); - llvm::Constant *PrologueStructElems[] = {PrologueSig, - FTRTTIConstEncoded}; - llvm::Constant *PrologueStructConst = - llvm::ConstantStruct::getAnon(PrologueStructElems, /*Packed=*/true); - Fn->setPrologueData(PrologueStructConst); - } - } - } - - // If we're checking nullability, we need to know whether we can check the - // return value. Initialize the flag to 'true' and refine it in EmitParmDecl. - if (SanOpts.has(SanitizerKind::NullabilityReturn)) { - auto Nullability = FnRetTy->getNullability(getContext()); - if (Nullability && *Nullability == NullabilityKind::NonNull) { - if (!(SanOpts.has(SanitizerKind::ReturnsNonnullAttribute) && - CurCodeDecl && CurCodeDecl->getAttr<ReturnsNonNullAttr>())) - RetValNullabilityPrecondition = - llvm::ConstantInt::getTrue(getLLVMContext()); - } - } - - // If we're in C++ mode and the function name is "main", it is guaranteed - // to be norecurse by the standard (3.6.1.3 "The function main shall not be - // used within a program"). - if (getLangOpts().CPlusPlus) - if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) - if (FD->isMain()) - Fn->addFnAttr(llvm::Attribute::NoRecurse); - - // If a custom alignment is used, force realigning to this alignment on - // any main function which certainly will need it. - if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) - if ((FD->isMain() || FD->isMSVCRTEntryPoint()) && - CGM.getCodeGenOpts().StackAlignment) - Fn->addFnAttr("stackrealign"); - - llvm::BasicBlock *EntryBB = createBasicBlock("entry", CurFn); - - // Create a marker to make it easy to insert allocas into the entryblock - // later. Don't create this with the builder, because we don't want it - // folded. - llvm::Value *Undef = llvm::UndefValue::get(Int32Ty); - AllocaInsertPt = new llvm::BitCastInst(Undef, Int32Ty, "allocapt", EntryBB); - - ReturnBlock = getJumpDestInCurrentScope("return"); - - Builder.SetInsertPoint(EntryBB); - - // If we're checking the return value, allocate space for a pointer to a - // precise source location of the checked return statement. - if (requiresReturnValueCheck()) { - ReturnLocation = CreateDefaultAlignTempAlloca(Int8PtrTy, "return.sloc.ptr"); - InitTempAlloca(ReturnLocation, llvm::ConstantPointerNull::get(Int8PtrTy)); - } - - // Emit subprogram debug descriptor. - if (CGDebugInfo *DI = getDebugInfo()) { - // Reconstruct the type from the argument list so that implicit parameters, - // such as 'this' and 'vtt', show up in the debug info. Preserve the calling - // convention. - CallingConv CC = CallingConv::CC_C; - if (auto *FD = dyn_cast_or_null<FunctionDecl>(D)) - if (const auto *SrcFnTy = FD->getType()->getAs<FunctionType>()) - CC = SrcFnTy->getCallConv(); - SmallVector<QualType, 16> ArgTypes; - for (const VarDecl *VD : Args) - ArgTypes.push_back(VD->getType()); - QualType FnType = getContext().getFunctionType( - RetTy, ArgTypes, FunctionProtoType::ExtProtoInfo(CC)); - DI->EmitFunctionStart(GD, Loc, StartLoc, FnType, CurFn, CurFuncIsThunk, - Builder); - } - - if (ShouldInstrumentFunction()) { - if (CGM.getCodeGenOpts().InstrumentFunctions) - CurFn->addFnAttr("instrument-function-entry", "__cyg_profile_func_enter"); - if (CGM.getCodeGenOpts().InstrumentFunctionsAfterInlining) - CurFn->addFnAttr("instrument-function-entry-inlined", - "__cyg_profile_func_enter"); - if (CGM.getCodeGenOpts().InstrumentFunctionEntryBare) - CurFn->addFnAttr("instrument-function-entry-inlined", - "__cyg_profile_func_enter_bare"); - } - - // Since emitting the mcount call here impacts optimizations such as function - // inlining, we just add an attribute to insert a mcount call in backend. - // The attribute "counting-function" is set to mcount function name which is - // architecture dependent. - if (CGM.getCodeGenOpts().InstrumentForProfiling) { - // Calls to fentry/mcount should not be generated if function has - // the no_instrument_function attribute. - if (!CurFuncDecl || !CurFuncDecl->hasAttr<NoInstrumentFunctionAttr>()) { - if (CGM.getCodeGenOpts().CallFEntry) - Fn->addFnAttr("fentry-call", "true"); - else { - Fn->addFnAttr("instrument-function-entry-inlined", - getTarget().getMCountName()); - } - } - } - - if (RetTy->isVoidType()) { - // Void type; nothing to return. - ReturnValue = Address::invalid(); - - // Count the implicit return. - if (!endsWithReturn(D)) - ++NumReturnExprs; - } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect) { - // Indirect return; emit returned value directly into sret slot. - // This reduces code size, and affects correctness in C++. - auto AI = CurFn->arg_begin(); - if (CurFnInfo->getReturnInfo().isSRetAfterThis()) - ++AI; - ReturnValue = Address(&*AI, CurFnInfo->getReturnInfo().getIndirectAlign()); - } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::InAlloca && - !hasScalarEvaluationKind(CurFnInfo->getReturnType())) { - // Load the sret pointer from the argument struct and return into that. - unsigned Idx = CurFnInfo->getReturnInfo().getInAllocaFieldIndex(); - llvm::Function::arg_iterator EI = CurFn->arg_end(); - --EI; - llvm::Value *Addr = Builder.CreateStructGEP(nullptr, &*EI, Idx); - Addr = Builder.CreateAlignedLoad(Addr, getPointerAlign(), "agg.result"); - ReturnValue = Address(Addr, getNaturalTypeAlignment(RetTy)); - } else { - ReturnValue = CreateIRTemp(RetTy, "retval"); - - // Tell the epilog emitter to autorelease the result. We do this - // now so that various specialized functions can suppress it - // during their IR-generation. - if (getLangOpts().ObjCAutoRefCount && - !CurFnInfo->isReturnsRetained() && - RetTy->isObjCRetainableType()) - AutoreleaseResult = true; - } - - EmitStartEHSpec(CurCodeDecl); - - PrologueCleanupDepth = EHStack.stable_begin(); - - // Emit OpenMP specific initialization of the device functions. - if (getLangOpts().OpenMP && CurCodeDecl) - CGM.getOpenMPRuntime().emitFunctionProlog(*this, CurCodeDecl); - - EmitFunctionProlog(*CurFnInfo, CurFn, Args); - - if (D && isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance()) { - CGM.getCXXABI().EmitInstanceFunctionProlog(*this); - const CXXMethodDecl *MD = cast<CXXMethodDecl>(D); - if (MD->getParent()->isLambda() && - MD->getOverloadedOperator() == OO_Call) { - // We're in a lambda; figure out the captures. - MD->getParent()->getCaptureFields(LambdaCaptureFields, - LambdaThisCaptureField); - if (LambdaThisCaptureField) { - // If the lambda captures the object referred to by '*this' - either by - // value or by reference, make sure CXXThisValue points to the correct - // object. - - // Get the lvalue for the field (which is a copy of the enclosing object - // or contains the address of the enclosing object). - LValue ThisFieldLValue = EmitLValueForLambdaField(LambdaThisCaptureField); - if (!LambdaThisCaptureField->getType()->isPointerType()) { - // If the enclosing object was captured by value, just use its address. - CXXThisValue = ThisFieldLValue.getAddress().getPointer(); - } else { - // Load the lvalue pointed to by the field, since '*this' was captured - // by reference. - CXXThisValue = - EmitLoadOfLValue(ThisFieldLValue, SourceLocation()).getScalarVal(); - } - } - for (auto *FD : MD->getParent()->fields()) { - if (FD->hasCapturedVLAType()) { - auto *ExprArg = EmitLoadOfLValue(EmitLValueForLambdaField(FD), - SourceLocation()).getScalarVal(); - auto VAT = FD->getCapturedVLAType(); - VLASizeMap[VAT->getSizeExpr()] = ExprArg; - } - } - } else { - // Not in a lambda; just use 'this' from the method. - // FIXME: Should we generate a new load for each use of 'this'? The - // fast register allocator would be happier... - CXXThisValue = CXXABIThisValue; - } - - // Check the 'this' pointer once per function, if it's available. - if (CXXABIThisValue) { - SanitizerSet SkippedChecks; - SkippedChecks.set(SanitizerKind::ObjectSize, true); - QualType ThisTy = MD->getThisType(); - - // If this is the call operator of a lambda with no capture-default, it - // may have a static invoker function, which may call this operator with - // a null 'this' pointer. - if (isLambdaCallOperator(MD) && - MD->getParent()->getLambdaCaptureDefault() == LCD_None) - SkippedChecks.set(SanitizerKind::Null, true); - - EmitTypeCheck(isa<CXXConstructorDecl>(MD) ? TCK_ConstructorCall - : TCK_MemberCall, - Loc, CXXABIThisValue, ThisTy, - getContext().getTypeAlignInChars(ThisTy->getPointeeType()), - SkippedChecks); - } - } - - // If any of the arguments have a variably modified type, make sure to - // emit the type size. - for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); - i != e; ++i) { - const VarDecl *VD = *i; - - // Dig out the type as written from ParmVarDecls; it's unclear whether - // the standard (C99 6.9.1p10) requires this, but we're following the - // precedent set by gcc. - QualType Ty; - if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(VD)) - Ty = PVD->getOriginalType(); - else - Ty = VD->getType(); - - if (Ty->isVariablyModifiedType()) - EmitVariablyModifiedType(Ty); - } - // Emit a location at the end of the prologue. - if (CGDebugInfo *DI = getDebugInfo()) - DI->EmitLocation(Builder, StartLoc); - - // TODO: Do we need to handle this in two places like we do with - // target-features/target-cpu? - if (CurFuncDecl) - if (const auto *VecWidth = CurFuncDecl->getAttr<MinVectorWidthAttr>()) - LargestVectorWidth = VecWidth->getVectorWidth(); -} - -void CodeGenFunction::EmitFunctionBody(const Stmt *Body) { - incrementProfileCounter(Body); - if (const CompoundStmt *S = dyn_cast<CompoundStmt>(Body)) - EmitCompoundStmtWithoutScope(*S); - else - EmitStmt(Body); -} - -/// When instrumenting to collect profile data, the counts for some blocks -/// such as switch cases need to not include the fall-through counts, so -/// emit a branch around the instrumentation code. When not instrumenting, -/// this just calls EmitBlock(). -void CodeGenFunction::EmitBlockWithFallThrough(llvm::BasicBlock *BB, - const Stmt *S) { - llvm::BasicBlock *SkipCountBB = nullptr; - if (HaveInsertPoint() && CGM.getCodeGenOpts().hasProfileClangInstr()) { - // When instrumenting for profiling, the fallthrough to certain - // statements needs to skip over the instrumentation code so that we - // get an accurate count. - SkipCountBB = createBasicBlock("skipcount"); - EmitBranch(SkipCountBB); - } - EmitBlock(BB); - uint64_t CurrentCount = getCurrentProfileCount(); - incrementProfileCounter(S); - setCurrentProfileCount(getCurrentProfileCount() + CurrentCount); - if (SkipCountBB) - EmitBlock(SkipCountBB); -} - -/// Tries to mark the given function nounwind based on the -/// non-existence of any throwing calls within it. We believe this is -/// lightweight enough to do at -O0. -static void TryMarkNoThrow(llvm::Function *F) { - // LLVM treats 'nounwind' on a function as part of the type, so we - // can't do this on functions that can be overwritten. - if (F->isInterposable()) return; - - for (llvm::BasicBlock &BB : *F) - for (llvm::Instruction &I : BB) - if (I.mayThrow()) - return; - - F->setDoesNotThrow(); -} - -QualType CodeGenFunction::BuildFunctionArgList(GlobalDecl GD, - FunctionArgList &Args) { - const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); - QualType ResTy = FD->getReturnType(); - - const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); - if (MD && MD->isInstance()) { - if (CGM.getCXXABI().HasThisReturn(GD)) - ResTy = MD->getThisType(); - else if (CGM.getCXXABI().hasMostDerivedReturn(GD)) - ResTy = CGM.getContext().VoidPtrTy; - CGM.getCXXABI().buildThisParam(*this, Args); - } - - // The base version of an inheriting constructor whose constructed base is a - // virtual base is not passed any arguments (because it doesn't actually call - // the inherited constructor). - bool PassedParams = true; - if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) - if (auto Inherited = CD->getInheritedConstructor()) - PassedParams = - getTypes().inheritingCtorHasParams(Inherited, GD.getCtorType()); - - if (PassedParams) { - for (auto *Param : FD->parameters()) { - Args.push_back(Param); - if (!Param->hasAttr<PassObjectSizeAttr>()) - continue; - - auto *Implicit = ImplicitParamDecl::Create( - getContext(), Param->getDeclContext(), Param->getLocation(), - /*Id=*/nullptr, getContext().getSizeType(), ImplicitParamDecl::Other); - SizeArguments[Param] = Implicit; - Args.push_back(Implicit); - } - } - - if (MD && (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))) - CGM.getCXXABI().addImplicitStructorParams(*this, ResTy, Args); - - return ResTy; -} - -static bool -shouldUseUndefinedBehaviorReturnOptimization(const FunctionDecl *FD, - const ASTContext &Context) { - QualType T = FD->getReturnType(); - // Avoid the optimization for functions that return a record type with a - // trivial destructor or another trivially copyable type. - if (const RecordType *RT = T.getCanonicalType()->getAs<RecordType>()) { - if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) - return !ClassDecl->hasTrivialDestructor(); - } - return !T.isTriviallyCopyableType(Context); -} - -void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, - const CGFunctionInfo &FnInfo) { - const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); - CurGD = GD; - - FunctionArgList Args; - QualType ResTy = BuildFunctionArgList(GD, Args); - - // Check if we should generate debug info for this function. - if (FD->hasAttr<NoDebugAttr>()) - DebugInfo = nullptr; // disable debug info indefinitely for this function - - // The function might not have a body if we're generating thunks for a - // function declaration. - SourceRange BodyRange; - if (Stmt *Body = FD->getBody()) - BodyRange = Body->getSourceRange(); - else - BodyRange = FD->getLocation(); - CurEHLocation = BodyRange.getEnd(); - - // Use the location of the start of the function to determine where - // the function definition is located. By default use the location - // of the declaration as the location for the subprogram. A function - // may lack a declaration in the source code if it is created by code - // gen. (examples: _GLOBAL__I_a, __cxx_global_array_dtor, thunk). - SourceLocation Loc = FD->getLocation(); - - // If this is a function specialization then use the pattern body - // as the location for the function. - if (const FunctionDecl *SpecDecl = FD->getTemplateInstantiationPattern()) - if (SpecDecl->hasBody(SpecDecl)) - Loc = SpecDecl->getLocation(); - - Stmt *Body = FD->getBody(); - - // Initialize helper which will detect jumps which can cause invalid lifetime - // markers. - if (Body && ShouldEmitLifetimeMarkers) - Bypasses.Init(Body); - - // Emit the standard function prologue. - StartFunction(GD, ResTy, Fn, FnInfo, Args, Loc, BodyRange.getBegin()); - - // Generate the body of the function. - PGO.assignRegionCounters(GD, CurFn); - if (isa<CXXDestructorDecl>(FD)) - EmitDestructorBody(Args); - else if (isa<CXXConstructorDecl>(FD)) - EmitConstructorBody(Args); - else if (getLangOpts().CUDA && - !getLangOpts().CUDAIsDevice && - FD->hasAttr<CUDAGlobalAttr>()) - CGM.getCUDARuntime().emitDeviceStub(*this, Args); - else if (isa<CXXMethodDecl>(FD) && - cast<CXXMethodDecl>(FD)->isLambdaStaticInvoker()) { - // The lambda static invoker function is special, because it forwards or - // clones the body of the function call operator (but is actually static). - EmitLambdaStaticInvokeBody(cast<CXXMethodDecl>(FD)); - } else if (FD->isDefaulted() && isa<CXXMethodDecl>(FD) && - (cast<CXXMethodDecl>(FD)->isCopyAssignmentOperator() || - cast<CXXMethodDecl>(FD)->isMoveAssignmentOperator())) { - // Implicit copy-assignment gets the same special treatment as implicit - // copy-constructors. - emitImplicitAssignmentOperatorBody(Args); - } else if (Body) { - EmitFunctionBody(Body); - } else - llvm_unreachable("no definition for emitted function"); - - // C++11 [stmt.return]p2: - // Flowing off the end of a function [...] results in undefined behavior in - // a value-returning function. - // C11 6.9.1p12: - // If the '}' that terminates a function is reached, and the value of the - // function call is used by the caller, the behavior is undefined. - if (getLangOpts().CPlusPlus && !FD->hasImplicitReturnZero() && !SawAsmBlock && - !FD->getReturnType()->isVoidType() && Builder.GetInsertBlock()) { - bool ShouldEmitUnreachable = - CGM.getCodeGenOpts().StrictReturn || - shouldUseUndefinedBehaviorReturnOptimization(FD, getContext()); - if (SanOpts.has(SanitizerKind::Return)) { - SanitizerScope SanScope(this); - llvm::Value *IsFalse = Builder.getFalse(); - EmitCheck(std::make_pair(IsFalse, SanitizerKind::Return), - SanitizerHandler::MissingReturn, - EmitCheckSourceLocation(FD->getLocation()), None); - } else if (ShouldEmitUnreachable) { - if (CGM.getCodeGenOpts().OptimizationLevel == 0) - EmitTrapCall(llvm::Intrinsic::trap); - } - if (SanOpts.has(SanitizerKind::Return) || ShouldEmitUnreachable) { - Builder.CreateUnreachable(); - Builder.ClearInsertionPoint(); - } - } - - // Emit the standard function epilogue. - FinishFunction(BodyRange.getEnd()); - - // If we haven't marked the function nothrow through other means, do - // a quick pass now to see if we can. - if (!CurFn->doesNotThrow()) - TryMarkNoThrow(CurFn); -} - -/// ContainsLabel - Return true if the statement contains a label in it. If -/// this statement is not executed normally, it not containing a label means -/// that we can just remove the code. -bool CodeGenFunction::ContainsLabel(const Stmt *S, bool IgnoreCaseStmts) { - // Null statement, not a label! - if (!S) return false; - - // If this is a label, we have to emit the code, consider something like: - // if (0) { ... foo: bar(); } goto foo; - // - // TODO: If anyone cared, we could track __label__'s, since we know that you - // can't jump to one from outside their declared region. - if (isa<LabelStmt>(S)) - return true; - - // If this is a case/default statement, and we haven't seen a switch, we have - // to emit the code. - if (isa<SwitchCase>(S) && !IgnoreCaseStmts) - return true; - - // If this is a switch statement, we want to ignore cases below it. - if (isa<SwitchStmt>(S)) - IgnoreCaseStmts = true; - - // Scan subexpressions for verboten labels. - for (const Stmt *SubStmt : S->children()) - if (ContainsLabel(SubStmt, IgnoreCaseStmts)) - return true; - - return false; -} - -/// containsBreak - Return true if the statement contains a break out of it. -/// If the statement (recursively) contains a switch or loop with a break -/// inside of it, this is fine. -bool CodeGenFunction::containsBreak(const Stmt *S) { - // Null statement, not a label! - if (!S) return false; - - // If this is a switch or loop that defines its own break scope, then we can - // include it and anything inside of it. - if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || isa<DoStmt>(S) || - isa<ForStmt>(S)) - return false; - - if (isa<BreakStmt>(S)) - return true; - - // Scan subexpressions for verboten breaks. - for (const Stmt *SubStmt : S->children()) - if (containsBreak(SubStmt)) - return true; - - return false; -} - -bool CodeGenFunction::mightAddDeclToScope(const Stmt *S) { - if (!S) return false; - - // Some statement kinds add a scope and thus never add a decl to the current - // scope. Note, this list is longer than the list of statements that might - // have an unscoped decl nested within them, but this way is conservatively - // correct even if more statement kinds are added. - if (isa<IfStmt>(S) || isa<SwitchStmt>(S) || isa<WhileStmt>(S) || - isa<DoStmt>(S) || isa<ForStmt>(S) || isa<CompoundStmt>(S) || - isa<CXXForRangeStmt>(S) || isa<CXXTryStmt>(S) || - isa<ObjCForCollectionStmt>(S) || isa<ObjCAtTryStmt>(S)) - return false; - - if (isa<DeclStmt>(S)) - return true; - - for (const Stmt *SubStmt : S->children()) - if (mightAddDeclToScope(SubStmt)) - return true; - - return false; -} - -/// ConstantFoldsToSimpleInteger - If the specified expression does not fold -/// to a constant, or if it does but contains a label, return false. If it -/// constant folds return true and set the boolean result in Result. -bool CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond, - bool &ResultBool, - bool AllowLabels) { - llvm::APSInt ResultInt; - if (!ConstantFoldsToSimpleInteger(Cond, ResultInt, AllowLabels)) - return false; - - ResultBool = ResultInt.getBoolValue(); - return true; -} - -/// ConstantFoldsToSimpleInteger - If the specified expression does not fold -/// to a constant, or if it does but contains a label, return false. If it -/// constant folds return true and set the folded value. -bool CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond, - llvm::APSInt &ResultInt, - bool AllowLabels) { - // FIXME: Rename and handle conversion of other evaluatable things - // to bool. - Expr::EvalResult Result; - if (!Cond->EvaluateAsInt(Result, getContext())) - return false; // Not foldable, not integer or not fully evaluatable. - - llvm::APSInt Int = Result.Val.getInt(); - if (!AllowLabels && CodeGenFunction::ContainsLabel(Cond)) - return false; // Contains a label. - - ResultInt = Int; - return true; -} - - - -/// EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g. for an if -/// statement) to the specified blocks. Based on the condition, this might try -/// to simplify the codegen of the conditional based on the branch. -/// -void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond, - llvm::BasicBlock *TrueBlock, - llvm::BasicBlock *FalseBlock, - uint64_t TrueCount) { - Cond = Cond->IgnoreParens(); - - if (const BinaryOperator *CondBOp = dyn_cast<BinaryOperator>(Cond)) { - - // Handle X && Y in a condition. - if (CondBOp->getOpcode() == BO_LAnd) { - // If we have "1 && X", simplify the code. "0 && X" would have constant - // folded if the case was simple enough. - bool ConstantBool = false; - if (ConstantFoldsToSimpleInteger(CondBOp->getLHS(), ConstantBool) && - ConstantBool) { - // br(1 && X) -> br(X). - incrementProfileCounter(CondBOp); - return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, - TrueCount); - } - - // If we have "X && 1", simplify the code to use an uncond branch. - // "X && 0" would have been constant folded to 0. - if (ConstantFoldsToSimpleInteger(CondBOp->getRHS(), ConstantBool) && - ConstantBool) { - // br(X && 1) -> br(X). - return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock, - TrueCount); - } - - // Emit the LHS as a conditional. If the LHS conditional is false, we - // want to jump to the FalseBlock. - llvm::BasicBlock *LHSTrue = createBasicBlock("land.lhs.true"); - // The counter tells us how often we evaluate RHS, and all of TrueCount - // can be propagated to that branch. - uint64_t RHSCount = getProfileCount(CondBOp->getRHS()); - - ConditionalEvaluation eval(*this); - { - ApplyDebugLocation DL(*this, Cond); - EmitBranchOnBoolExpr(CondBOp->getLHS(), LHSTrue, FalseBlock, RHSCount); - EmitBlock(LHSTrue); - } - - incrementProfileCounter(CondBOp); - setCurrentProfileCount(getProfileCount(CondBOp->getRHS())); - - // Any temporaries created here are conditional. - eval.begin(*this); - EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, TrueCount); - eval.end(*this); - - return; - } - - if (CondBOp->getOpcode() == BO_LOr) { - // If we have "0 || X", simplify the code. "1 || X" would have constant - // folded if the case was simple enough. - bool ConstantBool = false; - if (ConstantFoldsToSimpleInteger(CondBOp->getLHS(), ConstantBool) && - !ConstantBool) { - // br(0 || X) -> br(X). - incrementProfileCounter(CondBOp); - return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, - TrueCount); - } - - // If we have "X || 0", simplify the code to use an uncond branch. - // "X || 1" would have been constant folded to 1. - if (ConstantFoldsToSimpleInteger(CondBOp->getRHS(), ConstantBool) && - !ConstantBool) { - // br(X || 0) -> br(X). - return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock, - TrueCount); - } - - // Emit the LHS as a conditional. If the LHS conditional is true, we - // want to jump to the TrueBlock. - llvm::BasicBlock *LHSFalse = createBasicBlock("lor.lhs.false"); - // We have the count for entry to the RHS and for the whole expression - // being true, so we can divy up True count between the short circuit and - // the RHS. - uint64_t LHSCount = - getCurrentProfileCount() - getProfileCount(CondBOp->getRHS()); - uint64_t RHSCount = TrueCount - LHSCount; - - ConditionalEvaluation eval(*this); - { - ApplyDebugLocation DL(*this, Cond); - EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, LHSFalse, LHSCount); - EmitBlock(LHSFalse); - } - - incrementProfileCounter(CondBOp); - setCurrentProfileCount(getProfileCount(CondBOp->getRHS())); - - // Any temporaries created here are conditional. - eval.begin(*this); - EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, RHSCount); - - eval.end(*this); - - return; - } - } - - if (const UnaryOperator *CondUOp = dyn_cast<UnaryOperator>(Cond)) { - // br(!x, t, f) -> br(x, f, t) - if (CondUOp->getOpcode() == UO_LNot) { - // Negate the count. - uint64_t FalseCount = getCurrentProfileCount() - TrueCount; - // Negate the condition and swap the destination blocks. - return EmitBranchOnBoolExpr(CondUOp->getSubExpr(), FalseBlock, TrueBlock, - FalseCount); - } - } - - if (const ConditionalOperator *CondOp = dyn_cast<ConditionalOperator>(Cond)) { - // br(c ? x : y, t, f) -> br(c, br(x, t, f), br(y, t, f)) - llvm::BasicBlock *LHSBlock = createBasicBlock("cond.true"); - llvm::BasicBlock *RHSBlock = createBasicBlock("cond.false"); - - ConditionalEvaluation cond(*this); - EmitBranchOnBoolExpr(CondOp->getCond(), LHSBlock, RHSBlock, - getProfileCount(CondOp)); - - // When computing PGO branch weights, we only know the overall count for - // the true block. This code is essentially doing tail duplication of the - // naive code-gen, introducing new edges for which counts are not - // available. Divide the counts proportionally between the LHS and RHS of - // the conditional operator. - uint64_t LHSScaledTrueCount = 0; - if (TrueCount) { - double LHSRatio = - getProfileCount(CondOp) / (double)getCurrentProfileCount(); - LHSScaledTrueCount = TrueCount * LHSRatio; - } - - cond.begin(*this); - EmitBlock(LHSBlock); - incrementProfileCounter(CondOp); - { - ApplyDebugLocation DL(*this, Cond); - EmitBranchOnBoolExpr(CondOp->getLHS(), TrueBlock, FalseBlock, - LHSScaledTrueCount); - } - cond.end(*this); - - cond.begin(*this); - EmitBlock(RHSBlock); - EmitBranchOnBoolExpr(CondOp->getRHS(), TrueBlock, FalseBlock, - TrueCount - LHSScaledTrueCount); - cond.end(*this); - - return; - } - - if (const CXXThrowExpr *Throw = dyn_cast<CXXThrowExpr>(Cond)) { - // Conditional operator handling can give us a throw expression as a - // condition for a case like: - // br(c ? throw x : y, t, f) -> br(c, br(throw x, t, f), br(y, t, f) - // Fold this to: - // br(c, throw x, br(y, t, f)) - EmitCXXThrowExpr(Throw, /*KeepInsertionPoint*/false); - return; - } - - // If the branch has a condition wrapped by __builtin_unpredictable, - // create metadata that specifies that the branch is unpredictable. - // Don't bother if not optimizing because that metadata would not be used. - llvm::MDNode *Unpredictable = nullptr; - auto *Call = dyn_cast<CallExpr>(Cond->IgnoreImpCasts()); - if (Call && CGM.getCodeGenOpts().OptimizationLevel != 0) { - auto *FD = dyn_cast_or_null<FunctionDecl>(Call->getCalleeDecl()); - if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) { - llvm::MDBuilder MDHelper(getLLVMContext()); - Unpredictable = MDHelper.createUnpredictable(); - } - } - - // Create branch weights based on the number of times we get here and the - // number of times the condition should be true. - uint64_t CurrentCount = std::max(getCurrentProfileCount(), TrueCount); - llvm::MDNode *Weights = - createProfileWeights(TrueCount, CurrentCount - TrueCount); - - // Emit the code with the fully general case. - llvm::Value *CondV; - { - ApplyDebugLocation DL(*this, Cond); - CondV = EvaluateExprAsBool(Cond); - } - Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights, Unpredictable); -} - -/// ErrorUnsupported - Print out an error that codegen doesn't support the -/// specified stmt yet. -void CodeGenFunction::ErrorUnsupported(const Stmt *S, const char *Type) { - CGM.ErrorUnsupported(S, Type); -} - -/// emitNonZeroVLAInit - Emit the "zero" initialization of a -/// variable-length array whose elements have a non-zero bit-pattern. -/// -/// \param baseType the inner-most element type of the array -/// \param src - a char* pointing to the bit-pattern for a single -/// base element of the array -/// \param sizeInChars - the total size of the VLA, in chars -static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType, - Address dest, Address src, - llvm::Value *sizeInChars) { - CGBuilderTy &Builder = CGF.Builder; - - CharUnits baseSize = CGF.getContext().getTypeSizeInChars(baseType); - llvm::Value *baseSizeInChars - = llvm::ConstantInt::get(CGF.IntPtrTy, baseSize.getQuantity()); - - Address begin = - Builder.CreateElementBitCast(dest, CGF.Int8Ty, "vla.begin"); - llvm::Value *end = - Builder.CreateInBoundsGEP(begin.getPointer(), sizeInChars, "vla.end"); - - llvm::BasicBlock *originBB = CGF.Builder.GetInsertBlock(); - llvm::BasicBlock *loopBB = CGF.createBasicBlock("vla-init.loop"); - llvm::BasicBlock *contBB = CGF.createBasicBlock("vla-init.cont"); - - // Make a loop over the VLA. C99 guarantees that the VLA element - // count must be nonzero. - CGF.EmitBlock(loopBB); - - llvm::PHINode *cur = Builder.CreatePHI(begin.getType(), 2, "vla.cur"); - cur->addIncoming(begin.getPointer(), originBB); - - CharUnits curAlign = - dest.getAlignment().alignmentOfArrayElement(baseSize); - - // memcpy the individual element bit-pattern. - Builder.CreateMemCpy(Address(cur, curAlign), src, baseSizeInChars, - /*volatile*/ false); - - // Go to the next element. - llvm::Value *next = - Builder.CreateInBoundsGEP(CGF.Int8Ty, cur, baseSizeInChars, "vla.next"); - - // Leave if that's the end of the VLA. - llvm::Value *done = Builder.CreateICmpEQ(next, end, "vla-init.isdone"); - Builder.CreateCondBr(done, contBB, loopBB); - cur->addIncoming(next, loopBB); - - CGF.EmitBlock(contBB); -} - -void -CodeGenFunction::EmitNullInitialization(Address DestPtr, QualType Ty) { - // Ignore empty classes in C++. - if (getLangOpts().CPlusPlus) { - if (const RecordType *RT = Ty->getAs<RecordType>()) { - if (cast<CXXRecordDecl>(RT->getDecl())->isEmpty()) - return; - } - } - - // Cast the dest ptr to the appropriate i8 pointer type. - if (DestPtr.getElementType() != Int8Ty) - DestPtr = Builder.CreateElementBitCast(DestPtr, Int8Ty); - - // Get size and alignment info for this aggregate. - CharUnits size = getContext().getTypeSizeInChars(Ty); - - llvm::Value *SizeVal; - const VariableArrayType *vla; - - // Don't bother emitting a zero-byte memset. - if (size.isZero()) { - // But note that getTypeInfo returns 0 for a VLA. - if (const VariableArrayType *vlaType = - dyn_cast_or_null<VariableArrayType>( - getContext().getAsArrayType(Ty))) { - auto VlaSize = getVLASize(vlaType); - SizeVal = VlaSize.NumElts; - CharUnits eltSize = getContext().getTypeSizeInChars(VlaSize.Type); - if (!eltSize.isOne()) - SizeVal = Builder.CreateNUWMul(SizeVal, CGM.getSize(eltSize)); - vla = vlaType; - } else { - return; - } - } else { - SizeVal = CGM.getSize(size); - vla = nullptr; - } - - // If the type contains a pointer to data member we can't memset it to zero. - // Instead, create a null constant and copy it to the destination. - // TODO: there are other patterns besides zero that we can usefully memset, - // like -1, which happens to be the pattern used by member-pointers. - if (!CGM.getTypes().isZeroInitializable(Ty)) { - // For a VLA, emit a single element, then splat that over the VLA. - if (vla) Ty = getContext().getBaseElementType(vla); - - llvm::Constant *NullConstant = CGM.EmitNullConstant(Ty); - - llvm::GlobalVariable *NullVariable = - new llvm::GlobalVariable(CGM.getModule(), NullConstant->getType(), - /*isConstant=*/true, - llvm::GlobalVariable::PrivateLinkage, - NullConstant, Twine()); - CharUnits NullAlign = DestPtr.getAlignment(); - NullVariable->setAlignment(NullAlign.getQuantity()); - Address SrcPtr(Builder.CreateBitCast(NullVariable, Builder.getInt8PtrTy()), - NullAlign); - - if (vla) return emitNonZeroVLAInit(*this, Ty, DestPtr, SrcPtr, SizeVal); - - // Get and call the appropriate llvm.memcpy overload. - Builder.CreateMemCpy(DestPtr, SrcPtr, SizeVal, false); - return; - } - - // Otherwise, just memset the whole thing to zero. This is legal - // because in LLVM, all default initializers (other than the ones we just - // handled above) are guaranteed to have a bit pattern of all zeros. - Builder.CreateMemSet(DestPtr, Builder.getInt8(0), SizeVal, false); -} - -llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelDecl *L) { - // Make sure that there is a block for the indirect goto. - if (!IndirectBranch) - GetIndirectGotoBlock(); - - llvm::BasicBlock *BB = getJumpDestForLabel(L).getBlock(); - - // Make sure the indirect branch includes all of the address-taken blocks. - IndirectBranch->addDestination(BB); - return llvm::BlockAddress::get(CurFn, BB); -} - -llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() { - // If we already made the indirect branch for indirect goto, return its block. - if (IndirectBranch) return IndirectBranch->getParent(); - - CGBuilderTy TmpBuilder(*this, createBasicBlock("indirectgoto")); - - // Create the PHI node that indirect gotos will add entries to. - llvm::Value *DestVal = TmpBuilder.CreatePHI(Int8PtrTy, 0, - "indirect.goto.dest"); - - // Create the indirect branch instruction. - IndirectBranch = TmpBuilder.CreateIndirectBr(DestVal); - return IndirectBranch->getParent(); -} - -/// Computes the length of an array in elements, as well as the base -/// element type and a properly-typed first element pointer. -llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType, - QualType &baseType, - Address &addr) { - const ArrayType *arrayType = origArrayType; - - // If it's a VLA, we have to load the stored size. Note that - // this is the size of the VLA in bytes, not its size in elements. - llvm::Value *numVLAElements = nullptr; - if (isa<VariableArrayType>(arrayType)) { - numVLAElements = getVLASize(cast<VariableArrayType>(arrayType)).NumElts; - - // Walk into all VLAs. This doesn't require changes to addr, - // which has type T* where T is the first non-VLA element type. - do { - QualType elementType = arrayType->getElementType(); - arrayType = getContext().getAsArrayType(elementType); - - // If we only have VLA components, 'addr' requires no adjustment. - if (!arrayType) { - baseType = elementType; - return numVLAElements; - } - } while (isa<VariableArrayType>(arrayType)); - - // We get out here only if we find a constant array type - // inside the VLA. - } - - // We have some number of constant-length arrays, so addr should - // have LLVM type [M x [N x [...]]]*. Build a GEP that walks - // down to the first element of addr. - SmallVector<llvm::Value*, 8> gepIndices; - - // GEP down to the array type. - llvm::ConstantInt *zero = Builder.getInt32(0); - gepIndices.push_back(zero); - - uint64_t countFromCLAs = 1; - QualType eltType; - - llvm::ArrayType *llvmArrayType = - dyn_cast<llvm::ArrayType>(addr.getElementType()); - while (llvmArrayType) { - assert(isa<ConstantArrayType>(arrayType)); - assert(cast<ConstantArrayType>(arrayType)->getSize().getZExtValue() - == llvmArrayType->getNumElements()); - - gepIndices.push_back(zero); - countFromCLAs *= llvmArrayType->getNumElements(); - eltType = arrayType->getElementType(); - - llvmArrayType = - dyn_cast<llvm::ArrayType>(llvmArrayType->getElementType()); - arrayType = getContext().getAsArrayType(arrayType->getElementType()); - assert((!llvmArrayType || arrayType) && - "LLVM and Clang types are out-of-synch"); - } - - if (arrayType) { - // From this point onwards, the Clang array type has been emitted - // as some other type (probably a packed struct). Compute the array - // size, and just emit the 'begin' expression as a bitcast. - while (arrayType) { - countFromCLAs *= - cast<ConstantArrayType>(arrayType)->getSize().getZExtValue(); - eltType = arrayType->getElementType(); - arrayType = getContext().getAsArrayType(eltType); - } - - llvm::Type *baseType = ConvertType(eltType); - addr = Builder.CreateElementBitCast(addr, baseType, "array.begin"); - } else { - // Create the actual GEP. - addr = Address(Builder.CreateInBoundsGEP(addr.getPointer(), - gepIndices, "array.begin"), - addr.getAlignment()); - } - - baseType = eltType; - - llvm::Value *numElements - = llvm::ConstantInt::get(SizeTy, countFromCLAs); - - // If we had any VLA dimensions, factor them in. - if (numVLAElements) - numElements = Builder.CreateNUWMul(numVLAElements, numElements); - - return numElements; -} - -CodeGenFunction::VlaSizePair CodeGenFunction::getVLASize(QualType type) { - const VariableArrayType *vla = getContext().getAsVariableArrayType(type); - assert(vla && "type was not a variable array type!"); - return getVLASize(vla); -} - -CodeGenFunction::VlaSizePair -CodeGenFunction::getVLASize(const VariableArrayType *type) { - // The number of elements so far; always size_t. - llvm::Value *numElements = nullptr; - - QualType elementType; - do { - elementType = type->getElementType(); - llvm::Value *vlaSize = VLASizeMap[type->getSizeExpr()]; - assert(vlaSize && "no size for VLA!"); - assert(vlaSize->getType() == SizeTy); - - if (!numElements) { - numElements = vlaSize; - } else { - // It's undefined behavior if this wraps around, so mark it that way. - // FIXME: Teach -fsanitize=undefined to trap this. - numElements = Builder.CreateNUWMul(numElements, vlaSize); - } - } while ((type = getContext().getAsVariableArrayType(elementType))); - - return { numElements, elementType }; -} - -CodeGenFunction::VlaSizePair -CodeGenFunction::getVLAElements1D(QualType type) { - const VariableArrayType *vla = getContext().getAsVariableArrayType(type); - assert(vla && "type was not a variable array type!"); - return getVLAElements1D(vla); -} - -CodeGenFunction::VlaSizePair -CodeGenFunction::getVLAElements1D(const VariableArrayType *Vla) { - llvm::Value *VlaSize = VLASizeMap[Vla->getSizeExpr()]; - assert(VlaSize && "no size for VLA!"); - assert(VlaSize->getType() == SizeTy); - return { VlaSize, Vla->getElementType() }; -} - -void CodeGenFunction::EmitVariablyModifiedType(QualType type) { - assert(type->isVariablyModifiedType() && - "Must pass variably modified type to EmitVLASizes!"); - - EnsureInsertPoint(); - - // We're going to walk down into the type and look for VLA - // expressions. - do { - assert(type->isVariablyModifiedType()); - - const Type *ty = type.getTypePtr(); - switch (ty->getTypeClass()) { - -#define TYPE(Class, Base) -#define ABSTRACT_TYPE(Class, Base) -#define NON_CANONICAL_TYPE(Class, Base) -#define DEPENDENT_TYPE(Class, Base) case Type::Class: -#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) -#include "clang/AST/TypeNodes.def" - llvm_unreachable("unexpected dependent type!"); - - // These types are never variably-modified. - case Type::Builtin: - case Type::Complex: - case Type::Vector: - case Type::ExtVector: - case Type::Record: - case Type::Enum: - case Type::Elaborated: - case Type::TemplateSpecialization: - case Type::ObjCTypeParam: - case Type::ObjCObject: - case Type::ObjCInterface: - case Type::ObjCObjectPointer: - llvm_unreachable("type class is never variably-modified!"); - - case Type::Adjusted: - type = cast<AdjustedType>(ty)->getAdjustedType(); - break; - - case Type::Decayed: - type = cast<DecayedType>(ty)->getPointeeType(); - break; - - case Type::Pointer: - type = cast<PointerType>(ty)->getPointeeType(); - break; - - case Type::BlockPointer: - type = cast<BlockPointerType>(ty)->getPointeeType(); - break; - - case Type::LValueReference: - case Type::RValueReference: - type = cast<ReferenceType>(ty)->getPointeeType(); - break; - - case Type::MemberPointer: - type = cast<MemberPointerType>(ty)->getPointeeType(); - break; - - case Type::ConstantArray: - case Type::IncompleteArray: - // Losing element qualification here is fine. - type = cast<ArrayType>(ty)->getElementType(); - break; - - case Type::VariableArray: { - // Losing element qualification here is fine. - const VariableArrayType *vat = cast<VariableArrayType>(ty); - - // Unknown size indication requires no size computation. - // Otherwise, evaluate and record it. - if (const Expr *size = vat->getSizeExpr()) { - // It's possible that we might have emitted this already, - // e.g. with a typedef and a pointer to it. - llvm::Value *&entry = VLASizeMap[size]; - if (!entry) { - llvm::Value *Size = EmitScalarExpr(size); - - // C11 6.7.6.2p5: - // If the size is an expression that is not an integer constant - // expression [...] each time it is evaluated it shall have a value - // greater than zero. - if (SanOpts.has(SanitizerKind::VLABound) && - size->getType()->isSignedIntegerType()) { - SanitizerScope SanScope(this); - llvm::Value *Zero = llvm::Constant::getNullValue(Size->getType()); - llvm::Constant *StaticArgs[] = { - EmitCheckSourceLocation(size->getBeginLoc()), - EmitCheckTypeDescriptor(size->getType())}; - EmitCheck(std::make_pair(Builder.CreateICmpSGT(Size, Zero), - SanitizerKind::VLABound), - SanitizerHandler::VLABoundNotPositive, StaticArgs, Size); - } - - // Always zexting here would be wrong if it weren't - // undefined behavior to have a negative bound. - entry = Builder.CreateIntCast(Size, SizeTy, /*signed*/ false); - } - } - type = vat->getElementType(); - break; - } - - case Type::FunctionProto: - case Type::FunctionNoProto: - type = cast<FunctionType>(ty)->getReturnType(); - break; - - case Type::Paren: - case Type::TypeOf: - case Type::UnaryTransform: - case Type::Attributed: - case Type::SubstTemplateTypeParm: - case Type::PackExpansion: - // Keep walking after single level desugaring. - type = type.getSingleStepDesugaredType(getContext()); - break; - - case Type::Typedef: - case Type::Decltype: - case Type::Auto: - case Type::DeducedTemplateSpecialization: - // Stop walking: nothing to do. - return; - - case Type::TypeOfExpr: - // Stop walking: emit typeof expression. - EmitIgnoredExpr(cast<TypeOfExprType>(ty)->getUnderlyingExpr()); - return; - - case Type::Atomic: - type = cast<AtomicType>(ty)->getValueType(); - break; - - case Type::Pipe: - type = cast<PipeType>(ty)->getElementType(); - break; - } - } while (type->isVariablyModifiedType()); -} - -Address CodeGenFunction::EmitVAListRef(const Expr* E) { - if (getContext().getBuiltinVaListType()->isArrayType()) - return EmitPointerWithAlignment(E); - return EmitLValue(E).getAddress(); -} - -Address CodeGenFunction::EmitMSVAListRef(const Expr *E) { - return EmitLValue(E).getAddress(); -} - -void CodeGenFunction::EmitDeclRefExprDbgValue(const DeclRefExpr *E, - const APValue &Init) { - assert(!Init.isUninit() && "Invalid DeclRefExpr initializer!"); - if (CGDebugInfo *Dbg = getDebugInfo()) - if (CGM.getCodeGenOpts().getDebugInfo() >= codegenoptions::LimitedDebugInfo) - Dbg->EmitGlobalVariable(E->getDecl(), Init); -} - -CodeGenFunction::PeepholeProtection -CodeGenFunction::protectFromPeepholes(RValue rvalue) { - // At the moment, the only aggressive peephole we do in IR gen - // is trunc(zext) folding, but if we add more, we can easily - // extend this protection. - - if (!rvalue.isScalar()) return PeepholeProtection(); - llvm::Value *value = rvalue.getScalarVal(); - if (!isa<llvm::ZExtInst>(value)) return PeepholeProtection(); - - // Just make an extra bitcast. - assert(HaveInsertPoint()); - llvm::Instruction *inst = new llvm::BitCastInst(value, value->getType(), "", - Builder.GetInsertBlock()); - - PeepholeProtection protection; - protection.Inst = inst; - return protection; -} - -void CodeGenFunction::unprotectFromPeepholes(PeepholeProtection protection) { - if (!protection.Inst) return; - - // In theory, we could try to duplicate the peepholes now, but whatever. - protection.Inst->eraseFromParent(); -} - -void CodeGenFunction::EmitAlignmentAssumption(llvm::Value *PtrValue, - QualType Ty, SourceLocation Loc, - SourceLocation AssumptionLoc, - llvm::Value *Alignment, - llvm::Value *OffsetValue) { - llvm::Value *TheCheck; - llvm::Instruction *Assumption = Builder.CreateAlignmentAssumption( - CGM.getDataLayout(), PtrValue, Alignment, OffsetValue, &TheCheck); - if (SanOpts.has(SanitizerKind::Alignment)) { - EmitAlignmentAssumptionCheck(PtrValue, Ty, Loc, AssumptionLoc, Alignment, - OffsetValue, TheCheck, Assumption); - } -} - -void CodeGenFunction::EmitAlignmentAssumption(llvm::Value *PtrValue, - QualType Ty, SourceLocation Loc, - SourceLocation AssumptionLoc, - unsigned Alignment, - llvm::Value *OffsetValue) { - llvm::Value *TheCheck; - llvm::Instruction *Assumption = Builder.CreateAlignmentAssumption( - CGM.getDataLayout(), PtrValue, Alignment, OffsetValue, &TheCheck); - if (SanOpts.has(SanitizerKind::Alignment)) { - llvm::Value *AlignmentVal = llvm::ConstantInt::get(IntPtrTy, Alignment); - EmitAlignmentAssumptionCheck(PtrValue, Ty, Loc, AssumptionLoc, AlignmentVal, - OffsetValue, TheCheck, Assumption); - } -} - -void CodeGenFunction::EmitAlignmentAssumption(llvm::Value *PtrValue, - const Expr *E, - SourceLocation AssumptionLoc, - unsigned Alignment, - llvm::Value *OffsetValue) { - if (auto *CE = dyn_cast<CastExpr>(E)) - E = CE->getSubExprAsWritten(); - QualType Ty = E->getType(); - SourceLocation Loc = E->getExprLoc(); - - EmitAlignmentAssumption(PtrValue, Ty, Loc, AssumptionLoc, Alignment, - OffsetValue); -} - -llvm::Value *CodeGenFunction::EmitAnnotationCall(llvm::Value *AnnotationFn, - llvm::Value *AnnotatedVal, - StringRef AnnotationStr, - SourceLocation Location) { - llvm::Value *Args[4] = { - AnnotatedVal, - Builder.CreateBitCast(CGM.EmitAnnotationString(AnnotationStr), Int8PtrTy), - Builder.CreateBitCast(CGM.EmitAnnotationUnit(Location), Int8PtrTy), - CGM.EmitAnnotationLineNo(Location) - }; - return Builder.CreateCall(AnnotationFn, Args); -} - -void CodeGenFunction::EmitVarAnnotations(const VarDecl *D, llvm::Value *V) { - assert(D->hasAttr<AnnotateAttr>() && "no annotate attribute"); - // FIXME We create a new bitcast for every annotation because that's what - // llvm-gcc was doing. - for (const auto *I : D->specific_attrs<AnnotateAttr>()) - EmitAnnotationCall(CGM.getIntrinsic(llvm::Intrinsic::var_annotation), - Builder.CreateBitCast(V, CGM.Int8PtrTy, V->getName()), - I->getAnnotation(), D->getLocation()); -} - -Address CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D, - Address Addr) { - assert(D->hasAttr<AnnotateAttr>() && "no annotate attribute"); - llvm::Value *V = Addr.getPointer(); - llvm::Type *VTy = V->getType(); - llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::ptr_annotation, - CGM.Int8PtrTy); - - for (const auto *I : D->specific_attrs<AnnotateAttr>()) { - // FIXME Always emit the cast inst so we can differentiate between - // annotation on the first field of a struct and annotation on the struct - // itself. - if (VTy != CGM.Int8PtrTy) - V = Builder.CreateBitCast(V, CGM.Int8PtrTy); - V = EmitAnnotationCall(F, V, I->getAnnotation(), D->getLocation()); - V = Builder.CreateBitCast(V, VTy); - } - - return Address(V, Addr.getAlignment()); -} - -CodeGenFunction::CGCapturedStmtInfo::~CGCapturedStmtInfo() { } - -CodeGenFunction::SanitizerScope::SanitizerScope(CodeGenFunction *CGF) - : CGF(CGF) { - assert(!CGF->IsSanitizerScope); - CGF->IsSanitizerScope = true; -} - -CodeGenFunction::SanitizerScope::~SanitizerScope() { - CGF->IsSanitizerScope = false; -} - -void CodeGenFunction::InsertHelper(llvm::Instruction *I, - const llvm::Twine &Name, - llvm::BasicBlock *BB, - llvm::BasicBlock::iterator InsertPt) const { - LoopStack.InsertHelper(I); - if (IsSanitizerScope) - CGM.getSanitizerMetadata()->disableSanitizerForInstruction(I); -} - -void CGBuilderInserter::InsertHelper( - llvm::Instruction *I, const llvm::Twine &Name, llvm::BasicBlock *BB, - llvm::BasicBlock::iterator InsertPt) const { - llvm::IRBuilderDefaultInserter::InsertHelper(I, Name, BB, InsertPt); - if (CGF) - CGF->InsertHelper(I, Name, BB, InsertPt); -} - -static bool hasRequiredFeatures(const SmallVectorImpl<StringRef> &ReqFeatures, - CodeGenModule &CGM, const FunctionDecl *FD, - std::string &FirstMissing) { - // If there aren't any required features listed then go ahead and return. - if (ReqFeatures.empty()) - return false; - - // Now build up the set of caller features and verify that all the required - // features are there. - llvm::StringMap<bool> CallerFeatureMap; - CGM.getFunctionFeatureMap(CallerFeatureMap, GlobalDecl().getWithDecl(FD)); - - // If we have at least one of the features in the feature list return - // true, otherwise return false. - return std::all_of( - ReqFeatures.begin(), ReqFeatures.end(), [&](StringRef Feature) { - SmallVector<StringRef, 1> OrFeatures; - Feature.split(OrFeatures, '|'); - return llvm::any_of(OrFeatures, [&](StringRef Feature) { - if (!CallerFeatureMap.lookup(Feature)) { - FirstMissing = Feature.str(); - return false; - } - return true; - }); - }); -} - -// Emits an error if we don't have a valid set of target features for the -// called function. -void CodeGenFunction::checkTargetFeatures(const CallExpr *E, - const FunctionDecl *TargetDecl) { - // Early exit if this is an indirect call. - if (!TargetDecl) - return; - - // Get the current enclosing function if it exists. If it doesn't - // we can't check the target features anyhow. - const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl); - if (!FD) - return; - - // Grab the required features for the call. For a builtin this is listed in - // the td file with the default cpu, for an always_inline function this is any - // listed cpu and any listed features. - unsigned BuiltinID = TargetDecl->getBuiltinID(); - std::string MissingFeature; - if (BuiltinID) { - SmallVector<StringRef, 1> ReqFeatures; - const char *FeatureList = - CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID); - // Return if the builtin doesn't have any required features. - if (!FeatureList || StringRef(FeatureList) == "") - return; - StringRef(FeatureList).split(ReqFeatures, ','); - if (!hasRequiredFeatures(ReqFeatures, CGM, FD, MissingFeature)) - CGM.getDiags().Report(E->getBeginLoc(), diag::err_builtin_needs_feature) - << TargetDecl->getDeclName() - << CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID); - - } else if (TargetDecl->hasAttr<TargetAttr>() || - TargetDecl->hasAttr<CPUSpecificAttr>()) { - // Get the required features for the callee. - - const TargetAttr *TD = TargetDecl->getAttr<TargetAttr>(); - TargetAttr::ParsedTargetAttr ParsedAttr = CGM.filterFunctionTargetAttrs(TD); - - SmallVector<StringRef, 1> ReqFeatures; - llvm::StringMap<bool> CalleeFeatureMap; - CGM.getFunctionFeatureMap(CalleeFeatureMap, TargetDecl); - - for (const auto &F : ParsedAttr.Features) { - if (F[0] == '+' && CalleeFeatureMap.lookup(F.substr(1))) - ReqFeatures.push_back(StringRef(F).substr(1)); - } - - for (const auto &F : CalleeFeatureMap) { - // Only positive features are "required". - if (F.getValue()) - ReqFeatures.push_back(F.getKey()); - } - if (!hasRequiredFeatures(ReqFeatures, CGM, FD, MissingFeature)) - CGM.getDiags().Report(E->getBeginLoc(), diag::err_function_needs_feature) - << FD->getDeclName() << TargetDecl->getDeclName() << MissingFeature; - } -} - -void CodeGenFunction::EmitSanitizerStatReport(llvm::SanitizerStatKind SSK) { - if (!CGM.getCodeGenOpts().SanitizeStats) - return; - - llvm::IRBuilder<> IRB(Builder.GetInsertBlock(), Builder.GetInsertPoint()); - IRB.SetCurrentDebugLocation(Builder.getCurrentDebugLocation()); - CGM.getSanStats().create(IRB, SSK); -} - -llvm::Value * -CodeGenFunction::FormResolverCondition(const MultiVersionResolverOption &RO) { - llvm::Value *Condition = nullptr; - - if (!RO.Conditions.Architecture.empty()) - Condition = EmitX86CpuIs(RO.Conditions.Architecture); - - if (!RO.Conditions.Features.empty()) { - llvm::Value *FeatureCond = EmitX86CpuSupports(RO.Conditions.Features); - Condition = - Condition ? Builder.CreateAnd(Condition, FeatureCond) : FeatureCond; - } - return Condition; -} - -static void CreateMultiVersionResolverReturn(CodeGenModule &CGM, - llvm::Function *Resolver, - CGBuilderTy &Builder, - llvm::Function *FuncToReturn, - bool SupportsIFunc) { - if (SupportsIFunc) { - Builder.CreateRet(FuncToReturn); - return; - } - - llvm::SmallVector<llvm::Value *, 10> Args; - llvm::for_each(Resolver->args(), - [&](llvm::Argument &Arg) { Args.push_back(&Arg); }); - - llvm::CallInst *Result = Builder.CreateCall(FuncToReturn, Args); - Result->setTailCallKind(llvm::CallInst::TCK_MustTail); - - if (Resolver->getReturnType()->isVoidTy()) - Builder.CreateRetVoid(); - else - Builder.CreateRet(Result); -} - -void CodeGenFunction::EmitMultiVersionResolver( - llvm::Function *Resolver, ArrayRef<MultiVersionResolverOption> Options) { - assert((getContext().getTargetInfo().getTriple().getArch() == - llvm::Triple::x86 || - getContext().getTargetInfo().getTriple().getArch() == - llvm::Triple::x86_64) && - "Only implemented for x86 targets"); - - bool SupportsIFunc = getContext().getTargetInfo().supportsIFunc(); - - // Main function's basic block. - llvm::BasicBlock *CurBlock = createBasicBlock("resolver_entry", Resolver); - Builder.SetInsertPoint(CurBlock); - EmitX86CpuInit(); - - for (const MultiVersionResolverOption &RO : Options) { - Builder.SetInsertPoint(CurBlock); - llvm::Value *Condition = FormResolverCondition(RO); - - // The 'default' or 'generic' case. - if (!Condition) { - assert(&RO == Options.end() - 1 && - "Default or Generic case must be last"); - CreateMultiVersionResolverReturn(CGM, Resolver, Builder, RO.Function, - SupportsIFunc); - return; - } - - llvm::BasicBlock *RetBlock = createBasicBlock("resolver_return", Resolver); - CGBuilderTy RetBuilder(*this, RetBlock); - CreateMultiVersionResolverReturn(CGM, Resolver, RetBuilder, RO.Function, - SupportsIFunc); - CurBlock = createBasicBlock("resolver_else", Resolver); - Builder.CreateCondBr(Condition, RetBlock, CurBlock); - } - - // If no generic/default, emit an unreachable. - Builder.SetInsertPoint(CurBlock); - llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap); - TrapCall->setDoesNotReturn(); - TrapCall->setDoesNotThrow(); - Builder.CreateUnreachable(); - Builder.ClearInsertionPoint(); -} - -// Loc - where the diagnostic will point, where in the source code this -// alignment has failed. -// SecondaryLoc - if present (will be present if sufficiently different from -// Loc), the diagnostic will additionally point a "Note:" to this location. -// It should be the location where the __attribute__((assume_aligned)) -// was written e.g. -void CodeGenFunction::EmitAlignmentAssumptionCheck( - llvm::Value *Ptr, QualType Ty, SourceLocation Loc, - SourceLocation SecondaryLoc, llvm::Value *Alignment, - llvm::Value *OffsetValue, llvm::Value *TheCheck, - llvm::Instruction *Assumption) { - assert(Assumption && isa<llvm::CallInst>(Assumption) && - cast<llvm::CallInst>(Assumption)->getCalledValue() == - llvm::Intrinsic::getDeclaration( - Builder.GetInsertBlock()->getParent()->getParent(), - llvm::Intrinsic::assume) && - "Assumption should be a call to llvm.assume()."); - assert(&(Builder.GetInsertBlock()->back()) == Assumption && - "Assumption should be the last instruction of the basic block, " - "since the basic block is still being generated."); - - if (!SanOpts.has(SanitizerKind::Alignment)) - return; - - // Don't check pointers to volatile data. The behavior here is implementation- - // defined. - if (Ty->getPointeeType().isVolatileQualified()) - return; - - // We need to temorairly remove the assumption so we can insert the - // sanitizer check before it, else the check will be dropped by optimizations. - Assumption->removeFromParent(); - - { - SanitizerScope SanScope(this); - - if (!OffsetValue) - OffsetValue = Builder.getInt1(0); // no offset. - - llvm::Constant *StaticData[] = {EmitCheckSourceLocation(Loc), - EmitCheckSourceLocation(SecondaryLoc), - EmitCheckTypeDescriptor(Ty)}; - llvm::Value *DynamicData[] = {EmitCheckValue(Ptr), - EmitCheckValue(Alignment), - EmitCheckValue(OffsetValue)}; - EmitCheck({std::make_pair(TheCheck, SanitizerKind::Alignment)}, - SanitizerHandler::AlignmentAssumption, StaticData, DynamicData); - } - - // We are now in the (new, empty) "cont" basic block. - // Reintroduce the assumption. - Builder.Insert(Assumption); - // FIXME: Assumption still has it's original basic block as it's Parent. -} - -llvm::DebugLoc CodeGenFunction::SourceLocToDebugLoc(SourceLocation Location) { - if (CGDebugInfo *DI = getDebugInfo()) - return DI->SourceLocToDebugLoc(Location); - - return llvm::DebugLoc(); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h b/gnu/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h deleted file mode 100644 index 89cb850ab1b..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h +++ /dev/null @@ -1,4373 +0,0 @@ -//===-- CodeGenFunction.h - Per-Function state for LLVM CodeGen -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This is the internal per-function state used for llvm translation. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENFUNCTION_H -#define LLVM_CLANG_LIB_CODEGEN_CODEGENFUNCTION_H - -#include "CGBuilder.h" -#include "CGDebugInfo.h" -#include "CGLoopInfo.h" -#include "CGValue.h" -#include "CodeGenModule.h" -#include "CodeGenPGO.h" -#include "EHScopeStack.h" -#include "VarBypassDetector.h" -#include "clang/AST/CharUnits.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/ExprObjC.h" -#include "clang/AST/ExprOpenMP.h" -#include "clang/AST/Type.h" -#include "clang/Basic/ABI.h" -#include "clang/Basic/CapturedStmt.h" -#include "clang/Basic/CodeGenOptions.h" -#include "clang/Basic/OpenMPKinds.h" -#include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/IR/ValueHandle.h" -#include "llvm/Support/Debug.h" -#include "llvm/Transforms/Utils/SanitizerStats.h" - -namespace llvm { -class BasicBlock; -class LLVMContext; -class MDNode; -class Module; -class SwitchInst; -class Twine; -class Value; -class CallSite; -} - -namespace clang { -class ASTContext; -class BlockDecl; -class CXXDestructorDecl; -class CXXForRangeStmt; -class CXXTryStmt; -class Decl; -class LabelDecl; -class EnumConstantDecl; -class FunctionDecl; -class FunctionProtoType; -class LabelStmt; -class ObjCContainerDecl; -class ObjCInterfaceDecl; -class ObjCIvarDecl; -class ObjCMethodDecl; -class ObjCImplementationDecl; -class ObjCPropertyImplDecl; -class TargetInfo; -class VarDecl; -class ObjCForCollectionStmt; -class ObjCAtTryStmt; -class ObjCAtThrowStmt; -class ObjCAtSynchronizedStmt; -class ObjCAutoreleasePoolStmt; - -namespace analyze_os_log { -class OSLogBufferLayout; -} - -namespace CodeGen { -class CodeGenTypes; -class CGCallee; -class CGFunctionInfo; -class CGRecordLayout; -class CGBlockInfo; -class CGCXXABI; -class BlockByrefHelpers; -class BlockByrefInfo; -class BlockFlags; -class BlockFieldFlags; -class RegionCodeGenTy; -class TargetCodeGenInfo; -struct OMPTaskDataTy; -struct CGCoroData; - -/// The kind of evaluation to perform on values of a particular -/// type. Basically, is the code in CGExprScalar, CGExprComplex, or -/// CGExprAgg? -/// -/// TODO: should vectors maybe be split out into their own thing? -enum TypeEvaluationKind { - TEK_Scalar, - TEK_Complex, - TEK_Aggregate -}; - -#define LIST_SANITIZER_CHECKS \ - SANITIZER_CHECK(AddOverflow, add_overflow, 0) \ - SANITIZER_CHECK(BuiltinUnreachable, builtin_unreachable, 0) \ - SANITIZER_CHECK(CFICheckFail, cfi_check_fail, 0) \ - SANITIZER_CHECK(DivremOverflow, divrem_overflow, 0) \ - SANITIZER_CHECK(DynamicTypeCacheMiss, dynamic_type_cache_miss, 0) \ - SANITIZER_CHECK(FloatCastOverflow, float_cast_overflow, 0) \ - SANITIZER_CHECK(FunctionTypeMismatch, function_type_mismatch, 0) \ - SANITIZER_CHECK(ImplicitConversion, implicit_conversion, 0) \ - SANITIZER_CHECK(InvalidBuiltin, invalid_builtin, 0) \ - SANITIZER_CHECK(LoadInvalidValue, load_invalid_value, 0) \ - SANITIZER_CHECK(MissingReturn, missing_return, 0) \ - SANITIZER_CHECK(MulOverflow, mul_overflow, 0) \ - SANITIZER_CHECK(NegateOverflow, negate_overflow, 0) \ - SANITIZER_CHECK(NullabilityArg, nullability_arg, 0) \ - SANITIZER_CHECK(NullabilityReturn, nullability_return, 1) \ - SANITIZER_CHECK(NonnullArg, nonnull_arg, 0) \ - SANITIZER_CHECK(NonnullReturn, nonnull_return, 1) \ - SANITIZER_CHECK(OutOfBounds, out_of_bounds, 0) \ - SANITIZER_CHECK(PointerOverflow, pointer_overflow, 0) \ - SANITIZER_CHECK(ShiftOutOfBounds, shift_out_of_bounds, 0) \ - SANITIZER_CHECK(SubOverflow, sub_overflow, 0) \ - SANITIZER_CHECK(TypeMismatch, type_mismatch, 1) \ - SANITIZER_CHECK(AlignmentAssumption, alignment_assumption, 0) \ - SANITIZER_CHECK(VLABoundNotPositive, vla_bound_not_positive, 0) - -enum SanitizerHandler { -#define SANITIZER_CHECK(Enum, Name, Version) Enum, - LIST_SANITIZER_CHECKS -#undef SANITIZER_CHECK -}; - -/// Helper class with most of the code for saving a value for a -/// conditional expression cleanup. -struct DominatingLLVMValue { - typedef llvm::PointerIntPair<llvm::Value*, 1, bool> saved_type; - - /// Answer whether the given value needs extra work to be saved. - static bool needsSaving(llvm::Value *value) { - // If it's not an instruction, we don't need to save. - if (!isa<llvm::Instruction>(value)) return false; - - // If it's an instruction in the entry block, we don't need to save. - llvm::BasicBlock *block = cast<llvm::Instruction>(value)->getParent(); - return (block != &block->getParent()->getEntryBlock()); - } - - static saved_type save(CodeGenFunction &CGF, llvm::Value *value); - static llvm::Value *restore(CodeGenFunction &CGF, saved_type value); -}; - -/// A partial specialization of DominatingValue for llvm::Values that -/// might be llvm::Instructions. -template <class T> struct DominatingPointer<T,true> : DominatingLLVMValue { - typedef T *type; - static type restore(CodeGenFunction &CGF, saved_type value) { - return static_cast<T*>(DominatingLLVMValue::restore(CGF, value)); - } -}; - -/// A specialization of DominatingValue for Address. -template <> struct DominatingValue<Address> { - typedef Address type; - - struct saved_type { - DominatingLLVMValue::saved_type SavedValue; - CharUnits Alignment; - }; - - static bool needsSaving(type value) { - return DominatingLLVMValue::needsSaving(value.getPointer()); - } - static saved_type save(CodeGenFunction &CGF, type value) { - return { DominatingLLVMValue::save(CGF, value.getPointer()), - value.getAlignment() }; - } - static type restore(CodeGenFunction &CGF, saved_type value) { - return Address(DominatingLLVMValue::restore(CGF, value.SavedValue), - value.Alignment); - } -}; - -/// A specialization of DominatingValue for RValue. -template <> struct DominatingValue<RValue> { - typedef RValue type; - class saved_type { - enum Kind { ScalarLiteral, ScalarAddress, AggregateLiteral, - AggregateAddress, ComplexAddress }; - - llvm::Value *Value; - unsigned K : 3; - unsigned Align : 29; - saved_type(llvm::Value *v, Kind k, unsigned a = 0) - : Value(v), K(k), Align(a) {} - - public: - static bool needsSaving(RValue value); - static saved_type save(CodeGenFunction &CGF, RValue value); - RValue restore(CodeGenFunction &CGF); - - // implementations in CGCleanup.cpp - }; - - static bool needsSaving(type value) { - return saved_type::needsSaving(value); - } - static saved_type save(CodeGenFunction &CGF, type value) { - return saved_type::save(CGF, value); - } - static type restore(CodeGenFunction &CGF, saved_type value) { - return value.restore(CGF); - } -}; - -/// CodeGenFunction - This class organizes the per-function state that is used -/// while generating LLVM code. -class CodeGenFunction : public CodeGenTypeCache { - CodeGenFunction(const CodeGenFunction &) = delete; - void operator=(const CodeGenFunction &) = delete; - - friend class CGCXXABI; -public: - /// A jump destination is an abstract label, branching to which may - /// require a jump out through normal cleanups. - struct JumpDest { - JumpDest() : Block(nullptr), ScopeDepth(), Index(0) {} - JumpDest(llvm::BasicBlock *Block, - EHScopeStack::stable_iterator Depth, - unsigned Index) - : Block(Block), ScopeDepth(Depth), Index(Index) {} - - bool isValid() const { return Block != nullptr; } - llvm::BasicBlock *getBlock() const { return Block; } - EHScopeStack::stable_iterator getScopeDepth() const { return ScopeDepth; } - unsigned getDestIndex() const { return Index; } - - // This should be used cautiously. - void setScopeDepth(EHScopeStack::stable_iterator depth) { - ScopeDepth = depth; - } - - private: - llvm::BasicBlock *Block; - EHScopeStack::stable_iterator ScopeDepth; - unsigned Index; - }; - - CodeGenModule &CGM; // Per-module state. - const TargetInfo &Target; - - typedef std::pair<llvm::Value *, llvm::Value *> ComplexPairTy; - LoopInfoStack LoopStack; - CGBuilderTy Builder; - - // Stores variables for which we can't generate correct lifetime markers - // because of jumps. - VarBypassDetector Bypasses; - - // CodeGen lambda for loops and support for ordered clause - typedef llvm::function_ref<void(CodeGenFunction &, const OMPLoopDirective &, - JumpDest)> - CodeGenLoopTy; - typedef llvm::function_ref<void(CodeGenFunction &, SourceLocation, - const unsigned, const bool)> - CodeGenOrderedTy; - - // Codegen lambda for loop bounds in worksharing loop constructs - typedef llvm::function_ref<std::pair<LValue, LValue>( - CodeGenFunction &, const OMPExecutableDirective &S)> - CodeGenLoopBoundsTy; - - // Codegen lambda for loop bounds in dispatch-based loop implementation - typedef llvm::function_ref<std::pair<llvm::Value *, llvm::Value *>( - CodeGenFunction &, const OMPExecutableDirective &S, Address LB, - Address UB)> - CodeGenDispatchBoundsTy; - - /// CGBuilder insert helper. This function is called after an - /// instruction is created using Builder. - void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name, - llvm::BasicBlock *BB, - llvm::BasicBlock::iterator InsertPt) const; - - /// CurFuncDecl - Holds the Decl for the current outermost - /// non-closure context. - const Decl *CurFuncDecl; - /// CurCodeDecl - This is the inner-most code context, which includes blocks. - const Decl *CurCodeDecl; - const CGFunctionInfo *CurFnInfo; - QualType FnRetTy; - llvm::Function *CurFn = nullptr; - - // Holds coroutine data if the current function is a coroutine. We use a - // wrapper to manage its lifetime, so that we don't have to define CGCoroData - // in this header. - struct CGCoroInfo { - std::unique_ptr<CGCoroData> Data; - CGCoroInfo(); - ~CGCoroInfo(); - }; - CGCoroInfo CurCoro; - - bool isCoroutine() const { - return CurCoro.Data != nullptr; - } - - /// CurGD - The GlobalDecl for the current function being compiled. - GlobalDecl CurGD; - - /// PrologueCleanupDepth - The cleanup depth enclosing all the - /// cleanups associated with the parameters. - EHScopeStack::stable_iterator PrologueCleanupDepth; - - /// ReturnBlock - Unified return block. - JumpDest ReturnBlock; - - /// ReturnValue - The temporary alloca to hold the return - /// value. This is invalid iff the function has no return value. - Address ReturnValue = Address::invalid(); - - /// Return true if a label was seen in the current scope. - bool hasLabelBeenSeenInCurrentScope() const { - if (CurLexicalScope) - return CurLexicalScope->hasLabels(); - return !LabelMap.empty(); - } - - /// AllocaInsertPoint - This is an instruction in the entry block before which - /// we prefer to insert allocas. - llvm::AssertingVH<llvm::Instruction> AllocaInsertPt; - - /// API for captured statement code generation. - class CGCapturedStmtInfo { - public: - explicit CGCapturedStmtInfo(CapturedRegionKind K = CR_Default) - : Kind(K), ThisValue(nullptr), CXXThisFieldDecl(nullptr) {} - explicit CGCapturedStmtInfo(const CapturedStmt &S, - CapturedRegionKind K = CR_Default) - : Kind(K), ThisValue(nullptr), CXXThisFieldDecl(nullptr) { - - RecordDecl::field_iterator Field = - S.getCapturedRecordDecl()->field_begin(); - for (CapturedStmt::const_capture_iterator I = S.capture_begin(), - E = S.capture_end(); - I != E; ++I, ++Field) { - if (I->capturesThis()) - CXXThisFieldDecl = *Field; - else if (I->capturesVariable()) - CaptureFields[I->getCapturedVar()->getCanonicalDecl()] = *Field; - else if (I->capturesVariableByCopy()) - CaptureFields[I->getCapturedVar()->getCanonicalDecl()] = *Field; - } - } - - virtual ~CGCapturedStmtInfo(); - - CapturedRegionKind getKind() const { return Kind; } - - virtual void setContextValue(llvm::Value *V) { ThisValue = V; } - // Retrieve the value of the context parameter. - virtual llvm::Value *getContextValue() const { return ThisValue; } - - /// Lookup the captured field decl for a variable. - virtual const FieldDecl *lookup(const VarDecl *VD) const { - return CaptureFields.lookup(VD->getCanonicalDecl()); - } - - bool isCXXThisExprCaptured() const { return getThisFieldDecl() != nullptr; } - virtual FieldDecl *getThisFieldDecl() const { return CXXThisFieldDecl; } - - static bool classof(const CGCapturedStmtInfo *) { - return true; - } - - /// Emit the captured statement body. - virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S) { - CGF.incrementProfileCounter(S); - CGF.EmitStmt(S); - } - - /// Get the name of the capture helper. - virtual StringRef getHelperName() const { return "__captured_stmt"; } - - private: - /// The kind of captured statement being generated. - CapturedRegionKind Kind; - - /// Keep the map between VarDecl and FieldDecl. - llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields; - - /// The base address of the captured record, passed in as the first - /// argument of the parallel region function. - llvm::Value *ThisValue; - - /// Captured 'this' type. - FieldDecl *CXXThisFieldDecl; - }; - CGCapturedStmtInfo *CapturedStmtInfo = nullptr; - - /// RAII for correct setting/restoring of CapturedStmtInfo. - class CGCapturedStmtRAII { - private: - CodeGenFunction &CGF; - CGCapturedStmtInfo *PrevCapturedStmtInfo; - public: - CGCapturedStmtRAII(CodeGenFunction &CGF, - CGCapturedStmtInfo *NewCapturedStmtInfo) - : CGF(CGF), PrevCapturedStmtInfo(CGF.CapturedStmtInfo) { - CGF.CapturedStmtInfo = NewCapturedStmtInfo; - } - ~CGCapturedStmtRAII() { CGF.CapturedStmtInfo = PrevCapturedStmtInfo; } - }; - - /// An abstract representation of regular/ObjC call/message targets. - class AbstractCallee { - /// The function declaration of the callee. - const Decl *CalleeDecl; - - public: - AbstractCallee() : CalleeDecl(nullptr) {} - AbstractCallee(const FunctionDecl *FD) : CalleeDecl(FD) {} - AbstractCallee(const ObjCMethodDecl *OMD) : CalleeDecl(OMD) {} - bool hasFunctionDecl() const { - return dyn_cast_or_null<FunctionDecl>(CalleeDecl); - } - const Decl *getDecl() const { return CalleeDecl; } - unsigned getNumParams() const { - if (const auto *FD = dyn_cast<FunctionDecl>(CalleeDecl)) - return FD->getNumParams(); - return cast<ObjCMethodDecl>(CalleeDecl)->param_size(); - } - const ParmVarDecl *getParamDecl(unsigned I) const { - if (const auto *FD = dyn_cast<FunctionDecl>(CalleeDecl)) - return FD->getParamDecl(I); - return *(cast<ObjCMethodDecl>(CalleeDecl)->param_begin() + I); - } - }; - - /// Sanitizers enabled for this function. - SanitizerSet SanOpts; - - /// True if CodeGen currently emits code implementing sanitizer checks. - bool IsSanitizerScope = false; - - /// RAII object to set/unset CodeGenFunction::IsSanitizerScope. - class SanitizerScope { - CodeGenFunction *CGF; - public: - SanitizerScope(CodeGenFunction *CGF); - ~SanitizerScope(); - }; - - /// In C++, whether we are code generating a thunk. This controls whether we - /// should emit cleanups. - bool CurFuncIsThunk = false; - - /// In ARC, whether we should autorelease the return value. - bool AutoreleaseResult = false; - - /// Whether we processed a Microsoft-style asm block during CodeGen. These can - /// potentially set the return value. - bool SawAsmBlock = false; - - const NamedDecl *CurSEHParent = nullptr; - - /// True if the current function is an outlined SEH helper. This can be a - /// finally block or filter expression. - bool IsOutlinedSEHHelper = false; - - const CodeGen::CGBlockInfo *BlockInfo = nullptr; - llvm::Value *BlockPointer = nullptr; - - llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; - FieldDecl *LambdaThisCaptureField = nullptr; - - /// A mapping from NRVO variables to the flags used to indicate - /// when the NRVO has been applied to this variable. - llvm::DenseMap<const VarDecl *, llvm::Value *> NRVOFlags; - - EHScopeStack EHStack; - llvm::SmallVector<char, 256> LifetimeExtendedCleanupStack; - llvm::SmallVector<const JumpDest *, 2> SEHTryEpilogueStack; - - llvm::Instruction *CurrentFuncletPad = nullptr; - - class CallLifetimeEnd final : public EHScopeStack::Cleanup { - llvm::Value *Addr; - llvm::Value *Size; - - public: - CallLifetimeEnd(Address addr, llvm::Value *size) - : Addr(addr.getPointer()), Size(size) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - CGF.EmitLifetimeEnd(Size, Addr); - } - }; - - /// Header for data within LifetimeExtendedCleanupStack. - struct LifetimeExtendedCleanupHeader { - /// The size of the following cleanup object. - unsigned Size; - /// The kind of cleanup to push: a value from the CleanupKind enumeration. - unsigned Kind : 31; - /// Whether this is a conditional cleanup. - unsigned IsConditional : 1; - - size_t getSize() const { return Size; } - CleanupKind getKind() const { return (CleanupKind)Kind; } - bool isConditional() const { return IsConditional; } - }; - - /// i32s containing the indexes of the cleanup destinations. - Address NormalCleanupDest = Address::invalid(); - - unsigned NextCleanupDestIndex = 1; - - /// FirstBlockInfo - The head of a singly-linked-list of block layouts. - CGBlockInfo *FirstBlockInfo = nullptr; - - /// EHResumeBlock - Unified block containing a call to llvm.eh.resume. - llvm::BasicBlock *EHResumeBlock = nullptr; - - /// The exception slot. All landing pads write the current exception pointer - /// into this alloca. - llvm::Value *ExceptionSlot = nullptr; - - /// The selector slot. Under the MandatoryCleanup model, all landing pads - /// write the current selector value into this alloca. - llvm::AllocaInst *EHSelectorSlot = nullptr; - - /// A stack of exception code slots. Entering an __except block pushes a slot - /// on the stack and leaving pops one. The __exception_code() intrinsic loads - /// a value from the top of the stack. - SmallVector<Address, 1> SEHCodeSlotStack; - - /// Value returned by __exception_info intrinsic. - llvm::Value *SEHInfo = nullptr; - - /// Emits a landing pad for the current EH stack. - llvm::BasicBlock *EmitLandingPad(); - - llvm::BasicBlock *getInvokeDestImpl(); - - template <class T> - typename DominatingValue<T>::saved_type saveValueInCond(T value) { - return DominatingValue<T>::save(*this, value); - } - -public: - /// ObjCEHValueStack - Stack of Objective-C exception values, used for - /// rethrows. - SmallVector<llvm::Value*, 8> ObjCEHValueStack; - - /// A class controlling the emission of a finally block. - class FinallyInfo { - /// Where the catchall's edge through the cleanup should go. - JumpDest RethrowDest; - - /// A function to call to enter the catch. - llvm::Constant *BeginCatchFn; - - /// An i1 variable indicating whether or not the @finally is - /// running for an exception. - llvm::AllocaInst *ForEHVar; - - /// An i8* variable into which the exception pointer to rethrow - /// has been saved. - llvm::AllocaInst *SavedExnVar; - - public: - void enter(CodeGenFunction &CGF, const Stmt *Finally, - llvm::Constant *beginCatchFn, llvm::Constant *endCatchFn, - llvm::Constant *rethrowFn); - void exit(CodeGenFunction &CGF); - }; - - /// Returns true inside SEH __try blocks. - bool isSEHTryScope() const { return !SEHTryEpilogueStack.empty(); } - - /// Returns true while emitting a cleanuppad. - bool isCleanupPadScope() const { - return CurrentFuncletPad && isa<llvm::CleanupPadInst>(CurrentFuncletPad); - } - - /// pushFullExprCleanup - Push a cleanup to be run at the end of the - /// current full-expression. Safe against the possibility that - /// we're currently inside a conditionally-evaluated expression. - template <class T, class... As> - void pushFullExprCleanup(CleanupKind kind, As... A) { - // If we're not in a conditional branch, or if none of the - // arguments requires saving, then use the unconditional cleanup. - if (!isInConditionalBranch()) - return EHStack.pushCleanup<T>(kind, A...); - - // Stash values in a tuple so we can guarantee the order of saves. - typedef std::tuple<typename DominatingValue<As>::saved_type...> SavedTuple; - SavedTuple Saved{saveValueInCond(A)...}; - - typedef EHScopeStack::ConditionalCleanup<T, As...> CleanupType; - EHStack.pushCleanupTuple<CleanupType>(kind, Saved); - initFullExprCleanup(); - } - - /// Queue a cleanup to be pushed after finishing the current - /// full-expression. - template <class T, class... As> - void pushCleanupAfterFullExpr(CleanupKind Kind, As... A) { - if (!isInConditionalBranch()) - return pushCleanupAfterFullExprImpl<T>(Kind, Address::invalid(), A...); - - Address ActiveFlag = createCleanupActiveFlag(); - assert(!DominatingValue<Address>::needsSaving(ActiveFlag) && - "cleanup active flag should never need saving"); - - typedef std::tuple<typename DominatingValue<As>::saved_type...> SavedTuple; - SavedTuple Saved{saveValueInCond(A)...}; - - typedef EHScopeStack::ConditionalCleanup<T, As...> CleanupType; - pushCleanupAfterFullExprImpl<CleanupType>(Kind, ActiveFlag, Saved); - } - - template <class T, class... As> - void pushCleanupAfterFullExprImpl(CleanupKind Kind, Address ActiveFlag, - As... A) { - LifetimeExtendedCleanupHeader Header = {sizeof(T), Kind, - ActiveFlag.isValid()}; - - size_t OldSize = LifetimeExtendedCleanupStack.size(); - LifetimeExtendedCleanupStack.resize( - LifetimeExtendedCleanupStack.size() + sizeof(Header) + Header.Size + - (Header.IsConditional ? sizeof(ActiveFlag) : 0)); - - static_assert(sizeof(Header) % alignof(T) == 0, - "Cleanup will be allocated on misaligned address"); - char *Buffer = &LifetimeExtendedCleanupStack[OldSize]; - new (Buffer) LifetimeExtendedCleanupHeader(Header); - new (Buffer + sizeof(Header)) T(A...); - if (Header.IsConditional) - new (Buffer + sizeof(Header) + sizeof(T)) Address(ActiveFlag); - } - - /// Set up the last cleanup that was pushed as a conditional - /// full-expression cleanup. - void initFullExprCleanup() { - initFullExprCleanupWithFlag(createCleanupActiveFlag()); - } - - void initFullExprCleanupWithFlag(Address ActiveFlag); - Address createCleanupActiveFlag(); - - /// PushDestructorCleanup - Push a cleanup to call the - /// complete-object destructor of an object of the given type at the - /// given address. Does nothing if T is not a C++ class type with a - /// non-trivial destructor. - void PushDestructorCleanup(QualType T, Address Addr); - - /// PushDestructorCleanup - Push a cleanup to call the - /// complete-object variant of the given destructor on the object at - /// the given address. - void PushDestructorCleanup(const CXXDestructorDecl *Dtor, Address Addr); - - /// PopCleanupBlock - Will pop the cleanup entry on the stack and - /// process all branch fixups. - void PopCleanupBlock(bool FallThroughIsBranchThrough = false); - - /// DeactivateCleanupBlock - Deactivates the given cleanup block. - /// The block cannot be reactivated. Pops it if it's the top of the - /// stack. - /// - /// \param DominatingIP - An instruction which is known to - /// dominate the current IP (if set) and which lies along - /// all paths of execution between the current IP and the - /// the point at which the cleanup comes into scope. - void DeactivateCleanupBlock(EHScopeStack::stable_iterator Cleanup, - llvm::Instruction *DominatingIP); - - /// ActivateCleanupBlock - Activates an initially-inactive cleanup. - /// Cannot be used to resurrect a deactivated cleanup. - /// - /// \param DominatingIP - An instruction which is known to - /// dominate the current IP (if set) and which lies along - /// all paths of execution between the current IP and the - /// the point at which the cleanup comes into scope. - void ActivateCleanupBlock(EHScopeStack::stable_iterator Cleanup, - llvm::Instruction *DominatingIP); - - /// Enters a new scope for capturing cleanups, all of which - /// will be executed once the scope is exited. - class RunCleanupsScope { - EHScopeStack::stable_iterator CleanupStackDepth, OldCleanupScopeDepth; - size_t LifetimeExtendedCleanupStackSize; - bool OldDidCallStackSave; - protected: - bool PerformCleanup; - private: - - RunCleanupsScope(const RunCleanupsScope &) = delete; - void operator=(const RunCleanupsScope &) = delete; - - protected: - CodeGenFunction& CGF; - - public: - /// Enter a new cleanup scope. - explicit RunCleanupsScope(CodeGenFunction &CGF) - : PerformCleanup(true), CGF(CGF) - { - CleanupStackDepth = CGF.EHStack.stable_begin(); - LifetimeExtendedCleanupStackSize = - CGF.LifetimeExtendedCleanupStack.size(); - OldDidCallStackSave = CGF.DidCallStackSave; - CGF.DidCallStackSave = false; - OldCleanupScopeDepth = CGF.CurrentCleanupScopeDepth; - CGF.CurrentCleanupScopeDepth = CleanupStackDepth; - } - - /// Exit this cleanup scope, emitting any accumulated cleanups. - ~RunCleanupsScope() { - if (PerformCleanup) - ForceCleanup(); - } - - /// Determine whether this scope requires any cleanups. - bool requiresCleanups() const { - return CGF.EHStack.stable_begin() != CleanupStackDepth; - } - - /// Force the emission of cleanups now, instead of waiting - /// until this object is destroyed. - /// \param ValuesToReload - A list of values that need to be available at - /// the insertion point after cleanup emission. If cleanup emission created - /// a shared cleanup block, these value pointers will be rewritten. - /// Otherwise, they not will be modified. - void ForceCleanup(std::initializer_list<llvm::Value**> ValuesToReload = {}) { - assert(PerformCleanup && "Already forced cleanup"); - CGF.DidCallStackSave = OldDidCallStackSave; - CGF.PopCleanupBlocks(CleanupStackDepth, LifetimeExtendedCleanupStackSize, - ValuesToReload); - PerformCleanup = false; - CGF.CurrentCleanupScopeDepth = OldCleanupScopeDepth; - } - }; - - // Cleanup stack depth of the RunCleanupsScope that was pushed most recently. - EHScopeStack::stable_iterator CurrentCleanupScopeDepth = - EHScopeStack::stable_end(); - - class LexicalScope : public RunCleanupsScope { - SourceRange Range; - SmallVector<const LabelDecl*, 4> Labels; - LexicalScope *ParentScope; - - LexicalScope(const LexicalScope &) = delete; - void operator=(const LexicalScope &) = delete; - - public: - /// Enter a new cleanup scope. - explicit LexicalScope(CodeGenFunction &CGF, SourceRange Range) - : RunCleanupsScope(CGF), Range(Range), ParentScope(CGF.CurLexicalScope) { - CGF.CurLexicalScope = this; - if (CGDebugInfo *DI = CGF.getDebugInfo()) - DI->EmitLexicalBlockStart(CGF.Builder, Range.getBegin()); - } - - void addLabel(const LabelDecl *label) { - assert(PerformCleanup && "adding label to dead scope?"); - Labels.push_back(label); - } - - /// Exit this cleanup scope, emitting any accumulated - /// cleanups. - ~LexicalScope() { - if (CGDebugInfo *DI = CGF.getDebugInfo()) - DI->EmitLexicalBlockEnd(CGF.Builder, Range.getEnd()); - - // If we should perform a cleanup, force them now. Note that - // this ends the cleanup scope before rescoping any labels. - if (PerformCleanup) { - ApplyDebugLocation DL(CGF, Range.getEnd()); - ForceCleanup(); - } - } - - /// Force the emission of cleanups now, instead of waiting - /// until this object is destroyed. - void ForceCleanup() { - CGF.CurLexicalScope = ParentScope; - RunCleanupsScope::ForceCleanup(); - - if (!Labels.empty()) - rescopeLabels(); - } - - bool hasLabels() const { - return !Labels.empty(); - } - - void rescopeLabels(); - }; - - typedef llvm::DenseMap<const Decl *, Address> DeclMapTy; - - /// The class used to assign some variables some temporarily addresses. - class OMPMapVars { - DeclMapTy SavedLocals; - DeclMapTy SavedTempAddresses; - OMPMapVars(const OMPMapVars &) = delete; - void operator=(const OMPMapVars &) = delete; - - public: - explicit OMPMapVars() = default; - ~OMPMapVars() { - assert(SavedLocals.empty() && "Did not restored original addresses."); - }; - - /// Sets the address of the variable \p LocalVD to be \p TempAddr in - /// function \p CGF. - /// \return true if at least one variable was set already, false otherwise. - bool setVarAddr(CodeGenFunction &CGF, const VarDecl *LocalVD, - Address TempAddr) { - LocalVD = LocalVD->getCanonicalDecl(); - // Only save it once. - if (SavedLocals.count(LocalVD)) return false; - - // Copy the existing local entry to SavedLocals. - auto it = CGF.LocalDeclMap.find(LocalVD); - if (it != CGF.LocalDeclMap.end()) - SavedLocals.try_emplace(LocalVD, it->second); - else - SavedLocals.try_emplace(LocalVD, Address::invalid()); - - // Generate the private entry. - QualType VarTy = LocalVD->getType(); - if (VarTy->isReferenceType()) { - Address Temp = CGF.CreateMemTemp(VarTy); - CGF.Builder.CreateStore(TempAddr.getPointer(), Temp); - TempAddr = Temp; - } - SavedTempAddresses.try_emplace(LocalVD, TempAddr); - - return true; - } - - /// Applies new addresses to the list of the variables. - /// \return true if at least one variable is using new address, false - /// otherwise. - bool apply(CodeGenFunction &CGF) { - copyInto(SavedTempAddresses, CGF.LocalDeclMap); - SavedTempAddresses.clear(); - return !SavedLocals.empty(); - } - - /// Restores original addresses of the variables. - void restore(CodeGenFunction &CGF) { - if (!SavedLocals.empty()) { - copyInto(SavedLocals, CGF.LocalDeclMap); - SavedLocals.clear(); - } - } - - private: - /// Copy all the entries in the source map over the corresponding - /// entries in the destination, which must exist. - static void copyInto(const DeclMapTy &Src, DeclMapTy &Dest) { - for (auto &Pair : Src) { - if (!Pair.second.isValid()) { - Dest.erase(Pair.first); - continue; - } - - auto I = Dest.find(Pair.first); - if (I != Dest.end()) - I->second = Pair.second; - else - Dest.insert(Pair); - } - } - }; - - /// The scope used to remap some variables as private in the OpenMP loop body - /// (or other captured region emitted without outlining), and to restore old - /// vars back on exit. - class OMPPrivateScope : public RunCleanupsScope { - OMPMapVars MappedVars; - OMPPrivateScope(const OMPPrivateScope &) = delete; - void operator=(const OMPPrivateScope &) = delete; - - public: - /// Enter a new OpenMP private scope. - explicit OMPPrivateScope(CodeGenFunction &CGF) : RunCleanupsScope(CGF) {} - - /// Registers \p LocalVD variable as a private and apply \p PrivateGen - /// function for it to generate corresponding private variable. \p - /// PrivateGen returns an address of the generated private variable. - /// \return true if the variable is registered as private, false if it has - /// been privatized already. - bool addPrivate(const VarDecl *LocalVD, - const llvm::function_ref<Address()> PrivateGen) { - assert(PerformCleanup && "adding private to dead scope"); - return MappedVars.setVarAddr(CGF, LocalVD, PrivateGen()); - } - - /// Privatizes local variables previously registered as private. - /// Registration is separate from the actual privatization to allow - /// initializers use values of the original variables, not the private one. - /// This is important, for example, if the private variable is a class - /// variable initialized by a constructor that references other private - /// variables. But at initialization original variables must be used, not - /// private copies. - /// \return true if at least one variable was privatized, false otherwise. - bool Privatize() { return MappedVars.apply(CGF); } - - void ForceCleanup() { - RunCleanupsScope::ForceCleanup(); - MappedVars.restore(CGF); - } - - /// Exit scope - all the mapped variables are restored. - ~OMPPrivateScope() { - if (PerformCleanup) - ForceCleanup(); - } - - /// Checks if the global variable is captured in current function. - bool isGlobalVarCaptured(const VarDecl *VD) const { - VD = VD->getCanonicalDecl(); - return !VD->isLocalVarDeclOrParm() && CGF.LocalDeclMap.count(VD) > 0; - } - }; - - /// Takes the old cleanup stack size and emits the cleanup blocks - /// that have been added. - void - PopCleanupBlocks(EHScopeStack::stable_iterator OldCleanupStackSize, - std::initializer_list<llvm::Value **> ValuesToReload = {}); - - /// Takes the old cleanup stack size and emits the cleanup blocks - /// that have been added, then adds all lifetime-extended cleanups from - /// the given position to the stack. - void - PopCleanupBlocks(EHScopeStack::stable_iterator OldCleanupStackSize, - size_t OldLifetimeExtendedStackSize, - std::initializer_list<llvm::Value **> ValuesToReload = {}); - - void ResolveBranchFixups(llvm::BasicBlock *Target); - - /// The given basic block lies in the current EH scope, but may be a - /// target of a potentially scope-crossing jump; get a stable handle - /// to which we can perform this jump later. - JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target) { - return JumpDest(Target, - EHStack.getInnermostNormalCleanup(), - NextCleanupDestIndex++); - } - - /// The given basic block lies in the current EH scope, but may be a - /// target of a potentially scope-crossing jump; get a stable handle - /// to which we can perform this jump later. - JumpDest getJumpDestInCurrentScope(StringRef Name = StringRef()) { - return getJumpDestInCurrentScope(createBasicBlock(Name)); - } - - /// EmitBranchThroughCleanup - Emit a branch from the current insert - /// block through the normal cleanup handling code (if any) and then - /// on to \arg Dest. - void EmitBranchThroughCleanup(JumpDest Dest); - - /// isObviouslyBranchWithoutCleanups - Return true if a branch to the - /// specified destination obviously has no cleanups to run. 'false' is always - /// a conservatively correct answer for this method. - bool isObviouslyBranchWithoutCleanups(JumpDest Dest) const; - - /// popCatchScope - Pops the catch scope at the top of the EHScope - /// stack, emitting any required code (other than the catch handlers - /// themselves). - void popCatchScope(); - - llvm::BasicBlock *getEHResumeBlock(bool isCleanup); - llvm::BasicBlock *getEHDispatchBlock(EHScopeStack::stable_iterator scope); - llvm::BasicBlock * - getFuncletEHDispatchBlock(EHScopeStack::stable_iterator scope); - - /// An object to manage conditionally-evaluated expressions. - class ConditionalEvaluation { - llvm::BasicBlock *StartBB; - - public: - ConditionalEvaluation(CodeGenFunction &CGF) - : StartBB(CGF.Builder.GetInsertBlock()) {} - - void begin(CodeGenFunction &CGF) { - assert(CGF.OutermostConditional != this); - if (!CGF.OutermostConditional) - CGF.OutermostConditional = this; - } - - void end(CodeGenFunction &CGF) { - assert(CGF.OutermostConditional != nullptr); - if (CGF.OutermostConditional == this) - CGF.OutermostConditional = nullptr; - } - - /// Returns a block which will be executed prior to each - /// evaluation of the conditional code. - llvm::BasicBlock *getStartingBlock() const { - return StartBB; - } - }; - - /// isInConditionalBranch - Return true if we're currently emitting - /// one branch or the other of a conditional expression. - bool isInConditionalBranch() const { return OutermostConditional != nullptr; } - - void setBeforeOutermostConditional(llvm::Value *value, Address addr) { - assert(isInConditionalBranch()); - llvm::BasicBlock *block = OutermostConditional->getStartingBlock(); - auto store = new llvm::StoreInst(value, addr.getPointer(), &block->back()); - store->setAlignment(addr.getAlignment().getQuantity()); - } - - /// An RAII object to record that we're evaluating a statement - /// expression. - class StmtExprEvaluation { - CodeGenFunction &CGF; - - /// We have to save the outermost conditional: cleanups in a - /// statement expression aren't conditional just because the - /// StmtExpr is. - ConditionalEvaluation *SavedOutermostConditional; - - public: - StmtExprEvaluation(CodeGenFunction &CGF) - : CGF(CGF), SavedOutermostConditional(CGF.OutermostConditional) { - CGF.OutermostConditional = nullptr; - } - - ~StmtExprEvaluation() { - CGF.OutermostConditional = SavedOutermostConditional; - CGF.EnsureInsertPoint(); - } - }; - - /// An object which temporarily prevents a value from being - /// destroyed by aggressive peephole optimizations that assume that - /// all uses of a value have been realized in the IR. - class PeepholeProtection { - llvm::Instruction *Inst; - friend class CodeGenFunction; - - public: - PeepholeProtection() : Inst(nullptr) {} - }; - - /// A non-RAII class containing all the information about a bound - /// opaque value. OpaqueValueMapping, below, is a RAII wrapper for - /// this which makes individual mappings very simple; using this - /// class directly is useful when you have a variable number of - /// opaque values or don't want the RAII functionality for some - /// reason. - class OpaqueValueMappingData { - const OpaqueValueExpr *OpaqueValue; - bool BoundLValue; - CodeGenFunction::PeepholeProtection Protection; - - OpaqueValueMappingData(const OpaqueValueExpr *ov, - bool boundLValue) - : OpaqueValue(ov), BoundLValue(boundLValue) {} - public: - OpaqueValueMappingData() : OpaqueValue(nullptr) {} - - static bool shouldBindAsLValue(const Expr *expr) { - // gl-values should be bound as l-values for obvious reasons. - // Records should be bound as l-values because IR generation - // always keeps them in memory. Expressions of function type - // act exactly like l-values but are formally required to be - // r-values in C. - return expr->isGLValue() || - expr->getType()->isFunctionType() || - hasAggregateEvaluationKind(expr->getType()); - } - - static OpaqueValueMappingData bind(CodeGenFunction &CGF, - const OpaqueValueExpr *ov, - const Expr *e) { - if (shouldBindAsLValue(ov)) - return bind(CGF, ov, CGF.EmitLValue(e)); - return bind(CGF, ov, CGF.EmitAnyExpr(e)); - } - - static OpaqueValueMappingData bind(CodeGenFunction &CGF, - const OpaqueValueExpr *ov, - const LValue &lv) { - assert(shouldBindAsLValue(ov)); - CGF.OpaqueLValues.insert(std::make_pair(ov, lv)); - return OpaqueValueMappingData(ov, true); - } - - static OpaqueValueMappingData bind(CodeGenFunction &CGF, - const OpaqueValueExpr *ov, - const RValue &rv) { - assert(!shouldBindAsLValue(ov)); - CGF.OpaqueRValues.insert(std::make_pair(ov, rv)); - - OpaqueValueMappingData data(ov, false); - - // Work around an extremely aggressive peephole optimization in - // EmitScalarConversion which assumes that all other uses of a - // value are extant. - data.Protection = CGF.protectFromPeepholes(rv); - - return data; - } - - bool isValid() const { return OpaqueValue != nullptr; } - void clear() { OpaqueValue = nullptr; } - - void unbind(CodeGenFunction &CGF) { - assert(OpaqueValue && "no data to unbind!"); - - if (BoundLValue) { - CGF.OpaqueLValues.erase(OpaqueValue); - } else { - CGF.OpaqueRValues.erase(OpaqueValue); - CGF.unprotectFromPeepholes(Protection); - } - } - }; - - /// An RAII object to set (and then clear) a mapping for an OpaqueValueExpr. - class OpaqueValueMapping { - CodeGenFunction &CGF; - OpaqueValueMappingData Data; - - public: - static bool shouldBindAsLValue(const Expr *expr) { - return OpaqueValueMappingData::shouldBindAsLValue(expr); - } - - /// Build the opaque value mapping for the given conditional - /// operator if it's the GNU ?: extension. This is a common - /// enough pattern that the convenience operator is really - /// helpful. - /// - OpaqueValueMapping(CodeGenFunction &CGF, - const AbstractConditionalOperator *op) : CGF(CGF) { - if (isa<ConditionalOperator>(op)) - // Leave Data empty. - return; - - const BinaryConditionalOperator *e = cast<BinaryConditionalOperator>(op); - Data = OpaqueValueMappingData::bind(CGF, e->getOpaqueValue(), - e->getCommon()); - } - - /// Build the opaque value mapping for an OpaqueValueExpr whose source - /// expression is set to the expression the OVE represents. - OpaqueValueMapping(CodeGenFunction &CGF, const OpaqueValueExpr *OV) - : CGF(CGF) { - if (OV) { - assert(OV->getSourceExpr() && "wrong form of OpaqueValueMapping used " - "for OVE with no source expression"); - Data = OpaqueValueMappingData::bind(CGF, OV, OV->getSourceExpr()); - } - } - - OpaqueValueMapping(CodeGenFunction &CGF, - const OpaqueValueExpr *opaqueValue, - LValue lvalue) - : CGF(CGF), Data(OpaqueValueMappingData::bind(CGF, opaqueValue, lvalue)) { - } - - OpaqueValueMapping(CodeGenFunction &CGF, - const OpaqueValueExpr *opaqueValue, - RValue rvalue) - : CGF(CGF), Data(OpaqueValueMappingData::bind(CGF, opaqueValue, rvalue)) { - } - - void pop() { - Data.unbind(CGF); - Data.clear(); - } - - ~OpaqueValueMapping() { - if (Data.isValid()) Data.unbind(CGF); - } - }; - -private: - CGDebugInfo *DebugInfo; - /// Used to create unique names for artificial VLA size debug info variables. - unsigned VLAExprCounter = 0; - bool DisableDebugInfo = false; - - /// DidCallStackSave - Whether llvm.stacksave has been called. Used to avoid - /// calling llvm.stacksave for multiple VLAs in the same scope. - bool DidCallStackSave = false; - - /// IndirectBranch - The first time an indirect goto is seen we create a block - /// with an indirect branch. Every time we see the address of a label taken, - /// we add the label to the indirect goto. Every subsequent indirect goto is - /// codegen'd as a jump to the IndirectBranch's basic block. - llvm::IndirectBrInst *IndirectBranch = nullptr; - - /// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C - /// decls. - DeclMapTy LocalDeclMap; - - // Keep track of the cleanups for callee-destructed parameters pushed to the - // cleanup stack so that they can be deactivated later. - llvm::DenseMap<const ParmVarDecl *, EHScopeStack::stable_iterator> - CalleeDestructedParamCleanups; - - /// SizeArguments - If a ParmVarDecl had the pass_object_size attribute, this - /// will contain a mapping from said ParmVarDecl to its implicit "object_size" - /// parameter. - llvm::SmallDenseMap<const ParmVarDecl *, const ImplicitParamDecl *, 2> - SizeArguments; - - /// Track escaped local variables with auto storage. Used during SEH - /// outlining to produce a call to llvm.localescape. - llvm::DenseMap<llvm::AllocaInst *, int> EscapedLocals; - - /// LabelMap - This keeps track of the LLVM basic block for each C label. - llvm::DenseMap<const LabelDecl*, JumpDest> LabelMap; - - // BreakContinueStack - This keeps track of where break and continue - // statements should jump to. - struct BreakContinue { - BreakContinue(JumpDest Break, JumpDest Continue) - : BreakBlock(Break), ContinueBlock(Continue) {} - - JumpDest BreakBlock; - JumpDest ContinueBlock; - }; - SmallVector<BreakContinue, 8> BreakContinueStack; - - /// Handles cancellation exit points in OpenMP-related constructs. - class OpenMPCancelExitStack { - /// Tracks cancellation exit point and join point for cancel-related exit - /// and normal exit. - struct CancelExit { - CancelExit() = default; - CancelExit(OpenMPDirectiveKind Kind, JumpDest ExitBlock, - JumpDest ContBlock) - : Kind(Kind), ExitBlock(ExitBlock), ContBlock(ContBlock) {} - OpenMPDirectiveKind Kind = OMPD_unknown; - /// true if the exit block has been emitted already by the special - /// emitExit() call, false if the default codegen is used. - bool HasBeenEmitted = false; - JumpDest ExitBlock; - JumpDest ContBlock; - }; - - SmallVector<CancelExit, 8> Stack; - - public: - OpenMPCancelExitStack() : Stack(1) {} - ~OpenMPCancelExitStack() = default; - /// Fetches the exit block for the current OpenMP construct. - JumpDest getExitBlock() const { return Stack.back().ExitBlock; } - /// Emits exit block with special codegen procedure specific for the related - /// OpenMP construct + emits code for normal construct cleanup. - void emitExit(CodeGenFunction &CGF, OpenMPDirectiveKind Kind, - const llvm::function_ref<void(CodeGenFunction &)> CodeGen) { - if (Stack.back().Kind == Kind && getExitBlock().isValid()) { - assert(CGF.getOMPCancelDestination(Kind).isValid()); - assert(CGF.HaveInsertPoint()); - assert(!Stack.back().HasBeenEmitted); - auto IP = CGF.Builder.saveAndClearIP(); - CGF.EmitBlock(Stack.back().ExitBlock.getBlock()); - CodeGen(CGF); - CGF.EmitBranch(Stack.back().ContBlock.getBlock()); - CGF.Builder.restoreIP(IP); - Stack.back().HasBeenEmitted = true; - } - CodeGen(CGF); - } - /// Enter the cancel supporting \a Kind construct. - /// \param Kind OpenMP directive that supports cancel constructs. - /// \param HasCancel true, if the construct has inner cancel directive, - /// false otherwise. - void enter(CodeGenFunction &CGF, OpenMPDirectiveKind Kind, bool HasCancel) { - Stack.push_back({Kind, - HasCancel ? CGF.getJumpDestInCurrentScope("cancel.exit") - : JumpDest(), - HasCancel ? CGF.getJumpDestInCurrentScope("cancel.cont") - : JumpDest()}); - } - /// Emits default exit point for the cancel construct (if the special one - /// has not be used) + join point for cancel/normal exits. - void exit(CodeGenFunction &CGF) { - if (getExitBlock().isValid()) { - assert(CGF.getOMPCancelDestination(Stack.back().Kind).isValid()); - bool HaveIP = CGF.HaveInsertPoint(); - if (!Stack.back().HasBeenEmitted) { - if (HaveIP) - CGF.EmitBranchThroughCleanup(Stack.back().ContBlock); - CGF.EmitBlock(Stack.back().ExitBlock.getBlock()); - CGF.EmitBranchThroughCleanup(Stack.back().ContBlock); - } - CGF.EmitBlock(Stack.back().ContBlock.getBlock()); - if (!HaveIP) { - CGF.Builder.CreateUnreachable(); - CGF.Builder.ClearInsertionPoint(); - } - } - Stack.pop_back(); - } - }; - OpenMPCancelExitStack OMPCancelStack; - - CodeGenPGO PGO; - - /// Calculate branch weights appropriate for PGO data - llvm::MDNode *createProfileWeights(uint64_t TrueCount, uint64_t FalseCount); - llvm::MDNode *createProfileWeights(ArrayRef<uint64_t> Weights); - llvm::MDNode *createProfileWeightsForLoop(const Stmt *Cond, - uint64_t LoopCount); - -public: - /// Increment the profiler's counter for the given statement by \p StepV. - /// If \p StepV is null, the default increment is 1. - void incrementProfileCounter(const Stmt *S, llvm::Value *StepV = nullptr) { - if (CGM.getCodeGenOpts().hasProfileClangInstr()) - PGO.emitCounterIncrement(Builder, S, StepV); - PGO.setCurrentStmt(S); - } - - /// Get the profiler's count for the given statement. - uint64_t getProfileCount(const Stmt *S) { - Optional<uint64_t> Count = PGO.getStmtCount(S); - if (!Count.hasValue()) - return 0; - return *Count; - } - - /// Set the profiler's current count. - void setCurrentProfileCount(uint64_t Count) { - PGO.setCurrentRegionCount(Count); - } - - /// Get the profiler's current count. This is generally the count for the most - /// recently incremented counter. - uint64_t getCurrentProfileCount() { - return PGO.getCurrentRegionCount(); - } - -private: - - /// SwitchInsn - This is nearest current switch instruction. It is null if - /// current context is not in a switch. - llvm::SwitchInst *SwitchInsn = nullptr; - /// The branch weights of SwitchInsn when doing instrumentation based PGO. - SmallVector<uint64_t, 16> *SwitchWeights = nullptr; - - /// CaseRangeBlock - This block holds if condition check for last case - /// statement range in current switch instruction. - llvm::BasicBlock *CaseRangeBlock = nullptr; - - /// OpaqueLValues - Keeps track of the current set of opaque value - /// expressions. - llvm::DenseMap<const OpaqueValueExpr *, LValue> OpaqueLValues; - llvm::DenseMap<const OpaqueValueExpr *, RValue> OpaqueRValues; - - // VLASizeMap - This keeps track of the associated size for each VLA type. - // We track this by the size expression rather than the type itself because - // in certain situations, like a const qualifier applied to an VLA typedef, - // multiple VLA types can share the same size expression. - // FIXME: Maybe this could be a stack of maps that is pushed/popped as we - // enter/leave scopes. - llvm::DenseMap<const Expr*, llvm::Value*> VLASizeMap; - - /// A block containing a single 'unreachable' instruction. Created - /// lazily by getUnreachableBlock(). - llvm::BasicBlock *UnreachableBlock = nullptr; - - /// Counts of the number return expressions in the function. - unsigned NumReturnExprs = 0; - - /// Count the number of simple (constant) return expressions in the function. - unsigned NumSimpleReturnExprs = 0; - - /// The last regular (non-return) debug location (breakpoint) in the function. - SourceLocation LastStopPoint; - -public: - /// A scope within which we are constructing the fields of an object which - /// might use a CXXDefaultInitExpr. This stashes away a 'this' value to use - /// if we need to evaluate a CXXDefaultInitExpr within the evaluation. - class FieldConstructionScope { - public: - FieldConstructionScope(CodeGenFunction &CGF, Address This) - : CGF(CGF), OldCXXDefaultInitExprThis(CGF.CXXDefaultInitExprThis) { - CGF.CXXDefaultInitExprThis = This; - } - ~FieldConstructionScope() { - CGF.CXXDefaultInitExprThis = OldCXXDefaultInitExprThis; - } - - private: - CodeGenFunction &CGF; - Address OldCXXDefaultInitExprThis; - }; - - /// The scope of a CXXDefaultInitExpr. Within this scope, the value of 'this' - /// is overridden to be the object under construction. - class CXXDefaultInitExprScope { - public: - CXXDefaultInitExprScope(CodeGenFunction &CGF) - : CGF(CGF), OldCXXThisValue(CGF.CXXThisValue), - OldCXXThisAlignment(CGF.CXXThisAlignment) { - CGF.CXXThisValue = CGF.CXXDefaultInitExprThis.getPointer(); - CGF.CXXThisAlignment = CGF.CXXDefaultInitExprThis.getAlignment(); - } - ~CXXDefaultInitExprScope() { - CGF.CXXThisValue = OldCXXThisValue; - CGF.CXXThisAlignment = OldCXXThisAlignment; - } - - public: - CodeGenFunction &CGF; - llvm::Value *OldCXXThisValue; - CharUnits OldCXXThisAlignment; - }; - - /// The scope of an ArrayInitLoopExpr. Within this scope, the value of the - /// current loop index is overridden. - class ArrayInitLoopExprScope { - public: - ArrayInitLoopExprScope(CodeGenFunction &CGF, llvm::Value *Index) - : CGF(CGF), OldArrayInitIndex(CGF.ArrayInitIndex) { - CGF.ArrayInitIndex = Index; - } - ~ArrayInitLoopExprScope() { - CGF.ArrayInitIndex = OldArrayInitIndex; - } - - private: - CodeGenFunction &CGF; - llvm::Value *OldArrayInitIndex; - }; - - class InlinedInheritingConstructorScope { - public: - InlinedInheritingConstructorScope(CodeGenFunction &CGF, GlobalDecl GD) - : CGF(CGF), OldCurGD(CGF.CurGD), OldCurFuncDecl(CGF.CurFuncDecl), - OldCurCodeDecl(CGF.CurCodeDecl), - OldCXXABIThisDecl(CGF.CXXABIThisDecl), - OldCXXABIThisValue(CGF.CXXABIThisValue), - OldCXXThisValue(CGF.CXXThisValue), - OldCXXABIThisAlignment(CGF.CXXABIThisAlignment), - OldCXXThisAlignment(CGF.CXXThisAlignment), - OldReturnValue(CGF.ReturnValue), OldFnRetTy(CGF.FnRetTy), - OldCXXInheritedCtorInitExprArgs( - std::move(CGF.CXXInheritedCtorInitExprArgs)) { - CGF.CurGD = GD; - CGF.CurFuncDecl = CGF.CurCodeDecl = - cast<CXXConstructorDecl>(GD.getDecl()); - CGF.CXXABIThisDecl = nullptr; - CGF.CXXABIThisValue = nullptr; - CGF.CXXThisValue = nullptr; - CGF.CXXABIThisAlignment = CharUnits(); - CGF.CXXThisAlignment = CharUnits(); - CGF.ReturnValue = Address::invalid(); - CGF.FnRetTy = QualType(); - CGF.CXXInheritedCtorInitExprArgs.clear(); - } - ~InlinedInheritingConstructorScope() { - CGF.CurGD = OldCurGD; - CGF.CurFuncDecl = OldCurFuncDecl; - CGF.CurCodeDecl = OldCurCodeDecl; - CGF.CXXABIThisDecl = OldCXXABIThisDecl; - CGF.CXXABIThisValue = OldCXXABIThisValue; - CGF.CXXThisValue = OldCXXThisValue; - CGF.CXXABIThisAlignment = OldCXXABIThisAlignment; - CGF.CXXThisAlignment = OldCXXThisAlignment; - CGF.ReturnValue = OldReturnValue; - CGF.FnRetTy = OldFnRetTy; - CGF.CXXInheritedCtorInitExprArgs = - std::move(OldCXXInheritedCtorInitExprArgs); - } - - private: - CodeGenFunction &CGF; - GlobalDecl OldCurGD; - const Decl *OldCurFuncDecl; - const Decl *OldCurCodeDecl; - ImplicitParamDecl *OldCXXABIThisDecl; - llvm::Value *OldCXXABIThisValue; - llvm::Value *OldCXXThisValue; - CharUnits OldCXXABIThisAlignment; - CharUnits OldCXXThisAlignment; - Address OldReturnValue; - QualType OldFnRetTy; - CallArgList OldCXXInheritedCtorInitExprArgs; - }; - -private: - /// CXXThisDecl - When generating code for a C++ member function, - /// this will hold the implicit 'this' declaration. - ImplicitParamDecl *CXXABIThisDecl = nullptr; - llvm::Value *CXXABIThisValue = nullptr; - llvm::Value *CXXThisValue = nullptr; - CharUnits CXXABIThisAlignment; - CharUnits CXXThisAlignment; - - /// The value of 'this' to use when evaluating CXXDefaultInitExprs within - /// this expression. - Address CXXDefaultInitExprThis = Address::invalid(); - - /// The current array initialization index when evaluating an - /// ArrayInitIndexExpr within an ArrayInitLoopExpr. - llvm::Value *ArrayInitIndex = nullptr; - - /// The values of function arguments to use when evaluating - /// CXXInheritedCtorInitExprs within this context. - CallArgList CXXInheritedCtorInitExprArgs; - - /// CXXStructorImplicitParamDecl - When generating code for a constructor or - /// destructor, this will hold the implicit argument (e.g. VTT). - ImplicitParamDecl *CXXStructorImplicitParamDecl = nullptr; - llvm::Value *CXXStructorImplicitParamValue = nullptr; - - /// OutermostConditional - Points to the outermost active - /// conditional control. This is used so that we know if a - /// temporary should be destroyed conditionally. - ConditionalEvaluation *OutermostConditional = nullptr; - - /// The current lexical scope. - LexicalScope *CurLexicalScope = nullptr; - - /// The current source location that should be used for exception - /// handling code. - SourceLocation CurEHLocation; - - /// BlockByrefInfos - For each __block variable, contains - /// information about the layout of the variable. - llvm::DenseMap<const ValueDecl *, BlockByrefInfo> BlockByrefInfos; - - /// Used by -fsanitize=nullability-return to determine whether the return - /// value can be checked. - llvm::Value *RetValNullabilityPrecondition = nullptr; - - /// Check if -fsanitize=nullability-return instrumentation is required for - /// this function. - bool requiresReturnValueNullabilityCheck() const { - return RetValNullabilityPrecondition; - } - - /// Used to store precise source locations for return statements by the - /// runtime return value checks. - Address ReturnLocation = Address::invalid(); - - /// Check if the return value of this function requires sanitization. - bool requiresReturnValueCheck() const { - return requiresReturnValueNullabilityCheck() || - (SanOpts.has(SanitizerKind::ReturnsNonnullAttribute) && - CurCodeDecl && CurCodeDecl->getAttr<ReturnsNonNullAttr>()); - } - - llvm::BasicBlock *TerminateLandingPad = nullptr; - llvm::BasicBlock *TerminateHandler = nullptr; - llvm::BasicBlock *TrapBB = nullptr; - - /// Terminate funclets keyed by parent funclet pad. - llvm::MapVector<llvm::Value *, llvm::BasicBlock *> TerminateFunclets; - - /// Largest vector width used in ths function. Will be used to create a - /// function attribute. - unsigned LargestVectorWidth = 0; - - /// True if we need emit the life-time markers. - const bool ShouldEmitLifetimeMarkers; - - /// Add OpenCL kernel arg metadata and the kernel attribute metadata to - /// the function metadata. - void EmitOpenCLKernelMetadata(const FunctionDecl *FD, - llvm::Function *Fn); - -public: - CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext=false); - ~CodeGenFunction(); - - CodeGenTypes &getTypes() const { return CGM.getTypes(); } - ASTContext &getContext() const { return CGM.getContext(); } - CGDebugInfo *getDebugInfo() { - if (DisableDebugInfo) - return nullptr; - return DebugInfo; - } - void disableDebugInfo() { DisableDebugInfo = true; } - void enableDebugInfo() { DisableDebugInfo = false; } - - bool shouldUseFusedARCCalls() { - return CGM.getCodeGenOpts().OptimizationLevel == 0; - } - - const LangOptions &getLangOpts() const { return CGM.getLangOpts(); } - - /// Returns a pointer to the function's exception object and selector slot, - /// which is assigned in every landing pad. - Address getExceptionSlot(); - Address getEHSelectorSlot(); - - /// Returns the contents of the function's exception object and selector - /// slots. - llvm::Value *getExceptionFromSlot(); - llvm::Value *getSelectorFromSlot(); - - Address getNormalCleanupDestSlot(); - - llvm::BasicBlock *getUnreachableBlock() { - if (!UnreachableBlock) { - UnreachableBlock = createBasicBlock("unreachable"); - new llvm::UnreachableInst(getLLVMContext(), UnreachableBlock); - } - return UnreachableBlock; - } - - llvm::BasicBlock *getInvokeDest() { - if (!EHStack.requiresLandingPad()) return nullptr; - return getInvokeDestImpl(); - } - - bool currentFunctionUsesSEHTry() const { return CurSEHParent != nullptr; } - - const TargetInfo &getTarget() const { return Target; } - llvm::LLVMContext &getLLVMContext() { return CGM.getLLVMContext(); } - const TargetCodeGenInfo &getTargetHooks() const { - return CGM.getTargetCodeGenInfo(); - } - - //===--------------------------------------------------------------------===// - // Cleanups - //===--------------------------------------------------------------------===// - - typedef void Destroyer(CodeGenFunction &CGF, Address addr, QualType ty); - - void pushIrregularPartialArrayCleanup(llvm::Value *arrayBegin, - Address arrayEndPointer, - QualType elementType, - CharUnits elementAlignment, - Destroyer *destroyer); - void pushRegularPartialArrayCleanup(llvm::Value *arrayBegin, - llvm::Value *arrayEnd, - QualType elementType, - CharUnits elementAlignment, - Destroyer *destroyer); - - void pushDestroy(QualType::DestructionKind dtorKind, - Address addr, QualType type); - void pushEHDestroy(QualType::DestructionKind dtorKind, - Address addr, QualType type); - void pushDestroy(CleanupKind kind, Address addr, QualType type, - Destroyer *destroyer, bool useEHCleanupForArray); - void pushLifetimeExtendedDestroy(CleanupKind kind, Address addr, - QualType type, Destroyer *destroyer, - bool useEHCleanupForArray); - void pushCallObjectDeleteCleanup(const FunctionDecl *OperatorDelete, - llvm::Value *CompletePtr, - QualType ElementType); - void pushStackRestore(CleanupKind kind, Address SPMem); - void emitDestroy(Address addr, QualType type, Destroyer *destroyer, - bool useEHCleanupForArray); - llvm::Function *generateDestroyHelper(Address addr, QualType type, - Destroyer *destroyer, - bool useEHCleanupForArray, - const VarDecl *VD); - void emitArrayDestroy(llvm::Value *begin, llvm::Value *end, - QualType elementType, CharUnits elementAlign, - Destroyer *destroyer, - bool checkZeroLength, bool useEHCleanup); - - Destroyer *getDestroyer(QualType::DestructionKind destructionKind); - - /// Determines whether an EH cleanup is required to destroy a type - /// with the given destruction kind. - bool needsEHCleanup(QualType::DestructionKind kind) { - switch (kind) { - case QualType::DK_none: - return false; - case QualType::DK_cxx_destructor: - case QualType::DK_objc_weak_lifetime: - case QualType::DK_nontrivial_c_struct: - return getLangOpts().Exceptions; - case QualType::DK_objc_strong_lifetime: - return getLangOpts().Exceptions && - CGM.getCodeGenOpts().ObjCAutoRefCountExceptions; - } - llvm_unreachable("bad destruction kind"); - } - - CleanupKind getCleanupKind(QualType::DestructionKind kind) { - return (needsEHCleanup(kind) ? NormalAndEHCleanup : NormalCleanup); - } - - //===--------------------------------------------------------------------===// - // Objective-C - //===--------------------------------------------------------------------===// - - void GenerateObjCMethod(const ObjCMethodDecl *OMD); - - void StartObjCMethod(const ObjCMethodDecl *MD, const ObjCContainerDecl *CD); - - /// GenerateObjCGetter - Synthesize an Objective-C property getter function. - void GenerateObjCGetter(ObjCImplementationDecl *IMP, - const ObjCPropertyImplDecl *PID); - void generateObjCGetterBody(const ObjCImplementationDecl *classImpl, - const ObjCPropertyImplDecl *propImpl, - const ObjCMethodDecl *GetterMothodDecl, - llvm::Constant *AtomicHelperFn); - - void GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP, - ObjCMethodDecl *MD, bool ctor); - - /// GenerateObjCSetter - Synthesize an Objective-C property setter function - /// for the given property. - void GenerateObjCSetter(ObjCImplementationDecl *IMP, - const ObjCPropertyImplDecl *PID); - void generateObjCSetterBody(const ObjCImplementationDecl *classImpl, - const ObjCPropertyImplDecl *propImpl, - llvm::Constant *AtomicHelperFn); - - //===--------------------------------------------------------------------===// - // Block Bits - //===--------------------------------------------------------------------===// - - /// Emit block literal. - /// \return an LLVM value which is a pointer to a struct which contains - /// information about the block, including the block invoke function, the - /// captured variables, etc. - llvm::Value *EmitBlockLiteral(const BlockExpr *); - static void destroyBlockInfos(CGBlockInfo *info); - - llvm::Function *GenerateBlockFunction(GlobalDecl GD, - const CGBlockInfo &Info, - const DeclMapTy &ldm, - bool IsLambdaConversionToBlock, - bool BuildGlobalBlock); - - /// Check if \p T is a C++ class that has a destructor that can throw. - static bool cxxDestructorCanThrow(QualType T); - - llvm::Constant *GenerateCopyHelperFunction(const CGBlockInfo &blockInfo); - llvm::Constant *GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo); - llvm::Constant *GenerateObjCAtomicSetterCopyHelperFunction( - const ObjCPropertyImplDecl *PID); - llvm::Constant *GenerateObjCAtomicGetterCopyHelperFunction( - const ObjCPropertyImplDecl *PID); - llvm::Value *EmitBlockCopyAndAutorelease(llvm::Value *Block, QualType Ty); - - void BuildBlockRelease(llvm::Value *DeclPtr, BlockFieldFlags flags, - bool CanThrow); - - class AutoVarEmission; - - void emitByrefStructureInit(const AutoVarEmission &emission); - - /// Enter a cleanup to destroy a __block variable. Note that this - /// cleanup should be a no-op if the variable hasn't left the stack - /// yet; if a cleanup is required for the variable itself, that needs - /// to be done externally. - /// - /// \param Kind Cleanup kind. - /// - /// \param Addr When \p LoadBlockVarAddr is false, the address of the __block - /// structure that will be passed to _Block_object_dispose. When - /// \p LoadBlockVarAddr is true, the address of the field of the block - /// structure that holds the address of the __block structure. - /// - /// \param Flags The flag that will be passed to _Block_object_dispose. - /// - /// \param LoadBlockVarAddr Indicates whether we need to emit a load from - /// \p Addr to get the address of the __block structure. - void enterByrefCleanup(CleanupKind Kind, Address Addr, BlockFieldFlags Flags, - bool LoadBlockVarAddr, bool CanThrow); - - void setBlockContextParameter(const ImplicitParamDecl *D, unsigned argNum, - llvm::Value *ptr); - - Address LoadBlockStruct(); - Address GetAddrOfBlockDecl(const VarDecl *var); - - /// BuildBlockByrefAddress - Computes the location of the - /// data in a variable which is declared as __block. - Address emitBlockByrefAddress(Address baseAddr, const VarDecl *V, - bool followForward = true); - Address emitBlockByrefAddress(Address baseAddr, - const BlockByrefInfo &info, - bool followForward, - const llvm::Twine &name); - - const BlockByrefInfo &getBlockByrefInfo(const VarDecl *var); - - QualType BuildFunctionArgList(GlobalDecl GD, FunctionArgList &Args); - - void GenerateCode(GlobalDecl GD, llvm::Function *Fn, - const CGFunctionInfo &FnInfo); - - /// Annotate the function with an attribute that disables TSan checking at - /// runtime. - void markAsIgnoreThreadCheckingAtRuntime(llvm::Function *Fn); - - /// Emit code for the start of a function. - /// \param Loc The location to be associated with the function. - /// \param StartLoc The location of the function body. - void StartFunction(GlobalDecl GD, - QualType RetTy, - llvm::Function *Fn, - const CGFunctionInfo &FnInfo, - const FunctionArgList &Args, - SourceLocation Loc = SourceLocation(), - SourceLocation StartLoc = SourceLocation()); - - static bool IsConstructorDelegationValid(const CXXConstructorDecl *Ctor); - - void EmitConstructorBody(FunctionArgList &Args); - void EmitDestructorBody(FunctionArgList &Args); - void emitImplicitAssignmentOperatorBody(FunctionArgList &Args); - void EmitFunctionBody(const Stmt *Body); - void EmitBlockWithFallThrough(llvm::BasicBlock *BB, const Stmt *S); - - void EmitForwardingCallToLambda(const CXXMethodDecl *LambdaCallOperator, - CallArgList &CallArgs); - void EmitLambdaBlockInvokeBody(); - void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD); - void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD); - void EmitAsanPrologueOrEpilogue(bool Prologue); - - /// Emit the unified return block, trying to avoid its emission when - /// possible. - /// \return The debug location of the user written return statement if the - /// return block is is avoided. - llvm::DebugLoc EmitReturnBlock(); - - /// FinishFunction - Complete IR generation of the current function. It is - /// legal to call this function even if there is no current insertion point. - void FinishFunction(SourceLocation EndLoc=SourceLocation()); - - void StartThunk(llvm::Function *Fn, GlobalDecl GD, - const CGFunctionInfo &FnInfo, bool IsUnprototyped); - - void EmitCallAndReturnForThunk(llvm::Constant *Callee, const ThunkInfo *Thunk, - bool IsUnprototyped); - - void FinishThunk(); - - /// Emit a musttail call for a thunk with a potentially adjusted this pointer. - void EmitMustTailThunk(GlobalDecl GD, llvm::Value *AdjustedThisPtr, - llvm::Value *Callee); - - /// Generate a thunk for the given method. - void generateThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo, - GlobalDecl GD, const ThunkInfo &Thunk, - bool IsUnprototyped); - - llvm::Function *GenerateVarArgsThunk(llvm::Function *Fn, - const CGFunctionInfo &FnInfo, - GlobalDecl GD, const ThunkInfo &Thunk); - - void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type, - FunctionArgList &Args); - - void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init); - - /// Struct with all information about dynamic [sub]class needed to set vptr. - struct VPtr { - BaseSubobject Base; - const CXXRecordDecl *NearestVBase; - CharUnits OffsetFromNearestVBase; - const CXXRecordDecl *VTableClass; - }; - - /// Initialize the vtable pointer of the given subobject. - void InitializeVTablePointer(const VPtr &vptr); - - typedef llvm::SmallVector<VPtr, 4> VPtrsVector; - - typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy; - VPtrsVector getVTablePointers(const CXXRecordDecl *VTableClass); - - void getVTablePointers(BaseSubobject Base, const CXXRecordDecl *NearestVBase, - CharUnits OffsetFromNearestVBase, - bool BaseIsNonVirtualPrimaryBase, - const CXXRecordDecl *VTableClass, - VisitedVirtualBasesSetTy &VBases, VPtrsVector &vptrs); - - void InitializeVTablePointers(const CXXRecordDecl *ClassDecl); - - /// GetVTablePtr - Return the Value of the vtable pointer member pointed - /// to by This. - llvm::Value *GetVTablePtr(Address This, llvm::Type *VTableTy, - const CXXRecordDecl *VTableClass); - - enum CFITypeCheckKind { - CFITCK_VCall, - CFITCK_NVCall, - CFITCK_DerivedCast, - CFITCK_UnrelatedCast, - CFITCK_ICall, - CFITCK_NVMFCall, - CFITCK_VMFCall, - }; - - /// Derived is the presumed address of an object of type T after a - /// cast. If T is a polymorphic class type, emit a check that the virtual - /// table for Derived belongs to a class derived from T. - void EmitVTablePtrCheckForCast(QualType T, llvm::Value *Derived, - bool MayBeNull, CFITypeCheckKind TCK, - SourceLocation Loc); - - /// EmitVTablePtrCheckForCall - Virtual method MD is being called via VTable. - /// If vptr CFI is enabled, emit a check that VTable is valid. - void EmitVTablePtrCheckForCall(const CXXRecordDecl *RD, llvm::Value *VTable, - CFITypeCheckKind TCK, SourceLocation Loc); - - /// EmitVTablePtrCheck - Emit a check that VTable is a valid virtual table for - /// RD using llvm.type.test. - void EmitVTablePtrCheck(const CXXRecordDecl *RD, llvm::Value *VTable, - CFITypeCheckKind TCK, SourceLocation Loc); - - /// If whole-program virtual table optimization is enabled, emit an assumption - /// that VTable is a member of RD's type identifier. Or, if vptr CFI is - /// enabled, emit a check that VTable is a member of RD's type identifier. - void EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD, - llvm::Value *VTable, SourceLocation Loc); - - /// Returns whether we should perform a type checked load when loading a - /// virtual function for virtual calls to members of RD. This is generally - /// true when both vcall CFI and whole-program-vtables are enabled. - bool ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD); - - /// Emit a type checked load from the given vtable. - llvm::Value *EmitVTableTypeCheckedLoad(const CXXRecordDecl *RD, llvm::Value *VTable, - uint64_t VTableByteOffset); - - /// EnterDtorCleanups - Enter the cleanups necessary to complete the - /// given phase of destruction for a destructor. The end result - /// should call destructors on members and base classes in reverse - /// order of their construction. - void EnterDtorCleanups(const CXXDestructorDecl *Dtor, CXXDtorType Type); - - /// ShouldInstrumentFunction - Return true if the current function should be - /// instrumented with __cyg_profile_func_* calls - bool ShouldInstrumentFunction(); - - /// ShouldXRayInstrument - Return true if the current function should be - /// instrumented with XRay nop sleds. - bool ShouldXRayInstrumentFunction() const; - - /// AlwaysEmitXRayCustomEvents - Return true if we must unconditionally emit - /// XRay custom event handling calls. - bool AlwaysEmitXRayCustomEvents() const; - - /// AlwaysEmitXRayTypedEvents - Return true if clang must unconditionally emit - /// XRay typed event handling calls. - bool AlwaysEmitXRayTypedEvents() const; - - /// Encode an address into a form suitable for use in a function prologue. - llvm::Constant *EncodeAddrForUseInPrologue(llvm::Function *F, - llvm::Constant *Addr); - - /// Decode an address used in a function prologue, encoded by \c - /// EncodeAddrForUseInPrologue. - llvm::Value *DecodeAddrUsedInPrologue(llvm::Value *F, - llvm::Value *EncodedAddr); - - /// EmitFunctionProlog - Emit the target specific LLVM code to load the - /// arguments for the given function. This is also responsible for naming the - /// LLVM function arguments. - void EmitFunctionProlog(const CGFunctionInfo &FI, - llvm::Function *Fn, - const FunctionArgList &Args); - - /// EmitFunctionEpilog - Emit the target specific LLVM code to return the - /// given temporary. - void EmitFunctionEpilog(const CGFunctionInfo &FI, bool EmitRetDbgLoc, - SourceLocation EndLoc); - - /// Emit a test that checks if the return value \p RV is nonnull. - void EmitReturnValueCheck(llvm::Value *RV); - - /// EmitStartEHSpec - Emit the start of the exception spec. - void EmitStartEHSpec(const Decl *D); - - /// EmitEndEHSpec - Emit the end of the exception spec. - void EmitEndEHSpec(const Decl *D); - - /// getTerminateLandingPad - Return a landing pad that just calls terminate. - llvm::BasicBlock *getTerminateLandingPad(); - - /// getTerminateLandingPad - Return a cleanup funclet that just calls - /// terminate. - llvm::BasicBlock *getTerminateFunclet(); - - /// getTerminateHandler - Return a handler (not a landing pad, just - /// a catch handler) that just calls terminate. This is used when - /// a terminate scope encloses a try. - llvm::BasicBlock *getTerminateHandler(); - - llvm::Type *ConvertTypeForMem(QualType T); - llvm::Type *ConvertType(QualType T); - llvm::Type *ConvertType(const TypeDecl *T) { - return ConvertType(getContext().getTypeDeclType(T)); - } - - /// LoadObjCSelf - Load the value of self. This function is only valid while - /// generating code for an Objective-C method. - llvm::Value *LoadObjCSelf(); - - /// TypeOfSelfObject - Return type of object that this self represents. - QualType TypeOfSelfObject(); - - /// getEvaluationKind - Return the TypeEvaluationKind of QualType \c T. - static TypeEvaluationKind getEvaluationKind(QualType T); - - static bool hasScalarEvaluationKind(QualType T) { - return getEvaluationKind(T) == TEK_Scalar; - } - - static bool hasAggregateEvaluationKind(QualType T) { - return getEvaluationKind(T) == TEK_Aggregate; - } - - /// createBasicBlock - Create an LLVM basic block. - llvm::BasicBlock *createBasicBlock(const Twine &name = "", - llvm::Function *parent = nullptr, - llvm::BasicBlock *before = nullptr) { - return llvm::BasicBlock::Create(getLLVMContext(), name, parent, before); - } - - /// getBasicBlockForLabel - Return the LLVM basicblock that the specified - /// label maps to. - JumpDest getJumpDestForLabel(const LabelDecl *S); - - /// SimplifyForwardingBlocks - If the given basic block is only a branch to - /// another basic block, simplify it. This assumes that no other code could - /// potentially reference the basic block. - void SimplifyForwardingBlocks(llvm::BasicBlock *BB); - - /// EmitBlock - Emit the given block \arg BB and set it as the insert point, - /// adding a fall-through branch from the current insert block if - /// necessary. It is legal to call this function even if there is no current - /// insertion point. - /// - /// IsFinished - If true, indicates that the caller has finished emitting - /// branches to the given block and does not expect to emit code into it. This - /// means the block can be ignored if it is unreachable. - void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false); - - /// EmitBlockAfterUses - Emit the given block somewhere hopefully - /// near its uses, and leave the insertion point in it. - void EmitBlockAfterUses(llvm::BasicBlock *BB); - - /// EmitBranch - Emit a branch to the specified basic block from the current - /// insert block, taking care to avoid creation of branches from dummy - /// blocks. It is legal to call this function even if there is no current - /// insertion point. - /// - /// This function clears the current insertion point. The caller should follow - /// calls to this function with calls to Emit*Block prior to generation new - /// code. - void EmitBranch(llvm::BasicBlock *Block); - - /// HaveInsertPoint - True if an insertion point is defined. If not, this - /// indicates that the current code being emitted is unreachable. - bool HaveInsertPoint() const { - return Builder.GetInsertBlock() != nullptr; - } - - /// EnsureInsertPoint - Ensure that an insertion point is defined so that - /// emitted IR has a place to go. Note that by definition, if this function - /// creates a block then that block is unreachable; callers may do better to - /// detect when no insertion point is defined and simply skip IR generation. - void EnsureInsertPoint() { - if (!HaveInsertPoint()) - EmitBlock(createBasicBlock()); - } - - /// ErrorUnsupported - Print out an error that codegen doesn't support the - /// specified stmt yet. - void ErrorUnsupported(const Stmt *S, const char *Type); - - //===--------------------------------------------------------------------===// - // Helpers - //===--------------------------------------------------------------------===// - - LValue MakeAddrLValue(Address Addr, QualType T, - AlignmentSource Source = AlignmentSource::Type) { - return LValue::MakeAddr(Addr, T, getContext(), LValueBaseInfo(Source), - CGM.getTBAAAccessInfo(T)); - } - - LValue MakeAddrLValue(Address Addr, QualType T, LValueBaseInfo BaseInfo, - TBAAAccessInfo TBAAInfo) { - return LValue::MakeAddr(Addr, T, getContext(), BaseInfo, TBAAInfo); - } - - LValue MakeAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, - AlignmentSource Source = AlignmentSource::Type) { - return LValue::MakeAddr(Address(V, Alignment), T, getContext(), - LValueBaseInfo(Source), CGM.getTBAAAccessInfo(T)); - } - - LValue MakeAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, - LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { - return LValue::MakeAddr(Address(V, Alignment), T, getContext(), - BaseInfo, TBAAInfo); - } - - LValue MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T); - LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T); - CharUnits getNaturalTypeAlignment(QualType T, - LValueBaseInfo *BaseInfo = nullptr, - TBAAAccessInfo *TBAAInfo = nullptr, - bool forPointeeType = false); - CharUnits getNaturalPointeeTypeAlignment(QualType T, - LValueBaseInfo *BaseInfo = nullptr, - TBAAAccessInfo *TBAAInfo = nullptr); - - Address EmitLoadOfReference(LValue RefLVal, - LValueBaseInfo *PointeeBaseInfo = nullptr, - TBAAAccessInfo *PointeeTBAAInfo = nullptr); - LValue EmitLoadOfReferenceLValue(LValue RefLVal); - LValue EmitLoadOfReferenceLValue(Address RefAddr, QualType RefTy, - AlignmentSource Source = - AlignmentSource::Type) { - LValue RefLVal = MakeAddrLValue(RefAddr, RefTy, LValueBaseInfo(Source), - CGM.getTBAAAccessInfo(RefTy)); - return EmitLoadOfReferenceLValue(RefLVal); - } - - Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, - LValueBaseInfo *BaseInfo = nullptr, - TBAAAccessInfo *TBAAInfo = nullptr); - LValue EmitLoadOfPointerLValue(Address Ptr, const PointerType *PtrTy); - - /// CreateTempAlloca - This creates an alloca and inserts it into the entry - /// block if \p ArraySize is nullptr, otherwise inserts it at the current - /// insertion point of the builder. The caller is responsible for setting an - /// appropriate alignment on - /// the alloca. - /// - /// \p ArraySize is the number of array elements to be allocated if it - /// is not nullptr. - /// - /// LangAS::Default is the address space of pointers to local variables and - /// temporaries, as exposed in the source language. In certain - /// configurations, this is not the same as the alloca address space, and a - /// cast is needed to lift the pointer from the alloca AS into - /// LangAS::Default. This can happen when the target uses a restricted - /// address space for the stack but the source language requires - /// LangAS::Default to be a generic address space. The latter condition is - /// common for most programming languages; OpenCL is an exception in that - /// LangAS::Default is the private address space, which naturally maps - /// to the stack. - /// - /// Because the address of a temporary is often exposed to the program in - /// various ways, this function will perform the cast. The original alloca - /// instruction is returned through \p Alloca if it is not nullptr. - /// - /// The cast is not performaed in CreateTempAllocaWithoutCast. This is - /// more efficient if the caller knows that the address will not be exposed. - llvm::AllocaInst *CreateTempAlloca(llvm::Type *Ty, const Twine &Name = "tmp", - llvm::Value *ArraySize = nullptr); - Address CreateTempAlloca(llvm::Type *Ty, CharUnits align, - const Twine &Name = "tmp", - llvm::Value *ArraySize = nullptr, - Address *Alloca = nullptr); - Address CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits align, - const Twine &Name = "tmp", - llvm::Value *ArraySize = nullptr); - - /// CreateDefaultAlignedTempAlloca - This creates an alloca with the - /// default ABI alignment of the given LLVM type. - /// - /// IMPORTANT NOTE: This is *not* generally the right alignment for - /// any given AST type that happens to have been lowered to the - /// given IR type. This should only ever be used for function-local, - /// IR-driven manipulations like saving and restoring a value. Do - /// not hand this address off to arbitrary IRGen routines, and especially - /// do not pass it as an argument to a function that might expect a - /// properly ABI-aligned value. - Address CreateDefaultAlignTempAlloca(llvm::Type *Ty, - const Twine &Name = "tmp"); - - /// InitTempAlloca - Provide an initial value for the given alloca which - /// will be observable at all locations in the function. - /// - /// The address should be something that was returned from one of - /// the CreateTempAlloca or CreateMemTemp routines, and the - /// initializer must be valid in the entry block (i.e. it must - /// either be a constant or an argument value). - void InitTempAlloca(Address Alloca, llvm::Value *Value); - - /// CreateIRTemp - Create a temporary IR object of the given type, with - /// appropriate alignment. This routine should only be used when an temporary - /// value needs to be stored into an alloca (for example, to avoid explicit - /// PHI construction), but the type is the IR type, not the type appropriate - /// for storing in memory. - /// - /// That is, this is exactly equivalent to CreateMemTemp, but calling - /// ConvertType instead of ConvertTypeForMem. - Address CreateIRTemp(QualType T, const Twine &Name = "tmp"); - - /// CreateMemTemp - Create a temporary memory object of the given type, with - /// appropriate alignmen and cast it to the default address space. Returns - /// the original alloca instruction by \p Alloca if it is not nullptr. - Address CreateMemTemp(QualType T, const Twine &Name = "tmp", - Address *Alloca = nullptr); - Address CreateMemTemp(QualType T, CharUnits Align, const Twine &Name = "tmp", - Address *Alloca = nullptr); - - /// CreateMemTemp - Create a temporary memory object of the given type, with - /// appropriate alignmen without casting it to the default address space. - Address CreateMemTempWithoutCast(QualType T, const Twine &Name = "tmp"); - Address CreateMemTempWithoutCast(QualType T, CharUnits Align, - const Twine &Name = "tmp"); - - /// CreateAggTemp - Create a temporary memory object for the given - /// aggregate type. - AggValueSlot CreateAggTemp(QualType T, const Twine &Name = "tmp") { - return AggValueSlot::forAddr(CreateMemTemp(T, Name), - T.getQualifiers(), - AggValueSlot::IsNotDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - AggValueSlot::DoesNotOverlap); - } - - /// Emit a cast to void* in the appropriate address space. - llvm::Value *EmitCastToVoidPtr(llvm::Value *value); - - /// EvaluateExprAsBool - Perform the usual unary conversions on the specified - /// expression and compare the result against zero, returning an Int1Ty value. - llvm::Value *EvaluateExprAsBool(const Expr *E); - - /// EmitIgnoredExpr - Emit an expression in a context which ignores the result. - void EmitIgnoredExpr(const Expr *E); - - /// EmitAnyExpr - Emit code to compute the specified expression which can have - /// any type. The result is returned as an RValue struct. If this is an - /// aggregate expression, the aggloc/agglocvolatile arguments indicate where - /// the result should be returned. - /// - /// \param ignoreResult True if the resulting value isn't used. - RValue EmitAnyExpr(const Expr *E, - AggValueSlot aggSlot = AggValueSlot::ignored(), - bool ignoreResult = false); - - // EmitVAListRef - Emit a "reference" to a va_list; this is either the address - // or the value of the expression, depending on how va_list is defined. - Address EmitVAListRef(const Expr *E); - - /// Emit a "reference" to a __builtin_ms_va_list; this is - /// always the value of the expression, because a __builtin_ms_va_list is a - /// pointer to a char. - Address EmitMSVAListRef(const Expr *E); - - /// EmitAnyExprToTemp - Similarly to EmitAnyExpr(), however, the result will - /// always be accessible even if no aggregate location is provided. - RValue EmitAnyExprToTemp(const Expr *E); - - /// EmitAnyExprToMem - Emits the code necessary to evaluate an - /// arbitrary expression into the given memory location. - void EmitAnyExprToMem(const Expr *E, Address Location, - Qualifiers Quals, bool IsInitializer); - - void EmitAnyExprToExn(const Expr *E, Address Addr); - - /// EmitExprAsInit - Emits the code necessary to initialize a - /// location in memory with the given initializer. - void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, - bool capturedByInit); - - /// hasVolatileMember - returns true if aggregate type has a volatile - /// member. - bool hasVolatileMember(QualType T) { - if (const RecordType *RT = T->getAs<RecordType>()) { - const RecordDecl *RD = cast<RecordDecl>(RT->getDecl()); - return RD->hasVolatileMember(); - } - return false; - } - - /// Determine whether a return value slot may overlap some other object. - AggValueSlot::Overlap_t overlapForReturnValue() { - // FIXME: Assuming no overlap here breaks guaranteed copy elision for base - // class subobjects. These cases may need to be revisited depending on the - // resolution of the relevant core issue. - return AggValueSlot::DoesNotOverlap; - } - - /// Determine whether a field initialization may overlap some other object. - AggValueSlot::Overlap_t overlapForFieldInit(const FieldDecl *FD) { - // FIXME: These cases can result in overlap as a result of P0840R0's - // [[no_unique_address]] attribute. We can still infer NoOverlap in the - // presence of that attribute if the field is within the nvsize of its - // containing class, because non-virtual subobjects are initialized in - // address order. - return AggValueSlot::DoesNotOverlap; - } - - /// Determine whether a base class initialization may overlap some other - /// object. - AggValueSlot::Overlap_t overlapForBaseInit(const CXXRecordDecl *RD, - const CXXRecordDecl *BaseRD, - bool IsVirtual); - - /// Emit an aggregate assignment. - void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy) { - bool IsVolatile = hasVolatileMember(EltTy); - EmitAggregateCopy(Dest, Src, EltTy, AggValueSlot::MayOverlap, IsVolatile); - } - - void EmitAggregateCopyCtor(LValue Dest, LValue Src, - AggValueSlot::Overlap_t MayOverlap) { - EmitAggregateCopy(Dest, Src, Src.getType(), MayOverlap); - } - - /// EmitAggregateCopy - Emit an aggregate copy. - /// - /// \param isVolatile \c true iff either the source or the destination is - /// volatile. - /// \param MayOverlap Whether the tail padding of the destination might be - /// occupied by some other object. More efficient code can often be - /// generated if not. - void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, - AggValueSlot::Overlap_t MayOverlap, - bool isVolatile = false); - - /// GetAddrOfLocalVar - Return the address of a local variable. - Address GetAddrOfLocalVar(const VarDecl *VD) { - auto it = LocalDeclMap.find(VD); - assert(it != LocalDeclMap.end() && - "Invalid argument to GetAddrOfLocalVar(), no decl!"); - return it->second; - } - - /// Given an opaque value expression, return its LValue mapping if it exists, - /// otherwise create one. - LValue getOrCreateOpaqueLValueMapping(const OpaqueValueExpr *e); - - /// Given an opaque value expression, return its RValue mapping if it exists, - /// otherwise create one. - RValue getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e); - - /// Get the index of the current ArrayInitLoopExpr, if any. - llvm::Value *getArrayInitIndex() { return ArrayInitIndex; } - - /// getAccessedFieldNo - Given an encoded value and a result number, return - /// the input field number being accessed. - static unsigned getAccessedFieldNo(unsigned Idx, const llvm::Constant *Elts); - - llvm::BlockAddress *GetAddrOfLabel(const LabelDecl *L); - llvm::BasicBlock *GetIndirectGotoBlock(); - - /// Check if \p E is a C++ "this" pointer wrapped in value-preserving casts. - static bool IsWrappedCXXThis(const Expr *E); - - /// EmitNullInitialization - Generate code to set a value of the given type to - /// null, If the type contains data member pointers, they will be initialized - /// to -1 in accordance with the Itanium C++ ABI. - void EmitNullInitialization(Address DestPtr, QualType Ty); - - /// Emits a call to an LLVM variable-argument intrinsic, either - /// \c llvm.va_start or \c llvm.va_end. - /// \param ArgValue A reference to the \c va_list as emitted by either - /// \c EmitVAListRef or \c EmitMSVAListRef. - /// \param IsStart If \c true, emits a call to \c llvm.va_start; otherwise, - /// calls \c llvm.va_end. - llvm::Value *EmitVAStartEnd(llvm::Value *ArgValue, bool IsStart); - - /// Generate code to get an argument from the passed in pointer - /// and update it accordingly. - /// \param VE The \c VAArgExpr for which to generate code. - /// \param VAListAddr Receives a reference to the \c va_list as emitted by - /// either \c EmitVAListRef or \c EmitMSVAListRef. - /// \returns A pointer to the argument. - // FIXME: We should be able to get rid of this method and use the va_arg - // instruction in LLVM instead once it works well enough. - Address EmitVAArg(VAArgExpr *VE, Address &VAListAddr); - - /// emitArrayLength - Compute the length of an array, even if it's a - /// VLA, and drill down to the base element type. - llvm::Value *emitArrayLength(const ArrayType *arrayType, - QualType &baseType, - Address &addr); - - /// EmitVLASize - Capture all the sizes for the VLA expressions in - /// the given variably-modified type and store them in the VLASizeMap. - /// - /// This function can be called with a null (unreachable) insert point. - void EmitVariablyModifiedType(QualType Ty); - - struct VlaSizePair { - llvm::Value *NumElts; - QualType Type; - - VlaSizePair(llvm::Value *NE, QualType T) : NumElts(NE), Type(T) {} - }; - - /// Return the number of elements for a single dimension - /// for the given array type. - VlaSizePair getVLAElements1D(const VariableArrayType *vla); - VlaSizePair getVLAElements1D(QualType vla); - - /// Returns an LLVM value that corresponds to the size, - /// in non-variably-sized elements, of a variable length array type, - /// plus that largest non-variably-sized element type. Assumes that - /// the type has already been emitted with EmitVariablyModifiedType. - VlaSizePair getVLASize(const VariableArrayType *vla); - VlaSizePair getVLASize(QualType vla); - - /// LoadCXXThis - Load the value of 'this'. This function is only valid while - /// generating code for an C++ member function. - llvm::Value *LoadCXXThis() { - assert(CXXThisValue && "no 'this' value for this function"); - return CXXThisValue; - } - Address LoadCXXThisAddress(); - - /// LoadCXXVTT - Load the VTT parameter to base constructors/destructors have - /// virtual bases. - // FIXME: Every place that calls LoadCXXVTT is something - // that needs to be abstracted properly. - llvm::Value *LoadCXXVTT() { - assert(CXXStructorImplicitParamValue && "no VTT value for this function"); - return CXXStructorImplicitParamValue; - } - - /// GetAddressOfBaseOfCompleteClass - Convert the given pointer to a - /// complete class to the given direct base. - Address - GetAddressOfDirectBaseInCompleteClass(Address Value, - const CXXRecordDecl *Derived, - const CXXRecordDecl *Base, - bool BaseIsVirtual); - - static bool ShouldNullCheckClassCastValue(const CastExpr *Cast); - - /// GetAddressOfBaseClass - This function will add the necessary delta to the - /// load of 'this' and returns address of the base class. - Address GetAddressOfBaseClass(Address Value, - const CXXRecordDecl *Derived, - CastExpr::path_const_iterator PathBegin, - CastExpr::path_const_iterator PathEnd, - bool NullCheckValue, SourceLocation Loc); - - Address GetAddressOfDerivedClass(Address Value, - const CXXRecordDecl *Derived, - CastExpr::path_const_iterator PathBegin, - CastExpr::path_const_iterator PathEnd, - bool NullCheckValue); - - /// GetVTTParameter - Return the VTT parameter that should be passed to a - /// base constructor/destructor with virtual bases. - /// FIXME: VTTs are Itanium ABI-specific, so the definition should move - /// to ItaniumCXXABI.cpp together with all the references to VTT. - llvm::Value *GetVTTParameter(GlobalDecl GD, bool ForVirtualBase, - bool Delegating); - - void EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, - CXXCtorType CtorType, - const FunctionArgList &Args, - SourceLocation Loc); - // It's important not to confuse this and the previous function. Delegating - // constructors are the C++0x feature. The constructor delegate optimization - // is used to reduce duplication in the base and complete consturctors where - // they are substantially the same. - void EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor, - const FunctionArgList &Args); - - /// Emit a call to an inheriting constructor (that is, one that invokes a - /// constructor inherited from a base class) by inlining its definition. This - /// is necessary if the ABI does not support forwarding the arguments to the - /// base class constructor (because they're variadic or similar). - void EmitInlinedInheritingCXXConstructorCall(const CXXConstructorDecl *Ctor, - CXXCtorType CtorType, - bool ForVirtualBase, - bool Delegating, - CallArgList &Args); - - /// Emit a call to a constructor inherited from a base class, passing the - /// current constructor's arguments along unmodified (without even making - /// a copy). - void EmitInheritedCXXConstructorCall(const CXXConstructorDecl *D, - bool ForVirtualBase, Address This, - bool InheritedFromVBase, - const CXXInheritedCtorInitExpr *E); - - void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, - bool ForVirtualBase, bool Delegating, - Address This, const CXXConstructExpr *E, - AggValueSlot::Overlap_t Overlap, - bool NewPointerIsChecked); - - void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, - bool ForVirtualBase, bool Delegating, - Address This, CallArgList &Args, - AggValueSlot::Overlap_t Overlap, - SourceLocation Loc, - bool NewPointerIsChecked); - - /// Emit assumption load for all bases. Requires to be be called only on - /// most-derived class and not under construction of the object. - void EmitVTableAssumptionLoads(const CXXRecordDecl *ClassDecl, Address This); - - /// Emit assumption that vptr load == global vtable. - void EmitVTableAssumptionLoad(const VPtr &vptr, Address This); - - void EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, - Address This, Address Src, - const CXXConstructExpr *E); - - void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, - const ArrayType *ArrayTy, - Address ArrayPtr, - const CXXConstructExpr *E, - bool NewPointerIsChecked, - bool ZeroInitialization = false); - - void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, - llvm::Value *NumElements, - Address ArrayPtr, - const CXXConstructExpr *E, - bool NewPointerIsChecked, - bool ZeroInitialization = false); - - static Destroyer destroyCXXObject; - - void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type, - bool ForVirtualBase, bool Delegating, - Address This); - - void EmitNewArrayInitializer(const CXXNewExpr *E, QualType elementType, - llvm::Type *ElementTy, Address NewPtr, - llvm::Value *NumElements, - llvm::Value *AllocSizeWithoutCookie); - - void EmitCXXTemporary(const CXXTemporary *Temporary, QualType TempType, - Address Ptr); - - llvm::Value *EmitLifetimeStart(uint64_t Size, llvm::Value *Addr); - void EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr); - - llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E); - void EmitCXXDeleteExpr(const CXXDeleteExpr *E); - - void EmitDeleteCall(const FunctionDecl *DeleteFD, llvm::Value *Ptr, - QualType DeleteTy, llvm::Value *NumElements = nullptr, - CharUnits CookieSize = CharUnits()); - - RValue EmitBuiltinNewDeleteCall(const FunctionProtoType *Type, - const CallExpr *TheCallExpr, bool IsDelete); - - llvm::Value *EmitCXXTypeidExpr(const CXXTypeidExpr *E); - llvm::Value *EmitDynamicCast(Address V, const CXXDynamicCastExpr *DCE); - Address EmitCXXUuidofExpr(const CXXUuidofExpr *E); - - /// Situations in which we might emit a check for the suitability of a - /// pointer or glvalue. - enum TypeCheckKind { - /// Checking the operand of a load. Must be suitably sized and aligned. - TCK_Load, - /// Checking the destination of a store. Must be suitably sized and aligned. - TCK_Store, - /// Checking the bound value in a reference binding. Must be suitably sized - /// and aligned, but is not required to refer to an object (until the - /// reference is used), per core issue 453. - TCK_ReferenceBinding, - /// Checking the object expression in a non-static data member access. Must - /// be an object within its lifetime. - TCK_MemberAccess, - /// Checking the 'this' pointer for a call to a non-static member function. - /// Must be an object within its lifetime. - TCK_MemberCall, - /// Checking the 'this' pointer for a constructor call. - TCK_ConstructorCall, - /// Checking the operand of a static_cast to a derived pointer type. Must be - /// null or an object within its lifetime. - TCK_DowncastPointer, - /// Checking the operand of a static_cast to a derived reference type. Must - /// be an object within its lifetime. - TCK_DowncastReference, - /// Checking the operand of a cast to a base object. Must be suitably sized - /// and aligned. - TCK_Upcast, - /// Checking the operand of a cast to a virtual base object. Must be an - /// object within its lifetime. - TCK_UpcastToVirtualBase, - /// Checking the value assigned to a _Nonnull pointer. Must not be null. - TCK_NonnullAssign, - /// Checking the operand of a dynamic_cast or a typeid expression. Must be - /// null or an object within its lifetime. - TCK_DynamicOperation - }; - - /// Determine whether the pointer type check \p TCK permits null pointers. - static bool isNullPointerAllowed(TypeCheckKind TCK); - - /// Determine whether the pointer type check \p TCK requires a vptr check. - static bool isVptrCheckRequired(TypeCheckKind TCK, QualType Ty); - - /// Whether any type-checking sanitizers are enabled. If \c false, - /// calls to EmitTypeCheck can be skipped. - bool sanitizePerformTypeCheck() const; - - /// Emit a check that \p V is the address of storage of the - /// appropriate size and alignment for an object of type \p Type. - void EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, llvm::Value *V, - QualType Type, CharUnits Alignment = CharUnits::Zero(), - SanitizerSet SkippedChecks = SanitizerSet()); - - /// Emit a check that \p Base points into an array object, which - /// we can access at index \p Index. \p Accessed should be \c false if we - /// this expression is used as an lvalue, for instance in "&Arr[Idx]". - void EmitBoundsCheck(const Expr *E, const Expr *Base, llvm::Value *Index, - QualType IndexType, bool Accessed); - - llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, - bool isInc, bool isPre); - ComplexPairTy EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV, - bool isInc, bool isPre); - - /// Converts Location to a DebugLoc, if debug information is enabled. - llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location); - - - //===--------------------------------------------------------------------===// - // Declaration Emission - //===--------------------------------------------------------------------===// - - /// EmitDecl - Emit a declaration. - /// - /// This function can be called with a null (unreachable) insert point. - void EmitDecl(const Decl &D); - - /// EmitVarDecl - Emit a local variable declaration. - /// - /// This function can be called with a null (unreachable) insert point. - void EmitVarDecl(const VarDecl &D); - - void EmitScalarInit(const Expr *init, const ValueDecl *D, LValue lvalue, - bool capturedByInit); - - typedef void SpecialInitFn(CodeGenFunction &Init, const VarDecl &D, - llvm::Value *Address); - - /// Determine whether the given initializer is trivial in the sense - /// that it requires no code to be generated. - bool isTrivialInitializer(const Expr *Init); - - /// EmitAutoVarDecl - Emit an auto variable declaration. - /// - /// This function can be called with a null (unreachable) insert point. - void EmitAutoVarDecl(const VarDecl &D); - - class AutoVarEmission { - friend class CodeGenFunction; - - const VarDecl *Variable; - - /// The address of the alloca for languages with explicit address space - /// (e.g. OpenCL) or alloca casted to generic pointer for address space - /// agnostic languages (e.g. C++). Invalid if the variable was emitted - /// as a global constant. - Address Addr; - - llvm::Value *NRVOFlag; - - /// True if the variable is a __block variable that is captured by an - /// escaping block. - bool IsEscapingByRef; - - /// True if the variable is of aggregate type and has a constant - /// initializer. - bool IsConstantAggregate; - - /// Non-null if we should use lifetime annotations. - llvm::Value *SizeForLifetimeMarkers; - - /// Address with original alloca instruction. Invalid if the variable was - /// emitted as a global constant. - Address AllocaAddr; - - struct Invalid {}; - AutoVarEmission(Invalid) - : Variable(nullptr), Addr(Address::invalid()), - AllocaAddr(Address::invalid()) {} - - AutoVarEmission(const VarDecl &variable) - : Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr), - IsEscapingByRef(false), IsConstantAggregate(false), - SizeForLifetimeMarkers(nullptr), AllocaAddr(Address::invalid()) {} - - bool wasEmittedAsGlobal() const { return !Addr.isValid(); } - - public: - static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); } - - bool useLifetimeMarkers() const { - return SizeForLifetimeMarkers != nullptr; - } - llvm::Value *getSizeForLifetimeMarkers() const { - assert(useLifetimeMarkers()); - return SizeForLifetimeMarkers; - } - - /// Returns the raw, allocated address, which is not necessarily - /// the address of the object itself. It is casted to default - /// address space for address space agnostic languages. - Address getAllocatedAddress() const { - return Addr; - } - - /// Returns the address for the original alloca instruction. - Address getOriginalAllocatedAddress() const { return AllocaAddr; } - - /// Returns the address of the object within this declaration. - /// Note that this does not chase the forwarding pointer for - /// __block decls. - Address getObjectAddress(CodeGenFunction &CGF) const { - if (!IsEscapingByRef) return Addr; - - return CGF.emitBlockByrefAddress(Addr, Variable, /*forward*/ false); - } - }; - AutoVarEmission EmitAutoVarAlloca(const VarDecl &var); - void EmitAutoVarInit(const AutoVarEmission &emission); - void EmitAutoVarCleanups(const AutoVarEmission &emission); - void emitAutoVarTypeCleanup(const AutoVarEmission &emission, - QualType::DestructionKind dtorKind); - - /// Emits the alloca and debug information for the size expressions for each - /// dimension of an array. It registers the association of its (1-dimensional) - /// QualTypes and size expression's debug node, so that CGDebugInfo can - /// reference this node when creating the DISubrange object to describe the - /// array types. - void EmitAndRegisterVariableArrayDimensions(CGDebugInfo *DI, - const VarDecl &D, - bool EmitDebugInfo); - - void EmitStaticVarDecl(const VarDecl &D, - llvm::GlobalValue::LinkageTypes Linkage); - - class ParamValue { - llvm::Value *Value; - unsigned Alignment; - ParamValue(llvm::Value *V, unsigned A) : Value(V), Alignment(A) {} - public: - static ParamValue forDirect(llvm::Value *value) { - return ParamValue(value, 0); - } - static ParamValue forIndirect(Address addr) { - assert(!addr.getAlignment().isZero()); - return ParamValue(addr.getPointer(), addr.getAlignment().getQuantity()); - } - - bool isIndirect() const { return Alignment != 0; } - llvm::Value *getAnyValue() const { return Value; } - - llvm::Value *getDirectValue() const { - assert(!isIndirect()); - return Value; - } - - Address getIndirectAddress() const { - assert(isIndirect()); - return Address(Value, CharUnits::fromQuantity(Alignment)); - } - }; - - /// EmitParmDecl - Emit a ParmVarDecl or an ImplicitParamDecl. - void EmitParmDecl(const VarDecl &D, ParamValue Arg, unsigned ArgNo); - - /// protectFromPeepholes - Protect a value that we're intending to - /// store to the side, but which will probably be used later, from - /// aggressive peepholing optimizations that might delete it. - /// - /// Pass the result to unprotectFromPeepholes to declare that - /// protection is no longer required. - /// - /// There's no particular reason why this shouldn't apply to - /// l-values, it's just that no existing peepholes work on pointers. - PeepholeProtection protectFromPeepholes(RValue rvalue); - void unprotectFromPeepholes(PeepholeProtection protection); - - void EmitAlignmentAssumptionCheck(llvm::Value *Ptr, QualType Ty, - SourceLocation Loc, - SourceLocation AssumptionLoc, - llvm::Value *Alignment, - llvm::Value *OffsetValue, - llvm::Value *TheCheck, - llvm::Instruction *Assumption); - - void EmitAlignmentAssumption(llvm::Value *PtrValue, QualType Ty, - SourceLocation Loc, SourceLocation AssumptionLoc, - llvm::Value *Alignment, - llvm::Value *OffsetValue = nullptr); - - void EmitAlignmentAssumption(llvm::Value *PtrValue, QualType Ty, - SourceLocation Loc, SourceLocation AssumptionLoc, - unsigned Alignment, - llvm::Value *OffsetValue = nullptr); - - void EmitAlignmentAssumption(llvm::Value *PtrValue, const Expr *E, - SourceLocation AssumptionLoc, unsigned Alignment, - llvm::Value *OffsetValue = nullptr); - - //===--------------------------------------------------------------------===// - // Statement Emission - //===--------------------------------------------------------------------===// - - /// EmitStopPoint - Emit a debug stoppoint if we are emitting debug info. - void EmitStopPoint(const Stmt *S); - - /// EmitStmt - Emit the code for the statement \arg S. It is legal to call - /// this function even if there is no current insertion point. - /// - /// This function may clear the current insertion point; callers should use - /// EnsureInsertPoint if they wish to subsequently generate code without first - /// calling EmitBlock, EmitBranch, or EmitStmt. - void EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs = None); - - /// EmitSimpleStmt - Try to emit a "simple" statement which does not - /// necessarily require an insertion point or debug information; typically - /// because the statement amounts to a jump or a container of other - /// statements. - /// - /// \return True if the statement was handled. - bool EmitSimpleStmt(const Stmt *S); - - Address EmitCompoundStmt(const CompoundStmt &S, bool GetLast = false, - AggValueSlot AVS = AggValueSlot::ignored()); - Address EmitCompoundStmtWithoutScope(const CompoundStmt &S, - bool GetLast = false, - AggValueSlot AVS = - AggValueSlot::ignored()); - - /// EmitLabel - Emit the block for the given label. It is legal to call this - /// function even if there is no current insertion point. - void EmitLabel(const LabelDecl *D); // helper for EmitLabelStmt. - - void EmitLabelStmt(const LabelStmt &S); - void EmitAttributedStmt(const AttributedStmt &S); - void EmitGotoStmt(const GotoStmt &S); - void EmitIndirectGotoStmt(const IndirectGotoStmt &S); - void EmitIfStmt(const IfStmt &S); - - void EmitWhileStmt(const WhileStmt &S, - ArrayRef<const Attr *> Attrs = None); - void EmitDoStmt(const DoStmt &S, ArrayRef<const Attr *> Attrs = None); - void EmitForStmt(const ForStmt &S, - ArrayRef<const Attr *> Attrs = None); - void EmitReturnStmt(const ReturnStmt &S); - void EmitDeclStmt(const DeclStmt &S); - void EmitBreakStmt(const BreakStmt &S); - void EmitContinueStmt(const ContinueStmt &S); - void EmitSwitchStmt(const SwitchStmt &S); - void EmitDefaultStmt(const DefaultStmt &S); - void EmitCaseStmt(const CaseStmt &S); - void EmitCaseStmtRange(const CaseStmt &S); - void EmitAsmStmt(const AsmStmt &S); - - void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S); - void EmitObjCAtTryStmt(const ObjCAtTryStmt &S); - void EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S); - void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S); - void EmitObjCAutoreleasePoolStmt(const ObjCAutoreleasePoolStmt &S); - - void EmitCoroutineBody(const CoroutineBodyStmt &S); - void EmitCoreturnStmt(const CoreturnStmt &S); - RValue EmitCoawaitExpr(const CoawaitExpr &E, - AggValueSlot aggSlot = AggValueSlot::ignored(), - bool ignoreResult = false); - LValue EmitCoawaitLValue(const CoawaitExpr *E); - RValue EmitCoyieldExpr(const CoyieldExpr &E, - AggValueSlot aggSlot = AggValueSlot::ignored(), - bool ignoreResult = false); - LValue EmitCoyieldLValue(const CoyieldExpr *E); - RValue EmitCoroutineIntrinsic(const CallExpr *E, unsigned int IID); - - void EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false); - void ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false); - - void EmitCXXTryStmt(const CXXTryStmt &S); - void EmitSEHTryStmt(const SEHTryStmt &S); - void EmitSEHLeaveStmt(const SEHLeaveStmt &S); - void EnterSEHTryStmt(const SEHTryStmt &S); - void ExitSEHTryStmt(const SEHTryStmt &S); - - void pushSEHCleanup(CleanupKind kind, - llvm::Function *FinallyFunc); - void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, bool IsFilter, - const Stmt *OutlinedStmt); - - llvm::Function *GenerateSEHFilterFunction(CodeGenFunction &ParentCGF, - const SEHExceptStmt &Except); - - llvm::Function *GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF, - const SEHFinallyStmt &Finally); - - void EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF, - llvm::Value *ParentFP, - llvm::Value *EntryEBP); - llvm::Value *EmitSEHExceptionCode(); - llvm::Value *EmitSEHExceptionInfo(); - llvm::Value *EmitSEHAbnormalTermination(); - - /// Emit simple code for OpenMP directives in Simd-only mode. - void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D); - - /// Scan the outlined statement for captures from the parent function. For - /// each capture, mark the capture as escaped and emit a call to - /// llvm.localrecover. Insert the localrecover result into the LocalDeclMap. - void EmitCapturedLocals(CodeGenFunction &ParentCGF, const Stmt *OutlinedStmt, - bool IsFilter); - - /// Recovers the address of a local in a parent function. ParentVar is the - /// address of the variable used in the immediate parent function. It can - /// either be an alloca or a call to llvm.localrecover if there are nested - /// outlined functions. ParentFP is the frame pointer of the outermost parent - /// frame. - Address recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, - Address ParentVar, - llvm::Value *ParentFP); - - void EmitCXXForRangeStmt(const CXXForRangeStmt &S, - ArrayRef<const Attr *> Attrs = None); - - /// Controls insertion of cancellation exit blocks in worksharing constructs. - class OMPCancelStackRAII { - CodeGenFunction &CGF; - - public: - OMPCancelStackRAII(CodeGenFunction &CGF, OpenMPDirectiveKind Kind, - bool HasCancel) - : CGF(CGF) { - CGF.OMPCancelStack.enter(CGF, Kind, HasCancel); - } - ~OMPCancelStackRAII() { CGF.OMPCancelStack.exit(CGF); } - }; - - /// Returns calculated size of the specified type. - llvm::Value *getTypeSize(QualType Ty); - LValue InitCapturedStruct(const CapturedStmt &S); - llvm::Function *EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K); - llvm::Function *GenerateCapturedStmtFunction(const CapturedStmt &S); - Address GenerateCapturedStmtArgument(const CapturedStmt &S); - llvm::Function *GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S); - void GenerateOpenMPCapturedVars(const CapturedStmt &S, - SmallVectorImpl<llvm::Value *> &CapturedVars); - void emitOMPSimpleStore(LValue LVal, RValue RVal, QualType RValTy, - SourceLocation Loc); - /// Perform element by element copying of arrays with type \a - /// OriginalType from \a SrcAddr to \a DestAddr using copying procedure - /// generated by \a CopyGen. - /// - /// \param DestAddr Address of the destination array. - /// \param SrcAddr Address of the source array. - /// \param OriginalType Type of destination and source arrays. - /// \param CopyGen Copying procedure that copies value of single array element - /// to another single array element. - void EmitOMPAggregateAssign( - Address DestAddr, Address SrcAddr, QualType OriginalType, - const llvm::function_ref<void(Address, Address)> CopyGen); - /// Emit proper copying of data from one variable to another. - /// - /// \param OriginalType Original type of the copied variables. - /// \param DestAddr Destination address. - /// \param SrcAddr Source address. - /// \param DestVD Destination variable used in \a CopyExpr (for arrays, has - /// type of the base array element). - /// \param SrcVD Source variable used in \a CopyExpr (for arrays, has type of - /// the base array element). - /// \param Copy Actual copygin expression for copying data from \a SrcVD to \a - /// DestVD. - void EmitOMPCopy(QualType OriginalType, - Address DestAddr, Address SrcAddr, - const VarDecl *DestVD, const VarDecl *SrcVD, - const Expr *Copy); - /// Emit atomic update code for constructs: \a X = \a X \a BO \a E or - /// \a X = \a E \a BO \a E. - /// - /// \param X Value to be updated. - /// \param E Update value. - /// \param BO Binary operation for update operation. - /// \param IsXLHSInRHSPart true if \a X is LHS in RHS part of the update - /// expression, false otherwise. - /// \param AO Atomic ordering of the generated atomic instructions. - /// \param CommonGen Code generator for complex expressions that cannot be - /// expressed through atomicrmw instruction. - /// \returns <true, OldAtomicValue> if simple 'atomicrmw' instruction was - /// generated, <false, RValue::get(nullptr)> otherwise. - std::pair<bool, RValue> EmitOMPAtomicSimpleUpdateExpr( - LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart, - llvm::AtomicOrdering AO, SourceLocation Loc, - const llvm::function_ref<RValue(RValue)> CommonGen); - bool EmitOMPFirstprivateClause(const OMPExecutableDirective &D, - OMPPrivateScope &PrivateScope); - void EmitOMPPrivateClause(const OMPExecutableDirective &D, - OMPPrivateScope &PrivateScope); - void EmitOMPUseDevicePtrClause( - const OMPClause &C, OMPPrivateScope &PrivateScope, - const llvm::DenseMap<const ValueDecl *, Address> &CaptureDeviceAddrMap); - /// Emit code for copyin clause in \a D directive. The next code is - /// generated at the start of outlined functions for directives: - /// \code - /// threadprivate_var1 = master_threadprivate_var1; - /// operator=(threadprivate_var2, master_threadprivate_var2); - /// ... - /// __kmpc_barrier(&loc, global_tid); - /// \endcode - /// - /// \param D OpenMP directive possibly with 'copyin' clause(s). - /// \returns true if at least one copyin variable is found, false otherwise. - bool EmitOMPCopyinClause(const OMPExecutableDirective &D); - /// Emit initial code for lastprivate variables. If some variable is - /// not also firstprivate, then the default initialization is used. Otherwise - /// initialization of this variable is performed by EmitOMPFirstprivateClause - /// method. - /// - /// \param D Directive that may have 'lastprivate' directives. - /// \param PrivateScope Private scope for capturing lastprivate variables for - /// proper codegen in internal captured statement. - /// - /// \returns true if there is at least one lastprivate variable, false - /// otherwise. - bool EmitOMPLastprivateClauseInit(const OMPExecutableDirective &D, - OMPPrivateScope &PrivateScope); - /// Emit final copying of lastprivate values to original variables at - /// the end of the worksharing or simd directive. - /// - /// \param D Directive that has at least one 'lastprivate' directives. - /// \param IsLastIterCond Boolean condition that must be set to 'i1 true' if - /// it is the last iteration of the loop code in associated directive, or to - /// 'i1 false' otherwise. If this item is nullptr, no final check is required. - void EmitOMPLastprivateClauseFinal(const OMPExecutableDirective &D, - bool NoFinals, - llvm::Value *IsLastIterCond = nullptr); - /// Emit initial code for linear clauses. - void EmitOMPLinearClause(const OMPLoopDirective &D, - CodeGenFunction::OMPPrivateScope &PrivateScope); - /// Emit final code for linear clauses. - /// \param CondGen Optional conditional code for final part of codegen for - /// linear clause. - void EmitOMPLinearClauseFinal( - const OMPLoopDirective &D, - const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen); - /// Emit initial code for reduction variables. Creates reduction copies - /// and initializes them with the values according to OpenMP standard. - /// - /// \param D Directive (possibly) with the 'reduction' clause. - /// \param PrivateScope Private scope for capturing reduction variables for - /// proper codegen in internal captured statement. - /// - void EmitOMPReductionClauseInit(const OMPExecutableDirective &D, - OMPPrivateScope &PrivateScope); - /// Emit final update of reduction values to original variables at - /// the end of the directive. - /// - /// \param D Directive that has at least one 'reduction' directives. - /// \param ReductionKind The kind of reduction to perform. - void EmitOMPReductionClauseFinal(const OMPExecutableDirective &D, - const OpenMPDirectiveKind ReductionKind); - /// Emit initial code for linear variables. Creates private copies - /// and initializes them with the values according to OpenMP standard. - /// - /// \param D Directive (possibly) with the 'linear' clause. - /// \return true if at least one linear variable is found that should be - /// initialized with the value of the original variable, false otherwise. - bool EmitOMPLinearClauseInit(const OMPLoopDirective &D); - - typedef const llvm::function_ref<void(CodeGenFunction & /*CGF*/, - llvm::Value * /*OutlinedFn*/, - const OMPTaskDataTy & /*Data*/)> - TaskGenTy; - void EmitOMPTaskBasedDirective(const OMPExecutableDirective &S, - const OpenMPDirectiveKind CapturedRegion, - const RegionCodeGenTy &BodyGen, - const TaskGenTy &TaskGen, OMPTaskDataTy &Data); - struct OMPTargetDataInfo { - Address BasePointersArray = Address::invalid(); - Address PointersArray = Address::invalid(); - Address SizesArray = Address::invalid(); - unsigned NumberOfTargetItems = 0; - explicit OMPTargetDataInfo() = default; - OMPTargetDataInfo(Address BasePointersArray, Address PointersArray, - Address SizesArray, unsigned NumberOfTargetItems) - : BasePointersArray(BasePointersArray), PointersArray(PointersArray), - SizesArray(SizesArray), NumberOfTargetItems(NumberOfTargetItems) {} - }; - void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, - const RegionCodeGenTy &BodyGen, - OMPTargetDataInfo &InputInfo); - - void EmitOMPParallelDirective(const OMPParallelDirective &S); - void EmitOMPSimdDirective(const OMPSimdDirective &S); - void EmitOMPForDirective(const OMPForDirective &S); - void EmitOMPForSimdDirective(const OMPForSimdDirective &S); - void EmitOMPSectionsDirective(const OMPSectionsDirective &S); - void EmitOMPSectionDirective(const OMPSectionDirective &S); - void EmitOMPSingleDirective(const OMPSingleDirective &S); - void EmitOMPMasterDirective(const OMPMasterDirective &S); - void EmitOMPCriticalDirective(const OMPCriticalDirective &S); - void EmitOMPParallelForDirective(const OMPParallelForDirective &S); - void EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S); - void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S); - void EmitOMPTaskDirective(const OMPTaskDirective &S); - void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S); - void EmitOMPBarrierDirective(const OMPBarrierDirective &S); - void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S); - void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S); - void EmitOMPFlushDirective(const OMPFlushDirective &S); - void EmitOMPOrderedDirective(const OMPOrderedDirective &S); - void EmitOMPAtomicDirective(const OMPAtomicDirective &S); - void EmitOMPTargetDirective(const OMPTargetDirective &S); - void EmitOMPTargetDataDirective(const OMPTargetDataDirective &S); - void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S); - void EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &S); - void EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &S); - void EmitOMPTargetParallelDirective(const OMPTargetParallelDirective &S); - void - EmitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &S); - void EmitOMPTeamsDirective(const OMPTeamsDirective &S); - void - EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S); - void EmitOMPCancelDirective(const OMPCancelDirective &S); - void EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S); - void EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S); - void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S); - void EmitOMPDistributeDirective(const OMPDistributeDirective &S); - void EmitOMPDistributeParallelForDirective( - const OMPDistributeParallelForDirective &S); - void EmitOMPDistributeParallelForSimdDirective( - const OMPDistributeParallelForSimdDirective &S); - void EmitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &S); - void EmitOMPTargetParallelForSimdDirective( - const OMPTargetParallelForSimdDirective &S); - void EmitOMPTargetSimdDirective(const OMPTargetSimdDirective &S); - void EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S); - void - EmitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &S); - void EmitOMPTeamsDistributeParallelForSimdDirective( - const OMPTeamsDistributeParallelForSimdDirective &S); - void EmitOMPTeamsDistributeParallelForDirective( - const OMPTeamsDistributeParallelForDirective &S); - void EmitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &S); - void EmitOMPTargetTeamsDistributeDirective( - const OMPTargetTeamsDistributeDirective &S); - void EmitOMPTargetTeamsDistributeParallelForDirective( - const OMPTargetTeamsDistributeParallelForDirective &S); - void EmitOMPTargetTeamsDistributeParallelForSimdDirective( - const OMPTargetTeamsDistributeParallelForSimdDirective &S); - void EmitOMPTargetTeamsDistributeSimdDirective( - const OMPTargetTeamsDistributeSimdDirective &S); - - /// Emit device code for the target directive. - static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, - StringRef ParentName, - const OMPTargetDirective &S); - static void - EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, - const OMPTargetParallelDirective &S); - /// Emit device code for the target parallel for directive. - static void EmitOMPTargetParallelForDeviceFunction( - CodeGenModule &CGM, StringRef ParentName, - const OMPTargetParallelForDirective &S); - /// Emit device code for the target parallel for simd directive. - static void EmitOMPTargetParallelForSimdDeviceFunction( - CodeGenModule &CGM, StringRef ParentName, - const OMPTargetParallelForSimdDirective &S); - /// Emit device code for the target teams directive. - static void - EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, - const OMPTargetTeamsDirective &S); - /// Emit device code for the target teams distribute directive. - static void EmitOMPTargetTeamsDistributeDeviceFunction( - CodeGenModule &CGM, StringRef ParentName, - const OMPTargetTeamsDistributeDirective &S); - /// Emit device code for the target teams distribute simd directive. - static void EmitOMPTargetTeamsDistributeSimdDeviceFunction( - CodeGenModule &CGM, StringRef ParentName, - const OMPTargetTeamsDistributeSimdDirective &S); - /// Emit device code for the target simd directive. - static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, - StringRef ParentName, - const OMPTargetSimdDirective &S); - /// Emit device code for the target teams distribute parallel for simd - /// directive. - static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( - CodeGenModule &CGM, StringRef ParentName, - const OMPTargetTeamsDistributeParallelForSimdDirective &S); - - static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction( - CodeGenModule &CGM, StringRef ParentName, - const OMPTargetTeamsDistributeParallelForDirective &S); - /// Emit inner loop of the worksharing/simd construct. - /// - /// \param S Directive, for which the inner loop must be emitted. - /// \param RequiresCleanup true, if directive has some associated private - /// variables. - /// \param LoopCond Bollean condition for loop continuation. - /// \param IncExpr Increment expression for loop control variable. - /// \param BodyGen Generator for the inner body of the inner loop. - /// \param PostIncGen Genrator for post-increment code (required for ordered - /// loop directvies). - void EmitOMPInnerLoop( - const Stmt &S, bool RequiresCleanup, const Expr *LoopCond, - const Expr *IncExpr, - const llvm::function_ref<void(CodeGenFunction &)> BodyGen, - const llvm::function_ref<void(CodeGenFunction &)> PostIncGen); - - JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind); - /// Emit initial code for loop counters of loop-based directives. - void EmitOMPPrivateLoopCounters(const OMPLoopDirective &S, - OMPPrivateScope &LoopScope); - - /// Helper for the OpenMP loop directives. - void EmitOMPLoopBody(const OMPLoopDirective &D, JumpDest LoopExit); - - /// Emit code for the worksharing loop-based directive. - /// \return true, if this construct has any lastprivate clause, false - - /// otherwise. - bool EmitOMPWorksharingLoop(const OMPLoopDirective &S, Expr *EUB, - const CodeGenLoopBoundsTy &CodeGenLoopBounds, - const CodeGenDispatchBoundsTy &CGDispatchBounds); - - /// Emit code for the distribute loop-based directive. - void EmitOMPDistributeLoop(const OMPLoopDirective &S, - const CodeGenLoopTy &CodeGenLoop, Expr *IncExpr); - - /// Helpers for the OpenMP loop directives. - void EmitOMPSimdInit(const OMPLoopDirective &D, bool IsMonotonic = false); - void EmitOMPSimdFinal( - const OMPLoopDirective &D, - const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen); - - /// Emits the lvalue for the expression with possibly captured variable. - LValue EmitOMPSharedLValue(const Expr *E); - -private: - /// Helpers for blocks. - llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info); - - /// struct with the values to be passed to the OpenMP loop-related functions - struct OMPLoopArguments { - /// loop lower bound - Address LB = Address::invalid(); - /// loop upper bound - Address UB = Address::invalid(); - /// loop stride - Address ST = Address::invalid(); - /// isLastIteration argument for runtime functions - Address IL = Address::invalid(); - /// Chunk value generated by sema - llvm::Value *Chunk = nullptr; - /// EnsureUpperBound - Expr *EUB = nullptr; - /// IncrementExpression - Expr *IncExpr = nullptr; - /// Loop initialization - Expr *Init = nullptr; - /// Loop exit condition - Expr *Cond = nullptr; - /// Update of LB after a whole chunk has been executed - Expr *NextLB = nullptr; - /// Update of UB after a whole chunk has been executed - Expr *NextUB = nullptr; - OMPLoopArguments() = default; - OMPLoopArguments(Address LB, Address UB, Address ST, Address IL, - llvm::Value *Chunk = nullptr, Expr *EUB = nullptr, - Expr *IncExpr = nullptr, Expr *Init = nullptr, - Expr *Cond = nullptr, Expr *NextLB = nullptr, - Expr *NextUB = nullptr) - : LB(LB), UB(UB), ST(ST), IL(IL), Chunk(Chunk), EUB(EUB), - IncExpr(IncExpr), Init(Init), Cond(Cond), NextLB(NextLB), - NextUB(NextUB) {} - }; - void EmitOMPOuterLoop(bool DynamicOrOrdered, bool IsMonotonic, - const OMPLoopDirective &S, OMPPrivateScope &LoopScope, - const OMPLoopArguments &LoopArgs, - const CodeGenLoopTy &CodeGenLoop, - const CodeGenOrderedTy &CodeGenOrdered); - void EmitOMPForOuterLoop(const OpenMPScheduleTy &ScheduleKind, - bool IsMonotonic, const OMPLoopDirective &S, - OMPPrivateScope &LoopScope, bool Ordered, - const OMPLoopArguments &LoopArgs, - const CodeGenDispatchBoundsTy &CGDispatchBounds); - void EmitOMPDistributeOuterLoop(OpenMPDistScheduleClauseKind ScheduleKind, - const OMPLoopDirective &S, - OMPPrivateScope &LoopScope, - const OMPLoopArguments &LoopArgs, - const CodeGenLoopTy &CodeGenLoopContent); - /// Emit code for sections directive. - void EmitSections(const OMPExecutableDirective &S); - -public: - - //===--------------------------------------------------------------------===// - // LValue Expression Emission - //===--------------------------------------------------------------------===// - - /// GetUndefRValue - Get an appropriate 'undef' rvalue for the given type. - RValue GetUndefRValue(QualType Ty); - - /// EmitUnsupportedRValue - Emit a dummy r-value using the type of E - /// and issue an ErrorUnsupported style diagnostic (using the - /// provided Name). - RValue EmitUnsupportedRValue(const Expr *E, - const char *Name); - - /// EmitUnsupportedLValue - Emit a dummy l-value using the type of E and issue - /// an ErrorUnsupported style diagnostic (using the provided Name). - LValue EmitUnsupportedLValue(const Expr *E, - const char *Name); - - /// EmitLValue - Emit code to compute a designator that specifies the location - /// of the expression. - /// - /// This can return one of two things: a simple address or a bitfield - /// reference. In either case, the LLVM Value* in the LValue structure is - /// guaranteed to be an LLVM pointer type. - /// - /// If this returns a bitfield reference, nothing about the pointee type of - /// the LLVM value is known: For example, it may not be a pointer to an - /// integer. - /// - /// If this returns a normal address, and if the lvalue's C type is fixed - /// size, this method guarantees that the returned pointer type will point to - /// an LLVM type of the same size of the lvalue's type. If the lvalue has a - /// variable length type, this is not possible. - /// - LValue EmitLValue(const Expr *E); - - /// Same as EmitLValue but additionally we generate checking code to - /// guard against undefined behavior. This is only suitable when we know - /// that the address will be used to access the object. - LValue EmitCheckedLValue(const Expr *E, TypeCheckKind TCK); - - RValue convertTempToRValue(Address addr, QualType type, - SourceLocation Loc); - - void EmitAtomicInit(Expr *E, LValue lvalue); - - bool LValueIsSuitableForInlineAtomic(LValue Src); - - RValue EmitAtomicLoad(LValue LV, SourceLocation SL, - AggValueSlot Slot = AggValueSlot::ignored()); - - RValue EmitAtomicLoad(LValue lvalue, SourceLocation loc, - llvm::AtomicOrdering AO, bool IsVolatile = false, - AggValueSlot slot = AggValueSlot::ignored()); - - void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit); - - void EmitAtomicStore(RValue rvalue, LValue lvalue, llvm::AtomicOrdering AO, - bool IsVolatile, bool isInit); - - std::pair<RValue, llvm::Value *> EmitAtomicCompareExchange( - LValue Obj, RValue Expected, RValue Desired, SourceLocation Loc, - llvm::AtomicOrdering Success = - llvm::AtomicOrdering::SequentiallyConsistent, - llvm::AtomicOrdering Failure = - llvm::AtomicOrdering::SequentiallyConsistent, - bool IsWeak = false, AggValueSlot Slot = AggValueSlot::ignored()); - - void EmitAtomicUpdate(LValue LVal, llvm::AtomicOrdering AO, - const llvm::function_ref<RValue(RValue)> &UpdateOp, - bool IsVolatile); - - /// EmitToMemory - Change a scalar value from its value - /// representation to its in-memory representation. - llvm::Value *EmitToMemory(llvm::Value *Value, QualType Ty); - - /// EmitFromMemory - Change a scalar value from its memory - /// representation to its value representation. - llvm::Value *EmitFromMemory(llvm::Value *Value, QualType Ty); - - /// Check if the scalar \p Value is within the valid range for the given - /// type \p Ty. - /// - /// Returns true if a check is needed (even if the range is unknown). - bool EmitScalarRangeCheck(llvm::Value *Value, QualType Ty, - SourceLocation Loc); - - /// EmitLoadOfScalar - Load a scalar value from an address, taking - /// care to appropriately convert from the memory representation to - /// the LLVM value representation. - llvm::Value *EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, - SourceLocation Loc, - AlignmentSource Source = AlignmentSource::Type, - bool isNontemporal = false) { - return EmitLoadOfScalar(Addr, Volatile, Ty, Loc, LValueBaseInfo(Source), - CGM.getTBAAAccessInfo(Ty), isNontemporal); - } - - llvm::Value *EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, - SourceLocation Loc, LValueBaseInfo BaseInfo, - TBAAAccessInfo TBAAInfo, - bool isNontemporal = false); - - /// EmitLoadOfScalar - Load a scalar value from an address, taking - /// care to appropriately convert from the memory representation to - /// the LLVM value representation. The l-value must be a simple - /// l-value. - llvm::Value *EmitLoadOfScalar(LValue lvalue, SourceLocation Loc); - - /// EmitStoreOfScalar - Store a scalar value to an address, taking - /// care to appropriately convert from the memory representation to - /// the LLVM value representation. - void EmitStoreOfScalar(llvm::Value *Value, Address Addr, - bool Volatile, QualType Ty, - AlignmentSource Source = AlignmentSource::Type, - bool isInit = false, bool isNontemporal = false) { - EmitStoreOfScalar(Value, Addr, Volatile, Ty, LValueBaseInfo(Source), - CGM.getTBAAAccessInfo(Ty), isInit, isNontemporal); - } - - void EmitStoreOfScalar(llvm::Value *Value, Address Addr, - bool Volatile, QualType Ty, - LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo, - bool isInit = false, bool isNontemporal = false); - - /// EmitStoreOfScalar - Store a scalar value to an address, taking - /// care to appropriately convert from the memory representation to - /// the LLVM value representation. The l-value must be a simple - /// l-value. The isInit flag indicates whether this is an initialization. - /// If so, atomic qualifiers are ignored and the store is always non-atomic. - void EmitStoreOfScalar(llvm::Value *value, LValue lvalue, bool isInit=false); - - /// EmitLoadOfLValue - Given an expression that represents a value lvalue, - /// this method emits the address of the lvalue, then loads the result as an - /// rvalue, returning the rvalue. - RValue EmitLoadOfLValue(LValue V, SourceLocation Loc); - RValue EmitLoadOfExtVectorElementLValue(LValue V); - RValue EmitLoadOfBitfieldLValue(LValue LV, SourceLocation Loc); - RValue EmitLoadOfGlobalRegLValue(LValue LV); - - /// EmitStoreThroughLValue - Store the specified rvalue into the specified - /// lvalue, where both are guaranteed to the have the same type, and that type - /// is 'Ty'. - void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit = false); - void EmitStoreThroughExtVectorComponentLValue(RValue Src, LValue Dst); - void EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst); - - /// EmitStoreThroughBitfieldLValue - Store Src into Dst with same constraints - /// as EmitStoreThroughLValue. - /// - /// \param Result [out] - If non-null, this will be set to a Value* for the - /// bit-field contents after the store, appropriate for use as the result of - /// an assignment to the bit-field. - void EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, - llvm::Value **Result=nullptr); - - /// Emit an l-value for an assignment (simple or compound) of complex type. - LValue EmitComplexAssignmentLValue(const BinaryOperator *E); - LValue EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E); - LValue EmitScalarCompoundAssignWithComplex(const CompoundAssignOperator *E, - llvm::Value *&Result); - - // Note: only available for agg return types - LValue EmitBinaryOperatorLValue(const BinaryOperator *E); - LValue EmitCompoundAssignmentLValue(const CompoundAssignOperator *E); - // Note: only available for agg return types - LValue EmitCallExprLValue(const CallExpr *E); - // Note: only available for agg return types - LValue EmitVAArgExprLValue(const VAArgExpr *E); - LValue EmitDeclRefLValue(const DeclRefExpr *E); - LValue EmitStringLiteralLValue(const StringLiteral *E); - LValue EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E); - LValue EmitPredefinedLValue(const PredefinedExpr *E); - LValue EmitUnaryOpLValue(const UnaryOperator *E); - LValue EmitArraySubscriptExpr(const ArraySubscriptExpr *E, - bool Accessed = false); - LValue EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, - bool IsLowerBound = true); - LValue EmitExtVectorElementExpr(const ExtVectorElementExpr *E); - LValue EmitMemberExpr(const MemberExpr *E); - LValue EmitObjCIsaExpr(const ObjCIsaExpr *E); - LValue EmitCompoundLiteralLValue(const CompoundLiteralExpr *E); - LValue EmitInitListLValue(const InitListExpr *E); - LValue EmitConditionalOperatorLValue(const AbstractConditionalOperator *E); - LValue EmitCastLValue(const CastExpr *E); - LValue EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E); - LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e); - - Address EmitExtVectorElementLValue(LValue V); - - RValue EmitRValueForField(LValue LV, const FieldDecl *FD, SourceLocation Loc); - - Address EmitArrayToPointerDecay(const Expr *Array, - LValueBaseInfo *BaseInfo = nullptr, - TBAAAccessInfo *TBAAInfo = nullptr); - - class ConstantEmission { - llvm::PointerIntPair<llvm::Constant*, 1, bool> ValueAndIsReference; - ConstantEmission(llvm::Constant *C, bool isReference) - : ValueAndIsReference(C, isReference) {} - public: - ConstantEmission() {} - static ConstantEmission forReference(llvm::Constant *C) { - return ConstantEmission(C, true); - } - static ConstantEmission forValue(llvm::Constant *C) { - return ConstantEmission(C, false); - } - - explicit operator bool() const { - return ValueAndIsReference.getOpaqueValue() != nullptr; - } - - bool isReference() const { return ValueAndIsReference.getInt(); } - LValue getReferenceLValue(CodeGenFunction &CGF, Expr *refExpr) const { - assert(isReference()); - return CGF.MakeNaturalAlignAddrLValue(ValueAndIsReference.getPointer(), - refExpr->getType()); - } - - llvm::Constant *getValue() const { - assert(!isReference()); - return ValueAndIsReference.getPointer(); - } - }; - - ConstantEmission tryEmitAsConstant(DeclRefExpr *refExpr); - ConstantEmission tryEmitAsConstant(const MemberExpr *ME); - llvm::Value *emitScalarConstant(const ConstantEmission &Constant, Expr *E); - - RValue EmitPseudoObjectRValue(const PseudoObjectExpr *e, - AggValueSlot slot = AggValueSlot::ignored()); - LValue EmitPseudoObjectLValue(const PseudoObjectExpr *e); - - llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface, - const ObjCIvarDecl *Ivar); - LValue EmitLValueForField(LValue Base, const FieldDecl* Field); - LValue EmitLValueForLambdaField(const FieldDecl *Field); - - /// EmitLValueForFieldInitialization - Like EmitLValueForField, except that - /// if the Field is a reference, this will return the address of the reference - /// and not the address of the value stored in the reference. - LValue EmitLValueForFieldInitialization(LValue Base, - const FieldDecl* Field); - - LValue EmitLValueForIvar(QualType ObjectTy, - llvm::Value* Base, const ObjCIvarDecl *Ivar, - unsigned CVRQualifiers); - - LValue EmitCXXConstructLValue(const CXXConstructExpr *E); - LValue EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E); - LValue EmitLambdaLValue(const LambdaExpr *E); - LValue EmitCXXTypeidLValue(const CXXTypeidExpr *E); - LValue EmitCXXUuidofLValue(const CXXUuidofExpr *E); - - LValue EmitObjCMessageExprLValue(const ObjCMessageExpr *E); - LValue EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E); - LValue EmitStmtExprLValue(const StmtExpr *E); - LValue EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E); - LValue EmitObjCSelectorLValue(const ObjCSelectorExpr *E); - void EmitDeclRefExprDbgValue(const DeclRefExpr *E, const APValue &Init); - - //===--------------------------------------------------------------------===// - // Scalar Expression Emission - //===--------------------------------------------------------------------===// - - /// EmitCall - Generate a call of the given function, expecting the given - /// result type, and using the given argument list which specifies both the - /// LLVM arguments and the types they were derived from. - RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, - ReturnValueSlot ReturnValue, const CallArgList &Args, - llvm::Instruction **callOrInvoke, SourceLocation Loc); - RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, - ReturnValueSlot ReturnValue, const CallArgList &Args, - llvm::Instruction **callOrInvoke = nullptr) { - return EmitCall(CallInfo, Callee, ReturnValue, Args, callOrInvoke, - SourceLocation()); - } - RValue EmitCall(QualType FnType, const CGCallee &Callee, const CallExpr *E, - ReturnValueSlot ReturnValue, llvm::Value *Chain = nullptr); - RValue EmitCallExpr(const CallExpr *E, - ReturnValueSlot ReturnValue = ReturnValueSlot()); - RValue EmitSimpleCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue); - CGCallee EmitCallee(const Expr *E); - - void checkTargetFeatures(const CallExpr *E, const FunctionDecl *TargetDecl); - - llvm::CallInst *EmitRuntimeCall(llvm::Value *callee, - const Twine &name = ""); - llvm::CallInst *EmitRuntimeCall(llvm::Value *callee, - ArrayRef<llvm::Value*> args, - const Twine &name = ""); - llvm::CallInst *EmitNounwindRuntimeCall(llvm::Value *callee, - const Twine &name = ""); - llvm::CallInst *EmitNounwindRuntimeCall(llvm::Value *callee, - ArrayRef<llvm::Value*> args, - const Twine &name = ""); - - SmallVector<llvm::OperandBundleDef, 1> - getBundlesForFunclet(llvm::Value *Callee); - - llvm::CallSite EmitCallOrInvoke(llvm::Value *Callee, - ArrayRef<llvm::Value *> Args, - const Twine &Name = ""); - llvm::CallSite EmitRuntimeCallOrInvoke(llvm::Value *callee, - ArrayRef<llvm::Value*> args, - const Twine &name = ""); - llvm::CallSite EmitRuntimeCallOrInvoke(llvm::Value *callee, - const Twine &name = ""); - void EmitNoreturnRuntimeCallOrInvoke(llvm::Value *callee, - ArrayRef<llvm::Value*> args); - - CGCallee BuildAppleKextVirtualCall(const CXXMethodDecl *MD, - NestedNameSpecifier *Qual, - llvm::Type *Ty); - - CGCallee BuildAppleKextVirtualDestructorCall(const CXXDestructorDecl *DD, - CXXDtorType Type, - const CXXRecordDecl *RD); - - // Return the copy constructor name with the prefix "__copy_constructor_" - // removed. - static std::string getNonTrivialCopyConstructorStr(QualType QT, - CharUnits Alignment, - bool IsVolatile, - ASTContext &Ctx); - - // Return the destructor name with the prefix "__destructor_" removed. - static std::string getNonTrivialDestructorStr(QualType QT, - CharUnits Alignment, - bool IsVolatile, - ASTContext &Ctx); - - // These functions emit calls to the special functions of non-trivial C - // structs. - void defaultInitNonTrivialCStructVar(LValue Dst); - void callCStructDefaultConstructor(LValue Dst); - void callCStructDestructor(LValue Dst); - void callCStructCopyConstructor(LValue Dst, LValue Src); - void callCStructMoveConstructor(LValue Dst, LValue Src); - void callCStructCopyAssignmentOperator(LValue Dst, LValue Src); - void callCStructMoveAssignmentOperator(LValue Dst, LValue Src); - - RValue - EmitCXXMemberOrOperatorCall(const CXXMethodDecl *Method, - const CGCallee &Callee, - ReturnValueSlot ReturnValue, llvm::Value *This, - llvm::Value *ImplicitParam, - QualType ImplicitParamTy, const CallExpr *E, - CallArgList *RtlArgs); - RValue EmitCXXDestructorCall(const CXXDestructorDecl *DD, - const CGCallee &Callee, - llvm::Value *This, llvm::Value *ImplicitParam, - QualType ImplicitParamTy, const CallExpr *E, - StructorType Type); - RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E, - ReturnValueSlot ReturnValue); - RValue EmitCXXMemberOrOperatorMemberCallExpr(const CallExpr *CE, - const CXXMethodDecl *MD, - ReturnValueSlot ReturnValue, - bool HasQualifier, - NestedNameSpecifier *Qualifier, - bool IsArrow, const Expr *Base); - // Compute the object pointer. - Address EmitCXXMemberDataPointerAddress(const Expr *E, Address base, - llvm::Value *memberPtr, - const MemberPointerType *memberPtrType, - LValueBaseInfo *BaseInfo = nullptr, - TBAAAccessInfo *TBAAInfo = nullptr); - RValue EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, - ReturnValueSlot ReturnValue); - - RValue EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, - const CXXMethodDecl *MD, - ReturnValueSlot ReturnValue); - RValue EmitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *E); - - RValue EmitCUDAKernelCallExpr(const CUDAKernelCallExpr *E, - ReturnValueSlot ReturnValue); - - RValue EmitNVPTXDevicePrintfCallExpr(const CallExpr *E, - ReturnValueSlot ReturnValue); - - RValue EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, - const CallExpr *E, ReturnValueSlot ReturnValue); - - RValue emitRotate(const CallExpr *E, bool IsRotateRight); - - /// Emit IR for __builtin_os_log_format. - RValue emitBuiltinOSLogFormat(const CallExpr &E); - - llvm::Function *generateBuiltinOSLogHelperFunction( - const analyze_os_log::OSLogBufferLayout &Layout, - CharUnits BufferAlignment); - - RValue EmitBlockCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue); - - /// EmitTargetBuiltinExpr - Emit the given builtin call. Returns 0 if the call - /// is unhandled by the current target. - llvm::Value *EmitTargetBuiltinExpr(unsigned BuiltinID, const CallExpr *E); - - llvm::Value *EmitAArch64CompareBuiltinExpr(llvm::Value *Op, llvm::Type *Ty, - const llvm::CmpInst::Predicate Fp, - const llvm::CmpInst::Predicate Ip, - const llvm::Twine &Name = ""); - llvm::Value *EmitARMBuiltinExpr(unsigned BuiltinID, const CallExpr *E, - llvm::Triple::ArchType Arch); - - llvm::Value *EmitCommonNeonBuiltinExpr(unsigned BuiltinID, - unsigned LLVMIntrinsic, - unsigned AltLLVMIntrinsic, - const char *NameHint, - unsigned Modifier, - const CallExpr *E, - SmallVectorImpl<llvm::Value *> &Ops, - Address PtrOp0, Address PtrOp1, - llvm::Triple::ArchType Arch); - - llvm::Value *EmitISOVolatileLoad(const CallExpr *E); - llvm::Value *EmitISOVolatileStore(const CallExpr *E); - - llvm::Function *LookupNeonLLVMIntrinsic(unsigned IntrinsicID, - unsigned Modifier, llvm::Type *ArgTy, - const CallExpr *E); - llvm::Value *EmitNeonCall(llvm::Function *F, - SmallVectorImpl<llvm::Value*> &O, - const char *name, - unsigned shift = 0, bool rightshift = false); - llvm::Value *EmitNeonSplat(llvm::Value *V, llvm::Constant *Idx); - llvm::Value *EmitNeonShiftVector(llvm::Value *V, llvm::Type *Ty, - bool negateForRightShift); - llvm::Value *EmitNeonRShiftImm(llvm::Value *Vec, llvm::Value *Amt, - llvm::Type *Ty, bool usgn, const char *name); - llvm::Value *vectorWrapScalar16(llvm::Value *Op); - llvm::Value *EmitAArch64BuiltinExpr(unsigned BuiltinID, const CallExpr *E, - llvm::Triple::ArchType Arch); - - llvm::Value *BuildVector(ArrayRef<llvm::Value*> Ops); - llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E); - llvm::Value *EmitPPCBuiltinExpr(unsigned BuiltinID, const CallExpr *E); - llvm::Value *EmitAMDGPUBuiltinExpr(unsigned BuiltinID, const CallExpr *E); - llvm::Value *EmitSystemZBuiltinExpr(unsigned BuiltinID, const CallExpr *E); - llvm::Value *EmitNVPTXBuiltinExpr(unsigned BuiltinID, const CallExpr *E); - llvm::Value *EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, - const CallExpr *E); - llvm::Value *EmitHexagonBuiltinExpr(unsigned BuiltinID, const CallExpr *E); - -private: - enum class MSVCIntrin; - -public: - llvm::Value *EmitMSVCBuiltinExpr(MSVCIntrin BuiltinID, const CallExpr *E); - - llvm::Value *EmitBuiltinAvailable(ArrayRef<llvm::Value *> Args); - - llvm::Value *EmitObjCProtocolExpr(const ObjCProtocolExpr *E); - llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E); - llvm::Value *EmitObjCBoxedExpr(const ObjCBoxedExpr *E); - llvm::Value *EmitObjCArrayLiteral(const ObjCArrayLiteral *E); - llvm::Value *EmitObjCDictionaryLiteral(const ObjCDictionaryLiteral *E); - llvm::Value *EmitObjCCollectionLiteral(const Expr *E, - const ObjCMethodDecl *MethodWithObjects); - llvm::Value *EmitObjCSelectorExpr(const ObjCSelectorExpr *E); - RValue EmitObjCMessageExpr(const ObjCMessageExpr *E, - ReturnValueSlot Return = ReturnValueSlot()); - - /// Retrieves the default cleanup kind for an ARC cleanup. - /// Except under -fobjc-arc-eh, ARC cleanups are normal-only. - CleanupKind getARCCleanupKind() { - return CGM.getCodeGenOpts().ObjCAutoRefCountExceptions - ? NormalAndEHCleanup : NormalCleanup; - } - - // ARC primitives. - void EmitARCInitWeak(Address addr, llvm::Value *value); - void EmitARCDestroyWeak(Address addr); - llvm::Value *EmitARCLoadWeak(Address addr); - llvm::Value *EmitARCLoadWeakRetained(Address addr); - llvm::Value *EmitARCStoreWeak(Address addr, llvm::Value *value, bool ignored); - void emitARCCopyAssignWeak(QualType Ty, Address DstAddr, Address SrcAddr); - void emitARCMoveAssignWeak(QualType Ty, Address DstAddr, Address SrcAddr); - void EmitARCCopyWeak(Address dst, Address src); - void EmitARCMoveWeak(Address dst, Address src); - llvm::Value *EmitARCRetainAutorelease(QualType type, llvm::Value *value); - llvm::Value *EmitARCRetainAutoreleaseNonBlock(llvm::Value *value); - llvm::Value *EmitARCStoreStrong(LValue lvalue, llvm::Value *value, - bool resultIgnored); - llvm::Value *EmitARCStoreStrongCall(Address addr, llvm::Value *value, - bool resultIgnored); - llvm::Value *EmitARCRetain(QualType type, llvm::Value *value); - llvm::Value *EmitARCRetainNonBlock(llvm::Value *value); - llvm::Value *EmitARCRetainBlock(llvm::Value *value, bool mandatory); - void EmitARCDestroyStrong(Address addr, ARCPreciseLifetime_t precise); - void EmitARCRelease(llvm::Value *value, ARCPreciseLifetime_t precise); - llvm::Value *EmitARCAutorelease(llvm::Value *value); - llvm::Value *EmitARCAutoreleaseReturnValue(llvm::Value *value); - llvm::Value *EmitARCRetainAutoreleaseReturnValue(llvm::Value *value); - llvm::Value *EmitARCRetainAutoreleasedReturnValue(llvm::Value *value); - llvm::Value *EmitARCUnsafeClaimAutoreleasedReturnValue(llvm::Value *value); - - llvm::Value *EmitObjCAutorelease(llvm::Value *value, llvm::Type *returnType); - llvm::Value *EmitObjCRetainNonBlock(llvm::Value *value, - llvm::Type *returnType); - void EmitObjCRelease(llvm::Value *value, ARCPreciseLifetime_t precise); - - std::pair<LValue,llvm::Value*> - EmitARCStoreAutoreleasing(const BinaryOperator *e); - std::pair<LValue,llvm::Value*> - EmitARCStoreStrong(const BinaryOperator *e, bool ignored); - std::pair<LValue,llvm::Value*> - EmitARCStoreUnsafeUnretained(const BinaryOperator *e, bool ignored); - - llvm::Value *EmitObjCAlloc(llvm::Value *value, - llvm::Type *returnType); - llvm::Value *EmitObjCAllocWithZone(llvm::Value *value, - llvm::Type *returnType); - llvm::Value *EmitObjCThrowOperand(const Expr *expr); - llvm::Value *EmitObjCConsumeObject(QualType T, llvm::Value *Ptr); - llvm::Value *EmitObjCExtendObjectLifetime(QualType T, llvm::Value *Ptr); - - llvm::Value *EmitARCExtendBlockObject(const Expr *expr); - llvm::Value *EmitARCReclaimReturnedObject(const Expr *e, - bool allowUnsafeClaim); - llvm::Value *EmitARCRetainScalarExpr(const Expr *expr); - llvm::Value *EmitARCRetainAutoreleaseScalarExpr(const Expr *expr); - llvm::Value *EmitARCUnsafeUnretainedScalarExpr(const Expr *expr); - - void EmitARCIntrinsicUse(ArrayRef<llvm::Value*> values); - - static Destroyer destroyARCStrongImprecise; - static Destroyer destroyARCStrongPrecise; - static Destroyer destroyARCWeak; - static Destroyer emitARCIntrinsicUse; - static Destroyer destroyNonTrivialCStruct; - - void EmitObjCAutoreleasePoolPop(llvm::Value *Ptr); - llvm::Value *EmitObjCAutoreleasePoolPush(); - llvm::Value *EmitObjCMRRAutoreleasePoolPush(); - void EmitObjCAutoreleasePoolCleanup(llvm::Value *Ptr); - void EmitObjCMRRAutoreleasePoolPop(llvm::Value *Ptr); - - /// Emits a reference binding to the passed in expression. - RValue EmitReferenceBindingToExpr(const Expr *E); - - //===--------------------------------------------------------------------===// - // Expression Emission - //===--------------------------------------------------------------------===// - - // Expressions are broken into three classes: scalar, complex, aggregate. - - /// EmitScalarExpr - Emit the computation of the specified expression of LLVM - /// scalar type, returning the result. - llvm::Value *EmitScalarExpr(const Expr *E , bool IgnoreResultAssign = false); - - /// Emit a conversion from the specified type to the specified destination - /// type, both of which are LLVM scalar types. - llvm::Value *EmitScalarConversion(llvm::Value *Src, QualType SrcTy, - QualType DstTy, SourceLocation Loc); - - /// Emit a conversion from the specified complex type to the specified - /// destination type, where the destination type is an LLVM scalar type. - llvm::Value *EmitComplexToScalarConversion(ComplexPairTy Src, QualType SrcTy, - QualType DstTy, - SourceLocation Loc); - - /// EmitAggExpr - Emit the computation of the specified expression - /// of aggregate type. The result is computed into the given slot, - /// which may be null to indicate that the value is not needed. - void EmitAggExpr(const Expr *E, AggValueSlot AS); - - /// EmitAggExprToLValue - Emit the computation of the specified expression of - /// aggregate type into a temporary LValue. - LValue EmitAggExprToLValue(const Expr *E); - - /// EmitExtendGCLifetime - Given a pointer to an Objective-C object, - /// make sure it survives garbage collection until this point. - void EmitExtendGCLifetime(llvm::Value *object); - - /// EmitComplexExpr - Emit the computation of the specified expression of - /// complex type, returning the result. - ComplexPairTy EmitComplexExpr(const Expr *E, - bool IgnoreReal = false, - bool IgnoreImag = false); - - /// EmitComplexExprIntoLValue - Emit the given expression of complex - /// type and place its result into the specified l-value. - void EmitComplexExprIntoLValue(const Expr *E, LValue dest, bool isInit); - - /// EmitStoreOfComplex - Store a complex number into the specified l-value. - void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit); - - /// EmitLoadOfComplex - Load a complex number from the specified l-value. - ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc); - - Address emitAddrOfRealComponent(Address complex, QualType complexType); - Address emitAddrOfImagComponent(Address complex, QualType complexType); - - /// AddInitializerToStaticVarDecl - Add the initializer for 'D' to the - /// global variable that has already been created for it. If the initializer - /// has a different type than GV does, this may free GV and return a different - /// one. Otherwise it just returns GV. - llvm::GlobalVariable * - AddInitializerToStaticVarDecl(const VarDecl &D, - llvm::GlobalVariable *GV); - - // Emit an @llvm.invariant.start call for the given memory region. - void EmitInvariantStart(llvm::Constant *Addr, CharUnits Size); - - /// EmitCXXGlobalVarDeclInit - Create the initializer for a C++ - /// variable with global storage. - void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::Constant *DeclPtr, - bool PerformInit); - - llvm::Constant *createAtExitStub(const VarDecl &VD, llvm::Constant *Dtor, - llvm::Constant *Addr); - - /// Call atexit() with a function that passes the given argument to - /// the given function. - void registerGlobalDtorWithAtExit(const VarDecl &D, llvm::Constant *fn, - llvm::Constant *addr); - - /// Call atexit() with function dtorStub. - void registerGlobalDtorWithAtExit(llvm::Constant *dtorStub); - - /// Emit code in this function to perform a guarded variable - /// initialization. Guarded initializations are used when it's not - /// possible to prove that an initialization will be done exactly - /// once, e.g. with a static local variable or a static data member - /// of a class template. - void EmitCXXGuardedInit(const VarDecl &D, llvm::GlobalVariable *DeclPtr, - bool PerformInit); - - enum class GuardKind { VariableGuard, TlsGuard }; - - /// Emit a branch to select whether or not to perform guarded initialization. - void EmitCXXGuardedInitBranch(llvm::Value *NeedsInit, - llvm::BasicBlock *InitBlock, - llvm::BasicBlock *NoInitBlock, - GuardKind Kind, const VarDecl *D); - - /// GenerateCXXGlobalInitFunc - Generates code for initializing global - /// variables. - void - GenerateCXXGlobalInitFunc(llvm::Function *Fn, - ArrayRef<llvm::Function *> CXXThreadLocals, - ConstantAddress Guard = ConstantAddress::invalid()); - - /// GenerateCXXGlobalDtorsFunc - Generates code for destroying global - /// variables. - void GenerateCXXGlobalDtorsFunc( - llvm::Function *Fn, - const std::vector<std::pair<llvm::WeakTrackingVH, llvm::Constant *>> - &DtorsAndObjects); - - void GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, - const VarDecl *D, - llvm::GlobalVariable *Addr, - bool PerformInit); - - void EmitCXXConstructExpr(const CXXConstructExpr *E, AggValueSlot Dest); - - void EmitSynthesizedCXXCopyCtor(Address Dest, Address Src, const Expr *Exp); - - void enterFullExpression(const FullExpr *E) { - if (const auto *EWC = dyn_cast<ExprWithCleanups>(E)) - if (EWC->getNumObjects() == 0) - return; - enterNonTrivialFullExpression(E); - } - void enterNonTrivialFullExpression(const FullExpr *E); - - void EmitCXXThrowExpr(const CXXThrowExpr *E, bool KeepInsertionPoint = true); - - void EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Dest); - - RValue EmitAtomicExpr(AtomicExpr *E); - - //===--------------------------------------------------------------------===// - // Annotations Emission - //===--------------------------------------------------------------------===// - - /// Emit an annotation call (intrinsic or builtin). - llvm::Value *EmitAnnotationCall(llvm::Value *AnnotationFn, - llvm::Value *AnnotatedVal, - StringRef AnnotationStr, - SourceLocation Location); - - /// Emit local annotations for the local variable V, declared by D. - void EmitVarAnnotations(const VarDecl *D, llvm::Value *V); - - /// Emit field annotations for the given field & value. Returns the - /// annotation result. - Address EmitFieldAnnotations(const FieldDecl *D, Address V); - - //===--------------------------------------------------------------------===// - // Internal Helpers - //===--------------------------------------------------------------------===// - - /// ContainsLabel - Return true if the statement contains a label in it. If - /// this statement is not executed normally, it not containing a label means - /// that we can just remove the code. - static bool ContainsLabel(const Stmt *S, bool IgnoreCaseStmts = false); - - /// containsBreak - Return true if the statement contains a break out of it. - /// If the statement (recursively) contains a switch or loop with a break - /// inside of it, this is fine. - static bool containsBreak(const Stmt *S); - - /// Determine if the given statement might introduce a declaration into the - /// current scope, by being a (possibly-labelled) DeclStmt. - static bool mightAddDeclToScope(const Stmt *S); - - /// ConstantFoldsToSimpleInteger - If the specified expression does not fold - /// to a constant, or if it does but contains a label, return false. If it - /// constant folds return true and set the boolean result in Result. - bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, - bool AllowLabels = false); - - /// ConstantFoldsToSimpleInteger - If the specified expression does not fold - /// to a constant, or if it does but contains a label, return false. If it - /// constant folds return true and set the folded value. - bool ConstantFoldsToSimpleInteger(const Expr *Cond, llvm::APSInt &Result, - bool AllowLabels = false); - - /// EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g. for an - /// if statement) to the specified blocks. Based on the condition, this might - /// try to simplify the codegen of the conditional based on the branch. - /// TrueCount should be the number of times we expect the condition to - /// evaluate to true based on PGO data. - void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, - llvm::BasicBlock *FalseBlock, uint64_t TrueCount); - - /// Given an assignment `*LHS = RHS`, emit a test that checks if \p RHS is - /// nonnull, if \p LHS is marked _Nonnull. - void EmitNullabilityCheck(LValue LHS, llvm::Value *RHS, SourceLocation Loc); - - /// An enumeration which makes it easier to specify whether or not an - /// operation is a subtraction. - enum { NotSubtraction = false, IsSubtraction = true }; - - /// Same as IRBuilder::CreateInBoundsGEP, but additionally emits a check to - /// detect undefined behavior when the pointer overflow sanitizer is enabled. - /// \p SignedIndices indicates whether any of the GEP indices are signed. - /// \p IsSubtraction indicates whether the expression used to form the GEP - /// is a subtraction. - llvm::Value *EmitCheckedInBoundsGEP(llvm::Value *Ptr, - ArrayRef<llvm::Value *> IdxList, - bool SignedIndices, - bool IsSubtraction, - SourceLocation Loc, - const Twine &Name = ""); - - /// Specifies which type of sanitizer check to apply when handling a - /// particular builtin. - enum BuiltinCheckKind { - BCK_CTZPassedZero, - BCK_CLZPassedZero, - }; - - /// Emits an argument for a call to a builtin. If the builtin sanitizer is - /// enabled, a runtime check specified by \p Kind is also emitted. - llvm::Value *EmitCheckedArgForBuiltin(const Expr *E, BuiltinCheckKind Kind); - - /// Emit a description of a type in a format suitable for passing to - /// a runtime sanitizer handler. - llvm::Constant *EmitCheckTypeDescriptor(QualType T); - - /// Convert a value into a format suitable for passing to a runtime - /// sanitizer handler. - llvm::Value *EmitCheckValue(llvm::Value *V); - - /// Emit a description of a source location in a format suitable for - /// passing to a runtime sanitizer handler. - llvm::Constant *EmitCheckSourceLocation(SourceLocation Loc); - - /// Create a basic block that will call a handler function in a - /// sanitizer runtime with the provided arguments, and create a conditional - /// branch to it. - void EmitCheck(ArrayRef<std::pair<llvm::Value *, SanitizerMask>> Checked, - SanitizerHandler Check, ArrayRef<llvm::Constant *> StaticArgs, - ArrayRef<llvm::Value *> DynamicArgs); - - /// Emit a slow path cross-DSO CFI check which calls __cfi_slowpath - /// if Cond if false. - void EmitCfiSlowPathCheck(SanitizerMask Kind, llvm::Value *Cond, - llvm::ConstantInt *TypeId, llvm::Value *Ptr, - ArrayRef<llvm::Constant *> StaticArgs); - - /// Emit a reached-unreachable diagnostic if \p Loc is valid and runtime - /// checking is enabled. Otherwise, just emit an unreachable instruction. - void EmitUnreachable(SourceLocation Loc); - - /// Create a basic block that will call the trap intrinsic, and emit a - /// conditional branch to it, for the -ftrapv checks. - void EmitTrapCheck(llvm::Value *Checked); - - /// Emit a call to trap or debugtrap and attach function attribute - /// "trap-func-name" if specified. - llvm::CallInst *EmitTrapCall(llvm::Intrinsic::ID IntrID); - - /// Emit a stub for the cross-DSO CFI check function. - void EmitCfiCheckStub(); - - /// Emit a cross-DSO CFI failure handling function. - void EmitCfiCheckFail(); - - /// Create a check for a function parameter that may potentially be - /// declared as non-null. - void EmitNonNullArgCheck(RValue RV, QualType ArgType, SourceLocation ArgLoc, - AbstractCallee AC, unsigned ParmNum); - - /// EmitCallArg - Emit a single call argument. - void EmitCallArg(CallArgList &args, const Expr *E, QualType ArgType); - - /// EmitDelegateCallArg - We are performing a delegate call; that - /// is, the current function is delegating to another one. Produce - /// a r-value suitable for passing the given parameter. - void EmitDelegateCallArg(CallArgList &args, const VarDecl *param, - SourceLocation loc); - - /// SetFPAccuracy - Set the minimum required accuracy of the given floating - /// point operation, expressed as the maximum relative error in ulp. - void SetFPAccuracy(llvm::Value *Val, float Accuracy); - -private: - llvm::MDNode *getRangeForLoadFromType(QualType Ty); - void EmitReturnOfRValue(RValue RV, QualType Ty); - - void deferPlaceholderReplacement(llvm::Instruction *Old, llvm::Value *New); - - llvm::SmallVector<std::pair<llvm::Instruction *, llvm::Value *>, 4> - DeferredReplacements; - - /// Set the address of a local variable. - void setAddrOfLocalVar(const VarDecl *VD, Address Addr) { - assert(!LocalDeclMap.count(VD) && "Decl already exists in LocalDeclMap!"); - LocalDeclMap.insert({VD, Addr}); - } - - /// ExpandTypeFromArgs - Reconstruct a structure of type \arg Ty - /// from function arguments into \arg Dst. See ABIArgInfo::Expand. - /// - /// \param AI - The first function argument of the expansion. - void ExpandTypeFromArgs(QualType Ty, LValue Dst, - SmallVectorImpl<llvm::Value *>::iterator &AI); - - /// ExpandTypeToArgs - Expand an CallArg \arg Arg, with the LLVM type for \arg - /// Ty, into individual arguments on the provided vector \arg IRCallArgs, - /// starting at index \arg IRCallArgPos. See ABIArgInfo::Expand. - void ExpandTypeToArgs(QualType Ty, CallArg Arg, llvm::FunctionType *IRFuncTy, - SmallVectorImpl<llvm::Value *> &IRCallArgs, - unsigned &IRCallArgPos); - - llvm::Value* EmitAsmInput(const TargetInfo::ConstraintInfo &Info, - const Expr *InputExpr, std::string &ConstraintStr); - - llvm::Value* EmitAsmInputLValue(const TargetInfo::ConstraintInfo &Info, - LValue InputValue, QualType InputType, - std::string &ConstraintStr, - SourceLocation Loc); - - /// Attempts to statically evaluate the object size of E. If that - /// fails, emits code to figure the size of E out for us. This is - /// pass_object_size aware. - /// - /// If EmittedExpr is non-null, this will use that instead of re-emitting E. - llvm::Value *evaluateOrEmitBuiltinObjectSize(const Expr *E, unsigned Type, - llvm::IntegerType *ResType, - llvm::Value *EmittedE); - - /// Emits the size of E, as required by __builtin_object_size. This - /// function is aware of pass_object_size parameters, and will act accordingly - /// if E is a parameter with the pass_object_size attribute. - llvm::Value *emitBuiltinObjectSize(const Expr *E, unsigned Type, - llvm::IntegerType *ResType, - llvm::Value *EmittedE); - -public: -#ifndef NDEBUG - // Determine whether the given argument is an Objective-C method - // that may have type parameters in its signature. - static bool isObjCMethodWithTypeParams(const ObjCMethodDecl *method) { - const DeclContext *dc = method->getDeclContext(); - if (const ObjCInterfaceDecl *classDecl= dyn_cast<ObjCInterfaceDecl>(dc)) { - return classDecl->getTypeParamListAsWritten(); - } - - if (const ObjCCategoryDecl *catDecl = dyn_cast<ObjCCategoryDecl>(dc)) { - return catDecl->getTypeParamList(); - } - - return false; - } - - template<typename T> - static bool isObjCMethodWithTypeParams(const T *) { return false; } -#endif - - enum class EvaluationOrder { - ///! No language constraints on evaluation order. - Default, - ///! Language semantics require left-to-right evaluation. - ForceLeftToRight, - ///! Language semantics require right-to-left evaluation. - ForceRightToLeft - }; - - /// EmitCallArgs - Emit call arguments for a function. - template <typename T> - void EmitCallArgs(CallArgList &Args, const T *CallArgTypeInfo, - llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange, - AbstractCallee AC = AbstractCallee(), - unsigned ParamsToSkip = 0, - EvaluationOrder Order = EvaluationOrder::Default) { - SmallVector<QualType, 16> ArgTypes; - CallExpr::const_arg_iterator Arg = ArgRange.begin(); - - assert((ParamsToSkip == 0 || CallArgTypeInfo) && - "Can't skip parameters if type info is not provided"); - if (CallArgTypeInfo) { -#ifndef NDEBUG - bool isGenericMethod = isObjCMethodWithTypeParams(CallArgTypeInfo); -#endif - - // First, use the argument types that the type info knows about - for (auto I = CallArgTypeInfo->param_type_begin() + ParamsToSkip, - E = CallArgTypeInfo->param_type_end(); - I != E; ++I, ++Arg) { - assert(Arg != ArgRange.end() && "Running over edge of argument list!"); - assert((isGenericMethod || - ((*I)->isVariablyModifiedType() || - (*I).getNonReferenceType()->isObjCRetainableType() || - getContext() - .getCanonicalType((*I).getNonReferenceType()) - .getTypePtr() == - getContext() - .getCanonicalType((*Arg)->getType()) - .getTypePtr())) && - "type mismatch in call argument!"); - ArgTypes.push_back(*I); - } - } - - // Either we've emitted all the call args, or we have a call to variadic - // function. - assert((Arg == ArgRange.end() || !CallArgTypeInfo || - CallArgTypeInfo->isVariadic()) && - "Extra arguments in non-variadic function!"); - - // If we still have any arguments, emit them using the type of the argument. - for (auto *A : llvm::make_range(Arg, ArgRange.end())) - ArgTypes.push_back(CallArgTypeInfo ? getVarArgType(A) : A->getType()); - - EmitCallArgs(Args, ArgTypes, ArgRange, AC, ParamsToSkip, Order); - } - - void EmitCallArgs(CallArgList &Args, ArrayRef<QualType> ArgTypes, - llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange, - AbstractCallee AC = AbstractCallee(), - unsigned ParamsToSkip = 0, - EvaluationOrder Order = EvaluationOrder::Default); - - /// EmitPointerWithAlignment - Given an expression with a pointer type, - /// emit the value and compute our best estimate of the alignment of the - /// pointee. - /// - /// \param BaseInfo - If non-null, this will be initialized with - /// information about the source of the alignment and the may-alias - /// attribute. Note that this function will conservatively fall back on - /// the type when it doesn't recognize the expression and may-alias will - /// be set to false. - /// - /// One reasonable way to use this information is when there's a language - /// guarantee that the pointer must be aligned to some stricter value, and - /// we're simply trying to ensure that sufficiently obvious uses of under- - /// aligned objects don't get miscompiled; for example, a placement new - /// into the address of a local variable. In such a case, it's quite - /// reasonable to just ignore the returned alignment when it isn't from an - /// explicit source. - Address EmitPointerWithAlignment(const Expr *Addr, - LValueBaseInfo *BaseInfo = nullptr, - TBAAAccessInfo *TBAAInfo = nullptr); - - /// If \p E references a parameter with pass_object_size info or a constant - /// array size modifier, emit the object size divided by the size of \p EltTy. - /// Otherwise return null. - llvm::Value *LoadPassedObjectSize(const Expr *E, QualType EltTy); - - void EmitSanitizerStatReport(llvm::SanitizerStatKind SSK); - - struct MultiVersionResolverOption { - llvm::Function *Function; - FunctionDecl *FD; - struct Conds { - StringRef Architecture; - llvm::SmallVector<StringRef, 8> Features; - - Conds(StringRef Arch, ArrayRef<StringRef> Feats) - : Architecture(Arch), Features(Feats.begin(), Feats.end()) {} - } Conditions; - - MultiVersionResolverOption(llvm::Function *F, StringRef Arch, - ArrayRef<StringRef> Feats) - : Function(F), Conditions(Arch, Feats) {} - }; - - // Emits the body of a multiversion function's resolver. Assumes that the - // options are already sorted in the proper order, with the 'default' option - // last (if it exists). - void EmitMultiVersionResolver(llvm::Function *Resolver, - ArrayRef<MultiVersionResolverOption> Options); - - static uint64_t GetX86CpuSupportsMask(ArrayRef<StringRef> FeatureStrs); - -private: - QualType getVarArgType(const Expr *Arg); - - void EmitDeclMetadata(); - - BlockByrefHelpers *buildByrefHelpers(llvm::StructType &byrefType, - const AutoVarEmission &emission); - - void AddObjCARCExceptionMetadata(llvm::Instruction *Inst); - - llvm::Value *GetValueForARMHint(unsigned BuiltinID); - llvm::Value *EmitX86CpuIs(const CallExpr *E); - llvm::Value *EmitX86CpuIs(StringRef CPUStr); - llvm::Value *EmitX86CpuSupports(const CallExpr *E); - llvm::Value *EmitX86CpuSupports(ArrayRef<StringRef> FeatureStrs); - llvm::Value *EmitX86CpuSupports(uint64_t Mask); - llvm::Value *EmitX86CpuInit(); - llvm::Value *FormResolverCondition(const MultiVersionResolverOption &RO); -}; - -inline DominatingLLVMValue::saved_type -DominatingLLVMValue::save(CodeGenFunction &CGF, llvm::Value *value) { - if (!needsSaving(value)) return saved_type(value, false); - - // Otherwise, we need an alloca. - auto align = CharUnits::fromQuantity( - CGF.CGM.getDataLayout().getPrefTypeAlignment(value->getType())); - Address alloca = - CGF.CreateTempAlloca(value->getType(), align, "cond-cleanup.save"); - CGF.Builder.CreateStore(value, alloca); - - return saved_type(alloca.getPointer(), true); -} - -inline llvm::Value *DominatingLLVMValue::restore(CodeGenFunction &CGF, - saved_type value) { - // If the value says it wasn't saved, trust that it's still dominating. - if (!value.getInt()) return value.getPointer(); - - // Otherwise, it should be an alloca instruction, as set up in save(). - auto alloca = cast<llvm::AllocaInst>(value.getPointer()); - return CGF.Builder.CreateAlignedLoad(alloca, alloca->getAlignment()); -} - -} // end namespace CodeGen -} // end namespace clang - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp deleted file mode 100644 index 2ac59fb4de2..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp +++ /dev/null @@ -1,5511 +0,0 @@ -//===--- CodeGenModule.cpp - Emit LLVM Code from ASTs for a Module --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This coordinates the per-module state used while generating code. -// -//===----------------------------------------------------------------------===// - -#include "CodeGenModule.h" -#include "CGBlocks.h" -#include "CGCUDARuntime.h" -#include "CGCXXABI.h" -#include "CGCall.h" -#include "CGDebugInfo.h" -#include "CGObjCRuntime.h" -#include "CGOpenCLRuntime.h" -#include "CGOpenMPRuntime.h" -#include "CGOpenMPRuntimeNVPTX.h" -#include "CodeGenFunction.h" -#include "CodeGenPGO.h" -#include "ConstantEmitter.h" -#include "CoverageMappingGen.h" -#include "TargetInfo.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/CharUnits.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/Mangle.h" -#include "clang/AST/RecordLayout.h" -#include "clang/AST/RecursiveASTVisitor.h" -#include "clang/Basic/Builtins.h" -#include "clang/Basic/CharInfo.h" -#include "clang/Basic/CodeGenOptions.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/Module.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Basic/Version.h" -#include "clang/CodeGen/ConstantInitBuilder.h" -#include "clang/Frontend/FrontendDiagnostic.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/Triple.h" -#include "llvm/Analysis/TargetLibraryInfo.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/ProfileData/InstrProfReader.h" -#include "llvm/Support/CodeGen.h" -#include "llvm/Support/ConvertUTF.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MD5.h" - -using namespace clang; -using namespace CodeGen; - -static llvm::cl::opt<bool> LimitedCoverage( - "limited-coverage-experimental", llvm::cl::ZeroOrMore, llvm::cl::Hidden, - llvm::cl::desc("Emit limited coverage mapping information (experimental)"), - llvm::cl::init(false)); - -static const char AnnotationSection[] = "llvm.metadata"; - -static CGCXXABI *createCXXABI(CodeGenModule &CGM) { - switch (CGM.getTarget().getCXXABI().getKind()) { - case TargetCXXABI::GenericAArch64: - case TargetCXXABI::GenericARM: - case TargetCXXABI::iOS: - case TargetCXXABI::iOS64: - case TargetCXXABI::WatchOS: - case TargetCXXABI::GenericMIPS: - case TargetCXXABI::GenericItanium: - case TargetCXXABI::WebAssembly: - return CreateItaniumCXXABI(CGM); - case TargetCXXABI::Microsoft: - return CreateMicrosoftCXXABI(CGM); - } - - llvm_unreachable("invalid C++ ABI kind"); -} - -CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO, - const PreprocessorOptions &PPO, - const CodeGenOptions &CGO, llvm::Module &M, - DiagnosticsEngine &diags, - CoverageSourceInfo *CoverageInfo) - : Context(C), LangOpts(C.getLangOpts()), HeaderSearchOpts(HSO), - PreprocessorOpts(PPO), CodeGenOpts(CGO), TheModule(M), Diags(diags), - Target(C.getTargetInfo()), ABI(createCXXABI(*this)), - VMContext(M.getContext()), Types(*this), VTables(*this), - SanitizerMD(new SanitizerMetadata(*this)) { - - // Initialize the type cache. - llvm::LLVMContext &LLVMContext = M.getContext(); - VoidTy = llvm::Type::getVoidTy(LLVMContext); - Int8Ty = llvm::Type::getInt8Ty(LLVMContext); - Int16Ty = llvm::Type::getInt16Ty(LLVMContext); - Int32Ty = llvm::Type::getInt32Ty(LLVMContext); - Int64Ty = llvm::Type::getInt64Ty(LLVMContext); - HalfTy = llvm::Type::getHalfTy(LLVMContext); - FloatTy = llvm::Type::getFloatTy(LLVMContext); - DoubleTy = llvm::Type::getDoubleTy(LLVMContext); - PointerWidthInBits = C.getTargetInfo().getPointerWidth(0); - PointerAlignInBytes = - C.toCharUnitsFromBits(C.getTargetInfo().getPointerAlign(0)).getQuantity(); - SizeSizeInBytes = - C.toCharUnitsFromBits(C.getTargetInfo().getMaxPointerWidth()).getQuantity(); - IntAlignInBytes = - C.toCharUnitsFromBits(C.getTargetInfo().getIntAlign()).getQuantity(); - IntTy = llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getIntWidth()); - IntPtrTy = llvm::IntegerType::get(LLVMContext, - C.getTargetInfo().getMaxPointerWidth()); - Int8PtrTy = Int8Ty->getPointerTo(0); - Int8PtrPtrTy = Int8PtrTy->getPointerTo(0); - AllocaInt8PtrTy = Int8Ty->getPointerTo( - M.getDataLayout().getAllocaAddrSpace()); - ASTAllocaAddressSpace = getTargetCodeGenInfo().getASTAllocaAddressSpace(); - - RuntimeCC = getTargetCodeGenInfo().getABIInfo().getRuntimeCC(); - - if (LangOpts.ObjC) - createObjCRuntime(); - if (LangOpts.OpenCL) - createOpenCLRuntime(); - if (LangOpts.OpenMP) - createOpenMPRuntime(); - if (LangOpts.CUDA) - createCUDARuntime(); - - // Enable TBAA unless it's suppressed. ThreadSanitizer needs TBAA even at O0. - if (LangOpts.Sanitize.has(SanitizerKind::Thread) || - (!CodeGenOpts.RelaxedAliasing && CodeGenOpts.OptimizationLevel > 0)) - TBAA.reset(new CodeGenTBAA(Context, TheModule, CodeGenOpts, getLangOpts(), - getCXXABI().getMangleContext())); - - // If debug info or coverage generation is enabled, create the CGDebugInfo - // object. - if (CodeGenOpts.getDebugInfo() != codegenoptions::NoDebugInfo || - CodeGenOpts.EmitGcovArcs || CodeGenOpts.EmitGcovNotes) - DebugInfo.reset(new CGDebugInfo(*this)); - - Block.GlobalUniqueCount = 0; - - if (C.getLangOpts().ObjC) - ObjCData.reset(new ObjCEntrypoints()); - - if (CodeGenOpts.hasProfileClangUse()) { - auto ReaderOrErr = llvm::IndexedInstrProfReader::create( - CodeGenOpts.ProfileInstrumentUsePath, CodeGenOpts.ProfileRemappingFile); - if (auto E = ReaderOrErr.takeError()) { - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "Could not read profile %0: %1"); - llvm::handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EI) { - getDiags().Report(DiagID) << CodeGenOpts.ProfileInstrumentUsePath - << EI.message(); - }); - } else - PGOReader = std::move(ReaderOrErr.get()); - } - - // If coverage mapping generation is enabled, create the - // CoverageMappingModuleGen object. - if (CodeGenOpts.CoverageMapping) - CoverageMapping.reset(new CoverageMappingModuleGen(*this, *CoverageInfo)); -} - -CodeGenModule::~CodeGenModule() {} - -void CodeGenModule::createObjCRuntime() { - // This is just isGNUFamily(), but we want to force implementors of - // new ABIs to decide how best to do this. - switch (LangOpts.ObjCRuntime.getKind()) { - case ObjCRuntime::GNUstep: - case ObjCRuntime::GCC: - case ObjCRuntime::ObjFW: - ObjCRuntime.reset(CreateGNUObjCRuntime(*this)); - return; - - case ObjCRuntime::FragileMacOSX: - case ObjCRuntime::MacOSX: - case ObjCRuntime::iOS: - case ObjCRuntime::WatchOS: - ObjCRuntime.reset(CreateMacObjCRuntime(*this)); - return; - } - llvm_unreachable("bad runtime kind"); -} - -void CodeGenModule::createOpenCLRuntime() { - OpenCLRuntime.reset(new CGOpenCLRuntime(*this)); -} - -void CodeGenModule::createOpenMPRuntime() { - // Select a specialized code generation class based on the target, if any. - // If it does not exist use the default implementation. - switch (getTriple().getArch()) { - case llvm::Triple::nvptx: - case llvm::Triple::nvptx64: - assert(getLangOpts().OpenMPIsDevice && - "OpenMP NVPTX is only prepared to deal with device code."); - OpenMPRuntime.reset(new CGOpenMPRuntimeNVPTX(*this)); - break; - default: - if (LangOpts.OpenMPSimd) - OpenMPRuntime.reset(new CGOpenMPSIMDRuntime(*this)); - else - OpenMPRuntime.reset(new CGOpenMPRuntime(*this)); - break; - } -} - -void CodeGenModule::createCUDARuntime() { - CUDARuntime.reset(CreateNVCUDARuntime(*this)); -} - -void CodeGenModule::addReplacement(StringRef Name, llvm::Constant *C) { - Replacements[Name] = C; -} - -void CodeGenModule::applyReplacements() { - for (auto &I : Replacements) { - StringRef MangledName = I.first(); - llvm::Constant *Replacement = I.second; - llvm::GlobalValue *Entry = GetGlobalValue(MangledName); - if (!Entry) - continue; - auto *OldF = cast<llvm::Function>(Entry); - auto *NewF = dyn_cast<llvm::Function>(Replacement); - if (!NewF) { - if (auto *Alias = dyn_cast<llvm::GlobalAlias>(Replacement)) { - NewF = dyn_cast<llvm::Function>(Alias->getAliasee()); - } else { - auto *CE = cast<llvm::ConstantExpr>(Replacement); - assert(CE->getOpcode() == llvm::Instruction::BitCast || - CE->getOpcode() == llvm::Instruction::GetElementPtr); - NewF = dyn_cast<llvm::Function>(CE->getOperand(0)); - } - } - - // Replace old with new, but keep the old order. - OldF->replaceAllUsesWith(Replacement); - if (NewF) { - NewF->removeFromParent(); - OldF->getParent()->getFunctionList().insertAfter(OldF->getIterator(), - NewF); - } - OldF->eraseFromParent(); - } -} - -void CodeGenModule::addGlobalValReplacement(llvm::GlobalValue *GV, llvm::Constant *C) { - GlobalValReplacements.push_back(std::make_pair(GV, C)); -} - -void CodeGenModule::applyGlobalValReplacements() { - for (auto &I : GlobalValReplacements) { - llvm::GlobalValue *GV = I.first; - llvm::Constant *C = I.second; - - GV->replaceAllUsesWith(C); - GV->eraseFromParent(); - } -} - -// This is only used in aliases that we created and we know they have a -// linear structure. -static const llvm::GlobalObject *getAliasedGlobal( - const llvm::GlobalIndirectSymbol &GIS) { - llvm::SmallPtrSet<const llvm::GlobalIndirectSymbol*, 4> Visited; - const llvm::Constant *C = &GIS; - for (;;) { - C = C->stripPointerCasts(); - if (auto *GO = dyn_cast<llvm::GlobalObject>(C)) - return GO; - // stripPointerCasts will not walk over weak aliases. - auto *GIS2 = dyn_cast<llvm::GlobalIndirectSymbol>(C); - if (!GIS2) - return nullptr; - if (!Visited.insert(GIS2).second) - return nullptr; - C = GIS2->getIndirectSymbol(); - } -} - -void CodeGenModule::checkAliases() { - // Check if the constructed aliases are well formed. It is really unfortunate - // that we have to do this in CodeGen, but we only construct mangled names - // and aliases during codegen. - bool Error = false; - DiagnosticsEngine &Diags = getDiags(); - for (const GlobalDecl &GD : Aliases) { - const auto *D = cast<ValueDecl>(GD.getDecl()); - SourceLocation Location; - bool IsIFunc = D->hasAttr<IFuncAttr>(); - if (const Attr *A = D->getDefiningAttr()) - Location = A->getLocation(); - else - llvm_unreachable("Not an alias or ifunc?"); - StringRef MangledName = getMangledName(GD); - llvm::GlobalValue *Entry = GetGlobalValue(MangledName); - auto *Alias = cast<llvm::GlobalIndirectSymbol>(Entry); - const llvm::GlobalValue *GV = getAliasedGlobal(*Alias); - if (!GV) { - Error = true; - Diags.Report(Location, diag::err_cyclic_alias) << IsIFunc; - } else if (GV->isDeclaration()) { - Error = true; - Diags.Report(Location, diag::err_alias_to_undefined) - << IsIFunc << IsIFunc; - } else if (IsIFunc) { - // Check resolver function type. - llvm::FunctionType *FTy = dyn_cast<llvm::FunctionType>( - GV->getType()->getPointerElementType()); - assert(FTy); - if (!FTy->getReturnType()->isPointerTy()) - Diags.Report(Location, diag::err_ifunc_resolver_return); - } - - llvm::Constant *Aliasee = Alias->getIndirectSymbol(); - llvm::GlobalValue *AliaseeGV; - if (auto CE = dyn_cast<llvm::ConstantExpr>(Aliasee)) - AliaseeGV = cast<llvm::GlobalValue>(CE->getOperand(0)); - else - AliaseeGV = cast<llvm::GlobalValue>(Aliasee); - - if (const SectionAttr *SA = D->getAttr<SectionAttr>()) { - StringRef AliasSection = SA->getName(); - if (AliasSection != AliaseeGV->getSection()) - Diags.Report(SA->getLocation(), diag::warn_alias_with_section) - << AliasSection << IsIFunc << IsIFunc; - } - - // We have to handle alias to weak aliases in here. LLVM itself disallows - // this since the object semantics would not match the IL one. For - // compatibility with gcc we implement it by just pointing the alias - // to its aliasee's aliasee. We also warn, since the user is probably - // expecting the link to be weak. - if (auto GA = dyn_cast<llvm::GlobalIndirectSymbol>(AliaseeGV)) { - if (GA->isInterposable()) { - Diags.Report(Location, diag::warn_alias_to_weak_alias) - << GV->getName() << GA->getName() << IsIFunc; - Aliasee = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast( - GA->getIndirectSymbol(), Alias->getType()); - Alias->setIndirectSymbol(Aliasee); - } - } - } - if (!Error) - return; - - for (const GlobalDecl &GD : Aliases) { - StringRef MangledName = getMangledName(GD); - llvm::GlobalValue *Entry = GetGlobalValue(MangledName); - auto *Alias = dyn_cast<llvm::GlobalIndirectSymbol>(Entry); - Alias->replaceAllUsesWith(llvm::UndefValue::get(Alias->getType())); - Alias->eraseFromParent(); - } -} - -void CodeGenModule::clear() { - DeferredDeclsToEmit.clear(); - if (OpenMPRuntime) - OpenMPRuntime->clear(); -} - -void InstrProfStats::reportDiagnostics(DiagnosticsEngine &Diags, - StringRef MainFile) { - if (!hasDiagnostics()) - return; - if (VisitedInMainFile > 0 && VisitedInMainFile == MissingInMainFile) { - if (MainFile.empty()) - MainFile = "<stdin>"; - Diags.Report(diag::warn_profile_data_unprofiled) << MainFile; - } else { - if (Mismatched > 0) - Diags.Report(diag::warn_profile_data_out_of_date) << Visited << Mismatched; - - if (Missing > 0) - Diags.Report(diag::warn_profile_data_missing) << Visited << Missing; - } -} - -void CodeGenModule::Release() { - EmitDeferred(); - EmitVTablesOpportunistically(); - applyGlobalValReplacements(); - applyReplacements(); - checkAliases(); - emitMultiVersionFunctions(); - EmitCXXGlobalInitFunc(); - EmitCXXGlobalDtorFunc(); - registerGlobalDtorsWithAtExit(); - EmitCXXThreadLocalInitFunc(); - if (ObjCRuntime) - if (llvm::Function *ObjCInitFunction = ObjCRuntime->ModuleInitFunction()) - AddGlobalCtor(ObjCInitFunction); - if (Context.getLangOpts().CUDA && !Context.getLangOpts().CUDAIsDevice && - CUDARuntime) { - if (llvm::Function *CudaCtorFunction = - CUDARuntime->makeModuleCtorFunction()) - AddGlobalCtor(CudaCtorFunction); - } - if (OpenMPRuntime) { - if (llvm::Function *OpenMPRegistrationFunction = - OpenMPRuntime->emitRegistrationFunction()) { - auto ComdatKey = OpenMPRegistrationFunction->hasComdat() ? - OpenMPRegistrationFunction : nullptr; - AddGlobalCtor(OpenMPRegistrationFunction, 0, ComdatKey); - } - OpenMPRuntime->clear(); - } - if (PGOReader) { - getModule().setProfileSummary(PGOReader->getSummary().getMD(VMContext)); - if (PGOStats.hasDiagnostics()) - PGOStats.reportDiagnostics(getDiags(), getCodeGenOpts().MainFileName); - } - EmitCtorList(GlobalCtors, "llvm.global_ctors"); - EmitCtorList(GlobalDtors, "llvm.global_dtors"); - EmitGlobalAnnotations(); - EmitStaticExternCAliases(); - EmitDeferredUnusedCoverageMappings(); - if (CoverageMapping) - CoverageMapping->emit(); - if (CodeGenOpts.SanitizeCfiCrossDso) { - CodeGenFunction(*this).EmitCfiCheckFail(); - CodeGenFunction(*this).EmitCfiCheckStub(); - } - emitAtAvailableLinkGuard(); - emitLLVMUsed(); - if (SanStats) - SanStats->finish(); - - if (CodeGenOpts.Autolink && - (Context.getLangOpts().Modules || !LinkerOptionsMetadata.empty())) { - EmitModuleLinkOptions(); - } - - // Record mregparm value now so it is visible through rest of codegen. - if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) - getModule().addModuleFlag(llvm::Module::Error, "NumRegisterParameters", - CodeGenOpts.NumRegisterParameters); - - if (CodeGenOpts.DwarfVersion) { - // We actually want the latest version when there are conflicts. - // We can change from Warning to Latest if such mode is supported. - getModule().addModuleFlag(llvm::Module::Warning, "Dwarf Version", - CodeGenOpts.DwarfVersion); - } - if (CodeGenOpts.EmitCodeView) { - // Indicate that we want CodeView in the metadata. - getModule().addModuleFlag(llvm::Module::Warning, "CodeView", 1); - } - if (CodeGenOpts.CodeViewGHash) { - getModule().addModuleFlag(llvm::Module::Warning, "CodeViewGHash", 1); - } - if (CodeGenOpts.ControlFlowGuard) { - // We want function ID tables for Control Flow Guard. - getModule().addModuleFlag(llvm::Module::Warning, "cfguardtable", 1); - } - if (CodeGenOpts.OptimizationLevel > 0 && CodeGenOpts.StrictVTablePointers) { - // We don't support LTO with 2 with different StrictVTablePointers - // FIXME: we could support it by stripping all the information introduced - // by StrictVTablePointers. - - getModule().addModuleFlag(llvm::Module::Error, "StrictVTablePointers",1); - - llvm::Metadata *Ops[2] = { - llvm::MDString::get(VMContext, "StrictVTablePointers"), - llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - llvm::Type::getInt32Ty(VMContext), 1))}; - - getModule().addModuleFlag(llvm::Module::Require, - "StrictVTablePointersRequirement", - llvm::MDNode::get(VMContext, Ops)); - } - if (DebugInfo) - // We support a single version in the linked module. The LLVM - // parser will drop debug info with a different version number - // (and warn about it, too). - getModule().addModuleFlag(llvm::Module::Warning, "Debug Info Version", - llvm::DEBUG_METADATA_VERSION); - - // We need to record the widths of enums and wchar_t, so that we can generate - // the correct build attributes in the ARM backend. wchar_size is also used by - // TargetLibraryInfo. - uint64_t WCharWidth = - Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity(); - getModule().addModuleFlag(llvm::Module::Error, "wchar_size", WCharWidth); - - llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch(); - if ( Arch == llvm::Triple::arm - || Arch == llvm::Triple::armeb - || Arch == llvm::Triple::thumb - || Arch == llvm::Triple::thumbeb) { - // The minimum width of an enum in bytes - uint64_t EnumWidth = Context.getLangOpts().ShortEnums ? 1 : 4; - getModule().addModuleFlag(llvm::Module::Error, "min_enum_size", EnumWidth); - } - - if (CodeGenOpts.SanitizeCfiCrossDso) { - // Indicate that we want cross-DSO control flow integrity checks. - getModule().addModuleFlag(llvm::Module::Override, "Cross-DSO CFI", 1); - } - - if (CodeGenOpts.CFProtectionReturn && - Target.checkCFProtectionReturnSupported(getDiags())) { - // Indicate that we want to instrument return control flow protection. - getModule().addModuleFlag(llvm::Module::Override, "cf-protection-return", - 1); - } - - if (CodeGenOpts.CFProtectionBranch && - Target.checkCFProtectionBranchSupported(getDiags())) { - // Indicate that we want to instrument branch control flow protection. - getModule().addModuleFlag(llvm::Module::Override, "cf-protection-branch", - 1); - } - - if (LangOpts.CUDAIsDevice && getTriple().isNVPTX()) { - // Indicate whether __nvvm_reflect should be configured to flush denormal - // floating point values to 0. (This corresponds to its "__CUDA_FTZ" - // property.) - getModule().addModuleFlag(llvm::Module::Override, "nvvm-reflect-ftz", - CodeGenOpts.FlushDenorm ? 1 : 0); - } - - // Emit OpenCL specific module metadata: OpenCL/SPIR version. - if (LangOpts.OpenCL) { - EmitOpenCLMetadata(); - // Emit SPIR version. - if (getTriple().getArch() == llvm::Triple::spir || - getTriple().getArch() == llvm::Triple::spir64) { - // SPIR v2.0 s2.12 - The SPIR version used by the module is stored in the - // opencl.spir.version named metadata. - llvm::Metadata *SPIRVerElts[] = { - llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - Int32Ty, LangOpts.OpenCLVersion / 100)), - llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - Int32Ty, (LangOpts.OpenCLVersion / 100 > 1) ? 0 : 2))}; - llvm::NamedMDNode *SPIRVerMD = - TheModule.getOrInsertNamedMetadata("opencl.spir.version"); - llvm::LLVMContext &Ctx = TheModule.getContext(); - SPIRVerMD->addOperand(llvm::MDNode::get(Ctx, SPIRVerElts)); - } - } - - if (uint32_t PLevel = Context.getLangOpts().PICLevel) { - assert(PLevel < 3 && "Invalid PIC Level"); - getModule().setPICLevel(static_cast<llvm::PICLevel::Level>(PLevel)); - if (Context.getLangOpts().PIE) - getModule().setPIELevel(static_cast<llvm::PIELevel::Level>(PLevel)); - } - - if (getCodeGenOpts().CodeModel.size() > 0) { - unsigned CM = llvm::StringSwitch<unsigned>(getCodeGenOpts().CodeModel) - .Case("tiny", llvm::CodeModel::Tiny) - .Case("small", llvm::CodeModel::Small) - .Case("kernel", llvm::CodeModel::Kernel) - .Case("medium", llvm::CodeModel::Medium) - .Case("large", llvm::CodeModel::Large) - .Default(~0u); - if (CM != ~0u) { - llvm::CodeModel::Model codeModel = static_cast<llvm::CodeModel::Model>(CM); - getModule().setCodeModel(codeModel); - } - } - - if (CodeGenOpts.NoPLT) - getModule().setRtLibUseGOT(); - - SimplifyPersonality(); - - if (getCodeGenOpts().EmitDeclMetadata) - EmitDeclMetadata(); - - if (getCodeGenOpts().EmitGcovArcs || getCodeGenOpts().EmitGcovNotes) - EmitCoverageFile(); - - if (DebugInfo) - DebugInfo->finalize(); - - if (getCodeGenOpts().EmitVersionIdentMetadata) - EmitVersionIdentMetadata(); - - if (!getCodeGenOpts().RecordCommandLine.empty()) - EmitCommandLineMetadata(); - - EmitTargetMetadata(); -} - -void CodeGenModule::EmitOpenCLMetadata() { - // SPIR v2.0 s2.13 - The OpenCL version used by the module is stored in the - // opencl.ocl.version named metadata node. - llvm::Metadata *OCLVerElts[] = { - llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - Int32Ty, LangOpts.OpenCLVersion / 100)), - llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - Int32Ty, (LangOpts.OpenCLVersion % 100) / 10))}; - llvm::NamedMDNode *OCLVerMD = - TheModule.getOrInsertNamedMetadata("opencl.ocl.version"); - llvm::LLVMContext &Ctx = TheModule.getContext(); - OCLVerMD->addOperand(llvm::MDNode::get(Ctx, OCLVerElts)); -} - -void CodeGenModule::UpdateCompletedType(const TagDecl *TD) { - // Make sure that this type is translated. - Types.UpdateCompletedType(TD); -} - -void CodeGenModule::RefreshTypeCacheForClass(const CXXRecordDecl *RD) { - // Make sure that this type is translated. - Types.RefreshTypeCacheForClass(RD); -} - -llvm::MDNode *CodeGenModule::getTBAATypeInfo(QualType QTy) { - if (!TBAA) - return nullptr; - return TBAA->getTypeInfo(QTy); -} - -TBAAAccessInfo CodeGenModule::getTBAAAccessInfo(QualType AccessType) { - if (!TBAA) - return TBAAAccessInfo(); - return TBAA->getAccessInfo(AccessType); -} - -TBAAAccessInfo -CodeGenModule::getTBAAVTablePtrAccessInfo(llvm::Type *VTablePtrType) { - if (!TBAA) - return TBAAAccessInfo(); - return TBAA->getVTablePtrAccessInfo(VTablePtrType); -} - -llvm::MDNode *CodeGenModule::getTBAAStructInfo(QualType QTy) { - if (!TBAA) - return nullptr; - return TBAA->getTBAAStructInfo(QTy); -} - -llvm::MDNode *CodeGenModule::getTBAABaseTypeInfo(QualType QTy) { - if (!TBAA) - return nullptr; - return TBAA->getBaseTypeInfo(QTy); -} - -llvm::MDNode *CodeGenModule::getTBAAAccessTagInfo(TBAAAccessInfo Info) { - if (!TBAA) - return nullptr; - return TBAA->getAccessTagInfo(Info); -} - -TBAAAccessInfo CodeGenModule::mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo, - TBAAAccessInfo TargetInfo) { - if (!TBAA) - return TBAAAccessInfo(); - return TBAA->mergeTBAAInfoForCast(SourceInfo, TargetInfo); -} - -TBAAAccessInfo -CodeGenModule::mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA, - TBAAAccessInfo InfoB) { - if (!TBAA) - return TBAAAccessInfo(); - return TBAA->mergeTBAAInfoForConditionalOperator(InfoA, InfoB); -} - -TBAAAccessInfo -CodeGenModule::mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo DestInfo, - TBAAAccessInfo SrcInfo) { - if (!TBAA) - return TBAAAccessInfo(); - return TBAA->mergeTBAAInfoForConditionalOperator(DestInfo, SrcInfo); -} - -void CodeGenModule::DecorateInstructionWithTBAA(llvm::Instruction *Inst, - TBAAAccessInfo TBAAInfo) { - if (llvm::MDNode *Tag = getTBAAAccessTagInfo(TBAAInfo)) - Inst->setMetadata(llvm::LLVMContext::MD_tbaa, Tag); -} - -void CodeGenModule::DecorateInstructionWithInvariantGroup( - llvm::Instruction *I, const CXXRecordDecl *RD) { - I->setMetadata(llvm::LLVMContext::MD_invariant_group, - llvm::MDNode::get(getLLVMContext(), {})); -} - -void CodeGenModule::Error(SourceLocation loc, StringRef message) { - unsigned diagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, "%0"); - getDiags().Report(Context.getFullLoc(loc), diagID) << message; -} - -/// ErrorUnsupported - Print out an error that codegen doesn't support the -/// specified stmt yet. -void CodeGenModule::ErrorUnsupported(const Stmt *S, const char *Type) { - unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, - "cannot compile this %0 yet"); - std::string Msg = Type; - getDiags().Report(Context.getFullLoc(S->getBeginLoc()), DiagID) - << Msg << S->getSourceRange(); -} - -/// ErrorUnsupported - Print out an error that codegen doesn't support the -/// specified decl yet. -void CodeGenModule::ErrorUnsupported(const Decl *D, const char *Type) { - unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, - "cannot compile this %0 yet"); - std::string Msg = Type; - getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID) << Msg; -} - -llvm::ConstantInt *CodeGenModule::getSize(CharUnits size) { - return llvm::ConstantInt::get(SizeTy, size.getQuantity()); -} - -void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV, - const NamedDecl *D) const { - if (GV->hasDLLImportStorageClass()) - return; - // Internal definitions always have default visibility. - if (GV->hasLocalLinkage()) { - GV->setVisibility(llvm::GlobalValue::DefaultVisibility); - return; - } - if (!D) - return; - // Set visibility for definitions. - LinkageInfo LV = D->getLinkageAndVisibility(); - if (LV.isVisibilityExplicit() || !GV->isDeclarationForLinker()) - GV->setVisibility(GetLLVMVisibility(LV.getVisibility())); -} - -static bool shouldAssumeDSOLocal(const CodeGenModule &CGM, - llvm::GlobalValue *GV) { - if (GV->hasLocalLinkage()) - return true; - - if (!GV->hasDefaultVisibility() && !GV->hasExternalWeakLinkage()) - return true; - - // DLLImport explicitly marks the GV as external. - if (GV->hasDLLImportStorageClass()) - return false; - - const llvm::Triple &TT = CGM.getTriple(); - if (TT.isWindowsGNUEnvironment()) { - // In MinGW, variables without DLLImport can still be automatically - // imported from a DLL by the linker; don't mark variables that - // potentially could come from another DLL as DSO local. - if (GV->isDeclarationForLinker() && isa<llvm::GlobalVariable>(GV) && - !GV->isThreadLocal()) - return false; - } - // Every other GV is local on COFF. - // Make an exception for windows OS in the triple: Some firmware builds use - // *-win32-macho triples. This (accidentally?) produced windows relocations - // without GOT tables in older clang versions; Keep this behaviour. - // FIXME: even thread local variables? - if (TT.isOSBinFormatCOFF() || (TT.isOSWindows() && TT.isOSBinFormatMachO())) - return true; - - // Only handle COFF and ELF for now. - if (!TT.isOSBinFormatELF()) - return false; - - // If this is not an executable, don't assume anything is local. - const auto &CGOpts = CGM.getCodeGenOpts(); - llvm::Reloc::Model RM = CGOpts.RelocationModel; - const auto &LOpts = CGM.getLangOpts(); - if (RM != llvm::Reloc::Static && !LOpts.PIE) - return false; - - // A definition cannot be preempted from an executable. - if (!GV->isDeclarationForLinker()) - return true; - - // Most PIC code sequences that assume that a symbol is local cannot produce a - // 0 if it turns out the symbol is undefined. While this is ABI and relocation - // depended, it seems worth it to handle it here. - if (RM == llvm::Reloc::PIC_ && GV->hasExternalWeakLinkage()) - return false; - - // PPC has no copy relocations and cannot use a plt entry as a symbol address. - llvm::Triple::ArchType Arch = TT.getArch(); - if (Arch == llvm::Triple::ppc || Arch == llvm::Triple::ppc64 || - Arch == llvm::Triple::ppc64le) - return false; - - // If we can use copy relocations we can assume it is local. - if (auto *Var = dyn_cast<llvm::GlobalVariable>(GV)) - if (!Var->isThreadLocal() && - (RM == llvm::Reloc::Static || CGOpts.PIECopyRelocations)) - return true; - - // If we can use a plt entry as the symbol address we can assume it - // is local. - // FIXME: This should work for PIE, but the gold linker doesn't support it. - if (isa<llvm::Function>(GV) && !CGOpts.NoPLT && RM == llvm::Reloc::Static) - return true; - - // Otherwise don't assue it is local. - return false; -} - -void CodeGenModule::setDSOLocal(llvm::GlobalValue *GV) const { - GV->setDSOLocal(shouldAssumeDSOLocal(*this, GV)); -} - -void CodeGenModule::setDLLImportDLLExport(llvm::GlobalValue *GV, - GlobalDecl GD) const { - const auto *D = dyn_cast<NamedDecl>(GD.getDecl()); - // C++ destructors have a few C++ ABI specific special cases. - if (const auto *Dtor = dyn_cast_or_null<CXXDestructorDecl>(D)) { - getCXXABI().setCXXDestructorDLLStorage(GV, Dtor, GD.getDtorType()); - return; - } - setDLLImportDLLExport(GV, D); -} - -void CodeGenModule::setDLLImportDLLExport(llvm::GlobalValue *GV, - const NamedDecl *D) const { - if (D && D->isExternallyVisible()) { - if (D->hasAttr<DLLImportAttr>()) - GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass); - else if (D->hasAttr<DLLExportAttr>() && !GV->isDeclarationForLinker()) - GV->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass); - } -} - -void CodeGenModule::setGVProperties(llvm::GlobalValue *GV, - GlobalDecl GD) const { - setDLLImportDLLExport(GV, GD); - setGlobalVisibilityAndLocal(GV, dyn_cast<NamedDecl>(GD.getDecl())); -} - -void CodeGenModule::setGVProperties(llvm::GlobalValue *GV, - const NamedDecl *D) const { - setDLLImportDLLExport(GV, D); - setGlobalVisibilityAndLocal(GV, D); -} - -void CodeGenModule::setGlobalVisibilityAndLocal(llvm::GlobalValue *GV, - const NamedDecl *D) const { - setGlobalVisibility(GV, D); - setDSOLocal(GV); -} - -static llvm::GlobalVariable::ThreadLocalMode GetLLVMTLSModel(StringRef S) { - return llvm::StringSwitch<llvm::GlobalVariable::ThreadLocalMode>(S) - .Case("global-dynamic", llvm::GlobalVariable::GeneralDynamicTLSModel) - .Case("local-dynamic", llvm::GlobalVariable::LocalDynamicTLSModel) - .Case("initial-exec", llvm::GlobalVariable::InitialExecTLSModel) - .Case("local-exec", llvm::GlobalVariable::LocalExecTLSModel); -} - -static llvm::GlobalVariable::ThreadLocalMode GetLLVMTLSModel( - CodeGenOptions::TLSModel M) { - switch (M) { - case CodeGenOptions::GeneralDynamicTLSModel: - return llvm::GlobalVariable::GeneralDynamicTLSModel; - case CodeGenOptions::LocalDynamicTLSModel: - return llvm::GlobalVariable::LocalDynamicTLSModel; - case CodeGenOptions::InitialExecTLSModel: - return llvm::GlobalVariable::InitialExecTLSModel; - case CodeGenOptions::LocalExecTLSModel: - return llvm::GlobalVariable::LocalExecTLSModel; - } - llvm_unreachable("Invalid TLS model!"); -} - -void CodeGenModule::setTLSMode(llvm::GlobalValue *GV, const VarDecl &D) const { - assert(D.getTLSKind() && "setting TLS mode on non-TLS var!"); - - llvm::GlobalValue::ThreadLocalMode TLM; - TLM = GetLLVMTLSModel(CodeGenOpts.getDefaultTLSModel()); - - // Override the TLS model if it is explicitly specified. - if (const TLSModelAttr *Attr = D.getAttr<TLSModelAttr>()) { - TLM = GetLLVMTLSModel(Attr->getModel()); - } - - GV->setThreadLocalMode(TLM); -} - -static std::string getCPUSpecificMangling(const CodeGenModule &CGM, - StringRef Name) { - const TargetInfo &Target = CGM.getTarget(); - return (Twine('.') + Twine(Target.CPUSpecificManglingCharacter(Name))).str(); -} - -static void AppendCPUSpecificCPUDispatchMangling(const CodeGenModule &CGM, - const CPUSpecificAttr *Attr, - unsigned CPUIndex, - raw_ostream &Out) { - // cpu_specific gets the current name, dispatch gets the resolver if IFunc is - // supported. - if (Attr) - Out << getCPUSpecificMangling(CGM, Attr->getCPUName(CPUIndex)->getName()); - else if (CGM.getTarget().supportsIFunc()) - Out << ".resolver"; -} - -static void AppendTargetMangling(const CodeGenModule &CGM, - const TargetAttr *Attr, raw_ostream &Out) { - if (Attr->isDefaultVersion()) - return; - - Out << '.'; - const TargetInfo &Target = CGM.getTarget(); - TargetAttr::ParsedTargetAttr Info = - Attr->parse([&Target](StringRef LHS, StringRef RHS) { - // Multiversioning doesn't allow "no-${feature}", so we can - // only have "+" prefixes here. - assert(LHS.startswith("+") && RHS.startswith("+") && - "Features should always have a prefix."); - return Target.multiVersionSortPriority(LHS.substr(1)) > - Target.multiVersionSortPriority(RHS.substr(1)); - }); - - bool IsFirst = true; - - if (!Info.Architecture.empty()) { - IsFirst = false; - Out << "arch_" << Info.Architecture; - } - - for (StringRef Feat : Info.Features) { - if (!IsFirst) - Out << '_'; - IsFirst = false; - Out << Feat.substr(1); - } -} - -static std::string getMangledNameImpl(const CodeGenModule &CGM, GlobalDecl GD, - const NamedDecl *ND, - bool OmitMultiVersionMangling = false) { - SmallString<256> Buffer; - llvm::raw_svector_ostream Out(Buffer); - MangleContext &MC = CGM.getCXXABI().getMangleContext(); - if (MC.shouldMangleDeclName(ND)) { - llvm::raw_svector_ostream Out(Buffer); - if (const auto *D = dyn_cast<CXXConstructorDecl>(ND)) - MC.mangleCXXCtor(D, GD.getCtorType(), Out); - else if (const auto *D = dyn_cast<CXXDestructorDecl>(ND)) - MC.mangleCXXDtor(D, GD.getDtorType(), Out); - else - MC.mangleName(ND, Out); - } else { - IdentifierInfo *II = ND->getIdentifier(); - assert(II && "Attempt to mangle unnamed decl."); - const auto *FD = dyn_cast<FunctionDecl>(ND); - - if (FD && - FD->getType()->castAs<FunctionType>()->getCallConv() == CC_X86RegCall) { - llvm::raw_svector_ostream Out(Buffer); - Out << "__regcall3__" << II->getName(); - } else { - Out << II->getName(); - } - } - - if (const auto *FD = dyn_cast<FunctionDecl>(ND)) - if (FD->isMultiVersion() && !OmitMultiVersionMangling) { - switch (FD->getMultiVersionKind()) { - case MultiVersionKind::CPUDispatch: - case MultiVersionKind::CPUSpecific: - AppendCPUSpecificCPUDispatchMangling(CGM, - FD->getAttr<CPUSpecificAttr>(), - GD.getMultiVersionIndex(), Out); - break; - case MultiVersionKind::Target: - AppendTargetMangling(CGM, FD->getAttr<TargetAttr>(), Out); - break; - case MultiVersionKind::None: - llvm_unreachable("None multiversion type isn't valid here"); - } - } - - return Out.str(); -} - -void CodeGenModule::UpdateMultiVersionNames(GlobalDecl GD, - const FunctionDecl *FD) { - if (!FD->isMultiVersion()) - return; - - // Get the name of what this would be without the 'target' attribute. This - // allows us to lookup the version that was emitted when this wasn't a - // multiversion function. - std::string NonTargetName = - getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true); - GlobalDecl OtherGD; - if (lookupRepresentativeDecl(NonTargetName, OtherGD)) { - assert(OtherGD.getCanonicalDecl() - .getDecl() - ->getAsFunction() - ->isMultiVersion() && - "Other GD should now be a multiversioned function"); - // OtherFD is the version of this function that was mangled BEFORE - // becoming a MultiVersion function. It potentially needs to be updated. - const FunctionDecl *OtherFD = OtherGD.getCanonicalDecl() - .getDecl() - ->getAsFunction() - ->getMostRecentDecl(); - std::string OtherName = getMangledNameImpl(*this, OtherGD, OtherFD); - // This is so that if the initial version was already the 'default' - // version, we don't try to update it. - if (OtherName != NonTargetName) { - // Remove instead of erase, since others may have stored the StringRef - // to this. - const auto ExistingRecord = Manglings.find(NonTargetName); - if (ExistingRecord != std::end(Manglings)) - Manglings.remove(&(*ExistingRecord)); - auto Result = Manglings.insert(std::make_pair(OtherName, OtherGD)); - MangledDeclNames[OtherGD.getCanonicalDecl()] = Result.first->first(); - if (llvm::GlobalValue *Entry = GetGlobalValue(NonTargetName)) - Entry->setName(OtherName); - } - } -} - -StringRef CodeGenModule::getMangledName(GlobalDecl GD) { - GlobalDecl CanonicalGD = GD.getCanonicalDecl(); - - // Some ABIs don't have constructor variants. Make sure that base and - // complete constructors get mangled the same. - if (const auto *CD = dyn_cast<CXXConstructorDecl>(CanonicalGD.getDecl())) { - if (!getTarget().getCXXABI().hasConstructorVariants()) { - CXXCtorType OrigCtorType = GD.getCtorType(); - assert(OrigCtorType == Ctor_Base || OrigCtorType == Ctor_Complete); - if (OrigCtorType == Ctor_Base) - CanonicalGD = GlobalDecl(CD, Ctor_Complete); - } - } - - auto FoundName = MangledDeclNames.find(CanonicalGD); - if (FoundName != MangledDeclNames.end()) - return FoundName->second; - - // Keep the first result in the case of a mangling collision. - const auto *ND = cast<NamedDecl>(GD.getDecl()); - auto Result = - Manglings.insert(std::make_pair(getMangledNameImpl(*this, GD, ND), GD)); - return MangledDeclNames[CanonicalGD] = Result.first->first(); -} - -StringRef CodeGenModule::getBlockMangledName(GlobalDecl GD, - const BlockDecl *BD) { - MangleContext &MangleCtx = getCXXABI().getMangleContext(); - const Decl *D = GD.getDecl(); - - SmallString<256> Buffer; - llvm::raw_svector_ostream Out(Buffer); - if (!D) - MangleCtx.mangleGlobalBlock(BD, - dyn_cast_or_null<VarDecl>(initializedGlobalDecl.getDecl()), Out); - else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D)) - MangleCtx.mangleCtorBlock(CD, GD.getCtorType(), BD, Out); - else if (const auto *DD = dyn_cast<CXXDestructorDecl>(D)) - MangleCtx.mangleDtorBlock(DD, GD.getDtorType(), BD, Out); - else - MangleCtx.mangleBlock(cast<DeclContext>(D), BD, Out); - - auto Result = Manglings.insert(std::make_pair(Out.str(), BD)); - return Result.first->first(); -} - -llvm::GlobalValue *CodeGenModule::GetGlobalValue(StringRef Name) { - return getModule().getNamedValue(Name); -} - -/// AddGlobalCtor - Add a function to the list that will be called before -/// main() runs. -void CodeGenModule::AddGlobalCtor(llvm::Function *Ctor, int Priority, - llvm::Constant *AssociatedData) { - // FIXME: Type coercion of void()* types. - GlobalCtors.push_back(Structor(Priority, Ctor, AssociatedData)); -} - -/// AddGlobalDtor - Add a function to the list that will be called -/// when the module is unloaded. -void CodeGenModule::AddGlobalDtor(llvm::Function *Dtor, int Priority) { - if (CodeGenOpts.RegisterGlobalDtorsWithAtExit) { - DtorsUsingAtExit[Priority].push_back(Dtor); - return; - } - - // FIXME: Type coercion of void()* types. - GlobalDtors.push_back(Structor(Priority, Dtor, nullptr)); -} - -void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) { - if (Fns.empty()) return; - - // Ctor function type is void()*. - llvm::FunctionType* CtorFTy = llvm::FunctionType::get(VoidTy, false); - llvm::Type *CtorPFTy = llvm::PointerType::get(CtorFTy, - TheModule.getDataLayout().getProgramAddressSpace()); - - // Get the type of a ctor entry, { i32, void ()*, i8* }. - llvm::StructType *CtorStructTy = llvm::StructType::get( - Int32Ty, CtorPFTy, VoidPtrTy); - - // Construct the constructor and destructor arrays. - ConstantInitBuilder builder(*this); - auto ctors = builder.beginArray(CtorStructTy); - for (const auto &I : Fns) { - auto ctor = ctors.beginStruct(CtorStructTy); - ctor.addInt(Int32Ty, I.Priority); - ctor.add(llvm::ConstantExpr::getBitCast(I.Initializer, CtorPFTy)); - if (I.AssociatedData) - ctor.add(llvm::ConstantExpr::getBitCast(I.AssociatedData, VoidPtrTy)); - else - ctor.addNullPointer(VoidPtrTy); - ctor.finishAndAddTo(ctors); - } - - auto list = - ctors.finishAndCreateGlobal(GlobalName, getPointerAlign(), - /*constant*/ false, - llvm::GlobalValue::AppendingLinkage); - - // The LTO linker doesn't seem to like it when we set an alignment - // on appending variables. Take it off as a workaround. - list->setAlignment(0); - - Fns.clear(); -} - -llvm::GlobalValue::LinkageTypes -CodeGenModule::getFunctionLinkage(GlobalDecl GD) { - const auto *D = cast<FunctionDecl>(GD.getDecl()); - - GVALinkage Linkage = getContext().GetGVALinkageForFunction(D); - - if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(D)) - return getCXXABI().getCXXDestructorLinkage(Linkage, Dtor, GD.getDtorType()); - - if (isa<CXXConstructorDecl>(D) && - cast<CXXConstructorDecl>(D)->isInheritingConstructor() && - Context.getTargetInfo().getCXXABI().isMicrosoft()) { - // Our approach to inheriting constructors is fundamentally different from - // that used by the MS ABI, so keep our inheriting constructor thunks - // internal rather than trying to pick an unambiguous mangling for them. - return llvm::GlobalValue::InternalLinkage; - } - - return getLLVMLinkageForDeclarator(D, Linkage, /*isConstantVariable=*/false); -} - -llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) { - llvm::MDString *MDS = dyn_cast<llvm::MDString>(MD); - if (!MDS) return nullptr; - - return llvm::ConstantInt::get(Int64Ty, llvm::MD5Hash(MDS->getString())); -} - -void CodeGenModule::SetLLVMFunctionAttributes(GlobalDecl GD, - const CGFunctionInfo &Info, - llvm::Function *F) { - unsigned CallingConv; - llvm::AttributeList PAL; - ConstructAttributeList(F->getName(), Info, GD, PAL, CallingConv, false); - F->setAttributes(PAL); - F->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv)); -} - -/// Determines whether the language options require us to model -/// unwind exceptions. We treat -fexceptions as mandating this -/// except under the fragile ObjC ABI with only ObjC exceptions -/// enabled. This means, for example, that C with -fexceptions -/// enables this. -static bool hasUnwindExceptions(const LangOptions &LangOpts) { - // If exceptions are completely disabled, obviously this is false. - if (!LangOpts.Exceptions) return false; - - // If C++ exceptions are enabled, this is true. - if (LangOpts.CXXExceptions) return true; - - // If ObjC exceptions are enabled, this depends on the ABI. - if (LangOpts.ObjCExceptions) { - return LangOpts.ObjCRuntime.hasUnwindExceptions(); - } - - return true; -} - -static bool requiresMemberFunctionPointerTypeMetadata(CodeGenModule &CGM, - const CXXMethodDecl *MD) { - // Check that the type metadata can ever actually be used by a call. - if (!CGM.getCodeGenOpts().LTOUnit || - !CGM.HasHiddenLTOVisibility(MD->getParent())) - return false; - - // Only functions whose address can be taken with a member function pointer - // need this sort of type metadata. - return !MD->isStatic() && !MD->isVirtual() && !isa<CXXConstructorDecl>(MD) && - !isa<CXXDestructorDecl>(MD); -} - -std::vector<const CXXRecordDecl *> -CodeGenModule::getMostBaseClasses(const CXXRecordDecl *RD) { - llvm::SetVector<const CXXRecordDecl *> MostBases; - - std::function<void (const CXXRecordDecl *)> CollectMostBases; - CollectMostBases = [&](const CXXRecordDecl *RD) { - if (RD->getNumBases() == 0) - MostBases.insert(RD); - for (const CXXBaseSpecifier &B : RD->bases()) - CollectMostBases(B.getType()->getAsCXXRecordDecl()); - }; - CollectMostBases(RD); - return MostBases.takeVector(); -} - -void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, - llvm::Function *F) { - llvm::AttrBuilder B; - - if (CodeGenOpts.UnwindTables) - B.addAttribute(llvm::Attribute::UWTable); - - if (!hasUnwindExceptions(LangOpts)) - B.addAttribute(llvm::Attribute::NoUnwind); - - if (!D || !D->hasAttr<NoStackProtectorAttr>()) { - if (LangOpts.getStackProtector() == LangOptions::SSPOn) - B.addAttribute(llvm::Attribute::StackProtect); - else if (LangOpts.getStackProtector() == LangOptions::SSPStrong) - B.addAttribute(llvm::Attribute::StackProtectStrong); - else if (LangOpts.getStackProtector() == LangOptions::SSPReq) - B.addAttribute(llvm::Attribute::StackProtectReq); - } - - if (!D) { - // If we don't have a declaration to control inlining, the function isn't - // explicitly marked as alwaysinline for semantic reasons, and inlining is - // disabled, mark the function as noinline. - if (!F->hasFnAttribute(llvm::Attribute::AlwaysInline) && - CodeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) - B.addAttribute(llvm::Attribute::NoInline); - - F->addAttributes(llvm::AttributeList::FunctionIndex, B); - return; - } - - // Track whether we need to add the optnone LLVM attribute, - // starting with the default for this optimization level. - bool ShouldAddOptNone = - !CodeGenOpts.DisableO0ImplyOptNone && CodeGenOpts.OptimizationLevel == 0; - // We can't add optnone in the following cases, it won't pass the verifier. - ShouldAddOptNone &= !D->hasAttr<MinSizeAttr>(); - ShouldAddOptNone &= !F->hasFnAttribute(llvm::Attribute::AlwaysInline); - ShouldAddOptNone &= !D->hasAttr<AlwaysInlineAttr>(); - - if (ShouldAddOptNone || D->hasAttr<OptimizeNoneAttr>()) { - B.addAttribute(llvm::Attribute::OptimizeNone); - - // OptimizeNone implies noinline; we should not be inlining such functions. - B.addAttribute(llvm::Attribute::NoInline); - assert(!F->hasFnAttribute(llvm::Attribute::AlwaysInline) && - "OptimizeNone and AlwaysInline on same function!"); - - // We still need to handle naked functions even though optnone subsumes - // much of their semantics. - if (D->hasAttr<NakedAttr>()) - B.addAttribute(llvm::Attribute::Naked); - - // OptimizeNone wins over OptimizeForSize and MinSize. - F->removeFnAttr(llvm::Attribute::OptimizeForSize); - F->removeFnAttr(llvm::Attribute::MinSize); - } else if (D->hasAttr<NakedAttr>()) { - // Naked implies noinline: we should not be inlining such functions. - B.addAttribute(llvm::Attribute::Naked); - B.addAttribute(llvm::Attribute::NoInline); - } else if (D->hasAttr<NoDuplicateAttr>()) { - B.addAttribute(llvm::Attribute::NoDuplicate); - } else if (D->hasAttr<NoInlineAttr>()) { - B.addAttribute(llvm::Attribute::NoInline); - } else if (D->hasAttr<AlwaysInlineAttr>() && - !F->hasFnAttribute(llvm::Attribute::NoInline)) { - // (noinline wins over always_inline, and we can't specify both in IR) - B.addAttribute(llvm::Attribute::AlwaysInline); - } else if (CodeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) { - // If we're not inlining, then force everything that isn't always_inline to - // carry an explicit noinline attribute. - if (!F->hasFnAttribute(llvm::Attribute::AlwaysInline)) - B.addAttribute(llvm::Attribute::NoInline); - } else { - // Otherwise, propagate the inline hint attribute and potentially use its - // absence to mark things as noinline. - if (auto *FD = dyn_cast<FunctionDecl>(D)) { - // Search function and template pattern redeclarations for inline. - auto CheckForInline = [](const FunctionDecl *FD) { - auto CheckRedeclForInline = [](const FunctionDecl *Redecl) { - return Redecl->isInlineSpecified(); - }; - if (any_of(FD->redecls(), CheckRedeclForInline)) - return true; - const FunctionDecl *Pattern = FD->getTemplateInstantiationPattern(); - if (!Pattern) - return false; - return any_of(Pattern->redecls(), CheckRedeclForInline); - }; - if (CheckForInline(FD)) { - B.addAttribute(llvm::Attribute::InlineHint); - } else if (CodeGenOpts.getInlining() == - CodeGenOptions::OnlyHintInlining && - !FD->isInlined() && - !F->hasFnAttribute(llvm::Attribute::AlwaysInline)) { - B.addAttribute(llvm::Attribute::NoInline); - } - } - } - - // Add other optimization related attributes if we are optimizing this - // function. - if (!D->hasAttr<OptimizeNoneAttr>()) { - if (D->hasAttr<ColdAttr>()) { - if (!ShouldAddOptNone) - B.addAttribute(llvm::Attribute::OptimizeForSize); - B.addAttribute(llvm::Attribute::Cold); - } - - if (D->hasAttr<MinSizeAttr>()) - B.addAttribute(llvm::Attribute::MinSize); - } - - F->addAttributes(llvm::AttributeList::FunctionIndex, B); - - unsigned alignment = D->getMaxAlignment() / Context.getCharWidth(); - if (alignment) - F->setAlignment(alignment); - - if (!D->hasAttr<AlignedAttr>()) - if (LangOpts.FunctionAlignment) - F->setAlignment(1 << LangOpts.FunctionAlignment); - - // Some C++ ABIs require 2-byte alignment for member functions, in order to - // reserve a bit for differentiating between virtual and non-virtual member - // functions. If the current target's C++ ABI requires this and this is a - // member function, set its alignment accordingly. - if (getTarget().getCXXABI().areMemberFunctionsAligned()) { - if (F->getAlignment() < 2 && isa<CXXMethodDecl>(D)) - F->setAlignment(2); - } - - // In the cross-dso CFI mode, we want !type attributes on definitions only. - if (CodeGenOpts.SanitizeCfiCrossDso) - if (auto *FD = dyn_cast<FunctionDecl>(D)) - CreateFunctionTypeMetadataForIcall(FD, F); - - // Emit type metadata on member functions for member function pointer checks. - // These are only ever necessary on definitions; we're guaranteed that the - // definition will be present in the LTO unit as a result of LTO visibility. - auto *MD = dyn_cast<CXXMethodDecl>(D); - if (MD && requiresMemberFunctionPointerTypeMetadata(*this, MD)) { - for (const CXXRecordDecl *Base : getMostBaseClasses(MD->getParent())) { - llvm::Metadata *Id = - CreateMetadataIdentifierForType(Context.getMemberPointerType( - MD->getType(), Context.getRecordType(Base).getTypePtr())); - F->addTypeMetadata(0, Id); - } - } -} - -void CodeGenModule::SetCommonAttributes(GlobalDecl GD, llvm::GlobalValue *GV) { - const Decl *D = GD.getDecl(); - if (dyn_cast_or_null<NamedDecl>(D)) - setGVProperties(GV, GD); - else - GV->setVisibility(llvm::GlobalValue::DefaultVisibility); - - if (D && D->hasAttr<UsedAttr>()) - addUsedGlobal(GV); - - if (CodeGenOpts.KeepStaticConsts && D && isa<VarDecl>(D)) { - const auto *VD = cast<VarDecl>(D); - if (VD->getType().isConstQualified() && - VD->getStorageDuration() == SD_Static) - addUsedGlobal(GV); - } -} - -bool CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD, - llvm::AttrBuilder &Attrs) { - // Add target-cpu and target-features attributes to functions. If - // we have a decl for the function and it has a target attribute then - // parse that and add it to the feature set. - StringRef TargetCPU = getTarget().getTargetOpts().CPU; - std::vector<std::string> Features; - const auto *FD = dyn_cast_or_null<FunctionDecl>(GD.getDecl()); - FD = FD ? FD->getMostRecentDecl() : FD; - const auto *TD = FD ? FD->getAttr<TargetAttr>() : nullptr; - const auto *SD = FD ? FD->getAttr<CPUSpecificAttr>() : nullptr; - bool AddedAttr = false; - if (TD || SD) { - llvm::StringMap<bool> FeatureMap; - getFunctionFeatureMap(FeatureMap, GD); - - // Produce the canonical string for this set of features. - for (const llvm::StringMap<bool>::value_type &Entry : FeatureMap) - Features.push_back((Entry.getValue() ? "+" : "-") + Entry.getKey().str()); - - // Now add the target-cpu and target-features to the function. - // While we populated the feature map above, we still need to - // get and parse the target attribute so we can get the cpu for - // the function. - if (TD) { - TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse(); - if (ParsedAttr.Architecture != "" && - getTarget().isValidCPUName(ParsedAttr.Architecture)) - TargetCPU = ParsedAttr.Architecture; - } - } else { - // Otherwise just add the existing target cpu and target features to the - // function. - Features = getTarget().getTargetOpts().Features; - } - - if (TargetCPU != "") { - Attrs.addAttribute("target-cpu", TargetCPU); - AddedAttr = true; - } - if (!Features.empty()) { - llvm::sort(Features); - Attrs.addAttribute("target-features", llvm::join(Features, ",")); - AddedAttr = true; - } - - return AddedAttr; -} - -void CodeGenModule::setNonAliasAttributes(GlobalDecl GD, - llvm::GlobalObject *GO) { - const Decl *D = GD.getDecl(); - SetCommonAttributes(GD, GO); - - if (D) { - if (auto *GV = dyn_cast<llvm::GlobalVariable>(GO)) { - if (auto *SA = D->getAttr<PragmaClangBSSSectionAttr>()) - GV->addAttribute("bss-section", SA->getName()); - if (auto *SA = D->getAttr<PragmaClangDataSectionAttr>()) - GV->addAttribute("data-section", SA->getName()); - if (auto *SA = D->getAttr<PragmaClangRodataSectionAttr>()) - GV->addAttribute("rodata-section", SA->getName()); - } - - if (auto *F = dyn_cast<llvm::Function>(GO)) { - if (auto *SA = D->getAttr<PragmaClangTextSectionAttr>()) - if (!D->getAttr<SectionAttr>()) - F->addFnAttr("implicit-section-name", SA->getName()); - - llvm::AttrBuilder Attrs; - if (GetCPUAndFeaturesAttributes(GD, Attrs)) { - // We know that GetCPUAndFeaturesAttributes will always have the - // newest set, since it has the newest possible FunctionDecl, so the - // new ones should replace the old. - F->removeFnAttr("target-cpu"); - F->removeFnAttr("target-features"); - F->addAttributes(llvm::AttributeList::FunctionIndex, Attrs); - } - } - - if (const auto *CSA = D->getAttr<CodeSegAttr>()) - GO->setSection(CSA->getName()); - else if (const auto *SA = D->getAttr<SectionAttr>()) - GO->setSection(SA->getName()); - } - - getTargetCodeGenInfo().setTargetAttributes(D, GO, *this); -} - -void CodeGenModule::SetInternalFunctionAttributes(GlobalDecl GD, - llvm::Function *F, - const CGFunctionInfo &FI) { - const Decl *D = GD.getDecl(); - SetLLVMFunctionAttributes(GD, FI, F); - SetLLVMFunctionAttributesForDefinition(D, F); - - F->setLinkage(llvm::Function::InternalLinkage); - - setNonAliasAttributes(GD, F); -} - -static void setLinkageForGV(llvm::GlobalValue *GV, const NamedDecl *ND) { - // Set linkage and visibility in case we never see a definition. - LinkageInfo LV = ND->getLinkageAndVisibility(); - // Don't set internal linkage on declarations. - // "extern_weak" is overloaded in LLVM; we probably should have - // separate linkage types for this. - if (isExternallyVisible(LV.getLinkage()) && - (ND->hasAttr<WeakAttr>() || ND->isWeakImported())) - GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); -} - -void CodeGenModule::CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD, - llvm::Function *F) { - // Only if we are checking indirect calls. - if (!LangOpts.Sanitize.has(SanitizerKind::CFIICall)) - return; - - // Non-static class methods are handled via vtable or member function pointer - // checks elsewhere. - if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) - return; - - // Additionally, if building with cross-DSO support... - if (CodeGenOpts.SanitizeCfiCrossDso) { - // Skip available_externally functions. They won't be codegen'ed in the - // current module anyway. - if (getContext().GetGVALinkageForFunction(FD) == GVA_AvailableExternally) - return; - } - - llvm::Metadata *MD = CreateMetadataIdentifierForType(FD->getType()); - F->addTypeMetadata(0, MD); - F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType())); - - // Emit a hash-based bit set entry for cross-DSO calls. - if (CodeGenOpts.SanitizeCfiCrossDso) - if (auto CrossDsoTypeId = CreateCrossDsoCfiTypeId(MD)) - F->addTypeMetadata(0, llvm::ConstantAsMetadata::get(CrossDsoTypeId)); -} - -void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F, - bool IsIncompleteFunction, - bool IsThunk) { - - if (llvm::Intrinsic::ID IID = F->getIntrinsicID()) { - // If this is an intrinsic function, set the function's attributes - // to the intrinsic's attributes. - F->setAttributes(llvm::Intrinsic::getAttributes(getLLVMContext(), IID)); - return; - } - - const auto *FD = cast<FunctionDecl>(GD.getDecl()); - - if (!IsIncompleteFunction) { - SetLLVMFunctionAttributes(GD, getTypes().arrangeGlobalDeclaration(GD), F); - // Setup target-specific attributes. - if (F->isDeclaration()) - getTargetCodeGenInfo().setTargetAttributes(FD, F, *this); - } - - // Add the Returned attribute for "this", except for iOS 5 and earlier - // where substantial code, including the libstdc++ dylib, was compiled with - // GCC and does not actually return "this". - if (!IsThunk && getCXXABI().HasThisReturn(GD) && - !(getTriple().isiOS() && getTriple().isOSVersionLT(6))) { - assert(!F->arg_empty() && - F->arg_begin()->getType() - ->canLosslesslyBitCastTo(F->getReturnType()) && - "unexpected this return"); - F->addAttribute(1, llvm::Attribute::Returned); - } - - // Only a few attributes are set on declarations; these may later be - // overridden by a definition. - - setLinkageForGV(F, FD); - setGVProperties(F, FD); - - if (const auto *CSA = FD->getAttr<CodeSegAttr>()) - F->setSection(CSA->getName()); - else if (const auto *SA = FD->getAttr<SectionAttr>()) - F->setSection(SA->getName()); - - if (FD->isReplaceableGlobalAllocationFunction()) { - // A replaceable global allocation function does not act like a builtin by - // default, only if it is invoked by a new-expression or delete-expression. - F->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoBuiltin); - - // A sane operator new returns a non-aliasing pointer. - // FIXME: Also add NonNull attribute to the return value - // for the non-nothrow forms? - auto Kind = FD->getDeclName().getCXXOverloadedOperator(); - if (getCodeGenOpts().AssumeSaneOperatorNew && - (Kind == OO_New || Kind == OO_Array_New)) - F->addAttribute(llvm::AttributeList::ReturnIndex, - llvm::Attribute::NoAlias); - } - - if (isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD)) - F->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - else if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) - if (MD->isVirtual()) - F->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - - // Don't emit entries for function declarations in the cross-DSO mode. This - // is handled with better precision by the receiving DSO. - if (!CodeGenOpts.SanitizeCfiCrossDso) - CreateFunctionTypeMetadataForIcall(FD, F); - - if (getLangOpts().OpenMP && FD->hasAttr<OMPDeclareSimdDeclAttr>()) - getOpenMPRuntime().emitDeclareSimdFunction(FD, F); -} - -void CodeGenModule::addUsedGlobal(llvm::GlobalValue *GV) { - assert(!GV->isDeclaration() && - "Only globals with definition can force usage."); - LLVMUsed.emplace_back(GV); -} - -void CodeGenModule::addCompilerUsedGlobal(llvm::GlobalValue *GV) { - assert(!GV->isDeclaration() && - "Only globals with definition can force usage."); - LLVMCompilerUsed.emplace_back(GV); -} - -static void emitUsed(CodeGenModule &CGM, StringRef Name, - std::vector<llvm::WeakTrackingVH> &List) { - // Don't create llvm.used if there is no need. - if (List.empty()) - return; - - // Convert List to what ConstantArray needs. - SmallVector<llvm::Constant*, 8> UsedArray; - UsedArray.resize(List.size()); - for (unsigned i = 0, e = List.size(); i != e; ++i) { - UsedArray[i] = - llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast( - cast<llvm::Constant>(&*List[i]), CGM.Int8PtrTy); - } - - if (UsedArray.empty()) - return; - llvm::ArrayType *ATy = llvm::ArrayType::get(CGM.Int8PtrTy, UsedArray.size()); - - auto *GV = new llvm::GlobalVariable( - CGM.getModule(), ATy, false, llvm::GlobalValue::AppendingLinkage, - llvm::ConstantArray::get(ATy, UsedArray), Name); - - GV->setSection("llvm.metadata"); -} - -void CodeGenModule::emitLLVMUsed() { - emitUsed(*this, "llvm.used", LLVMUsed); - emitUsed(*this, "llvm.compiler.used", LLVMCompilerUsed); -} - -void CodeGenModule::AppendLinkerOptions(StringRef Opts) { - auto *MDOpts = llvm::MDString::get(getLLVMContext(), Opts); - LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts)); -} - -void CodeGenModule::AddDetectMismatch(StringRef Name, StringRef Value) { - llvm::SmallString<32> Opt; - getTargetCodeGenInfo().getDetectMismatchOption(Name, Value, Opt); - auto *MDOpts = llvm::MDString::get(getLLVMContext(), Opt); - LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts)); -} - -void CodeGenModule::AddELFLibDirective(StringRef Lib) { - auto &C = getLLVMContext(); - LinkerOptionsMetadata.push_back(llvm::MDNode::get( - C, {llvm::MDString::get(C, "lib"), llvm::MDString::get(C, Lib)})); -} - -void CodeGenModule::AddDependentLib(StringRef Lib) { - llvm::SmallString<24> Opt; - getTargetCodeGenInfo().getDependentLibraryOption(Lib, Opt); - auto *MDOpts = llvm::MDString::get(getLLVMContext(), Opt); - LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts)); -} - -/// Add link options implied by the given module, including modules -/// it depends on, using a postorder walk. -static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod, - SmallVectorImpl<llvm::MDNode *> &Metadata, - llvm::SmallPtrSet<Module *, 16> &Visited) { - // Import this module's parent. - if (Mod->Parent && Visited.insert(Mod->Parent).second) { - addLinkOptionsPostorder(CGM, Mod->Parent, Metadata, Visited); - } - - // Import this module's dependencies. - for (unsigned I = Mod->Imports.size(); I > 0; --I) { - if (Visited.insert(Mod->Imports[I - 1]).second) - addLinkOptionsPostorder(CGM, Mod->Imports[I-1], Metadata, Visited); - } - - // Add linker options to link against the libraries/frameworks - // described by this module. - llvm::LLVMContext &Context = CGM.getLLVMContext(); - bool IsELF = CGM.getTarget().getTriple().isOSBinFormatELF(); - bool IsPS4 = CGM.getTarget().getTriple().isPS4(); - - // For modules that use export_as for linking, use that module - // name instead. - if (Mod->UseExportAsModuleLinkName) - return; - - for (unsigned I = Mod->LinkLibraries.size(); I > 0; --I) { - // Link against a framework. Frameworks are currently Darwin only, so we - // don't to ask TargetCodeGenInfo for the spelling of the linker option. - if (Mod->LinkLibraries[I-1].IsFramework) { - llvm::Metadata *Args[2] = { - llvm::MDString::get(Context, "-framework"), - llvm::MDString::get(Context, Mod->LinkLibraries[I - 1].Library)}; - - Metadata.push_back(llvm::MDNode::get(Context, Args)); - continue; - } - - // Link against a library. - if (IsELF && !IsPS4) { - llvm::Metadata *Args[2] = { - llvm::MDString::get(Context, "lib"), - llvm::MDString::get(Context, Mod->LinkLibraries[I - 1].Library), - }; - Metadata.push_back(llvm::MDNode::get(Context, Args)); - } else { - llvm::SmallString<24> Opt; - CGM.getTargetCodeGenInfo().getDependentLibraryOption( - Mod->LinkLibraries[I - 1].Library, Opt); - auto *OptString = llvm::MDString::get(Context, Opt); - Metadata.push_back(llvm::MDNode::get(Context, OptString)); - } - } -} - -void CodeGenModule::EmitModuleLinkOptions() { - // Collect the set of all of the modules we want to visit to emit link - // options, which is essentially the imported modules and all of their - // non-explicit child modules. - llvm::SetVector<clang::Module *> LinkModules; - llvm::SmallPtrSet<clang::Module *, 16> Visited; - SmallVector<clang::Module *, 16> Stack; - - // Seed the stack with imported modules. - for (Module *M : ImportedModules) { - // Do not add any link flags when an implementation TU of a module imports - // a header of that same module. - if (M->getTopLevelModuleName() == getLangOpts().CurrentModule && - !getLangOpts().isCompilingModule()) - continue; - if (Visited.insert(M).second) - Stack.push_back(M); - } - - // Find all of the modules to import, making a little effort to prune - // non-leaf modules. - while (!Stack.empty()) { - clang::Module *Mod = Stack.pop_back_val(); - - bool AnyChildren = false; - - // Visit the submodules of this module. - for (const auto &SM : Mod->submodules()) { - // Skip explicit children; they need to be explicitly imported to be - // linked against. - if (SM->IsExplicit) - continue; - - if (Visited.insert(SM).second) { - Stack.push_back(SM); - AnyChildren = true; - } - } - - // We didn't find any children, so add this module to the list of - // modules to link against. - if (!AnyChildren) { - LinkModules.insert(Mod); - } - } - - // Add link options for all of the imported modules in reverse topological - // order. We don't do anything to try to order import link flags with respect - // to linker options inserted by things like #pragma comment(). - SmallVector<llvm::MDNode *, 16> MetadataArgs; - Visited.clear(); - for (Module *M : LinkModules) - if (Visited.insert(M).second) - addLinkOptionsPostorder(*this, M, MetadataArgs, Visited); - std::reverse(MetadataArgs.begin(), MetadataArgs.end()); - LinkerOptionsMetadata.append(MetadataArgs.begin(), MetadataArgs.end()); - - // Add the linker options metadata flag. - auto *NMD = getModule().getOrInsertNamedMetadata("llvm.linker.options"); - for (auto *MD : LinkerOptionsMetadata) - NMD->addOperand(MD); -} - -void CodeGenModule::EmitDeferred() { - // Emit deferred declare target declarations. - if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd) - getOpenMPRuntime().emitDeferredTargetDecls(); - - // Emit code for any potentially referenced deferred decls. Since a - // previously unused static decl may become used during the generation of code - // for a static function, iterate until no changes are made. - - if (!DeferredVTables.empty()) { - EmitDeferredVTables(); - - // Emitting a vtable doesn't directly cause more vtables to - // become deferred, although it can cause functions to be - // emitted that then need those vtables. - assert(DeferredVTables.empty()); - } - - // Stop if we're out of both deferred vtables and deferred declarations. - if (DeferredDeclsToEmit.empty()) - return; - - // Grab the list of decls to emit. If EmitGlobalDefinition schedules more - // work, it will not interfere with this. - std::vector<GlobalDecl> CurDeclsToEmit; - CurDeclsToEmit.swap(DeferredDeclsToEmit); - - for (GlobalDecl &D : CurDeclsToEmit) { - // We should call GetAddrOfGlobal with IsForDefinition set to true in order - // to get GlobalValue with exactly the type we need, not something that - // might had been created for another decl with the same mangled name but - // different type. - llvm::GlobalValue *GV = dyn_cast<llvm::GlobalValue>( - GetAddrOfGlobal(D, ForDefinition)); - - // In case of different address spaces, we may still get a cast, even with - // IsForDefinition equal to true. Query mangled names table to get - // GlobalValue. - if (!GV) - GV = GetGlobalValue(getMangledName(D)); - - // Make sure GetGlobalValue returned non-null. - assert(GV); - - // Check to see if we've already emitted this. This is necessary - // for a couple of reasons: first, decls can end up in the - // deferred-decls queue multiple times, and second, decls can end - // up with definitions in unusual ways (e.g. by an extern inline - // function acquiring a strong function redefinition). Just - // ignore these cases. - if (!GV->isDeclaration()) - continue; - - // Otherwise, emit the definition and move on to the next one. - EmitGlobalDefinition(D, GV); - - // If we found out that we need to emit more decls, do that recursively. - // This has the advantage that the decls are emitted in a DFS and related - // ones are close together, which is convenient for testing. - if (!DeferredVTables.empty() || !DeferredDeclsToEmit.empty()) { - EmitDeferred(); - assert(DeferredVTables.empty() && DeferredDeclsToEmit.empty()); - } - } -} - -void CodeGenModule::EmitVTablesOpportunistically() { - // Try to emit external vtables as available_externally if they have emitted - // all inlined virtual functions. It runs after EmitDeferred() and therefore - // is not allowed to create new references to things that need to be emitted - // lazily. Note that it also uses fact that we eagerly emitting RTTI. - - assert((OpportunisticVTables.empty() || shouldOpportunisticallyEmitVTables()) - && "Only emit opportunistic vtables with optimizations"); - - for (const CXXRecordDecl *RD : OpportunisticVTables) { - assert(getVTables().isVTableExternal(RD) && - "This queue should only contain external vtables"); - if (getCXXABI().canSpeculativelyEmitVTable(RD)) - VTables.GenerateClassData(RD); - } - OpportunisticVTables.clear(); -} - -void CodeGenModule::EmitGlobalAnnotations() { - if (Annotations.empty()) - return; - - // Create a new global variable for the ConstantStruct in the Module. - llvm::Constant *Array = llvm::ConstantArray::get(llvm::ArrayType::get( - Annotations[0]->getType(), Annotations.size()), Annotations); - auto *gv = new llvm::GlobalVariable(getModule(), Array->getType(), false, - llvm::GlobalValue::AppendingLinkage, - Array, "llvm.global.annotations"); - gv->setSection(AnnotationSection); -} - -llvm::Constant *CodeGenModule::EmitAnnotationString(StringRef Str) { - llvm::Constant *&AStr = AnnotationStrings[Str]; - if (AStr) - return AStr; - - // Not found yet, create a new global. - llvm::Constant *s = llvm::ConstantDataArray::getString(getLLVMContext(), Str); - auto *gv = - new llvm::GlobalVariable(getModule(), s->getType(), true, - llvm::GlobalValue::PrivateLinkage, s, ".str"); - gv->setSection(AnnotationSection); - gv->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - AStr = gv; - return gv; -} - -llvm::Constant *CodeGenModule::EmitAnnotationUnit(SourceLocation Loc) { - SourceManager &SM = getContext().getSourceManager(); - PresumedLoc PLoc = SM.getPresumedLoc(Loc); - if (PLoc.isValid()) - return EmitAnnotationString(PLoc.getFilename()); - return EmitAnnotationString(SM.getBufferName(Loc)); -} - -llvm::Constant *CodeGenModule::EmitAnnotationLineNo(SourceLocation L) { - SourceManager &SM = getContext().getSourceManager(); - PresumedLoc PLoc = SM.getPresumedLoc(L); - unsigned LineNo = PLoc.isValid() ? PLoc.getLine() : - SM.getExpansionLineNumber(L); - return llvm::ConstantInt::get(Int32Ty, LineNo); -} - -llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV, - const AnnotateAttr *AA, - SourceLocation L) { - // Get the globals for file name, annotation, and the line number. - llvm::Constant *AnnoGV = EmitAnnotationString(AA->getAnnotation()), - *UnitGV = EmitAnnotationUnit(L), - *LineNoCst = EmitAnnotationLineNo(L); - - // Create the ConstantStruct for the global annotation. - llvm::Constant *Fields[4] = { - llvm::ConstantExpr::getBitCast(GV, Int8PtrTy), - llvm::ConstantExpr::getBitCast(AnnoGV, Int8PtrTy), - llvm::ConstantExpr::getBitCast(UnitGV, Int8PtrTy), - LineNoCst - }; - return llvm::ConstantStruct::getAnon(Fields); -} - -void CodeGenModule::AddGlobalAnnotations(const ValueDecl *D, - llvm::GlobalValue *GV) { - assert(D->hasAttr<AnnotateAttr>() && "no annotate attribute"); - // Get the struct elements for these annotations. - for (const auto *I : D->specific_attrs<AnnotateAttr>()) - Annotations.push_back(EmitAnnotateAttr(GV, I, D->getLocation())); -} - -bool CodeGenModule::isInSanitizerBlacklist(SanitizerMask Kind, - llvm::Function *Fn, - SourceLocation Loc) const { - const auto &SanitizerBL = getContext().getSanitizerBlacklist(); - // Blacklist by function name. - if (SanitizerBL.isBlacklistedFunction(Kind, Fn->getName())) - return true; - // Blacklist by location. - if (Loc.isValid()) - return SanitizerBL.isBlacklistedLocation(Kind, Loc); - // If location is unknown, this may be a compiler-generated function. Assume - // it's located in the main file. - auto &SM = Context.getSourceManager(); - if (const auto *MainFile = SM.getFileEntryForID(SM.getMainFileID())) { - return SanitizerBL.isBlacklistedFile(Kind, MainFile->getName()); - } - return false; -} - -bool CodeGenModule::isInSanitizerBlacklist(llvm::GlobalVariable *GV, - SourceLocation Loc, QualType Ty, - StringRef Category) const { - // For now globals can be blacklisted only in ASan and KASan. - const SanitizerMask EnabledAsanMask = LangOpts.Sanitize.Mask & - (SanitizerKind::Address | SanitizerKind::KernelAddress | - SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress); - if (!EnabledAsanMask) - return false; - const auto &SanitizerBL = getContext().getSanitizerBlacklist(); - if (SanitizerBL.isBlacklistedGlobal(EnabledAsanMask, GV->getName(), Category)) - return true; - if (SanitizerBL.isBlacklistedLocation(EnabledAsanMask, Loc, Category)) - return true; - // Check global type. - if (!Ty.isNull()) { - // Drill down the array types: if global variable of a fixed type is - // blacklisted, we also don't instrument arrays of them. - while (auto AT = dyn_cast<ArrayType>(Ty.getTypePtr())) - Ty = AT->getElementType(); - Ty = Ty.getCanonicalType().getUnqualifiedType(); - // We allow to blacklist only record types (classes, structs etc.) - if (Ty->isRecordType()) { - std::string TypeStr = Ty.getAsString(getContext().getPrintingPolicy()); - if (SanitizerBL.isBlacklistedType(EnabledAsanMask, TypeStr, Category)) - return true; - } - } - return false; -} - -bool CodeGenModule::imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc, - StringRef Category) const { - const auto &XRayFilter = getContext().getXRayFilter(); - using ImbueAttr = XRayFunctionFilter::ImbueAttribute; - auto Attr = ImbueAttr::NONE; - if (Loc.isValid()) - Attr = XRayFilter.shouldImbueLocation(Loc, Category); - if (Attr == ImbueAttr::NONE) - Attr = XRayFilter.shouldImbueFunction(Fn->getName()); - switch (Attr) { - case ImbueAttr::NONE: - return false; - case ImbueAttr::ALWAYS: - Fn->addFnAttr("function-instrument", "xray-always"); - break; - case ImbueAttr::ALWAYS_ARG1: - Fn->addFnAttr("function-instrument", "xray-always"); - Fn->addFnAttr("xray-log-args", "1"); - break; - case ImbueAttr::NEVER: - Fn->addFnAttr("function-instrument", "xray-never"); - break; - } - return true; -} - -bool CodeGenModule::MustBeEmitted(const ValueDecl *Global) { - // Never defer when EmitAllDecls is specified. - if (LangOpts.EmitAllDecls) - return true; - - if (CodeGenOpts.KeepStaticConsts) { - const auto *VD = dyn_cast<VarDecl>(Global); - if (VD && VD->getType().isConstQualified() && - VD->getStorageDuration() == SD_Static) - return true; - } - - return getContext().DeclMustBeEmitted(Global); -} - -bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) { - if (const auto *FD = dyn_cast<FunctionDecl>(Global)) - if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) - // Implicit template instantiations may change linkage if they are later - // explicitly instantiated, so they should not be emitted eagerly. - return false; - if (const auto *VD = dyn_cast<VarDecl>(Global)) - if (Context.getInlineVariableDefinitionKind(VD) == - ASTContext::InlineVariableDefinitionKind::WeakUnknown) - // A definition of an inline constexpr static data member may change - // linkage later if it's redeclared outside the class. - return false; - // If OpenMP is enabled and threadprivates must be generated like TLS, delay - // codegen for global variables, because they may be marked as threadprivate. - if (LangOpts.OpenMP && LangOpts.OpenMPUseTLS && - getContext().getTargetInfo().isTLSSupported() && isa<VarDecl>(Global) && - !isTypeConstant(Global->getType(), false) && - !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(Global)) - return false; - - return true; -} - -ConstantAddress CodeGenModule::GetAddrOfUuidDescriptor( - const CXXUuidofExpr* E) { - // Sema has verified that IIDSource has a __declspec(uuid()), and that its - // well-formed. - StringRef Uuid = E->getUuidStr(); - std::string Name = "_GUID_" + Uuid.lower(); - std::replace(Name.begin(), Name.end(), '-', '_'); - - // The UUID descriptor should be pointer aligned. - CharUnits Alignment = CharUnits::fromQuantity(PointerAlignInBytes); - - // Look for an existing global. - if (llvm::GlobalVariable *GV = getModule().getNamedGlobal(Name)) - return ConstantAddress(GV, Alignment); - - llvm::Constant *Init = EmitUuidofInitializer(Uuid); - assert(Init && "failed to initialize as constant"); - - auto *GV = new llvm::GlobalVariable( - getModule(), Init->getType(), - /*isConstant=*/true, llvm::GlobalValue::LinkOnceODRLinkage, Init, Name); - if (supportsCOMDAT()) - GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); - setDSOLocal(GV); - return ConstantAddress(GV, Alignment); -} - -ConstantAddress CodeGenModule::GetWeakRefReference(const ValueDecl *VD) { - const AliasAttr *AA = VD->getAttr<AliasAttr>(); - assert(AA && "No alias?"); - - CharUnits Alignment = getContext().getDeclAlign(VD); - llvm::Type *DeclTy = getTypes().ConvertTypeForMem(VD->getType()); - - // See if there is already something with the target's name in the module. - llvm::GlobalValue *Entry = GetGlobalValue(AA->getAliasee()); - if (Entry) { - unsigned AS = getContext().getTargetAddressSpace(VD->getType()); - auto Ptr = llvm::ConstantExpr::getBitCast(Entry, DeclTy->getPointerTo(AS)); - return ConstantAddress(Ptr, Alignment); - } - - llvm::Constant *Aliasee; - if (isa<llvm::FunctionType>(DeclTy)) - Aliasee = GetOrCreateLLVMFunction(AA->getAliasee(), DeclTy, - GlobalDecl(cast<FunctionDecl>(VD)), - /*ForVTable=*/false); - else - Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(), - llvm::PointerType::getUnqual(DeclTy), - nullptr); - - auto *F = cast<llvm::GlobalValue>(Aliasee); - F->setLinkage(llvm::Function::ExternalWeakLinkage); - WeakRefReferences.insert(F); - - return ConstantAddress(Aliasee, Alignment); -} - -void CodeGenModule::EmitGlobal(GlobalDecl GD) { - const auto *Global = cast<ValueDecl>(GD.getDecl()); - - // Weak references don't produce any output by themselves. - if (Global->hasAttr<WeakRefAttr>()) - return; - - // If this is an alias definition (which otherwise looks like a declaration) - // emit it now. - if (Global->hasAttr<AliasAttr>()) - return EmitAliasDefinition(GD); - - // IFunc like an alias whose value is resolved at runtime by calling resolver. - if (Global->hasAttr<IFuncAttr>()) - return emitIFuncDefinition(GD); - - // If this is a cpu_dispatch multiversion function, emit the resolver. - if (Global->hasAttr<CPUDispatchAttr>()) - return emitCPUDispatchDefinition(GD); - - // If this is CUDA, be selective about which declarations we emit. - if (LangOpts.CUDA) { - if (LangOpts.CUDAIsDevice) { - if (!Global->hasAttr<CUDADeviceAttr>() && - !Global->hasAttr<CUDAGlobalAttr>() && - !Global->hasAttr<CUDAConstantAttr>() && - !Global->hasAttr<CUDASharedAttr>()) - return; - } else { - // We need to emit host-side 'shadows' for all global - // device-side variables because the CUDA runtime needs their - // size and host-side address in order to provide access to - // their device-side incarnations. - - // So device-only functions are the only things we skip. - if (isa<FunctionDecl>(Global) && !Global->hasAttr<CUDAHostAttr>() && - Global->hasAttr<CUDADeviceAttr>()) - return; - - assert((isa<FunctionDecl>(Global) || isa<VarDecl>(Global)) && - "Expected Variable or Function"); - } - } - - if (LangOpts.OpenMP) { - // If this is OpenMP device, check if it is legal to emit this global - // normally. - if (OpenMPRuntime && OpenMPRuntime->emitTargetGlobal(GD)) - return; - if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(Global)) { - if (MustBeEmitted(Global)) - EmitOMPDeclareReduction(DRD); - return; - } - } - - // Ignore declarations, they will be emitted on their first use. - if (const auto *FD = dyn_cast<FunctionDecl>(Global)) { - // Forward declarations are emitted lazily on first use. - if (!FD->doesThisDeclarationHaveABody()) { - if (!FD->doesDeclarationForceExternallyVisibleDefinition()) - return; - - StringRef MangledName = getMangledName(GD); - - // Compute the function info and LLVM type. - const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD); - llvm::Type *Ty = getTypes().GetFunctionType(FI); - - GetOrCreateLLVMFunction(MangledName, Ty, GD, /*ForVTable=*/false, - /*DontDefer=*/false); - return; - } - } else { - const auto *VD = cast<VarDecl>(Global); - assert(VD->isFileVarDecl() && "Cannot emit local var decl as global."); - if (VD->isThisDeclarationADefinition() != VarDecl::Definition && - !Context.isMSStaticDataMemberInlineDefinition(VD)) { - if (LangOpts.OpenMP) { - // Emit declaration of the must-be-emitted declare target variable. - if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { - if (*Res == OMPDeclareTargetDeclAttr::MT_To) { - (void)GetAddrOfGlobalVar(VD); - } else { - assert(*Res == OMPDeclareTargetDeclAttr::MT_Link && - "link claue expected."); - (void)getOpenMPRuntime().getAddrOfDeclareTargetLink(VD); - } - return; - } - } - // If this declaration may have caused an inline variable definition to - // change linkage, make sure that it's emitted. - if (Context.getInlineVariableDefinitionKind(VD) == - ASTContext::InlineVariableDefinitionKind::Strong) - GetAddrOfGlobalVar(VD); - return; - } - } - - // Defer code generation to first use when possible, e.g. if this is an inline - // function. If the global must always be emitted, do it eagerly if possible - // to benefit from cache locality. - if (MustBeEmitted(Global) && MayBeEmittedEagerly(Global)) { - // Emit the definition if it can't be deferred. - EmitGlobalDefinition(GD); - return; - } - - // If we're deferring emission of a C++ variable with an - // initializer, remember the order in which it appeared in the file. - if (getLangOpts().CPlusPlus && isa<VarDecl>(Global) && - cast<VarDecl>(Global)->hasInit()) { - DelayedCXXInitPosition[Global] = CXXGlobalInits.size(); - CXXGlobalInits.push_back(nullptr); - } - - StringRef MangledName = getMangledName(GD); - if (GetGlobalValue(MangledName) != nullptr) { - // The value has already been used and should therefore be emitted. - addDeferredDeclToEmit(GD); - } else if (MustBeEmitted(Global)) { - // The value must be emitted, but cannot be emitted eagerly. - assert(!MayBeEmittedEagerly(Global)); - addDeferredDeclToEmit(GD); - } else { - // Otherwise, remember that we saw a deferred decl with this name. The - // first use of the mangled name will cause it to move into - // DeferredDeclsToEmit. - DeferredDecls[MangledName] = GD; - } -} - -// Check if T is a class type with a destructor that's not dllimport. -static bool HasNonDllImportDtor(QualType T) { - if (const auto *RT = T->getBaseElementTypeUnsafe()->getAs<RecordType>()) - if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) - if (RD->getDestructor() && !RD->getDestructor()->hasAttr<DLLImportAttr>()) - return true; - - return false; -} - -namespace { - struct FunctionIsDirectlyRecursive : - public RecursiveASTVisitor<FunctionIsDirectlyRecursive> { - const StringRef Name; - const Builtin::Context &BI; - bool Result; - FunctionIsDirectlyRecursive(StringRef N, const Builtin::Context &C) : - Name(N), BI(C), Result(false) { - } - typedef RecursiveASTVisitor<FunctionIsDirectlyRecursive> Base; - - bool TraverseCallExpr(CallExpr *E) { - const FunctionDecl *FD = E->getDirectCallee(); - if (!FD) - return true; - AsmLabelAttr *Attr = FD->getAttr<AsmLabelAttr>(); - if (Attr && Name == Attr->getLabel()) { - Result = true; - return false; - } - unsigned BuiltinID = FD->getBuiltinID(); - if (!BuiltinID || !BI.isLibFunction(BuiltinID)) - return true; - StringRef BuiltinName = BI.getName(BuiltinID); - if (BuiltinName.startswith("__builtin_") && - Name == BuiltinName.slice(strlen("__builtin_"), StringRef::npos)) { - Result = true; - return false; - } - return true; - } - }; - - // Make sure we're not referencing non-imported vars or functions. - struct DLLImportFunctionVisitor - : public RecursiveASTVisitor<DLLImportFunctionVisitor> { - bool SafeToInline = true; - - bool shouldVisitImplicitCode() const { return true; } - - bool VisitVarDecl(VarDecl *VD) { - if (VD->getTLSKind()) { - // A thread-local variable cannot be imported. - SafeToInline = false; - return SafeToInline; - } - - // A variable definition might imply a destructor call. - if (VD->isThisDeclarationADefinition()) - SafeToInline = !HasNonDllImportDtor(VD->getType()); - - return SafeToInline; - } - - bool VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { - if (const auto *D = E->getTemporary()->getDestructor()) - SafeToInline = D->hasAttr<DLLImportAttr>(); - return SafeToInline; - } - - bool VisitDeclRefExpr(DeclRefExpr *E) { - ValueDecl *VD = E->getDecl(); - if (isa<FunctionDecl>(VD)) - SafeToInline = VD->hasAttr<DLLImportAttr>(); - else if (VarDecl *V = dyn_cast<VarDecl>(VD)) - SafeToInline = !V->hasGlobalStorage() || V->hasAttr<DLLImportAttr>(); - return SafeToInline; - } - - bool VisitCXXConstructExpr(CXXConstructExpr *E) { - SafeToInline = E->getConstructor()->hasAttr<DLLImportAttr>(); - return SafeToInline; - } - - bool VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { - CXXMethodDecl *M = E->getMethodDecl(); - if (!M) { - // Call through a pointer to member function. This is safe to inline. - SafeToInline = true; - } else { - SafeToInline = M->hasAttr<DLLImportAttr>(); - } - return SafeToInline; - } - - bool VisitCXXDeleteExpr(CXXDeleteExpr *E) { - SafeToInline = E->getOperatorDelete()->hasAttr<DLLImportAttr>(); - return SafeToInline; - } - - bool VisitCXXNewExpr(CXXNewExpr *E) { - SafeToInline = E->getOperatorNew()->hasAttr<DLLImportAttr>(); - return SafeToInline; - } - }; -} - -// isTriviallyRecursive - Check if this function calls another -// decl that, because of the asm attribute or the other decl being a builtin, -// ends up pointing to itself. -bool -CodeGenModule::isTriviallyRecursive(const FunctionDecl *FD) { - StringRef Name; - if (getCXXABI().getMangleContext().shouldMangleDeclName(FD)) { - // asm labels are a special kind of mangling we have to support. - AsmLabelAttr *Attr = FD->getAttr<AsmLabelAttr>(); - if (!Attr) - return false; - Name = Attr->getLabel(); - } else { - Name = FD->getName(); - } - - FunctionIsDirectlyRecursive Walker(Name, Context.BuiltinInfo); - Walker.TraverseFunctionDecl(const_cast<FunctionDecl*>(FD)); - return Walker.Result; -} - -bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) { - if (getFunctionLinkage(GD) != llvm::Function::AvailableExternallyLinkage) - return true; - const auto *F = cast<FunctionDecl>(GD.getDecl()); - if (CodeGenOpts.OptimizationLevel == 0 && !F->hasAttr<AlwaysInlineAttr>()) - return false; - - if (F->hasAttr<DLLImportAttr>()) { - // Check whether it would be safe to inline this dllimport function. - DLLImportFunctionVisitor Visitor; - Visitor.TraverseFunctionDecl(const_cast<FunctionDecl*>(F)); - if (!Visitor.SafeToInline) - return false; - - if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(F)) { - // Implicit destructor invocations aren't captured in the AST, so the - // check above can't see them. Check for them manually here. - for (const Decl *Member : Dtor->getParent()->decls()) - if (isa<FieldDecl>(Member)) - if (HasNonDllImportDtor(cast<FieldDecl>(Member)->getType())) - return false; - for (const CXXBaseSpecifier &B : Dtor->getParent()->bases()) - if (HasNonDllImportDtor(B.getType())) - return false; - } - } - - // PR9614. Avoid cases where the source code is lying to us. An available - // externally function should have an equivalent function somewhere else, - // but a function that calls itself is clearly not equivalent to the real - // implementation. - // This happens in glibc's btowc and in some configure checks. - return !isTriviallyRecursive(F); -} - -bool CodeGenModule::shouldOpportunisticallyEmitVTables() { - return CodeGenOpts.OptimizationLevel > 0; -} - -void CodeGenModule::EmitMultiVersionFunctionDefinition(GlobalDecl GD, - llvm::GlobalValue *GV) { - const auto *FD = cast<FunctionDecl>(GD.getDecl()); - - if (FD->isCPUSpecificMultiVersion()) { - auto *Spec = FD->getAttr<CPUSpecificAttr>(); - for (unsigned I = 0; I < Spec->cpus_size(); ++I) - EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr); - // Requires multiple emits. - } else - EmitGlobalFunctionDefinition(GD, GV); -} - -void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) { - const auto *D = cast<ValueDecl>(GD.getDecl()); - - PrettyStackTraceDecl CrashInfo(const_cast<ValueDecl *>(D), D->getLocation(), - Context.getSourceManager(), - "Generating code for declaration"); - - if (const auto *FD = dyn_cast<FunctionDecl>(D)) { - // At -O0, don't generate IR for functions with available_externally - // linkage. - if (!shouldEmitFunction(GD)) - return; - - if (const auto *Method = dyn_cast<CXXMethodDecl>(D)) { - // Make sure to emit the definition(s) before we emit the thunks. - // This is necessary for the generation of certain thunks. - if (const auto *CD = dyn_cast<CXXConstructorDecl>(Method)) - ABI->emitCXXStructor(CD, getFromCtorType(GD.getCtorType())); - else if (const auto *DD = dyn_cast<CXXDestructorDecl>(Method)) - ABI->emitCXXStructor(DD, getFromDtorType(GD.getDtorType())); - else if (FD->isMultiVersion()) - EmitMultiVersionFunctionDefinition(GD, GV); - else - EmitGlobalFunctionDefinition(GD, GV); - - if (Method->isVirtual()) - getVTables().EmitThunks(GD); - - return; - } - - if (FD->isMultiVersion()) - return EmitMultiVersionFunctionDefinition(GD, GV); - return EmitGlobalFunctionDefinition(GD, GV); - } - - if (const auto *VD = dyn_cast<VarDecl>(D)) - return EmitGlobalVarDefinition(VD, !VD->hasDefinition()); - - llvm_unreachable("Invalid argument to EmitGlobalDefinition()"); -} - -static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, - llvm::Function *NewFn); - -static unsigned -TargetMVPriority(const TargetInfo &TI, - const CodeGenFunction::MultiVersionResolverOption &RO) { - unsigned Priority = 0; - for (StringRef Feat : RO.Conditions.Features) - Priority = std::max(Priority, TI.multiVersionSortPriority(Feat)); - - if (!RO.Conditions.Architecture.empty()) - Priority = std::max( - Priority, TI.multiVersionSortPriority(RO.Conditions.Architecture)); - return Priority; -} - -void CodeGenModule::emitMultiVersionFunctions() { - for (GlobalDecl GD : MultiVersionFuncs) { - SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options; - const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); - getContext().forEachMultiversionedFunctionVersion( - FD, [this, &GD, &Options](const FunctionDecl *CurFD) { - GlobalDecl CurGD{ - (CurFD->isDefined() ? CurFD->getDefinition() : CurFD)}; - StringRef MangledName = getMangledName(CurGD); - llvm::Constant *Func = GetGlobalValue(MangledName); - if (!Func) { - if (CurFD->isDefined()) { - EmitGlobalFunctionDefinition(CurGD, nullptr); - Func = GetGlobalValue(MangledName); - } else { - const CGFunctionInfo &FI = - getTypes().arrangeGlobalDeclaration(GD); - llvm::FunctionType *Ty = getTypes().GetFunctionType(FI); - Func = GetAddrOfFunction(CurGD, Ty, /*ForVTable=*/false, - /*DontDefer=*/false, ForDefinition); - } - assert(Func && "This should have just been created"); - } - - const auto *TA = CurFD->getAttr<TargetAttr>(); - llvm::SmallVector<StringRef, 8> Feats; - TA->getAddedFeatures(Feats); - - Options.emplace_back(cast<llvm::Function>(Func), - TA->getArchitecture(), Feats); - }); - - llvm::Function *ResolverFunc; - const TargetInfo &TI = getTarget(); - - if (TI.supportsIFunc() || FD->isTargetMultiVersion()) - ResolverFunc = cast<llvm::Function>( - GetGlobalValue((getMangledName(GD) + ".resolver").str())); - else - ResolverFunc = cast<llvm::Function>(GetGlobalValue(getMangledName(GD))); - - if (supportsCOMDAT()) - ResolverFunc->setComdat( - getModule().getOrInsertComdat(ResolverFunc->getName())); - - std::stable_sort( - Options.begin(), Options.end(), - [&TI](const CodeGenFunction::MultiVersionResolverOption &LHS, - const CodeGenFunction::MultiVersionResolverOption &RHS) { - return TargetMVPriority(TI, LHS) > TargetMVPriority(TI, RHS); - }); - CodeGenFunction CGF(*this); - CGF.EmitMultiVersionResolver(ResolverFunc, Options); - } -} - -void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) { - const auto *FD = cast<FunctionDecl>(GD.getDecl()); - assert(FD && "Not a FunctionDecl?"); - const auto *DD = FD->getAttr<CPUDispatchAttr>(); - assert(DD && "Not a cpu_dispatch Function?"); - QualType CanonTy = Context.getCanonicalType(FD->getType()); - llvm::Type *DeclTy = getTypes().ConvertFunctionType(CanonTy, FD); - - if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) { - const CGFunctionInfo &FInfo = getTypes().arrangeCXXMethodDeclaration(CXXFD); - DeclTy = getTypes().GetFunctionType(FInfo); - } - - StringRef ResolverName = getMangledName(GD); - - llvm::Type *ResolverType; - GlobalDecl ResolverGD; - if (getTarget().supportsIFunc()) - ResolverType = llvm::FunctionType::get( - llvm::PointerType::get(DeclTy, - Context.getTargetAddressSpace(FD->getType())), - false); - else { - ResolverType = DeclTy; - ResolverGD = GD; - } - - auto *ResolverFunc = cast<llvm::Function>(GetOrCreateLLVMFunction( - ResolverName, ResolverType, ResolverGD, /*ForVTable=*/false)); - - SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options; - const TargetInfo &Target = getTarget(); - unsigned Index = 0; - for (const IdentifierInfo *II : DD->cpus()) { - // Get the name of the target function so we can look it up/create it. - std::string MangledName = getMangledNameImpl(*this, GD, FD, true) + - getCPUSpecificMangling(*this, II->getName()); - - llvm::Constant *Func = GetGlobalValue(MangledName); - - if (!Func) { - GlobalDecl ExistingDecl = Manglings.lookup(MangledName); - if (ExistingDecl.getDecl() && - ExistingDecl.getDecl()->getAsFunction()->isDefined()) { - EmitGlobalFunctionDefinition(ExistingDecl, nullptr); - Func = GetGlobalValue(MangledName); - } else { - if (!ExistingDecl.getDecl()) - ExistingDecl = GD.getWithMultiVersionIndex(Index); - - Func = GetOrCreateLLVMFunction( - MangledName, DeclTy, ExistingDecl, - /*ForVTable=*/false, /*DontDefer=*/true, - /*IsThunk=*/false, llvm::AttributeList(), ForDefinition); - } - } - - llvm::SmallVector<StringRef, 32> Features; - Target.getCPUSpecificCPUDispatchFeatures(II->getName(), Features); - llvm::transform(Features, Features.begin(), - [](StringRef Str) { return Str.substr(1); }); - Features.erase(std::remove_if( - Features.begin(), Features.end(), [&Target](StringRef Feat) { - return !Target.validateCpuSupports(Feat); - }), Features.end()); - Options.emplace_back(cast<llvm::Function>(Func), StringRef{}, Features); - ++Index; - } - - llvm::sort( - Options, [](const CodeGenFunction::MultiVersionResolverOption &LHS, - const CodeGenFunction::MultiVersionResolverOption &RHS) { - return CodeGenFunction::GetX86CpuSupportsMask(LHS.Conditions.Features) > - CodeGenFunction::GetX86CpuSupportsMask(RHS.Conditions.Features); - }); - - // If the list contains multiple 'default' versions, such as when it contains - // 'pentium' and 'generic', don't emit the call to the generic one (since we - // always run on at least a 'pentium'). We do this by deleting the 'least - // advanced' (read, lowest mangling letter). - while (Options.size() > 1 && - CodeGenFunction::GetX86CpuSupportsMask( - (Options.end() - 2)->Conditions.Features) == 0) { - StringRef LHSName = (Options.end() - 2)->Function->getName(); - StringRef RHSName = (Options.end() - 1)->Function->getName(); - if (LHSName.compare(RHSName) < 0) - Options.erase(Options.end() - 2); - else - Options.erase(Options.end() - 1); - } - - CodeGenFunction CGF(*this); - CGF.EmitMultiVersionResolver(ResolverFunc, Options); -} - -/// If a dispatcher for the specified mangled name is not in the module, create -/// and return an llvm Function with the specified type. -llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver( - GlobalDecl GD, llvm::Type *DeclTy, const FunctionDecl *FD) { - std::string MangledName = - getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true); - - // Holds the name of the resolver, in ifunc mode this is the ifunc (which has - // a separate resolver). - std::string ResolverName = MangledName; - if (getTarget().supportsIFunc()) - ResolverName += ".ifunc"; - else if (FD->isTargetMultiVersion()) - ResolverName += ".resolver"; - - // If this already exists, just return that one. - if (llvm::GlobalValue *ResolverGV = GetGlobalValue(ResolverName)) - return ResolverGV; - - // Since this is the first time we've created this IFunc, make sure - // that we put this multiversioned function into the list to be - // replaced later if necessary (target multiversioning only). - if (!FD->isCPUDispatchMultiVersion() && !FD->isCPUSpecificMultiVersion()) - MultiVersionFuncs.push_back(GD); - - if (getTarget().supportsIFunc()) { - llvm::Type *ResolverType = llvm::FunctionType::get( - llvm::PointerType::get( - DeclTy, getContext().getTargetAddressSpace(FD->getType())), - false); - llvm::Constant *Resolver = GetOrCreateLLVMFunction( - MangledName + ".resolver", ResolverType, GlobalDecl{}, - /*ForVTable=*/false); - llvm::GlobalIFunc *GIF = llvm::GlobalIFunc::create( - DeclTy, 0, llvm::Function::ExternalLinkage, "", Resolver, &getModule()); - GIF->setName(ResolverName); - SetCommonAttributes(FD, GIF); - - return GIF; - } - - llvm::Constant *Resolver = GetOrCreateLLVMFunction( - ResolverName, DeclTy, GlobalDecl{}, /*ForVTable=*/false); - assert(isa<llvm::GlobalValue>(Resolver) && - "Resolver should be created for the first time"); - SetCommonAttributes(FD, cast<llvm::GlobalValue>(Resolver)); - return Resolver; -} - -/// GetOrCreateLLVMFunction - If the specified mangled name is not in the -/// module, create and return an llvm Function with the specified type. If there -/// is something in the module with the specified name, return it potentially -/// bitcasted to the right type. -/// -/// If D is non-null, it specifies a decl that correspond to this. This is used -/// to set the attributes on the function when it is first created. -llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( - StringRef MangledName, llvm::Type *Ty, GlobalDecl GD, bool ForVTable, - bool DontDefer, bool IsThunk, llvm::AttributeList ExtraAttrs, - ForDefinition_t IsForDefinition) { - const Decl *D = GD.getDecl(); - - // Any attempts to use a MultiVersion function should result in retrieving - // the iFunc instead. Name Mangling will handle the rest of the changes. - if (const FunctionDecl *FD = cast_or_null<FunctionDecl>(D)) { - // For the device mark the function as one that should be emitted. - if (getLangOpts().OpenMPIsDevice && OpenMPRuntime && - !OpenMPRuntime->markAsGlobalTarget(GD) && FD->isDefined() && - !DontDefer && !IsForDefinition) { - if (const FunctionDecl *FDDef = FD->getDefinition()) { - GlobalDecl GDDef; - if (const auto *CD = dyn_cast<CXXConstructorDecl>(FDDef)) - GDDef = GlobalDecl(CD, GD.getCtorType()); - else if (const auto *DD = dyn_cast<CXXDestructorDecl>(FDDef)) - GDDef = GlobalDecl(DD, GD.getDtorType()); - else - GDDef = GlobalDecl(FDDef); - EmitGlobal(GDDef); - } - } - - if (FD->isMultiVersion()) { - const auto *TA = FD->getAttr<TargetAttr>(); - if (TA && TA->isDefaultVersion()) - UpdateMultiVersionNames(GD, FD); - if (!IsForDefinition) - return GetOrCreateMultiVersionResolver(GD, Ty, FD); - } - } - - // Lookup the entry, lazily creating it if necessary. - llvm::GlobalValue *Entry = GetGlobalValue(MangledName); - if (Entry) { - if (WeakRefReferences.erase(Entry)) { - const FunctionDecl *FD = cast_or_null<FunctionDecl>(D); - if (FD && !FD->hasAttr<WeakAttr>()) - Entry->setLinkage(llvm::Function::ExternalLinkage); - } - - // Handle dropped DLL attributes. - if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>()) { - Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); - setDSOLocal(Entry); - } - - // If there are two attempts to define the same mangled name, issue an - // error. - if (IsForDefinition && !Entry->isDeclaration()) { - GlobalDecl OtherGD; - // Check that GD is not yet in DiagnosedConflictingDefinitions is required - // to make sure that we issue an error only once. - if (lookupRepresentativeDecl(MangledName, OtherGD) && - (GD.getCanonicalDecl().getDecl() != - OtherGD.getCanonicalDecl().getDecl()) && - DiagnosedConflictingDefinitions.insert(GD).second) { - getDiags().Report(D->getLocation(), diag::err_duplicate_mangled_name) - << MangledName; - getDiags().Report(OtherGD.getDecl()->getLocation(), - diag::note_previous_definition); - } - } - - if ((isa<llvm::Function>(Entry) || isa<llvm::GlobalAlias>(Entry)) && - (Entry->getType()->getElementType() == Ty)) { - return Entry; - } - - // Make sure the result is of the correct type. - // (If function is requested for a definition, we always need to create a new - // function, not just return a bitcast.) - if (!IsForDefinition) - return llvm::ConstantExpr::getBitCast(Entry, Ty->getPointerTo()); - } - - // This function doesn't have a complete type (for example, the return - // type is an incomplete struct). Use a fake type instead, and make - // sure not to try to set attributes. - bool IsIncompleteFunction = false; - - llvm::FunctionType *FTy; - if (isa<llvm::FunctionType>(Ty)) { - FTy = cast<llvm::FunctionType>(Ty); - } else { - FTy = llvm::FunctionType::get(VoidTy, false); - IsIncompleteFunction = true; - } - - llvm::Function *F = - llvm::Function::Create(FTy, llvm::Function::ExternalLinkage, - Entry ? StringRef() : MangledName, &getModule()); - - // If we already created a function with the same mangled name (but different - // type) before, take its name and add it to the list of functions to be - // replaced with F at the end of CodeGen. - // - // This happens if there is a prototype for a function (e.g. "int f()") and - // then a definition of a different type (e.g. "int f(int x)"). - if (Entry) { - F->takeName(Entry); - - // This might be an implementation of a function without a prototype, in - // which case, try to do special replacement of calls which match the new - // prototype. The really key thing here is that we also potentially drop - // arguments from the call site so as to make a direct call, which makes the - // inliner happier and suppresses a number of optimizer warnings (!) about - // dropping arguments. - if (!Entry->use_empty()) { - ReplaceUsesOfNonProtoTypeWithRealFunction(Entry, F); - Entry->removeDeadConstantUsers(); - } - - llvm::Constant *BC = llvm::ConstantExpr::getBitCast( - F, Entry->getType()->getElementType()->getPointerTo()); - addGlobalValReplacement(Entry, BC); - } - - assert(F->getName() == MangledName && "name was uniqued!"); - if (D) - SetFunctionAttributes(GD, F, IsIncompleteFunction, IsThunk); - if (ExtraAttrs.hasAttributes(llvm::AttributeList::FunctionIndex)) { - llvm::AttrBuilder B(ExtraAttrs, llvm::AttributeList::FunctionIndex); - F->addAttributes(llvm::AttributeList::FunctionIndex, B); - } - - if (!DontDefer) { - // All MSVC dtors other than the base dtor are linkonce_odr and delegate to - // each other bottoming out with the base dtor. Therefore we emit non-base - // dtors on usage, even if there is no dtor definition in the TU. - if (D && isa<CXXDestructorDecl>(D) && - getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(D), - GD.getDtorType())) - addDeferredDeclToEmit(GD); - - // This is the first use or definition of a mangled name. If there is a - // deferred decl with this name, remember that we need to emit it at the end - // of the file. - auto DDI = DeferredDecls.find(MangledName); - if (DDI != DeferredDecls.end()) { - // Move the potentially referenced deferred decl to the - // DeferredDeclsToEmit list, and remove it from DeferredDecls (since we - // don't need it anymore). - addDeferredDeclToEmit(DDI->second); - DeferredDecls.erase(DDI); - - // Otherwise, there are cases we have to worry about where we're - // using a declaration for which we must emit a definition but where - // we might not find a top-level definition: - // - member functions defined inline in their classes - // - friend functions defined inline in some class - // - special member functions with implicit definitions - // If we ever change our AST traversal to walk into class methods, - // this will be unnecessary. - // - // We also don't emit a definition for a function if it's going to be an - // entry in a vtable, unless it's already marked as used. - } else if (getLangOpts().CPlusPlus && D) { - // Look for a declaration that's lexically in a record. - for (const auto *FD = cast<FunctionDecl>(D)->getMostRecentDecl(); FD; - FD = FD->getPreviousDecl()) { - if (isa<CXXRecordDecl>(FD->getLexicalDeclContext())) { - if (FD->doesThisDeclarationHaveABody()) { - addDeferredDeclToEmit(GD.getWithDecl(FD)); - break; - } - } - } - } - } - - // Make sure the result is of the requested type. - if (!IsIncompleteFunction) { - assert(F->getType()->getElementType() == Ty); - return F; - } - - llvm::Type *PTy = llvm::PointerType::getUnqual(Ty); - return llvm::ConstantExpr::getBitCast(F, PTy); -} - -/// GetAddrOfFunction - Return the address of the given function. If Ty is -/// non-null, then this function will use the specified type if it has to -/// create it (this occurs when we see a definition of the function). -llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD, - llvm::Type *Ty, - bool ForVTable, - bool DontDefer, - ForDefinition_t IsForDefinition) { - // If there was no specific requested type, just convert it now. - if (!Ty) { - const auto *FD = cast<FunctionDecl>(GD.getDecl()); - auto CanonTy = Context.getCanonicalType(FD->getType()); - Ty = getTypes().ConvertFunctionType(CanonTy, FD); - } - - // Devirtualized destructor calls may come through here instead of via - // getAddrOfCXXStructor. Make sure we use the MS ABI base destructor instead - // of the complete destructor when necessary. - if (const auto *DD = dyn_cast<CXXDestructorDecl>(GD.getDecl())) { - if (getTarget().getCXXABI().isMicrosoft() && - GD.getDtorType() == Dtor_Complete && - DD->getParent()->getNumVBases() == 0) - GD = GlobalDecl(DD, Dtor_Base); - } - - StringRef MangledName = getMangledName(GD); - return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable, DontDefer, - /*IsThunk=*/false, llvm::AttributeList(), - IsForDefinition); -} - -static const FunctionDecl * -GetRuntimeFunctionDecl(ASTContext &C, StringRef Name) { - TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl(); - DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl); - - IdentifierInfo &CII = C.Idents.get(Name); - for (const auto &Result : DC->lookup(&CII)) - if (const auto FD = dyn_cast<FunctionDecl>(Result)) - return FD; - - if (!C.getLangOpts().CPlusPlus) - return nullptr; - - // Demangle the premangled name from getTerminateFn() - IdentifierInfo &CXXII = - (Name == "_ZSt9terminatev" || Name == "?terminate@@YAXXZ") - ? C.Idents.get("terminate") - : C.Idents.get(Name); - - for (const auto &N : {"__cxxabiv1", "std"}) { - IdentifierInfo &NS = C.Idents.get(N); - for (const auto &Result : DC->lookup(&NS)) { - NamespaceDecl *ND = dyn_cast<NamespaceDecl>(Result); - if (auto LSD = dyn_cast<LinkageSpecDecl>(Result)) - for (const auto &Result : LSD->lookup(&NS)) - if ((ND = dyn_cast<NamespaceDecl>(Result))) - break; - - if (ND) - for (const auto &Result : ND->lookup(&CXXII)) - if (const auto *FD = dyn_cast<FunctionDecl>(Result)) - return FD; - } - } - - return nullptr; -} - -/// CreateRuntimeFunction - Create a new runtime function with the specified -/// type and name. -llvm::Constant * -CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name, - llvm::AttributeList ExtraAttrs, - bool Local) { - llvm::Constant *C = - GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false, - /*DontDefer=*/false, /*IsThunk=*/false, - ExtraAttrs); - - if (auto *F = dyn_cast<llvm::Function>(C)) { - if (F->empty()) { - F->setCallingConv(getRuntimeCC()); - - if (!Local && getTriple().isOSBinFormatCOFF() && - !getCodeGenOpts().LTOVisibilityPublicStd && - !getTriple().isWindowsGNUEnvironment()) { - const FunctionDecl *FD = GetRuntimeFunctionDecl(Context, Name); - if (!FD || FD->hasAttr<DLLImportAttr>()) { - F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); - F->setLinkage(llvm::GlobalValue::ExternalLinkage); - } - } - setDSOLocal(F); - } - } - - return C; -} - -/// CreateBuiltinFunction - Create a new builtin function with the specified -/// type and name. -llvm::Constant * -CodeGenModule::CreateBuiltinFunction(llvm::FunctionType *FTy, StringRef Name, - llvm::AttributeList ExtraAttrs) { - return CreateRuntimeFunction(FTy, Name, ExtraAttrs, true); -} - -/// isTypeConstant - Determine whether an object of this type can be emitted -/// as a constant. -/// -/// If ExcludeCtor is true, the duration when the object's constructor runs -/// will not be considered. The caller will need to verify that the object is -/// not written to during its construction. -bool CodeGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor) { - if (!Ty.isConstant(Context) && !Ty->isReferenceType()) - return false; - - if (Context.getLangOpts().CPlusPlus) { - if (const CXXRecordDecl *Record - = Context.getBaseElementType(Ty)->getAsCXXRecordDecl()) - return ExcludeCtor && !Record->hasMutableFields() && - Record->hasTrivialDestructor(); - } - - return true; -} - -/// GetOrCreateLLVMGlobal - If the specified mangled name is not in the module, -/// create and return an llvm GlobalVariable with the specified type. If there -/// is something in the module with the specified name, return it potentially -/// bitcasted to the right type. -/// -/// If D is non-null, it specifies a decl that correspond to this. This is used -/// to set the attributes on the global when it is first created. -/// -/// If IsForDefinition is true, it is guaranteed that an actual global with -/// type Ty will be returned, not conversion of a variable with the same -/// mangled name but some other type. -llvm::Constant * -CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, - llvm::PointerType *Ty, - const VarDecl *D, - ForDefinition_t IsForDefinition) { - // Lookup the entry, lazily creating it if necessary. - llvm::GlobalValue *Entry = GetGlobalValue(MangledName); - if (Entry) { - if (WeakRefReferences.erase(Entry)) { - if (D && !D->hasAttr<WeakAttr>()) - Entry->setLinkage(llvm::Function::ExternalLinkage); - } - - // Handle dropped DLL attributes. - if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>()) - Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); - - if (LangOpts.OpenMP && !LangOpts.OpenMPSimd && D) - getOpenMPRuntime().registerTargetGlobalVariable(D, Entry); - - if (Entry->getType() == Ty) - return Entry; - - // If there are two attempts to define the same mangled name, issue an - // error. - if (IsForDefinition && !Entry->isDeclaration()) { - GlobalDecl OtherGD; - const VarDecl *OtherD; - - // Check that D is not yet in DiagnosedConflictingDefinitions is required - // to make sure that we issue an error only once. - if (D && lookupRepresentativeDecl(MangledName, OtherGD) && - (D->getCanonicalDecl() != OtherGD.getCanonicalDecl().getDecl()) && - (OtherD = dyn_cast<VarDecl>(OtherGD.getDecl())) && - OtherD->hasInit() && - DiagnosedConflictingDefinitions.insert(D).second) { - getDiags().Report(D->getLocation(), diag::err_duplicate_mangled_name) - << MangledName; - getDiags().Report(OtherGD.getDecl()->getLocation(), - diag::note_previous_definition); - } - } - - // Make sure the result is of the correct type. - if (Entry->getType()->getAddressSpace() != Ty->getAddressSpace()) - return llvm::ConstantExpr::getAddrSpaceCast(Entry, Ty); - - // (If global is requested for a definition, we always need to create a new - // global, not just return a bitcast.) - if (!IsForDefinition) - return llvm::ConstantExpr::getBitCast(Entry, Ty); - } - - auto AddrSpace = GetGlobalVarAddressSpace(D); - auto TargetAddrSpace = getContext().getTargetAddressSpace(AddrSpace); - - auto *GV = new llvm::GlobalVariable( - getModule(), Ty->getElementType(), false, - llvm::GlobalValue::ExternalLinkage, nullptr, MangledName, nullptr, - llvm::GlobalVariable::NotThreadLocal, TargetAddrSpace); - - // If we already created a global with the same mangled name (but different - // type) before, take its name and remove it from its parent. - if (Entry) { - GV->takeName(Entry); - - if (!Entry->use_empty()) { - llvm::Constant *NewPtrForOldDecl = - llvm::ConstantExpr::getBitCast(GV, Entry->getType()); - Entry->replaceAllUsesWith(NewPtrForOldDecl); - } - - Entry->eraseFromParent(); - } - - // This is the first use or definition of a mangled name. If there is a - // deferred decl with this name, remember that we need to emit it at the end - // of the file. - auto DDI = DeferredDecls.find(MangledName); - if (DDI != DeferredDecls.end()) { - // Move the potentially referenced deferred decl to the DeferredDeclsToEmit - // list, and remove it from DeferredDecls (since we don't need it anymore). - addDeferredDeclToEmit(DDI->second); - DeferredDecls.erase(DDI); - } - - // Handle things which are present even on external declarations. - if (D) { - if (LangOpts.OpenMP && !LangOpts.OpenMPSimd) - getOpenMPRuntime().registerTargetGlobalVariable(D, GV); - - // FIXME: This code is overly simple and should be merged with other global - // handling. - GV->setConstant(isTypeConstant(D->getType(), false)); - - GV->setAlignment(getContext().getDeclAlign(D).getQuantity()); - - setLinkageForGV(GV, D); - - if (D->getTLSKind()) { - if (D->getTLSKind() == VarDecl::TLS_Dynamic) - CXXThreadLocals.push_back(D); - setTLSMode(GV, *D); - } - - setGVProperties(GV, D); - - // If required by the ABI, treat declarations of static data members with - // inline initializers as definitions. - if (getContext().isMSStaticDataMemberInlineDefinition(D)) { - EmitGlobalVarDefinition(D); - } - - // Emit section information for extern variables. - if (D->hasExternalStorage()) { - if (const SectionAttr *SA = D->getAttr<SectionAttr>()) - GV->setSection(SA->getName()); - } - - // Handle XCore specific ABI requirements. - if (getTriple().getArch() == llvm::Triple::xcore && - D->getLanguageLinkage() == CLanguageLinkage && - D->getType().isConstant(Context) && - isExternallyVisible(D->getLinkageAndVisibility().getLinkage())) - GV->setSection(".cp.rodata"); - - // Check if we a have a const declaration with an initializer, we may be - // able to emit it as available_externally to expose it's value to the - // optimizer. - if (Context.getLangOpts().CPlusPlus && GV->hasExternalLinkage() && - D->getType().isConstQualified() && !GV->hasInitializer() && - !D->hasDefinition() && D->hasInit() && !D->hasAttr<DLLImportAttr>()) { - const auto *Record = - Context.getBaseElementType(D->getType())->getAsCXXRecordDecl(); - bool HasMutableFields = Record && Record->hasMutableFields(); - if (!HasMutableFields) { - const VarDecl *InitDecl; - const Expr *InitExpr = D->getAnyInitializer(InitDecl); - if (InitExpr) { - ConstantEmitter emitter(*this); - llvm::Constant *Init = emitter.tryEmitForInitializer(*InitDecl); - if (Init) { - auto *InitType = Init->getType(); - if (GV->getType()->getElementType() != InitType) { - // The type of the initializer does not match the definition. - // This happens when an initializer has a different type from - // the type of the global (because of padding at the end of a - // structure for instance). - GV->setName(StringRef()); - // Make a new global with the correct type, this is now guaranteed - // to work. - auto *NewGV = cast<llvm::GlobalVariable>( - GetAddrOfGlobalVar(D, InitType, IsForDefinition)); - - // Erase the old global, since it is no longer used. - GV->eraseFromParent(); - GV = NewGV; - } else { - GV->setInitializer(Init); - GV->setConstant(true); - GV->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage); - } - emitter.finalize(GV); - } - } - } - } - } - - LangAS ExpectedAS = - D ? D->getType().getAddressSpace() - : (LangOpts.OpenCL ? LangAS::opencl_global : LangAS::Default); - assert(getContext().getTargetAddressSpace(ExpectedAS) == - Ty->getPointerAddressSpace()); - if (AddrSpace != ExpectedAS) - return getTargetCodeGenInfo().performAddrSpaceCast(*this, GV, AddrSpace, - ExpectedAS, Ty); - - return GV; -} - -llvm::Constant * -CodeGenModule::GetAddrOfGlobal(GlobalDecl GD, - ForDefinition_t IsForDefinition) { - const Decl *D = GD.getDecl(); - if (isa<CXXConstructorDecl>(D)) - return getAddrOfCXXStructor(cast<CXXConstructorDecl>(D), - getFromCtorType(GD.getCtorType()), - /*FnInfo=*/nullptr, /*FnType=*/nullptr, - /*DontDefer=*/false, IsForDefinition); - else if (isa<CXXDestructorDecl>(D)) - return getAddrOfCXXStructor(cast<CXXDestructorDecl>(D), - getFromDtorType(GD.getDtorType()), - /*FnInfo=*/nullptr, /*FnType=*/nullptr, - /*DontDefer=*/false, IsForDefinition); - else if (isa<CXXMethodDecl>(D)) { - auto FInfo = &getTypes().arrangeCXXMethodDeclaration( - cast<CXXMethodDecl>(D)); - auto Ty = getTypes().GetFunctionType(*FInfo); - return GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer=*/false, - IsForDefinition); - } else if (isa<FunctionDecl>(D)) { - const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD); - llvm::FunctionType *Ty = getTypes().GetFunctionType(FI); - return GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer=*/false, - IsForDefinition); - } else - return GetAddrOfGlobalVar(cast<VarDecl>(D), /*Ty=*/nullptr, - IsForDefinition); -} - -llvm::GlobalVariable *CodeGenModule::CreateOrReplaceCXXRuntimeVariable( - StringRef Name, llvm::Type *Ty, llvm::GlobalValue::LinkageTypes Linkage, - unsigned Alignment) { - llvm::GlobalVariable *GV = getModule().getNamedGlobal(Name); - llvm::GlobalVariable *OldGV = nullptr; - - if (GV) { - // Check if the variable has the right type. - if (GV->getType()->getElementType() == Ty) - return GV; - - // Because C++ name mangling, the only way we can end up with an already - // existing global with the same name is if it has been declared extern "C". - assert(GV->isDeclaration() && "Declaration has wrong type!"); - OldGV = GV; - } - - // Create a new variable. - GV = new llvm::GlobalVariable(getModule(), Ty, /*isConstant=*/true, - Linkage, nullptr, Name); - - if (OldGV) { - // Replace occurrences of the old variable if needed. - GV->takeName(OldGV); - - if (!OldGV->use_empty()) { - llvm::Constant *NewPtrForOldDecl = - llvm::ConstantExpr::getBitCast(GV, OldGV->getType()); - OldGV->replaceAllUsesWith(NewPtrForOldDecl); - } - - OldGV->eraseFromParent(); - } - - if (supportsCOMDAT() && GV->isWeakForLinker() && - !GV->hasAvailableExternallyLinkage()) - GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); - - GV->setAlignment(Alignment); - - return GV; -} - -/// GetAddrOfGlobalVar - Return the llvm::Constant for the address of the -/// given global variable. If Ty is non-null and if the global doesn't exist, -/// then it will be created with the specified type instead of whatever the -/// normal requested type would be. If IsForDefinition is true, it is guaranteed -/// that an actual global with type Ty will be returned, not conversion of a -/// variable with the same mangled name but some other type. -llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D, - llvm::Type *Ty, - ForDefinition_t IsForDefinition) { - assert(D->hasGlobalStorage() && "Not a global variable"); - QualType ASTTy = D->getType(); - if (!Ty) - Ty = getTypes().ConvertTypeForMem(ASTTy); - - llvm::PointerType *PTy = - llvm::PointerType::get(Ty, getContext().getTargetAddressSpace(ASTTy)); - - StringRef MangledName = getMangledName(D); - return GetOrCreateLLVMGlobal(MangledName, PTy, D, IsForDefinition); -} - -/// CreateRuntimeVariable - Create a new runtime global variable with the -/// specified type and name. -llvm::Constant * -CodeGenModule::CreateRuntimeVariable(llvm::Type *Ty, - StringRef Name) { - auto *Ret = - GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), nullptr); - setDSOLocal(cast<llvm::GlobalValue>(Ret->stripPointerCasts())); - return Ret; -} - -void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) { - assert(!D->getInit() && "Cannot emit definite definitions here!"); - - StringRef MangledName = getMangledName(D); - llvm::GlobalValue *GV = GetGlobalValue(MangledName); - - // We already have a definition, not declaration, with the same mangled name. - // Emitting of declaration is not required (and actually overwrites emitted - // definition). - if (GV && !GV->isDeclaration()) - return; - - // If we have not seen a reference to this variable yet, place it into the - // deferred declarations table to be emitted if needed later. - if (!MustBeEmitted(D) && !GV) { - DeferredDecls[MangledName] = D; - return; - } - - // The tentative definition is the only definition. - EmitGlobalVarDefinition(D); -} - -CharUnits CodeGenModule::GetTargetTypeStoreSize(llvm::Type *Ty) const { - return Context.toCharUnitsFromBits( - getDataLayout().getTypeStoreSizeInBits(Ty)); -} - -LangAS CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D) { - LangAS AddrSpace = LangAS::Default; - if (LangOpts.OpenCL) { - AddrSpace = D ? D->getType().getAddressSpace() : LangAS::opencl_global; - assert(AddrSpace == LangAS::opencl_global || - AddrSpace == LangAS::opencl_constant || - AddrSpace == LangAS::opencl_local || - AddrSpace >= LangAS::FirstTargetAddressSpace); - return AddrSpace; - } - - if (LangOpts.CUDA && LangOpts.CUDAIsDevice) { - if (D && D->hasAttr<CUDAConstantAttr>()) - return LangAS::cuda_constant; - else if (D && D->hasAttr<CUDASharedAttr>()) - return LangAS::cuda_shared; - else if (D && D->hasAttr<CUDADeviceAttr>()) - return LangAS::cuda_device; - else if (D && D->getType().isConstQualified()) - return LangAS::cuda_constant; - else - return LangAS::cuda_device; - } - - return getTargetCodeGenInfo().getGlobalVarAddressSpace(*this, D); -} - -LangAS CodeGenModule::getStringLiteralAddressSpace() const { - // OpenCL v1.2 s6.5.3: a string literal is in the constant address space. - if (LangOpts.OpenCL) - return LangAS::opencl_constant; - if (auto AS = getTarget().getConstantAddressSpace()) - return AS.getValue(); - return LangAS::Default; -} - -// In address space agnostic languages, string literals are in default address -// space in AST. However, certain targets (e.g. amdgcn) request them to be -// emitted in constant address space in LLVM IR. To be consistent with other -// parts of AST, string literal global variables in constant address space -// need to be casted to default address space before being put into address -// map and referenced by other part of CodeGen. -// In OpenCL, string literals are in constant address space in AST, therefore -// they should not be casted to default address space. -static llvm::Constant * -castStringLiteralToDefaultAddressSpace(CodeGenModule &CGM, - llvm::GlobalVariable *GV) { - llvm::Constant *Cast = GV; - if (!CGM.getLangOpts().OpenCL) { - if (auto AS = CGM.getTarget().getConstantAddressSpace()) { - if (AS != LangAS::Default) - Cast = CGM.getTargetCodeGenInfo().performAddrSpaceCast( - CGM, GV, AS.getValue(), LangAS::Default, - GV->getValueType()->getPointerTo( - CGM.getContext().getTargetAddressSpace(LangAS::Default))); - } - } - return Cast; -} - -template<typename SomeDecl> -void CodeGenModule::MaybeHandleStaticInExternC(const SomeDecl *D, - llvm::GlobalValue *GV) { - if (!getLangOpts().CPlusPlus) - return; - - // Must have 'used' attribute, or else inline assembly can't rely on - // the name existing. - if (!D->template hasAttr<UsedAttr>()) - return; - - // Must have internal linkage and an ordinary name. - if (!D->getIdentifier() || D->getFormalLinkage() != InternalLinkage) - return; - - // Must be in an extern "C" context. Entities declared directly within - // a record are not extern "C" even if the record is in such a context. - const SomeDecl *First = D->getFirstDecl(); - if (First->getDeclContext()->isRecord() || !First->isInExternCContext()) - return; - - // OK, this is an internal linkage entity inside an extern "C" linkage - // specification. Make a note of that so we can give it the "expected" - // mangled name if nothing else is using that name. - std::pair<StaticExternCMap::iterator, bool> R = - StaticExternCValues.insert(std::make_pair(D->getIdentifier(), GV)); - - // If we have multiple internal linkage entities with the same name - // in extern "C" regions, none of them gets that name. - if (!R.second) - R.first->second = nullptr; -} - -static bool shouldBeInCOMDAT(CodeGenModule &CGM, const Decl &D) { - if (!CGM.supportsCOMDAT()) - return false; - - if (D.hasAttr<SelectAnyAttr>()) - return true; - - GVALinkage Linkage; - if (auto *VD = dyn_cast<VarDecl>(&D)) - Linkage = CGM.getContext().GetGVALinkageForVariable(VD); - else - Linkage = CGM.getContext().GetGVALinkageForFunction(cast<FunctionDecl>(&D)); - - switch (Linkage) { - case GVA_Internal: - case GVA_AvailableExternally: - case GVA_StrongExternal: - return false; - case GVA_DiscardableODR: - case GVA_StrongODR: - return true; - } - llvm_unreachable("No such linkage"); -} - -void CodeGenModule::maybeSetTrivialComdat(const Decl &D, - llvm::GlobalObject &GO) { - if (!shouldBeInCOMDAT(*this, D)) - return; - GO.setComdat(TheModule.getOrInsertComdat(GO.getName())); -} - -/// Pass IsTentative as true if you want to create a tentative definition. -void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, - bool IsTentative) { - // OpenCL global variables of sampler type are translated to function calls, - // therefore no need to be translated. - QualType ASTTy = D->getType(); - if (getLangOpts().OpenCL && ASTTy->isSamplerT()) - return; - - // If this is OpenMP device, check if it is legal to emit this global - // normally. - if (LangOpts.OpenMPIsDevice && OpenMPRuntime && - OpenMPRuntime->emitTargetGlobalVariable(D)) - return; - - llvm::Constant *Init = nullptr; - CXXRecordDecl *RD = ASTTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); - bool NeedsGlobalCtor = false; - bool NeedsGlobalDtor = RD && !RD->hasTrivialDestructor(); - - const VarDecl *InitDecl; - const Expr *InitExpr = D->getAnyInitializer(InitDecl); - - Optional<ConstantEmitter> emitter; - - // CUDA E.2.4.1 "__shared__ variables cannot have an initialization - // as part of their declaration." Sema has already checked for - // error cases, so we just need to set Init to UndefValue. - bool IsCUDASharedVar = - getLangOpts().CUDAIsDevice && D->hasAttr<CUDASharedAttr>(); - // Shadows of initialized device-side global variables are also left - // undefined. - bool IsCUDAShadowVar = - !getLangOpts().CUDAIsDevice && - (D->hasAttr<CUDAConstantAttr>() || D->hasAttr<CUDADeviceAttr>() || - D->hasAttr<CUDASharedAttr>()); - if (getLangOpts().CUDA && (IsCUDASharedVar || IsCUDAShadowVar)) - Init = llvm::UndefValue::get(getTypes().ConvertType(ASTTy)); - else if (!InitExpr) { - // This is a tentative definition; tentative definitions are - // implicitly initialized with { 0 }. - // - // Note that tentative definitions are only emitted at the end of - // a translation unit, so they should never have incomplete - // type. In addition, EmitTentativeDefinition makes sure that we - // never attempt to emit a tentative definition if a real one - // exists. A use may still exists, however, so we still may need - // to do a RAUW. - assert(!ASTTy->isIncompleteType() && "Unexpected incomplete type"); - Init = EmitNullConstant(D->getType()); - } else { - initializedGlobalDecl = GlobalDecl(D); - emitter.emplace(*this); - Init = emitter->tryEmitForInitializer(*InitDecl); - - if (!Init) { - QualType T = InitExpr->getType(); - if (D->getType()->isReferenceType()) - T = D->getType(); - - if (getLangOpts().CPlusPlus) { - Init = EmitNullConstant(T); - NeedsGlobalCtor = true; - } else { - ErrorUnsupported(D, "static initializer"); - Init = llvm::UndefValue::get(getTypes().ConvertType(T)); - } - } else { - // We don't need an initializer, so remove the entry for the delayed - // initializer position (just in case this entry was delayed) if we - // also don't need to register a destructor. - if (getLangOpts().CPlusPlus && !NeedsGlobalDtor) - DelayedCXXInitPosition.erase(D); - } - } - - llvm::Type* InitType = Init->getType(); - llvm::Constant *Entry = - GetAddrOfGlobalVar(D, InitType, ForDefinition_t(!IsTentative)); - - // Strip off a bitcast if we got one back. - if (auto *CE = dyn_cast<llvm::ConstantExpr>(Entry)) { - assert(CE->getOpcode() == llvm::Instruction::BitCast || - CE->getOpcode() == llvm::Instruction::AddrSpaceCast || - // All zero index gep. - CE->getOpcode() == llvm::Instruction::GetElementPtr); - Entry = CE->getOperand(0); - } - - // Entry is now either a Function or GlobalVariable. - auto *GV = dyn_cast<llvm::GlobalVariable>(Entry); - - // We have a definition after a declaration with the wrong type. - // We must make a new GlobalVariable* and update everything that used OldGV - // (a declaration or tentative definition) with the new GlobalVariable* - // (which will be a definition). - // - // This happens if there is a prototype for a global (e.g. - // "extern int x[];") and then a definition of a different type (e.g. - // "int x[10];"). This also happens when an initializer has a different type - // from the type of the global (this happens with unions). - if (!GV || GV->getType()->getElementType() != InitType || - GV->getType()->getAddressSpace() != - getContext().getTargetAddressSpace(GetGlobalVarAddressSpace(D))) { - - // Move the old entry aside so that we'll create a new one. - Entry->setName(StringRef()); - - // Make a new global with the correct type, this is now guaranteed to work. - GV = cast<llvm::GlobalVariable>( - GetAddrOfGlobalVar(D, InitType, ForDefinition_t(!IsTentative))); - - // Replace all uses of the old global with the new global - llvm::Constant *NewPtrForOldDecl = - llvm::ConstantExpr::getBitCast(GV, Entry->getType()); - Entry->replaceAllUsesWith(NewPtrForOldDecl); - - // Erase the old global, since it is no longer used. - cast<llvm::GlobalValue>(Entry)->eraseFromParent(); - } - - MaybeHandleStaticInExternC(D, GV); - - if (D->hasAttr<AnnotateAttr>()) - AddGlobalAnnotations(D, GV); - - // Set the llvm linkage type as appropriate. - llvm::GlobalValue::LinkageTypes Linkage = - getLLVMLinkageVarDefinition(D, GV->isConstant()); - - // CUDA B.2.1 "The __device__ qualifier declares a variable that resides on - // the device. [...]" - // CUDA B.2.2 "The __constant__ qualifier, optionally used together with - // __device__, declares a variable that: [...] - // Is accessible from all the threads within the grid and from the host - // through the runtime library (cudaGetSymbolAddress() / cudaGetSymbolSize() - // / cudaMemcpyToSymbol() / cudaMemcpyFromSymbol())." - if (GV && LangOpts.CUDA) { - if (LangOpts.CUDAIsDevice) { - if (D->hasAttr<CUDADeviceAttr>() || D->hasAttr<CUDAConstantAttr>()) - GV->setExternallyInitialized(true); - } else { - // Host-side shadows of external declarations of device-side - // global variables become internal definitions. These have to - // be internal in order to prevent name conflicts with global - // host variables with the same name in a different TUs. - if (D->hasAttr<CUDADeviceAttr>() || D->hasAttr<CUDAConstantAttr>()) { - Linkage = llvm::GlobalValue::InternalLinkage; - - // Shadow variables and their properties must be registered - // with CUDA runtime. - unsigned Flags = 0; - if (!D->hasDefinition()) - Flags |= CGCUDARuntime::ExternDeviceVar; - if (D->hasAttr<CUDAConstantAttr>()) - Flags |= CGCUDARuntime::ConstantDeviceVar; - // Extern global variables will be registered in the TU where they are - // defined. - if (!D->hasExternalStorage()) - getCUDARuntime().registerDeviceVar(*GV, Flags); - } else if (D->hasAttr<CUDASharedAttr>()) - // __shared__ variables are odd. Shadows do get created, but - // they are not registered with the CUDA runtime, so they - // can't really be used to access their device-side - // counterparts. It's not clear yet whether it's nvcc's bug or - // a feature, but we've got to do the same for compatibility. - Linkage = llvm::GlobalValue::InternalLinkage; - } - } - - GV->setInitializer(Init); - if (emitter) emitter->finalize(GV); - - // If it is safe to mark the global 'constant', do so now. - GV->setConstant(!NeedsGlobalCtor && !NeedsGlobalDtor && - isTypeConstant(D->getType(), true)); - - // If it is in a read-only section, mark it 'constant'. - if (const SectionAttr *SA = D->getAttr<SectionAttr>()) { - const ASTContext::SectionInfo &SI = Context.SectionInfos[SA->getName()]; - if ((SI.SectionFlags & ASTContext::PSF_Write) == 0) - GV->setConstant(true); - } - - GV->setAlignment(getContext().getDeclAlign(D).getQuantity()); - - - // On Darwin, if the normal linkage of a C++ thread_local variable is - // LinkOnce or Weak, we keep the normal linkage to prevent multiple - // copies within a linkage unit; otherwise, the backing variable has - // internal linkage and all accesses should just be calls to the - // Itanium-specified entry point, which has the normal linkage of the - // variable. This is to preserve the ability to change the implementation - // behind the scenes. - if (!D->isStaticLocal() && D->getTLSKind() == VarDecl::TLS_Dynamic && - Context.getTargetInfo().getTriple().isOSDarwin() && - !llvm::GlobalVariable::isLinkOnceLinkage(Linkage) && - !llvm::GlobalVariable::isWeakLinkage(Linkage)) - Linkage = llvm::GlobalValue::InternalLinkage; - - GV->setLinkage(Linkage); - if (D->hasAttr<DLLImportAttr>()) - GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass); - else if (D->hasAttr<DLLExportAttr>()) - GV->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass); - else - GV->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass); - - if (Linkage == llvm::GlobalVariable::CommonLinkage) { - // common vars aren't constant even if declared const. - GV->setConstant(false); - // Tentative definition of global variables may be initialized with - // non-zero null pointers. In this case they should have weak linkage - // since common linkage must have zero initializer and must not have - // explicit section therefore cannot have non-zero initial value. - if (!GV->getInitializer()->isNullValue()) - GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage); - } - - setNonAliasAttributes(D, GV); - - if (D->getTLSKind() && !GV->isThreadLocal()) { - if (D->getTLSKind() == VarDecl::TLS_Dynamic) - CXXThreadLocals.push_back(D); - setTLSMode(GV, *D); - } - - maybeSetTrivialComdat(*D, *GV); - - // Emit the initializer function if necessary. - if (NeedsGlobalCtor || NeedsGlobalDtor) - EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor); - - SanitizerMD->reportGlobalToASan(GV, *D, NeedsGlobalCtor); - - // Emit global variable debug information. - if (CGDebugInfo *DI = getModuleDebugInfo()) - if (getCodeGenOpts().getDebugInfo() >= codegenoptions::LimitedDebugInfo) - DI->EmitGlobalVariable(GV, D); -} - -static bool isVarDeclStrongDefinition(const ASTContext &Context, - CodeGenModule &CGM, const VarDecl *D, - bool NoCommon) { - // Don't give variables common linkage if -fno-common was specified unless it - // was overridden by a NoCommon attribute. - if ((NoCommon || D->hasAttr<NoCommonAttr>()) && !D->hasAttr<CommonAttr>()) - return true; - - // C11 6.9.2/2: - // A declaration of an identifier for an object that has file scope without - // an initializer, and without a storage-class specifier or with the - // storage-class specifier static, constitutes a tentative definition. - if (D->getInit() || D->hasExternalStorage()) - return true; - - // A variable cannot be both common and exist in a section. - if (D->hasAttr<SectionAttr>()) - return true; - - // A variable cannot be both common and exist in a section. - // We don't try to determine which is the right section in the front-end. - // If no specialized section name is applicable, it will resort to default. - if (D->hasAttr<PragmaClangBSSSectionAttr>() || - D->hasAttr<PragmaClangDataSectionAttr>() || - D->hasAttr<PragmaClangRodataSectionAttr>()) - return true; - - // Thread local vars aren't considered common linkage. - if (D->getTLSKind()) - return true; - - // Tentative definitions marked with WeakImportAttr are true definitions. - if (D->hasAttr<WeakImportAttr>()) - return true; - - // A variable cannot be both common and exist in a comdat. - if (shouldBeInCOMDAT(CGM, *D)) - return true; - - // Declarations with a required alignment do not have common linkage in MSVC - // mode. - if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { - if (D->hasAttr<AlignedAttr>()) - return true; - QualType VarType = D->getType(); - if (Context.isAlignmentRequired(VarType)) - return true; - - if (const auto *RT = VarType->getAs<RecordType>()) { - const RecordDecl *RD = RT->getDecl(); - for (const FieldDecl *FD : RD->fields()) { - if (FD->isBitField()) - continue; - if (FD->hasAttr<AlignedAttr>()) - return true; - if (Context.isAlignmentRequired(FD->getType())) - return true; - } - } - } - - // Microsoft's link.exe doesn't support alignments greater than 32 bytes for - // common symbols, so symbols with greater alignment requirements cannot be - // common. - // Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two - // alignments for common symbols via the aligncomm directive, so this - // restriction only applies to MSVC environments. - if (Context.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() && - Context.getTypeAlignIfKnown(D->getType()) > - Context.toBits(CharUnits::fromQuantity(32))) - return true; - - return false; -} - -llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageForDeclarator( - const DeclaratorDecl *D, GVALinkage Linkage, bool IsConstantVariable) { - if (Linkage == GVA_Internal) - return llvm::Function::InternalLinkage; - - if (D->hasAttr<WeakAttr>()) { - if (IsConstantVariable) - return llvm::GlobalVariable::WeakODRLinkage; - else - return llvm::GlobalVariable::WeakAnyLinkage; - } - - if (const auto *FD = D->getAsFunction()) - if (FD->isMultiVersion() && Linkage == GVA_AvailableExternally) - return llvm::GlobalVariable::LinkOnceAnyLinkage; - - // We are guaranteed to have a strong definition somewhere else, - // so we can use available_externally linkage. - if (Linkage == GVA_AvailableExternally) - return llvm::GlobalValue::AvailableExternallyLinkage; - - // Note that Apple's kernel linker doesn't support symbol - // coalescing, so we need to avoid linkonce and weak linkages there. - // Normally, this means we just map to internal, but for explicit - // instantiations we'll map to external. - - // In C++, the compiler has to emit a definition in every translation unit - // that references the function. We should use linkonce_odr because - // a) if all references in this translation unit are optimized away, we - // don't need to codegen it. b) if the function persists, it needs to be - // merged with other definitions. c) C++ has the ODR, so we know the - // definition is dependable. - if (Linkage == GVA_DiscardableODR) - return !Context.getLangOpts().AppleKext ? llvm::Function::LinkOnceODRLinkage - : llvm::Function::InternalLinkage; - - // An explicit instantiation of a template has weak linkage, since - // explicit instantiations can occur in multiple translation units - // and must all be equivalent. However, we are not allowed to - // throw away these explicit instantiations. - // - // We don't currently support CUDA device code spread out across multiple TUs, - // so say that CUDA templates are either external (for kernels) or internal. - // This lets llvm perform aggressive inter-procedural optimizations. - if (Linkage == GVA_StrongODR) { - if (Context.getLangOpts().AppleKext) - return llvm::Function::ExternalLinkage; - if (Context.getLangOpts().CUDA && Context.getLangOpts().CUDAIsDevice) - return D->hasAttr<CUDAGlobalAttr>() ? llvm::Function::ExternalLinkage - : llvm::Function::InternalLinkage; - return llvm::Function::WeakODRLinkage; - } - - // C++ doesn't have tentative definitions and thus cannot have common - // linkage. - if (!getLangOpts().CPlusPlus && isa<VarDecl>(D) && - !isVarDeclStrongDefinition(Context, *this, cast<VarDecl>(D), - CodeGenOpts.NoCommon)) - return llvm::GlobalVariable::CommonLinkage; - - // selectany symbols are externally visible, so use weak instead of - // linkonce. MSVC optimizes away references to const selectany globals, so - // all definitions should be the same and ODR linkage should be used. - // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx - if (D->hasAttr<SelectAnyAttr>()) - return llvm::GlobalVariable::WeakODRLinkage; - - // Otherwise, we have strong external linkage. - assert(Linkage == GVA_StrongExternal); - return llvm::GlobalVariable::ExternalLinkage; -} - -llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageVarDefinition( - const VarDecl *VD, bool IsConstant) { - GVALinkage Linkage = getContext().GetGVALinkageForVariable(VD); - return getLLVMLinkageForDeclarator(VD, Linkage, IsConstant); -} - -/// Replace the uses of a function that was declared with a non-proto type. -/// We want to silently drop extra arguments from call sites -static void replaceUsesOfNonProtoConstant(llvm::Constant *old, - llvm::Function *newFn) { - // Fast path. - if (old->use_empty()) return; - - llvm::Type *newRetTy = newFn->getReturnType(); - SmallVector<llvm::Value*, 4> newArgs; - SmallVector<llvm::OperandBundleDef, 1> newBundles; - - for (llvm::Value::use_iterator ui = old->use_begin(), ue = old->use_end(); - ui != ue; ) { - llvm::Value::use_iterator use = ui++; // Increment before the use is erased. - llvm::User *user = use->getUser(); - - // Recognize and replace uses of bitcasts. Most calls to - // unprototyped functions will use bitcasts. - if (auto *bitcast = dyn_cast<llvm::ConstantExpr>(user)) { - if (bitcast->getOpcode() == llvm::Instruction::BitCast) - replaceUsesOfNonProtoConstant(bitcast, newFn); - continue; - } - - // Recognize calls to the function. - llvm::CallSite callSite(user); - if (!callSite) continue; - if (!callSite.isCallee(&*use)) continue; - - // If the return types don't match exactly, then we can't - // transform this call unless it's dead. - if (callSite->getType() != newRetTy && !callSite->use_empty()) - continue; - - // Get the call site's attribute list. - SmallVector<llvm::AttributeSet, 8> newArgAttrs; - llvm::AttributeList oldAttrs = callSite.getAttributes(); - - // If the function was passed too few arguments, don't transform. - unsigned newNumArgs = newFn->arg_size(); - if (callSite.arg_size() < newNumArgs) continue; - - // If extra arguments were passed, we silently drop them. - // If any of the types mismatch, we don't transform. - unsigned argNo = 0; - bool dontTransform = false; - for (llvm::Argument &A : newFn->args()) { - if (callSite.getArgument(argNo)->getType() != A.getType()) { - dontTransform = true; - break; - } - - // Add any parameter attributes. - newArgAttrs.push_back(oldAttrs.getParamAttributes(argNo)); - argNo++; - } - if (dontTransform) - continue; - - // Okay, we can transform this. Create the new call instruction and copy - // over the required information. - newArgs.append(callSite.arg_begin(), callSite.arg_begin() + argNo); - - // Copy over any operand bundles. - callSite.getOperandBundlesAsDefs(newBundles); - - llvm::CallSite newCall; - if (callSite.isCall()) { - newCall = llvm::CallInst::Create(newFn, newArgs, newBundles, "", - callSite.getInstruction()); - } else { - auto *oldInvoke = cast<llvm::InvokeInst>(callSite.getInstruction()); - newCall = llvm::InvokeInst::Create(newFn, - oldInvoke->getNormalDest(), - oldInvoke->getUnwindDest(), - newArgs, newBundles, "", - callSite.getInstruction()); - } - newArgs.clear(); // for the next iteration - - if (!newCall->getType()->isVoidTy()) - newCall->takeName(callSite.getInstruction()); - newCall.setAttributes(llvm::AttributeList::get( - newFn->getContext(), oldAttrs.getFnAttributes(), - oldAttrs.getRetAttributes(), newArgAttrs)); - newCall.setCallingConv(callSite.getCallingConv()); - - // Finally, remove the old call, replacing any uses with the new one. - if (!callSite->use_empty()) - callSite->replaceAllUsesWith(newCall.getInstruction()); - - // Copy debug location attached to CI. - if (callSite->getDebugLoc()) - newCall->setDebugLoc(callSite->getDebugLoc()); - - callSite->eraseFromParent(); - } -} - -/// ReplaceUsesOfNonProtoTypeWithRealFunction - This function is called when we -/// implement a function with no prototype, e.g. "int foo() {}". If there are -/// existing call uses of the old function in the module, this adjusts them to -/// call the new function directly. -/// -/// This is not just a cleanup: the always_inline pass requires direct calls to -/// functions to be able to inline them. If there is a bitcast in the way, it -/// won't inline them. Instcombine normally deletes these calls, but it isn't -/// run at -O0. -static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, - llvm::Function *NewFn) { - // If we're redefining a global as a function, don't transform it. - if (!isa<llvm::Function>(Old)) return; - - replaceUsesOfNonProtoConstant(Old, NewFn); -} - -void CodeGenModule::HandleCXXStaticMemberVarInstantiation(VarDecl *VD) { - auto DK = VD->isThisDeclarationADefinition(); - if (DK == VarDecl::Definition && VD->hasAttr<DLLImportAttr>()) - return; - - TemplateSpecializationKind TSK = VD->getTemplateSpecializationKind(); - // If we have a definition, this might be a deferred decl. If the - // instantiation is explicit, make sure we emit it at the end. - if (VD->getDefinition() && TSK == TSK_ExplicitInstantiationDefinition) - GetAddrOfGlobalVar(VD); - - EmitTopLevelDecl(VD); -} - -void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD, - llvm::GlobalValue *GV) { - const auto *D = cast<FunctionDecl>(GD.getDecl()); - - // Compute the function info and LLVM type. - const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD); - llvm::FunctionType *Ty = getTypes().GetFunctionType(FI); - - // Get or create the prototype for the function. - if (!GV || (GV->getType()->getElementType() != Ty)) - GV = cast<llvm::GlobalValue>(GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, - /*DontDefer=*/true, - ForDefinition)); - - // Already emitted. - if (!GV->isDeclaration()) - return; - - // We need to set linkage and visibility on the function before - // generating code for it because various parts of IR generation - // want to propagate this information down (e.g. to local static - // declarations). - auto *Fn = cast<llvm::Function>(GV); - setFunctionLinkage(GD, Fn); - - // FIXME: this is redundant with part of setFunctionDefinitionAttributes - setGVProperties(Fn, GD); - - MaybeHandleStaticInExternC(D, Fn); - - - maybeSetTrivialComdat(*D, *Fn); - - CodeGenFunction(*this).GenerateCode(D, Fn, FI); - - setNonAliasAttributes(GD, Fn); - SetLLVMFunctionAttributesForDefinition(D, Fn); - - if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>()) - AddGlobalCtor(Fn, CA->getPriority()); - if (const DestructorAttr *DA = D->getAttr<DestructorAttr>()) - AddGlobalDtor(Fn, DA->getPriority()); - if (D->hasAttr<AnnotateAttr>()) - AddGlobalAnnotations(D, Fn); -} - -void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) { - const auto *D = cast<ValueDecl>(GD.getDecl()); - const AliasAttr *AA = D->getAttr<AliasAttr>(); - assert(AA && "Not an alias?"); - - StringRef MangledName = getMangledName(GD); - - if (AA->getAliasee() == MangledName) { - Diags.Report(AA->getLocation(), diag::err_cyclic_alias) << 0; - return; - } - - // If there is a definition in the module, then it wins over the alias. - // This is dubious, but allow it to be safe. Just ignore the alias. - llvm::GlobalValue *Entry = GetGlobalValue(MangledName); - if (Entry && !Entry->isDeclaration()) - return; - - Aliases.push_back(GD); - - llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType()); - - // Create a reference to the named value. This ensures that it is emitted - // if a deferred decl. - llvm::Constant *Aliasee; - if (isa<llvm::FunctionType>(DeclTy)) - Aliasee = GetOrCreateLLVMFunction(AA->getAliasee(), DeclTy, GD, - /*ForVTable=*/false); - else - Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(), - llvm::PointerType::getUnqual(DeclTy), - /*D=*/nullptr); - - // Create the new alias itself, but don't set a name yet. - auto *GA = llvm::GlobalAlias::create( - DeclTy, 0, llvm::Function::ExternalLinkage, "", Aliasee, &getModule()); - - if (Entry) { - if (GA->getAliasee() == Entry) { - Diags.Report(AA->getLocation(), diag::err_cyclic_alias) << 0; - return; - } - - assert(Entry->isDeclaration()); - - // If there is a declaration in the module, then we had an extern followed - // by the alias, as in: - // extern int test6(); - // ... - // int test6() __attribute__((alias("test7"))); - // - // Remove it and replace uses of it with the alias. - GA->takeName(Entry); - - Entry->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(GA, - Entry->getType())); - Entry->eraseFromParent(); - } else { - GA->setName(MangledName); - } - - // Set attributes which are particular to an alias; this is a - // specialization of the attributes which may be set on a global - // variable/function. - if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakRefAttr>() || - D->isWeakImported()) { - GA->setLinkage(llvm::Function::WeakAnyLinkage); - } - - if (const auto *VD = dyn_cast<VarDecl>(D)) - if (VD->getTLSKind()) - setTLSMode(GA, *VD); - - SetCommonAttributes(GD, GA); -} - -void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) { - const auto *D = cast<ValueDecl>(GD.getDecl()); - const IFuncAttr *IFA = D->getAttr<IFuncAttr>(); - assert(IFA && "Not an ifunc?"); - - StringRef MangledName = getMangledName(GD); - - if (IFA->getResolver() == MangledName) { - Diags.Report(IFA->getLocation(), diag::err_cyclic_alias) << 1; - return; - } - - // Report an error if some definition overrides ifunc. - llvm::GlobalValue *Entry = GetGlobalValue(MangledName); - if (Entry && !Entry->isDeclaration()) { - GlobalDecl OtherGD; - if (lookupRepresentativeDecl(MangledName, OtherGD) && - DiagnosedConflictingDefinitions.insert(GD).second) { - Diags.Report(D->getLocation(), diag::err_duplicate_mangled_name) - << MangledName; - Diags.Report(OtherGD.getDecl()->getLocation(), - diag::note_previous_definition); - } - return; - } - - Aliases.push_back(GD); - - llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType()); - llvm::Constant *Resolver = - GetOrCreateLLVMFunction(IFA->getResolver(), DeclTy, GD, - /*ForVTable=*/false); - llvm::GlobalIFunc *GIF = - llvm::GlobalIFunc::create(DeclTy, 0, llvm::Function::ExternalLinkage, - "", Resolver, &getModule()); - if (Entry) { - if (GIF->getResolver() == Entry) { - Diags.Report(IFA->getLocation(), diag::err_cyclic_alias) << 1; - return; - } - assert(Entry->isDeclaration()); - - // If there is a declaration in the module, then we had an extern followed - // by the ifunc, as in: - // extern int test(); - // ... - // int test() __attribute__((ifunc("resolver"))); - // - // Remove it and replace uses of it with the ifunc. - GIF->takeName(Entry); - - Entry->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(GIF, - Entry->getType())); - Entry->eraseFromParent(); - } else - GIF->setName(MangledName); - - SetCommonAttributes(GD, GIF); -} - -llvm::Function *CodeGenModule::getIntrinsic(unsigned IID, - ArrayRef<llvm::Type*> Tys) { - return llvm::Intrinsic::getDeclaration(&getModule(), (llvm::Intrinsic::ID)IID, - Tys); -} - -static llvm::StringMapEntry<llvm::GlobalVariable *> & -GetConstantCFStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map, - const StringLiteral *Literal, bool TargetIsLSB, - bool &IsUTF16, unsigned &StringLength) { - StringRef String = Literal->getString(); - unsigned NumBytes = String.size(); - - // Check for simple case. - if (!Literal->containsNonAsciiOrNull()) { - StringLength = NumBytes; - return *Map.insert(std::make_pair(String, nullptr)).first; - } - - // Otherwise, convert the UTF8 literals into a string of shorts. - IsUTF16 = true; - - SmallVector<llvm::UTF16, 128> ToBuf(NumBytes + 1); // +1 for ending nulls. - const llvm::UTF8 *FromPtr = (const llvm::UTF8 *)String.data(); - llvm::UTF16 *ToPtr = &ToBuf[0]; - - (void)llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes, &ToPtr, - ToPtr + NumBytes, llvm::strictConversion); - - // ConvertUTF8toUTF16 returns the length in ToPtr. - StringLength = ToPtr - &ToBuf[0]; - - // Add an explicit null. - *ToPtr = 0; - return *Map.insert(std::make_pair( - StringRef(reinterpret_cast<const char *>(ToBuf.data()), - (StringLength + 1) * 2), - nullptr)).first; -} - -ConstantAddress -CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { - unsigned StringLength = 0; - bool isUTF16 = false; - llvm::StringMapEntry<llvm::GlobalVariable *> &Entry = - GetConstantCFStringEntry(CFConstantStringMap, Literal, - getDataLayout().isLittleEndian(), isUTF16, - StringLength); - - if (auto *C = Entry.second) - return ConstantAddress(C, CharUnits::fromQuantity(C->getAlignment())); - - llvm::Constant *Zero = llvm::Constant::getNullValue(Int32Ty); - llvm::Constant *Zeros[] = { Zero, Zero }; - - const ASTContext &Context = getContext(); - const llvm::Triple &Triple = getTriple(); - - const auto CFRuntime = getLangOpts().CFRuntime; - const bool IsSwiftABI = - static_cast<unsigned>(CFRuntime) >= - static_cast<unsigned>(LangOptions::CoreFoundationABI::Swift); - const bool IsSwift4_1 = CFRuntime == LangOptions::CoreFoundationABI::Swift4_1; - - // If we don't already have it, get __CFConstantStringClassReference. - if (!CFConstantStringClassRef) { - const char *CFConstantStringClassName = "__CFConstantStringClassReference"; - llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy); - Ty = llvm::ArrayType::get(Ty, 0); - - switch (CFRuntime) { - default: break; - case LangOptions::CoreFoundationABI::Swift: LLVM_FALLTHROUGH; - case LangOptions::CoreFoundationABI::Swift5_0: - CFConstantStringClassName = - Triple.isOSDarwin() ? "$s15SwiftFoundation19_NSCFConstantStringCN" - : "$s10Foundation19_NSCFConstantStringCN"; - Ty = IntPtrTy; - break; - case LangOptions::CoreFoundationABI::Swift4_2: - CFConstantStringClassName = - Triple.isOSDarwin() ? "$S15SwiftFoundation19_NSCFConstantStringCN" - : "$S10Foundation19_NSCFConstantStringCN"; - Ty = IntPtrTy; - break; - case LangOptions::CoreFoundationABI::Swift4_1: - CFConstantStringClassName = - Triple.isOSDarwin() ? "__T015SwiftFoundation19_NSCFConstantStringCN" - : "__T010Foundation19_NSCFConstantStringCN"; - Ty = IntPtrTy; - break; - } - - llvm::Constant *C = CreateRuntimeVariable(Ty, CFConstantStringClassName); - - if (Triple.isOSBinFormatELF() || Triple.isOSBinFormatCOFF()) { - llvm::GlobalValue *GV = nullptr; - - if ((GV = dyn_cast<llvm::GlobalValue>(C))) { - IdentifierInfo &II = Context.Idents.get(GV->getName()); - TranslationUnitDecl *TUDecl = Context.getTranslationUnitDecl(); - DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl); - - const VarDecl *VD = nullptr; - for (const auto &Result : DC->lookup(&II)) - if ((VD = dyn_cast<VarDecl>(Result))) - break; - - if (Triple.isOSBinFormatELF()) { - if (!VD) - GV->setLinkage(llvm::GlobalValue::ExternalLinkage); - } else { - GV->setLinkage(llvm::GlobalValue::ExternalLinkage); - if (!VD || !VD->hasAttr<DLLExportAttr>()) - GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); - else - GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); - } - - setDSOLocal(GV); - } - } - - // Decay array -> ptr - CFConstantStringClassRef = - IsSwiftABI ? llvm::ConstantExpr::getPtrToInt(C, Ty) - : llvm::ConstantExpr::getGetElementPtr(Ty, C, Zeros); - } - - QualType CFTy = Context.getCFConstantStringType(); - - auto *STy = cast<llvm::StructType>(getTypes().ConvertType(CFTy)); - - ConstantInitBuilder Builder(*this); - auto Fields = Builder.beginStruct(STy); - - // Class pointer. - Fields.add(cast<llvm::ConstantExpr>(CFConstantStringClassRef)); - - // Flags. - if (IsSwiftABI) { - Fields.addInt(IntPtrTy, IsSwift4_1 ? 0x05 : 0x01); - Fields.addInt(Int64Ty, isUTF16 ? 0x07d0 : 0x07c8); - } else { - Fields.addInt(IntTy, isUTF16 ? 0x07d0 : 0x07C8); - } - - // String pointer. - llvm::Constant *C = nullptr; - if (isUTF16) { - auto Arr = llvm::makeArrayRef( - reinterpret_cast<uint16_t *>(const_cast<char *>(Entry.first().data())), - Entry.first().size() / 2); - C = llvm::ConstantDataArray::get(VMContext, Arr); - } else { - C = llvm::ConstantDataArray::getString(VMContext, Entry.first()); - } - - // Note: -fwritable-strings doesn't make the backing store strings of - // CFStrings writable. (See <rdar://problem/10657500>) - auto *GV = - new llvm::GlobalVariable(getModule(), C->getType(), /*isConstant=*/true, - llvm::GlobalValue::PrivateLinkage, C, ".str"); - GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - // Don't enforce the target's minimum global alignment, since the only use - // of the string is via this class initializer. - CharUnits Align = isUTF16 ? Context.getTypeAlignInChars(Context.ShortTy) - : Context.getTypeAlignInChars(Context.CharTy); - GV->setAlignment(Align.getQuantity()); - - // FIXME: We set the section explicitly to avoid a bug in ld64 224.1. - // Without it LLVM can merge the string with a non unnamed_addr one during - // LTO. Doing that changes the section it ends in, which surprises ld64. - if (Triple.isOSBinFormatMachO()) - GV->setSection(isUTF16 ? "__TEXT,__ustring" - : "__TEXT,__cstring,cstring_literals"); - // Make sure the literal ends up in .rodata to allow for safe ICF and for - // the static linker to adjust permissions to read-only later on. - else if (Triple.isOSBinFormatELF()) - GV->setSection(".rodata"); - - // String. - llvm::Constant *Str = - llvm::ConstantExpr::getGetElementPtr(GV->getValueType(), GV, Zeros); - - if (isUTF16) - // Cast the UTF16 string to the correct type. - Str = llvm::ConstantExpr::getBitCast(Str, Int8PtrTy); - Fields.add(Str); - - // String length. - llvm::IntegerType *LengthTy = - llvm::IntegerType::get(getModule().getContext(), - Context.getTargetInfo().getLongWidth()); - if (IsSwiftABI) { - if (CFRuntime == LangOptions::CoreFoundationABI::Swift4_1 || - CFRuntime == LangOptions::CoreFoundationABI::Swift4_2) - LengthTy = Int32Ty; - else - LengthTy = IntPtrTy; - } - Fields.addInt(LengthTy, StringLength); - - CharUnits Alignment = getPointerAlign(); - - // The struct. - GV = Fields.finishAndCreateGlobal("_unnamed_cfstring_", Alignment, - /*isConstant=*/false, - llvm::GlobalVariable::PrivateLinkage); - switch (Triple.getObjectFormat()) { - case llvm::Triple::UnknownObjectFormat: - llvm_unreachable("unknown file format"); - case llvm::Triple::COFF: - case llvm::Triple::ELF: - case llvm::Triple::Wasm: - GV->setSection("cfstring"); - break; - case llvm::Triple::MachO: - GV->setSection("__DATA,__cfstring"); - break; - } - Entry.second = GV; - - return ConstantAddress(GV, Alignment); -} - -bool CodeGenModule::getExpressionLocationsEnabled() const { - return !CodeGenOpts.EmitCodeView || CodeGenOpts.DebugColumnInfo; -} - -QualType CodeGenModule::getObjCFastEnumerationStateType() { - if (ObjCFastEnumerationStateType.isNull()) { - RecordDecl *D = Context.buildImplicitRecord("__objcFastEnumerationState"); - D->startDefinition(); - - QualType FieldTypes[] = { - Context.UnsignedLongTy, - Context.getPointerType(Context.getObjCIdType()), - Context.getPointerType(Context.UnsignedLongTy), - Context.getConstantArrayType(Context.UnsignedLongTy, - llvm::APInt(32, 5), ArrayType::Normal, 0) - }; - - for (size_t i = 0; i < 4; ++i) { - FieldDecl *Field = FieldDecl::Create(Context, - D, - SourceLocation(), - SourceLocation(), nullptr, - FieldTypes[i], /*TInfo=*/nullptr, - /*BitWidth=*/nullptr, - /*Mutable=*/false, - ICIS_NoInit); - Field->setAccess(AS_public); - D->addDecl(Field); - } - - D->completeDefinition(); - ObjCFastEnumerationStateType = Context.getTagDeclType(D); - } - - return ObjCFastEnumerationStateType; -} - -llvm::Constant * -CodeGenModule::GetConstantArrayFromStringLiteral(const StringLiteral *E) { - assert(!E->getType()->isPointerType() && "Strings are always arrays"); - - // Don't emit it as the address of the string, emit the string data itself - // as an inline array. - if (E->getCharByteWidth() == 1) { - SmallString<64> Str(E->getString()); - - // Resize the string to the right size, which is indicated by its type. - const ConstantArrayType *CAT = Context.getAsConstantArrayType(E->getType()); - Str.resize(CAT->getSize().getZExtValue()); - return llvm::ConstantDataArray::getString(VMContext, Str, false); - } - - auto *AType = cast<llvm::ArrayType>(getTypes().ConvertType(E->getType())); - llvm::Type *ElemTy = AType->getElementType(); - unsigned NumElements = AType->getNumElements(); - - // Wide strings have either 2-byte or 4-byte elements. - if (ElemTy->getPrimitiveSizeInBits() == 16) { - SmallVector<uint16_t, 32> Elements; - Elements.reserve(NumElements); - - for(unsigned i = 0, e = E->getLength(); i != e; ++i) - Elements.push_back(E->getCodeUnit(i)); - Elements.resize(NumElements); - return llvm::ConstantDataArray::get(VMContext, Elements); - } - - assert(ElemTy->getPrimitiveSizeInBits() == 32); - SmallVector<uint32_t, 32> Elements; - Elements.reserve(NumElements); - - for(unsigned i = 0, e = E->getLength(); i != e; ++i) - Elements.push_back(E->getCodeUnit(i)); - Elements.resize(NumElements); - return llvm::ConstantDataArray::get(VMContext, Elements); -} - -static llvm::GlobalVariable * -GenerateStringLiteral(llvm::Constant *C, llvm::GlobalValue::LinkageTypes LT, - CodeGenModule &CGM, StringRef GlobalName, - CharUnits Alignment) { - unsigned AddrSpace = CGM.getContext().getTargetAddressSpace( - CGM.getStringLiteralAddressSpace()); - - llvm::Module &M = CGM.getModule(); - // Create a global variable for this string - auto *GV = new llvm::GlobalVariable( - M, C->getType(), !CGM.getLangOpts().WritableStrings, LT, C, GlobalName, - nullptr, llvm::GlobalVariable::NotThreadLocal, AddrSpace); - GV->setAlignment(Alignment.getQuantity()); - GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - if (GV->isWeakForLinker()) { - assert(CGM.supportsCOMDAT() && "Only COFF uses weak string literals"); - GV->setComdat(M.getOrInsertComdat(GV->getName())); - } - CGM.setDSOLocal(GV); - - return GV; -} - -/// GetAddrOfConstantStringFromLiteral - Return a pointer to a -/// constant array for the given string literal. -ConstantAddress -CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S, - StringRef Name) { - CharUnits Alignment = getContext().getAlignOfGlobalVarInChars(S->getType()); - - llvm::Constant *C = GetConstantArrayFromStringLiteral(S); - llvm::GlobalVariable **Entry = nullptr; - if (!LangOpts.WritableStrings) { - Entry = &ConstantStringMap[C]; - if (auto GV = *Entry) { - if (Alignment.getQuantity() > GV->getAlignment()) - GV->setAlignment(Alignment.getQuantity()); - return ConstantAddress(GV, Alignment); - } - } - - SmallString<256> MangledNameBuffer; - StringRef GlobalVariableName; - llvm::GlobalValue::LinkageTypes LT; - - // Mangle the string literal if that's how the ABI merges duplicate strings. - // Don't do it if they are writable, since we don't want writes in one TU to - // affect strings in another. - if (getCXXABI().getMangleContext().shouldMangleStringLiteral(S) && - !LangOpts.WritableStrings) { - llvm::raw_svector_ostream Out(MangledNameBuffer); - getCXXABI().getMangleContext().mangleStringLiteral(S, Out); - LT = llvm::GlobalValue::LinkOnceODRLinkage; - GlobalVariableName = MangledNameBuffer; - } else { - LT = llvm::GlobalValue::PrivateLinkage; - GlobalVariableName = Name; - } - - auto GV = GenerateStringLiteral(C, LT, *this, GlobalVariableName, Alignment); - if (Entry) - *Entry = GV; - - SanitizerMD->reportGlobalToASan(GV, S->getStrTokenLoc(0), "<string literal>", - QualType()); - - return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV), - Alignment); -} - -/// GetAddrOfConstantStringFromObjCEncode - Return a pointer to a constant -/// array for the given ObjCEncodeExpr node. -ConstantAddress -CodeGenModule::GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *E) { - std::string Str; - getContext().getObjCEncodingForType(E->getEncodedType(), Str); - - return GetAddrOfConstantCString(Str); -} - -/// GetAddrOfConstantCString - Returns a pointer to a character array containing -/// the literal and a terminating '\0' character. -/// The result has pointer to array type. -ConstantAddress CodeGenModule::GetAddrOfConstantCString( - const std::string &Str, const char *GlobalName) { - StringRef StrWithNull(Str.c_str(), Str.size() + 1); - CharUnits Alignment = - getContext().getAlignOfGlobalVarInChars(getContext().CharTy); - - llvm::Constant *C = - llvm::ConstantDataArray::getString(getLLVMContext(), StrWithNull, false); - - // Don't share any string literals if strings aren't constant. - llvm::GlobalVariable **Entry = nullptr; - if (!LangOpts.WritableStrings) { - Entry = &ConstantStringMap[C]; - if (auto GV = *Entry) { - if (Alignment.getQuantity() > GV->getAlignment()) - GV->setAlignment(Alignment.getQuantity()); - return ConstantAddress(GV, Alignment); - } - } - - // Get the default prefix if a name wasn't specified. - if (!GlobalName) - GlobalName = ".str"; - // Create a global variable for this. - auto GV = GenerateStringLiteral(C, llvm::GlobalValue::PrivateLinkage, *this, - GlobalName, Alignment); - if (Entry) - *Entry = GV; - - return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV), - Alignment); -} - -ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( - const MaterializeTemporaryExpr *E, const Expr *Init) { - assert((E->getStorageDuration() == SD_Static || - E->getStorageDuration() == SD_Thread) && "not a global temporary"); - const auto *VD = cast<VarDecl>(E->getExtendingDecl()); - - // If we're not materializing a subobject of the temporary, keep the - // cv-qualifiers from the type of the MaterializeTemporaryExpr. - QualType MaterializedType = Init->getType(); - if (Init == E->GetTemporaryExpr()) - MaterializedType = E->getType(); - - CharUnits Align = getContext().getTypeAlignInChars(MaterializedType); - - if (llvm::Constant *Slot = MaterializedGlobalTemporaryMap[E]) - return ConstantAddress(Slot, Align); - - // FIXME: If an externally-visible declaration extends multiple temporaries, - // we need to give each temporary the same name in every translation unit (and - // we also need to make the temporaries externally-visible). - SmallString<256> Name; - llvm::raw_svector_ostream Out(Name); - getCXXABI().getMangleContext().mangleReferenceTemporary( - VD, E->getManglingNumber(), Out); - - APValue *Value = nullptr; - if (E->getStorageDuration() == SD_Static) { - // We might have a cached constant initializer for this temporary. Note - // that this might have a different value from the value computed by - // evaluating the initializer if the surrounding constant expression - // modifies the temporary. - Value = getContext().getMaterializedTemporaryValue(E, false); - if (Value && Value->isUninit()) - Value = nullptr; - } - - // Try evaluating it now, it might have a constant initializer. - Expr::EvalResult EvalResult; - if (!Value && Init->EvaluateAsRValue(EvalResult, getContext()) && - !EvalResult.hasSideEffects()) - Value = &EvalResult.Val; - - LangAS AddrSpace = - VD ? GetGlobalVarAddressSpace(VD) : MaterializedType.getAddressSpace(); - - Optional<ConstantEmitter> emitter; - llvm::Constant *InitialValue = nullptr; - bool Constant = false; - llvm::Type *Type; - if (Value) { - // The temporary has a constant initializer, use it. - emitter.emplace(*this); - InitialValue = emitter->emitForInitializer(*Value, AddrSpace, - MaterializedType); - Constant = isTypeConstant(MaterializedType, /*ExcludeCtor*/Value); - Type = InitialValue->getType(); - } else { - // No initializer, the initialization will be provided when we - // initialize the declaration which performed lifetime extension. - Type = getTypes().ConvertTypeForMem(MaterializedType); - } - - // Create a global variable for this lifetime-extended temporary. - llvm::GlobalValue::LinkageTypes Linkage = - getLLVMLinkageVarDefinition(VD, Constant); - if (Linkage == llvm::GlobalVariable::ExternalLinkage) { - const VarDecl *InitVD; - if (VD->isStaticDataMember() && VD->getAnyInitializer(InitVD) && - isa<CXXRecordDecl>(InitVD->getLexicalDeclContext())) { - // Temporaries defined inside a class get linkonce_odr linkage because the - // class can be defined in multiple translation units. - Linkage = llvm::GlobalVariable::LinkOnceODRLinkage; - } else { - // There is no need for this temporary to have external linkage if the - // VarDecl has external linkage. - Linkage = llvm::GlobalVariable::InternalLinkage; - } - } - auto TargetAS = getContext().getTargetAddressSpace(AddrSpace); - auto *GV = new llvm::GlobalVariable( - getModule(), Type, Constant, Linkage, InitialValue, Name.c_str(), - /*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS); - if (emitter) emitter->finalize(GV); - setGVProperties(GV, VD); - GV->setAlignment(Align.getQuantity()); - if (supportsCOMDAT() && GV->isWeakForLinker()) - GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); - if (VD->getTLSKind()) - setTLSMode(GV, *VD); - llvm::Constant *CV = GV; - if (AddrSpace != LangAS::Default) - CV = getTargetCodeGenInfo().performAddrSpaceCast( - *this, GV, AddrSpace, LangAS::Default, - Type->getPointerTo( - getContext().getTargetAddressSpace(LangAS::Default))); - MaterializedGlobalTemporaryMap[E] = CV; - return ConstantAddress(CV, Align); -} - -/// EmitObjCPropertyImplementations - Emit information for synthesized -/// properties for an implementation. -void CodeGenModule::EmitObjCPropertyImplementations(const - ObjCImplementationDecl *D) { - for (const auto *PID : D->property_impls()) { - // Dynamic is just for type-checking. - if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) { - ObjCPropertyDecl *PD = PID->getPropertyDecl(); - - // Determine which methods need to be implemented, some may have - // been overridden. Note that ::isPropertyAccessor is not the method - // we want, that just indicates if the decl came from a - // property. What we want to know is if the method is defined in - // this implementation. - if (!D->getInstanceMethod(PD->getGetterName())) - CodeGenFunction(*this).GenerateObjCGetter( - const_cast<ObjCImplementationDecl *>(D), PID); - if (!PD->isReadOnly() && - !D->getInstanceMethod(PD->getSetterName())) - CodeGenFunction(*this).GenerateObjCSetter( - const_cast<ObjCImplementationDecl *>(D), PID); - } - } -} - -static bool needsDestructMethod(ObjCImplementationDecl *impl) { - const ObjCInterfaceDecl *iface = impl->getClassInterface(); - for (const ObjCIvarDecl *ivar = iface->all_declared_ivar_begin(); - ivar; ivar = ivar->getNextIvar()) - if (ivar->getType().isDestructedType()) - return true; - - return false; -} - -static bool AllTrivialInitializers(CodeGenModule &CGM, - ObjCImplementationDecl *D) { - CodeGenFunction CGF(CGM); - for (ObjCImplementationDecl::init_iterator B = D->init_begin(), - E = D->init_end(); B != E; ++B) { - CXXCtorInitializer *CtorInitExp = *B; - Expr *Init = CtorInitExp->getInit(); - if (!CGF.isTrivialInitializer(Init)) - return false; - } - return true; -} - -/// EmitObjCIvarInitializations - Emit information for ivar initialization -/// for an implementation. -void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) { - // We might need a .cxx_destruct even if we don't have any ivar initializers. - if (needsDestructMethod(D)) { - IdentifierInfo *II = &getContext().Idents.get(".cxx_destruct"); - Selector cxxSelector = getContext().Selectors.getSelector(0, &II); - ObjCMethodDecl *DTORMethod = - ObjCMethodDecl::Create(getContext(), D->getLocation(), D->getLocation(), - cxxSelector, getContext().VoidTy, nullptr, D, - /*isInstance=*/true, /*isVariadic=*/false, - /*isPropertyAccessor=*/true, /*isImplicitlyDeclared=*/true, - /*isDefined=*/false, ObjCMethodDecl::Required); - D->addInstanceMethod(DTORMethod); - CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, DTORMethod, false); - D->setHasDestructors(true); - } - - // If the implementation doesn't have any ivar initializers, we don't need - // a .cxx_construct. - if (D->getNumIvarInitializers() == 0 || - AllTrivialInitializers(*this, D)) - return; - - IdentifierInfo *II = &getContext().Idents.get(".cxx_construct"); - Selector cxxSelector = getContext().Selectors.getSelector(0, &II); - // The constructor returns 'self'. - ObjCMethodDecl *CTORMethod = ObjCMethodDecl::Create(getContext(), - D->getLocation(), - D->getLocation(), - cxxSelector, - getContext().getObjCIdType(), - nullptr, D, /*isInstance=*/true, - /*isVariadic=*/false, - /*isPropertyAccessor=*/true, - /*isImplicitlyDeclared=*/true, - /*isDefined=*/false, - ObjCMethodDecl::Required); - D->addInstanceMethod(CTORMethod); - CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true); - D->setHasNonZeroConstructors(true); -} - -// EmitLinkageSpec - Emit all declarations in a linkage spec. -void CodeGenModule::EmitLinkageSpec(const LinkageSpecDecl *LSD) { - if (LSD->getLanguage() != LinkageSpecDecl::lang_c && - LSD->getLanguage() != LinkageSpecDecl::lang_cxx) { - ErrorUnsupported(LSD, "linkage spec"); - return; - } - - EmitDeclContext(LSD); -} - -void CodeGenModule::EmitDeclContext(const DeclContext *DC) { - for (auto *I : DC->decls()) { - // Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope - // are themselves considered "top-level", so EmitTopLevelDecl on an - // ObjCImplDecl does not recursively visit them. We need to do that in - // case they're nested inside another construct (LinkageSpecDecl / - // ExportDecl) that does stop them from being considered "top-level". - if (auto *OID = dyn_cast<ObjCImplDecl>(I)) { - for (auto *M : OID->methods()) - EmitTopLevelDecl(M); - } - - EmitTopLevelDecl(I); - } -} - -/// EmitTopLevelDecl - Emit code for a single top level declaration. -void CodeGenModule::EmitTopLevelDecl(Decl *D) { - // Ignore dependent declarations. - if (D->isTemplated()) - return; - - switch (D->getKind()) { - case Decl::CXXConversion: - case Decl::CXXMethod: - case Decl::Function: - EmitGlobal(cast<FunctionDecl>(D)); - // Always provide some coverage mapping - // even for the functions that aren't emitted. - AddDeferredUnusedCoverageMapping(D); - break; - - case Decl::CXXDeductionGuide: - // Function-like, but does not result in code emission. - break; - - case Decl::Var: - case Decl::Decomposition: - case Decl::VarTemplateSpecialization: - EmitGlobal(cast<VarDecl>(D)); - if (auto *DD = dyn_cast<DecompositionDecl>(D)) - for (auto *B : DD->bindings()) - if (auto *HD = B->getHoldingVar()) - EmitGlobal(HD); - break; - - // Indirect fields from global anonymous structs and unions can be - // ignored; only the actual variable requires IR gen support. - case Decl::IndirectField: - break; - - // C++ Decls - case Decl::Namespace: - EmitDeclContext(cast<NamespaceDecl>(D)); - break; - case Decl::ClassTemplateSpecialization: { - const auto *Spec = cast<ClassTemplateSpecializationDecl>(D); - if (DebugInfo && - Spec->getSpecializationKind() == TSK_ExplicitInstantiationDefinition && - Spec->hasDefinition()) - DebugInfo->completeTemplateDefinition(*Spec); - } LLVM_FALLTHROUGH; - case Decl::CXXRecord: - if (DebugInfo) { - if (auto *ES = D->getASTContext().getExternalSource()) - if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never) - DebugInfo->completeUnusedClass(cast<CXXRecordDecl>(*D)); - } - // Emit any static data members, they may be definitions. - for (auto *I : cast<CXXRecordDecl>(D)->decls()) - if (isa<VarDecl>(I) || isa<CXXRecordDecl>(I)) - EmitTopLevelDecl(I); - break; - // No code generation needed. - case Decl::UsingShadow: - case Decl::ClassTemplate: - case Decl::VarTemplate: - case Decl::VarTemplatePartialSpecialization: - case Decl::FunctionTemplate: - case Decl::TypeAliasTemplate: - case Decl::Block: - case Decl::Empty: - case Decl::Binding: - break; - case Decl::Using: // using X; [C++] - if (CGDebugInfo *DI = getModuleDebugInfo()) - DI->EmitUsingDecl(cast<UsingDecl>(*D)); - return; - case Decl::NamespaceAlias: - if (CGDebugInfo *DI = getModuleDebugInfo()) - DI->EmitNamespaceAlias(cast<NamespaceAliasDecl>(*D)); - return; - case Decl::UsingDirective: // using namespace X; [C++] - if (CGDebugInfo *DI = getModuleDebugInfo()) - DI->EmitUsingDirective(cast<UsingDirectiveDecl>(*D)); - return; - case Decl::CXXConstructor: - getCXXABI().EmitCXXConstructors(cast<CXXConstructorDecl>(D)); - break; - case Decl::CXXDestructor: - getCXXABI().EmitCXXDestructors(cast<CXXDestructorDecl>(D)); - break; - - case Decl::StaticAssert: - // Nothing to do. - break; - - // Objective-C Decls - - // Forward declarations, no (immediate) code generation. - case Decl::ObjCInterface: - case Decl::ObjCCategory: - break; - - case Decl::ObjCProtocol: { - auto *Proto = cast<ObjCProtocolDecl>(D); - if (Proto->isThisDeclarationADefinition()) - ObjCRuntime->GenerateProtocol(Proto); - break; - } - - case Decl::ObjCCategoryImpl: - // Categories have properties but don't support synthesize so we - // can ignore them here. - ObjCRuntime->GenerateCategory(cast<ObjCCategoryImplDecl>(D)); - break; - - case Decl::ObjCImplementation: { - auto *OMD = cast<ObjCImplementationDecl>(D); - EmitObjCPropertyImplementations(OMD); - EmitObjCIvarInitializations(OMD); - ObjCRuntime->GenerateClass(OMD); - // Emit global variable debug information. - if (CGDebugInfo *DI = getModuleDebugInfo()) - if (getCodeGenOpts().getDebugInfo() >= codegenoptions::LimitedDebugInfo) - DI->getOrCreateInterfaceType(getContext().getObjCInterfaceType( - OMD->getClassInterface()), OMD->getLocation()); - break; - } - case Decl::ObjCMethod: { - auto *OMD = cast<ObjCMethodDecl>(D); - // If this is not a prototype, emit the body. - if (OMD->getBody()) - CodeGenFunction(*this).GenerateObjCMethod(OMD); - break; - } - case Decl::ObjCCompatibleAlias: - ObjCRuntime->RegisterAlias(cast<ObjCCompatibleAliasDecl>(D)); - break; - - case Decl::PragmaComment: { - const auto *PCD = cast<PragmaCommentDecl>(D); - switch (PCD->getCommentKind()) { - case PCK_Unknown: - llvm_unreachable("unexpected pragma comment kind"); - case PCK_Linker: - AppendLinkerOptions(PCD->getArg()); - break; - case PCK_Lib: - if (getTarget().getTriple().isOSBinFormatELF() && - !getTarget().getTriple().isPS4()) - AddELFLibDirective(PCD->getArg()); - else - AddDependentLib(PCD->getArg()); - break; - case PCK_Compiler: - case PCK_ExeStr: - case PCK_User: - break; // We ignore all of these. - } - break; - } - - case Decl::PragmaDetectMismatch: { - const auto *PDMD = cast<PragmaDetectMismatchDecl>(D); - AddDetectMismatch(PDMD->getName(), PDMD->getValue()); - break; - } - - case Decl::LinkageSpec: - EmitLinkageSpec(cast<LinkageSpecDecl>(D)); - break; - - case Decl::FileScopeAsm: { - // File-scope asm is ignored during device-side CUDA compilation. - if (LangOpts.CUDA && LangOpts.CUDAIsDevice) - break; - // File-scope asm is ignored during device-side OpenMP compilation. - if (LangOpts.OpenMPIsDevice) - break; - auto *AD = cast<FileScopeAsmDecl>(D); - getModule().appendModuleInlineAsm(AD->getAsmString()->getString()); - break; - } - - case Decl::Import: { - auto *Import = cast<ImportDecl>(D); - - // If we've already imported this module, we're done. - if (!ImportedModules.insert(Import->getImportedModule())) - break; - - // Emit debug information for direct imports. - if (!Import->getImportedOwningModule()) { - if (CGDebugInfo *DI = getModuleDebugInfo()) - DI->EmitImportDecl(*Import); - } - - // Find all of the submodules and emit the module initializers. - llvm::SmallPtrSet<clang::Module *, 16> Visited; - SmallVector<clang::Module *, 16> Stack; - Visited.insert(Import->getImportedModule()); - Stack.push_back(Import->getImportedModule()); - - while (!Stack.empty()) { - clang::Module *Mod = Stack.pop_back_val(); - if (!EmittedModuleInitializers.insert(Mod).second) - continue; - - for (auto *D : Context.getModuleInitializers(Mod)) - EmitTopLevelDecl(D); - - // Visit the submodules of this module. - for (clang::Module::submodule_iterator Sub = Mod->submodule_begin(), - SubEnd = Mod->submodule_end(); - Sub != SubEnd; ++Sub) { - // Skip explicit children; they need to be explicitly imported to emit - // the initializers. - if ((*Sub)->IsExplicit) - continue; - - if (Visited.insert(*Sub).second) - Stack.push_back(*Sub); - } - } - break; - } - - case Decl::Export: - EmitDeclContext(cast<ExportDecl>(D)); - break; - - case Decl::OMPThreadPrivate: - EmitOMPThreadPrivateDecl(cast<OMPThreadPrivateDecl>(D)); - break; - - case Decl::OMPDeclareReduction: - EmitOMPDeclareReduction(cast<OMPDeclareReductionDecl>(D)); - break; - - case Decl::OMPRequires: - EmitOMPRequiresDecl(cast<OMPRequiresDecl>(D)); - break; - - default: - // Make sure we handled everything we should, every other kind is a - // non-top-level decl. FIXME: Would be nice to have an isTopLevelDeclKind - // function. Need to recode Decl::Kind to do that easily. - assert(isa<TypeDecl>(D) && "Unsupported decl kind"); - break; - } -} - -void CodeGenModule::AddDeferredUnusedCoverageMapping(Decl *D) { - // Do we need to generate coverage mapping? - if (!CodeGenOpts.CoverageMapping) - return; - switch (D->getKind()) { - case Decl::CXXConversion: - case Decl::CXXMethod: - case Decl::Function: - case Decl::ObjCMethod: - case Decl::CXXConstructor: - case Decl::CXXDestructor: { - if (!cast<FunctionDecl>(D)->doesThisDeclarationHaveABody()) - return; - SourceManager &SM = getContext().getSourceManager(); - if (LimitedCoverage && SM.getMainFileID() != SM.getFileID(D->getBeginLoc())) - return; - auto I = DeferredEmptyCoverageMappingDecls.find(D); - if (I == DeferredEmptyCoverageMappingDecls.end()) - DeferredEmptyCoverageMappingDecls[D] = true; - break; - } - default: - break; - }; -} - -void CodeGenModule::ClearUnusedCoverageMapping(const Decl *D) { - // Do we need to generate coverage mapping? - if (!CodeGenOpts.CoverageMapping) - return; - if (const auto *Fn = dyn_cast<FunctionDecl>(D)) { - if (Fn->isTemplateInstantiation()) - ClearUnusedCoverageMapping(Fn->getTemplateInstantiationPattern()); - } - auto I = DeferredEmptyCoverageMappingDecls.find(D); - if (I == DeferredEmptyCoverageMappingDecls.end()) - DeferredEmptyCoverageMappingDecls[D] = false; - else - I->second = false; -} - -void CodeGenModule::EmitDeferredUnusedCoverageMappings() { - // We call takeVector() here to avoid use-after-free. - // FIXME: DeferredEmptyCoverageMappingDecls is getting mutated because - // we deserialize function bodies to emit coverage info for them, and that - // deserializes more declarations. How should we handle that case? - for (const auto &Entry : DeferredEmptyCoverageMappingDecls.takeVector()) { - if (!Entry.second) - continue; - const Decl *D = Entry.first; - switch (D->getKind()) { - case Decl::CXXConversion: - case Decl::CXXMethod: - case Decl::Function: - case Decl::ObjCMethod: { - CodeGenPGO PGO(*this); - GlobalDecl GD(cast<FunctionDecl>(D)); - PGO.emitEmptyCounterMapping(D, getMangledName(GD), - getFunctionLinkage(GD)); - break; - } - case Decl::CXXConstructor: { - CodeGenPGO PGO(*this); - GlobalDecl GD(cast<CXXConstructorDecl>(D), Ctor_Base); - PGO.emitEmptyCounterMapping(D, getMangledName(GD), - getFunctionLinkage(GD)); - break; - } - case Decl::CXXDestructor: { - CodeGenPGO PGO(*this); - GlobalDecl GD(cast<CXXDestructorDecl>(D), Dtor_Base); - PGO.emitEmptyCounterMapping(D, getMangledName(GD), - getFunctionLinkage(GD)); - break; - } - default: - break; - }; - } -} - -/// Turns the given pointer into a constant. -static llvm::Constant *GetPointerConstant(llvm::LLVMContext &Context, - const void *Ptr) { - uintptr_t PtrInt = reinterpret_cast<uintptr_t>(Ptr); - llvm::Type *i64 = llvm::Type::getInt64Ty(Context); - return llvm::ConstantInt::get(i64, PtrInt); -} - -static void EmitGlobalDeclMetadata(CodeGenModule &CGM, - llvm::NamedMDNode *&GlobalMetadata, - GlobalDecl D, - llvm::GlobalValue *Addr) { - if (!GlobalMetadata) - GlobalMetadata = - CGM.getModule().getOrInsertNamedMetadata("clang.global.decl.ptrs"); - - // TODO: should we report variant information for ctors/dtors? - llvm::Metadata *Ops[] = {llvm::ConstantAsMetadata::get(Addr), - llvm::ConstantAsMetadata::get(GetPointerConstant( - CGM.getLLVMContext(), D.getDecl()))}; - GlobalMetadata->addOperand(llvm::MDNode::get(CGM.getLLVMContext(), Ops)); -} - -/// For each function which is declared within an extern "C" region and marked -/// as 'used', but has internal linkage, create an alias from the unmangled -/// name to the mangled name if possible. People expect to be able to refer -/// to such functions with an unmangled name from inline assembly within the -/// same translation unit. -void CodeGenModule::EmitStaticExternCAliases() { - if (!getTargetCodeGenInfo().shouldEmitStaticExternCAliases()) - return; - for (auto &I : StaticExternCValues) { - IdentifierInfo *Name = I.first; - llvm::GlobalValue *Val = I.second; - if (Val && !getModule().getNamedValue(Name->getName())) - addUsedGlobal(llvm::GlobalAlias::create(Name->getName(), Val)); - } -} - -bool CodeGenModule::lookupRepresentativeDecl(StringRef MangledName, - GlobalDecl &Result) const { - auto Res = Manglings.find(MangledName); - if (Res == Manglings.end()) - return false; - Result = Res->getValue(); - return true; -} - -/// Emits metadata nodes associating all the global values in the -/// current module with the Decls they came from. This is useful for -/// projects using IR gen as a subroutine. -/// -/// Since there's currently no way to associate an MDNode directly -/// with an llvm::GlobalValue, we create a global named metadata -/// with the name 'clang.global.decl.ptrs'. -void CodeGenModule::EmitDeclMetadata() { - llvm::NamedMDNode *GlobalMetadata = nullptr; - - for (auto &I : MangledDeclNames) { - llvm::GlobalValue *Addr = getModule().getNamedValue(I.second); - // Some mangled names don't necessarily have an associated GlobalValue - // in this module, e.g. if we mangled it for DebugInfo. - if (Addr) - EmitGlobalDeclMetadata(*this, GlobalMetadata, I.first, Addr); - } -} - -/// Emits metadata nodes for all the local variables in the current -/// function. -void CodeGenFunction::EmitDeclMetadata() { - if (LocalDeclMap.empty()) return; - - llvm::LLVMContext &Context = getLLVMContext(); - - // Find the unique metadata ID for this name. - unsigned DeclPtrKind = Context.getMDKindID("clang.decl.ptr"); - - llvm::NamedMDNode *GlobalMetadata = nullptr; - - for (auto &I : LocalDeclMap) { - const Decl *D = I.first; - llvm::Value *Addr = I.second.getPointer(); - if (auto *Alloca = dyn_cast<llvm::AllocaInst>(Addr)) { - llvm::Value *DAddr = GetPointerConstant(getLLVMContext(), D); - Alloca->setMetadata( - DeclPtrKind, llvm::MDNode::get( - Context, llvm::ValueAsMetadata::getConstant(DAddr))); - } else if (auto *GV = dyn_cast<llvm::GlobalValue>(Addr)) { - GlobalDecl GD = GlobalDecl(cast<VarDecl>(D)); - EmitGlobalDeclMetadata(CGM, GlobalMetadata, GD, GV); - } - } -} - -void CodeGenModule::EmitVersionIdentMetadata() { - llvm::NamedMDNode *IdentMetadata = - TheModule.getOrInsertNamedMetadata("llvm.ident"); - std::string Version = getClangFullVersion(); - llvm::LLVMContext &Ctx = TheModule.getContext(); - - llvm::Metadata *IdentNode[] = {llvm::MDString::get(Ctx, Version)}; - IdentMetadata->addOperand(llvm::MDNode::get(Ctx, IdentNode)); -} - -void CodeGenModule::EmitCommandLineMetadata() { - llvm::NamedMDNode *CommandLineMetadata = - TheModule.getOrInsertNamedMetadata("llvm.commandline"); - std::string CommandLine = getCodeGenOpts().RecordCommandLine; - llvm::LLVMContext &Ctx = TheModule.getContext(); - - llvm::Metadata *CommandLineNode[] = {llvm::MDString::get(Ctx, CommandLine)}; - CommandLineMetadata->addOperand(llvm::MDNode::get(Ctx, CommandLineNode)); -} - -void CodeGenModule::EmitTargetMetadata() { - // Warning, new MangledDeclNames may be appended within this loop. - // We rely on MapVector insertions adding new elements to the end - // of the container. - // FIXME: Move this loop into the one target that needs it, and only - // loop over those declarations for which we couldn't emit the target - // metadata when we emitted the declaration. - for (unsigned I = 0; I != MangledDeclNames.size(); ++I) { - auto Val = *(MangledDeclNames.begin() + I); - const Decl *D = Val.first.getDecl()->getMostRecentDecl(); - llvm::GlobalValue *GV = GetGlobalValue(Val.second); - getTargetCodeGenInfo().emitTargetMD(D, GV, *this); - } -} - -void CodeGenModule::EmitCoverageFile() { - if (getCodeGenOpts().CoverageDataFile.empty() && - getCodeGenOpts().CoverageNotesFile.empty()) - return; - - llvm::NamedMDNode *CUNode = TheModule.getNamedMetadata("llvm.dbg.cu"); - if (!CUNode) - return; - - llvm::NamedMDNode *GCov = TheModule.getOrInsertNamedMetadata("llvm.gcov"); - llvm::LLVMContext &Ctx = TheModule.getContext(); - auto *CoverageDataFile = - llvm::MDString::get(Ctx, getCodeGenOpts().CoverageDataFile); - auto *CoverageNotesFile = - llvm::MDString::get(Ctx, getCodeGenOpts().CoverageNotesFile); - for (int i = 0, e = CUNode->getNumOperands(); i != e; ++i) { - llvm::MDNode *CU = CUNode->getOperand(i); - llvm::Metadata *Elts[] = {CoverageNotesFile, CoverageDataFile, CU}; - GCov->addOperand(llvm::MDNode::get(Ctx, Elts)); - } -} - -llvm::Constant *CodeGenModule::EmitUuidofInitializer(StringRef Uuid) { - // Sema has checked that all uuid strings are of the form - // "12345678-1234-1234-1234-1234567890ab". - assert(Uuid.size() == 36); - for (unsigned i = 0; i < 36; ++i) { - if (i == 8 || i == 13 || i == 18 || i == 23) assert(Uuid[i] == '-'); - else assert(isHexDigit(Uuid[i])); - } - - // The starts of all bytes of Field3 in Uuid. Field 3 is "1234-1234567890ab". - const unsigned Field3ValueOffsets[8] = { 19, 21, 24, 26, 28, 30, 32, 34 }; - - llvm::Constant *Field3[8]; - for (unsigned Idx = 0; Idx < 8; ++Idx) - Field3[Idx] = llvm::ConstantInt::get( - Int8Ty, Uuid.substr(Field3ValueOffsets[Idx], 2), 16); - - llvm::Constant *Fields[4] = { - llvm::ConstantInt::get(Int32Ty, Uuid.substr(0, 8), 16), - llvm::ConstantInt::get(Int16Ty, Uuid.substr(9, 4), 16), - llvm::ConstantInt::get(Int16Ty, Uuid.substr(14, 4), 16), - llvm::ConstantArray::get(llvm::ArrayType::get(Int8Ty, 8), Field3) - }; - - return llvm::ConstantStruct::getAnon(Fields); -} - -llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty, - bool ForEH) { - // Return a bogus pointer if RTTI is disabled, unless it's for EH. - // FIXME: should we even be calling this method if RTTI is disabled - // and it's not for EH? - if ((!ForEH && !getLangOpts().RTTI) || getLangOpts().CUDAIsDevice) - return llvm::Constant::getNullValue(Int8PtrTy); - - if (ForEH && Ty->isObjCObjectPointerType() && - LangOpts.ObjCRuntime.isGNUFamily()) - return ObjCRuntime->GetEHType(Ty); - - return getCXXABI().getAddrOfRTTIDescriptor(Ty); -} - -void CodeGenModule::EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) { - // Do not emit threadprivates in simd-only mode. - if (LangOpts.OpenMP && LangOpts.OpenMPSimd) - return; - for (auto RefExpr : D->varlists()) { - auto *VD = cast<VarDecl>(cast<DeclRefExpr>(RefExpr)->getDecl()); - bool PerformInit = - VD->getAnyInitializer() && - !VD->getAnyInitializer()->isConstantInitializer(getContext(), - /*ForRef=*/false); - - Address Addr(GetAddrOfGlobalVar(VD), getContext().getDeclAlign(VD)); - if (auto InitFunction = getOpenMPRuntime().emitThreadPrivateVarDefinition( - VD, Addr, RefExpr->getBeginLoc(), PerformInit)) - CXXGlobalInits.push_back(InitFunction); - } -} - -llvm::Metadata * -CodeGenModule::CreateMetadataIdentifierImpl(QualType T, MetadataTypeMap &Map, - StringRef Suffix) { - llvm::Metadata *&InternalId = Map[T.getCanonicalType()]; - if (InternalId) - return InternalId; - - if (isExternallyVisible(T->getLinkage())) { - std::string OutName; - llvm::raw_string_ostream Out(OutName); - getCXXABI().getMangleContext().mangleTypeName(T, Out); - Out << Suffix; - - InternalId = llvm::MDString::get(getLLVMContext(), Out.str()); - } else { - InternalId = llvm::MDNode::getDistinct(getLLVMContext(), - llvm::ArrayRef<llvm::Metadata *>()); - } - - return InternalId; -} - -llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) { - return CreateMetadataIdentifierImpl(T, MetadataIdMap, ""); -} - -llvm::Metadata * -CodeGenModule::CreateMetadataIdentifierForVirtualMemPtrType(QualType T) { - return CreateMetadataIdentifierImpl(T, VirtualMetadataIdMap, ".virtual"); -} - -// Generalize pointer types to a void pointer with the qualifiers of the -// originally pointed-to type, e.g. 'const char *' and 'char * const *' -// generalize to 'const void *' while 'char *' and 'const char **' generalize to -// 'void *'. -static QualType GeneralizeType(ASTContext &Ctx, QualType Ty) { - if (!Ty->isPointerType()) - return Ty; - - return Ctx.getPointerType( - QualType(Ctx.VoidTy).withCVRQualifiers( - Ty->getPointeeType().getCVRQualifiers())); -} - -// Apply type generalization to a FunctionType's return and argument types -static QualType GeneralizeFunctionType(ASTContext &Ctx, QualType Ty) { - if (auto *FnType = Ty->getAs<FunctionProtoType>()) { - SmallVector<QualType, 8> GeneralizedParams; - for (auto &Param : FnType->param_types()) - GeneralizedParams.push_back(GeneralizeType(Ctx, Param)); - - return Ctx.getFunctionType( - GeneralizeType(Ctx, FnType->getReturnType()), - GeneralizedParams, FnType->getExtProtoInfo()); - } - - if (auto *FnType = Ty->getAs<FunctionNoProtoType>()) - return Ctx.getFunctionNoProtoType( - GeneralizeType(Ctx, FnType->getReturnType())); - - llvm_unreachable("Encountered unknown FunctionType"); -} - -llvm::Metadata *CodeGenModule::CreateMetadataIdentifierGeneralized(QualType T) { - return CreateMetadataIdentifierImpl(GeneralizeFunctionType(getContext(), T), - GeneralizedMetadataIdMap, ".generalized"); -} - -/// Returns whether this module needs the "all-vtables" type identifier. -bool CodeGenModule::NeedAllVtablesTypeId() const { - // Returns true if at least one of vtable-based CFI checkers is enabled and - // is not in the trapping mode. - return ((LangOpts.Sanitize.has(SanitizerKind::CFIVCall) && - !CodeGenOpts.SanitizeTrap.has(SanitizerKind::CFIVCall)) || - (LangOpts.Sanitize.has(SanitizerKind::CFINVCall) && - !CodeGenOpts.SanitizeTrap.has(SanitizerKind::CFINVCall)) || - (LangOpts.Sanitize.has(SanitizerKind::CFIDerivedCast) && - !CodeGenOpts.SanitizeTrap.has(SanitizerKind::CFIDerivedCast)) || - (LangOpts.Sanitize.has(SanitizerKind::CFIUnrelatedCast) && - !CodeGenOpts.SanitizeTrap.has(SanitizerKind::CFIUnrelatedCast))); -} - -void CodeGenModule::AddVTableTypeMetadata(llvm::GlobalVariable *VTable, - CharUnits Offset, - const CXXRecordDecl *RD) { - llvm::Metadata *MD = - CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0)); - VTable->addTypeMetadata(Offset.getQuantity(), MD); - - if (CodeGenOpts.SanitizeCfiCrossDso) - if (auto CrossDsoTypeId = CreateCrossDsoCfiTypeId(MD)) - VTable->addTypeMetadata(Offset.getQuantity(), - llvm::ConstantAsMetadata::get(CrossDsoTypeId)); - - if (NeedAllVtablesTypeId()) { - llvm::Metadata *MD = llvm::MDString::get(getLLVMContext(), "all-vtables"); - VTable->addTypeMetadata(Offset.getQuantity(), MD); - } -} - -TargetAttr::ParsedTargetAttr CodeGenModule::filterFunctionTargetAttrs(const TargetAttr *TD) { - assert(TD != nullptr); - TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse(); - - ParsedAttr.Features.erase( - llvm::remove_if(ParsedAttr.Features, - [&](const std::string &Feat) { - return !Target.isValidFeatureName( - StringRef{Feat}.substr(1)); - }), - ParsedAttr.Features.end()); - return ParsedAttr; -} - - -// Fills in the supplied string map with the set of target features for the -// passed in function. -void CodeGenModule::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, - GlobalDecl GD) { - StringRef TargetCPU = Target.getTargetOpts().CPU; - const FunctionDecl *FD = GD.getDecl()->getAsFunction(); - if (const auto *TD = FD->getAttr<TargetAttr>()) { - TargetAttr::ParsedTargetAttr ParsedAttr = filterFunctionTargetAttrs(TD); - - // Make a copy of the features as passed on the command line into the - // beginning of the additional features from the function to override. - ParsedAttr.Features.insert(ParsedAttr.Features.begin(), - Target.getTargetOpts().FeaturesAsWritten.begin(), - Target.getTargetOpts().FeaturesAsWritten.end()); - - if (ParsedAttr.Architecture != "" && - Target.isValidCPUName(ParsedAttr.Architecture)) - TargetCPU = ParsedAttr.Architecture; - - // Now populate the feature map, first with the TargetCPU which is either - // the default or a new one from the target attribute string. Then we'll use - // the passed in features (FeaturesAsWritten) along with the new ones from - // the attribute. - Target.initFeatureMap(FeatureMap, getDiags(), TargetCPU, - ParsedAttr.Features); - } else if (const auto *SD = FD->getAttr<CPUSpecificAttr>()) { - llvm::SmallVector<StringRef, 32> FeaturesTmp; - Target.getCPUSpecificCPUDispatchFeatures( - SD->getCPUName(GD.getMultiVersionIndex())->getName(), FeaturesTmp); - std::vector<std::string> Features(FeaturesTmp.begin(), FeaturesTmp.end()); - Target.initFeatureMap(FeatureMap, getDiags(), TargetCPU, Features); - } else { - Target.initFeatureMap(FeatureMap, getDiags(), TargetCPU, - Target.getTargetOpts().Features); - } -} - -llvm::SanitizerStatReport &CodeGenModule::getSanStats() { - if (!SanStats) - SanStats = llvm::make_unique<llvm::SanitizerStatReport>(&getModule()); - - return *SanStats; -} -llvm::Value * -CodeGenModule::createOpenCLIntToSamplerConversion(const Expr *E, - CodeGenFunction &CGF) { - llvm::Constant *C = ConstantEmitter(CGF).emitAbstract(E, E->getType()); - auto SamplerT = getOpenCLRuntime().getSamplerType(E->getType().getTypePtr()); - auto FTy = llvm::FunctionType::get(SamplerT, {C->getType()}, false); - return CGF.Builder.CreateCall(CreateRuntimeFunction(FTy, - "__translate_sampler_initializer"), - {C}); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenModule.h b/gnu/llvm/tools/clang/lib/CodeGen/CodeGenModule.h deleted file mode 100644 index 75679d11c13..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenModule.h +++ /dev/null @@ -1,1470 +0,0 @@ -//===--- CodeGenModule.h - Per-Module state for LLVM CodeGen ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This is the internal per-translation-unit state used for llvm translation. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENMODULE_H -#define LLVM_CLANG_LIB_CODEGEN_CODEGENMODULE_H - -#include "CGVTables.h" -#include "CodeGenTypeCache.h" -#include "CodeGenTypes.h" -#include "SanitizerMetadata.h" -#include "clang/AST/Attr.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclOpenMP.h" -#include "clang/AST/GlobalDecl.h" -#include "clang/AST/Mangle.h" -#include "clang/Basic/ABI.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/Module.h" -#include "clang/Basic/SanitizerBlacklist.h" -#include "clang/Basic/XRayLists.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/ValueHandle.h" -#include "llvm/Transforms/Utils/SanitizerStats.h" - -namespace llvm { -class Module; -class Constant; -class ConstantInt; -class Function; -class GlobalValue; -class DataLayout; -class FunctionType; -class LLVMContext; -class IndexedInstrProfReader; -} - -namespace clang { -class ASTContext; -class AtomicType; -class FunctionDecl; -class IdentifierInfo; -class ObjCMethodDecl; -class ObjCImplementationDecl; -class ObjCCategoryImplDecl; -class ObjCProtocolDecl; -class ObjCEncodeExpr; -class BlockExpr; -class CharUnits; -class Decl; -class Expr; -class Stmt; -class InitListExpr; -class StringLiteral; -class NamedDecl; -class ValueDecl; -class VarDecl; -class LangOptions; -class CodeGenOptions; -class HeaderSearchOptions; -class PreprocessorOptions; -class DiagnosticsEngine; -class AnnotateAttr; -class CXXDestructorDecl; -class Module; -class CoverageSourceInfo; - -namespace CodeGen { - -class CallArgList; -class CodeGenFunction; -class CodeGenTBAA; -class CGCXXABI; -class CGDebugInfo; -class CGObjCRuntime; -class CGOpenCLRuntime; -class CGOpenMPRuntime; -class CGCUDARuntime; -class BlockFieldFlags; -class FunctionArgList; -class CoverageMappingModuleGen; -class TargetCodeGenInfo; - -enum ForDefinition_t : bool { - NotForDefinition = false, - ForDefinition = true -}; - -struct OrderGlobalInits { - unsigned int priority; - unsigned int lex_order; - OrderGlobalInits(unsigned int p, unsigned int l) - : priority(p), lex_order(l) {} - - bool operator==(const OrderGlobalInits &RHS) const { - return priority == RHS.priority && lex_order == RHS.lex_order; - } - - bool operator<(const OrderGlobalInits &RHS) const { - return std::tie(priority, lex_order) < - std::tie(RHS.priority, RHS.lex_order); - } -}; - -struct ObjCEntrypoints { - ObjCEntrypoints() { memset(this, 0, sizeof(*this)); } - - /// void objc_alloc(id); - llvm::Constant *objc_alloc; - - /// void objc_allocWithZone(id); - llvm::Constant *objc_allocWithZone; - - /// void objc_autoreleasePoolPop(void*); - llvm::Constant *objc_autoreleasePoolPop; - - /// void objc_autoreleasePoolPop(void*); - /// Note this method is used when we are using exception handling - llvm::Constant *objc_autoreleasePoolPopInvoke; - - /// void *objc_autoreleasePoolPush(void); - llvm::Constant *objc_autoreleasePoolPush; - - /// id objc_autorelease(id); - llvm::Constant *objc_autorelease; - - /// id objc_autorelease(id); - /// Note this is the runtime method not the intrinsic. - llvm::Constant *objc_autoreleaseRuntimeFunction; - - /// id objc_autoreleaseReturnValue(id); - llvm::Constant *objc_autoreleaseReturnValue; - - /// void objc_copyWeak(id *dest, id *src); - llvm::Constant *objc_copyWeak; - - /// void objc_destroyWeak(id*); - llvm::Constant *objc_destroyWeak; - - /// id objc_initWeak(id*, id); - llvm::Constant *objc_initWeak; - - /// id objc_loadWeak(id*); - llvm::Constant *objc_loadWeak; - - /// id objc_loadWeakRetained(id*); - llvm::Constant *objc_loadWeakRetained; - - /// void objc_moveWeak(id *dest, id *src); - llvm::Constant *objc_moveWeak; - - /// id objc_retain(id); - llvm::Constant *objc_retain; - - /// id objc_retain(id); - /// Note this is the runtime method not the intrinsic. - llvm::Constant *objc_retainRuntimeFunction; - - /// id objc_retainAutorelease(id); - llvm::Constant *objc_retainAutorelease; - - /// id objc_retainAutoreleaseReturnValue(id); - llvm::Constant *objc_retainAutoreleaseReturnValue; - - /// id objc_retainAutoreleasedReturnValue(id); - llvm::Constant *objc_retainAutoreleasedReturnValue; - - /// id objc_retainBlock(id); - llvm::Constant *objc_retainBlock; - - /// void objc_release(id); - llvm::Constant *objc_release; - - /// void objc_release(id); - /// Note this is the runtime method not the intrinsic. - llvm::Constant *objc_releaseRuntimeFunction; - - /// void objc_storeStrong(id*, id); - llvm::Constant *objc_storeStrong; - - /// id objc_storeWeak(id*, id); - llvm::Constant *objc_storeWeak; - - /// id objc_unsafeClaimAutoreleasedReturnValue(id); - llvm::Constant *objc_unsafeClaimAutoreleasedReturnValue; - - /// A void(void) inline asm to use to mark that the return value of - /// a call will be immediately retain. - llvm::InlineAsm *retainAutoreleasedReturnValueMarker; - - /// void clang.arc.use(...); - llvm::Constant *clang_arc_use; -}; - -/// This class records statistics on instrumentation based profiling. -class InstrProfStats { - uint32_t VisitedInMainFile; - uint32_t MissingInMainFile; - uint32_t Visited; - uint32_t Missing; - uint32_t Mismatched; - -public: - InstrProfStats() - : VisitedInMainFile(0), MissingInMainFile(0), Visited(0), Missing(0), - Mismatched(0) {} - /// Record that we've visited a function and whether or not that function was - /// in the main source file. - void addVisited(bool MainFile) { - if (MainFile) - ++VisitedInMainFile; - ++Visited; - } - /// Record that a function we've visited has no profile data. - void addMissing(bool MainFile) { - if (MainFile) - ++MissingInMainFile; - ++Missing; - } - /// Record that a function we've visited has mismatched profile data. - void addMismatched(bool MainFile) { ++Mismatched; } - /// Whether or not the stats we've gathered indicate any potential problems. - bool hasDiagnostics() { return Missing || Mismatched; } - /// Report potential problems we've found to \c Diags. - void reportDiagnostics(DiagnosticsEngine &Diags, StringRef MainFile); -}; - -/// A pair of helper functions for a __block variable. -class BlockByrefHelpers : public llvm::FoldingSetNode { - // MSVC requires this type to be complete in order to process this - // header. -public: - llvm::Constant *CopyHelper; - llvm::Constant *DisposeHelper; - - /// The alignment of the field. This is important because - /// different offsets to the field within the byref struct need to - /// have different helper functions. - CharUnits Alignment; - - BlockByrefHelpers(CharUnits alignment) : Alignment(alignment) {} - BlockByrefHelpers(const BlockByrefHelpers &) = default; - virtual ~BlockByrefHelpers(); - - void Profile(llvm::FoldingSetNodeID &id) const { - id.AddInteger(Alignment.getQuantity()); - profileImpl(id); - } - virtual void profileImpl(llvm::FoldingSetNodeID &id) const = 0; - - virtual bool needsCopy() const { return true; } - virtual void emitCopy(CodeGenFunction &CGF, Address dest, Address src) = 0; - - virtual bool needsDispose() const { return true; } - virtual void emitDispose(CodeGenFunction &CGF, Address field) = 0; -}; - -/// This class organizes the cross-function state that is used while generating -/// LLVM code. -class CodeGenModule : public CodeGenTypeCache { - CodeGenModule(const CodeGenModule &) = delete; - void operator=(const CodeGenModule &) = delete; - -public: - struct Structor { - Structor() : Priority(0), Initializer(nullptr), AssociatedData(nullptr) {} - Structor(int Priority, llvm::Constant *Initializer, - llvm::Constant *AssociatedData) - : Priority(Priority), Initializer(Initializer), - AssociatedData(AssociatedData) {} - int Priority; - llvm::Constant *Initializer; - llvm::Constant *AssociatedData; - }; - - typedef std::vector<Structor> CtorList; - -private: - ASTContext &Context; - const LangOptions &LangOpts; - const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info. - const PreprocessorOptions &PreprocessorOpts; // Only used for debug info. - const CodeGenOptions &CodeGenOpts; - llvm::Module &TheModule; - DiagnosticsEngine &Diags; - const TargetInfo &Target; - std::unique_ptr<CGCXXABI> ABI; - llvm::LLVMContext &VMContext; - - std::unique_ptr<CodeGenTBAA> TBAA; - - mutable std::unique_ptr<TargetCodeGenInfo> TheTargetCodeGenInfo; - - // This should not be moved earlier, since its initialization depends on some - // of the previous reference members being already initialized and also checks - // if TheTargetCodeGenInfo is NULL - CodeGenTypes Types; - - /// Holds information about C++ vtables. - CodeGenVTables VTables; - - std::unique_ptr<CGObjCRuntime> ObjCRuntime; - std::unique_ptr<CGOpenCLRuntime> OpenCLRuntime; - std::unique_ptr<CGOpenMPRuntime> OpenMPRuntime; - std::unique_ptr<CGCUDARuntime> CUDARuntime; - std::unique_ptr<CGDebugInfo> DebugInfo; - std::unique_ptr<ObjCEntrypoints> ObjCData; - llvm::MDNode *NoObjCARCExceptionsMetadata = nullptr; - std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader; - InstrProfStats PGOStats; - std::unique_ptr<llvm::SanitizerStatReport> SanStats; - - // A set of references that have only been seen via a weakref so far. This is - // used to remove the weak of the reference if we ever see a direct reference - // or a definition. - llvm::SmallPtrSet<llvm::GlobalValue*, 10> WeakRefReferences; - - /// This contains all the decls which have definitions but/ which are deferred - /// for emission and therefore should only be output if they are actually - /// used. If a decl is in this, then it is known to have not been referenced - /// yet. - std::map<StringRef, GlobalDecl> DeferredDecls; - - /// This is a list of deferred decls which we have seen that *are* actually - /// referenced. These get code generated when the module is done. - std::vector<GlobalDecl> DeferredDeclsToEmit; - void addDeferredDeclToEmit(GlobalDecl GD) { - DeferredDeclsToEmit.emplace_back(GD); - } - - /// List of alias we have emitted. Used to make sure that what they point to - /// is defined once we get to the end of the of the translation unit. - std::vector<GlobalDecl> Aliases; - - /// List of multiversion functions that have to be emitted. Used to make sure - /// we properly emit the iFunc. - std::vector<GlobalDecl> MultiVersionFuncs; - - typedef llvm::StringMap<llvm::TrackingVH<llvm::Constant> > ReplacementsTy; - ReplacementsTy Replacements; - - /// List of global values to be replaced with something else. Used when we - /// want to replace a GlobalValue but can't identify it by its mangled name - /// anymore (because the name is already taken). - llvm::SmallVector<std::pair<llvm::GlobalValue *, llvm::Constant *>, 8> - GlobalValReplacements; - - /// Set of global decls for which we already diagnosed mangled name conflict. - /// Required to not issue a warning (on a mangling conflict) multiple times - /// for the same decl. - llvm::DenseSet<GlobalDecl> DiagnosedConflictingDefinitions; - - /// A queue of (optional) vtables to consider emitting. - std::vector<const CXXRecordDecl*> DeferredVTables; - - /// A queue of (optional) vtables that may be emitted opportunistically. - std::vector<const CXXRecordDecl *> OpportunisticVTables; - - /// List of global values which are required to be present in the object file; - /// bitcast to i8*. This is used for forcing visibility of symbols which may - /// otherwise be optimized out. - std::vector<llvm::WeakTrackingVH> LLVMUsed; - std::vector<llvm::WeakTrackingVH> LLVMCompilerUsed; - - /// Store the list of global constructors and their respective priorities to - /// be emitted when the translation unit is complete. - CtorList GlobalCtors; - - /// Store the list of global destructors and their respective priorities to be - /// emitted when the translation unit is complete. - CtorList GlobalDtors; - - /// An ordered map of canonical GlobalDecls to their mangled names. - llvm::MapVector<GlobalDecl, StringRef> MangledDeclNames; - llvm::StringMap<GlobalDecl, llvm::BumpPtrAllocator> Manglings; - - // An ordered map of canonical GlobalDecls paired with the cpu-index for - // cpu-specific name manglings. - llvm::MapVector<std::pair<GlobalDecl, unsigned>, StringRef> - CPUSpecificMangledDeclNames; - llvm::StringMap<std::pair<GlobalDecl, unsigned>, llvm::BumpPtrAllocator> - CPUSpecificManglings; - - /// Global annotations. - std::vector<llvm::Constant*> Annotations; - - /// Map used to get unique annotation strings. - llvm::StringMap<llvm::Constant*> AnnotationStrings; - - llvm::StringMap<llvm::GlobalVariable *> CFConstantStringMap; - - llvm::DenseMap<llvm::Constant *, llvm::GlobalVariable *> ConstantStringMap; - llvm::DenseMap<const Decl*, llvm::Constant *> StaticLocalDeclMap; - llvm::DenseMap<const Decl*, llvm::GlobalVariable*> StaticLocalDeclGuardMap; - llvm::DenseMap<const Expr*, llvm::Constant *> MaterializedGlobalTemporaryMap; - - llvm::DenseMap<QualType, llvm::Constant *> AtomicSetterHelperFnMap; - llvm::DenseMap<QualType, llvm::Constant *> AtomicGetterHelperFnMap; - - /// Map used to get unique type descriptor constants for sanitizers. - llvm::DenseMap<QualType, llvm::Constant *> TypeDescriptorMap; - - /// Map used to track internal linkage functions declared within - /// extern "C" regions. - typedef llvm::MapVector<IdentifierInfo *, - llvm::GlobalValue *> StaticExternCMap; - StaticExternCMap StaticExternCValues; - - /// thread_local variables defined or used in this TU. - std::vector<const VarDecl *> CXXThreadLocals; - - /// thread_local variables with initializers that need to run - /// before any thread_local variable in this TU is odr-used. - std::vector<llvm::Function *> CXXThreadLocalInits; - std::vector<const VarDecl *> CXXThreadLocalInitVars; - - /// Global variables with initializers that need to run before main. - std::vector<llvm::Function *> CXXGlobalInits; - - /// When a C++ decl with an initializer is deferred, null is - /// appended to CXXGlobalInits, and the index of that null is placed - /// here so that the initializer will be performed in the correct - /// order. Once the decl is emitted, the index is replaced with ~0U to ensure - /// that we don't re-emit the initializer. - llvm::DenseMap<const Decl*, unsigned> DelayedCXXInitPosition; - - typedef std::pair<OrderGlobalInits, llvm::Function*> GlobalInitData; - - struct GlobalInitPriorityCmp { - bool operator()(const GlobalInitData &LHS, - const GlobalInitData &RHS) const { - return LHS.first.priority < RHS.first.priority; - } - }; - - /// Global variables with initializers whose order of initialization is set by - /// init_priority attribute. - SmallVector<GlobalInitData, 8> PrioritizedCXXGlobalInits; - - /// Global destructor functions and arguments that need to run on termination. - std::vector<std::pair<llvm::WeakTrackingVH, llvm::Constant *>> CXXGlobalDtors; - - /// The complete set of modules that has been imported. - llvm::SetVector<clang::Module *> ImportedModules; - - /// The set of modules for which the module initializers - /// have been emitted. - llvm::SmallPtrSet<clang::Module *, 16> EmittedModuleInitializers; - - /// A vector of metadata strings. - SmallVector<llvm::MDNode *, 16> LinkerOptionsMetadata; - - /// @name Cache for Objective-C runtime types - /// @{ - - /// Cached reference to the class for constant strings. This value has type - /// int * but is actually an Obj-C class pointer. - llvm::WeakTrackingVH CFConstantStringClassRef; - - /// The type used to describe the state of a fast enumeration in - /// Objective-C's for..in loop. - QualType ObjCFastEnumerationStateType; - - /// @} - - /// Lazily create the Objective-C runtime - void createObjCRuntime(); - - void createOpenCLRuntime(); - void createOpenMPRuntime(); - void createCUDARuntime(); - - bool isTriviallyRecursive(const FunctionDecl *F); - bool shouldEmitFunction(GlobalDecl GD); - bool shouldOpportunisticallyEmitVTables(); - /// Map used to be sure we don't emit the same CompoundLiteral twice. - llvm::DenseMap<const CompoundLiteralExpr *, llvm::GlobalVariable *> - EmittedCompoundLiterals; - - /// Map of the global blocks we've emitted, so that we don't have to re-emit - /// them if the constexpr evaluator gets aggressive. - llvm::DenseMap<const BlockExpr *, llvm::Constant *> EmittedGlobalBlocks; - - /// @name Cache for Blocks Runtime Globals - /// @{ - - llvm::Constant *NSConcreteGlobalBlock = nullptr; - llvm::Constant *NSConcreteStackBlock = nullptr; - - llvm::Constant *BlockObjectAssign = nullptr; - llvm::Constant *BlockObjectDispose = nullptr; - - llvm::Type *BlockDescriptorType = nullptr; - llvm::Type *GenericBlockLiteralType = nullptr; - - struct { - int GlobalUniqueCount; - } Block; - - /// void @llvm.lifetime.start(i64 %size, i8* nocapture <ptr>) - llvm::Constant *LifetimeStartFn = nullptr; - - /// void @llvm.lifetime.end(i64 %size, i8* nocapture <ptr>) - llvm::Constant *LifetimeEndFn = nullptr; - - GlobalDecl initializedGlobalDecl; - - std::unique_ptr<SanitizerMetadata> SanitizerMD; - - /// @} - - llvm::MapVector<const Decl *, bool> DeferredEmptyCoverageMappingDecls; - - std::unique_ptr<CoverageMappingModuleGen> CoverageMapping; - - /// Mapping from canonical types to their metadata identifiers. We need to - /// maintain this mapping because identifiers may be formed from distinct - /// MDNodes. - typedef llvm::DenseMap<QualType, llvm::Metadata *> MetadataTypeMap; - MetadataTypeMap MetadataIdMap; - MetadataTypeMap VirtualMetadataIdMap; - MetadataTypeMap GeneralizedMetadataIdMap; - -public: - CodeGenModule(ASTContext &C, const HeaderSearchOptions &headersearchopts, - const PreprocessorOptions &ppopts, - const CodeGenOptions &CodeGenOpts, llvm::Module &M, - DiagnosticsEngine &Diags, - CoverageSourceInfo *CoverageInfo = nullptr); - - ~CodeGenModule(); - - void clear(); - - /// Finalize LLVM code generation. - void Release(); - - /// Return true if we should emit location information for expressions. - bool getExpressionLocationsEnabled() const; - - /// Return a reference to the configured Objective-C runtime. - CGObjCRuntime &getObjCRuntime() { - if (!ObjCRuntime) createObjCRuntime(); - return *ObjCRuntime; - } - - /// Return true iff an Objective-C runtime has been configured. - bool hasObjCRuntime() { return !!ObjCRuntime; } - - /// Return a reference to the configured OpenCL runtime. - CGOpenCLRuntime &getOpenCLRuntime() { - assert(OpenCLRuntime != nullptr); - return *OpenCLRuntime; - } - - /// Return a reference to the configured OpenMP runtime. - CGOpenMPRuntime &getOpenMPRuntime() { - assert(OpenMPRuntime != nullptr); - return *OpenMPRuntime; - } - - /// Return a reference to the configured CUDA runtime. - CGCUDARuntime &getCUDARuntime() { - assert(CUDARuntime != nullptr); - return *CUDARuntime; - } - - ObjCEntrypoints &getObjCEntrypoints() const { - assert(ObjCData != nullptr); - return *ObjCData; - } - - // Version checking function, used to implement ObjC's @available: - // i32 @__isOSVersionAtLeast(i32, i32, i32) - llvm::Constant *IsOSVersionAtLeastFn = nullptr; - - InstrProfStats &getPGOStats() { return PGOStats; } - llvm::IndexedInstrProfReader *getPGOReader() const { return PGOReader.get(); } - - CoverageMappingModuleGen *getCoverageMapping() const { - return CoverageMapping.get(); - } - - llvm::Constant *getStaticLocalDeclAddress(const VarDecl *D) { - return StaticLocalDeclMap[D]; - } - void setStaticLocalDeclAddress(const VarDecl *D, - llvm::Constant *C) { - StaticLocalDeclMap[D] = C; - } - - llvm::Constant * - getOrCreateStaticVarDecl(const VarDecl &D, - llvm::GlobalValue::LinkageTypes Linkage); - - llvm::GlobalVariable *getStaticLocalDeclGuardAddress(const VarDecl *D) { - return StaticLocalDeclGuardMap[D]; - } - void setStaticLocalDeclGuardAddress(const VarDecl *D, - llvm::GlobalVariable *C) { - StaticLocalDeclGuardMap[D] = C; - } - - bool lookupRepresentativeDecl(StringRef MangledName, - GlobalDecl &Result) const; - - llvm::Constant *getAtomicSetterHelperFnMap(QualType Ty) { - return AtomicSetterHelperFnMap[Ty]; - } - void setAtomicSetterHelperFnMap(QualType Ty, - llvm::Constant *Fn) { - AtomicSetterHelperFnMap[Ty] = Fn; - } - - llvm::Constant *getAtomicGetterHelperFnMap(QualType Ty) { - return AtomicGetterHelperFnMap[Ty]; - } - void setAtomicGetterHelperFnMap(QualType Ty, - llvm::Constant *Fn) { - AtomicGetterHelperFnMap[Ty] = Fn; - } - - llvm::Constant *getTypeDescriptorFromMap(QualType Ty) { - return TypeDescriptorMap[Ty]; - } - void setTypeDescriptorInMap(QualType Ty, llvm::Constant *C) { - TypeDescriptorMap[Ty] = C; - } - - CGDebugInfo *getModuleDebugInfo() { return DebugInfo.get(); } - - llvm::MDNode *getNoObjCARCExceptionsMetadata() { - if (!NoObjCARCExceptionsMetadata) - NoObjCARCExceptionsMetadata = llvm::MDNode::get(getLLVMContext(), None); - return NoObjCARCExceptionsMetadata; - } - - ASTContext &getContext() const { return Context; } - const LangOptions &getLangOpts() const { return LangOpts; } - const HeaderSearchOptions &getHeaderSearchOpts() - const { return HeaderSearchOpts; } - const PreprocessorOptions &getPreprocessorOpts() - const { return PreprocessorOpts; } - const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; } - llvm::Module &getModule() const { return TheModule; } - DiagnosticsEngine &getDiags() const { return Diags; } - const llvm::DataLayout &getDataLayout() const { - return TheModule.getDataLayout(); - } - const TargetInfo &getTarget() const { return Target; } - const llvm::Triple &getTriple() const { return Target.getTriple(); } - bool supportsCOMDAT() const; - void maybeSetTrivialComdat(const Decl &D, llvm::GlobalObject &GO); - - CGCXXABI &getCXXABI() const { return *ABI; } - llvm::LLVMContext &getLLVMContext() { return VMContext; } - - bool shouldUseTBAA() const { return TBAA != nullptr; } - - const TargetCodeGenInfo &getTargetCodeGenInfo(); - - CodeGenTypes &getTypes() { return Types; } - - CodeGenVTables &getVTables() { return VTables; } - - ItaniumVTableContext &getItaniumVTableContext() { - return VTables.getItaniumVTableContext(); - } - - MicrosoftVTableContext &getMicrosoftVTableContext() { - return VTables.getMicrosoftVTableContext(); - } - - CtorList &getGlobalCtors() { return GlobalCtors; } - CtorList &getGlobalDtors() { return GlobalDtors; } - - /// getTBAATypeInfo - Get metadata used to describe accesses to objects of - /// the given type. - llvm::MDNode *getTBAATypeInfo(QualType QTy); - - /// getTBAAAccessInfo - Get TBAA information that describes an access to - /// an object of the given type. - TBAAAccessInfo getTBAAAccessInfo(QualType AccessType); - - /// getTBAAVTablePtrAccessInfo - Get the TBAA information that describes an - /// access to a virtual table pointer. - TBAAAccessInfo getTBAAVTablePtrAccessInfo(llvm::Type *VTablePtrType); - - llvm::MDNode *getTBAAStructInfo(QualType QTy); - - /// getTBAABaseTypeInfo - Get metadata that describes the given base access - /// type. Return null if the type is not suitable for use in TBAA access tags. - llvm::MDNode *getTBAABaseTypeInfo(QualType QTy); - - /// getTBAAAccessTagInfo - Get TBAA tag for a given memory access. - llvm::MDNode *getTBAAAccessTagInfo(TBAAAccessInfo Info); - - /// mergeTBAAInfoForCast - Get merged TBAA information for the purposes of - /// type casts. - TBAAAccessInfo mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo, - TBAAAccessInfo TargetInfo); - - /// mergeTBAAInfoForConditionalOperator - Get merged TBAA information for the - /// purposes of conditional operator. - TBAAAccessInfo mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA, - TBAAAccessInfo InfoB); - - /// mergeTBAAInfoForMemoryTransfer - Get merged TBAA information for the - /// purposes of memory transfer calls. - TBAAAccessInfo mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo DestInfo, - TBAAAccessInfo SrcInfo); - - /// getTBAAInfoForSubobject - Get TBAA information for an access with a given - /// base lvalue. - TBAAAccessInfo getTBAAInfoForSubobject(LValue Base, QualType AccessType) { - if (Base.getTBAAInfo().isMayAlias()) - return TBAAAccessInfo::getMayAliasInfo(); - return getTBAAAccessInfo(AccessType); - } - - bool isTypeConstant(QualType QTy, bool ExcludeCtorDtor); - - bool isPaddedAtomicType(QualType type); - bool isPaddedAtomicType(const AtomicType *type); - - /// DecorateInstructionWithTBAA - Decorate the instruction with a TBAA tag. - void DecorateInstructionWithTBAA(llvm::Instruction *Inst, - TBAAAccessInfo TBAAInfo); - - /// Adds !invariant.barrier !tag to instruction - void DecorateInstructionWithInvariantGroup(llvm::Instruction *I, - const CXXRecordDecl *RD); - - /// Emit the given number of characters as a value of type size_t. - llvm::ConstantInt *getSize(CharUnits numChars); - - /// Set the visibility for the given LLVM GlobalValue. - void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const; - - void setGlobalVisibilityAndLocal(llvm::GlobalValue *GV, - const NamedDecl *D) const; - - void setDSOLocal(llvm::GlobalValue *GV) const; - - void setDLLImportDLLExport(llvm::GlobalValue *GV, GlobalDecl D) const; - void setDLLImportDLLExport(llvm::GlobalValue *GV, const NamedDecl *D) const; - /// Set visibility, dllimport/dllexport and dso_local. - /// This must be called after dllimport/dllexport is set. - void setGVProperties(llvm::GlobalValue *GV, GlobalDecl GD) const; - void setGVProperties(llvm::GlobalValue *GV, const NamedDecl *D) const; - - /// Set the TLS mode for the given LLVM GlobalValue for the thread-local - /// variable declaration D. - void setTLSMode(llvm::GlobalValue *GV, const VarDecl &D) const; - - static llvm::GlobalValue::VisibilityTypes GetLLVMVisibility(Visibility V) { - switch (V) { - case DefaultVisibility: return llvm::GlobalValue::DefaultVisibility; - case HiddenVisibility: return llvm::GlobalValue::HiddenVisibility; - case ProtectedVisibility: return llvm::GlobalValue::ProtectedVisibility; - } - llvm_unreachable("unknown visibility!"); - } - - llvm::Constant *GetAddrOfGlobal(GlobalDecl GD, - ForDefinition_t IsForDefinition - = NotForDefinition); - - /// Will return a global variable of the given type. If a variable with a - /// different type already exists then a new variable with the right type - /// will be created and all uses of the old variable will be replaced with a - /// bitcast to the new variable. - llvm::GlobalVariable * - CreateOrReplaceCXXRuntimeVariable(StringRef Name, llvm::Type *Ty, - llvm::GlobalValue::LinkageTypes Linkage, - unsigned Alignment); - - llvm::Function * - CreateGlobalInitOrDestructFunction(llvm::FunctionType *ty, const Twine &name, - const CGFunctionInfo &FI, - SourceLocation Loc = SourceLocation(), - bool TLS = false); - - /// Return the AST address space of the underlying global variable for D, as - /// determined by its declaration. Normally this is the same as the address - /// space of D's type, but in CUDA, address spaces are associated with - /// declarations, not types. If D is nullptr, return the default address - /// space for global variable. - /// - /// For languages without explicit address spaces, if D has default address - /// space, target-specific global or constant address space may be returned. - LangAS GetGlobalVarAddressSpace(const VarDecl *D); - - /// Return the llvm::Constant for the address of the given global variable. - /// If Ty is non-null and if the global doesn't exist, then it will be created - /// with the specified type instead of whatever the normal requested type - /// would be. If IsForDefinition is true, it is guaranteed that an actual - /// global with type Ty will be returned, not conversion of a variable with - /// the same mangled name but some other type. - llvm::Constant *GetAddrOfGlobalVar(const VarDecl *D, - llvm::Type *Ty = nullptr, - ForDefinition_t IsForDefinition - = NotForDefinition); - - /// Return the AST address space of string literal, which is used to emit - /// the string literal as global variable in LLVM IR. - /// Note: This is not necessarily the address space of the string literal - /// in AST. For address space agnostic language, e.g. C++, string literal - /// in AST is always in default address space. - LangAS getStringLiteralAddressSpace() const; - - /// Return the address of the given function. If Ty is non-null, then this - /// function will use the specified type if it has to create it. - llvm::Constant *GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty = nullptr, - bool ForVTable = false, - bool DontDefer = false, - ForDefinition_t IsForDefinition - = NotForDefinition); - - /// Get the address of the RTTI descriptor for the given type. - llvm::Constant *GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH = false); - - /// Get the address of a uuid descriptor . - ConstantAddress GetAddrOfUuidDescriptor(const CXXUuidofExpr* E); - - /// Get the address of the thunk for the given global decl. - llvm::Constant *GetAddrOfThunk(StringRef Name, llvm::Type *FnTy, - GlobalDecl GD); - - /// Get a reference to the target of VD. - ConstantAddress GetWeakRefReference(const ValueDecl *VD); - - /// Returns the assumed alignment of an opaque pointer to the given class. - CharUnits getClassPointerAlignment(const CXXRecordDecl *CD); - - /// Returns the assumed alignment of a virtual base of a class. - CharUnits getVBaseAlignment(CharUnits DerivedAlign, - const CXXRecordDecl *Derived, - const CXXRecordDecl *VBase); - - /// Given a class pointer with an actual known alignment, and the - /// expected alignment of an object at a dynamic offset w.r.t that - /// pointer, return the alignment to assume at the offset. - CharUnits getDynamicOffsetAlignment(CharUnits ActualAlign, - const CXXRecordDecl *Class, - CharUnits ExpectedTargetAlign); - - CharUnits - computeNonVirtualBaseClassOffset(const CXXRecordDecl *DerivedClass, - CastExpr::path_const_iterator Start, - CastExpr::path_const_iterator End); - - /// Returns the offset from a derived class to a class. Returns null if the - /// offset is 0. - llvm::Constant * - GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl, - CastExpr::path_const_iterator PathBegin, - CastExpr::path_const_iterator PathEnd); - - llvm::FoldingSet<BlockByrefHelpers> ByrefHelpersCache; - - /// Fetches the global unique block count. - int getUniqueBlockCount() { return ++Block.GlobalUniqueCount; } - - /// Fetches the type of a generic block descriptor. - llvm::Type *getBlockDescriptorType(); - - /// The type of a generic block literal. - llvm::Type *getGenericBlockLiteralType(); - - /// Gets the address of a block which requires no captures. - llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, StringRef Name); - - /// Returns the address of a block which requires no caputres, or null if - /// we've yet to emit the block for BE. - llvm::Constant *getAddrOfGlobalBlockIfEmitted(const BlockExpr *BE) { - return EmittedGlobalBlocks.lookup(BE); - } - - /// Notes that BE's global block is available via Addr. Asserts that BE - /// isn't already emitted. - void setAddrOfGlobalBlock(const BlockExpr *BE, llvm::Constant *Addr); - - /// Return a pointer to a constant CFString object for the given string. - ConstantAddress GetAddrOfConstantCFString(const StringLiteral *Literal); - - /// Return a pointer to a constant NSString object for the given string. Or a - /// user defined String object as defined via - /// -fconstant-string-class=class_name option. - ConstantAddress GetAddrOfConstantString(const StringLiteral *Literal); - - /// Return a constant array for the given string. - llvm::Constant *GetConstantArrayFromStringLiteral(const StringLiteral *E); - - /// Return a pointer to a constant array for the given string literal. - ConstantAddress - GetAddrOfConstantStringFromLiteral(const StringLiteral *S, - StringRef Name = ".str"); - - /// Return a pointer to a constant array for the given ObjCEncodeExpr node. - ConstantAddress - GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *); - - /// Returns a pointer to a character array containing the literal and a - /// terminating '\0' character. The result has pointer to array type. - /// - /// \param GlobalName If provided, the name to use for the global (if one is - /// created). - ConstantAddress - GetAddrOfConstantCString(const std::string &Str, - const char *GlobalName = nullptr); - - /// Returns a pointer to a constant global variable for the given file-scope - /// compound literal expression. - ConstantAddress GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr*E); - - /// If it's been emitted already, returns the GlobalVariable corresponding to - /// a compound literal. Otherwise, returns null. - llvm::GlobalVariable * - getAddrOfConstantCompoundLiteralIfEmitted(const CompoundLiteralExpr *E); - - /// Notes that CLE's GlobalVariable is GV. Asserts that CLE isn't already - /// emitted. - void setAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *CLE, - llvm::GlobalVariable *GV); - - /// Returns a pointer to a global variable representing a temporary - /// with static or thread storage duration. - ConstantAddress GetAddrOfGlobalTemporary(const MaterializeTemporaryExpr *E, - const Expr *Inner); - - /// Retrieve the record type that describes the state of an - /// Objective-C fast enumeration loop (for..in). - QualType getObjCFastEnumerationStateType(); - - // Produce code for this constructor/destructor. This method doesn't try - // to apply any ABI rules about which other constructors/destructors - // are needed or if they are alias to each other. - llvm::Function *codegenCXXStructor(const CXXMethodDecl *MD, - StructorType Type); - - /// Return the address of the constructor/destructor of the given type. - llvm::Constant * - getAddrOfCXXStructor(const CXXMethodDecl *MD, StructorType Type, - const CGFunctionInfo *FnInfo = nullptr, - llvm::FunctionType *FnType = nullptr, - bool DontDefer = false, - ForDefinition_t IsForDefinition = NotForDefinition); - - /// Given a builtin id for a function like "__builtin_fabsf", return a - /// Function* for "fabsf". - llvm::Constant *getBuiltinLibFunction(const FunctionDecl *FD, - unsigned BuiltinID); - - llvm::Function *getIntrinsic(unsigned IID, ArrayRef<llvm::Type*> Tys = None); - - /// Emit code for a single top level declaration. - void EmitTopLevelDecl(Decl *D); - - /// Stored a deferred empty coverage mapping for an unused - /// and thus uninstrumented top level declaration. - void AddDeferredUnusedCoverageMapping(Decl *D); - - /// Remove the deferred empty coverage mapping as this - /// declaration is actually instrumented. - void ClearUnusedCoverageMapping(const Decl *D); - - /// Emit all the deferred coverage mappings - /// for the uninstrumented functions. - void EmitDeferredUnusedCoverageMappings(); - - /// Tell the consumer that this variable has been instantiated. - void HandleCXXStaticMemberVarInstantiation(VarDecl *VD); - - /// If the declaration has internal linkage but is inside an - /// extern "C" linkage specification, prepare to emit an alias for it - /// to the expected name. - template<typename SomeDecl> - void MaybeHandleStaticInExternC(const SomeDecl *D, llvm::GlobalValue *GV); - - /// Add a global to a list to be added to the llvm.used metadata. - void addUsedGlobal(llvm::GlobalValue *GV); - - /// Add a global to a list to be added to the llvm.compiler.used metadata. - void addCompilerUsedGlobal(llvm::GlobalValue *GV); - - /// Add a destructor and object to add to the C++ global destructor function. - void AddCXXDtorEntry(llvm::Constant *DtorFn, llvm::Constant *Object) { - CXXGlobalDtors.emplace_back(DtorFn, Object); - } - - /// Create a new runtime function with the specified type and name. - llvm::Constant * - CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, - llvm::AttributeList ExtraAttrs = llvm::AttributeList(), - bool Local = false); - - /// Create a new compiler builtin function with the specified type and name. - llvm::Constant * - CreateBuiltinFunction(llvm::FunctionType *Ty, StringRef Name, - llvm::AttributeList ExtraAttrs = llvm::AttributeList()); - /// Create a new runtime global variable with the specified type and name. - llvm::Constant *CreateRuntimeVariable(llvm::Type *Ty, - StringRef Name); - - ///@name Custom Blocks Runtime Interfaces - ///@{ - - llvm::Constant *getNSConcreteGlobalBlock(); - llvm::Constant *getNSConcreteStackBlock(); - llvm::Constant *getBlockObjectAssign(); - llvm::Constant *getBlockObjectDispose(); - - ///@} - - llvm::Constant *getLLVMLifetimeStartFn(); - llvm::Constant *getLLVMLifetimeEndFn(); - - // Make sure that this type is translated. - void UpdateCompletedType(const TagDecl *TD); - - llvm::Constant *getMemberPointerConstant(const UnaryOperator *e); - - /// Emit type info if type of an expression is a variably modified - /// type. Also emit proper debug info for cast types. - void EmitExplicitCastExprType(const ExplicitCastExpr *E, - CodeGenFunction *CGF = nullptr); - - /// Return the result of value-initializing the given type, i.e. a null - /// expression of the given type. This is usually, but not always, an LLVM - /// null constant. - llvm::Constant *EmitNullConstant(QualType T); - - /// Return a null constant appropriate for zero-initializing a base class with - /// the given type. This is usually, but not always, an LLVM null constant. - llvm::Constant *EmitNullConstantForBase(const CXXRecordDecl *Record); - - /// Emit a general error that something can't be done. - void Error(SourceLocation loc, StringRef error); - - /// Print out an error that codegen doesn't support the specified stmt yet. - void ErrorUnsupported(const Stmt *S, const char *Type); - - /// Print out an error that codegen doesn't support the specified decl yet. - void ErrorUnsupported(const Decl *D, const char *Type); - - /// Set the attributes on the LLVM function for the given decl and function - /// info. This applies attributes necessary for handling the ABI as well as - /// user specified attributes like section. - void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, - const CGFunctionInfo &FI); - - /// Set the LLVM function attributes (sext, zext, etc). - void SetLLVMFunctionAttributes(GlobalDecl GD, const CGFunctionInfo &Info, - llvm::Function *F); - - /// Set the LLVM function attributes which only apply to a function - /// definition. - void SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F); - - /// Return true iff the given type uses 'sret' when used as a return type. - bool ReturnTypeUsesSRet(const CGFunctionInfo &FI); - - /// Return true iff the given type uses an argument slot when 'sret' is used - /// as a return type. - bool ReturnSlotInterferesWithArgs(const CGFunctionInfo &FI); - - /// Return true iff the given type uses 'fpret' when used as a return type. - bool ReturnTypeUsesFPRet(QualType ResultType); - - /// Return true iff the given type uses 'fp2ret' when used as a return type. - bool ReturnTypeUsesFP2Ret(QualType ResultType); - - /// Get the LLVM attributes and calling convention to use for a particular - /// function type. - /// - /// \param Name - The function name. - /// \param Info - The function type information. - /// \param CalleeInfo - The callee information these attributes are being - /// constructed for. If valid, the attributes applied to this decl may - /// contribute to the function attributes and calling convention. - /// \param Attrs [out] - On return, the attribute list to use. - /// \param CallingConv [out] - On return, the LLVM calling convention to use. - void ConstructAttributeList(StringRef Name, const CGFunctionInfo &Info, - CGCalleeInfo CalleeInfo, - llvm::AttributeList &Attrs, unsigned &CallingConv, - bool AttrOnCallSite); - - /// Adds attributes to F according to our CodeGenOptions and LangOptions, as - /// though we had emitted it ourselves. We remove any attributes on F that - /// conflict with the attributes we add here. - /// - /// This is useful for adding attrs to bitcode modules that you want to link - /// with but don't control, such as CUDA's libdevice. When linking with such - /// a bitcode library, you might want to set e.g. its functions' - /// "unsafe-fp-math" attribute to match the attr of the functions you're - /// codegen'ing. Otherwise, LLVM will interpret the bitcode module's lack of - /// unsafe-fp-math attrs as tantamount to unsafe-fp-math=false, and then LLVM - /// will propagate unsafe-fp-math=false up to every transitive caller of a - /// function in the bitcode library! - /// - /// With the exception of fast-math attrs, this will only make the attributes - /// on the function more conservative. But it's unsafe to call this on a - /// function which relies on particular fast-math attributes for correctness. - /// It's up to you to ensure that this is safe. - void AddDefaultFnAttrs(llvm::Function &F); - - /// Parses the target attributes passed in, and returns only the ones that are - /// valid feature names. - TargetAttr::ParsedTargetAttr filterFunctionTargetAttrs(const TargetAttr *TD); - - // Fills in the supplied string map with the set of target features for the - // passed in function. - void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, GlobalDecl GD); - - StringRef getMangledName(GlobalDecl GD); - StringRef getBlockMangledName(GlobalDecl GD, const BlockDecl *BD); - - void EmitTentativeDefinition(const VarDecl *D); - - void EmitVTable(CXXRecordDecl *Class); - - void RefreshTypeCacheForClass(const CXXRecordDecl *Class); - - /// Appends Opts to the "llvm.linker.options" metadata value. - void AppendLinkerOptions(StringRef Opts); - - /// Appends a detect mismatch command to the linker options. - void AddDetectMismatch(StringRef Name, StringRef Value); - - /// Appends a dependent lib to the "llvm.linker.options" metadata - /// value. - void AddDependentLib(StringRef Lib); - - void AddELFLibDirective(StringRef Lib); - - llvm::GlobalVariable::LinkageTypes getFunctionLinkage(GlobalDecl GD); - - void setFunctionLinkage(GlobalDecl GD, llvm::Function *F) { - F->setLinkage(getFunctionLinkage(GD)); - } - - /// Return the appropriate linkage for the vtable, VTT, and type information - /// of the given class. - llvm::GlobalVariable::LinkageTypes getVTableLinkage(const CXXRecordDecl *RD); - - /// Return the store size, in character units, of the given LLVM type. - CharUnits GetTargetTypeStoreSize(llvm::Type *Ty) const; - - /// Returns LLVM linkage for a declarator. - llvm::GlobalValue::LinkageTypes - getLLVMLinkageForDeclarator(const DeclaratorDecl *D, GVALinkage Linkage, - bool IsConstantVariable); - - /// Returns LLVM linkage for a declarator. - llvm::GlobalValue::LinkageTypes - getLLVMLinkageVarDefinition(const VarDecl *VD, bool IsConstant); - - /// Emit all the global annotations. - void EmitGlobalAnnotations(); - - /// Emit an annotation string. - llvm::Constant *EmitAnnotationString(StringRef Str); - - /// Emit the annotation's translation unit. - llvm::Constant *EmitAnnotationUnit(SourceLocation Loc); - - /// Emit the annotation line number. - llvm::Constant *EmitAnnotationLineNo(SourceLocation L); - - /// Generate the llvm::ConstantStruct which contains the annotation - /// information for a given GlobalValue. The annotation struct is - /// {i8 *, i8 *, i8 *, i32}. The first field is a constant expression, the - /// GlobalValue being annotated. The second field is the constant string - /// created from the AnnotateAttr's annotation. The third field is a constant - /// string containing the name of the translation unit. The fourth field is - /// the line number in the file of the annotated value declaration. - llvm::Constant *EmitAnnotateAttr(llvm::GlobalValue *GV, - const AnnotateAttr *AA, - SourceLocation L); - - /// Add global annotations that are set on D, for the global GV. Those - /// annotations are emitted during finalization of the LLVM code. - void AddGlobalAnnotations(const ValueDecl *D, llvm::GlobalValue *GV); - - bool isInSanitizerBlacklist(SanitizerMask Kind, llvm::Function *Fn, - SourceLocation Loc) const; - - bool isInSanitizerBlacklist(llvm::GlobalVariable *GV, SourceLocation Loc, - QualType Ty, - StringRef Category = StringRef()) const; - - /// Imbue XRay attributes to a function, applying the always/never attribute - /// lists in the process. Returns true if we did imbue attributes this way, - /// false otherwise. - bool imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc, - StringRef Category = StringRef()) const; - - SanitizerMetadata *getSanitizerMetadata() { - return SanitizerMD.get(); - } - - void addDeferredVTable(const CXXRecordDecl *RD) { - DeferredVTables.push_back(RD); - } - - /// Emit code for a single global function or var decl. Forward declarations - /// are emitted lazily. - void EmitGlobal(GlobalDecl D); - - bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D); - - llvm::GlobalValue *GetGlobalValue(StringRef Ref); - - /// Set attributes which are common to any form of a global definition (alias, - /// Objective-C method, function, global variable). - /// - /// NOTE: This should only be called for definitions. - void SetCommonAttributes(GlobalDecl GD, llvm::GlobalValue *GV); - - void addReplacement(StringRef Name, llvm::Constant *C); - - void addGlobalValReplacement(llvm::GlobalValue *GV, llvm::Constant *C); - - /// Emit a code for threadprivate directive. - /// \param D Threadprivate declaration. - void EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D); - - /// Emit a code for declare reduction construct. - void EmitOMPDeclareReduction(const OMPDeclareReductionDecl *D, - CodeGenFunction *CGF = nullptr); - - /// Emit a code for requires directive. - /// \param D Requires declaration - void EmitOMPRequiresDecl(const OMPRequiresDecl *D); - - /// Returns whether the given record has hidden LTO visibility and therefore - /// may participate in (single-module) CFI and whole-program vtable - /// optimization. - bool HasHiddenLTOVisibility(const CXXRecordDecl *RD); - - /// Emit type metadata for the given vtable using the given layout. - void EmitVTableTypeMetadata(llvm::GlobalVariable *VTable, - const VTableLayout &VTLayout); - - /// Generate a cross-DSO type identifier for MD. - llvm::ConstantInt *CreateCrossDsoCfiTypeId(llvm::Metadata *MD); - - /// Create a metadata identifier for the given type. This may either be an - /// MDString (for external identifiers) or a distinct unnamed MDNode (for - /// internal identifiers). - llvm::Metadata *CreateMetadataIdentifierForType(QualType T); - - /// Create a metadata identifier that is intended to be used to check virtual - /// calls via a member function pointer. - llvm::Metadata *CreateMetadataIdentifierForVirtualMemPtrType(QualType T); - - /// Create a metadata identifier for the generalization of the given type. - /// This may either be an MDString (for external identifiers) or a distinct - /// unnamed MDNode (for internal identifiers). - llvm::Metadata *CreateMetadataIdentifierGeneralized(QualType T); - - /// Create and attach type metadata to the given function. - void CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD, - llvm::Function *F); - - /// Returns whether this module needs the "all-vtables" type identifier. - bool NeedAllVtablesTypeId() const; - - /// Create and attach type metadata for the given vtable. - void AddVTableTypeMetadata(llvm::GlobalVariable *VTable, CharUnits Offset, - const CXXRecordDecl *RD); - - /// Return a vector of most-base classes for RD. This is used to implement - /// control flow integrity checks for member function pointers. - /// - /// A most-base class of a class C is defined as a recursive base class of C, - /// including C itself, that does not have any bases. - std::vector<const CXXRecordDecl *> - getMostBaseClasses(const CXXRecordDecl *RD); - - /// Get the declaration of std::terminate for the platform. - llvm::Constant *getTerminateFn(); - - llvm::SanitizerStatReport &getSanStats(); - - llvm::Value * - createOpenCLIntToSamplerConversion(const Expr *E, CodeGenFunction &CGF); - - /// Get target specific null pointer. - /// \param T is the LLVM type of the null pointer. - /// \param QT is the clang QualType of the null pointer. - llvm::Constant *getNullPointer(llvm::PointerType *T, QualType QT); - -private: - llvm::Constant *GetOrCreateLLVMFunction( - StringRef MangledName, llvm::Type *Ty, GlobalDecl D, bool ForVTable, - bool DontDefer = false, bool IsThunk = false, - llvm::AttributeList ExtraAttrs = llvm::AttributeList(), - ForDefinition_t IsForDefinition = NotForDefinition); - - llvm::Constant *GetOrCreateMultiVersionResolver(GlobalDecl GD, - llvm::Type *DeclTy, - const FunctionDecl *FD); - void UpdateMultiVersionNames(GlobalDecl GD, const FunctionDecl *FD); - - llvm::Constant *GetOrCreateLLVMGlobal(StringRef MangledName, - llvm::PointerType *PTy, - const VarDecl *D, - ForDefinition_t IsForDefinition - = NotForDefinition); - - bool GetCPUAndFeaturesAttributes(GlobalDecl GD, - llvm::AttrBuilder &AttrBuilder); - void setNonAliasAttributes(GlobalDecl GD, llvm::GlobalObject *GO); - - /// Set function attributes for a function declaration. - void SetFunctionAttributes(GlobalDecl GD, llvm::Function *F, - bool IsIncompleteFunction, bool IsThunk); - - void EmitGlobalDefinition(GlobalDecl D, llvm::GlobalValue *GV = nullptr); - - void EmitGlobalFunctionDefinition(GlobalDecl GD, llvm::GlobalValue *GV); - void EmitMultiVersionFunctionDefinition(GlobalDecl GD, llvm::GlobalValue *GV); - - void EmitGlobalVarDefinition(const VarDecl *D, bool IsTentative = false); - void EmitAliasDefinition(GlobalDecl GD); - void emitIFuncDefinition(GlobalDecl GD); - void emitCPUDispatchDefinition(GlobalDecl GD); - void EmitObjCPropertyImplementations(const ObjCImplementationDecl *D); - void EmitObjCIvarInitializations(ObjCImplementationDecl *D); - - // C++ related functions. - - void EmitDeclContext(const DeclContext *DC); - void EmitLinkageSpec(const LinkageSpecDecl *D); - - /// Emit the function that initializes C++ thread_local variables. - void EmitCXXThreadLocalInitFunc(); - - /// Emit the function that initializes C++ globals. - void EmitCXXGlobalInitFunc(); - - /// Emit the function that destroys C++ globals. - void EmitCXXGlobalDtorFunc(); - - /// Emit the function that initializes the specified global (if PerformInit is - /// true) and registers its destructor. - void EmitCXXGlobalVarDeclInitFunc(const VarDecl *D, - llvm::GlobalVariable *Addr, - bool PerformInit); - - void EmitPointerToInitFunc(const VarDecl *VD, llvm::GlobalVariable *Addr, - llvm::Function *InitFunc, InitSegAttr *ISA); - - // FIXME: Hardcoding priority here is gross. - void AddGlobalCtor(llvm::Function *Ctor, int Priority = 65535, - llvm::Constant *AssociatedData = nullptr); - void AddGlobalDtor(llvm::Function *Dtor, int Priority = 65535); - - /// EmitCtorList - Generates a global array of functions and priorities using - /// the given list and name. This array will have appending linkage and is - /// suitable for use as a LLVM constructor or destructor array. Clears Fns. - void EmitCtorList(CtorList &Fns, const char *GlobalName); - - /// Emit any needed decls for which code generation was deferred. - void EmitDeferred(); - - /// Try to emit external vtables as available_externally if they have emitted - /// all inlined virtual functions. It runs after EmitDeferred() and therefore - /// is not allowed to create new references to things that need to be emitted - /// lazily. - void EmitVTablesOpportunistically(); - - /// Call replaceAllUsesWith on all pairs in Replacements. - void applyReplacements(); - - /// Call replaceAllUsesWith on all pairs in GlobalValReplacements. - void applyGlobalValReplacements(); - - void checkAliases(); - - std::map<int, llvm::TinyPtrVector<llvm::Function *>> DtorsUsingAtExit; - - /// Register functions annotated with __attribute__((destructor)) using - /// __cxa_atexit, if it is available, or atexit otherwise. - void registerGlobalDtorsWithAtExit(); - - void emitMultiVersionFunctions(); - - /// Emit any vtables which we deferred and still have a use for. - void EmitDeferredVTables(); - - /// Emit a dummy function that reference a CoreFoundation symbol when - /// @available is used on Darwin. - void emitAtAvailableLinkGuard(); - - /// Emit the llvm.used and llvm.compiler.used metadata. - void emitLLVMUsed(); - - /// Emit the link options introduced by imported modules. - void EmitModuleLinkOptions(); - - /// Emit aliases for internal-linkage declarations inside "C" language - /// linkage specifications, giving them the "expected" name where possible. - void EmitStaticExternCAliases(); - - void EmitDeclMetadata(); - - /// Emit the Clang version as llvm.ident metadata. - void EmitVersionIdentMetadata(); - - /// Emit the Clang commandline as llvm.commandline metadata. - void EmitCommandLineMetadata(); - - /// Emits target specific Metadata for global declarations. - void EmitTargetMetadata(); - - /// Emits OpenCL specific Metadata e.g. OpenCL version. - void EmitOpenCLMetadata(); - - /// Emit the llvm.gcov metadata used to tell LLVM where to emit the .gcno and - /// .gcda files in a way that persists in .bc files. - void EmitCoverageFile(); - - /// Emits the initializer for a uuidof string. - llvm::Constant *EmitUuidofInitializer(StringRef uuidstr); - - /// Determine whether the definition must be emitted; if this returns \c - /// false, the definition can be emitted lazily if it's used. - bool MustBeEmitted(const ValueDecl *D); - - /// Determine whether the definition can be emitted eagerly, or should be - /// delayed until the end of the translation unit. This is relevant for - /// definitions whose linkage can change, e.g. implicit function instantions - /// which may later be explicitly instantiated. - bool MayBeEmittedEagerly(const ValueDecl *D); - - /// Check whether we can use a "simpler", more core exceptions personality - /// function. - void SimplifyPersonality(); - - /// Helper function for ConstructAttributeList and AddDefaultFnAttrs. - /// Constructs an AttrList for a function with the given properties. - void ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone, - bool AttrOnCallSite, - llvm::AttrBuilder &FuncAttrs); - - llvm::Metadata *CreateMetadataIdentifierImpl(QualType T, MetadataTypeMap &Map, - StringRef Suffix); -}; - -} // end namespace CodeGen -} // end namespace clang - -#endif // LLVM_CLANG_LIB_CODEGEN_CODEGENMODULE_H diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp deleted file mode 100644 index 776060743a6..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp +++ /dev/null @@ -1,1059 +0,0 @@ -//===--- CodeGenPGO.cpp - PGO Instrumentation for LLVM CodeGen --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Instrumentation-based profile-guided optimization -// -//===----------------------------------------------------------------------===// - -#include "CodeGenPGO.h" -#include "CodeGenFunction.h" -#include "CoverageMappingGen.h" -#include "clang/AST/RecursiveASTVisitor.h" -#include "clang/AST/StmtVisitor.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/MDBuilder.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/MD5.h" - -static llvm::cl::opt<bool> - EnableValueProfiling("enable-value-profiling", llvm::cl::ZeroOrMore, - llvm::cl::desc("Enable value profiling"), - llvm::cl::Hidden, llvm::cl::init(false)); - -using namespace clang; -using namespace CodeGen; - -void CodeGenPGO::setFuncName(StringRef Name, - llvm::GlobalValue::LinkageTypes Linkage) { - llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader(); - FuncName = llvm::getPGOFuncName( - Name, Linkage, CGM.getCodeGenOpts().MainFileName, - PGOReader ? PGOReader->getVersion() : llvm::IndexedInstrProf::Version); - - // If we're generating a profile, create a variable for the name. - if (CGM.getCodeGenOpts().hasProfileClangInstr()) - FuncNameVar = llvm::createPGOFuncNameVar(CGM.getModule(), Linkage, FuncName); -} - -void CodeGenPGO::setFuncName(llvm::Function *Fn) { - setFuncName(Fn->getName(), Fn->getLinkage()); - // Create PGOFuncName meta data. - llvm::createPGOFuncNameMetadata(*Fn, FuncName); -} - -/// The version of the PGO hash algorithm. -enum PGOHashVersion : unsigned { - PGO_HASH_V1, - PGO_HASH_V2, - - // Keep this set to the latest hash version. - PGO_HASH_LATEST = PGO_HASH_V2 -}; - -namespace { -/// Stable hasher for PGO region counters. -/// -/// PGOHash produces a stable hash of a given function's control flow. -/// -/// Changing the output of this hash will invalidate all previously generated -/// profiles -- i.e., don't do it. -/// -/// \note When this hash does eventually change (years?), we still need to -/// support old hashes. We'll need to pull in the version number from the -/// profile data format and use the matching hash function. -class PGOHash { - uint64_t Working; - unsigned Count; - PGOHashVersion HashVersion; - llvm::MD5 MD5; - - static const int NumBitsPerType = 6; - static const unsigned NumTypesPerWord = sizeof(uint64_t) * 8 / NumBitsPerType; - static const unsigned TooBig = 1u << NumBitsPerType; - -public: - /// Hash values for AST nodes. - /// - /// Distinct values for AST nodes that have region counters attached. - /// - /// These values must be stable. All new members must be added at the end, - /// and no members should be removed. Changing the enumeration value for an - /// AST node will affect the hash of every function that contains that node. - enum HashType : unsigned char { - None = 0, - LabelStmt = 1, - WhileStmt, - DoStmt, - ForStmt, - CXXForRangeStmt, - ObjCForCollectionStmt, - SwitchStmt, - CaseStmt, - DefaultStmt, - IfStmt, - CXXTryStmt, - CXXCatchStmt, - ConditionalOperator, - BinaryOperatorLAnd, - BinaryOperatorLOr, - BinaryConditionalOperator, - // The preceding values are available with PGO_HASH_V1. - - EndOfScope, - IfThenBranch, - IfElseBranch, - GotoStmt, - IndirectGotoStmt, - BreakStmt, - ContinueStmt, - ReturnStmt, - ThrowExpr, - UnaryOperatorLNot, - BinaryOperatorLT, - BinaryOperatorGT, - BinaryOperatorLE, - BinaryOperatorGE, - BinaryOperatorEQ, - BinaryOperatorNE, - // The preceding values are available with PGO_HASH_V2. - - // Keep this last. It's for the static assert that follows. - LastHashType - }; - static_assert(LastHashType <= TooBig, "Too many types in HashType"); - - PGOHash(PGOHashVersion HashVersion) - : Working(0), Count(0), HashVersion(HashVersion), MD5() {} - void combine(HashType Type); - uint64_t finalize(); - PGOHashVersion getHashVersion() const { return HashVersion; } -}; -const int PGOHash::NumBitsPerType; -const unsigned PGOHash::NumTypesPerWord; -const unsigned PGOHash::TooBig; - -/// Get the PGO hash version used in the given indexed profile. -static PGOHashVersion getPGOHashVersion(llvm::IndexedInstrProfReader *PGOReader, - CodeGenModule &CGM) { - if (PGOReader->getVersion() <= 4) - return PGO_HASH_V1; - return PGO_HASH_V2; -} - -/// A RecursiveASTVisitor that fills a map of statements to PGO counters. -struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> { - using Base = RecursiveASTVisitor<MapRegionCounters>; - - /// The next counter value to assign. - unsigned NextCounter; - /// The function hash. - PGOHash Hash; - /// The map of statements to counters. - llvm::DenseMap<const Stmt *, unsigned> &CounterMap; - - MapRegionCounters(PGOHashVersion HashVersion, - llvm::DenseMap<const Stmt *, unsigned> &CounterMap) - : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap) {} - - // Blocks and lambdas are handled as separate functions, so we need not - // traverse them in the parent context. - bool TraverseBlockExpr(BlockExpr *BE) { return true; } - bool TraverseLambdaExpr(LambdaExpr *LE) { - // Traverse the captures, but not the body. - for (const auto &C : zip(LE->captures(), LE->capture_inits())) - TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C)); - return true; - } - bool TraverseCapturedStmt(CapturedStmt *CS) { return true; } - - bool VisitDecl(const Decl *D) { - switch (D->getKind()) { - default: - break; - case Decl::Function: - case Decl::CXXMethod: - case Decl::CXXConstructor: - case Decl::CXXDestructor: - case Decl::CXXConversion: - case Decl::ObjCMethod: - case Decl::Block: - case Decl::Captured: - CounterMap[D->getBody()] = NextCounter++; - break; - } - return true; - } - - /// If \p S gets a fresh counter, update the counter mappings. Return the - /// V1 hash of \p S. - PGOHash::HashType updateCounterMappings(Stmt *S) { - auto Type = getHashType(PGO_HASH_V1, S); - if (Type != PGOHash::None) - CounterMap[S] = NextCounter++; - return Type; - } - - /// Include \p S in the function hash. - bool VisitStmt(Stmt *S) { - auto Type = updateCounterMappings(S); - if (Hash.getHashVersion() != PGO_HASH_V1) - Type = getHashType(Hash.getHashVersion(), S); - if (Type != PGOHash::None) - Hash.combine(Type); - return true; - } - - bool TraverseIfStmt(IfStmt *If) { - // If we used the V1 hash, use the default traversal. - if (Hash.getHashVersion() == PGO_HASH_V1) - return Base::TraverseIfStmt(If); - - // Otherwise, keep track of which branch we're in while traversing. - VisitStmt(If); - for (Stmt *CS : If->children()) { - if (!CS) - continue; - if (CS == If->getThen()) - Hash.combine(PGOHash::IfThenBranch); - else if (CS == If->getElse()) - Hash.combine(PGOHash::IfElseBranch); - TraverseStmt(CS); - } - Hash.combine(PGOHash::EndOfScope); - return true; - } - -// If the statement type \p N is nestable, and its nesting impacts profile -// stability, define a custom traversal which tracks the end of the statement -// in the hash (provided we're not using the V1 hash). -#define DEFINE_NESTABLE_TRAVERSAL(N) \ - bool Traverse##N(N *S) { \ - Base::Traverse##N(S); \ - if (Hash.getHashVersion() != PGO_HASH_V1) \ - Hash.combine(PGOHash::EndOfScope); \ - return true; \ - } - - DEFINE_NESTABLE_TRAVERSAL(WhileStmt) - DEFINE_NESTABLE_TRAVERSAL(DoStmt) - DEFINE_NESTABLE_TRAVERSAL(ForStmt) - DEFINE_NESTABLE_TRAVERSAL(CXXForRangeStmt) - DEFINE_NESTABLE_TRAVERSAL(ObjCForCollectionStmt) - DEFINE_NESTABLE_TRAVERSAL(CXXTryStmt) - DEFINE_NESTABLE_TRAVERSAL(CXXCatchStmt) - - /// Get version \p HashVersion of the PGO hash for \p S. - PGOHash::HashType getHashType(PGOHashVersion HashVersion, const Stmt *S) { - switch (S->getStmtClass()) { - default: - break; - case Stmt::LabelStmtClass: - return PGOHash::LabelStmt; - case Stmt::WhileStmtClass: - return PGOHash::WhileStmt; - case Stmt::DoStmtClass: - return PGOHash::DoStmt; - case Stmt::ForStmtClass: - return PGOHash::ForStmt; - case Stmt::CXXForRangeStmtClass: - return PGOHash::CXXForRangeStmt; - case Stmt::ObjCForCollectionStmtClass: - return PGOHash::ObjCForCollectionStmt; - case Stmt::SwitchStmtClass: - return PGOHash::SwitchStmt; - case Stmt::CaseStmtClass: - return PGOHash::CaseStmt; - case Stmt::DefaultStmtClass: - return PGOHash::DefaultStmt; - case Stmt::IfStmtClass: - return PGOHash::IfStmt; - case Stmt::CXXTryStmtClass: - return PGOHash::CXXTryStmt; - case Stmt::CXXCatchStmtClass: - return PGOHash::CXXCatchStmt; - case Stmt::ConditionalOperatorClass: - return PGOHash::ConditionalOperator; - case Stmt::BinaryConditionalOperatorClass: - return PGOHash::BinaryConditionalOperator; - case Stmt::BinaryOperatorClass: { - const BinaryOperator *BO = cast<BinaryOperator>(S); - if (BO->getOpcode() == BO_LAnd) - return PGOHash::BinaryOperatorLAnd; - if (BO->getOpcode() == BO_LOr) - return PGOHash::BinaryOperatorLOr; - if (HashVersion == PGO_HASH_V2) { - switch (BO->getOpcode()) { - default: - break; - case BO_LT: - return PGOHash::BinaryOperatorLT; - case BO_GT: - return PGOHash::BinaryOperatorGT; - case BO_LE: - return PGOHash::BinaryOperatorLE; - case BO_GE: - return PGOHash::BinaryOperatorGE; - case BO_EQ: - return PGOHash::BinaryOperatorEQ; - case BO_NE: - return PGOHash::BinaryOperatorNE; - } - } - break; - } - } - - if (HashVersion == PGO_HASH_V2) { - switch (S->getStmtClass()) { - default: - break; - case Stmt::GotoStmtClass: - return PGOHash::GotoStmt; - case Stmt::IndirectGotoStmtClass: - return PGOHash::IndirectGotoStmt; - case Stmt::BreakStmtClass: - return PGOHash::BreakStmt; - case Stmt::ContinueStmtClass: - return PGOHash::ContinueStmt; - case Stmt::ReturnStmtClass: - return PGOHash::ReturnStmt; - case Stmt::CXXThrowExprClass: - return PGOHash::ThrowExpr; - case Stmt::UnaryOperatorClass: { - const UnaryOperator *UO = cast<UnaryOperator>(S); - if (UO->getOpcode() == UO_LNot) - return PGOHash::UnaryOperatorLNot; - break; - } - } - } - - return PGOHash::None; - } -}; - -/// A StmtVisitor that propagates the raw counts through the AST and -/// records the count at statements where the value may change. -struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> { - /// PGO state. - CodeGenPGO &PGO; - - /// A flag that is set when the current count should be recorded on the - /// next statement, such as at the exit of a loop. - bool RecordNextStmtCount; - - /// The count at the current location in the traversal. - uint64_t CurrentCount; - - /// The map of statements to count values. - llvm::DenseMap<const Stmt *, uint64_t> &CountMap; - - /// BreakContinueStack - Keep counts of breaks and continues inside loops. - struct BreakContinue { - uint64_t BreakCount; - uint64_t ContinueCount; - BreakContinue() : BreakCount(0), ContinueCount(0) {} - }; - SmallVector<BreakContinue, 8> BreakContinueStack; - - ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &CountMap, - CodeGenPGO &PGO) - : PGO(PGO), RecordNextStmtCount(false), CountMap(CountMap) {} - - void RecordStmtCount(const Stmt *S) { - if (RecordNextStmtCount) { - CountMap[S] = CurrentCount; - RecordNextStmtCount = false; - } - } - - /// Set and return the current count. - uint64_t setCount(uint64_t Count) { - CurrentCount = Count; - return Count; - } - - void VisitStmt(const Stmt *S) { - RecordStmtCount(S); - for (const Stmt *Child : S->children()) - if (Child) - this->Visit(Child); - } - - void VisitFunctionDecl(const FunctionDecl *D) { - // Counter tracks entry to the function body. - uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); - CountMap[D->getBody()] = BodyCount; - Visit(D->getBody()); - } - - // Skip lambda expressions. We visit these as FunctionDecls when we're - // generating them and aren't interested in the body when generating a - // parent context. - void VisitLambdaExpr(const LambdaExpr *LE) {} - - void VisitCapturedDecl(const CapturedDecl *D) { - // Counter tracks entry to the capture body. - uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); - CountMap[D->getBody()] = BodyCount; - Visit(D->getBody()); - } - - void VisitObjCMethodDecl(const ObjCMethodDecl *D) { - // Counter tracks entry to the method body. - uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); - CountMap[D->getBody()] = BodyCount; - Visit(D->getBody()); - } - - void VisitBlockDecl(const BlockDecl *D) { - // Counter tracks entry to the block body. - uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); - CountMap[D->getBody()] = BodyCount; - Visit(D->getBody()); - } - - void VisitReturnStmt(const ReturnStmt *S) { - RecordStmtCount(S); - if (S->getRetValue()) - Visit(S->getRetValue()); - CurrentCount = 0; - RecordNextStmtCount = true; - } - - void VisitCXXThrowExpr(const CXXThrowExpr *E) { - RecordStmtCount(E); - if (E->getSubExpr()) - Visit(E->getSubExpr()); - CurrentCount = 0; - RecordNextStmtCount = true; - } - - void VisitGotoStmt(const GotoStmt *S) { - RecordStmtCount(S); - CurrentCount = 0; - RecordNextStmtCount = true; - } - - void VisitLabelStmt(const LabelStmt *S) { - RecordNextStmtCount = false; - // Counter tracks the block following the label. - uint64_t BlockCount = setCount(PGO.getRegionCount(S)); - CountMap[S] = BlockCount; - Visit(S->getSubStmt()); - } - - void VisitBreakStmt(const BreakStmt *S) { - RecordStmtCount(S); - assert(!BreakContinueStack.empty() && "break not in a loop or switch!"); - BreakContinueStack.back().BreakCount += CurrentCount; - CurrentCount = 0; - RecordNextStmtCount = true; - } - - void VisitContinueStmt(const ContinueStmt *S) { - RecordStmtCount(S); - assert(!BreakContinueStack.empty() && "continue stmt not in a loop!"); - BreakContinueStack.back().ContinueCount += CurrentCount; - CurrentCount = 0; - RecordNextStmtCount = true; - } - - void VisitWhileStmt(const WhileStmt *S) { - RecordStmtCount(S); - uint64_t ParentCount = CurrentCount; - - BreakContinueStack.push_back(BreakContinue()); - // Visit the body region first so the break/continue adjustments can be - // included when visiting the condition. - uint64_t BodyCount = setCount(PGO.getRegionCount(S)); - CountMap[S->getBody()] = CurrentCount; - Visit(S->getBody()); - uint64_t BackedgeCount = CurrentCount; - - // ...then go back and propagate counts through the condition. The count - // at the start of the condition is the sum of the incoming edges, - // the backedge from the end of the loop body, and the edges from - // continue statements. - BreakContinue BC = BreakContinueStack.pop_back_val(); - uint64_t CondCount = - setCount(ParentCount + BackedgeCount + BC.ContinueCount); - CountMap[S->getCond()] = CondCount; - Visit(S->getCond()); - setCount(BC.BreakCount + CondCount - BodyCount); - RecordNextStmtCount = true; - } - - void VisitDoStmt(const DoStmt *S) { - RecordStmtCount(S); - uint64_t LoopCount = PGO.getRegionCount(S); - - BreakContinueStack.push_back(BreakContinue()); - // The count doesn't include the fallthrough from the parent scope. Add it. - uint64_t BodyCount = setCount(LoopCount + CurrentCount); - CountMap[S->getBody()] = BodyCount; - Visit(S->getBody()); - uint64_t BackedgeCount = CurrentCount; - - BreakContinue BC = BreakContinueStack.pop_back_val(); - // The count at the start of the condition is equal to the count at the - // end of the body, plus any continues. - uint64_t CondCount = setCount(BackedgeCount + BC.ContinueCount); - CountMap[S->getCond()] = CondCount; - Visit(S->getCond()); - setCount(BC.BreakCount + CondCount - LoopCount); - RecordNextStmtCount = true; - } - - void VisitForStmt(const ForStmt *S) { - RecordStmtCount(S); - if (S->getInit()) - Visit(S->getInit()); - - uint64_t ParentCount = CurrentCount; - - BreakContinueStack.push_back(BreakContinue()); - // Visit the body region first. (This is basically the same as a while - // loop; see further comments in VisitWhileStmt.) - uint64_t BodyCount = setCount(PGO.getRegionCount(S)); - CountMap[S->getBody()] = BodyCount; - Visit(S->getBody()); - uint64_t BackedgeCount = CurrentCount; - BreakContinue BC = BreakContinueStack.pop_back_val(); - - // The increment is essentially part of the body but it needs to include - // the count for all the continue statements. - if (S->getInc()) { - uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount); - CountMap[S->getInc()] = IncCount; - Visit(S->getInc()); - } - - // ...then go back and propagate counts through the condition. - uint64_t CondCount = - setCount(ParentCount + BackedgeCount + BC.ContinueCount); - if (S->getCond()) { - CountMap[S->getCond()] = CondCount; - Visit(S->getCond()); - } - setCount(BC.BreakCount + CondCount - BodyCount); - RecordNextStmtCount = true; - } - - void VisitCXXForRangeStmt(const CXXForRangeStmt *S) { - RecordStmtCount(S); - if (S->getInit()) - Visit(S->getInit()); - Visit(S->getLoopVarStmt()); - Visit(S->getRangeStmt()); - Visit(S->getBeginStmt()); - Visit(S->getEndStmt()); - - uint64_t ParentCount = CurrentCount; - BreakContinueStack.push_back(BreakContinue()); - // Visit the body region first. (This is basically the same as a while - // loop; see further comments in VisitWhileStmt.) - uint64_t BodyCount = setCount(PGO.getRegionCount(S)); - CountMap[S->getBody()] = BodyCount; - Visit(S->getBody()); - uint64_t BackedgeCount = CurrentCount; - BreakContinue BC = BreakContinueStack.pop_back_val(); - - // The increment is essentially part of the body but it needs to include - // the count for all the continue statements. - uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount); - CountMap[S->getInc()] = IncCount; - Visit(S->getInc()); - - // ...then go back and propagate counts through the condition. - uint64_t CondCount = - setCount(ParentCount + BackedgeCount + BC.ContinueCount); - CountMap[S->getCond()] = CondCount; - Visit(S->getCond()); - setCount(BC.BreakCount + CondCount - BodyCount); - RecordNextStmtCount = true; - } - - void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) { - RecordStmtCount(S); - Visit(S->getElement()); - uint64_t ParentCount = CurrentCount; - BreakContinueStack.push_back(BreakContinue()); - // Counter tracks the body of the loop. - uint64_t BodyCount = setCount(PGO.getRegionCount(S)); - CountMap[S->getBody()] = BodyCount; - Visit(S->getBody()); - uint64_t BackedgeCount = CurrentCount; - BreakContinue BC = BreakContinueStack.pop_back_val(); - - setCount(BC.BreakCount + ParentCount + BackedgeCount + BC.ContinueCount - - BodyCount); - RecordNextStmtCount = true; - } - - void VisitSwitchStmt(const SwitchStmt *S) { - RecordStmtCount(S); - if (S->getInit()) - Visit(S->getInit()); - Visit(S->getCond()); - CurrentCount = 0; - BreakContinueStack.push_back(BreakContinue()); - Visit(S->getBody()); - // If the switch is inside a loop, add the continue counts. - BreakContinue BC = BreakContinueStack.pop_back_val(); - if (!BreakContinueStack.empty()) - BreakContinueStack.back().ContinueCount += BC.ContinueCount; - // Counter tracks the exit block of the switch. - setCount(PGO.getRegionCount(S)); - RecordNextStmtCount = true; - } - - void VisitSwitchCase(const SwitchCase *S) { - RecordNextStmtCount = false; - // Counter for this particular case. This counts only jumps from the - // switch header and does not include fallthrough from the case before - // this one. - uint64_t CaseCount = PGO.getRegionCount(S); - setCount(CurrentCount + CaseCount); - // We need the count without fallthrough in the mapping, so it's more useful - // for branch probabilities. - CountMap[S] = CaseCount; - RecordNextStmtCount = true; - Visit(S->getSubStmt()); - } - - void VisitIfStmt(const IfStmt *S) { - RecordStmtCount(S); - uint64_t ParentCount = CurrentCount; - if (S->getInit()) - Visit(S->getInit()); - Visit(S->getCond()); - - // Counter tracks the "then" part of an if statement. The count for - // the "else" part, if it exists, will be calculated from this counter. - uint64_t ThenCount = setCount(PGO.getRegionCount(S)); - CountMap[S->getThen()] = ThenCount; - Visit(S->getThen()); - uint64_t OutCount = CurrentCount; - - uint64_t ElseCount = ParentCount - ThenCount; - if (S->getElse()) { - setCount(ElseCount); - CountMap[S->getElse()] = ElseCount; - Visit(S->getElse()); - OutCount += CurrentCount; - } else - OutCount += ElseCount; - setCount(OutCount); - RecordNextStmtCount = true; - } - - void VisitCXXTryStmt(const CXXTryStmt *S) { - RecordStmtCount(S); - Visit(S->getTryBlock()); - for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I) - Visit(S->getHandler(I)); - // Counter tracks the continuation block of the try statement. - setCount(PGO.getRegionCount(S)); - RecordNextStmtCount = true; - } - - void VisitCXXCatchStmt(const CXXCatchStmt *S) { - RecordNextStmtCount = false; - // Counter tracks the catch statement's handler block. - uint64_t CatchCount = setCount(PGO.getRegionCount(S)); - CountMap[S] = CatchCount; - Visit(S->getHandlerBlock()); - } - - void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { - RecordStmtCount(E); - uint64_t ParentCount = CurrentCount; - Visit(E->getCond()); - - // Counter tracks the "true" part of a conditional operator. The - // count in the "false" part will be calculated from this counter. - uint64_t TrueCount = setCount(PGO.getRegionCount(E)); - CountMap[E->getTrueExpr()] = TrueCount; - Visit(E->getTrueExpr()); - uint64_t OutCount = CurrentCount; - - uint64_t FalseCount = setCount(ParentCount - TrueCount); - CountMap[E->getFalseExpr()] = FalseCount; - Visit(E->getFalseExpr()); - OutCount += CurrentCount; - - setCount(OutCount); - RecordNextStmtCount = true; - } - - void VisitBinLAnd(const BinaryOperator *E) { - RecordStmtCount(E); - uint64_t ParentCount = CurrentCount; - Visit(E->getLHS()); - // Counter tracks the right hand side of a logical and operator. - uint64_t RHSCount = setCount(PGO.getRegionCount(E)); - CountMap[E->getRHS()] = RHSCount; - Visit(E->getRHS()); - setCount(ParentCount + RHSCount - CurrentCount); - RecordNextStmtCount = true; - } - - void VisitBinLOr(const BinaryOperator *E) { - RecordStmtCount(E); - uint64_t ParentCount = CurrentCount; - Visit(E->getLHS()); - // Counter tracks the right hand side of a logical or operator. - uint64_t RHSCount = setCount(PGO.getRegionCount(E)); - CountMap[E->getRHS()] = RHSCount; - Visit(E->getRHS()); - setCount(ParentCount + RHSCount - CurrentCount); - RecordNextStmtCount = true; - } -}; -} // end anonymous namespace - -void PGOHash::combine(HashType Type) { - // Check that we never combine 0 and only have six bits. - assert(Type && "Hash is invalid: unexpected type 0"); - assert(unsigned(Type) < TooBig && "Hash is invalid: too many types"); - - // Pass through MD5 if enough work has built up. - if (Count && Count % NumTypesPerWord == 0) { - using namespace llvm::support; - uint64_t Swapped = endian::byte_swap<uint64_t, little>(Working); - MD5.update(llvm::makeArrayRef((uint8_t *)&Swapped, sizeof(Swapped))); - Working = 0; - } - - // Accumulate the current type. - ++Count; - Working = Working << NumBitsPerType | Type; -} - -uint64_t PGOHash::finalize() { - // Use Working as the hash directly if we never used MD5. - if (Count <= NumTypesPerWord) - // No need to byte swap here, since none of the math was endian-dependent. - // This number will be byte-swapped as required on endianness transitions, - // so we will see the same value on the other side. - return Working; - - // Check for remaining work in Working. - if (Working) - MD5.update(Working); - - // Finalize the MD5 and return the hash. - llvm::MD5::MD5Result Result; - MD5.final(Result); - using namespace llvm::support; - return Result.low(); -} - -void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) { - const Decl *D = GD.getDecl(); - if (!D->hasBody()) - return; - - bool InstrumentRegions = CGM.getCodeGenOpts().hasProfileClangInstr(); - llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader(); - if (!InstrumentRegions && !PGOReader) - return; - if (D->isImplicit()) - return; - // Constructors and destructors may be represented by several functions in IR. - // If so, instrument only base variant, others are implemented by delegation - // to the base one, it would be counted twice otherwise. - if (CGM.getTarget().getCXXABI().hasConstructorVariants()) { - if (isa<CXXDestructorDecl>(D) && GD.getDtorType() != Dtor_Base) - return; - - if (const auto *CCD = dyn_cast<CXXConstructorDecl>(D)) - if (GD.getCtorType() != Ctor_Base && - CodeGenFunction::IsConstructorDelegationValid(CCD)) - return; - } - CGM.ClearUnusedCoverageMapping(D); - setFuncName(Fn); - - mapRegionCounters(D); - if (CGM.getCodeGenOpts().CoverageMapping) - emitCounterRegionMapping(D); - if (PGOReader) { - SourceManager &SM = CGM.getContext().getSourceManager(); - loadRegionCounts(PGOReader, SM.isInMainFile(D->getLocation())); - computeRegionCounts(D); - applyFunctionAttributes(PGOReader, Fn); - } -} - -void CodeGenPGO::mapRegionCounters(const Decl *D) { - // Use the latest hash version when inserting instrumentation, but use the - // version in the indexed profile if we're reading PGO data. - PGOHashVersion HashVersion = PGO_HASH_LATEST; - if (auto *PGOReader = CGM.getPGOReader()) - HashVersion = getPGOHashVersion(PGOReader, CGM); - - RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>); - MapRegionCounters Walker(HashVersion, *RegionCounterMap); - if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) - Walker.TraverseDecl(const_cast<FunctionDecl *>(FD)); - else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D)) - Walker.TraverseDecl(const_cast<ObjCMethodDecl *>(MD)); - else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D)) - Walker.TraverseDecl(const_cast<BlockDecl *>(BD)); - else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D)) - Walker.TraverseDecl(const_cast<CapturedDecl *>(CD)); - assert(Walker.NextCounter > 0 && "no entry counter mapped for decl"); - NumRegionCounters = Walker.NextCounter; - FunctionHash = Walker.Hash.finalize(); -} - -bool CodeGenPGO::skipRegionMappingForDecl(const Decl *D) { - if (!D->getBody()) - return true; - - // Don't map the functions in system headers. - const auto &SM = CGM.getContext().getSourceManager(); - auto Loc = D->getBody()->getBeginLoc(); - return SM.isInSystemHeader(Loc); -} - -void CodeGenPGO::emitCounterRegionMapping(const Decl *D) { - if (skipRegionMappingForDecl(D)) - return; - - std::string CoverageMapping; - llvm::raw_string_ostream OS(CoverageMapping); - CoverageMappingGen MappingGen(*CGM.getCoverageMapping(), - CGM.getContext().getSourceManager(), - CGM.getLangOpts(), RegionCounterMap.get()); - MappingGen.emitCounterMapping(D, OS); - OS.flush(); - - if (CoverageMapping.empty()) - return; - - CGM.getCoverageMapping()->addFunctionMappingRecord( - FuncNameVar, FuncName, FunctionHash, CoverageMapping); -} - -void -CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef Name, - llvm::GlobalValue::LinkageTypes Linkage) { - if (skipRegionMappingForDecl(D)) - return; - - std::string CoverageMapping; - llvm::raw_string_ostream OS(CoverageMapping); - CoverageMappingGen MappingGen(*CGM.getCoverageMapping(), - CGM.getContext().getSourceManager(), - CGM.getLangOpts()); - MappingGen.emitEmptyMapping(D, OS); - OS.flush(); - - if (CoverageMapping.empty()) - return; - - setFuncName(Name, Linkage); - CGM.getCoverageMapping()->addFunctionMappingRecord( - FuncNameVar, FuncName, FunctionHash, CoverageMapping, false); -} - -void CodeGenPGO::computeRegionCounts(const Decl *D) { - StmtCountMap.reset(new llvm::DenseMap<const Stmt *, uint64_t>); - ComputeRegionCounts Walker(*StmtCountMap, *this); - if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) - Walker.VisitFunctionDecl(FD); - else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D)) - Walker.VisitObjCMethodDecl(MD); - else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D)) - Walker.VisitBlockDecl(BD); - else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D)) - Walker.VisitCapturedDecl(const_cast<CapturedDecl *>(CD)); -} - -void -CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader, - llvm::Function *Fn) { - if (!haveRegionCounts()) - return; - - uint64_t FunctionCount = getRegionCount(nullptr); - Fn->setEntryCount(FunctionCount); -} - -void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S, - llvm::Value *StepV) { - if (!CGM.getCodeGenOpts().hasProfileClangInstr() || !RegionCounterMap) - return; - if (!Builder.GetInsertBlock()) - return; - - unsigned Counter = (*RegionCounterMap)[S]; - auto *I8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); - - llvm::Value *Args[] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy), - Builder.getInt64(FunctionHash), - Builder.getInt32(NumRegionCounters), - Builder.getInt32(Counter), StepV}; - if (!StepV) - Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment), - makeArrayRef(Args, 4)); - else - Builder.CreateCall( - CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment_step), - makeArrayRef(Args)); -} - -// This method either inserts a call to the profile run-time during -// instrumentation or puts profile data into metadata for PGO use. -void CodeGenPGO::valueProfile(CGBuilderTy &Builder, uint32_t ValueKind, - llvm::Instruction *ValueSite, llvm::Value *ValuePtr) { - - if (!EnableValueProfiling) - return; - - if (!ValuePtr || !ValueSite || !Builder.GetInsertBlock()) - return; - - if (isa<llvm::Constant>(ValuePtr)) - return; - - bool InstrumentValueSites = CGM.getCodeGenOpts().hasProfileClangInstr(); - if (InstrumentValueSites && RegionCounterMap) { - auto BuilderInsertPoint = Builder.saveIP(); - Builder.SetInsertPoint(ValueSite); - llvm::Value *Args[5] = { - llvm::ConstantExpr::getBitCast(FuncNameVar, Builder.getInt8PtrTy()), - Builder.getInt64(FunctionHash), - Builder.CreatePtrToInt(ValuePtr, Builder.getInt64Ty()), - Builder.getInt32(ValueKind), - Builder.getInt32(NumValueSites[ValueKind]++) - }; - Builder.CreateCall( - CGM.getIntrinsic(llvm::Intrinsic::instrprof_value_profile), Args); - Builder.restoreIP(BuilderInsertPoint); - return; - } - - llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader(); - if (PGOReader && haveRegionCounts()) { - // We record the top most called three functions at each call site. - // Profile metadata contains "VP" string identifying this metadata - // as value profiling data, then a uint32_t value for the value profiling - // kind, a uint64_t value for the total number of times the call is - // executed, followed by the function hash and execution count (uint64_t) - // pairs for each function. - if (NumValueSites[ValueKind] >= ProfRecord->getNumValueSites(ValueKind)) - return; - - llvm::annotateValueSite(CGM.getModule(), *ValueSite, *ProfRecord, - (llvm::InstrProfValueKind)ValueKind, - NumValueSites[ValueKind]); - - NumValueSites[ValueKind]++; - } -} - -void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader, - bool IsInMainFile) { - CGM.getPGOStats().addVisited(IsInMainFile); - RegionCounts.clear(); - llvm::Expected<llvm::InstrProfRecord> RecordExpected = - PGOReader->getInstrProfRecord(FuncName, FunctionHash); - if (auto E = RecordExpected.takeError()) { - auto IPE = llvm::InstrProfError::take(std::move(E)); - if (IPE == llvm::instrprof_error::unknown_function) - CGM.getPGOStats().addMissing(IsInMainFile); - else if (IPE == llvm::instrprof_error::hash_mismatch) - CGM.getPGOStats().addMismatched(IsInMainFile); - else if (IPE == llvm::instrprof_error::malformed) - // TODO: Consider a more specific warning for this case. - CGM.getPGOStats().addMismatched(IsInMainFile); - return; - } - ProfRecord = - llvm::make_unique<llvm::InstrProfRecord>(std::move(RecordExpected.get())); - RegionCounts = ProfRecord->Counts; -} - -/// Calculate what to divide by to scale weights. -/// -/// Given the maximum weight, calculate a divisor that will scale all the -/// weights to strictly less than UINT32_MAX. -static uint64_t calculateWeightScale(uint64_t MaxWeight) { - return MaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1; -} - -/// Scale an individual branch weight (and add 1). -/// -/// Scale a 64-bit weight down to 32-bits using \c Scale. -/// -/// According to Laplace's Rule of Succession, it is better to compute the -/// weight based on the count plus 1, so universally add 1 to the value. -/// -/// \pre \c Scale was calculated by \a calculateWeightScale() with a weight no -/// greater than \c Weight. -static uint32_t scaleBranchWeight(uint64_t Weight, uint64_t Scale) { - assert(Scale && "scale by 0?"); - uint64_t Scaled = Weight / Scale + 1; - assert(Scaled <= UINT32_MAX && "overflow 32-bits"); - return Scaled; -} - -llvm::MDNode *CodeGenFunction::createProfileWeights(uint64_t TrueCount, - uint64_t FalseCount) { - // Check for empty weights. - if (!TrueCount && !FalseCount) - return nullptr; - - // Calculate how to scale down to 32-bits. - uint64_t Scale = calculateWeightScale(std::max(TrueCount, FalseCount)); - - llvm::MDBuilder MDHelper(CGM.getLLVMContext()); - return MDHelper.createBranchWeights(scaleBranchWeight(TrueCount, Scale), - scaleBranchWeight(FalseCount, Scale)); -} - -llvm::MDNode * -CodeGenFunction::createProfileWeights(ArrayRef<uint64_t> Weights) { - // We need at least two elements to create meaningful weights. - if (Weights.size() < 2) - return nullptr; - - // Check for empty weights. - uint64_t MaxWeight = *std::max_element(Weights.begin(), Weights.end()); - if (MaxWeight == 0) - return nullptr; - - // Calculate how to scale down to 32-bits. - uint64_t Scale = calculateWeightScale(MaxWeight); - - SmallVector<uint32_t, 16> ScaledWeights; - ScaledWeights.reserve(Weights.size()); - for (uint64_t W : Weights) - ScaledWeights.push_back(scaleBranchWeight(W, Scale)); - - llvm::MDBuilder MDHelper(CGM.getLLVMContext()); - return MDHelper.createBranchWeights(ScaledWeights); -} - -llvm::MDNode *CodeGenFunction::createProfileWeightsForLoop(const Stmt *Cond, - uint64_t LoopCount) { - if (!PGO.haveRegionCounts()) - return nullptr; - Optional<uint64_t> CondCount = PGO.getStmtCount(Cond); - assert(CondCount.hasValue() && "missing expected loop condition count"); - if (*CondCount == 0) - return nullptr; - return createProfileWeights(LoopCount, - std::max(*CondCount, LoopCount) - LoopCount); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenPGO.h b/gnu/llvm/tools/clang/lib/CodeGen/CodeGenPGO.h deleted file mode 100644 index 120ab651a4a..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenPGO.h +++ /dev/null @@ -1,120 +0,0 @@ -//===--- CodeGenPGO.h - PGO Instrumentation for LLVM CodeGen ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Instrumentation-based profile-guided optimization -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENPGO_H -#define LLVM_CLANG_LIB_CODEGEN_CODEGENPGO_H - -#include "CGBuilder.h" -#include "CodeGenModule.h" -#include "CodeGenTypes.h" -#include "llvm/ProfileData/InstrProfReader.h" -#include <array> -#include <memory> - -namespace clang { -namespace CodeGen { - -/// Per-function PGO state. -class CodeGenPGO { -private: - CodeGenModule &CGM; - std::string FuncName; - llvm::GlobalVariable *FuncNameVar; - - std::array <unsigned, llvm::IPVK_Last + 1> NumValueSites; - unsigned NumRegionCounters; - uint64_t FunctionHash; - std::unique_ptr<llvm::DenseMap<const Stmt *, unsigned>> RegionCounterMap; - std::unique_ptr<llvm::DenseMap<const Stmt *, uint64_t>> StmtCountMap; - std::unique_ptr<llvm::InstrProfRecord> ProfRecord; - std::vector<uint64_t> RegionCounts; - uint64_t CurrentRegionCount; - -public: - CodeGenPGO(CodeGenModule &CGM) - : CGM(CGM), NumValueSites({{0}}), NumRegionCounters(0), FunctionHash(0), - CurrentRegionCount(0) {} - - /// Whether or not we have PGO region data for the current function. This is - /// false both when we have no data at all and when our data has been - /// discarded. - bool haveRegionCounts() const { return !RegionCounts.empty(); } - - /// Return the counter value of the current region. - uint64_t getCurrentRegionCount() const { return CurrentRegionCount; } - - /// Set the counter value for the current region. This is used to keep track - /// of changes to the most recent counter from control flow and non-local - /// exits. - void setCurrentRegionCount(uint64_t Count) { CurrentRegionCount = Count; } - - /// Check if an execution count is known for a given statement. If so, return - /// true and put the value in Count; else return false. - Optional<uint64_t> getStmtCount(const Stmt *S) { - if (!StmtCountMap) - return None; - auto I = StmtCountMap->find(S); - if (I == StmtCountMap->end()) - return None; - return I->second; - } - - /// If the execution count for the current statement is known, record that - /// as the current count. - void setCurrentStmt(const Stmt *S) { - if (auto Count = getStmtCount(S)) - setCurrentRegionCount(*Count); - } - - /// Assign counters to regions and configure them for PGO of a given - /// function. Does nothing if instrumentation is not enabled and either - /// generates global variables or associates PGO data with each of the - /// counters depending on whether we are generating or using instrumentation. - void assignRegionCounters(GlobalDecl GD, llvm::Function *Fn); - /// Emit a coverage mapping range with a counter zero - /// for an unused declaration. - void emitEmptyCounterMapping(const Decl *D, StringRef FuncName, - llvm::GlobalValue::LinkageTypes Linkage); - // Insert instrumentation or attach profile metadata at value sites - void valueProfile(CGBuilderTy &Builder, uint32_t ValueKind, - llvm::Instruction *ValueSite, llvm::Value *ValuePtr); -private: - void setFuncName(llvm::Function *Fn); - void setFuncName(StringRef Name, llvm::GlobalValue::LinkageTypes Linkage); - void mapRegionCounters(const Decl *D); - void computeRegionCounts(const Decl *D); - void applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader, - llvm::Function *Fn); - void loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader, - bool IsInMainFile); - bool skipRegionMappingForDecl(const Decl *D); - void emitCounterRegionMapping(const Decl *D); - -public: - void emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S, - llvm::Value *StepV); - - /// Return the region count for the counter at the given index. - uint64_t getRegionCount(const Stmt *S) { - if (!RegionCounterMap) - return 0; - if (!haveRegionCounts()) - return 0; - return RegionCounts[(*RegionCounterMap)[S]]; - } -}; - -} // end namespace CodeGen -} // end namespace clang - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp deleted file mode 100644 index 27d39716d22..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp +++ /dev/null @@ -1,424 +0,0 @@ -//===--- CodeGenTypes.cpp - TBAA information for LLVM CodeGen -------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This is the code that manages TBAA information and defines the TBAA policy -// for the optimizer to use. Relevant standards text includes: -// -// C99 6.5p7 -// C++ [basic.lval] (p10 in n3126, p15 in some earlier versions) -// -//===----------------------------------------------------------------------===// - -#include "CodeGenTBAA.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Attr.h" -#include "clang/AST/Mangle.h" -#include "clang/AST/RecordLayout.h" -#include "clang/Basic/CodeGenOptions.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Metadata.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Type.h" -using namespace clang; -using namespace CodeGen; - -CodeGenTBAA::CodeGenTBAA(ASTContext &Ctx, llvm::Module &M, - const CodeGenOptions &CGO, - const LangOptions &Features, MangleContext &MContext) - : Context(Ctx), Module(M), CodeGenOpts(CGO), - Features(Features), MContext(MContext), MDHelper(M.getContext()), - Root(nullptr), Char(nullptr) -{} - -CodeGenTBAA::~CodeGenTBAA() { -} - -llvm::MDNode *CodeGenTBAA::getRoot() { - // Define the root of the tree. This identifies the tree, so that - // if our LLVM IR is linked with LLVM IR from a different front-end - // (or a different version of this front-end), their TBAA trees will - // remain distinct, and the optimizer will treat them conservatively. - if (!Root) { - if (Features.CPlusPlus) - Root = MDHelper.createTBAARoot("Simple C++ TBAA"); - else - Root = MDHelper.createTBAARoot("Simple C/C++ TBAA"); - } - - return Root; -} - -llvm::MDNode *CodeGenTBAA::createScalarTypeNode(StringRef Name, - llvm::MDNode *Parent, - uint64_t Size) { - if (CodeGenOpts.NewStructPathTBAA) { - llvm::Metadata *Id = MDHelper.createString(Name); - return MDHelper.createTBAATypeNode(Parent, Size, Id); - } - return MDHelper.createTBAAScalarTypeNode(Name, Parent); -} - -llvm::MDNode *CodeGenTBAA::getChar() { - // Define the root of the tree for user-accessible memory. C and C++ - // give special powers to char and certain similar types. However, - // these special powers only cover user-accessible memory, and doesn't - // include things like vtables. - if (!Char) - Char = createScalarTypeNode("omnipotent char", getRoot(), /* Size= */ 1); - - return Char; -} - -static bool TypeHasMayAlias(QualType QTy) { - // Tagged types have declarations, and therefore may have attributes. - if (const TagType *TTy = dyn_cast<TagType>(QTy)) - return TTy->getDecl()->hasAttr<MayAliasAttr>(); - - // Typedef types have declarations, and therefore may have attributes. - if (const TypedefType *TTy = dyn_cast<TypedefType>(QTy)) { - if (TTy->getDecl()->hasAttr<MayAliasAttr>()) - return true; - // Also, their underlying types may have relevant attributes. - return TypeHasMayAlias(TTy->desugar()); - } - - return false; -} - -/// Check if the given type is a valid base type to be used in access tags. -static bool isValidBaseType(QualType QTy) { - if (QTy->isReferenceType()) - return false; - if (const RecordType *TTy = QTy->getAs<RecordType>()) { - const RecordDecl *RD = TTy->getDecl()->getDefinition(); - // Incomplete types are not valid base access types. - if (!RD) - return false; - if (RD->hasFlexibleArrayMember()) - return false; - // RD can be struct, union, class, interface or enum. - // For now, we only handle struct and class. - if (RD->isStruct() || RD->isClass()) - return true; - } - return false; -} - -llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) { - uint64_t Size = Context.getTypeSizeInChars(Ty).getQuantity(); - - // Handle builtin types. - if (const BuiltinType *BTy = dyn_cast<BuiltinType>(Ty)) { - switch (BTy->getKind()) { - // Character types are special and can alias anything. - // In C++, this technically only includes "char" and "unsigned char", - // and not "signed char". In C, it includes all three. For now, - // the risk of exploiting this detail in C++ seems likely to outweigh - // the benefit. - case BuiltinType::Char_U: - case BuiltinType::Char_S: - case BuiltinType::UChar: - case BuiltinType::SChar: - return getChar(); - - // Unsigned types can alias their corresponding signed types. - case BuiltinType::UShort: - return getTypeInfo(Context.ShortTy); - case BuiltinType::UInt: - return getTypeInfo(Context.IntTy); - case BuiltinType::ULong: - return getTypeInfo(Context.LongTy); - case BuiltinType::ULongLong: - return getTypeInfo(Context.LongLongTy); - case BuiltinType::UInt128: - return getTypeInfo(Context.Int128Ty); - - // Treat all other builtin types as distinct types. This includes - // treating wchar_t, char16_t, and char32_t as distinct from their - // "underlying types". - default: - return createScalarTypeNode(BTy->getName(Features), getChar(), Size); - } - } - - // C++1z [basic.lval]p10: "If a program attempts to access the stored value of - // an object through a glvalue of other than one of the following types the - // behavior is undefined: [...] a char, unsigned char, or std::byte type." - if (Ty->isStdByteType()) - return getChar(); - - // Handle pointers and references. - // TODO: Implement C++'s type "similarity" and consider dis-"similar" - // pointers distinct. - if (Ty->isPointerType() || Ty->isReferenceType()) - return createScalarTypeNode("any pointer", getChar(), Size); - - // Accesses to arrays are accesses to objects of their element types. - if (CodeGenOpts.NewStructPathTBAA && Ty->isArrayType()) - return getTypeInfo(cast<ArrayType>(Ty)->getElementType()); - - // Enum types are distinct types. In C++ they have "underlying types", - // however they aren't related for TBAA. - if (const EnumType *ETy = dyn_cast<EnumType>(Ty)) { - // In C++ mode, types have linkage, so we can rely on the ODR and - // on their mangled names, if they're external. - // TODO: Is there a way to get a program-wide unique name for a - // decl with local linkage or no linkage? - if (!Features.CPlusPlus || !ETy->getDecl()->isExternallyVisible()) - return getChar(); - - SmallString<256> OutName; - llvm::raw_svector_ostream Out(OutName); - MContext.mangleTypeName(QualType(ETy, 0), Out); - return createScalarTypeNode(OutName, getChar(), Size); - } - - // For now, handle any other kind of type conservatively. - return getChar(); -} - -llvm::MDNode *CodeGenTBAA::getTypeInfo(QualType QTy) { - // At -O0 or relaxed aliasing, TBAA is not emitted for regular types. - if (CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing) - return nullptr; - - // If the type has the may_alias attribute (even on a typedef), it is - // effectively in the general char alias class. - if (TypeHasMayAlias(QTy)) - return getChar(); - - // We need this function to not fall back to returning the "omnipotent char" - // type node for aggregate and union types. Otherwise, any dereference of an - // aggregate will result into the may-alias access descriptor, meaning all - // subsequent accesses to direct and indirect members of that aggregate will - // be considered may-alias too. - // TODO: Combine getTypeInfo() and getBaseTypeInfo() into a single function. - if (isValidBaseType(QTy)) - return getBaseTypeInfo(QTy); - - const Type *Ty = Context.getCanonicalType(QTy).getTypePtr(); - if (llvm::MDNode *N = MetadataCache[Ty]) - return N; - - // Note that the following helper call is allowed to add new nodes to the - // cache, which invalidates all its previously obtained iterators. So we - // first generate the node for the type and then add that node to the cache. - llvm::MDNode *TypeNode = getTypeInfoHelper(Ty); - return MetadataCache[Ty] = TypeNode; -} - -TBAAAccessInfo CodeGenTBAA::getAccessInfo(QualType AccessType) { - // Pointee values may have incomplete types, but they shall never be - // dereferenced. - if (AccessType->isIncompleteType()) - return TBAAAccessInfo::getIncompleteInfo(); - - if (TypeHasMayAlias(AccessType)) - return TBAAAccessInfo::getMayAliasInfo(); - - uint64_t Size = Context.getTypeSizeInChars(AccessType).getQuantity(); - return TBAAAccessInfo(getTypeInfo(AccessType), Size); -} - -TBAAAccessInfo CodeGenTBAA::getVTablePtrAccessInfo(llvm::Type *VTablePtrType) { - llvm::DataLayout DL(&Module); - unsigned Size = DL.getPointerTypeSize(VTablePtrType); - return TBAAAccessInfo(createScalarTypeNode("vtable pointer", getRoot(), Size), - Size); -} - -bool -CodeGenTBAA::CollectFields(uint64_t BaseOffset, - QualType QTy, - SmallVectorImpl<llvm::MDBuilder::TBAAStructField> & - Fields, - bool MayAlias) { - /* Things not handled yet include: C++ base classes, bitfields, */ - - if (const RecordType *TTy = QTy->getAs<RecordType>()) { - const RecordDecl *RD = TTy->getDecl()->getDefinition(); - if (RD->hasFlexibleArrayMember()) - return false; - - // TODO: Handle C++ base classes. - if (const CXXRecordDecl *Decl = dyn_cast<CXXRecordDecl>(RD)) - if (Decl->bases_begin() != Decl->bases_end()) - return false; - - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - - unsigned idx = 0; - for (RecordDecl::field_iterator i = RD->field_begin(), - e = RD->field_end(); i != e; ++i, ++idx) { - uint64_t Offset = BaseOffset + - Layout.getFieldOffset(idx) / Context.getCharWidth(); - QualType FieldQTy = i->getType(); - if (!CollectFields(Offset, FieldQTy, Fields, - MayAlias || TypeHasMayAlias(FieldQTy))) - return false; - } - return true; - } - - /* Otherwise, treat whatever it is as a field. */ - uint64_t Offset = BaseOffset; - uint64_t Size = Context.getTypeSizeInChars(QTy).getQuantity(); - llvm::MDNode *TBAAType = MayAlias ? getChar() : getTypeInfo(QTy); - llvm::MDNode *TBAATag = getAccessTagInfo(TBAAAccessInfo(TBAAType, Size)); - Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size, TBAATag)); - return true; -} - -llvm::MDNode * -CodeGenTBAA::getTBAAStructInfo(QualType QTy) { - const Type *Ty = Context.getCanonicalType(QTy).getTypePtr(); - - if (llvm::MDNode *N = StructMetadataCache[Ty]) - return N; - - SmallVector<llvm::MDBuilder::TBAAStructField, 4> Fields; - if (CollectFields(0, QTy, Fields, TypeHasMayAlias(QTy))) - return MDHelper.createTBAAStructNode(Fields); - - // For now, handle any other kind of type conservatively. - return StructMetadataCache[Ty] = nullptr; -} - -llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) { - if (auto *TTy = dyn_cast<RecordType>(Ty)) { - const RecordDecl *RD = TTy->getDecl()->getDefinition(); - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - SmallVector<llvm::MDBuilder::TBAAStructField, 4> Fields; - for (FieldDecl *Field : RD->fields()) { - QualType FieldQTy = Field->getType(); - llvm::MDNode *TypeNode = isValidBaseType(FieldQTy) ? - getBaseTypeInfo(FieldQTy) : getTypeInfo(FieldQTy); - if (!TypeNode) - return BaseTypeMetadataCache[Ty] = nullptr; - - uint64_t BitOffset = Layout.getFieldOffset(Field->getFieldIndex()); - uint64_t Offset = Context.toCharUnitsFromBits(BitOffset).getQuantity(); - uint64_t Size = Context.getTypeSizeInChars(FieldQTy).getQuantity(); - Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size, - TypeNode)); - } - - SmallString<256> OutName; - if (Features.CPlusPlus) { - // Don't use the mangler for C code. - llvm::raw_svector_ostream Out(OutName); - MContext.mangleTypeName(QualType(Ty, 0), Out); - } else { - OutName = RD->getName(); - } - - if (CodeGenOpts.NewStructPathTBAA) { - llvm::MDNode *Parent = getChar(); - uint64_t Size = Context.getTypeSizeInChars(Ty).getQuantity(); - llvm::Metadata *Id = MDHelper.createString(OutName); - return MDHelper.createTBAATypeNode(Parent, Size, Id, Fields); - } - - // Create the struct type node with a vector of pairs (offset, type). - SmallVector<std::pair<llvm::MDNode*, uint64_t>, 4> OffsetsAndTypes; - for (const auto &Field : Fields) - OffsetsAndTypes.push_back(std::make_pair(Field.Type, Field.Offset)); - return MDHelper.createTBAAStructTypeNode(OutName, OffsetsAndTypes); - } - - return nullptr; -} - -llvm::MDNode *CodeGenTBAA::getBaseTypeInfo(QualType QTy) { - if (!isValidBaseType(QTy)) - return nullptr; - - const Type *Ty = Context.getCanonicalType(QTy).getTypePtr(); - if (llvm::MDNode *N = BaseTypeMetadataCache[Ty]) - return N; - - // Note that the following helper call is allowed to add new nodes to the - // cache, which invalidates all its previously obtained iterators. So we - // first generate the node for the type and then add that node to the cache. - llvm::MDNode *TypeNode = getBaseTypeInfoHelper(Ty); - return BaseTypeMetadataCache[Ty] = TypeNode; -} - -llvm::MDNode *CodeGenTBAA::getAccessTagInfo(TBAAAccessInfo Info) { - assert(!Info.isIncomplete() && "Access to an object of an incomplete type!"); - - if (Info.isMayAlias()) - Info = TBAAAccessInfo(getChar(), Info.Size); - - if (!Info.AccessType) - return nullptr; - - if (!CodeGenOpts.StructPathTBAA) - Info = TBAAAccessInfo(Info.AccessType, Info.Size); - - llvm::MDNode *&N = AccessTagMetadataCache[Info]; - if (N) - return N; - - if (!Info.BaseType) { - Info.BaseType = Info.AccessType; - assert(!Info.Offset && "Nonzero offset for an access with no base type!"); - } - if (CodeGenOpts.NewStructPathTBAA) { - return N = MDHelper.createTBAAAccessTag(Info.BaseType, Info.AccessType, - Info.Offset, Info.Size); - } - return N = MDHelper.createTBAAStructTagNode(Info.BaseType, Info.AccessType, - Info.Offset); -} - -TBAAAccessInfo CodeGenTBAA::mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo, - TBAAAccessInfo TargetInfo) { - if (SourceInfo.isMayAlias() || TargetInfo.isMayAlias()) - return TBAAAccessInfo::getMayAliasInfo(); - return TargetInfo; -} - -TBAAAccessInfo -CodeGenTBAA::mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA, - TBAAAccessInfo InfoB) { - if (InfoA == InfoB) - return InfoA; - - if (!InfoA || !InfoB) - return TBAAAccessInfo(); - - if (InfoA.isMayAlias() || InfoB.isMayAlias()) - return TBAAAccessInfo::getMayAliasInfo(); - - // TODO: Implement the rest of the logic here. For example, two accesses - // with same final access types result in an access to an object of that final - // access type regardless of their base types. - return TBAAAccessInfo::getMayAliasInfo(); -} - -TBAAAccessInfo -CodeGenTBAA::mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo DestInfo, - TBAAAccessInfo SrcInfo) { - if (DestInfo == SrcInfo) - return DestInfo; - - if (!DestInfo || !SrcInfo) - return TBAAAccessInfo(); - - if (DestInfo.isMayAlias() || SrcInfo.isMayAlias()) - return TBAAAccessInfo::getMayAliasInfo(); - - // TODO: Implement the rest of the logic here. For example, two accesses - // with same final access types result in an access to an object of that final - // access type regardless of their base types. - return TBAAAccessInfo::getMayAliasInfo(); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.h b/gnu/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.h deleted file mode 100644 index 86ba407c05c..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.h +++ /dev/null @@ -1,258 +0,0 @@ -//===--- CodeGenTBAA.h - TBAA information for LLVM CodeGen ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This is the code that manages TBAA information and defines the TBAA policy -// for the optimizer to use. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENTBAA_H -#define LLVM_CLANG_LIB_CODEGEN_CODEGENTBAA_H - -#include "clang/AST/Type.h" -#include "clang/Basic/LLVM.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/IR/MDBuilder.h" -#include "llvm/IR/Metadata.h" - -namespace clang { - class ASTContext; - class CodeGenOptions; - class LangOptions; - class MangleContext; - class QualType; - class Type; - -namespace CodeGen { -class CGRecordLayout; - -// TBAAAccessKind - A kind of TBAA memory access descriptor. -enum class TBAAAccessKind : unsigned { - Ordinary, - MayAlias, - Incomplete, -}; - -// TBAAAccessInfo - Describes a memory access in terms of TBAA. -struct TBAAAccessInfo { - TBAAAccessInfo(TBAAAccessKind Kind, llvm::MDNode *BaseType, - llvm::MDNode *AccessType, uint64_t Offset, uint64_t Size) - : Kind(Kind), BaseType(BaseType), AccessType(AccessType), - Offset(Offset), Size(Size) - {} - - TBAAAccessInfo(llvm::MDNode *BaseType, llvm::MDNode *AccessType, - uint64_t Offset, uint64_t Size) - : TBAAAccessInfo(TBAAAccessKind::Ordinary, BaseType, AccessType, - Offset, Size) - {} - - explicit TBAAAccessInfo(llvm::MDNode *AccessType, uint64_t Size) - : TBAAAccessInfo(/* BaseType= */ nullptr, AccessType, /* Offset= */ 0, Size) - {} - - TBAAAccessInfo() - : TBAAAccessInfo(/* AccessType= */ nullptr, /* Size= */ 0) - {} - - static TBAAAccessInfo getMayAliasInfo() { - return TBAAAccessInfo(TBAAAccessKind::MayAlias, - /* BaseType= */ nullptr, /* AccessType= */ nullptr, - /* Offset= */ 0, /* Size= */ 0); - } - - bool isMayAlias() const { return Kind == TBAAAccessKind::MayAlias; } - - static TBAAAccessInfo getIncompleteInfo() { - return TBAAAccessInfo(TBAAAccessKind::Incomplete, - /* BaseType= */ nullptr, /* AccessType= */ nullptr, - /* Offset= */ 0, /* Size= */ 0); - } - - bool isIncomplete() const { return Kind == TBAAAccessKind::Incomplete; } - - bool operator==(const TBAAAccessInfo &Other) const { - return Kind == Other.Kind && - BaseType == Other.BaseType && - AccessType == Other.AccessType && - Offset == Other.Offset && - Size == Other.Size; - } - - bool operator!=(const TBAAAccessInfo &Other) const { - return !(*this == Other); - } - - explicit operator bool() const { - return *this != TBAAAccessInfo(); - } - - /// Kind - The kind of the access descriptor. - TBAAAccessKind Kind; - - /// BaseType - The base/leading access type. May be null if this access - /// descriptor represents an access that is not considered to be an access - /// to an aggregate or union member. - llvm::MDNode *BaseType; - - /// AccessType - The final access type. May be null if there is no TBAA - /// information available about this access. - llvm::MDNode *AccessType; - - /// Offset - The byte offset of the final access within the base one. Must be - /// zero if the base access type is not specified. - uint64_t Offset; - - /// Size - The size of access, in bytes. - uint64_t Size; -}; - -/// CodeGenTBAA - This class organizes the cross-module state that is used -/// while lowering AST types to LLVM types. -class CodeGenTBAA { - ASTContext &Context; - llvm::Module &Module; - const CodeGenOptions &CodeGenOpts; - const LangOptions &Features; - MangleContext &MContext; - - // MDHelper - Helper for creating metadata. - llvm::MDBuilder MDHelper; - - /// MetadataCache - This maps clang::Types to scalar llvm::MDNodes describing - /// them. - llvm::DenseMap<const Type *, llvm::MDNode *> MetadataCache; - /// This maps clang::Types to a base access type in the type DAG. - llvm::DenseMap<const Type *, llvm::MDNode *> BaseTypeMetadataCache; - /// This maps TBAA access descriptors to tag nodes. - llvm::DenseMap<TBAAAccessInfo, llvm::MDNode *> AccessTagMetadataCache; - - /// StructMetadataCache - This maps clang::Types to llvm::MDNodes describing - /// them for struct assignments. - llvm::DenseMap<const Type *, llvm::MDNode *> StructMetadataCache; - - llvm::MDNode *Root; - llvm::MDNode *Char; - - /// getRoot - This is the mdnode for the root of the metadata type graph - /// for this translation unit. - llvm::MDNode *getRoot(); - - /// getChar - This is the mdnode for "char", which is special, and any types - /// considered to be equivalent to it. - llvm::MDNode *getChar(); - - /// CollectFields - Collect information about the fields of a type for - /// !tbaa.struct metadata formation. Return false for an unsupported type. - bool CollectFields(uint64_t BaseOffset, - QualType Ty, - SmallVectorImpl<llvm::MDBuilder::TBAAStructField> &Fields, - bool MayAlias); - - /// createScalarTypeNode - A wrapper function to create a metadata node - /// describing a scalar type. - llvm::MDNode *createScalarTypeNode(StringRef Name, llvm::MDNode *Parent, - uint64_t Size); - - /// getTypeInfoHelper - An internal helper function to generate metadata used - /// to describe accesses to objects of the given type. - llvm::MDNode *getTypeInfoHelper(const Type *Ty); - - /// getBaseTypeInfoHelper - An internal helper function to generate metadata - /// used to describe accesses to objects of the given base type. - llvm::MDNode *getBaseTypeInfoHelper(const Type *Ty); - -public: - CodeGenTBAA(ASTContext &Ctx, llvm::Module &M, const CodeGenOptions &CGO, - const LangOptions &Features, MangleContext &MContext); - ~CodeGenTBAA(); - - /// getTypeInfo - Get metadata used to describe accesses to objects of the - /// given type. - llvm::MDNode *getTypeInfo(QualType QTy); - - /// getAccessInfo - Get TBAA information that describes an access to - /// an object of the given type. - TBAAAccessInfo getAccessInfo(QualType AccessType); - - /// getVTablePtrAccessInfo - Get the TBAA information that describes an - /// access to a virtual table pointer. - TBAAAccessInfo getVTablePtrAccessInfo(llvm::Type *VTablePtrType); - - /// getTBAAStructInfo - Get the TBAAStruct MDNode to be used for a memcpy of - /// the given type. - llvm::MDNode *getTBAAStructInfo(QualType QTy); - - /// getBaseTypeInfo - Get metadata that describes the given base access type. - /// Return null if the type is not suitable for use in TBAA access tags. - llvm::MDNode *getBaseTypeInfo(QualType QTy); - - /// getAccessTagInfo - Get TBAA tag for a given memory access. - llvm::MDNode *getAccessTagInfo(TBAAAccessInfo Info); - - /// mergeTBAAInfoForCast - Get merged TBAA information for the purpose of - /// type casts. - TBAAAccessInfo mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo, - TBAAAccessInfo TargetInfo); - - /// mergeTBAAInfoForConditionalOperator - Get merged TBAA information for the - /// purpose of conditional operator. - TBAAAccessInfo mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA, - TBAAAccessInfo InfoB); - - /// mergeTBAAInfoForMemoryTransfer - Get merged TBAA information for the - /// purpose of memory transfer calls. - TBAAAccessInfo mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo DestInfo, - TBAAAccessInfo SrcInfo); -}; - -} // end namespace CodeGen -} // end namespace clang - -namespace llvm { - -template<> struct DenseMapInfo<clang::CodeGen::TBAAAccessInfo> { - static clang::CodeGen::TBAAAccessInfo getEmptyKey() { - unsigned UnsignedKey = DenseMapInfo<unsigned>::getEmptyKey(); - return clang::CodeGen::TBAAAccessInfo( - static_cast<clang::CodeGen::TBAAAccessKind>(UnsignedKey), - DenseMapInfo<MDNode *>::getEmptyKey(), - DenseMapInfo<MDNode *>::getEmptyKey(), - DenseMapInfo<uint64_t>::getEmptyKey(), - DenseMapInfo<uint64_t>::getEmptyKey()); - } - - static clang::CodeGen::TBAAAccessInfo getTombstoneKey() { - unsigned UnsignedKey = DenseMapInfo<unsigned>::getTombstoneKey(); - return clang::CodeGen::TBAAAccessInfo( - static_cast<clang::CodeGen::TBAAAccessKind>(UnsignedKey), - DenseMapInfo<MDNode *>::getTombstoneKey(), - DenseMapInfo<MDNode *>::getTombstoneKey(), - DenseMapInfo<uint64_t>::getTombstoneKey(), - DenseMapInfo<uint64_t>::getTombstoneKey()); - } - - static unsigned getHashValue(const clang::CodeGen::TBAAAccessInfo &Val) { - auto KindValue = static_cast<unsigned>(Val.Kind); - return DenseMapInfo<unsigned>::getHashValue(KindValue) ^ - DenseMapInfo<MDNode *>::getHashValue(Val.BaseType) ^ - DenseMapInfo<MDNode *>::getHashValue(Val.AccessType) ^ - DenseMapInfo<uint64_t>::getHashValue(Val.Offset) ^ - DenseMapInfo<uint64_t>::getHashValue(Val.Size); - } - - static bool isEqual(const clang::CodeGen::TBAAAccessInfo &LHS, - const clang::CodeGen::TBAAAccessInfo &RHS) { - return LHS == RHS; - } -}; - -} // end namespace llvm - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenTypeCache.h b/gnu/llvm/tools/clang/lib/CodeGen/CodeGenTypeCache.h deleted file mode 100644 index 901aed6c00b..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenTypeCache.h +++ /dev/null @@ -1,122 +0,0 @@ -//===--- CodeGenTypeCache.h - Commonly used LLVM types and info -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This structure provides a set of common types useful during IR emission. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENTYPECACHE_H -#define LLVM_CLANG_LIB_CODEGEN_CODEGENTYPECACHE_H - -#include "clang/AST/CharUnits.h" -#include "clang/Basic/AddressSpaces.h" -#include "llvm/IR/CallingConv.h" - -namespace llvm { - class Type; - class IntegerType; - class PointerType; -} - -namespace clang { -namespace CodeGen { - -/// This structure provides a set of types that are commonly used -/// during IR emission. It's initialized once in CodeGenModule's -/// constructor and then copied around into new CodeGenFunctions. -struct CodeGenTypeCache { - /// void - llvm::Type *VoidTy; - - /// i8, i16, i32, and i64 - llvm::IntegerType *Int8Ty, *Int16Ty, *Int32Ty, *Int64Ty; - /// float, double - llvm::Type *HalfTy, *FloatTy, *DoubleTy; - - /// int - llvm::IntegerType *IntTy; - - /// intptr_t, size_t, and ptrdiff_t, which we assume are the same size. - union { - llvm::IntegerType *IntPtrTy; - llvm::IntegerType *SizeTy; - llvm::IntegerType *PtrDiffTy; - }; - - /// void* in address space 0 - union { - llvm::PointerType *VoidPtrTy; - llvm::PointerType *Int8PtrTy; - }; - - /// void** in address space 0 - union { - llvm::PointerType *VoidPtrPtrTy; - llvm::PointerType *Int8PtrPtrTy; - }; - - /// void* in alloca address space - union { - llvm::PointerType *AllocaVoidPtrTy; - llvm::PointerType *AllocaInt8PtrTy; - }; - - /// The size and alignment of the builtin C type 'int'. This comes - /// up enough in various ABI lowering tasks to be worth pre-computing. - union { - unsigned char IntSizeInBytes; - unsigned char IntAlignInBytes; - }; - CharUnits getIntSize() const { - return CharUnits::fromQuantity(IntSizeInBytes); - } - CharUnits getIntAlign() const { - return CharUnits::fromQuantity(IntAlignInBytes); - } - - /// The width of a pointer into the generic address space. - unsigned char PointerWidthInBits; - - /// The size and alignment of a pointer into the generic address space. - union { - unsigned char PointerAlignInBytes; - unsigned char PointerSizeInBytes; - }; - - /// The size and alignment of size_t. - union { - unsigned char SizeSizeInBytes; // sizeof(size_t) - unsigned char SizeAlignInBytes; - }; - - LangAS ASTAllocaAddressSpace; - - CharUnits getSizeSize() const { - return CharUnits::fromQuantity(SizeSizeInBytes); - } - CharUnits getSizeAlign() const { - return CharUnits::fromQuantity(SizeAlignInBytes); - } - CharUnits getPointerSize() const { - return CharUnits::fromQuantity(PointerSizeInBytes); - } - CharUnits getPointerAlign() const { - return CharUnits::fromQuantity(PointerAlignInBytes); - } - - llvm::CallingConv::ID RuntimeCC; - llvm::CallingConv::ID getRuntimeCC() const { return RuntimeCC; } - - LangAS getASTAllocaAddressSpace() const { return ASTAllocaAddressSpace; } -}; - -} // end namespace CodeGen -} // end namespace clang - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp deleted file mode 100644 index 2acf1ac1618..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp +++ /dev/null @@ -1,812 +0,0 @@ -//===--- CodeGenTypes.cpp - Type translation for LLVM CodeGen -------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This is the code that handles AST -> LLVM type lowering. -// -//===----------------------------------------------------------------------===// - -#include "CodeGenTypes.h" -#include "CGCXXABI.h" -#include "CGCall.h" -#include "CGOpenCLRuntime.h" -#include "CGRecordLayout.h" -#include "TargetInfo.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/Expr.h" -#include "clang/AST/RecordLayout.h" -#include "clang/CodeGen/CGFunctionInfo.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Module.h" -using namespace clang; -using namespace CodeGen; - -CodeGenTypes::CodeGenTypes(CodeGenModule &cgm) - : CGM(cgm), Context(cgm.getContext()), TheModule(cgm.getModule()), - Target(cgm.getTarget()), TheCXXABI(cgm.getCXXABI()), - TheABIInfo(cgm.getTargetCodeGenInfo().getABIInfo()) { - SkippedLayout = false; -} - -CodeGenTypes::~CodeGenTypes() { - llvm::DeleteContainerSeconds(CGRecordLayouts); - - for (llvm::FoldingSet<CGFunctionInfo>::iterator - I = FunctionInfos.begin(), E = FunctionInfos.end(); I != E; ) - delete &*I++; -} - -const CodeGenOptions &CodeGenTypes::getCodeGenOpts() const { - return CGM.getCodeGenOpts(); -} - -void CodeGenTypes::addRecordTypeName(const RecordDecl *RD, - llvm::StructType *Ty, - StringRef suffix) { - SmallString<256> TypeName; - llvm::raw_svector_ostream OS(TypeName); - OS << RD->getKindName() << '.'; - - // Name the codegen type after the typedef name - // if there is no tag type name available - if (RD->getIdentifier()) { - // FIXME: We should not have to check for a null decl context here. - // Right now we do it because the implicit Obj-C decls don't have one. - if (RD->getDeclContext()) - RD->printQualifiedName(OS); - else - RD->printName(OS); - } else if (const TypedefNameDecl *TDD = RD->getTypedefNameForAnonDecl()) { - // FIXME: We should not have to check for a null decl context here. - // Right now we do it because the implicit Obj-C decls don't have one. - if (TDD->getDeclContext()) - TDD->printQualifiedName(OS); - else - TDD->printName(OS); - } else - OS << "anon"; - - if (!suffix.empty()) - OS << suffix; - - Ty->setName(OS.str()); -} - -/// ConvertTypeForMem - Convert type T into a llvm::Type. This differs from -/// ConvertType in that it is used to convert to the memory representation for -/// a type. For example, the scalar representation for _Bool is i1, but the -/// memory representation is usually i8 or i32, depending on the target. -llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T) { - llvm::Type *R = ConvertType(T); - - // If this is a non-bool type, don't map it. - if (!R->isIntegerTy(1)) - return R; - - // Otherwise, return an integer of the target-specified size. - return llvm::IntegerType::get(getLLVMContext(), - (unsigned)Context.getTypeSize(T)); -} - - -/// isRecordLayoutComplete - Return true if the specified type is already -/// completely laid out. -bool CodeGenTypes::isRecordLayoutComplete(const Type *Ty) const { - llvm::DenseMap<const Type*, llvm::StructType *>::const_iterator I = - RecordDeclTypes.find(Ty); - return I != RecordDeclTypes.end() && !I->second->isOpaque(); -} - -static bool -isSafeToConvert(QualType T, CodeGenTypes &CGT, - llvm::SmallPtrSet<const RecordDecl*, 16> &AlreadyChecked); - - -/// isSafeToConvert - Return true if it is safe to convert the specified record -/// decl to IR and lay it out, false if doing so would cause us to get into a -/// recursive compilation mess. -static bool -isSafeToConvert(const RecordDecl *RD, CodeGenTypes &CGT, - llvm::SmallPtrSet<const RecordDecl*, 16> &AlreadyChecked) { - // If we have already checked this type (maybe the same type is used by-value - // multiple times in multiple structure fields, don't check again. - if (!AlreadyChecked.insert(RD).second) - return true; - - const Type *Key = CGT.getContext().getTagDeclType(RD).getTypePtr(); - - // If this type is already laid out, converting it is a noop. - if (CGT.isRecordLayoutComplete(Key)) return true; - - // If this type is currently being laid out, we can't recursively compile it. - if (CGT.isRecordBeingLaidOut(Key)) - return false; - - // If this type would require laying out bases that are currently being laid - // out, don't do it. This includes virtual base classes which get laid out - // when a class is translated, even though they aren't embedded by-value into - // the class. - if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) { - for (const auto &I : CRD->bases()) - if (!isSafeToConvert(I.getType()->getAs<RecordType>()->getDecl(), - CGT, AlreadyChecked)) - return false; - } - - // If this type would require laying out members that are currently being laid - // out, don't do it. - for (const auto *I : RD->fields()) - if (!isSafeToConvert(I->getType(), CGT, AlreadyChecked)) - return false; - - // If there are no problems, lets do it. - return true; -} - -/// isSafeToConvert - Return true if it is safe to convert this field type, -/// which requires the structure elements contained by-value to all be -/// recursively safe to convert. -static bool -isSafeToConvert(QualType T, CodeGenTypes &CGT, - llvm::SmallPtrSet<const RecordDecl*, 16> &AlreadyChecked) { - // Strip off atomic type sugar. - if (const auto *AT = T->getAs<AtomicType>()) - T = AT->getValueType(); - - // If this is a record, check it. - if (const auto *RT = T->getAs<RecordType>()) - return isSafeToConvert(RT->getDecl(), CGT, AlreadyChecked); - - // If this is an array, check the elements, which are embedded inline. - if (const auto *AT = CGT.getContext().getAsArrayType(T)) - return isSafeToConvert(AT->getElementType(), CGT, AlreadyChecked); - - // Otherwise, there is no concern about transforming this. We only care about - // things that are contained by-value in a structure that can have another - // structure as a member. - return true; -} - - -/// isSafeToConvert - Return true if it is safe to convert the specified record -/// decl to IR and lay it out, false if doing so would cause us to get into a -/// recursive compilation mess. -static bool isSafeToConvert(const RecordDecl *RD, CodeGenTypes &CGT) { - // If no structs are being laid out, we can certainly do this one. - if (CGT.noRecordsBeingLaidOut()) return true; - - llvm::SmallPtrSet<const RecordDecl*, 16> AlreadyChecked; - return isSafeToConvert(RD, CGT, AlreadyChecked); -} - -/// isFuncParamTypeConvertible - Return true if the specified type in a -/// function parameter or result position can be converted to an IR type at this -/// point. This boils down to being whether it is complete, as well as whether -/// we've temporarily deferred expanding the type because we're in a recursive -/// context. -bool CodeGenTypes::isFuncParamTypeConvertible(QualType Ty) { - // Some ABIs cannot have their member pointers represented in IR unless - // certain circumstances have been reached. - if (const auto *MPT = Ty->getAs<MemberPointerType>()) - return getCXXABI().isMemberPointerConvertible(MPT); - - // If this isn't a tagged type, we can convert it! - const TagType *TT = Ty->getAs<TagType>(); - if (!TT) return true; - - // Incomplete types cannot be converted. - if (TT->isIncompleteType()) - return false; - - // If this is an enum, then it is always safe to convert. - const RecordType *RT = dyn_cast<RecordType>(TT); - if (!RT) return true; - - // Otherwise, we have to be careful. If it is a struct that we're in the - // process of expanding, then we can't convert the function type. That's ok - // though because we must be in a pointer context under the struct, so we can - // just convert it to a dummy type. - // - // We decide this by checking whether ConvertRecordDeclType returns us an - // opaque type for a struct that we know is defined. - return isSafeToConvert(RT->getDecl(), *this); -} - - -/// Code to verify a given function type is complete, i.e. the return type -/// and all of the parameter types are complete. Also check to see if we are in -/// a RS_StructPointer context, and if so whether any struct types have been -/// pended. If so, we don't want to ask the ABI lowering code to handle a type -/// that cannot be converted to an IR type. -bool CodeGenTypes::isFuncTypeConvertible(const FunctionType *FT) { - if (!isFuncParamTypeConvertible(FT->getReturnType())) - return false; - - if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT)) - for (unsigned i = 0, e = FPT->getNumParams(); i != e; i++) - if (!isFuncParamTypeConvertible(FPT->getParamType(i))) - return false; - - return true; -} - -/// UpdateCompletedType - When we find the full definition for a TagDecl, -/// replace the 'opaque' type we previously made for it if applicable. -void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) { - // If this is an enum being completed, then we flush all non-struct types from - // the cache. This allows function types and other things that may be derived - // from the enum to be recomputed. - if (const EnumDecl *ED = dyn_cast<EnumDecl>(TD)) { - // Only flush the cache if we've actually already converted this type. - if (TypeCache.count(ED->getTypeForDecl())) { - // Okay, we formed some types based on this. We speculated that the enum - // would be lowered to i32, so we only need to flush the cache if this - // didn't happen. - if (!ConvertType(ED->getIntegerType())->isIntegerTy(32)) - TypeCache.clear(); - } - // If necessary, provide the full definition of a type only used with a - // declaration so far. - if (CGDebugInfo *DI = CGM.getModuleDebugInfo()) - DI->completeType(ED); - return; - } - - // If we completed a RecordDecl that we previously used and converted to an - // anonymous type, then go ahead and complete it now. - const RecordDecl *RD = cast<RecordDecl>(TD); - if (RD->isDependentType()) return; - - // Only complete it if we converted it already. If we haven't converted it - // yet, we'll just do it lazily. - if (RecordDeclTypes.count(Context.getTagDeclType(RD).getTypePtr())) - ConvertRecordDeclType(RD); - - // If necessary, provide the full definition of a type only used with a - // declaration so far. - if (CGDebugInfo *DI = CGM.getModuleDebugInfo()) - DI->completeType(RD); -} - -void CodeGenTypes::RefreshTypeCacheForClass(const CXXRecordDecl *RD) { - QualType T = Context.getRecordType(RD); - T = Context.getCanonicalType(T); - - const Type *Ty = T.getTypePtr(); - if (RecordsWithOpaqueMemberPointers.count(Ty)) { - TypeCache.clear(); - RecordsWithOpaqueMemberPointers.clear(); - } -} - -static llvm::Type *getTypeForFormat(llvm::LLVMContext &VMContext, - const llvm::fltSemantics &format, - bool UseNativeHalf = false) { - if (&format == &llvm::APFloat::IEEEhalf()) { - if (UseNativeHalf) - return llvm::Type::getHalfTy(VMContext); - else - return llvm::Type::getInt16Ty(VMContext); - } - if (&format == &llvm::APFloat::IEEEsingle()) - return llvm::Type::getFloatTy(VMContext); - if (&format == &llvm::APFloat::IEEEdouble()) - return llvm::Type::getDoubleTy(VMContext); - if (&format == &llvm::APFloat::IEEEquad()) - return llvm::Type::getFP128Ty(VMContext); - if (&format == &llvm::APFloat::PPCDoubleDouble()) - return llvm::Type::getPPC_FP128Ty(VMContext); - if (&format == &llvm::APFloat::x87DoubleExtended()) - return llvm::Type::getX86_FP80Ty(VMContext); - llvm_unreachable("Unknown float format!"); -} - -llvm::Type *CodeGenTypes::ConvertFunctionType(QualType QFT, - const FunctionDecl *FD) { - assert(QFT.isCanonical()); - const Type *Ty = QFT.getTypePtr(); - const FunctionType *FT = cast<FunctionType>(QFT.getTypePtr()); - // First, check whether we can build the full function type. If the - // function type depends on an incomplete type (e.g. a struct or enum), we - // cannot lower the function type. - if (!isFuncTypeConvertible(FT)) { - // This function's type depends on an incomplete tag type. - - // Force conversion of all the relevant record types, to make sure - // we re-convert the FunctionType when appropriate. - if (const RecordType *RT = FT->getReturnType()->getAs<RecordType>()) - ConvertRecordDeclType(RT->getDecl()); - if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT)) - for (unsigned i = 0, e = FPT->getNumParams(); i != e; i++) - if (const RecordType *RT = FPT->getParamType(i)->getAs<RecordType>()) - ConvertRecordDeclType(RT->getDecl()); - - SkippedLayout = true; - - // Return a placeholder type. - return llvm::StructType::get(getLLVMContext()); - } - - // While we're converting the parameter types for a function, we don't want - // to recursively convert any pointed-to structs. Converting directly-used - // structs is ok though. - if (!RecordsBeingLaidOut.insert(Ty).second) { - SkippedLayout = true; - return llvm::StructType::get(getLLVMContext()); - } - - // The function type can be built; call the appropriate routines to - // build it. - const CGFunctionInfo *FI; - if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT)) { - FI = &arrangeFreeFunctionType( - CanQual<FunctionProtoType>::CreateUnsafe(QualType(FPT, 0)), FD); - } else { - const FunctionNoProtoType *FNPT = cast<FunctionNoProtoType>(FT); - FI = &arrangeFreeFunctionType( - CanQual<FunctionNoProtoType>::CreateUnsafe(QualType(FNPT, 0))); - } - - llvm::Type *ResultType = nullptr; - // If there is something higher level prodding our CGFunctionInfo, then - // don't recurse into it again. - if (FunctionsBeingProcessed.count(FI)) { - - ResultType = llvm::StructType::get(getLLVMContext()); - SkippedLayout = true; - } else { - - // Otherwise, we're good to go, go ahead and convert it. - ResultType = GetFunctionType(*FI); - } - - RecordsBeingLaidOut.erase(Ty); - - if (SkippedLayout) - TypeCache.clear(); - - if (RecordsBeingLaidOut.empty()) - while (!DeferredRecords.empty()) - ConvertRecordDeclType(DeferredRecords.pop_back_val()); - return ResultType; -} - -/// ConvertType - Convert the specified type to its LLVM form. -llvm::Type *CodeGenTypes::ConvertType(QualType T) { - T = Context.getCanonicalType(T); - - const Type *Ty = T.getTypePtr(); - - // RecordTypes are cached and processed specially. - if (const RecordType *RT = dyn_cast<RecordType>(Ty)) - return ConvertRecordDeclType(RT->getDecl()); - - // See if type is already cached. - llvm::DenseMap<const Type *, llvm::Type *>::iterator TCI = TypeCache.find(Ty); - // If type is found in map then use it. Otherwise, convert type T. - if (TCI != TypeCache.end()) - return TCI->second; - - // If we don't have it in the cache, convert it now. - llvm::Type *ResultType = nullptr; - switch (Ty->getTypeClass()) { - case Type::Record: // Handled above. -#define TYPE(Class, Base) -#define ABSTRACT_TYPE(Class, Base) -#define NON_CANONICAL_TYPE(Class, Base) case Type::Class: -#define DEPENDENT_TYPE(Class, Base) case Type::Class: -#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class: -#include "clang/AST/TypeNodes.def" - llvm_unreachable("Non-canonical or dependent types aren't possible."); - - case Type::Builtin: { - switch (cast<BuiltinType>(Ty)->getKind()) { - case BuiltinType::Void: - case BuiltinType::ObjCId: - case BuiltinType::ObjCClass: - case BuiltinType::ObjCSel: - // LLVM void type can only be used as the result of a function call. Just - // map to the same as char. - ResultType = llvm::Type::getInt8Ty(getLLVMContext()); - break; - - case BuiltinType::Bool: - // Note that we always return bool as i1 for use as a scalar type. - ResultType = llvm::Type::getInt1Ty(getLLVMContext()); - break; - - case BuiltinType::Char_S: - case BuiltinType::Char_U: - case BuiltinType::SChar: - case BuiltinType::UChar: - case BuiltinType::Short: - case BuiltinType::UShort: - case BuiltinType::Int: - case BuiltinType::UInt: - case BuiltinType::Long: - case BuiltinType::ULong: - case BuiltinType::LongLong: - case BuiltinType::ULongLong: - case BuiltinType::WChar_S: - case BuiltinType::WChar_U: - case BuiltinType::Char8: - case BuiltinType::Char16: - case BuiltinType::Char32: - case BuiltinType::ShortAccum: - case BuiltinType::Accum: - case BuiltinType::LongAccum: - case BuiltinType::UShortAccum: - case BuiltinType::UAccum: - case BuiltinType::ULongAccum: - case BuiltinType::ShortFract: - case BuiltinType::Fract: - case BuiltinType::LongFract: - case BuiltinType::UShortFract: - case BuiltinType::UFract: - case BuiltinType::ULongFract: - case BuiltinType::SatShortAccum: - case BuiltinType::SatAccum: - case BuiltinType::SatLongAccum: - case BuiltinType::SatUShortAccum: - case BuiltinType::SatUAccum: - case BuiltinType::SatULongAccum: - case BuiltinType::SatShortFract: - case BuiltinType::SatFract: - case BuiltinType::SatLongFract: - case BuiltinType::SatUShortFract: - case BuiltinType::SatUFract: - case BuiltinType::SatULongFract: - ResultType = llvm::IntegerType::get(getLLVMContext(), - static_cast<unsigned>(Context.getTypeSize(T))); - break; - - case BuiltinType::Float16: - ResultType = - getTypeForFormat(getLLVMContext(), Context.getFloatTypeSemantics(T), - /* UseNativeHalf = */ true); - break; - - case BuiltinType::Half: - // Half FP can either be storage-only (lowered to i16) or native. - ResultType = getTypeForFormat( - getLLVMContext(), Context.getFloatTypeSemantics(T), - Context.getLangOpts().NativeHalfType || - !Context.getTargetInfo().useFP16ConversionIntrinsics()); - break; - case BuiltinType::Float: - case BuiltinType::Double: - case BuiltinType::LongDouble: - case BuiltinType::Float128: - ResultType = getTypeForFormat(getLLVMContext(), - Context.getFloatTypeSemantics(T), - /* UseNativeHalf = */ false); - break; - - case BuiltinType::NullPtr: - // Model std::nullptr_t as i8* - ResultType = llvm::Type::getInt8PtrTy(getLLVMContext()); - break; - - case BuiltinType::UInt128: - case BuiltinType::Int128: - ResultType = llvm::IntegerType::get(getLLVMContext(), 128); - break; - -#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ - case BuiltinType::Id: -#include "clang/Basic/OpenCLImageTypes.def" -#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ - case BuiltinType::Id: -#include "clang/Basic/OpenCLExtensionTypes.def" - case BuiltinType::OCLSampler: - case BuiltinType::OCLEvent: - case BuiltinType::OCLClkEvent: - case BuiltinType::OCLQueue: - case BuiltinType::OCLReserveID: - ResultType = CGM.getOpenCLRuntime().convertOpenCLSpecificType(Ty); - break; - - case BuiltinType::Dependent: -#define BUILTIN_TYPE(Id, SingletonId) -#define PLACEHOLDER_TYPE(Id, SingletonId) \ - case BuiltinType::Id: -#include "clang/AST/BuiltinTypes.def" - llvm_unreachable("Unexpected placeholder builtin type!"); - } - break; - } - case Type::Auto: - case Type::DeducedTemplateSpecialization: - llvm_unreachable("Unexpected undeduced type!"); - case Type::Complex: { - llvm::Type *EltTy = ConvertType(cast<ComplexType>(Ty)->getElementType()); - ResultType = llvm::StructType::get(EltTy, EltTy); - break; - } - case Type::LValueReference: - case Type::RValueReference: { - const ReferenceType *RTy = cast<ReferenceType>(Ty); - QualType ETy = RTy->getPointeeType(); - llvm::Type *PointeeType = ConvertTypeForMem(ETy); - unsigned AS = Context.getTargetAddressSpace(ETy); - ResultType = llvm::PointerType::get(PointeeType, AS); - break; - } - case Type::Pointer: { - const PointerType *PTy = cast<PointerType>(Ty); - QualType ETy = PTy->getPointeeType(); - llvm::Type *PointeeType = ConvertTypeForMem(ETy); - if (PointeeType->isVoidTy()) - PointeeType = llvm::Type::getInt8Ty(getLLVMContext()); - unsigned AS = Context.getTargetAddressSpace(ETy); - ResultType = llvm::PointerType::get(PointeeType, AS); - break; - } - - case Type::VariableArray: { - const VariableArrayType *A = cast<VariableArrayType>(Ty); - assert(A->getIndexTypeCVRQualifiers() == 0 && - "FIXME: We only handle trivial array types so far!"); - // VLAs resolve to the innermost element type; this matches - // the return of alloca, and there isn't any obviously better choice. - ResultType = ConvertTypeForMem(A->getElementType()); - break; - } - case Type::IncompleteArray: { - const IncompleteArrayType *A = cast<IncompleteArrayType>(Ty); - assert(A->getIndexTypeCVRQualifiers() == 0 && - "FIXME: We only handle trivial array types so far!"); - // int X[] -> [0 x int], unless the element type is not sized. If it is - // unsized (e.g. an incomplete struct) just use [0 x i8]. - ResultType = ConvertTypeForMem(A->getElementType()); - if (!ResultType->isSized()) { - SkippedLayout = true; - ResultType = llvm::Type::getInt8Ty(getLLVMContext()); - } - ResultType = llvm::ArrayType::get(ResultType, 0); - break; - } - case Type::ConstantArray: { - const ConstantArrayType *A = cast<ConstantArrayType>(Ty); - llvm::Type *EltTy = ConvertTypeForMem(A->getElementType()); - - // Lower arrays of undefined struct type to arrays of i8 just to have a - // concrete type. - if (!EltTy->isSized()) { - SkippedLayout = true; - EltTy = llvm::Type::getInt8Ty(getLLVMContext()); - } - - ResultType = llvm::ArrayType::get(EltTy, A->getSize().getZExtValue()); - break; - } - case Type::ExtVector: - case Type::Vector: { - const VectorType *VT = cast<VectorType>(Ty); - ResultType = llvm::VectorType::get(ConvertType(VT->getElementType()), - VT->getNumElements()); - break; - } - case Type::FunctionNoProto: - case Type::FunctionProto: - ResultType = ConvertFunctionType(T); - break; - case Type::ObjCObject: - ResultType = ConvertType(cast<ObjCObjectType>(Ty)->getBaseType()); - break; - - case Type::ObjCInterface: { - // Objective-C interfaces are always opaque (outside of the - // runtime, which can do whatever it likes); we never refine - // these. - llvm::Type *&T = InterfaceTypes[cast<ObjCInterfaceType>(Ty)]; - if (!T) - T = llvm::StructType::create(getLLVMContext()); - ResultType = T; - break; - } - - case Type::ObjCObjectPointer: { - // Protocol qualifications do not influence the LLVM type, we just return a - // pointer to the underlying interface type. We don't need to worry about - // recursive conversion. - llvm::Type *T = - ConvertTypeForMem(cast<ObjCObjectPointerType>(Ty)->getPointeeType()); - ResultType = T->getPointerTo(); - break; - } - - case Type::Enum: { - const EnumDecl *ED = cast<EnumType>(Ty)->getDecl(); - if (ED->isCompleteDefinition() || ED->isFixed()) - return ConvertType(ED->getIntegerType()); - // Return a placeholder 'i32' type. This can be changed later when the - // type is defined (see UpdateCompletedType), but is likely to be the - // "right" answer. - ResultType = llvm::Type::getInt32Ty(getLLVMContext()); - break; - } - - case Type::BlockPointer: { - const QualType FTy = cast<BlockPointerType>(Ty)->getPointeeType(); - llvm::Type *PointeeType = ConvertTypeForMem(FTy); - unsigned AS = Context.getTargetAddressSpace(FTy); - ResultType = llvm::PointerType::get(PointeeType, AS); - break; - } - - case Type::MemberPointer: { - auto *MPTy = cast<MemberPointerType>(Ty); - if (!getCXXABI().isMemberPointerConvertible(MPTy)) { - RecordsWithOpaqueMemberPointers.insert(MPTy->getClass()); - ResultType = llvm::StructType::create(getLLVMContext()); - } else { - ResultType = getCXXABI().ConvertMemberPointerType(MPTy); - } - break; - } - - case Type::Atomic: { - QualType valueType = cast<AtomicType>(Ty)->getValueType(); - ResultType = ConvertTypeForMem(valueType); - - // Pad out to the inflated size if necessary. - uint64_t valueSize = Context.getTypeSize(valueType); - uint64_t atomicSize = Context.getTypeSize(Ty); - if (valueSize != atomicSize) { - assert(valueSize < atomicSize); - llvm::Type *elts[] = { - ResultType, - llvm::ArrayType::get(CGM.Int8Ty, (atomicSize - valueSize) / 8) - }; - ResultType = llvm::StructType::get(getLLVMContext(), - llvm::makeArrayRef(elts)); - } - break; - } - case Type::Pipe: { - ResultType = CGM.getOpenCLRuntime().getPipeType(cast<PipeType>(Ty)); - break; - } - } - - assert(ResultType && "Didn't convert a type?"); - - TypeCache[Ty] = ResultType; - return ResultType; -} - -bool CodeGenModule::isPaddedAtomicType(QualType type) { - return isPaddedAtomicType(type->castAs<AtomicType>()); -} - -bool CodeGenModule::isPaddedAtomicType(const AtomicType *type) { - return Context.getTypeSize(type) != Context.getTypeSize(type->getValueType()); -} - -/// ConvertRecordDeclType - Lay out a tagged decl type like struct or union. -llvm::StructType *CodeGenTypes::ConvertRecordDeclType(const RecordDecl *RD) { - // TagDecl's are not necessarily unique, instead use the (clang) - // type connected to the decl. - const Type *Key = Context.getTagDeclType(RD).getTypePtr(); - - llvm::StructType *&Entry = RecordDeclTypes[Key]; - - // If we don't have a StructType at all yet, create the forward declaration. - if (!Entry) { - Entry = llvm::StructType::create(getLLVMContext()); - addRecordTypeName(RD, Entry, ""); - } - llvm::StructType *Ty = Entry; - - // If this is still a forward declaration, or the LLVM type is already - // complete, there's nothing more to do. - RD = RD->getDefinition(); - if (!RD || !RD->isCompleteDefinition() || !Ty->isOpaque()) - return Ty; - - // If converting this type would cause us to infinitely loop, don't do it! - if (!isSafeToConvert(RD, *this)) { - DeferredRecords.push_back(RD); - return Ty; - } - - // Okay, this is a definition of a type. Compile the implementation now. - bool InsertResult = RecordsBeingLaidOut.insert(Key).second; - (void)InsertResult; - assert(InsertResult && "Recursively compiling a struct?"); - - // Force conversion of non-virtual base classes recursively. - if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) { - for (const auto &I : CRD->bases()) { - if (I.isVirtual()) continue; - - ConvertRecordDeclType(I.getType()->getAs<RecordType>()->getDecl()); - } - } - - // Layout fields. - CGRecordLayout *Layout = ComputeRecordLayout(RD, Ty); - CGRecordLayouts[Key] = Layout; - - // We're done laying out this struct. - bool EraseResult = RecordsBeingLaidOut.erase(Key); (void)EraseResult; - assert(EraseResult && "struct not in RecordsBeingLaidOut set?"); - - // If this struct blocked a FunctionType conversion, then recompute whatever - // was derived from that. - // FIXME: This is hugely overconservative. - if (SkippedLayout) - TypeCache.clear(); - - // If we're done converting the outer-most record, then convert any deferred - // structs as well. - if (RecordsBeingLaidOut.empty()) - while (!DeferredRecords.empty()) - ConvertRecordDeclType(DeferredRecords.pop_back_val()); - - return Ty; -} - -/// getCGRecordLayout - Return record layout info for the given record decl. -const CGRecordLayout & -CodeGenTypes::getCGRecordLayout(const RecordDecl *RD) { - const Type *Key = Context.getTagDeclType(RD).getTypePtr(); - - const CGRecordLayout *Layout = CGRecordLayouts.lookup(Key); - if (!Layout) { - // Compute the type information. - ConvertRecordDeclType(RD); - - // Now try again. - Layout = CGRecordLayouts.lookup(Key); - } - - assert(Layout && "Unable to find record layout information for type"); - return *Layout; -} - -bool CodeGenTypes::isPointerZeroInitializable(QualType T) { - assert((T->isAnyPointerType() || T->isBlockPointerType()) && "Invalid type"); - return isZeroInitializable(T); -} - -bool CodeGenTypes::isZeroInitializable(QualType T) { - if (T->getAs<PointerType>()) - return Context.getTargetNullPointerValue(T) == 0; - - if (const auto *AT = Context.getAsArrayType(T)) { - if (isa<IncompleteArrayType>(AT)) - return true; - if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) - if (Context.getConstantArrayElementCount(CAT) == 0) - return true; - T = Context.getBaseElementType(T); - } - - // Records are non-zero-initializable if they contain any - // non-zero-initializable subobjects. - if (const RecordType *RT = T->getAs<RecordType>()) { - const RecordDecl *RD = RT->getDecl(); - return isZeroInitializable(RD); - } - - // We have to ask the ABI about member pointers. - if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) - return getCXXABI().isZeroInitializable(MPT); - - // Everything else is okay. - return true; -} - -bool CodeGenTypes::isZeroInitializable(const RecordDecl *RD) { - return getCGRecordLayout(RD).isZeroInitializable(); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h b/gnu/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h deleted file mode 100644 index 8e344e91b8c..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h +++ /dev/null @@ -1,381 +0,0 @@ -//===--- CodeGenTypes.h - Type translation for LLVM CodeGen -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This is the code that handles AST -> LLVM type lowering. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENTYPES_H -#define LLVM_CLANG_LIB_CODEGEN_CODEGENTYPES_H - -#include "CGCall.h" -#include "clang/Basic/ABI.h" -#include "clang/CodeGen/CGFunctionInfo.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/IR/Module.h" - -namespace llvm { -class FunctionType; -class DataLayout; -class Type; -class LLVMContext; -class StructType; -} - -namespace clang { -class ASTContext; -template <typename> class CanQual; -class CXXConstructorDecl; -class CXXDestructorDecl; -class CXXMethodDecl; -class CodeGenOptions; -class FieldDecl; -class FunctionProtoType; -class ObjCInterfaceDecl; -class ObjCIvarDecl; -class PointerType; -class QualType; -class RecordDecl; -class TagDecl; -class TargetInfo; -class Type; -typedef CanQual<Type> CanQualType; -class GlobalDecl; - -namespace CodeGen { -class ABIInfo; -class CGCXXABI; -class CGRecordLayout; -class CodeGenModule; -class RequiredArgs; - -enum class StructorType { - Complete, // constructor or destructor - Base, // constructor or destructor - Deleting // destructor only -}; - -inline CXXCtorType toCXXCtorType(StructorType T) { - switch (T) { - case StructorType::Complete: - return Ctor_Complete; - case StructorType::Base: - return Ctor_Base; - case StructorType::Deleting: - llvm_unreachable("cannot have a deleting ctor"); - } - llvm_unreachable("not a StructorType"); -} - -inline StructorType getFromCtorType(CXXCtorType T) { - switch (T) { - case Ctor_Complete: - return StructorType::Complete; - case Ctor_Base: - return StructorType::Base; - case Ctor_Comdat: - llvm_unreachable("not expecting a COMDAT"); - case Ctor_CopyingClosure: - case Ctor_DefaultClosure: - llvm_unreachable("not expecting a closure"); - } - llvm_unreachable("not a CXXCtorType"); -} - -inline CXXDtorType toCXXDtorType(StructorType T) { - switch (T) { - case StructorType::Complete: - return Dtor_Complete; - case StructorType::Base: - return Dtor_Base; - case StructorType::Deleting: - return Dtor_Deleting; - } - llvm_unreachable("not a StructorType"); -} - -inline StructorType getFromDtorType(CXXDtorType T) { - switch (T) { - case Dtor_Deleting: - return StructorType::Deleting; - case Dtor_Complete: - return StructorType::Complete; - case Dtor_Base: - return StructorType::Base; - case Dtor_Comdat: - llvm_unreachable("not expecting a COMDAT"); - } - llvm_unreachable("not a CXXDtorType"); -} - -/// This class organizes the cross-module state that is used while lowering -/// AST types to LLVM types. -class CodeGenTypes { - CodeGenModule &CGM; - // Some of this stuff should probably be left on the CGM. - ASTContext &Context; - llvm::Module &TheModule; - const TargetInfo &Target; - CGCXXABI &TheCXXABI; - - // This should not be moved earlier, since its initialization depends on some - // of the previous reference members being already initialized - const ABIInfo &TheABIInfo; - - /// The opaque type map for Objective-C interfaces. All direct - /// manipulation is done by the runtime interfaces, which are - /// responsible for coercing to the appropriate type; these opaque - /// types are never refined. - llvm::DenseMap<const ObjCInterfaceType*, llvm::Type *> InterfaceTypes; - - /// Maps clang struct type with corresponding record layout info. - llvm::DenseMap<const Type*, CGRecordLayout *> CGRecordLayouts; - - /// Contains the LLVM IR type for any converted RecordDecl. - llvm::DenseMap<const Type*, llvm::StructType *> RecordDeclTypes; - - /// Hold memoized CGFunctionInfo results. - llvm::FoldingSet<CGFunctionInfo> FunctionInfos; - - /// This set keeps track of records that we're currently converting - /// to an IR type. For example, when converting: - /// struct A { struct B { int x; } } when processing 'x', the 'A' and 'B' - /// types will be in this set. - llvm::SmallPtrSet<const Type*, 4> RecordsBeingLaidOut; - - llvm::SmallPtrSet<const CGFunctionInfo*, 4> FunctionsBeingProcessed; - - /// True if we didn't layout a function due to a being inside - /// a recursive struct conversion, set this to true. - bool SkippedLayout; - - SmallVector<const RecordDecl *, 8> DeferredRecords; - - /// This map keeps cache of llvm::Types and maps clang::Type to - /// corresponding llvm::Type. - llvm::DenseMap<const Type *, llvm::Type *> TypeCache; - - llvm::SmallSet<const Type *, 8> RecordsWithOpaqueMemberPointers; - -public: - CodeGenTypes(CodeGenModule &cgm); - ~CodeGenTypes(); - - const llvm::DataLayout &getDataLayout() const { - return TheModule.getDataLayout(); - } - ASTContext &getContext() const { return Context; } - const ABIInfo &getABIInfo() const { return TheABIInfo; } - const TargetInfo &getTarget() const { return Target; } - CGCXXABI &getCXXABI() const { return TheCXXABI; } - llvm::LLVMContext &getLLVMContext() { return TheModule.getContext(); } - const CodeGenOptions &getCodeGenOpts() const; - - /// Convert clang calling convention to LLVM callilng convention. - unsigned ClangCallConvToLLVMCallConv(CallingConv CC); - - /// ConvertType - Convert type T into a llvm::Type. - llvm::Type *ConvertType(QualType T); - - /// Converts the GlobalDecl into an llvm::Type. This should be used - /// when we know the target of the function we want to convert. This is - /// because some functions (explicitly, those with pass_object_size - /// parameters) may not have the same signature as their type portrays, and - /// can only be called directly. - llvm::Type *ConvertFunctionType(QualType FT, - const FunctionDecl *FD = nullptr); - - /// ConvertTypeForMem - Convert type T into a llvm::Type. This differs from - /// ConvertType in that it is used to convert to the memory representation for - /// a type. For example, the scalar representation for _Bool is i1, but the - /// memory representation is usually i8 or i32, depending on the target. - llvm::Type *ConvertTypeForMem(QualType T); - - /// GetFunctionType - Get the LLVM function type for \arg Info. - llvm::FunctionType *GetFunctionType(const CGFunctionInfo &Info); - - llvm::FunctionType *GetFunctionType(GlobalDecl GD); - - /// isFuncTypeConvertible - Utility to check whether a function type can - /// be converted to an LLVM type (i.e. doesn't depend on an incomplete tag - /// type). - bool isFuncTypeConvertible(const FunctionType *FT); - bool isFuncParamTypeConvertible(QualType Ty); - - /// Determine if a C++ inheriting constructor should have parameters matching - /// those of its inherited constructor. - bool inheritingCtorHasParams(const InheritedConstructor &Inherited, - CXXCtorType Type); - - /// GetFunctionTypeForVTable - Get the LLVM function type for use in a vtable, - /// given a CXXMethodDecl. If the method to has an incomplete return type, - /// and/or incomplete argument types, this will return the opaque type. - llvm::Type *GetFunctionTypeForVTable(GlobalDecl GD); - - const CGRecordLayout &getCGRecordLayout(const RecordDecl*); - - /// UpdateCompletedType - When we find the full definition for a TagDecl, - /// replace the 'opaque' type we previously made for it if applicable. - void UpdateCompletedType(const TagDecl *TD); - - /// Remove stale types from the type cache when an inheritance model - /// gets assigned to a class. - void RefreshTypeCacheForClass(const CXXRecordDecl *RD); - - // The arrangement methods are split into three families: - // - those meant to drive the signature and prologue/epilogue - // of a function declaration or definition, - // - those meant for the computation of the LLVM type for an abstract - // appearance of a function, and - // - those meant for performing the IR-generation of a call. - // They differ mainly in how they deal with optional (i.e. variadic) - // arguments, as well as unprototyped functions. - // - // Key points: - // - The CGFunctionInfo for emitting a specific call site must include - // entries for the optional arguments. - // - The function type used at the call site must reflect the formal - // signature of the declaration being called, or else the call will - // go awry. - // - For the most part, unprototyped functions are called by casting to - // a formal signature inferred from the specific argument types used - // at the call-site. However, some targets (e.g. x86-64) screw with - // this for compatibility reasons. - - const CGFunctionInfo &arrangeGlobalDeclaration(GlobalDecl GD); - - /// Given a function info for a declaration, return the function info - /// for a call with the given arguments. - /// - /// Often this will be able to simply return the declaration info. - const CGFunctionInfo &arrangeCall(const CGFunctionInfo &declFI, - const CallArgList &args); - - /// Free functions are functions that are compatible with an ordinary - /// C function pointer type. - const CGFunctionInfo &arrangeFunctionDeclaration(const FunctionDecl *FD); - const CGFunctionInfo &arrangeFreeFunctionCall(const CallArgList &Args, - const FunctionType *Ty, - bool ChainCall); - const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty, - const FunctionDecl *FD); - const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionNoProtoType> Ty); - - /// A nullary function is a freestanding function of type 'void ()'. - /// This method works for both calls and declarations. - const CGFunctionInfo &arrangeNullaryFunction(); - - /// A builtin function is a freestanding function using the default - /// C conventions. - const CGFunctionInfo & - arrangeBuiltinFunctionDeclaration(QualType resultType, - const FunctionArgList &args); - const CGFunctionInfo & - arrangeBuiltinFunctionDeclaration(CanQualType resultType, - ArrayRef<CanQualType> argTypes); - const CGFunctionInfo &arrangeBuiltinFunctionCall(QualType resultType, - const CallArgList &args); - - /// Objective-C methods are C functions with some implicit parameters. - const CGFunctionInfo &arrangeObjCMethodDeclaration(const ObjCMethodDecl *MD); - const CGFunctionInfo &arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD, - QualType receiverType); - const CGFunctionInfo &arrangeUnprototypedObjCMessageSend( - QualType returnType, - const CallArgList &args); - - /// Block invocation functions are C functions with an implicit parameter. - const CGFunctionInfo &arrangeBlockFunctionDeclaration( - const FunctionProtoType *type, - const FunctionArgList &args); - const CGFunctionInfo &arrangeBlockFunctionCall(const CallArgList &args, - const FunctionType *type); - - /// C++ methods have some special rules and also have implicit parameters. - const CGFunctionInfo &arrangeCXXMethodDeclaration(const CXXMethodDecl *MD); - const CGFunctionInfo &arrangeCXXStructorDeclaration(const CXXMethodDecl *MD, - StructorType Type); - const CGFunctionInfo &arrangeCXXConstructorCall(const CallArgList &Args, - const CXXConstructorDecl *D, - CXXCtorType CtorKind, - unsigned ExtraPrefixArgs, - unsigned ExtraSuffixArgs, - bool PassProtoArgs = true); - - const CGFunctionInfo &arrangeCXXMethodCall(const CallArgList &args, - const FunctionProtoType *type, - RequiredArgs required, - unsigned numPrefixArgs); - const CGFunctionInfo & - arrangeUnprototypedMustTailThunk(const CXXMethodDecl *MD); - const CGFunctionInfo &arrangeMSCtorClosure(const CXXConstructorDecl *CD, - CXXCtorType CT); - const CGFunctionInfo &arrangeCXXMethodType(const CXXRecordDecl *RD, - const FunctionProtoType *FTP, - const CXXMethodDecl *MD); - - /// "Arrange" the LLVM information for a call or type with the given - /// signature. This is largely an internal method; other clients - /// should use one of the above routines, which ultimately defer to - /// this. - /// - /// \param argTypes - must all actually be canonical as params - const CGFunctionInfo &arrangeLLVMFunctionInfo(CanQualType returnType, - bool instanceMethod, - bool chainCall, - ArrayRef<CanQualType> argTypes, - FunctionType::ExtInfo info, - ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, - RequiredArgs args); - - /// Compute a new LLVM record layout object for the given record. - CGRecordLayout *ComputeRecordLayout(const RecordDecl *D, - llvm::StructType *Ty); - - /// addRecordTypeName - Compute a name from the given record decl with an - /// optional suffix and name the given LLVM type using it. - void addRecordTypeName(const RecordDecl *RD, llvm::StructType *Ty, - StringRef suffix); - - -public: // These are internal details of CGT that shouldn't be used externally. - /// ConvertRecordDeclType - Lay out a tagged decl type like struct or union. - llvm::StructType *ConvertRecordDeclType(const RecordDecl *TD); - - /// getExpandedTypes - Expand the type \arg Ty into the LLVM - /// argument types it would be passed as. See ABIArgInfo::Expand. - void getExpandedTypes(QualType Ty, - SmallVectorImpl<llvm::Type *>::iterator &TI); - - /// IsZeroInitializable - Return whether a type can be - /// zero-initialized (in the C++ sense) with an LLVM zeroinitializer. - bool isZeroInitializable(QualType T); - - /// Check if the pointer type can be zero-initialized (in the C++ sense) - /// with an LLVM zeroinitializer. - bool isPointerZeroInitializable(QualType T); - - /// IsZeroInitializable - Return whether a record type can be - /// zero-initialized (in the C++ sense) with an LLVM zeroinitializer. - bool isZeroInitializable(const RecordDecl *RD); - - bool isRecordLayoutComplete(const Type *Ty) const; - bool noRecordsBeingLaidOut() const { - return RecordsBeingLaidOut.empty(); - } - bool isRecordBeingLaidOut(const Type *Ty) const { - return RecordsBeingLaidOut.count(Ty); - } - -}; - -} // end namespace CodeGen -} // end namespace clang - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/ConstantEmitter.h b/gnu/llvm/tools/clang/lib/CodeGen/ConstantEmitter.h deleted file mode 100644 index 7ad8e5d37cd..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/ConstantEmitter.h +++ /dev/null @@ -1,181 +0,0 @@ -//===--- ConstantEmitter.h - IR constant emission ---------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// A helper class for emitting expressions and values as llvm::Constants -// and as initializers for global variables. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_CONSTANTEMITTER_H -#define LLVM_CLANG_LIB_CODEGEN_CONSTANTEMITTER_H - -#include "CodeGenFunction.h" -#include "CodeGenModule.h" - -namespace clang { -namespace CodeGen { - -class ConstantEmitter { -public: - CodeGenModule &CGM; - CodeGenFunction *CGF; - -private: - bool Abstract = false; - - /// Whether non-abstract components of the emitter have been initialized. - bool InitializedNonAbstract = false; - - /// Whether the emitter has been finalized. - bool Finalized = false; - - /// Whether the constant-emission failed. - bool Failed = false; - - /// Whether we're in a constant context. - bool InConstantContext = false; - - /// The AST address space where this (non-abstract) initializer is going. - /// Used for generating appropriate placeholders. - LangAS DestAddressSpace; - - llvm::SmallVector<std::pair<llvm::Constant *, llvm::GlobalVariable*>, 4> - PlaceholderAddresses; - -public: - ConstantEmitter(CodeGenModule &CGM, CodeGenFunction *CGF = nullptr) - : CGM(CGM), CGF(CGF) {} - - /// Initialize this emission in the context of the given function. - /// Use this if the expression might contain contextual references like - /// block addresses or PredefinedExprs. - ConstantEmitter(CodeGenFunction &CGF) - : CGM(CGF.CGM), CGF(&CGF) {} - - ConstantEmitter(const ConstantEmitter &other) = delete; - ConstantEmitter &operator=(const ConstantEmitter &other) = delete; - - ~ConstantEmitter(); - - /// Is the current emission context abstract? - bool isAbstract() const { - return Abstract; - } - - /// Try to emit the initiaizer of the given declaration as an abstract - /// constant. If this succeeds, the emission must be finalized. - llvm::Constant *tryEmitForInitializer(const VarDecl &D); - llvm::Constant *tryEmitForInitializer(const Expr *E, LangAS destAddrSpace, - QualType destType); - llvm::Constant *emitForInitializer(const APValue &value, LangAS destAddrSpace, - QualType destType); - - void finalize(llvm::GlobalVariable *global); - - // All of the "abstract" emission methods below permit the emission to - // be immediately discarded without finalizing anything. Therefore, they - // must also promise not to do anything that will, in the future, require - // finalization: - // - // - using the CGF (if present) for anything other than establishing - // semantic context; for example, an expression with ignored - // side-effects must not be emitted as an abstract expression - // - // - doing anything that would not be safe to duplicate within an - // initializer or to propagate to another context; for example, - // side effects, or emitting an initialization that requires a - // reference to its current location. - - /// Try to emit the initializer of the given declaration as an abstract - /// constant. - llvm::Constant *tryEmitAbstractForInitializer(const VarDecl &D); - - /// Emit the result of the given expression as an abstract constant, - /// asserting that it succeeded. This is only safe to do when the - /// expression is known to be a constant expression with either a fairly - /// simple type or a known simple form. - llvm::Constant *emitAbstract(const Expr *E, QualType T); - llvm::Constant *emitAbstract(SourceLocation loc, const APValue &value, - QualType T); - - /// Try to emit the result of the given expression as an abstract constant. - llvm::Constant *tryEmitAbstract(const Expr *E, QualType T); - llvm::Constant *tryEmitAbstractForMemory(const Expr *E, QualType T); - - llvm::Constant *tryEmitAbstract(const APValue &value, QualType T); - llvm::Constant *tryEmitAbstractForMemory(const APValue &value, QualType T); - - llvm::Constant *emitNullForMemory(QualType T) { - return emitNullForMemory(CGM, T); - } - llvm::Constant *emitForMemory(llvm::Constant *C, QualType T) { - return emitForMemory(CGM, C, T); - } - - static llvm::Constant *emitNullForMemory(CodeGenModule &CGM, QualType T); - static llvm::Constant *emitForMemory(CodeGenModule &CGM, llvm::Constant *C, - QualType T); - - // These are private helper routines of the constant emitter that - // can't actually be private because things are split out into helper - // functions and classes. - - llvm::Constant *tryEmitPrivateForVarInit(const VarDecl &D); - - llvm::Constant *tryEmitPrivate(const Expr *E, QualType T); - llvm::Constant *tryEmitPrivateForMemory(const Expr *E, QualType T); - - llvm::Constant *tryEmitPrivate(const APValue &value, QualType T); - llvm::Constant *tryEmitPrivateForMemory(const APValue &value, QualType T); - - /// Get the address of the current location. This is a constant - /// that will resolve, after finalization, to the address of the - /// 'signal' value that is registered with the emitter later. - llvm::GlobalValue *getCurrentAddrPrivate(); - - /// Register a 'signal' value with the emitter to inform it where to - /// resolve a placeholder. The signal value must be unique in the - /// initializer; it might, for example, be the address of a global that - /// refers to the current-address value in its own initializer. - /// - /// Uses of the placeholder must be properly anchored before finalizing - /// the emitter, e.g. by being installed as the initializer of a global - /// variable. That is, it must be possible to replaceAllUsesWith - /// the placeholder with the proper address of the signal. - void registerCurrentAddrPrivate(llvm::Constant *signal, - llvm::GlobalValue *placeholder); - -private: - void initializeNonAbstract(LangAS destAS) { - assert(!InitializedNonAbstract); - InitializedNonAbstract = true; - DestAddressSpace = destAS; - } - llvm::Constant *markIfFailed(llvm::Constant *init) { - if (!init) - Failed = true; - return init; - } - - struct AbstractState { - bool OldValue; - size_t OldPlaceholdersSize; - }; - AbstractState pushAbstract() { - AbstractState saved = { Abstract, PlaceholderAddresses.size() }; - Abstract = true; - return saved; - } - llvm::Constant *validateAndPopAbstract(llvm::Constant *C, AbstractState save); -}; - -} -} - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/ConstantInitBuilder.cpp b/gnu/llvm/tools/clang/lib/CodeGen/ConstantInitBuilder.cpp deleted file mode 100644 index 59e66b88fb0..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/ConstantInitBuilder.cpp +++ /dev/null @@ -1,280 +0,0 @@ -//===--- ConstantInitBuilder.cpp - Global initializer builder -------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines out-of-line routines for building initializers for -// global variables, in particular the kind of globals that are implicitly -// introduced by various language ABIs. -// -//===----------------------------------------------------------------------===// - -#include "clang/CodeGen/ConstantInitBuilder.h" -#include "CodeGenModule.h" - -using namespace clang; -using namespace CodeGen; - -llvm::Type *ConstantInitFuture::getType() const { - assert(Data && "dereferencing null future"); - if (Data.is<llvm::Constant*>()) { - return Data.get<llvm::Constant*>()->getType(); - } else { - return Data.get<ConstantInitBuilderBase*>()->Buffer[0]->getType(); - } -} - -void ConstantInitFuture::abandon() { - assert(Data && "abandoning null future"); - if (auto builder = Data.dyn_cast<ConstantInitBuilderBase*>()) { - builder->abandon(0); - } - Data = nullptr; -} - -void ConstantInitFuture::installInGlobal(llvm::GlobalVariable *GV) { - assert(Data && "installing null future"); - if (Data.is<llvm::Constant*>()) { - GV->setInitializer(Data.get<llvm::Constant*>()); - } else { - auto &builder = *Data.get<ConstantInitBuilderBase*>(); - assert(builder.Buffer.size() == 1); - builder.setGlobalInitializer(GV, builder.Buffer[0]); - builder.Buffer.clear(); - Data = nullptr; - } -} - -ConstantInitFuture -ConstantInitBuilderBase::createFuture(llvm::Constant *initializer) { - assert(Buffer.empty() && "buffer not current empty"); - Buffer.push_back(initializer); - return ConstantInitFuture(this); -} - -// Only used in this file. -inline ConstantInitFuture::ConstantInitFuture(ConstantInitBuilderBase *builder) - : Data(builder) { - assert(!builder->Frozen); - assert(builder->Buffer.size() == 1); - assert(builder->Buffer[0] != nullptr); -} - -llvm::GlobalVariable * -ConstantInitBuilderBase::createGlobal(llvm::Constant *initializer, - const llvm::Twine &name, - CharUnits alignment, - bool constant, - llvm::GlobalValue::LinkageTypes linkage, - unsigned addressSpace) { - auto GV = new llvm::GlobalVariable(CGM.getModule(), - initializer->getType(), - constant, - linkage, - initializer, - name, - /*insert before*/ nullptr, - llvm::GlobalValue::NotThreadLocal, - addressSpace); - GV->setAlignment(alignment.getQuantity()); - resolveSelfReferences(GV); - return GV; -} - -void ConstantInitBuilderBase::setGlobalInitializer(llvm::GlobalVariable *GV, - llvm::Constant *initializer){ - GV->setInitializer(initializer); - - if (!SelfReferences.empty()) - resolveSelfReferences(GV); -} - -void ConstantInitBuilderBase::resolveSelfReferences(llvm::GlobalVariable *GV) { - for (auto &entry : SelfReferences) { - llvm::Constant *resolvedReference = - llvm::ConstantExpr::getInBoundsGetElementPtr( - GV->getValueType(), GV, entry.Indices); - auto dummy = entry.Dummy; - dummy->replaceAllUsesWith(resolvedReference); - dummy->eraseFromParent(); - } - SelfReferences.clear(); -} - -void ConstantInitBuilderBase::abandon(size_t newEnd) { - // Remove all the entries we've added. - Buffer.erase(Buffer.begin() + newEnd, Buffer.end()); - - // If we're abandoning all the way to the beginning, destroy - // all the self-references, because we might not get another - // opportunity. - if (newEnd == 0) { - for (auto &entry : SelfReferences) { - auto dummy = entry.Dummy; - dummy->replaceAllUsesWith(llvm::UndefValue::get(dummy->getType())); - dummy->eraseFromParent(); - } - SelfReferences.clear(); - } -} - -void ConstantAggregateBuilderBase::addSize(CharUnits size) { - add(Builder.CGM.getSize(size)); -} - -llvm::Constant * -ConstantAggregateBuilderBase::getRelativeOffset(llvm::IntegerType *offsetType, - llvm::Constant *target) { - // Compute the address of the relative-address slot. - auto base = getAddrOfCurrentPosition(offsetType); - - // Subtract. - base = llvm::ConstantExpr::getPtrToInt(base, Builder.CGM.IntPtrTy); - target = llvm::ConstantExpr::getPtrToInt(target, Builder.CGM.IntPtrTy); - llvm::Constant *offset = llvm::ConstantExpr::getSub(target, base); - - // Truncate to the relative-address type if necessary. - if (Builder.CGM.IntPtrTy != offsetType) { - offset = llvm::ConstantExpr::getTrunc(offset, offsetType); - } - - return offset; -} - -llvm::Constant * -ConstantAggregateBuilderBase::getAddrOfCurrentPosition(llvm::Type *type) { - // Make a global variable. We will replace this with a GEP to this - // position after installing the initializer. - auto dummy = - new llvm::GlobalVariable(Builder.CGM.getModule(), type, true, - llvm::GlobalVariable::PrivateLinkage, - nullptr, ""); - Builder.SelfReferences.emplace_back(dummy); - auto &entry = Builder.SelfReferences.back(); - (void) getGEPIndicesToCurrentPosition(entry.Indices); - return dummy; -} - -void ConstantAggregateBuilderBase::getGEPIndicesTo( - llvm::SmallVectorImpl<llvm::Constant*> &indices, - size_t position) const { - // Recurse on the parent builder if present. - if (Parent) { - Parent->getGEPIndicesTo(indices, Begin); - - // Otherwise, add an index to drill into the first level of pointer. - } else { - assert(indices.empty()); - indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty, 0)); - } - - assert(position >= Begin); - // We have to use i32 here because struct GEPs demand i32 indices. - // It's rather unlikely to matter in practice. - indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty, - position - Begin)); -} - -ConstantAggregateBuilderBase::PlaceholderPosition -ConstantAggregateBuilderBase::addPlaceholderWithSize(llvm::Type *type) { - // Bring the offset up to the last field. - CharUnits offset = getNextOffsetFromGlobal(); - - // Create the placeholder. - auto position = addPlaceholder(); - - // Advance the offset past that field. - auto &layout = Builder.CGM.getDataLayout(); - if (!Packed) - offset = offset.alignTo(CharUnits::fromQuantity( - layout.getABITypeAlignment(type))); - offset += CharUnits::fromQuantity(layout.getTypeStoreSize(type)); - - CachedOffsetEnd = Builder.Buffer.size(); - CachedOffsetFromGlobal = offset; - - return position; -} - -CharUnits ConstantAggregateBuilderBase::getOffsetFromGlobalTo(size_t end) const{ - size_t cacheEnd = CachedOffsetEnd; - assert(cacheEnd <= end); - - // Fast path: if the cache is valid, just use it. - if (cacheEnd == end) { - return CachedOffsetFromGlobal; - } - - // If the cached range ends before the index at which the current - // aggregate starts, recurse for the parent. - CharUnits offset; - if (cacheEnd < Begin) { - assert(cacheEnd == 0); - assert(Parent && "Begin != 0 for root builder"); - cacheEnd = Begin; - offset = Parent->getOffsetFromGlobalTo(Begin); - } else { - offset = CachedOffsetFromGlobal; - } - - // Perform simple layout on the elements in cacheEnd..<end. - if (cacheEnd != end) { - auto &layout = Builder.CGM.getDataLayout(); - do { - llvm::Constant *element = Builder.Buffer[cacheEnd]; - assert(element != nullptr && - "cannot compute offset when a placeholder is present"); - llvm::Type *elementType = element->getType(); - if (!Packed) - offset = offset.alignTo(CharUnits::fromQuantity( - layout.getABITypeAlignment(elementType))); - offset += CharUnits::fromQuantity(layout.getTypeStoreSize(elementType)); - } while (++cacheEnd != end); - } - - // Cache and return. - CachedOffsetEnd = cacheEnd; - CachedOffsetFromGlobal = offset; - return offset; -} - -llvm::Constant *ConstantAggregateBuilderBase::finishArray(llvm::Type *eltTy) { - markFinished(); - - auto &buffer = getBuffer(); - assert((Begin < buffer.size() || - (Begin == buffer.size() && eltTy)) - && "didn't add any array elements without element type"); - auto elts = llvm::makeArrayRef(buffer).slice(Begin); - if (!eltTy) eltTy = elts[0]->getType(); - auto type = llvm::ArrayType::get(eltTy, elts.size()); - auto constant = llvm::ConstantArray::get(type, elts); - buffer.erase(buffer.begin() + Begin, buffer.end()); - return constant; -} - -llvm::Constant * -ConstantAggregateBuilderBase::finishStruct(llvm::StructType *ty) { - markFinished(); - - auto &buffer = getBuffer(); - auto elts = llvm::makeArrayRef(buffer).slice(Begin); - - if (ty == nullptr && elts.empty()) - ty = llvm::StructType::get(Builder.CGM.getLLVMContext(), {}, Packed); - - llvm::Constant *constant; - if (ty) { - assert(ty->isPacked() == Packed); - constant = llvm::ConstantStruct::get(ty, elts); - } else { - constant = llvm::ConstantStruct::getAnon(elts, Packed); - } - - buffer.erase(buffer.begin() + Begin, buffer.end()); - return constant; -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp deleted file mode 100644 index 35962c73d9a..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp +++ /dev/null @@ -1,1476 +0,0 @@ -//===--- CoverageMappingGen.cpp - Coverage mapping generation ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Instrumentation-based code coverage mapping generator -// -//===----------------------------------------------------------------------===// - -#include "CoverageMappingGen.h" -#include "CodeGenFunction.h" -#include "clang/AST/StmtVisitor.h" -#include "clang/Lex/Lexer.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ProfileData/Coverage/CoverageMapping.h" -#include "llvm/ProfileData/Coverage/CoverageMappingReader.h" -#include "llvm/ProfileData/Coverage/CoverageMappingWriter.h" -#include "llvm/ProfileData/InstrProfReader.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Path.h" - -using namespace clang; -using namespace CodeGen; -using namespace llvm::coverage; - -void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range, SourceLocation) { - SkippedRanges.push_back(Range); -} - -namespace { - -/// A region of source code that can be mapped to a counter. -class SourceMappingRegion { - Counter Count; - - /// The region's starting location. - Optional<SourceLocation> LocStart; - - /// The region's ending location. - Optional<SourceLocation> LocEnd; - - /// Whether this region should be emitted after its parent is emitted. - bool DeferRegion; - - /// Whether this region is a gap region. The count from a gap region is set - /// as the line execution count if there are no other regions on the line. - bool GapRegion; - -public: - SourceMappingRegion(Counter Count, Optional<SourceLocation> LocStart, - Optional<SourceLocation> LocEnd, bool DeferRegion = false, - bool GapRegion = false) - : Count(Count), LocStart(LocStart), LocEnd(LocEnd), - DeferRegion(DeferRegion), GapRegion(GapRegion) {} - - const Counter &getCounter() const { return Count; } - - void setCounter(Counter C) { Count = C; } - - bool hasStartLoc() const { return LocStart.hasValue(); } - - void setStartLoc(SourceLocation Loc) { LocStart = Loc; } - - SourceLocation getBeginLoc() const { - assert(LocStart && "Region has no start location"); - return *LocStart; - } - - bool hasEndLoc() const { return LocEnd.hasValue(); } - - void setEndLoc(SourceLocation Loc) { - assert(Loc.isValid() && "Setting an invalid end location"); - LocEnd = Loc; - } - - SourceLocation getEndLoc() const { - assert(LocEnd && "Region has no end location"); - return *LocEnd; - } - - bool isDeferred() const { return DeferRegion; } - - void setDeferred(bool Deferred) { DeferRegion = Deferred; } - - bool isGap() const { return GapRegion; } - - void setGap(bool Gap) { GapRegion = Gap; } -}; - -/// Spelling locations for the start and end of a source region. -struct SpellingRegion { - /// The line where the region starts. - unsigned LineStart; - - /// The column where the region starts. - unsigned ColumnStart; - - /// The line where the region ends. - unsigned LineEnd; - - /// The column where the region ends. - unsigned ColumnEnd; - - SpellingRegion(SourceManager &SM, SourceLocation LocStart, - SourceLocation LocEnd) { - LineStart = SM.getSpellingLineNumber(LocStart); - ColumnStart = SM.getSpellingColumnNumber(LocStart); - LineEnd = SM.getSpellingLineNumber(LocEnd); - ColumnEnd = SM.getSpellingColumnNumber(LocEnd); - } - - SpellingRegion(SourceManager &SM, SourceMappingRegion &R) - : SpellingRegion(SM, R.getBeginLoc(), R.getEndLoc()) {} - - /// Check if the start and end locations appear in source order, i.e - /// top->bottom, left->right. - bool isInSourceOrder() const { - return (LineStart < LineEnd) || - (LineStart == LineEnd && ColumnStart <= ColumnEnd); - } -}; - -/// Provides the common functionality for the different -/// coverage mapping region builders. -class CoverageMappingBuilder { -public: - CoverageMappingModuleGen &CVM; - SourceManager &SM; - const LangOptions &LangOpts; - -private: - /// Map of clang's FileIDs to IDs used for coverage mapping. - llvm::SmallDenseMap<FileID, std::pair<unsigned, SourceLocation>, 8> - FileIDMapping; - -public: - /// The coverage mapping regions for this function - llvm::SmallVector<CounterMappingRegion, 32> MappingRegions; - /// The source mapping regions for this function. - std::vector<SourceMappingRegion> SourceRegions; - - /// A set of regions which can be used as a filter. - /// - /// It is produced by emitExpansionRegions() and is used in - /// emitSourceRegions() to suppress producing code regions if - /// the same area is covered by expansion regions. - typedef llvm::SmallSet<std::pair<SourceLocation, SourceLocation>, 8> - SourceRegionFilter; - - CoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM, - const LangOptions &LangOpts) - : CVM(CVM), SM(SM), LangOpts(LangOpts) {} - - /// Return the precise end location for the given token. - SourceLocation getPreciseTokenLocEnd(SourceLocation Loc) { - // We avoid getLocForEndOfToken here, because it doesn't do what we want for - // macro locations, which we just treat as expanded files. - unsigned TokLen = - Lexer::MeasureTokenLength(SM.getSpellingLoc(Loc), SM, LangOpts); - return Loc.getLocWithOffset(TokLen); - } - - /// Return the start location of an included file or expanded macro. - SourceLocation getStartOfFileOrMacro(SourceLocation Loc) { - if (Loc.isMacroID()) - return Loc.getLocWithOffset(-SM.getFileOffset(Loc)); - return SM.getLocForStartOfFile(SM.getFileID(Loc)); - } - - /// Return the end location of an included file or expanded macro. - SourceLocation getEndOfFileOrMacro(SourceLocation Loc) { - if (Loc.isMacroID()) - return Loc.getLocWithOffset(SM.getFileIDSize(SM.getFileID(Loc)) - - SM.getFileOffset(Loc)); - return SM.getLocForEndOfFile(SM.getFileID(Loc)); - } - - /// Find out where the current file is included or macro is expanded. - SourceLocation getIncludeOrExpansionLoc(SourceLocation Loc) { - return Loc.isMacroID() ? SM.getImmediateExpansionRange(Loc).getBegin() - : SM.getIncludeLoc(SM.getFileID(Loc)); - } - - /// Return true if \c Loc is a location in a built-in macro. - bool isInBuiltin(SourceLocation Loc) { - return SM.getBufferName(SM.getSpellingLoc(Loc)) == "<built-in>"; - } - - /// Check whether \c Loc is included or expanded from \c Parent. - bool isNestedIn(SourceLocation Loc, FileID Parent) { - do { - Loc = getIncludeOrExpansionLoc(Loc); - if (Loc.isInvalid()) - return false; - } while (!SM.isInFileID(Loc, Parent)); - return true; - } - - /// Get the start of \c S ignoring macro arguments and builtin macros. - SourceLocation getStart(const Stmt *S) { - SourceLocation Loc = S->getBeginLoc(); - while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc)) - Loc = SM.getImmediateExpansionRange(Loc).getBegin(); - return Loc; - } - - /// Get the end of \c S ignoring macro arguments and builtin macros. - SourceLocation getEnd(const Stmt *S) { - SourceLocation Loc = S->getEndLoc(); - while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc)) - Loc = SM.getImmediateExpansionRange(Loc).getBegin(); - return getPreciseTokenLocEnd(Loc); - } - - /// Find the set of files we have regions for and assign IDs - /// - /// Fills \c Mapping with the virtual file mapping needed to write out - /// coverage and collects the necessary file information to emit source and - /// expansion regions. - void gatherFileIDs(SmallVectorImpl<unsigned> &Mapping) { - FileIDMapping.clear(); - - llvm::SmallSet<FileID, 8> Visited; - SmallVector<std::pair<SourceLocation, unsigned>, 8> FileLocs; - for (const auto &Region : SourceRegions) { - SourceLocation Loc = Region.getBeginLoc(); - FileID File = SM.getFileID(Loc); - if (!Visited.insert(File).second) - continue; - - // Do not map FileID's associated with system headers. - if (SM.isInSystemHeader(SM.getSpellingLoc(Loc))) - continue; - - unsigned Depth = 0; - for (SourceLocation Parent = getIncludeOrExpansionLoc(Loc); - Parent.isValid(); Parent = getIncludeOrExpansionLoc(Parent)) - ++Depth; - FileLocs.push_back(std::make_pair(Loc, Depth)); - } - std::stable_sort(FileLocs.begin(), FileLocs.end(), llvm::less_second()); - - for (const auto &FL : FileLocs) { - SourceLocation Loc = FL.first; - FileID SpellingFile = SM.getDecomposedSpellingLoc(Loc).first; - auto Entry = SM.getFileEntryForID(SpellingFile); - if (!Entry) - continue; - - FileIDMapping[SM.getFileID(Loc)] = std::make_pair(Mapping.size(), Loc); - Mapping.push_back(CVM.getFileID(Entry)); - } - } - - /// Get the coverage mapping file ID for \c Loc. - /// - /// If such file id doesn't exist, return None. - Optional<unsigned> getCoverageFileID(SourceLocation Loc) { - auto Mapping = FileIDMapping.find(SM.getFileID(Loc)); - if (Mapping != FileIDMapping.end()) - return Mapping->second.first; - return None; - } - - /// Gather all the regions that were skipped by the preprocessor - /// using the constructs like #if. - void gatherSkippedRegions() { - /// An array of the minimum lineStarts and the maximum lineEnds - /// for mapping regions from the appropriate source files. - llvm::SmallVector<std::pair<unsigned, unsigned>, 8> FileLineRanges; - FileLineRanges.resize( - FileIDMapping.size(), - std::make_pair(std::numeric_limits<unsigned>::max(), 0)); - for (const auto &R : MappingRegions) { - FileLineRanges[R.FileID].first = - std::min(FileLineRanges[R.FileID].first, R.LineStart); - FileLineRanges[R.FileID].second = - std::max(FileLineRanges[R.FileID].second, R.LineEnd); - } - - auto SkippedRanges = CVM.getSourceInfo().getSkippedRanges(); - for (const auto &I : SkippedRanges) { - auto LocStart = I.getBegin(); - auto LocEnd = I.getEnd(); - assert(SM.isWrittenInSameFile(LocStart, LocEnd) && - "region spans multiple files"); - - auto CovFileID = getCoverageFileID(LocStart); - if (!CovFileID) - continue; - SpellingRegion SR{SM, LocStart, LocEnd}; - auto Region = CounterMappingRegion::makeSkipped( - *CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd, SR.ColumnEnd); - // Make sure that we only collect the regions that are inside - // the source code of this function. - if (Region.LineStart >= FileLineRanges[*CovFileID].first && - Region.LineEnd <= FileLineRanges[*CovFileID].second) - MappingRegions.push_back(Region); - } - } - - /// Generate the coverage counter mapping regions from collected - /// source regions. - void emitSourceRegions(const SourceRegionFilter &Filter) { - for (const auto &Region : SourceRegions) { - assert(Region.hasEndLoc() && "incomplete region"); - - SourceLocation LocStart = Region.getBeginLoc(); - assert(SM.getFileID(LocStart).isValid() && "region in invalid file"); - - // Ignore regions from system headers. - if (SM.isInSystemHeader(SM.getSpellingLoc(LocStart))) - continue; - - auto CovFileID = getCoverageFileID(LocStart); - // Ignore regions that don't have a file, such as builtin macros. - if (!CovFileID) - continue; - - SourceLocation LocEnd = Region.getEndLoc(); - assert(SM.isWrittenInSameFile(LocStart, LocEnd) && - "region spans multiple files"); - - // Don't add code regions for the area covered by expansion regions. - // This not only suppresses redundant regions, but sometimes prevents - // creating regions with wrong counters if, for example, a statement's - // body ends at the end of a nested macro. - if (Filter.count(std::make_pair(LocStart, LocEnd))) - continue; - - // Find the spelling locations for the mapping region. - SpellingRegion SR{SM, LocStart, LocEnd}; - assert(SR.isInSourceOrder() && "region start and end out of order"); - - if (Region.isGap()) { - MappingRegions.push_back(CounterMappingRegion::makeGapRegion( - Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart, - SR.LineEnd, SR.ColumnEnd)); - } else { - MappingRegions.push_back(CounterMappingRegion::makeRegion( - Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart, - SR.LineEnd, SR.ColumnEnd)); - } - } - } - - /// Generate expansion regions for each virtual file we've seen. - SourceRegionFilter emitExpansionRegions() { - SourceRegionFilter Filter; - for (const auto &FM : FileIDMapping) { - SourceLocation ExpandedLoc = FM.second.second; - SourceLocation ParentLoc = getIncludeOrExpansionLoc(ExpandedLoc); - if (ParentLoc.isInvalid()) - continue; - - auto ParentFileID = getCoverageFileID(ParentLoc); - if (!ParentFileID) - continue; - auto ExpandedFileID = getCoverageFileID(ExpandedLoc); - assert(ExpandedFileID && "expansion in uncovered file"); - - SourceLocation LocEnd = getPreciseTokenLocEnd(ParentLoc); - assert(SM.isWrittenInSameFile(ParentLoc, LocEnd) && - "region spans multiple files"); - Filter.insert(std::make_pair(ParentLoc, LocEnd)); - - SpellingRegion SR{SM, ParentLoc, LocEnd}; - assert(SR.isInSourceOrder() && "region start and end out of order"); - MappingRegions.push_back(CounterMappingRegion::makeExpansion( - *ParentFileID, *ExpandedFileID, SR.LineStart, SR.ColumnStart, - SR.LineEnd, SR.ColumnEnd)); - } - return Filter; - } -}; - -/// Creates unreachable coverage regions for the functions that -/// are not emitted. -struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder { - EmptyCoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM, - const LangOptions &LangOpts) - : CoverageMappingBuilder(CVM, SM, LangOpts) {} - - void VisitDecl(const Decl *D) { - if (!D->hasBody()) - return; - auto Body = D->getBody(); - SourceLocation Start = getStart(Body); - SourceLocation End = getEnd(Body); - if (!SM.isWrittenInSameFile(Start, End)) { - // Walk up to find the common ancestor. - // Correct the locations accordingly. - FileID StartFileID = SM.getFileID(Start); - FileID EndFileID = SM.getFileID(End); - while (StartFileID != EndFileID && !isNestedIn(End, StartFileID)) { - Start = getIncludeOrExpansionLoc(Start); - assert(Start.isValid() && - "Declaration start location not nested within a known region"); - StartFileID = SM.getFileID(Start); - } - while (StartFileID != EndFileID) { - End = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(End)); - assert(End.isValid() && - "Declaration end location not nested within a known region"); - EndFileID = SM.getFileID(End); - } - } - SourceRegions.emplace_back(Counter(), Start, End); - } - - /// Write the mapping data to the output stream - void write(llvm::raw_ostream &OS) { - SmallVector<unsigned, 16> FileIDMapping; - gatherFileIDs(FileIDMapping); - emitSourceRegions(SourceRegionFilter()); - - if (MappingRegions.empty()) - return; - - CoverageMappingWriter Writer(FileIDMapping, None, MappingRegions); - Writer.write(OS); - } -}; - -/// A StmtVisitor that creates coverage mapping regions which map -/// from the source code locations to the PGO counters. -struct CounterCoverageMappingBuilder - : public CoverageMappingBuilder, - public ConstStmtVisitor<CounterCoverageMappingBuilder> { - /// The map of statements to count values. - llvm::DenseMap<const Stmt *, unsigned> &CounterMap; - - /// A stack of currently live regions. - std::vector<SourceMappingRegion> RegionStack; - - /// The currently deferred region: its end location and count can be set once - /// its parent has been popped from the region stack. - Optional<SourceMappingRegion> DeferredRegion; - - CounterExpressionBuilder Builder; - - /// A location in the most recently visited file or macro. - /// - /// This is used to adjust the active source regions appropriately when - /// expressions cross file or macro boundaries. - SourceLocation MostRecentLocation; - - /// Location of the last terminated region. - Optional<std::pair<SourceLocation, size_t>> LastTerminatedRegion; - - /// Return a counter for the subtraction of \c RHS from \c LHS - Counter subtractCounters(Counter LHS, Counter RHS) { - return Builder.subtract(LHS, RHS); - } - - /// Return a counter for the sum of \c LHS and \c RHS. - Counter addCounters(Counter LHS, Counter RHS) { - return Builder.add(LHS, RHS); - } - - Counter addCounters(Counter C1, Counter C2, Counter C3) { - return addCounters(addCounters(C1, C2), C3); - } - - /// Return the region counter for the given statement. - /// - /// This should only be called on statements that have a dedicated counter. - Counter getRegionCounter(const Stmt *S) { - return Counter::getCounter(CounterMap[S]); - } - - /// Push a region onto the stack. - /// - /// Returns the index on the stack where the region was pushed. This can be - /// used with popRegions to exit a "scope", ending the region that was pushed. - size_t pushRegion(Counter Count, Optional<SourceLocation> StartLoc = None, - Optional<SourceLocation> EndLoc = None) { - if (StartLoc) { - MostRecentLocation = *StartLoc; - completeDeferred(Count, MostRecentLocation); - } - RegionStack.emplace_back(Count, StartLoc, EndLoc); - - return RegionStack.size() - 1; - } - - /// Complete any pending deferred region by setting its end location and - /// count, and then pushing it onto the region stack. - size_t completeDeferred(Counter Count, SourceLocation DeferredEndLoc) { - size_t Index = RegionStack.size(); - if (!DeferredRegion) - return Index; - - // Consume the pending region. - SourceMappingRegion DR = DeferredRegion.getValue(); - DeferredRegion = None; - - // If the region ends in an expansion, find the expansion site. - FileID StartFile = SM.getFileID(DR.getBeginLoc()); - if (SM.getFileID(DeferredEndLoc) != StartFile) { - if (isNestedIn(DeferredEndLoc, StartFile)) { - do { - DeferredEndLoc = getIncludeOrExpansionLoc(DeferredEndLoc); - } while (StartFile != SM.getFileID(DeferredEndLoc)); - } else { - return Index; - } - } - - // The parent of this deferred region ends where the containing decl ends, - // so the region isn't useful. - if (DR.getBeginLoc() == DeferredEndLoc) - return Index; - - // If we're visiting statements in non-source order (e.g switch cases or - // a loop condition) we can't construct a sensible deferred region. - if (!SpellingRegion(SM, DR.getBeginLoc(), DeferredEndLoc).isInSourceOrder()) - return Index; - - DR.setGap(true); - DR.setCounter(Count); - DR.setEndLoc(DeferredEndLoc); - handleFileExit(DeferredEndLoc); - RegionStack.push_back(DR); - return Index; - } - - /// Complete a deferred region created after a terminated region at the - /// top-level. - void completeTopLevelDeferredRegion(Counter Count, - SourceLocation DeferredEndLoc) { - if (DeferredRegion || !LastTerminatedRegion) - return; - - if (LastTerminatedRegion->second != RegionStack.size()) - return; - - SourceLocation Start = LastTerminatedRegion->first; - if (SM.getFileID(Start) != SM.getMainFileID()) - return; - - SourceMappingRegion DR = RegionStack.back(); - DR.setStartLoc(Start); - DR.setDeferred(false); - DeferredRegion = DR; - completeDeferred(Count, DeferredEndLoc); - } - - size_t locationDepth(SourceLocation Loc) { - size_t Depth = 0; - while (Loc.isValid()) { - Loc = getIncludeOrExpansionLoc(Loc); - Depth++; - } - return Depth; - } - - /// Pop regions from the stack into the function's list of regions. - /// - /// Adds all regions from \c ParentIndex to the top of the stack to the - /// function's \c SourceRegions. - void popRegions(size_t ParentIndex) { - assert(RegionStack.size() >= ParentIndex && "parent not in stack"); - bool ParentOfDeferredRegion = false; - while (RegionStack.size() > ParentIndex) { - SourceMappingRegion &Region = RegionStack.back(); - if (Region.hasStartLoc()) { - SourceLocation StartLoc = Region.getBeginLoc(); - SourceLocation EndLoc = Region.hasEndLoc() - ? Region.getEndLoc() - : RegionStack[ParentIndex].getEndLoc(); - size_t StartDepth = locationDepth(StartLoc); - size_t EndDepth = locationDepth(EndLoc); - while (!SM.isWrittenInSameFile(StartLoc, EndLoc)) { - bool UnnestStart = StartDepth >= EndDepth; - bool UnnestEnd = EndDepth >= StartDepth; - if (UnnestEnd) { - // The region ends in a nested file or macro expansion. Create a - // separate region for each expansion. - SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc); - assert(SM.isWrittenInSameFile(NestedLoc, EndLoc)); - - if (!isRegionAlreadyAdded(NestedLoc, EndLoc)) - SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc); - - EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc)); - if (EndLoc.isInvalid()) - llvm::report_fatal_error("File exit not handled before popRegions"); - EndDepth--; - } - if (UnnestStart) { - // The region begins in a nested file or macro expansion. Create a - // separate region for each expansion. - SourceLocation NestedLoc = getEndOfFileOrMacro(StartLoc); - assert(SM.isWrittenInSameFile(StartLoc, NestedLoc)); - - if (!isRegionAlreadyAdded(StartLoc, NestedLoc)) - SourceRegions.emplace_back(Region.getCounter(), StartLoc, NestedLoc); - - StartLoc = getIncludeOrExpansionLoc(StartLoc); - if (StartLoc.isInvalid()) - llvm::report_fatal_error("File exit not handled before popRegions"); - StartDepth--; - } - } - Region.setStartLoc(StartLoc); - Region.setEndLoc(EndLoc); - - MostRecentLocation = EndLoc; - // If this region happens to span an entire expansion, we need to make - // sure we don't overlap the parent region with it. - if (StartLoc == getStartOfFileOrMacro(StartLoc) && - EndLoc == getEndOfFileOrMacro(EndLoc)) - MostRecentLocation = getIncludeOrExpansionLoc(EndLoc); - - assert(SM.isWrittenInSameFile(Region.getBeginLoc(), EndLoc)); - assert(SpellingRegion(SM, Region).isInSourceOrder()); - SourceRegions.push_back(Region); - - if (ParentOfDeferredRegion) { - ParentOfDeferredRegion = false; - - // If there's an existing deferred region, keep the old one, because - // it means there are two consecutive returns (or a similar pattern). - if (!DeferredRegion.hasValue() && - // File IDs aren't gathered within macro expansions, so it isn't - // useful to try and create a deferred region inside of one. - !EndLoc.isMacroID()) - DeferredRegion = - SourceMappingRegion(Counter::getZero(), EndLoc, None); - } - } else if (Region.isDeferred()) { - assert(!ParentOfDeferredRegion && "Consecutive deferred regions"); - ParentOfDeferredRegion = true; - } - RegionStack.pop_back(); - - // If the zero region pushed after the last terminated region no longer - // exists, clear its cached information. - if (LastTerminatedRegion && - RegionStack.size() < LastTerminatedRegion->second) - LastTerminatedRegion = None; - } - assert(!ParentOfDeferredRegion && "Deferred region with no parent"); - } - - /// Return the currently active region. - SourceMappingRegion &getRegion() { - assert(!RegionStack.empty() && "statement has no region"); - return RegionStack.back(); - } - - /// Propagate counts through the children of \p S if \p VisitChildren is true. - /// Otherwise, only emit a count for \p S itself. - Counter propagateCounts(Counter TopCount, const Stmt *S, - bool VisitChildren = true) { - SourceLocation StartLoc = getStart(S); - SourceLocation EndLoc = getEnd(S); - size_t Index = pushRegion(TopCount, StartLoc, EndLoc); - if (VisitChildren) - Visit(S); - Counter ExitCount = getRegion().getCounter(); - popRegions(Index); - - // The statement may be spanned by an expansion. Make sure we handle a file - // exit out of this expansion before moving to the next statement. - if (SM.isBeforeInTranslationUnit(StartLoc, S->getBeginLoc())) - MostRecentLocation = EndLoc; - - return ExitCount; - } - - /// Check whether a region with bounds \c StartLoc and \c EndLoc - /// is already added to \c SourceRegions. - bool isRegionAlreadyAdded(SourceLocation StartLoc, SourceLocation EndLoc) { - return SourceRegions.rend() != - std::find_if(SourceRegions.rbegin(), SourceRegions.rend(), - [&](const SourceMappingRegion &Region) { - return Region.getBeginLoc() == StartLoc && - Region.getEndLoc() == EndLoc; - }); - } - - /// Adjust the most recently visited location to \c EndLoc. - /// - /// This should be used after visiting any statements in non-source order. - void adjustForOutOfOrderTraversal(SourceLocation EndLoc) { - MostRecentLocation = EndLoc; - // The code region for a whole macro is created in handleFileExit() when - // it detects exiting of the virtual file of that macro. If we visited - // statements in non-source order, we might already have such a region - // added, for example, if a body of a loop is divided among multiple - // macros. Avoid adding duplicate regions in such case. - if (getRegion().hasEndLoc() && - MostRecentLocation == getEndOfFileOrMacro(MostRecentLocation) && - isRegionAlreadyAdded(getStartOfFileOrMacro(MostRecentLocation), - MostRecentLocation)) - MostRecentLocation = getIncludeOrExpansionLoc(MostRecentLocation); - } - - /// Adjust regions and state when \c NewLoc exits a file. - /// - /// If moving from our most recently tracked location to \c NewLoc exits any - /// files, this adjusts our current region stack and creates the file regions - /// for the exited file. - void handleFileExit(SourceLocation NewLoc) { - if (NewLoc.isInvalid() || - SM.isWrittenInSameFile(MostRecentLocation, NewLoc)) - return; - - // If NewLoc is not in a file that contains MostRecentLocation, walk up to - // find the common ancestor. - SourceLocation LCA = NewLoc; - FileID ParentFile = SM.getFileID(LCA); - while (!isNestedIn(MostRecentLocation, ParentFile)) { - LCA = getIncludeOrExpansionLoc(LCA); - if (LCA.isInvalid() || SM.isWrittenInSameFile(LCA, MostRecentLocation)) { - // Since there isn't a common ancestor, no file was exited. We just need - // to adjust our location to the new file. - MostRecentLocation = NewLoc; - return; - } - ParentFile = SM.getFileID(LCA); - } - - llvm::SmallSet<SourceLocation, 8> StartLocs; - Optional<Counter> ParentCounter; - for (SourceMappingRegion &I : llvm::reverse(RegionStack)) { - if (!I.hasStartLoc()) - continue; - SourceLocation Loc = I.getBeginLoc(); - if (!isNestedIn(Loc, ParentFile)) { - ParentCounter = I.getCounter(); - break; - } - - while (!SM.isInFileID(Loc, ParentFile)) { - // The most nested region for each start location is the one with the - // correct count. We avoid creating redundant regions by stopping once - // we've seen this region. - if (StartLocs.insert(Loc).second) - SourceRegions.emplace_back(I.getCounter(), Loc, - getEndOfFileOrMacro(Loc)); - Loc = getIncludeOrExpansionLoc(Loc); - } - I.setStartLoc(getPreciseTokenLocEnd(Loc)); - } - - if (ParentCounter) { - // If the file is contained completely by another region and doesn't - // immediately start its own region, the whole file gets a region - // corresponding to the parent. - SourceLocation Loc = MostRecentLocation; - while (isNestedIn(Loc, ParentFile)) { - SourceLocation FileStart = getStartOfFileOrMacro(Loc); - if (StartLocs.insert(FileStart).second) { - SourceRegions.emplace_back(*ParentCounter, FileStart, - getEndOfFileOrMacro(Loc)); - assert(SpellingRegion(SM, SourceRegions.back()).isInSourceOrder()); - } - Loc = getIncludeOrExpansionLoc(Loc); - } - } - - MostRecentLocation = NewLoc; - } - - /// Ensure that \c S is included in the current region. - void extendRegion(const Stmt *S) { - SourceMappingRegion &Region = getRegion(); - SourceLocation StartLoc = getStart(S); - - handleFileExit(StartLoc); - if (!Region.hasStartLoc()) - Region.setStartLoc(StartLoc); - - completeDeferred(Region.getCounter(), StartLoc); - } - - /// Mark \c S as a terminator, starting a zero region. - void terminateRegion(const Stmt *S) { - extendRegion(S); - SourceMappingRegion &Region = getRegion(); - SourceLocation EndLoc = getEnd(S); - if (!Region.hasEndLoc()) - Region.setEndLoc(EndLoc); - pushRegion(Counter::getZero()); - auto &ZeroRegion = getRegion(); - ZeroRegion.setDeferred(true); - LastTerminatedRegion = {EndLoc, RegionStack.size()}; - } - - /// Find a valid gap range between \p AfterLoc and \p BeforeLoc. - Optional<SourceRange> findGapAreaBetween(SourceLocation AfterLoc, - SourceLocation BeforeLoc) { - // If the start and end locations of the gap are both within the same macro - // file, the range may not be in source order. - if (AfterLoc.isMacroID() || BeforeLoc.isMacroID()) - return None; - if (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc)) - return None; - return {{AfterLoc, BeforeLoc}}; - } - - /// Find the source range after \p AfterStmt and before \p BeforeStmt. - Optional<SourceRange> findGapAreaBetween(const Stmt *AfterStmt, - const Stmt *BeforeStmt) { - return findGapAreaBetween(getPreciseTokenLocEnd(getEnd(AfterStmt)), - getStart(BeforeStmt)); - } - - /// Emit a gap region between \p StartLoc and \p EndLoc with the given count. - void fillGapAreaWithCount(SourceLocation StartLoc, SourceLocation EndLoc, - Counter Count) { - if (StartLoc == EndLoc) - return; - assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder()); - handleFileExit(StartLoc); - size_t Index = pushRegion(Count, StartLoc, EndLoc); - getRegion().setGap(true); - handleFileExit(EndLoc); - popRegions(Index); - } - - /// Keep counts of breaks and continues inside loops. - struct BreakContinue { - Counter BreakCount; - Counter ContinueCount; - }; - SmallVector<BreakContinue, 8> BreakContinueStack; - - CounterCoverageMappingBuilder( - CoverageMappingModuleGen &CVM, - llvm::DenseMap<const Stmt *, unsigned> &CounterMap, SourceManager &SM, - const LangOptions &LangOpts) - : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap), - DeferredRegion(None) {} - - /// Write the mapping data to the output stream - void write(llvm::raw_ostream &OS) { - llvm::SmallVector<unsigned, 8> VirtualFileMapping; - gatherFileIDs(VirtualFileMapping); - SourceRegionFilter Filter = emitExpansionRegions(); - assert(!DeferredRegion && "Deferred region never completed"); - emitSourceRegions(Filter); - gatherSkippedRegions(); - - if (MappingRegions.empty()) - return; - - CoverageMappingWriter Writer(VirtualFileMapping, Builder.getExpressions(), - MappingRegions); - Writer.write(OS); - } - - void VisitStmt(const Stmt *S) { - if (S->getBeginLoc().isValid()) - extendRegion(S); - for (const Stmt *Child : S->children()) - if (Child) - this->Visit(Child); - handleFileExit(getEnd(S)); - } - - void VisitDecl(const Decl *D) { - assert(!DeferredRegion && "Deferred region never completed"); - - Stmt *Body = D->getBody(); - - // Do not propagate region counts into system headers. - if (Body && SM.isInSystemHeader(SM.getSpellingLoc(getStart(Body)))) - return; - - // Do not visit the artificial children nodes of defaulted methods. The - // lexer may not be able to report back precise token end locations for - // these children nodes (llvm.org/PR39822), and moreover users will not be - // able to see coverage for them. - bool Defaulted = false; - if (auto *Method = dyn_cast<CXXMethodDecl>(D)) - Defaulted = Method->isDefaulted(); - - propagateCounts(getRegionCounter(Body), Body, - /*VisitChildren=*/!Defaulted); - assert(RegionStack.empty() && "Regions entered but never exited"); - - // Discard the last uncompleted deferred region in a decl, if one exists. - // This prevents lines at the end of a function containing only whitespace - // or closing braces from being marked as uncovered. - DeferredRegion = None; - } - - void VisitReturnStmt(const ReturnStmt *S) { - extendRegion(S); - if (S->getRetValue()) - Visit(S->getRetValue()); - terminateRegion(S); - } - - void VisitCXXThrowExpr(const CXXThrowExpr *E) { - extendRegion(E); - if (E->getSubExpr()) - Visit(E->getSubExpr()); - terminateRegion(E); - } - - void VisitGotoStmt(const GotoStmt *S) { terminateRegion(S); } - - void VisitLabelStmt(const LabelStmt *S) { - Counter LabelCount = getRegionCounter(S); - SourceLocation Start = getStart(S); - completeTopLevelDeferredRegion(LabelCount, Start); - completeDeferred(LabelCount, Start); - // We can't extendRegion here or we risk overlapping with our new region. - handleFileExit(Start); - pushRegion(LabelCount, Start); - Visit(S->getSubStmt()); - } - - void VisitBreakStmt(const BreakStmt *S) { - assert(!BreakContinueStack.empty() && "break not in a loop or switch!"); - BreakContinueStack.back().BreakCount = addCounters( - BreakContinueStack.back().BreakCount, getRegion().getCounter()); - // FIXME: a break in a switch should terminate regions for all preceding - // case statements, not just the most recent one. - terminateRegion(S); - } - - void VisitContinueStmt(const ContinueStmt *S) { - assert(!BreakContinueStack.empty() && "continue stmt not in a loop!"); - BreakContinueStack.back().ContinueCount = addCounters( - BreakContinueStack.back().ContinueCount, getRegion().getCounter()); - terminateRegion(S); - } - - void VisitCallExpr(const CallExpr *E) { - VisitStmt(E); - - // Terminate the region when we hit a noreturn function. - // (This is helpful dealing with switch statements.) - QualType CalleeType = E->getCallee()->getType(); - if (getFunctionExtInfo(*CalleeType).getNoReturn()) - terminateRegion(E); - } - - void VisitWhileStmt(const WhileStmt *S) { - extendRegion(S); - - Counter ParentCount = getRegion().getCounter(); - Counter BodyCount = getRegionCounter(S); - - // Handle the body first so that we can get the backedge count. - BreakContinueStack.push_back(BreakContinue()); - extendRegion(S->getBody()); - Counter BackedgeCount = propagateCounts(BodyCount, S->getBody()); - BreakContinue BC = BreakContinueStack.pop_back_val(); - - // Go back to handle the condition. - Counter CondCount = - addCounters(ParentCount, BackedgeCount, BC.ContinueCount); - propagateCounts(CondCount, S->getCond()); - adjustForOutOfOrderTraversal(getEnd(S)); - - // The body count applies to the area immediately after the increment. - auto Gap = findGapAreaBetween(S->getCond(), S->getBody()); - if (Gap) - fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount); - - Counter OutCount = - addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount)); - if (OutCount != ParentCount) - pushRegion(OutCount); - } - - void VisitDoStmt(const DoStmt *S) { - extendRegion(S); - - Counter ParentCount = getRegion().getCounter(); - Counter BodyCount = getRegionCounter(S); - - BreakContinueStack.push_back(BreakContinue()); - extendRegion(S->getBody()); - Counter BackedgeCount = - propagateCounts(addCounters(ParentCount, BodyCount), S->getBody()); - BreakContinue BC = BreakContinueStack.pop_back_val(); - - Counter CondCount = addCounters(BackedgeCount, BC.ContinueCount); - propagateCounts(CondCount, S->getCond()); - - Counter OutCount = - addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount)); - if (OutCount != ParentCount) - pushRegion(OutCount); - } - - void VisitForStmt(const ForStmt *S) { - extendRegion(S); - if (S->getInit()) - Visit(S->getInit()); - - Counter ParentCount = getRegion().getCounter(); - Counter BodyCount = getRegionCounter(S); - - // The loop increment may contain a break or continue. - if (S->getInc()) - BreakContinueStack.emplace_back(); - - // Handle the body first so that we can get the backedge count. - BreakContinueStack.emplace_back(); - extendRegion(S->getBody()); - Counter BackedgeCount = propagateCounts(BodyCount, S->getBody()); - BreakContinue BodyBC = BreakContinueStack.pop_back_val(); - - // The increment is essentially part of the body but it needs to include - // the count for all the continue statements. - BreakContinue IncrementBC; - if (const Stmt *Inc = S->getInc()) { - propagateCounts(addCounters(BackedgeCount, BodyBC.ContinueCount), Inc); - IncrementBC = BreakContinueStack.pop_back_val(); - } - - // Go back to handle the condition. - Counter CondCount = addCounters( - addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount), - IncrementBC.ContinueCount); - if (const Expr *Cond = S->getCond()) { - propagateCounts(CondCount, Cond); - adjustForOutOfOrderTraversal(getEnd(S)); - } - - // The body count applies to the area immediately after the increment. - auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->getRParenLoc()), - getStart(S->getBody())); - if (Gap) - fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount); - - Counter OutCount = addCounters(BodyBC.BreakCount, IncrementBC.BreakCount, - subtractCounters(CondCount, BodyCount)); - if (OutCount != ParentCount) - pushRegion(OutCount); - } - - void VisitCXXForRangeStmt(const CXXForRangeStmt *S) { - extendRegion(S); - if (S->getInit()) - Visit(S->getInit()); - Visit(S->getLoopVarStmt()); - Visit(S->getRangeStmt()); - - Counter ParentCount = getRegion().getCounter(); - Counter BodyCount = getRegionCounter(S); - - BreakContinueStack.push_back(BreakContinue()); - extendRegion(S->getBody()); - Counter BackedgeCount = propagateCounts(BodyCount, S->getBody()); - BreakContinue BC = BreakContinueStack.pop_back_val(); - - // The body count applies to the area immediately after the range. - auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->getRParenLoc()), - getStart(S->getBody())); - if (Gap) - fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount); - - Counter LoopCount = - addCounters(ParentCount, BackedgeCount, BC.ContinueCount); - Counter OutCount = - addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount)); - if (OutCount != ParentCount) - pushRegion(OutCount); - } - - void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) { - extendRegion(S); - Visit(S->getElement()); - - Counter ParentCount = getRegion().getCounter(); - Counter BodyCount = getRegionCounter(S); - - BreakContinueStack.push_back(BreakContinue()); - extendRegion(S->getBody()); - Counter BackedgeCount = propagateCounts(BodyCount, S->getBody()); - BreakContinue BC = BreakContinueStack.pop_back_val(); - - // The body count applies to the area immediately after the collection. - auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->getRParenLoc()), - getStart(S->getBody())); - if (Gap) - fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount); - - Counter LoopCount = - addCounters(ParentCount, BackedgeCount, BC.ContinueCount); - Counter OutCount = - addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount)); - if (OutCount != ParentCount) - pushRegion(OutCount); - } - - void VisitSwitchStmt(const SwitchStmt *S) { - extendRegion(S); - if (S->getInit()) - Visit(S->getInit()); - Visit(S->getCond()); - - BreakContinueStack.push_back(BreakContinue()); - - const Stmt *Body = S->getBody(); - extendRegion(Body); - if (const auto *CS = dyn_cast<CompoundStmt>(Body)) { - if (!CS->body_empty()) { - // Make a region for the body of the switch. If the body starts with - // a case, that case will reuse this region; otherwise, this covers - // the unreachable code at the beginning of the switch body. - size_t Index = - pushRegion(Counter::getZero(), getStart(CS->body_front())); - for (const auto *Child : CS->children()) - Visit(Child); - - // Set the end for the body of the switch, if it isn't already set. - for (size_t i = RegionStack.size(); i != Index; --i) { - if (!RegionStack[i - 1].hasEndLoc()) - RegionStack[i - 1].setEndLoc(getEnd(CS->body_back())); - } - - popRegions(Index); - } - } else - propagateCounts(Counter::getZero(), Body); - BreakContinue BC = BreakContinueStack.pop_back_val(); - - if (!BreakContinueStack.empty()) - BreakContinueStack.back().ContinueCount = addCounters( - BreakContinueStack.back().ContinueCount, BC.ContinueCount); - - Counter ExitCount = getRegionCounter(S); - SourceLocation ExitLoc = getEnd(S); - pushRegion(ExitCount); - - // Ensure that handleFileExit recognizes when the end location is located - // in a different file. - MostRecentLocation = getStart(S); - handleFileExit(ExitLoc); - } - - void VisitSwitchCase(const SwitchCase *S) { - extendRegion(S); - - SourceMappingRegion &Parent = getRegion(); - - Counter Count = addCounters(Parent.getCounter(), getRegionCounter(S)); - // Reuse the existing region if it starts at our label. This is typical of - // the first case in a switch. - if (Parent.hasStartLoc() && Parent.getBeginLoc() == getStart(S)) - Parent.setCounter(Count); - else - pushRegion(Count, getStart(S)); - - if (const auto *CS = dyn_cast<CaseStmt>(S)) { - Visit(CS->getLHS()); - if (const Expr *RHS = CS->getRHS()) - Visit(RHS); - } - Visit(S->getSubStmt()); - } - - void VisitIfStmt(const IfStmt *S) { - extendRegion(S); - if (S->getInit()) - Visit(S->getInit()); - - // Extend into the condition before we propagate through it below - this is - // needed to handle macros that generate the "if" but not the condition. - extendRegion(S->getCond()); - - Counter ParentCount = getRegion().getCounter(); - Counter ThenCount = getRegionCounter(S); - - // Emitting a counter for the condition makes it easier to interpret the - // counter for the body when looking at the coverage. - propagateCounts(ParentCount, S->getCond()); - - // The 'then' count applies to the area immediately after the condition. - auto Gap = findGapAreaBetween(S->getCond(), S->getThen()); - if (Gap) - fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount); - - extendRegion(S->getThen()); - Counter OutCount = propagateCounts(ThenCount, S->getThen()); - - Counter ElseCount = subtractCounters(ParentCount, ThenCount); - if (const Stmt *Else = S->getElse()) { - // The 'else' count applies to the area immediately after the 'then'. - Gap = findGapAreaBetween(S->getThen(), Else); - if (Gap) - fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount); - extendRegion(Else); - OutCount = addCounters(OutCount, propagateCounts(ElseCount, Else)); - } else - OutCount = addCounters(OutCount, ElseCount); - - if (OutCount != ParentCount) - pushRegion(OutCount); - } - - void VisitCXXTryStmt(const CXXTryStmt *S) { - extendRegion(S); - // Handle macros that generate the "try" but not the rest. - extendRegion(S->getTryBlock()); - - Counter ParentCount = getRegion().getCounter(); - propagateCounts(ParentCount, S->getTryBlock()); - - for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I) - Visit(S->getHandler(I)); - - Counter ExitCount = getRegionCounter(S); - pushRegion(ExitCount); - } - - void VisitCXXCatchStmt(const CXXCatchStmt *S) { - propagateCounts(getRegionCounter(S), S->getHandlerBlock()); - } - - void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { - extendRegion(E); - - Counter ParentCount = getRegion().getCounter(); - Counter TrueCount = getRegionCounter(E); - - Visit(E->getCond()); - - if (!isa<BinaryConditionalOperator>(E)) { - // The 'then' count applies to the area immediately after the condition. - auto Gap = - findGapAreaBetween(E->getQuestionLoc(), getStart(E->getTrueExpr())); - if (Gap) - fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), TrueCount); - - extendRegion(E->getTrueExpr()); - propagateCounts(TrueCount, E->getTrueExpr()); - } - - extendRegion(E->getFalseExpr()); - propagateCounts(subtractCounters(ParentCount, TrueCount), - E->getFalseExpr()); - } - - void VisitBinLAnd(const BinaryOperator *E) { - extendRegion(E->getLHS()); - propagateCounts(getRegion().getCounter(), E->getLHS()); - handleFileExit(getEnd(E->getLHS())); - - extendRegion(E->getRHS()); - propagateCounts(getRegionCounter(E), E->getRHS()); - } - - void VisitBinLOr(const BinaryOperator *E) { - extendRegion(E->getLHS()); - propagateCounts(getRegion().getCounter(), E->getLHS()); - handleFileExit(getEnd(E->getLHS())); - - extendRegion(E->getRHS()); - propagateCounts(getRegionCounter(E), E->getRHS()); - } - - void VisitLambdaExpr(const LambdaExpr *LE) { - // Lambdas are treated as their own functions for now, so we shouldn't - // propagate counts into them. - } -}; - -std::string getCoverageSection(const CodeGenModule &CGM) { - return llvm::getInstrProfSectionName( - llvm::IPSK_covmap, - CGM.getContext().getTargetInfo().getTriple().getObjectFormat()); -} - -std::string normalizeFilename(StringRef Filename) { - llvm::SmallString<256> Path(Filename); - llvm::sys::fs::make_absolute(Path); - llvm::sys::path::remove_dots(Path, /*remove_dot_dots=*/true); - return Path.str().str(); -} - -} // end anonymous namespace - -static void dump(llvm::raw_ostream &OS, StringRef FunctionName, - ArrayRef<CounterExpression> Expressions, - ArrayRef<CounterMappingRegion> Regions) { - OS << FunctionName << ":\n"; - CounterMappingContext Ctx(Expressions); - for (const auto &R : Regions) { - OS.indent(2); - switch (R.Kind) { - case CounterMappingRegion::CodeRegion: - break; - case CounterMappingRegion::ExpansionRegion: - OS << "Expansion,"; - break; - case CounterMappingRegion::SkippedRegion: - OS << "Skipped,"; - break; - case CounterMappingRegion::GapRegion: - OS << "Gap,"; - break; - } - - OS << "File " << R.FileID << ", " << R.LineStart << ":" << R.ColumnStart - << " -> " << R.LineEnd << ":" << R.ColumnEnd << " = "; - Ctx.dump(R.Count, OS); - if (R.Kind == CounterMappingRegion::ExpansionRegion) - OS << " (Expanded file = " << R.ExpandedFileID << ")"; - OS << "\n"; - } -} - -void CoverageMappingModuleGen::addFunctionMappingRecord( - llvm::GlobalVariable *NamePtr, StringRef NameValue, uint64_t FuncHash, - const std::string &CoverageMapping, bool IsUsed) { - llvm::LLVMContext &Ctx = CGM.getLLVMContext(); - if (!FunctionRecordTy) { -#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType, - llvm::Type *FunctionRecordTypes[] = { - #include "llvm/ProfileData/InstrProfData.inc" - }; - FunctionRecordTy = - llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes), - /*isPacked=*/true); - } - - #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Init, - llvm::Constant *FunctionRecordVals[] = { - #include "llvm/ProfileData/InstrProfData.inc" - }; - FunctionRecords.push_back(llvm::ConstantStruct::get( - FunctionRecordTy, makeArrayRef(FunctionRecordVals))); - if (!IsUsed) - FunctionNames.push_back( - llvm::ConstantExpr::getBitCast(NamePtr, llvm::Type::getInt8PtrTy(Ctx))); - CoverageMappings.push_back(CoverageMapping); - - if (CGM.getCodeGenOpts().DumpCoverageMapping) { - // Dump the coverage mapping data for this function by decoding the - // encoded data. This allows us to dump the mapping regions which were - // also processed by the CoverageMappingWriter which performs - // additional minimization operations such as reducing the number of - // expressions. - std::vector<StringRef> Filenames; - std::vector<CounterExpression> Expressions; - std::vector<CounterMappingRegion> Regions; - llvm::SmallVector<std::string, 16> FilenameStrs; - llvm::SmallVector<StringRef, 16> FilenameRefs; - FilenameStrs.resize(FileEntries.size()); - FilenameRefs.resize(FileEntries.size()); - for (const auto &Entry : FileEntries) { - auto I = Entry.second; - FilenameStrs[I] = normalizeFilename(Entry.first->getName()); - FilenameRefs[I] = FilenameStrs[I]; - } - RawCoverageMappingReader Reader(CoverageMapping, FilenameRefs, Filenames, - Expressions, Regions); - if (Reader.read()) - return; - dump(llvm::outs(), NameValue, Expressions, Regions); - } -} - -void CoverageMappingModuleGen::emit() { - if (FunctionRecords.empty()) - return; - llvm::LLVMContext &Ctx = CGM.getLLVMContext(); - auto *Int32Ty = llvm::Type::getInt32Ty(Ctx); - - // Create the filenames and merge them with coverage mappings - llvm::SmallVector<std::string, 16> FilenameStrs; - llvm::SmallVector<StringRef, 16> FilenameRefs; - FilenameStrs.resize(FileEntries.size()); - FilenameRefs.resize(FileEntries.size()); - for (const auto &Entry : FileEntries) { - auto I = Entry.second; - FilenameStrs[I] = normalizeFilename(Entry.first->getName()); - FilenameRefs[I] = FilenameStrs[I]; - } - - std::string FilenamesAndCoverageMappings; - llvm::raw_string_ostream OS(FilenamesAndCoverageMappings); - CoverageFilenamesSectionWriter(FilenameRefs).write(OS); - std::string RawCoverageMappings = - llvm::join(CoverageMappings.begin(), CoverageMappings.end(), ""); - OS << RawCoverageMappings; - size_t CoverageMappingSize = RawCoverageMappings.size(); - size_t FilenamesSize = OS.str().size() - CoverageMappingSize; - // Append extra zeroes if necessary to ensure that the size of the filenames - // and coverage mappings is a multiple of 8. - if (size_t Rem = OS.str().size() % 8) { - CoverageMappingSize += 8 - Rem; - OS.write_zeros(8 - Rem); - } - auto *FilenamesAndMappingsVal = - llvm::ConstantDataArray::getString(Ctx, OS.str(), false); - - // Create the deferred function records array - auto RecordsTy = - llvm::ArrayType::get(FunctionRecordTy, FunctionRecords.size()); - auto RecordsVal = llvm::ConstantArray::get(RecordsTy, FunctionRecords); - - llvm::Type *CovDataHeaderTypes[] = { -#define COVMAP_HEADER(Type, LLVMType, Name, Init) LLVMType, -#include "llvm/ProfileData/InstrProfData.inc" - }; - auto CovDataHeaderTy = - llvm::StructType::get(Ctx, makeArrayRef(CovDataHeaderTypes)); - llvm::Constant *CovDataHeaderVals[] = { -#define COVMAP_HEADER(Type, LLVMType, Name, Init) Init, -#include "llvm/ProfileData/InstrProfData.inc" - }; - auto CovDataHeaderVal = llvm::ConstantStruct::get( - CovDataHeaderTy, makeArrayRef(CovDataHeaderVals)); - - // Create the coverage data record - llvm::Type *CovDataTypes[] = {CovDataHeaderTy, RecordsTy, - FilenamesAndMappingsVal->getType()}; - auto CovDataTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataTypes)); - llvm::Constant *TUDataVals[] = {CovDataHeaderVal, RecordsVal, - FilenamesAndMappingsVal}; - auto CovDataVal = - llvm::ConstantStruct::get(CovDataTy, makeArrayRef(TUDataVals)); - auto CovData = new llvm::GlobalVariable( - CGM.getModule(), CovDataTy, true, llvm::GlobalValue::InternalLinkage, - CovDataVal, llvm::getCoverageMappingVarName()); - - CovData->setSection(getCoverageSection(CGM)); - CovData->setAlignment(8); - - // Make sure the data doesn't get deleted. - CGM.addUsedGlobal(CovData); - // Create the deferred function records array - if (!FunctionNames.empty()) { - auto NamesArrTy = llvm::ArrayType::get(llvm::Type::getInt8PtrTy(Ctx), - FunctionNames.size()); - auto NamesArrVal = llvm::ConstantArray::get(NamesArrTy, FunctionNames); - // This variable will *NOT* be emitted to the object file. It is used - // to pass the list of names referenced to codegen. - new llvm::GlobalVariable(CGM.getModule(), NamesArrTy, true, - llvm::GlobalValue::InternalLinkage, NamesArrVal, - llvm::getCoverageUnusedNamesVarName()); - } -} - -unsigned CoverageMappingModuleGen::getFileID(const FileEntry *File) { - auto It = FileEntries.find(File); - if (It != FileEntries.end()) - return It->second; - unsigned FileID = FileEntries.size(); - FileEntries.insert(std::make_pair(File, FileID)); - return FileID; -} - -void CoverageMappingGen::emitCounterMapping(const Decl *D, - llvm::raw_ostream &OS) { - assert(CounterMap); - CounterCoverageMappingBuilder Walker(CVM, *CounterMap, SM, LangOpts); - Walker.VisitDecl(D); - Walker.write(OS); -} - -void CoverageMappingGen::emitEmptyMapping(const Decl *D, - llvm::raw_ostream &OS) { - EmptyCoverageMappingBuilder Walker(CVM, SM, LangOpts); - Walker.VisitDecl(D); - Walker.write(OS); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.h b/gnu/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.h deleted file mode 100644 index c62db096952..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.h +++ /dev/null @@ -1,114 +0,0 @@ -//===---- CoverageMappingGen.h - Coverage mapping generation ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Instrumentation-based code coverage mapping generator -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_COVERAGEMAPPINGGEN_H -#define LLVM_CLANG_LIB_CODEGEN_COVERAGEMAPPINGGEN_H - -#include "clang/Basic/LLVM.h" -#include "clang/Basic/SourceLocation.h" -#include "clang/Lex/PPCallbacks.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/Support/raw_ostream.h" - -namespace clang { - -class LangOptions; -class SourceManager; -class FileEntry; -class Preprocessor; -class Decl; -class Stmt; - -/// Stores additional source code information like skipped ranges which -/// is required by the coverage mapping generator and is obtained from -/// the preprocessor. -class CoverageSourceInfo : public PPCallbacks { - std::vector<SourceRange> SkippedRanges; -public: - ArrayRef<SourceRange> getSkippedRanges() const { return SkippedRanges; } - - void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override; -}; - -namespace CodeGen { - -class CodeGenModule; - -/// Organizes the cross-function state that is used while generating -/// code coverage mapping data. -class CoverageMappingModuleGen { - CodeGenModule &CGM; - CoverageSourceInfo &SourceInfo; - llvm::SmallDenseMap<const FileEntry *, unsigned, 8> FileEntries; - std::vector<llvm::Constant *> FunctionRecords; - std::vector<llvm::Constant *> FunctionNames; - llvm::StructType *FunctionRecordTy; - std::vector<std::string> CoverageMappings; - -public: - CoverageMappingModuleGen(CodeGenModule &CGM, CoverageSourceInfo &SourceInfo) - : CGM(CGM), SourceInfo(SourceInfo), FunctionRecordTy(nullptr) {} - - CoverageSourceInfo &getSourceInfo() const { - return SourceInfo; - } - - /// Add a function's coverage mapping record to the collection of the - /// function mapping records. - void addFunctionMappingRecord(llvm::GlobalVariable *FunctionName, - StringRef FunctionNameValue, - uint64_t FunctionHash, - const std::string &CoverageMapping, - bool IsUsed = true); - - /// Emit the coverage mapping data for a translation unit. - void emit(); - - /// Return the coverage mapping translation unit file id - /// for the given file. - unsigned getFileID(const FileEntry *File); -}; - -/// Organizes the per-function state that is used while generating -/// code coverage mapping data. -class CoverageMappingGen { - CoverageMappingModuleGen &CVM; - SourceManager &SM; - const LangOptions &LangOpts; - llvm::DenseMap<const Stmt *, unsigned> *CounterMap; - -public: - CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM, - const LangOptions &LangOpts) - : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(nullptr) {} - - CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM, - const LangOptions &LangOpts, - llvm::DenseMap<const Stmt *, unsigned> *CounterMap) - : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(CounterMap) {} - - /// Emit the coverage mapping data which maps the regions of - /// code to counters that will be used to find the execution - /// counts for those regions. - void emitCounterMapping(const Decl *D, llvm::raw_ostream &OS); - - /// Emit the coverage mapping data for an unused function. - /// It creates mapping regions with the counter of zero. - void emitEmptyMapping(const Decl *D, llvm::raw_ostream &OS); -}; - -} // end namespace CodeGen -} // end namespace clang - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/EHScopeStack.h b/gnu/llvm/tools/clang/lib/CodeGen/EHScopeStack.h deleted file mode 100644 index c7bdeac58a1..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/EHScopeStack.h +++ /dev/null @@ -1,421 +0,0 @@ -//===-- EHScopeStack.h - Stack for cleanup IR generation --------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// These classes should be the minimum interface required for other parts of -// CodeGen to emit cleanups. The implementation is in CGCleanup.cpp and other -// implemenentation details that are not widely needed are in CGCleanup.h. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_EHSCOPESTACK_H -#define LLVM_CLANG_LIB_CODEGEN_EHSCOPESTACK_H - -#include "clang/Basic/LLVM.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Value.h" - -namespace clang { -namespace CodeGen { - -class CodeGenFunction; - -/// A branch fixup. These are required when emitting a goto to a -/// label which hasn't been emitted yet. The goto is optimistically -/// emitted as a branch to the basic block for the label, and (if it -/// occurs in a scope with non-trivial cleanups) a fixup is added to -/// the innermost cleanup. When a (normal) cleanup is popped, any -/// unresolved fixups in that scope are threaded through the cleanup. -struct BranchFixup { - /// The block containing the terminator which needs to be modified - /// into a switch if this fixup is resolved into the current scope. - /// If null, LatestBranch points directly to the destination. - llvm::BasicBlock *OptimisticBranchBlock; - - /// The ultimate destination of the branch. - /// - /// This can be set to null to indicate that this fixup was - /// successfully resolved. - llvm::BasicBlock *Destination; - - /// The destination index value. - unsigned DestinationIndex; - - /// The initial branch of the fixup. - llvm::BranchInst *InitialBranch; -}; - -template <class T> struct InvariantValue { - typedef T type; - typedef T saved_type; - static bool needsSaving(type value) { return false; } - static saved_type save(CodeGenFunction &CGF, type value) { return value; } - static type restore(CodeGenFunction &CGF, saved_type value) { return value; } -}; - -/// A metaprogramming class for ensuring that a value will dominate an -/// arbitrary position in a function. -template <class T> struct DominatingValue : InvariantValue<T> {}; - -template <class T, bool mightBeInstruction = - std::is_base_of<llvm::Value, T>::value && - !std::is_base_of<llvm::Constant, T>::value && - !std::is_base_of<llvm::BasicBlock, T>::value> -struct DominatingPointer; -template <class T> struct DominatingPointer<T,false> : InvariantValue<T*> {}; -// template <class T> struct DominatingPointer<T,true> at end of file - -template <class T> struct DominatingValue<T*> : DominatingPointer<T> {}; - -enum CleanupKind : unsigned { - /// Denotes a cleanup that should run when a scope is exited using exceptional - /// control flow (a throw statement leading to stack unwinding, ). - EHCleanup = 0x1, - - /// Denotes a cleanup that should run when a scope is exited using normal - /// control flow (falling off the end of the scope, return, goto, ...). - NormalCleanup = 0x2, - - NormalAndEHCleanup = EHCleanup | NormalCleanup, - - InactiveCleanup = 0x4, - InactiveEHCleanup = EHCleanup | InactiveCleanup, - InactiveNormalCleanup = NormalCleanup | InactiveCleanup, - InactiveNormalAndEHCleanup = NormalAndEHCleanup | InactiveCleanup, - - LifetimeMarker = 0x8, - NormalEHLifetimeMarker = LifetimeMarker | NormalAndEHCleanup, -}; - -/// A stack of scopes which respond to exceptions, including cleanups -/// and catch blocks. -class EHScopeStack { -public: - /* Should switch to alignof(uint64_t) instead of 8, when EHCleanupScope can */ - enum { ScopeStackAlignment = 8 }; - - /// A saved depth on the scope stack. This is necessary because - /// pushing scopes onto the stack invalidates iterators. - class stable_iterator { - friend class EHScopeStack; - - /// Offset from StartOfData to EndOfBuffer. - ptrdiff_t Size; - - stable_iterator(ptrdiff_t Size) : Size(Size) {} - - public: - static stable_iterator invalid() { return stable_iterator(-1); } - stable_iterator() : Size(-1) {} - - bool isValid() const { return Size >= 0; } - - /// Returns true if this scope encloses I. - /// Returns false if I is invalid. - /// This scope must be valid. - bool encloses(stable_iterator I) const { return Size <= I.Size; } - - /// Returns true if this scope strictly encloses I: that is, - /// if it encloses I and is not I. - /// Returns false is I is invalid. - /// This scope must be valid. - bool strictlyEncloses(stable_iterator I) const { return Size < I.Size; } - - friend bool operator==(stable_iterator A, stable_iterator B) { - return A.Size == B.Size; - } - friend bool operator!=(stable_iterator A, stable_iterator B) { - return A.Size != B.Size; - } - }; - - /// Information for lazily generating a cleanup. Subclasses must be - /// POD-like: cleanups will not be destructed, and they will be - /// allocated on the cleanup stack and freely copied and moved - /// around. - /// - /// Cleanup implementations should generally be declared in an - /// anonymous namespace. - class Cleanup { - // Anchor the construction vtable. - virtual void anchor(); - - protected: - ~Cleanup() = default; - - public: - Cleanup(const Cleanup &) = default; - Cleanup(Cleanup &&) {} - Cleanup() = default; - - /// Generation flags. - class Flags { - enum { - F_IsForEH = 0x1, - F_IsNormalCleanupKind = 0x2, - F_IsEHCleanupKind = 0x4 - }; - unsigned flags; - - public: - Flags() : flags(0) {} - - /// isForEH - true if the current emission is for an EH cleanup. - bool isForEHCleanup() const { return flags & F_IsForEH; } - bool isForNormalCleanup() const { return !isForEHCleanup(); } - void setIsForEHCleanup() { flags |= F_IsForEH; } - - bool isNormalCleanupKind() const { return flags & F_IsNormalCleanupKind; } - void setIsNormalCleanupKind() { flags |= F_IsNormalCleanupKind; } - - /// isEHCleanupKind - true if the cleanup was pushed as an EH - /// cleanup. - bool isEHCleanupKind() const { return flags & F_IsEHCleanupKind; } - void setIsEHCleanupKind() { flags |= F_IsEHCleanupKind; } - }; - - - /// Emit the cleanup. For normal cleanups, this is run in the - /// same EH context as when the cleanup was pushed, i.e. the - /// immediately-enclosing context of the cleanup scope. For - /// EH cleanups, this is run in a terminate context. - /// - // \param flags cleanup kind. - virtual void Emit(CodeGenFunction &CGF, Flags flags) = 0; - }; - - /// ConditionalCleanup stores the saved form of its parameters, - /// then restores them and performs the cleanup. - template <class T, class... As> - class ConditionalCleanup final : public Cleanup { - typedef std::tuple<typename DominatingValue<As>::saved_type...> SavedTuple; - SavedTuple Saved; - - template <std::size_t... Is> - T restore(CodeGenFunction &CGF, llvm::index_sequence<Is...>) { - // It's important that the restores are emitted in order. The braced init - // list guarantees that. - return T{DominatingValue<As>::restore(CGF, std::get<Is>(Saved))...}; - } - - void Emit(CodeGenFunction &CGF, Flags flags) override { - restore(CGF, llvm::index_sequence_for<As...>()).Emit(CGF, flags); - } - - public: - ConditionalCleanup(typename DominatingValue<As>::saved_type... A) - : Saved(A...) {} - - ConditionalCleanup(SavedTuple Tuple) : Saved(std::move(Tuple)) {} - }; - -private: - // The implementation for this class is in CGException.h and - // CGException.cpp; the definition is here because it's used as a - // member of CodeGenFunction. - - /// The start of the scope-stack buffer, i.e. the allocated pointer - /// for the buffer. All of these pointers are either simultaneously - /// null or simultaneously valid. - char *StartOfBuffer; - - /// The end of the buffer. - char *EndOfBuffer; - - /// The first valid entry in the buffer. - char *StartOfData; - - /// The innermost normal cleanup on the stack. - stable_iterator InnermostNormalCleanup; - - /// The innermost EH scope on the stack. - stable_iterator InnermostEHScope; - - /// The current set of branch fixups. A branch fixup is a jump to - /// an as-yet unemitted label, i.e. a label for which we don't yet - /// know the EH stack depth. Whenever we pop a cleanup, we have - /// to thread all the current branch fixups through it. - /// - /// Fixups are recorded as the Use of the respective branch or - /// switch statement. The use points to the final destination. - /// When popping out of a cleanup, these uses are threaded through - /// the cleanup and adjusted to point to the new cleanup. - /// - /// Note that branches are allowed to jump into protected scopes - /// in certain situations; e.g. the following code is legal: - /// struct A { ~A(); }; // trivial ctor, non-trivial dtor - /// goto foo; - /// A a; - /// foo: - /// bar(); - SmallVector<BranchFixup, 8> BranchFixups; - - char *allocate(size_t Size); - void deallocate(size_t Size); - - void *pushCleanup(CleanupKind K, size_t DataSize); - -public: - EHScopeStack() : StartOfBuffer(nullptr), EndOfBuffer(nullptr), - StartOfData(nullptr), InnermostNormalCleanup(stable_end()), - InnermostEHScope(stable_end()) {} - ~EHScopeStack() { delete[] StartOfBuffer; } - - /// Push a lazily-created cleanup on the stack. - template <class T, class... As> void pushCleanup(CleanupKind Kind, As... A) { - static_assert(alignof(T) <= ScopeStackAlignment, - "Cleanup's alignment is too large."); - void *Buffer = pushCleanup(Kind, sizeof(T)); - Cleanup *Obj = new (Buffer) T(A...); - (void) Obj; - } - - /// Push a lazily-created cleanup on the stack. Tuple version. - template <class T, class... As> - void pushCleanupTuple(CleanupKind Kind, std::tuple<As...> A) { - static_assert(alignof(T) <= ScopeStackAlignment, - "Cleanup's alignment is too large."); - void *Buffer = pushCleanup(Kind, sizeof(T)); - Cleanup *Obj = new (Buffer) T(std::move(A)); - (void) Obj; - } - - // Feel free to add more variants of the following: - - /// Push a cleanup with non-constant storage requirements on the - /// stack. The cleanup type must provide an additional static method: - /// static size_t getExtraSize(size_t); - /// The argument to this method will be the value N, which will also - /// be passed as the first argument to the constructor. - /// - /// The data stored in the extra storage must obey the same - /// restrictions as normal cleanup member data. - /// - /// The pointer returned from this method is valid until the cleanup - /// stack is modified. - template <class T, class... As> - T *pushCleanupWithExtra(CleanupKind Kind, size_t N, As... A) { - static_assert(alignof(T) <= ScopeStackAlignment, - "Cleanup's alignment is too large."); - void *Buffer = pushCleanup(Kind, sizeof(T) + T::getExtraSize(N)); - return new (Buffer) T(N, A...); - } - - void pushCopyOfCleanup(CleanupKind Kind, const void *Cleanup, size_t Size) { - void *Buffer = pushCleanup(Kind, Size); - std::memcpy(Buffer, Cleanup, Size); - } - - /// Pops a cleanup scope off the stack. This is private to CGCleanup.cpp. - void popCleanup(); - - /// Push a set of catch handlers on the stack. The catch is - /// uninitialized and will need to have the given number of handlers - /// set on it. - class EHCatchScope *pushCatch(unsigned NumHandlers); - - /// Pops a catch scope off the stack. This is private to CGException.cpp. - void popCatch(); - - /// Push an exceptions filter on the stack. - class EHFilterScope *pushFilter(unsigned NumFilters); - - /// Pops an exceptions filter off the stack. - void popFilter(); - - /// Push a terminate handler on the stack. - void pushTerminate(); - - /// Pops a terminate handler off the stack. - void popTerminate(); - - // Returns true iff the current scope is either empty or contains only - // lifetime markers, i.e. no real cleanup code - bool containsOnlyLifetimeMarkers(stable_iterator Old) const; - - /// Determines whether the exception-scopes stack is empty. - bool empty() const { return StartOfData == EndOfBuffer; } - - bool requiresLandingPad() const; - - /// Determines whether there are any normal cleanups on the stack. - bool hasNormalCleanups() const { - return InnermostNormalCleanup != stable_end(); - } - - /// Returns the innermost normal cleanup on the stack, or - /// stable_end() if there are no normal cleanups. - stable_iterator getInnermostNormalCleanup() const { - return InnermostNormalCleanup; - } - stable_iterator getInnermostActiveNormalCleanup() const; - - stable_iterator getInnermostEHScope() const { - return InnermostEHScope; - } - - - /// An unstable reference to a scope-stack depth. Invalidated by - /// pushes but not pops. - class iterator; - - /// Returns an iterator pointing to the innermost EH scope. - iterator begin() const; - - /// Returns an iterator pointing to the outermost EH scope. - iterator end() const; - - /// Create a stable reference to the top of the EH stack. The - /// returned reference is valid until that scope is popped off the - /// stack. - stable_iterator stable_begin() const { - return stable_iterator(EndOfBuffer - StartOfData); - } - - /// Create a stable reference to the bottom of the EH stack. - static stable_iterator stable_end() { - return stable_iterator(0); - } - - /// Translates an iterator into a stable_iterator. - stable_iterator stabilize(iterator it) const; - - /// Turn a stable reference to a scope depth into a unstable pointer - /// to the EH stack. - iterator find(stable_iterator save) const; - - /// Add a branch fixup to the current cleanup scope. - BranchFixup &addBranchFixup() { - assert(hasNormalCleanups() && "adding fixup in scope without cleanups"); - BranchFixups.push_back(BranchFixup()); - return BranchFixups.back(); - } - - unsigned getNumBranchFixups() const { return BranchFixups.size(); } - BranchFixup &getBranchFixup(unsigned I) { - assert(I < getNumBranchFixups()); - return BranchFixups[I]; - } - - /// Pops lazily-removed fixups from the end of the list. This - /// should only be called by procedures which have just popped a - /// cleanup or resolved one or more fixups. - void popNullFixups(); - - /// Clears the branch-fixups list. This should only be called by - /// ResolveAllBranchFixups. - void clearFixups() { BranchFixups.clear(); } -}; - -} // namespace CodeGen -} // namespace clang - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp b/gnu/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp deleted file mode 100644 index c56875a0368..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ /dev/null @@ -1,4281 +0,0 @@ -//===------- ItaniumCXXABI.cpp - Emit LLVM Code from ASTs for a Module ----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This provides C++ code generation targeting the Itanium C++ ABI. The class -// in this file generates structures that follow the Itanium C++ ABI, which is -// documented at: -// http://www.codesourcery.com/public/cxx-abi/abi.html -// http://www.codesourcery.com/public/cxx-abi/abi-eh.html -// -// It also supports the closely-related ARM ABI, documented at: -// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf -// -//===----------------------------------------------------------------------===// - -#include "CGCXXABI.h" -#include "CGCleanup.h" -#include "CGRecordLayout.h" -#include "CGVTables.h" -#include "CodeGenFunction.h" -#include "CodeGenModule.h" -#include "TargetInfo.h" -#include "clang/CodeGen/ConstantInitBuilder.h" -#include "clang/AST/Mangle.h" -#include "clang/AST/Type.h" -#include "clang/AST/StmtCXX.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/ScopedPrinter.h" - -using namespace clang; -using namespace CodeGen; - -namespace { -class ItaniumCXXABI : public CodeGen::CGCXXABI { - /// VTables - All the vtables which have been defined. - llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables; - -protected: - bool UseARMMethodPtrABI; - bool UseARMGuardVarABI; - bool Use32BitVTableOffsetABI; - - ItaniumMangleContext &getMangleContext() { - return cast<ItaniumMangleContext>(CodeGen::CGCXXABI::getMangleContext()); - } - -public: - ItaniumCXXABI(CodeGen::CodeGenModule &CGM, - bool UseARMMethodPtrABI = false, - bool UseARMGuardVarABI = false) : - CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI), - UseARMGuardVarABI(UseARMGuardVarABI), - Use32BitVTableOffsetABI(false) { } - - bool classifyReturnType(CGFunctionInfo &FI) const override; - - bool passClassIndirect(const CXXRecordDecl *RD) const { - return !canCopyArgument(RD); - } - - RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override { - // If C++ prohibits us from making a copy, pass by address. - if (passClassIndirect(RD)) - return RAA_Indirect; - return RAA_Default; - } - - bool isThisCompleteObject(GlobalDecl GD) const override { - // The Itanium ABI has separate complete-object vs. base-object - // variants of both constructors and destructors. - if (isa<CXXDestructorDecl>(GD.getDecl())) { - switch (GD.getDtorType()) { - case Dtor_Complete: - case Dtor_Deleting: - return true; - - case Dtor_Base: - return false; - - case Dtor_Comdat: - llvm_unreachable("emitting dtor comdat as function?"); - } - llvm_unreachable("bad dtor kind"); - } - if (isa<CXXConstructorDecl>(GD.getDecl())) { - switch (GD.getCtorType()) { - case Ctor_Complete: - return true; - - case Ctor_Base: - return false; - - case Ctor_CopyingClosure: - case Ctor_DefaultClosure: - llvm_unreachable("closure ctors in Itanium ABI?"); - - case Ctor_Comdat: - llvm_unreachable("emitting ctor comdat as function?"); - } - llvm_unreachable("bad dtor kind"); - } - - // No other kinds. - return false; - } - - bool isZeroInitializable(const MemberPointerType *MPT) override; - - llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT) override; - - CGCallee - EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, - const Expr *E, - Address This, - llvm::Value *&ThisPtrForCall, - llvm::Value *MemFnPtr, - const MemberPointerType *MPT) override; - - llvm::Value * - EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E, - Address Base, - llvm::Value *MemPtr, - const MemberPointerType *MPT) override; - - llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF, - const CastExpr *E, - llvm::Value *Src) override; - llvm::Constant *EmitMemberPointerConversion(const CastExpr *E, - llvm::Constant *Src) override; - - llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT) override; - - llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD) override; - llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT, - CharUnits offset) override; - llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT) override; - llvm::Constant *BuildMemberPointer(const CXXMethodDecl *MD, - CharUnits ThisAdjustment); - - llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF, - llvm::Value *L, llvm::Value *R, - const MemberPointerType *MPT, - bool Inequality) override; - - llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF, - llvm::Value *Addr, - const MemberPointerType *MPT) override; - - void emitVirtualObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, - Address Ptr, QualType ElementType, - const CXXDestructorDecl *Dtor) override; - - /// Itanium says that an _Unwind_Exception has to be "double-word" - /// aligned (and thus the end of it is also so-aligned), meaning 16 - /// bytes. Of course, that was written for the actual Itanium, - /// which is a 64-bit platform. Classically, the ABI doesn't really - /// specify the alignment on other platforms, but in practice - /// libUnwind declares the struct with __attribute__((aligned)), so - /// we assume that alignment here. (It's generally 16 bytes, but - /// some targets overwrite it.) - CharUnits getAlignmentOfExnObject() { - auto align = CGM.getContext().getTargetDefaultAlignForAttributeAligned(); - return CGM.getContext().toCharUnitsFromBits(align); - } - - void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) override; - void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) override; - - void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override; - - llvm::CallInst * - emitTerminateForUnexpectedException(CodeGenFunction &CGF, - llvm::Value *Exn) override; - - void EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD); - llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override; - CatchTypeInfo - getAddrOfCXXCatchHandlerType(QualType Ty, - QualType CatchHandlerType) override { - return CatchTypeInfo{getAddrOfRTTIDescriptor(Ty), 0}; - } - - bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy) override; - void EmitBadTypeidCall(CodeGenFunction &CGF) override; - llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy, - Address ThisPtr, - llvm::Type *StdTypeInfoPtrTy) override; - - bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr, - QualType SrcRecordTy) override; - - llvm::Value *EmitDynamicCastCall(CodeGenFunction &CGF, Address Value, - QualType SrcRecordTy, QualType DestTy, - QualType DestRecordTy, - llvm::BasicBlock *CastEnd) override; - - llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF, Address Value, - QualType SrcRecordTy, - QualType DestTy) override; - - bool EmitBadCastCall(CodeGenFunction &CGF) override; - - llvm::Value * - GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This, - const CXXRecordDecl *ClassDecl, - const CXXRecordDecl *BaseClassDecl) override; - - void EmitCXXConstructors(const CXXConstructorDecl *D) override; - - AddedStructorArgs - buildStructorSignature(const CXXMethodDecl *MD, StructorType T, - SmallVectorImpl<CanQualType> &ArgTys) override; - - bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor, - CXXDtorType DT) const override { - // Itanium does not emit any destructor variant as an inline thunk. - // Delegating may occur as an optimization, but all variants are either - // emitted with external linkage or as linkonce if they are inline and used. - return false; - } - - void EmitCXXDestructors(const CXXDestructorDecl *D) override; - - void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy, - FunctionArgList &Params) override; - - void EmitInstanceFunctionProlog(CodeGenFunction &CGF) override; - - AddedStructorArgs - addImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D, - CXXCtorType Type, bool ForVirtualBase, - bool Delegating, CallArgList &Args) override; - - void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, - CXXDtorType Type, bool ForVirtualBase, - bool Delegating, Address This) override; - - void emitVTableDefinitions(CodeGenVTables &CGVT, - const CXXRecordDecl *RD) override; - - bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF, - CodeGenFunction::VPtr Vptr) override; - - bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass) override { - return true; - } - - llvm::Constant * - getVTableAddressPoint(BaseSubobject Base, - const CXXRecordDecl *VTableClass) override; - - llvm::Value *getVTableAddressPointInStructor( - CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, - BaseSubobject Base, const CXXRecordDecl *NearestVBase) override; - - llvm::Value *getVTableAddressPointInStructorWithVTT( - CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, - BaseSubobject Base, const CXXRecordDecl *NearestVBase); - - llvm::Constant * - getVTableAddressPointForConstExpr(BaseSubobject Base, - const CXXRecordDecl *VTableClass) override; - - llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, - CharUnits VPtrOffset) override; - - CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD, - Address This, llvm::Type *Ty, - SourceLocation Loc) override; - - llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF, - const CXXDestructorDecl *Dtor, - CXXDtorType DtorType, - Address This, - const CXXMemberCallExpr *CE) override; - - void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override; - - bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override; - bool canSpeculativelyEmitVTableAsBaseClass(const CXXRecordDecl *RD) const; - - void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD, - bool ReturnAdjustment) override { - // Allow inlining of thunks by emitting them with available_externally - // linkage together with vtables when needed. - if (ForVTable && !Thunk->hasLocalLinkage()) - Thunk->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage); - CGM.setGVProperties(Thunk, GD); - } - - bool exportThunk() override { return true; } - - llvm::Value *performThisAdjustment(CodeGenFunction &CGF, Address This, - const ThisAdjustment &TA) override; - - llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, Address Ret, - const ReturnAdjustment &RA) override; - - size_t getSrcArgforCopyCtor(const CXXConstructorDecl *, - FunctionArgList &Args) const override { - assert(!Args.empty() && "expected the arglist to not be empty!"); - return Args.size() - 1; - } - - StringRef GetPureVirtualCallName() override { return "__cxa_pure_virtual"; } - StringRef GetDeletedVirtualCallName() override - { return "__cxa_deleted_virtual"; } - - CharUnits getArrayCookieSizeImpl(QualType elementType) override; - Address InitializeArrayCookie(CodeGenFunction &CGF, - Address NewPtr, - llvm::Value *NumElements, - const CXXNewExpr *expr, - QualType ElementType) override; - llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, - Address allocPtr, - CharUnits cookieSize) override; - - void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, - llvm::GlobalVariable *DeclPtr, - bool PerformInit) override; - void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, - llvm::Constant *dtor, llvm::Constant *addr) override; - - llvm::Function *getOrCreateThreadLocalWrapper(const VarDecl *VD, - llvm::Value *Val); - void EmitThreadLocalInitFuncs( - CodeGenModule &CGM, - ArrayRef<const VarDecl *> CXXThreadLocals, - ArrayRef<llvm::Function *> CXXThreadLocalInits, - ArrayRef<const VarDecl *> CXXThreadLocalInitVars) override; - - bool usesThreadWrapperFunction() const override { return true; } - LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD, - QualType LValType) override; - - bool NeedsVTTParameter(GlobalDecl GD) override; - - /**************************** RTTI Uniqueness ******************************/ - -protected: - /// Returns true if the ABI requires RTTI type_info objects to be unique - /// across a program. - virtual bool shouldRTTIBeUnique() const { return true; } - -public: - /// What sort of unique-RTTI behavior should we use? - enum RTTIUniquenessKind { - /// We are guaranteeing, or need to guarantee, that the RTTI string - /// is unique. - RUK_Unique, - - /// We are not guaranteeing uniqueness for the RTTI string, so we - /// can demote to hidden visibility but must use string comparisons. - RUK_NonUniqueHidden, - - /// We are not guaranteeing uniqueness for the RTTI string, so we - /// have to use string comparisons, but we also have to emit it with - /// non-hidden visibility. - RUK_NonUniqueVisible - }; - - /// Return the required visibility status for the given type and linkage in - /// the current ABI. - RTTIUniquenessKind - classifyRTTIUniqueness(QualType CanTy, - llvm::GlobalValue::LinkageTypes Linkage) const; - friend class ItaniumRTTIBuilder; - - void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override; - - std::pair<llvm::Value *, const CXXRecordDecl *> - LoadVTablePtr(CodeGenFunction &CGF, Address This, - const CXXRecordDecl *RD) override; - - private: - bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const { - const auto &VtableLayout = - CGM.getItaniumVTableContext().getVTableLayout(RD); - - for (const auto &VtableComponent : VtableLayout.vtable_components()) { - // Skip empty slot. - if (!VtableComponent.isUsedFunctionPointerKind()) - continue; - - const CXXMethodDecl *Method = VtableComponent.getFunctionDecl(); - if (!Method->getCanonicalDecl()->isInlined()) - continue; - - StringRef Name = CGM.getMangledName(VtableComponent.getGlobalDecl()); - auto *Entry = CGM.GetGlobalValue(Name); - // This checks if virtual inline function has already been emitted. - // Note that it is possible that this inline function would be emitted - // after trying to emit vtable speculatively. Because of this we do - // an extra pass after emitting all deferred vtables to find and emit - // these vtables opportunistically. - if (!Entry || Entry->isDeclaration()) - return true; - } - return false; - } - - bool isVTableHidden(const CXXRecordDecl *RD) const { - const auto &VtableLayout = - CGM.getItaniumVTableContext().getVTableLayout(RD); - - for (const auto &VtableComponent : VtableLayout.vtable_components()) { - if (VtableComponent.isRTTIKind()) { - const CXXRecordDecl *RTTIDecl = VtableComponent.getRTTIDecl(); - if (RTTIDecl->getVisibility() == Visibility::HiddenVisibility) - return true; - } else if (VtableComponent.isUsedFunctionPointerKind()) { - const CXXMethodDecl *Method = VtableComponent.getFunctionDecl(); - if (Method->getVisibility() == Visibility::HiddenVisibility && - !Method->isDefined()) - return true; - } - } - return false; - } -}; - -class ARMCXXABI : public ItaniumCXXABI { -public: - ARMCXXABI(CodeGen::CodeGenModule &CGM) : - ItaniumCXXABI(CGM, /* UseARMMethodPtrABI = */ true, - /* UseARMGuardVarABI = */ true) {} - - bool HasThisReturn(GlobalDecl GD) const override { - return (isa<CXXConstructorDecl>(GD.getDecl()) || ( - isa<CXXDestructorDecl>(GD.getDecl()) && - GD.getDtorType() != Dtor_Deleting)); - } - - void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, - QualType ResTy) override; - - CharUnits getArrayCookieSizeImpl(QualType elementType) override; - Address InitializeArrayCookie(CodeGenFunction &CGF, - Address NewPtr, - llvm::Value *NumElements, - const CXXNewExpr *expr, - QualType ElementType) override; - llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, Address allocPtr, - CharUnits cookieSize) override; -}; - -class iOS64CXXABI : public ARMCXXABI { -public: - iOS64CXXABI(CodeGen::CodeGenModule &CGM) : ARMCXXABI(CGM) { - Use32BitVTableOffsetABI = true; - } - - // ARM64 libraries are prepared for non-unique RTTI. - bool shouldRTTIBeUnique() const override { return false; } -}; - -class WebAssemblyCXXABI final : public ItaniumCXXABI { -public: - explicit WebAssemblyCXXABI(CodeGen::CodeGenModule &CGM) - : ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true, - /*UseARMGuardVarABI=*/true) {} - void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override; - -private: - bool HasThisReturn(GlobalDecl GD) const override { - return isa<CXXConstructorDecl>(GD.getDecl()) || - (isa<CXXDestructorDecl>(GD.getDecl()) && - GD.getDtorType() != Dtor_Deleting); - } - bool canCallMismatchedFunctionType() const override { return false; } -}; -} - -CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) { - switch (CGM.getTarget().getCXXABI().getKind()) { - // For IR-generation purposes, there's no significant difference - // between the ARM and iOS ABIs. - case TargetCXXABI::GenericARM: - case TargetCXXABI::iOS: - case TargetCXXABI::WatchOS: - return new ARMCXXABI(CGM); - - case TargetCXXABI::iOS64: - return new iOS64CXXABI(CGM); - - // Note that AArch64 uses the generic ItaniumCXXABI class since it doesn't - // include the other 32-bit ARM oddities: constructor/destructor return values - // and array cookies. - case TargetCXXABI::GenericAArch64: - return new ItaniumCXXABI(CGM, /* UseARMMethodPtrABI = */ true, - /* UseARMGuardVarABI = */ true); - - case TargetCXXABI::GenericMIPS: - return new ItaniumCXXABI(CGM, /* UseARMMethodPtrABI = */ true); - - case TargetCXXABI::WebAssembly: - return new WebAssemblyCXXABI(CGM); - - case TargetCXXABI::GenericItanium: - if (CGM.getContext().getTargetInfo().getTriple().getArch() - == llvm::Triple::le32) { - // For PNaCl, use ARM-style method pointers so that PNaCl code - // does not assume anything about the alignment of function - // pointers. - return new ItaniumCXXABI(CGM, /* UseARMMethodPtrABI = */ true, - /* UseARMGuardVarABI = */ false); - } - return new ItaniumCXXABI(CGM); - - case TargetCXXABI::Microsoft: - llvm_unreachable("Microsoft ABI is not Itanium-based"); - } - llvm_unreachable("bad ABI kind"); -} - -llvm::Type * -ItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) { - if (MPT->isMemberDataPointer()) - return CGM.PtrDiffTy; - return llvm::StructType::get(CGM.PtrDiffTy, CGM.PtrDiffTy); -} - -/// In the Itanium and ARM ABIs, method pointers have the form: -/// struct { ptrdiff_t ptr; ptrdiff_t adj; } memptr; -/// -/// In the Itanium ABI: -/// - method pointers are virtual if (memptr.ptr & 1) is nonzero -/// - the this-adjustment is (memptr.adj) -/// - the virtual offset is (memptr.ptr - 1) -/// -/// In the ARM ABI: -/// - method pointers are virtual if (memptr.adj & 1) is nonzero -/// - the this-adjustment is (memptr.adj >> 1) -/// - the virtual offset is (memptr.ptr) -/// ARM uses 'adj' for the virtual flag because Thumb functions -/// may be only single-byte aligned. -/// -/// If the member is virtual, the adjusted 'this' pointer points -/// to a vtable pointer from which the virtual offset is applied. -/// -/// If the member is non-virtual, memptr.ptr is the address of -/// the function to call. -CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( - CodeGenFunction &CGF, const Expr *E, Address ThisAddr, - llvm::Value *&ThisPtrForCall, - llvm::Value *MemFnPtr, const MemberPointerType *MPT) { - CGBuilderTy &Builder = CGF.Builder; - - const FunctionProtoType *FPT = - MPT->getPointeeType()->getAs<FunctionProtoType>(); - const CXXRecordDecl *RD = - cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl()); - - llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType( - CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr)); - - llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1); - - llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("memptr.virtual"); - llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("memptr.nonvirtual"); - llvm::BasicBlock *FnEnd = CGF.createBasicBlock("memptr.end"); - - // Extract memptr.adj, which is in the second field. - llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1, "memptr.adj"); - - // Compute the true adjustment. - llvm::Value *Adj = RawAdj; - if (UseARMMethodPtrABI) - Adj = Builder.CreateAShr(Adj, ptrdiff_1, "memptr.adj.shifted"); - - // Apply the adjustment and cast back to the original struct type - // for consistency. - llvm::Value *This = ThisAddr.getPointer(); - llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy()); - Ptr = Builder.CreateInBoundsGEP(Ptr, Adj); - This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted"); - ThisPtrForCall = This; - - // Load the function pointer. - llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0, "memptr.ptr"); - - // If the LSB in the function pointer is 1, the function pointer points to - // a virtual function. - llvm::Value *IsVirtual; - if (UseARMMethodPtrABI) - IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1); - else - IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1); - IsVirtual = Builder.CreateIsNotNull(IsVirtual, "memptr.isvirtual"); - Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual); - - // In the virtual path, the adjustment left 'This' pointing to the - // vtable of the correct base subobject. The "function pointer" is an - // offset within the vtable (+1 for the virtual flag on non-ARM). - CGF.EmitBlock(FnVirtual); - - // Cast the adjusted this to a pointer to vtable pointer and load. - llvm::Type *VTableTy = Builder.getInt8PtrTy(); - CharUnits VTablePtrAlign = - CGF.CGM.getDynamicOffsetAlignment(ThisAddr.getAlignment(), RD, - CGF.getPointerAlign()); - llvm::Value *VTable = - CGF.GetVTablePtr(Address(This, VTablePtrAlign), VTableTy, RD); - - // Apply the offset. - // On ARM64, to reserve extra space in virtual member function pointers, - // we only pay attention to the low 32 bits of the offset. - llvm::Value *VTableOffset = FnAsInt; - if (!UseARMMethodPtrABI) - VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1); - if (Use32BitVTableOffsetABI) { - VTableOffset = Builder.CreateTrunc(VTableOffset, CGF.Int32Ty); - VTableOffset = Builder.CreateZExt(VTableOffset, CGM.PtrDiffTy); - } - // Compute the address of the virtual function pointer. - llvm::Value *VFPAddr = Builder.CreateGEP(VTable, VTableOffset); - - // Check the address of the function pointer if CFI on member function - // pointers is enabled. - llvm::Constant *CheckSourceLocation; - llvm::Constant *CheckTypeDesc; - bool ShouldEmitCFICheck = CGF.SanOpts.has(SanitizerKind::CFIMFCall) && - CGM.HasHiddenLTOVisibility(RD); - if (ShouldEmitCFICheck) { - CodeGenFunction::SanitizerScope SanScope(&CGF); - - CheckSourceLocation = CGF.EmitCheckSourceLocation(E->getBeginLoc()); - CheckTypeDesc = CGF.EmitCheckTypeDescriptor(QualType(MPT, 0)); - llvm::Constant *StaticData[] = { - llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_VMFCall), - CheckSourceLocation, - CheckTypeDesc, - }; - - llvm::Metadata *MD = - CGM.CreateMetadataIdentifierForVirtualMemPtrType(QualType(MPT, 0)); - llvm::Value *TypeId = llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD); - - llvm::Value *TypeTest = Builder.CreateCall( - CGM.getIntrinsic(llvm::Intrinsic::type_test), {VFPAddr, TypeId}); - - if (CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIMFCall)) { - CGF.EmitTrapCheck(TypeTest); - } else { - llvm::Value *AllVtables = llvm::MetadataAsValue::get( - CGM.getLLVMContext(), - llvm::MDString::get(CGM.getLLVMContext(), "all-vtables")); - llvm::Value *ValidVtable = Builder.CreateCall( - CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables}); - CGF.EmitCheck(std::make_pair(TypeTest, SanitizerKind::CFIMFCall), - SanitizerHandler::CFICheckFail, StaticData, - {VTable, ValidVtable}); - } - - FnVirtual = Builder.GetInsertBlock(); - } - - // Load the virtual function to call. - VFPAddr = Builder.CreateBitCast(VFPAddr, FTy->getPointerTo()->getPointerTo()); - llvm::Value *VirtualFn = Builder.CreateAlignedLoad( - VFPAddr, CGF.getPointerAlign(), "memptr.virtualfn"); - CGF.EmitBranch(FnEnd); - - // In the non-virtual path, the function pointer is actually a - // function pointer. - CGF.EmitBlock(FnNonVirtual); - llvm::Value *NonVirtualFn = - Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo(), "memptr.nonvirtualfn"); - - // Check the function pointer if CFI on member function pointers is enabled. - if (ShouldEmitCFICheck) { - CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl(); - if (RD->hasDefinition()) { - CodeGenFunction::SanitizerScope SanScope(&CGF); - - llvm::Constant *StaticData[] = { - llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_NVMFCall), - CheckSourceLocation, - CheckTypeDesc, - }; - - llvm::Value *Bit = Builder.getFalse(); - llvm::Value *CastedNonVirtualFn = - Builder.CreateBitCast(NonVirtualFn, CGF.Int8PtrTy); - for (const CXXRecordDecl *Base : CGM.getMostBaseClasses(RD)) { - llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType( - getContext().getMemberPointerType( - MPT->getPointeeType(), - getContext().getRecordType(Base).getTypePtr())); - llvm::Value *TypeId = - llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD); - - llvm::Value *TypeTest = - Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test), - {CastedNonVirtualFn, TypeId}); - Bit = Builder.CreateOr(Bit, TypeTest); - } - - CGF.EmitCheck(std::make_pair(Bit, SanitizerKind::CFIMFCall), - SanitizerHandler::CFICheckFail, StaticData, - {CastedNonVirtualFn, llvm::UndefValue::get(CGF.IntPtrTy)}); - - FnNonVirtual = Builder.GetInsertBlock(); - } - } - - // We're done. - CGF.EmitBlock(FnEnd); - llvm::PHINode *CalleePtr = Builder.CreatePHI(FTy->getPointerTo(), 2); - CalleePtr->addIncoming(VirtualFn, FnVirtual); - CalleePtr->addIncoming(NonVirtualFn, FnNonVirtual); - - CGCallee Callee(FPT, CalleePtr); - return Callee; -} - -/// Compute an l-value by applying the given pointer-to-member to a -/// base object. -llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress( - CodeGenFunction &CGF, const Expr *E, Address Base, llvm::Value *MemPtr, - const MemberPointerType *MPT) { - assert(MemPtr->getType() == CGM.PtrDiffTy); - - CGBuilderTy &Builder = CGF.Builder; - - // Cast to char*. - Base = Builder.CreateElementBitCast(Base, CGF.Int8Ty); - - // Apply the offset, which we assume is non-null. - llvm::Value *Addr = - Builder.CreateInBoundsGEP(Base.getPointer(), MemPtr, "memptr.offset"); - - // Cast the address to the appropriate pointer type, adopting the - // address space of the base pointer. - llvm::Type *PType = CGF.ConvertTypeForMem(MPT->getPointeeType()) - ->getPointerTo(Base.getAddressSpace()); - return Builder.CreateBitCast(Addr, PType); -} - -/// Perform a bitcast, derived-to-base, or base-to-derived member pointer -/// conversion. -/// -/// Bitcast conversions are always a no-op under Itanium. -/// -/// Obligatory offset/adjustment diagram: -/// <-- offset --> <-- adjustment --> -/// |--------------------------|----------------------|--------------------| -/// ^Derived address point ^Base address point ^Member address point -/// -/// So when converting a base member pointer to a derived member pointer, -/// we add the offset to the adjustment because the address point has -/// decreased; and conversely, when converting a derived MP to a base MP -/// we subtract the offset from the adjustment because the address point -/// has increased. -/// -/// The standard forbids (at compile time) conversion to and from -/// virtual bases, which is why we don't have to consider them here. -/// -/// The standard forbids (at run time) casting a derived MP to a base -/// MP when the derived MP does not point to a member of the base. -/// This is why -1 is a reasonable choice for null data member -/// pointers. -llvm::Value * -ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, - const CastExpr *E, - llvm::Value *src) { - assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || - E->getCastKind() == CK_BaseToDerivedMemberPointer || - E->getCastKind() == CK_ReinterpretMemberPointer); - - // Under Itanium, reinterprets don't require any additional processing. - if (E->getCastKind() == CK_ReinterpretMemberPointer) return src; - - // Use constant emission if we can. - if (isa<llvm::Constant>(src)) - return EmitMemberPointerConversion(E, cast<llvm::Constant>(src)); - - llvm::Constant *adj = getMemberPointerAdjustment(E); - if (!adj) return src; - - CGBuilderTy &Builder = CGF.Builder; - bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer); - - const MemberPointerType *destTy = - E->getType()->castAs<MemberPointerType>(); - - // For member data pointers, this is just a matter of adding the - // offset if the source is non-null. - if (destTy->isMemberDataPointer()) { - llvm::Value *dst; - if (isDerivedToBase) - dst = Builder.CreateNSWSub(src, adj, "adj"); - else - dst = Builder.CreateNSWAdd(src, adj, "adj"); - - // Null check. - llvm::Value *null = llvm::Constant::getAllOnesValue(src->getType()); - llvm::Value *isNull = Builder.CreateICmpEQ(src, null, "memptr.isnull"); - return Builder.CreateSelect(isNull, src, dst); - } - - // The this-adjustment is left-shifted by 1 on ARM. - if (UseARMMethodPtrABI) { - uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue(); - offset <<= 1; - adj = llvm::ConstantInt::get(adj->getType(), offset); - } - - llvm::Value *srcAdj = Builder.CreateExtractValue(src, 1, "src.adj"); - llvm::Value *dstAdj; - if (isDerivedToBase) - dstAdj = Builder.CreateNSWSub(srcAdj, adj, "adj"); - else - dstAdj = Builder.CreateNSWAdd(srcAdj, adj, "adj"); - - return Builder.CreateInsertValue(src, dstAdj, 1); -} - -llvm::Constant * -ItaniumCXXABI::EmitMemberPointerConversion(const CastExpr *E, - llvm::Constant *src) { - assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || - E->getCastKind() == CK_BaseToDerivedMemberPointer || - E->getCastKind() == CK_ReinterpretMemberPointer); - - // Under Itanium, reinterprets don't require any additional processing. - if (E->getCastKind() == CK_ReinterpretMemberPointer) return src; - - // If the adjustment is trivial, we don't need to do anything. - llvm::Constant *adj = getMemberPointerAdjustment(E); - if (!adj) return src; - - bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer); - - const MemberPointerType *destTy = - E->getType()->castAs<MemberPointerType>(); - - // For member data pointers, this is just a matter of adding the - // offset if the source is non-null. - if (destTy->isMemberDataPointer()) { - // null maps to null. - if (src->isAllOnesValue()) return src; - - if (isDerivedToBase) - return llvm::ConstantExpr::getNSWSub(src, adj); - else - return llvm::ConstantExpr::getNSWAdd(src, adj); - } - - // The this-adjustment is left-shifted by 1 on ARM. - if (UseARMMethodPtrABI) { - uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue(); - offset <<= 1; - adj = llvm::ConstantInt::get(adj->getType(), offset); - } - - llvm::Constant *srcAdj = llvm::ConstantExpr::getExtractValue(src, 1); - llvm::Constant *dstAdj; - if (isDerivedToBase) - dstAdj = llvm::ConstantExpr::getNSWSub(srcAdj, adj); - else - dstAdj = llvm::ConstantExpr::getNSWAdd(srcAdj, adj); - - return llvm::ConstantExpr::getInsertValue(src, dstAdj, 1); -} - -llvm::Constant * -ItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { - // Itanium C++ ABI 2.3: - // A NULL pointer is represented as -1. - if (MPT->isMemberDataPointer()) - return llvm::ConstantInt::get(CGM.PtrDiffTy, -1ULL, /*isSigned=*/true); - - llvm::Constant *Zero = llvm::ConstantInt::get(CGM.PtrDiffTy, 0); - llvm::Constant *Values[2] = { Zero, Zero }; - return llvm::ConstantStruct::getAnon(Values); -} - -llvm::Constant * -ItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, - CharUnits offset) { - // Itanium C++ ABI 2.3: - // A pointer to data member is an offset from the base address of - // the class object containing it, represented as a ptrdiff_t - return llvm::ConstantInt::get(CGM.PtrDiffTy, offset.getQuantity()); -} - -llvm::Constant * -ItaniumCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { - return BuildMemberPointer(MD, CharUnits::Zero()); -} - -llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD, - CharUnits ThisAdjustment) { - assert(MD->isInstance() && "Member function must not be static!"); - - CodeGenTypes &Types = CGM.getTypes(); - - // Get the function pointer (or index if this is a virtual function). - llvm::Constant *MemPtr[2]; - if (MD->isVirtual()) { - uint64_t Index = CGM.getItaniumVTableContext().getMethodVTableIndex(MD); - - const ASTContext &Context = getContext(); - CharUnits PointerWidth = - Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); - uint64_t VTableOffset = (Index * PointerWidth.getQuantity()); - - if (UseARMMethodPtrABI) { - // ARM C++ ABI 3.2.1: - // This ABI specifies that adj contains twice the this - // adjustment, plus 1 if the member function is virtual. The - // least significant bit of adj then makes exactly the same - // discrimination as the least significant bit of ptr does for - // Itanium. - MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset); - MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy, - 2 * ThisAdjustment.getQuantity() + 1); - } else { - // Itanium C++ ABI 2.3: - // For a virtual function, [the pointer field] is 1 plus the - // virtual table offset (in bytes) of the function, - // represented as a ptrdiff_t. - MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset + 1); - MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy, - ThisAdjustment.getQuantity()); - } - } else { - const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); - llvm::Type *Ty; - // Check whether the function has a computable LLVM signature. - if (Types.isFuncTypeConvertible(FPT)) { - // The function has a computable LLVM signature; use the correct type. - Ty = Types.GetFunctionType(Types.arrangeCXXMethodDeclaration(MD)); - } else { - // Use an arbitrary non-function type to tell GetAddrOfFunction that the - // function type is incomplete. - Ty = CGM.PtrDiffTy; - } - llvm::Constant *addr = CGM.GetAddrOfFunction(MD, Ty); - - MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, CGM.PtrDiffTy); - MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy, - (UseARMMethodPtrABI ? 2 : 1) * - ThisAdjustment.getQuantity()); - } - - return llvm::ConstantStruct::getAnon(MemPtr); -} - -llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP, - QualType MPType) { - const MemberPointerType *MPT = MPType->castAs<MemberPointerType>(); - const ValueDecl *MPD = MP.getMemberPointerDecl(); - if (!MPD) - return EmitNullMemberPointer(MPT); - - CharUnits ThisAdjustment = getMemberPointerPathAdjustment(MP); - - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) - return BuildMemberPointer(MD, ThisAdjustment); - - CharUnits FieldOffset = - getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD)); - return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset); -} - -/// The comparison algorithm is pretty easy: the member pointers are -/// the same if they're either bitwise identical *or* both null. -/// -/// ARM is different here only because null-ness is more complicated. -llvm::Value * -ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF, - llvm::Value *L, - llvm::Value *R, - const MemberPointerType *MPT, - bool Inequality) { - CGBuilderTy &Builder = CGF.Builder; - - llvm::ICmpInst::Predicate Eq; - llvm::Instruction::BinaryOps And, Or; - if (Inequality) { - Eq = llvm::ICmpInst::ICMP_NE; - And = llvm::Instruction::Or; - Or = llvm::Instruction::And; - } else { - Eq = llvm::ICmpInst::ICMP_EQ; - And = llvm::Instruction::And; - Or = llvm::Instruction::Or; - } - - // Member data pointers are easy because there's a unique null - // value, so it just comes down to bitwise equality. - if (MPT->isMemberDataPointer()) - return Builder.CreateICmp(Eq, L, R); - - // For member function pointers, the tautologies are more complex. - // The Itanium tautology is: - // (L == R) <==> (L.ptr == R.ptr && (L.ptr == 0 || L.adj == R.adj)) - // The ARM tautology is: - // (L == R) <==> (L.ptr == R.ptr && - // (L.adj == R.adj || - // (L.ptr == 0 && ((L.adj|R.adj) & 1) == 0))) - // The inequality tautologies have exactly the same structure, except - // applying De Morgan's laws. - - llvm::Value *LPtr = Builder.CreateExtractValue(L, 0, "lhs.memptr.ptr"); - llvm::Value *RPtr = Builder.CreateExtractValue(R, 0, "rhs.memptr.ptr"); - - // This condition tests whether L.ptr == R.ptr. This must always be - // true for equality to hold. - llvm::Value *PtrEq = Builder.CreateICmp(Eq, LPtr, RPtr, "cmp.ptr"); - - // This condition, together with the assumption that L.ptr == R.ptr, - // tests whether the pointers are both null. ARM imposes an extra - // condition. - llvm::Value *Zero = llvm::Constant::getNullValue(LPtr->getType()); - llvm::Value *EqZero = Builder.CreateICmp(Eq, LPtr, Zero, "cmp.ptr.null"); - - // This condition tests whether L.adj == R.adj. If this isn't - // true, the pointers are unequal unless they're both null. - llvm::Value *LAdj = Builder.CreateExtractValue(L, 1, "lhs.memptr.adj"); - llvm::Value *RAdj = Builder.CreateExtractValue(R, 1, "rhs.memptr.adj"); - llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj, "cmp.adj"); - - // Null member function pointers on ARM clear the low bit of Adj, - // so the zero condition has to check that neither low bit is set. - if (UseARMMethodPtrABI) { - llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1); - - // Compute (l.adj | r.adj) & 1 and test it against zero. - llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj, "or.adj"); - llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One); - llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1, Zero, - "cmp.or.adj"); - EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero); - } - - // Tie together all our conditions. - llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq); - Result = Builder.CreateBinOp(And, PtrEq, Result, - Inequality ? "memptr.ne" : "memptr.eq"); - return Result; -} - -llvm::Value * -ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF, - llvm::Value *MemPtr, - const MemberPointerType *MPT) { - CGBuilderTy &Builder = CGF.Builder; - - /// For member data pointers, this is just a check against -1. - if (MPT->isMemberDataPointer()) { - assert(MemPtr->getType() == CGM.PtrDiffTy); - llvm::Value *NegativeOne = - llvm::Constant::getAllOnesValue(MemPtr->getType()); - return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool"); - } - - // In Itanium, a member function pointer is not null if 'ptr' is not null. - llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0, "memptr.ptr"); - - llvm::Constant *Zero = llvm::ConstantInt::get(Ptr->getType(), 0); - llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero, "memptr.tobool"); - - // On ARM, a member function pointer is also non-null if the low bit of 'adj' - // (the virtual bit) is set. - if (UseARMMethodPtrABI) { - llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1); - llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj"); - llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit"); - llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit, Zero, - "memptr.isvirtual"); - Result = Builder.CreateOr(Result, IsVirtual); - } - - return Result; -} - -bool ItaniumCXXABI::classifyReturnType(CGFunctionInfo &FI) const { - const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl(); - if (!RD) - return false; - - // If C++ prohibits us from making a copy, return by address. - if (passClassIndirect(RD)) { - auto Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType()); - FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false); - return true; - } - return false; -} - -/// The Itanium ABI requires non-zero initialization only for data -/// member pointers, for which '0' is a valid offset. -bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) { - return MPT->isMemberFunctionPointer(); -} - -/// The Itanium ABI always places an offset to the complete object -/// at entry -2 in the vtable. -void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, - const CXXDeleteExpr *DE, - Address Ptr, - QualType ElementType, - const CXXDestructorDecl *Dtor) { - bool UseGlobalDelete = DE->isGlobalDelete(); - if (UseGlobalDelete) { - // Derive the complete-object pointer, which is what we need - // to pass to the deallocation function. - - // Grab the vtable pointer as an intptr_t*. - auto *ClassDecl = - cast<CXXRecordDecl>(ElementType->getAs<RecordType>()->getDecl()); - llvm::Value *VTable = - CGF.GetVTablePtr(Ptr, CGF.IntPtrTy->getPointerTo(), ClassDecl); - - // Track back to entry -2 and pull out the offset there. - llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64( - VTable, -2, "complete-offset.ptr"); - llvm::Value *Offset = - CGF.Builder.CreateAlignedLoad(OffsetPtr, CGF.getPointerAlign()); - - // Apply the offset. - llvm::Value *CompletePtr = - CGF.Builder.CreateBitCast(Ptr.getPointer(), CGF.Int8PtrTy); - CompletePtr = CGF.Builder.CreateInBoundsGEP(CompletePtr, Offset); - - // If we're supposed to call the global delete, make sure we do so - // even if the destructor throws. - CGF.pushCallObjectDeleteCleanup(DE->getOperatorDelete(), CompletePtr, - ElementType); - } - - // FIXME: Provide a source location here even though there's no - // CXXMemberCallExpr for dtor call. - CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting; - EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, /*CE=*/nullptr); - - if (UseGlobalDelete) - CGF.PopCleanupBlock(); -} - -void ItaniumCXXABI::emitRethrow(CodeGenFunction &CGF, bool isNoReturn) { - // void __cxa_rethrow(); - - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, /*IsVarArgs=*/false); - - llvm::Constant *Fn = CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow"); - - if (isNoReturn) - CGF.EmitNoreturnRuntimeCallOrInvoke(Fn, None); - else - CGF.EmitRuntimeCallOrInvoke(Fn); -} - -static llvm::Constant *getAllocateExceptionFn(CodeGenModule &CGM) { - // void *__cxa_allocate_exception(size_t thrown_size); - - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.Int8PtrTy, CGM.SizeTy, /*IsVarArgs=*/false); - - return CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception"); -} - -static llvm::Constant *getThrowFn(CodeGenModule &CGM) { - // void __cxa_throw(void *thrown_exception, std::type_info *tinfo, - // void (*dest) (void *)); - - llvm::Type *Args[3] = { CGM.Int8PtrTy, CGM.Int8PtrTy, CGM.Int8PtrTy }; - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, Args, /*IsVarArgs=*/false); - - return CGM.CreateRuntimeFunction(FTy, "__cxa_throw"); -} - -void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) { - QualType ThrowType = E->getSubExpr()->getType(); - // Now allocate the exception object. - llvm::Type *SizeTy = CGF.ConvertType(getContext().getSizeType()); - uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity(); - - llvm::Constant *AllocExceptionFn = getAllocateExceptionFn(CGM); - llvm::CallInst *ExceptionPtr = CGF.EmitNounwindRuntimeCall( - AllocExceptionFn, llvm::ConstantInt::get(SizeTy, TypeSize), "exception"); - - CharUnits ExnAlign = getAlignmentOfExnObject(); - CGF.EmitAnyExprToExn(E->getSubExpr(), Address(ExceptionPtr, ExnAlign)); - - // Now throw the exception. - llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType, - /*ForEH=*/true); - - // The address of the destructor. If the exception type has a - // trivial destructor (or isn't a record), we just pass null. - llvm::Constant *Dtor = nullptr; - if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) { - CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl()); - if (!Record->hasTrivialDestructor()) { - CXXDestructorDecl *DtorD = Record->getDestructor(); - Dtor = CGM.getAddrOfCXXStructor(DtorD, StructorType::Complete); - Dtor = llvm::ConstantExpr::getBitCast(Dtor, CGM.Int8PtrTy); - } - } - if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy); - - llvm::Value *args[] = { ExceptionPtr, TypeInfo, Dtor }; - CGF.EmitNoreturnRuntimeCallOrInvoke(getThrowFn(CGM), args); -} - -static llvm::Constant *getItaniumDynamicCastFn(CodeGenFunction &CGF) { - // void *__dynamic_cast(const void *sub, - // const abi::__class_type_info *src, - // const abi::__class_type_info *dst, - // std::ptrdiff_t src2dst_offset); - - llvm::Type *Int8PtrTy = CGF.Int8PtrTy; - llvm::Type *PtrDiffTy = - CGF.ConvertType(CGF.getContext().getPointerDiffType()); - - llvm::Type *Args[4] = { Int8PtrTy, Int8PtrTy, Int8PtrTy, PtrDiffTy }; - - llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false); - - // Mark the function as nounwind readonly. - llvm::Attribute::AttrKind FuncAttrs[] = { llvm::Attribute::NoUnwind, - llvm::Attribute::ReadOnly }; - llvm::AttributeList Attrs = llvm::AttributeList::get( - CGF.getLLVMContext(), llvm::AttributeList::FunctionIndex, FuncAttrs); - - return CGF.CGM.CreateRuntimeFunction(FTy, "__dynamic_cast", Attrs); -} - -static llvm::Constant *getBadCastFn(CodeGenFunction &CGF) { - // void __cxa_bad_cast(); - llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false); - return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_cast"); -} - -/// Compute the src2dst_offset hint as described in the -/// Itanium C++ ABI [2.9.7] -static CharUnits computeOffsetHint(ASTContext &Context, - const CXXRecordDecl *Src, - const CXXRecordDecl *Dst) { - CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, - /*DetectVirtual=*/false); - - // If Dst is not derived from Src we can skip the whole computation below and - // return that Src is not a public base of Dst. Record all inheritance paths. - if (!Dst->isDerivedFrom(Src, Paths)) - return CharUnits::fromQuantity(-2ULL); - - unsigned NumPublicPaths = 0; - CharUnits Offset; - - // Now walk all possible inheritance paths. - for (const CXXBasePath &Path : Paths) { - if (Path.Access != AS_public) // Ignore non-public inheritance. - continue; - - ++NumPublicPaths; - - for (const CXXBasePathElement &PathElement : Path) { - // If the path contains a virtual base class we can't give any hint. - // -1: no hint. - if (PathElement.Base->isVirtual()) - return CharUnits::fromQuantity(-1ULL); - - if (NumPublicPaths > 1) // Won't use offsets, skip computation. - continue; - - // Accumulate the base class offsets. - const ASTRecordLayout &L = Context.getASTRecordLayout(PathElement.Class); - Offset += L.getBaseClassOffset( - PathElement.Base->getType()->getAsCXXRecordDecl()); - } - } - - // -2: Src is not a public base of Dst. - if (NumPublicPaths == 0) - return CharUnits::fromQuantity(-2ULL); - - // -3: Src is a multiple public base type but never a virtual base type. - if (NumPublicPaths > 1) - return CharUnits::fromQuantity(-3ULL); - - // Otherwise, the Src type is a unique public nonvirtual base type of Dst. - // Return the offset of Src from the origin of Dst. - return Offset; -} - -static llvm::Constant *getBadTypeidFn(CodeGenFunction &CGF) { - // void __cxa_bad_typeid(); - llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false); - - return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid"); -} - -bool ItaniumCXXABI::shouldTypeidBeNullChecked(bool IsDeref, - QualType SrcRecordTy) { - return IsDeref; -} - -void ItaniumCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) { - llvm::Value *Fn = getBadTypeidFn(CGF); - CGF.EmitRuntimeCallOrInvoke(Fn).setDoesNotReturn(); - CGF.Builder.CreateUnreachable(); -} - -llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF, - QualType SrcRecordTy, - Address ThisPtr, - llvm::Type *StdTypeInfoPtrTy) { - auto *ClassDecl = - cast<CXXRecordDecl>(SrcRecordTy->getAs<RecordType>()->getDecl()); - llvm::Value *Value = - CGF.GetVTablePtr(ThisPtr, StdTypeInfoPtrTy->getPointerTo(), ClassDecl); - - // Load the type info. - Value = CGF.Builder.CreateConstInBoundsGEP1_64(Value, -1ULL); - return CGF.Builder.CreateAlignedLoad(Value, CGF.getPointerAlign()); -} - -bool ItaniumCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr, - QualType SrcRecordTy) { - return SrcIsPtr; -} - -llvm::Value *ItaniumCXXABI::EmitDynamicCastCall( - CodeGenFunction &CGF, Address ThisAddr, QualType SrcRecordTy, - QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd) { - llvm::Type *PtrDiffLTy = - CGF.ConvertType(CGF.getContext().getPointerDiffType()); - llvm::Type *DestLTy = CGF.ConvertType(DestTy); - - llvm::Value *SrcRTTI = - CGF.CGM.GetAddrOfRTTIDescriptor(SrcRecordTy.getUnqualifiedType()); - llvm::Value *DestRTTI = - CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType()); - - // Compute the offset hint. - const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl(); - const CXXRecordDecl *DestDecl = DestRecordTy->getAsCXXRecordDecl(); - llvm::Value *OffsetHint = llvm::ConstantInt::get( - PtrDiffLTy, - computeOffsetHint(CGF.getContext(), SrcDecl, DestDecl).getQuantity()); - - // Emit the call to __dynamic_cast. - llvm::Value *Value = ThisAddr.getPointer(); - Value = CGF.EmitCastToVoidPtr(Value); - - llvm::Value *args[] = {Value, SrcRTTI, DestRTTI, OffsetHint}; - Value = CGF.EmitNounwindRuntimeCall(getItaniumDynamicCastFn(CGF), args); - Value = CGF.Builder.CreateBitCast(Value, DestLTy); - - /// C++ [expr.dynamic.cast]p9: - /// A failed cast to reference type throws std::bad_cast - if (DestTy->isReferenceType()) { - llvm::BasicBlock *BadCastBlock = - CGF.createBasicBlock("dynamic_cast.bad_cast"); - - llvm::Value *IsNull = CGF.Builder.CreateIsNull(Value); - CGF.Builder.CreateCondBr(IsNull, BadCastBlock, CastEnd); - - CGF.EmitBlock(BadCastBlock); - EmitBadCastCall(CGF); - } - - return Value; -} - -llvm::Value *ItaniumCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF, - Address ThisAddr, - QualType SrcRecordTy, - QualType DestTy) { - llvm::Type *PtrDiffLTy = - CGF.ConvertType(CGF.getContext().getPointerDiffType()); - llvm::Type *DestLTy = CGF.ConvertType(DestTy); - - auto *ClassDecl = - cast<CXXRecordDecl>(SrcRecordTy->getAs<RecordType>()->getDecl()); - // Get the vtable pointer. - llvm::Value *VTable = CGF.GetVTablePtr(ThisAddr, PtrDiffLTy->getPointerTo(), - ClassDecl); - - // Get the offset-to-top from the vtable. - llvm::Value *OffsetToTop = - CGF.Builder.CreateConstInBoundsGEP1_64(VTable, -2ULL); - OffsetToTop = - CGF.Builder.CreateAlignedLoad(OffsetToTop, CGF.getPointerAlign(), - "offset.to.top"); - - // Finally, add the offset to the pointer. - llvm::Value *Value = ThisAddr.getPointer(); - Value = CGF.EmitCastToVoidPtr(Value); - Value = CGF.Builder.CreateInBoundsGEP(Value, OffsetToTop); - - return CGF.Builder.CreateBitCast(Value, DestLTy); -} - -bool ItaniumCXXABI::EmitBadCastCall(CodeGenFunction &CGF) { - llvm::Value *Fn = getBadCastFn(CGF); - CGF.EmitRuntimeCallOrInvoke(Fn).setDoesNotReturn(); - CGF.Builder.CreateUnreachable(); - return true; -} - -llvm::Value * -ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF, - Address This, - const CXXRecordDecl *ClassDecl, - const CXXRecordDecl *BaseClassDecl) { - llvm::Value *VTablePtr = CGF.GetVTablePtr(This, CGM.Int8PtrTy, ClassDecl); - CharUnits VBaseOffsetOffset = - CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl, - BaseClassDecl); - - llvm::Value *VBaseOffsetPtr = - CGF.Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetOffset.getQuantity(), - "vbase.offset.ptr"); - VBaseOffsetPtr = CGF.Builder.CreateBitCast(VBaseOffsetPtr, - CGM.PtrDiffTy->getPointerTo()); - - llvm::Value *VBaseOffset = - CGF.Builder.CreateAlignedLoad(VBaseOffsetPtr, CGF.getPointerAlign(), - "vbase.offset"); - - return VBaseOffset; -} - -void ItaniumCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) { - // Just make sure we're in sync with TargetCXXABI. - assert(CGM.getTarget().getCXXABI().hasConstructorVariants()); - - // The constructor used for constructing this as a base class; - // ignores virtual bases. - CGM.EmitGlobal(GlobalDecl(D, Ctor_Base)); - - // The constructor used for constructing this as a complete class; - // constructs the virtual bases, then calls the base constructor. - if (!D->getParent()->isAbstract()) { - // We don't need to emit the complete ctor if the class is abstract. - CGM.EmitGlobal(GlobalDecl(D, Ctor_Complete)); - } -} - -CGCXXABI::AddedStructorArgs -ItaniumCXXABI::buildStructorSignature(const CXXMethodDecl *MD, StructorType T, - SmallVectorImpl<CanQualType> &ArgTys) { - ASTContext &Context = getContext(); - - // All parameters are already in place except VTT, which goes after 'this'. - // These are Clang types, so we don't need to worry about sret yet. - - // Check if we need to add a VTT parameter (which has type void **). - if (T == StructorType::Base && MD->getParent()->getNumVBases() != 0) { - ArgTys.insert(ArgTys.begin() + 1, - Context.getPointerType(Context.VoidPtrTy)); - return AddedStructorArgs::prefix(1); - } - return AddedStructorArgs{}; -} - -void ItaniumCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) { - // The destructor used for destructing this as a base class; ignores - // virtual bases. - CGM.EmitGlobal(GlobalDecl(D, Dtor_Base)); - - // The destructor used for destructing this as a most-derived class; - // call the base destructor and then destructs any virtual bases. - CGM.EmitGlobal(GlobalDecl(D, Dtor_Complete)); - - // The destructor in a virtual table is always a 'deleting' - // destructor, which calls the complete destructor and then uses the - // appropriate operator delete. - if (D->isVirtual()) - CGM.EmitGlobal(GlobalDecl(D, Dtor_Deleting)); -} - -void ItaniumCXXABI::addImplicitStructorParams(CodeGenFunction &CGF, - QualType &ResTy, - FunctionArgList &Params) { - const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); - assert(isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)); - - // Check if we need a VTT parameter as well. - if (NeedsVTTParameter(CGF.CurGD)) { - ASTContext &Context = getContext(); - - // FIXME: avoid the fake decl - QualType T = Context.getPointerType(Context.VoidPtrTy); - auto *VTTDecl = ImplicitParamDecl::Create( - Context, /*DC=*/nullptr, MD->getLocation(), &Context.Idents.get("vtt"), - T, ImplicitParamDecl::CXXVTT); - Params.insert(Params.begin() + 1, VTTDecl); - getStructorImplicitParamDecl(CGF) = VTTDecl; - } -} - -void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { - // Naked functions have no prolog. - if (CGF.CurFuncDecl && CGF.CurFuncDecl->hasAttr<NakedAttr>()) - return; - - /// Initialize the 'this' slot. In the Itanium C++ ABI, no prologue - /// adjustments are required, because they are all handled by thunks. - setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF)); - - /// Initialize the 'vtt' slot if needed. - if (getStructorImplicitParamDecl(CGF)) { - getStructorImplicitParamValue(CGF) = CGF.Builder.CreateLoad( - CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)), "vtt"); - } - - /// If this is a function that the ABI specifies returns 'this', initialize - /// the return slot to 'this' at the start of the function. - /// - /// Unlike the setting of return types, this is done within the ABI - /// implementation instead of by clients of CGCXXABI because: - /// 1) getThisValue is currently protected - /// 2) in theory, an ABI could implement 'this' returns some other way; - /// HasThisReturn only specifies a contract, not the implementation - if (HasThisReturn(CGF.CurGD)) - CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue); -} - -CGCXXABI::AddedStructorArgs ItaniumCXXABI::addImplicitConstructorArgs( - CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type, - bool ForVirtualBase, bool Delegating, CallArgList &Args) { - if (!NeedsVTTParameter(GlobalDecl(D, Type))) - return AddedStructorArgs{}; - - // Insert the implicit 'vtt' argument as the second argument. - llvm::Value *VTT = - CGF.GetVTTParameter(GlobalDecl(D, Type), ForVirtualBase, Delegating); - QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy); - Args.insert(Args.begin() + 1, CallArg(RValue::get(VTT), VTTTy)); - return AddedStructorArgs::prefix(1); // Added one arg. -} - -void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF, - const CXXDestructorDecl *DD, - CXXDtorType Type, bool ForVirtualBase, - bool Delegating, Address This) { - GlobalDecl GD(DD, Type); - llvm::Value *VTT = CGF.GetVTTParameter(GD, ForVirtualBase, Delegating); - QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy); - - CGCallee Callee; - if (getContext().getLangOpts().AppleKext && - Type != Dtor_Base && DD->isVirtual()) - Callee = CGF.BuildAppleKextVirtualDestructorCall(DD, Type, DD->getParent()); - else - Callee = CGCallee::forDirect( - CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)), GD); - - CGF.EmitCXXMemberOrOperatorCall(DD, Callee, ReturnValueSlot(), - This.getPointer(), VTT, VTTTy, - nullptr, nullptr); -} - -void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, - const CXXRecordDecl *RD) { - llvm::GlobalVariable *VTable = getAddrOfVTable(RD, CharUnits()); - if (VTable->hasInitializer()) - return; - - ItaniumVTableContext &VTContext = CGM.getItaniumVTableContext(); - const VTableLayout &VTLayout = VTContext.getVTableLayout(RD); - llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD); - llvm::Constant *RTTI = - CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getTagDeclType(RD)); - - // Create and set the initializer. - ConstantInitBuilder Builder(CGM); - auto Components = Builder.beginStruct(); - CGVT.createVTableInitializer(Components, VTLayout, RTTI); - Components.finishAndSetAsInitializer(VTable); - - // Set the correct linkage. - VTable->setLinkage(Linkage); - - if (CGM.supportsCOMDAT() && VTable->isWeakForLinker()) - VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName())); - - // Set the right visibility. - CGM.setGVProperties(VTable, RD); - - // If this is the magic class __cxxabiv1::__fundamental_type_info, - // we will emit the typeinfo for the fundamental types. This is the - // same behaviour as GCC. - const DeclContext *DC = RD->getDeclContext(); - if (RD->getIdentifier() && - RD->getIdentifier()->isStr("__fundamental_type_info") && - isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() && - cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") && - DC->getParent()->isTranslationUnit()) - EmitFundamentalRTTIDescriptors(RD); - - if (!VTable->isDeclarationForLinker()) - CGM.EmitVTableTypeMetadata(VTable, VTLayout); -} - -bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField( - CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr) { - if (Vptr.NearestVBase == nullptr) - return false; - return NeedsVTTParameter(CGF.CurGD); -} - -llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor( - CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, - const CXXRecordDecl *NearestVBase) { - - if ((Base.getBase()->getNumVBases() || NearestVBase != nullptr) && - NeedsVTTParameter(CGF.CurGD)) { - return getVTableAddressPointInStructorWithVTT(CGF, VTableClass, Base, - NearestVBase); - } - return getVTableAddressPoint(Base, VTableClass); -} - -llvm::Constant * -ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base, - const CXXRecordDecl *VTableClass) { - llvm::GlobalValue *VTable = getAddrOfVTable(VTableClass, CharUnits()); - - // Find the appropriate vtable within the vtable group, and the address point - // within that vtable. - VTableLayout::AddressPointLocation AddressPoint = - CGM.getItaniumVTableContext() - .getVTableLayout(VTableClass) - .getAddressPoint(Base); - llvm::Value *Indices[] = { - llvm::ConstantInt::get(CGM.Int32Ty, 0), - llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.VTableIndex), - llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.AddressPointIndex), - }; - - return llvm::ConstantExpr::getGetElementPtr(VTable->getValueType(), VTable, - Indices, /*InBounds=*/true, - /*InRangeIndex=*/1); -} - -llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT( - CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, - const CXXRecordDecl *NearestVBase) { - assert((Base.getBase()->getNumVBases() || NearestVBase != nullptr) && - NeedsVTTParameter(CGF.CurGD) && "This class doesn't have VTT"); - - // Get the secondary vpointer index. - uint64_t VirtualPointerIndex = - CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass, Base); - - /// Load the VTT. - llvm::Value *VTT = CGF.LoadCXXVTT(); - if (VirtualPointerIndex) - VTT = CGF.Builder.CreateConstInBoundsGEP1_64(VTT, VirtualPointerIndex); - - // And load the address point from the VTT. - return CGF.Builder.CreateAlignedLoad(VTT, CGF.getPointerAlign()); -} - -llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr( - BaseSubobject Base, const CXXRecordDecl *VTableClass) { - return getVTableAddressPoint(Base, VTableClass); -} - -llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, - CharUnits VPtrOffset) { - assert(VPtrOffset.isZero() && "Itanium ABI only supports zero vptr offsets"); - - llvm::GlobalVariable *&VTable = VTables[RD]; - if (VTable) - return VTable; - - // Queue up this vtable for possible deferred emission. - CGM.addDeferredVTable(RD); - - SmallString<256> Name; - llvm::raw_svector_ostream Out(Name); - getMangleContext().mangleCXXVTable(RD, Out); - - const VTableLayout &VTLayout = - CGM.getItaniumVTableContext().getVTableLayout(RD); - llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout); - - // Use pointer alignment for the vtable. Otherwise we would align them based - // on the size of the initializer which doesn't make sense as only single - // values are read. - unsigned PAlign = CGM.getTarget().getPointerAlign(0); - - VTable = CGM.CreateOrReplaceCXXRuntimeVariable( - Name, VTableType, llvm::GlobalValue::ExternalLinkage, - getContext().toCharUnitsFromBits(PAlign).getQuantity()); - VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - - CGM.setGVProperties(VTable, RD); - - return VTable; -} - -CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, - GlobalDecl GD, - Address This, - llvm::Type *Ty, - SourceLocation Loc) { - Ty = Ty->getPointerTo()->getPointerTo(); - auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl()); - llvm::Value *VTable = CGF.GetVTablePtr(This, Ty, MethodDecl->getParent()); - - uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD); - llvm::Value *VFunc; - if (CGF.ShouldEmitVTableTypeCheckedLoad(MethodDecl->getParent())) { - VFunc = CGF.EmitVTableTypeCheckedLoad( - MethodDecl->getParent(), VTable, - VTableIndex * CGM.getContext().getTargetInfo().getPointerWidth(0) / 8); - } else { - CGF.EmitTypeMetadataCodeForVCall(MethodDecl->getParent(), VTable, Loc); - - llvm::Value *VFuncPtr = - CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn"); - auto *VFuncLoad = - CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign()); - - // Add !invariant.load md to virtual function load to indicate that - // function didn't change inside vtable. - // It's safe to add it without -fstrict-vtable-pointers, but it would not - // help in devirtualization because it will only matter if we will have 2 - // the same virtual function loads from the same vtable load, which won't - // happen without enabled devirtualization with -fstrict-vtable-pointers. - if (CGM.getCodeGenOpts().OptimizationLevel > 0 && - CGM.getCodeGenOpts().StrictVTablePointers) - VFuncLoad->setMetadata( - llvm::LLVMContext::MD_invariant_load, - llvm::MDNode::get(CGM.getLLVMContext(), - llvm::ArrayRef<llvm::Metadata *>())); - VFunc = VFuncLoad; - } - - CGCallee Callee(GD, VFunc); - return Callee; -} - -llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall( - CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, - Address This, const CXXMemberCallExpr *CE) { - assert(CE == nullptr || CE->arg_begin() == CE->arg_end()); - assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete); - - const CGFunctionInfo *FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration( - Dtor, getFromDtorType(DtorType)); - llvm::FunctionType *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo); - CGCallee Callee = - CGCallee::forVirtual(CE, GlobalDecl(Dtor, DtorType), This, Ty); - - CGF.EmitCXXMemberOrOperatorCall(Dtor, Callee, ReturnValueSlot(), - This.getPointer(), /*ImplicitParam=*/nullptr, - QualType(), CE, nullptr); - return nullptr; -} - -void ItaniumCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) { - CodeGenVTables &VTables = CGM.getVTables(); - llvm::GlobalVariable *VTT = VTables.GetAddrOfVTT(RD); - VTables.EmitVTTDefinition(VTT, CGM.getVTableLinkage(RD), RD); -} - -bool ItaniumCXXABI::canSpeculativelyEmitVTableAsBaseClass( - const CXXRecordDecl *RD) const { - // We don't emit available_externally vtables if we are in -fapple-kext mode - // because kext mode does not permit devirtualization. - if (CGM.getLangOpts().AppleKext) - return false; - - // If the vtable is hidden then it is not safe to emit an available_externally - // copy of vtable. - if (isVTableHidden(RD)) - return false; - - if (CGM.getCodeGenOpts().ForceEmitVTables) - return true; - - // If we don't have any not emitted inline virtual function then we are safe - // to emit an available_externally copy of vtable. - // FIXME we can still emit a copy of the vtable if we - // can emit definition of the inline functions. - if (hasAnyUnusedVirtualInlineFunction(RD)) - return false; - - // For a class with virtual bases, we must also be able to speculatively - // emit the VTT, because CodeGen doesn't have separate notions of "can emit - // the vtable" and "can emit the VTT". For a base subobject, this means we - // need to be able to emit non-virtual base vtables. - if (RD->getNumVBases()) { - for (const auto &B : RD->bases()) { - auto *BRD = B.getType()->getAsCXXRecordDecl(); - assert(BRD && "no class for base specifier"); - if (B.isVirtual() || !BRD->isDynamicClass()) - continue; - if (!canSpeculativelyEmitVTableAsBaseClass(BRD)) - return false; - } - } - - return true; -} - -bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const { - if (!canSpeculativelyEmitVTableAsBaseClass(RD)) - return false; - - // For a complete-object vtable (or more specifically, for the VTT), we need - // to be able to speculatively emit the vtables of all dynamic virtual bases. - for (const auto &B : RD->vbases()) { - auto *BRD = B.getType()->getAsCXXRecordDecl(); - assert(BRD && "no class for base specifier"); - if (!BRD->isDynamicClass()) - continue; - if (!canSpeculativelyEmitVTableAsBaseClass(BRD)) - return false; - } - - return true; -} -static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF, - Address InitialPtr, - int64_t NonVirtualAdjustment, - int64_t VirtualAdjustment, - bool IsReturnAdjustment) { - if (!NonVirtualAdjustment && !VirtualAdjustment) - return InitialPtr.getPointer(); - - Address V = CGF.Builder.CreateElementBitCast(InitialPtr, CGF.Int8Ty); - - // In a base-to-derived cast, the non-virtual adjustment is applied first. - if (NonVirtualAdjustment && !IsReturnAdjustment) { - V = CGF.Builder.CreateConstInBoundsByteGEP(V, - CharUnits::fromQuantity(NonVirtualAdjustment)); - } - - // Perform the virtual adjustment if we have one. - llvm::Value *ResultPtr; - if (VirtualAdjustment) { - llvm::Type *PtrDiffTy = - CGF.ConvertType(CGF.getContext().getPointerDiffType()); - - Address VTablePtrPtr = CGF.Builder.CreateElementBitCast(V, CGF.Int8PtrTy); - llvm::Value *VTablePtr = CGF.Builder.CreateLoad(VTablePtrPtr); - - llvm::Value *OffsetPtr = - CGF.Builder.CreateConstInBoundsGEP1_64(VTablePtr, VirtualAdjustment); - - OffsetPtr = CGF.Builder.CreateBitCast(OffsetPtr, PtrDiffTy->getPointerTo()); - - // Load the adjustment offset from the vtable. - llvm::Value *Offset = - CGF.Builder.CreateAlignedLoad(OffsetPtr, CGF.getPointerAlign()); - - // Adjust our pointer. - ResultPtr = CGF.Builder.CreateInBoundsGEP(V.getPointer(), Offset); - } else { - ResultPtr = V.getPointer(); - } - - // In a derived-to-base conversion, the non-virtual adjustment is - // applied second. - if (NonVirtualAdjustment && IsReturnAdjustment) { - ResultPtr = CGF.Builder.CreateConstInBoundsGEP1_64(ResultPtr, - NonVirtualAdjustment); - } - - // Cast back to the original type. - return CGF.Builder.CreateBitCast(ResultPtr, InitialPtr.getType()); -} - -llvm::Value *ItaniumCXXABI::performThisAdjustment(CodeGenFunction &CGF, - Address This, - const ThisAdjustment &TA) { - return performTypeAdjustment(CGF, This, TA.NonVirtual, - TA.Virtual.Itanium.VCallOffsetOffset, - /*IsReturnAdjustment=*/false); -} - -llvm::Value * -ItaniumCXXABI::performReturnAdjustment(CodeGenFunction &CGF, Address Ret, - const ReturnAdjustment &RA) { - return performTypeAdjustment(CGF, Ret, RA.NonVirtual, - RA.Virtual.Itanium.VBaseOffsetOffset, - /*IsReturnAdjustment=*/true); -} - -void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, - RValue RV, QualType ResultType) { - if (!isa<CXXDestructorDecl>(CGF.CurGD.getDecl())) - return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType); - - // Destructor thunks in the ARM ABI have indeterminate results. - llvm::Type *T = CGF.ReturnValue.getElementType(); - RValue Undef = RValue::get(llvm::UndefValue::get(T)); - return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType); -} - -/************************** Array allocation cookies **************************/ - -CharUnits ItaniumCXXABI::getArrayCookieSizeImpl(QualType elementType) { - // The array cookie is a size_t; pad that up to the element alignment. - // The cookie is actually right-justified in that space. - return std::max(CharUnits::fromQuantity(CGM.SizeSizeInBytes), - CGM.getContext().getTypeAlignInChars(elementType)); -} - -Address ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, - Address NewPtr, - llvm::Value *NumElements, - const CXXNewExpr *expr, - QualType ElementType) { - assert(requiresArrayCookie(expr)); - - unsigned AS = NewPtr.getAddressSpace(); - - ASTContext &Ctx = getContext(); - CharUnits SizeSize = CGF.getSizeSize(); - - // The size of the cookie. - CharUnits CookieSize = - std::max(SizeSize, Ctx.getTypeAlignInChars(ElementType)); - assert(CookieSize == getArrayCookieSizeImpl(ElementType)); - - // Compute an offset to the cookie. - Address CookiePtr = NewPtr; - CharUnits CookieOffset = CookieSize - SizeSize; - if (!CookieOffset.isZero()) - CookiePtr = CGF.Builder.CreateConstInBoundsByteGEP(CookiePtr, CookieOffset); - - // Write the number of elements into the appropriate slot. - Address NumElementsPtr = - CGF.Builder.CreateElementBitCast(CookiePtr, CGF.SizeTy); - llvm::Instruction *SI = CGF.Builder.CreateStore(NumElements, NumElementsPtr); - - // Handle the array cookie specially in ASan. - if (CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) && AS == 0 && - (expr->getOperatorNew()->isReplaceableGlobalAllocationFunction() || - CGM.getCodeGenOpts().SanitizeAddressPoisonCustomArrayCookie)) { - // The store to the CookiePtr does not need to be instrumented. - CGM.getSanitizerMetadata()->disableSanitizerForInstruction(SI); - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, NumElementsPtr.getType(), false); - llvm::Constant *F = - CGM.CreateRuntimeFunction(FTy, "__asan_poison_cxx_array_cookie"); - CGF.Builder.CreateCall(F, NumElementsPtr.getPointer()); - } - - // Finally, compute a pointer to the actual data buffer by skipping - // over the cookie completely. - return CGF.Builder.CreateConstInBoundsByteGEP(NewPtr, CookieSize); -} - -llvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, - Address allocPtr, - CharUnits cookieSize) { - // The element size is right-justified in the cookie. - Address numElementsPtr = allocPtr; - CharUnits numElementsOffset = cookieSize - CGF.getSizeSize(); - if (!numElementsOffset.isZero()) - numElementsPtr = - CGF.Builder.CreateConstInBoundsByteGEP(numElementsPtr, numElementsOffset); - - unsigned AS = allocPtr.getAddressSpace(); - numElementsPtr = CGF.Builder.CreateElementBitCast(numElementsPtr, CGF.SizeTy); - if (!CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) || AS != 0) - return CGF.Builder.CreateLoad(numElementsPtr); - // In asan mode emit a function call instead of a regular load and let the - // run-time deal with it: if the shadow is properly poisoned return the - // cookie, otherwise return 0 to avoid an infinite loop calling DTORs. - // We can't simply ignore this load using nosanitize metadata because - // the metadata may be lost. - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGF.SizeTy, CGF.SizeTy->getPointerTo(0), false); - llvm::Constant *F = - CGM.CreateRuntimeFunction(FTy, "__asan_load_cxx_array_cookie"); - return CGF.Builder.CreateCall(F, numElementsPtr.getPointer()); -} - -CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) { - // ARM says that the cookie is always: - // struct array_cookie { - // std::size_t element_size; // element_size != 0 - // std::size_t element_count; - // }; - // But the base ABI doesn't give anything an alignment greater than - // 8, so we can dismiss this as typical ABI-author blindness to - // actual language complexity and round up to the element alignment. - return std::max(CharUnits::fromQuantity(2 * CGM.SizeSizeInBytes), - CGM.getContext().getTypeAlignInChars(elementType)); -} - -Address ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, - Address newPtr, - llvm::Value *numElements, - const CXXNewExpr *expr, - QualType elementType) { - assert(requiresArrayCookie(expr)); - - // The cookie is always at the start of the buffer. - Address cookie = newPtr; - - // The first element is the element size. - cookie = CGF.Builder.CreateElementBitCast(cookie, CGF.SizeTy); - llvm::Value *elementSize = llvm::ConstantInt::get(CGF.SizeTy, - getContext().getTypeSizeInChars(elementType).getQuantity()); - CGF.Builder.CreateStore(elementSize, cookie); - - // The second element is the element count. - cookie = CGF.Builder.CreateConstInBoundsGEP(cookie, 1, CGF.getSizeSize()); - CGF.Builder.CreateStore(numElements, cookie); - - // Finally, compute a pointer to the actual data buffer by skipping - // over the cookie completely. - CharUnits cookieSize = ARMCXXABI::getArrayCookieSizeImpl(elementType); - return CGF.Builder.CreateConstInBoundsByteGEP(newPtr, cookieSize); -} - -llvm::Value *ARMCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, - Address allocPtr, - CharUnits cookieSize) { - // The number of elements is at offset sizeof(size_t) relative to - // the allocated pointer. - Address numElementsPtr - = CGF.Builder.CreateConstInBoundsByteGEP(allocPtr, CGF.getSizeSize()); - - numElementsPtr = CGF.Builder.CreateElementBitCast(numElementsPtr, CGF.SizeTy); - return CGF.Builder.CreateLoad(numElementsPtr); -} - -/*********************** Static local initialization **************************/ - -static llvm::Constant *getGuardAcquireFn(CodeGenModule &CGM, - llvm::PointerType *GuardPtrTy) { - // int __cxa_guard_acquire(__guard *guard_object); - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.getTypes().ConvertType(CGM.getContext().IntTy), - GuardPtrTy, /*isVarArg=*/false); - return CGM.CreateRuntimeFunction( - FTy, "__cxa_guard_acquire", - llvm::AttributeList::get(CGM.getLLVMContext(), - llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind)); -} - -static llvm::Constant *getGuardReleaseFn(CodeGenModule &CGM, - llvm::PointerType *GuardPtrTy) { - // void __cxa_guard_release(__guard *guard_object); - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, /*isVarArg=*/false); - return CGM.CreateRuntimeFunction( - FTy, "__cxa_guard_release", - llvm::AttributeList::get(CGM.getLLVMContext(), - llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind)); -} - -static llvm::Constant *getGuardAbortFn(CodeGenModule &CGM, - llvm::PointerType *GuardPtrTy) { - // void __cxa_guard_abort(__guard *guard_object); - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, /*isVarArg=*/false); - return CGM.CreateRuntimeFunction( - FTy, "__cxa_guard_abort", - llvm::AttributeList::get(CGM.getLLVMContext(), - llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind)); -} - -namespace { - struct CallGuardAbort final : EHScopeStack::Cleanup { - llvm::GlobalVariable *Guard; - CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - CGF.EmitNounwindRuntimeCall(getGuardAbortFn(CGF.CGM, Guard->getType()), - Guard); - } - }; -} - -/// The ARM code here follows the Itanium code closely enough that we -/// just special-case it at particular places. -void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, - const VarDecl &D, - llvm::GlobalVariable *var, - bool shouldPerformInit) { - CGBuilderTy &Builder = CGF.Builder; - - // Inline variables that weren't instantiated from variable templates have - // partially-ordered initialization within their translation unit. - bool NonTemplateInline = - D.isInline() && - !isTemplateInstantiation(D.getTemplateSpecializationKind()); - - // We only need to use thread-safe statics for local non-TLS variables and - // inline variables; other global initialization is always single-threaded - // or (through lazy dynamic loading in multiple threads) unsequenced. - bool threadsafe = getContext().getLangOpts().ThreadsafeStatics && - (D.isLocalVarDecl() || NonTemplateInline) && - !D.getTLSKind(); - - // If we have a global variable with internal linkage and thread-safe statics - // are disabled, we can just let the guard variable be of type i8. - bool useInt8GuardVariable = !threadsafe && var->hasInternalLinkage(); - - llvm::IntegerType *guardTy; - CharUnits guardAlignment; - if (useInt8GuardVariable) { - guardTy = CGF.Int8Ty; - guardAlignment = CharUnits::One(); - } else { - // Guard variables are 64 bits in the generic ABI and size width on ARM - // (i.e. 32-bit on AArch32, 64-bit on AArch64). - if (UseARMGuardVarABI) { - guardTy = CGF.SizeTy; - guardAlignment = CGF.getSizeAlign(); - } else { - guardTy = CGF.Int64Ty; - guardAlignment = CharUnits::fromQuantity( - CGM.getDataLayout().getABITypeAlignment(guardTy)); - } - } - llvm::PointerType *guardPtrTy = guardTy->getPointerTo(); - - // Create the guard variable if we don't already have it (as we - // might if we're double-emitting this function body). - llvm::GlobalVariable *guard = CGM.getStaticLocalDeclGuardAddress(&D); - if (!guard) { - // Mangle the name for the guard. - SmallString<256> guardName; - { - llvm::raw_svector_ostream out(guardName); - getMangleContext().mangleStaticGuardVariable(&D, out); - } - - // Create the guard variable with a zero-initializer. - // Just absorb linkage and visibility from the guarded variable. - guard = new llvm::GlobalVariable(CGM.getModule(), guardTy, - false, var->getLinkage(), - llvm::ConstantInt::get(guardTy, 0), - guardName.str()); - guard->setDSOLocal(var->isDSOLocal()); - guard->setVisibility(var->getVisibility()); - // If the variable is thread-local, so is its guard variable. - guard->setThreadLocalMode(var->getThreadLocalMode()); - guard->setAlignment(guardAlignment.getQuantity()); - - // The ABI says: "It is suggested that it be emitted in the same COMDAT - // group as the associated data object." In practice, this doesn't work for - // non-ELF and non-Wasm object formats, so only do it for ELF and Wasm. - llvm::Comdat *C = var->getComdat(); - if (!D.isLocalVarDecl() && C && - (CGM.getTarget().getTriple().isOSBinFormatELF() || - CGM.getTarget().getTriple().isOSBinFormatWasm())) { - guard->setComdat(C); - // An inline variable's guard function is run from the per-TU - // initialization function, not via a dedicated global ctor function, so - // we can't put it in a comdat. - if (!NonTemplateInline) - CGF.CurFn->setComdat(C); - } else if (CGM.supportsCOMDAT() && guard->isWeakForLinker()) { - guard->setComdat(CGM.getModule().getOrInsertComdat(guard->getName())); - } - - CGM.setStaticLocalDeclGuardAddress(&D, guard); - } - - Address guardAddr = Address(guard, guardAlignment); - - // Test whether the variable has completed initialization. - // - // Itanium C++ ABI 3.3.2: - // The following is pseudo-code showing how these functions can be used: - // if (obj_guard.first_byte == 0) { - // if ( __cxa_guard_acquire (&obj_guard) ) { - // try { - // ... initialize the object ...; - // } catch (...) { - // __cxa_guard_abort (&obj_guard); - // throw; - // } - // ... queue object destructor with __cxa_atexit() ...; - // __cxa_guard_release (&obj_guard); - // } - // } - - // Load the first byte of the guard variable. - llvm::LoadInst *LI = - Builder.CreateLoad(Builder.CreateElementBitCast(guardAddr, CGM.Int8Ty)); - - // Itanium ABI: - // An implementation supporting thread-safety on multiprocessor - // systems must also guarantee that references to the initialized - // object do not occur before the load of the initialization flag. - // - // In LLVM, we do this by marking the load Acquire. - if (threadsafe) - LI->setAtomic(llvm::AtomicOrdering::Acquire); - - // For ARM, we should only check the first bit, rather than the entire byte: - // - // ARM C++ ABI 3.2.3.1: - // To support the potential use of initialization guard variables - // as semaphores that are the target of ARM SWP and LDREX/STREX - // synchronizing instructions we define a static initialization - // guard variable to be a 4-byte aligned, 4-byte word with the - // following inline access protocol. - // #define INITIALIZED 1 - // if ((obj_guard & INITIALIZED) != INITIALIZED) { - // if (__cxa_guard_acquire(&obj_guard)) - // ... - // } - // - // and similarly for ARM64: - // - // ARM64 C++ ABI 3.2.2: - // This ABI instead only specifies the value bit 0 of the static guard - // variable; all other bits are platform defined. Bit 0 shall be 0 when the - // variable is not initialized and 1 when it is. - llvm::Value *V = - (UseARMGuardVarABI && !useInt8GuardVariable) - ? Builder.CreateAnd(LI, llvm::ConstantInt::get(CGM.Int8Ty, 1)) - : LI; - llvm::Value *NeedsInit = Builder.CreateIsNull(V, "guard.uninitialized"); - - llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check"); - llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end"); - - // Check if the first byte of the guard variable is zero. - CGF.EmitCXXGuardedInitBranch(NeedsInit, InitCheckBlock, EndBlock, - CodeGenFunction::GuardKind::VariableGuard, &D); - - CGF.EmitBlock(InitCheckBlock); - - // Variables used when coping with thread-safe statics and exceptions. - if (threadsafe) { - // Call __cxa_guard_acquire. - llvm::Value *V - = CGF.EmitNounwindRuntimeCall(getGuardAcquireFn(CGM, guardPtrTy), guard); - - llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init"); - - Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"), - InitBlock, EndBlock); - - // Call __cxa_guard_abort along the exceptional edge. - CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, guard); - - CGF.EmitBlock(InitBlock); - } - - // Emit the initializer and add a global destructor if appropriate. - CGF.EmitCXXGlobalVarDeclInit(D, var, shouldPerformInit); - - if (threadsafe) { - // Pop the guard-abort cleanup if we pushed one. - CGF.PopCleanupBlock(); - - // Call __cxa_guard_release. This cannot throw. - CGF.EmitNounwindRuntimeCall(getGuardReleaseFn(CGM, guardPtrTy), - guardAddr.getPointer()); - } else { - Builder.CreateStore(llvm::ConstantInt::get(guardTy, 1), guardAddr); - } - - CGF.EmitBlock(EndBlock); -} - -/// Register a global destructor using __cxa_atexit. -static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF, - llvm::Constant *dtor, - llvm::Constant *addr, - bool TLS) { - const char *Name = "__cxa_atexit"; - if (TLS) { - const llvm::Triple &T = CGF.getTarget().getTriple(); - Name = T.isOSDarwin() ? "_tlv_atexit" : "__cxa_thread_atexit"; - } - - // We're assuming that the destructor function is something we can - // reasonably call with the default CC. Go ahead and cast it to the - // right prototype. - llvm::Type *dtorTy = - llvm::FunctionType::get(CGF.VoidTy, CGF.Int8PtrTy, false)->getPointerTo(); - - // extern "C" int __cxa_atexit(void (*f)(void *), void *p, void *d); - llvm::Type *paramTys[] = { dtorTy, CGF.Int8PtrTy, CGF.Int8PtrTy }; - llvm::FunctionType *atexitTy = - llvm::FunctionType::get(CGF.IntTy, paramTys, false); - - // Fetch the actual function. - llvm::Constant *atexit = CGF.CGM.CreateRuntimeFunction(atexitTy, Name); - if (llvm::Function *fn = dyn_cast<llvm::Function>(atexit)) - fn->setDoesNotThrow(); - - // Create a variable that binds the atexit to this shared object. - llvm::Constant *handle = - CGF.CGM.CreateRuntimeVariable(CGF.Int8Ty, "__dso_handle"); - auto *GV = cast<llvm::GlobalValue>(handle->stripPointerCasts()); - GV->setVisibility(llvm::GlobalValue::HiddenVisibility); - - if (!addr) - // addr is null when we are trying to register a dtor annotated with - // __attribute__((destructor)) in a constructor function. Using null here is - // okay because this argument is just passed back to the destructor - // function. - addr = llvm::Constant::getNullValue(CGF.Int8PtrTy); - - llvm::Value *args[] = { - llvm::ConstantExpr::getBitCast(dtor, dtorTy), - llvm::ConstantExpr::getBitCast(addr, CGF.Int8PtrTy), - handle - }; - CGF.EmitNounwindRuntimeCall(atexit, args); -} - -void CodeGenModule::registerGlobalDtorsWithAtExit() { - for (const auto I : DtorsUsingAtExit) { - int Priority = I.first; - const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second; - - // Create a function that registers destructors that have the same priority. - // - // Since constructor functions are run in non-descending order of their - // priorities, destructors are registered in non-descending order of their - // priorities, and since destructor functions are run in the reverse order - // of their registration, destructor functions are run in non-ascending - // order of their priorities. - CodeGenFunction CGF(*this); - std::string GlobalInitFnName = - std::string("__GLOBAL_init_") + llvm::to_string(Priority); - llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); - llvm::Function *GlobalInitFn = CreateGlobalInitOrDestructFunction( - FTy, GlobalInitFnName, getTypes().arrangeNullaryFunction(), - SourceLocation()); - ASTContext &Ctx = getContext(); - QualType ReturnTy = Ctx.VoidTy; - QualType FunctionTy = Ctx.getFunctionType(ReturnTy, llvm::None, {}); - FunctionDecl *FD = FunctionDecl::Create( - Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), - &Ctx.Idents.get(GlobalInitFnName), FunctionTy, nullptr, SC_Static, - false, false); - CGF.StartFunction(GlobalDecl(FD), ReturnTy, GlobalInitFn, - getTypes().arrangeNullaryFunction(), FunctionArgList(), - SourceLocation(), SourceLocation()); - - for (auto *Dtor : Dtors) { - // Register the destructor function calling __cxa_atexit if it is - // available. Otherwise fall back on calling atexit. - if (getCodeGenOpts().CXAAtExit) - emitGlobalDtorWithCXAAtExit(CGF, Dtor, nullptr, false); - else - CGF.registerGlobalDtorWithAtExit(Dtor); - } - - CGF.FinishFunction(); - AddGlobalCtor(GlobalInitFn, Priority, nullptr); - } -} - -/// Register a global destructor as best as we know how. -void ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF, - const VarDecl &D, - llvm::Constant *dtor, - llvm::Constant *addr) { - if (D.isNoDestroy(CGM.getContext())) - return; - - // Use __cxa_atexit if available. - if (CGM.getCodeGenOpts().CXAAtExit) - return emitGlobalDtorWithCXAAtExit(CGF, dtor, addr, D.getTLSKind()); - - if (D.getTLSKind()) - CGM.ErrorUnsupported(&D, "non-trivial TLS destruction"); - - // In Apple kexts, we want to add a global destructor entry. - // FIXME: shouldn't this be guarded by some variable? - if (CGM.getLangOpts().AppleKext) { - // Generate a global destructor entry. - return CGM.AddCXXDtorEntry(dtor, addr); - } - - CGF.registerGlobalDtorWithAtExit(D, dtor, addr); -} - -static bool isThreadWrapperReplaceable(const VarDecl *VD, - CodeGen::CodeGenModule &CGM) { - assert(!VD->isStaticLocal() && "static local VarDecls don't need wrappers!"); - // Darwin prefers to have references to thread local variables to go through - // the thread wrapper instead of directly referencing the backing variable. - return VD->getTLSKind() == VarDecl::TLS_Dynamic && - CGM.getTarget().getTriple().isOSDarwin(); -} - -/// Get the appropriate linkage for the wrapper function. This is essentially -/// the weak form of the variable's linkage; every translation unit which needs -/// the wrapper emits a copy, and we want the linker to merge them. -static llvm::GlobalValue::LinkageTypes -getThreadLocalWrapperLinkage(const VarDecl *VD, CodeGen::CodeGenModule &CGM) { - llvm::GlobalValue::LinkageTypes VarLinkage = - CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false); - - // For internal linkage variables, we don't need an external or weak wrapper. - if (llvm::GlobalValue::isLocalLinkage(VarLinkage)) - return VarLinkage; - - // If the thread wrapper is replaceable, give it appropriate linkage. - if (isThreadWrapperReplaceable(VD, CGM)) - if (!llvm::GlobalVariable::isLinkOnceLinkage(VarLinkage) && - !llvm::GlobalVariable::isWeakODRLinkage(VarLinkage)) - return VarLinkage; - return llvm::GlobalValue::WeakODRLinkage; -} - -llvm::Function * -ItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD, - llvm::Value *Val) { - // Mangle the name for the thread_local wrapper function. - SmallString<256> WrapperName; - { - llvm::raw_svector_ostream Out(WrapperName); - getMangleContext().mangleItaniumThreadLocalWrapper(VD, Out); - } - - // FIXME: If VD is a definition, we should regenerate the function attributes - // before returning. - if (llvm::Value *V = CGM.getModule().getNamedValue(WrapperName)) - return cast<llvm::Function>(V); - - QualType RetQT = VD->getType(); - if (RetQT->isReferenceType()) - RetQT = RetQT.getNonReferenceType(); - - const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( - getContext().getPointerType(RetQT), FunctionArgList()); - - llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FI); - llvm::Function *Wrapper = - llvm::Function::Create(FnTy, getThreadLocalWrapperLinkage(VD, CGM), - WrapperName.str(), &CGM.getModule()); - - CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Wrapper); - - if (VD->hasDefinition()) - CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Wrapper); - - // Always resolve references to the wrapper at link time. - if (!Wrapper->hasLocalLinkage()) - if (!isThreadWrapperReplaceable(VD, CGM) || - llvm::GlobalVariable::isLinkOnceLinkage(Wrapper->getLinkage()) || - llvm::GlobalVariable::isWeakODRLinkage(Wrapper->getLinkage()) || - VD->getVisibility() == HiddenVisibility) - Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility); - - if (isThreadWrapperReplaceable(VD, CGM)) { - Wrapper->setCallingConv(llvm::CallingConv::CXX_FAST_TLS); - Wrapper->addFnAttr(llvm::Attribute::NoUnwind); - } - return Wrapper; -} - -void ItaniumCXXABI::EmitThreadLocalInitFuncs( - CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals, - ArrayRef<llvm::Function *> CXXThreadLocalInits, - ArrayRef<const VarDecl *> CXXThreadLocalInitVars) { - llvm::Function *InitFunc = nullptr; - - // Separate initializers into those with ordered (or partially-ordered) - // initialization and those with unordered initialization. - llvm::SmallVector<llvm::Function *, 8> OrderedInits; - llvm::SmallDenseMap<const VarDecl *, llvm::Function *> UnorderedInits; - for (unsigned I = 0; I != CXXThreadLocalInits.size(); ++I) { - if (isTemplateInstantiation( - CXXThreadLocalInitVars[I]->getTemplateSpecializationKind())) - UnorderedInits[CXXThreadLocalInitVars[I]->getCanonicalDecl()] = - CXXThreadLocalInits[I]; - else - OrderedInits.push_back(CXXThreadLocalInits[I]); - } - - if (!OrderedInits.empty()) { - // Generate a guarded initialization function. - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); - const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); - InitFunc = CGM.CreateGlobalInitOrDestructFunction(FTy, "__tls_init", FI, - SourceLocation(), - /*TLS=*/true); - llvm::GlobalVariable *Guard = new llvm::GlobalVariable( - CGM.getModule(), CGM.Int8Ty, /*isConstant=*/false, - llvm::GlobalVariable::InternalLinkage, - llvm::ConstantInt::get(CGM.Int8Ty, 0), "__tls_guard"); - Guard->setThreadLocal(true); - - CharUnits GuardAlign = CharUnits::One(); - Guard->setAlignment(GuardAlign.getQuantity()); - - CodeGenFunction(CGM).GenerateCXXGlobalInitFunc( - InitFunc, OrderedInits, ConstantAddress(Guard, GuardAlign)); - // On Darwin platforms, use CXX_FAST_TLS calling convention. - if (CGM.getTarget().getTriple().isOSDarwin()) { - InitFunc->setCallingConv(llvm::CallingConv::CXX_FAST_TLS); - InitFunc->addFnAttr(llvm::Attribute::NoUnwind); - } - } - - // Emit thread wrappers. - for (const VarDecl *VD : CXXThreadLocals) { - llvm::GlobalVariable *Var = - cast<llvm::GlobalVariable>(CGM.GetGlobalValue(CGM.getMangledName(VD))); - llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Var); - - // Some targets require that all access to thread local variables go through - // the thread wrapper. This means that we cannot attempt to create a thread - // wrapper or a thread helper. - if (isThreadWrapperReplaceable(VD, CGM) && !VD->hasDefinition()) { - Wrapper->setLinkage(llvm::Function::ExternalLinkage); - continue; - } - - // Mangle the name for the thread_local initialization function. - SmallString<256> InitFnName; - { - llvm::raw_svector_ostream Out(InitFnName); - getMangleContext().mangleItaniumThreadLocalInit(VD, Out); - } - - // If we have a definition for the variable, emit the initialization - // function as an alias to the global Init function (if any). Otherwise, - // produce a declaration of the initialization function. - llvm::GlobalValue *Init = nullptr; - bool InitIsInitFunc = false; - if (VD->hasDefinition()) { - InitIsInitFunc = true; - llvm::Function *InitFuncToUse = InitFunc; - if (isTemplateInstantiation(VD->getTemplateSpecializationKind())) - InitFuncToUse = UnorderedInits.lookup(VD->getCanonicalDecl()); - if (InitFuncToUse) - Init = llvm::GlobalAlias::create(Var->getLinkage(), InitFnName.str(), - InitFuncToUse); - } else { - // Emit a weak global function referring to the initialization function. - // This function will not exist if the TU defining the thread_local - // variable in question does not need any dynamic initialization for - // its thread_local variables. - llvm::FunctionType *FnTy = llvm::FunctionType::get(CGM.VoidTy, false); - Init = llvm::Function::Create(FnTy, - llvm::GlobalVariable::ExternalWeakLinkage, - InitFnName.str(), &CGM.getModule()); - const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); - CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, - cast<llvm::Function>(Init)); - } - - if (Init) { - Init->setVisibility(Var->getVisibility()); - Init->setDSOLocal(Var->isDSOLocal()); - } - - llvm::LLVMContext &Context = CGM.getModule().getContext(); - llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Wrapper); - CGBuilderTy Builder(CGM, Entry); - if (InitIsInitFunc) { - if (Init) { - llvm::CallInst *CallVal = Builder.CreateCall(Init); - if (isThreadWrapperReplaceable(VD, CGM)) { - CallVal->setCallingConv(llvm::CallingConv::CXX_FAST_TLS); - llvm::Function *Fn = - cast<llvm::Function>(cast<llvm::GlobalAlias>(Init)->getAliasee()); - Fn->setCallingConv(llvm::CallingConv::CXX_FAST_TLS); - } - } - } else { - // Don't know whether we have an init function. Call it if it exists. - llvm::Value *Have = Builder.CreateIsNotNull(Init); - llvm::BasicBlock *InitBB = llvm::BasicBlock::Create(Context, "", Wrapper); - llvm::BasicBlock *ExitBB = llvm::BasicBlock::Create(Context, "", Wrapper); - Builder.CreateCondBr(Have, InitBB, ExitBB); - - Builder.SetInsertPoint(InitBB); - Builder.CreateCall(Init); - Builder.CreateBr(ExitBB); - - Builder.SetInsertPoint(ExitBB); - } - - // For a reference, the result of the wrapper function is a pointer to - // the referenced object. - llvm::Value *Val = Var; - if (VD->getType()->isReferenceType()) { - CharUnits Align = CGM.getContext().getDeclAlign(VD); - Val = Builder.CreateAlignedLoad(Val, Align); - } - if (Val->getType() != Wrapper->getReturnType()) - Val = Builder.CreatePointerBitCastOrAddrSpaceCast( - Val, Wrapper->getReturnType(), ""); - Builder.CreateRet(Val); - } -} - -LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, - const VarDecl *VD, - QualType LValType) { - llvm::Value *Val = CGF.CGM.GetAddrOfGlobalVar(VD); - llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Val); - - llvm::CallInst *CallVal = CGF.Builder.CreateCall(Wrapper); - CallVal->setCallingConv(Wrapper->getCallingConv()); - - LValue LV; - if (VD->getType()->isReferenceType()) - LV = CGF.MakeNaturalAlignAddrLValue(CallVal, LValType); - else - LV = CGF.MakeAddrLValue(CallVal, LValType, - CGF.getContext().getDeclAlign(VD)); - // FIXME: need setObjCGCLValueClass? - return LV; -} - -/// Return whether the given global decl needs a VTT parameter, which it does -/// if it's a base constructor or destructor with virtual bases. -bool ItaniumCXXABI::NeedsVTTParameter(GlobalDecl GD) { - const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); - - // We don't have any virtual bases, just return early. - if (!MD->getParent()->getNumVBases()) - return false; - - // Check if we have a base constructor. - if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base) - return true; - - // Check if we have a base destructor. - if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base) - return true; - - return false; -} - -namespace { -class ItaniumRTTIBuilder { - CodeGenModule &CGM; // Per-module state. - llvm::LLVMContext &VMContext; - const ItaniumCXXABI &CXXABI; // Per-module state. - - /// Fields - The fields of the RTTI descriptor currently being built. - SmallVector<llvm::Constant *, 16> Fields; - - /// GetAddrOfTypeName - Returns the mangled type name of the given type. - llvm::GlobalVariable * - GetAddrOfTypeName(QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage); - - /// GetAddrOfExternalRTTIDescriptor - Returns the constant for the RTTI - /// descriptor of the given type. - llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty); - - /// BuildVTablePointer - Build the vtable pointer for the given type. - void BuildVTablePointer(const Type *Ty); - - /// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single - /// inheritance, according to the Itanium C++ ABI, 2.9.5p6b. - void BuildSIClassTypeInfo(const CXXRecordDecl *RD); - - /// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for - /// classes with bases that do not satisfy the abi::__si_class_type_info - /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c. - void BuildVMIClassTypeInfo(const CXXRecordDecl *RD); - - /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, used - /// for pointer types. - void BuildPointerTypeInfo(QualType PointeeTy); - - /// BuildObjCObjectTypeInfo - Build the appropriate kind of - /// type_info for an object type. - void BuildObjCObjectTypeInfo(const ObjCObjectType *Ty); - - /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info - /// struct, used for member pointer types. - void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty); - -public: - ItaniumRTTIBuilder(const ItaniumCXXABI &ABI) - : CGM(ABI.CGM), VMContext(CGM.getModule().getContext()), CXXABI(ABI) {} - - // Pointer type info flags. - enum { - /// PTI_Const - Type has const qualifier. - PTI_Const = 0x1, - - /// PTI_Volatile - Type has volatile qualifier. - PTI_Volatile = 0x2, - - /// PTI_Restrict - Type has restrict qualifier. - PTI_Restrict = 0x4, - - /// PTI_Incomplete - Type is incomplete. - PTI_Incomplete = 0x8, - - /// PTI_ContainingClassIncomplete - Containing class is incomplete. - /// (in pointer to member). - PTI_ContainingClassIncomplete = 0x10, - - /// PTI_TransactionSafe - Pointee is transaction_safe function (C++ TM TS). - //PTI_TransactionSafe = 0x20, - - /// PTI_Noexcept - Pointee is noexcept function (C++1z). - PTI_Noexcept = 0x40, - }; - - // VMI type info flags. - enum { - /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance. - VMI_NonDiamondRepeat = 0x1, - - /// VMI_DiamondShaped - Class is diamond shaped. - VMI_DiamondShaped = 0x2 - }; - - // Base class type info flags. - enum { - /// BCTI_Virtual - Base class is virtual. - BCTI_Virtual = 0x1, - - /// BCTI_Public - Base class is public. - BCTI_Public = 0x2 - }; - - /// BuildTypeInfo - Build the RTTI type info struct for the given type, or - /// link to an existing RTTI descriptor if one already exists. - llvm::Constant *BuildTypeInfo(QualType Ty); - - /// BuildTypeInfo - Build the RTTI type info struct for the given type. - llvm::Constant *BuildTypeInfo( - QualType Ty, - llvm::GlobalVariable::LinkageTypes Linkage, - llvm::GlobalValue::VisibilityTypes Visibility, - llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass); -}; -} - -llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName( - QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage) { - SmallString<256> Name; - llvm::raw_svector_ostream Out(Name); - CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out); - - // We know that the mangled name of the type starts at index 4 of the - // mangled name of the typename, so we can just index into it in order to - // get the mangled name of the type. - llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext, - Name.substr(4)); - auto Align = CGM.getContext().getTypeAlignInChars(CGM.getContext().CharTy); - - llvm::GlobalVariable *GV = CGM.CreateOrReplaceCXXRuntimeVariable( - Name, Init->getType(), Linkage, Align.getQuantity()); - - GV->setInitializer(Init); - - return GV; -} - -llvm::Constant * -ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) { - // Mangle the RTTI name. - SmallString<256> Name; - llvm::raw_svector_ostream Out(Name); - CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out); - - // Look for an existing global. - llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name); - - if (!GV) { - // Create a new global variable. - // Note for the future: If we would ever like to do deferred emission of - // RTTI, check if emitting vtables opportunistically need any adjustment. - - GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy, - /*Constant=*/true, - llvm::GlobalValue::ExternalLinkage, nullptr, - Name); - const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); - CGM.setGVProperties(GV, RD); - } - - return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy); -} - -/// TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type -/// info for that type is defined in the standard library. -static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) { - // Itanium C++ ABI 2.9.2: - // Basic type information (e.g. for "int", "bool", etc.) will be kept in - // the run-time support library. Specifically, the run-time support - // library should contain type_info objects for the types X, X* and - // X const*, for every X in: void, std::nullptr_t, bool, wchar_t, char, - // unsigned char, signed char, short, unsigned short, int, unsigned int, - // long, unsigned long, long long, unsigned long long, float, double, - // long double, char16_t, char32_t, and the IEEE 754r decimal and - // half-precision floating point types. - // - // GCC also emits RTTI for __int128. - // FIXME: We do not emit RTTI information for decimal types here. - - // Types added here must also be added to EmitFundamentalRTTIDescriptors. - switch (Ty->getKind()) { - case BuiltinType::Void: - case BuiltinType::NullPtr: - case BuiltinType::Bool: - case BuiltinType::WChar_S: - case BuiltinType::WChar_U: - case BuiltinType::Char_U: - case BuiltinType::Char_S: - case BuiltinType::UChar: - case BuiltinType::SChar: - case BuiltinType::Short: - case BuiltinType::UShort: - case BuiltinType::Int: - case BuiltinType::UInt: - case BuiltinType::Long: - case BuiltinType::ULong: - case BuiltinType::LongLong: - case BuiltinType::ULongLong: - case BuiltinType::Half: - case BuiltinType::Float: - case BuiltinType::Double: - case BuiltinType::LongDouble: - case BuiltinType::Float16: - case BuiltinType::Float128: - case BuiltinType::Char8: - case BuiltinType::Char16: - case BuiltinType::Char32: - case BuiltinType::Int128: - case BuiltinType::UInt128: - return true; - -#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ - case BuiltinType::Id: -#include "clang/Basic/OpenCLImageTypes.def" -#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ - case BuiltinType::Id: -#include "clang/Basic/OpenCLExtensionTypes.def" - case BuiltinType::OCLSampler: - case BuiltinType::OCLEvent: - case BuiltinType::OCLClkEvent: - case BuiltinType::OCLQueue: - case BuiltinType::OCLReserveID: - case BuiltinType::ShortAccum: - case BuiltinType::Accum: - case BuiltinType::LongAccum: - case BuiltinType::UShortAccum: - case BuiltinType::UAccum: - case BuiltinType::ULongAccum: - case BuiltinType::ShortFract: - case BuiltinType::Fract: - case BuiltinType::LongFract: - case BuiltinType::UShortFract: - case BuiltinType::UFract: - case BuiltinType::ULongFract: - case BuiltinType::SatShortAccum: - case BuiltinType::SatAccum: - case BuiltinType::SatLongAccum: - case BuiltinType::SatUShortAccum: - case BuiltinType::SatUAccum: - case BuiltinType::SatULongAccum: - case BuiltinType::SatShortFract: - case BuiltinType::SatFract: - case BuiltinType::SatLongFract: - case BuiltinType::SatUShortFract: - case BuiltinType::SatUFract: - case BuiltinType::SatULongFract: - return false; - - case BuiltinType::Dependent: -#define BUILTIN_TYPE(Id, SingletonId) -#define PLACEHOLDER_TYPE(Id, SingletonId) \ - case BuiltinType::Id: -#include "clang/AST/BuiltinTypes.def" - llvm_unreachable("asking for RRTI for a placeholder type!"); - - case BuiltinType::ObjCId: - case BuiltinType::ObjCClass: - case BuiltinType::ObjCSel: - llvm_unreachable("FIXME: Objective-C types are unsupported!"); - } - - llvm_unreachable("Invalid BuiltinType Kind!"); -} - -static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) { - QualType PointeeTy = PointerTy->getPointeeType(); - const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy); - if (!BuiltinTy) - return false; - - // Check the qualifiers. - Qualifiers Quals = PointeeTy.getQualifiers(); - Quals.removeConst(); - - if (!Quals.empty()) - return false; - - return TypeInfoIsInStandardLibrary(BuiltinTy); -} - -/// IsStandardLibraryRTTIDescriptor - Returns whether the type -/// information for the given type exists in the standard library. -static bool IsStandardLibraryRTTIDescriptor(QualType Ty) { - // Type info for builtin types is defined in the standard library. - if (const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty)) - return TypeInfoIsInStandardLibrary(BuiltinTy); - - // Type info for some pointer types to builtin types is defined in the - // standard library. - if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty)) - return TypeInfoIsInStandardLibrary(PointerTy); - - return false; -} - -/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for -/// the given type exists somewhere else, and that we should not emit the type -/// information in this translation unit. Assumes that it is not a -/// standard-library type. -static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, - QualType Ty) { - ASTContext &Context = CGM.getContext(); - - // If RTTI is disabled, assume it might be disabled in the - // translation unit that defines any potential key function, too. - if (!Context.getLangOpts().RTTI) return false; - - if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) { - const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl()); - if (!RD->hasDefinition()) - return false; - - if (!RD->isDynamicClass()) - return false; - - // FIXME: this may need to be reconsidered if the key function - // changes. - // N.B. We must always emit the RTTI data ourselves if there exists a key - // function. - bool IsDLLImport = RD->hasAttr<DLLImportAttr>(); - - // Don't import the RTTI but emit it locally. - if (CGM.getTriple().isWindowsGNUEnvironment() && IsDLLImport) - return false; - - if (CGM.getVTables().isVTableExternal(RD)) - return IsDLLImport && !CGM.getTriple().isWindowsItaniumEnvironment() - ? false - : true; - - if (IsDLLImport) - return true; - } - - return false; -} - -/// IsIncompleteClassType - Returns whether the given record type is incomplete. -static bool IsIncompleteClassType(const RecordType *RecordTy) { - return !RecordTy->getDecl()->isCompleteDefinition(); -} - -/// ContainsIncompleteClassType - Returns whether the given type contains an -/// incomplete class type. This is true if -/// -/// * The given type is an incomplete class type. -/// * The given type is a pointer type whose pointee type contains an -/// incomplete class type. -/// * The given type is a member pointer type whose class is an incomplete -/// class type. -/// * The given type is a member pointer type whoise pointee type contains an -/// incomplete class type. -/// is an indirect or direct pointer to an incomplete class type. -static bool ContainsIncompleteClassType(QualType Ty) { - if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) { - if (IsIncompleteClassType(RecordTy)) - return true; - } - - if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty)) - return ContainsIncompleteClassType(PointerTy->getPointeeType()); - - if (const MemberPointerType *MemberPointerTy = - dyn_cast<MemberPointerType>(Ty)) { - // Check if the class type is incomplete. - const RecordType *ClassType = cast<RecordType>(MemberPointerTy->getClass()); - if (IsIncompleteClassType(ClassType)) - return true; - - return ContainsIncompleteClassType(MemberPointerTy->getPointeeType()); - } - - return false; -} - -// CanUseSingleInheritance - Return whether the given record decl has a "single, -// public, non-virtual base at offset zero (i.e. the derived class is dynamic -// iff the base is)", according to Itanium C++ ABI, 2.95p6b. -static bool CanUseSingleInheritance(const CXXRecordDecl *RD) { - // Check the number of bases. - if (RD->getNumBases() != 1) - return false; - - // Get the base. - CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(); - - // Check that the base is not virtual. - if (Base->isVirtual()) - return false; - - // Check that the base is public. - if (Base->getAccessSpecifier() != AS_public) - return false; - - // Check that the class is dynamic iff the base is. - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - if (!BaseDecl->isEmpty() && - BaseDecl->isDynamicClass() != RD->isDynamicClass()) - return false; - - return true; -} - -void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) { - // abi::__class_type_info. - static const char * const ClassTypeInfo = - "_ZTVN10__cxxabiv117__class_type_infoE"; - // abi::__si_class_type_info. - static const char * const SIClassTypeInfo = - "_ZTVN10__cxxabiv120__si_class_type_infoE"; - // abi::__vmi_class_type_info. - static const char * const VMIClassTypeInfo = - "_ZTVN10__cxxabiv121__vmi_class_type_infoE"; - - const char *VTableName = nullptr; - - switch (Ty->getTypeClass()) { -#define TYPE(Class, Base) -#define ABSTRACT_TYPE(Class, Base) -#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class: -#define NON_CANONICAL_TYPE(Class, Base) case Type::Class: -#define DEPENDENT_TYPE(Class, Base) case Type::Class: -#include "clang/AST/TypeNodes.def" - llvm_unreachable("Non-canonical and dependent types shouldn't get here"); - - case Type::LValueReference: - case Type::RValueReference: - llvm_unreachable("References shouldn't get here"); - - case Type::Auto: - case Type::DeducedTemplateSpecialization: - llvm_unreachable("Undeduced type shouldn't get here"); - - case Type::Pipe: - llvm_unreachable("Pipe types shouldn't get here"); - - case Type::Builtin: - // GCC treats vector and complex types as fundamental types. - case Type::Vector: - case Type::ExtVector: - case Type::Complex: - case Type::Atomic: - // FIXME: GCC treats block pointers as fundamental types?! - case Type::BlockPointer: - // abi::__fundamental_type_info. - VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE"; - break; - - case Type::ConstantArray: - case Type::IncompleteArray: - case Type::VariableArray: - // abi::__array_type_info. - VTableName = "_ZTVN10__cxxabiv117__array_type_infoE"; - break; - - case Type::FunctionNoProto: - case Type::FunctionProto: - // abi::__function_type_info. - VTableName = "_ZTVN10__cxxabiv120__function_type_infoE"; - break; - - case Type::Enum: - // abi::__enum_type_info. - VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE"; - break; - - case Type::Record: { - const CXXRecordDecl *RD = - cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl()); - - if (!RD->hasDefinition() || !RD->getNumBases()) { - VTableName = ClassTypeInfo; - } else if (CanUseSingleInheritance(RD)) { - VTableName = SIClassTypeInfo; - } else { - VTableName = VMIClassTypeInfo; - } - - break; - } - - case Type::ObjCObject: - // Ignore protocol qualifiers. - Ty = cast<ObjCObjectType>(Ty)->getBaseType().getTypePtr(); - - // Handle id and Class. - if (isa<BuiltinType>(Ty)) { - VTableName = ClassTypeInfo; - break; - } - - assert(isa<ObjCInterfaceType>(Ty)); - LLVM_FALLTHROUGH; - - case Type::ObjCInterface: - if (cast<ObjCInterfaceType>(Ty)->getDecl()->getSuperClass()) { - VTableName = SIClassTypeInfo; - } else { - VTableName = ClassTypeInfo; - } - break; - - case Type::ObjCObjectPointer: - case Type::Pointer: - // abi::__pointer_type_info. - VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE"; - break; - - case Type::MemberPointer: - // abi::__pointer_to_member_type_info. - VTableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE"; - break; - } - - llvm::Constant *VTable = - CGM.getModule().getOrInsertGlobal(VTableName, CGM.Int8PtrTy); - CGM.setDSOLocal(cast<llvm::GlobalValue>(VTable->stripPointerCasts())); - - llvm::Type *PtrDiffTy = - CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType()); - - // The vtable address point is 2. - llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2); - VTable = - llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.Int8PtrTy, VTable, Two); - VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy); - - Fields.push_back(VTable); -} - -/// Return the linkage that the type info and type info name constants -/// should have for the given type. -static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM, - QualType Ty) { - // Itanium C++ ABI 2.9.5p7: - // In addition, it and all of the intermediate abi::__pointer_type_info - // structs in the chain down to the abi::__class_type_info for the - // incomplete class type must be prevented from resolving to the - // corresponding type_info structs for the complete class type, possibly - // by making them local static objects. Finally, a dummy class RTTI is - // generated for the incomplete type that will not resolve to the final - // complete class RTTI (because the latter need not exist), possibly by - // making it a local static object. - if (ContainsIncompleteClassType(Ty)) - return llvm::GlobalValue::InternalLinkage; - - switch (Ty->getLinkage()) { - case NoLinkage: - case InternalLinkage: - case UniqueExternalLinkage: - return llvm::GlobalValue::InternalLinkage; - - case VisibleNoLinkage: - case ModuleInternalLinkage: - case ModuleLinkage: - case ExternalLinkage: - // RTTI is not enabled, which means that this type info struct is going - // to be used for exception handling. Give it linkonce_odr linkage. - if (!CGM.getLangOpts().RTTI) - return llvm::GlobalValue::LinkOnceODRLinkage; - - if (const RecordType *Record = dyn_cast<RecordType>(Ty)) { - const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl()); - if (RD->hasAttr<WeakAttr>()) - return llvm::GlobalValue::WeakODRLinkage; - if (CGM.getTriple().isWindowsItaniumEnvironment()) - if (RD->hasAttr<DLLImportAttr>() && - ShouldUseExternalRTTIDescriptor(CGM, Ty)) - return llvm::GlobalValue::ExternalLinkage; - // MinGW always uses LinkOnceODRLinkage for type info. - if (RD->isDynamicClass() && - !CGM.getContext() - .getTargetInfo() - .getTriple() - .isWindowsGNUEnvironment()) - return CGM.getVTableLinkage(RD); - } - - return llvm::GlobalValue::LinkOnceODRLinkage; - } - - llvm_unreachable("Invalid linkage!"); -} - -llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty) { - // We want to operate on the canonical type. - Ty = Ty.getCanonicalType(); - - // Check if we've already emitted an RTTI descriptor for this type. - SmallString<256> Name; - llvm::raw_svector_ostream Out(Name); - CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out); - - llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name); - if (OldGV && !OldGV->isDeclaration()) { - assert(!OldGV->hasAvailableExternallyLinkage() && - "available_externally typeinfos not yet implemented"); - - return llvm::ConstantExpr::getBitCast(OldGV, CGM.Int8PtrTy); - } - - // Check if there is already an external RTTI descriptor for this type. - if (IsStandardLibraryRTTIDescriptor(Ty) || - ShouldUseExternalRTTIDescriptor(CGM, Ty)) - return GetAddrOfExternalRTTIDescriptor(Ty); - - // Emit the standard library with external linkage. - llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(CGM, Ty); - - // Give the type_info object and name the formal visibility of the - // type itself. - llvm::GlobalValue::VisibilityTypes llvmVisibility; - if (llvm::GlobalValue::isLocalLinkage(Linkage)) - // If the linkage is local, only default visibility makes sense. - llvmVisibility = llvm::GlobalValue::DefaultVisibility; - else if (CXXABI.classifyRTTIUniqueness(Ty, Linkage) == - ItaniumCXXABI::RUK_NonUniqueHidden) - llvmVisibility = llvm::GlobalValue::HiddenVisibility; - else - llvmVisibility = CodeGenModule::GetLLVMVisibility(Ty->getVisibility()); - - llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass = - llvm::GlobalValue::DefaultStorageClass; - if (CGM.getTriple().isWindowsItaniumEnvironment()) { - auto RD = Ty->getAsCXXRecordDecl(); - if (RD && RD->hasAttr<DLLExportAttr>()) - DLLStorageClass = llvm::GlobalValue::DLLExportStorageClass; - } - - return BuildTypeInfo(Ty, Linkage, llvmVisibility, DLLStorageClass); -} - -llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo( - QualType Ty, - llvm::GlobalVariable::LinkageTypes Linkage, - llvm::GlobalValue::VisibilityTypes Visibility, - llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) { - // Add the vtable pointer. - BuildVTablePointer(cast<Type>(Ty)); - - // And the name. - llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage); - llvm::Constant *TypeNameField; - - // If we're supposed to demote the visibility, be sure to set a flag - // to use a string comparison for type_info comparisons. - ItaniumCXXABI::RTTIUniquenessKind RTTIUniqueness = - CXXABI.classifyRTTIUniqueness(Ty, Linkage); - if (RTTIUniqueness != ItaniumCXXABI::RUK_Unique) { - // The flag is the sign bit, which on ARM64 is defined to be clear - // for global pointers. This is very ARM64-specific. - TypeNameField = llvm::ConstantExpr::getPtrToInt(TypeName, CGM.Int64Ty); - llvm::Constant *flag = - llvm::ConstantInt::get(CGM.Int64Ty, ((uint64_t)1) << 63); - TypeNameField = llvm::ConstantExpr::getAdd(TypeNameField, flag); - TypeNameField = - llvm::ConstantExpr::getIntToPtr(TypeNameField, CGM.Int8PtrTy); - } else { - TypeNameField = llvm::ConstantExpr::getBitCast(TypeName, CGM.Int8PtrTy); - } - Fields.push_back(TypeNameField); - - switch (Ty->getTypeClass()) { -#define TYPE(Class, Base) -#define ABSTRACT_TYPE(Class, Base) -#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class: -#define NON_CANONICAL_TYPE(Class, Base) case Type::Class: -#define DEPENDENT_TYPE(Class, Base) case Type::Class: -#include "clang/AST/TypeNodes.def" - llvm_unreachable("Non-canonical and dependent types shouldn't get here"); - - // GCC treats vector types as fundamental types. - case Type::Builtin: - case Type::Vector: - case Type::ExtVector: - case Type::Complex: - case Type::BlockPointer: - // Itanium C++ ABI 2.9.5p4: - // abi::__fundamental_type_info adds no data members to std::type_info. - break; - - case Type::LValueReference: - case Type::RValueReference: - llvm_unreachable("References shouldn't get here"); - - case Type::Auto: - case Type::DeducedTemplateSpecialization: - llvm_unreachable("Undeduced type shouldn't get here"); - - case Type::Pipe: - llvm_unreachable("Pipe type shouldn't get here"); - - case Type::ConstantArray: - case Type::IncompleteArray: - case Type::VariableArray: - // Itanium C++ ABI 2.9.5p5: - // abi::__array_type_info adds no data members to std::type_info. - break; - - case Type::FunctionNoProto: - case Type::FunctionProto: - // Itanium C++ ABI 2.9.5p5: - // abi::__function_type_info adds no data members to std::type_info. - break; - - case Type::Enum: - // Itanium C++ ABI 2.9.5p5: - // abi::__enum_type_info adds no data members to std::type_info. - break; - - case Type::Record: { - const CXXRecordDecl *RD = - cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl()); - if (!RD->hasDefinition() || !RD->getNumBases()) { - // We don't need to emit any fields. - break; - } - - if (CanUseSingleInheritance(RD)) - BuildSIClassTypeInfo(RD); - else - BuildVMIClassTypeInfo(RD); - - break; - } - - case Type::ObjCObject: - case Type::ObjCInterface: - BuildObjCObjectTypeInfo(cast<ObjCObjectType>(Ty)); - break; - - case Type::ObjCObjectPointer: - BuildPointerTypeInfo(cast<ObjCObjectPointerType>(Ty)->getPointeeType()); - break; - - case Type::Pointer: - BuildPointerTypeInfo(cast<PointerType>(Ty)->getPointeeType()); - break; - - case Type::MemberPointer: - BuildPointerToMemberTypeInfo(cast<MemberPointerType>(Ty)); - break; - - case Type::Atomic: - // No fields, at least for the moment. - break; - } - - llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields); - - SmallString<256> Name; - llvm::raw_svector_ostream Out(Name); - CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out); - llvm::Module &M = CGM.getModule(); - llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name); - llvm::GlobalVariable *GV = - new llvm::GlobalVariable(M, Init->getType(), - /*Constant=*/true, Linkage, Init, Name); - - // If there's already an old global variable, replace it with the new one. - if (OldGV) { - GV->takeName(OldGV); - llvm::Constant *NewPtr = - llvm::ConstantExpr::getBitCast(GV, OldGV->getType()); - OldGV->replaceAllUsesWith(NewPtr); - OldGV->eraseFromParent(); - } - - if (CGM.supportsCOMDAT() && GV->isWeakForLinker()) - GV->setComdat(M.getOrInsertComdat(GV->getName())); - - CharUnits Align = - CGM.getContext().toCharUnitsFromBits(CGM.getTarget().getPointerAlign(0)); - GV->setAlignment(Align.getQuantity()); - - // The Itanium ABI specifies that type_info objects must be globally - // unique, with one exception: if the type is an incomplete class - // type or a (possibly indirect) pointer to one. That exception - // affects the general case of comparing type_info objects produced - // by the typeid operator, which is why the comparison operators on - // std::type_info generally use the type_info name pointers instead - // of the object addresses. However, the language's built-in uses - // of RTTI generally require class types to be complete, even when - // manipulating pointers to those class types. This allows the - // implementation of dynamic_cast to rely on address equality tests, - // which is much faster. - - // All of this is to say that it's important that both the type_info - // object and the type_info name be uniqued when weakly emitted. - - TypeName->setVisibility(Visibility); - CGM.setDSOLocal(TypeName); - - GV->setVisibility(Visibility); - CGM.setDSOLocal(GV); - - TypeName->setDLLStorageClass(DLLStorageClass); - GV->setDLLStorageClass(DLLStorageClass); - - return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy); -} - -/// BuildObjCObjectTypeInfo - Build the appropriate kind of type_info -/// for the given Objective-C object type. -void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) { - // Drop qualifiers. - const Type *T = OT->getBaseType().getTypePtr(); - assert(isa<BuiltinType>(T) || isa<ObjCInterfaceType>(T)); - - // The builtin types are abi::__class_type_infos and don't require - // extra fields. - if (isa<BuiltinType>(T)) return; - - ObjCInterfaceDecl *Class = cast<ObjCInterfaceType>(T)->getDecl(); - ObjCInterfaceDecl *Super = Class->getSuperClass(); - - // Root classes are also __class_type_info. - if (!Super) return; - - QualType SuperTy = CGM.getContext().getObjCInterfaceType(Super); - - // Everything else is single inheritance. - llvm::Constant *BaseTypeInfo = - ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(SuperTy); - Fields.push_back(BaseTypeInfo); -} - -/// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single -/// inheritance, according to the Itanium C++ ABI, 2.95p6b. -void ItaniumRTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) { - // Itanium C++ ABI 2.9.5p6b: - // It adds to abi::__class_type_info a single member pointing to the - // type_info structure for the base type, - llvm::Constant *BaseTypeInfo = - ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(RD->bases_begin()->getType()); - Fields.push_back(BaseTypeInfo); -} - -namespace { - /// SeenBases - Contains virtual and non-virtual bases seen when traversing - /// a class hierarchy. - struct SeenBases { - llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases; - llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases; - }; -} - -/// ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in -/// abi::__vmi_class_type_info. -/// -static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base, - SeenBases &Bases) { - - unsigned Flags = 0; - - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - - if (Base->isVirtual()) { - // Mark the virtual base as seen. - if (!Bases.VirtualBases.insert(BaseDecl).second) { - // If this virtual base has been seen before, then the class is diamond - // shaped. - Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped; - } else { - if (Bases.NonVirtualBases.count(BaseDecl)) - Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat; - } - } else { - // Mark the non-virtual base as seen. - if (!Bases.NonVirtualBases.insert(BaseDecl).second) { - // If this non-virtual base has been seen before, then the class has non- - // diamond shaped repeated inheritance. - Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat; - } else { - if (Bases.VirtualBases.count(BaseDecl)) - Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat; - } - } - - // Walk all bases. - for (const auto &I : BaseDecl->bases()) - Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases); - - return Flags; -} - -static unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) { - unsigned Flags = 0; - SeenBases Bases; - - // Walk all bases. - for (const auto &I : RD->bases()) - Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases); - - return Flags; -} - -/// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for -/// classes with bases that do not satisfy the abi::__si_class_type_info -/// constraints, according ti the Itanium C++ ABI, 2.9.5p5c. -void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) { - llvm::Type *UnsignedIntLTy = - CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy); - - // Itanium C++ ABI 2.9.5p6c: - // __flags is a word with flags describing details about the class - // structure, which may be referenced by using the __flags_masks - // enumeration. These flags refer to both direct and indirect bases. - unsigned Flags = ComputeVMIClassTypeInfoFlags(RD); - Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags)); - - // Itanium C++ ABI 2.9.5p6c: - // __base_count is a word with the number of direct proper base class - // descriptions that follow. - Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->getNumBases())); - - if (!RD->getNumBases()) - return; - - // Now add the base class descriptions. - - // Itanium C++ ABI 2.9.5p6c: - // __base_info[] is an array of base class descriptions -- one for every - // direct proper base. Each description is of the type: - // - // struct abi::__base_class_type_info { - // public: - // const __class_type_info *__base_type; - // long __offset_flags; - // - // enum __offset_flags_masks { - // __virtual_mask = 0x1, - // __public_mask = 0x2, - // __offset_shift = 8 - // }; - // }; - - // If we're in mingw and 'long' isn't wide enough for a pointer, use 'long - // long' instead of 'long' for __offset_flags. libstdc++abi uses long long on - // LLP64 platforms. - // FIXME: Consider updating libc++abi to match, and extend this logic to all - // LLP64 platforms. - QualType OffsetFlagsTy = CGM.getContext().LongTy; - const TargetInfo &TI = CGM.getContext().getTargetInfo(); - if (TI.getTriple().isOSCygMing() && TI.getPointerWidth(0) > TI.getLongWidth()) - OffsetFlagsTy = CGM.getContext().LongLongTy; - llvm::Type *OffsetFlagsLTy = - CGM.getTypes().ConvertType(OffsetFlagsTy); - - for (const auto &Base : RD->bases()) { - // The __base_type member points to the RTTI for the base type. - Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(Base.getType())); - - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl()); - - int64_t OffsetFlags = 0; - - // All but the lower 8 bits of __offset_flags are a signed offset. - // For a non-virtual base, this is the offset in the object of the base - // subobject. For a virtual base, this is the offset in the virtual table of - // the virtual base offset for the virtual base referenced (negative). - CharUnits Offset; - if (Base.isVirtual()) - Offset = - CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(RD, BaseDecl); - else { - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - Offset = Layout.getBaseClassOffset(BaseDecl); - }; - - OffsetFlags = uint64_t(Offset.getQuantity()) << 8; - - // The low-order byte of __offset_flags contains flags, as given by the - // masks from the enumeration __offset_flags_masks. - if (Base.isVirtual()) - OffsetFlags |= BCTI_Virtual; - if (Base.getAccessSpecifier() == AS_public) - OffsetFlags |= BCTI_Public; - - Fields.push_back(llvm::ConstantInt::get(OffsetFlagsLTy, OffsetFlags)); - } -} - -/// Compute the flags for a __pbase_type_info, and remove the corresponding -/// pieces from \p Type. -static unsigned extractPBaseFlags(ASTContext &Ctx, QualType &Type) { - unsigned Flags = 0; - - if (Type.isConstQualified()) - Flags |= ItaniumRTTIBuilder::PTI_Const; - if (Type.isVolatileQualified()) - Flags |= ItaniumRTTIBuilder::PTI_Volatile; - if (Type.isRestrictQualified()) - Flags |= ItaniumRTTIBuilder::PTI_Restrict; - Type = Type.getUnqualifiedType(); - - // Itanium C++ ABI 2.9.5p7: - // When the abi::__pbase_type_info is for a direct or indirect pointer to an - // incomplete class type, the incomplete target type flag is set. - if (ContainsIncompleteClassType(Type)) - Flags |= ItaniumRTTIBuilder::PTI_Incomplete; - - if (auto *Proto = Type->getAs<FunctionProtoType>()) { - if (Proto->isNothrow()) { - Flags |= ItaniumRTTIBuilder::PTI_Noexcept; - Type = Ctx.getFunctionTypeWithExceptionSpec(Type, EST_None); - } - } - - return Flags; -} - -/// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, -/// used for pointer types. -void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) { - // Itanium C++ ABI 2.9.5p7: - // __flags is a flag word describing the cv-qualification and other - // attributes of the type pointed to - unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy); - - llvm::Type *UnsignedIntLTy = - CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy); - Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags)); - - // Itanium C++ ABI 2.9.5p7: - // __pointee is a pointer to the std::type_info derivation for the - // unqualified type being pointed to. - llvm::Constant *PointeeTypeInfo = - ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy); - Fields.push_back(PointeeTypeInfo); -} - -/// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info -/// struct, used for member pointer types. -void -ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) { - QualType PointeeTy = Ty->getPointeeType(); - - // Itanium C++ ABI 2.9.5p7: - // __flags is a flag word describing the cv-qualification and other - // attributes of the type pointed to. - unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy); - - const RecordType *ClassType = cast<RecordType>(Ty->getClass()); - if (IsIncompleteClassType(ClassType)) - Flags |= PTI_ContainingClassIncomplete; - - llvm::Type *UnsignedIntLTy = - CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy); - Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags)); - - // Itanium C++ ABI 2.9.5p7: - // __pointee is a pointer to the std::type_info derivation for the - // unqualified type being pointed to. - llvm::Constant *PointeeTypeInfo = - ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy); - Fields.push_back(PointeeTypeInfo); - - // Itanium C++ ABI 2.9.5p9: - // __context is a pointer to an abi::__class_type_info corresponding to the - // class type containing the member pointed to - // (e.g., the "A" in "int A::*"). - Fields.push_back( - ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(QualType(ClassType, 0))); -} - -llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) { - return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty); -} - -void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD) { - // Types added here must also be added to TypeInfoIsInStandardLibrary. - QualType FundamentalTypes[] = { - getContext().VoidTy, getContext().NullPtrTy, - getContext().BoolTy, getContext().WCharTy, - getContext().CharTy, getContext().UnsignedCharTy, - getContext().SignedCharTy, getContext().ShortTy, - getContext().UnsignedShortTy, getContext().IntTy, - getContext().UnsignedIntTy, getContext().LongTy, - getContext().UnsignedLongTy, getContext().LongLongTy, - getContext().UnsignedLongLongTy, getContext().Int128Ty, - getContext().UnsignedInt128Ty, getContext().HalfTy, - getContext().FloatTy, getContext().DoubleTy, - getContext().LongDoubleTy, getContext().Float128Ty, - getContext().Char8Ty, getContext().Char16Ty, - getContext().Char32Ty - }; - llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass = - RD->hasAttr<DLLExportAttr>() - ? llvm::GlobalValue::DLLExportStorageClass - : llvm::GlobalValue::DefaultStorageClass; - llvm::GlobalValue::VisibilityTypes Visibility = - CodeGenModule::GetLLVMVisibility(RD->getVisibility()); - for (const QualType &FundamentalType : FundamentalTypes) { - QualType PointerType = getContext().getPointerType(FundamentalType); - QualType PointerTypeConst = getContext().getPointerType( - FundamentalType.withConst()); - for (QualType Type : {FundamentalType, PointerType, PointerTypeConst}) - ItaniumRTTIBuilder(*this).BuildTypeInfo( - Type, llvm::GlobalValue::ExternalLinkage, - Visibility, DLLStorageClass); - } -} - -/// What sort of uniqueness rules should we use for the RTTI for the -/// given type? -ItaniumCXXABI::RTTIUniquenessKind ItaniumCXXABI::classifyRTTIUniqueness( - QualType CanTy, llvm::GlobalValue::LinkageTypes Linkage) const { - if (shouldRTTIBeUnique()) - return RUK_Unique; - - // It's only necessary for linkonce_odr or weak_odr linkage. - if (Linkage != llvm::GlobalValue::LinkOnceODRLinkage && - Linkage != llvm::GlobalValue::WeakODRLinkage) - return RUK_Unique; - - // It's only necessary with default visibility. - if (CanTy->getVisibility() != DefaultVisibility) - return RUK_Unique; - - // If we're not required to publish this symbol, hide it. - if (Linkage == llvm::GlobalValue::LinkOnceODRLinkage) - return RUK_NonUniqueHidden; - - // If we're required to publish this symbol, as we might be under an - // explicit instantiation, leave it with default visibility but - // enable string-comparisons. - assert(Linkage == llvm::GlobalValue::WeakODRLinkage); - return RUK_NonUniqueVisible; -} - -// Find out how to codegen the complete destructor and constructor -namespace { -enum class StructorCodegen { Emit, RAUW, Alias, COMDAT }; -} -static StructorCodegen getCodegenToUse(CodeGenModule &CGM, - const CXXMethodDecl *MD) { - if (!CGM.getCodeGenOpts().CXXCtorDtorAliases) - return StructorCodegen::Emit; - - // The complete and base structors are not equivalent if there are any virtual - // bases, so emit separate functions. - if (MD->getParent()->getNumVBases()) - return StructorCodegen::Emit; - - GlobalDecl AliasDecl; - if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) { - AliasDecl = GlobalDecl(DD, Dtor_Complete); - } else { - const auto *CD = cast<CXXConstructorDecl>(MD); - AliasDecl = GlobalDecl(CD, Ctor_Complete); - } - llvm::GlobalValue::LinkageTypes Linkage = CGM.getFunctionLinkage(AliasDecl); - - if (llvm::GlobalValue::isDiscardableIfUnused(Linkage)) - return StructorCodegen::RAUW; - - // FIXME: Should we allow available_externally aliases? - if (!llvm::GlobalAlias::isValidLinkage(Linkage)) - return StructorCodegen::RAUW; - - if (llvm::GlobalValue::isWeakForLinker(Linkage)) { - // Only ELF and wasm support COMDATs with arbitrary names (C5/D5). - if (CGM.getTarget().getTriple().isOSBinFormatELF() || - CGM.getTarget().getTriple().isOSBinFormatWasm()) - return StructorCodegen::COMDAT; - return StructorCodegen::Emit; - } - - return StructorCodegen::Alias; -} - -static void emitConstructorDestructorAlias(CodeGenModule &CGM, - GlobalDecl AliasDecl, - GlobalDecl TargetDecl) { - llvm::GlobalValue::LinkageTypes Linkage = CGM.getFunctionLinkage(AliasDecl); - - StringRef MangledName = CGM.getMangledName(AliasDecl); - llvm::GlobalValue *Entry = CGM.GetGlobalValue(MangledName); - if (Entry && !Entry->isDeclaration()) - return; - - auto *Aliasee = cast<llvm::GlobalValue>(CGM.GetAddrOfGlobal(TargetDecl)); - - // Create the alias with no name. - auto *Alias = llvm::GlobalAlias::create(Linkage, "", Aliasee); - - // Constructors and destructors are always unnamed_addr. - Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - - // Switch any previous uses to the alias. - if (Entry) { - assert(Entry->getType() == Aliasee->getType() && - "declaration exists with different type"); - Alias->takeName(Entry); - Entry->replaceAllUsesWith(Alias); - Entry->eraseFromParent(); - } else { - Alias->setName(MangledName); - } - - // Finally, set up the alias with its proper name and attributes. - CGM.SetCommonAttributes(AliasDecl, Alias); -} - -void ItaniumCXXABI::emitCXXStructor(const CXXMethodDecl *MD, - StructorType Type) { - auto *CD = dyn_cast<CXXConstructorDecl>(MD); - const CXXDestructorDecl *DD = CD ? nullptr : cast<CXXDestructorDecl>(MD); - - StructorCodegen CGType = getCodegenToUse(CGM, MD); - - if (Type == StructorType::Complete) { - GlobalDecl CompleteDecl; - GlobalDecl BaseDecl; - if (CD) { - CompleteDecl = GlobalDecl(CD, Ctor_Complete); - BaseDecl = GlobalDecl(CD, Ctor_Base); - } else { - CompleteDecl = GlobalDecl(DD, Dtor_Complete); - BaseDecl = GlobalDecl(DD, Dtor_Base); - } - - if (CGType == StructorCodegen::Alias || CGType == StructorCodegen::COMDAT) { - emitConstructorDestructorAlias(CGM, CompleteDecl, BaseDecl); - return; - } - - if (CGType == StructorCodegen::RAUW) { - StringRef MangledName = CGM.getMangledName(CompleteDecl); - auto *Aliasee = CGM.GetAddrOfGlobal(BaseDecl); - CGM.addReplacement(MangledName, Aliasee); - return; - } - } - - // The base destructor is equivalent to the base destructor of its - // base class if there is exactly one non-virtual base class with a - // non-trivial destructor, there are no fields with a non-trivial - // destructor, and the body of the destructor is trivial. - if (DD && Type == StructorType::Base && CGType != StructorCodegen::COMDAT && - !CGM.TryEmitBaseDestructorAsAlias(DD)) - return; - - // FIXME: The deleting destructor is equivalent to the selected operator - // delete if: - // * either the delete is a destroying operator delete or the destructor - // would be trivial if it weren't virtual, - // * the conversion from the 'this' parameter to the first parameter of the - // destructor is equivalent to a bitcast, - // * the destructor does not have an implicit "this" return, and - // * the operator delete has the same calling convention and IR function type - // as the destructor. - // In such cases we should try to emit the deleting dtor as an alias to the - // selected 'operator delete'. - - llvm::Function *Fn = CGM.codegenCXXStructor(MD, Type); - - if (CGType == StructorCodegen::COMDAT) { - SmallString<256> Buffer; - llvm::raw_svector_ostream Out(Buffer); - if (DD) - getMangleContext().mangleCXXDtorComdat(DD, Out); - else - getMangleContext().mangleCXXCtorComdat(CD, Out); - llvm::Comdat *C = CGM.getModule().getOrInsertComdat(Out.str()); - Fn->setComdat(C); - } else { - CGM.maybeSetTrivialComdat(*MD, *Fn); - } -} - -static llvm::Constant *getBeginCatchFn(CodeGenModule &CGM) { - // void *__cxa_begin_catch(void*); - llvm::FunctionType *FTy = llvm::FunctionType::get( - CGM.Int8PtrTy, CGM.Int8PtrTy, /*IsVarArgs=*/false); - - return CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch"); -} - -static llvm::Constant *getEndCatchFn(CodeGenModule &CGM) { - // void __cxa_end_catch(); - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, /*IsVarArgs=*/false); - - return CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch"); -} - -static llvm::Constant *getGetExceptionPtrFn(CodeGenModule &CGM) { - // void *__cxa_get_exception_ptr(void*); - llvm::FunctionType *FTy = llvm::FunctionType::get( - CGM.Int8PtrTy, CGM.Int8PtrTy, /*IsVarArgs=*/false); - - return CGM.CreateRuntimeFunction(FTy, "__cxa_get_exception_ptr"); -} - -namespace { - /// A cleanup to call __cxa_end_catch. In many cases, the caught - /// exception type lets us state definitively that the thrown exception - /// type does not have a destructor. In particular: - /// - Catch-alls tell us nothing, so we have to conservatively - /// assume that the thrown exception might have a destructor. - /// - Catches by reference behave according to their base types. - /// - Catches of non-record types will only trigger for exceptions - /// of non-record types, which never have destructors. - /// - Catches of record types can trigger for arbitrary subclasses - /// of the caught type, so we have to assume the actual thrown - /// exception type might have a throwing destructor, even if the - /// caught type's destructor is trivial or nothrow. - struct CallEndCatch final : EHScopeStack::Cleanup { - CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {} - bool MightThrow; - - void Emit(CodeGenFunction &CGF, Flags flags) override { - if (!MightThrow) { - CGF.EmitNounwindRuntimeCall(getEndCatchFn(CGF.CGM)); - return; - } - - CGF.EmitRuntimeCallOrInvoke(getEndCatchFn(CGF.CGM)); - } - }; -} - -/// Emits a call to __cxa_begin_catch and enters a cleanup to call -/// __cxa_end_catch. -/// -/// \param EndMightThrow - true if __cxa_end_catch might throw -static llvm::Value *CallBeginCatch(CodeGenFunction &CGF, - llvm::Value *Exn, - bool EndMightThrow) { - llvm::CallInst *call = - CGF.EmitNounwindRuntimeCall(getBeginCatchFn(CGF.CGM), Exn); - - CGF.EHStack.pushCleanup<CallEndCatch>(NormalAndEHCleanup, EndMightThrow); - - return call; -} - -/// A "special initializer" callback for initializing a catch -/// parameter during catch initialization. -static void InitCatchParam(CodeGenFunction &CGF, - const VarDecl &CatchParam, - Address ParamAddr, - SourceLocation Loc) { - // Load the exception from where the landing pad saved it. - llvm::Value *Exn = CGF.getExceptionFromSlot(); - - CanQualType CatchType = - CGF.CGM.getContext().getCanonicalType(CatchParam.getType()); - llvm::Type *LLVMCatchTy = CGF.ConvertTypeForMem(CatchType); - - // If we're catching by reference, we can just cast the object - // pointer to the appropriate pointer. - if (isa<ReferenceType>(CatchType)) { - QualType CaughtType = cast<ReferenceType>(CatchType)->getPointeeType(); - bool EndCatchMightThrow = CaughtType->isRecordType(); - - // __cxa_begin_catch returns the adjusted object pointer. - llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow); - - // We have no way to tell the personality function that we're - // catching by reference, so if we're catching a pointer, - // __cxa_begin_catch will actually return that pointer by value. - if (const PointerType *PT = dyn_cast<PointerType>(CaughtType)) { - QualType PointeeType = PT->getPointeeType(); - - // When catching by reference, generally we should just ignore - // this by-value pointer and use the exception object instead. - if (!PointeeType->isRecordType()) { - - // Exn points to the struct _Unwind_Exception header, which - // we have to skip past in order to reach the exception data. - unsigned HeaderSize = - CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException(); - AdjustedExn = CGF.Builder.CreateConstGEP1_32(Exn, HeaderSize); - - // However, if we're catching a pointer-to-record type that won't - // work, because the personality function might have adjusted - // the pointer. There's actually no way for us to fully satisfy - // the language/ABI contract here: we can't use Exn because it - // might have the wrong adjustment, but we can't use the by-value - // pointer because it's off by a level of abstraction. - // - // The current solution is to dump the adjusted pointer into an - // alloca, which breaks language semantics (because changing the - // pointer doesn't change the exception) but at least works. - // The better solution would be to filter out non-exact matches - // and rethrow them, but this is tricky because the rethrow - // really needs to be catchable by other sites at this landing - // pad. The best solution is to fix the personality function. - } else { - // Pull the pointer for the reference type off. - llvm::Type *PtrTy = - cast<llvm::PointerType>(LLVMCatchTy)->getElementType(); - - // Create the temporary and write the adjusted pointer into it. - Address ExnPtrTmp = - CGF.CreateTempAlloca(PtrTy, CGF.getPointerAlign(), "exn.byref.tmp"); - llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy); - CGF.Builder.CreateStore(Casted, ExnPtrTmp); - - // Bind the reference to the temporary. - AdjustedExn = ExnPtrTmp.getPointer(); - } - } - - llvm::Value *ExnCast = - CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref"); - CGF.Builder.CreateStore(ExnCast, ParamAddr); - return; - } - - // Scalars and complexes. - TypeEvaluationKind TEK = CGF.getEvaluationKind(CatchType); - if (TEK != TEK_Aggregate) { - llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false); - - // If the catch type is a pointer type, __cxa_begin_catch returns - // the pointer by value. - if (CatchType->hasPointerRepresentation()) { - llvm::Value *CastExn = - CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted"); - - switch (CatchType.getQualifiers().getObjCLifetime()) { - case Qualifiers::OCL_Strong: - CastExn = CGF.EmitARCRetainNonBlock(CastExn); - LLVM_FALLTHROUGH; - - case Qualifiers::OCL_None: - case Qualifiers::OCL_ExplicitNone: - case Qualifiers::OCL_Autoreleasing: - CGF.Builder.CreateStore(CastExn, ParamAddr); - return; - - case Qualifiers::OCL_Weak: - CGF.EmitARCInitWeak(ParamAddr, CastExn); - return; - } - llvm_unreachable("bad ownership qualifier!"); - } - - // Otherwise, it returns a pointer into the exception object. - - llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok - llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy); - - LValue srcLV = CGF.MakeNaturalAlignAddrLValue(Cast, CatchType); - LValue destLV = CGF.MakeAddrLValue(ParamAddr, CatchType); - switch (TEK) { - case TEK_Complex: - CGF.EmitStoreOfComplex(CGF.EmitLoadOfComplex(srcLV, Loc), destLV, - /*init*/ true); - return; - case TEK_Scalar: { - llvm::Value *ExnLoad = CGF.EmitLoadOfScalar(srcLV, Loc); - CGF.EmitStoreOfScalar(ExnLoad, destLV, /*init*/ true); - return; - } - case TEK_Aggregate: - llvm_unreachable("evaluation kind filtered out!"); - } - llvm_unreachable("bad evaluation kind"); - } - - assert(isa<RecordType>(CatchType) && "unexpected catch type!"); - auto catchRD = CatchType->getAsCXXRecordDecl(); - CharUnits caughtExnAlignment = CGF.CGM.getClassPointerAlignment(catchRD); - - llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok - - // Check for a copy expression. If we don't have a copy expression, - // that means a trivial copy is okay. - const Expr *copyExpr = CatchParam.getInit(); - if (!copyExpr) { - llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true); - Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy), - caughtExnAlignment); - LValue Dest = CGF.MakeAddrLValue(ParamAddr, CatchType); - LValue Src = CGF.MakeAddrLValue(adjustedExn, CatchType); - CGF.EmitAggregateCopy(Dest, Src, CatchType, AggValueSlot::DoesNotOverlap); - return; - } - - // We have to call __cxa_get_exception_ptr to get the adjusted - // pointer before copying. - llvm::CallInst *rawAdjustedExn = - CGF.EmitNounwindRuntimeCall(getGetExceptionPtrFn(CGF.CGM), Exn); - - // Cast that to the appropriate type. - Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy), - caughtExnAlignment); - - // The copy expression is defined in terms of an OpaqueValueExpr. - // Find it and map it to the adjusted expression. - CodeGenFunction::OpaqueValueMapping - opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr), - CGF.MakeAddrLValue(adjustedExn, CatchParam.getType())); - - // Call the copy ctor in a terminate scope. - CGF.EHStack.pushTerminate(); - - // Perform the copy construction. - CGF.EmitAggExpr(copyExpr, - AggValueSlot::forAddr(ParamAddr, Qualifiers(), - AggValueSlot::IsNotDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - AggValueSlot::DoesNotOverlap)); - - // Leave the terminate scope. - CGF.EHStack.popTerminate(); - - // Undo the opaque value mapping. - opaque.pop(); - - // Finally we can call __cxa_begin_catch. - CallBeginCatch(CGF, Exn, true); -} - -/// Begins a catch statement by initializing the catch variable and -/// calling __cxa_begin_catch. -void ItaniumCXXABI::emitBeginCatch(CodeGenFunction &CGF, - const CXXCatchStmt *S) { - // We have to be very careful with the ordering of cleanups here: - // C++ [except.throw]p4: - // The destruction [of the exception temporary] occurs - // immediately after the destruction of the object declared in - // the exception-declaration in the handler. - // - // So the precise ordering is: - // 1. Construct catch variable. - // 2. __cxa_begin_catch - // 3. Enter __cxa_end_catch cleanup - // 4. Enter dtor cleanup - // - // We do this by using a slightly abnormal initialization process. - // Delegation sequence: - // - ExitCXXTryStmt opens a RunCleanupsScope - // - EmitAutoVarAlloca creates the variable and debug info - // - InitCatchParam initializes the variable from the exception - // - CallBeginCatch calls __cxa_begin_catch - // - CallBeginCatch enters the __cxa_end_catch cleanup - // - EmitAutoVarCleanups enters the variable destructor cleanup - // - EmitCXXTryStmt emits the code for the catch body - // - EmitCXXTryStmt close the RunCleanupsScope - - VarDecl *CatchParam = S->getExceptionDecl(); - if (!CatchParam) { - llvm::Value *Exn = CGF.getExceptionFromSlot(); - CallBeginCatch(CGF, Exn, true); - return; - } - - // Emit the local. - CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam); - InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF), S->getBeginLoc()); - CGF.EmitAutoVarCleanups(var); -} - -/// Get or define the following function: -/// void @__clang_call_terminate(i8* %exn) nounwind noreturn -/// This code is used only in C++. -static llvm::Constant *getClangCallTerminateFn(CodeGenModule &CGM) { - llvm::FunctionType *fnTy = - llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false); - llvm::Constant *fnRef = CGM.CreateRuntimeFunction( - fnTy, "__clang_call_terminate", llvm::AttributeList(), /*Local=*/true); - - llvm::Function *fn = dyn_cast<llvm::Function>(fnRef); - if (fn && fn->empty()) { - fn->setDoesNotThrow(); - fn->setDoesNotReturn(); - - // What we really want is to massively penalize inlining without - // forbidding it completely. The difference between that and - // 'noinline' is negligible. - fn->addFnAttr(llvm::Attribute::NoInline); - - // Allow this function to be shared across translation units, but - // we don't want it to turn into an exported symbol. - fn->setLinkage(llvm::Function::LinkOnceODRLinkage); - fn->setVisibility(llvm::Function::HiddenVisibility); - if (CGM.supportsCOMDAT()) - fn->setComdat(CGM.getModule().getOrInsertComdat(fn->getName())); - - // Set up the function. - llvm::BasicBlock *entry = - llvm::BasicBlock::Create(CGM.getLLVMContext(), "", fn); - CGBuilderTy builder(CGM, entry); - - // Pull the exception pointer out of the parameter list. - llvm::Value *exn = &*fn->arg_begin(); - - // Call __cxa_begin_catch(exn). - llvm::CallInst *catchCall = builder.CreateCall(getBeginCatchFn(CGM), exn); - catchCall->setDoesNotThrow(); - catchCall->setCallingConv(CGM.getRuntimeCC()); - - // Call std::terminate(). - llvm::CallInst *termCall = builder.CreateCall(CGM.getTerminateFn()); - termCall->setDoesNotThrow(); - termCall->setDoesNotReturn(); - termCall->setCallingConv(CGM.getRuntimeCC()); - - // std::terminate cannot return. - builder.CreateUnreachable(); - } - - return fnRef; -} - -llvm::CallInst * -ItaniumCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF, - llvm::Value *Exn) { - // In C++, we want to call __cxa_begin_catch() before terminating. - if (Exn) { - assert(CGF.CGM.getLangOpts().CPlusPlus); - return CGF.EmitNounwindRuntimeCall(getClangCallTerminateFn(CGF.CGM), Exn); - } - return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn()); -} - -std::pair<llvm::Value *, const CXXRecordDecl *> -ItaniumCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This, - const CXXRecordDecl *RD) { - return {CGF.GetVTablePtr(This, CGM.Int8PtrTy, RD), RD}; -} - -void WebAssemblyCXXABI::emitBeginCatch(CodeGenFunction &CGF, - const CXXCatchStmt *C) { - if (CGF.getTarget().hasFeature("exception-handling")) - CGF.EHStack.pushCleanup<CatchRetScope>( - NormalCleanup, cast<llvm::CatchPadInst>(CGF.CurrentFuncletPad)); - ItaniumCXXABI::emitBeginCatch(CGF, C); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.cpp b/gnu/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.cpp deleted file mode 100644 index 013ca15e239..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.cpp +++ /dev/null @@ -1,200 +0,0 @@ -//===--- MacroPPCallbacks.cpp ---------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains implementation for the macro preprocessors callbacks. -// -//===----------------------------------------------------------------------===// - -#include "MacroPPCallbacks.h" -#include "CGDebugInfo.h" -#include "clang/CodeGen/ModuleBuilder.h" -#include "clang/Lex/MacroInfo.h" -#include "clang/Lex/Preprocessor.h" - -using namespace clang; - -void MacroPPCallbacks::writeMacroDefinition(const IdentifierInfo &II, - const MacroInfo &MI, - Preprocessor &PP, raw_ostream &Name, - raw_ostream &Value) { - Name << II.getName(); - - if (MI.isFunctionLike()) { - Name << '('; - if (!MI.param_empty()) { - MacroInfo::param_iterator AI = MI.param_begin(), E = MI.param_end(); - for (; AI + 1 != E; ++AI) { - Name << (*AI)->getName(); - Name << ','; - } - - // Last argument. - if ((*AI)->getName() == "__VA_ARGS__") - Name << "..."; - else - Name << (*AI)->getName(); - } - - if (MI.isGNUVarargs()) - // #define foo(x...) - Name << "..."; - - Name << ')'; - } - - SmallString<128> SpellingBuffer; - bool First = true; - for (const auto &T : MI.tokens()) { - if (!First && T.hasLeadingSpace()) - Value << ' '; - - Value << PP.getSpelling(T, SpellingBuffer); - First = false; - } -} - -MacroPPCallbacks::MacroPPCallbacks(CodeGenerator *Gen, Preprocessor &PP) - : Gen(Gen), PP(PP), Status(NoScope) {} - -// This is the expected flow of enter/exit compiler and user files: -// - Main File Enter -// - <built-in> file enter -// {Compiler macro definitions} - (Line=0, no scope) -// - (Optional) <command line> file enter -// {Command line macro definitions} - (Line=0, no scope) -// - (Optional) <command line> file exit -// {Command line file includes} - (Line=0, Main file scope) -// {macro definitions and file includes} - (Line!=0, Parent scope) -// - <built-in> file exit -// {User code macro definitions and file includes} - (Line!=0, Parent scope) - -llvm::DIMacroFile *MacroPPCallbacks::getCurrentScope() { - if (Status == MainFileScope || Status == CommandLineIncludeScope) - return Scopes.back(); - return nullptr; -} - -SourceLocation MacroPPCallbacks::getCorrectLocation(SourceLocation Loc) { - if (Status == MainFileScope || EnteredCommandLineIncludeFiles) - return Loc; - - // While parsing skipped files, location of macros is invalid. - // Invalid location represents line zero. - return SourceLocation(); -} - -void MacroPPCallbacks::updateStatusToNextScope() { - switch (Status) { - case NoScope: - Status = InitializedScope; - break; - case InitializedScope: - Status = BuiltinScope; - break; - case BuiltinScope: - Status = CommandLineIncludeScope; - break; - case CommandLineIncludeScope: - Status = MainFileScope; - break; - case MainFileScope: - llvm_unreachable("There is no next scope, already in the final scope"); - } -} - -void MacroPPCallbacks::FileEntered(SourceLocation Loc) { - SourceLocation LineLoc = getCorrectLocation(LastHashLoc); - switch (Status) { - case NoScope: - updateStatusToNextScope(); - break; - case InitializedScope: - updateStatusToNextScope(); - return; - case BuiltinScope: - if (PP.getSourceManager().isWrittenInCommandLineFile(Loc)) - return; - updateStatusToNextScope(); - LLVM_FALLTHROUGH; - case CommandLineIncludeScope: - EnteredCommandLineIncludeFiles++; - break; - case MainFileScope: - break; - } - - Scopes.push_back(Gen->getCGDebugInfo()->CreateTempMacroFile(getCurrentScope(), - LineLoc, Loc)); -} - -void MacroPPCallbacks::FileExited(SourceLocation Loc) { - switch (Status) { - default: - llvm_unreachable("Do not expect to exit a file from current scope"); - case BuiltinScope: - if (!PP.getSourceManager().isWrittenInBuiltinFile(Loc)) - // Skip next scope and change status to MainFileScope. - Status = MainFileScope; - return; - case CommandLineIncludeScope: - if (!EnteredCommandLineIncludeFiles) { - updateStatusToNextScope(); - return; - } - EnteredCommandLineIncludeFiles--; - break; - case MainFileScope: - break; - } - - Scopes.pop_back(); -} - -void MacroPPCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason, - SrcMgr::CharacteristicKind FileType, - FileID PrevFID) { - // Only care about enter file or exit file changes. - if (Reason == EnterFile) - FileEntered(Loc); - else if (Reason == ExitFile) - FileExited(Loc); -} - -void MacroPPCallbacks::InclusionDirective( - SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, - bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File, - StringRef SearchPath, StringRef RelativePath, const Module *Imported, - SrcMgr::CharacteristicKind FileType) { - - // Record the line location of the current included file. - LastHashLoc = HashLoc; -} - -void MacroPPCallbacks::MacroDefined(const Token &MacroNameTok, - const MacroDirective *MD) { - IdentifierInfo *Id = MacroNameTok.getIdentifierInfo(); - SourceLocation location = getCorrectLocation(MacroNameTok.getLocation()); - std::string NameBuffer, ValueBuffer; - llvm::raw_string_ostream Name(NameBuffer); - llvm::raw_string_ostream Value(ValueBuffer); - writeMacroDefinition(*Id, *MD->getMacroInfo(), PP, Name, Value); - Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(), - llvm::dwarf::DW_MACINFO_define, location, - Name.str(), Value.str()); -} - -void MacroPPCallbacks::MacroUndefined(const Token &MacroNameTok, - const MacroDefinition &MD, - const MacroDirective *Undef) { - IdentifierInfo *Id = MacroNameTok.getIdentifierInfo(); - SourceLocation location = getCorrectLocation(MacroNameTok.getLocation()); - Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(), - llvm::dwarf::DW_MACINFO_undef, location, - Id->getName(), ""); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.h b/gnu/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.h deleted file mode 100644 index b87a4005d48..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.h +++ /dev/null @@ -1,123 +0,0 @@ -//===--- MacroPPCallbacks.h -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines implementation for the macro preprocessors callbacks. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_MACROPPCALLBACKS_H -#define LLVM_CLANG_LIB_CODEGEN_MACROPPCALLBACKS_H - -#include "clang/Lex/PPCallbacks.h" - -namespace llvm { -class DIMacroFile; -class DIMacroNode; -} -namespace clang { -class Preprocessor; -class MacroInfo; -class CodeGenerator; - -class MacroPPCallbacks : public PPCallbacks { - /// A pointer to code generator, where debug info generator can be found. - CodeGenerator *Gen; - - /// Preprocessor. - Preprocessor &PP; - - /// Location of recent included file, used for line number. - SourceLocation LastHashLoc; - - /// Counts current number of command line included files, which were entered - /// and were not exited yet. - int EnteredCommandLineIncludeFiles = 0; - - enum FileScopeStatus { - NoScope = 0, // Scope is not initialized yet. - InitializedScope, // Main file scope is initialized but not set yet. - BuiltinScope, // <built-in> and <command line> file scopes. - CommandLineIncludeScope, // Included file, from <command line> file, scope. - MainFileScope // Main file scope. - }; - FileScopeStatus Status; - - /// Parent contains all entered files that were not exited yet according to - /// the inclusion order. - llvm::SmallVector<llvm::DIMacroFile *, 4> Scopes; - - /// Get current DIMacroFile scope. - /// \return current DIMacroFile scope or nullptr if there is no such scope. - llvm::DIMacroFile *getCurrentScope(); - - /// Get current line location or invalid location. - /// \param Loc current line location. - /// \return current line location \p `Loc`, or invalid location if it's in a - /// skipped file scope. - SourceLocation getCorrectLocation(SourceLocation Loc); - - /// Use the passed preprocessor to write the macro name and value from the - /// given macro info and identifier info into the given \p `Name` and \p - /// `Value` output streams. - /// - /// \param II Identifier info, used to get the Macro name. - /// \param MI Macro info, used to get the Macro argumets and values. - /// \param PP Preprocessor. - /// \param [out] Name Place holder for returned macro name and arguments. - /// \param [out] Value Place holder for returned macro value. - static void writeMacroDefinition(const IdentifierInfo &II, - const MacroInfo &MI, Preprocessor &PP, - raw_ostream &Name, raw_ostream &Value); - - /// Update current file scope status to next file scope. - void updateStatusToNextScope(); - - /// Handle the case when entering a file. - /// - /// \param Loc Indicates the new location. - void FileEntered(SourceLocation Loc); - - /// Handle the case when exiting a file. - /// - /// \param Loc Indicates the new location. - void FileExited(SourceLocation Loc); - -public: - MacroPPCallbacks(CodeGenerator *Gen, Preprocessor &PP); - - /// Callback invoked whenever a source file is entered or exited. - /// - /// \param Loc Indicates the new location. - /// \param PrevFID the file that was exited if \p Reason is ExitFile. - void FileChanged(SourceLocation Loc, FileChangeReason Reason, - SrcMgr::CharacteristicKind FileType, - FileID PrevFID = FileID()) override; - - /// Callback invoked whenever a directive (#xxx) is processed. - void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, - StringRef FileName, bool IsAngled, - CharSourceRange FilenameRange, const FileEntry *File, - StringRef SearchPath, StringRef RelativePath, - const Module *Imported, - SrcMgr::CharacteristicKind FileType) override; - - /// Hook called whenever a macro definition is seen. - void MacroDefined(const Token &MacroNameTok, - const MacroDirective *MD) override; - - /// Hook called whenever a macro \#undef is seen. - /// - /// MD is released immediately following this callback. - void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD, - const MacroDirective *Undef) override; -}; - -} // end namespace clang - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/gnu/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp deleted file mode 100644 index 5545bc6647e..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ /dev/null @@ -1,4273 +0,0 @@ -//===--- MicrosoftCXXABI.cpp - Emit LLVM Code from ASTs for a Module ------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This provides C++ code generation targeting the Microsoft Visual C++ ABI. -// The class in this file generates structures that follow the Microsoft -// Visual C++ ABI, which is actually not very well documented at all outside -// of Microsoft. -// -//===----------------------------------------------------------------------===// - -#include "CGCXXABI.h" -#include "CGCleanup.h" -#include "CGVTables.h" -#include "CodeGenModule.h" -#include "CodeGenTypes.h" -#include "TargetInfo.h" -#include "clang/CodeGen/ConstantInitBuilder.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/StmtCXX.h" -#include "clang/AST/VTableBuilder.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringSet.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/Intrinsics.h" - -using namespace clang; -using namespace CodeGen; - -namespace { - -/// Holds all the vbtable globals for a given class. -struct VBTableGlobals { - const VPtrInfoVector *VBTables; - SmallVector<llvm::GlobalVariable *, 2> Globals; -}; - -class MicrosoftCXXABI : public CGCXXABI { -public: - MicrosoftCXXABI(CodeGenModule &CGM) - : CGCXXABI(CGM), BaseClassDescriptorType(nullptr), - ClassHierarchyDescriptorType(nullptr), - CompleteObjectLocatorType(nullptr), CatchableTypeType(nullptr), - ThrowInfoType(nullptr) {} - - bool HasThisReturn(GlobalDecl GD) const override; - bool hasMostDerivedReturn(GlobalDecl GD) const override; - - bool classifyReturnType(CGFunctionInfo &FI) const override; - - RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override; - - bool isSRetParameterAfterThis() const override { return true; } - - bool isThisCompleteObject(GlobalDecl GD) const override { - // The Microsoft ABI doesn't use separate complete-object vs. - // base-object variants of constructors, but it does of destructors. - if (isa<CXXDestructorDecl>(GD.getDecl())) { - switch (GD.getDtorType()) { - case Dtor_Complete: - case Dtor_Deleting: - return true; - - case Dtor_Base: - return false; - - case Dtor_Comdat: llvm_unreachable("emitting dtor comdat as function?"); - } - llvm_unreachable("bad dtor kind"); - } - - // No other kinds. - return false; - } - - size_t getSrcArgforCopyCtor(const CXXConstructorDecl *CD, - FunctionArgList &Args) const override { - assert(Args.size() >= 2 && - "expected the arglist to have at least two args!"); - // The 'most_derived' parameter goes second if the ctor is variadic and - // has v-bases. - if (CD->getParent()->getNumVBases() > 0 && - CD->getType()->castAs<FunctionProtoType>()->isVariadic()) - return 2; - return 1; - } - - std::vector<CharUnits> getVBPtrOffsets(const CXXRecordDecl *RD) override { - std::vector<CharUnits> VBPtrOffsets; - const ASTContext &Context = getContext(); - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - - const VBTableGlobals &VBGlobals = enumerateVBTables(RD); - for (const std::unique_ptr<VPtrInfo> &VBT : *VBGlobals.VBTables) { - const ASTRecordLayout &SubobjectLayout = - Context.getASTRecordLayout(VBT->IntroducingObject); - CharUnits Offs = VBT->NonVirtualOffset; - Offs += SubobjectLayout.getVBPtrOffset(); - if (VBT->getVBaseWithVPtr()) - Offs += Layout.getVBaseClassOffset(VBT->getVBaseWithVPtr()); - VBPtrOffsets.push_back(Offs); - } - llvm::array_pod_sort(VBPtrOffsets.begin(), VBPtrOffsets.end()); - return VBPtrOffsets; - } - - StringRef GetPureVirtualCallName() override { return "_purecall"; } - StringRef GetDeletedVirtualCallName() override { return "_purecall"; } - - void emitVirtualObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, - Address Ptr, QualType ElementType, - const CXXDestructorDecl *Dtor) override; - - void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) override; - void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) override; - - void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override; - - llvm::GlobalVariable *getMSCompleteObjectLocator(const CXXRecordDecl *RD, - const VPtrInfo &Info); - - llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override; - CatchTypeInfo - getAddrOfCXXCatchHandlerType(QualType Ty, QualType CatchHandlerType) override; - - /// MSVC needs an extra flag to indicate a catchall. - CatchTypeInfo getCatchAllTypeInfo() override { - return CatchTypeInfo{nullptr, 0x40}; - } - - bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy) override; - void EmitBadTypeidCall(CodeGenFunction &CGF) override; - llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy, - Address ThisPtr, - llvm::Type *StdTypeInfoPtrTy) override; - - bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr, - QualType SrcRecordTy) override; - - llvm::Value *EmitDynamicCastCall(CodeGenFunction &CGF, Address Value, - QualType SrcRecordTy, QualType DestTy, - QualType DestRecordTy, - llvm::BasicBlock *CastEnd) override; - - llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF, Address Value, - QualType SrcRecordTy, - QualType DestTy) override; - - bool EmitBadCastCall(CodeGenFunction &CGF) override; - bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override { - return false; - } - - llvm::Value * - GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This, - const CXXRecordDecl *ClassDecl, - const CXXRecordDecl *BaseClassDecl) override; - - llvm::BasicBlock * - EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, - const CXXRecordDecl *RD) override; - - llvm::BasicBlock * - EmitDtorCompleteObjectHandler(CodeGenFunction &CGF); - - void initializeHiddenVirtualInheritanceMembers(CodeGenFunction &CGF, - const CXXRecordDecl *RD) override; - - void EmitCXXConstructors(const CXXConstructorDecl *D) override; - - // Background on MSVC destructors - // ============================== - // - // Both Itanium and MSVC ABIs have destructor variants. The variant names - // roughly correspond in the following way: - // Itanium Microsoft - // Base -> no name, just ~Class - // Complete -> vbase destructor - // Deleting -> scalar deleting destructor - // vector deleting destructor - // - // The base and complete destructors are the same as in Itanium, although the - // complete destructor does not accept a VTT parameter when there are virtual - // bases. A separate mechanism involving vtordisps is used to ensure that - // virtual methods of destroyed subobjects are not called. - // - // The deleting destructors accept an i32 bitfield as a second parameter. Bit - // 1 indicates if the memory should be deleted. Bit 2 indicates if the this - // pointer points to an array. The scalar deleting destructor assumes that - // bit 2 is zero, and therefore does not contain a loop. - // - // For virtual destructors, only one entry is reserved in the vftable, and it - // always points to the vector deleting destructor. The vector deleting - // destructor is the most general, so it can be used to destroy objects in - // place, delete single heap objects, or delete arrays. - // - // A TU defining a non-inline destructor is only guaranteed to emit a base - // destructor, and all of the other variants are emitted on an as-needed basis - // in COMDATs. Because a non-base destructor can be emitted in a TU that - // lacks a definition for the destructor, non-base destructors must always - // delegate to or alias the base destructor. - - AddedStructorArgs - buildStructorSignature(const CXXMethodDecl *MD, StructorType T, - SmallVectorImpl<CanQualType> &ArgTys) override; - - /// Non-base dtors should be emitted as delegating thunks in this ABI. - bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor, - CXXDtorType DT) const override { - return DT != Dtor_Base; - } - - void setCXXDestructorDLLStorage(llvm::GlobalValue *GV, - const CXXDestructorDecl *Dtor, - CXXDtorType DT) const override; - - llvm::GlobalValue::LinkageTypes - getCXXDestructorLinkage(GVALinkage Linkage, const CXXDestructorDecl *Dtor, - CXXDtorType DT) const override; - - void EmitCXXDestructors(const CXXDestructorDecl *D) override; - - const CXXRecordDecl * - getThisArgumentTypeForMethod(const CXXMethodDecl *MD) override { - if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD)) { - MethodVFTableLocation ML = - CGM.getMicrosoftVTableContext().getMethodVFTableLocation(MD); - // The vbases might be ordered differently in the final overrider object - // and the complete object, so the "this" argument may sometimes point to - // memory that has no particular type (e.g. past the complete object). - // In this case, we just use a generic pointer type. - // FIXME: might want to have a more precise type in the non-virtual - // multiple inheritance case. - if (ML.VBase || !ML.VFPtrOffset.isZero()) - return nullptr; - } - return MD->getParent(); - } - - Address - adjustThisArgumentForVirtualFunctionCall(CodeGenFunction &CGF, GlobalDecl GD, - Address This, - bool VirtualCall) override; - - void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy, - FunctionArgList &Params) override; - - void EmitInstanceFunctionProlog(CodeGenFunction &CGF) override; - - AddedStructorArgs - addImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D, - CXXCtorType Type, bool ForVirtualBase, - bool Delegating, CallArgList &Args) override; - - void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, - CXXDtorType Type, bool ForVirtualBase, - bool Delegating, Address This) override; - - void emitVTableTypeMetadata(const VPtrInfo &Info, const CXXRecordDecl *RD, - llvm::GlobalVariable *VTable); - - void emitVTableDefinitions(CodeGenVTables &CGVT, - const CXXRecordDecl *RD) override; - - bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF, - CodeGenFunction::VPtr Vptr) override; - - /// Don't initialize vptrs if dynamic class - /// is marked with with the 'novtable' attribute. - bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass) override { - return !VTableClass->hasAttr<MSNoVTableAttr>(); - } - - llvm::Constant * - getVTableAddressPoint(BaseSubobject Base, - const CXXRecordDecl *VTableClass) override; - - llvm::Value *getVTableAddressPointInStructor( - CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, - BaseSubobject Base, const CXXRecordDecl *NearestVBase) override; - - llvm::Constant * - getVTableAddressPointForConstExpr(BaseSubobject Base, - const CXXRecordDecl *VTableClass) override; - - llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, - CharUnits VPtrOffset) override; - - CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD, - Address This, llvm::Type *Ty, - SourceLocation Loc) override; - - llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF, - const CXXDestructorDecl *Dtor, - CXXDtorType DtorType, - Address This, - const CXXMemberCallExpr *CE) override; - - void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD, - CallArgList &CallArgs) override { - assert(GD.getDtorType() == Dtor_Deleting && - "Only deleting destructor thunks are available in this ABI"); - CallArgs.add(RValue::get(getStructorImplicitParamValue(CGF)), - getContext().IntTy); - } - - void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override; - - llvm::GlobalVariable * - getAddrOfVBTable(const VPtrInfo &VBT, const CXXRecordDecl *RD, - llvm::GlobalVariable::LinkageTypes Linkage); - - llvm::GlobalVariable * - getAddrOfVirtualDisplacementMap(const CXXRecordDecl *SrcRD, - const CXXRecordDecl *DstRD) { - SmallString<256> OutName; - llvm::raw_svector_ostream Out(OutName); - getMangleContext().mangleCXXVirtualDisplacementMap(SrcRD, DstRD, Out); - StringRef MangledName = OutName.str(); - - if (auto *VDispMap = CGM.getModule().getNamedGlobal(MangledName)) - return VDispMap; - - MicrosoftVTableContext &VTContext = CGM.getMicrosoftVTableContext(); - unsigned NumEntries = 1 + SrcRD->getNumVBases(); - SmallVector<llvm::Constant *, 4> Map(NumEntries, - llvm::UndefValue::get(CGM.IntTy)); - Map[0] = llvm::ConstantInt::get(CGM.IntTy, 0); - bool AnyDifferent = false; - for (const auto &I : SrcRD->vbases()) { - const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl(); - if (!DstRD->isVirtuallyDerivedFrom(VBase)) - continue; - - unsigned SrcVBIndex = VTContext.getVBTableIndex(SrcRD, VBase); - unsigned DstVBIndex = VTContext.getVBTableIndex(DstRD, VBase); - Map[SrcVBIndex] = llvm::ConstantInt::get(CGM.IntTy, DstVBIndex * 4); - AnyDifferent |= SrcVBIndex != DstVBIndex; - } - // This map would be useless, don't use it. - if (!AnyDifferent) - return nullptr; - - llvm::ArrayType *VDispMapTy = llvm::ArrayType::get(CGM.IntTy, Map.size()); - llvm::Constant *Init = llvm::ConstantArray::get(VDispMapTy, Map); - llvm::GlobalValue::LinkageTypes Linkage = - SrcRD->isExternallyVisible() && DstRD->isExternallyVisible() - ? llvm::GlobalValue::LinkOnceODRLinkage - : llvm::GlobalValue::InternalLinkage; - auto *VDispMap = new llvm::GlobalVariable( - CGM.getModule(), VDispMapTy, /*Constant=*/true, Linkage, - /*Initializer=*/Init, MangledName); - return VDispMap; - } - - void emitVBTableDefinition(const VPtrInfo &VBT, const CXXRecordDecl *RD, - llvm::GlobalVariable *GV) const; - - void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, - GlobalDecl GD, bool ReturnAdjustment) override { - GVALinkage Linkage = - getContext().GetGVALinkageForFunction(cast<FunctionDecl>(GD.getDecl())); - - if (Linkage == GVA_Internal) - Thunk->setLinkage(llvm::GlobalValue::InternalLinkage); - else if (ReturnAdjustment) - Thunk->setLinkage(llvm::GlobalValue::WeakODRLinkage); - else - Thunk->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage); - } - - bool exportThunk() override { return false; } - - llvm::Value *performThisAdjustment(CodeGenFunction &CGF, Address This, - const ThisAdjustment &TA) override; - - llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, Address Ret, - const ReturnAdjustment &RA) override; - - void EmitThreadLocalInitFuncs( - CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals, - ArrayRef<llvm::Function *> CXXThreadLocalInits, - ArrayRef<const VarDecl *> CXXThreadLocalInitVars) override; - - bool usesThreadWrapperFunction() const override { return false; } - LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD, - QualType LValType) override; - - void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, - llvm::GlobalVariable *DeclPtr, - bool PerformInit) override; - void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, - llvm::Constant *Dtor, llvm::Constant *Addr) override; - - // ==== Notes on array cookies ========= - // - // MSVC seems to only use cookies when the class has a destructor; a - // two-argument usual array deallocation function isn't sufficient. - // - // For example, this code prints "100" and "1": - // struct A { - // char x; - // void *operator new[](size_t sz) { - // printf("%u\n", sz); - // return malloc(sz); - // } - // void operator delete[](void *p, size_t sz) { - // printf("%u\n", sz); - // free(p); - // } - // }; - // int main() { - // A *p = new A[100]; - // delete[] p; - // } - // Whereas it prints "104" and "104" if you give A a destructor. - - bool requiresArrayCookie(const CXXDeleteExpr *expr, - QualType elementType) override; - bool requiresArrayCookie(const CXXNewExpr *expr) override; - CharUnits getArrayCookieSizeImpl(QualType type) override; - Address InitializeArrayCookie(CodeGenFunction &CGF, - Address NewPtr, - llvm::Value *NumElements, - const CXXNewExpr *expr, - QualType ElementType) override; - llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, - Address allocPtr, - CharUnits cookieSize) override; - - friend struct MSRTTIBuilder; - - bool isImageRelative() const { - return CGM.getTarget().getPointerWidth(/*AddressSpace=*/0) == 64; - } - - // 5 routines for constructing the llvm types for MS RTTI structs. - llvm::StructType *getTypeDescriptorType(StringRef TypeInfoString) { - llvm::SmallString<32> TDTypeName("rtti.TypeDescriptor"); - TDTypeName += llvm::utostr(TypeInfoString.size()); - llvm::StructType *&TypeDescriptorType = - TypeDescriptorTypeMap[TypeInfoString.size()]; - if (TypeDescriptorType) - return TypeDescriptorType; - llvm::Type *FieldTypes[] = { - CGM.Int8PtrPtrTy, - CGM.Int8PtrTy, - llvm::ArrayType::get(CGM.Int8Ty, TypeInfoString.size() + 1)}; - TypeDescriptorType = - llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, TDTypeName); - return TypeDescriptorType; - } - - llvm::Type *getImageRelativeType(llvm::Type *PtrType) { - if (!isImageRelative()) - return PtrType; - return CGM.IntTy; - } - - llvm::StructType *getBaseClassDescriptorType() { - if (BaseClassDescriptorType) - return BaseClassDescriptorType; - llvm::Type *FieldTypes[] = { - getImageRelativeType(CGM.Int8PtrTy), - CGM.IntTy, - CGM.IntTy, - CGM.IntTy, - CGM.IntTy, - CGM.IntTy, - getImageRelativeType(getClassHierarchyDescriptorType()->getPointerTo()), - }; - BaseClassDescriptorType = llvm::StructType::create( - CGM.getLLVMContext(), FieldTypes, "rtti.BaseClassDescriptor"); - return BaseClassDescriptorType; - } - - llvm::StructType *getClassHierarchyDescriptorType() { - if (ClassHierarchyDescriptorType) - return ClassHierarchyDescriptorType; - // Forward-declare RTTIClassHierarchyDescriptor to break a cycle. - ClassHierarchyDescriptorType = llvm::StructType::create( - CGM.getLLVMContext(), "rtti.ClassHierarchyDescriptor"); - llvm::Type *FieldTypes[] = { - CGM.IntTy, - CGM.IntTy, - CGM.IntTy, - getImageRelativeType( - getBaseClassDescriptorType()->getPointerTo()->getPointerTo()), - }; - ClassHierarchyDescriptorType->setBody(FieldTypes); - return ClassHierarchyDescriptorType; - } - - llvm::StructType *getCompleteObjectLocatorType() { - if (CompleteObjectLocatorType) - return CompleteObjectLocatorType; - CompleteObjectLocatorType = llvm::StructType::create( - CGM.getLLVMContext(), "rtti.CompleteObjectLocator"); - llvm::Type *FieldTypes[] = { - CGM.IntTy, - CGM.IntTy, - CGM.IntTy, - getImageRelativeType(CGM.Int8PtrTy), - getImageRelativeType(getClassHierarchyDescriptorType()->getPointerTo()), - getImageRelativeType(CompleteObjectLocatorType), - }; - llvm::ArrayRef<llvm::Type *> FieldTypesRef(FieldTypes); - if (!isImageRelative()) - FieldTypesRef = FieldTypesRef.drop_back(); - CompleteObjectLocatorType->setBody(FieldTypesRef); - return CompleteObjectLocatorType; - } - - llvm::GlobalVariable *getImageBase() { - StringRef Name = "__ImageBase"; - if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name)) - return GV; - - auto *GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8Ty, - /*isConstant=*/true, - llvm::GlobalValue::ExternalLinkage, - /*Initializer=*/nullptr, Name); - CGM.setDSOLocal(GV); - return GV; - } - - llvm::Constant *getImageRelativeConstant(llvm::Constant *PtrVal) { - if (!isImageRelative()) - return PtrVal; - - if (PtrVal->isNullValue()) - return llvm::Constant::getNullValue(CGM.IntTy); - - llvm::Constant *ImageBaseAsInt = - llvm::ConstantExpr::getPtrToInt(getImageBase(), CGM.IntPtrTy); - llvm::Constant *PtrValAsInt = - llvm::ConstantExpr::getPtrToInt(PtrVal, CGM.IntPtrTy); - llvm::Constant *Diff = - llvm::ConstantExpr::getSub(PtrValAsInt, ImageBaseAsInt, - /*HasNUW=*/true, /*HasNSW=*/true); - return llvm::ConstantExpr::getTrunc(Diff, CGM.IntTy); - } - -private: - MicrosoftMangleContext &getMangleContext() { - return cast<MicrosoftMangleContext>(CodeGen::CGCXXABI::getMangleContext()); - } - - llvm::Constant *getZeroInt() { - return llvm::ConstantInt::get(CGM.IntTy, 0); - } - - llvm::Constant *getAllOnesInt() { - return llvm::Constant::getAllOnesValue(CGM.IntTy); - } - - CharUnits getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD) override; - - void - GetNullMemberPointerFields(const MemberPointerType *MPT, - llvm::SmallVectorImpl<llvm::Constant *> &fields); - - /// Shared code for virtual base adjustment. Returns the offset from - /// the vbptr to the virtual base. Optionally returns the address of the - /// vbptr itself. - llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF, - Address Base, - llvm::Value *VBPtrOffset, - llvm::Value *VBTableOffset, - llvm::Value **VBPtr = nullptr); - - llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF, - Address Base, - int32_t VBPtrOffset, - int32_t VBTableOffset, - llvm::Value **VBPtr = nullptr) { - assert(VBTableOffset % 4 == 0 && "should be byte offset into table of i32s"); - llvm::Value *VBPOffset = llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset), - *VBTOffset = llvm::ConstantInt::get(CGM.IntTy, VBTableOffset); - return GetVBaseOffsetFromVBPtr(CGF, Base, VBPOffset, VBTOffset, VBPtr); - } - - std::tuple<Address, llvm::Value *, const CXXRecordDecl *> - performBaseAdjustment(CodeGenFunction &CGF, Address Value, - QualType SrcRecordTy); - - /// Performs a full virtual base adjustment. Used to dereference - /// pointers to members of virtual bases. - llvm::Value *AdjustVirtualBase(CodeGenFunction &CGF, const Expr *E, - const CXXRecordDecl *RD, Address Base, - llvm::Value *VirtualBaseAdjustmentOffset, - llvm::Value *VBPtrOffset /* optional */); - - /// Emits a full member pointer with the fields common to data and - /// function member pointers. - llvm::Constant *EmitFullMemberPointer(llvm::Constant *FirstField, - bool IsMemberFunction, - const CXXRecordDecl *RD, - CharUnits NonVirtualBaseAdjustment, - unsigned VBTableIndex); - - bool MemberPointerConstantIsNull(const MemberPointerType *MPT, - llvm::Constant *MP); - - /// - Initialize all vbptrs of 'this' with RD as the complete type. - void EmitVBPtrStores(CodeGenFunction &CGF, const CXXRecordDecl *RD); - - /// Caching wrapper around VBTableBuilder::enumerateVBTables(). - const VBTableGlobals &enumerateVBTables(const CXXRecordDecl *RD); - - /// Generate a thunk for calling a virtual member function MD. - llvm::Function *EmitVirtualMemPtrThunk(const CXXMethodDecl *MD, - const MethodVFTableLocation &ML); - -public: - llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT) override; - - bool isZeroInitializable(const MemberPointerType *MPT) override; - - bool isMemberPointerConvertible(const MemberPointerType *MPT) const override { - const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); - return RD->hasAttr<MSInheritanceAttr>(); - } - - llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT) override; - - llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT, - CharUnits offset) override; - llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD) override; - llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT) override; - - llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF, - llvm::Value *L, - llvm::Value *R, - const MemberPointerType *MPT, - bool Inequality) override; - - llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF, - llvm::Value *MemPtr, - const MemberPointerType *MPT) override; - - llvm::Value * - EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E, - Address Base, llvm::Value *MemPtr, - const MemberPointerType *MPT) override; - - llvm::Value *EmitNonNullMemberPointerConversion( - const MemberPointerType *SrcTy, const MemberPointerType *DstTy, - CastKind CK, CastExpr::path_const_iterator PathBegin, - CastExpr::path_const_iterator PathEnd, llvm::Value *Src, - CGBuilderTy &Builder); - - llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF, - const CastExpr *E, - llvm::Value *Src) override; - - llvm::Constant *EmitMemberPointerConversion(const CastExpr *E, - llvm::Constant *Src) override; - - llvm::Constant *EmitMemberPointerConversion( - const MemberPointerType *SrcTy, const MemberPointerType *DstTy, - CastKind CK, CastExpr::path_const_iterator PathBegin, - CastExpr::path_const_iterator PathEnd, llvm::Constant *Src); - - CGCallee - EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E, - Address This, llvm::Value *&ThisPtrForCall, - llvm::Value *MemPtr, - const MemberPointerType *MPT) override; - - void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override; - - llvm::StructType *getCatchableTypeType() { - if (CatchableTypeType) - return CatchableTypeType; - llvm::Type *FieldTypes[] = { - CGM.IntTy, // Flags - getImageRelativeType(CGM.Int8PtrTy), // TypeDescriptor - CGM.IntTy, // NonVirtualAdjustment - CGM.IntTy, // OffsetToVBPtr - CGM.IntTy, // VBTableIndex - CGM.IntTy, // Size - getImageRelativeType(CGM.Int8PtrTy) // CopyCtor - }; - CatchableTypeType = llvm::StructType::create( - CGM.getLLVMContext(), FieldTypes, "eh.CatchableType"); - return CatchableTypeType; - } - - llvm::StructType *getCatchableTypeArrayType(uint32_t NumEntries) { - llvm::StructType *&CatchableTypeArrayType = - CatchableTypeArrayTypeMap[NumEntries]; - if (CatchableTypeArrayType) - return CatchableTypeArrayType; - - llvm::SmallString<23> CTATypeName("eh.CatchableTypeArray."); - CTATypeName += llvm::utostr(NumEntries); - llvm::Type *CTType = - getImageRelativeType(getCatchableTypeType()->getPointerTo()); - llvm::Type *FieldTypes[] = { - CGM.IntTy, // NumEntries - llvm::ArrayType::get(CTType, NumEntries) // CatchableTypes - }; - CatchableTypeArrayType = - llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, CTATypeName); - return CatchableTypeArrayType; - } - - llvm::StructType *getThrowInfoType() { - if (ThrowInfoType) - return ThrowInfoType; - llvm::Type *FieldTypes[] = { - CGM.IntTy, // Flags - getImageRelativeType(CGM.Int8PtrTy), // CleanupFn - getImageRelativeType(CGM.Int8PtrTy), // ForwardCompat - getImageRelativeType(CGM.Int8PtrTy) // CatchableTypeArray - }; - ThrowInfoType = llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, - "eh.ThrowInfo"); - return ThrowInfoType; - } - - llvm::Constant *getThrowFn() { - // _CxxThrowException is passed an exception object and a ThrowInfo object - // which describes the exception. - llvm::Type *Args[] = {CGM.Int8PtrTy, getThrowInfoType()->getPointerTo()}; - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, Args, /*IsVarArgs=*/false); - auto *Fn = cast<llvm::Function>( - CGM.CreateRuntimeFunction(FTy, "_CxxThrowException")); - // _CxxThrowException is stdcall on 32-bit x86 platforms. - if (CGM.getTarget().getTriple().getArch() == llvm::Triple::x86) - Fn->setCallingConv(llvm::CallingConv::X86_StdCall); - return Fn; - } - - llvm::Function *getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD, - CXXCtorType CT); - - llvm::Constant *getCatchableType(QualType T, - uint32_t NVOffset = 0, - int32_t VBPtrOffset = -1, - uint32_t VBIndex = 0); - - llvm::GlobalVariable *getCatchableTypeArray(QualType T); - - llvm::GlobalVariable *getThrowInfo(QualType T) override; - - std::pair<llvm::Value *, const CXXRecordDecl *> - LoadVTablePtr(CodeGenFunction &CGF, Address This, - const CXXRecordDecl *RD) override; - -private: - typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy; - typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *> VTablesMapTy; - typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalValue *> VFTablesMapTy; - /// All the vftables that have been referenced. - VFTablesMapTy VFTablesMap; - VTablesMapTy VTablesMap; - - /// This set holds the record decls we've deferred vtable emission for. - llvm::SmallPtrSet<const CXXRecordDecl *, 4> DeferredVFTables; - - - /// All the vbtables which have been referenced. - llvm::DenseMap<const CXXRecordDecl *, VBTableGlobals> VBTablesMap; - - /// Info on the global variable used to guard initialization of static locals. - /// The BitIndex field is only used for externally invisible declarations. - struct GuardInfo { - GuardInfo() : Guard(nullptr), BitIndex(0) {} - llvm::GlobalVariable *Guard; - unsigned BitIndex; - }; - - /// Map from DeclContext to the current guard variable. We assume that the - /// AST is visited in source code order. - llvm::DenseMap<const DeclContext *, GuardInfo> GuardVariableMap; - llvm::DenseMap<const DeclContext *, GuardInfo> ThreadLocalGuardVariableMap; - llvm::DenseMap<const DeclContext *, unsigned> ThreadSafeGuardNumMap; - - llvm::DenseMap<size_t, llvm::StructType *> TypeDescriptorTypeMap; - llvm::StructType *BaseClassDescriptorType; - llvm::StructType *ClassHierarchyDescriptorType; - llvm::StructType *CompleteObjectLocatorType; - - llvm::DenseMap<QualType, llvm::GlobalVariable *> CatchableTypeArrays; - - llvm::StructType *CatchableTypeType; - llvm::DenseMap<uint32_t, llvm::StructType *> CatchableTypeArrayTypeMap; - llvm::StructType *ThrowInfoType; -}; - -} - -CGCXXABI::RecordArgABI -MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const { - switch (CGM.getTarget().getTriple().getArch()) { - default: - // FIXME: Implement for other architectures. - return RAA_Default; - - case llvm::Triple::thumb: - // Use the simple Itanium rules for now. - // FIXME: This is incompatible with MSVC for arguments with a dtor and no - // copy ctor. - return !canCopyArgument(RD) ? RAA_Indirect : RAA_Default; - - case llvm::Triple::x86: - // All record arguments are passed in memory on x86. Decide whether to - // construct the object directly in argument memory, or to construct the - // argument elsewhere and copy the bytes during the call. - - // If C++ prohibits us from making a copy, construct the arguments directly - // into argument memory. - if (!canCopyArgument(RD)) - return RAA_DirectInMemory; - - // Otherwise, construct the argument into a temporary and copy the bytes - // into the outgoing argument memory. - return RAA_Default; - - case llvm::Triple::x86_64: - case llvm::Triple::aarch64: - return !canCopyArgument(RD) ? RAA_Indirect : RAA_Default; - } - - llvm_unreachable("invalid enum"); -} - -void MicrosoftCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, - const CXXDeleteExpr *DE, - Address Ptr, - QualType ElementType, - const CXXDestructorDecl *Dtor) { - // FIXME: Provide a source location here even though there's no - // CXXMemberCallExpr for dtor call. - bool UseGlobalDelete = DE->isGlobalDelete(); - CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting; - llvm::Value *MDThis = - EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, /*CE=*/nullptr); - if (UseGlobalDelete) - CGF.EmitDeleteCall(DE->getOperatorDelete(), MDThis, ElementType); -} - -void MicrosoftCXXABI::emitRethrow(CodeGenFunction &CGF, bool isNoReturn) { - llvm::Value *Args[] = { - llvm::ConstantPointerNull::get(CGM.Int8PtrTy), - llvm::ConstantPointerNull::get(getThrowInfoType()->getPointerTo())}; - auto *Fn = getThrowFn(); - if (isNoReturn) - CGF.EmitNoreturnRuntimeCallOrInvoke(Fn, Args); - else - CGF.EmitRuntimeCallOrInvoke(Fn, Args); -} - -void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF, - const CXXCatchStmt *S) { - // In the MS ABI, the runtime handles the copy, and the catch handler is - // responsible for destruction. - VarDecl *CatchParam = S->getExceptionDecl(); - llvm::BasicBlock *CatchPadBB = CGF.Builder.GetInsertBlock(); - llvm::CatchPadInst *CPI = - cast<llvm::CatchPadInst>(CatchPadBB->getFirstNonPHI()); - CGF.CurrentFuncletPad = CPI; - - // If this is a catch-all or the catch parameter is unnamed, we don't need to - // emit an alloca to the object. - if (!CatchParam || !CatchParam->getDeclName()) { - CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI); - return; - } - - CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam); - CPI->setArgOperand(2, var.getObjectAddress(CGF).getPointer()); - CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI); - CGF.EmitAutoVarCleanups(var); -} - -/// We need to perform a generic polymorphic operation (like a typeid -/// or a cast), which requires an object with a vfptr. Adjust the -/// address to point to an object with a vfptr. -std::tuple<Address, llvm::Value *, const CXXRecordDecl *> -MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address Value, - QualType SrcRecordTy) { - Value = CGF.Builder.CreateBitCast(Value, CGF.Int8PtrTy); - const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl(); - const ASTContext &Context = getContext(); - - // If the class itself has a vfptr, great. This check implicitly - // covers non-virtual base subobjects: a class with its own virtual - // functions would be a candidate to be a primary base. - if (Context.getASTRecordLayout(SrcDecl).hasExtendableVFPtr()) - return std::make_tuple(Value, llvm::ConstantInt::get(CGF.Int32Ty, 0), - SrcDecl); - - // Okay, one of the vbases must have a vfptr, or else this isn't - // actually a polymorphic class. - const CXXRecordDecl *PolymorphicBase = nullptr; - for (auto &Base : SrcDecl->vbases()) { - const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); - if (Context.getASTRecordLayout(BaseDecl).hasExtendableVFPtr()) { - PolymorphicBase = BaseDecl; - break; - } - } - assert(PolymorphicBase && "polymorphic class has no apparent vfptr?"); - - llvm::Value *Offset = - GetVirtualBaseClassOffset(CGF, Value, SrcDecl, PolymorphicBase); - llvm::Value *Ptr = CGF.Builder.CreateInBoundsGEP(Value.getPointer(), Offset); - CharUnits VBaseAlign = - CGF.CGM.getVBaseAlignment(Value.getAlignment(), SrcDecl, PolymorphicBase); - return std::make_tuple(Address(Ptr, VBaseAlign), Offset, PolymorphicBase); -} - -bool MicrosoftCXXABI::shouldTypeidBeNullChecked(bool IsDeref, - QualType SrcRecordTy) { - const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl(); - return IsDeref && - !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr(); -} - -static llvm::CallSite emitRTtypeidCall(CodeGenFunction &CGF, - llvm::Value *Argument) { - llvm::Type *ArgTypes[] = {CGF.Int8PtrTy}; - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false); - llvm::Value *Args[] = {Argument}; - llvm::Constant *Fn = CGF.CGM.CreateRuntimeFunction(FTy, "__RTtypeid"); - return CGF.EmitRuntimeCallOrInvoke(Fn, Args); -} - -void MicrosoftCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) { - llvm::CallSite Call = - emitRTtypeidCall(CGF, llvm::Constant::getNullValue(CGM.VoidPtrTy)); - Call.setDoesNotReturn(); - CGF.Builder.CreateUnreachable(); -} - -llvm::Value *MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF, - QualType SrcRecordTy, - Address ThisPtr, - llvm::Type *StdTypeInfoPtrTy) { - std::tie(ThisPtr, std::ignore, std::ignore) = - performBaseAdjustment(CGF, ThisPtr, SrcRecordTy); - auto Typeid = emitRTtypeidCall(CGF, ThisPtr.getPointer()).getInstruction(); - return CGF.Builder.CreateBitCast(Typeid, StdTypeInfoPtrTy); -} - -bool MicrosoftCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr, - QualType SrcRecordTy) { - const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl(); - return SrcIsPtr && - !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr(); -} - -llvm::Value *MicrosoftCXXABI::EmitDynamicCastCall( - CodeGenFunction &CGF, Address This, QualType SrcRecordTy, - QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd) { - llvm::Type *DestLTy = CGF.ConvertType(DestTy); - - llvm::Value *SrcRTTI = - CGF.CGM.GetAddrOfRTTIDescriptor(SrcRecordTy.getUnqualifiedType()); - llvm::Value *DestRTTI = - CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType()); - - llvm::Value *Offset; - std::tie(This, Offset, std::ignore) = - performBaseAdjustment(CGF, This, SrcRecordTy); - llvm::Value *ThisPtr = This.getPointer(); - Offset = CGF.Builder.CreateTrunc(Offset, CGF.Int32Ty); - - // PVOID __RTDynamicCast( - // PVOID inptr, - // LONG VfDelta, - // PVOID SrcType, - // PVOID TargetType, - // BOOL isReference) - llvm::Type *ArgTypes[] = {CGF.Int8PtrTy, CGF.Int32Ty, CGF.Int8PtrTy, - CGF.Int8PtrTy, CGF.Int32Ty}; - llvm::Constant *Function = CGF.CGM.CreateRuntimeFunction( - llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false), - "__RTDynamicCast"); - llvm::Value *Args[] = { - ThisPtr, Offset, SrcRTTI, DestRTTI, - llvm::ConstantInt::get(CGF.Int32Ty, DestTy->isReferenceType())}; - ThisPtr = CGF.EmitRuntimeCallOrInvoke(Function, Args).getInstruction(); - return CGF.Builder.CreateBitCast(ThisPtr, DestLTy); -} - -llvm::Value * -MicrosoftCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF, Address Value, - QualType SrcRecordTy, - QualType DestTy) { - std::tie(Value, std::ignore, std::ignore) = - performBaseAdjustment(CGF, Value, SrcRecordTy); - - // PVOID __RTCastToVoid( - // PVOID inptr) - llvm::Type *ArgTypes[] = {CGF.Int8PtrTy}; - llvm::Constant *Function = CGF.CGM.CreateRuntimeFunction( - llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false), - "__RTCastToVoid"); - llvm::Value *Args[] = {Value.getPointer()}; - return CGF.EmitRuntimeCall(Function, Args); -} - -bool MicrosoftCXXABI::EmitBadCastCall(CodeGenFunction &CGF) { - return false; -} - -llvm::Value *MicrosoftCXXABI::GetVirtualBaseClassOffset( - CodeGenFunction &CGF, Address This, const CXXRecordDecl *ClassDecl, - const CXXRecordDecl *BaseClassDecl) { - const ASTContext &Context = getContext(); - int64_t VBPtrChars = - Context.getASTRecordLayout(ClassDecl).getVBPtrOffset().getQuantity(); - llvm::Value *VBPtrOffset = llvm::ConstantInt::get(CGM.PtrDiffTy, VBPtrChars); - CharUnits IntSize = Context.getTypeSizeInChars(Context.IntTy); - CharUnits VBTableChars = - IntSize * - CGM.getMicrosoftVTableContext().getVBTableIndex(ClassDecl, BaseClassDecl); - llvm::Value *VBTableOffset = - llvm::ConstantInt::get(CGM.IntTy, VBTableChars.getQuantity()); - - llvm::Value *VBPtrToNewBase = - GetVBaseOffsetFromVBPtr(CGF, This, VBPtrOffset, VBTableOffset); - VBPtrToNewBase = - CGF.Builder.CreateSExtOrBitCast(VBPtrToNewBase, CGM.PtrDiffTy); - return CGF.Builder.CreateNSWAdd(VBPtrOffset, VBPtrToNewBase); -} - -bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD) const { - return isa<CXXConstructorDecl>(GD.getDecl()); -} - -static bool isDeletingDtor(GlobalDecl GD) { - return isa<CXXDestructorDecl>(GD.getDecl()) && - GD.getDtorType() == Dtor_Deleting; -} - -bool MicrosoftCXXABI::hasMostDerivedReturn(GlobalDecl GD) const { - return isDeletingDtor(GD); -} - -bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI) const { - const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl(); - if (!RD) - return false; - - CharUnits Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType()); - if (FI.isInstanceMethod()) { - // If it's an instance method, aggregates are always returned indirectly via - // the second parameter. - FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false); - FI.getReturnInfo().setSRetAfterThis(FI.isInstanceMethod()); - - // aarch64-windows requires that instance methods use X1 for the return - // address. So for aarch64-windows we do not mark the - // return as SRet. - FI.getReturnInfo().setSuppressSRet(CGM.getTarget().getTriple().getArch() == - llvm::Triple::aarch64); - return true; - } else if (!RD->isPOD()) { - // If it's a free function, non-POD types are returned indirectly. - FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false); - - // aarch64-windows requires that non-POD, non-instance returns use X0 for - // the return address. So for aarch64-windows we do not mark the return as - // SRet. - FI.getReturnInfo().setSuppressSRet(CGM.getTarget().getTriple().getArch() == - llvm::Triple::aarch64); - return true; - } - - // Otherwise, use the C ABI rules. - return false; -} - -llvm::BasicBlock * -MicrosoftCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, - const CXXRecordDecl *RD) { - llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF); - assert(IsMostDerivedClass && - "ctor for a class with virtual bases must have an implicit parameter"); - llvm::Value *IsCompleteObject = - CGF.Builder.CreateIsNotNull(IsMostDerivedClass, "is_complete_object"); - - llvm::BasicBlock *CallVbaseCtorsBB = CGF.createBasicBlock("ctor.init_vbases"); - llvm::BasicBlock *SkipVbaseCtorsBB = CGF.createBasicBlock("ctor.skip_vbases"); - CGF.Builder.CreateCondBr(IsCompleteObject, - CallVbaseCtorsBB, SkipVbaseCtorsBB); - - CGF.EmitBlock(CallVbaseCtorsBB); - - // Fill in the vbtable pointers here. - EmitVBPtrStores(CGF, RD); - - // CGF will put the base ctor calls in this basic block for us later. - - return SkipVbaseCtorsBB; -} - -llvm::BasicBlock * -MicrosoftCXXABI::EmitDtorCompleteObjectHandler(CodeGenFunction &CGF) { - llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF); - assert(IsMostDerivedClass && - "ctor for a class with virtual bases must have an implicit parameter"); - llvm::Value *IsCompleteObject = - CGF.Builder.CreateIsNotNull(IsMostDerivedClass, "is_complete_object"); - - llvm::BasicBlock *CallVbaseDtorsBB = CGF.createBasicBlock("Dtor.dtor_vbases"); - llvm::BasicBlock *SkipVbaseDtorsBB = CGF.createBasicBlock("Dtor.skip_vbases"); - CGF.Builder.CreateCondBr(IsCompleteObject, - CallVbaseDtorsBB, SkipVbaseDtorsBB); - - CGF.EmitBlock(CallVbaseDtorsBB); - // CGF will put the base dtor calls in this basic block for us later. - - return SkipVbaseDtorsBB; -} - -void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers( - CodeGenFunction &CGF, const CXXRecordDecl *RD) { - // In most cases, an override for a vbase virtual method can adjust - // the "this" parameter by applying a constant offset. - // However, this is not enough while a constructor or a destructor of some - // class X is being executed if all the following conditions are met: - // - X has virtual bases, (1) - // - X overrides a virtual method M of a vbase Y, (2) - // - X itself is a vbase of the most derived class. - // - // If (1) and (2) are true, the vtorDisp for vbase Y is a hidden member of X - // which holds the extra amount of "this" adjustment we must do when we use - // the X vftables (i.e. during X ctor or dtor). - // Outside the ctors and dtors, the values of vtorDisps are zero. - - const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); - typedef ASTRecordLayout::VBaseOffsetsMapTy VBOffsets; - const VBOffsets &VBaseMap = Layout.getVBaseOffsetsMap(); - CGBuilderTy &Builder = CGF.Builder; - - unsigned AS = getThisAddress(CGF).getAddressSpace(); - llvm::Value *Int8This = nullptr; // Initialize lazily. - - for (const CXXBaseSpecifier &S : RD->vbases()) { - const CXXRecordDecl *VBase = S.getType()->getAsCXXRecordDecl(); - auto I = VBaseMap.find(VBase); - assert(I != VBaseMap.end()); - if (!I->second.hasVtorDisp()) - continue; - - llvm::Value *VBaseOffset = - GetVirtualBaseClassOffset(CGF, getThisAddress(CGF), RD, VBase); - uint64_t ConstantVBaseOffset = I->second.VBaseOffset.getQuantity(); - - // vtorDisp_for_vbase = vbptr[vbase_idx] - offsetof(RD, vbase). - llvm::Value *VtorDispValue = Builder.CreateSub( - VBaseOffset, llvm::ConstantInt::get(CGM.PtrDiffTy, ConstantVBaseOffset), - "vtordisp.value"); - VtorDispValue = Builder.CreateTruncOrBitCast(VtorDispValue, CGF.Int32Ty); - - if (!Int8This) - Int8This = Builder.CreateBitCast(getThisValue(CGF), - CGF.Int8Ty->getPointerTo(AS)); - llvm::Value *VtorDispPtr = Builder.CreateInBoundsGEP(Int8This, VBaseOffset); - // vtorDisp is always the 32-bits before the vbase in the class layout. - VtorDispPtr = Builder.CreateConstGEP1_32(VtorDispPtr, -4); - VtorDispPtr = Builder.CreateBitCast( - VtorDispPtr, CGF.Int32Ty->getPointerTo(AS), "vtordisp.ptr"); - - Builder.CreateAlignedStore(VtorDispValue, VtorDispPtr, - CharUnits::fromQuantity(4)); - } -} - -static bool hasDefaultCXXMethodCC(ASTContext &Context, - const CXXMethodDecl *MD) { - CallingConv ExpectedCallingConv = Context.getDefaultCallingConvention( - /*IsVariadic=*/false, /*IsCXXMethod=*/true); - CallingConv ActualCallingConv = - MD->getType()->getAs<FunctionProtoType>()->getCallConv(); - return ExpectedCallingConv == ActualCallingConv; -} - -void MicrosoftCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) { - // There's only one constructor type in this ABI. - CGM.EmitGlobal(GlobalDecl(D, Ctor_Complete)); - - // Exported default constructors either have a simple call-site where they use - // the typical calling convention and have a single 'this' pointer for an - // argument -or- they get a wrapper function which appropriately thunks to the - // real default constructor. This thunk is the default constructor closure. - if (D->hasAttr<DLLExportAttr>() && D->isDefaultConstructor()) - if (!hasDefaultCXXMethodCC(getContext(), D) || D->getNumParams() != 0) { - llvm::Function *Fn = getAddrOfCXXCtorClosure(D, Ctor_DefaultClosure); - Fn->setLinkage(llvm::GlobalValue::WeakODRLinkage); - CGM.setGVProperties(Fn, D); - } -} - -void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF, - const CXXRecordDecl *RD) { - Address This = getThisAddress(CGF); - This = CGF.Builder.CreateElementBitCast(This, CGM.Int8Ty, "this.int8"); - const ASTContext &Context = getContext(); - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - - const VBTableGlobals &VBGlobals = enumerateVBTables(RD); - for (unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) { - const std::unique_ptr<VPtrInfo> &VBT = (*VBGlobals.VBTables)[I]; - llvm::GlobalVariable *GV = VBGlobals.Globals[I]; - const ASTRecordLayout &SubobjectLayout = - Context.getASTRecordLayout(VBT->IntroducingObject); - CharUnits Offs = VBT->NonVirtualOffset; - Offs += SubobjectLayout.getVBPtrOffset(); - if (VBT->getVBaseWithVPtr()) - Offs += Layout.getVBaseClassOffset(VBT->getVBaseWithVPtr()); - Address VBPtr = CGF.Builder.CreateConstInBoundsByteGEP(This, Offs); - llvm::Value *GVPtr = - CGF.Builder.CreateConstInBoundsGEP2_32(GV->getValueType(), GV, 0, 0); - VBPtr = CGF.Builder.CreateElementBitCast(VBPtr, GVPtr->getType(), - "vbptr." + VBT->ObjectWithVPtr->getName()); - CGF.Builder.CreateStore(GVPtr, VBPtr); - } -} - -CGCXXABI::AddedStructorArgs -MicrosoftCXXABI::buildStructorSignature(const CXXMethodDecl *MD, StructorType T, - SmallVectorImpl<CanQualType> &ArgTys) { - AddedStructorArgs Added; - // TODO: 'for base' flag - if (T == StructorType::Deleting) { - // The scalar deleting destructor takes an implicit int parameter. - ArgTys.push_back(getContext().IntTy); - ++Added.Suffix; - } - auto *CD = dyn_cast<CXXConstructorDecl>(MD); - if (!CD) - return Added; - - // All parameters are already in place except is_most_derived, which goes - // after 'this' if it's variadic and last if it's not. - - const CXXRecordDecl *Class = CD->getParent(); - const FunctionProtoType *FPT = CD->getType()->castAs<FunctionProtoType>(); - if (Class->getNumVBases()) { - if (FPT->isVariadic()) { - ArgTys.insert(ArgTys.begin() + 1, getContext().IntTy); - ++Added.Prefix; - } else { - ArgTys.push_back(getContext().IntTy); - ++Added.Suffix; - } - } - - return Added; -} - -void MicrosoftCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV, - const CXXDestructorDecl *Dtor, - CXXDtorType DT) const { - // Deleting destructor variants are never imported or exported. Give them the - // default storage class. - if (DT == Dtor_Deleting) { - GV->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); - } else { - const NamedDecl *ND = Dtor; - CGM.setDLLImportDLLExport(GV, ND); - } -} - -llvm::GlobalValue::LinkageTypes MicrosoftCXXABI::getCXXDestructorLinkage( - GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const { - // Internal things are always internal, regardless of attributes. After this, - // we know the thunk is externally visible. - if (Linkage == GVA_Internal) - return llvm::GlobalValue::InternalLinkage; - - switch (DT) { - case Dtor_Base: - // The base destructor most closely tracks the user-declared constructor, so - // we delegate back to the normal declarator case. - return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage, - /*isConstantVariable=*/false); - case Dtor_Complete: - // The complete destructor is like an inline function, but it may be - // imported and therefore must be exported as well. This requires changing - // the linkage if a DLL attribute is present. - if (Dtor->hasAttr<DLLExportAttr>()) - return llvm::GlobalValue::WeakODRLinkage; - if (Dtor->hasAttr<DLLImportAttr>()) - return llvm::GlobalValue::AvailableExternallyLinkage; - return llvm::GlobalValue::LinkOnceODRLinkage; - case Dtor_Deleting: - // Deleting destructors are like inline functions. They have vague linkage - // and are emitted everywhere they are used. They are internal if the class - // is internal. - return llvm::GlobalValue::LinkOnceODRLinkage; - case Dtor_Comdat: - llvm_unreachable("MS C++ ABI does not support comdat dtors"); - } - llvm_unreachable("invalid dtor type"); -} - -void MicrosoftCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) { - // The TU defining a dtor is only guaranteed to emit a base destructor. All - // other destructor variants are delegating thunks. - CGM.EmitGlobal(GlobalDecl(D, Dtor_Base)); -} - -CharUnits -MicrosoftCXXABI::getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD) { - const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); - - if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { - // Complete destructors take a pointer to the complete object as a - // parameter, thus don't need this adjustment. - if (GD.getDtorType() == Dtor_Complete) - return CharUnits(); - - // There's no Dtor_Base in vftable but it shares the this adjustment with - // the deleting one, so look it up instead. - GD = GlobalDecl(DD, Dtor_Deleting); - } - - MethodVFTableLocation ML = - CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD); - CharUnits Adjustment = ML.VFPtrOffset; - - // Normal virtual instance methods need to adjust from the vfptr that first - // defined the virtual method to the virtual base subobject, but destructors - // do not. The vector deleting destructor thunk applies this adjustment for - // us if necessary. - if (isa<CXXDestructorDecl>(MD)) - Adjustment = CharUnits::Zero(); - - if (ML.VBase) { - const ASTRecordLayout &DerivedLayout = - getContext().getASTRecordLayout(MD->getParent()); - Adjustment += DerivedLayout.getVBaseClassOffset(ML.VBase); - } - - return Adjustment; -} - -Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall( - CodeGenFunction &CGF, GlobalDecl GD, Address This, - bool VirtualCall) { - if (!VirtualCall) { - // If the call of a virtual function is not virtual, we just have to - // compensate for the adjustment the virtual function does in its prologue. - CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(GD); - if (Adjustment.isZero()) - return This; - - This = CGF.Builder.CreateElementBitCast(This, CGF.Int8Ty); - assert(Adjustment.isPositive()); - return CGF.Builder.CreateConstByteGEP(This, Adjustment); - } - - const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); - - GlobalDecl LookupGD = GD; - if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { - // Complete dtors take a pointer to the complete object, - // thus don't need adjustment. - if (GD.getDtorType() == Dtor_Complete) - return This; - - // There's only Dtor_Deleting in vftable but it shares the this adjustment - // with the base one, so look up the deleting one instead. - LookupGD = GlobalDecl(DD, Dtor_Deleting); - } - MethodVFTableLocation ML = - CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD); - - CharUnits StaticOffset = ML.VFPtrOffset; - - // Base destructors expect 'this' to point to the beginning of the base - // subobject, not the first vfptr that happens to contain the virtual dtor. - // However, we still need to apply the virtual base adjustment. - if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base) - StaticOffset = CharUnits::Zero(); - - Address Result = This; - if (ML.VBase) { - Result = CGF.Builder.CreateElementBitCast(Result, CGF.Int8Ty); - - const CXXRecordDecl *Derived = MD->getParent(); - const CXXRecordDecl *VBase = ML.VBase; - llvm::Value *VBaseOffset = - GetVirtualBaseClassOffset(CGF, Result, Derived, VBase); - llvm::Value *VBasePtr = - CGF.Builder.CreateInBoundsGEP(Result.getPointer(), VBaseOffset); - CharUnits VBaseAlign = - CGF.CGM.getVBaseAlignment(Result.getAlignment(), Derived, VBase); - Result = Address(VBasePtr, VBaseAlign); - } - if (!StaticOffset.isZero()) { - assert(StaticOffset.isPositive()); - Result = CGF.Builder.CreateElementBitCast(Result, CGF.Int8Ty); - if (ML.VBase) { - // Non-virtual adjustment might result in a pointer outside the allocated - // object, e.g. if the final overrider class is laid out after the virtual - // base that declares a method in the most derived class. - // FIXME: Update the code that emits this adjustment in thunks prologues. - Result = CGF.Builder.CreateConstByteGEP(Result, StaticOffset); - } else { - Result = CGF.Builder.CreateConstInBoundsByteGEP(Result, StaticOffset); - } - } - return Result; -} - -void MicrosoftCXXABI::addImplicitStructorParams(CodeGenFunction &CGF, - QualType &ResTy, - FunctionArgList &Params) { - ASTContext &Context = getContext(); - const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); - assert(isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)); - if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) { - auto *IsMostDerived = ImplicitParamDecl::Create( - Context, /*DC=*/nullptr, CGF.CurGD.getDecl()->getLocation(), - &Context.Idents.get("is_most_derived"), Context.IntTy, - ImplicitParamDecl::Other); - // The 'most_derived' parameter goes second if the ctor is variadic and last - // if it's not. Dtors can't be variadic. - const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); - if (FPT->isVariadic()) - Params.insert(Params.begin() + 1, IsMostDerived); - else - Params.push_back(IsMostDerived); - getStructorImplicitParamDecl(CGF) = IsMostDerived; - } else if (isDeletingDtor(CGF.CurGD)) { - auto *ShouldDelete = ImplicitParamDecl::Create( - Context, /*DC=*/nullptr, CGF.CurGD.getDecl()->getLocation(), - &Context.Idents.get("should_call_delete"), Context.IntTy, - ImplicitParamDecl::Other); - Params.push_back(ShouldDelete); - getStructorImplicitParamDecl(CGF) = ShouldDelete; - } -} - -void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { - // Naked functions have no prolog. - if (CGF.CurFuncDecl && CGF.CurFuncDecl->hasAttr<NakedAttr>()) - return; - - // Overridden virtual methods of non-primary bases need to adjust the incoming - // 'this' pointer in the prologue. In this hierarchy, C::b will subtract - // sizeof(void*) to adjust from B* to C*: - // struct A { virtual void a(); }; - // struct B { virtual void b(); }; - // struct C : A, B { virtual void b(); }; - // - // Leave the value stored in the 'this' alloca unadjusted, so that the - // debugger sees the unadjusted value. Microsoft debuggers require this, and - // will apply the ThisAdjustment in the method type information. - // FIXME: Do something better for DWARF debuggers, which won't expect this, - // without making our codegen depend on debug info settings. - llvm::Value *This = loadIncomingCXXThis(CGF); - const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); - if (!CGF.CurFuncIsThunk && MD->isVirtual()) { - CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(CGF.CurGD); - if (!Adjustment.isZero()) { - unsigned AS = cast<llvm::PointerType>(This->getType())->getAddressSpace(); - llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS), - *thisTy = This->getType(); - This = CGF.Builder.CreateBitCast(This, charPtrTy); - assert(Adjustment.isPositive()); - This = CGF.Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, This, - -Adjustment.getQuantity()); - This = CGF.Builder.CreateBitCast(This, thisTy, "this.adjusted"); - } - } - setCXXABIThisValue(CGF, This); - - // If this is a function that the ABI specifies returns 'this', initialize - // the return slot to 'this' at the start of the function. - // - // Unlike the setting of return types, this is done within the ABI - // implementation instead of by clients of CGCXXABI because: - // 1) getThisValue is currently protected - // 2) in theory, an ABI could implement 'this' returns some other way; - // HasThisReturn only specifies a contract, not the implementation - if (HasThisReturn(CGF.CurGD)) - CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue); - else if (hasMostDerivedReturn(CGF.CurGD)) - CGF.Builder.CreateStore(CGF.EmitCastToVoidPtr(getThisValue(CGF)), - CGF.ReturnValue); - - if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) { - assert(getStructorImplicitParamDecl(CGF) && - "no implicit parameter for a constructor with virtual bases?"); - getStructorImplicitParamValue(CGF) - = CGF.Builder.CreateLoad( - CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)), - "is_most_derived"); - } - - if (isDeletingDtor(CGF.CurGD)) { - assert(getStructorImplicitParamDecl(CGF) && - "no implicit parameter for a deleting destructor?"); - getStructorImplicitParamValue(CGF) - = CGF.Builder.CreateLoad( - CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)), - "should_call_delete"); - } -} - -CGCXXABI::AddedStructorArgs MicrosoftCXXABI::addImplicitConstructorArgs( - CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type, - bool ForVirtualBase, bool Delegating, CallArgList &Args) { - assert(Type == Ctor_Complete || Type == Ctor_Base); - - // Check if we need a 'most_derived' parameter. - if (!D->getParent()->getNumVBases()) - return AddedStructorArgs{}; - - // Add the 'most_derived' argument second if we are variadic or last if not. - const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>(); - llvm::Value *MostDerivedArg; - if (Delegating) { - MostDerivedArg = getStructorImplicitParamValue(CGF); - } else { - MostDerivedArg = llvm::ConstantInt::get(CGM.Int32Ty, Type == Ctor_Complete); - } - RValue RV = RValue::get(MostDerivedArg); - if (FPT->isVariadic()) { - Args.insert(Args.begin() + 1, CallArg(RV, getContext().IntTy)); - return AddedStructorArgs::prefix(1); - } - Args.add(RV, getContext().IntTy); - return AddedStructorArgs::suffix(1); -} - -void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, - const CXXDestructorDecl *DD, - CXXDtorType Type, bool ForVirtualBase, - bool Delegating, Address This) { - // Use the base destructor variant in place of the complete destructor variant - // if the class has no virtual bases. This effectively implements some of the - // -mconstructor-aliases optimization, but as part of the MS C++ ABI. - if (Type == Dtor_Complete && DD->getParent()->getNumVBases() == 0) - Type = Dtor_Base; - - CGCallee Callee = - CGCallee::forDirect(CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)), - GlobalDecl(DD, Type)); - - if (DD->isVirtual()) { - assert(Type != CXXDtorType::Dtor_Deleting && - "The deleting destructor should only be called via a virtual call"); - This = adjustThisArgumentForVirtualFunctionCall(CGF, GlobalDecl(DD, Type), - This, false); - } - - llvm::BasicBlock *BaseDtorEndBB = nullptr; - if (ForVirtualBase && isa<CXXConstructorDecl>(CGF.CurCodeDecl)) { - BaseDtorEndBB = EmitDtorCompleteObjectHandler(CGF); - } - - CGF.EmitCXXDestructorCall(DD, Callee, This.getPointer(), - /*ImplicitParam=*/nullptr, - /*ImplicitParamTy=*/QualType(), nullptr, - getFromDtorType(Type)); - if (BaseDtorEndBB) { - // Complete object handler should continue to be the remaining - CGF.Builder.CreateBr(BaseDtorEndBB); - CGF.EmitBlock(BaseDtorEndBB); - } -} - -void MicrosoftCXXABI::emitVTableTypeMetadata(const VPtrInfo &Info, - const CXXRecordDecl *RD, - llvm::GlobalVariable *VTable) { - if (!CGM.getCodeGenOpts().LTOUnit) - return; - - // The location of the first virtual function pointer in the virtual table, - // aka the "address point" on Itanium. This is at offset 0 if RTTI is - // disabled, or sizeof(void*) if RTTI is enabled. - CharUnits AddressPoint = - getContext().getLangOpts().RTTIData - ? getContext().toCharUnitsFromBits( - getContext().getTargetInfo().getPointerWidth(0)) - : CharUnits::Zero(); - - if (Info.PathToIntroducingObject.empty()) { - CGM.AddVTableTypeMetadata(VTable, AddressPoint, RD); - return; - } - - // Add a bitset entry for the least derived base belonging to this vftable. - CGM.AddVTableTypeMetadata(VTable, AddressPoint, - Info.PathToIntroducingObject.back()); - - // Add a bitset entry for each derived class that is laid out at the same - // offset as the least derived base. - for (unsigned I = Info.PathToIntroducingObject.size() - 1; I != 0; --I) { - const CXXRecordDecl *DerivedRD = Info.PathToIntroducingObject[I - 1]; - const CXXRecordDecl *BaseRD = Info.PathToIntroducingObject[I]; - - const ASTRecordLayout &Layout = - getContext().getASTRecordLayout(DerivedRD); - CharUnits Offset; - auto VBI = Layout.getVBaseOffsetsMap().find(BaseRD); - if (VBI == Layout.getVBaseOffsetsMap().end()) - Offset = Layout.getBaseClassOffset(BaseRD); - else - Offset = VBI->second.VBaseOffset; - if (!Offset.isZero()) - return; - CGM.AddVTableTypeMetadata(VTable, AddressPoint, DerivedRD); - } - - // Finally do the same for the most derived class. - if (Info.FullOffsetInMDC.isZero()) - CGM.AddVTableTypeMetadata(VTable, AddressPoint, RD); -} - -void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, - const CXXRecordDecl *RD) { - MicrosoftVTableContext &VFTContext = CGM.getMicrosoftVTableContext(); - const VPtrInfoVector &VFPtrs = VFTContext.getVFPtrOffsets(RD); - - for (const std::unique_ptr<VPtrInfo>& Info : VFPtrs) { - llvm::GlobalVariable *VTable = getAddrOfVTable(RD, Info->FullOffsetInMDC); - if (VTable->hasInitializer()) - continue; - - const VTableLayout &VTLayout = - VFTContext.getVFTableLayout(RD, Info->FullOffsetInMDC); - - llvm::Constant *RTTI = nullptr; - if (any_of(VTLayout.vtable_components(), - [](const VTableComponent &VTC) { return VTC.isRTTIKind(); })) - RTTI = getMSCompleteObjectLocator(RD, *Info); - - ConstantInitBuilder Builder(CGM); - auto Components = Builder.beginStruct(); - CGVT.createVTableInitializer(Components, VTLayout, RTTI); - Components.finishAndSetAsInitializer(VTable); - - emitVTableTypeMetadata(*Info, RD, VTable); - } -} - -bool MicrosoftCXXABI::isVirtualOffsetNeededForVTableField( - CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr) { - return Vptr.NearestVBase != nullptr; -} - -llvm::Value *MicrosoftCXXABI::getVTableAddressPointInStructor( - CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, - const CXXRecordDecl *NearestVBase) { - llvm::Constant *VTableAddressPoint = getVTableAddressPoint(Base, VTableClass); - if (!VTableAddressPoint) { - assert(Base.getBase()->getNumVBases() && - !getContext().getASTRecordLayout(Base.getBase()).hasOwnVFPtr()); - } - return VTableAddressPoint; -} - -static void mangleVFTableName(MicrosoftMangleContext &MangleContext, - const CXXRecordDecl *RD, const VPtrInfo &VFPtr, - SmallString<256> &Name) { - llvm::raw_svector_ostream Out(Name); - MangleContext.mangleCXXVFTable(RD, VFPtr.MangledPath, Out); -} - -llvm::Constant * -MicrosoftCXXABI::getVTableAddressPoint(BaseSubobject Base, - const CXXRecordDecl *VTableClass) { - (void)getAddrOfVTable(VTableClass, Base.getBaseOffset()); - VFTableIdTy ID(VTableClass, Base.getBaseOffset()); - return VFTablesMap[ID]; -} - -llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr( - BaseSubobject Base, const CXXRecordDecl *VTableClass) { - llvm::Constant *VFTable = getVTableAddressPoint(Base, VTableClass); - assert(VFTable && "Couldn't find a vftable for the given base?"); - return VFTable; -} - -llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, - CharUnits VPtrOffset) { - // getAddrOfVTable may return 0 if asked to get an address of a vtable which - // shouldn't be used in the given record type. We want to cache this result in - // VFTablesMap, thus a simple zero check is not sufficient. - - VFTableIdTy ID(RD, VPtrOffset); - VTablesMapTy::iterator I; - bool Inserted; - std::tie(I, Inserted) = VTablesMap.insert(std::make_pair(ID, nullptr)); - if (!Inserted) - return I->second; - - llvm::GlobalVariable *&VTable = I->second; - - MicrosoftVTableContext &VTContext = CGM.getMicrosoftVTableContext(); - const VPtrInfoVector &VFPtrs = VTContext.getVFPtrOffsets(RD); - - if (DeferredVFTables.insert(RD).second) { - // We haven't processed this record type before. - // Queue up this vtable for possible deferred emission. - CGM.addDeferredVTable(RD); - -#ifndef NDEBUG - // Create all the vftables at once in order to make sure each vftable has - // a unique mangled name. - llvm::StringSet<> ObservedMangledNames; - for (size_t J = 0, F = VFPtrs.size(); J != F; ++J) { - SmallString<256> Name; - mangleVFTableName(getMangleContext(), RD, *VFPtrs[J], Name); - if (!ObservedMangledNames.insert(Name.str()).second) - llvm_unreachable("Already saw this mangling before?"); - } -#endif - } - - const std::unique_ptr<VPtrInfo> *VFPtrI = std::find_if( - VFPtrs.begin(), VFPtrs.end(), [&](const std::unique_ptr<VPtrInfo>& VPI) { - return VPI->FullOffsetInMDC == VPtrOffset; - }); - if (VFPtrI == VFPtrs.end()) { - VFTablesMap[ID] = nullptr; - return nullptr; - } - const std::unique_ptr<VPtrInfo> &VFPtr = *VFPtrI; - - SmallString<256> VFTableName; - mangleVFTableName(getMangleContext(), RD, *VFPtr, VFTableName); - - // Classes marked __declspec(dllimport) need vftables generated on the - // import-side in order to support features like constexpr. No other - // translation unit relies on the emission of the local vftable, translation - // units are expected to generate them as needed. - // - // Because of this unique behavior, we maintain this logic here instead of - // getVTableLinkage. - llvm::GlobalValue::LinkageTypes VFTableLinkage = - RD->hasAttr<DLLImportAttr>() ? llvm::GlobalValue::LinkOnceODRLinkage - : CGM.getVTableLinkage(RD); - bool VFTableComesFromAnotherTU = - llvm::GlobalValue::isAvailableExternallyLinkage(VFTableLinkage) || - llvm::GlobalValue::isExternalLinkage(VFTableLinkage); - bool VTableAliasIsRequred = - !VFTableComesFromAnotherTU && getContext().getLangOpts().RTTIData; - - if (llvm::GlobalValue *VFTable = - CGM.getModule().getNamedGlobal(VFTableName)) { - VFTablesMap[ID] = VFTable; - VTable = VTableAliasIsRequred - ? cast<llvm::GlobalVariable>( - cast<llvm::GlobalAlias>(VFTable)->getBaseObject()) - : cast<llvm::GlobalVariable>(VFTable); - return VTable; - } - - const VTableLayout &VTLayout = - VTContext.getVFTableLayout(RD, VFPtr->FullOffsetInMDC); - llvm::GlobalValue::LinkageTypes VTableLinkage = - VTableAliasIsRequred ? llvm::GlobalValue::PrivateLinkage : VFTableLinkage; - - StringRef VTableName = VTableAliasIsRequred ? StringRef() : VFTableName.str(); - - llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout); - - // Create a backing variable for the contents of VTable. The VTable may - // or may not include space for a pointer to RTTI data. - llvm::GlobalValue *VFTable; - VTable = new llvm::GlobalVariable(CGM.getModule(), VTableType, - /*isConstant=*/true, VTableLinkage, - /*Initializer=*/nullptr, VTableName); - VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - - llvm::Comdat *C = nullptr; - if (!VFTableComesFromAnotherTU && - (llvm::GlobalValue::isWeakForLinker(VFTableLinkage) || - (llvm::GlobalValue::isLocalLinkage(VFTableLinkage) && - VTableAliasIsRequred))) - C = CGM.getModule().getOrInsertComdat(VFTableName.str()); - - // Only insert a pointer into the VFTable for RTTI data if we are not - // importing it. We never reference the RTTI data directly so there is no - // need to make room for it. - if (VTableAliasIsRequred) { - llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.Int32Ty, 0), - llvm::ConstantInt::get(CGM.Int32Ty, 0), - llvm::ConstantInt::get(CGM.Int32Ty, 1)}; - // Create a GEP which points just after the first entry in the VFTable, - // this should be the location of the first virtual method. - llvm::Constant *VTableGEP = llvm::ConstantExpr::getInBoundsGetElementPtr( - VTable->getValueType(), VTable, GEPIndices); - if (llvm::GlobalValue::isWeakForLinker(VFTableLinkage)) { - VFTableLinkage = llvm::GlobalValue::ExternalLinkage; - if (C) - C->setSelectionKind(llvm::Comdat::Largest); - } - VFTable = llvm::GlobalAlias::create(CGM.Int8PtrTy, - /*AddressSpace=*/0, VFTableLinkage, - VFTableName.str(), VTableGEP, - &CGM.getModule()); - VFTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - } else { - // We don't need a GlobalAlias to be a symbol for the VTable if we won't - // be referencing any RTTI data. - // The GlobalVariable will end up being an appropriate definition of the - // VFTable. - VFTable = VTable; - } - if (C) - VTable->setComdat(C); - - if (RD->hasAttr<DLLExportAttr>()) - VFTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); - - VFTablesMap[ID] = VFTable; - return VTable; -} - -CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, - GlobalDecl GD, - Address This, - llvm::Type *Ty, - SourceLocation Loc) { - CGBuilderTy &Builder = CGF.Builder; - - Ty = Ty->getPointerTo()->getPointerTo(); - Address VPtr = - adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true); - - auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl()); - llvm::Value *VTable = CGF.GetVTablePtr(VPtr, Ty, MethodDecl->getParent()); - - MicrosoftVTableContext &VFTContext = CGM.getMicrosoftVTableContext(); - MethodVFTableLocation ML = VFTContext.getMethodVFTableLocation(GD); - - // Compute the identity of the most derived class whose virtual table is - // located at the MethodVFTableLocation ML. - auto getObjectWithVPtr = [&] { - return llvm::find_if(VFTContext.getVFPtrOffsets( - ML.VBase ? ML.VBase : MethodDecl->getParent()), - [&](const std::unique_ptr<VPtrInfo> &Info) { - return Info->FullOffsetInMDC == ML.VFPtrOffset; - }) - ->get() - ->ObjectWithVPtr; - }; - - llvm::Value *VFunc; - if (CGF.ShouldEmitVTableTypeCheckedLoad(MethodDecl->getParent())) { - VFunc = CGF.EmitVTableTypeCheckedLoad( - getObjectWithVPtr(), VTable, - ML.Index * CGM.getContext().getTargetInfo().getPointerWidth(0) / 8); - } else { - if (CGM.getCodeGenOpts().PrepareForLTO) - CGF.EmitTypeMetadataCodeForVCall(getObjectWithVPtr(), VTable, Loc); - - llvm::Value *VFuncPtr = - Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn"); - VFunc = Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign()); - } - - CGCallee Callee(GD, VFunc); - return Callee; -} - -llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall( - CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, - Address This, const CXXMemberCallExpr *CE) { - assert(CE == nullptr || CE->arg_begin() == CE->arg_end()); - assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete); - - // We have only one destructor in the vftable but can get both behaviors - // by passing an implicit int parameter. - GlobalDecl GD(Dtor, Dtor_Deleting); - const CGFunctionInfo *FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration( - Dtor, StructorType::Deleting); - llvm::FunctionType *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo); - CGCallee Callee = CGCallee::forVirtual(CE, GD, This, Ty); - - ASTContext &Context = getContext(); - llvm::Value *ImplicitParam = llvm::ConstantInt::get( - llvm::IntegerType::getInt32Ty(CGF.getLLVMContext()), - DtorType == Dtor_Deleting); - - This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true); - RValue RV = - CGF.EmitCXXDestructorCall(Dtor, Callee, This.getPointer(), ImplicitParam, - Context.IntTy, CE, StructorType::Deleting); - return RV.getScalarVal(); -} - -const VBTableGlobals & -MicrosoftCXXABI::enumerateVBTables(const CXXRecordDecl *RD) { - // At this layer, we can key the cache off of a single class, which is much - // easier than caching each vbtable individually. - llvm::DenseMap<const CXXRecordDecl*, VBTableGlobals>::iterator Entry; - bool Added; - std::tie(Entry, Added) = - VBTablesMap.insert(std::make_pair(RD, VBTableGlobals())); - VBTableGlobals &VBGlobals = Entry->second; - if (!Added) - return VBGlobals; - - MicrosoftVTableContext &Context = CGM.getMicrosoftVTableContext(); - VBGlobals.VBTables = &Context.enumerateVBTables(RD); - - // Cache the globals for all vbtables so we don't have to recompute the - // mangled names. - llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD); - for (VPtrInfoVector::const_iterator I = VBGlobals.VBTables->begin(), - E = VBGlobals.VBTables->end(); - I != E; ++I) { - VBGlobals.Globals.push_back(getAddrOfVBTable(**I, RD, Linkage)); - } - - return VBGlobals; -} - -llvm::Function * -MicrosoftCXXABI::EmitVirtualMemPtrThunk(const CXXMethodDecl *MD, - const MethodVFTableLocation &ML) { - assert(!isa<CXXConstructorDecl>(MD) && !isa<CXXDestructorDecl>(MD) && - "can't form pointers to ctors or virtual dtors"); - - // Calculate the mangled name. - SmallString<256> ThunkName; - llvm::raw_svector_ostream Out(ThunkName); - getMangleContext().mangleVirtualMemPtrThunk(MD, ML, Out); - - // If the thunk has been generated previously, just return it. - if (llvm::GlobalValue *GV = CGM.getModule().getNamedValue(ThunkName)) - return cast<llvm::Function>(GV); - - // Create the llvm::Function. - const CGFunctionInfo &FnInfo = - CGM.getTypes().arrangeUnprototypedMustTailThunk(MD); - llvm::FunctionType *ThunkTy = CGM.getTypes().GetFunctionType(FnInfo); - llvm::Function *ThunkFn = - llvm::Function::Create(ThunkTy, llvm::Function::ExternalLinkage, - ThunkName.str(), &CGM.getModule()); - assert(ThunkFn->getName() == ThunkName && "name was uniqued!"); - - ThunkFn->setLinkage(MD->isExternallyVisible() - ? llvm::GlobalValue::LinkOnceODRLinkage - : llvm::GlobalValue::InternalLinkage); - if (MD->isExternallyVisible()) - ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName())); - - CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn); - CGM.SetLLVMFunctionAttributesForDefinition(MD, ThunkFn); - - // Add the "thunk" attribute so that LLVM knows that the return type is - // meaningless. These thunks can be used to call functions with differing - // return types, and the caller is required to cast the prototype - // appropriately to extract the correct value. - ThunkFn->addFnAttr("thunk"); - - // These thunks can be compared, so they are not unnamed. - ThunkFn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None); - - // Start codegen. - CodeGenFunction CGF(CGM); - CGF.CurGD = GlobalDecl(MD); - CGF.CurFuncIsThunk = true; - - // Build FunctionArgs, but only include the implicit 'this' parameter - // declaration. - FunctionArgList FunctionArgs; - buildThisParam(CGF, FunctionArgs); - - // Start defining the function. - CGF.StartFunction(GlobalDecl(), FnInfo.getReturnType(), ThunkFn, FnInfo, - FunctionArgs, MD->getLocation(), SourceLocation()); - setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF)); - - // Load the vfptr and then callee from the vftable. The callee should have - // adjusted 'this' so that the vfptr is at offset zero. - llvm::Value *VTable = CGF.GetVTablePtr( - getThisAddress(CGF), ThunkTy->getPointerTo()->getPointerTo(), MD->getParent()); - - llvm::Value *VFuncPtr = - CGF.Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn"); - llvm::Value *Callee = - CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign()); - - CGF.EmitMustTailThunk(MD, getThisValue(CGF), Callee); - - return ThunkFn; -} - -void MicrosoftCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) { - const VBTableGlobals &VBGlobals = enumerateVBTables(RD); - for (unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) { - const std::unique_ptr<VPtrInfo>& VBT = (*VBGlobals.VBTables)[I]; - llvm::GlobalVariable *GV = VBGlobals.Globals[I]; - if (GV->isDeclaration()) - emitVBTableDefinition(*VBT, RD, GV); - } -} - -llvm::GlobalVariable * -MicrosoftCXXABI::getAddrOfVBTable(const VPtrInfo &VBT, const CXXRecordDecl *RD, - llvm::GlobalVariable::LinkageTypes Linkage) { - SmallString<256> OutName; - llvm::raw_svector_ostream Out(OutName); - getMangleContext().mangleCXXVBTable(RD, VBT.MangledPath, Out); - StringRef Name = OutName.str(); - - llvm::ArrayType *VBTableType = - llvm::ArrayType::get(CGM.IntTy, 1 + VBT.ObjectWithVPtr->getNumVBases()); - - assert(!CGM.getModule().getNamedGlobal(Name) && - "vbtable with this name already exists: mangling bug?"); - CharUnits Alignment = - CGM.getContext().getTypeAlignInChars(CGM.getContext().IntTy); - llvm::GlobalVariable *GV = CGM.CreateOrReplaceCXXRuntimeVariable( - Name, VBTableType, Linkage, Alignment.getQuantity()); - GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - - if (RD->hasAttr<DLLImportAttr>()) - GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); - else if (RD->hasAttr<DLLExportAttr>()) - GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); - - if (!GV->hasExternalLinkage()) - emitVBTableDefinition(VBT, RD, GV); - - return GV; -} - -void MicrosoftCXXABI::emitVBTableDefinition(const VPtrInfo &VBT, - const CXXRecordDecl *RD, - llvm::GlobalVariable *GV) const { - const CXXRecordDecl *ObjectWithVPtr = VBT.ObjectWithVPtr; - - assert(RD->getNumVBases() && ObjectWithVPtr->getNumVBases() && - "should only emit vbtables for classes with vbtables"); - - const ASTRecordLayout &BaseLayout = - getContext().getASTRecordLayout(VBT.IntroducingObject); - const ASTRecordLayout &DerivedLayout = getContext().getASTRecordLayout(RD); - - SmallVector<llvm::Constant *, 4> Offsets(1 + ObjectWithVPtr->getNumVBases(), - nullptr); - - // The offset from ObjectWithVPtr's vbptr to itself always leads. - CharUnits VBPtrOffset = BaseLayout.getVBPtrOffset(); - Offsets[0] = llvm::ConstantInt::get(CGM.IntTy, -VBPtrOffset.getQuantity()); - - MicrosoftVTableContext &Context = CGM.getMicrosoftVTableContext(); - for (const auto &I : ObjectWithVPtr->vbases()) { - const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl(); - CharUnits Offset = DerivedLayout.getVBaseClassOffset(VBase); - assert(!Offset.isNegative()); - - // Make it relative to the subobject vbptr. - CharUnits CompleteVBPtrOffset = VBT.NonVirtualOffset + VBPtrOffset; - if (VBT.getVBaseWithVPtr()) - CompleteVBPtrOffset += - DerivedLayout.getVBaseClassOffset(VBT.getVBaseWithVPtr()); - Offset -= CompleteVBPtrOffset; - - unsigned VBIndex = Context.getVBTableIndex(ObjectWithVPtr, VBase); - assert(Offsets[VBIndex] == nullptr && "The same vbindex seen twice?"); - Offsets[VBIndex] = llvm::ConstantInt::get(CGM.IntTy, Offset.getQuantity()); - } - - assert(Offsets.size() == - cast<llvm::ArrayType>(cast<llvm::PointerType>(GV->getType()) - ->getElementType())->getNumElements()); - llvm::ArrayType *VBTableType = - llvm::ArrayType::get(CGM.IntTy, Offsets.size()); - llvm::Constant *Init = llvm::ConstantArray::get(VBTableType, Offsets); - GV->setInitializer(Init); - - if (RD->hasAttr<DLLImportAttr>()) - GV->setLinkage(llvm::GlobalVariable::AvailableExternallyLinkage); -} - -llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF, - Address This, - const ThisAdjustment &TA) { - if (TA.isEmpty()) - return This.getPointer(); - - This = CGF.Builder.CreateElementBitCast(This, CGF.Int8Ty); - - llvm::Value *V; - if (TA.Virtual.isEmpty()) { - V = This.getPointer(); - } else { - assert(TA.Virtual.Microsoft.VtordispOffset < 0); - // Adjust the this argument based on the vtordisp value. - Address VtorDispPtr = - CGF.Builder.CreateConstInBoundsByteGEP(This, - CharUnits::fromQuantity(TA.Virtual.Microsoft.VtordispOffset)); - VtorDispPtr = CGF.Builder.CreateElementBitCast(VtorDispPtr, CGF.Int32Ty); - llvm::Value *VtorDisp = CGF.Builder.CreateLoad(VtorDispPtr, "vtordisp"); - V = CGF.Builder.CreateGEP(This.getPointer(), - CGF.Builder.CreateNeg(VtorDisp)); - - // Unfortunately, having applied the vtordisp means that we no - // longer really have a known alignment for the vbptr step. - // We'll assume the vbptr is pointer-aligned. - - if (TA.Virtual.Microsoft.VBPtrOffset) { - // If the final overrider is defined in a virtual base other than the one - // that holds the vfptr, we have to use a vtordispex thunk which looks up - // the vbtable of the derived class. - assert(TA.Virtual.Microsoft.VBPtrOffset > 0); - assert(TA.Virtual.Microsoft.VBOffsetOffset >= 0); - llvm::Value *VBPtr; - llvm::Value *VBaseOffset = - GetVBaseOffsetFromVBPtr(CGF, Address(V, CGF.getPointerAlign()), - -TA.Virtual.Microsoft.VBPtrOffset, - TA.Virtual.Microsoft.VBOffsetOffset, &VBPtr); - V = CGF.Builder.CreateInBoundsGEP(VBPtr, VBaseOffset); - } - } - - if (TA.NonVirtual) { - // Non-virtual adjustment might result in a pointer outside the allocated - // object, e.g. if the final overrider class is laid out after the virtual - // base that declares a method in the most derived class. - V = CGF.Builder.CreateConstGEP1_32(V, TA.NonVirtual); - } - - // Don't need to bitcast back, the call CodeGen will handle this. - return V; -} - -llvm::Value * -MicrosoftCXXABI::performReturnAdjustment(CodeGenFunction &CGF, Address Ret, - const ReturnAdjustment &RA) { - if (RA.isEmpty()) - return Ret.getPointer(); - - auto OrigTy = Ret.getType(); - Ret = CGF.Builder.CreateElementBitCast(Ret, CGF.Int8Ty); - - llvm::Value *V = Ret.getPointer(); - if (RA.Virtual.Microsoft.VBIndex) { - assert(RA.Virtual.Microsoft.VBIndex > 0); - int32_t IntSize = CGF.getIntSize().getQuantity(); - llvm::Value *VBPtr; - llvm::Value *VBaseOffset = - GetVBaseOffsetFromVBPtr(CGF, Ret, RA.Virtual.Microsoft.VBPtrOffset, - IntSize * RA.Virtual.Microsoft.VBIndex, &VBPtr); - V = CGF.Builder.CreateInBoundsGEP(VBPtr, VBaseOffset); - } - - if (RA.NonVirtual) - V = CGF.Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, V, RA.NonVirtual); - - // Cast back to the original type. - return CGF.Builder.CreateBitCast(V, OrigTy); -} - -bool MicrosoftCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr, - QualType elementType) { - // Microsoft seems to completely ignore the possibility of a - // two-argument usual deallocation function. - return elementType.isDestructedType(); -} - -bool MicrosoftCXXABI::requiresArrayCookie(const CXXNewExpr *expr) { - // Microsoft seems to completely ignore the possibility of a - // two-argument usual deallocation function. - return expr->getAllocatedType().isDestructedType(); -} - -CharUnits MicrosoftCXXABI::getArrayCookieSizeImpl(QualType type) { - // The array cookie is always a size_t; we then pad that out to the - // alignment of the element type. - ASTContext &Ctx = getContext(); - return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()), - Ctx.getTypeAlignInChars(type)); -} - -llvm::Value *MicrosoftCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, - Address allocPtr, - CharUnits cookieSize) { - Address numElementsPtr = - CGF.Builder.CreateElementBitCast(allocPtr, CGF.SizeTy); - return CGF.Builder.CreateLoad(numElementsPtr); -} - -Address MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, - Address newPtr, - llvm::Value *numElements, - const CXXNewExpr *expr, - QualType elementType) { - assert(requiresArrayCookie(expr)); - - // The size of the cookie. - CharUnits cookieSize = getArrayCookieSizeImpl(elementType); - - // Compute an offset to the cookie. - Address cookiePtr = newPtr; - - // Write the number of elements into the appropriate slot. - Address numElementsPtr - = CGF.Builder.CreateElementBitCast(cookiePtr, CGF.SizeTy); - CGF.Builder.CreateStore(numElements, numElementsPtr); - - // Finally, compute a pointer to the actual data buffer by skipping - // over the cookie completely. - return CGF.Builder.CreateConstInBoundsByteGEP(newPtr, cookieSize); -} - -static void emitGlobalDtorWithTLRegDtor(CodeGenFunction &CGF, const VarDecl &VD, - llvm::Constant *Dtor, - llvm::Constant *Addr) { - // Create a function which calls the destructor. - llvm::Constant *DtorStub = CGF.createAtExitStub(VD, Dtor, Addr); - - // extern "C" int __tlregdtor(void (*f)(void)); - llvm::FunctionType *TLRegDtorTy = llvm::FunctionType::get( - CGF.IntTy, DtorStub->getType(), /*IsVarArg=*/false); - - llvm::Constant *TLRegDtor = CGF.CGM.CreateRuntimeFunction( - TLRegDtorTy, "__tlregdtor", llvm::AttributeList(), /*Local=*/true); - if (llvm::Function *TLRegDtorFn = dyn_cast<llvm::Function>(TLRegDtor)) - TLRegDtorFn->setDoesNotThrow(); - - CGF.EmitNounwindRuntimeCall(TLRegDtor, DtorStub); -} - -void MicrosoftCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, - llvm::Constant *Dtor, - llvm::Constant *Addr) { - if (D.isNoDestroy(CGM.getContext())) - return; - - if (D.getTLSKind()) - return emitGlobalDtorWithTLRegDtor(CGF, D, Dtor, Addr); - - // The default behavior is to use atexit. - CGF.registerGlobalDtorWithAtExit(D, Dtor, Addr); -} - -void MicrosoftCXXABI::EmitThreadLocalInitFuncs( - CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals, - ArrayRef<llvm::Function *> CXXThreadLocalInits, - ArrayRef<const VarDecl *> CXXThreadLocalInitVars) { - if (CXXThreadLocalInits.empty()) - return; - - CGM.AppendLinkerOptions(CGM.getTarget().getTriple().getArch() == - llvm::Triple::x86 - ? "/include:___dyn_tls_init@12" - : "/include:__dyn_tls_init"); - - // This will create a GV in the .CRT$XDU section. It will point to our - // initialization function. The CRT will call all of these function - // pointers at start-up time and, eventually, at thread-creation time. - auto AddToXDU = [&CGM](llvm::Function *InitFunc) { - llvm::GlobalVariable *InitFuncPtr = new llvm::GlobalVariable( - CGM.getModule(), InitFunc->getType(), /*IsConstant=*/true, - llvm::GlobalVariable::InternalLinkage, InitFunc, - Twine(InitFunc->getName(), "$initializer$")); - InitFuncPtr->setSection(".CRT$XDU"); - // This variable has discardable linkage, we have to add it to @llvm.used to - // ensure it won't get discarded. - CGM.addUsedGlobal(InitFuncPtr); - return InitFuncPtr; - }; - - std::vector<llvm::Function *> NonComdatInits; - for (size_t I = 0, E = CXXThreadLocalInitVars.size(); I != E; ++I) { - llvm::GlobalVariable *GV = cast<llvm::GlobalVariable>( - CGM.GetGlobalValue(CGM.getMangledName(CXXThreadLocalInitVars[I]))); - llvm::Function *F = CXXThreadLocalInits[I]; - - // If the GV is already in a comdat group, then we have to join it. - if (llvm::Comdat *C = GV->getComdat()) - AddToXDU(F)->setComdat(C); - else - NonComdatInits.push_back(F); - } - - if (!NonComdatInits.empty()) { - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); - llvm::Function *InitFunc = CGM.CreateGlobalInitOrDestructFunction( - FTy, "__tls_init", CGM.getTypes().arrangeNullaryFunction(), - SourceLocation(), /*TLS=*/true); - CodeGenFunction(CGM).GenerateCXXGlobalInitFunc(InitFunc, NonComdatInits); - - AddToXDU(InitFunc); - } -} - -LValue MicrosoftCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, - const VarDecl *VD, - QualType LValType) { - CGF.CGM.ErrorUnsupported(VD, "thread wrappers"); - return LValue(); -} - -static ConstantAddress getInitThreadEpochPtr(CodeGenModule &CGM) { - StringRef VarName("_Init_thread_epoch"); - CharUnits Align = CGM.getIntAlign(); - if (auto *GV = CGM.getModule().getNamedGlobal(VarName)) - return ConstantAddress(GV, Align); - auto *GV = new llvm::GlobalVariable( - CGM.getModule(), CGM.IntTy, - /*Constant=*/false, llvm::GlobalVariable::ExternalLinkage, - /*Initializer=*/nullptr, VarName, - /*InsertBefore=*/nullptr, llvm::GlobalVariable::GeneralDynamicTLSModel); - GV->setAlignment(Align.getQuantity()); - return ConstantAddress(GV, Align); -} - -static llvm::Constant *getInitThreadHeaderFn(CodeGenModule &CGM) { - llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()), - CGM.IntTy->getPointerTo(), /*isVarArg=*/false); - return CGM.CreateRuntimeFunction( - FTy, "_Init_thread_header", - llvm::AttributeList::get(CGM.getLLVMContext(), - llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind), - /*Local=*/true); -} - -static llvm::Constant *getInitThreadFooterFn(CodeGenModule &CGM) { - llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()), - CGM.IntTy->getPointerTo(), /*isVarArg=*/false); - return CGM.CreateRuntimeFunction( - FTy, "_Init_thread_footer", - llvm::AttributeList::get(CGM.getLLVMContext(), - llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind), - /*Local=*/true); -} - -static llvm::Constant *getInitThreadAbortFn(CodeGenModule &CGM) { - llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()), - CGM.IntTy->getPointerTo(), /*isVarArg=*/false); - return CGM.CreateRuntimeFunction( - FTy, "_Init_thread_abort", - llvm::AttributeList::get(CGM.getLLVMContext(), - llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind), - /*Local=*/true); -} - -namespace { -struct ResetGuardBit final : EHScopeStack::Cleanup { - Address Guard; - unsigned GuardNum; - ResetGuardBit(Address Guard, unsigned GuardNum) - : Guard(Guard), GuardNum(GuardNum) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - // Reset the bit in the mask so that the static variable may be - // reinitialized. - CGBuilderTy &Builder = CGF.Builder; - llvm::LoadInst *LI = Builder.CreateLoad(Guard); - llvm::ConstantInt *Mask = - llvm::ConstantInt::get(CGF.IntTy, ~(1ULL << GuardNum)); - Builder.CreateStore(Builder.CreateAnd(LI, Mask), Guard); - } -}; - -struct CallInitThreadAbort final : EHScopeStack::Cleanup { - llvm::Value *Guard; - CallInitThreadAbort(Address Guard) : Guard(Guard.getPointer()) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - // Calling _Init_thread_abort will reset the guard's state. - CGF.EmitNounwindRuntimeCall(getInitThreadAbortFn(CGF.CGM), Guard); - } -}; -} - -void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, - llvm::GlobalVariable *GV, - bool PerformInit) { - // MSVC only uses guards for static locals. - if (!D.isStaticLocal()) { - assert(GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()); - // GlobalOpt is allowed to discard the initializer, so use linkonce_odr. - llvm::Function *F = CGF.CurFn; - F->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage); - F->setComdat(CGM.getModule().getOrInsertComdat(F->getName())); - CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit); - return; - } - - bool ThreadlocalStatic = D.getTLSKind(); - bool ThreadsafeStatic = getContext().getLangOpts().ThreadsafeStatics; - - // Thread-safe static variables which aren't thread-specific have a - // per-variable guard. - bool HasPerVariableGuard = ThreadsafeStatic && !ThreadlocalStatic; - - CGBuilderTy &Builder = CGF.Builder; - llvm::IntegerType *GuardTy = CGF.Int32Ty; - llvm::ConstantInt *Zero = llvm::ConstantInt::get(GuardTy, 0); - CharUnits GuardAlign = CharUnits::fromQuantity(4); - - // Get the guard variable for this function if we have one already. - GuardInfo *GI = nullptr; - if (ThreadlocalStatic) - GI = &ThreadLocalGuardVariableMap[D.getDeclContext()]; - else if (!ThreadsafeStatic) - GI = &GuardVariableMap[D.getDeclContext()]; - - llvm::GlobalVariable *GuardVar = GI ? GI->Guard : nullptr; - unsigned GuardNum; - if (D.isExternallyVisible()) { - // Externally visible variables have to be numbered in Sema to properly - // handle unreachable VarDecls. - GuardNum = getContext().getStaticLocalNumber(&D); - assert(GuardNum > 0); - GuardNum--; - } else if (HasPerVariableGuard) { - GuardNum = ThreadSafeGuardNumMap[D.getDeclContext()]++; - } else { - // Non-externally visible variables are numbered here in CodeGen. - GuardNum = GI->BitIndex++; - } - - if (!HasPerVariableGuard && GuardNum >= 32) { - if (D.isExternallyVisible()) - ErrorUnsupportedABI(CGF, "more than 32 guarded initializations"); - GuardNum %= 32; - GuardVar = nullptr; - } - - if (!GuardVar) { - // Mangle the name for the guard. - SmallString<256> GuardName; - { - llvm::raw_svector_ostream Out(GuardName); - if (HasPerVariableGuard) - getMangleContext().mangleThreadSafeStaticGuardVariable(&D, GuardNum, - Out); - else - getMangleContext().mangleStaticGuardVariable(&D, Out); - } - - // Create the guard variable with a zero-initializer. Just absorb linkage, - // visibility and dll storage class from the guarded variable. - GuardVar = - new llvm::GlobalVariable(CGM.getModule(), GuardTy, /*isConstant=*/false, - GV->getLinkage(), Zero, GuardName.str()); - GuardVar->setVisibility(GV->getVisibility()); - GuardVar->setDLLStorageClass(GV->getDLLStorageClass()); - GuardVar->setAlignment(GuardAlign.getQuantity()); - if (GuardVar->isWeakForLinker()) - GuardVar->setComdat( - CGM.getModule().getOrInsertComdat(GuardVar->getName())); - if (D.getTLSKind()) - GuardVar->setThreadLocal(true); - if (GI && !HasPerVariableGuard) - GI->Guard = GuardVar; - } - - ConstantAddress GuardAddr(GuardVar, GuardAlign); - - assert(GuardVar->getLinkage() == GV->getLinkage() && - "static local from the same function had different linkage"); - - if (!HasPerVariableGuard) { - // Pseudo code for the test: - // if (!(GuardVar & MyGuardBit)) { - // GuardVar |= MyGuardBit; - // ... initialize the object ...; - // } - - // Test our bit from the guard variable. - llvm::ConstantInt *Bit = llvm::ConstantInt::get(GuardTy, 1ULL << GuardNum); - llvm::LoadInst *LI = Builder.CreateLoad(GuardAddr); - llvm::Value *NeedsInit = - Builder.CreateICmpEQ(Builder.CreateAnd(LI, Bit), Zero); - llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init"); - llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end"); - CGF.EmitCXXGuardedInitBranch(NeedsInit, InitBlock, EndBlock, - CodeGenFunction::GuardKind::VariableGuard, &D); - - // Set our bit in the guard variable and emit the initializer and add a global - // destructor if appropriate. - CGF.EmitBlock(InitBlock); - Builder.CreateStore(Builder.CreateOr(LI, Bit), GuardAddr); - CGF.EHStack.pushCleanup<ResetGuardBit>(EHCleanup, GuardAddr, GuardNum); - CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit); - CGF.PopCleanupBlock(); - Builder.CreateBr(EndBlock); - - // Continue. - CGF.EmitBlock(EndBlock); - } else { - // Pseudo code for the test: - // if (TSS > _Init_thread_epoch) { - // _Init_thread_header(&TSS); - // if (TSS == -1) { - // ... initialize the object ...; - // _Init_thread_footer(&TSS); - // } - // } - // - // The algorithm is almost identical to what can be found in the appendix - // found in N2325. - - // This BasicBLock determines whether or not we have any work to do. - llvm::LoadInst *FirstGuardLoad = Builder.CreateLoad(GuardAddr); - FirstGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered); - llvm::LoadInst *InitThreadEpoch = - Builder.CreateLoad(getInitThreadEpochPtr(CGM)); - llvm::Value *IsUninitialized = - Builder.CreateICmpSGT(FirstGuardLoad, InitThreadEpoch); - llvm::BasicBlock *AttemptInitBlock = CGF.createBasicBlock("init.attempt"); - llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end"); - CGF.EmitCXXGuardedInitBranch(IsUninitialized, AttemptInitBlock, EndBlock, - CodeGenFunction::GuardKind::VariableGuard, &D); - - // This BasicBlock attempts to determine whether or not this thread is - // responsible for doing the initialization. - CGF.EmitBlock(AttemptInitBlock); - CGF.EmitNounwindRuntimeCall(getInitThreadHeaderFn(CGM), - GuardAddr.getPointer()); - llvm::LoadInst *SecondGuardLoad = Builder.CreateLoad(GuardAddr); - SecondGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered); - llvm::Value *ShouldDoInit = - Builder.CreateICmpEQ(SecondGuardLoad, getAllOnesInt()); - llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init"); - Builder.CreateCondBr(ShouldDoInit, InitBlock, EndBlock); - - // Ok, we ended up getting selected as the initializing thread. - CGF.EmitBlock(InitBlock); - CGF.EHStack.pushCleanup<CallInitThreadAbort>(EHCleanup, GuardAddr); - CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit); - CGF.PopCleanupBlock(); - CGF.EmitNounwindRuntimeCall(getInitThreadFooterFn(CGM), - GuardAddr.getPointer()); - Builder.CreateBr(EndBlock); - - CGF.EmitBlock(EndBlock); - } -} - -bool MicrosoftCXXABI::isZeroInitializable(const MemberPointerType *MPT) { - // Null-ness for function memptrs only depends on the first field, which is - // the function pointer. The rest don't matter, so we can zero initialize. - if (MPT->isMemberFunctionPointer()) - return true; - - // The virtual base adjustment field is always -1 for null, so if we have one - // we can't zero initialize. The field offset is sometimes also -1 if 0 is a - // valid field offset. - const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); - MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); - return (!MSInheritanceAttr::hasVBTableOffsetField(Inheritance) && - RD->nullFieldOffsetIsZero()); -} - -llvm::Type * -MicrosoftCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) { - const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); - MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); - llvm::SmallVector<llvm::Type *, 4> fields; - if (MPT->isMemberFunctionPointer()) - fields.push_back(CGM.VoidPtrTy); // FunctionPointerOrVirtualThunk - else - fields.push_back(CGM.IntTy); // FieldOffset - - if (MSInheritanceAttr::hasNVOffsetField(MPT->isMemberFunctionPointer(), - Inheritance)) - fields.push_back(CGM.IntTy); - if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) - fields.push_back(CGM.IntTy); - if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance)) - fields.push_back(CGM.IntTy); // VirtualBaseAdjustmentOffset - - if (fields.size() == 1) - return fields[0]; - return llvm::StructType::get(CGM.getLLVMContext(), fields); -} - -void MicrosoftCXXABI:: -GetNullMemberPointerFields(const MemberPointerType *MPT, - llvm::SmallVectorImpl<llvm::Constant *> &fields) { - assert(fields.empty()); - const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); - MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); - if (MPT->isMemberFunctionPointer()) { - // FunctionPointerOrVirtualThunk - fields.push_back(llvm::Constant::getNullValue(CGM.VoidPtrTy)); - } else { - if (RD->nullFieldOffsetIsZero()) - fields.push_back(getZeroInt()); // FieldOffset - else - fields.push_back(getAllOnesInt()); // FieldOffset - } - - if (MSInheritanceAttr::hasNVOffsetField(MPT->isMemberFunctionPointer(), - Inheritance)) - fields.push_back(getZeroInt()); - if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) - fields.push_back(getZeroInt()); - if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance)) - fields.push_back(getAllOnesInt()); -} - -llvm::Constant * -MicrosoftCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { - llvm::SmallVector<llvm::Constant *, 4> fields; - GetNullMemberPointerFields(MPT, fields); - if (fields.size() == 1) - return fields[0]; - llvm::Constant *Res = llvm::ConstantStruct::getAnon(fields); - assert(Res->getType() == ConvertMemberPointerType(MPT)); - return Res; -} - -llvm::Constant * -MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField, - bool IsMemberFunction, - const CXXRecordDecl *RD, - CharUnits NonVirtualBaseAdjustment, - unsigned VBTableIndex) { - MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); - - // Single inheritance class member pointer are represented as scalars instead - // of aggregates. - if (MSInheritanceAttr::hasOnlyOneField(IsMemberFunction, Inheritance)) - return FirstField; - - llvm::SmallVector<llvm::Constant *, 4> fields; - fields.push_back(FirstField); - - if (MSInheritanceAttr::hasNVOffsetField(IsMemberFunction, Inheritance)) - fields.push_back(llvm::ConstantInt::get( - CGM.IntTy, NonVirtualBaseAdjustment.getQuantity())); - - if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) { - CharUnits Offs = CharUnits::Zero(); - if (VBTableIndex) - Offs = getContext().getASTRecordLayout(RD).getVBPtrOffset(); - fields.push_back(llvm::ConstantInt::get(CGM.IntTy, Offs.getQuantity())); - } - - // The rest of the fields are adjusted by conversions to a more derived class. - if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance)) - fields.push_back(llvm::ConstantInt::get(CGM.IntTy, VBTableIndex)); - - return llvm::ConstantStruct::getAnon(fields); -} - -llvm::Constant * -MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, - CharUnits offset) { - const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); - if (RD->getMSInheritanceModel() == - MSInheritanceAttr::Keyword_virtual_inheritance) - offset -= getContext().getOffsetOfBaseWithVBPtr(RD); - llvm::Constant *FirstField = - llvm::ConstantInt::get(CGM.IntTy, offset.getQuantity()); - return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/false, RD, - CharUnits::Zero(), /*VBTableIndex=*/0); -} - -llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const APValue &MP, - QualType MPType) { - const MemberPointerType *DstTy = MPType->castAs<MemberPointerType>(); - const ValueDecl *MPD = MP.getMemberPointerDecl(); - if (!MPD) - return EmitNullMemberPointer(DstTy); - - ASTContext &Ctx = getContext(); - ArrayRef<const CXXRecordDecl *> MemberPointerPath = MP.getMemberPointerPath(); - - llvm::Constant *C; - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) { - C = EmitMemberFunctionPointer(MD); - } else { - CharUnits FieldOffset = Ctx.toCharUnitsFromBits(Ctx.getFieldOffset(MPD)); - C = EmitMemberDataPointer(DstTy, FieldOffset); - } - - if (!MemberPointerPath.empty()) { - const CXXRecordDecl *SrcRD = cast<CXXRecordDecl>(MPD->getDeclContext()); - const Type *SrcRecTy = Ctx.getTypeDeclType(SrcRD).getTypePtr(); - const MemberPointerType *SrcTy = - Ctx.getMemberPointerType(DstTy->getPointeeType(), SrcRecTy) - ->castAs<MemberPointerType>(); - - bool DerivedMember = MP.isMemberPointerToDerivedMember(); - SmallVector<const CXXBaseSpecifier *, 4> DerivedToBasePath; - const CXXRecordDecl *PrevRD = SrcRD; - for (const CXXRecordDecl *PathElem : MemberPointerPath) { - const CXXRecordDecl *Base = nullptr; - const CXXRecordDecl *Derived = nullptr; - if (DerivedMember) { - Base = PathElem; - Derived = PrevRD; - } else { - Base = PrevRD; - Derived = PathElem; - } - for (const CXXBaseSpecifier &BS : Derived->bases()) - if (BS.getType()->getAsCXXRecordDecl()->getCanonicalDecl() == - Base->getCanonicalDecl()) - DerivedToBasePath.push_back(&BS); - PrevRD = PathElem; - } - assert(DerivedToBasePath.size() == MemberPointerPath.size()); - - CastKind CK = DerivedMember ? CK_DerivedToBaseMemberPointer - : CK_BaseToDerivedMemberPointer; - C = EmitMemberPointerConversion(SrcTy, DstTy, CK, DerivedToBasePath.begin(), - DerivedToBasePath.end(), C); - } - return C; -} - -llvm::Constant * -MicrosoftCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { - assert(MD->isInstance() && "Member function must not be static!"); - - CharUnits NonVirtualBaseAdjustment = CharUnits::Zero(); - const CXXRecordDecl *RD = MD->getParent()->getMostRecentNonInjectedDecl(); - CodeGenTypes &Types = CGM.getTypes(); - - unsigned VBTableIndex = 0; - llvm::Constant *FirstField; - const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); - if (!MD->isVirtual()) { - llvm::Type *Ty; - // Check whether the function has a computable LLVM signature. - if (Types.isFuncTypeConvertible(FPT)) { - // The function has a computable LLVM signature; use the correct type. - Ty = Types.GetFunctionType(Types.arrangeCXXMethodDeclaration(MD)); - } else { - // Use an arbitrary non-function type to tell GetAddrOfFunction that the - // function type is incomplete. - Ty = CGM.PtrDiffTy; - } - FirstField = CGM.GetAddrOfFunction(MD, Ty); - } else { - auto &VTableContext = CGM.getMicrosoftVTableContext(); - MethodVFTableLocation ML = VTableContext.getMethodVFTableLocation(MD); - FirstField = EmitVirtualMemPtrThunk(MD, ML); - // Include the vfptr adjustment if the method is in a non-primary vftable. - NonVirtualBaseAdjustment += ML.VFPtrOffset; - if (ML.VBase) - VBTableIndex = VTableContext.getVBTableIndex(RD, ML.VBase) * 4; - } - - if (VBTableIndex == 0 && - RD->getMSInheritanceModel() == - MSInheritanceAttr::Keyword_virtual_inheritance) - NonVirtualBaseAdjustment -= getContext().getOffsetOfBaseWithVBPtr(RD); - - // The rest of the fields are common with data member pointers. - FirstField = llvm::ConstantExpr::getBitCast(FirstField, CGM.VoidPtrTy); - return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/true, RD, - NonVirtualBaseAdjustment, VBTableIndex); -} - -/// Member pointers are the same if they're either bitwise identical *or* both -/// null. Null-ness for function members is determined by the first field, -/// while for data member pointers we must compare all fields. -llvm::Value * -MicrosoftCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF, - llvm::Value *L, - llvm::Value *R, - const MemberPointerType *MPT, - bool Inequality) { - CGBuilderTy &Builder = CGF.Builder; - - // Handle != comparisons by switching the sense of all boolean operations. - llvm::ICmpInst::Predicate Eq; - llvm::Instruction::BinaryOps And, Or; - if (Inequality) { - Eq = llvm::ICmpInst::ICMP_NE; - And = llvm::Instruction::Or; - Or = llvm::Instruction::And; - } else { - Eq = llvm::ICmpInst::ICMP_EQ; - And = llvm::Instruction::And; - Or = llvm::Instruction::Or; - } - - // If this is a single field member pointer (single inheritance), this is a - // single icmp. - const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); - MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); - if (MSInheritanceAttr::hasOnlyOneField(MPT->isMemberFunctionPointer(), - Inheritance)) - return Builder.CreateICmp(Eq, L, R); - - // Compare the first field. - llvm::Value *L0 = Builder.CreateExtractValue(L, 0, "lhs.0"); - llvm::Value *R0 = Builder.CreateExtractValue(R, 0, "rhs.0"); - llvm::Value *Cmp0 = Builder.CreateICmp(Eq, L0, R0, "memptr.cmp.first"); - - // Compare everything other than the first field. - llvm::Value *Res = nullptr; - llvm::StructType *LType = cast<llvm::StructType>(L->getType()); - for (unsigned I = 1, E = LType->getNumElements(); I != E; ++I) { - llvm::Value *LF = Builder.CreateExtractValue(L, I); - llvm::Value *RF = Builder.CreateExtractValue(R, I); - llvm::Value *Cmp = Builder.CreateICmp(Eq, LF, RF, "memptr.cmp.rest"); - if (Res) - Res = Builder.CreateBinOp(And, Res, Cmp); - else - Res = Cmp; - } - - // Check if the first field is 0 if this is a function pointer. - if (MPT->isMemberFunctionPointer()) { - // (l1 == r1 && ...) || l0 == 0 - llvm::Value *Zero = llvm::Constant::getNullValue(L0->getType()); - llvm::Value *IsZero = Builder.CreateICmp(Eq, L0, Zero, "memptr.cmp.iszero"); - Res = Builder.CreateBinOp(Or, Res, IsZero); - } - - // Combine the comparison of the first field, which must always be true for - // this comparison to succeeed. - return Builder.CreateBinOp(And, Res, Cmp0, "memptr.cmp"); -} - -llvm::Value * -MicrosoftCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF, - llvm::Value *MemPtr, - const MemberPointerType *MPT) { - CGBuilderTy &Builder = CGF.Builder; - llvm::SmallVector<llvm::Constant *, 4> fields; - // We only need one field for member functions. - if (MPT->isMemberFunctionPointer()) - fields.push_back(llvm::Constant::getNullValue(CGM.VoidPtrTy)); - else - GetNullMemberPointerFields(MPT, fields); - assert(!fields.empty()); - llvm::Value *FirstField = MemPtr; - if (MemPtr->getType()->isStructTy()) - FirstField = Builder.CreateExtractValue(MemPtr, 0); - llvm::Value *Res = Builder.CreateICmpNE(FirstField, fields[0], "memptr.cmp0"); - - // For function member pointers, we only need to test the function pointer - // field. The other fields if any can be garbage. - if (MPT->isMemberFunctionPointer()) - return Res; - - // Otherwise, emit a series of compares and combine the results. - for (int I = 1, E = fields.size(); I < E; ++I) { - llvm::Value *Field = Builder.CreateExtractValue(MemPtr, I); - llvm::Value *Next = Builder.CreateICmpNE(Field, fields[I], "memptr.cmp"); - Res = Builder.CreateOr(Res, Next, "memptr.tobool"); - } - return Res; -} - -bool MicrosoftCXXABI::MemberPointerConstantIsNull(const MemberPointerType *MPT, - llvm::Constant *Val) { - // Function pointers are null if the pointer in the first field is null. - if (MPT->isMemberFunctionPointer()) { - llvm::Constant *FirstField = Val->getType()->isStructTy() ? - Val->getAggregateElement(0U) : Val; - return FirstField->isNullValue(); - } - - // If it's not a function pointer and it's zero initializable, we can easily - // check zero. - if (isZeroInitializable(MPT) && Val->isNullValue()) - return true; - - // Otherwise, break down all the fields for comparison. Hopefully these - // little Constants are reused, while a big null struct might not be. - llvm::SmallVector<llvm::Constant *, 4> Fields; - GetNullMemberPointerFields(MPT, Fields); - if (Fields.size() == 1) { - assert(Val->getType()->isIntegerTy()); - return Val == Fields[0]; - } - - unsigned I, E; - for (I = 0, E = Fields.size(); I != E; ++I) { - if (Val->getAggregateElement(I) != Fields[I]) - break; - } - return I == E; -} - -llvm::Value * -MicrosoftCXXABI::GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF, - Address This, - llvm::Value *VBPtrOffset, - llvm::Value *VBTableOffset, - llvm::Value **VBPtrOut) { - CGBuilderTy &Builder = CGF.Builder; - // Load the vbtable pointer from the vbptr in the instance. - This = Builder.CreateElementBitCast(This, CGM.Int8Ty); - llvm::Value *VBPtr = - Builder.CreateInBoundsGEP(This.getPointer(), VBPtrOffset, "vbptr"); - if (VBPtrOut) *VBPtrOut = VBPtr; - VBPtr = Builder.CreateBitCast(VBPtr, - CGM.Int32Ty->getPointerTo(0)->getPointerTo(This.getAddressSpace())); - - CharUnits VBPtrAlign; - if (auto CI = dyn_cast<llvm::ConstantInt>(VBPtrOffset)) { - VBPtrAlign = This.getAlignment().alignmentAtOffset( - CharUnits::fromQuantity(CI->getSExtValue())); - } else { - VBPtrAlign = CGF.getPointerAlign(); - } - - llvm::Value *VBTable = Builder.CreateAlignedLoad(VBPtr, VBPtrAlign, "vbtable"); - - // Translate from byte offset to table index. It improves analyzability. - llvm::Value *VBTableIndex = Builder.CreateAShr( - VBTableOffset, llvm::ConstantInt::get(VBTableOffset->getType(), 2), - "vbtindex", /*isExact=*/true); - - // Load an i32 offset from the vb-table. - llvm::Value *VBaseOffs = Builder.CreateInBoundsGEP(VBTable, VBTableIndex); - VBaseOffs = Builder.CreateBitCast(VBaseOffs, CGM.Int32Ty->getPointerTo(0)); - return Builder.CreateAlignedLoad(VBaseOffs, CharUnits::fromQuantity(4), - "vbase_offs"); -} - -// Returns an adjusted base cast to i8*, since we do more address arithmetic on -// it. -llvm::Value *MicrosoftCXXABI::AdjustVirtualBase( - CodeGenFunction &CGF, const Expr *E, const CXXRecordDecl *RD, - Address Base, llvm::Value *VBTableOffset, llvm::Value *VBPtrOffset) { - CGBuilderTy &Builder = CGF.Builder; - Base = Builder.CreateElementBitCast(Base, CGM.Int8Ty); - llvm::BasicBlock *OriginalBB = nullptr; - llvm::BasicBlock *SkipAdjustBB = nullptr; - llvm::BasicBlock *VBaseAdjustBB = nullptr; - - // In the unspecified inheritance model, there might not be a vbtable at all, - // in which case we need to skip the virtual base lookup. If there is a - // vbtable, the first entry is a no-op entry that gives back the original - // base, so look for a virtual base adjustment offset of zero. - if (VBPtrOffset) { - OriginalBB = Builder.GetInsertBlock(); - VBaseAdjustBB = CGF.createBasicBlock("memptr.vadjust"); - SkipAdjustBB = CGF.createBasicBlock("memptr.skip_vadjust"); - llvm::Value *IsVirtual = - Builder.CreateICmpNE(VBTableOffset, getZeroInt(), - "memptr.is_vbase"); - Builder.CreateCondBr(IsVirtual, VBaseAdjustBB, SkipAdjustBB); - CGF.EmitBlock(VBaseAdjustBB); - } - - // If we weren't given a dynamic vbptr offset, RD should be complete and we'll - // know the vbptr offset. - if (!VBPtrOffset) { - CharUnits offs = CharUnits::Zero(); - if (!RD->hasDefinition()) { - DiagnosticsEngine &Diags = CGF.CGM.getDiags(); - unsigned DiagID = Diags.getCustomDiagID( - DiagnosticsEngine::Error, - "member pointer representation requires a " - "complete class type for %0 to perform this expression"); - Diags.Report(E->getExprLoc(), DiagID) << RD << E->getSourceRange(); - } else if (RD->getNumVBases()) - offs = getContext().getASTRecordLayout(RD).getVBPtrOffset(); - VBPtrOffset = llvm::ConstantInt::get(CGM.IntTy, offs.getQuantity()); - } - llvm::Value *VBPtr = nullptr; - llvm::Value *VBaseOffs = - GetVBaseOffsetFromVBPtr(CGF, Base, VBPtrOffset, VBTableOffset, &VBPtr); - llvm::Value *AdjustedBase = Builder.CreateInBoundsGEP(VBPtr, VBaseOffs); - - // Merge control flow with the case where we didn't have to adjust. - if (VBaseAdjustBB) { - Builder.CreateBr(SkipAdjustBB); - CGF.EmitBlock(SkipAdjustBB); - llvm::PHINode *Phi = Builder.CreatePHI(CGM.Int8PtrTy, 2, "memptr.base"); - Phi->addIncoming(Base.getPointer(), OriginalBB); - Phi->addIncoming(AdjustedBase, VBaseAdjustBB); - return Phi; - } - return AdjustedBase; -} - -llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress( - CodeGenFunction &CGF, const Expr *E, Address Base, llvm::Value *MemPtr, - const MemberPointerType *MPT) { - assert(MPT->isMemberDataPointer()); - unsigned AS = Base.getAddressSpace(); - llvm::Type *PType = - CGF.ConvertTypeForMem(MPT->getPointeeType())->getPointerTo(AS); - CGBuilderTy &Builder = CGF.Builder; - const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); - MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); - - // Extract the fields we need, regardless of model. We'll apply them if we - // have them. - llvm::Value *FieldOffset = MemPtr; - llvm::Value *VirtualBaseAdjustmentOffset = nullptr; - llvm::Value *VBPtrOffset = nullptr; - if (MemPtr->getType()->isStructTy()) { - // We need to extract values. - unsigned I = 0; - FieldOffset = Builder.CreateExtractValue(MemPtr, I++); - if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) - VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++); - if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance)) - VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++); - } - - llvm::Value *Addr; - if (VirtualBaseAdjustmentOffset) { - Addr = AdjustVirtualBase(CGF, E, RD, Base, VirtualBaseAdjustmentOffset, - VBPtrOffset); - } else { - Addr = Base.getPointer(); - } - - // Cast to char*. - Addr = Builder.CreateBitCast(Addr, CGF.Int8Ty->getPointerTo(AS)); - - // Apply the offset, which we assume is non-null. - Addr = Builder.CreateInBoundsGEP(Addr, FieldOffset, "memptr.offset"); - - // Cast the address to the appropriate pointer type, adopting the address - // space of the base pointer. - return Builder.CreateBitCast(Addr, PType); -} - -llvm::Value * -MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, - const CastExpr *E, - llvm::Value *Src) { - assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || - E->getCastKind() == CK_BaseToDerivedMemberPointer || - E->getCastKind() == CK_ReinterpretMemberPointer); - - // Use constant emission if we can. - if (isa<llvm::Constant>(Src)) - return EmitMemberPointerConversion(E, cast<llvm::Constant>(Src)); - - // We may be adding or dropping fields from the member pointer, so we need - // both types and the inheritance models of both records. - const MemberPointerType *SrcTy = - E->getSubExpr()->getType()->castAs<MemberPointerType>(); - const MemberPointerType *DstTy = E->getType()->castAs<MemberPointerType>(); - bool IsFunc = SrcTy->isMemberFunctionPointer(); - - // If the classes use the same null representation, reinterpret_cast is a nop. - bool IsReinterpret = E->getCastKind() == CK_ReinterpretMemberPointer; - if (IsReinterpret && IsFunc) - return Src; - - CXXRecordDecl *SrcRD = SrcTy->getMostRecentCXXRecordDecl(); - CXXRecordDecl *DstRD = DstTy->getMostRecentCXXRecordDecl(); - if (IsReinterpret && - SrcRD->nullFieldOffsetIsZero() == DstRD->nullFieldOffsetIsZero()) - return Src; - - CGBuilderTy &Builder = CGF.Builder; - - // Branch past the conversion if Src is null. - llvm::Value *IsNotNull = EmitMemberPointerIsNotNull(CGF, Src, SrcTy); - llvm::Constant *DstNull = EmitNullMemberPointer(DstTy); - - // C++ 5.2.10p9: The null member pointer value is converted to the null member - // pointer value of the destination type. - if (IsReinterpret) { - // For reinterpret casts, sema ensures that src and dst are both functions - // or data and have the same size, which means the LLVM types should match. - assert(Src->getType() == DstNull->getType()); - return Builder.CreateSelect(IsNotNull, Src, DstNull); - } - - llvm::BasicBlock *OriginalBB = Builder.GetInsertBlock(); - llvm::BasicBlock *ConvertBB = CGF.createBasicBlock("memptr.convert"); - llvm::BasicBlock *ContinueBB = CGF.createBasicBlock("memptr.converted"); - Builder.CreateCondBr(IsNotNull, ConvertBB, ContinueBB); - CGF.EmitBlock(ConvertBB); - - llvm::Value *Dst = EmitNonNullMemberPointerConversion( - SrcTy, DstTy, E->getCastKind(), E->path_begin(), E->path_end(), Src, - Builder); - - Builder.CreateBr(ContinueBB); - - // In the continuation, choose between DstNull and Dst. - CGF.EmitBlock(ContinueBB); - llvm::PHINode *Phi = Builder.CreatePHI(DstNull->getType(), 2, "memptr.converted"); - Phi->addIncoming(DstNull, OriginalBB); - Phi->addIncoming(Dst, ConvertBB); - return Phi; -} - -llvm::Value *MicrosoftCXXABI::EmitNonNullMemberPointerConversion( - const MemberPointerType *SrcTy, const MemberPointerType *DstTy, CastKind CK, - CastExpr::path_const_iterator PathBegin, - CastExpr::path_const_iterator PathEnd, llvm::Value *Src, - CGBuilderTy &Builder) { - const CXXRecordDecl *SrcRD = SrcTy->getMostRecentCXXRecordDecl(); - const CXXRecordDecl *DstRD = DstTy->getMostRecentCXXRecordDecl(); - MSInheritanceAttr::Spelling SrcInheritance = SrcRD->getMSInheritanceModel(); - MSInheritanceAttr::Spelling DstInheritance = DstRD->getMSInheritanceModel(); - bool IsFunc = SrcTy->isMemberFunctionPointer(); - bool IsConstant = isa<llvm::Constant>(Src); - - // Decompose src. - llvm::Value *FirstField = Src; - llvm::Value *NonVirtualBaseAdjustment = getZeroInt(); - llvm::Value *VirtualBaseAdjustmentOffset = getZeroInt(); - llvm::Value *VBPtrOffset = getZeroInt(); - if (!MSInheritanceAttr::hasOnlyOneField(IsFunc, SrcInheritance)) { - // We need to extract values. - unsigned I = 0; - FirstField = Builder.CreateExtractValue(Src, I++); - if (MSInheritanceAttr::hasNVOffsetField(IsFunc, SrcInheritance)) - NonVirtualBaseAdjustment = Builder.CreateExtractValue(Src, I++); - if (MSInheritanceAttr::hasVBPtrOffsetField(SrcInheritance)) - VBPtrOffset = Builder.CreateExtractValue(Src, I++); - if (MSInheritanceAttr::hasVBTableOffsetField(SrcInheritance)) - VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(Src, I++); - } - - bool IsDerivedToBase = (CK == CK_DerivedToBaseMemberPointer); - const MemberPointerType *DerivedTy = IsDerivedToBase ? SrcTy : DstTy; - const CXXRecordDecl *DerivedClass = DerivedTy->getMostRecentCXXRecordDecl(); - - // For data pointers, we adjust the field offset directly. For functions, we - // have a separate field. - llvm::Value *&NVAdjustField = IsFunc ? NonVirtualBaseAdjustment : FirstField; - - // The virtual inheritance model has a quirk: the virtual base table is always - // referenced when dereferencing a member pointer even if the member pointer - // is non-virtual. This is accounted for by adjusting the non-virtual offset - // to point backwards to the top of the MDC from the first VBase. Undo this - // adjustment to normalize the member pointer. - llvm::Value *SrcVBIndexEqZero = - Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt()); - if (SrcInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) { - if (int64_t SrcOffsetToFirstVBase = - getContext().getOffsetOfBaseWithVBPtr(SrcRD).getQuantity()) { - llvm::Value *UndoSrcAdjustment = Builder.CreateSelect( - SrcVBIndexEqZero, - llvm::ConstantInt::get(CGM.IntTy, SrcOffsetToFirstVBase), - getZeroInt()); - NVAdjustField = Builder.CreateNSWAdd(NVAdjustField, UndoSrcAdjustment); - } - } - - // A non-zero vbindex implies that we are dealing with a source member in a - // floating virtual base in addition to some non-virtual offset. If the - // vbindex is zero, we are dealing with a source that exists in a non-virtual, - // fixed, base. The difference between these two cases is that the vbindex + - // nvoffset *always* point to the member regardless of what context they are - // evaluated in so long as the vbindex is adjusted. A member inside a fixed - // base requires explicit nv adjustment. - llvm::Constant *BaseClassOffset = llvm::ConstantInt::get( - CGM.IntTy, - CGM.computeNonVirtualBaseClassOffset(DerivedClass, PathBegin, PathEnd) - .getQuantity()); - - llvm::Value *NVDisp; - if (IsDerivedToBase) - NVDisp = Builder.CreateNSWSub(NVAdjustField, BaseClassOffset, "adj"); - else - NVDisp = Builder.CreateNSWAdd(NVAdjustField, BaseClassOffset, "adj"); - - NVAdjustField = Builder.CreateSelect(SrcVBIndexEqZero, NVDisp, getZeroInt()); - - // Update the vbindex to an appropriate value in the destination because - // SrcRD's vbtable might not be a strict prefix of the one in DstRD. - llvm::Value *DstVBIndexEqZero = SrcVBIndexEqZero; - if (MSInheritanceAttr::hasVBTableOffsetField(DstInheritance) && - MSInheritanceAttr::hasVBTableOffsetField(SrcInheritance)) { - if (llvm::GlobalVariable *VDispMap = - getAddrOfVirtualDisplacementMap(SrcRD, DstRD)) { - llvm::Value *VBIndex = Builder.CreateExactUDiv( - VirtualBaseAdjustmentOffset, llvm::ConstantInt::get(CGM.IntTy, 4)); - if (IsConstant) { - llvm::Constant *Mapping = VDispMap->getInitializer(); - VirtualBaseAdjustmentOffset = - Mapping->getAggregateElement(cast<llvm::Constant>(VBIndex)); - } else { - llvm::Value *Idxs[] = {getZeroInt(), VBIndex}; - VirtualBaseAdjustmentOffset = - Builder.CreateAlignedLoad(Builder.CreateInBoundsGEP(VDispMap, Idxs), - CharUnits::fromQuantity(4)); - } - - DstVBIndexEqZero = - Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt()); - } - } - - // Set the VBPtrOffset to zero if the vbindex is zero. Otherwise, initialize - // it to the offset of the vbptr. - if (MSInheritanceAttr::hasVBPtrOffsetField(DstInheritance)) { - llvm::Value *DstVBPtrOffset = llvm::ConstantInt::get( - CGM.IntTy, - getContext().getASTRecordLayout(DstRD).getVBPtrOffset().getQuantity()); - VBPtrOffset = - Builder.CreateSelect(DstVBIndexEqZero, getZeroInt(), DstVBPtrOffset); - } - - // Likewise, apply a similar adjustment so that dereferencing the member - // pointer correctly accounts for the distance between the start of the first - // virtual base and the top of the MDC. - if (DstInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) { - if (int64_t DstOffsetToFirstVBase = - getContext().getOffsetOfBaseWithVBPtr(DstRD).getQuantity()) { - llvm::Value *DoDstAdjustment = Builder.CreateSelect( - DstVBIndexEqZero, - llvm::ConstantInt::get(CGM.IntTy, DstOffsetToFirstVBase), - getZeroInt()); - NVAdjustField = Builder.CreateNSWSub(NVAdjustField, DoDstAdjustment); - } - } - - // Recompose dst from the null struct and the adjusted fields from src. - llvm::Value *Dst; - if (MSInheritanceAttr::hasOnlyOneField(IsFunc, DstInheritance)) { - Dst = FirstField; - } else { - Dst = llvm::UndefValue::get(ConvertMemberPointerType(DstTy)); - unsigned Idx = 0; - Dst = Builder.CreateInsertValue(Dst, FirstField, Idx++); - if (MSInheritanceAttr::hasNVOffsetField(IsFunc, DstInheritance)) - Dst = Builder.CreateInsertValue(Dst, NonVirtualBaseAdjustment, Idx++); - if (MSInheritanceAttr::hasVBPtrOffsetField(DstInheritance)) - Dst = Builder.CreateInsertValue(Dst, VBPtrOffset, Idx++); - if (MSInheritanceAttr::hasVBTableOffsetField(DstInheritance)) - Dst = Builder.CreateInsertValue(Dst, VirtualBaseAdjustmentOffset, Idx++); - } - return Dst; -} - -llvm::Constant * -MicrosoftCXXABI::EmitMemberPointerConversion(const CastExpr *E, - llvm::Constant *Src) { - const MemberPointerType *SrcTy = - E->getSubExpr()->getType()->castAs<MemberPointerType>(); - const MemberPointerType *DstTy = E->getType()->castAs<MemberPointerType>(); - - CastKind CK = E->getCastKind(); - - return EmitMemberPointerConversion(SrcTy, DstTy, CK, E->path_begin(), - E->path_end(), Src); -} - -llvm::Constant *MicrosoftCXXABI::EmitMemberPointerConversion( - const MemberPointerType *SrcTy, const MemberPointerType *DstTy, CastKind CK, - CastExpr::path_const_iterator PathBegin, - CastExpr::path_const_iterator PathEnd, llvm::Constant *Src) { - assert(CK == CK_DerivedToBaseMemberPointer || - CK == CK_BaseToDerivedMemberPointer || - CK == CK_ReinterpretMemberPointer); - // If src is null, emit a new null for dst. We can't return src because dst - // might have a new representation. - if (MemberPointerConstantIsNull(SrcTy, Src)) - return EmitNullMemberPointer(DstTy); - - // We don't need to do anything for reinterpret_casts of non-null member - // pointers. We should only get here when the two type representations have - // the same size. - if (CK == CK_ReinterpretMemberPointer) - return Src; - - CGBuilderTy Builder(CGM, CGM.getLLVMContext()); - auto *Dst = cast<llvm::Constant>(EmitNonNullMemberPointerConversion( - SrcTy, DstTy, CK, PathBegin, PathEnd, Src, Builder)); - - return Dst; -} - -CGCallee MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer( - CodeGenFunction &CGF, const Expr *E, Address This, - llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr, - const MemberPointerType *MPT) { - assert(MPT->isMemberFunctionPointer()); - const FunctionProtoType *FPT = - MPT->getPointeeType()->castAs<FunctionProtoType>(); - const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); - llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType( - CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr)); - CGBuilderTy &Builder = CGF.Builder; - - MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); - - // Extract the fields we need, regardless of model. We'll apply them if we - // have them. - llvm::Value *FunctionPointer = MemPtr; - llvm::Value *NonVirtualBaseAdjustment = nullptr; - llvm::Value *VirtualBaseAdjustmentOffset = nullptr; - llvm::Value *VBPtrOffset = nullptr; - if (MemPtr->getType()->isStructTy()) { - // We need to extract values. - unsigned I = 0; - FunctionPointer = Builder.CreateExtractValue(MemPtr, I++); - if (MSInheritanceAttr::hasNVOffsetField(MPT, Inheritance)) - NonVirtualBaseAdjustment = Builder.CreateExtractValue(MemPtr, I++); - if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) - VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++); - if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance)) - VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++); - } - - if (VirtualBaseAdjustmentOffset) { - ThisPtrForCall = AdjustVirtualBase(CGF, E, RD, This, - VirtualBaseAdjustmentOffset, VBPtrOffset); - } else { - ThisPtrForCall = This.getPointer(); - } - - if (NonVirtualBaseAdjustment) { - // Apply the adjustment and cast back to the original struct type. - llvm::Value *Ptr = Builder.CreateBitCast(ThisPtrForCall, CGF.Int8PtrTy); - Ptr = Builder.CreateInBoundsGEP(Ptr, NonVirtualBaseAdjustment); - ThisPtrForCall = Builder.CreateBitCast(Ptr, ThisPtrForCall->getType(), - "this.adjusted"); - } - - FunctionPointer = - Builder.CreateBitCast(FunctionPointer, FTy->getPointerTo()); - CGCallee Callee(FPT, FunctionPointer); - return Callee; -} - -CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) { - return new MicrosoftCXXABI(CGM); -} - -// MS RTTI Overview: -// The run time type information emitted by cl.exe contains 5 distinct types of -// structures. Many of them reference each other. -// -// TypeInfo: Static classes that are returned by typeid. -// -// CompleteObjectLocator: Referenced by vftables. They contain information -// required for dynamic casting, including OffsetFromTop. They also contain -// a reference to the TypeInfo for the type and a reference to the -// CompleteHierarchyDescriptor for the type. -// -// ClassHierarchyDescriptor: Contains information about a class hierarchy. -// Used during dynamic_cast to walk a class hierarchy. References a base -// class array and the size of said array. -// -// BaseClassArray: Contains a list of classes in a hierarchy. BaseClassArray is -// somewhat of a misnomer because the most derived class is also in the list -// as well as multiple copies of virtual bases (if they occur multiple times -// in the hierarchy.) The BaseClassArray contains one BaseClassDescriptor for -// every path in the hierarchy, in pre-order depth first order. Note, we do -// not declare a specific llvm type for BaseClassArray, it's merely an array -// of BaseClassDescriptor pointers. -// -// BaseClassDescriptor: Contains information about a class in a class hierarchy. -// BaseClassDescriptor is also somewhat of a misnomer for the same reason that -// BaseClassArray is. It contains information about a class within a -// hierarchy such as: is this base is ambiguous and what is its offset in the -// vbtable. The names of the BaseClassDescriptors have all of their fields -// mangled into them so they can be aggressively deduplicated by the linker. - -static llvm::GlobalVariable *getTypeInfoVTable(CodeGenModule &CGM) { - StringRef MangledName("??_7type_info@@6B@"); - if (auto VTable = CGM.getModule().getNamedGlobal(MangledName)) - return VTable; - return new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy, - /*Constant=*/true, - llvm::GlobalVariable::ExternalLinkage, - /*Initializer=*/nullptr, MangledName); -} - -namespace { - -/// A Helper struct that stores information about a class in a class -/// hierarchy. The information stored in these structs struct is used during -/// the generation of ClassHierarchyDescriptors and BaseClassDescriptors. -// During RTTI creation, MSRTTIClasses are stored in a contiguous array with -// implicit depth first pre-order tree connectivity. getFirstChild and -// getNextSibling allow us to walk the tree efficiently. -struct MSRTTIClass { - enum { - IsPrivateOnPath = 1 | 8, - IsAmbiguous = 2, - IsPrivate = 4, - IsVirtual = 16, - HasHierarchyDescriptor = 64 - }; - MSRTTIClass(const CXXRecordDecl *RD) : RD(RD) {} - uint32_t initialize(const MSRTTIClass *Parent, - const CXXBaseSpecifier *Specifier); - - MSRTTIClass *getFirstChild() { return this + 1; } - static MSRTTIClass *getNextChild(MSRTTIClass *Child) { - return Child + 1 + Child->NumBases; - } - - const CXXRecordDecl *RD, *VirtualRoot; - uint32_t Flags, NumBases, OffsetInVBase; -}; - -/// Recursively initialize the base class array. -uint32_t MSRTTIClass::initialize(const MSRTTIClass *Parent, - const CXXBaseSpecifier *Specifier) { - Flags = HasHierarchyDescriptor; - if (!Parent) { - VirtualRoot = nullptr; - OffsetInVBase = 0; - } else { - if (Specifier->getAccessSpecifier() != AS_public) - Flags |= IsPrivate | IsPrivateOnPath; - if (Specifier->isVirtual()) { - Flags |= IsVirtual; - VirtualRoot = RD; - OffsetInVBase = 0; - } else { - if (Parent->Flags & IsPrivateOnPath) - Flags |= IsPrivateOnPath; - VirtualRoot = Parent->VirtualRoot; - OffsetInVBase = Parent->OffsetInVBase + RD->getASTContext() - .getASTRecordLayout(Parent->RD).getBaseClassOffset(RD).getQuantity(); - } - } - NumBases = 0; - MSRTTIClass *Child = getFirstChild(); - for (const CXXBaseSpecifier &Base : RD->bases()) { - NumBases += Child->initialize(this, &Base) + 1; - Child = getNextChild(Child); - } - return NumBases; -} - -static llvm::GlobalValue::LinkageTypes getLinkageForRTTI(QualType Ty) { - switch (Ty->getLinkage()) { - case NoLinkage: - case InternalLinkage: - case UniqueExternalLinkage: - return llvm::GlobalValue::InternalLinkage; - - case VisibleNoLinkage: - case ModuleInternalLinkage: - case ModuleLinkage: - case ExternalLinkage: - return llvm::GlobalValue::LinkOnceODRLinkage; - } - llvm_unreachable("Invalid linkage!"); -} - -/// An ephemeral helper class for building MS RTTI types. It caches some -/// calls to the module and information about the most derived class in a -/// hierarchy. -struct MSRTTIBuilder { - enum { - HasBranchingHierarchy = 1, - HasVirtualBranchingHierarchy = 2, - HasAmbiguousBases = 4 - }; - - MSRTTIBuilder(MicrosoftCXXABI &ABI, const CXXRecordDecl *RD) - : CGM(ABI.CGM), Context(CGM.getContext()), - VMContext(CGM.getLLVMContext()), Module(CGM.getModule()), RD(RD), - Linkage(getLinkageForRTTI(CGM.getContext().getTagDeclType(RD))), - ABI(ABI) {} - - llvm::GlobalVariable *getBaseClassDescriptor(const MSRTTIClass &Classes); - llvm::GlobalVariable * - getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes); - llvm::GlobalVariable *getClassHierarchyDescriptor(); - llvm::GlobalVariable *getCompleteObjectLocator(const VPtrInfo &Info); - - CodeGenModule &CGM; - ASTContext &Context; - llvm::LLVMContext &VMContext; - llvm::Module &Module; - const CXXRecordDecl *RD; - llvm::GlobalVariable::LinkageTypes Linkage; - MicrosoftCXXABI &ABI; -}; - -} // namespace - -/// Recursively serializes a class hierarchy in pre-order depth first -/// order. -static void serializeClassHierarchy(SmallVectorImpl<MSRTTIClass> &Classes, - const CXXRecordDecl *RD) { - Classes.push_back(MSRTTIClass(RD)); - for (const CXXBaseSpecifier &Base : RD->bases()) - serializeClassHierarchy(Classes, Base.getType()->getAsCXXRecordDecl()); -} - -/// Find ambiguity among base classes. -static void -detectAmbiguousBases(SmallVectorImpl<MSRTTIClass> &Classes) { - llvm::SmallPtrSet<const CXXRecordDecl *, 8> VirtualBases; - llvm::SmallPtrSet<const CXXRecordDecl *, 8> UniqueBases; - llvm::SmallPtrSet<const CXXRecordDecl *, 8> AmbiguousBases; - for (MSRTTIClass *Class = &Classes.front(); Class <= &Classes.back();) { - if ((Class->Flags & MSRTTIClass::IsVirtual) && - !VirtualBases.insert(Class->RD).second) { - Class = MSRTTIClass::getNextChild(Class); - continue; - } - if (!UniqueBases.insert(Class->RD).second) - AmbiguousBases.insert(Class->RD); - Class++; - } - if (AmbiguousBases.empty()) - return; - for (MSRTTIClass &Class : Classes) - if (AmbiguousBases.count(Class.RD)) - Class.Flags |= MSRTTIClass::IsAmbiguous; -} - -llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() { - SmallString<256> MangledName; - { - llvm::raw_svector_ostream Out(MangledName); - ABI.getMangleContext().mangleCXXRTTIClassHierarchyDescriptor(RD, Out); - } - - // Check to see if we've already declared this ClassHierarchyDescriptor. - if (auto CHD = Module.getNamedGlobal(MangledName)) - return CHD; - - // Serialize the class hierarchy and initialize the CHD Fields. - SmallVector<MSRTTIClass, 8> Classes; - serializeClassHierarchy(Classes, RD); - Classes.front().initialize(/*Parent=*/nullptr, /*Specifier=*/nullptr); - detectAmbiguousBases(Classes); - int Flags = 0; - for (auto Class : Classes) { - if (Class.RD->getNumBases() > 1) - Flags |= HasBranchingHierarchy; - // Note: cl.exe does not calculate "HasAmbiguousBases" correctly. We - // believe the field isn't actually used. - if (Class.Flags & MSRTTIClass::IsAmbiguous) - Flags |= HasAmbiguousBases; - } - if ((Flags & HasBranchingHierarchy) && RD->getNumVBases() != 0) - Flags |= HasVirtualBranchingHierarchy; - // These gep indices are used to get the address of the first element of the - // base class array. - llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.IntTy, 0), - llvm::ConstantInt::get(CGM.IntTy, 0)}; - - // Forward-declare the class hierarchy descriptor - auto Type = ABI.getClassHierarchyDescriptorType(); - auto CHD = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage, - /*Initializer=*/nullptr, - MangledName); - if (CHD->isWeakForLinker()) - CHD->setComdat(CGM.getModule().getOrInsertComdat(CHD->getName())); - - auto *Bases = getBaseClassArray(Classes); - - // Initialize the base class ClassHierarchyDescriptor. - llvm::Constant *Fields[] = { - llvm::ConstantInt::get(CGM.IntTy, 0), // reserved by the runtime - llvm::ConstantInt::get(CGM.IntTy, Flags), - llvm::ConstantInt::get(CGM.IntTy, Classes.size()), - ABI.getImageRelativeConstant(llvm::ConstantExpr::getInBoundsGetElementPtr( - Bases->getValueType(), Bases, - llvm::ArrayRef<llvm::Value *>(GEPIndices))), - }; - CHD->setInitializer(llvm::ConstantStruct::get(Type, Fields)); - return CHD; -} - -llvm::GlobalVariable * -MSRTTIBuilder::getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes) { - SmallString<256> MangledName; - { - llvm::raw_svector_ostream Out(MangledName); - ABI.getMangleContext().mangleCXXRTTIBaseClassArray(RD, Out); - } - - // Forward-declare the base class array. - // cl.exe pads the base class array with 1 (in 32 bit mode) or 4 (in 64 bit - // mode) bytes of padding. We provide a pointer sized amount of padding by - // adding +1 to Classes.size(). The sections have pointer alignment and are - // marked pick-any so it shouldn't matter. - llvm::Type *PtrType = ABI.getImageRelativeType( - ABI.getBaseClassDescriptorType()->getPointerTo()); - auto *ArrType = llvm::ArrayType::get(PtrType, Classes.size() + 1); - auto *BCA = - new llvm::GlobalVariable(Module, ArrType, - /*Constant=*/true, Linkage, - /*Initializer=*/nullptr, MangledName); - if (BCA->isWeakForLinker()) - BCA->setComdat(CGM.getModule().getOrInsertComdat(BCA->getName())); - - // Initialize the BaseClassArray. - SmallVector<llvm::Constant *, 8> BaseClassArrayData; - for (MSRTTIClass &Class : Classes) - BaseClassArrayData.push_back( - ABI.getImageRelativeConstant(getBaseClassDescriptor(Class))); - BaseClassArrayData.push_back(llvm::Constant::getNullValue(PtrType)); - BCA->setInitializer(llvm::ConstantArray::get(ArrType, BaseClassArrayData)); - return BCA; -} - -llvm::GlobalVariable * -MSRTTIBuilder::getBaseClassDescriptor(const MSRTTIClass &Class) { - // Compute the fields for the BaseClassDescriptor. They are computed up front - // because they are mangled into the name of the object. - uint32_t OffsetInVBTable = 0; - int32_t VBPtrOffset = -1; - if (Class.VirtualRoot) { - auto &VTableContext = CGM.getMicrosoftVTableContext(); - OffsetInVBTable = VTableContext.getVBTableIndex(RD, Class.VirtualRoot) * 4; - VBPtrOffset = Context.getASTRecordLayout(RD).getVBPtrOffset().getQuantity(); - } - - SmallString<256> MangledName; - { - llvm::raw_svector_ostream Out(MangledName); - ABI.getMangleContext().mangleCXXRTTIBaseClassDescriptor( - Class.RD, Class.OffsetInVBase, VBPtrOffset, OffsetInVBTable, - Class.Flags, Out); - } - - // Check to see if we've already declared this object. - if (auto BCD = Module.getNamedGlobal(MangledName)) - return BCD; - - // Forward-declare the base class descriptor. - auto Type = ABI.getBaseClassDescriptorType(); - auto BCD = - new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage, - /*Initializer=*/nullptr, MangledName); - if (BCD->isWeakForLinker()) - BCD->setComdat(CGM.getModule().getOrInsertComdat(BCD->getName())); - - // Initialize the BaseClassDescriptor. - llvm::Constant *Fields[] = { - ABI.getImageRelativeConstant( - ABI.getAddrOfRTTIDescriptor(Context.getTypeDeclType(Class.RD))), - llvm::ConstantInt::get(CGM.IntTy, Class.NumBases), - llvm::ConstantInt::get(CGM.IntTy, Class.OffsetInVBase), - llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset), - llvm::ConstantInt::get(CGM.IntTy, OffsetInVBTable), - llvm::ConstantInt::get(CGM.IntTy, Class.Flags), - ABI.getImageRelativeConstant( - MSRTTIBuilder(ABI, Class.RD).getClassHierarchyDescriptor()), - }; - BCD->setInitializer(llvm::ConstantStruct::get(Type, Fields)); - return BCD; -} - -llvm::GlobalVariable * -MSRTTIBuilder::getCompleteObjectLocator(const VPtrInfo &Info) { - SmallString<256> MangledName; - { - llvm::raw_svector_ostream Out(MangledName); - ABI.getMangleContext().mangleCXXRTTICompleteObjectLocator(RD, Info.MangledPath, Out); - } - - // Check to see if we've already computed this complete object locator. - if (auto COL = Module.getNamedGlobal(MangledName)) - return COL; - - // Compute the fields of the complete object locator. - int OffsetToTop = Info.FullOffsetInMDC.getQuantity(); - int VFPtrOffset = 0; - // The offset includes the vtordisp if one exists. - if (const CXXRecordDecl *VBase = Info.getVBaseWithVPtr()) - if (Context.getASTRecordLayout(RD) - .getVBaseOffsetsMap() - .find(VBase) - ->second.hasVtorDisp()) - VFPtrOffset = Info.NonVirtualOffset.getQuantity() + 4; - - // Forward-declare the complete object locator. - llvm::StructType *Type = ABI.getCompleteObjectLocatorType(); - auto COL = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage, - /*Initializer=*/nullptr, MangledName); - - // Initialize the CompleteObjectLocator. - llvm::Constant *Fields[] = { - llvm::ConstantInt::get(CGM.IntTy, ABI.isImageRelative()), - llvm::ConstantInt::get(CGM.IntTy, OffsetToTop), - llvm::ConstantInt::get(CGM.IntTy, VFPtrOffset), - ABI.getImageRelativeConstant( - CGM.GetAddrOfRTTIDescriptor(Context.getTypeDeclType(RD))), - ABI.getImageRelativeConstant(getClassHierarchyDescriptor()), - ABI.getImageRelativeConstant(COL), - }; - llvm::ArrayRef<llvm::Constant *> FieldsRef(Fields); - if (!ABI.isImageRelative()) - FieldsRef = FieldsRef.drop_back(); - COL->setInitializer(llvm::ConstantStruct::get(Type, FieldsRef)); - if (COL->isWeakForLinker()) - COL->setComdat(CGM.getModule().getOrInsertComdat(COL->getName())); - return COL; -} - -static QualType decomposeTypeForEH(ASTContext &Context, QualType T, - bool &IsConst, bool &IsVolatile, - bool &IsUnaligned) { - T = Context.getExceptionObjectType(T); - - // C++14 [except.handle]p3: - // A handler is a match for an exception object of type E if [...] - // - the handler is of type cv T or const T& where T is a pointer type and - // E is a pointer type that can be converted to T by [...] - // - a qualification conversion - IsConst = false; - IsVolatile = false; - IsUnaligned = false; - QualType PointeeType = T->getPointeeType(); - if (!PointeeType.isNull()) { - IsConst = PointeeType.isConstQualified(); - IsVolatile = PointeeType.isVolatileQualified(); - IsUnaligned = PointeeType.getQualifiers().hasUnaligned(); - } - - // Member pointer types like "const int A::*" are represented by having RTTI - // for "int A::*" and separately storing the const qualifier. - if (const auto *MPTy = T->getAs<MemberPointerType>()) - T = Context.getMemberPointerType(PointeeType.getUnqualifiedType(), - MPTy->getClass()); - - // Pointer types like "const int * const *" are represented by having RTTI - // for "const int **" and separately storing the const qualifier. - if (T->isPointerType()) - T = Context.getPointerType(PointeeType.getUnqualifiedType()); - - return T; -} - -CatchTypeInfo -MicrosoftCXXABI::getAddrOfCXXCatchHandlerType(QualType Type, - QualType CatchHandlerType) { - // TypeDescriptors for exceptions never have qualified pointer types, - // qualifiers are stored separately in order to support qualification - // conversions. - bool IsConst, IsVolatile, IsUnaligned; - Type = - decomposeTypeForEH(getContext(), Type, IsConst, IsVolatile, IsUnaligned); - - bool IsReference = CatchHandlerType->isReferenceType(); - - uint32_t Flags = 0; - if (IsConst) - Flags |= 1; - if (IsVolatile) - Flags |= 2; - if (IsUnaligned) - Flags |= 4; - if (IsReference) - Flags |= 8; - - return CatchTypeInfo{getAddrOfRTTIDescriptor(Type)->stripPointerCasts(), - Flags}; -} - -/// Gets a TypeDescriptor. Returns a llvm::Constant * rather than a -/// llvm::GlobalVariable * because different type descriptors have different -/// types, and need to be abstracted. They are abstracting by casting the -/// address to an Int8PtrTy. -llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType Type) { - SmallString<256> MangledName; - { - llvm::raw_svector_ostream Out(MangledName); - getMangleContext().mangleCXXRTTI(Type, Out); - } - - // Check to see if we've already declared this TypeDescriptor. - if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName)) - return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy); - - // Note for the future: If we would ever like to do deferred emission of - // RTTI, check if emitting vtables opportunistically need any adjustment. - - // Compute the fields for the TypeDescriptor. - SmallString<256> TypeInfoString; - { - llvm::raw_svector_ostream Out(TypeInfoString); - getMangleContext().mangleCXXRTTIName(Type, Out); - } - - // Declare and initialize the TypeDescriptor. - llvm::Constant *Fields[] = { - getTypeInfoVTable(CGM), // VFPtr - llvm::ConstantPointerNull::get(CGM.Int8PtrTy), // Runtime data - llvm::ConstantDataArray::getString(CGM.getLLVMContext(), TypeInfoString)}; - llvm::StructType *TypeDescriptorType = - getTypeDescriptorType(TypeInfoString); - auto *Var = new llvm::GlobalVariable( - CGM.getModule(), TypeDescriptorType, /*Constant=*/false, - getLinkageForRTTI(Type), - llvm::ConstantStruct::get(TypeDescriptorType, Fields), - MangledName); - if (Var->isWeakForLinker()) - Var->setComdat(CGM.getModule().getOrInsertComdat(Var->getName())); - return llvm::ConstantExpr::getBitCast(Var, CGM.Int8PtrTy); -} - -/// Gets or a creates a Microsoft CompleteObjectLocator. -llvm::GlobalVariable * -MicrosoftCXXABI::getMSCompleteObjectLocator(const CXXRecordDecl *RD, - const VPtrInfo &Info) { - return MSRTTIBuilder(*this, RD).getCompleteObjectLocator(Info); -} - -static void emitCXXConstructor(CodeGenModule &CGM, - const CXXConstructorDecl *ctor, - StructorType ctorType) { - // There are no constructor variants, always emit the complete destructor. - llvm::Function *Fn = CGM.codegenCXXStructor(ctor, StructorType::Complete); - CGM.maybeSetTrivialComdat(*ctor, *Fn); -} - -static void emitCXXDestructor(CodeGenModule &CGM, const CXXDestructorDecl *dtor, - StructorType dtorType) { - // Emit the base destructor if the base and complete (vbase) destructors are - // equivalent. This effectively implements -mconstructor-aliases as part of - // the ABI. - if (dtorType == StructorType::Complete && - dtor->getParent()->getNumVBases() == 0) - dtorType = StructorType::Base; - - // The base destructor is equivalent to the base destructor of its - // base class if there is exactly one non-virtual base class with a - // non-trivial destructor, there are no fields with a non-trivial - // destructor, and the body of the destructor is trivial. - if (dtorType == StructorType::Base && !CGM.TryEmitBaseDestructorAsAlias(dtor)) - return; - - llvm::Function *Fn = CGM.codegenCXXStructor(dtor, dtorType); - if (Fn->isWeakForLinker()) - Fn->setComdat(CGM.getModule().getOrInsertComdat(Fn->getName())); -} - -void MicrosoftCXXABI::emitCXXStructor(const CXXMethodDecl *MD, - StructorType Type) { - if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) { - emitCXXConstructor(CGM, CD, Type); - return; - } - emitCXXDestructor(CGM, cast<CXXDestructorDecl>(MD), Type); -} - -llvm::Function * -MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD, - CXXCtorType CT) { - assert(CT == Ctor_CopyingClosure || CT == Ctor_DefaultClosure); - - // Calculate the mangled name. - SmallString<256> ThunkName; - llvm::raw_svector_ostream Out(ThunkName); - getMangleContext().mangleCXXCtor(CD, CT, Out); - - // If the thunk has been generated previously, just return it. - if (llvm::GlobalValue *GV = CGM.getModule().getNamedValue(ThunkName)) - return cast<llvm::Function>(GV); - - // Create the llvm::Function. - const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeMSCtorClosure(CD, CT); - llvm::FunctionType *ThunkTy = CGM.getTypes().GetFunctionType(FnInfo); - const CXXRecordDecl *RD = CD->getParent(); - QualType RecordTy = getContext().getRecordType(RD); - llvm::Function *ThunkFn = llvm::Function::Create( - ThunkTy, getLinkageForRTTI(RecordTy), ThunkName.str(), &CGM.getModule()); - ThunkFn->setCallingConv(static_cast<llvm::CallingConv::ID>( - FnInfo.getEffectiveCallingConvention())); - if (ThunkFn->isWeakForLinker()) - ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName())); - bool IsCopy = CT == Ctor_CopyingClosure; - - // Start codegen. - CodeGenFunction CGF(CGM); - CGF.CurGD = GlobalDecl(CD, Ctor_Complete); - - // Build FunctionArgs. - FunctionArgList FunctionArgs; - - // A constructor always starts with a 'this' pointer as its first argument. - buildThisParam(CGF, FunctionArgs); - - // Following the 'this' pointer is a reference to the source object that we - // are copying from. - ImplicitParamDecl SrcParam( - getContext(), /*DC=*/nullptr, SourceLocation(), - &getContext().Idents.get("src"), - getContext().getLValueReferenceType(RecordTy, - /*SpelledAsLValue=*/true), - ImplicitParamDecl::Other); - if (IsCopy) - FunctionArgs.push_back(&SrcParam); - - // Constructors for classes which utilize virtual bases have an additional - // parameter which indicates whether or not it is being delegated to by a more - // derived constructor. - ImplicitParamDecl IsMostDerived(getContext(), /*DC=*/nullptr, - SourceLocation(), - &getContext().Idents.get("is_most_derived"), - getContext().IntTy, ImplicitParamDecl::Other); - // Only add the parameter to the list if the class has virtual bases. - if (RD->getNumVBases() > 0) - FunctionArgs.push_back(&IsMostDerived); - - // Start defining the function. - auto NL = ApplyDebugLocation::CreateEmpty(CGF); - CGF.StartFunction(GlobalDecl(), FnInfo.getReturnType(), ThunkFn, FnInfo, - FunctionArgs, CD->getLocation(), SourceLocation()); - // Create a scope with an artificial location for the body of this function. - auto AL = ApplyDebugLocation::CreateArtificial(CGF); - setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF)); - llvm::Value *This = getThisValue(CGF); - - llvm::Value *SrcVal = - IsCopy ? CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&SrcParam), "src") - : nullptr; - - CallArgList Args; - - // Push the this ptr. - Args.add(RValue::get(This), CD->getThisType()); - - // Push the src ptr. - if (SrcVal) - Args.add(RValue::get(SrcVal), SrcParam.getType()); - - // Add the rest of the default arguments. - SmallVector<const Stmt *, 4> ArgVec; - ArrayRef<ParmVarDecl *> params = CD->parameters().drop_front(IsCopy ? 1 : 0); - for (const ParmVarDecl *PD : params) { - assert(PD->hasDefaultArg() && "ctor closure lacks default args"); - ArgVec.push_back(PD->getDefaultArg()); - } - - CodeGenFunction::RunCleanupsScope Cleanups(CGF); - - const auto *FPT = CD->getType()->castAs<FunctionProtoType>(); - CGF.EmitCallArgs(Args, FPT, llvm::makeArrayRef(ArgVec), CD, IsCopy ? 1 : 0); - - // Insert any ABI-specific implicit constructor arguments. - AddedStructorArgs ExtraArgs = - addImplicitConstructorArgs(CGF, CD, Ctor_Complete, - /*ForVirtualBase=*/false, - /*Delegating=*/false, Args); - // Call the destructor with our arguments. - llvm::Constant *CalleePtr = - CGM.getAddrOfCXXStructor(CD, StructorType::Complete); - CGCallee Callee = - CGCallee::forDirect(CalleePtr, GlobalDecl(CD, Ctor_Complete)); - const CGFunctionInfo &CalleeInfo = CGM.getTypes().arrangeCXXConstructorCall( - Args, CD, Ctor_Complete, ExtraArgs.Prefix, ExtraArgs.Suffix); - CGF.EmitCall(CalleeInfo, Callee, ReturnValueSlot(), Args); - - Cleanups.ForceCleanup(); - - // Emit the ret instruction, remove any temporary instructions created for the - // aid of CodeGen. - CGF.FinishFunction(SourceLocation()); - - return ThunkFn; -} - -llvm::Constant *MicrosoftCXXABI::getCatchableType(QualType T, - uint32_t NVOffset, - int32_t VBPtrOffset, - uint32_t VBIndex) { - assert(!T->isReferenceType()); - - CXXRecordDecl *RD = T->getAsCXXRecordDecl(); - const CXXConstructorDecl *CD = - RD ? CGM.getContext().getCopyConstructorForExceptionObject(RD) : nullptr; - CXXCtorType CT = Ctor_Complete; - if (CD) - if (!hasDefaultCXXMethodCC(getContext(), CD) || CD->getNumParams() != 1) - CT = Ctor_CopyingClosure; - - uint32_t Size = getContext().getTypeSizeInChars(T).getQuantity(); - SmallString<256> MangledName; - { - llvm::raw_svector_ostream Out(MangledName); - getMangleContext().mangleCXXCatchableType(T, CD, CT, Size, NVOffset, - VBPtrOffset, VBIndex, Out); - } - if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName)) - return getImageRelativeConstant(GV); - - // The TypeDescriptor is used by the runtime to determine if a catch handler - // is appropriate for the exception object. - llvm::Constant *TD = getImageRelativeConstant(getAddrOfRTTIDescriptor(T)); - - // The runtime is responsible for calling the copy constructor if the - // exception is caught by value. - llvm::Constant *CopyCtor; - if (CD) { - if (CT == Ctor_CopyingClosure) - CopyCtor = getAddrOfCXXCtorClosure(CD, Ctor_CopyingClosure); - else - CopyCtor = CGM.getAddrOfCXXStructor(CD, StructorType::Complete); - - CopyCtor = llvm::ConstantExpr::getBitCast(CopyCtor, CGM.Int8PtrTy); - } else { - CopyCtor = llvm::Constant::getNullValue(CGM.Int8PtrTy); - } - CopyCtor = getImageRelativeConstant(CopyCtor); - - bool IsScalar = !RD; - bool HasVirtualBases = false; - bool IsStdBadAlloc = false; // std::bad_alloc is special for some reason. - QualType PointeeType = T; - if (T->isPointerType()) - PointeeType = T->getPointeeType(); - if (const CXXRecordDecl *RD = PointeeType->getAsCXXRecordDecl()) { - HasVirtualBases = RD->getNumVBases() > 0; - if (IdentifierInfo *II = RD->getIdentifier()) - IsStdBadAlloc = II->isStr("bad_alloc") && RD->isInStdNamespace(); - } - - // Encode the relevant CatchableType properties into the Flags bitfield. - // FIXME: Figure out how bits 2 or 8 can get set. - uint32_t Flags = 0; - if (IsScalar) - Flags |= 1; - if (HasVirtualBases) - Flags |= 4; - if (IsStdBadAlloc) - Flags |= 16; - - llvm::Constant *Fields[] = { - llvm::ConstantInt::get(CGM.IntTy, Flags), // Flags - TD, // TypeDescriptor - llvm::ConstantInt::get(CGM.IntTy, NVOffset), // NonVirtualAdjustment - llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset), // OffsetToVBPtr - llvm::ConstantInt::get(CGM.IntTy, VBIndex), // VBTableIndex - llvm::ConstantInt::get(CGM.IntTy, Size), // Size - CopyCtor // CopyCtor - }; - llvm::StructType *CTType = getCatchableTypeType(); - auto *GV = new llvm::GlobalVariable( - CGM.getModule(), CTType, /*Constant=*/true, getLinkageForRTTI(T), - llvm::ConstantStruct::get(CTType, Fields), MangledName); - GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - GV->setSection(".xdata"); - if (GV->isWeakForLinker()) - GV->setComdat(CGM.getModule().getOrInsertComdat(GV->getName())); - return getImageRelativeConstant(GV); -} - -llvm::GlobalVariable *MicrosoftCXXABI::getCatchableTypeArray(QualType T) { - assert(!T->isReferenceType()); - - // See if we've already generated a CatchableTypeArray for this type before. - llvm::GlobalVariable *&CTA = CatchableTypeArrays[T]; - if (CTA) - return CTA; - - // Ensure that we don't have duplicate entries in our CatchableTypeArray by - // using a SmallSetVector. Duplicates may arise due to virtual bases - // occurring more than once in the hierarchy. - llvm::SmallSetVector<llvm::Constant *, 2> CatchableTypes; - - // C++14 [except.handle]p3: - // A handler is a match for an exception object of type E if [...] - // - the handler is of type cv T or cv T& and T is an unambiguous public - // base class of E, or - // - the handler is of type cv T or const T& where T is a pointer type and - // E is a pointer type that can be converted to T by [...] - // - a standard pointer conversion (4.10) not involving conversions to - // pointers to private or protected or ambiguous classes - const CXXRecordDecl *MostDerivedClass = nullptr; - bool IsPointer = T->isPointerType(); - if (IsPointer) - MostDerivedClass = T->getPointeeType()->getAsCXXRecordDecl(); - else - MostDerivedClass = T->getAsCXXRecordDecl(); - - // Collect all the unambiguous public bases of the MostDerivedClass. - if (MostDerivedClass) { - const ASTContext &Context = getContext(); - const ASTRecordLayout &MostDerivedLayout = - Context.getASTRecordLayout(MostDerivedClass); - MicrosoftVTableContext &VTableContext = CGM.getMicrosoftVTableContext(); - SmallVector<MSRTTIClass, 8> Classes; - serializeClassHierarchy(Classes, MostDerivedClass); - Classes.front().initialize(/*Parent=*/nullptr, /*Specifier=*/nullptr); - detectAmbiguousBases(Classes); - for (const MSRTTIClass &Class : Classes) { - // Skip any ambiguous or private bases. - if (Class.Flags & - (MSRTTIClass::IsPrivateOnPath | MSRTTIClass::IsAmbiguous)) - continue; - // Write down how to convert from a derived pointer to a base pointer. - uint32_t OffsetInVBTable = 0; - int32_t VBPtrOffset = -1; - if (Class.VirtualRoot) { - OffsetInVBTable = - VTableContext.getVBTableIndex(MostDerivedClass, Class.VirtualRoot)*4; - VBPtrOffset = MostDerivedLayout.getVBPtrOffset().getQuantity(); - } - - // Turn our record back into a pointer if the exception object is a - // pointer. - QualType RTTITy = QualType(Class.RD->getTypeForDecl(), 0); - if (IsPointer) - RTTITy = Context.getPointerType(RTTITy); - CatchableTypes.insert(getCatchableType(RTTITy, Class.OffsetInVBase, - VBPtrOffset, OffsetInVBTable)); - } - } - - // C++14 [except.handle]p3: - // A handler is a match for an exception object of type E if - // - The handler is of type cv T or cv T& and E and T are the same type - // (ignoring the top-level cv-qualifiers) - CatchableTypes.insert(getCatchableType(T)); - - // C++14 [except.handle]p3: - // A handler is a match for an exception object of type E if - // - the handler is of type cv T or const T& where T is a pointer type and - // E is a pointer type that can be converted to T by [...] - // - a standard pointer conversion (4.10) not involving conversions to - // pointers to private or protected or ambiguous classes - // - // C++14 [conv.ptr]p2: - // A prvalue of type "pointer to cv T," where T is an object type, can be - // converted to a prvalue of type "pointer to cv void". - if (IsPointer && T->getPointeeType()->isObjectType()) - CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy)); - - // C++14 [except.handle]p3: - // A handler is a match for an exception object of type E if [...] - // - the handler is of type cv T or const T& where T is a pointer or - // pointer to member type and E is std::nullptr_t. - // - // We cannot possibly list all possible pointer types here, making this - // implementation incompatible with the standard. However, MSVC includes an - // entry for pointer-to-void in this case. Let's do the same. - if (T->isNullPtrType()) - CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy)); - - uint32_t NumEntries = CatchableTypes.size(); - llvm::Type *CTType = - getImageRelativeType(getCatchableTypeType()->getPointerTo()); - llvm::ArrayType *AT = llvm::ArrayType::get(CTType, NumEntries); - llvm::StructType *CTAType = getCatchableTypeArrayType(NumEntries); - llvm::Constant *Fields[] = { - llvm::ConstantInt::get(CGM.IntTy, NumEntries), // NumEntries - llvm::ConstantArray::get( - AT, llvm::makeArrayRef(CatchableTypes.begin(), - CatchableTypes.end())) // CatchableTypes - }; - SmallString<256> MangledName; - { - llvm::raw_svector_ostream Out(MangledName); - getMangleContext().mangleCXXCatchableTypeArray(T, NumEntries, Out); - } - CTA = new llvm::GlobalVariable( - CGM.getModule(), CTAType, /*Constant=*/true, getLinkageForRTTI(T), - llvm::ConstantStruct::get(CTAType, Fields), MangledName); - CTA->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - CTA->setSection(".xdata"); - if (CTA->isWeakForLinker()) - CTA->setComdat(CGM.getModule().getOrInsertComdat(CTA->getName())); - return CTA; -} - -llvm::GlobalVariable *MicrosoftCXXABI::getThrowInfo(QualType T) { - bool IsConst, IsVolatile, IsUnaligned; - T = decomposeTypeForEH(getContext(), T, IsConst, IsVolatile, IsUnaligned); - - // The CatchableTypeArray enumerates the various (CV-unqualified) types that - // the exception object may be caught as. - llvm::GlobalVariable *CTA = getCatchableTypeArray(T); - // The first field in a CatchableTypeArray is the number of CatchableTypes. - // This is used as a component of the mangled name which means that we need to - // know what it is in order to see if we have previously generated the - // ThrowInfo. - uint32_t NumEntries = - cast<llvm::ConstantInt>(CTA->getInitializer()->getAggregateElement(0U)) - ->getLimitedValue(); - - SmallString<256> MangledName; - { - llvm::raw_svector_ostream Out(MangledName); - getMangleContext().mangleCXXThrowInfo(T, IsConst, IsVolatile, IsUnaligned, - NumEntries, Out); - } - - // Reuse a previously generated ThrowInfo if we have generated an appropriate - // one before. - if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName)) - return GV; - - // The RTTI TypeDescriptor uses an unqualified type but catch clauses must - // be at least as CV qualified. Encode this requirement into the Flags - // bitfield. - uint32_t Flags = 0; - if (IsConst) - Flags |= 1; - if (IsVolatile) - Flags |= 2; - if (IsUnaligned) - Flags |= 4; - - // The cleanup-function (a destructor) must be called when the exception - // object's lifetime ends. - llvm::Constant *CleanupFn = llvm::Constant::getNullValue(CGM.Int8PtrTy); - if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) - if (CXXDestructorDecl *DtorD = RD->getDestructor()) - if (!DtorD->isTrivial()) - CleanupFn = llvm::ConstantExpr::getBitCast( - CGM.getAddrOfCXXStructor(DtorD, StructorType::Complete), - CGM.Int8PtrTy); - // This is unused as far as we can tell, initialize it to null. - llvm::Constant *ForwardCompat = - getImageRelativeConstant(llvm::Constant::getNullValue(CGM.Int8PtrTy)); - llvm::Constant *PointerToCatchableTypes = getImageRelativeConstant( - llvm::ConstantExpr::getBitCast(CTA, CGM.Int8PtrTy)); - llvm::StructType *TIType = getThrowInfoType(); - llvm::Constant *Fields[] = { - llvm::ConstantInt::get(CGM.IntTy, Flags), // Flags - getImageRelativeConstant(CleanupFn), // CleanupFn - ForwardCompat, // ForwardCompat - PointerToCatchableTypes // CatchableTypeArray - }; - auto *GV = new llvm::GlobalVariable( - CGM.getModule(), TIType, /*Constant=*/true, getLinkageForRTTI(T), - llvm::ConstantStruct::get(TIType, Fields), StringRef(MangledName)); - GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - GV->setSection(".xdata"); - if (GV->isWeakForLinker()) - GV->setComdat(CGM.getModule().getOrInsertComdat(GV->getName())); - return GV; -} - -void MicrosoftCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) { - const Expr *SubExpr = E->getSubExpr(); - QualType ThrowType = SubExpr->getType(); - // The exception object lives on the stack and it's address is passed to the - // runtime function. - Address AI = CGF.CreateMemTemp(ThrowType); - CGF.EmitAnyExprToMem(SubExpr, AI, ThrowType.getQualifiers(), - /*IsInit=*/true); - - // The so-called ThrowInfo is used to describe how the exception object may be - // caught. - llvm::GlobalVariable *TI = getThrowInfo(ThrowType); - - // Call into the runtime to throw the exception. - llvm::Value *Args[] = { - CGF.Builder.CreateBitCast(AI.getPointer(), CGM.Int8PtrTy), - TI - }; - CGF.EmitNoreturnRuntimeCallOrInvoke(getThrowFn(), Args); -} - -std::pair<llvm::Value *, const CXXRecordDecl *> -MicrosoftCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This, - const CXXRecordDecl *RD) { - std::tie(This, std::ignore, RD) = - performBaseAdjustment(CGF, This, QualType(RD->getTypeForDecl(), 0)); - return {CGF.GetVTablePtr(This, CGM.Int8PtrTy, RD), RD}; -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp b/gnu/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp deleted file mode 100644 index c0a37698e76..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp +++ /dev/null @@ -1,332 +0,0 @@ -//===--- ModuleBuilder.cpp - Emit LLVM Code from ASTs ---------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This builds an AST and converts it to LLVM Code. -// -//===----------------------------------------------------------------------===// - -#include "clang/CodeGen/ModuleBuilder.h" -#include "CGDebugInfo.h" -#include "CodeGenModule.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/Expr.h" -#include "clang/Basic/CodeGenOptions.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include <memory> - -using namespace clang; -using namespace CodeGen; - -namespace { - class CodeGeneratorImpl : public CodeGenerator { - DiagnosticsEngine &Diags; - ASTContext *Ctx; - const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info. - const PreprocessorOptions &PreprocessorOpts; // Only used for debug info. - const CodeGenOptions CodeGenOpts; // Intentionally copied in. - - unsigned HandlingTopLevelDecls; - - /// Use this when emitting decls to block re-entrant decl emission. It will - /// emit all deferred decls on scope exit. Set EmitDeferred to false if decl - /// emission must be deferred longer, like at the end of a tag definition. - struct HandlingTopLevelDeclRAII { - CodeGeneratorImpl &Self; - bool EmitDeferred; - HandlingTopLevelDeclRAII(CodeGeneratorImpl &Self, - bool EmitDeferred = true) - : Self(Self), EmitDeferred(EmitDeferred) { - ++Self.HandlingTopLevelDecls; - } - ~HandlingTopLevelDeclRAII() { - unsigned Level = --Self.HandlingTopLevelDecls; - if (Level == 0 && EmitDeferred) - Self.EmitDeferredDecls(); - } - }; - - CoverageSourceInfo *CoverageInfo; - - protected: - std::unique_ptr<llvm::Module> M; - std::unique_ptr<CodeGen::CodeGenModule> Builder; - - private: - SmallVector<FunctionDecl *, 8> DeferredInlineMemberFuncDefs; - - public: - CodeGeneratorImpl(DiagnosticsEngine &diags, llvm::StringRef ModuleName, - const HeaderSearchOptions &HSO, - const PreprocessorOptions &PPO, const CodeGenOptions &CGO, - llvm::LLVMContext &C, - CoverageSourceInfo *CoverageInfo = nullptr) - : Diags(diags), Ctx(nullptr), HeaderSearchOpts(HSO), - PreprocessorOpts(PPO), CodeGenOpts(CGO), HandlingTopLevelDecls(0), - CoverageInfo(CoverageInfo), M(new llvm::Module(ModuleName, C)) { - C.setDiscardValueNames(CGO.DiscardValueNames); - } - - ~CodeGeneratorImpl() override { - // There should normally not be any leftover inline method definitions. - assert(DeferredInlineMemberFuncDefs.empty() || - Diags.hasErrorOccurred()); - } - - CodeGenModule &CGM() { - return *Builder; - } - - llvm::Module *GetModule() { - return M.get(); - } - - CGDebugInfo *getCGDebugInfo() { - return Builder->getModuleDebugInfo(); - } - - llvm::Module *ReleaseModule() { - return M.release(); - } - - const Decl *GetDeclForMangledName(StringRef MangledName) { - GlobalDecl Result; - if (!Builder->lookupRepresentativeDecl(MangledName, Result)) - return nullptr; - const Decl *D = Result.getCanonicalDecl().getDecl(); - if (auto FD = dyn_cast<FunctionDecl>(D)) { - if (FD->hasBody(FD)) - return FD; - } else if (auto TD = dyn_cast<TagDecl>(D)) { - if (auto Def = TD->getDefinition()) - return Def; - } - return D; - } - - llvm::Constant *GetAddrOfGlobal(GlobalDecl global, bool isForDefinition) { - return Builder->GetAddrOfGlobal(global, ForDefinition_t(isForDefinition)); - } - - llvm::Module *StartModule(llvm::StringRef ModuleName, - llvm::LLVMContext &C) { - assert(!M && "Replacing existing Module?"); - M.reset(new llvm::Module(ModuleName, C)); - Initialize(*Ctx); - return M.get(); - } - - void Initialize(ASTContext &Context) override { - Ctx = &Context; - - M->setTargetTriple(Ctx->getTargetInfo().getTriple().getTriple()); - M->setDataLayout(Ctx->getTargetInfo().getDataLayout()); - const auto &SDKVersion = Ctx->getTargetInfo().getSDKVersion(); - if (!SDKVersion.empty()) - M->setSDKVersion(SDKVersion); - Builder.reset(new CodeGen::CodeGenModule(Context, HeaderSearchOpts, - PreprocessorOpts, CodeGenOpts, - *M, Diags, CoverageInfo)); - - for (auto &&Lib : CodeGenOpts.DependentLibraries) - Builder->AddDependentLib(Lib); - for (auto &&Opt : CodeGenOpts.LinkerOptions) - Builder->AppendLinkerOptions(Opt); - } - - void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override { - if (Diags.hasErrorOccurred()) - return; - - Builder->HandleCXXStaticMemberVarInstantiation(VD); - } - - bool HandleTopLevelDecl(DeclGroupRef DG) override { - if (Diags.hasErrorOccurred()) - return true; - - HandlingTopLevelDeclRAII HandlingDecl(*this); - - // Make sure to emit all elements of a Decl. - for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) - Builder->EmitTopLevelDecl(*I); - - return true; - } - - void EmitDeferredDecls() { - if (DeferredInlineMemberFuncDefs.empty()) - return; - - // Emit any deferred inline method definitions. Note that more deferred - // methods may be added during this loop, since ASTConsumer callbacks - // can be invoked if AST inspection results in declarations being added. - HandlingTopLevelDeclRAII HandlingDecl(*this); - for (unsigned I = 0; I != DeferredInlineMemberFuncDefs.size(); ++I) - Builder->EmitTopLevelDecl(DeferredInlineMemberFuncDefs[I]); - DeferredInlineMemberFuncDefs.clear(); - } - - void HandleInlineFunctionDefinition(FunctionDecl *D) override { - if (Diags.hasErrorOccurred()) - return; - - assert(D->doesThisDeclarationHaveABody()); - - // We may want to emit this definition. However, that decision might be - // based on computing the linkage, and we have to defer that in case we - // are inside of something that will change the method's final linkage, - // e.g. - // typedef struct { - // void bar(); - // void foo() { bar(); } - // } A; - DeferredInlineMemberFuncDefs.push_back(D); - - // Provide some coverage mapping even for methods that aren't emitted. - // Don't do this for templated classes though, as they may not be - // instantiable. - if (!D->getLexicalDeclContext()->isDependentContext()) - Builder->AddDeferredUnusedCoverageMapping(D); - } - - /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl - /// to (e.g. struct, union, enum, class) is completed. This allows the - /// client hack on the type, which can occur at any point in the file - /// (because these can be defined in declspecs). - void HandleTagDeclDefinition(TagDecl *D) override { - if (Diags.hasErrorOccurred()) - return; - - // Don't allow re-entrant calls to CodeGen triggered by PCH - // deserialization to emit deferred decls. - HandlingTopLevelDeclRAII HandlingDecl(*this, /*EmitDeferred=*/false); - - Builder->UpdateCompletedType(D); - - // For MSVC compatibility, treat declarations of static data members with - // inline initializers as definitions. - if (Ctx->getTargetInfo().getCXXABI().isMicrosoft()) { - for (Decl *Member : D->decls()) { - if (VarDecl *VD = dyn_cast<VarDecl>(Member)) { - if (Ctx->isMSStaticDataMemberInlineDefinition(VD) && - Ctx->DeclMustBeEmitted(VD)) { - Builder->EmitGlobal(VD); - } - } - } - } - // For OpenMP emit declare reduction functions, if required. - if (Ctx->getLangOpts().OpenMP) { - for (Decl *Member : D->decls()) { - if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(Member)) { - if (Ctx->DeclMustBeEmitted(DRD)) - Builder->EmitGlobal(DRD); - } - } - } - } - - void HandleTagDeclRequiredDefinition(const TagDecl *D) override { - if (Diags.hasErrorOccurred()) - return; - - // Don't allow re-entrant calls to CodeGen triggered by PCH - // deserialization to emit deferred decls. - HandlingTopLevelDeclRAII HandlingDecl(*this, /*EmitDeferred=*/false); - - if (CodeGen::CGDebugInfo *DI = Builder->getModuleDebugInfo()) - if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) - DI->completeRequiredType(RD); - } - - void HandleTranslationUnit(ASTContext &Ctx) override { - // Release the Builder when there is no error. - if (!Diags.hasErrorOccurred() && Builder) - Builder->Release(); - - // If there are errors before or when releasing the Builder, reset - // the module to stop here before invoking the backend. - if (Diags.hasErrorOccurred()) { - if (Builder) - Builder->clear(); - M.reset(); - return; - } - } - - void AssignInheritanceModel(CXXRecordDecl *RD) override { - if (Diags.hasErrorOccurred()) - return; - - Builder->RefreshTypeCacheForClass(RD); - } - - void CompleteTentativeDefinition(VarDecl *D) override { - if (Diags.hasErrorOccurred()) - return; - - Builder->EmitTentativeDefinition(D); - } - - void HandleVTable(CXXRecordDecl *RD) override { - if (Diags.hasErrorOccurred()) - return; - - Builder->EmitVTable(RD); - } - }; -} - -void CodeGenerator::anchor() { } - -CodeGenModule &CodeGenerator::CGM() { - return static_cast<CodeGeneratorImpl*>(this)->CGM(); -} - -llvm::Module *CodeGenerator::GetModule() { - return static_cast<CodeGeneratorImpl*>(this)->GetModule(); -} - -llvm::Module *CodeGenerator::ReleaseModule() { - return static_cast<CodeGeneratorImpl*>(this)->ReleaseModule(); -} - -CGDebugInfo *CodeGenerator::getCGDebugInfo() { - return static_cast<CodeGeneratorImpl*>(this)->getCGDebugInfo(); -} - -const Decl *CodeGenerator::GetDeclForMangledName(llvm::StringRef name) { - return static_cast<CodeGeneratorImpl*>(this)->GetDeclForMangledName(name); -} - -llvm::Constant *CodeGenerator::GetAddrOfGlobal(GlobalDecl global, - bool isForDefinition) { - return static_cast<CodeGeneratorImpl*>(this) - ->GetAddrOfGlobal(global, isForDefinition); -} - -llvm::Module *CodeGenerator::StartModule(llvm::StringRef ModuleName, - llvm::LLVMContext &C) { - return static_cast<CodeGeneratorImpl*>(this)->StartModule(ModuleName, C); -} - -CodeGenerator *clang::CreateLLVMCodeGen( - DiagnosticsEngine &Diags, llvm::StringRef ModuleName, - const HeaderSearchOptions &HeaderSearchOpts, - const PreprocessorOptions &PreprocessorOpts, const CodeGenOptions &CGO, - llvm::LLVMContext &C, CoverageSourceInfo *CoverageInfo) { - return new CodeGeneratorImpl(Diags, ModuleName, HeaderSearchOpts, - PreprocessorOpts, CGO, C, CoverageInfo); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/gnu/llvm/tools/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp deleted file mode 100644 index 6f00c836f93..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp +++ /dev/null @@ -1,355 +0,0 @@ -//===--- ObjectFilePCHContainerOperations.cpp -----------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "clang/CodeGen/ObjectFilePCHContainerOperations.h" -#include "CGDebugInfo.h" -#include "CodeGenModule.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/Expr.h" -#include "clang/AST/RecursiveASTVisitor.h" -#include "clang/Basic/CodeGenOptions.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/CodeGen/BackendUtil.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Lex/HeaderSearch.h" -#include "clang/Lex/Preprocessor.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Bitcode/BitstreamReader.h" -#include "llvm/DebugInfo/DWARF/DWARFContext.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/Object/COFF.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/TargetRegistry.h" -#include <memory> -#include <utility> - -using namespace clang; - -#define DEBUG_TYPE "pchcontainer" - -namespace { -class PCHContainerGenerator : public ASTConsumer { - DiagnosticsEngine &Diags; - const std::string MainFileName; - const std::string OutputFileName; - ASTContext *Ctx; - ModuleMap &MMap; - const HeaderSearchOptions &HeaderSearchOpts; - const PreprocessorOptions &PreprocessorOpts; - CodeGenOptions CodeGenOpts; - const TargetOptions TargetOpts; - const LangOptions LangOpts; - std::unique_ptr<llvm::LLVMContext> VMContext; - std::unique_ptr<llvm::Module> M; - std::unique_ptr<CodeGen::CodeGenModule> Builder; - std::unique_ptr<raw_pwrite_stream> OS; - std::shared_ptr<PCHBuffer> Buffer; - - /// Visit every type and emit debug info for it. - struct DebugTypeVisitor : public RecursiveASTVisitor<DebugTypeVisitor> { - clang::CodeGen::CGDebugInfo &DI; - ASTContext &Ctx; - DebugTypeVisitor(clang::CodeGen::CGDebugInfo &DI, ASTContext &Ctx) - : DI(DI), Ctx(Ctx) {} - - /// Determine whether this type can be represented in DWARF. - static bool CanRepresent(const Type *Ty) { - return !Ty->isDependentType() && !Ty->isUndeducedType(); - } - - bool VisitImportDecl(ImportDecl *D) { - if (!D->getImportedOwningModule()) - DI.EmitImportDecl(*D); - return true; - } - - bool VisitTypeDecl(TypeDecl *D) { - // TagDecls may be deferred until after all decls have been merged and we - // know the complete type. Pure forward declarations will be skipped, but - // they don't need to be emitted into the module anyway. - if (auto *TD = dyn_cast<TagDecl>(D)) - if (!TD->isCompleteDefinition()) - return true; - - QualType QualTy = Ctx.getTypeDeclType(D); - if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr())) - DI.getOrCreateStandaloneType(QualTy, D->getLocation()); - return true; - } - - bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { - QualType QualTy(D->getTypeForDecl(), 0); - if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr())) - DI.getOrCreateStandaloneType(QualTy, D->getLocation()); - return true; - } - - bool VisitFunctionDecl(FunctionDecl *D) { - if (isa<CXXMethodDecl>(D)) - // This is not yet supported. Constructing the `this' argument - // mandates a CodeGenFunction. - return true; - - SmallVector<QualType, 16> ArgTypes; - for (auto i : D->parameters()) - ArgTypes.push_back(i->getType()); - QualType RetTy = D->getReturnType(); - QualType FnTy = Ctx.getFunctionType(RetTy, ArgTypes, - FunctionProtoType::ExtProtoInfo()); - if (CanRepresent(FnTy.getTypePtr())) - DI.EmitFunctionDecl(D, D->getLocation(), FnTy); - return true; - } - - bool VisitObjCMethodDecl(ObjCMethodDecl *D) { - if (!D->getClassInterface()) - return true; - - bool selfIsPseudoStrong, selfIsConsumed; - SmallVector<QualType, 16> ArgTypes; - ArgTypes.push_back(D->getSelfType(Ctx, D->getClassInterface(), - selfIsPseudoStrong, selfIsConsumed)); - ArgTypes.push_back(Ctx.getObjCSelType()); - for (auto i : D->parameters()) - ArgTypes.push_back(i->getType()); - QualType RetTy = D->getReturnType(); - QualType FnTy = Ctx.getFunctionType(RetTy, ArgTypes, - FunctionProtoType::ExtProtoInfo()); - if (CanRepresent(FnTy.getTypePtr())) - DI.EmitFunctionDecl(D, D->getLocation(), FnTy); - return true; - } - }; - -public: - PCHContainerGenerator(CompilerInstance &CI, const std::string &MainFileName, - const std::string &OutputFileName, - std::unique_ptr<raw_pwrite_stream> OS, - std::shared_ptr<PCHBuffer> Buffer) - : Diags(CI.getDiagnostics()), MainFileName(MainFileName), - OutputFileName(OutputFileName), Ctx(nullptr), - MMap(CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()), - HeaderSearchOpts(CI.getHeaderSearchOpts()), - PreprocessorOpts(CI.getPreprocessorOpts()), - TargetOpts(CI.getTargetOpts()), LangOpts(CI.getLangOpts()), - OS(std::move(OS)), Buffer(std::move(Buffer)) { - // The debug info output isn't affected by CodeModel and - // ThreadModel, but the backend expects them to be nonempty. - CodeGenOpts.CodeModel = "default"; - CodeGenOpts.ThreadModel = "single"; - CodeGenOpts.DebugTypeExtRefs = true; - // When building a module MainFileName is the name of the modulemap file. - CodeGenOpts.MainFileName = - LangOpts.CurrentModule.empty() ? MainFileName : LangOpts.CurrentModule; - CodeGenOpts.setDebugInfo(codegenoptions::FullDebugInfo); - CodeGenOpts.setDebuggerTuning(CI.getCodeGenOpts().getDebuggerTuning()); - CodeGenOpts.DebugPrefixMap = - CI.getInvocation().getCodeGenOpts().DebugPrefixMap; - } - - ~PCHContainerGenerator() override = default; - - void Initialize(ASTContext &Context) override { - assert(!Ctx && "initialized multiple times"); - - Ctx = &Context; - VMContext.reset(new llvm::LLVMContext()); - M.reset(new llvm::Module(MainFileName, *VMContext)); - M->setDataLayout(Ctx->getTargetInfo().getDataLayout()); - Builder.reset(new CodeGen::CodeGenModule( - *Ctx, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags)); - - // Prepare CGDebugInfo to emit debug info for a clang module. - auto *DI = Builder->getModuleDebugInfo(); - StringRef ModuleName = llvm::sys::path::filename(MainFileName); - DI->setPCHDescriptor({ModuleName, "", OutputFileName, - ASTFileSignature{{{~0U, ~0U, ~0U, ~0U, ~1U}}}}); - DI->setModuleMap(MMap); - } - - bool HandleTopLevelDecl(DeclGroupRef D) override { - if (Diags.hasErrorOccurred()) - return true; - - // Collect debug info for all decls in this group. - for (auto *I : D) - if (!I->isFromASTFile()) { - DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx); - DTV.TraverseDecl(I); - } - return true; - } - - void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override { - HandleTopLevelDecl(D); - } - - void HandleTagDeclDefinition(TagDecl *D) override { - if (Diags.hasErrorOccurred()) - return; - - if (D->isFromASTFile()) - return; - - // Anonymous tag decls are deferred until we are building their declcontext. - if (D->getName().empty()) - return; - - // Defer tag decls until their declcontext is complete. - auto *DeclCtx = D->getDeclContext(); - while (DeclCtx) { - if (auto *D = dyn_cast<TagDecl>(DeclCtx)) - if (!D->isCompleteDefinition()) - return; - DeclCtx = DeclCtx->getParent(); - } - - DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx); - DTV.TraverseDecl(D); - Builder->UpdateCompletedType(D); - } - - void HandleTagDeclRequiredDefinition(const TagDecl *D) override { - if (Diags.hasErrorOccurred()) - return; - - if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) - Builder->getModuleDebugInfo()->completeRequiredType(RD); - } - - void HandleImplicitImportDecl(ImportDecl *D) override { - if (!D->getImportedOwningModule()) - Builder->getModuleDebugInfo()->EmitImportDecl(*D); - } - - /// Emit a container holding the serialized AST. - void HandleTranslationUnit(ASTContext &Ctx) override { - assert(M && VMContext && Builder); - // Delete these on function exit. - std::unique_ptr<llvm::LLVMContext> VMContext = std::move(this->VMContext); - std::unique_ptr<llvm::Module> M = std::move(this->M); - std::unique_ptr<CodeGen::CodeGenModule> Builder = std::move(this->Builder); - - if (Diags.hasErrorOccurred()) - return; - - M->setTargetTriple(Ctx.getTargetInfo().getTriple().getTriple()); - M->setDataLayout(Ctx.getTargetInfo().getDataLayout()); - - // PCH files don't have a signature field in the control block, - // but LLVM detects DWO CUs by looking for a non-zero DWO id. - // We use the lower 64 bits for debug info. - uint64_t Signature = - Buffer->Signature - ? (uint64_t)Buffer->Signature[1] << 32 | Buffer->Signature[0] - : ~1ULL; - Builder->getModuleDebugInfo()->setDwoId(Signature); - - // Finalize the Builder. - if (Builder) - Builder->Release(); - - // Ensure the target exists. - std::string Error; - auto Triple = Ctx.getTargetInfo().getTriple(); - if (!llvm::TargetRegistry::lookupTarget(Triple.getTriple(), Error)) - llvm::report_fatal_error(Error); - - // Emit the serialized Clang AST into its own section. - assert(Buffer->IsComplete && "serialization did not complete"); - auto &SerializedAST = Buffer->Data; - auto Size = SerializedAST.size(); - auto Int8Ty = llvm::Type::getInt8Ty(*VMContext); - auto *Ty = llvm::ArrayType::get(Int8Ty, Size); - auto *Data = llvm::ConstantDataArray::getString( - *VMContext, StringRef(SerializedAST.data(), Size), - /*AddNull=*/false); - auto *ASTSym = new llvm::GlobalVariable( - *M, Ty, /*constant*/ true, llvm::GlobalVariable::InternalLinkage, Data, - "__clang_ast"); - // The on-disk hashtable needs to be aligned. - ASTSym->setAlignment(8); - - // Mach-O also needs a segment name. - if (Triple.isOSBinFormatMachO()) - ASTSym->setSection("__CLANG,__clangast"); - // COFF has an eight character length limit. - else if (Triple.isOSBinFormatCOFF()) - ASTSym->setSection("clangast"); - else - ASTSym->setSection("__clangast"); - - LLVM_DEBUG({ - // Print the IR for the PCH container to the debug output. - llvm::SmallString<0> Buffer; - clang::EmitBackendOutput( - Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, LangOpts, - Ctx.getTargetInfo().getDataLayout(), M.get(), - BackendAction::Backend_EmitLL, - llvm::make_unique<llvm::raw_svector_ostream>(Buffer)); - llvm::dbgs() << Buffer; - }); - - // Use the LLVM backend to emit the pch container. - clang::EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, - LangOpts, Ctx.getTargetInfo().getDataLayout(), - M.get(), BackendAction::Backend_EmitObj, - std::move(OS)); - - // Free the memory for the temporary buffer. - llvm::SmallVector<char, 0> Empty; - SerializedAST = std::move(Empty); - } -}; - -} // anonymous namespace - -std::unique_ptr<ASTConsumer> -ObjectFilePCHContainerWriter::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 { - return llvm::make_unique<PCHContainerGenerator>( - CI, MainFileName, OutputFileName, std::move(OS), Buffer); -} - -StringRef -ObjectFilePCHContainerReader::ExtractPCH(llvm::MemoryBufferRef Buffer) const { - StringRef PCH; - auto OFOrErr = llvm::object::ObjectFile::createObjectFile(Buffer); - if (OFOrErr) { - auto &OF = OFOrErr.get(); - bool IsCOFF = isa<llvm::object::COFFObjectFile>(*OF); - // Find the clang AST section in the container. - for (auto &Section : OF->sections()) { - StringRef Name; - Section.getName(Name); - if ((!IsCOFF && Name == "__clangast") || (IsCOFF && Name == "clangast")) { - Section.getContents(PCH); - return PCH; - } - } - } - handleAllErrors(OFOrErr.takeError(), [&](const llvm::ErrorInfoBase &EIB) { - if (EIB.convertToErrorCode() == - llvm::object::object_error::invalid_file_type) - // As a fallback, treat the buffer as a raw AST. - PCH = Buffer.getBuffer(); - else - EIB.log(llvm::errs()); - }); - return PCH; -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/README.txt b/gnu/llvm/tools/clang/lib/CodeGen/README.txt deleted file mode 100644 index e6d61095bf2..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/README.txt +++ /dev/null @@ -1,47 +0,0 @@ -IRgen optimization opportunities. - -//===---------------------------------------------------------------------===// - -The common pattern of --- -short x; // or char, etc -(x == 10) --- -generates an zext/sext of x which can easily be avoided. - -//===---------------------------------------------------------------------===// - -Bitfields accesses can be shifted to simplify masking and sign -extension. For example, if the bitfield width is 8 and it is -appropriately aligned then is is a lot shorter to just load the char -directly. - -//===---------------------------------------------------------------------===// - -It may be worth avoiding creation of alloca's for formal arguments -for the common situation where the argument is never written to or has -its address taken. The idea would be to begin generating code by using -the argument directly and if its address is taken or it is stored to -then generate the alloca and patch up the existing code. - -In theory, the same optimization could be a win for block local -variables as long as the declaration dominates all statements in the -block. - -NOTE: The main case we care about this for is for -O0 -g compile time -performance, and in that scenario we will need to emit the alloca -anyway currently to emit proper debug info. So this is blocked by -being able to emit debug information which refers to an LLVM -temporary, not an alloca. - -//===---------------------------------------------------------------------===// - -We should try and avoid generating basic blocks which only contain -jumps. At -O0, this penalizes us all the way from IRgen (malloc & -instruction overhead), all the way down through code generation and -assembly time. - -On 176.gcc:expr.ll, it looks like over 12% of basic blocks are just -direct branches! - -//===---------------------------------------------------------------------===// diff --git a/gnu/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.cpp b/gnu/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.cpp deleted file mode 100644 index 23cf9e49082..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.cpp +++ /dev/null @@ -1,107 +0,0 @@ -//===--- SanitizerMetadata.cpp - Blacklist for sanitizers -----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Class which emits metadata consumed by sanitizer instrumentation passes. -// -//===----------------------------------------------------------------------===// -#include "SanitizerMetadata.h" -#include "CodeGenModule.h" -#include "clang/AST/Type.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/IR/Constants.h" - -using namespace clang; -using namespace CodeGen; - -SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {} - -void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV, - SourceLocation Loc, StringRef Name, - QualType Ty, bool IsDynInit, - bool IsBlacklisted) { - if (!CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address | - SanitizerKind::KernelAddress | - SanitizerKind::HWAddress | - SanitizerKind::KernelHWAddress)) - return; - IsDynInit &= !CGM.isInSanitizerBlacklist(GV, Loc, Ty, "init"); - IsBlacklisted |= CGM.isInSanitizerBlacklist(GV, Loc, Ty); - - llvm::Metadata *LocDescr = nullptr; - llvm::Metadata *GlobalName = nullptr; - llvm::LLVMContext &VMContext = CGM.getLLVMContext(); - if (!IsBlacklisted) { - // Don't generate source location and global name if it is blacklisted - - // it won't be instrumented anyway. - LocDescr = getLocationMetadata(Loc); - if (!Name.empty()) - GlobalName = llvm::MDString::get(VMContext, Name); - } - - llvm::Metadata *GlobalMetadata[] = { - llvm::ConstantAsMetadata::get(GV), LocDescr, GlobalName, - llvm::ConstantAsMetadata::get( - llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsDynInit)), - llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - llvm::Type::getInt1Ty(VMContext), IsBlacklisted))}; - - llvm::MDNode *ThisGlobal = llvm::MDNode::get(VMContext, GlobalMetadata); - llvm::NamedMDNode *AsanGlobals = - CGM.getModule().getOrInsertNamedMetadata("llvm.asan.globals"); - AsanGlobals->addOperand(ThisGlobal); -} - -void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV, - const VarDecl &D, bool IsDynInit) { - if (!CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address | - SanitizerKind::KernelAddress | - SanitizerKind::HWAddress | - SanitizerKind::KernelHWAddress)) - return; - std::string QualName; - llvm::raw_string_ostream OS(QualName); - D.printQualifiedName(OS); - - bool IsBlacklisted = false; - for (auto Attr : D.specific_attrs<NoSanitizeAttr>()) - if (Attr->getMask() & SanitizerKind::Address) - IsBlacklisted = true; - reportGlobalToASan(GV, D.getLocation(), OS.str(), D.getType(), IsDynInit, - IsBlacklisted); -} - -void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) { - // For now, just make sure the global is not modified by the ASan - // instrumentation. - if (CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address | - SanitizerKind::KernelAddress | - SanitizerKind::HWAddress | - SanitizerKind::KernelHWAddress)) - reportGlobalToASan(GV, SourceLocation(), "", QualType(), false, true); -} - -void SanitizerMetadata::disableSanitizerForInstruction(llvm::Instruction *I) { - I->setMetadata(CGM.getModule().getMDKindID("nosanitize"), - llvm::MDNode::get(CGM.getLLVMContext(), None)); -} - -llvm::MDNode *SanitizerMetadata::getLocationMetadata(SourceLocation Loc) { - PresumedLoc PLoc = CGM.getContext().getSourceManager().getPresumedLoc(Loc); - if (!PLoc.isValid()) - return nullptr; - llvm::LLVMContext &VMContext = CGM.getLLVMContext(); - llvm::Metadata *LocMetadata[] = { - llvm::MDString::get(VMContext, PLoc.getFilename()), - llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - llvm::Type::getInt32Ty(VMContext), PLoc.getLine())), - llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - llvm::Type::getInt32Ty(VMContext), PLoc.getColumn())), - }; - return llvm::MDNode::get(VMContext, LocMetadata); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.h b/gnu/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.h deleted file mode 100644 index 166f0e6c9b5..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.h +++ /dev/null @@ -1,53 +0,0 @@ -//===--- SanitizerMetadata.h - Metadata for sanitizers ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Class which emits metadata consumed by sanitizer instrumentation passes. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_LIB_CODEGEN_SANITIZERMETADATA_H -#define LLVM_CLANG_LIB_CODEGEN_SANITIZERMETADATA_H - -#include "clang/AST/Type.h" -#include "clang/Basic/LLVM.h" -#include "clang/Basic/SourceLocation.h" - -namespace llvm { -class GlobalVariable; -class Instruction; -class MDNode; -} - -namespace clang { -class VarDecl; - -namespace CodeGen { - -class CodeGenModule; - -class SanitizerMetadata { - SanitizerMetadata(const SanitizerMetadata &) = delete; - void operator=(const SanitizerMetadata &) = delete; - - CodeGenModule &CGM; -public: - SanitizerMetadata(CodeGenModule &CGM); - void reportGlobalToASan(llvm::GlobalVariable *GV, const VarDecl &D, - bool IsDynInit = false); - void reportGlobalToASan(llvm::GlobalVariable *GV, SourceLocation Loc, - StringRef Name, QualType Ty, bool IsDynInit = false, - bool IsBlacklisted = false); - void disableSanitizerForGlobal(llvm::GlobalVariable *GV); - void disableSanitizerForInstruction(llvm::Instruction *I); -private: - llvm::MDNode *getLocationMetadata(SourceLocation Loc); -}; -} // end namespace CodeGen -} // end namespace clang - -#endif diff --git a/gnu/llvm/tools/clang/lib/CodeGen/SwiftCallingConv.cpp b/gnu/llvm/tools/clang/lib/CodeGen/SwiftCallingConv.cpp deleted file mode 100644 index 75a0fa5ce18..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/SwiftCallingConv.cpp +++ /dev/null @@ -1,865 +0,0 @@ -//===--- SwiftCallingConv.cpp - Lowering for the Swift calling convention -===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Implementation of the abstract lowering for the Swift calling convention. -// -//===----------------------------------------------------------------------===// - -#include "clang/CodeGen/SwiftCallingConv.h" -#include "clang/Basic/TargetInfo.h" -#include "CodeGenModule.h" -#include "TargetInfo.h" - -using namespace clang; -using namespace CodeGen; -using namespace swiftcall; - -static const SwiftABIInfo &getSwiftABIInfo(CodeGenModule &CGM) { - return cast<SwiftABIInfo>(CGM.getTargetCodeGenInfo().getABIInfo()); -} - -static bool isPowerOf2(unsigned n) { - return n == (n & -n); -} - -/// Given two types with the same size, try to find a common type. -static llvm::Type *getCommonType(llvm::Type *first, llvm::Type *second) { - assert(first != second); - - // Allow pointers to merge with integers, but prefer the integer type. - if (first->isIntegerTy()) { - if (second->isPointerTy()) return first; - } else if (first->isPointerTy()) { - if (second->isIntegerTy()) return second; - if (second->isPointerTy()) return first; - - // Allow two vectors to be merged (given that they have the same size). - // This assumes that we never have two different vector register sets. - } else if (auto firstVecTy = dyn_cast<llvm::VectorType>(first)) { - if (auto secondVecTy = dyn_cast<llvm::VectorType>(second)) { - if (auto commonTy = getCommonType(firstVecTy->getElementType(), - secondVecTy->getElementType())) { - return (commonTy == firstVecTy->getElementType() ? first : second); - } - } - } - - return nullptr; -} - -static CharUnits getTypeStoreSize(CodeGenModule &CGM, llvm::Type *type) { - return CharUnits::fromQuantity(CGM.getDataLayout().getTypeStoreSize(type)); -} - -static CharUnits getTypeAllocSize(CodeGenModule &CGM, llvm::Type *type) { - return CharUnits::fromQuantity(CGM.getDataLayout().getTypeAllocSize(type)); -} - -void SwiftAggLowering::addTypedData(QualType type, CharUnits begin) { - // Deal with various aggregate types as special cases: - - // Record types. - if (auto recType = type->getAs<RecordType>()) { - addTypedData(recType->getDecl(), begin); - - // Array types. - } else if (type->isArrayType()) { - // Incomplete array types (flexible array members?) don't provide - // data to lay out, and the other cases shouldn't be possible. - auto arrayType = CGM.getContext().getAsConstantArrayType(type); - if (!arrayType) return; - - QualType eltType = arrayType->getElementType(); - auto eltSize = CGM.getContext().getTypeSizeInChars(eltType); - for (uint64_t i = 0, e = arrayType->getSize().getZExtValue(); i != e; ++i) { - addTypedData(eltType, begin + i * eltSize); - } - - // Complex types. - } else if (auto complexType = type->getAs<ComplexType>()) { - auto eltType = complexType->getElementType(); - auto eltSize = CGM.getContext().getTypeSizeInChars(eltType); - auto eltLLVMType = CGM.getTypes().ConvertType(eltType); - addTypedData(eltLLVMType, begin, begin + eltSize); - addTypedData(eltLLVMType, begin + eltSize, begin + 2 * eltSize); - - // Member pointer types. - } else if (type->getAs<MemberPointerType>()) { - // Just add it all as opaque. - addOpaqueData(begin, begin + CGM.getContext().getTypeSizeInChars(type)); - - // Everything else is scalar and should not convert as an LLVM aggregate. - } else { - // We intentionally convert as !ForMem because we want to preserve - // that a type was an i1. - auto llvmType = CGM.getTypes().ConvertType(type); - addTypedData(llvmType, begin); - } -} - -void SwiftAggLowering::addTypedData(const RecordDecl *record, CharUnits begin) { - addTypedData(record, begin, CGM.getContext().getASTRecordLayout(record)); -} - -void SwiftAggLowering::addTypedData(const RecordDecl *record, CharUnits begin, - const ASTRecordLayout &layout) { - // Unions are a special case. - if (record->isUnion()) { - for (auto field : record->fields()) { - if (field->isBitField()) { - addBitFieldData(field, begin, 0); - } else { - addTypedData(field->getType(), begin); - } - } - return; - } - - // Note that correctness does not rely on us adding things in - // their actual order of layout; it's just somewhat more efficient - // for the builder. - - // With that in mind, add "early" C++ data. - auto cxxRecord = dyn_cast<CXXRecordDecl>(record); - if (cxxRecord) { - // - a v-table pointer, if the class adds its own - if (layout.hasOwnVFPtr()) { - addTypedData(CGM.Int8PtrTy, begin); - } - - // - non-virtual bases - for (auto &baseSpecifier : cxxRecord->bases()) { - if (baseSpecifier.isVirtual()) continue; - - auto baseRecord = baseSpecifier.getType()->getAsCXXRecordDecl(); - addTypedData(baseRecord, begin + layout.getBaseClassOffset(baseRecord)); - } - - // - a vbptr if the class adds its own - if (layout.hasOwnVBPtr()) { - addTypedData(CGM.Int8PtrTy, begin + layout.getVBPtrOffset()); - } - } - - // Add fields. - for (auto field : record->fields()) { - auto fieldOffsetInBits = layout.getFieldOffset(field->getFieldIndex()); - if (field->isBitField()) { - addBitFieldData(field, begin, fieldOffsetInBits); - } else { - addTypedData(field->getType(), - begin + CGM.getContext().toCharUnitsFromBits(fieldOffsetInBits)); - } - } - - // Add "late" C++ data: - if (cxxRecord) { - // - virtual bases - for (auto &vbaseSpecifier : cxxRecord->vbases()) { - auto baseRecord = vbaseSpecifier.getType()->getAsCXXRecordDecl(); - addTypedData(baseRecord, begin + layout.getVBaseClassOffset(baseRecord)); - } - } -} - -void SwiftAggLowering::addBitFieldData(const FieldDecl *bitfield, - CharUnits recordBegin, - uint64_t bitfieldBitBegin) { - assert(bitfield->isBitField()); - auto &ctx = CGM.getContext(); - auto width = bitfield->getBitWidthValue(ctx); - - // We can ignore zero-width bit-fields. - if (width == 0) return; - - // toCharUnitsFromBits rounds down. - CharUnits bitfieldByteBegin = ctx.toCharUnitsFromBits(bitfieldBitBegin); - - // Find the offset of the last byte that is partially occupied by the - // bit-field; since we otherwise expect exclusive ends, the end is the - // next byte. - uint64_t bitfieldBitLast = bitfieldBitBegin + width - 1; - CharUnits bitfieldByteEnd = - ctx.toCharUnitsFromBits(bitfieldBitLast) + CharUnits::One(); - addOpaqueData(recordBegin + bitfieldByteBegin, - recordBegin + bitfieldByteEnd); -} - -void SwiftAggLowering::addTypedData(llvm::Type *type, CharUnits begin) { - assert(type && "didn't provide type for typed data"); - addTypedData(type, begin, begin + getTypeStoreSize(CGM, type)); -} - -void SwiftAggLowering::addTypedData(llvm::Type *type, - CharUnits begin, CharUnits end) { - assert(type && "didn't provide type for typed data"); - assert(getTypeStoreSize(CGM, type) == end - begin); - - // Legalize vector types. - if (auto vecTy = dyn_cast<llvm::VectorType>(type)) { - SmallVector<llvm::Type*, 4> componentTys; - legalizeVectorType(CGM, end - begin, vecTy, componentTys); - assert(componentTys.size() >= 1); - - // Walk the initial components. - for (size_t i = 0, e = componentTys.size(); i != e - 1; ++i) { - llvm::Type *componentTy = componentTys[i]; - auto componentSize = getTypeStoreSize(CGM, componentTy); - assert(componentSize < end - begin); - addLegalTypedData(componentTy, begin, begin + componentSize); - begin += componentSize; - } - - return addLegalTypedData(componentTys.back(), begin, end); - } - - // Legalize integer types. - if (auto intTy = dyn_cast<llvm::IntegerType>(type)) { - if (!isLegalIntegerType(CGM, intTy)) - return addOpaqueData(begin, end); - } - - // All other types should be legal. - return addLegalTypedData(type, begin, end); -} - -void SwiftAggLowering::addLegalTypedData(llvm::Type *type, - CharUnits begin, CharUnits end) { - // Require the type to be naturally aligned. - if (!begin.isZero() && !begin.isMultipleOf(getNaturalAlignment(CGM, type))) { - - // Try splitting vector types. - if (auto vecTy = dyn_cast<llvm::VectorType>(type)) { - auto split = splitLegalVectorType(CGM, end - begin, vecTy); - auto eltTy = split.first; - auto numElts = split.second; - - auto eltSize = (end - begin) / numElts; - assert(eltSize == getTypeStoreSize(CGM, eltTy)); - for (size_t i = 0, e = numElts; i != e; ++i) { - addLegalTypedData(eltTy, begin, begin + eltSize); - begin += eltSize; - } - assert(begin == end); - return; - } - - return addOpaqueData(begin, end); - } - - addEntry(type, begin, end); -} - -void SwiftAggLowering::addEntry(llvm::Type *type, - CharUnits begin, CharUnits end) { - assert((!type || - (!isa<llvm::StructType>(type) && !isa<llvm::ArrayType>(type))) && - "cannot add aggregate-typed data"); - assert(!type || begin.isMultipleOf(getNaturalAlignment(CGM, type))); - - // Fast path: we can just add entries to the end. - if (Entries.empty() || Entries.back().End <= begin) { - Entries.push_back({begin, end, type}); - return; - } - - // Find the first existing entry that ends after the start of the new data. - // TODO: do a binary search if Entries is big enough for it to matter. - size_t index = Entries.size() - 1; - while (index != 0) { - if (Entries[index - 1].End <= begin) break; - --index; - } - - // The entry ends after the start of the new data. - // If the entry starts after the end of the new data, there's no conflict. - if (Entries[index].Begin >= end) { - // This insertion is potentially O(n), but the way we generally build - // these layouts makes that unlikely to matter: we'd need a union of - // several very large types. - Entries.insert(Entries.begin() + index, {begin, end, type}); - return; - } - - // Otherwise, the ranges overlap. The new range might also overlap - // with later ranges. -restartAfterSplit: - - // Simplest case: an exact overlap. - if (Entries[index].Begin == begin && Entries[index].End == end) { - // If the types match exactly, great. - if (Entries[index].Type == type) return; - - // If either type is opaque, make the entry opaque and return. - if (Entries[index].Type == nullptr) { - return; - } else if (type == nullptr) { - Entries[index].Type = nullptr; - return; - } - - // If they disagree in an ABI-agnostic way, just resolve the conflict - // arbitrarily. - if (auto entryType = getCommonType(Entries[index].Type, type)) { - Entries[index].Type = entryType; - return; - } - - // Otherwise, make the entry opaque. - Entries[index].Type = nullptr; - return; - } - - // Okay, we have an overlapping conflict of some sort. - - // If we have a vector type, split it. - if (auto vecTy = dyn_cast_or_null<llvm::VectorType>(type)) { - auto eltTy = vecTy->getElementType(); - CharUnits eltSize = (end - begin) / vecTy->getNumElements(); - assert(eltSize == getTypeStoreSize(CGM, eltTy)); - for (unsigned i = 0, e = vecTy->getNumElements(); i != e; ++i) { - addEntry(eltTy, begin, begin + eltSize); - begin += eltSize; - } - assert(begin == end); - return; - } - - // If the entry is a vector type, split it and try again. - if (Entries[index].Type && Entries[index].Type->isVectorTy()) { - splitVectorEntry(index); - goto restartAfterSplit; - } - - // Okay, we have no choice but to make the existing entry opaque. - - Entries[index].Type = nullptr; - - // Stretch the start of the entry to the beginning of the range. - if (begin < Entries[index].Begin) { - Entries[index].Begin = begin; - assert(index == 0 || begin >= Entries[index - 1].End); - } - - // Stretch the end of the entry to the end of the range; but if we run - // into the start of the next entry, just leave the range there and repeat. - while (end > Entries[index].End) { - assert(Entries[index].Type == nullptr); - - // If the range doesn't overlap the next entry, we're done. - if (index == Entries.size() - 1 || end <= Entries[index + 1].Begin) { - Entries[index].End = end; - break; - } - - // Otherwise, stretch to the start of the next entry. - Entries[index].End = Entries[index + 1].Begin; - - // Continue with the next entry. - index++; - - // This entry needs to be made opaque if it is not already. - if (Entries[index].Type == nullptr) - continue; - - // Split vector entries unless we completely subsume them. - if (Entries[index].Type->isVectorTy() && - end < Entries[index].End) { - splitVectorEntry(index); - } - - // Make the entry opaque. - Entries[index].Type = nullptr; - } -} - -/// Replace the entry of vector type at offset 'index' with a sequence -/// of its component vectors. -void SwiftAggLowering::splitVectorEntry(unsigned index) { - auto vecTy = cast<llvm::VectorType>(Entries[index].Type); - auto split = splitLegalVectorType(CGM, Entries[index].getWidth(), vecTy); - - auto eltTy = split.first; - CharUnits eltSize = getTypeStoreSize(CGM, eltTy); - auto numElts = split.second; - Entries.insert(Entries.begin() + index + 1, numElts - 1, StorageEntry()); - - CharUnits begin = Entries[index].Begin; - for (unsigned i = 0; i != numElts; ++i) { - Entries[index].Type = eltTy; - Entries[index].Begin = begin; - Entries[index].End = begin + eltSize; - begin += eltSize; - } -} - -/// Given a power-of-two unit size, return the offset of the aligned unit -/// of that size which contains the given offset. -/// -/// In other words, round down to the nearest multiple of the unit size. -static CharUnits getOffsetAtStartOfUnit(CharUnits offset, CharUnits unitSize) { - assert(isPowerOf2(unitSize.getQuantity())); - auto unitMask = ~(unitSize.getQuantity() - 1); - return CharUnits::fromQuantity(offset.getQuantity() & unitMask); -} - -static bool areBytesInSameUnit(CharUnits first, CharUnits second, - CharUnits chunkSize) { - return getOffsetAtStartOfUnit(first, chunkSize) - == getOffsetAtStartOfUnit(second, chunkSize); -} - -static bool isMergeableEntryType(llvm::Type *type) { - // Opaquely-typed memory is always mergeable. - if (type == nullptr) return true; - - // Pointers and integers are always mergeable. In theory we should not - // merge pointers, but (1) it doesn't currently matter in practice because - // the chunk size is never greater than the size of a pointer and (2) - // Swift IRGen uses integer types for a lot of things that are "really" - // just storing pointers (like Optional<SomePointer>). If we ever have a - // target that would otherwise combine pointers, we should put some effort - // into fixing those cases in Swift IRGen and then call out pointer types - // here. - - // Floating-point and vector types should never be merged. - // Most such types are too large and highly-aligned to ever trigger merging - // in practice, but it's important for the rule to cover at least 'half' - // and 'float', as well as things like small vectors of 'i1' or 'i8'. - return (!type->isFloatingPointTy() && !type->isVectorTy()); -} - -bool SwiftAggLowering::shouldMergeEntries(const StorageEntry &first, - const StorageEntry &second, - CharUnits chunkSize) { - // Only merge entries that overlap the same chunk. We test this first - // despite being a bit more expensive because this is the condition that - // tends to prevent merging. - if (!areBytesInSameUnit(first.End - CharUnits::One(), second.Begin, - chunkSize)) - return false; - - return (isMergeableEntryType(first.Type) && - isMergeableEntryType(second.Type)); -} - -void SwiftAggLowering::finish() { - if (Entries.empty()) { - Finished = true; - return; - } - - // We logically split the layout down into a series of chunks of this size, - // which is generally the size of a pointer. - const CharUnits chunkSize = getMaximumVoluntaryIntegerSize(CGM); - - // First pass: if two entries should be merged, make them both opaque - // and stretch one to meet the next. - // Also, remember if there are any opaque entries. - bool hasOpaqueEntries = (Entries[0].Type == nullptr); - for (size_t i = 1, e = Entries.size(); i != e; ++i) { - if (shouldMergeEntries(Entries[i - 1], Entries[i], chunkSize)) { - Entries[i - 1].Type = nullptr; - Entries[i].Type = nullptr; - Entries[i - 1].End = Entries[i].Begin; - hasOpaqueEntries = true; - - } else if (Entries[i].Type == nullptr) { - hasOpaqueEntries = true; - } - } - - // The rest of the algorithm leaves non-opaque entries alone, so if we - // have no opaque entries, we're done. - if (!hasOpaqueEntries) { - Finished = true; - return; - } - - // Okay, move the entries to a temporary and rebuild Entries. - auto orig = std::move(Entries); - assert(Entries.empty()); - - for (size_t i = 0, e = orig.size(); i != e; ++i) { - // Just copy over non-opaque entries. - if (orig[i].Type != nullptr) { - Entries.push_back(orig[i]); - continue; - } - - // Scan forward to determine the full extent of the next opaque range. - // We know from the first pass that only contiguous ranges will overlap - // the same aligned chunk. - auto begin = orig[i].Begin; - auto end = orig[i].End; - while (i + 1 != e && - orig[i + 1].Type == nullptr && - end == orig[i + 1].Begin) { - end = orig[i + 1].End; - i++; - } - - // Add an entry per intersected chunk. - do { - // Find the smallest aligned storage unit in the maximal aligned - // storage unit containing 'begin' that contains all the bytes in - // the intersection between the range and this chunk. - CharUnits localBegin = begin; - CharUnits chunkBegin = getOffsetAtStartOfUnit(localBegin, chunkSize); - CharUnits chunkEnd = chunkBegin + chunkSize; - CharUnits localEnd = std::min(end, chunkEnd); - - // Just do a simple loop over ever-increasing unit sizes. - CharUnits unitSize = CharUnits::One(); - CharUnits unitBegin, unitEnd; - for (; ; unitSize *= 2) { - assert(unitSize <= chunkSize); - unitBegin = getOffsetAtStartOfUnit(localBegin, unitSize); - unitEnd = unitBegin + unitSize; - if (unitEnd >= localEnd) break; - } - - // Add an entry for this unit. - auto entryTy = - llvm::IntegerType::get(CGM.getLLVMContext(), - CGM.getContext().toBits(unitSize)); - Entries.push_back({unitBegin, unitEnd, entryTy}); - - // The next chunk starts where this chunk left off. - begin = localEnd; - } while (begin != end); - } - - // Okay, finally finished. - Finished = true; -} - -void SwiftAggLowering::enumerateComponents(EnumerationCallback callback) const { - assert(Finished && "haven't yet finished lowering"); - - for (auto &entry : Entries) { - callback(entry.Begin, entry.End, entry.Type); - } -} - -std::pair<llvm::StructType*, llvm::Type*> -SwiftAggLowering::getCoerceAndExpandTypes() const { - assert(Finished && "haven't yet finished lowering"); - - auto &ctx = CGM.getLLVMContext(); - - if (Entries.empty()) { - auto type = llvm::StructType::get(ctx); - return { type, type }; - } - - SmallVector<llvm::Type*, 8> elts; - CharUnits lastEnd = CharUnits::Zero(); - bool hasPadding = false; - bool packed = false; - for (auto &entry : Entries) { - if (entry.Begin != lastEnd) { - auto paddingSize = entry.Begin - lastEnd; - assert(!paddingSize.isNegative()); - - auto padding = llvm::ArrayType::get(llvm::Type::getInt8Ty(ctx), - paddingSize.getQuantity()); - elts.push_back(padding); - hasPadding = true; - } - - if (!packed && !entry.Begin.isMultipleOf( - CharUnits::fromQuantity( - CGM.getDataLayout().getABITypeAlignment(entry.Type)))) - packed = true; - - elts.push_back(entry.Type); - - lastEnd = entry.Begin + getTypeAllocSize(CGM, entry.Type); - assert(entry.End <= lastEnd); - } - - // We don't need to adjust 'packed' to deal with possible tail padding - // because we never do that kind of access through the coercion type. - auto coercionType = llvm::StructType::get(ctx, elts, packed); - - llvm::Type *unpaddedType = coercionType; - if (hasPadding) { - elts.clear(); - for (auto &entry : Entries) { - elts.push_back(entry.Type); - } - if (elts.size() == 1) { - unpaddedType = elts[0]; - } else { - unpaddedType = llvm::StructType::get(ctx, elts, /*packed*/ false); - } - } else if (Entries.size() == 1) { - unpaddedType = Entries[0].Type; - } - - return { coercionType, unpaddedType }; -} - -bool SwiftAggLowering::shouldPassIndirectly(bool asReturnValue) const { - assert(Finished && "haven't yet finished lowering"); - - // Empty types don't need to be passed indirectly. - if (Entries.empty()) return false; - - // Avoid copying the array of types when there's just a single element. - if (Entries.size() == 1) { - return getSwiftABIInfo(CGM).shouldPassIndirectlyForSwift( - Entries.back().Type, - asReturnValue); - } - - SmallVector<llvm::Type*, 8> componentTys; - componentTys.reserve(Entries.size()); - for (auto &entry : Entries) { - componentTys.push_back(entry.Type); - } - return getSwiftABIInfo(CGM).shouldPassIndirectlyForSwift(componentTys, - asReturnValue); -} - -bool swiftcall::shouldPassIndirectly(CodeGenModule &CGM, - ArrayRef<llvm::Type*> componentTys, - bool asReturnValue) { - return getSwiftABIInfo(CGM).shouldPassIndirectlyForSwift(componentTys, - asReturnValue); -} - -CharUnits swiftcall::getMaximumVoluntaryIntegerSize(CodeGenModule &CGM) { - // Currently always the size of an ordinary pointer. - return CGM.getContext().toCharUnitsFromBits( - CGM.getContext().getTargetInfo().getPointerWidth(0)); -} - -CharUnits swiftcall::getNaturalAlignment(CodeGenModule &CGM, llvm::Type *type) { - // For Swift's purposes, this is always just the store size of the type - // rounded up to a power of 2. - auto size = (unsigned long long) getTypeStoreSize(CGM, type).getQuantity(); - if (!isPowerOf2(size)) { - size = 1ULL << (llvm::findLastSet(size, llvm::ZB_Undefined) + 1); - } - assert(size >= CGM.getDataLayout().getABITypeAlignment(type)); - return CharUnits::fromQuantity(size); -} - -bool swiftcall::isLegalIntegerType(CodeGenModule &CGM, - llvm::IntegerType *intTy) { - auto size = intTy->getBitWidth(); - switch (size) { - case 1: - case 8: - case 16: - case 32: - case 64: - // Just assume that the above are always legal. - return true; - - case 128: - return CGM.getContext().getTargetInfo().hasInt128Type(); - - default: - return false; - } -} - -bool swiftcall::isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize, - llvm::VectorType *vectorTy) { - return isLegalVectorType(CGM, vectorSize, vectorTy->getElementType(), - vectorTy->getNumElements()); -} - -bool swiftcall::isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize, - llvm::Type *eltTy, unsigned numElts) { - assert(numElts > 1 && "illegal vector length"); - return getSwiftABIInfo(CGM) - .isLegalVectorTypeForSwift(vectorSize, eltTy, numElts); -} - -std::pair<llvm::Type*, unsigned> -swiftcall::splitLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize, - llvm::VectorType *vectorTy) { - auto numElts = vectorTy->getNumElements(); - auto eltTy = vectorTy->getElementType(); - - // Try to split the vector type in half. - if (numElts >= 4 && isPowerOf2(numElts)) { - if (isLegalVectorType(CGM, vectorSize / 2, eltTy, numElts / 2)) - return {llvm::VectorType::get(eltTy, numElts / 2), 2}; - } - - return {eltTy, numElts}; -} - -void swiftcall::legalizeVectorType(CodeGenModule &CGM, CharUnits origVectorSize, - llvm::VectorType *origVectorTy, - llvm::SmallVectorImpl<llvm::Type*> &components) { - // If it's already a legal vector type, use it. - if (isLegalVectorType(CGM, origVectorSize, origVectorTy)) { - components.push_back(origVectorTy); - return; - } - - // Try to split the vector into legal subvectors. - auto numElts = origVectorTy->getNumElements(); - auto eltTy = origVectorTy->getElementType(); - assert(numElts != 1); - - // The largest size that we're still considering making subvectors of. - // Always a power of 2. - unsigned logCandidateNumElts = llvm::findLastSet(numElts, llvm::ZB_Undefined); - unsigned candidateNumElts = 1U << logCandidateNumElts; - assert(candidateNumElts <= numElts && candidateNumElts * 2 > numElts); - - // Minor optimization: don't check the legality of this exact size twice. - if (candidateNumElts == numElts) { - logCandidateNumElts--; - candidateNumElts >>= 1; - } - - CharUnits eltSize = (origVectorSize / numElts); - CharUnits candidateSize = eltSize * candidateNumElts; - - // The sensibility of this algorithm relies on the fact that we never - // have a legal non-power-of-2 vector size without having the power of 2 - // also be legal. - while (logCandidateNumElts > 0) { - assert(candidateNumElts == 1U << logCandidateNumElts); - assert(candidateNumElts <= numElts); - assert(candidateSize == eltSize * candidateNumElts); - - // Skip illegal vector sizes. - if (!isLegalVectorType(CGM, candidateSize, eltTy, candidateNumElts)) { - logCandidateNumElts--; - candidateNumElts /= 2; - candidateSize /= 2; - continue; - } - - // Add the right number of vectors of this size. - auto numVecs = numElts >> logCandidateNumElts; - components.append(numVecs, llvm::VectorType::get(eltTy, candidateNumElts)); - numElts -= (numVecs << logCandidateNumElts); - - if (numElts == 0) return; - - // It's possible that the number of elements remaining will be legal. - // This can happen with e.g. <7 x float> when <3 x float> is legal. - // This only needs to be separately checked if it's not a power of 2. - if (numElts > 2 && !isPowerOf2(numElts) && - isLegalVectorType(CGM, eltSize * numElts, eltTy, numElts)) { - components.push_back(llvm::VectorType::get(eltTy, numElts)); - return; - } - - // Bring vecSize down to something no larger than numElts. - do { - logCandidateNumElts--; - candidateNumElts /= 2; - candidateSize /= 2; - } while (candidateNumElts > numElts); - } - - // Otherwise, just append a bunch of individual elements. - components.append(numElts, eltTy); -} - -bool swiftcall::mustPassRecordIndirectly(CodeGenModule &CGM, - const RecordDecl *record) { - // FIXME: should we not rely on the standard computation in Sema, just in - // case we want to diverge from the platform ABI (e.g. on targets where - // that uses the MSVC rule)? - return !record->canPassInRegisters(); -} - -static ABIArgInfo classifyExpandedType(SwiftAggLowering &lowering, - bool forReturn, - CharUnits alignmentForIndirect) { - if (lowering.empty()) { - return ABIArgInfo::getIgnore(); - } else if (lowering.shouldPassIndirectly(forReturn)) { - return ABIArgInfo::getIndirect(alignmentForIndirect, /*byval*/ false); - } else { - auto types = lowering.getCoerceAndExpandTypes(); - return ABIArgInfo::getCoerceAndExpand(types.first, types.second); - } -} - -static ABIArgInfo classifyType(CodeGenModule &CGM, CanQualType type, - bool forReturn) { - if (auto recordType = dyn_cast<RecordType>(type)) { - auto record = recordType->getDecl(); - auto &layout = CGM.getContext().getASTRecordLayout(record); - - if (mustPassRecordIndirectly(CGM, record)) - return ABIArgInfo::getIndirect(layout.getAlignment(), /*byval*/ false); - - SwiftAggLowering lowering(CGM); - lowering.addTypedData(recordType->getDecl(), CharUnits::Zero(), layout); - lowering.finish(); - - return classifyExpandedType(lowering, forReturn, layout.getAlignment()); - } - - // Just assume that all of our target ABIs can support returning at least - // two integer or floating-point values. - if (isa<ComplexType>(type)) { - return (forReturn ? ABIArgInfo::getDirect() : ABIArgInfo::getExpand()); - } - - // Vector types may need to be legalized. - if (isa<VectorType>(type)) { - SwiftAggLowering lowering(CGM); - lowering.addTypedData(type, CharUnits::Zero()); - lowering.finish(); - - CharUnits alignment = CGM.getContext().getTypeAlignInChars(type); - return classifyExpandedType(lowering, forReturn, alignment); - } - - // Member pointer types need to be expanded, but it's a simple form of - // expansion that 'Direct' can handle. Note that CanBeFlattened should be - // true for this to work. - - // 'void' needs to be ignored. - if (type->isVoidType()) { - return ABIArgInfo::getIgnore(); - } - - // Everything else can be passed directly. - return ABIArgInfo::getDirect(); -} - -ABIArgInfo swiftcall::classifyReturnType(CodeGenModule &CGM, CanQualType type) { - return classifyType(CGM, type, /*forReturn*/ true); -} - -ABIArgInfo swiftcall::classifyArgumentType(CodeGenModule &CGM, - CanQualType type) { - return classifyType(CGM, type, /*forReturn*/ false); -} - -void swiftcall::computeABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI) { - auto &retInfo = FI.getReturnInfo(); - retInfo = classifyReturnType(CGM, FI.getReturnType()); - - for (unsigned i = 0, e = FI.arg_size(); i != e; ++i) { - auto &argInfo = FI.arg_begin()[i]; - argInfo.info = classifyArgumentType(CGM, argInfo.type); - } -} - -// Is swifterror lowered to a register by the target ABI. -bool swiftcall::isSwiftErrorLoweredInRegister(CodeGenModule &CGM) { - return getSwiftABIInfo(CGM).isSwiftErrorInRegister(); -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp b/gnu/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp deleted file mode 100644 index f54decf5106..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp +++ /dev/null @@ -1,9608 +0,0 @@ -//===---- TargetInfo.cpp - Encapsulate target details -----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// These classes wrap the information about a call or function -// definition used to handle ABI compliancy. -// -//===----------------------------------------------------------------------===// - -#include "TargetInfo.h" -#include "ABIInfo.h" -#include "CGBlocks.h" -#include "CGCXXABI.h" -#include "CGValue.h" -#include "CodeGenFunction.h" -#include "clang/AST/RecordLayout.h" -#include "clang/Basic/CodeGenOptions.h" -#include "clang/CodeGen/CGFunctionInfo.h" -#include "clang/CodeGen/SwiftCallingConv.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/Triple.h" -#include "llvm/ADT/Twine.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/Type.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> // std::sort - -using namespace clang; -using namespace CodeGen; - -// Helper for coercing an aggregate argument or return value into an integer -// array of the same size (including padding) and alignment. This alternate -// coercion happens only for the RenderScript ABI and can be removed after -// runtimes that rely on it are no longer supported. -// -// RenderScript assumes that the size of the argument / return value in the IR -// is the same as the size of the corresponding qualified type. This helper -// coerces the aggregate type into an array of the same size (including -// padding). This coercion is used in lieu of expansion of struct members or -// other canonical coercions that return a coerced-type of larger size. -// -// Ty - The argument / return value type -// Context - The associated ASTContext -// LLVMContext - The associated LLVMContext -static ABIArgInfo coerceToIntArray(QualType Ty, - ASTContext &Context, - llvm::LLVMContext &LLVMContext) { - // Alignment and Size are measured in bits. - const uint64_t Size = Context.getTypeSize(Ty); - const uint64_t Alignment = Context.getTypeAlign(Ty); - llvm::Type *IntType = llvm::Type::getIntNTy(LLVMContext, Alignment); - const uint64_t NumElements = (Size + Alignment - 1) / Alignment; - return ABIArgInfo::getDirect(llvm::ArrayType::get(IntType, NumElements)); -} - -static void AssignToArrayRange(CodeGen::CGBuilderTy &Builder, - llvm::Value *Array, - llvm::Value *Value, - unsigned FirstIndex, - unsigned LastIndex) { - // Alternatively, we could emit this as a loop in the source. - for (unsigned I = FirstIndex; I <= LastIndex; ++I) { - llvm::Value *Cell = - Builder.CreateConstInBoundsGEP1_32(Builder.getInt8Ty(), Array, I); - Builder.CreateAlignedStore(Value, Cell, CharUnits::One()); - } -} - -static bool isAggregateTypeForABI(QualType T) { - return !CodeGenFunction::hasScalarEvaluationKind(T) || - T->isMemberFunctionPointerType(); -} - -ABIArgInfo -ABIInfo::getNaturalAlignIndirect(QualType Ty, bool ByRef, bool Realign, - llvm::Type *Padding) const { - return ABIArgInfo::getIndirect(getContext().getTypeAlignInChars(Ty), - ByRef, Realign, Padding); -} - -ABIArgInfo -ABIInfo::getNaturalAlignIndirectInReg(QualType Ty, bool Realign) const { - return ABIArgInfo::getIndirectInReg(getContext().getTypeAlignInChars(Ty), - /*ByRef*/ false, Realign); -} - -Address ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const { - return Address::invalid(); -} - -ABIInfo::~ABIInfo() {} - -/// Does the given lowering require more than the given number of -/// registers when expanded? -/// -/// This is intended to be the basis of a reasonable basic implementation -/// of should{Pass,Return}IndirectlyForSwift. -/// -/// For most targets, a limit of four total registers is reasonable; this -/// limits the amount of code required in order to move around the value -/// in case it wasn't produced immediately prior to the call by the caller -/// (or wasn't produced in exactly the right registers) or isn't used -/// immediately within the callee. But some targets may need to further -/// limit the register count due to an inability to support that many -/// return registers. -static bool occupiesMoreThan(CodeGenTypes &cgt, - ArrayRef<llvm::Type*> scalarTypes, - unsigned maxAllRegisters) { - unsigned intCount = 0, fpCount = 0; - for (llvm::Type *type : scalarTypes) { - if (type->isPointerTy()) { - intCount++; - } else if (auto intTy = dyn_cast<llvm::IntegerType>(type)) { - auto ptrWidth = cgt.getTarget().getPointerWidth(0); - intCount += (intTy->getBitWidth() + ptrWidth - 1) / ptrWidth; - } else { - assert(type->isVectorTy() || type->isFloatingPointTy()); - fpCount++; - } - } - - return (intCount + fpCount > maxAllRegisters); -} - -bool SwiftABIInfo::isLegalVectorTypeForSwift(CharUnits vectorSize, - llvm::Type *eltTy, - unsigned numElts) const { - // The default implementation of this assumes that the target guarantees - // 128-bit SIMD support but nothing more. - return (vectorSize.getQuantity() > 8 && vectorSize.getQuantity() <= 16); -} - -static CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT, - CGCXXABI &CXXABI) { - const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); - if (!RD) { - if (!RT->getDecl()->canPassInRegisters()) - return CGCXXABI::RAA_Indirect; - return CGCXXABI::RAA_Default; - } - return CXXABI.getRecordArgABI(RD); -} - -static CGCXXABI::RecordArgABI getRecordArgABI(QualType T, - CGCXXABI &CXXABI) { - const RecordType *RT = T->getAs<RecordType>(); - if (!RT) - return CGCXXABI::RAA_Default; - return getRecordArgABI(RT, CXXABI); -} - -static bool classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, - const ABIInfo &Info) { - QualType Ty = FI.getReturnType(); - - if (const auto *RT = Ty->getAs<RecordType>()) - if (!isa<CXXRecordDecl>(RT->getDecl()) && - !RT->getDecl()->canPassInRegisters()) { - FI.getReturnInfo() = Info.getNaturalAlignIndirect(Ty); - return true; - } - - return CXXABI.classifyReturnType(FI); -} - -/// Pass transparent unions as if they were the type of the first element. Sema -/// should ensure that all elements of the union have the same "machine type". -static QualType useFirstFieldIfTransparentUnion(QualType Ty) { - if (const RecordType *UT = Ty->getAsUnionType()) { - const RecordDecl *UD = UT->getDecl(); - if (UD->hasAttr<TransparentUnionAttr>()) { - assert(!UD->field_empty() && "sema created an empty transparent union"); - return UD->field_begin()->getType(); - } - } - return Ty; -} - -CGCXXABI &ABIInfo::getCXXABI() const { - return CGT.getCXXABI(); -} - -ASTContext &ABIInfo::getContext() const { - return CGT.getContext(); -} - -llvm::LLVMContext &ABIInfo::getVMContext() const { - return CGT.getLLVMContext(); -} - -const llvm::DataLayout &ABIInfo::getDataLayout() const { - return CGT.getDataLayout(); -} - -const TargetInfo &ABIInfo::getTarget() const { - return CGT.getTarget(); -} - -const CodeGenOptions &ABIInfo::getCodeGenOpts() const { - return CGT.getCodeGenOpts(); -} - -bool ABIInfo::isAndroid() const { return getTarget().getTriple().isAndroid(); } - -bool ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const { - return false; -} - -bool ABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base, - uint64_t Members) const { - return false; -} - -LLVM_DUMP_METHOD void ABIArgInfo::dump() const { - raw_ostream &OS = llvm::errs(); - OS << "(ABIArgInfo Kind="; - switch (TheKind) { - case Direct: - OS << "Direct Type="; - if (llvm::Type *Ty = getCoerceToType()) - Ty->print(OS); - else - OS << "null"; - break; - case Extend: - OS << "Extend"; - break; - case Ignore: - OS << "Ignore"; - break; - case InAlloca: - OS << "InAlloca Offset=" << getInAllocaFieldIndex(); - break; - case Indirect: - OS << "Indirect Align=" << getIndirectAlign().getQuantity() - << " ByVal=" << getIndirectByVal() - << " Realign=" << getIndirectRealign(); - break; - case Expand: - OS << "Expand"; - break; - case CoerceAndExpand: - OS << "CoerceAndExpand Type="; - getCoerceAndExpandType()->print(OS); - break; - } - OS << ")\n"; -} - -// Dynamically round a pointer up to a multiple of the given alignment. -static llvm::Value *emitRoundPointerUpToAlignment(CodeGenFunction &CGF, - llvm::Value *Ptr, - CharUnits Align) { - llvm::Value *PtrAsInt = Ptr; - // OverflowArgArea = (OverflowArgArea + Align - 1) & -Align; - PtrAsInt = CGF.Builder.CreatePtrToInt(PtrAsInt, CGF.IntPtrTy); - PtrAsInt = CGF.Builder.CreateAdd(PtrAsInt, - llvm::ConstantInt::get(CGF.IntPtrTy, Align.getQuantity() - 1)); - PtrAsInt = CGF.Builder.CreateAnd(PtrAsInt, - llvm::ConstantInt::get(CGF.IntPtrTy, -Align.getQuantity())); - PtrAsInt = CGF.Builder.CreateIntToPtr(PtrAsInt, - Ptr->getType(), - Ptr->getName() + ".aligned"); - return PtrAsInt; -} - -/// Emit va_arg for a platform using the common void* representation, -/// where arguments are simply emitted in an array of slots on the stack. -/// -/// This version implements the core direct-value passing rules. -/// -/// \param SlotSize - The size and alignment of a stack slot. -/// Each argument will be allocated to a multiple of this number of -/// slots, and all the slots will be aligned to this value. -/// \param AllowHigherAlign - The slot alignment is not a cap; -/// an argument type with an alignment greater than the slot size -/// will be emitted on a higher-alignment address, potentially -/// leaving one or more empty slots behind as padding. If this -/// is false, the returned address might be less-aligned than -/// DirectAlign. -static Address emitVoidPtrDirectVAArg(CodeGenFunction &CGF, - Address VAListAddr, - llvm::Type *DirectTy, - CharUnits DirectSize, - CharUnits DirectAlign, - CharUnits SlotSize, - bool AllowHigherAlign) { - // Cast the element type to i8* if necessary. Some platforms define - // va_list as a struct containing an i8* instead of just an i8*. - if (VAListAddr.getElementType() != CGF.Int8PtrTy) - VAListAddr = CGF.Builder.CreateElementBitCast(VAListAddr, CGF.Int8PtrTy); - - llvm::Value *Ptr = CGF.Builder.CreateLoad(VAListAddr, "argp.cur"); - - // If the CC aligns values higher than the slot size, do so if needed. - Address Addr = Address::invalid(); - if (AllowHigherAlign && DirectAlign > SlotSize) { - Addr = Address(emitRoundPointerUpToAlignment(CGF, Ptr, DirectAlign), - DirectAlign); - } else { - Addr = Address(Ptr, SlotSize); - } - - // Advance the pointer past the argument, then store that back. - CharUnits FullDirectSize = DirectSize.alignTo(SlotSize); - llvm::Value *NextPtr = - CGF.Builder.CreateConstInBoundsByteGEP(Addr.getPointer(), FullDirectSize, - "argp.next"); - CGF.Builder.CreateStore(NextPtr, 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. - if (DirectSize < SlotSize && CGF.CGM.getDataLayout().isBigEndian() && - !DirectTy->isStructTy()) { - Addr = CGF.Builder.CreateConstInBoundsByteGEP(Addr, SlotSize - DirectSize); - } - - Addr = CGF.Builder.CreateElementBitCast(Addr, DirectTy); - return Addr; -} - -/// Emit va_arg for a platform using the common void* representation, -/// where arguments are simply emitted in an array of slots on the stack. -/// -/// \param IsIndirect - Values of this type are passed indirectly. -/// \param ValueInfo - The size and alignment of this type, generally -/// computed with getContext().getTypeInfoInChars(ValueTy). -/// \param SlotSizeAndAlign - The size and alignment of a stack slot. -/// Each argument will be allocated to a multiple of this number of -/// slots, and all the slots will be aligned to this value. -/// \param AllowHigherAlign - The slot alignment is not a cap; -/// an argument type with an alignment greater than the slot size -/// will be emitted on a higher-alignment address, potentially -/// leaving one or more empty slots behind as padding. -static Address emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType ValueTy, bool IsIndirect, - std::pair<CharUnits, CharUnits> ValueInfo, - CharUnits SlotSizeAndAlign, - bool AllowHigherAlign) { - // The size and alignment of the value that was passed directly. - CharUnits DirectSize, DirectAlign; - if (IsIndirect) { - DirectSize = CGF.getPointerSize(); - DirectAlign = CGF.getPointerAlign(); - } else { - DirectSize = ValueInfo.first; - DirectAlign = ValueInfo.second; - } - - // Cast the address we've calculated to the right type. - llvm::Type *DirectTy = CGF.ConvertTypeForMem(ValueTy); - if (IsIndirect) - DirectTy = DirectTy->getPointerTo(0); - - Address Addr = emitVoidPtrDirectVAArg(CGF, VAListAddr, DirectTy, - DirectSize, DirectAlign, - SlotSizeAndAlign, - AllowHigherAlign); - - if (IsIndirect) { - Addr = Address(CGF.Builder.CreateLoad(Addr), ValueInfo.second); - } - - return Addr; - -} - -static Address emitMergePHI(CodeGenFunction &CGF, - Address Addr1, llvm::BasicBlock *Block1, - Address Addr2, llvm::BasicBlock *Block2, - 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); - CharUnits Align = std::min(Addr1.getAlignment(), Addr2.getAlignment()); - return Address(PHI, Align); -} - -TargetCodeGenInfo::~TargetCodeGenInfo() { delete Info; } - -// If someone can figure out a general rule for this, that would be great. -// It's probably just doomed to be platform-dependent, though. -unsigned TargetCodeGenInfo::getSizeOfUnwindException() const { - // Verified for: - // x86-64 FreeBSD, Linux, Darwin - // x86-32 FreeBSD, Linux, Darwin - // PowerPC Linux, Darwin - // ARM Darwin (*not* EABI) - // AArch64 Linux - return 32; -} - -bool TargetCodeGenInfo::isNoProtoCallVariadic(const CallArgList &args, - const FunctionNoProtoType *fnType) const { - // The following conventions are known to require this to be false: - // x86_stdcall - // MIPS - // For everything else, we just prefer false unless we opt out. - return false; -} - -void -TargetCodeGenInfo::getDependentLibraryOption(llvm::StringRef Lib, - llvm::SmallString<24> &Opt) const { - // This assumes the user is passing a library name like "rt" instead of a - // filename like "librt.a/so", and that they don't care whether it's static or - // dynamic. - Opt = "-l"; - Opt += Lib; -} - -unsigned TargetCodeGenInfo::getOpenCLKernelCallingConv() const { - // OpenCL kernels are called via an explicit runtime API with arguments - // set with clSetKernelArg(), not as normal sub-functions. - // Return SPIR_KERNEL by default as the kernel calling convention to - // ensure the fingerprint is fixed such way that each OpenCL argument - // gets one matching argument in the produced kernel function argument - // list to enable feasible implementation of clSetKernelArg() with - // aggregates etc. In case we would use the default C calling conv here, - // clSetKernelArg() might break depending on the target-specific - // conventions; different targets might split structs passed as values - // to multiple function arguments etc. - return llvm::CallingConv::SPIR_KERNEL; -} - -llvm::Constant *TargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule &CGM, - llvm::PointerType *T, QualType QT) const { - return llvm::ConstantPointerNull::get(T); -} - -LangAS TargetCodeGenInfo::getGlobalVarAddressSpace(CodeGenModule &CGM, - const VarDecl *D) const { - assert(!CGM.getLangOpts().OpenCL && - !(CGM.getLangOpts().CUDA && CGM.getLangOpts().CUDAIsDevice) && - "Address space agnostic languages only"); - return D ? D->getType().getAddressSpace() : LangAS::Default; -} - -llvm::Value *TargetCodeGenInfo::performAddrSpaceCast( - CodeGen::CodeGenFunction &CGF, llvm::Value *Src, LangAS SrcAddr, - LangAS DestAddr, llvm::Type *DestTy, bool isNonNull) const { - // Since target may map different address spaces in AST to the same address - // space, an address space conversion may end up as a bitcast. - if (auto *C = dyn_cast<llvm::Constant>(Src)) - return performAddrSpaceCast(CGF.CGM, C, SrcAddr, DestAddr, DestTy); - return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Src, DestTy); -} - -llvm::Constant * -TargetCodeGenInfo::performAddrSpaceCast(CodeGenModule &CGM, llvm::Constant *Src, - LangAS SrcAddr, LangAS DestAddr, - llvm::Type *DestTy) const { - // Since target may map different address spaces in AST to the same address - // space, an address space conversion may end up as a bitcast. - return llvm::ConstantExpr::getPointerCast(Src, DestTy); -} - -llvm::SyncScope::ID -TargetCodeGenInfo::getLLVMSyncScopeID(SyncScope S, llvm::LLVMContext &C) const { - return C.getOrInsertSyncScopeID(""); /* default sync scope */ -} - -static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays); - -/// isEmptyField - Return true iff a the field is "empty", that is it -/// is an unnamed bit-field or an (array of) empty record(s). -static bool isEmptyField(ASTContext &Context, const FieldDecl *FD, - bool AllowArrays) { - if (FD->isUnnamedBitfield()) - return true; - - QualType FT = FD->getType(); - - // Constant arrays of empty records count as empty, strip them off. - // Constant arrays of zero length always count as empty. - if (AllowArrays) - while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) { - if (AT->getSize() == 0) - return true; - FT = AT->getElementType(); - } - - const RecordType *RT = FT->getAs<RecordType>(); - if (!RT) - return false; - - // C++ record fields are never empty, at least in the Itanium ABI. - // - // FIXME: We should use a predicate for whether this behavior is true in the - // current ABI. - if (isa<CXXRecordDecl>(RT->getDecl())) - return false; - - return isEmptyRecord(Context, FT, AllowArrays); -} - -/// isEmptyRecord - Return true iff a structure contains only empty -/// fields. Note that a structure with a flexible array member is not -/// considered empty. -static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays) { - const RecordType *RT = T->getAs<RecordType>(); - if (!RT) - return false; - const RecordDecl *RD = RT->getDecl(); - if (RD->hasFlexibleArrayMember()) - return false; - - // If this is a C++ record, check the bases first. - if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) - for (const auto &I : CXXRD->bases()) - if (!isEmptyRecord(Context, I.getType(), true)) - return false; - - for (const auto *I : RD->fields()) - if (!isEmptyField(Context, I, AllowArrays)) - return false; - return true; -} - -/// isSingleElementStruct - Determine if a structure is a "single -/// element struct", i.e. it has exactly one non-empty field or -/// exactly one field which is itself a single element -/// struct. Structures with flexible array members are never -/// considered single element structs. -/// -/// \return The field declaration for the single non-empty field, if -/// it exists. -static const Type *isSingleElementStruct(QualType T, ASTContext &Context) { - const RecordType *RT = T->getAs<RecordType>(); - if (!RT) - return nullptr; - - const RecordDecl *RD = RT->getDecl(); - if (RD->hasFlexibleArrayMember()) - return nullptr; - - const Type *Found = nullptr; - - // If this is a C++ record, check the bases first. - if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) { - for (const auto &I : CXXRD->bases()) { - // Ignore empty records. - if (isEmptyRecord(Context, I.getType(), true)) - continue; - - // If we already found an element then this isn't a single-element struct. - if (Found) - return nullptr; - - // If this is non-empty and not a single element struct, the composite - // cannot be a single element struct. - Found = isSingleElementStruct(I.getType(), Context); - if (!Found) - return nullptr; - } - } - - // Check for single element. - for (const auto *FD : RD->fields()) { - QualType FT = FD->getType(); - - // Ignore empty fields. - if (isEmptyField(Context, FD, true)) - continue; - - // If we already found an element then this isn't a single-element - // struct. - if (Found) - return nullptr; - - // Treat single element arrays as the element. - while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) { - if (AT->getSize().getZExtValue() != 1) - break; - FT = AT->getElementType(); - } - - if (!isAggregateTypeForABI(FT)) { - Found = FT.getTypePtr(); - } else { - Found = isSingleElementStruct(FT, Context); - if (!Found) - return nullptr; - } - } - - // We don't consider a struct a single-element struct if it has - // padding beyond the element type. - if (Found && Context.getTypeSize(Found) != Context.getTypeSize(T)) - return nullptr; - - return Found; -} - -namespace { -Address EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, - const ABIArgInfo &AI) { - // This default implementation defers to the llvm backend's va_arg - // instruction. It can handle only passing arguments directly - // (typically only handled in the backend for primitive types), or - // aggregates passed indirectly by pointer (NOTE: if the "byval" - // flag has ABI impact in the callee, this implementation cannot - // work.) - - // Only a few cases are covered here at the moment -- those needed - // by the default abi. - llvm::Value *Val; - - if (AI.isIndirect()) { - assert(!AI.getPaddingType() && - "Unexpected PaddingType seen in arginfo in generic VAArg emitter!"); - assert( - !AI.getIndirectRealign() && - "Unexpected IndirectRealign seen in arginfo in generic VAArg emitter!"); - - auto TyInfo = CGF.getContext().getTypeInfoInChars(Ty); - CharUnits TyAlignForABI = TyInfo.second; - - llvm::Type *BaseTy = - llvm::PointerType::getUnqual(CGF.ConvertTypeForMem(Ty)); - llvm::Value *Addr = - CGF.Builder.CreateVAArg(VAListAddr.getPointer(), BaseTy); - return Address(Addr, TyAlignForABI); - } else { - assert((AI.isDirect() || AI.isExtend()) && - "Unexpected ArgInfo Kind in generic VAArg emitter!"); - - assert(!AI.getInReg() && - "Unexpected InReg seen in arginfo in generic VAArg emitter!"); - assert(!AI.getPaddingType() && - "Unexpected PaddingType seen in arginfo in generic VAArg emitter!"); - assert(!AI.getDirectOffset() && - "Unexpected DirectOffset seen in arginfo in generic VAArg emitter!"); - assert(!AI.getCoerceToType() && - "Unexpected CoerceToType seen in arginfo in generic VAArg emitter!"); - - Address Temp = CGF.CreateMemTemp(Ty, "varet"); - Val = CGF.Builder.CreateVAArg(VAListAddr.getPointer(), CGF.ConvertType(Ty)); - CGF.Builder.CreateStore(Val, Temp); - return Temp; - } -} - -/// DefaultABIInfo - The default implementation for ABI specific -/// details. This implementation provides information which results in -/// self-consistent and sensible LLVM IR generation, but does not -/// conform to any particular ABI. -class DefaultABIInfo : public ABIInfo { -public: - DefaultABIInfo(CodeGen::CodeGenTypes &CGT) : ABIInfo(CGT) {} - - ABIArgInfo classifyReturnType(QualType RetTy) const; - ABIArgInfo classifyArgumentType(QualType RetTy) const; - - void computeInfo(CGFunctionInfo &FI) const override { - if (!getCXXABI().classifyReturnType(FI)) - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); - for (auto &I : FI.arguments()) - I.info = classifyArgumentType(I.type); - } - - Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const override { - return EmitVAArgInstr(CGF, VAListAddr, Ty, classifyArgumentType(Ty)); - } -}; - -class DefaultTargetCodeGenInfo : public TargetCodeGenInfo { -public: - DefaultTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT) - : TargetCodeGenInfo(new DefaultABIInfo(CGT)) {} -}; - -ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const { - Ty = useFirstFieldIfTransparentUnion(Ty); - - if (isAggregateTypeForABI(Ty)) { - // Records with non-trivial destructors/copy-constructors should not be - // passed by value. - if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); - - return getNaturalAlignIndirect(Ty); - } - - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = Ty->getAs<EnumType>()) - Ty = EnumTy->getDecl()->getIntegerType(); - - return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect()); -} - -ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const { - if (RetTy->isVoidType()) - return ABIArgInfo::getIgnore(); - - if (isAggregateTypeForABI(RetTy)) - return getNaturalAlignIndirect(RetTy); - - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) - RetTy = EnumTy->getDecl()->getIntegerType(); - - return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy) - : ABIArgInfo::getDirect()); -} - -//===----------------------------------------------------------------------===// -// WebAssembly ABI Implementation -// -// This is a very simple ABI that relies a lot on DefaultABIInfo. -//===----------------------------------------------------------------------===// - -class WebAssemblyABIInfo final : public SwiftABIInfo { - DefaultABIInfo defaultInfo; - -public: - explicit WebAssemblyABIInfo(CodeGen::CodeGenTypes &CGT) - : SwiftABIInfo(CGT), defaultInfo(CGT) {} - -private: - ABIArgInfo classifyReturnType(QualType RetTy) const; - ABIArgInfo classifyArgumentType(QualType Ty) const; - - // DefaultABIInfo's classifyReturnType and classifyArgumentType are - // non-virtual, but computeInfo and EmitVAArg are virtual, so we - // overload them. - void computeInfo(CGFunctionInfo &FI) const override { - if (!getCXXABI().classifyReturnType(FI)) - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); - for (auto &Arg : FI.arguments()) - Arg.info = classifyArgumentType(Arg.type); - } - - Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const override; - - bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> scalars, - bool asReturnValue) const override { - return occupiesMoreThan(CGT, scalars, /*total*/ 4); - } - - bool isSwiftErrorInRegister() const override { - return false; - } -}; - -class WebAssemblyTargetCodeGenInfo final : public TargetCodeGenInfo { -public: - explicit WebAssemblyTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT) - : TargetCodeGenInfo(new WebAssemblyABIInfo(CGT)) {} - - void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &CGM) const override { - TargetCodeGenInfo::setTargetAttributes(D, GV, CGM); - if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D)) { - if (const auto *Attr = FD->getAttr<WebAssemblyImportModuleAttr>()) { - llvm::Function *Fn = cast<llvm::Function>(GV); - llvm::AttrBuilder B; - B.addAttribute("wasm-import-module", Attr->getImportModule()); - Fn->addAttributes(llvm::AttributeList::FunctionIndex, B); - } - if (const auto *Attr = FD->getAttr<WebAssemblyImportNameAttr>()) { - llvm::Function *Fn = cast<llvm::Function>(GV); - llvm::AttrBuilder B; - B.addAttribute("wasm-import-name", Attr->getImportName()); - Fn->addAttributes(llvm::AttributeList::FunctionIndex, B); - } - } - - if (auto *FD = dyn_cast_or_null<FunctionDecl>(D)) { - llvm::Function *Fn = cast<llvm::Function>(GV); - if (!FD->doesThisDeclarationHaveABody() && !FD->hasPrototype()) - Fn->addFnAttr("no-prototype"); - } - } -}; - -/// Classify argument of given type \p Ty. -ABIArgInfo WebAssemblyABIInfo::classifyArgumentType(QualType Ty) const { - Ty = useFirstFieldIfTransparentUnion(Ty); - - if (isAggregateTypeForABI(Ty)) { - // Records with non-trivial destructors/copy-constructors should not be - // passed by value. - if (auto RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); - // Ignore empty structs/unions. - if (isEmptyRecord(getContext(), Ty, true)) - return ABIArgInfo::getIgnore(); - // Lower single-element structs to just pass a regular value. TODO: We - // could do reasonable-size multiple-element structs too, using getExpand(), - // though watch out for things like bitfields. - if (const Type *SeltTy = isSingleElementStruct(Ty, getContext())) - return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); - } - - // Otherwise just do the default thing. - return defaultInfo.classifyArgumentType(Ty); -} - -ABIArgInfo WebAssemblyABIInfo::classifyReturnType(QualType RetTy) const { - if (isAggregateTypeForABI(RetTy)) { - // Records with non-trivial destructors/copy-constructors should not be - // returned by value. - if (!getRecordArgABI(RetTy, getCXXABI())) { - // Ignore empty structs/unions. - if (isEmptyRecord(getContext(), RetTy, true)) - return ABIArgInfo::getIgnore(); - // Lower single-element structs to just return a regular value. TODO: We - // could do reasonable-size multiple-element structs too, using - // ABIArgInfo::getDirect(). - if (const Type *SeltTy = isSingleElementStruct(RetTy, getContext())) - return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); - } - } - - // Otherwise just do the default thing. - return defaultInfo.classifyReturnType(RetTy); -} - -Address WebAssemblyABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const { - return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*Indirect=*/ false, - getContext().getTypeInfoInChars(Ty), - CharUnits::fromQuantity(4), - /*AllowHigherAlign=*/ true); -} - -//===----------------------------------------------------------------------===// -// le32/PNaCl bitcode ABI Implementation -// -// This is a simplified version of the x86_32 ABI. Arguments and return values -// are always passed on the stack. -//===----------------------------------------------------------------------===// - -class PNaClABIInfo : public ABIInfo { - public: - PNaClABIInfo(CodeGen::CodeGenTypes &CGT) : ABIInfo(CGT) {} - - ABIArgInfo classifyReturnType(QualType RetTy) const; - ABIArgInfo classifyArgumentType(QualType RetTy) const; - - void computeInfo(CGFunctionInfo &FI) const override; - Address EmitVAArg(CodeGenFunction &CGF, - Address VAListAddr, QualType Ty) const override; -}; - -class PNaClTargetCodeGenInfo : public TargetCodeGenInfo { - public: - PNaClTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT) - : TargetCodeGenInfo(new PNaClABIInfo(CGT)) {} -}; - -void PNaClABIInfo::computeInfo(CGFunctionInfo &FI) const { - if (!getCXXABI().classifyReturnType(FI)) - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); - - for (auto &I : FI.arguments()) - I.info = classifyArgumentType(I.type); -} - -Address PNaClABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const { - // The PNaCL ABI is a bit odd, in that varargs don't use normal - // function classification. Structs get passed directly for varargs - // functions, through a rewriting transform in - // pnacl-llvm/lib/Transforms/NaCl/ExpandVarArgs.cpp, which allows - // this target to actually support a va_arg instructions with an - // aggregate type, unlike other targets. - return EmitVAArgInstr(CGF, VAListAddr, Ty, ABIArgInfo::getDirect()); -} - -/// Classify argument of given type \p Ty. -ABIArgInfo PNaClABIInfo::classifyArgumentType(QualType Ty) const { - if (isAggregateTypeForABI(Ty)) { - if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); - return getNaturalAlignIndirect(Ty); - } else if (const EnumType *EnumTy = Ty->getAs<EnumType>()) { - // Treat an enum type as its underlying type. - Ty = EnumTy->getDecl()->getIntegerType(); - } else if (Ty->isFloatingType()) { - // Floating-point types don't go inreg. - return ABIArgInfo::getDirect(); - } - - return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect()); -} - -ABIArgInfo PNaClABIInfo::classifyReturnType(QualType RetTy) const { - if (RetTy->isVoidType()) - return ABIArgInfo::getIgnore(); - - // In the PNaCl ABI we always return records/structures on the stack. - if (isAggregateTypeForABI(RetTy)) - return getNaturalAlignIndirect(RetTy); - - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) - RetTy = EnumTy->getDecl()->getIntegerType(); - - return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy) - : ABIArgInfo::getDirect()); -} - -/// IsX86_MMXType - Return true if this is an MMX type. -bool IsX86_MMXType(llvm::Type *IRType) { - // Return true if the type is an MMX type <2 x i32>, <4 x i16>, or <8 x i8>. - return IRType->isVectorTy() && IRType->getPrimitiveSizeInBits() == 64 && - cast<llvm::VectorType>(IRType)->getElementType()->isIntegerTy() && - IRType->getScalarSizeInBits() != 64; -} - -static llvm::Type* X86AdjustInlineAsmType(CodeGen::CodeGenFunction &CGF, - StringRef Constraint, - llvm::Type* Ty) { - bool IsMMXCons = llvm::StringSwitch<bool>(Constraint) - .Cases("y", "&y", "^Ym", true) - .Default(false); - if (IsMMXCons && Ty->isVectorTy()) { - if (cast<llvm::VectorType>(Ty)->getBitWidth() != 64) { - // Invalid MMX constraint - return nullptr; - } - - return llvm::Type::getX86_MMXTy(CGF.getLLVMContext()); - } - - // No operation needed - return Ty; -} - -/// Returns true if this type can be passed in SSE registers with the -/// X86_VectorCall calling convention. Shared between x86_32 and x86_64. -static bool isX86VectorTypeForVectorCall(ASTContext &Context, QualType Ty) { - if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) { - if (BT->isFloatingPoint() && BT->getKind() != BuiltinType::Half) { - if (BT->getKind() == BuiltinType::LongDouble) { - if (&Context.getTargetInfo().getLongDoubleFormat() == - &llvm::APFloat::x87DoubleExtended()) - return false; - } - return true; - } - } else if (const VectorType *VT = Ty->getAs<VectorType>()) { - // vectorcall can pass XMM, YMM, and ZMM vectors. We don't pass SSE1 MMX - // registers specially. - unsigned VecSize = Context.getTypeSize(VT); - if (VecSize == 128 || VecSize == 256 || VecSize == 512) - return true; - } - return false; -} - -/// Returns true if this aggregate is small enough to be passed in SSE registers -/// in the X86_VectorCall calling convention. Shared between x86_32 and x86_64. -static bool isX86VectorCallAggregateSmallEnough(uint64_t NumMembers) { - return NumMembers <= 4; -} - -/// Returns a Homogeneous Vector Aggregate ABIArgInfo, used in X86. -static ABIArgInfo getDirectX86Hva(llvm::Type* T = nullptr) { - auto AI = ABIArgInfo::getDirect(T); - AI.setInReg(true); - AI.setCanBeFlattened(false); - return AI; -} - -//===----------------------------------------------------------------------===// -// X86-32 ABI Implementation -//===----------------------------------------------------------------------===// - -/// Similar to llvm::CCState, but for Clang. -struct CCState { - CCState(unsigned CC) : CC(CC), FreeRegs(0), FreeSSERegs(0) {} - - unsigned CC; - unsigned FreeRegs; - unsigned FreeSSERegs; -}; - -enum { - // Vectorcall only allows the first 6 parameters to be passed in registers. - VectorcallMaxParamNumAsReg = 6 -}; - -/// X86_32ABIInfo - The X86-32 ABI information. -class X86_32ABIInfo : public SwiftABIInfo { - enum Class { - Integer, - Float - }; - - static const unsigned MinABIStackAlignInBytes = 4; - - bool IsDarwinVectorABI; - bool IsRetSmallStructInRegABI; - bool IsWin32StructABI; - bool IsSoftFloatABI; - bool IsMCUABI; - unsigned DefaultNumRegisterParameters; - - static bool isRegisterSize(unsigned Size) { - return (Size == 8 || Size == 16 || Size == 32 || Size == 64); - } - - bool isHomogeneousAggregateBaseType(QualType Ty) const override { - // FIXME: Assumes vectorcall is in use. - return isX86VectorTypeForVectorCall(getContext(), Ty); - } - - bool isHomogeneousAggregateSmallEnough(const Type *Ty, - uint64_t NumMembers) const override { - // FIXME: Assumes vectorcall is in use. - return isX86VectorCallAggregateSmallEnough(NumMembers); - } - - bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context) const; - - /// getIndirectResult - Give a source type \arg Ty, return a suitable result - /// such that the argument will be passed in memory. - ABIArgInfo getIndirectResult(QualType Ty, bool ByVal, CCState &State) const; - - ABIArgInfo getIndirectReturnResult(QualType Ty, CCState &State) const; - - /// Return the alignment to use for the given type on the stack. - unsigned getTypeStackAlignInBytes(QualType Ty, unsigned Align) const; - - Class classify(QualType Ty) const; - ABIArgInfo classifyReturnType(QualType RetTy, CCState &State) const; - ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State) const; - - /// Updates the number of available free registers, returns - /// true if any registers were allocated. - bool updateFreeRegs(QualType Ty, CCState &State) const; - - bool shouldAggregateUseDirect(QualType Ty, CCState &State, bool &InReg, - bool &NeedsPadding) const; - bool shouldPrimitiveUseInReg(QualType Ty, CCState &State) const; - - bool canExpandIndirectArgument(QualType Ty) const; - - /// Rewrite the function info so that all memory arguments use - /// inalloca. - void rewriteWithInAlloca(CGFunctionInfo &FI) const; - - void addFieldToArgStruct(SmallVector<llvm::Type *, 6> &FrameFields, - CharUnits &StackOffset, ABIArgInfo &Info, - QualType Type) const; - void computeVectorCallArgs(CGFunctionInfo &FI, CCState &State, - bool &UsedInAlloca) const; - -public: - - void computeInfo(CGFunctionInfo &FI) const override; - Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const override; - - X86_32ABIInfo(CodeGen::CodeGenTypes &CGT, bool DarwinVectorABI, - bool RetSmallStructInRegABI, bool Win32StructABI, - unsigned NumRegisterParameters, bool SoftFloatABI) - : SwiftABIInfo(CGT), IsDarwinVectorABI(DarwinVectorABI), - IsRetSmallStructInRegABI(RetSmallStructInRegABI), - IsWin32StructABI(Win32StructABI), - IsSoftFloatABI(SoftFloatABI), - IsMCUABI(CGT.getTarget().getTriple().isOSIAMCU()), - DefaultNumRegisterParameters(NumRegisterParameters) {} - - bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> scalars, - bool asReturnValue) const override { - // LLVM's x86-32 lowering currently only assigns up to three - // integer registers and three fp registers. Oddly, it'll use up to - // four vector registers for vectors, but those can overlap with the - // scalar registers. - return occupiesMoreThan(CGT, scalars, /*total*/ 3); - } - - bool isSwiftErrorInRegister() const override { - // x86-32 lowering does not support passing swifterror in a register. - return false; - } -}; - -class X86_32TargetCodeGenInfo : public TargetCodeGenInfo { -public: - X86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool DarwinVectorABI, - bool RetSmallStructInRegABI, bool Win32StructABI, - unsigned NumRegisterParameters, bool SoftFloatABI) - : TargetCodeGenInfo(new X86_32ABIInfo( - CGT, DarwinVectorABI, RetSmallStructInRegABI, Win32StructABI, - NumRegisterParameters, SoftFloatABI)) {} - - static bool isStructReturnInRegABI( - const llvm::Triple &Triple, const CodeGenOptions &Opts); - - void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &CGM) const override; - - int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override { - // Darwin uses different dwarf register numbers for EH. - if (CGM.getTarget().getTriple().isOSDarwin()) return 5; - return 4; - } - - bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, - llvm::Value *Address) const override; - - llvm::Type* adjustInlineAsmType(CodeGen::CodeGenFunction &CGF, - StringRef Constraint, - llvm::Type* Ty) const override { - return X86AdjustInlineAsmType(CGF, Constraint, Ty); - } - - void addReturnRegisterOutputs(CodeGenFunction &CGF, LValue ReturnValue, - std::string &Constraints, - std::vector<llvm::Type *> &ResultRegTypes, - std::vector<llvm::Type *> &ResultTruncRegTypes, - std::vector<LValue> &ResultRegDests, - std::string &AsmString, - unsigned NumOutputs) const override; - - llvm::Constant * - getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const override { - unsigned Sig = (0xeb << 0) | // jmp rel8 - (0x06 << 8) | // .+0x08 - ('v' << 16) | - ('2' << 24); - return llvm::ConstantInt::get(CGM.Int32Ty, Sig); - } - - StringRef getARCRetainAutoreleasedReturnValueMarker() const override { - return "movl\t%ebp, %ebp" - "\t\t// marker for objc_retainAutoreleaseReturnValue"; - } -}; - -} - -/// Rewrite input constraint references after adding some output constraints. -/// In the case where there is one output and one input and we add one output, -/// we need to replace all operand references greater than or equal to 1: -/// mov $0, $1 -/// mov eax, $1 -/// The result will be: -/// mov $0, $2 -/// mov eax, $2 -static void rewriteInputConstraintReferences(unsigned FirstIn, - unsigned NumNewOuts, - std::string &AsmString) { - std::string Buf; - llvm::raw_string_ostream OS(Buf); - size_t Pos = 0; - while (Pos < AsmString.size()) { - size_t DollarStart = AsmString.find('$', Pos); - if (DollarStart == std::string::npos) - DollarStart = AsmString.size(); - size_t DollarEnd = AsmString.find_first_not_of('$', DollarStart); - if (DollarEnd == std::string::npos) - DollarEnd = AsmString.size(); - OS << StringRef(&AsmString[Pos], DollarEnd - Pos); - Pos = DollarEnd; - size_t NumDollars = DollarEnd - DollarStart; - if (NumDollars % 2 != 0 && Pos < AsmString.size()) { - // We have an operand reference. - size_t DigitStart = Pos; - size_t DigitEnd = AsmString.find_first_not_of("0123456789", DigitStart); - if (DigitEnd == std::string::npos) - DigitEnd = AsmString.size(); - StringRef OperandStr(&AsmString[DigitStart], DigitEnd - DigitStart); - unsigned OperandIndex; - if (!OperandStr.getAsInteger(10, OperandIndex)) { - if (OperandIndex >= FirstIn) - OperandIndex += NumNewOuts; - OS << OperandIndex; - } else { - OS << OperandStr; - } - Pos = DigitEnd; - } - } - AsmString = std::move(OS.str()); -} - -/// Add output constraints for EAX:EDX because they are return registers. -void X86_32TargetCodeGenInfo::addReturnRegisterOutputs( - CodeGenFunction &CGF, LValue ReturnSlot, std::string &Constraints, - std::vector<llvm::Type *> &ResultRegTypes, - std::vector<llvm::Type *> &ResultTruncRegTypes, - std::vector<LValue> &ResultRegDests, std::string &AsmString, - unsigned NumOutputs) const { - uint64_t RetWidth = CGF.getContext().getTypeSize(ReturnSlot.getType()); - - // Use the EAX constraint if the width is 32 or smaller and EAX:EDX if it is - // larger. - if (!Constraints.empty()) - Constraints += ','; - if (RetWidth <= 32) { - Constraints += "={eax}"; - ResultRegTypes.push_back(CGF.Int32Ty); - } else { - // Use the 'A' constraint for EAX:EDX. - Constraints += "=A"; - ResultRegTypes.push_back(CGF.Int64Ty); - } - - // Truncate EAX or EAX:EDX to an integer of the appropriate size. - llvm::Type *CoerceTy = llvm::IntegerType::get(CGF.getLLVMContext(), RetWidth); - ResultTruncRegTypes.push_back(CoerceTy); - - // Coerce the integer by bitcasting the return slot pointer. - ReturnSlot.setAddress(CGF.Builder.CreateBitCast(ReturnSlot.getAddress(), - CoerceTy->getPointerTo())); - ResultRegDests.push_back(ReturnSlot); - - rewriteInputConstraintReferences(NumOutputs, 1, AsmString); -} - -/// shouldReturnTypeInRegister - Determine if the given type should be -/// returned in a register (for the Darwin and MCU ABI). -bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty, - ASTContext &Context) const { - uint64_t Size = Context.getTypeSize(Ty); - - // For i386, type must be register sized. - // For the MCU ABI, it only needs to be <= 8-byte - if ((IsMCUABI && Size > 64) || (!IsMCUABI && !isRegisterSize(Size))) - return false; - - if (Ty->isVectorType()) { - // 64- and 128- bit vectors inside structures are not returned in - // registers. - if (Size == 64 || Size == 128) - return false; - - return true; - } - - // If this is a builtin, pointer, enum, complex type, member pointer, or - // member function pointer it is ok. - if (Ty->getAs<BuiltinType>() || Ty->hasPointerRepresentation() || - Ty->isAnyComplexType() || Ty->isEnumeralType() || - Ty->isBlockPointerType() || Ty->isMemberPointerType()) - return true; - - // Arrays are treated like records. - if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) - return shouldReturnTypeInRegister(AT->getElementType(), Context); - - // Otherwise, it must be a record type. - const RecordType *RT = Ty->getAs<RecordType>(); - if (!RT) return false; - - // FIXME: Traverse bases here too. - - // Structure types are passed in register if all fields would be - // passed in a register. - for (const auto *FD : RT->getDecl()->fields()) { - // Empty fields are ignored. - if (isEmptyField(Context, FD, true)) - continue; - - // Check fields recursively. - if (!shouldReturnTypeInRegister(FD->getType(), Context)) - return false; - } - return true; -} - -static bool is32Or64BitBasicType(QualType Ty, ASTContext &Context) { - // Treat complex types as the element type. - if (const ComplexType *CTy = Ty->getAs<ComplexType>()) - Ty = CTy->getElementType(); - - // Check for a type which we know has a simple scalar argument-passing - // convention without any padding. (We're specifically looking for 32 - // and 64-bit integer and integer-equivalents, float, and double.) - if (!Ty->getAs<BuiltinType>() && !Ty->hasPointerRepresentation() && - !Ty->isEnumeralType() && !Ty->isBlockPointerType()) - return false; - - uint64_t Size = Context.getTypeSize(Ty); - return Size == 32 || Size == 64; -} - -static bool addFieldSizes(ASTContext &Context, const RecordDecl *RD, - uint64_t &Size) { - for (const auto *FD : RD->fields()) { - // Scalar arguments on the stack get 4 byte alignment on x86. If the - // argument is smaller than 32-bits, expanding the struct will create - // alignment padding. - if (!is32Or64BitBasicType(FD->getType(), Context)) - return false; - - // FIXME: Reject bit-fields wholesale; there are two problems, we don't know - // how to expand them yet, and the predicate for telling if a bitfield still - // counts as "basic" is more complicated than what we were doing previously. - if (FD->isBitField()) - return false; - - Size += Context.getTypeSize(FD->getType()); - } - return true; -} - -static bool addBaseAndFieldSizes(ASTContext &Context, const CXXRecordDecl *RD, - uint64_t &Size) { - // Don't do this if there are any non-empty bases. - for (const CXXBaseSpecifier &Base : RD->bases()) { - if (!addBaseAndFieldSizes(Context, Base.getType()->getAsCXXRecordDecl(), - Size)) - return false; - } - if (!addFieldSizes(Context, RD, Size)) - return false; - return true; -} - -/// Test whether an argument type which is to be passed indirectly (on the -/// stack) would have the equivalent layout if it was expanded into separate -/// arguments. If so, we prefer to do the latter to avoid inhibiting -/// optimizations. -bool X86_32ABIInfo::canExpandIndirectArgument(QualType Ty) const { - // We can only expand structure types. - const RecordType *RT = Ty->getAs<RecordType>(); - if (!RT) - return false; - const RecordDecl *RD = RT->getDecl(); - uint64_t Size = 0; - if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) { - if (!IsWin32StructABI) { - // On non-Windows, we have to conservatively match our old bitcode - // prototypes in order to be ABI-compatible at the bitcode level. - if (!CXXRD->isCLike()) - return false; - } else { - // Don't do this for dynamic classes. - if (CXXRD->isDynamicClass()) - return false; - } - if (!addBaseAndFieldSizes(getContext(), CXXRD, Size)) - return false; - } else { - if (!addFieldSizes(getContext(), RD, Size)) - return false; - } - - // We can do this if there was no alignment padding. - return Size == getContext().getTypeSize(Ty); -} - -ABIArgInfo X86_32ABIInfo::getIndirectReturnResult(QualType RetTy, CCState &State) const { - // If the return value is indirect, then the hidden argument is consuming one - // integer register. - if (State.FreeRegs) { - --State.FreeRegs; - if (!IsMCUABI) - return getNaturalAlignIndirectInReg(RetTy); - } - return getNaturalAlignIndirect(RetTy, /*ByVal=*/false); -} - -ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, - CCState &State) const { - if (RetTy->isVoidType()) - return ABIArgInfo::getIgnore(); - - const Type *Base = nullptr; - uint64_t NumElts = 0; - if ((State.CC == llvm::CallingConv::X86_VectorCall || - State.CC == llvm::CallingConv::X86_RegCall) && - isHomogeneousAggregate(RetTy, Base, NumElts)) { - // The LLVM struct type for such an aggregate should lower properly. - return ABIArgInfo::getDirect(); - } - - if (const VectorType *VT = RetTy->getAs<VectorType>()) { - // On Darwin, some vectors are returned in registers. - if (IsDarwinVectorABI) { - uint64_t Size = getContext().getTypeSize(RetTy); - - // 128-bit vectors are a special case; they are returned in - // registers and we need to make sure to pick a type the LLVM - // backend will like. - if (Size == 128) - return ABIArgInfo::getDirect(llvm::VectorType::get( - llvm::Type::getInt64Ty(getVMContext()), 2)); - - // Always return in register if it fits in a general purpose - // register, or if it is 64 bits and has a single element. - if ((Size == 8 || Size == 16 || Size == 32) || - (Size == 64 && VT->getNumElements() == 1)) - return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), - Size)); - - return getIndirectReturnResult(RetTy, State); - } - - return ABIArgInfo::getDirect(); - } - - if (isAggregateTypeForABI(RetTy)) { - if (const RecordType *RT = RetTy->getAs<RecordType>()) { - // Structures with flexible arrays are always indirect. - if (RT->getDecl()->hasFlexibleArrayMember()) - return getIndirectReturnResult(RetTy, State); - } - - // If specified, structs and unions are always indirect. - if (!IsRetSmallStructInRegABI && !RetTy->isAnyComplexType()) - return getIndirectReturnResult(RetTy, State); - - // Ignore empty structs/unions. - if (isEmptyRecord(getContext(), RetTy, true)) - return ABIArgInfo::getIgnore(); - - // Small structures which are register sized are generally returned - // in a register. - if (shouldReturnTypeInRegister(RetTy, getContext())) { - uint64_t Size = getContext().getTypeSize(RetTy); - - // As a special-case, if the struct is a "single-element" struct, and - // the field is of type "float" or "double", return it in a - // floating-point register. (MSVC does not apply this special case.) - // We apply a similar transformation for pointer types to improve the - // quality of the generated IR. - if (const Type *SeltTy = isSingleElementStruct(RetTy, getContext())) - if ((!IsWin32StructABI && SeltTy->isRealFloatingType()) - || SeltTy->hasPointerRepresentation()) - return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); - - // FIXME: We should be able to narrow this integer in cases with dead - // padding. - return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),Size)); - } - - return getIndirectReturnResult(RetTy, State); - } - - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) - RetTy = EnumTy->getDecl()->getIntegerType(); - - return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy) - : ABIArgInfo::getDirect()); -} - -static bool isSSEVectorType(ASTContext &Context, QualType Ty) { - return Ty->getAs<VectorType>() && Context.getTypeSize(Ty) == 128; -} - -static bool isRecordWithSSEVectorType(ASTContext &Context, QualType Ty) { - const RecordType *RT = Ty->getAs<RecordType>(); - if (!RT) - return 0; - const RecordDecl *RD = RT->getDecl(); - - // If this is a C++ record, check the bases first. - if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) - for (const auto &I : CXXRD->bases()) - if (!isRecordWithSSEVectorType(Context, I.getType())) - return false; - - for (const auto *i : RD->fields()) { - QualType FT = i->getType(); - - if (isSSEVectorType(Context, FT)) - return true; - - if (isRecordWithSSEVectorType(Context, FT)) - return true; - } - - return false; -} - -unsigned X86_32ABIInfo::getTypeStackAlignInBytes(QualType Ty, - unsigned Align) const { - // Otherwise, if the alignment is less than or equal to the minimum ABI - // alignment, just use the default; the backend will handle this. - if (Align <= MinABIStackAlignInBytes) - return 0; // Use default alignment. - - // On non-Darwin, the stack type alignment is always 4. - if (!IsDarwinVectorABI) { - // Set explicit alignment, since we may need to realign the top. - return MinABIStackAlignInBytes; - } - - // Otherwise, if the type contains an SSE vector type, the alignment is 16. - if (Align >= 16 && (isSSEVectorType(getContext(), Ty) || - isRecordWithSSEVectorType(getContext(), Ty))) - return 16; - - return MinABIStackAlignInBytes; -} - -ABIArgInfo X86_32ABIInfo::getIndirectResult(QualType Ty, bool ByVal, - CCState &State) const { - if (!ByVal) { - if (State.FreeRegs) { - --State.FreeRegs; // Non-byval indirects just use one pointer. - if (!IsMCUABI) - return getNaturalAlignIndirectInReg(Ty); - } - return getNaturalAlignIndirect(Ty, false); - } - - // Compute the byval alignment. - unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8; - unsigned StackAlign = getTypeStackAlignInBytes(Ty, TypeAlign); - if (StackAlign == 0) - return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true); - - // If the stack alignment is less than the type alignment, realign the - // argument. - bool Realign = TypeAlign > StackAlign; - return ABIArgInfo::getIndirect(CharUnits::fromQuantity(StackAlign), - /*ByVal=*/true, Realign); -} - -X86_32ABIInfo::Class X86_32ABIInfo::classify(QualType Ty) const { - const Type *T = isSingleElementStruct(Ty, getContext()); - if (!T) - T = Ty.getTypePtr(); - - if (const BuiltinType *BT = T->getAs<BuiltinType>()) { - BuiltinType::Kind K = BT->getKind(); - if (K == BuiltinType::Float || K == BuiltinType::Double) - return Float; - } - return Integer; -} - -bool X86_32ABIInfo::updateFreeRegs(QualType Ty, CCState &State) const { - if (!IsSoftFloatABI) { - Class C = classify(Ty); - if (C == Float) - return false; - } - - unsigned Size = getContext().getTypeSize(Ty); - unsigned SizeInRegs = (Size + 31) / 32; - - if (SizeInRegs == 0) - return false; - - if (!IsMCUABI) { - if (SizeInRegs > State.FreeRegs) { - State.FreeRegs = 0; - return false; - } - } else { - // The MCU psABI allows passing parameters in-reg even if there are - // earlier parameters that are passed on the stack. Also, - // it does not allow passing >8-byte structs in-register, - // even if there are 3 free registers available. - if (SizeInRegs > State.FreeRegs || SizeInRegs > 2) - return false; - } - - State.FreeRegs -= SizeInRegs; - return true; -} - -bool X86_32ABIInfo::shouldAggregateUseDirect(QualType Ty, CCState &State, - bool &InReg, - bool &NeedsPadding) const { - // On Windows, aggregates other than HFAs are never passed in registers, and - // they do not consume register slots. Homogenous floating-point aggregates - // (HFAs) have already been dealt with at this point. - if (IsWin32StructABI && isAggregateTypeForABI(Ty)) - return false; - - NeedsPadding = false; - InReg = !IsMCUABI; - - if (!updateFreeRegs(Ty, State)) - return false; - - if (IsMCUABI) - return true; - - if (State.CC == llvm::CallingConv::X86_FastCall || - State.CC == llvm::CallingConv::X86_VectorCall || - State.CC == llvm::CallingConv::X86_RegCall) { - if (getContext().getTypeSize(Ty) <= 32 && State.FreeRegs) - NeedsPadding = true; - - return false; - } - - return true; -} - -bool X86_32ABIInfo::shouldPrimitiveUseInReg(QualType Ty, CCState &State) const { - if (!updateFreeRegs(Ty, State)) - return false; - - if (IsMCUABI) - return false; - - if (State.CC == llvm::CallingConv::X86_FastCall || - State.CC == llvm::CallingConv::X86_VectorCall || - State.CC == llvm::CallingConv::X86_RegCall) { - if (getContext().getTypeSize(Ty) > 32) - return false; - - return (Ty->isIntegralOrEnumerationType() || Ty->isPointerType() || - Ty->isReferenceType()); - } - - return true; -} - -ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, - CCState &State) const { - // FIXME: Set alignment on indirect arguments. - - Ty = useFirstFieldIfTransparentUnion(Ty); - - // Check with the C++ ABI first. - const RecordType *RT = Ty->getAs<RecordType>(); - if (RT) { - CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI()); - if (RAA == CGCXXABI::RAA_Indirect) { - return getIndirectResult(Ty, false, State); - } else if (RAA == CGCXXABI::RAA_DirectInMemory) { - // The field index doesn't matter, we'll fix it up later. - return ABIArgInfo::getInAlloca(/*FieldIndex=*/0); - } - } - - // Regcall uses the concept of a homogenous vector aggregate, similar - // to other targets. - const Type *Base = nullptr; - uint64_t NumElts = 0; - if (State.CC == llvm::CallingConv::X86_RegCall && - isHomogeneousAggregate(Ty, Base, NumElts)) { - - if (State.FreeSSERegs >= NumElts) { - State.FreeSSERegs -= NumElts; - if (Ty->isBuiltinType() || Ty->isVectorType()) - return ABIArgInfo::getDirect(); - return ABIArgInfo::getExpand(); - } - return getIndirectResult(Ty, /*ByVal=*/false, State); - } - - if (isAggregateTypeForABI(Ty)) { - // Structures with flexible arrays are always indirect. - // FIXME: This should not be byval! - if (RT && RT->getDecl()->hasFlexibleArrayMember()) - return getIndirectResult(Ty, true, State); - - // Ignore empty structs/unions on non-Windows. - if (!IsWin32StructABI && isEmptyRecord(getContext(), Ty, true)) - return ABIArgInfo::getIgnore(); - - llvm::LLVMContext &LLVMContext = getVMContext(); - llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext); - bool NeedsPadding = false; - bool InReg; - if (shouldAggregateUseDirect(Ty, State, InReg, NeedsPadding)) { - unsigned SizeInRegs = (getContext().getTypeSize(Ty) + 31) / 32; - SmallVector<llvm::Type*, 3> Elements(SizeInRegs, Int32); - llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements); - if (InReg) - return ABIArgInfo::getDirectInReg(Result); - else - return ABIArgInfo::getDirect(Result); - } - llvm::IntegerType *PaddingType = NeedsPadding ? Int32 : nullptr; - - // Expand small (<= 128-bit) record types when we know that the stack layout - // of those arguments will match the struct. This is important because the - // LLVM backend isn't smart enough to remove byval, which inhibits many - // optimizations. - // Don't do this for the MCU if there are still free integer registers - // (see X86_64 ABI for full explanation). - if (getContext().getTypeSize(Ty) <= 4 * 32 && - (!IsMCUABI || State.FreeRegs == 0) && canExpandIndirectArgument(Ty)) - return ABIArgInfo::getExpandWithPadding( - State.CC == llvm::CallingConv::X86_FastCall || - State.CC == llvm::CallingConv::X86_VectorCall || - State.CC == llvm::CallingConv::X86_RegCall, - PaddingType); - - return getIndirectResult(Ty, true, State); - } - - if (const VectorType *VT = Ty->getAs<VectorType>()) { - // On Darwin, some vectors are passed in memory, we handle this by passing - // it as an i8/i16/i32/i64. - if (IsDarwinVectorABI) { - uint64_t Size = getContext().getTypeSize(Ty); - if ((Size == 8 || Size == 16 || Size == 32) || - (Size == 64 && VT->getNumElements() == 1)) - return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), - Size)); - } - - if (IsX86_MMXType(CGT.ConvertType(Ty))) - return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), 64)); - - return ABIArgInfo::getDirect(); - } - - - if (const EnumType *EnumTy = Ty->getAs<EnumType>()) - Ty = EnumTy->getDecl()->getIntegerType(); - - bool InReg = shouldPrimitiveUseInReg(Ty, State); - - if (Ty->isPromotableIntegerType()) { - if (InReg) - return ABIArgInfo::getExtendInReg(Ty); - return ABIArgInfo::getExtend(Ty); - } - - if (InReg) - return ABIArgInfo::getDirectInReg(); - return ABIArgInfo::getDirect(); -} - -void X86_32ABIInfo::computeVectorCallArgs(CGFunctionInfo &FI, CCState &State, - bool &UsedInAlloca) const { - // Vectorcall x86 works subtly different than in x64, so the format is - // a bit different than the x64 version. First, all vector types (not HVAs) - // are assigned, with the first 6 ending up in the YMM0-5 or XMM0-5 registers. - // This differs from the x64 implementation, where the first 6 by INDEX get - // registers. - // After that, integers AND HVAs are assigned Left to Right in the same pass. - // Integers are passed as ECX/EDX if one is available (in order). HVAs will - // first take up the remaining YMM/XMM registers. If insufficient registers - // remain but an integer register (ECX/EDX) is available, it will be passed - // in that, else, on the stack. - for (auto &I : FI.arguments()) { - // First pass do all the vector types. - const Type *Base = nullptr; - uint64_t NumElts = 0; - const QualType& Ty = I.type; - if ((Ty->isVectorType() || Ty->isBuiltinType()) && - isHomogeneousAggregate(Ty, Base, NumElts)) { - if (State.FreeSSERegs >= NumElts) { - State.FreeSSERegs -= NumElts; - I.info = ABIArgInfo::getDirect(); - } else { - I.info = classifyArgumentType(Ty, State); - } - UsedInAlloca |= (I.info.getKind() == ABIArgInfo::InAlloca); - } - } - - for (auto &I : FI.arguments()) { - // Second pass, do the rest! - const Type *Base = nullptr; - uint64_t NumElts = 0; - const QualType& Ty = I.type; - bool IsHva = isHomogeneousAggregate(Ty, Base, NumElts); - - if (IsHva && !Ty->isVectorType() && !Ty->isBuiltinType()) { - // Assign true HVAs (non vector/native FP types). - if (State.FreeSSERegs >= NumElts) { - State.FreeSSERegs -= NumElts; - I.info = getDirectX86Hva(); - } else { - I.info = getIndirectResult(Ty, /*ByVal=*/false, State); - } - } else if (!IsHva) { - // Assign all Non-HVAs, so this will exclude Vector/FP args. - I.info = classifyArgumentType(Ty, State); - UsedInAlloca |= (I.info.getKind() == ABIArgInfo::InAlloca); - } - } -} - -void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI) const { - CCState State(FI.getCallingConvention()); - if (IsMCUABI) - State.FreeRegs = 3; - else if (State.CC == llvm::CallingConv::X86_FastCall) - State.FreeRegs = 2; - else if (State.CC == llvm::CallingConv::X86_VectorCall) { - State.FreeRegs = 2; - State.FreeSSERegs = 6; - } else if (FI.getHasRegParm()) - State.FreeRegs = FI.getRegParm(); - else if (State.CC == llvm::CallingConv::X86_RegCall) { - State.FreeRegs = 5; - State.FreeSSERegs = 8; - } else - State.FreeRegs = DefaultNumRegisterParameters; - - if (!::classifyReturnType(getCXXABI(), FI, *this)) { - FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), State); - } else if (FI.getReturnInfo().isIndirect()) { - // The C++ ABI is not aware of register usage, so we have to check if the - // return value was sret and put it in a register ourselves if appropriate. - if (State.FreeRegs) { - --State.FreeRegs; // The sret parameter consumes a register. - if (!IsMCUABI) - FI.getReturnInfo().setInReg(true); - } - } - - // The chain argument effectively gives us another free register. - if (FI.isChainCall()) - ++State.FreeRegs; - - bool UsedInAlloca = false; - if (State.CC == llvm::CallingConv::X86_VectorCall) { - computeVectorCallArgs(FI, State, UsedInAlloca); - } else { - // If not vectorcall, revert to normal behavior. - for (auto &I : FI.arguments()) { - I.info = classifyArgumentType(I.type, State); - UsedInAlloca |= (I.info.getKind() == ABIArgInfo::InAlloca); - } - } - - // If we needed to use inalloca for any argument, do a second pass and rewrite - // all the memory arguments to use inalloca. - if (UsedInAlloca) - rewriteWithInAlloca(FI); -} - -void -X86_32ABIInfo::addFieldToArgStruct(SmallVector<llvm::Type *, 6> &FrameFields, - CharUnits &StackOffset, ABIArgInfo &Info, - QualType Type) const { - // Arguments are always 4-byte-aligned. - CharUnits FieldAlign = CharUnits::fromQuantity(4); - - assert(StackOffset.isMultipleOf(FieldAlign) && "unaligned inalloca struct"); - Info = ABIArgInfo::getInAlloca(FrameFields.size()); - FrameFields.push_back(CGT.ConvertTypeForMem(Type)); - StackOffset += getContext().getTypeSizeInChars(Type); - - // Insert padding bytes to respect alignment. - CharUnits FieldEnd = StackOffset; - StackOffset = FieldEnd.alignTo(FieldAlign); - if (StackOffset != FieldEnd) { - CharUnits NumBytes = StackOffset - FieldEnd; - llvm::Type *Ty = llvm::Type::getInt8Ty(getVMContext()); - Ty = llvm::ArrayType::get(Ty, NumBytes.getQuantity()); - FrameFields.push_back(Ty); - } -} - -static bool isArgInAlloca(const ABIArgInfo &Info) { - // Leave ignored and inreg arguments alone. - switch (Info.getKind()) { - case ABIArgInfo::InAlloca: - return true; - case ABIArgInfo::Indirect: - assert(Info.getIndirectByVal()); - return true; - case ABIArgInfo::Ignore: - return false; - case ABIArgInfo::Direct: - case ABIArgInfo::Extend: - if (Info.getInReg()) - return false; - return true; - case ABIArgInfo::Expand: - case ABIArgInfo::CoerceAndExpand: - // These are aggregate types which are never passed in registers when - // inalloca is involved. - return true; - } - llvm_unreachable("invalid enum"); -} - -void X86_32ABIInfo::rewriteWithInAlloca(CGFunctionInfo &FI) const { - assert(IsWin32StructABI && "inalloca only supported on win32"); - - // Build a packed struct type for all of the arguments in memory. - SmallVector<llvm::Type *, 6> FrameFields; - - // The stack alignment is always 4. - CharUnits StackAlign = CharUnits::fromQuantity(4); - - CharUnits StackOffset; - CGFunctionInfo::arg_iterator I = FI.arg_begin(), E = FI.arg_end(); - - // Put 'this' into the struct before 'sret', if necessary. - bool IsThisCall = - FI.getCallingConvention() == llvm::CallingConv::X86_ThisCall; - ABIArgInfo &Ret = FI.getReturnInfo(); - if (Ret.isIndirect() && Ret.isSRetAfterThis() && !IsThisCall && - isArgInAlloca(I->info)) { - addFieldToArgStruct(FrameFields, StackOffset, I->info, I->type); - ++I; - } - - // Put the sret parameter into the inalloca struct if it's in memory. - if (Ret.isIndirect() && !Ret.getInReg()) { - CanQualType PtrTy = getContext().getPointerType(FI.getReturnType()); - addFieldToArgStruct(FrameFields, StackOffset, Ret, PtrTy); - // On Windows, the hidden sret parameter is always returned in eax. - Ret.setInAllocaSRet(IsWin32StructABI); - } - - // Skip the 'this' parameter in ecx. - if (IsThisCall) - ++I; - - // Put arguments passed in memory into the struct. - for (; I != E; ++I) { - if (isArgInAlloca(I->info)) - addFieldToArgStruct(FrameFields, StackOffset, I->info, I->type); - } - - FI.setArgStruct(llvm::StructType::get(getVMContext(), FrameFields, - /*isPacked=*/true), - StackAlign); -} - -Address X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF, - Address VAListAddr, QualType Ty) const { - - auto TypeInfo = getContext().getTypeInfoInChars(Ty); - - // x86-32 changes the alignment of certain arguments on the stack. - // - // Just messing with TypeInfo like this works because we never pass - // anything indirectly. - TypeInfo.second = CharUnits::fromQuantity( - getTypeStackAlignInBytes(Ty, TypeInfo.second.getQuantity())); - - return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*Indirect*/ false, - TypeInfo, CharUnits::fromQuantity(4), - /*AllowHigherAlign*/ true); -} - -bool X86_32TargetCodeGenInfo::isStructReturnInRegABI( - const llvm::Triple &Triple, const CodeGenOptions &Opts) { - assert(Triple.getArch() == llvm::Triple::x86); - - switch (Opts.getStructReturnConvention()) { - case CodeGenOptions::SRCK_Default: - break; - case CodeGenOptions::SRCK_OnStack: // -fpcc-struct-return - return false; - case CodeGenOptions::SRCK_InRegs: // -freg-struct-return - return true; - } - - if (Triple.isOSDarwin() || Triple.isOSIAMCU()) - return true; - - switch (Triple.getOS()) { - case llvm::Triple::DragonFly: - case llvm::Triple::FreeBSD: - case llvm::Triple::OpenBSD: - case llvm::Triple::Win32: - return true; - default: - return false; - } -} - -void X86_32TargetCodeGenInfo::setTargetAttributes( - const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const { - if (GV->isDeclaration()) - return; - if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) { - if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) { - llvm::Function *Fn = cast<llvm::Function>(GV); - Fn->addFnAttr("stackrealign"); - } - if (FD->hasAttr<AnyX86InterruptAttr>()) { - llvm::Function *Fn = cast<llvm::Function>(GV); - Fn->setCallingConv(llvm::CallingConv::X86_INTR); - } - } -} - -bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable( - CodeGen::CodeGenFunction &CGF, - llvm::Value *Address) const { - CodeGen::CGBuilderTy &Builder = CGF.Builder; - - llvm::Value *Four8 = llvm::ConstantInt::get(CGF.Int8Ty, 4); - - // 0-7 are the eight integer registers; the order is different - // on Darwin (for EH), but the range is the same. - // 8 is %eip. - AssignToArrayRange(Builder, Address, Four8, 0, 8); - - if (CGF.CGM.getTarget().getTriple().isOSDarwin()) { - // 12-16 are st(0..4). Not sure why we stop at 4. - // These have size 16, which is sizeof(long double) on - // platforms with 8-byte alignment for that type. - llvm::Value *Sixteen8 = llvm::ConstantInt::get(CGF.Int8Ty, 16); - AssignToArrayRange(Builder, Address, Sixteen8, 12, 16); - - } else { - // 9 is %eflags, which doesn't get a size on Darwin for some - // reason. - Builder.CreateAlignedStore( - Four8, Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, Address, 9), - CharUnits::One()); - - // 11-16 are st(0..5). Not sure why we stop at 5. - // These have size 12, which is sizeof(long double) on - // platforms with 4-byte alignment for that type. - llvm::Value *Twelve8 = llvm::ConstantInt::get(CGF.Int8Ty, 12); - AssignToArrayRange(Builder, Address, Twelve8, 11, 16); - } - - return false; -} - -//===----------------------------------------------------------------------===// -// X86-64 ABI Implementation -//===----------------------------------------------------------------------===// - - -namespace { -/// The AVX ABI level for X86 targets. -enum class X86AVXABILevel { - None, - AVX, - AVX512 -}; - -/// \p returns the size in bits of the largest (native) vector for \p AVXLevel. -static unsigned getNativeVectorSizeForAVXABI(X86AVXABILevel AVXLevel) { - switch (AVXLevel) { - case X86AVXABILevel::AVX512: - return 512; - case X86AVXABILevel::AVX: - return 256; - case X86AVXABILevel::None: - return 128; - } - llvm_unreachable("Unknown AVXLevel"); -} - -/// X86_64ABIInfo - The X86_64 ABI information. -class X86_64ABIInfo : public SwiftABIInfo { - enum Class { - Integer = 0, - SSE, - SSEUp, - X87, - X87Up, - ComplexX87, - NoClass, - Memory - }; - - /// merge - Implement the X86_64 ABI merging algorithm. - /// - /// Merge an accumulating classification \arg Accum with a field - /// classification \arg Field. - /// - /// \param Accum - The accumulating classification. This should - /// always be either NoClass or the result of a previous merge - /// call. In addition, this should never be Memory (the caller - /// should just return Memory for the aggregate). - static Class merge(Class Accum, Class Field); - - /// postMerge - Implement the X86_64 ABI post merging algorithm. - /// - /// Post merger cleanup, reduces a malformed Hi and Lo pair to - /// final MEMORY or SSE classes when necessary. - /// - /// \param AggregateSize - The size of the current aggregate in - /// the classification process. - /// - /// \param Lo - The classification for the parts of the type - /// residing in the low word of the containing object. - /// - /// \param Hi - The classification for the parts of the type - /// residing in the higher words of the containing object. - /// - void postMerge(unsigned AggregateSize, Class &Lo, Class &Hi) const; - - /// classify - Determine the x86_64 register classes in which the - /// given type T should be passed. - /// - /// \param Lo - The classification for the parts of the type - /// residing in the low word of the containing object. - /// - /// \param Hi - The classification for the parts of the type - /// residing in the high word of the containing object. - /// - /// \param OffsetBase - The bit offset of this type in the - /// containing object. Some parameters are classified different - /// depending on whether they straddle an eightbyte boundary. - /// - /// \param isNamedArg - Whether the argument in question is a "named" - /// argument, as used in AMD64-ABI 3.5.7. - /// - /// If a word is unused its result will be NoClass; if a type should - /// be passed in Memory then at least the classification of \arg Lo - /// will be Memory. - /// - /// The \arg Lo class will be NoClass iff the argument is ignored. - /// - /// If the \arg Lo class is ComplexX87, then the \arg Hi class will - /// also be ComplexX87. - void classify(QualType T, uint64_t OffsetBase, Class &Lo, Class &Hi, - bool isNamedArg) const; - - llvm::Type *GetByteVectorType(QualType Ty) const; - llvm::Type *GetSSETypeAtOffset(llvm::Type *IRType, - unsigned IROffset, QualType SourceTy, - unsigned SourceOffset) const; - llvm::Type *GetINTEGERTypeAtOffset(llvm::Type *IRType, - unsigned IROffset, QualType SourceTy, - unsigned SourceOffset) const; - - /// getIndirectResult - Give a source type \arg Ty, return a suitable result - /// such that the argument will be returned in memory. - ABIArgInfo getIndirectReturnResult(QualType Ty) const; - - /// getIndirectResult - Give a source type \arg Ty, return a suitable result - /// such that the argument will be passed in memory. - /// - /// \param freeIntRegs - The number of free integer registers remaining - /// available. - ABIArgInfo getIndirectResult(QualType Ty, unsigned freeIntRegs) const; - - ABIArgInfo classifyReturnType(QualType RetTy) const; - - ABIArgInfo classifyArgumentType(QualType Ty, unsigned freeIntRegs, - unsigned &neededInt, unsigned &neededSSE, - bool isNamedArg) const; - - ABIArgInfo classifyRegCallStructType(QualType Ty, unsigned &NeededInt, - unsigned &NeededSSE) const; - - ABIArgInfo classifyRegCallStructTypeImpl(QualType Ty, unsigned &NeededInt, - unsigned &NeededSSE) const; - - bool IsIllegalVectorType(QualType Ty) const; - - /// The 0.98 ABI revision clarified a lot of ambiguities, - /// unfortunately in ways that were not always consistent with - /// certain previous compilers. In particular, platforms which - /// required strict binary compatibility with older versions of GCC - /// may need to exempt themselves. - bool honorsRevision0_98() const { - return !getTarget().getTriple().isOSDarwin(); - } - - /// GCC classifies <1 x long long> as SSE but some platform ABIs choose to - /// classify it as INTEGER (for compatibility with older clang compilers). - bool classifyIntegerMMXAsSSE() const { - // Clang <= 3.8 did not do this. - if (getContext().getLangOpts().getClangABICompat() <= - LangOptions::ClangABI::Ver3_8) - return false; - - const llvm::Triple &Triple = getTarget().getTriple(); - if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::PS4) - return false; - if (Triple.isOSFreeBSD() && Triple.getOSMajorVersion() >= 10) - return false; - return true; - } - - X86AVXABILevel AVXLevel; - // Some ABIs (e.g. X32 ABI and Native Client OS) use 32 bit pointers on - // 64-bit hardware. - bool Has64BitPointers; - -public: - X86_64ABIInfo(CodeGen::CodeGenTypes &CGT, X86AVXABILevel AVXLevel) : - SwiftABIInfo(CGT), AVXLevel(AVXLevel), - Has64BitPointers(CGT.getDataLayout().getPointerSize(0) == 8) { - } - - bool isPassedUsingAVXType(QualType type) const { - unsigned neededInt, neededSSE; - // The freeIntRegs argument doesn't matter here. - ABIArgInfo info = classifyArgumentType(type, 0, neededInt, neededSSE, - /*isNamedArg*/true); - if (info.isDirect()) { - llvm::Type *ty = info.getCoerceToType(); - if (llvm::VectorType *vectorTy = dyn_cast_or_null<llvm::VectorType>(ty)) - return (vectorTy->getBitWidth() > 128); - } - return false; - } - - void computeInfo(CGFunctionInfo &FI) const override; - - Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const override; - Address EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const override; - - bool has64BitPointers() const { - return Has64BitPointers; - } - - bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> scalars, - bool asReturnValue) const override { - return occupiesMoreThan(CGT, scalars, /*total*/ 4); - } - bool isSwiftErrorInRegister() const override { - return true; - } -}; - -/// WinX86_64ABIInfo - The Windows X86_64 ABI information. -class WinX86_64ABIInfo : public SwiftABIInfo { -public: - WinX86_64ABIInfo(CodeGen::CodeGenTypes &CGT) - : SwiftABIInfo(CGT), - IsMingw64(getTarget().getTriple().isWindowsGNUEnvironment()) {} - - void computeInfo(CGFunctionInfo &FI) const override; - - Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const override; - - bool isHomogeneousAggregateBaseType(QualType Ty) const override { - // FIXME: Assumes vectorcall is in use. - return isX86VectorTypeForVectorCall(getContext(), Ty); - } - - bool isHomogeneousAggregateSmallEnough(const Type *Ty, - uint64_t NumMembers) const override { - // FIXME: Assumes vectorcall is in use. - return isX86VectorCallAggregateSmallEnough(NumMembers); - } - - bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type *> scalars, - bool asReturnValue) const override { - return occupiesMoreThan(CGT, scalars, /*total*/ 4); - } - - bool isSwiftErrorInRegister() const override { - return true; - } - -private: - ABIArgInfo classify(QualType Ty, unsigned &FreeSSERegs, bool IsReturnType, - bool IsVectorCall, bool IsRegCall) const; - ABIArgInfo reclassifyHvaArgType(QualType Ty, unsigned &FreeSSERegs, - const ABIArgInfo ¤t) const; - void computeVectorCallArgs(CGFunctionInfo &FI, unsigned FreeSSERegs, - bool IsVectorCall, bool IsRegCall) const; - - bool IsMingw64; -}; - -class X86_64TargetCodeGenInfo : public TargetCodeGenInfo { -public: - X86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, X86AVXABILevel AVXLevel) - : TargetCodeGenInfo(new X86_64ABIInfo(CGT, AVXLevel)) {} - - const X86_64ABIInfo &getABIInfo() const { - return static_cast<const X86_64ABIInfo&>(TargetCodeGenInfo::getABIInfo()); - } - - int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override { - return 7; - } - - bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, - llvm::Value *Address) const override { - llvm::Value *Eight8 = llvm::ConstantInt::get(CGF.Int8Ty, 8); - - // 0-15 are the 16 integer registers. - // 16 is %rip. - AssignToArrayRange(CGF.Builder, Address, Eight8, 0, 16); - return false; - } - - llvm::Type* adjustInlineAsmType(CodeGen::CodeGenFunction &CGF, - StringRef Constraint, - llvm::Type* Ty) const override { - return X86AdjustInlineAsmType(CGF, Constraint, Ty); - } - - bool isNoProtoCallVariadic(const CallArgList &args, - const FunctionNoProtoType *fnType) const override { - // The default CC on x86-64 sets %al to the number of SSA - // registers used, and GCC sets this when calling an unprototyped - // function, so we override the default behavior. However, don't do - // that when AVX types are involved: the ABI explicitly states it is - // undefined, and it doesn't work in practice because of how the ABI - // defines varargs anyway. - if (fnType->getCallConv() == CC_C) { - bool HasAVXType = false; - for (CallArgList::const_iterator - it = args.begin(), ie = args.end(); it != ie; ++it) { - if (getABIInfo().isPassedUsingAVXType(it->Ty)) { - HasAVXType = true; - break; - } - } - - if (!HasAVXType) - return true; - } - - return TargetCodeGenInfo::isNoProtoCallVariadic(args, fnType); - } - - llvm::Constant * - getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const override { - unsigned Sig = (0xeb << 0) | // jmp rel8 - (0x06 << 8) | // .+0x08 - ('v' << 16) | - ('2' << 24); - return llvm::ConstantInt::get(CGM.Int32Ty, Sig); - } - - void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &CGM) const override { - if (GV->isDeclaration()) - return; - if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) { - if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) { - llvm::Function *Fn = cast<llvm::Function>(GV); - Fn->addFnAttr("stackrealign"); - } - if (FD->hasAttr<AnyX86InterruptAttr>()) { - llvm::Function *Fn = cast<llvm::Function>(GV); - Fn->setCallingConv(llvm::CallingConv::X86_INTR); - } - } - } -}; - -class PS4TargetCodeGenInfo : public X86_64TargetCodeGenInfo { -public: - PS4TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, X86AVXABILevel AVXLevel) - : X86_64TargetCodeGenInfo(CGT, AVXLevel) {} - - void getDependentLibraryOption(llvm::StringRef Lib, - llvm::SmallString<24> &Opt) const override { - Opt = "\01"; - // If the argument contains a space, enclose it in quotes. - if (Lib.find(" ") != StringRef::npos) - Opt += "\"" + Lib.str() + "\""; - else - Opt += Lib; - } -}; - -static std::string qualifyWindowsLibrary(llvm::StringRef Lib) { - // If the argument does not end in .lib, automatically add the suffix. - // If the argument contains a space, enclose it in quotes. - // This matches the behavior of MSVC. - bool Quote = (Lib.find(" ") != StringRef::npos); - std::string ArgStr = Quote ? "\"" : ""; - ArgStr += Lib; - if (!Lib.endswith_lower(".lib") && !Lib.endswith_lower(".a")) - ArgStr += ".lib"; - ArgStr += Quote ? "\"" : ""; - return ArgStr; -} - -class WinX86_32TargetCodeGenInfo : public X86_32TargetCodeGenInfo { -public: - WinX86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, - bool DarwinVectorABI, bool RetSmallStructInRegABI, bool Win32StructABI, - unsigned NumRegisterParameters) - : X86_32TargetCodeGenInfo(CGT, DarwinVectorABI, RetSmallStructInRegABI, - Win32StructABI, NumRegisterParameters, false) {} - - void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &CGM) const override; - - void getDependentLibraryOption(llvm::StringRef Lib, - llvm::SmallString<24> &Opt) const override { - Opt = "/DEFAULTLIB:"; - Opt += qualifyWindowsLibrary(Lib); - } - - void getDetectMismatchOption(llvm::StringRef Name, - llvm::StringRef Value, - llvm::SmallString<32> &Opt) const override { - Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\""; - } -}; - -static void addStackProbeTargetAttributes(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &CGM) { - if (llvm::Function *Fn = dyn_cast_or_null<llvm::Function>(GV)) { - - if (CGM.getCodeGenOpts().StackProbeSize != 4096) - Fn->addFnAttr("stack-probe-size", - llvm::utostr(CGM.getCodeGenOpts().StackProbeSize)); - if (CGM.getCodeGenOpts().NoStackArgProbe) - Fn->addFnAttr("no-stack-arg-probe"); - } -} - -void WinX86_32TargetCodeGenInfo::setTargetAttributes( - const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const { - X86_32TargetCodeGenInfo::setTargetAttributes(D, GV, CGM); - if (GV->isDeclaration()) - return; - addStackProbeTargetAttributes(D, GV, CGM); -} - -class WinX86_64TargetCodeGenInfo : public TargetCodeGenInfo { -public: - WinX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, - X86AVXABILevel AVXLevel) - : TargetCodeGenInfo(new WinX86_64ABIInfo(CGT)) {} - - void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &CGM) const override; - - int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override { - return 7; - } - - bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, - llvm::Value *Address) const override { - llvm::Value *Eight8 = llvm::ConstantInt::get(CGF.Int8Ty, 8); - - // 0-15 are the 16 integer registers. - // 16 is %rip. - AssignToArrayRange(CGF.Builder, Address, Eight8, 0, 16); - return false; - } - - void getDependentLibraryOption(llvm::StringRef Lib, - llvm::SmallString<24> &Opt) const override { - Opt = "/DEFAULTLIB:"; - Opt += qualifyWindowsLibrary(Lib); - } - - void getDetectMismatchOption(llvm::StringRef Name, - llvm::StringRef Value, - llvm::SmallString<32> &Opt) const override { - Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\""; - } -}; - -void WinX86_64TargetCodeGenInfo::setTargetAttributes( - const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const { - TargetCodeGenInfo::setTargetAttributes(D, GV, CGM); - if (GV->isDeclaration()) - return; - if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) { - if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) { - llvm::Function *Fn = cast<llvm::Function>(GV); - Fn->addFnAttr("stackrealign"); - } - if (FD->hasAttr<AnyX86InterruptAttr>()) { - llvm::Function *Fn = cast<llvm::Function>(GV); - Fn->setCallingConv(llvm::CallingConv::X86_INTR); - } - } - - addStackProbeTargetAttributes(D, GV, CGM); -} -} - -void X86_64ABIInfo::postMerge(unsigned AggregateSize, Class &Lo, - Class &Hi) const { - // AMD64-ABI 3.2.3p2: Rule 5. Then a post merger cleanup is done: - // - // (a) If one of the classes is Memory, the whole argument is passed in - // memory. - // - // (b) If X87UP is not preceded by X87, the whole argument is passed in - // memory. - // - // (c) If the size of the aggregate exceeds two eightbytes and the first - // eightbyte isn't SSE or any other eightbyte isn't SSEUP, the whole - // argument is passed in memory. NOTE: This is necessary to keep the - // ABI working for processors that don't support the __m256 type. - // - // (d) If SSEUP is not preceded by SSE or SSEUP, it is converted to SSE. - // - // Some of these are enforced by the merging logic. Others can arise - // only with unions; for example: - // union { _Complex double; unsigned; } - // - // Note that clauses (b) and (c) were added in 0.98. - // - if (Hi == Memory) - Lo = Memory; - if (Hi == X87Up && Lo != X87 && honorsRevision0_98()) - Lo = Memory; - if (AggregateSize > 128 && (Lo != SSE || Hi != SSEUp)) - Lo = Memory; - if (Hi == SSEUp && Lo != SSE) - Hi = SSE; -} - -X86_64ABIInfo::Class X86_64ABIInfo::merge(Class Accum, Class Field) { - // AMD64-ABI 3.2.3p2: Rule 4. Each field of an object is - // classified recursively so that always two fields are - // considered. The resulting class is calculated according to - // the classes of the fields in the eightbyte: - // - // (a) If both classes are equal, this is the resulting class. - // - // (b) If one of the classes is NO_CLASS, the resulting class is - // the other class. - // - // (c) If one of the classes is MEMORY, the result is the MEMORY - // class. - // - // (d) If one of the classes is INTEGER, the result is the - // INTEGER. - // - // (e) If one of the classes is X87, X87UP, COMPLEX_X87 class, - // MEMORY is used as class. - // - // (f) Otherwise class SSE is used. - - // Accum should never be memory (we should have returned) or - // ComplexX87 (because this cannot be passed in a structure). - assert((Accum != Memory && Accum != ComplexX87) && - "Invalid accumulated classification during merge."); - if (Accum == Field || Field == NoClass) - return Accum; - if (Field == Memory) - return Memory; - if (Accum == NoClass) - return Field; - if (Accum == Integer || Field == Integer) - return Integer; - if (Field == X87 || Field == X87Up || Field == ComplexX87 || - Accum == X87 || Accum == X87Up) - return Memory; - return SSE; -} - -void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, - Class &Lo, Class &Hi, bool isNamedArg) const { - // FIXME: This code can be simplified by introducing a simple value class for - // Class pairs with appropriate constructor methods for the various - // situations. - - // FIXME: Some of the split computations are wrong; unaligned vectors - // shouldn't be passed in registers for example, so there is no chance they - // can straddle an eightbyte. Verify & simplify. - - Lo = Hi = NoClass; - - Class &Current = OffsetBase < 64 ? Lo : Hi; - Current = Memory; - - if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) { - BuiltinType::Kind k = BT->getKind(); - - if (k == BuiltinType::Void) { - Current = NoClass; - } else if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) { - Lo = Integer; - Hi = Integer; - } else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) { - Current = Integer; - } else if (k == BuiltinType::Float || k == BuiltinType::Double) { - Current = SSE; - } else if (k == BuiltinType::LongDouble) { - const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat(); - if (LDF == &llvm::APFloat::IEEEquad()) { - Lo = SSE; - Hi = SSEUp; - } else if (LDF == &llvm::APFloat::x87DoubleExtended()) { - Lo = X87; - Hi = X87Up; - } else if (LDF == &llvm::APFloat::IEEEdouble()) { - Current = SSE; - } else - llvm_unreachable("unexpected long double representation!"); - } - // FIXME: _Decimal32 and _Decimal64 are SSE. - // FIXME: _float128 and _Decimal128 are (SSE, SSEUp). - return; - } - - if (const EnumType *ET = Ty->getAs<EnumType>()) { - // Classify the underlying integer type. - classify(ET->getDecl()->getIntegerType(), OffsetBase, Lo, Hi, isNamedArg); - return; - } - - if (Ty->hasPointerRepresentation()) { - Current = Integer; - return; - } - - if (Ty->isMemberPointerType()) { - if (Ty->isMemberFunctionPointerType()) { - if (Has64BitPointers) { - // If Has64BitPointers, this is an {i64, i64}, so classify both - // Lo and Hi now. - Lo = Hi = Integer; - } else { - // Otherwise, with 32-bit pointers, this is an {i32, i32}. If that - // straddles an eightbyte boundary, Hi should be classified as well. - uint64_t EB_FuncPtr = (OffsetBase) / 64; - uint64_t EB_ThisAdj = (OffsetBase + 64 - 1) / 64; - if (EB_FuncPtr != EB_ThisAdj) { - Lo = Hi = Integer; - } else { - Current = Integer; - } - } - } else { - Current = Integer; - } - return; - } - - if (const VectorType *VT = Ty->getAs<VectorType>()) { - uint64_t Size = getContext().getTypeSize(VT); - if (Size == 1 || Size == 8 || Size == 16 || Size == 32) { - // gcc passes the following as integer: - // 4 bytes - <4 x char>, <2 x short>, <1 x int>, <1 x float> - // 2 bytes - <2 x char>, <1 x short> - // 1 byte - <1 x char> - Current = Integer; - - // If this type crosses an eightbyte boundary, it should be - // split. - uint64_t EB_Lo = (OffsetBase) / 64; - uint64_t EB_Hi = (OffsetBase + Size - 1) / 64; - if (EB_Lo != EB_Hi) - Hi = Lo; - } else if (Size == 64) { - QualType ElementType = VT->getElementType(); - - // gcc passes <1 x double> in memory. :( - if (ElementType->isSpecificBuiltinType(BuiltinType::Double)) - return; - - // gcc passes <1 x long long> as SSE but clang used to unconditionally - // pass them as integer. For platforms where clang is the de facto - // platform compiler, we must continue to use integer. - if (!classifyIntegerMMXAsSSE() && - (ElementType->isSpecificBuiltinType(BuiltinType::LongLong) || - ElementType->isSpecificBuiltinType(BuiltinType::ULongLong) || - ElementType->isSpecificBuiltinType(BuiltinType::Long) || - ElementType->isSpecificBuiltinType(BuiltinType::ULong))) - Current = Integer; - else - Current = SSE; - - // If this type crosses an eightbyte boundary, it should be - // split. - if (OffsetBase && OffsetBase != 64) - Hi = Lo; - } else if (Size == 128 || - (isNamedArg && Size <= getNativeVectorSizeForAVXABI(AVXLevel))) { - // Arguments of 256-bits are split into four eightbyte chunks. The - // least significant one belongs to class SSE and all the others to class - // SSEUP. The original Lo and Hi design considers that types can't be - // greater than 128-bits, so a 64-bit split in Hi and Lo makes sense. - // This design isn't correct for 256-bits, but since there're no cases - // where the upper parts would need to be inspected, avoid adding - // complexity and just consider Hi to match the 64-256 part. - // - // Note that per 3.5.7 of AMD64-ABI, 256-bit args are only passed in - // registers if they are "named", i.e. not part of the "..." of a - // variadic function. - // - // Similarly, per 3.2.3. of the AVX512 draft, 512-bits ("named") args are - // split into eight eightbyte chunks, one SSE and seven SSEUP. - Lo = SSE; - Hi = SSEUp; - } - return; - } - - if (const ComplexType *CT = Ty->getAs<ComplexType>()) { - QualType ET = getContext().getCanonicalType(CT->getElementType()); - - uint64_t Size = getContext().getTypeSize(Ty); - if (ET->isIntegralOrEnumerationType()) { - if (Size <= 64) - Current = Integer; - else if (Size <= 128) - Lo = Hi = Integer; - } else if (ET == getContext().FloatTy) { - Current = SSE; - } else if (ET == getContext().DoubleTy) { - Lo = Hi = SSE; - } else if (ET == getContext().LongDoubleTy) { - const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat(); - if (LDF == &llvm::APFloat::IEEEquad()) - Current = Memory; - else if (LDF == &llvm::APFloat::x87DoubleExtended()) - Current = ComplexX87; - else if (LDF == &llvm::APFloat::IEEEdouble()) - Lo = Hi = SSE; - else - llvm_unreachable("unexpected long double representation!"); - } - - // If this complex type crosses an eightbyte boundary then it - // should be split. - uint64_t EB_Real = (OffsetBase) / 64; - uint64_t EB_Imag = (OffsetBase + getContext().getTypeSize(ET)) / 64; - if (Hi == NoClass && EB_Real != EB_Imag) - Hi = Lo; - - return; - } - - if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) { - // Arrays are treated like structures. - - uint64_t Size = getContext().getTypeSize(Ty); - - // AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger - // than eight eightbytes, ..., it has class MEMORY. - if (Size > 512) - return; - - // AMD64-ABI 3.2.3p2: Rule 1. If ..., or it contains unaligned - // fields, it has class MEMORY. - // - // Only need to check alignment of array base. - if (OffsetBase % getContext().getTypeAlign(AT->getElementType())) - return; - - // Otherwise implement simplified merge. We could be smarter about - // this, but it isn't worth it and would be harder to verify. - Current = NoClass; - uint64_t EltSize = getContext().getTypeSize(AT->getElementType()); - uint64_t ArraySize = AT->getSize().getZExtValue(); - - // The only case a 256-bit wide vector could be used is when the array - // contains a single 256-bit element. Since Lo and Hi logic isn't extended - // to work for sizes wider than 128, early check and fallback to memory. - // - if (Size > 128 && - (Size != EltSize || Size > getNativeVectorSizeForAVXABI(AVXLevel))) - return; - - for (uint64_t i=0, Offset=OffsetBase; i<ArraySize; ++i, Offset += EltSize) { - Class FieldLo, FieldHi; - classify(AT->getElementType(), Offset, FieldLo, FieldHi, isNamedArg); - Lo = merge(Lo, FieldLo); - Hi = merge(Hi, FieldHi); - if (Lo == Memory || Hi == Memory) - break; - } - - postMerge(Size, Lo, Hi); - assert((Hi != SSEUp || Lo == SSE) && "Invalid SSEUp array classification."); - return; - } - - if (const RecordType *RT = Ty->getAs<RecordType>()) { - uint64_t Size = getContext().getTypeSize(Ty); - - // AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger - // than eight eightbytes, ..., it has class MEMORY. - if (Size > 512) - return; - - // AMD64-ABI 3.2.3p2: Rule 2. If a C++ object has either a non-trivial - // copy constructor or a non-trivial destructor, it is passed by invisible - // reference. - if (getRecordArgABI(RT, getCXXABI())) - return; - - const RecordDecl *RD = RT->getDecl(); - - // Assume variable sized types are passed in memory. - if (RD->hasFlexibleArrayMember()) - return; - - const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); - - // Reset Lo class, this will be recomputed. - Current = NoClass; - - // If this is a C++ record, classify the bases first. - if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) { - for (const auto &I : CXXRD->bases()) { - assert(!I.isVirtual() && !I.getType()->isDependentType() && - "Unexpected base class!"); - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl()); - - // Classify this field. - // - // AMD64-ABI 3.2.3p2: Rule 3. If the size of the aggregate exceeds a - // single eightbyte, each is classified separately. Each eightbyte gets - // initialized to class NO_CLASS. - Class FieldLo, FieldHi; - uint64_t Offset = - OffsetBase + getContext().toBits(Layout.getBaseClassOffset(Base)); - classify(I.getType(), Offset, FieldLo, FieldHi, isNamedArg); - Lo = merge(Lo, FieldLo); - Hi = merge(Hi, FieldHi); - if (Lo == Memory || Hi == Memory) { - postMerge(Size, Lo, Hi); - return; - } - } - } - - // Classify the fields one at a time, merging the results. - unsigned idx = 0; - for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); - i != e; ++i, ++idx) { - uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx); - bool BitField = i->isBitField(); - - // Ignore padding bit-fields. - if (BitField && i->isUnnamedBitfield()) - continue; - - // AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger than - // four eightbytes, or it contains unaligned fields, it has class MEMORY. - // - // The only case a 256-bit wide vector could be used is when the struct - // contains a single 256-bit element. Since Lo and Hi logic isn't extended - // to work for sizes wider than 128, early check and fallback to memory. - // - if (Size > 128 && (Size != getContext().getTypeSize(i->getType()) || - Size > getNativeVectorSizeForAVXABI(AVXLevel))) { - Lo = Memory; - postMerge(Size, Lo, Hi); - return; - } - // Note, skip this test for bit-fields, see below. - if (!BitField && Offset % getContext().getTypeAlign(i->getType())) { - Lo = Memory; - postMerge(Size, Lo, Hi); - return; - } - - // Classify this field. - // - // AMD64-ABI 3.2.3p2: Rule 3. If the size of the aggregate - // exceeds a single eightbyte, each is classified - // separately. Each eightbyte gets initialized to class - // NO_CLASS. - Class FieldLo, FieldHi; - - // Bit-fields require special handling, they do not force the - // structure to be passed in memory even if unaligned, and - // therefore they can straddle an eightbyte. - if (BitField) { - assert(!i->isUnnamedBitfield()); - uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx); - uint64_t Size = i->getBitWidthValue(getContext()); - - uint64_t EB_Lo = Offset / 64; - uint64_t EB_Hi = (Offset + Size - 1) / 64; - - if (EB_Lo) { - assert(EB_Hi == EB_Lo && "Invalid classification, type > 16 bytes."); - FieldLo = NoClass; - FieldHi = Integer; - } else { - FieldLo = Integer; - FieldHi = EB_Hi ? Integer : NoClass; - } - } else - classify(i->getType(), Offset, FieldLo, FieldHi, isNamedArg); - Lo = merge(Lo, FieldLo); - Hi = merge(Hi, FieldHi); - if (Lo == Memory || Hi == Memory) - break; - } - - postMerge(Size, Lo, Hi); - } -} - -ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty) const { - // If this is a scalar LLVM value then assume LLVM will pass it in the right - // place naturally. - if (!isAggregateTypeForABI(Ty)) { - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = Ty->getAs<EnumType>()) - Ty = EnumTy->getDecl()->getIntegerType(); - - return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect()); - } - - return getNaturalAlignIndirect(Ty); -} - -bool X86_64ABIInfo::IsIllegalVectorType(QualType Ty) const { - if (const VectorType *VecTy = Ty->getAs<VectorType>()) { - uint64_t Size = getContext().getTypeSize(VecTy); - unsigned LargestVector = getNativeVectorSizeForAVXABI(AVXLevel); - if (Size <= 64 || Size > LargestVector) - return true; - } - - return false; -} - -ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty, - unsigned freeIntRegs) const { - // If this is a scalar LLVM value then assume LLVM will pass it in the right - // place naturally. - // - // This assumption is optimistic, as there could be free registers available - // when we need to pass this argument in memory, and LLVM could try to pass - // the argument in the free register. This does not seem to happen currently, - // but this code would be much safer if we could mark the argument with - // 'onstack'. See PR12193. - if (!isAggregateTypeForABI(Ty) && !IsIllegalVectorType(Ty)) { - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = Ty->getAs<EnumType>()) - Ty = EnumTy->getDecl()->getIntegerType(); - - return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect()); - } - - if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); - - // Compute the byval alignment. We specify the alignment of the byval in all - // cases so that the mid-level optimizer knows the alignment of the byval. - unsigned Align = std::max(getContext().getTypeAlign(Ty) / 8, 8U); - - // Attempt to avoid passing indirect results using byval when possible. This - // is important for good codegen. - // - // We do this by coercing the value into a scalar type which the backend can - // handle naturally (i.e., without using byval). - // - // For simplicity, we currently only do this when we have exhausted all of the - // free integer registers. Doing this when there are free integer registers - // would require more care, as we would have to ensure that the coerced value - // did not claim the unused register. That would require either reording the - // arguments to the function (so that any subsequent inreg values came first), - // or only doing this optimization when there were no following arguments that - // might be inreg. - // - // We currently expect it to be rare (particularly in well written code) for - // arguments to be passed on the stack when there are still free integer - // registers available (this would typically imply large structs being passed - // by value), so this seems like a fair tradeoff for now. - // - // We can revisit this if the backend grows support for 'onstack' parameter - // attributes. See PR12193. - if (freeIntRegs == 0) { - uint64_t Size = getContext().getTypeSize(Ty); - - // If this type fits in an eightbyte, coerce it into the matching integral - // type, which will end up on the stack (with alignment 8). - if (Align == 8 && Size <= 64) - return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), - Size)); - } - - return ABIArgInfo::getIndirect(CharUnits::fromQuantity(Align)); -} - -/// The ABI specifies that a value should be passed in a full vector XMM/YMM -/// register. Pick an LLVM IR type that will be passed as a vector register. -llvm::Type *X86_64ABIInfo::GetByteVectorType(QualType Ty) const { - // Wrapper structs/arrays that only contain vectors are passed just like - // vectors; strip them off if present. - if (const Type *InnerTy = isSingleElementStruct(Ty, getContext())) - Ty = QualType(InnerTy, 0); - - llvm::Type *IRType = CGT.ConvertType(Ty); - if (isa<llvm::VectorType>(IRType) || - IRType->getTypeID() == llvm::Type::FP128TyID) - return IRType; - - // We couldn't find the preferred IR vector type for 'Ty'. - uint64_t Size = getContext().getTypeSize(Ty); - assert((Size == 128 || Size == 256 || Size == 512) && "Invalid type found!"); - - // Return a LLVM IR vector type based on the size of 'Ty'. - return llvm::VectorType::get(llvm::Type::getDoubleTy(getVMContext()), - Size / 64); -} - -/// BitsContainNoUserData - Return true if the specified [start,end) bit range -/// is known to either be off the end of the specified type or being in -/// alignment padding. The user type specified is known to be at most 128 bits -/// in size, and have passed through X86_64ABIInfo::classify with a successful -/// classification that put one of the two halves in the INTEGER class. -/// -/// It is conservatively correct to return false. -static bool BitsContainNoUserData(QualType Ty, unsigned StartBit, - unsigned EndBit, ASTContext &Context) { - // If the bytes being queried are off the end of the type, there is no user - // data hiding here. This handles analysis of builtins, vectors and other - // types that don't contain interesting padding. - unsigned TySize = (unsigned)Context.getTypeSize(Ty); - if (TySize <= StartBit) - return true; - - if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) { - unsigned EltSize = (unsigned)Context.getTypeSize(AT->getElementType()); - unsigned NumElts = (unsigned)AT->getSize().getZExtValue(); - - // Check each element to see if the element overlaps with the queried range. - for (unsigned i = 0; i != NumElts; ++i) { - // If the element is after the span we care about, then we're done.. - unsigned EltOffset = i*EltSize; - if (EltOffset >= EndBit) break; - - unsigned EltStart = EltOffset < StartBit ? StartBit-EltOffset :0; - if (!BitsContainNoUserData(AT->getElementType(), EltStart, - EndBit-EltOffset, Context)) - return false; - } - // If it overlaps no elements, then it is safe to process as padding. - return true; - } - - if (const RecordType *RT = Ty->getAs<RecordType>()) { - const RecordDecl *RD = RT->getDecl(); - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - - // If this is a C++ record, check the bases first. - if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) { - for (const auto &I : CXXRD->bases()) { - assert(!I.isVirtual() && !I.getType()->isDependentType() && - "Unexpected base class!"); - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl()); - - // If the base is after the span we care about, ignore it. - unsigned BaseOffset = Context.toBits(Layout.getBaseClassOffset(Base)); - if (BaseOffset >= EndBit) continue; - - unsigned BaseStart = BaseOffset < StartBit ? StartBit-BaseOffset :0; - if (!BitsContainNoUserData(I.getType(), BaseStart, - EndBit-BaseOffset, Context)) - return false; - } - } - - // Verify that no field has data that overlaps the region of interest. Yes - // this could be sped up a lot by being smarter about queried fields, - // however we're only looking at structs up to 16 bytes, so we don't care - // much. - unsigned idx = 0; - for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); - i != e; ++i, ++idx) { - unsigned FieldOffset = (unsigned)Layout.getFieldOffset(idx); - - // If we found a field after the region we care about, then we're done. - if (FieldOffset >= EndBit) break; - - unsigned FieldStart = FieldOffset < StartBit ? StartBit-FieldOffset :0; - if (!BitsContainNoUserData(i->getType(), FieldStart, EndBit-FieldOffset, - Context)) - return false; - } - - // If nothing in this record overlapped the area of interest, then we're - // clean. - return true; - } - - return false; -} - -/// ContainsFloatAtOffset - Return true if the specified LLVM IR type has a -/// float member at the specified offset. For example, {int,{float}} has a -/// float at offset 4. It is conservatively correct for this routine to return -/// false. -static bool ContainsFloatAtOffset(llvm::Type *IRType, unsigned IROffset, - const llvm::DataLayout &TD) { - // Base case if we find a float. - if (IROffset == 0 && IRType->isFloatTy()) - return true; - - // If this is a struct, recurse into the field at the specified offset. - if (llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) { - const llvm::StructLayout *SL = TD.getStructLayout(STy); - unsigned Elt = SL->getElementContainingOffset(IROffset); - IROffset -= SL->getElementOffset(Elt); - return ContainsFloatAtOffset(STy->getElementType(Elt), IROffset, TD); - } - - // If this is an array, recurse into the field at the specified offset. - if (llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) { - llvm::Type *EltTy = ATy->getElementType(); - unsigned EltSize = TD.getTypeAllocSize(EltTy); - IROffset -= IROffset/EltSize*EltSize; - return ContainsFloatAtOffset(EltTy, IROffset, TD); - } - - return false; -} - - -/// GetSSETypeAtOffset - Return a type that will be passed by the backend in the -/// low 8 bytes of an XMM register, corresponding to the SSE class. -llvm::Type *X86_64ABIInfo:: -GetSSETypeAtOffset(llvm::Type *IRType, unsigned IROffset, - QualType SourceTy, unsigned SourceOffset) const { - // The only three choices we have are either double, <2 x float>, or float. We - // pass as float if the last 4 bytes is just padding. This happens for - // structs that contain 3 floats. - if (BitsContainNoUserData(SourceTy, SourceOffset*8+32, - SourceOffset*8+64, getContext())) - return llvm::Type::getFloatTy(getVMContext()); - - // We want to pass as <2 x float> if the LLVM IR type contains a float at - // offset+0 and offset+4. Walk the LLVM IR type to find out if this is the - // case. - if (ContainsFloatAtOffset(IRType, IROffset, getDataLayout()) && - ContainsFloatAtOffset(IRType, IROffset+4, getDataLayout())) - return llvm::VectorType::get(llvm::Type::getFloatTy(getVMContext()), 2); - - return llvm::Type::getDoubleTy(getVMContext()); -} - - -/// GetINTEGERTypeAtOffset - The ABI specifies that a value should be passed in -/// an 8-byte GPR. This means that we either have a scalar or we are talking -/// about the high or low part of an up-to-16-byte struct. This routine picks -/// the best LLVM IR type to represent this, which may be i64 or may be anything -/// else that the backend will pass in a GPR that works better (e.g. i8, %foo*, -/// etc). -/// -/// PrefType is an LLVM IR type that corresponds to (part of) the IR type for -/// the source type. IROffset is an offset in bytes into the LLVM IR type that -/// the 8-byte value references. PrefType may be null. -/// -/// SourceTy is the source-level type for the entire argument. SourceOffset is -/// an offset into this that we're processing (which is always either 0 or 8). -/// -llvm::Type *X86_64ABIInfo:: -GetINTEGERTypeAtOffset(llvm::Type *IRType, unsigned IROffset, - QualType SourceTy, unsigned SourceOffset) const { - // If we're dealing with an un-offset LLVM IR type, then it means that we're - // returning an 8-byte unit starting with it. See if we can safely use it. - if (IROffset == 0) { - // Pointers and int64's always fill the 8-byte unit. - if ((isa<llvm::PointerType>(IRType) && Has64BitPointers) || - IRType->isIntegerTy(64)) - return IRType; - - // If we have a 1/2/4-byte integer, we can use it only if the rest of the - // goodness in the source type is just tail padding. This is allowed to - // kick in for struct {double,int} on the int, but not on - // struct{double,int,int} because we wouldn't return the second int. We - // have to do this analysis on the source type because we can't depend on - // unions being lowered a specific way etc. - if (IRType->isIntegerTy(8) || IRType->isIntegerTy(16) || - IRType->isIntegerTy(32) || - (isa<llvm::PointerType>(IRType) && !Has64BitPointers)) { - unsigned BitWidth = isa<llvm::PointerType>(IRType) ? 32 : - cast<llvm::IntegerType>(IRType)->getBitWidth(); - - if (BitsContainNoUserData(SourceTy, SourceOffset*8+BitWidth, - SourceOffset*8+64, getContext())) - return IRType; - } - } - - if (llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) { - // If this is a struct, recurse into the field at the specified offset. - const llvm::StructLayout *SL = getDataLayout().getStructLayout(STy); - if (IROffset < SL->getSizeInBytes()) { - unsigned FieldIdx = SL->getElementContainingOffset(IROffset); - IROffset -= SL->getElementOffset(FieldIdx); - - return GetINTEGERTypeAtOffset(STy->getElementType(FieldIdx), IROffset, - SourceTy, SourceOffset); - } - } - - if (llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) { - llvm::Type *EltTy = ATy->getElementType(); - unsigned EltSize = getDataLayout().getTypeAllocSize(EltTy); - unsigned EltOffset = IROffset/EltSize*EltSize; - return GetINTEGERTypeAtOffset(EltTy, IROffset-EltOffset, SourceTy, - SourceOffset); - } - - // Okay, we don't have any better idea of what to pass, so we pass this in an - // integer register that isn't too big to fit the rest of the struct. - unsigned TySizeInBytes = - (unsigned)getContext().getTypeSizeInChars(SourceTy).getQuantity(); - - assert(TySizeInBytes != SourceOffset && "Empty field?"); - - // It is always safe to classify this as an integer type up to i64 that - // isn't larger than the structure. - return llvm::IntegerType::get(getVMContext(), - std::min(TySizeInBytes-SourceOffset, 8U)*8); -} - - -/// GetX86_64ByValArgumentPair - Given a high and low type that can ideally -/// be used as elements of a two register pair to pass or return, return a -/// first class aggregate to represent them. For example, if the low part of -/// a by-value argument should be passed as i32* and the high part as float, -/// return {i32*, float}. -static llvm::Type * -GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type *Hi, - const llvm::DataLayout &TD) { - // In order to correctly satisfy the ABI, we need to the high part to start - // at offset 8. If the high and low parts we inferred are both 4-byte types - // (e.g. i32 and i32) then the resultant struct type ({i32,i32}) won't have - // the second element at offset 8. Check for this: - unsigned LoSize = (unsigned)TD.getTypeAllocSize(Lo); - unsigned HiAlign = TD.getABITypeAlignment(Hi); - unsigned HiStart = llvm::alignTo(LoSize, HiAlign); - assert(HiStart != 0 && HiStart <= 8 && "Invalid x86-64 argument pair!"); - - // To handle this, we have to increase the size of the low part so that the - // second element will start at an 8 byte offset. We can't increase the size - // of the second element because it might make us access off the end of the - // struct. - if (HiStart != 8) { - // There are usually two sorts of types the ABI generation code can produce - // for the low part of a pair that aren't 8 bytes in size: float or - // i8/i16/i32. This can also include pointers when they are 32-bit (X32 and - // NaCl). - // Promote these to a larger type. - if (Lo->isFloatTy()) - Lo = llvm::Type::getDoubleTy(Lo->getContext()); - else { - assert((Lo->isIntegerTy() || Lo->isPointerTy()) - && "Invalid/unknown lo type"); - Lo = llvm::Type::getInt64Ty(Lo->getContext()); - } - } - - llvm::StructType *Result = llvm::StructType::get(Lo, Hi); - - // Verify that the second element is at an 8-byte offset. - assert(TD.getStructLayout(Result)->getElementOffset(1) == 8 && - "Invalid x86-64 argument pair!"); - return Result; -} - -ABIArgInfo X86_64ABIInfo:: -classifyReturnType(QualType RetTy) const { - // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the - // classification algorithm. - X86_64ABIInfo::Class Lo, Hi; - classify(RetTy, 0, Lo, Hi, /*isNamedArg*/ true); - - // Check some invariants. - assert((Hi != Memory || Lo == Memory) && "Invalid memory classification."); - assert((Hi != SSEUp || Lo == SSE) && "Invalid SSEUp classification."); - - llvm::Type *ResType = nullptr; - switch (Lo) { - case NoClass: - if (Hi == NoClass) - return ABIArgInfo::getIgnore(); - // If the low part is just padding, it takes no register, leave ResType - // null. - assert((Hi == SSE || Hi == Integer || Hi == X87Up) && - "Unknown missing lo part"); - break; - - case SSEUp: - case X87Up: - llvm_unreachable("Invalid classification for lo word."); - - // AMD64-ABI 3.2.3p4: Rule 2. Types of class memory are returned via - // hidden argument. - case Memory: - return getIndirectReturnResult(RetTy); - - // AMD64-ABI 3.2.3p4: Rule 3. If the class is INTEGER, the next - // available register of the sequence %rax, %rdx is used. - case Integer: - ResType = GetINTEGERTypeAtOffset(CGT.ConvertType(RetTy), 0, RetTy, 0); - - // If we have a sign or zero extended integer, make sure to return Extend - // so that the parameter gets the right LLVM IR attributes. - if (Hi == NoClass && isa<llvm::IntegerType>(ResType)) { - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) - RetTy = EnumTy->getDecl()->getIntegerType(); - - if (RetTy->isIntegralOrEnumerationType() && - RetTy->isPromotableIntegerType()) - return ABIArgInfo::getExtend(RetTy); - } - break; - - // AMD64-ABI 3.2.3p4: Rule 4. If the class is SSE, the next - // available SSE register of the sequence %xmm0, %xmm1 is used. - case SSE: - ResType = GetSSETypeAtOffset(CGT.ConvertType(RetTy), 0, RetTy, 0); - break; - - // AMD64-ABI 3.2.3p4: Rule 6. If the class is X87, the value is - // returned on the X87 stack in %st0 as 80-bit x87 number. - case X87: - ResType = llvm::Type::getX86_FP80Ty(getVMContext()); - break; - - // AMD64-ABI 3.2.3p4: Rule 8. If the class is COMPLEX_X87, the real - // part of the value is returned in %st0 and the imaginary part in - // %st1. - case ComplexX87: - assert(Hi == ComplexX87 && "Unexpected ComplexX87 classification."); - ResType = llvm::StructType::get(llvm::Type::getX86_FP80Ty(getVMContext()), - llvm::Type::getX86_FP80Ty(getVMContext())); - break; - } - - llvm::Type *HighPart = nullptr; - switch (Hi) { - // Memory was handled previously and X87 should - // never occur as a hi class. - case Memory: - case X87: - llvm_unreachable("Invalid classification for hi word."); - - case ComplexX87: // Previously handled. - case NoClass: - break; - - case Integer: - HighPart = GetINTEGERTypeAtOffset(CGT.ConvertType(RetTy), 8, RetTy, 8); - if (Lo == NoClass) // Return HighPart at offset 8 in memory. - return ABIArgInfo::getDirect(HighPart, 8); - break; - case SSE: - HighPart = GetSSETypeAtOffset(CGT.ConvertType(RetTy), 8, RetTy, 8); - if (Lo == NoClass) // Return HighPart at offset 8 in memory. - return ABIArgInfo::getDirect(HighPart, 8); - break; - - // AMD64-ABI 3.2.3p4: Rule 5. If the class is SSEUP, the eightbyte - // is passed in the next available eightbyte chunk if the last used - // vector register. - // - // SSEUP should always be preceded by SSE, just widen. - case SSEUp: - assert(Lo == SSE && "Unexpected SSEUp classification."); - ResType = GetByteVectorType(RetTy); - break; - - // AMD64-ABI 3.2.3p4: Rule 7. If the class is X87UP, the value is - // returned together with the previous X87 value in %st0. - case X87Up: - // If X87Up is preceded by X87, we don't need to do - // anything. However, in some cases with unions it may not be - // preceded by X87. In such situations we follow gcc and pass the - // extra bits in an SSE reg. - if (Lo != X87) { - HighPart = GetSSETypeAtOffset(CGT.ConvertType(RetTy), 8, RetTy, 8); - if (Lo == NoClass) // Return HighPart at offset 8 in memory. - return ABIArgInfo::getDirect(HighPart, 8); - } - break; - } - - // If a high part was specified, merge it together with the low part. It is - // known to pass in the high eightbyte of the result. We do this by forming a - // first class struct aggregate with the high and low part: {low, high} - if (HighPart) - ResType = GetX86_64ByValArgumentPair(ResType, HighPart, getDataLayout()); - - return ABIArgInfo::getDirect(ResType); -} - -ABIArgInfo X86_64ABIInfo::classifyArgumentType( - QualType Ty, unsigned freeIntRegs, unsigned &neededInt, unsigned &neededSSE, - bool isNamedArg) - const -{ - Ty = useFirstFieldIfTransparentUnion(Ty); - - X86_64ABIInfo::Class Lo, Hi; - classify(Ty, 0, Lo, Hi, isNamedArg); - - // Check some invariants. - // FIXME: Enforce these by construction. - assert((Hi != Memory || Lo == Memory) && "Invalid memory classification."); - assert((Hi != SSEUp || Lo == SSE) && "Invalid SSEUp classification."); - - neededInt = 0; - neededSSE = 0; - llvm::Type *ResType = nullptr; - switch (Lo) { - case NoClass: - if (Hi == NoClass) - return ABIArgInfo::getIgnore(); - // If the low part is just padding, it takes no register, leave ResType - // null. - assert((Hi == SSE || Hi == Integer || Hi == X87Up) && - "Unknown missing lo part"); - break; - - // AMD64-ABI 3.2.3p3: Rule 1. If the class is MEMORY, pass the argument - // on the stack. - case Memory: - - // AMD64-ABI 3.2.3p3: Rule 5. If the class is X87, X87UP or - // COMPLEX_X87, it is passed in memory. - case X87: - case ComplexX87: - if (getRecordArgABI(Ty, getCXXABI()) == CGCXXABI::RAA_Indirect) - ++neededInt; - return getIndirectResult(Ty, freeIntRegs); - - case SSEUp: - case X87Up: - llvm_unreachable("Invalid classification for lo word."); - - // AMD64-ABI 3.2.3p3: Rule 2. If the class is INTEGER, the next - // available register of the sequence %rdi, %rsi, %rdx, %rcx, %r8 - // and %r9 is used. - case Integer: - ++neededInt; - - // Pick an 8-byte type based on the preferred type. - ResType = GetINTEGERTypeAtOffset(CGT.ConvertType(Ty), 0, Ty, 0); - - // If we have a sign or zero extended integer, make sure to return Extend - // so that the parameter gets the right LLVM IR attributes. - if (Hi == NoClass && isa<llvm::IntegerType>(ResType)) { - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = Ty->getAs<EnumType>()) - Ty = EnumTy->getDecl()->getIntegerType(); - - if (Ty->isIntegralOrEnumerationType() && - Ty->isPromotableIntegerType()) - return ABIArgInfo::getExtend(Ty); - } - - break; - - // AMD64-ABI 3.2.3p3: Rule 3. If the class is SSE, the next - // available SSE register is used, the registers are taken in the - // order from %xmm0 to %xmm7. - case SSE: { - llvm::Type *IRType = CGT.ConvertType(Ty); - ResType = GetSSETypeAtOffset(IRType, 0, Ty, 0); - ++neededSSE; - break; - } - } - - llvm::Type *HighPart = nullptr; - switch (Hi) { - // Memory was handled previously, ComplexX87 and X87 should - // never occur as hi classes, and X87Up must be preceded by X87, - // which is passed in memory. - case Memory: - case X87: - case ComplexX87: - llvm_unreachable("Invalid classification for hi word."); - - case NoClass: break; - - case Integer: - ++neededInt; - // Pick an 8-byte type based on the preferred type. - HighPart = GetINTEGERTypeAtOffset(CGT.ConvertType(Ty), 8, Ty, 8); - - if (Lo == NoClass) // Pass HighPart at offset 8 in memory. - return ABIArgInfo::getDirect(HighPart, 8); - break; - - // X87Up generally doesn't occur here (long double is passed in - // memory), except in situations involving unions. - case X87Up: - case SSE: - HighPart = GetSSETypeAtOffset(CGT.ConvertType(Ty), 8, Ty, 8); - - if (Lo == NoClass) // Pass HighPart at offset 8 in memory. - return ABIArgInfo::getDirect(HighPart, 8); - - ++neededSSE; - break; - - // AMD64-ABI 3.2.3p3: Rule 4. If the class is SSEUP, the - // eightbyte is passed in the upper half of the last used SSE - // register. This only happens when 128-bit vectors are passed. - case SSEUp: - assert(Lo == SSE && "Unexpected SSEUp classification"); - ResType = GetByteVectorType(Ty); - break; - } - - // If a high part was specified, merge it together with the low part. It is - // known to pass in the high eightbyte of the result. We do this by forming a - // first class struct aggregate with the high and low part: {low, high} - if (HighPart) - ResType = GetX86_64ByValArgumentPair(ResType, HighPart, getDataLayout()); - - return ABIArgInfo::getDirect(ResType); -} - -ABIArgInfo -X86_64ABIInfo::classifyRegCallStructTypeImpl(QualType Ty, unsigned &NeededInt, - unsigned &NeededSSE) const { - auto RT = Ty->getAs<RecordType>(); - assert(RT && "classifyRegCallStructType only valid with struct types"); - - if (RT->getDecl()->hasFlexibleArrayMember()) - return getIndirectReturnResult(Ty); - - // Sum up bases - if (auto CXXRD = dyn_cast<CXXRecordDecl>(RT->getDecl())) { - if (CXXRD->isDynamicClass()) { - NeededInt = NeededSSE = 0; - return getIndirectReturnResult(Ty); - } - - for (const auto &I : CXXRD->bases()) - if (classifyRegCallStructTypeImpl(I.getType(), NeededInt, NeededSSE) - .isIndirect()) { - NeededInt = NeededSSE = 0; - return getIndirectReturnResult(Ty); - } - } - - // Sum up members - for (const auto *FD : RT->getDecl()->fields()) { - if (FD->getType()->isRecordType() && !FD->getType()->isUnionType()) { - if (classifyRegCallStructTypeImpl(FD->getType(), NeededInt, NeededSSE) - .isIndirect()) { - NeededInt = NeededSSE = 0; - return getIndirectReturnResult(Ty); - } - } else { - unsigned LocalNeededInt, LocalNeededSSE; - if (classifyArgumentType(FD->getType(), UINT_MAX, LocalNeededInt, - LocalNeededSSE, true) - .isIndirect()) { - NeededInt = NeededSSE = 0; - return getIndirectReturnResult(Ty); - } - NeededInt += LocalNeededInt; - NeededSSE += LocalNeededSSE; - } - } - - return ABIArgInfo::getDirect(); -} - -ABIArgInfo X86_64ABIInfo::classifyRegCallStructType(QualType Ty, - unsigned &NeededInt, - unsigned &NeededSSE) const { - - NeededInt = 0; - NeededSSE = 0; - - return classifyRegCallStructTypeImpl(Ty, NeededInt, NeededSSE); -} - -void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const { - - const unsigned CallingConv = FI.getCallingConvention(); - // It is possible to force Win64 calling convention on any x86_64 target by - // using __attribute__((ms_abi)). In such case to correctly emit Win64 - // compatible code delegate this call to WinX86_64ABIInfo::computeInfo. - if (CallingConv == llvm::CallingConv::Win64) { - WinX86_64ABIInfo Win64ABIInfo(CGT); - Win64ABIInfo.computeInfo(FI); - return; - } - - bool IsRegCall = CallingConv == llvm::CallingConv::X86_RegCall; - - // Keep track of the number of assigned registers. - unsigned FreeIntRegs = IsRegCall ? 11 : 6; - unsigned FreeSSERegs = IsRegCall ? 16 : 8; - unsigned NeededInt, NeededSSE; - - if (!::classifyReturnType(getCXXABI(), FI, *this)) { - if (IsRegCall && FI.getReturnType()->getTypePtr()->isRecordType() && - !FI.getReturnType()->getTypePtr()->isUnionType()) { - FI.getReturnInfo() = - classifyRegCallStructType(FI.getReturnType(), NeededInt, NeededSSE); - if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) { - FreeIntRegs -= NeededInt; - FreeSSERegs -= NeededSSE; - } else { - FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType()); - } - } else if (IsRegCall && FI.getReturnType()->getAs<ComplexType>()) { - // Complex Long Double Type is passed in Memory when Regcall - // calling convention is used. - const ComplexType *CT = FI.getReturnType()->getAs<ComplexType>(); - if (getContext().getCanonicalType(CT->getElementType()) == - getContext().LongDoubleTy) - FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType()); - } else - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); - } - - // If the return value is indirect, then the hidden argument is consuming one - // integer register. - if (FI.getReturnInfo().isIndirect()) - --FreeIntRegs; - - // The chain argument effectively gives us another free register. - if (FI.isChainCall()) - ++FreeIntRegs; - - unsigned NumRequiredArgs = FI.getNumRequiredArgs(); - // AMD64-ABI 3.2.3p3: Once arguments are classified, the registers - // get assigned (in left-to-right order) for passing as follows... - unsigned ArgNo = 0; - for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end(); - it != ie; ++it, ++ArgNo) { - bool IsNamedArg = ArgNo < NumRequiredArgs; - - if (IsRegCall && it->type->isStructureOrClassType()) - it->info = classifyRegCallStructType(it->type, NeededInt, NeededSSE); - else - it->info = classifyArgumentType(it->type, FreeIntRegs, NeededInt, - NeededSSE, IsNamedArg); - - // AMD64-ABI 3.2.3p3: If there are no registers available for any - // eightbyte of an argument, the whole argument is passed on the - // stack. If registers have already been assigned for some - // eightbytes of such an argument, the assignments get reverted. - if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) { - FreeIntRegs -= NeededInt; - FreeSSERegs -= NeededSSE; - } else { - it->info = getIndirectResult(it->type, FreeIntRegs); - } - } -} - -static Address EmitX86_64VAArgFromMemory(CodeGenFunction &CGF, - Address VAListAddr, QualType Ty) { - Address overflow_arg_area_p = CGF.Builder.CreateStructGEP( - VAListAddr, 2, CharUnits::fromQuantity(8), "overflow_arg_area_p"); - llvm::Value *overflow_arg_area = - CGF.Builder.CreateLoad(overflow_arg_area_p, "overflow_arg_area"); - - // AMD64-ABI 3.5.7p5: Step 7. Align l->overflow_arg_area upwards to a 16 - // byte boundary if alignment needed by type exceeds 8 byte boundary. - // It isn't stated explicitly in the standard, but in practice we use - // alignment greater than 16 where necessary. - CharUnits Align = CGF.getContext().getTypeAlignInChars(Ty); - if (Align > CharUnits::fromQuantity(8)) { - overflow_arg_area = emitRoundPointerUpToAlignment(CGF, overflow_arg_area, - Align); - } - - // AMD64-ABI 3.5.7p5: Step 8. Fetch type from l->overflow_arg_area. - llvm::Type *LTy = CGF.ConvertTypeForMem(Ty); - llvm::Value *Res = - CGF.Builder.CreateBitCast(overflow_arg_area, - llvm::PointerType::getUnqual(LTy)); - - // AMD64-ABI 3.5.7p5: Step 9. Set l->overflow_arg_area to: - // l->overflow_arg_area + sizeof(type). - // AMD64-ABI 3.5.7p5: Step 10. Align l->overflow_arg_area upwards to - // an 8 byte boundary. - - uint64_t SizeInBytes = (CGF.getContext().getTypeSize(Ty) + 7) / 8; - llvm::Value *Offset = - llvm::ConstantInt::get(CGF.Int32Ty, (SizeInBytes + 7) & ~7); - overflow_arg_area = CGF.Builder.CreateGEP(overflow_arg_area, Offset, - "overflow_arg_area.next"); - CGF.Builder.CreateStore(overflow_arg_area, overflow_arg_area_p); - - // AMD64-ABI 3.5.7p5: Step 11. Return the fetched type. - return Address(Res, Align); -} - -Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const { - // Assume that va_list type is correct; should be pointer to LLVM type: - // struct { - // i32 gp_offset; - // i32 fp_offset; - // i8* overflow_arg_area; - // i8* reg_save_area; - // }; - unsigned neededInt, neededSSE; - - Ty = getContext().getCanonicalType(Ty); - ABIArgInfo AI = classifyArgumentType(Ty, 0, neededInt, neededSSE, - /*isNamedArg*/false); - - // AMD64-ABI 3.5.7p5: Step 1. Determine whether type may be passed - // in the registers. If not go to step 7. - if (!neededInt && !neededSSE) - return EmitX86_64VAArgFromMemory(CGF, VAListAddr, Ty); - - // AMD64-ABI 3.5.7p5: Step 2. Compute num_gp to hold the number of - // general purpose registers needed to pass type and num_fp to hold - // the number of floating point registers needed. - - // AMD64-ABI 3.5.7p5: Step 3. Verify whether arguments fit into - // registers. In the case: l->gp_offset > 48 - num_gp * 8 or - // l->fp_offset > 304 - num_fp * 16 go to step 7. - // - // NOTE: 304 is a typo, there are (6 * 8 + 8 * 16) = 176 bytes of - // register save space). - - llvm::Value *InRegs = nullptr; - Address gp_offset_p = Address::invalid(), fp_offset_p = Address::invalid(); - llvm::Value *gp_offset = nullptr, *fp_offset = nullptr; - if (neededInt) { - gp_offset_p = - CGF.Builder.CreateStructGEP(VAListAddr, 0, CharUnits::Zero(), - "gp_offset_p"); - gp_offset = CGF.Builder.CreateLoad(gp_offset_p, "gp_offset"); - InRegs = llvm::ConstantInt::get(CGF.Int32Ty, 48 - neededInt * 8); - InRegs = CGF.Builder.CreateICmpULE(gp_offset, InRegs, "fits_in_gp"); - } - - if (neededSSE) { - fp_offset_p = - CGF.Builder.CreateStructGEP(VAListAddr, 1, CharUnits::fromQuantity(4), - "fp_offset_p"); - fp_offset = CGF.Builder.CreateLoad(fp_offset_p, "fp_offset"); - llvm::Value *FitsInFP = - llvm::ConstantInt::get(CGF.Int32Ty, 176 - neededSSE * 16); - FitsInFP = CGF.Builder.CreateICmpULE(fp_offset, FitsInFP, "fits_in_fp"); - InRegs = InRegs ? CGF.Builder.CreateAnd(InRegs, FitsInFP) : FitsInFP; - } - - llvm::BasicBlock *InRegBlock = CGF.createBasicBlock("vaarg.in_reg"); - llvm::BasicBlock *InMemBlock = CGF.createBasicBlock("vaarg.in_mem"); - llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end"); - CGF.Builder.CreateCondBr(InRegs, InRegBlock, InMemBlock); - - // Emit code to load the value if it was passed in registers. - - CGF.EmitBlock(InRegBlock); - - // AMD64-ABI 3.5.7p5: Step 4. Fetch type from l->reg_save_area with - // an offset of l->gp_offset and/or l->fp_offset. This may require - // copying to a temporary location in case the parameter is passed - // in different register classes or requires an alignment greater - // than 8 for general purpose registers and 16 for XMM registers. - // - // FIXME: This really results in shameful code when we end up needing to - // collect arguments from different places; often what should result in a - // simple assembling of a structure from scattered addresses has many more - // loads than necessary. Can we clean this up? - llvm::Type *LTy = CGF.ConvertTypeForMem(Ty); - llvm::Value *RegSaveArea = CGF.Builder.CreateLoad( - CGF.Builder.CreateStructGEP(VAListAddr, 3, CharUnits::fromQuantity(16)), - "reg_save_area"); - - Address RegAddr = Address::invalid(); - if (neededInt && neededSSE) { - // FIXME: Cleanup. - assert(AI.isDirect() && "Unexpected ABI info for mixed regs"); - llvm::StructType *ST = cast<llvm::StructType>(AI.getCoerceToType()); - Address Tmp = CGF.CreateMemTemp(Ty); - Tmp = CGF.Builder.CreateElementBitCast(Tmp, ST); - assert(ST->getNumElements() == 2 && "Unexpected ABI info for mixed regs"); - llvm::Type *TyLo = ST->getElementType(0); - llvm::Type *TyHi = ST->getElementType(1); - assert((TyLo->isFPOrFPVectorTy() ^ TyHi->isFPOrFPVectorTy()) && - "Unexpected ABI info for mixed regs"); - llvm::Type *PTyLo = llvm::PointerType::getUnqual(TyLo); - llvm::Type *PTyHi = llvm::PointerType::getUnqual(TyHi); - llvm::Value *GPAddr = CGF.Builder.CreateGEP(RegSaveArea, gp_offset); - llvm::Value *FPAddr = CGF.Builder.CreateGEP(RegSaveArea, fp_offset); - llvm::Value *RegLoAddr = TyLo->isFPOrFPVectorTy() ? FPAddr : GPAddr; - llvm::Value *RegHiAddr = TyLo->isFPOrFPVectorTy() ? GPAddr : FPAddr; - - // Copy the first element. - // FIXME: Our choice of alignment here and below is probably pessimistic. - llvm::Value *V = CGF.Builder.CreateAlignedLoad( - TyLo, CGF.Builder.CreateBitCast(RegLoAddr, PTyLo), - CharUnits::fromQuantity(getDataLayout().getABITypeAlignment(TyLo))); - CGF.Builder.CreateStore(V, - CGF.Builder.CreateStructGEP(Tmp, 0, CharUnits::Zero())); - - // Copy the second element. - V = CGF.Builder.CreateAlignedLoad( - TyHi, CGF.Builder.CreateBitCast(RegHiAddr, PTyHi), - CharUnits::fromQuantity(getDataLayout().getABITypeAlignment(TyHi))); - CharUnits Offset = CharUnits::fromQuantity( - getDataLayout().getStructLayout(ST)->getElementOffset(1)); - CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1, Offset)); - - RegAddr = CGF.Builder.CreateElementBitCast(Tmp, LTy); - } else if (neededInt) { - RegAddr = Address(CGF.Builder.CreateGEP(RegSaveArea, gp_offset), - CharUnits::fromQuantity(8)); - RegAddr = CGF.Builder.CreateElementBitCast(RegAddr, LTy); - - // Copy to a temporary if necessary to ensure the appropriate alignment. - std::pair<CharUnits, CharUnits> SizeAlign = - getContext().getTypeInfoInChars(Ty); - uint64_t TySize = SizeAlign.first.getQuantity(); - CharUnits TyAlign = SizeAlign.second; - - // Copy into a temporary if the type is more aligned than the - // register save area. - if (TyAlign.getQuantity() > 8) { - Address Tmp = CGF.CreateMemTemp(Ty); - CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); - RegAddr = Tmp; - } - - } else if (neededSSE == 1) { - RegAddr = Address(CGF.Builder.CreateGEP(RegSaveArea, fp_offset), - CharUnits::fromQuantity(16)); - RegAddr = CGF.Builder.CreateElementBitCast(RegAddr, LTy); - } else { - assert(neededSSE == 2 && "Invalid number of needed registers!"); - // SSE registers are spaced 16 bytes apart in the register save - // area, we need to collect the two eightbytes together. - // The ABI isn't explicit about this, but it seems reasonable - // to assume that the slots are 16-byte aligned, since the stack is - // naturally 16-byte aligned and the prologue is expected to store - // all the SSE registers to the RSA. - Address RegAddrLo = Address(CGF.Builder.CreateGEP(RegSaveArea, fp_offset), - CharUnits::fromQuantity(16)); - Address RegAddrHi = - CGF.Builder.CreateConstInBoundsByteGEP(RegAddrLo, - CharUnits::fromQuantity(16)); - llvm::Type *ST = AI.canHaveCoerceToType() - ? AI.getCoerceToType() - : llvm::StructType::get(CGF.DoubleTy, CGF.DoubleTy); - llvm::Value *V; - Address Tmp = CGF.CreateMemTemp(Ty); - Tmp = CGF.Builder.CreateElementBitCast(Tmp, ST); - V = CGF.Builder.CreateLoad(CGF.Builder.CreateElementBitCast( - RegAddrLo, ST->getStructElementType(0))); - CGF.Builder.CreateStore(V, - CGF.Builder.CreateStructGEP(Tmp, 0, CharUnits::Zero())); - V = CGF.Builder.CreateLoad(CGF.Builder.CreateElementBitCast( - RegAddrHi, ST->getStructElementType(1))); - CGF.Builder.CreateStore(V, - CGF.Builder.CreateStructGEP(Tmp, 1, CharUnits::fromQuantity(8))); - - RegAddr = CGF.Builder.CreateElementBitCast(Tmp, LTy); - } - - // AMD64-ABI 3.5.7p5: Step 5. Set: - // l->gp_offset = l->gp_offset + num_gp * 8 - // l->fp_offset = l->fp_offset + num_fp * 16. - if (neededInt) { - llvm::Value *Offset = llvm::ConstantInt::get(CGF.Int32Ty, neededInt * 8); - CGF.Builder.CreateStore(CGF.Builder.CreateAdd(gp_offset, Offset), - gp_offset_p); - } - if (neededSSE) { - llvm::Value *Offset = llvm::ConstantInt::get(CGF.Int32Ty, neededSSE * 16); - CGF.Builder.CreateStore(CGF.Builder.CreateAdd(fp_offset, Offset), - fp_offset_p); - } - CGF.EmitBranch(ContBlock); - - // Emit code to load the value if it was passed in memory. - - CGF.EmitBlock(InMemBlock); - Address MemAddr = EmitX86_64VAArgFromMemory(CGF, VAListAddr, Ty); - - // Return the appropriate result. - - CGF.EmitBlock(ContBlock); - Address ResAddr = emitMergePHI(CGF, RegAddr, InRegBlock, MemAddr, InMemBlock, - "vaarg.addr"); - return ResAddr; -} - -Address X86_64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const { - return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false, - CGF.getContext().getTypeInfoInChars(Ty), - CharUnits::fromQuantity(8), - /*allowHigherAlign*/ false); -} - -ABIArgInfo -WinX86_64ABIInfo::reclassifyHvaArgType(QualType Ty, unsigned &FreeSSERegs, - const ABIArgInfo ¤t) const { - // Assumes vectorCall calling convention. - const Type *Base = nullptr; - uint64_t NumElts = 0; - - if (!Ty->isBuiltinType() && !Ty->isVectorType() && - isHomogeneousAggregate(Ty, Base, NumElts) && FreeSSERegs >= NumElts) { - FreeSSERegs -= NumElts; - return getDirectX86Hva(); - } - return current; -} - -ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs, - bool IsReturnType, bool IsVectorCall, - bool IsRegCall) const { - - if (Ty->isVoidType()) - return ABIArgInfo::getIgnore(); - - if (const EnumType *EnumTy = Ty->getAs<EnumType>()) - Ty = EnumTy->getDecl()->getIntegerType(); - - TypeInfo Info = getContext().getTypeInfo(Ty); - uint64_t Width = Info.Width; - CharUnits Align = getContext().toCharUnitsFromBits(Info.Align); - - const RecordType *RT = Ty->getAs<RecordType>(); - if (RT) { - if (!IsReturnType) { - if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); - } - - if (RT->getDecl()->hasFlexibleArrayMember()) - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); - - } - - const Type *Base = nullptr; - uint64_t NumElts = 0; - // vectorcall adds the concept of a homogenous vector aggregate, similar to - // other targets. - if ((IsVectorCall || IsRegCall) && - isHomogeneousAggregate(Ty, Base, NumElts)) { - if (IsRegCall) { - if (FreeSSERegs >= NumElts) { - FreeSSERegs -= NumElts; - if (IsReturnType || Ty->isBuiltinType() || Ty->isVectorType()) - return ABIArgInfo::getDirect(); - return ABIArgInfo::getExpand(); - } - return ABIArgInfo::getIndirect(Align, /*ByVal=*/false); - } else if (IsVectorCall) { - if (FreeSSERegs >= NumElts && - (IsReturnType || Ty->isBuiltinType() || Ty->isVectorType())) { - FreeSSERegs -= NumElts; - return ABIArgInfo::getDirect(); - } else if (IsReturnType) { - return ABIArgInfo::getExpand(); - } else if (!Ty->isBuiltinType() && !Ty->isVectorType()) { - // HVAs are delayed and reclassified in the 2nd step. - return ABIArgInfo::getIndirect(Align, /*ByVal=*/false); - } - } - } - - if (Ty->isMemberPointerType()) { - // If the member pointer is represented by an LLVM int or ptr, pass it - // directly. - llvm::Type *LLTy = CGT.ConvertType(Ty); - if (LLTy->isPointerTy() || LLTy->isIntegerTy()) - return ABIArgInfo::getDirect(); - } - - if (RT || Ty->isAnyComplexType() || Ty->isMemberPointerType()) { - // MS x64 ABI requirement: "Any argument that doesn't fit in 8 bytes, or is - // not 1, 2, 4, or 8 bytes, must be passed by reference." - if (Width > 64 || !llvm::isPowerOf2_64(Width)) - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); - - // Otherwise, coerce it to a small integer. - return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Width)); - } - - if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) { - switch (BT->getKind()) { - case BuiltinType::Bool: - // Bool type is always extended to the ABI, other builtin types are not - // extended. - return ABIArgInfo::getExtend(Ty); - - case BuiltinType::LongDouble: - // Mingw64 GCC uses the old 80 bit extended precision floating point - // unit. It passes them indirectly through memory. - if (IsMingw64) { - const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat(); - if (LDF == &llvm::APFloat::x87DoubleExtended()) - return ABIArgInfo::getIndirect(Align, /*ByVal=*/false); - } - break; - - case BuiltinType::Int128: - case BuiltinType::UInt128: - // If it's a parameter type, the normal ABI rule is that arguments larger - // than 8 bytes are passed indirectly. GCC follows it. We follow it too, - // even though it isn't particularly efficient. - if (!IsReturnType) - return ABIArgInfo::getIndirect(Align, /*ByVal=*/false); - - // Mingw64 GCC returns i128 in XMM0. Coerce to v2i64 to handle that. - // Clang matches them for compatibility. - return ABIArgInfo::getDirect( - llvm::VectorType::get(llvm::Type::getInt64Ty(getVMContext()), 2)); - - default: - break; - } - } - - return ABIArgInfo::getDirect(); -} - -void WinX86_64ABIInfo::computeVectorCallArgs(CGFunctionInfo &FI, - unsigned FreeSSERegs, - bool IsVectorCall, - bool IsRegCall) const { - unsigned Count = 0; - for (auto &I : FI.arguments()) { - // Vectorcall in x64 only permits the first 6 arguments to be passed - // as XMM/YMM registers. - if (Count < VectorcallMaxParamNumAsReg) - I.info = classify(I.type, FreeSSERegs, false, IsVectorCall, IsRegCall); - else { - // Since these cannot be passed in registers, pretend no registers - // are left. - unsigned ZeroSSERegsAvail = 0; - I.info = classify(I.type, /*FreeSSERegs=*/ZeroSSERegsAvail, false, - IsVectorCall, IsRegCall); - } - ++Count; - } - - for (auto &I : FI.arguments()) { - I.info = reclassifyHvaArgType(I.type, FreeSSERegs, I.info); - } -} - -void WinX86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const { - bool IsVectorCall = - FI.getCallingConvention() == llvm::CallingConv::X86_VectorCall; - bool IsRegCall = FI.getCallingConvention() == llvm::CallingConv::X86_RegCall; - - unsigned FreeSSERegs = 0; - if (IsVectorCall) { - // We can use up to 4 SSE return registers with vectorcall. - FreeSSERegs = 4; - } else if (IsRegCall) { - // RegCall gives us 16 SSE registers. - FreeSSERegs = 16; - } - - if (!getCXXABI().classifyReturnType(FI)) - FI.getReturnInfo() = classify(FI.getReturnType(), FreeSSERegs, true, - IsVectorCall, IsRegCall); - - if (IsVectorCall) { - // We can use up to 6 SSE register parameters with vectorcall. - FreeSSERegs = 6; - } else if (IsRegCall) { - // RegCall gives us 16 SSE registers, we can reuse the return registers. - FreeSSERegs = 16; - } - - if (IsVectorCall) { - computeVectorCallArgs(FI, FreeSSERegs, IsVectorCall, IsRegCall); - } else { - for (auto &I : FI.arguments()) - I.info = classify(I.type, FreeSSERegs, false, IsVectorCall, IsRegCall); - } - -} - -Address WinX86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const { - - bool IsIndirect = false; - - // MS x64 ABI requirement: "Any argument that doesn't fit in 8 bytes, or is - // not 1, 2, 4, or 8 bytes, must be passed by reference." - if (isAggregateTypeForABI(Ty) || Ty->isMemberPointerType()) { - uint64_t Width = getContext().getTypeSize(Ty); - IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width); - } - - return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect, - CGF.getContext().getTypeInfoInChars(Ty), - CharUnits::fromQuantity(8), - /*allowHigherAlign*/ false); -} - -// PowerPC-32 -namespace { -/// PPC32_SVR4_ABIInfo - The 32-bit PowerPC ELF (SVR4) ABI information. -class PPC32_SVR4_ABIInfo : public DefaultABIInfo { - bool IsSoftFloatABI; - bool IsRetSmallStructInRegABI; - - CharUnits getParamTypeAlignment(QualType Ty) const; - -public: - PPC32_SVR4_ABIInfo(CodeGen::CodeGenTypes &CGT, bool SoftFloatABI, - bool RetSmallStructInRegABI) - : DefaultABIInfo(CGT), IsSoftFloatABI(SoftFloatABI), - IsRetSmallStructInRegABI(RetSmallStructInRegABI) {} - - ABIArgInfo classifyReturnType(QualType RetTy) const; - - void computeInfo(CGFunctionInfo &FI) const override { - if (!getCXXABI().classifyReturnType(FI)) - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); - for (auto &I : FI.arguments()) - I.info = classifyArgumentType(I.type); - } - - Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const override; -}; - -class PPC32TargetCodeGenInfo : public TargetCodeGenInfo { -public: - PPC32TargetCodeGenInfo(CodeGenTypes &CGT, bool SoftFloatABI, - bool RetSmallStructInRegABI) - : TargetCodeGenInfo(new PPC32_SVR4_ABIInfo(CGT, SoftFloatABI, - RetSmallStructInRegABI)) {} - - static bool isStructReturnInRegABI(const llvm::Triple &Triple, - const CodeGenOptions &Opts); - - int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override { - // This is recovered from gcc output. - return 1; // r1 is the dedicated stack pointer - } - - bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, - llvm::Value *Address) const override; -}; -} - -CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { - // Complex types are passed just like their elements - if (const ComplexType *CTy = Ty->getAs<ComplexType>()) - Ty = CTy->getElementType(); - - if (Ty->isVectorType()) - return CharUnits::fromQuantity(getContext().getTypeSize(Ty) == 128 ? 16 - : 4); - - // For single-element float/vector structs, we consider the whole type - // to have the same alignment requirements as its single element. - const Type *AlignTy = nullptr; - if (const Type *EltType = isSingleElementStruct(Ty, getContext())) { - const BuiltinType *BT = EltType->getAs<BuiltinType>(); - if ((EltType->isVectorType() && getContext().getTypeSize(EltType) == 128) || - (BT && BT->isFloatingPoint())) - AlignTy = EltType; - } - - if (AlignTy) - return CharUnits::fromQuantity(AlignTy->isVectorType() ? 16 : 4); - return CharUnits::fromQuantity(4); -} - -ABIArgInfo PPC32_SVR4_ABIInfo::classifyReturnType(QualType RetTy) const { - uint64_t Size; - - // -msvr4-struct-return puts small aggregates in GPR3 and GPR4. - if (isAggregateTypeForABI(RetTy) && IsRetSmallStructInRegABI && - (Size = getContext().getTypeSize(RetTy)) <= 64) { - // System V ABI (1995), page 3-22, specified: - // > A structure or union whose size is less than or equal to 8 bytes - // > shall be returned in r3 and r4, as if it were first stored in the - // > 8-byte aligned memory area and then the low addressed word were - // > loaded into r3 and the high-addressed word into r4. Bits beyond - // > the last member of the structure or union are not defined. - // - // GCC for big-endian PPC32 inserts the pad before the first member, - // not "beyond the last member" of the struct. To stay compatible - // with GCC, we coerce the struct to an integer of the same size. - // LLVM will extend it and return i32 in r3, or i64 in r3:r4. - if (Size == 0) - return ABIArgInfo::getIgnore(); - else { - llvm::Type *CoerceTy = llvm::Type::getIntNTy(getVMContext(), Size); - return ABIArgInfo::getDirect(CoerceTy); - } - } - - return DefaultABIInfo::classifyReturnType(RetTy); -} - -// TODO: this implementation is now likely redundant with -// DefaultABIInfo::EmitVAArg. -Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, - QualType Ty) const { - if (getTarget().getTriple().isOSDarwin()) { - auto TI = getContext().getTypeInfoInChars(Ty); - TI.second = getParamTypeAlignment(Ty); - - CharUnits SlotSize = CharUnits::fromQuantity(4); - return emitVoidPtrVAArg(CGF, VAList, Ty, - classifyArgumentType(Ty).isIndirect(), TI, SlotSize, - /*AllowHigherAlign=*/true); - } - - const unsigned OverflowLimit = 8; - if (const ComplexType *CTy = Ty->getAs<ComplexType>()) { - // TODO: Implement this. For now ignore. - (void)CTy; - return Address::invalid(); // FIXME? - } - - // struct __va_list_tag { - // unsigned char gpr; - // unsigned char fpr; - // unsigned short reserved; - // void *overflow_arg_area; - // void *reg_save_area; - // }; - - bool isI64 = Ty->isIntegerType() && getContext().getTypeSize(Ty) == 64; - bool isInt = - Ty->isIntegerType() || Ty->isPointerType() || Ty->isAggregateType(); - bool isF64 = Ty->isFloatingType() && getContext().getTypeSize(Ty) == 64; - - // All aggregates are passed indirectly? That doesn't seem consistent - // with the argument-lowering code. - bool isIndirect = Ty->isAggregateType(); - - CGBuilderTy &Builder = CGF.Builder; - - // The calling convention either uses 1-2 GPRs or 1 FPR. - Address NumRegsAddr = Address::invalid(); - if (isInt || IsSoftFloatABI) { - NumRegsAddr = Builder.CreateStructGEP(VAList, 0, CharUnits::Zero(), "gpr"); - } else { - NumRegsAddr = Builder.CreateStructGEP(VAList, 1, CharUnits::One(), "fpr"); - } - - llvm::Value *NumRegs = Builder.CreateLoad(NumRegsAddr, "numUsedRegs"); - - // "Align" the register count when TY is i64. - if (isI64 || (isF64 && IsSoftFloatABI)) { - NumRegs = Builder.CreateAdd(NumRegs, Builder.getInt8(1)); - NumRegs = Builder.CreateAnd(NumRegs, Builder.getInt8((uint8_t) ~1U)); - } - - llvm::Value *CC = - Builder.CreateICmpULT(NumRegs, Builder.getInt8(OverflowLimit), "cond"); - - llvm::BasicBlock *UsingRegs = CGF.createBasicBlock("using_regs"); - llvm::BasicBlock *UsingOverflow = CGF.createBasicBlock("using_overflow"); - llvm::BasicBlock *Cont = CGF.createBasicBlock("cont"); - - Builder.CreateCondBr(CC, UsingRegs, UsingOverflow); - - llvm::Type *DirectTy = CGF.ConvertType(Ty); - if (isIndirect) DirectTy = DirectTy->getPointerTo(0); - - // Case 1: consume registers. - Address RegAddr = Address::invalid(); - { - CGF.EmitBlock(UsingRegs); - - Address RegSaveAreaPtr = - Builder.CreateStructGEP(VAList, 4, CharUnits::fromQuantity(8)); - RegAddr = Address(Builder.CreateLoad(RegSaveAreaPtr), - CharUnits::fromQuantity(8)); - assert(RegAddr.getElementType() == CGF.Int8Ty); - - // Floating-point registers start after the general-purpose registers. - if (!(isInt || IsSoftFloatABI)) { - RegAddr = Builder.CreateConstInBoundsByteGEP(RegAddr, - CharUnits::fromQuantity(32)); - } - - // Get the address of the saved value by scaling the number of - // registers we've used by the number of - CharUnits RegSize = CharUnits::fromQuantity((isInt || IsSoftFloatABI) ? 4 : 8); - llvm::Value *RegOffset = - Builder.CreateMul(NumRegs, Builder.getInt8(RegSize.getQuantity())); - RegAddr = Address(Builder.CreateInBoundsGEP(CGF.Int8Ty, - RegAddr.getPointer(), RegOffset), - RegAddr.getAlignment().alignmentOfArrayElement(RegSize)); - RegAddr = Builder.CreateElementBitCast(RegAddr, DirectTy); - - // Increase the used-register count. - NumRegs = - Builder.CreateAdd(NumRegs, - Builder.getInt8((isI64 || (isF64 && IsSoftFloatABI)) ? 2 : 1)); - Builder.CreateStore(NumRegs, NumRegsAddr); - - CGF.EmitBranch(Cont); - } - - // Case 2: consume space in the overflow area. - Address MemAddr = Address::invalid(); - { - CGF.EmitBlock(UsingOverflow); - - Builder.CreateStore(Builder.getInt8(OverflowLimit), NumRegsAddr); - - // Everything in the overflow area is rounded up to a size of at least 4. - CharUnits OverflowAreaAlign = CharUnits::fromQuantity(4); - - CharUnits Size; - if (!isIndirect) { - auto TypeInfo = CGF.getContext().getTypeInfoInChars(Ty); - Size = TypeInfo.first.alignTo(OverflowAreaAlign); - } else { - Size = CGF.getPointerSize(); - } - - Address OverflowAreaAddr = - Builder.CreateStructGEP(VAList, 3, CharUnits::fromQuantity(4)); - Address OverflowArea(Builder.CreateLoad(OverflowAreaAddr, "argp.cur"), - OverflowAreaAlign); - // Round up address of argument to alignment - CharUnits Align = CGF.getContext().getTypeAlignInChars(Ty); - if (Align > OverflowAreaAlign) { - llvm::Value *Ptr = OverflowArea.getPointer(); - OverflowArea = Address(emitRoundPointerUpToAlignment(CGF, Ptr, Align), - Align); - } - - MemAddr = Builder.CreateElementBitCast(OverflowArea, DirectTy); - - // Increase the overflow area. - OverflowArea = Builder.CreateConstInBoundsByteGEP(OverflowArea, Size); - Builder.CreateStore(OverflowArea.getPointer(), OverflowAreaAddr); - CGF.EmitBranch(Cont); - } - - CGF.EmitBlock(Cont); - - // Merge the cases with a phi. - Address Result = emitMergePHI(CGF, RegAddr, UsingRegs, MemAddr, UsingOverflow, - "vaarg.addr"); - - // Load the pointer if the argument was passed indirectly. - if (isIndirect) { - Result = Address(Builder.CreateLoad(Result, "aggr"), - getContext().getTypeAlignInChars(Ty)); - } - - return Result; -} - -bool PPC32TargetCodeGenInfo::isStructReturnInRegABI( - const llvm::Triple &Triple, const CodeGenOptions &Opts) { - assert(Triple.getArch() == llvm::Triple::ppc); - - switch (Opts.getStructReturnConvention()) { - case CodeGenOptions::SRCK_Default: - break; - case CodeGenOptions::SRCK_OnStack: // -maix-struct-return - return false; - case CodeGenOptions::SRCK_InRegs: // -msvr4-struct-return - return true; - } - - if (Triple.isOSBinFormatELF() && !Triple.isOSLinux()) - return true; - - return false; -} - -bool -PPC32TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, - llvm::Value *Address) const { - // This is calculated from the LLVM and GCC tables and verified - // against gcc output. AFAIK all ABIs use the same encoding. - - CodeGen::CGBuilderTy &Builder = CGF.Builder; - - llvm::IntegerType *i8 = CGF.Int8Ty; - llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4); - llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8); - llvm::Value *Sixteen8 = llvm::ConstantInt::get(i8, 16); - - // 0-31: r0-31, the 4-byte general-purpose registers - AssignToArrayRange(Builder, Address, Four8, 0, 31); - - // 32-63: fp0-31, the 8-byte floating-point registers - AssignToArrayRange(Builder, Address, Eight8, 32, 63); - - // 64-76 are various 4-byte special-purpose registers: - // 64: mq - // 65: lr - // 66: ctr - // 67: ap - // 68-75 cr0-7 - // 76: xer - AssignToArrayRange(Builder, Address, Four8, 64, 76); - - // 77-108: v0-31, the 16-byte vector registers - AssignToArrayRange(Builder, Address, Sixteen8, 77, 108); - - // 109: vrsave - // 110: vscr - // 111: spe_acc - // 112: spefscr - // 113: sfp - AssignToArrayRange(Builder, Address, Four8, 109, 113); - - return false; -} - -// PowerPC-64 - -namespace { -/// PPC64_SVR4_ABIInfo - The 64-bit PowerPC ELF (SVR4) ABI information. -class PPC64_SVR4_ABIInfo : public SwiftABIInfo { -public: - enum ABIKind { - ELFv1 = 0, - ELFv2 - }; - -private: - static const unsigned GPRBits = 64; - ABIKind Kind; - bool HasQPX; - bool IsSoftFloatABI; - - // A vector of float or double will be promoted to <4 x f32> or <4 x f64> and - // will be passed in a QPX register. - bool IsQPXVectorTy(const Type *Ty) const { - if (!HasQPX) - return false; - - if (const VectorType *VT = Ty->getAs<VectorType>()) { - unsigned NumElements = VT->getNumElements(); - if (NumElements == 1) - return false; - - if (VT->getElementType()->isSpecificBuiltinType(BuiltinType::Double)) { - if (getContext().getTypeSize(Ty) <= 256) - return true; - } else if (VT->getElementType()-> - isSpecificBuiltinType(BuiltinType::Float)) { - if (getContext().getTypeSize(Ty) <= 128) - return true; - } - } - - return false; - } - - bool IsQPXVectorTy(QualType Ty) const { - return IsQPXVectorTy(Ty.getTypePtr()); - } - -public: - PPC64_SVR4_ABIInfo(CodeGen::CodeGenTypes &CGT, ABIKind Kind, bool HasQPX, - bool SoftFloatABI) - : SwiftABIInfo(CGT), Kind(Kind), HasQPX(HasQPX), - IsSoftFloatABI(SoftFloatABI) {} - - bool isPromotableTypeForABI(QualType Ty) const; - CharUnits getParamTypeAlignment(QualType Ty) const; - - ABIArgInfo classifyReturnType(QualType RetTy) const; - ABIArgInfo classifyArgumentType(QualType Ty) const; - - bool isHomogeneousAggregateBaseType(QualType Ty) const override; - bool isHomogeneousAggregateSmallEnough(const Type *Ty, - uint64_t Members) const override; - - // TODO: We can add more logic to computeInfo to improve performance. - // Example: For aggregate arguments that fit in a register, we could - // use getDirectInReg (as is done below for structs containing a single - // floating-point value) to avoid pushing them to memory on function - // entry. This would require changing the logic in PPCISelLowering - // when lowering the parameters in the caller and args in the callee. - void computeInfo(CGFunctionInfo &FI) const override { - if (!getCXXABI().classifyReturnType(FI)) - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); - for (auto &I : FI.arguments()) { - // We rely on the default argument classification for the most part. - // One exception: An aggregate containing a single floating-point - // or vector item must be passed in a register if one is available. - const Type *T = isSingleElementStruct(I.type, getContext()); - if (T) { - const BuiltinType *BT = T->getAs<BuiltinType>(); - if (IsQPXVectorTy(T) || - (T->isVectorType() && getContext().getTypeSize(T) == 128) || - (BT && BT->isFloatingPoint())) { - QualType QT(T, 0); - I.info = ABIArgInfo::getDirectInReg(CGT.ConvertType(QT)); - continue; - } - } - I.info = classifyArgumentType(I.type); - } - } - - Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const override; - - bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> scalars, - bool asReturnValue) const override { - return occupiesMoreThan(CGT, scalars, /*total*/ 4); - } - - bool isSwiftErrorInRegister() const override { - return false; - } -}; - -class PPC64_SVR4_TargetCodeGenInfo : public TargetCodeGenInfo { - -public: - PPC64_SVR4_TargetCodeGenInfo(CodeGenTypes &CGT, - PPC64_SVR4_ABIInfo::ABIKind Kind, bool HasQPX, - bool SoftFloatABI) - : TargetCodeGenInfo(new PPC64_SVR4_ABIInfo(CGT, Kind, HasQPX, - SoftFloatABI)) {} - - int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override { - // This is recovered from gcc output. - return 1; // r1 is the dedicated stack pointer - } - - bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, - llvm::Value *Address) const override; -}; - -class PPC64TargetCodeGenInfo : public DefaultTargetCodeGenInfo { -public: - PPC64TargetCodeGenInfo(CodeGenTypes &CGT) : DefaultTargetCodeGenInfo(CGT) {} - - int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override { - // This is recovered from gcc output. - return 1; // r1 is the dedicated stack pointer - } - - bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, - llvm::Value *Address) const override; -}; - -} - -// Return true if the ABI requires Ty to be passed sign- or zero- -// extended to 64 bits. -bool -PPC64_SVR4_ABIInfo::isPromotableTypeForABI(QualType Ty) const { - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = Ty->getAs<EnumType>()) - Ty = EnumTy->getDecl()->getIntegerType(); - - // Promotable integer types are required to be promoted by the ABI. - if (Ty->isPromotableIntegerType()) - return true; - - // In addition to the usual promotable integer types, we also need to - // extend all 32-bit types, since the ABI requires promotion to 64 bits. - if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) - switch (BT->getKind()) { - case BuiltinType::Int: - case BuiltinType::UInt: - return true; - default: - break; - } - - return false; -} - -/// isAlignedParamType - Determine whether a type requires 16-byte or -/// higher alignment in the parameter area. Always returns at least 8. -CharUnits PPC64_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { - // Complex types are passed just like their elements. - if (const ComplexType *CTy = Ty->getAs<ComplexType>()) - Ty = CTy->getElementType(); - - // Only vector types of size 16 bytes need alignment (larger types are - // passed via reference, smaller types are not aligned). - if (IsQPXVectorTy(Ty)) { - if (getContext().getTypeSize(Ty) > 128) - return CharUnits::fromQuantity(32); - - return CharUnits::fromQuantity(16); - } else if (Ty->isVectorType()) { - return CharUnits::fromQuantity(getContext().getTypeSize(Ty) == 128 ? 16 : 8); - } - - // For single-element float/vector structs, we consider the whole type - // to have the same alignment requirements as its single element. - const Type *AlignAsType = nullptr; - const Type *EltType = isSingleElementStruct(Ty, getContext()); - if (EltType) { - const BuiltinType *BT = EltType->getAs<BuiltinType>(); - if (IsQPXVectorTy(EltType) || (EltType->isVectorType() && - getContext().getTypeSize(EltType) == 128) || - (BT && BT->isFloatingPoint())) - AlignAsType = EltType; - } - - // Likewise for ELFv2 homogeneous aggregates. - const Type *Base = nullptr; - uint64_t Members = 0; - if (!AlignAsType && Kind == ELFv2 && - isAggregateTypeForABI(Ty) && isHomogeneousAggregate(Ty, Base, Members)) - AlignAsType = Base; - - // With special case aggregates, only vector base types need alignment. - if (AlignAsType && IsQPXVectorTy(AlignAsType)) { - if (getContext().getTypeSize(AlignAsType) > 128) - return CharUnits::fromQuantity(32); - - return CharUnits::fromQuantity(16); - } else if (AlignAsType) { - return CharUnits::fromQuantity(AlignAsType->isVectorType() ? 16 : 8); - } - - // Otherwise, we only need alignment for any aggregate type that - // has an alignment requirement of >= 16 bytes. - if (isAggregateTypeForABI(Ty) && getContext().getTypeAlign(Ty) >= 128) { - if (HasQPX && getContext().getTypeAlign(Ty) >= 256) - return CharUnits::fromQuantity(32); - return CharUnits::fromQuantity(16); - } - - return CharUnits::fromQuantity(8); -} - -/// isHomogeneousAggregate - Return true if a type is an ELFv2 homogeneous -/// aggregate. Base is set to the base element type, and Members is set -/// to the number of base elements. -bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base, - uint64_t &Members) const { - if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) { - uint64_t NElements = AT->getSize().getZExtValue(); - if (NElements == 0) - return false; - if (!isHomogeneousAggregate(AT->getElementType(), Base, Members)) - return false; - Members *= NElements; - } else if (const RecordType *RT = Ty->getAs<RecordType>()) { - const RecordDecl *RD = RT->getDecl(); - if (RD->hasFlexibleArrayMember()) - return false; - - Members = 0; - - // If this is a C++ record, check the bases first. - if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) { - for (const auto &I : CXXRD->bases()) { - // Ignore empty records. - if (isEmptyRecord(getContext(), I.getType(), true)) - continue; - - uint64_t FldMembers; - if (!isHomogeneousAggregate(I.getType(), Base, FldMembers)) - return false; - - Members += FldMembers; - } - } - - for (const auto *FD : RD->fields()) { - // Ignore (non-zero arrays of) empty records. - QualType FT = FD->getType(); - while (const ConstantArrayType *AT = - getContext().getAsConstantArrayType(FT)) { - if (AT->getSize().getZExtValue() == 0) - return false; - FT = AT->getElementType(); - } - if (isEmptyRecord(getContext(), FT, true)) - continue; - - // For compatibility with GCC, ignore empty bitfields in C++ mode. - if (getContext().getLangOpts().CPlusPlus && - FD->isZeroLengthBitField(getContext())) - continue; - - uint64_t FldMembers; - if (!isHomogeneousAggregate(FD->getType(), Base, FldMembers)) - return false; - - Members = (RD->isUnion() ? - std::max(Members, FldMembers) : Members + FldMembers); - } - - if (!Base) - return false; - - // Ensure there is no padding. - if (getContext().getTypeSize(Base) * Members != - getContext().getTypeSize(Ty)) - return false; - } else { - Members = 1; - if (const ComplexType *CT = Ty->getAs<ComplexType>()) { - Members = 2; - Ty = CT->getElementType(); - } - - // Most ABIs only support float, double, and some vector type widths. - if (!isHomogeneousAggregateBaseType(Ty)) - return false; - - // The base type must be the same for all members. Types that - // agree in both total size and mode (float vs. vector) are - // treated as being equivalent here. - const Type *TyPtr = Ty.getTypePtr(); - if (!Base) { - Base = TyPtr; - // If it's a non-power-of-2 vector, its size is already a power-of-2, - // so make sure to widen it explicitly. - if (const VectorType *VT = Base->getAs<VectorType>()) { - QualType EltTy = VT->getElementType(); - unsigned NumElements = - getContext().getTypeSize(VT) / getContext().getTypeSize(EltTy); - Base = getContext() - .getVectorType(EltTy, NumElements, VT->getVectorKind()) - .getTypePtr(); - } - } - - if (Base->isVectorType() != TyPtr->isVectorType() || - getContext().getTypeSize(Base) != getContext().getTypeSize(TyPtr)) - return false; - } - return Members > 0 && isHomogeneousAggregateSmallEnough(Base, Members); -} - -bool PPC64_SVR4_ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const { - // Homogeneous aggregates for ELFv2 must have base types of float, - // double, long double, or 128-bit vectors. - if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) { - if (BT->getKind() == BuiltinType::Float || - BT->getKind() == BuiltinType::Double || - BT->getKind() == BuiltinType::LongDouble || - (getContext().getTargetInfo().hasFloat128Type() && - (BT->getKind() == BuiltinType::Float128))) { - if (IsSoftFloatABI) - return false; - return true; - } - } - if (const VectorType *VT = Ty->getAs<VectorType>()) { - if (getContext().getTypeSize(VT) == 128 || IsQPXVectorTy(Ty)) - return true; - } - return false; -} - -bool PPC64_SVR4_ABIInfo::isHomogeneousAggregateSmallEnough( - const Type *Base, uint64_t Members) const { - // Vector and fp128 types require one register, other floating point types - // require one or two registers depending on their size. - uint32_t NumRegs = - ((getContext().getTargetInfo().hasFloat128Type() && - Base->isFloat128Type()) || - Base->isVectorType()) ? 1 - : (getContext().getTypeSize(Base) + 63) / 64; - - // Homogeneous Aggregates may occupy at most 8 registers. - return Members * NumRegs <= 8; -} - -ABIArgInfo -PPC64_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const { - Ty = useFirstFieldIfTransparentUnion(Ty); - - if (Ty->isAnyComplexType()) - return ABIArgInfo::getDirect(); - - // Non-Altivec vector types are passed in GPRs (smaller than 16 bytes) - // or via reference (larger than 16 bytes). - if (Ty->isVectorType() && !IsQPXVectorTy(Ty)) { - uint64_t Size = getContext().getTypeSize(Ty); - if (Size > 128) - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); - else if (Size < 128) { - llvm::Type *CoerceTy = llvm::IntegerType::get(getVMContext(), Size); - return ABIArgInfo::getDirect(CoerceTy); - } - } - - if (isAggregateTypeForABI(Ty)) { - if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); - - uint64_t ABIAlign = getParamTypeAlignment(Ty).getQuantity(); - uint64_t TyAlign = getContext().getTypeAlignInChars(Ty).getQuantity(); - - // ELFv2 homogeneous aggregates are passed as array types. - const Type *Base = nullptr; - uint64_t Members = 0; - if (Kind == ELFv2 && - isHomogeneousAggregate(Ty, Base, Members)) { - llvm::Type *BaseTy = CGT.ConvertType(QualType(Base, 0)); - llvm::Type *CoerceTy = llvm::ArrayType::get(BaseTy, Members); - return ABIArgInfo::getDirect(CoerceTy); - } - - // If an aggregate may end up fully in registers, we do not - // use the ByVal method, but pass the aggregate as array. - // This is usually beneficial since we avoid forcing the - // back-end to store the argument to memory. - uint64_t Bits = getContext().getTypeSize(Ty); - if (Bits > 0 && Bits <= 8 * GPRBits) { - llvm::Type *CoerceTy; - - // Types up to 8 bytes are passed as integer type (which will be - // properly aligned in the argument save area doubleword). - if (Bits <= GPRBits) - CoerceTy = - llvm::IntegerType::get(getVMContext(), llvm::alignTo(Bits, 8)); - // Larger types are passed as arrays, with the base type selected - // according to the required alignment in the save area. - else { - uint64_t RegBits = ABIAlign * 8; - uint64_t NumRegs = llvm::alignTo(Bits, RegBits) / RegBits; - llvm::Type *RegTy = llvm::IntegerType::get(getVMContext(), RegBits); - CoerceTy = llvm::ArrayType::get(RegTy, NumRegs); - } - - return ABIArgInfo::getDirect(CoerceTy); - } - - // All other aggregates are passed ByVal. - return ABIArgInfo::getIndirect(CharUnits::fromQuantity(ABIAlign), - /*ByVal=*/true, - /*Realign=*/TyAlign > ABIAlign); - } - - return (isPromotableTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect()); -} - -ABIArgInfo -PPC64_SVR4_ABIInfo::classifyReturnType(QualType RetTy) const { - if (RetTy->isVoidType()) - return ABIArgInfo::getIgnore(); - - if (RetTy->isAnyComplexType()) - return ABIArgInfo::getDirect(); - - // Non-Altivec vector types are returned in GPRs (smaller than 16 bytes) - // or via reference (larger than 16 bytes). - if (RetTy->isVectorType() && !IsQPXVectorTy(RetTy)) { - uint64_t Size = getContext().getTypeSize(RetTy); - if (Size > 128) - return getNaturalAlignIndirect(RetTy); - else if (Size < 128) { - llvm::Type *CoerceTy = llvm::IntegerType::get(getVMContext(), Size); - return ABIArgInfo::getDirect(CoerceTy); - } - } - - if (isAggregateTypeForABI(RetTy)) { - // ELFv2 homogeneous aggregates are returned as array types. - const Type *Base = nullptr; - uint64_t Members = 0; - if (Kind == ELFv2 && - isHomogeneousAggregate(RetTy, Base, Members)) { - llvm::Type *BaseTy = CGT.ConvertType(QualType(Base, 0)); - llvm::Type *CoerceTy = llvm::ArrayType::get(BaseTy, Members); - return ABIArgInfo::getDirect(CoerceTy); - } - - // ELFv2 small aggregates are returned in up to two registers. - uint64_t Bits = getContext().getTypeSize(RetTy); - if (Kind == ELFv2 && Bits <= 2 * GPRBits) { - if (Bits == 0) - return ABIArgInfo::getIgnore(); - - llvm::Type *CoerceTy; - if (Bits > GPRBits) { - CoerceTy = llvm::IntegerType::get(getVMContext(), GPRBits); - CoerceTy = llvm::StructType::get(CoerceTy, CoerceTy); - } else - CoerceTy = - llvm::IntegerType::get(getVMContext(), llvm::alignTo(Bits, 8)); - return ABIArgInfo::getDirect(CoerceTy); - } - - // All other aggregates are returned indirectly. - return getNaturalAlignIndirect(RetTy); - } - - return (isPromotableTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) - : ABIArgInfo::getDirect()); -} - -// Based on ARMABIInfo::EmitVAArg, adjusted for 64-bit machine. -Address PPC64_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const { - auto TypeInfo = getContext().getTypeInfoInChars(Ty); - TypeInfo.second = getParamTypeAlignment(Ty); - - CharUnits SlotSize = CharUnits::fromQuantity(8); - - // If we have a complex type and the base type is smaller than 8 bytes, - // the ABI calls for the real and imaginary parts to be right-adjusted - // in separate doublewords. However, Clang expects us to produce a - // pointer to a structure with the two parts packed tightly. So generate - // loads of the real and imaginary parts relative to the va_list pointer, - // and store them to a temporary structure. - if (const ComplexType *CTy = Ty->getAs<ComplexType>()) { - CharUnits EltSize = TypeInfo.first / 2; - if (EltSize < SlotSize) { - Address Addr = emitVoidPtrDirectVAArg(CGF, VAListAddr, CGF.Int8Ty, - SlotSize * 2, SlotSize, - SlotSize, /*AllowHigher*/ true); - - Address RealAddr = Addr; - Address ImagAddr = RealAddr; - if (CGF.CGM.getDataLayout().isBigEndian()) { - RealAddr = CGF.Builder.CreateConstInBoundsByteGEP(RealAddr, - SlotSize - EltSize); - ImagAddr = CGF.Builder.CreateConstInBoundsByteGEP(ImagAddr, - 2 * SlotSize - EltSize); - } else { - ImagAddr = CGF.Builder.CreateConstInBoundsByteGEP(RealAddr, SlotSize); - } - - llvm::Type *EltTy = CGF.ConvertTypeForMem(CTy->getElementType()); - RealAddr = CGF.Builder.CreateElementBitCast(RealAddr, EltTy); - ImagAddr = CGF.Builder.CreateElementBitCast(ImagAddr, EltTy); - llvm::Value *Real = CGF.Builder.CreateLoad(RealAddr, ".vareal"); - llvm::Value *Imag = CGF.Builder.CreateLoad(ImagAddr, ".vaimag"); - - Address Temp = CGF.CreateMemTemp(Ty, "vacplx"); - CGF.EmitStoreOfComplex({Real, Imag}, CGF.MakeAddrLValue(Temp, Ty), - /*init*/ true); - return Temp; - } - } - - // Otherwise, just use the general rule. - return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*Indirect*/ false, - TypeInfo, SlotSize, /*AllowHigher*/ true); -} - -static bool -PPC64_initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, - llvm::Value *Address) { - // This is calculated from the LLVM and GCC tables and verified - // against gcc output. AFAIK all ABIs use the same encoding. - - CodeGen::CGBuilderTy &Builder = CGF.Builder; - - llvm::IntegerType *i8 = CGF.Int8Ty; - llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4); - llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8); - llvm::Value *Sixteen8 = llvm::ConstantInt::get(i8, 16); - - // 0-31: r0-31, the 8-byte general-purpose registers - AssignToArrayRange(Builder, Address, Eight8, 0, 31); - - // 32-63: fp0-31, the 8-byte floating-point registers - AssignToArrayRange(Builder, Address, Eight8, 32, 63); - - // 64-67 are various 8-byte special-purpose registers: - // 64: mq - // 65: lr - // 66: ctr - // 67: ap - AssignToArrayRange(Builder, Address, Eight8, 64, 67); - - // 68-76 are various 4-byte special-purpose registers: - // 68-75 cr0-7 - // 76: xer - AssignToArrayRange(Builder, Address, Four8, 68, 76); - - // 77-108: v0-31, the 16-byte vector registers - AssignToArrayRange(Builder, Address, Sixteen8, 77, 108); - - // 109: vrsave - // 110: vscr - // 111: spe_acc - // 112: spefscr - // 113: sfp - // 114: tfhar - // 115: tfiar - // 116: texasr - AssignToArrayRange(Builder, Address, Eight8, 109, 116); - - return false; -} - -bool -PPC64_SVR4_TargetCodeGenInfo::initDwarfEHRegSizeTable( - CodeGen::CodeGenFunction &CGF, - llvm::Value *Address) const { - - return PPC64_initDwarfEHRegSizeTable(CGF, Address); -} - -bool -PPC64TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, - llvm::Value *Address) const { - - return PPC64_initDwarfEHRegSizeTable(CGF, Address); -} - -//===----------------------------------------------------------------------===// -// AArch64 ABI Implementation -//===----------------------------------------------------------------------===// - -namespace { - -class AArch64ABIInfo : public SwiftABIInfo { -public: - enum ABIKind { - AAPCS = 0, - DarwinPCS, - Win64 - }; - -private: - ABIKind Kind; - -public: - AArch64ABIInfo(CodeGenTypes &CGT, ABIKind Kind) - : SwiftABIInfo(CGT), Kind(Kind) {} - -private: - ABIKind getABIKind() const { return Kind; } - bool isDarwinPCS() const { return Kind == DarwinPCS; } - - ABIArgInfo classifyReturnType(QualType RetTy) const; - ABIArgInfo classifyArgumentType(QualType RetTy) const; - bool isHomogeneousAggregateBaseType(QualType Ty) const override; - bool isHomogeneousAggregateSmallEnough(const Type *Ty, - uint64_t Members) const override; - - bool isIllegalVectorType(QualType Ty) const; - - void computeInfo(CGFunctionInfo &FI) const override { - if (!::classifyReturnType(getCXXABI(), FI, *this)) - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); - - for (auto &it : FI.arguments()) - it.info = classifyArgumentType(it.type); - } - - Address EmitDarwinVAArg(Address VAListAddr, QualType Ty, - CodeGenFunction &CGF) const; - - Address EmitAAPCSVAArg(Address VAListAddr, QualType Ty, - CodeGenFunction &CGF) const; - - Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const override { - return Kind == Win64 ? EmitMSVAArg(CGF, VAListAddr, Ty) - : isDarwinPCS() ? EmitDarwinVAArg(VAListAddr, Ty, CGF) - : EmitAAPCSVAArg(VAListAddr, Ty, CGF); - } - - Address EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const override; - - bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> scalars, - bool asReturnValue) const override { - return occupiesMoreThan(CGT, scalars, /*total*/ 4); - } - bool isSwiftErrorInRegister() const override { - return true; - } - - bool isLegalVectorTypeForSwift(CharUnits totalSize, llvm::Type *eltTy, - unsigned elts) const override; -}; - -class AArch64TargetCodeGenInfo : public TargetCodeGenInfo { -public: - AArch64TargetCodeGenInfo(CodeGenTypes &CGT, AArch64ABIInfo::ABIKind Kind) - : TargetCodeGenInfo(new AArch64ABIInfo(CGT, Kind)) {} - - StringRef getARCRetainAutoreleasedReturnValueMarker() const override { - return "mov\tfp, fp\t\t// marker for objc_retainAutoreleaseReturnValue"; - } - - int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override { - return 31; - } - - bool doesReturnSlotInterfereWithArgs() const override { return false; } - - void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &CGM) const override { - const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D); - if (!FD) - return; - llvm::Function *Fn = cast<llvm::Function>(GV); - - auto Kind = CGM.getCodeGenOpts().getSignReturnAddress(); - if (Kind != CodeGenOptions::SignReturnAddressScope::None) { - Fn->addFnAttr("sign-return-address", - Kind == CodeGenOptions::SignReturnAddressScope::All - ? "all" - : "non-leaf"); - - auto Key = CGM.getCodeGenOpts().getSignReturnAddressKey(); - Fn->addFnAttr("sign-return-address-key", - Key == CodeGenOptions::SignReturnAddressKeyValue::AKey - ? "a_key" - : "b_key"); - } - - if (CGM.getCodeGenOpts().BranchTargetEnforcement) - Fn->addFnAttr("branch-target-enforcement"); - } -}; - -class WindowsAArch64TargetCodeGenInfo : public AArch64TargetCodeGenInfo { -public: - WindowsAArch64TargetCodeGenInfo(CodeGenTypes &CGT, AArch64ABIInfo::ABIKind K) - : AArch64TargetCodeGenInfo(CGT, K) {} - - void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &CGM) const override; - - void getDependentLibraryOption(llvm::StringRef Lib, - llvm::SmallString<24> &Opt) const override { - Opt = "/DEFAULTLIB:" + qualifyWindowsLibrary(Lib); - } - - void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef Value, - llvm::SmallString<32> &Opt) const override { - Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\""; - } -}; - -void WindowsAArch64TargetCodeGenInfo::setTargetAttributes( - const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const { - AArch64TargetCodeGenInfo::setTargetAttributes(D, GV, CGM); - if (GV->isDeclaration()) - return; - addStackProbeTargetAttributes(D, GV, CGM); -} -} - -ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty) const { - Ty = useFirstFieldIfTransparentUnion(Ty); - - // Handle illegal vector types here. - if (isIllegalVectorType(Ty)) { - uint64_t Size = getContext().getTypeSize(Ty); - // Android promotes <2 x i8> to i16, not i32 - if (isAndroid() && (Size <= 16)) { - llvm::Type *ResType = llvm::Type::getInt16Ty(getVMContext()); - return ABIArgInfo::getDirect(ResType); - } - if (Size <= 32) { - llvm::Type *ResType = llvm::Type::getInt32Ty(getVMContext()); - return ABIArgInfo::getDirect(ResType); - } - if (Size == 64) { - llvm::Type *ResType = - llvm::VectorType::get(llvm::Type::getInt32Ty(getVMContext()), 2); - return ABIArgInfo::getDirect(ResType); - } - if (Size == 128) { - llvm::Type *ResType = - llvm::VectorType::get(llvm::Type::getInt32Ty(getVMContext()), 4); - return ABIArgInfo::getDirect(ResType); - } - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); - } - - if (!isAggregateTypeForABI(Ty)) { - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = Ty->getAs<EnumType>()) - Ty = EnumTy->getDecl()->getIntegerType(); - - return (Ty->isPromotableIntegerType() && isDarwinPCS() - ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect()); - } - - // Structures with either a non-trivial destructor or a non-trivial - // copy constructor are always indirect. - if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { - return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA == - CGCXXABI::RAA_DirectInMemory); - } - - // Empty records are always ignored on Darwin, but actually passed in C++ mode - // elsewhere for GNU compatibility. - uint64_t Size = getContext().getTypeSize(Ty); - bool IsEmpty = isEmptyRecord(getContext(), Ty, true); - if (IsEmpty || Size == 0) { - if (!getContext().getLangOpts().CPlusPlus || isDarwinPCS()) - return ABIArgInfo::getIgnore(); - - // GNU C mode. The only argument that gets ignored is an empty one with size - // 0. - if (IsEmpty && Size == 0) - return ABIArgInfo::getIgnore(); - return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext())); - } - - // Homogeneous Floating-point Aggregates (HFAs) need to be expanded. - const Type *Base = nullptr; - uint64_t Members = 0; - if (isHomogeneousAggregate(Ty, Base, Members)) { - return ABIArgInfo::getDirect( - llvm::ArrayType::get(CGT.ConvertType(QualType(Base, 0)), Members)); - } - - // Aggregates <= 16 bytes are passed directly in registers or on the stack. - if (Size <= 128) { - // On RenderScript, coerce Aggregates <= 16 bytes to an integer array of - // same size and alignment. - if (getTarget().isRenderScriptTarget()) { - return coerceToIntArray(Ty, getContext(), getVMContext()); - } - unsigned Alignment; - if (Kind == AArch64ABIInfo::AAPCS) { - Alignment = getContext().getTypeUnadjustedAlign(Ty); - Alignment = Alignment < 128 ? 64 : 128; - } else { - Alignment = getContext().getTypeAlign(Ty); - } - Size = llvm::alignTo(Size, 64); // round up to multiple of 8 bytes - - // We use a pair of i64 for 16-byte aggregate with 8-byte alignment. - // For aggregates with 16-byte alignment, we use i128. - if (Alignment < 128 && Size == 128) { - llvm::Type *BaseTy = llvm::Type::getInt64Ty(getVMContext()); - return ABIArgInfo::getDirect(llvm::ArrayType::get(BaseTy, Size / 64)); - } - return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Size)); - } - - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); -} - -ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy) const { - if (RetTy->isVoidType()) - return ABIArgInfo::getIgnore(); - - // Large vector types should be returned via memory. - if (RetTy->isVectorType() && getContext().getTypeSize(RetTy) > 128) - return getNaturalAlignIndirect(RetTy); - - if (!isAggregateTypeForABI(RetTy)) { - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) - RetTy = EnumTy->getDecl()->getIntegerType(); - - return (RetTy->isPromotableIntegerType() && isDarwinPCS() - ? ABIArgInfo::getExtend(RetTy) - : ABIArgInfo::getDirect()); - } - - uint64_t Size = getContext().getTypeSize(RetTy); - if (isEmptyRecord(getContext(), RetTy, true) || Size == 0) - return ABIArgInfo::getIgnore(); - - const Type *Base = nullptr; - uint64_t Members = 0; - if (isHomogeneousAggregate(RetTy, Base, Members)) - // Homogeneous Floating-point Aggregates (HFAs) are returned directly. - return ABIArgInfo::getDirect(); - - // Aggregates <= 16 bytes are returned directly in registers or on the stack. - if (Size <= 128) { - // On RenderScript, coerce Aggregates <= 16 bytes to an integer array of - // same size and alignment. - if (getTarget().isRenderScriptTarget()) { - return coerceToIntArray(RetTy, getContext(), getVMContext()); - } - unsigned Alignment = getContext().getTypeAlign(RetTy); - Size = llvm::alignTo(Size, 64); // round up to multiple of 8 bytes - - // We use a pair of i64 for 16-byte aggregate with 8-byte alignment. - // For aggregates with 16-byte alignment, we use i128. - if (Alignment < 128 && Size == 128) { - llvm::Type *BaseTy = llvm::Type::getInt64Ty(getVMContext()); - return ABIArgInfo::getDirect(llvm::ArrayType::get(BaseTy, Size / 64)); - } - return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Size)); - } - - return getNaturalAlignIndirect(RetTy); -} - -/// isIllegalVectorType - check whether the vector type is legal for AArch64. -bool AArch64ABIInfo::isIllegalVectorType(QualType Ty) const { - if (const VectorType *VT = Ty->getAs<VectorType>()) { - // Check whether VT is legal. - unsigned NumElements = VT->getNumElements(); - uint64_t Size = getContext().getTypeSize(VT); - // NumElements should be power of 2. - if (!llvm::isPowerOf2_32(NumElements)) - return true; - return Size != 64 && (Size != 128 || NumElements == 1); - } - return false; -} - -bool AArch64ABIInfo::isLegalVectorTypeForSwift(CharUnits totalSize, - llvm::Type *eltTy, - unsigned elts) const { - if (!llvm::isPowerOf2_32(elts)) - return false; - if (totalSize.getQuantity() != 8 && - (totalSize.getQuantity() != 16 || elts == 1)) - return false; - return true; -} - -bool AArch64ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const { - // Homogeneous aggregates for AAPCS64 must have base types of a floating - // point type or a short-vector type. This is the same as the 32-bit ABI, - // but with the difference that any floating-point type is allowed, - // including __fp16. - if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) { - if (BT->isFloatingPoint()) - return true; - } else if (const VectorType *VT = Ty->getAs<VectorType>()) { - unsigned VecSize = getContext().getTypeSize(VT); - if (VecSize == 64 || VecSize == 128) - return true; - } - return false; -} - -bool AArch64ABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base, - uint64_t Members) const { - return Members <= 4; -} - -Address AArch64ABIInfo::EmitAAPCSVAArg(Address VAListAddr, - QualType Ty, - CodeGenFunction &CGF) const { - ABIArgInfo AI = classifyArgumentType(Ty); - bool IsIndirect = AI.isIndirect(); - - llvm::Type *BaseTy = CGF.ConvertType(Ty); - if (IsIndirect) - BaseTy = llvm::PointerType::getUnqual(BaseTy); - else if (AI.getCoerceToType()) - BaseTy = AI.getCoerceToType(); - - unsigned NumRegs = 1; - if (llvm::ArrayType *ArrTy = dyn_cast<llvm::ArrayType>(BaseTy)) { - BaseTy = ArrTy->getElementType(); - NumRegs = ArrTy->getNumElements(); - } - bool IsFPR = BaseTy->isFloatingPointTy() || BaseTy->isVectorTy(); - - // The AArch64 va_list type and handling is specified in the Procedure Call - // Standard, section B.4: - // - // struct { - // void *__stack; - // void *__gr_top; - // void *__vr_top; - // int __gr_offs; - // int __vr_offs; - // }; - - llvm::BasicBlock *MaybeRegBlock = CGF.createBasicBlock("vaarg.maybe_reg"); - llvm::BasicBlock *InRegBlock = CGF.createBasicBlock("vaarg.in_reg"); - llvm::BasicBlock *OnStackBlock = CGF.createBasicBlock("vaarg.on_stack"); - llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end"); - - auto TyInfo = getContext().getTypeInfoInChars(Ty); - CharUnits TyAlign = TyInfo.second; - - Address reg_offs_p = Address::invalid(); - llvm::Value *reg_offs = nullptr; - int reg_top_index; - CharUnits reg_top_offset; - int RegSize = IsIndirect ? 8 : TyInfo.first.getQuantity(); - if (!IsFPR) { - // 3 is the field number of __gr_offs - reg_offs_p = - CGF.Builder.CreateStructGEP(VAListAddr, 3, CharUnits::fromQuantity(24), - "gr_offs_p"); - reg_offs = CGF.Builder.CreateLoad(reg_offs_p, "gr_offs"); - reg_top_index = 1; // field number for __gr_top - reg_top_offset = CharUnits::fromQuantity(8); - RegSize = llvm::alignTo(RegSize, 8); - } else { - // 4 is the field number of __vr_offs. - reg_offs_p = - CGF.Builder.CreateStructGEP(VAListAddr, 4, CharUnits::fromQuantity(28), - "vr_offs_p"); - reg_offs = CGF.Builder.CreateLoad(reg_offs_p, "vr_offs"); - reg_top_index = 2; // field number for __vr_top - reg_top_offset = CharUnits::fromQuantity(16); - RegSize = 16 * NumRegs; - } - - //======================================= - // Find out where argument was passed - //======================================= - - // If reg_offs >= 0 we're already using the stack for this type of - // argument. We don't want to keep updating reg_offs (in case it overflows, - // though anyone passing 2GB of arguments, each at most 16 bytes, deserves - // whatever they get). - llvm::Value *UsingStack = nullptr; - UsingStack = CGF.Builder.CreateICmpSGE( - reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, 0)); - - CGF.Builder.CreateCondBr(UsingStack, OnStackBlock, MaybeRegBlock); - - // Otherwise, at least some kind of argument could go in these registers, the - // question is whether this particular type is too big. - CGF.EmitBlock(MaybeRegBlock); - - // Integer arguments may need to correct register alignment (for example a - // "struct { __int128 a; };" gets passed in x_2N, x_{2N+1}). In this case we - // align __gr_offs to calculate the potential address. - if (!IsFPR && !IsIndirect && TyAlign.getQuantity() > 8) { - int Align = TyAlign.getQuantity(); - - reg_offs = CGF.Builder.CreateAdd( - reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, Align - 1), - "align_regoffs"); - reg_offs = CGF.Builder.CreateAnd( - reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, -Align), - "aligned_regoffs"); - } - - // Update the gr_offs/vr_offs pointer for next call to va_arg on this va_list. - // The fact that this is done unconditionally reflects the fact that - // allocating an argument to the stack also uses up all the remaining - // registers of the appropriate kind. - llvm::Value *NewOffset = nullptr; - NewOffset = CGF.Builder.CreateAdd( - reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, RegSize), "new_reg_offs"); - CGF.Builder.CreateStore(NewOffset, reg_offs_p); - - // Now we're in a position to decide whether this argument really was in - // registers or not. - llvm::Value *InRegs = nullptr; - InRegs = CGF.Builder.CreateICmpSLE( - NewOffset, llvm::ConstantInt::get(CGF.Int32Ty, 0), "inreg"); - - CGF.Builder.CreateCondBr(InRegs, InRegBlock, OnStackBlock); - - //======================================= - // Argument was in registers - //======================================= - - // Now we emit the code for if the argument was originally passed in - // registers. First start the appropriate block: - CGF.EmitBlock(InRegBlock); - - llvm::Value *reg_top = nullptr; - Address reg_top_p = CGF.Builder.CreateStructGEP(VAListAddr, reg_top_index, - reg_top_offset, "reg_top_p"); - reg_top = CGF.Builder.CreateLoad(reg_top_p, "reg_top"); - Address BaseAddr(CGF.Builder.CreateInBoundsGEP(reg_top, reg_offs), - CharUnits::fromQuantity(IsFPR ? 16 : 8)); - Address RegAddr = Address::invalid(); - llvm::Type *MemTy = CGF.ConvertTypeForMem(Ty); - - if (IsIndirect) { - // If it's been passed indirectly (actually a struct), whatever we find from - // stored registers or on the stack will actually be a struct **. - MemTy = llvm::PointerType::getUnqual(MemTy); - } - - const Type *Base = nullptr; - uint64_t NumMembers = 0; - bool IsHFA = isHomogeneousAggregate(Ty, Base, NumMembers); - if (IsHFA && NumMembers > 1) { - // Homogeneous aggregates passed in registers will have their elements split - // and stored 16-bytes apart regardless of size (they're notionally in qN, - // qN+1, ...). We reload and store into a temporary local variable - // contiguously. - assert(!IsIndirect && "Homogeneous aggregates should be passed directly"); - auto BaseTyInfo = getContext().getTypeInfoInChars(QualType(Base, 0)); - llvm::Type *BaseTy = CGF.ConvertType(QualType(Base, 0)); - llvm::Type *HFATy = llvm::ArrayType::get(BaseTy, NumMembers); - Address Tmp = CGF.CreateTempAlloca(HFATy, - std::max(TyAlign, BaseTyInfo.second)); - - // On big-endian platforms, the value will be right-aligned in its slot. - int Offset = 0; - if (CGF.CGM.getDataLayout().isBigEndian() && - BaseTyInfo.first.getQuantity() < 16) - Offset = 16 - BaseTyInfo.first.getQuantity(); - - for (unsigned i = 0; i < NumMembers; ++i) { - CharUnits BaseOffset = CharUnits::fromQuantity(16 * i + Offset); - Address LoadAddr = - CGF.Builder.CreateConstInBoundsByteGEP(BaseAddr, BaseOffset); - LoadAddr = CGF.Builder.CreateElementBitCast(LoadAddr, BaseTy); - - Address StoreAddr = - CGF.Builder.CreateConstArrayGEP(Tmp, i, BaseTyInfo.first); - - llvm::Value *Elem = CGF.Builder.CreateLoad(LoadAddr); - CGF.Builder.CreateStore(Elem, StoreAddr); - } - - RegAddr = CGF.Builder.CreateElementBitCast(Tmp, MemTy); - } else { - // Otherwise the object is contiguous in memory. - - // It might be right-aligned in its slot. - CharUnits SlotSize = BaseAddr.getAlignment(); - if (CGF.CGM.getDataLayout().isBigEndian() && !IsIndirect && - (IsHFA || !isAggregateTypeForABI(Ty)) && - TyInfo.first < SlotSize) { - CharUnits Offset = SlotSize - TyInfo.first; - BaseAddr = CGF.Builder.CreateConstInBoundsByteGEP(BaseAddr, Offset); - } - - RegAddr = CGF.Builder.CreateElementBitCast(BaseAddr, MemTy); - } - - CGF.EmitBranch(ContBlock); - - //======================================= - // Argument was on the stack - //======================================= - CGF.EmitBlock(OnStackBlock); - - Address stack_p = CGF.Builder.CreateStructGEP(VAListAddr, 0, - CharUnits::Zero(), "stack_p"); - llvm::Value *OnStackPtr = CGF.Builder.CreateLoad(stack_p, "stack"); - - // Again, stack arguments may need realignment. In this case both integer and - // floating-point ones might be affected. - if (!IsIndirect && TyAlign.getQuantity() > 8) { - int Align = TyAlign.getQuantity(); - - OnStackPtr = CGF.Builder.CreatePtrToInt(OnStackPtr, CGF.Int64Ty); - - OnStackPtr = CGF.Builder.CreateAdd( - OnStackPtr, llvm::ConstantInt::get(CGF.Int64Ty, Align - 1), - "align_stack"); - OnStackPtr = CGF.Builder.CreateAnd( - OnStackPtr, llvm::ConstantInt::get(CGF.Int64Ty, -Align), - "align_stack"); - - OnStackPtr = CGF.Builder.CreateIntToPtr(OnStackPtr, CGF.Int8PtrTy); - } - Address OnStackAddr(OnStackPtr, - std::max(CharUnits::fromQuantity(8), TyAlign)); - - // All stack slots are multiples of 8 bytes. - CharUnits StackSlotSize = CharUnits::fromQuantity(8); - CharUnits StackSize; - if (IsIndirect) - StackSize = StackSlotSize; - else - StackSize = TyInfo.first.alignTo(StackSlotSize); - - llvm::Value *StackSizeC = CGF.Builder.getSize(StackSize); - llvm::Value *NewStack = - CGF.Builder.CreateInBoundsGEP(OnStackPtr, StackSizeC, "new_stack"); - - // Write the new value of __stack for the next call to va_arg - CGF.Builder.CreateStore(NewStack, stack_p); - - if (CGF.CGM.getDataLayout().isBigEndian() && !isAggregateTypeForABI(Ty) && - TyInfo.first < StackSlotSize) { - CharUnits Offset = StackSlotSize - TyInfo.first; - OnStackAddr = CGF.Builder.CreateConstInBoundsByteGEP(OnStackAddr, Offset); - } - - OnStackAddr = CGF.Builder.CreateElementBitCast(OnStackAddr, MemTy); - - CGF.EmitBranch(ContBlock); - - //======================================= - // Tidy up - //======================================= - CGF.EmitBlock(ContBlock); - - Address ResAddr = emitMergePHI(CGF, RegAddr, InRegBlock, - OnStackAddr, OnStackBlock, "vaargs.addr"); - - if (IsIndirect) - return Address(CGF.Builder.CreateLoad(ResAddr, "vaarg.addr"), - TyInfo.second); - - return ResAddr; -} - -Address AArch64ABIInfo::EmitDarwinVAArg(Address VAListAddr, QualType Ty, - CodeGenFunction &CGF) const { - // The backend's lowering doesn't support va_arg for aggregates or - // illegal vector types. Lower VAArg here for these cases and use - // the LLVM va_arg instruction for everything else. - if (!isAggregateTypeForABI(Ty) && !isIllegalVectorType(Ty)) - return EmitVAArgInstr(CGF, VAListAddr, Ty, ABIArgInfo::getDirect()); - - CharUnits SlotSize = CharUnits::fromQuantity(8); - - // Empty records are ignored for parameter passing purposes. - if (isEmptyRecord(getContext(), Ty, true)) { - Address Addr(CGF.Builder.CreateLoad(VAListAddr, "ap.cur"), SlotSize); - Addr = CGF.Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(Ty)); - return Addr; - } - - // The size of the actual thing passed, which might end up just - // being a pointer for indirect types. - auto TyInfo = getContext().getTypeInfoInChars(Ty); - - // Arguments bigger than 16 bytes which aren't homogeneous - // aggregates should be passed indirectly. - bool IsIndirect = false; - if (TyInfo.first.getQuantity() > 16) { - const Type *Base = nullptr; - uint64_t Members = 0; - IsIndirect = !isHomogeneousAggregate(Ty, Base, Members); - } - - return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect, - TyInfo, SlotSize, /*AllowHigherAlign*/ true); -} - -Address AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const { - return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false, - CGF.getContext().getTypeInfoInChars(Ty), - CharUnits::fromQuantity(8), - /*allowHigherAlign*/ false); -} - -//===----------------------------------------------------------------------===// -// ARM ABI Implementation -//===----------------------------------------------------------------------===// - -namespace { - -class ARMABIInfo : public SwiftABIInfo { -public: - enum ABIKind { - APCS = 0, - AAPCS = 1, - AAPCS_VFP = 2, - AAPCS16_VFP = 3, - }; - -private: - ABIKind Kind; - -public: - ARMABIInfo(CodeGenTypes &CGT, ABIKind _Kind) - : SwiftABIInfo(CGT), Kind(_Kind) { - setCCs(); - } - - bool isEABI() const { - switch (getTarget().getTriple().getEnvironment()) { - case llvm::Triple::Android: - case llvm::Triple::EABI: - case llvm::Triple::EABIHF: - case llvm::Triple::GNUEABI: - case llvm::Triple::GNUEABIHF: - case llvm::Triple::MuslEABI: - case llvm::Triple::MuslEABIHF: - return true; - default: - return false; - } - } - - bool isEABIHF() const { - switch (getTarget().getTriple().getEnvironment()) { - case llvm::Triple::EABIHF: - case llvm::Triple::GNUEABIHF: - case llvm::Triple::MuslEABIHF: - return true; - default: - return false; - } - } - - ABIKind getABIKind() const { return Kind; } - -private: - ABIArgInfo classifyReturnType(QualType RetTy, bool isVariadic) const; - ABIArgInfo classifyArgumentType(QualType RetTy, bool isVariadic) const; - ABIArgInfo classifyHomogeneousAggregate(QualType Ty, const Type *Base, - uint64_t Members) const; - ABIArgInfo coerceIllegalVector(QualType Ty) const; - bool isIllegalVectorType(QualType Ty) const; - - bool isHomogeneousAggregateBaseType(QualType Ty) const override; - bool isHomogeneousAggregateSmallEnough(const Type *Ty, - uint64_t Members) const override; - - void computeInfo(CGFunctionInfo &FI) const override; - - Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const override; - - llvm::CallingConv::ID getLLVMDefaultCC() const; - llvm::CallingConv::ID getABIDefaultCC() const; - void setCCs(); - - bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> scalars, - bool asReturnValue) const override { - return occupiesMoreThan(CGT, scalars, /*total*/ 4); - } - bool isSwiftErrorInRegister() const override { - return true; - } - bool isLegalVectorTypeForSwift(CharUnits totalSize, llvm::Type *eltTy, - unsigned elts) const override; -}; - -class ARMTargetCodeGenInfo : public TargetCodeGenInfo { -public: - ARMTargetCodeGenInfo(CodeGenTypes &CGT, ARMABIInfo::ABIKind K) - :TargetCodeGenInfo(new ARMABIInfo(CGT, K)) {} - - const ARMABIInfo &getABIInfo() const { - return static_cast<const ARMABIInfo&>(TargetCodeGenInfo::getABIInfo()); - } - - int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override { - return 13; - } - - StringRef getARCRetainAutoreleasedReturnValueMarker() const override { - return "mov\tr7, r7\t\t// marker for objc_retainAutoreleaseReturnValue"; - } - - bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, - llvm::Value *Address) const override { - llvm::Value *Four8 = llvm::ConstantInt::get(CGF.Int8Ty, 4); - - // 0-15 are the 16 integer registers. - AssignToArrayRange(CGF.Builder, Address, Four8, 0, 15); - return false; - } - - unsigned getSizeOfUnwindException() const override { - if (getABIInfo().isEABI()) return 88; - return TargetCodeGenInfo::getSizeOfUnwindException(); - } - - void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &CGM) const override { - if (GV->isDeclaration()) - return; - const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D); - if (!FD) - return; - - const ARMInterruptAttr *Attr = FD->getAttr<ARMInterruptAttr>(); - if (!Attr) - return; - - const char *Kind; - switch (Attr->getInterrupt()) { - case ARMInterruptAttr::Generic: Kind = ""; break; - case ARMInterruptAttr::IRQ: Kind = "IRQ"; break; - case ARMInterruptAttr::FIQ: Kind = "FIQ"; break; - case ARMInterruptAttr::SWI: Kind = "SWI"; break; - case ARMInterruptAttr::ABORT: Kind = "ABORT"; break; - case ARMInterruptAttr::UNDEF: Kind = "UNDEF"; break; - } - - llvm::Function *Fn = cast<llvm::Function>(GV); - - Fn->addFnAttr("interrupt", Kind); - - ARMABIInfo::ABIKind ABI = cast<ARMABIInfo>(getABIInfo()).getABIKind(); - if (ABI == ARMABIInfo::APCS) - return; - - // AAPCS guarantees that sp will be 8-byte aligned on any public interface, - // however this is not necessarily true on taking any interrupt. Instruct - // the backend to perform a realignment as part of the function prologue. - llvm::AttrBuilder B; - B.addStackAlignmentAttr(8); - Fn->addAttributes(llvm::AttributeList::FunctionIndex, B); - } -}; - -class WindowsARMTargetCodeGenInfo : public ARMTargetCodeGenInfo { -public: - WindowsARMTargetCodeGenInfo(CodeGenTypes &CGT, ARMABIInfo::ABIKind K) - : ARMTargetCodeGenInfo(CGT, K) {} - - void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &CGM) const override; - - void getDependentLibraryOption(llvm::StringRef Lib, - llvm::SmallString<24> &Opt) const override { - Opt = "/DEFAULTLIB:" + qualifyWindowsLibrary(Lib); - } - - void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef Value, - llvm::SmallString<32> &Opt) const override { - Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\""; - } -}; - -void WindowsARMTargetCodeGenInfo::setTargetAttributes( - const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const { - ARMTargetCodeGenInfo::setTargetAttributes(D, GV, CGM); - if (GV->isDeclaration()) - return; - addStackProbeTargetAttributes(D, GV, CGM); -} -} - -void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const { - if (!::classifyReturnType(getCXXABI(), FI, *this)) - FI.getReturnInfo() = - classifyReturnType(FI.getReturnType(), FI.isVariadic()); - - for (auto &I : FI.arguments()) - I.info = classifyArgumentType(I.type, FI.isVariadic()); - - // Always honor user-specified calling convention. - if (FI.getCallingConvention() != llvm::CallingConv::C) - return; - - llvm::CallingConv::ID cc = getRuntimeCC(); - if (cc != llvm::CallingConv::C) - FI.setEffectiveCallingConvention(cc); -} - -/// Return the default calling convention that LLVM will use. -llvm::CallingConv::ID ARMABIInfo::getLLVMDefaultCC() const { - // The default calling convention that LLVM will infer. - if (isEABIHF() || getTarget().getTriple().isWatchABI()) - return llvm::CallingConv::ARM_AAPCS_VFP; - else if (isEABI()) - return llvm::CallingConv::ARM_AAPCS; - else - return llvm::CallingConv::ARM_APCS; -} - -/// Return the calling convention that our ABI would like us to use -/// as the C calling convention. -llvm::CallingConv::ID ARMABIInfo::getABIDefaultCC() const { - switch (getABIKind()) { - case APCS: return llvm::CallingConv::ARM_APCS; - case AAPCS: return llvm::CallingConv::ARM_AAPCS; - case AAPCS_VFP: return llvm::CallingConv::ARM_AAPCS_VFP; - case AAPCS16_VFP: return llvm::CallingConv::ARM_AAPCS_VFP; - } - llvm_unreachable("bad ABI kind"); -} - -void ARMABIInfo::setCCs() { - assert(getRuntimeCC() == llvm::CallingConv::C); - - // Don't muddy up the IR with a ton of explicit annotations if - // they'd just match what LLVM will infer from the triple. - llvm::CallingConv::ID abiCC = getABIDefaultCC(); - if (abiCC != getLLVMDefaultCC()) - RuntimeCC = abiCC; -} - -ABIArgInfo ARMABIInfo::coerceIllegalVector(QualType Ty) const { - uint64_t Size = getContext().getTypeSize(Ty); - if (Size <= 32) { - llvm::Type *ResType = - llvm::Type::getInt32Ty(getVMContext()); - return ABIArgInfo::getDirect(ResType); - } - if (Size == 64 || Size == 128) { - llvm::Type *ResType = llvm::VectorType::get( - llvm::Type::getInt32Ty(getVMContext()), Size / 32); - return ABIArgInfo::getDirect(ResType); - } - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); -} - -ABIArgInfo ARMABIInfo::classifyHomogeneousAggregate(QualType Ty, - const Type *Base, - uint64_t Members) const { - assert(Base && "Base class should be set for homogeneous aggregate"); - // Base can be a floating-point or a vector. - if (const VectorType *VT = Base->getAs<VectorType>()) { - // FP16 vectors should be converted to integer vectors - if (!getTarget().hasLegalHalfType() && - (VT->getElementType()->isFloat16Type() || - VT->getElementType()->isHalfType())) { - uint64_t Size = getContext().getTypeSize(VT); - llvm::Type *NewVecTy = llvm::VectorType::get( - llvm::Type::getInt32Ty(getVMContext()), Size / 32); - llvm::Type *Ty = llvm::ArrayType::get(NewVecTy, Members); - return ABIArgInfo::getDirect(Ty, 0, nullptr, false); - } - } - return ABIArgInfo::getDirect(nullptr, 0, nullptr, false); -} - -ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, - bool isVariadic) const { - // 6.1.2.1 The following argument types are VFP CPRCs: - // A single-precision floating-point type (including promoted - // half-precision types); A double-precision floating-point type; - // A 64-bit or 128-bit containerized vector type; Homogeneous Aggregate - // with a Base Type of a single- or double-precision floating-point type, - // 64-bit containerized vectors or 128-bit containerized vectors with one - // to four Elements. - bool IsEffectivelyAAPCS_VFP = getABIKind() == AAPCS_VFP && !isVariadic; - - Ty = useFirstFieldIfTransparentUnion(Ty); - - // Handle illegal vector types here. - if (isIllegalVectorType(Ty)) - return coerceIllegalVector(Ty); - - // _Float16 and __fp16 get passed as if it were an int or float, but with - // the top 16 bits unspecified. This is not done for OpenCL as it handles the - // half type natively, and does not need to interwork with AAPCS code. - if ((Ty->isFloat16Type() || Ty->isHalfType()) && - !getContext().getLangOpts().NativeHalfArgsAndReturns) { - llvm::Type *ResType = IsEffectivelyAAPCS_VFP ? - llvm::Type::getFloatTy(getVMContext()) : - llvm::Type::getInt32Ty(getVMContext()); - return ABIArgInfo::getDirect(ResType); - } - - if (!isAggregateTypeForABI(Ty)) { - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = Ty->getAs<EnumType>()) { - Ty = EnumTy->getDecl()->getIntegerType(); - } - - return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect()); - } - - if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); - } - - // Ignore empty records. - if (isEmptyRecord(getContext(), Ty, true)) - return ABIArgInfo::getIgnore(); - - if (IsEffectivelyAAPCS_VFP) { - // Homogeneous Aggregates need to be expanded when we can fit the aggregate - // into VFP registers. - const Type *Base = nullptr; - uint64_t Members = 0; - if (isHomogeneousAggregate(Ty, Base, Members)) - return classifyHomogeneousAggregate(Ty, Base, Members); - } else if (getABIKind() == ARMABIInfo::AAPCS16_VFP) { - // WatchOS does have homogeneous aggregates. Note that we intentionally use - // this convention even for a variadic function: the backend will use GPRs - // if needed. - const Type *Base = nullptr; - uint64_t Members = 0; - if (isHomogeneousAggregate(Ty, Base, Members)) { - assert(Base && Members <= 4 && "unexpected homogeneous aggregate"); - llvm::Type *Ty = - llvm::ArrayType::get(CGT.ConvertType(QualType(Base, 0)), Members); - return ABIArgInfo::getDirect(Ty, 0, nullptr, false); - } - } - - if (getABIKind() == ARMABIInfo::AAPCS16_VFP && - getContext().getTypeSizeInChars(Ty) > CharUnits::fromQuantity(16)) { - // WatchOS is adopting the 64-bit AAPCS rule on composite types: if they're - // bigger than 128-bits, they get placed in space allocated by the caller, - // and a pointer is passed. - return ABIArgInfo::getIndirect( - CharUnits::fromQuantity(getContext().getTypeAlign(Ty) / 8), false); - } - - // Support byval for ARM. - // The ABI alignment for APCS is 4-byte and for AAPCS at least 4-byte and at - // most 8-byte. We realign the indirect argument if type alignment is bigger - // than ABI alignment. - uint64_t ABIAlign = 4; - uint64_t TyAlign; - if (getABIKind() == ARMABIInfo::AAPCS_VFP || - getABIKind() == ARMABIInfo::AAPCS) { - TyAlign = getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity(); - ABIAlign = std::min(std::max(TyAlign, (uint64_t)4), (uint64_t)8); - } else { - TyAlign = getContext().getTypeAlignInChars(Ty).getQuantity(); - } - if (getContext().getTypeSizeInChars(Ty) > CharUnits::fromQuantity(64)) { - assert(getABIKind() != ARMABIInfo::AAPCS16_VFP && "unexpected byval"); - return ABIArgInfo::getIndirect(CharUnits::fromQuantity(ABIAlign), - /*ByVal=*/true, - /*Realign=*/TyAlign > ABIAlign); - } - - // On RenderScript, coerce Aggregates <= 64 bytes to an integer array of - // same size and alignment. - if (getTarget().isRenderScriptTarget()) { - return coerceToIntArray(Ty, getContext(), getVMContext()); - } - - // Otherwise, pass by coercing to a structure of the appropriate size. - llvm::Type* ElemTy; - unsigned SizeRegs; - // FIXME: Try to match the types of the arguments more accurately where - // we can. - if (TyAlign <= 4) { - ElemTy = llvm::Type::getInt32Ty(getVMContext()); - SizeRegs = (getContext().getTypeSize(Ty) + 31) / 32; - } else { - ElemTy = llvm::Type::getInt64Ty(getVMContext()); - SizeRegs = (getContext().getTypeSize(Ty) + 63) / 64; - } - - return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, SizeRegs)); -} - -static bool isIntegerLikeType(QualType Ty, ASTContext &Context, - llvm::LLVMContext &VMContext) { - // APCS, C Language Calling Conventions, Non-Simple Return Values: A structure - // is called integer-like if its size is less than or equal to one word, and - // the offset of each of its addressable sub-fields is zero. - - uint64_t Size = Context.getTypeSize(Ty); - - // Check that the type fits in a word. - if (Size > 32) - return false; - - // FIXME: Handle vector types! - if (Ty->isVectorType()) - return false; - - // Float types are never treated as "integer like". - if (Ty->isRealFloatingType()) - return false; - - // If this is a builtin or pointer type then it is ok. - if (Ty->getAs<BuiltinType>() || Ty->isPointerType()) - return true; - - // Small complex integer types are "integer like". - if (const ComplexType *CT = Ty->getAs<ComplexType>()) - return isIntegerLikeType(CT->getElementType(), Context, VMContext); - - // Single element and zero sized arrays should be allowed, by the definition - // above, but they are not. - - // Otherwise, it must be a record type. - const RecordType *RT = Ty->getAs<RecordType>(); - if (!RT) return false; - - // Ignore records with flexible arrays. - const RecordDecl *RD = RT->getDecl(); - if (RD->hasFlexibleArrayMember()) - return false; - - // Check that all sub-fields are at offset 0, and are themselves "integer - // like". - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - - bool HadField = false; - unsigned idx = 0; - for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); - i != e; ++i, ++idx) { - const FieldDecl *FD = *i; - - // Bit-fields are not addressable, we only need to verify they are "integer - // like". We still have to disallow a subsequent non-bitfield, for example: - // struct { int : 0; int x } - // is non-integer like according to gcc. - if (FD->isBitField()) { - if (!RD->isUnion()) - HadField = true; - - if (!isIntegerLikeType(FD->getType(), Context, VMContext)) - return false; - - continue; - } - - // Check if this field is at offset 0. - if (Layout.getFieldOffset(idx) != 0) - return false; - - if (!isIntegerLikeType(FD->getType(), Context, VMContext)) - return false; - - // Only allow at most one field in a structure. This doesn't match the - // wording above, but follows gcc in situations with a field following an - // empty structure. - if (!RD->isUnion()) { - if (HadField) - return false; - - HadField = true; - } - } - - return true; -} - -ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, - bool isVariadic) const { - bool IsEffectivelyAAPCS_VFP = - (getABIKind() == AAPCS_VFP || getABIKind() == AAPCS16_VFP) && !isVariadic; - - if (RetTy->isVoidType()) - return ABIArgInfo::getIgnore(); - - if (const VectorType *VT = RetTy->getAs<VectorType>()) { - // Large vector types should be returned via memory. - if (getContext().getTypeSize(RetTy) > 128) - return getNaturalAlignIndirect(RetTy); - // FP16 vectors should be converted to integer vectors - if (!getTarget().hasLegalHalfType() && - (VT->getElementType()->isFloat16Type() || - VT->getElementType()->isHalfType())) - return coerceIllegalVector(RetTy); - } - - // _Float16 and __fp16 get returned as if it were an int or float, but with - // the top 16 bits unspecified. This is not done for OpenCL as it handles the - // half type natively, and does not need to interwork with AAPCS code. - if ((RetTy->isFloat16Type() || RetTy->isHalfType()) && - !getContext().getLangOpts().NativeHalfArgsAndReturns) { - llvm::Type *ResType = IsEffectivelyAAPCS_VFP ? - llvm::Type::getFloatTy(getVMContext()) : - llvm::Type::getInt32Ty(getVMContext()); - return ABIArgInfo::getDirect(ResType); - } - - if (!isAggregateTypeForABI(RetTy)) { - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) - RetTy = EnumTy->getDecl()->getIntegerType(); - - return RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy) - : ABIArgInfo::getDirect(); - } - - // Are we following APCS? - if (getABIKind() == APCS) { - if (isEmptyRecord(getContext(), RetTy, false)) - return ABIArgInfo::getIgnore(); - - // Complex types are all returned as packed integers. - // - // FIXME: Consider using 2 x vector types if the back end handles them - // correctly. - if (RetTy->isAnyComplexType()) - return ABIArgInfo::getDirect(llvm::IntegerType::get( - getVMContext(), getContext().getTypeSize(RetTy))); - - // Integer like structures are returned in r0. - if (isIntegerLikeType(RetTy, getContext(), getVMContext())) { - // Return in the smallest viable integer type. - uint64_t Size = getContext().getTypeSize(RetTy); - if (Size <= 8) - return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext())); - if (Size <= 16) - return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext())); - return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); - } - - // Otherwise return in memory. - return getNaturalAlignIndirect(RetTy); - } - - // Otherwise this is an AAPCS variant. - - if (isEmptyRecord(getContext(), RetTy, true)) - return ABIArgInfo::getIgnore(); - - // Check for homogeneous aggregates with AAPCS-VFP. - if (IsEffectivelyAAPCS_VFP) { - const Type *Base = nullptr; - uint64_t Members = 0; - if (isHomogeneousAggregate(RetTy, Base, Members)) - return classifyHomogeneousAggregate(RetTy, Base, Members); - } - - // Aggregates <= 4 bytes are returned in r0; other aggregates - // are returned indirectly. - uint64_t Size = getContext().getTypeSize(RetTy); - if (Size <= 32) { - // On RenderScript, coerce Aggregates <= 4 bytes to an integer array of - // same size and alignment. - if (getTarget().isRenderScriptTarget()) { - return coerceToIntArray(RetTy, getContext(), getVMContext()); - } - if (getDataLayout().isBigEndian()) - // Return in 32 bit integer integer type (as if loaded by LDR, AAPCS 5.4) - return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); - - // Return in the smallest viable integer type. - if (Size <= 8) - return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext())); - if (Size <= 16) - return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext())); - return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); - } else if (Size <= 128 && getABIKind() == AAPCS16_VFP) { - llvm::Type *Int32Ty = llvm::Type::getInt32Ty(getVMContext()); - llvm::Type *CoerceTy = - llvm::ArrayType::get(Int32Ty, llvm::alignTo(Size, 32) / 32); - return ABIArgInfo::getDirect(CoerceTy); - } - - return getNaturalAlignIndirect(RetTy); -} - -/// isIllegalVector - check whether Ty is an illegal vector type. -bool ARMABIInfo::isIllegalVectorType(QualType Ty) const { - if (const VectorType *VT = Ty->getAs<VectorType> ()) { - // On targets that don't support FP16, FP16 is expanded into float, and we - // don't want the ABI to depend on whether or not FP16 is supported in - // hardware. Thus return false to coerce FP16 vectors into integer vectors. - if (!getTarget().hasLegalHalfType() && - (VT->getElementType()->isFloat16Type() || - VT->getElementType()->isHalfType())) - return true; - if (isAndroid()) { - // Android shipped using Clang 3.1, which supported a slightly different - // vector ABI. The primary differences were that 3-element vector types - // were legal, and so were sub 32-bit vectors (i.e. <2 x i8>). This path - // accepts that legacy behavior for Android only. - // Check whether VT is legal. - unsigned NumElements = VT->getNumElements(); - // NumElements should be power of 2 or equal to 3. - if (!llvm::isPowerOf2_32(NumElements) && NumElements != 3) - return true; - } else { - // Check whether VT is legal. - unsigned NumElements = VT->getNumElements(); - uint64_t Size = getContext().getTypeSize(VT); - // NumElements should be power of 2. - if (!llvm::isPowerOf2_32(NumElements)) - return true; - // Size should be greater than 32 bits. - return Size <= 32; - } - } - return false; -} - -bool ARMABIInfo::isLegalVectorTypeForSwift(CharUnits vectorSize, - llvm::Type *eltTy, - unsigned numElts) const { - if (!llvm::isPowerOf2_32(numElts)) - return false; - unsigned size = getDataLayout().getTypeStoreSizeInBits(eltTy); - if (size > 64) - return false; - if (vectorSize.getQuantity() != 8 && - (vectorSize.getQuantity() != 16 || numElts == 1)) - return false; - return true; -} - -bool ARMABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const { - // Homogeneous aggregates for AAPCS-VFP must have base types of float, - // double, or 64-bit or 128-bit vectors. - if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) { - if (BT->getKind() == BuiltinType::Float || - BT->getKind() == BuiltinType::Double || - BT->getKind() == BuiltinType::LongDouble) - return true; - } else if (const VectorType *VT = Ty->getAs<VectorType>()) { - unsigned VecSize = getContext().getTypeSize(VT); - if (VecSize == 64 || VecSize == 128) - return true; - } - return false; -} - -bool ARMABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base, - uint64_t Members) const { - return Members <= 4; -} - -Address ARMABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const { - CharUnits SlotSize = CharUnits::fromQuantity(4); - - // Empty records are ignored for parameter passing purposes. - if (isEmptyRecord(getContext(), Ty, true)) { - Address Addr(CGF.Builder.CreateLoad(VAListAddr), SlotSize); - Addr = CGF.Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(Ty)); - return Addr; - } - - auto TyInfo = getContext().getTypeInfoInChars(Ty); - CharUnits TyAlignForABI = TyInfo.second; - - // Use indirect if size of the illegal vector is bigger than 16 bytes. - bool IsIndirect = false; - const Type *Base = nullptr; - uint64_t Members = 0; - if (TyInfo.first > CharUnits::fromQuantity(16) && isIllegalVectorType(Ty)) { - IsIndirect = true; - - // ARMv7k passes structs bigger than 16 bytes indirectly, in space - // allocated by the caller. - } else if (TyInfo.first > CharUnits::fromQuantity(16) && - getABIKind() == ARMABIInfo::AAPCS16_VFP && - !isHomogeneousAggregate(Ty, Base, Members)) { - IsIndirect = true; - - // Otherwise, bound the type's ABI alignment. - // The ABI alignment for 64-bit or 128-bit vectors is 8 for AAPCS and 4 for - // APCS. For AAPCS, the ABI alignment is at least 4-byte and at most 8-byte. - // Our callers should be prepared to handle an under-aligned address. - } else if (getABIKind() == ARMABIInfo::AAPCS_VFP || - getABIKind() == ARMABIInfo::AAPCS) { - TyAlignForABI = std::max(TyAlignForABI, CharUnits::fromQuantity(4)); - TyAlignForABI = std::min(TyAlignForABI, CharUnits::fromQuantity(8)); - } else if (getABIKind() == ARMABIInfo::AAPCS16_VFP) { - // ARMv7k allows type alignment up to 16 bytes. - TyAlignForABI = std::max(TyAlignForABI, CharUnits::fromQuantity(4)); - TyAlignForABI = std::min(TyAlignForABI, CharUnits::fromQuantity(16)); - } else { - TyAlignForABI = CharUnits::fromQuantity(4); - } - TyInfo.second = TyAlignForABI; - - return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect, TyInfo, - SlotSize, /*AllowHigherAlign*/ true); -} - -//===----------------------------------------------------------------------===// -// NVPTX ABI Implementation -//===----------------------------------------------------------------------===// - -namespace { - -class NVPTXABIInfo : public ABIInfo { -public: - NVPTXABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {} - - ABIArgInfo classifyReturnType(QualType RetTy) const; - ABIArgInfo classifyArgumentType(QualType Ty) const; - - void computeInfo(CGFunctionInfo &FI) const override; - Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const override; -}; - -class NVPTXTargetCodeGenInfo : public TargetCodeGenInfo { -public: - NVPTXTargetCodeGenInfo(CodeGenTypes &CGT) - : TargetCodeGenInfo(new NVPTXABIInfo(CGT)) {} - - void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &M) const override; - bool shouldEmitStaticExternCAliases() const override; - -private: - // Adds a NamedMDNode with F, Name, and Operand as operands, and adds the - // resulting MDNode to the nvvm.annotations MDNode. - static void addNVVMMetadata(llvm::Function *F, StringRef Name, int Operand); -}; - -ABIArgInfo NVPTXABIInfo::classifyReturnType(QualType RetTy) const { - if (RetTy->isVoidType()) - return ABIArgInfo::getIgnore(); - - // note: this is different from default ABI - if (!RetTy->isScalarType()) - return ABIArgInfo::getDirect(); - - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) - RetTy = EnumTy->getDecl()->getIntegerType(); - - return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy) - : ABIArgInfo::getDirect()); -} - -ABIArgInfo NVPTXABIInfo::classifyArgumentType(QualType Ty) const { - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = Ty->getAs<EnumType>()) - Ty = EnumTy->getDecl()->getIntegerType(); - - // Return aggregates type as indirect by value - if (isAggregateTypeForABI(Ty)) - return getNaturalAlignIndirect(Ty, /* byval */ true); - - return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect()); -} - -void NVPTXABIInfo::computeInfo(CGFunctionInfo &FI) const { - if (!getCXXABI().classifyReturnType(FI)) - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); - for (auto &I : FI.arguments()) - I.info = classifyArgumentType(I.type); - - // Always honor user-specified calling convention. - if (FI.getCallingConvention() != llvm::CallingConv::C) - return; - - FI.setEffectiveCallingConvention(getRuntimeCC()); -} - -Address NVPTXABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const { - llvm_unreachable("NVPTX does not support varargs"); -} - -void NVPTXTargetCodeGenInfo::setTargetAttributes( - const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const { - if (GV->isDeclaration()) - return; - const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D); - if (!FD) return; - - llvm::Function *F = cast<llvm::Function>(GV); - - // Perform special handling in OpenCL mode - if (M.getLangOpts().OpenCL) { - // Use OpenCL function attributes to check for kernel functions - // By default, all functions are device functions - if (FD->hasAttr<OpenCLKernelAttr>()) { - // OpenCL __kernel functions get kernel metadata - // Create !{<func-ref>, metadata !"kernel", i32 1} node - addNVVMMetadata(F, "kernel", 1); - // And kernel functions are not subject to inlining - F->addFnAttr(llvm::Attribute::NoInline); - } - } - - // Perform special handling in CUDA mode. - if (M.getLangOpts().CUDA) { - // CUDA __global__ functions get a kernel metadata entry. Since - // __global__ functions cannot be called from the device, we do not - // need to set the noinline attribute. - if (FD->hasAttr<CUDAGlobalAttr>()) { - // Create !{<func-ref>, metadata !"kernel", i32 1} node - addNVVMMetadata(F, "kernel", 1); - } - if (CUDALaunchBoundsAttr *Attr = FD->getAttr<CUDALaunchBoundsAttr>()) { - // Create !{<func-ref>, metadata !"maxntidx", i32 <val>} node - llvm::APSInt MaxThreads(32); - MaxThreads = Attr->getMaxThreads()->EvaluateKnownConstInt(M.getContext()); - if (MaxThreads > 0) - addNVVMMetadata(F, "maxntidx", MaxThreads.getExtValue()); - - // min blocks is an optional argument for CUDALaunchBoundsAttr. If it was - // not specified in __launch_bounds__ or if the user specified a 0 value, - // we don't have to add a PTX directive. - if (Attr->getMinBlocks()) { - llvm::APSInt MinBlocks(32); - MinBlocks = Attr->getMinBlocks()->EvaluateKnownConstInt(M.getContext()); - if (MinBlocks > 0) - // Create !{<func-ref>, metadata !"minctasm", i32 <val>} node - addNVVMMetadata(F, "minctasm", MinBlocks.getExtValue()); - } - } - } -} - -void NVPTXTargetCodeGenInfo::addNVVMMetadata(llvm::Function *F, StringRef Name, - int Operand) { - llvm::Module *M = F->getParent(); - llvm::LLVMContext &Ctx = M->getContext(); - - // Get "nvvm.annotations" metadata node - llvm::NamedMDNode *MD = M->getOrInsertNamedMetadata("nvvm.annotations"); - - llvm::Metadata *MDVals[] = { - llvm::ConstantAsMetadata::get(F), llvm::MDString::get(Ctx, Name), - llvm::ConstantAsMetadata::get( - llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx), Operand))}; - // Append metadata to nvvm.annotations - MD->addOperand(llvm::MDNode::get(Ctx, MDVals)); -} - -bool NVPTXTargetCodeGenInfo::shouldEmitStaticExternCAliases() const { - return false; -} -} - -//===----------------------------------------------------------------------===// -// SystemZ ABI Implementation -//===----------------------------------------------------------------------===// - -namespace { - -class SystemZABIInfo : public SwiftABIInfo { - bool HasVector; - -public: - SystemZABIInfo(CodeGenTypes &CGT, bool HV) - : SwiftABIInfo(CGT), HasVector(HV) {} - - bool isPromotableIntegerType(QualType Ty) const; - bool isCompoundType(QualType Ty) const; - bool isVectorArgumentType(QualType Ty) const; - bool isFPArgumentType(QualType Ty) const; - QualType GetSingleElementType(QualType Ty) const; - - ABIArgInfo classifyReturnType(QualType RetTy) const; - ABIArgInfo classifyArgumentType(QualType ArgTy) const; - - void computeInfo(CGFunctionInfo &FI) const override { - if (!getCXXABI().classifyReturnType(FI)) - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); - for (auto &I : FI.arguments()) - I.info = classifyArgumentType(I.type); - } - - Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const override; - - bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> scalars, - bool asReturnValue) const override { - return occupiesMoreThan(CGT, scalars, /*total*/ 4); - } - bool isSwiftErrorInRegister() const override { - return false; - } -}; - -class SystemZTargetCodeGenInfo : public TargetCodeGenInfo { -public: - SystemZTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector) - : TargetCodeGenInfo(new SystemZABIInfo(CGT, HasVector)) {} -}; - -} - -bool SystemZABIInfo::isPromotableIntegerType(QualType Ty) const { - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = Ty->getAs<EnumType>()) - Ty = EnumTy->getDecl()->getIntegerType(); - - // Promotable integer types are required to be promoted by the ABI. - if (Ty->isPromotableIntegerType()) - return true; - - // 32-bit values must also be promoted. - if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) - switch (BT->getKind()) { - case BuiltinType::Int: - case BuiltinType::UInt: - return true; - default: - return false; - } - return false; -} - -bool SystemZABIInfo::isCompoundType(QualType Ty) const { - return (Ty->isAnyComplexType() || - Ty->isVectorType() || - isAggregateTypeForABI(Ty)); -} - -bool SystemZABIInfo::isVectorArgumentType(QualType Ty) const { - return (HasVector && - Ty->isVectorType() && - getContext().getTypeSize(Ty) <= 128); -} - -bool SystemZABIInfo::isFPArgumentType(QualType Ty) const { - if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) - switch (BT->getKind()) { - case BuiltinType::Float: - case BuiltinType::Double: - return true; - default: - return false; - } - - return false; -} - -QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const { - if (const RecordType *RT = Ty->getAsStructureType()) { - const RecordDecl *RD = RT->getDecl(); - QualType Found; - - // If this is a C++ record, check the bases first. - if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) - for (const auto &I : CXXRD->bases()) { - QualType Base = I.getType(); - - // Empty bases don't affect things either way. - if (isEmptyRecord(getContext(), Base, true)) - continue; - - if (!Found.isNull()) - return Ty; - Found = GetSingleElementType(Base); - } - - // Check the fields. - for (const auto *FD : RD->fields()) { - // For compatibility with GCC, ignore empty bitfields in C++ mode. - // Unlike isSingleElementStruct(), empty structure and array fields - // do count. So do anonymous bitfields that aren't zero-sized. - if (getContext().getLangOpts().CPlusPlus && - FD->isZeroLengthBitField(getContext())) - continue; - - // Unlike isSingleElementStruct(), arrays do not count. - // Nested structures still do though. - if (!Found.isNull()) - return Ty; - Found = GetSingleElementType(FD->getType()); - } - - // Unlike isSingleElementStruct(), trailing padding is allowed. - // An 8-byte aligned struct s { float f; } is passed as a double. - if (!Found.isNull()) - return Found; - } - - return Ty; -} - -Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const { - // Assume that va_list type is correct; should be pointer to LLVM type: - // struct { - // i64 __gpr; - // i64 __fpr; - // i8 *__overflow_arg_area; - // i8 *__reg_save_area; - // }; - - // Every non-vector argument occupies 8 bytes and is passed by preference - // in either GPRs or FPRs. Vector arguments occupy 8 or 16 bytes and are - // always passed on the stack. - Ty = getContext().getCanonicalType(Ty); - auto TyInfo = getContext().getTypeInfoInChars(Ty); - llvm::Type *ArgTy = CGF.ConvertTypeForMem(Ty); - llvm::Type *DirectTy = ArgTy; - ABIArgInfo AI = classifyArgumentType(Ty); - bool IsIndirect = AI.isIndirect(); - bool InFPRs = false; - bool IsVector = false; - CharUnits UnpaddedSize; - CharUnits DirectAlign; - if (IsIndirect) { - DirectTy = llvm::PointerType::getUnqual(DirectTy); - UnpaddedSize = DirectAlign = CharUnits::fromQuantity(8); - } else { - if (AI.getCoerceToType()) - ArgTy = AI.getCoerceToType(); - InFPRs = ArgTy->isFloatTy() || ArgTy->isDoubleTy(); - IsVector = ArgTy->isVectorTy(); - UnpaddedSize = TyInfo.first; - DirectAlign = TyInfo.second; - } - CharUnits PaddedSize = CharUnits::fromQuantity(8); - if (IsVector && UnpaddedSize > PaddedSize) - PaddedSize = CharUnits::fromQuantity(16); - assert((UnpaddedSize <= PaddedSize) && "Invalid argument size."); - - CharUnits Padding = (PaddedSize - UnpaddedSize); - - llvm::Type *IndexTy = CGF.Int64Ty; - llvm::Value *PaddedSizeV = - llvm::ConstantInt::get(IndexTy, PaddedSize.getQuantity()); - - if (IsVector) { - // Work out the address of a vector argument on the stack. - // Vector arguments are always passed in the high bits of a - // single (8 byte) or double (16 byte) stack slot. - Address OverflowArgAreaPtr = - CGF.Builder.CreateStructGEP(VAListAddr, 2, CharUnits::fromQuantity(16), - "overflow_arg_area_ptr"); - Address OverflowArgArea = - Address(CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area"), - TyInfo.second); - Address MemAddr = - CGF.Builder.CreateElementBitCast(OverflowArgArea, DirectTy, "mem_addr"); - - // Update overflow_arg_area_ptr pointer - llvm::Value *NewOverflowArgArea = - CGF.Builder.CreateGEP(OverflowArgArea.getPointer(), PaddedSizeV, - "overflow_arg_area"); - CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); - - return MemAddr; - } - - assert(PaddedSize.getQuantity() == 8); - - unsigned MaxRegs, RegCountField, RegSaveIndex; - CharUnits RegPadding; - if (InFPRs) { - MaxRegs = 4; // Maximum of 4 FPR arguments - RegCountField = 1; // __fpr - RegSaveIndex = 16; // save offset for f0 - RegPadding = CharUnits(); // floats are passed in the high bits of an FPR - } else { - MaxRegs = 5; // Maximum of 5 GPR arguments - RegCountField = 0; // __gpr - RegSaveIndex = 2; // save offset for r2 - RegPadding = Padding; // values are passed in the low bits of a GPR - } - - Address RegCountPtr = CGF.Builder.CreateStructGEP( - VAListAddr, RegCountField, RegCountField * CharUnits::fromQuantity(8), - "reg_count_ptr"); - llvm::Value *RegCount = CGF.Builder.CreateLoad(RegCountPtr, "reg_count"); - llvm::Value *MaxRegsV = llvm::ConstantInt::get(IndexTy, MaxRegs); - llvm::Value *InRegs = CGF.Builder.CreateICmpULT(RegCount, MaxRegsV, - "fits_in_regs"); - - llvm::BasicBlock *InRegBlock = CGF.createBasicBlock("vaarg.in_reg"); - llvm::BasicBlock *InMemBlock = CGF.createBasicBlock("vaarg.in_mem"); - llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end"); - CGF.Builder.CreateCondBr(InRegs, InRegBlock, InMemBlock); - - // Emit code to load the value if it was passed in registers. - CGF.EmitBlock(InRegBlock); - - // Work out the address of an argument register. - llvm::Value *ScaledRegCount = - CGF.Builder.CreateMul(RegCount, PaddedSizeV, "scaled_reg_count"); - llvm::Value *RegBase = - llvm::ConstantInt::get(IndexTy, RegSaveIndex * PaddedSize.getQuantity() - + RegPadding.getQuantity()); - llvm::Value *RegOffset = - CGF.Builder.CreateAdd(ScaledRegCount, RegBase, "reg_offset"); - Address RegSaveAreaPtr = - CGF.Builder.CreateStructGEP(VAListAddr, 3, CharUnits::fromQuantity(24), - "reg_save_area_ptr"); - llvm::Value *RegSaveArea = - CGF.Builder.CreateLoad(RegSaveAreaPtr, "reg_save_area"); - Address RawRegAddr(CGF.Builder.CreateGEP(RegSaveArea, RegOffset, - "raw_reg_addr"), - PaddedSize); - Address RegAddr = - CGF.Builder.CreateElementBitCast(RawRegAddr, DirectTy, "reg_addr"); - - // Update the register count - llvm::Value *One = llvm::ConstantInt::get(IndexTy, 1); - llvm::Value *NewRegCount = - CGF.Builder.CreateAdd(RegCount, One, "reg_count"); - CGF.Builder.CreateStore(NewRegCount, RegCountPtr); - CGF.EmitBranch(ContBlock); - - // Emit code to load the value if it was passed in memory. - CGF.EmitBlock(InMemBlock); - - // Work out the address of a stack argument. - Address OverflowArgAreaPtr = CGF.Builder.CreateStructGEP( - VAListAddr, 2, CharUnits::fromQuantity(16), "overflow_arg_area_ptr"); - Address OverflowArgArea = - Address(CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area"), - PaddedSize); - Address RawMemAddr = - CGF.Builder.CreateConstByteGEP(OverflowArgArea, Padding, "raw_mem_addr"); - Address MemAddr = - CGF.Builder.CreateElementBitCast(RawMemAddr, DirectTy, "mem_addr"); - - // Update overflow_arg_area_ptr pointer - llvm::Value *NewOverflowArgArea = - CGF.Builder.CreateGEP(OverflowArgArea.getPointer(), PaddedSizeV, - "overflow_arg_area"); - CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); - CGF.EmitBranch(ContBlock); - - // Return the appropriate result. - CGF.EmitBlock(ContBlock); - Address ResAddr = emitMergePHI(CGF, RegAddr, InRegBlock, - MemAddr, InMemBlock, "va_arg.addr"); - - if (IsIndirect) - ResAddr = Address(CGF.Builder.CreateLoad(ResAddr, "indirect_arg"), - TyInfo.second); - - return ResAddr; -} - -ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const { - if (RetTy->isVoidType()) - return ABIArgInfo::getIgnore(); - if (isVectorArgumentType(RetTy)) - return ABIArgInfo::getDirect(); - if (isCompoundType(RetTy) || getContext().getTypeSize(RetTy) > 64) - return getNaturalAlignIndirect(RetTy); - return (isPromotableIntegerType(RetTy) ? ABIArgInfo::getExtend(RetTy) - : ABIArgInfo::getDirect()); -} - -ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const { - // Handle the generic C++ ABI. - if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); - - // Integers and enums are extended to full register width. - if (isPromotableIntegerType(Ty)) - return ABIArgInfo::getExtend(Ty); - - // Handle vector types and vector-like structure types. Note that - // as opposed to float-like structure types, we do not allow any - // padding for vector-like structures, so verify the sizes match. - uint64_t Size = getContext().getTypeSize(Ty); - QualType SingleElementTy = GetSingleElementType(Ty); - if (isVectorArgumentType(SingleElementTy) && - getContext().getTypeSize(SingleElementTy) == Size) - return ABIArgInfo::getDirect(CGT.ConvertType(SingleElementTy)); - - // Values that are not 1, 2, 4 or 8 bytes in size are passed indirectly. - if (Size != 8 && Size != 16 && Size != 32 && Size != 64) - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); - - // Handle small structures. - if (const RecordType *RT = Ty->getAs<RecordType>()) { - // Structures with flexible arrays have variable length, so really - // fail the size test above. - const RecordDecl *RD = RT->getDecl(); - if (RD->hasFlexibleArrayMember()) - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); - - // The structure is passed as an unextended integer, a float, or a double. - llvm::Type *PassTy; - if (isFPArgumentType(SingleElementTy)) { - assert(Size == 32 || Size == 64); - if (Size == 32) - PassTy = llvm::Type::getFloatTy(getVMContext()); - else - PassTy = llvm::Type::getDoubleTy(getVMContext()); - } else - PassTy = llvm::IntegerType::get(getVMContext(), Size); - return ABIArgInfo::getDirect(PassTy); - } - - // Non-structure compounds are passed indirectly. - if (isCompoundType(Ty)) - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); - - return ABIArgInfo::getDirect(nullptr); -} - -//===----------------------------------------------------------------------===// -// MSP430 ABI Implementation -//===----------------------------------------------------------------------===// - -namespace { - -class MSP430TargetCodeGenInfo : public TargetCodeGenInfo { -public: - MSP430TargetCodeGenInfo(CodeGenTypes &CGT) - : TargetCodeGenInfo(new DefaultABIInfo(CGT)) {} - void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &M) const override; -}; - -} - -void MSP430TargetCodeGenInfo::setTargetAttributes( - const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const { - if (GV->isDeclaration()) - return; - if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) { - const auto *InterruptAttr = FD->getAttr<MSP430InterruptAttr>(); - if (!InterruptAttr) - return; - - // Handle 'interrupt' attribute: - llvm::Function *F = cast<llvm::Function>(GV); - - // Step 1: Set ISR calling convention. - F->setCallingConv(llvm::CallingConv::MSP430_INTR); - - // Step 2: Add attributes goodness. - F->addFnAttr(llvm::Attribute::NoInline); - F->addFnAttr("interrupt", llvm::utostr(InterruptAttr->getNumber())); - } -} - -//===----------------------------------------------------------------------===// -// MIPS ABI Implementation. This works for both little-endian and -// big-endian variants. -//===----------------------------------------------------------------------===// - -namespace { -class MipsABIInfo : public ABIInfo { - bool IsO32; - unsigned MinABIStackAlignInBytes, StackAlignInBytes; - void CoerceToIntArgs(uint64_t TySize, - SmallVectorImpl<llvm::Type *> &ArgList) const; - llvm::Type* HandleAggregates(QualType Ty, uint64_t TySize) const; - llvm::Type* returnAggregateInRegs(QualType RetTy, uint64_t Size) const; - llvm::Type* getPaddingType(uint64_t Align, uint64_t Offset) const; -public: - MipsABIInfo(CodeGenTypes &CGT, bool _IsO32) : - ABIInfo(CGT), IsO32(_IsO32), MinABIStackAlignInBytes(IsO32 ? 4 : 8), - StackAlignInBytes(IsO32 ? 8 : 16) {} - - ABIArgInfo classifyReturnType(QualType RetTy) const; - ABIArgInfo classifyArgumentType(QualType RetTy, uint64_t &Offset) const; - void computeInfo(CGFunctionInfo &FI) const override; - Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const override; - ABIArgInfo extendType(QualType Ty) const; -}; - -class MIPSTargetCodeGenInfo : public TargetCodeGenInfo { - unsigned SizeOfUnwindException; -public: - MIPSTargetCodeGenInfo(CodeGenTypes &CGT, bool IsO32) - : TargetCodeGenInfo(new MipsABIInfo(CGT, IsO32)), - SizeOfUnwindException(IsO32 ? 24 : 32) {} - - int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override { - return 29; - } - - void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &CGM) const override { - const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D); - if (!FD) return; - llvm::Function *Fn = cast<llvm::Function>(GV); - - if (FD->hasAttr<MipsLongCallAttr>()) - Fn->addFnAttr("long-call"); - else if (FD->hasAttr<MipsShortCallAttr>()) - Fn->addFnAttr("short-call"); - - // Other attributes do not have a meaning for declarations. - if (GV->isDeclaration()) - return; - - if (FD->hasAttr<Mips16Attr>()) { - Fn->addFnAttr("mips16"); - } - else if (FD->hasAttr<NoMips16Attr>()) { - Fn->addFnAttr("nomips16"); - } - - if (FD->hasAttr<MicroMipsAttr>()) - Fn->addFnAttr("micromips"); - else if (FD->hasAttr<NoMicroMipsAttr>()) - Fn->addFnAttr("nomicromips"); - - const MipsInterruptAttr *Attr = FD->getAttr<MipsInterruptAttr>(); - if (!Attr) - return; - - const char *Kind; - switch (Attr->getInterrupt()) { - case MipsInterruptAttr::eic: Kind = "eic"; break; - case MipsInterruptAttr::sw0: Kind = "sw0"; break; - case MipsInterruptAttr::sw1: Kind = "sw1"; break; - case MipsInterruptAttr::hw0: Kind = "hw0"; break; - case MipsInterruptAttr::hw1: Kind = "hw1"; break; - case MipsInterruptAttr::hw2: Kind = "hw2"; break; - case MipsInterruptAttr::hw3: Kind = "hw3"; break; - case MipsInterruptAttr::hw4: Kind = "hw4"; break; - case MipsInterruptAttr::hw5: Kind = "hw5"; break; - } - - Fn->addFnAttr("interrupt", Kind); - - } - - bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, - llvm::Value *Address) const override; - - unsigned getSizeOfUnwindException() const override { - return SizeOfUnwindException; - } -}; -} - -void MipsABIInfo::CoerceToIntArgs( - uint64_t TySize, SmallVectorImpl<llvm::Type *> &ArgList) const { - llvm::IntegerType *IntTy = - llvm::IntegerType::get(getVMContext(), MinABIStackAlignInBytes * 8); - - // Add (TySize / MinABIStackAlignInBytes) args of IntTy. - for (unsigned N = TySize / (MinABIStackAlignInBytes * 8); N; --N) - ArgList.push_back(IntTy); - - // If necessary, add one more integer type to ArgList. - unsigned R = TySize % (MinABIStackAlignInBytes * 8); - - if (R) - ArgList.push_back(llvm::IntegerType::get(getVMContext(), R)); -} - -// In N32/64, an aligned double precision floating point field is passed in -// a register. -llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize) const { - SmallVector<llvm::Type*, 8> ArgList, IntArgList; - - if (IsO32) { - CoerceToIntArgs(TySize, ArgList); - return llvm::StructType::get(getVMContext(), ArgList); - } - - if (Ty->isComplexType()) - return CGT.ConvertType(Ty); - - const RecordType *RT = Ty->getAs<RecordType>(); - - // Unions/vectors are passed in integer registers. - if (!RT || !RT->isStructureOrClassType()) { - CoerceToIntArgs(TySize, ArgList); - return llvm::StructType::get(getVMContext(), ArgList); - } - - const RecordDecl *RD = RT->getDecl(); - const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); - assert(!(TySize % 8) && "Size of structure must be multiple of 8."); - - uint64_t LastOffset = 0; - unsigned idx = 0; - llvm::IntegerType *I64 = llvm::IntegerType::get(getVMContext(), 64); - - // Iterate over fields in the struct/class and check if there are any aligned - // double fields. - for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); - i != e; ++i, ++idx) { - const QualType Ty = i->getType(); - const BuiltinType *BT = Ty->getAs<BuiltinType>(); - - if (!BT || BT->getKind() != BuiltinType::Double) - continue; - - uint64_t Offset = Layout.getFieldOffset(idx); - if (Offset % 64) // Ignore doubles that are not aligned. - continue; - - // Add ((Offset - LastOffset) / 64) args of type i64. - for (unsigned j = (Offset - LastOffset) / 64; j > 0; --j) - ArgList.push_back(I64); - - // Add double type. - ArgList.push_back(llvm::Type::getDoubleTy(getVMContext())); - LastOffset = Offset + 64; - } - - CoerceToIntArgs(TySize - LastOffset, IntArgList); - ArgList.append(IntArgList.begin(), IntArgList.end()); - - return llvm::StructType::get(getVMContext(), ArgList); -} - -llvm::Type *MipsABIInfo::getPaddingType(uint64_t OrigOffset, - uint64_t Offset) const { - if (OrigOffset + MinABIStackAlignInBytes > Offset) - return nullptr; - - return llvm::IntegerType::get(getVMContext(), (Offset - OrigOffset) * 8); -} - -ABIArgInfo -MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const { - Ty = useFirstFieldIfTransparentUnion(Ty); - - uint64_t OrigOffset = Offset; - uint64_t TySize = getContext().getTypeSize(Ty); - uint64_t Align = getContext().getTypeAlign(Ty) / 8; - - Align = std::min(std::max(Align, (uint64_t)MinABIStackAlignInBytes), - (uint64_t)StackAlignInBytes); - unsigned CurrOffset = llvm::alignTo(Offset, Align); - Offset = CurrOffset + llvm::alignTo(TySize, Align * 8) / 8; - - if (isAggregateTypeForABI(Ty) || Ty->isVectorType()) { - // Ignore empty aggregates. - if (TySize == 0) - return ABIArgInfo::getIgnore(); - - if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { - Offset = OrigOffset + MinABIStackAlignInBytes; - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); - } - - // If we have reached here, aggregates are passed directly by coercing to - // another structure type. Padding is inserted if the offset of the - // aggregate is unaligned. - ABIArgInfo ArgInfo = - ABIArgInfo::getDirect(HandleAggregates(Ty, TySize), 0, - getPaddingType(OrigOffset, CurrOffset)); - ArgInfo.setInReg(true); - return ArgInfo; - } - - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = Ty->getAs<EnumType>()) - Ty = EnumTy->getDecl()->getIntegerType(); - - // All integral types are promoted to the GPR width. - if (Ty->isIntegralOrEnumerationType()) - return extendType(Ty); - - return ABIArgInfo::getDirect( - nullptr, 0, IsO32 ? nullptr : getPaddingType(OrigOffset, CurrOffset)); -} - -llvm::Type* -MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size) const { - const RecordType *RT = RetTy->getAs<RecordType>(); - SmallVector<llvm::Type*, 8> RTList; - - if (RT && RT->isStructureOrClassType()) { - const RecordDecl *RD = RT->getDecl(); - const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); - unsigned FieldCnt = Layout.getFieldCount(); - - // N32/64 returns struct/classes in floating point registers if the - // following conditions are met: - // 1. The size of the struct/class is no larger than 128-bit. - // 2. The struct/class has one or two fields all of which are floating - // point types. - // 3. The offset of the first field is zero (this follows what gcc does). - // - // Any other composite results are returned in integer registers. - // - if (FieldCnt && (FieldCnt <= 2) && !Layout.getFieldOffset(0)) { - RecordDecl::field_iterator b = RD->field_begin(), e = RD->field_end(); - for (; b != e; ++b) { - const BuiltinType *BT = b->getType()->getAs<BuiltinType>(); - - if (!BT || !BT->isFloatingPoint()) - break; - - RTList.push_back(CGT.ConvertType(b->getType())); - } - - if (b == e) - return llvm::StructType::get(getVMContext(), RTList, - RD->hasAttr<PackedAttr>()); - - RTList.clear(); - } - } - - CoerceToIntArgs(Size, RTList); - return llvm::StructType::get(getVMContext(), RTList); -} - -ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const { - uint64_t Size = getContext().getTypeSize(RetTy); - - if (RetTy->isVoidType()) - return ABIArgInfo::getIgnore(); - - // O32 doesn't treat zero-sized structs differently from other structs. - // However, N32/N64 ignores zero sized return values. - if (!IsO32 && Size == 0) - return ABIArgInfo::getIgnore(); - - if (isAggregateTypeForABI(RetTy) || RetTy->isVectorType()) { - if (Size <= 128) { - if (RetTy->isAnyComplexType()) - return ABIArgInfo::getDirect(); - - // O32 returns integer vectors in registers and N32/N64 returns all small - // aggregates in registers. - if (!IsO32 || - (RetTy->isVectorType() && !RetTy->hasFloatingRepresentation())) { - ABIArgInfo ArgInfo = - ABIArgInfo::getDirect(returnAggregateInRegs(RetTy, Size)); - ArgInfo.setInReg(true); - return ArgInfo; - } - } - - return getNaturalAlignIndirect(RetTy); - } - - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) - RetTy = EnumTy->getDecl()->getIntegerType(); - - if (RetTy->isPromotableIntegerType()) - return ABIArgInfo::getExtend(RetTy); - - if ((RetTy->isUnsignedIntegerOrEnumerationType() || - RetTy->isSignedIntegerOrEnumerationType()) && Size == 32 && !IsO32) - return ABIArgInfo::getSignExtend(RetTy); - - return ABIArgInfo::getDirect(); -} - -void MipsABIInfo::computeInfo(CGFunctionInfo &FI) const { - ABIArgInfo &RetInfo = FI.getReturnInfo(); - if (!getCXXABI().classifyReturnType(FI)) - RetInfo = classifyReturnType(FI.getReturnType()); - - // Check if a pointer to an aggregate is passed as a hidden argument. - uint64_t Offset = RetInfo.isIndirect() ? MinABIStackAlignInBytes : 0; - - for (auto &I : FI.arguments()) - I.info = classifyArgumentType(I.type, Offset); -} - -Address MipsABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType OrigTy) const { - QualType Ty = OrigTy; - - // Integer arguments are promoted to 32-bit on O32 and 64-bit on N32/N64. - // Pointers are also promoted in the same way but this only matters for N32. - unsigned SlotSizeInBits = IsO32 ? 32 : 64; - unsigned PtrWidth = getTarget().getPointerWidth(0); - bool DidPromote = false; - if ((Ty->isIntegerType() && - getContext().getIntWidth(Ty) < SlotSizeInBits) || - (Ty->isPointerType() && PtrWidth < SlotSizeInBits)) { - DidPromote = true; - Ty = getContext().getIntTypeForBitwidth(SlotSizeInBits, - Ty->isSignedIntegerType()); - } - - auto TyInfo = getContext().getTypeInfoInChars(Ty); - - // The alignment of things in the argument area is never larger than - // StackAlignInBytes. - TyInfo.second = - std::min(TyInfo.second, CharUnits::fromQuantity(StackAlignInBytes)); - - // MinABIStackAlignInBytes is the size of argument slots on the stack. - CharUnits ArgSlotSize = CharUnits::fromQuantity(MinABIStackAlignInBytes); - - Address Addr = emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false, - TyInfo, ArgSlotSize, /*AllowHigherAlign*/ true); - - - // If there was a promotion, "unpromote" into a temporary. - // TODO: can we just use a pointer into a subset of the original slot? - if (DidPromote) { - Address Temp = CGF.CreateMemTemp(OrigTy, "vaarg.promotion-temp"); - llvm::Value *Promoted = CGF.Builder.CreateLoad(Addr); - - // Truncate down to the right width. - llvm::Type *IntTy = (OrigTy->isIntegerType() ? Temp.getElementType() - : CGF.IntPtrTy); - llvm::Value *V = CGF.Builder.CreateTrunc(Promoted, IntTy); - if (OrigTy->isPointerType()) - V = CGF.Builder.CreateIntToPtr(V, Temp.getElementType()); - - CGF.Builder.CreateStore(V, Temp); - Addr = Temp; - } - - return Addr; -} - -ABIArgInfo MipsABIInfo::extendType(QualType Ty) const { - int TySize = getContext().getTypeSize(Ty); - - // MIPS64 ABI requires unsigned 32 bit integers to be sign extended. - if (Ty->isUnsignedIntegerOrEnumerationType() && TySize == 32) - return ABIArgInfo::getSignExtend(Ty); - - return ABIArgInfo::getExtend(Ty); -} - -bool -MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, - llvm::Value *Address) const { - // This information comes from gcc's implementation, which seems to - // as canonical as it gets. - - // Everything on MIPS is 4 bytes. Double-precision FP registers - // are aliased to pairs of single-precision FP registers. - llvm::Value *Four8 = llvm::ConstantInt::get(CGF.Int8Ty, 4); - - // 0-31 are the general purpose registers, $0 - $31. - // 32-63 are the floating-point registers, $f0 - $f31. - // 64 and 65 are the multiply/divide registers, $hi and $lo. - // 66 is the (notional, I think) register for signal-handler return. - AssignToArrayRange(CGF.Builder, Address, Four8, 0, 65); - - // 67-74 are the floating-point status registers, $fcc0 - $fcc7. - // They are one bit wide and ignored here. - - // 80-111 are the coprocessor 0 registers, $c0r0 - $c0r31. - // (coprocessor 1 is the FP unit) - // 112-143 are the coprocessor 2 registers, $c2r0 - $c2r31. - // 144-175 are the coprocessor 3 registers, $c3r0 - $c3r31. - // 176-181 are the DSP accumulator registers. - AssignToArrayRange(CGF.Builder, Address, Four8, 80, 181); - return false; -} - -//===----------------------------------------------------------------------===// -// AVR ABI Implementation. -//===----------------------------------------------------------------------===// - -namespace { -class AVRTargetCodeGenInfo : public TargetCodeGenInfo { -public: - AVRTargetCodeGenInfo(CodeGenTypes &CGT) - : TargetCodeGenInfo(new DefaultABIInfo(CGT)) { } - - void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &CGM) const override { - if (GV->isDeclaration()) - return; - const auto *FD = dyn_cast_or_null<FunctionDecl>(D); - if (!FD) return; - auto *Fn = cast<llvm::Function>(GV); - - if (FD->getAttr<AVRInterruptAttr>()) - Fn->addFnAttr("interrupt"); - - if (FD->getAttr<AVRSignalAttr>()) - Fn->addFnAttr("signal"); - } -}; -} - -//===----------------------------------------------------------------------===// -// TCE ABI Implementation (see http://tce.cs.tut.fi). Uses mostly the defaults. -// Currently subclassed only to implement custom OpenCL C function attribute -// handling. -//===----------------------------------------------------------------------===// - -namespace { - -class TCETargetCodeGenInfo : public DefaultTargetCodeGenInfo { -public: - TCETargetCodeGenInfo(CodeGenTypes &CGT) - : DefaultTargetCodeGenInfo(CGT) {} - - void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &M) const override; -}; - -void TCETargetCodeGenInfo::setTargetAttributes( - const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const { - if (GV->isDeclaration()) - return; - const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D); - if (!FD) return; - - llvm::Function *F = cast<llvm::Function>(GV); - - if (M.getLangOpts().OpenCL) { - if (FD->hasAttr<OpenCLKernelAttr>()) { - // OpenCL C Kernel functions are not subject to inlining - F->addFnAttr(llvm::Attribute::NoInline); - const ReqdWorkGroupSizeAttr *Attr = FD->getAttr<ReqdWorkGroupSizeAttr>(); - if (Attr) { - // Convert the reqd_work_group_size() attributes to metadata. - llvm::LLVMContext &Context = F->getContext(); - llvm::NamedMDNode *OpenCLMetadata = - M.getModule().getOrInsertNamedMetadata( - "opencl.kernel_wg_size_info"); - - SmallVector<llvm::Metadata *, 5> Operands; - Operands.push_back(llvm::ConstantAsMetadata::get(F)); - - Operands.push_back( - llvm::ConstantAsMetadata::get(llvm::Constant::getIntegerValue( - M.Int32Ty, llvm::APInt(32, Attr->getXDim())))); - Operands.push_back( - llvm::ConstantAsMetadata::get(llvm::Constant::getIntegerValue( - M.Int32Ty, llvm::APInt(32, Attr->getYDim())))); - Operands.push_back( - llvm::ConstantAsMetadata::get(llvm::Constant::getIntegerValue( - M.Int32Ty, llvm::APInt(32, Attr->getZDim())))); - - // Add a boolean constant operand for "required" (true) or "hint" - // (false) for implementing the work_group_size_hint attr later. - // Currently always true as the hint is not yet implemented. - Operands.push_back( - llvm::ConstantAsMetadata::get(llvm::ConstantInt::getTrue(Context))); - OpenCLMetadata->addOperand(llvm::MDNode::get(Context, Operands)); - } - } - } -} - -} - -//===----------------------------------------------------------------------===// -// Hexagon ABI Implementation -//===----------------------------------------------------------------------===// - -namespace { - -class HexagonABIInfo : public ABIInfo { - - -public: - HexagonABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {} - -private: - - ABIArgInfo classifyReturnType(QualType RetTy) const; - ABIArgInfo classifyArgumentType(QualType RetTy) const; - - void computeInfo(CGFunctionInfo &FI) const override; - - Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const override; -}; - -class HexagonTargetCodeGenInfo : public TargetCodeGenInfo { -public: - HexagonTargetCodeGenInfo(CodeGenTypes &CGT) - :TargetCodeGenInfo(new HexagonABIInfo(CGT)) {} - - int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override { - return 29; - } -}; - -} - -void HexagonABIInfo::computeInfo(CGFunctionInfo &FI) const { - if (!getCXXABI().classifyReturnType(FI)) - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); - for (auto &I : FI.arguments()) - I.info = classifyArgumentType(I.type); -} - -ABIArgInfo HexagonABIInfo::classifyArgumentType(QualType Ty) const { - if (!isAggregateTypeForABI(Ty)) { - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = Ty->getAs<EnumType>()) - Ty = EnumTy->getDecl()->getIntegerType(); - - return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect()); - } - - if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); - - // Ignore empty records. - if (isEmptyRecord(getContext(), Ty, true)) - return ABIArgInfo::getIgnore(); - - uint64_t Size = getContext().getTypeSize(Ty); - if (Size > 64) - return getNaturalAlignIndirect(Ty, /*ByVal=*/true); - // Pass in the smallest viable integer type. - else if (Size > 32) - return ABIArgInfo::getDirect(llvm::Type::getInt64Ty(getVMContext())); - else if (Size > 16) - return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); - else if (Size > 8) - return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext())); - else - return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext())); -} - -ABIArgInfo HexagonABIInfo::classifyReturnType(QualType RetTy) const { - if (RetTy->isVoidType()) - return ABIArgInfo::getIgnore(); - - // Large vector types should be returned via memory. - if (RetTy->isVectorType() && getContext().getTypeSize(RetTy) > 64) - return getNaturalAlignIndirect(RetTy); - - if (!isAggregateTypeForABI(RetTy)) { - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) - RetTy = EnumTy->getDecl()->getIntegerType(); - - return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy) - : ABIArgInfo::getDirect()); - } - - if (isEmptyRecord(getContext(), RetTy, true)) - return ABIArgInfo::getIgnore(); - - // Aggregates <= 8 bytes are returned in r0; other aggregates - // are returned indirectly. - uint64_t Size = getContext().getTypeSize(RetTy); - if (Size <= 64) { - // Return in the smallest viable integer type. - if (Size <= 8) - return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext())); - if (Size <= 16) - return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext())); - if (Size <= 32) - return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); - return ABIArgInfo::getDirect(llvm::Type::getInt64Ty(getVMContext())); - } - - return getNaturalAlignIndirect(RetTy, /*ByVal=*/true); -} - -Address HexagonABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const { - // FIXME: Someone needs to audit that this handle alignment correctly. - return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false, - getContext().getTypeInfoInChars(Ty), - CharUnits::fromQuantity(4), - /*AllowHigherAlign*/ true); -} - -//===----------------------------------------------------------------------===// -// Lanai ABI Implementation -//===----------------------------------------------------------------------===// - -namespace { -class LanaiABIInfo : public DefaultABIInfo { -public: - LanaiABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} - - bool shouldUseInReg(QualType Ty, CCState &State) const; - - void computeInfo(CGFunctionInfo &FI) const override { - CCState State(FI.getCallingConvention()); - // Lanai uses 4 registers to pass arguments unless the function has the - // regparm attribute set. - if (FI.getHasRegParm()) { - State.FreeRegs = FI.getRegParm(); - } else { - State.FreeRegs = 4; - } - - if (!getCXXABI().classifyReturnType(FI)) - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); - for (auto &I : FI.arguments()) - I.info = classifyArgumentType(I.type, State); - } - - ABIArgInfo getIndirectResult(QualType Ty, bool ByVal, CCState &State) const; - ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State) const; -}; -} // end anonymous namespace - -bool LanaiABIInfo::shouldUseInReg(QualType Ty, CCState &State) const { - unsigned Size = getContext().getTypeSize(Ty); - unsigned SizeInRegs = llvm::alignTo(Size, 32U) / 32U; - - if (SizeInRegs == 0) - return false; - - if (SizeInRegs > State.FreeRegs) { - State.FreeRegs = 0; - return false; - } - - State.FreeRegs -= SizeInRegs; - - return true; -} - -ABIArgInfo LanaiABIInfo::getIndirectResult(QualType Ty, bool ByVal, - CCState &State) const { - if (!ByVal) { - if (State.FreeRegs) { - --State.FreeRegs; // Non-byval indirects just use one pointer. - return getNaturalAlignIndirectInReg(Ty); - } - return getNaturalAlignIndirect(Ty, false); - } - - // Compute the byval alignment. - const unsigned MinABIStackAlignInBytes = 4; - unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8; - return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true, - /*Realign=*/TypeAlign > - MinABIStackAlignInBytes); -} - -ABIArgInfo LanaiABIInfo::classifyArgumentType(QualType Ty, - CCState &State) const { - // Check with the C++ ABI first. - const RecordType *RT = Ty->getAs<RecordType>(); - if (RT) { - CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI()); - if (RAA == CGCXXABI::RAA_Indirect) { - return getIndirectResult(Ty, /*ByVal=*/false, State); - } else if (RAA == CGCXXABI::RAA_DirectInMemory) { - return getNaturalAlignIndirect(Ty, /*ByRef=*/true); - } - } - - if (isAggregateTypeForABI(Ty)) { - // Structures with flexible arrays are always indirect. - if (RT && RT->getDecl()->hasFlexibleArrayMember()) - return getIndirectResult(Ty, /*ByVal=*/true, State); - - // Ignore empty structs/unions. - if (isEmptyRecord(getContext(), Ty, true)) - return ABIArgInfo::getIgnore(); - - llvm::LLVMContext &LLVMContext = getVMContext(); - unsigned SizeInRegs = (getContext().getTypeSize(Ty) + 31) / 32; - if (SizeInRegs <= State.FreeRegs) { - llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext); - SmallVector<llvm::Type *, 3> Elements(SizeInRegs, Int32); - llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements); - State.FreeRegs -= SizeInRegs; - return ABIArgInfo::getDirectInReg(Result); - } else { - State.FreeRegs = 0; - } - return getIndirectResult(Ty, true, State); - } - - // Treat an enum type as its underlying type. - if (const auto *EnumTy = Ty->getAs<EnumType>()) - Ty = EnumTy->getDecl()->getIntegerType(); - - bool InReg = shouldUseInReg(Ty, State); - if (Ty->isPromotableIntegerType()) { - if (InReg) - return ABIArgInfo::getDirectInReg(); - return ABIArgInfo::getExtend(Ty); - } - if (InReg) - return ABIArgInfo::getDirectInReg(); - return ABIArgInfo::getDirect(); -} - -namespace { -class LanaiTargetCodeGenInfo : public TargetCodeGenInfo { -public: - LanaiTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT) - : TargetCodeGenInfo(new LanaiABIInfo(CGT)) {} -}; -} - -//===----------------------------------------------------------------------===// -// AMDGPU ABI Implementation -//===----------------------------------------------------------------------===// - -namespace { - -class AMDGPUABIInfo final : public DefaultABIInfo { -private: - static const unsigned MaxNumRegsForArgsRet = 16; - - unsigned numRegsForType(QualType Ty) const; - - bool isHomogeneousAggregateBaseType(QualType Ty) const override; - bool isHomogeneousAggregateSmallEnough(const Type *Base, - uint64_t Members) const override; - -public: - explicit AMDGPUABIInfo(CodeGen::CodeGenTypes &CGT) : - DefaultABIInfo(CGT) {} - - ABIArgInfo classifyReturnType(QualType RetTy) const; - ABIArgInfo classifyKernelArgumentType(QualType Ty) const; - ABIArgInfo classifyArgumentType(QualType Ty, unsigned &NumRegsLeft) const; - - void computeInfo(CGFunctionInfo &FI) const override; -}; - -bool AMDGPUABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const { - return true; -} - -bool AMDGPUABIInfo::isHomogeneousAggregateSmallEnough( - const Type *Base, uint64_t Members) const { - uint32_t NumRegs = (getContext().getTypeSize(Base) + 31) / 32; - - // Homogeneous Aggregates may occupy at most 16 registers. - return Members * NumRegs <= MaxNumRegsForArgsRet; -} - -/// Estimate number of registers the type will use when passed in registers. -unsigned AMDGPUABIInfo::numRegsForType(QualType Ty) const { - unsigned NumRegs = 0; - - if (const VectorType *VT = Ty->getAs<VectorType>()) { - // Compute from the number of elements. The reported size is based on the - // in-memory size, which includes the padding 4th element for 3-vectors. - QualType EltTy = VT->getElementType(); - unsigned EltSize = getContext().getTypeSize(EltTy); - - // 16-bit element vectors should be passed as packed. - if (EltSize == 16) - return (VT->getNumElements() + 1) / 2; - - unsigned EltNumRegs = (EltSize + 31) / 32; - return EltNumRegs * VT->getNumElements(); - } - - if (const RecordType *RT = Ty->getAs<RecordType>()) { - const RecordDecl *RD = RT->getDecl(); - assert(!RD->hasFlexibleArrayMember()); - - for (const FieldDecl *Field : RD->fields()) { - QualType FieldTy = Field->getType(); - NumRegs += numRegsForType(FieldTy); - } - - return NumRegs; - } - - return (getContext().getTypeSize(Ty) + 31) / 32; -} - -void AMDGPUABIInfo::computeInfo(CGFunctionInfo &FI) const { - llvm::CallingConv::ID CC = FI.getCallingConvention(); - - if (!getCXXABI().classifyReturnType(FI)) - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); - - unsigned NumRegsLeft = MaxNumRegsForArgsRet; - for (auto &Arg : FI.arguments()) { - if (CC == llvm::CallingConv::AMDGPU_KERNEL) { - Arg.info = classifyKernelArgumentType(Arg.type); - } else { - Arg.info = classifyArgumentType(Arg.type, NumRegsLeft); - } - } -} - -ABIArgInfo AMDGPUABIInfo::classifyReturnType(QualType RetTy) const { - if (isAggregateTypeForABI(RetTy)) { - // Records with non-trivial destructors/copy-constructors should not be - // returned by value. - if (!getRecordArgABI(RetTy, getCXXABI())) { - // Ignore empty structs/unions. - if (isEmptyRecord(getContext(), RetTy, true)) - return ABIArgInfo::getIgnore(); - - // Lower single-element structs to just return a regular value. - if (const Type *SeltTy = isSingleElementStruct(RetTy, getContext())) - return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); - - if (const RecordType *RT = RetTy->getAs<RecordType>()) { - const RecordDecl *RD = RT->getDecl(); - if (RD->hasFlexibleArrayMember()) - return DefaultABIInfo::classifyReturnType(RetTy); - } - - // Pack aggregates <= 4 bytes into single VGPR or pair. - uint64_t Size = getContext().getTypeSize(RetTy); - if (Size <= 16) - return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext())); - - if (Size <= 32) - return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); - - if (Size <= 64) { - llvm::Type *I32Ty = llvm::Type::getInt32Ty(getVMContext()); - return ABIArgInfo::getDirect(llvm::ArrayType::get(I32Ty, 2)); - } - - if (numRegsForType(RetTy) <= MaxNumRegsForArgsRet) - return ABIArgInfo::getDirect(); - } - } - - // Otherwise just do the default thing. - return DefaultABIInfo::classifyReturnType(RetTy); -} - -/// For kernels all parameters are really passed in a special buffer. It doesn't -/// make sense to pass anything byval, so everything must be direct. -ABIArgInfo AMDGPUABIInfo::classifyKernelArgumentType(QualType Ty) const { - Ty = useFirstFieldIfTransparentUnion(Ty); - - // TODO: Can we omit empty structs? - - // Coerce single element structs to its element. - if (const Type *SeltTy = isSingleElementStruct(Ty, getContext())) - return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); - - // If we set CanBeFlattened to true, CodeGen will expand the struct to its - // individual elements, which confuses the Clover OpenCL backend; therefore we - // have to set it to false here. Other args of getDirect() are just defaults. - return ABIArgInfo::getDirect(nullptr, 0, nullptr, false); -} - -ABIArgInfo AMDGPUABIInfo::classifyArgumentType(QualType Ty, - unsigned &NumRegsLeft) const { - assert(NumRegsLeft <= MaxNumRegsForArgsRet && "register estimate underflow"); - - Ty = useFirstFieldIfTransparentUnion(Ty); - - if (isAggregateTypeForABI(Ty)) { - // Records with non-trivial destructors/copy-constructors should not be - // passed by value. - if (auto RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); - - // Ignore empty structs/unions. - if (isEmptyRecord(getContext(), Ty, true)) - return ABIArgInfo::getIgnore(); - - // Lower single-element structs to just pass a regular value. TODO: We - // could do reasonable-size multiple-element structs too, using getExpand(), - // though watch out for things like bitfields. - if (const Type *SeltTy = isSingleElementStruct(Ty, getContext())) - return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); - - if (const RecordType *RT = Ty->getAs<RecordType>()) { - const RecordDecl *RD = RT->getDecl(); - if (RD->hasFlexibleArrayMember()) - return DefaultABIInfo::classifyArgumentType(Ty); - } - - // Pack aggregates <= 8 bytes into single VGPR or pair. - uint64_t Size = getContext().getTypeSize(Ty); - if (Size <= 64) { - unsigned NumRegs = (Size + 31) / 32; - NumRegsLeft -= std::min(NumRegsLeft, NumRegs); - - if (Size <= 16) - return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext())); - - if (Size <= 32) - return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); - - // XXX: Should this be i64 instead, and should the limit increase? - llvm::Type *I32Ty = llvm::Type::getInt32Ty(getVMContext()); - return ABIArgInfo::getDirect(llvm::ArrayType::get(I32Ty, 2)); - } - - if (NumRegsLeft > 0) { - unsigned NumRegs = numRegsForType(Ty); - if (NumRegsLeft >= NumRegs) { - NumRegsLeft -= NumRegs; - return ABIArgInfo::getDirect(); - } - } - } - - // Otherwise just do the default thing. - ABIArgInfo ArgInfo = DefaultABIInfo::classifyArgumentType(Ty); - if (!ArgInfo.isIndirect()) { - unsigned NumRegs = numRegsForType(Ty); - NumRegsLeft -= std::min(NumRegs, NumRegsLeft); - } - - return ArgInfo; -} - -class AMDGPUTargetCodeGenInfo : public TargetCodeGenInfo { -public: - AMDGPUTargetCodeGenInfo(CodeGenTypes &CGT) - : TargetCodeGenInfo(new AMDGPUABIInfo(CGT)) {} - void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &M) const override; - unsigned getOpenCLKernelCallingConv() const override; - - llvm::Constant *getNullPointer(const CodeGen::CodeGenModule &CGM, - llvm::PointerType *T, QualType QT) const override; - - LangAS getASTAllocaAddressSpace() const override { - return getLangASFromTargetAS( - getABIInfo().getDataLayout().getAllocaAddrSpace()); - } - LangAS getGlobalVarAddressSpace(CodeGenModule &CGM, - const VarDecl *D) const override; - llvm::SyncScope::ID getLLVMSyncScopeID(SyncScope S, - llvm::LLVMContext &C) const override; - llvm::Function * - createEnqueuedBlockKernel(CodeGenFunction &CGF, - llvm::Function *BlockInvokeFunc, - llvm::Value *BlockLiteral) const override; - bool shouldEmitStaticExternCAliases() const override; - void setCUDAKernelCallingConvention(const FunctionType *&FT) const override; -}; -} - -void AMDGPUTargetCodeGenInfo::setTargetAttributes( - const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const { - if (GV->isDeclaration()) - return; - const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D); - if (!FD) - return; - - llvm::Function *F = cast<llvm::Function>(GV); - - const auto *ReqdWGS = M.getLangOpts().OpenCL ? - FD->getAttr<ReqdWorkGroupSizeAttr>() : nullptr; - - if (M.getLangOpts().OpenCL && FD->hasAttr<OpenCLKernelAttr>() && - (M.getTriple().getOS() == llvm::Triple::AMDHSA)) - F->addFnAttr("amdgpu-implicitarg-num-bytes", "48"); - - const auto *FlatWGS = FD->getAttr<AMDGPUFlatWorkGroupSizeAttr>(); - if (ReqdWGS || FlatWGS) { - unsigned Min = FlatWGS ? FlatWGS->getMin() : 0; - unsigned Max = FlatWGS ? FlatWGS->getMax() : 0; - if (ReqdWGS && Min == 0 && Max == 0) - Min = Max = ReqdWGS->getXDim() * ReqdWGS->getYDim() * ReqdWGS->getZDim(); - - if (Min != 0) { - assert(Min <= Max && "Min must be less than or equal Max"); - - std::string AttrVal = llvm::utostr(Min) + "," + llvm::utostr(Max); - F->addFnAttr("amdgpu-flat-work-group-size", AttrVal); - } else - assert(Max == 0 && "Max must be zero"); - } - - if (const auto *Attr = FD->getAttr<AMDGPUWavesPerEUAttr>()) { - unsigned Min = Attr->getMin(); - unsigned Max = Attr->getMax(); - - if (Min != 0) { - assert((Max == 0 || Min <= Max) && "Min must be less than or equal Max"); - - std::string AttrVal = llvm::utostr(Min); - if (Max != 0) - AttrVal = AttrVal + "," + llvm::utostr(Max); - F->addFnAttr("amdgpu-waves-per-eu", AttrVal); - } else - assert(Max == 0 && "Max must be zero"); - } - - if (const auto *Attr = FD->getAttr<AMDGPUNumSGPRAttr>()) { - unsigned NumSGPR = Attr->getNumSGPR(); - - if (NumSGPR != 0) - F->addFnAttr("amdgpu-num-sgpr", llvm::utostr(NumSGPR)); - } - - if (const auto *Attr = FD->getAttr<AMDGPUNumVGPRAttr>()) { - uint32_t NumVGPR = Attr->getNumVGPR(); - - if (NumVGPR != 0) - F->addFnAttr("amdgpu-num-vgpr", llvm::utostr(NumVGPR)); - } -} - -unsigned AMDGPUTargetCodeGenInfo::getOpenCLKernelCallingConv() const { - return llvm::CallingConv::AMDGPU_KERNEL; -} - -// Currently LLVM assumes null pointers always have value 0, -// which results in incorrectly transformed IR. Therefore, instead of -// emitting null pointers in private and local address spaces, a null -// pointer in generic address space is emitted which is casted to a -// pointer in local or private address space. -llvm::Constant *AMDGPUTargetCodeGenInfo::getNullPointer( - const CodeGen::CodeGenModule &CGM, llvm::PointerType *PT, - QualType QT) const { - if (CGM.getContext().getTargetNullPointerValue(QT) == 0) - return llvm::ConstantPointerNull::get(PT); - - auto &Ctx = CGM.getContext(); - auto NPT = llvm::PointerType::get(PT->getElementType(), - Ctx.getTargetAddressSpace(LangAS::opencl_generic)); - return llvm::ConstantExpr::getAddrSpaceCast( - llvm::ConstantPointerNull::get(NPT), PT); -} - -LangAS -AMDGPUTargetCodeGenInfo::getGlobalVarAddressSpace(CodeGenModule &CGM, - const VarDecl *D) const { - assert(!CGM.getLangOpts().OpenCL && - !(CGM.getLangOpts().CUDA && CGM.getLangOpts().CUDAIsDevice) && - "Address space agnostic languages only"); - LangAS DefaultGlobalAS = getLangASFromTargetAS( - CGM.getContext().getTargetAddressSpace(LangAS::opencl_global)); - if (!D) - return DefaultGlobalAS; - - LangAS AddrSpace = D->getType().getAddressSpace(); - assert(AddrSpace == LangAS::Default || isTargetAddressSpace(AddrSpace)); - if (AddrSpace != LangAS::Default) - return AddrSpace; - - if (CGM.isTypeConstant(D->getType(), false)) { - if (auto ConstAS = CGM.getTarget().getConstantAddressSpace()) - return ConstAS.getValue(); - } - return DefaultGlobalAS; -} - -llvm::SyncScope::ID -AMDGPUTargetCodeGenInfo::getLLVMSyncScopeID(SyncScope S, - llvm::LLVMContext &C) const { - StringRef Name; - switch (S) { - case SyncScope::OpenCLWorkGroup: - Name = "workgroup"; - break; - case SyncScope::OpenCLDevice: - Name = "agent"; - break; - case SyncScope::OpenCLAllSVMDevices: - Name = ""; - break; - case SyncScope::OpenCLSubGroup: - Name = "subgroup"; - } - return C.getOrInsertSyncScopeID(Name); -} - -bool AMDGPUTargetCodeGenInfo::shouldEmitStaticExternCAliases() const { - return false; -} - -void AMDGPUTargetCodeGenInfo::setCUDAKernelCallingConvention( - const FunctionType *&FT) const { - FT = getABIInfo().getContext().adjustFunctionType( - FT, FT->getExtInfo().withCallingConv(CC_OpenCLKernel)); -} - -//===----------------------------------------------------------------------===// -// SPARC v8 ABI Implementation. -// Based on the SPARC Compliance Definition version 2.4.1. -// -// Ensures that complex values are passed in registers. -// -namespace { -class SparcV8ABIInfo : public DefaultABIInfo { -public: - SparcV8ABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} - -private: - ABIArgInfo classifyReturnType(QualType RetTy) const; - void computeInfo(CGFunctionInfo &FI) const override; -}; -} // end anonymous namespace - - -ABIArgInfo -SparcV8ABIInfo::classifyReturnType(QualType Ty) const { - if (Ty->isAnyComplexType()) { - return ABIArgInfo::getDirect(); - } - else { - return DefaultABIInfo::classifyReturnType(Ty); - } -} - -void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const { - - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); - for (auto &Arg : FI.arguments()) - Arg.info = classifyArgumentType(Arg.type); -} - -namespace { -class SparcV8TargetCodeGenInfo : public TargetCodeGenInfo { -public: - SparcV8TargetCodeGenInfo(CodeGenTypes &CGT) - : TargetCodeGenInfo(new SparcV8ABIInfo(CGT)) {} -}; -} // end anonymous namespace - -//===----------------------------------------------------------------------===// -// SPARC v9 ABI Implementation. -// Based on the SPARC Compliance Definition version 2.4.1. -// -// Function arguments a mapped to a nominal "parameter array" and promoted to -// registers depending on their type. Each argument occupies 8 or 16 bytes in -// the array, structs larger than 16 bytes are passed indirectly. -// -// One case requires special care: -// -// struct mixed { -// int i; -// float f; -// }; -// -// When a struct mixed is passed by value, it only occupies 8 bytes in the -// parameter array, but the int is passed in an integer register, and the float -// is passed in a floating point register. This is represented as two arguments -// with the LLVM IR inreg attribute: -// -// declare void f(i32 inreg %i, float inreg %f) -// -// The code generator will only allocate 4 bytes from the parameter array for -// the inreg arguments. All other arguments are allocated a multiple of 8 -// bytes. -// -namespace { -class SparcV9ABIInfo : public ABIInfo { -public: - SparcV9ABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {} - -private: - ABIArgInfo classifyType(QualType RetTy, unsigned SizeLimit) const; - void computeInfo(CGFunctionInfo &FI) const override; - Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const override; - - // Coercion type builder for structs passed in registers. The coercion type - // serves two purposes: - // - // 1. Pad structs to a multiple of 64 bits, so they are passed 'left-aligned' - // in registers. - // 2. Expose aligned floating point elements as first-level elements, so the - // code generator knows to pass them in floating point registers. - // - // We also compute the InReg flag which indicates that the struct contains - // aligned 32-bit floats. - // - struct CoerceBuilder { - llvm::LLVMContext &Context; - const llvm::DataLayout &DL; - SmallVector<llvm::Type*, 8> Elems; - uint64_t Size; - bool InReg; - - CoerceBuilder(llvm::LLVMContext &c, const llvm::DataLayout &dl) - : Context(c), DL(dl), Size(0), InReg(false) {} - - // Pad Elems with integers until Size is ToSize. - void pad(uint64_t ToSize) { - assert(ToSize >= Size && "Cannot remove elements"); - if (ToSize == Size) - return; - - // Finish the current 64-bit word. - uint64_t Aligned = llvm::alignTo(Size, 64); - if (Aligned > Size && Aligned <= ToSize) { - Elems.push_back(llvm::IntegerType::get(Context, Aligned - Size)); - Size = Aligned; - } - - // Add whole 64-bit words. - while (Size + 64 <= ToSize) { - Elems.push_back(llvm::Type::getInt64Ty(Context)); - Size += 64; - } - - // Final in-word padding. - if (Size < ToSize) { - Elems.push_back(llvm::IntegerType::get(Context, ToSize - Size)); - Size = ToSize; - } - } - - // Add a floating point element at Offset. - void addFloat(uint64_t Offset, llvm::Type *Ty, unsigned Bits) { - // Unaligned floats are treated as integers. - if (Offset % Bits) - return; - // The InReg flag is only required if there are any floats < 64 bits. - if (Bits < 64) - InReg = true; - pad(Offset); - Elems.push_back(Ty); - Size = Offset + Bits; - } - - // Add a struct type to the coercion type, starting at Offset (in bits). - void addStruct(uint64_t Offset, llvm::StructType *StrTy) { - const llvm::StructLayout *Layout = DL.getStructLayout(StrTy); - for (unsigned i = 0, e = StrTy->getNumElements(); i != e; ++i) { - llvm::Type *ElemTy = StrTy->getElementType(i); - uint64_t ElemOffset = Offset + Layout->getElementOffsetInBits(i); - switch (ElemTy->getTypeID()) { - case llvm::Type::StructTyID: - addStruct(ElemOffset, cast<llvm::StructType>(ElemTy)); - break; - case llvm::Type::FloatTyID: - addFloat(ElemOffset, ElemTy, 32); - break; - case llvm::Type::DoubleTyID: - addFloat(ElemOffset, ElemTy, 64); - break; - case llvm::Type::FP128TyID: - addFloat(ElemOffset, ElemTy, 128); - break; - case llvm::Type::PointerTyID: - if (ElemOffset % 64 == 0) { - pad(ElemOffset); - Elems.push_back(ElemTy); - Size += 64; - } - break; - default: - break; - } - } - } - - // Check if Ty is a usable substitute for the coercion type. - bool isUsableType(llvm::StructType *Ty) const { - return llvm::makeArrayRef(Elems) == Ty->elements(); - } - - // Get the coercion type as a literal struct type. - llvm::Type *getType() const { - if (Elems.size() == 1) - return Elems.front(); - else - return llvm::StructType::get(Context, Elems); - } - }; -}; -} // end anonymous namespace - -ABIArgInfo -SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const { - if (Ty->isVoidType()) - return ABIArgInfo::getIgnore(); - - uint64_t Size = getContext().getTypeSize(Ty); - - // Anything too big to fit in registers is passed with an explicit indirect - // pointer / sret pointer. - if (Size > SizeLimit) - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); - - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = Ty->getAs<EnumType>()) - Ty = EnumTy->getDecl()->getIntegerType(); - - // Integer types smaller than a register are extended. - if (Size < 64 && Ty->isIntegerType()) - return ABIArgInfo::getExtend(Ty); - - // Other non-aggregates go in registers. - if (!isAggregateTypeForABI(Ty)) - return ABIArgInfo::getDirect(); - - // If a C++ object has either a non-trivial copy constructor or a non-trivial - // destructor, it is passed with an explicit indirect pointer / sret pointer. - if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); - - // This is a small aggregate type that should be passed in registers. - // Build a coercion type from the LLVM struct type. - llvm::StructType *StrTy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty)); - if (!StrTy) - return ABIArgInfo::getDirect(); - - CoerceBuilder CB(getVMContext(), getDataLayout()); - CB.addStruct(0, StrTy); - CB.pad(llvm::alignTo(CB.DL.getTypeSizeInBits(StrTy), 64)); - - // Try to use the original type for coercion. - llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType(); - - if (CB.InReg) - return ABIArgInfo::getDirectInReg(CoerceTy); - else - return ABIArgInfo::getDirect(CoerceTy); -} - -Address SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const { - ABIArgInfo AI = classifyType(Ty, 16 * 8); - llvm::Type *ArgTy = CGT.ConvertType(Ty); - if (AI.canHaveCoerceToType() && !AI.getCoerceToType()) - AI.setCoerceToType(ArgTy); - - CharUnits SlotSize = CharUnits::fromQuantity(8); - - CGBuilderTy &Builder = CGF.Builder; - Address Addr(Builder.CreateLoad(VAListAddr, "ap.cur"), SlotSize); - llvm::Type *ArgPtrTy = llvm::PointerType::getUnqual(ArgTy); - - auto TypeInfo = getContext().getTypeInfoInChars(Ty); - - Address ArgAddr = Address::invalid(); - CharUnits Stride; - switch (AI.getKind()) { - case ABIArgInfo::Expand: - case ABIArgInfo::CoerceAndExpand: - case ABIArgInfo::InAlloca: - llvm_unreachable("Unsupported ABI kind for va_arg"); - - case ABIArgInfo::Extend: { - Stride = SlotSize; - CharUnits Offset = SlotSize - TypeInfo.first; - ArgAddr = Builder.CreateConstInBoundsByteGEP(Addr, Offset, "extend"); - break; - } - - case ABIArgInfo::Direct: { - auto AllocSize = getDataLayout().getTypeAllocSize(AI.getCoerceToType()); - Stride = CharUnits::fromQuantity(AllocSize).alignTo(SlotSize); - ArgAddr = Addr; - break; - } - - case ABIArgInfo::Indirect: - Stride = SlotSize; - ArgAddr = Builder.CreateElementBitCast(Addr, ArgPtrTy, "indirect"); - ArgAddr = Address(Builder.CreateLoad(ArgAddr, "indirect.arg"), - TypeInfo.second); - break; - - case ABIArgInfo::Ignore: - return Address(llvm::UndefValue::get(ArgPtrTy), TypeInfo.second); - } - - // Update VAList. - llvm::Value *NextPtr = - Builder.CreateConstInBoundsByteGEP(Addr.getPointer(), Stride, "ap.next"); - Builder.CreateStore(NextPtr, VAListAddr); - - return Builder.CreateBitCast(ArgAddr, ArgPtrTy, "arg.addr"); -} - -void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const { - FI.getReturnInfo() = classifyType(FI.getReturnType(), 32 * 8); - for (auto &I : FI.arguments()) - I.info = classifyType(I.type, 16 * 8); -} - -namespace { -class SparcV9TargetCodeGenInfo : public TargetCodeGenInfo { -public: - SparcV9TargetCodeGenInfo(CodeGenTypes &CGT) - : TargetCodeGenInfo(new SparcV9ABIInfo(CGT)) {} - - int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override { - return 14; - } - - bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, - llvm::Value *Address) const override; -}; -} // end anonymous namespace - -bool -SparcV9TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, - llvm::Value *Address) const { - // This is calculated from the LLVM and GCC tables and verified - // against gcc output. AFAIK all ABIs use the same encoding. - - CodeGen::CGBuilderTy &Builder = CGF.Builder; - - llvm::IntegerType *i8 = CGF.Int8Ty; - llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4); - llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8); - - // 0-31: the 8-byte general-purpose registers - AssignToArrayRange(Builder, Address, Eight8, 0, 31); - - // 32-63: f0-31, the 4-byte floating-point registers - AssignToArrayRange(Builder, Address, Four8, 32, 63); - - // Y = 64 - // PSR = 65 - // WIM = 66 - // TBR = 67 - // PC = 68 - // NPC = 69 - // FSR = 70 - // CSR = 71 - AssignToArrayRange(Builder, Address, Eight8, 64, 71); - - // 72-87: d0-15, the 8-byte floating-point registers - AssignToArrayRange(Builder, Address, Eight8, 72, 87); - - return false; -} - -// ARC ABI implementation. -namespace { - -class ARCABIInfo : public DefaultABIInfo { -public: - using DefaultABIInfo::DefaultABIInfo; - -private: - Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const override; - - void updateState(const ABIArgInfo &Info, QualType Ty, CCState &State) const { - if (!State.FreeRegs) - return; - if (Info.isIndirect() && Info.getInReg()) - State.FreeRegs--; - else if (Info.isDirect() && Info.getInReg()) { - unsigned sz = (getContext().getTypeSize(Ty) + 31) / 32; - if (sz < State.FreeRegs) - State.FreeRegs -= sz; - else - State.FreeRegs = 0; - } - } - - void computeInfo(CGFunctionInfo &FI) const override { - CCState State(FI.getCallingConvention()); - // ARC uses 8 registers to pass arguments. - State.FreeRegs = 8; - - if (!getCXXABI().classifyReturnType(FI)) - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); - updateState(FI.getReturnInfo(), FI.getReturnType(), State); - for (auto &I : FI.arguments()) { - I.info = classifyArgumentType(I.type, State.FreeRegs); - updateState(I.info, I.type, State); - } - } - - ABIArgInfo getIndirectByRef(QualType Ty, bool HasFreeRegs) const; - ABIArgInfo getIndirectByValue(QualType Ty) const; - ABIArgInfo classifyArgumentType(QualType Ty, uint8_t FreeRegs) const; - ABIArgInfo classifyReturnType(QualType RetTy) const; -}; - -class ARCTargetCodeGenInfo : public TargetCodeGenInfo { -public: - ARCTargetCodeGenInfo(CodeGenTypes &CGT) - : TargetCodeGenInfo(new ARCABIInfo(CGT)) {} -}; - - -ABIArgInfo ARCABIInfo::getIndirectByRef(QualType Ty, bool HasFreeRegs) const { - return HasFreeRegs ? getNaturalAlignIndirectInReg(Ty) : - getNaturalAlignIndirect(Ty, false); -} - -ABIArgInfo ARCABIInfo::getIndirectByValue(QualType Ty) const { - // Compute the byval alignment. - const unsigned MinABIStackAlignInBytes = 4; - unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8; - return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true, - TypeAlign > MinABIStackAlignInBytes); -} - -Address ARCABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const { - return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false, - getContext().getTypeInfoInChars(Ty), - CharUnits::fromQuantity(4), true); -} - -ABIArgInfo ARCABIInfo::classifyArgumentType(QualType Ty, - uint8_t FreeRegs) const { - // Handle the generic C++ ABI. - const RecordType *RT = Ty->getAs<RecordType>(); - if (RT) { - CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI()); - if (RAA == CGCXXABI::RAA_Indirect) - return getIndirectByRef(Ty, FreeRegs > 0); - - if (RAA == CGCXXABI::RAA_DirectInMemory) - return getIndirectByValue(Ty); - } - - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = Ty->getAs<EnumType>()) - Ty = EnumTy->getDecl()->getIntegerType(); - - auto SizeInRegs = llvm::alignTo(getContext().getTypeSize(Ty), 32) / 32; - - if (isAggregateTypeForABI(Ty)) { - // Structures with flexible arrays are always indirect. - if (RT && RT->getDecl()->hasFlexibleArrayMember()) - return getIndirectByValue(Ty); - - // Ignore empty structs/unions. - if (isEmptyRecord(getContext(), Ty, true)) - return ABIArgInfo::getIgnore(); - - llvm::LLVMContext &LLVMContext = getVMContext(); - - llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext); - SmallVector<llvm::Type *, 3> Elements(SizeInRegs, Int32); - llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements); - - return FreeRegs >= SizeInRegs ? - ABIArgInfo::getDirectInReg(Result) : - ABIArgInfo::getDirect(Result, 0, nullptr, false); - } - - return Ty->isPromotableIntegerType() ? - (FreeRegs >= SizeInRegs ? ABIArgInfo::getExtendInReg(Ty) : - ABIArgInfo::getExtend(Ty)) : - (FreeRegs >= SizeInRegs ? ABIArgInfo::getDirectInReg() : - ABIArgInfo::getDirect()); -} - -ABIArgInfo ARCABIInfo::classifyReturnType(QualType RetTy) const { - if (RetTy->isAnyComplexType()) - return ABIArgInfo::getDirectInReg(); - - // Arguments of size > 4 registers are indirect. - auto RetSize = llvm::alignTo(getContext().getTypeSize(RetTy), 32) / 32; - if (RetSize > 4) - return getIndirectByRef(RetTy, /*HasFreeRegs*/ true); - - return DefaultABIInfo::classifyReturnType(RetTy); -} - -} // End anonymous namespace. - -//===----------------------------------------------------------------------===// -// XCore ABI Implementation -//===----------------------------------------------------------------------===// - -namespace { - -/// A SmallStringEnc instance is used to build up the TypeString by passing -/// it by reference between functions that append to it. -typedef llvm::SmallString<128> SmallStringEnc; - -/// TypeStringCache caches the meta encodings of Types. -/// -/// The reason for caching TypeStrings is two fold: -/// 1. To cache a type's encoding for later uses; -/// 2. As a means to break recursive member type inclusion. -/// -/// A cache Entry can have a Status of: -/// NonRecursive: The type encoding is not recursive; -/// Recursive: The type encoding is recursive; -/// Incomplete: An incomplete TypeString; -/// IncompleteUsed: An incomplete TypeString that has been used in a -/// Recursive type encoding. -/// -/// A NonRecursive entry will have all of its sub-members expanded as fully -/// as possible. Whilst it may contain types which are recursive, the type -/// itself is not recursive and thus its encoding may be safely used whenever -/// the type is encountered. -/// -/// A Recursive entry will have all of its sub-members expanded as fully as -/// possible. The type itself is recursive and it may contain other types which -/// are recursive. The Recursive encoding must not be used during the expansion -/// of a recursive type's recursive branch. For simplicity the code uses -/// IncompleteCount to reject all usage of Recursive encodings for member types. -/// -/// An Incomplete entry is always a RecordType and only encodes its -/// identifier e.g. "s(S){}". Incomplete 'StubEnc' entries are ephemeral and -/// are placed into the cache during type expansion as a means to identify and -/// handle recursive inclusion of types as sub-members. If there is recursion -/// the entry becomes IncompleteUsed. -/// -/// During the expansion of a RecordType's members: -/// -/// If the cache contains a NonRecursive encoding for the member type, the -/// cached encoding is used; -/// -/// If the cache contains a Recursive encoding for the member type, the -/// cached encoding is 'Swapped' out, as it may be incorrect, and... -/// -/// If the member is a RecordType, an Incomplete encoding is placed into the -/// cache to break potential recursive inclusion of itself as a sub-member; -/// -/// Once a member RecordType has been expanded, its temporary incomplete -/// entry is removed from the cache. If a Recursive encoding was swapped out -/// it is swapped back in; -/// -/// If an incomplete entry is used to expand a sub-member, the incomplete -/// entry is marked as IncompleteUsed. The cache keeps count of how many -/// IncompleteUsed entries it currently contains in IncompleteUsedCount; -/// -/// If a member's encoding is found to be a NonRecursive or Recursive viz: -/// IncompleteUsedCount==0, the member's encoding is added to the cache. -/// Else the member is part of a recursive type and thus the recursion has -/// been exited too soon for the encoding to be correct for the member. -/// -class TypeStringCache { - enum Status {NonRecursive, Recursive, Incomplete, IncompleteUsed}; - struct Entry { - std::string Str; // The encoded TypeString for the type. - enum Status State; // Information about the encoding in 'Str'. - std::string Swapped; // A temporary place holder for a Recursive encoding - // during the expansion of RecordType's members. - }; - std::map<const IdentifierInfo *, struct Entry> Map; - unsigned IncompleteCount; // Number of Incomplete entries in the Map. - unsigned IncompleteUsedCount; // Number of IncompleteUsed entries in the Map. -public: - TypeStringCache() : IncompleteCount(0), IncompleteUsedCount(0) {} - void addIncomplete(const IdentifierInfo *ID, std::string StubEnc); - bool removeIncomplete(const IdentifierInfo *ID); - void addIfComplete(const IdentifierInfo *ID, StringRef Str, - bool IsRecursive); - StringRef lookupStr(const IdentifierInfo *ID); -}; - -/// TypeString encodings for enum & union fields must be order. -/// FieldEncoding is a helper for this ordering process. -class FieldEncoding { - bool HasName; - std::string Enc; -public: - FieldEncoding(bool b, SmallStringEnc &e) : HasName(b), Enc(e.c_str()) {} - StringRef str() { return Enc; } - bool operator<(const FieldEncoding &rhs) const { - if (HasName != rhs.HasName) return HasName; - return Enc < rhs.Enc; - } -}; - -class XCoreABIInfo : public DefaultABIInfo { -public: - XCoreABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} - Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const override; -}; - -class XCoreTargetCodeGenInfo : public TargetCodeGenInfo { - mutable TypeStringCache TSC; -public: - XCoreTargetCodeGenInfo(CodeGenTypes &CGT) - :TargetCodeGenInfo(new XCoreABIInfo(CGT)) {} - void emitTargetMD(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &M) const override; -}; - -} // End anonymous namespace. - -// TODO: this implementation is likely now redundant with the default -// EmitVAArg. -Address XCoreABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const { - CGBuilderTy &Builder = CGF.Builder; - - // Get the VAList. - CharUnits SlotSize = CharUnits::fromQuantity(4); - Address AP(Builder.CreateLoad(VAListAddr), SlotSize); - - // Handle the argument. - ABIArgInfo AI = classifyArgumentType(Ty); - CharUnits TypeAlign = getContext().getTypeAlignInChars(Ty); - llvm::Type *ArgTy = CGT.ConvertType(Ty); - if (AI.canHaveCoerceToType() && !AI.getCoerceToType()) - AI.setCoerceToType(ArgTy); - llvm::Type *ArgPtrTy = llvm::PointerType::getUnqual(ArgTy); - - Address Val = Address::invalid(); - CharUnits ArgSize = CharUnits::Zero(); - switch (AI.getKind()) { - case ABIArgInfo::Expand: - case ABIArgInfo::CoerceAndExpand: - case ABIArgInfo::InAlloca: - llvm_unreachable("Unsupported ABI kind for va_arg"); - case ABIArgInfo::Ignore: - Val = Address(llvm::UndefValue::get(ArgPtrTy), TypeAlign); - ArgSize = CharUnits::Zero(); - break; - case ABIArgInfo::Extend: - case ABIArgInfo::Direct: - Val = Builder.CreateBitCast(AP, ArgPtrTy); - ArgSize = CharUnits::fromQuantity( - getDataLayout().getTypeAllocSize(AI.getCoerceToType())); - ArgSize = ArgSize.alignTo(SlotSize); - break; - case ABIArgInfo::Indirect: - Val = Builder.CreateElementBitCast(AP, ArgPtrTy); - Val = Address(Builder.CreateLoad(Val), TypeAlign); - ArgSize = SlotSize; - break; - } - - // Increment the VAList. - if (!ArgSize.isZero()) { - llvm::Value *APN = - Builder.CreateConstInBoundsByteGEP(AP.getPointer(), ArgSize); - Builder.CreateStore(APN, VAListAddr); - } - - return Val; -} - -/// During the expansion of a RecordType, an incomplete TypeString is placed -/// into the cache as a means to identify and break recursion. -/// If there is a Recursive encoding in the cache, it is swapped out and will -/// be reinserted by removeIncomplete(). -/// All other types of encoding should have been used rather than arriving here. -void TypeStringCache::addIncomplete(const IdentifierInfo *ID, - std::string StubEnc) { - if (!ID) - return; - Entry &E = Map[ID]; - assert( (E.Str.empty() || E.State == Recursive) && - "Incorrectly use of addIncomplete"); - assert(!StubEnc.empty() && "Passing an empty string to addIncomplete()"); - E.Swapped.swap(E.Str); // swap out the Recursive - E.Str.swap(StubEnc); - E.State = Incomplete; - ++IncompleteCount; -} - -/// Once the RecordType has been expanded, the temporary incomplete TypeString -/// must be removed from the cache. -/// If a Recursive was swapped out by addIncomplete(), it will be replaced. -/// Returns true if the RecordType was defined recursively. -bool TypeStringCache::removeIncomplete(const IdentifierInfo *ID) { - if (!ID) - return false; - auto I = Map.find(ID); - assert(I != Map.end() && "Entry not present"); - Entry &E = I->second; - assert( (E.State == Incomplete || - E.State == IncompleteUsed) && - "Entry must be an incomplete type"); - bool IsRecursive = false; - if (E.State == IncompleteUsed) { - // We made use of our Incomplete encoding, thus we are recursive. - IsRecursive = true; - --IncompleteUsedCount; - } - if (E.Swapped.empty()) - Map.erase(I); - else { - // Swap the Recursive back. - E.Swapped.swap(E.Str); - E.Swapped.clear(); - E.State = Recursive; - } - --IncompleteCount; - return IsRecursive; -} - -/// Add the encoded TypeString to the cache only if it is NonRecursive or -/// Recursive (viz: all sub-members were expanded as fully as possible). -void TypeStringCache::addIfComplete(const IdentifierInfo *ID, StringRef Str, - bool IsRecursive) { - if (!ID || IncompleteUsedCount) - return; // No key or it is is an incomplete sub-type so don't add. - Entry &E = Map[ID]; - if (IsRecursive && !E.Str.empty()) { - assert(E.State==Recursive && E.Str.size() == Str.size() && - "This is not the same Recursive entry"); - // The parent container was not recursive after all, so we could have used - // this Recursive sub-member entry after all, but we assumed the worse when - // we started viz: IncompleteCount!=0. - return; - } - assert(E.Str.empty() && "Entry already present"); - E.Str = Str.str(); - E.State = IsRecursive? Recursive : NonRecursive; -} - -/// Return a cached TypeString encoding for the ID. If there isn't one, or we -/// are recursively expanding a type (IncompleteCount != 0) and the cached -/// encoding is Recursive, return an empty StringRef. -StringRef TypeStringCache::lookupStr(const IdentifierInfo *ID) { - if (!ID) - return StringRef(); // We have no key. - auto I = Map.find(ID); - if (I == Map.end()) - return StringRef(); // We have no encoding. - Entry &E = I->second; - if (E.State == Recursive && IncompleteCount) - return StringRef(); // We don't use Recursive encodings for member types. - - if (E.State == Incomplete) { - // The incomplete type is being used to break out of recursion. - E.State = IncompleteUsed; - ++IncompleteUsedCount; - } - return E.Str; -} - -/// The XCore ABI includes a type information section that communicates symbol -/// type information to the linker. The linker uses this information to verify -/// safety/correctness of things such as array bound and pointers et al. -/// The ABI only requires C (and XC) language modules to emit TypeStrings. -/// This type information (TypeString) is emitted into meta data for all global -/// symbols: definitions, declarations, functions & variables. -/// -/// The TypeString carries type, qualifier, name, size & value details. -/// Please see 'Tools Development Guide' section 2.16.2 for format details: -/// https://www.xmos.com/download/public/Tools-Development-Guide%28X9114A%29.pdf -/// The output is tested by test/CodeGen/xcore-stringtype.c. -/// -static bool getTypeString(SmallStringEnc &Enc, const Decl *D, - CodeGen::CodeGenModule &CGM, TypeStringCache &TSC); - -/// XCore uses emitTargetMD to emit TypeString metadata for global symbols. -void XCoreTargetCodeGenInfo::emitTargetMD(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &CGM) const { - SmallStringEnc Enc; - if (getTypeString(Enc, D, CGM, TSC)) { - llvm::LLVMContext &Ctx = CGM.getModule().getContext(); - llvm::Metadata *MDVals[] = {llvm::ConstantAsMetadata::get(GV), - llvm::MDString::get(Ctx, Enc.str())}; - llvm::NamedMDNode *MD = - CGM.getModule().getOrInsertNamedMetadata("xcore.typestrings"); - MD->addOperand(llvm::MDNode::get(Ctx, MDVals)); - } -} - -//===----------------------------------------------------------------------===// -// SPIR ABI Implementation -//===----------------------------------------------------------------------===// - -namespace { -class SPIRTargetCodeGenInfo : public TargetCodeGenInfo { -public: - SPIRTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT) - : TargetCodeGenInfo(new DefaultABIInfo(CGT)) {} - unsigned getOpenCLKernelCallingConv() const override; -}; - -} // End anonymous namespace. - -namespace clang { -namespace CodeGen { -void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI) { - DefaultABIInfo SPIRABI(CGM.getTypes()); - SPIRABI.computeInfo(FI); -} -} -} - -unsigned SPIRTargetCodeGenInfo::getOpenCLKernelCallingConv() const { - return llvm::CallingConv::SPIR_KERNEL; -} - -static bool appendType(SmallStringEnc &Enc, QualType QType, - const CodeGen::CodeGenModule &CGM, - TypeStringCache &TSC); - -/// Helper function for appendRecordType(). -/// Builds a SmallVector containing the encoded field types in declaration -/// order. -static bool extractFieldType(SmallVectorImpl<FieldEncoding> &FE, - const RecordDecl *RD, - const CodeGen::CodeGenModule &CGM, - TypeStringCache &TSC) { - for (const auto *Field : RD->fields()) { - SmallStringEnc Enc; - Enc += "m("; - Enc += Field->getName(); - Enc += "){"; - if (Field->isBitField()) { - Enc += "b("; - llvm::raw_svector_ostream OS(Enc); - OS << Field->getBitWidthValue(CGM.getContext()); - Enc += ':'; - } - if (!appendType(Enc, Field->getType(), CGM, TSC)) - return false; - if (Field->isBitField()) - Enc += ')'; - Enc += '}'; - FE.emplace_back(!Field->getName().empty(), Enc); - } - return true; -} - -/// Appends structure and union types to Enc and adds encoding to cache. -/// Recursively calls appendType (via extractFieldType) for each field. -/// Union types have their fields ordered according to the ABI. -static bool appendRecordType(SmallStringEnc &Enc, const RecordType *RT, - const CodeGen::CodeGenModule &CGM, - TypeStringCache &TSC, const IdentifierInfo *ID) { - // Append the cached TypeString if we have one. - StringRef TypeString = TSC.lookupStr(ID); - if (!TypeString.empty()) { - Enc += TypeString; - return true; - } - - // Start to emit an incomplete TypeString. - size_t Start = Enc.size(); - Enc += (RT->isUnionType()? 'u' : 's'); - Enc += '('; - if (ID) - Enc += ID->getName(); - Enc += "){"; - - // We collect all encoded fields and order as necessary. - bool IsRecursive = false; - const RecordDecl *RD = RT->getDecl()->getDefinition(); - if (RD && !RD->field_empty()) { - // An incomplete TypeString stub is placed in the cache for this RecordType - // so that recursive calls to this RecordType will use it whilst building a - // complete TypeString for this RecordType. - SmallVector<FieldEncoding, 16> FE; - std::string StubEnc(Enc.substr(Start).str()); - StubEnc += '}'; // StubEnc now holds a valid incomplete TypeString. - TSC.addIncomplete(ID, std::move(StubEnc)); - if (!extractFieldType(FE, RD, CGM, TSC)) { - (void) TSC.removeIncomplete(ID); - return false; - } - IsRecursive = TSC.removeIncomplete(ID); - // The ABI requires unions to be sorted but not structures. - // See FieldEncoding::operator< for sort algorithm. - if (RT->isUnionType()) - llvm::sort(FE); - // We can now complete the TypeString. - unsigned E = FE.size(); - for (unsigned I = 0; I != E; ++I) { - if (I) - Enc += ','; - Enc += FE[I].str(); - } - } - Enc += '}'; - TSC.addIfComplete(ID, Enc.substr(Start), IsRecursive); - return true; -} - -/// Appends enum types to Enc and adds the encoding to the cache. -static bool appendEnumType(SmallStringEnc &Enc, const EnumType *ET, - TypeStringCache &TSC, - const IdentifierInfo *ID) { - // Append the cached TypeString if we have one. - StringRef TypeString = TSC.lookupStr(ID); - if (!TypeString.empty()) { - Enc += TypeString; - return true; - } - - size_t Start = Enc.size(); - Enc += "e("; - if (ID) - Enc += ID->getName(); - Enc += "){"; - - // We collect all encoded enumerations and order them alphanumerically. - if (const EnumDecl *ED = ET->getDecl()->getDefinition()) { - SmallVector<FieldEncoding, 16> FE; - for (auto I = ED->enumerator_begin(), E = ED->enumerator_end(); I != E; - ++I) { - SmallStringEnc EnumEnc; - EnumEnc += "m("; - EnumEnc += I->getName(); - EnumEnc += "){"; - I->getInitVal().toString(EnumEnc); - EnumEnc += '}'; - FE.push_back(FieldEncoding(!I->getName().empty(), EnumEnc)); - } - llvm::sort(FE); - unsigned E = FE.size(); - for (unsigned I = 0; I != E; ++I) { - if (I) - Enc += ','; - Enc += FE[I].str(); - } - } - Enc += '}'; - TSC.addIfComplete(ID, Enc.substr(Start), false); - return true; -} - -/// Appends type's qualifier to Enc. -/// This is done prior to appending the type's encoding. -static void appendQualifier(SmallStringEnc &Enc, QualType QT) { - // Qualifiers are emitted in alphabetical order. - static const char *const Table[]={"","c:","r:","cr:","v:","cv:","rv:","crv:"}; - int Lookup = 0; - if (QT.isConstQualified()) - Lookup += 1<<0; - if (QT.isRestrictQualified()) - Lookup += 1<<1; - if (QT.isVolatileQualified()) - Lookup += 1<<2; - Enc += Table[Lookup]; -} - -/// Appends built-in types to Enc. -static bool appendBuiltinType(SmallStringEnc &Enc, const BuiltinType *BT) { - const char *EncType; - switch (BT->getKind()) { - case BuiltinType::Void: - EncType = "0"; - break; - case BuiltinType::Bool: - EncType = "b"; - break; - case BuiltinType::Char_U: - EncType = "uc"; - break; - case BuiltinType::UChar: - EncType = "uc"; - break; - case BuiltinType::SChar: - EncType = "sc"; - break; - case BuiltinType::UShort: - EncType = "us"; - break; - case BuiltinType::Short: - EncType = "ss"; - break; - case BuiltinType::UInt: - EncType = "ui"; - break; - case BuiltinType::Int: - EncType = "si"; - break; - case BuiltinType::ULong: - EncType = "ul"; - break; - case BuiltinType::Long: - EncType = "sl"; - break; - case BuiltinType::ULongLong: - EncType = "ull"; - break; - case BuiltinType::LongLong: - EncType = "sll"; - break; - case BuiltinType::Float: - EncType = "ft"; - break; - case BuiltinType::Double: - EncType = "d"; - break; - case BuiltinType::LongDouble: - EncType = "ld"; - break; - default: - return false; - } - Enc += EncType; - return true; -} - -/// Appends a pointer encoding to Enc before calling appendType for the pointee. -static bool appendPointerType(SmallStringEnc &Enc, const PointerType *PT, - const CodeGen::CodeGenModule &CGM, - TypeStringCache &TSC) { - Enc += "p("; - if (!appendType(Enc, PT->getPointeeType(), CGM, TSC)) - return false; - Enc += ')'; - return true; -} - -/// Appends array encoding to Enc before calling appendType for the element. -static bool appendArrayType(SmallStringEnc &Enc, QualType QT, - const ArrayType *AT, - const CodeGen::CodeGenModule &CGM, - TypeStringCache &TSC, StringRef NoSizeEnc) { - if (AT->getSizeModifier() != ArrayType::Normal) - return false; - Enc += "a("; - if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) - CAT->getSize().toStringUnsigned(Enc); - else - Enc += NoSizeEnc; // Global arrays use "*", otherwise it is "". - Enc += ':'; - // The Qualifiers should be attached to the type rather than the array. - appendQualifier(Enc, QT); - if (!appendType(Enc, AT->getElementType(), CGM, TSC)) - return false; - Enc += ')'; - return true; -} - -/// Appends a function encoding to Enc, calling appendType for the return type -/// and the arguments. -static bool appendFunctionType(SmallStringEnc &Enc, const FunctionType *FT, - const CodeGen::CodeGenModule &CGM, - TypeStringCache &TSC) { - Enc += "f{"; - if (!appendType(Enc, FT->getReturnType(), CGM, TSC)) - return false; - Enc += "}("; - if (const FunctionProtoType *FPT = FT->getAs<FunctionProtoType>()) { - // N.B. we are only interested in the adjusted param types. - auto I = FPT->param_type_begin(); - auto E = FPT->param_type_end(); - if (I != E) { - do { - if (!appendType(Enc, *I, CGM, TSC)) - return false; - ++I; - if (I != E) - Enc += ','; - } while (I != E); - if (FPT->isVariadic()) - Enc += ",va"; - } else { - if (FPT->isVariadic()) - Enc += "va"; - else - Enc += '0'; - } - } - Enc += ')'; - return true; -} - -/// Handles the type's qualifier before dispatching a call to handle specific -/// type encodings. -static bool appendType(SmallStringEnc &Enc, QualType QType, - const CodeGen::CodeGenModule &CGM, - TypeStringCache &TSC) { - - QualType QT = QType.getCanonicalType(); - - if (const ArrayType *AT = QT->getAsArrayTypeUnsafe()) - // The Qualifiers should be attached to the type rather than the array. - // Thus we don't call appendQualifier() here. - return appendArrayType(Enc, QT, AT, CGM, TSC, ""); - - appendQualifier(Enc, QT); - - if (const BuiltinType *BT = QT->getAs<BuiltinType>()) - return appendBuiltinType(Enc, BT); - - if (const PointerType *PT = QT->getAs<PointerType>()) - return appendPointerType(Enc, PT, CGM, TSC); - - if (const EnumType *ET = QT->getAs<EnumType>()) - return appendEnumType(Enc, ET, TSC, QT.getBaseTypeIdentifier()); - - if (const RecordType *RT = QT->getAsStructureType()) - return appendRecordType(Enc, RT, CGM, TSC, QT.getBaseTypeIdentifier()); - - if (const RecordType *RT = QT->getAsUnionType()) - return appendRecordType(Enc, RT, CGM, TSC, QT.getBaseTypeIdentifier()); - - if (const FunctionType *FT = QT->getAs<FunctionType>()) - return appendFunctionType(Enc, FT, CGM, TSC); - - return false; -} - -static bool getTypeString(SmallStringEnc &Enc, const Decl *D, - CodeGen::CodeGenModule &CGM, TypeStringCache &TSC) { - if (!D) - return false; - - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - if (FD->getLanguageLinkage() != CLanguageLinkage) - return false; - return appendType(Enc, FD->getType(), CGM, TSC); - } - - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { - if (VD->getLanguageLinkage() != CLanguageLinkage) - return false; - QualType QT = VD->getType().getCanonicalType(); - if (const ArrayType *AT = QT->getAsArrayTypeUnsafe()) { - // Global ArrayTypes are given a size of '*' if the size is unknown. - // The Qualifiers should be attached to the type rather than the array. - // Thus we don't call appendQualifier() here. - return appendArrayType(Enc, QT, AT, CGM, TSC, "*"); - } - return appendType(Enc, QT, CGM, TSC); - } - return false; -} - -//===----------------------------------------------------------------------===// -// RISCV ABI Implementation -//===----------------------------------------------------------------------===// - -namespace { -class RISCVABIInfo : public DefaultABIInfo { -private: - unsigned XLen; // Size of the integer ('x') registers in bits. - static const int NumArgGPRs = 8; - -public: - RISCVABIInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen) - : DefaultABIInfo(CGT), XLen(XLen) {} - - // DefaultABIInfo's classifyReturnType and classifyArgumentType are - // non-virtual, but computeInfo is virtual, so we overload it. - void computeInfo(CGFunctionInfo &FI) const override; - - ABIArgInfo classifyArgumentType(QualType Ty, bool IsFixed, - int &ArgGPRsLeft) const; - ABIArgInfo classifyReturnType(QualType RetTy) const; - - Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const override; - - ABIArgInfo extendType(QualType Ty) const; -}; -} // end anonymous namespace - -void RISCVABIInfo::computeInfo(CGFunctionInfo &FI) const { - QualType RetTy = FI.getReturnType(); - if (!getCXXABI().classifyReturnType(FI)) - FI.getReturnInfo() = classifyReturnType(RetTy); - - // IsRetIndirect is true if classifyArgumentType indicated the value should - // be passed indirect or if the type size is greater than 2*xlen. e.g. fp128 - // is passed direct in LLVM IR, relying on the backend lowering code to - // rewrite the argument list and pass indirectly on RV32. - bool IsRetIndirect = FI.getReturnInfo().getKind() == ABIArgInfo::Indirect || - getContext().getTypeSize(RetTy) > (2 * XLen); - - // We must track the number of GPRs used in order to conform to the RISC-V - // ABI, as integer scalars passed in registers should have signext/zeroext - // when promoted, but are anyext if passed on the stack. As GPR usage is - // different for variadic arguments, we must also track whether we are - // examining a vararg or not. - int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs; - int NumFixedArgs = FI.getNumRequiredArgs(); - - int ArgNum = 0; - for (auto &ArgInfo : FI.arguments()) { - bool IsFixed = ArgNum < NumFixedArgs; - ArgInfo.info = classifyArgumentType(ArgInfo.type, IsFixed, ArgGPRsLeft); - ArgNum++; - } -} - -ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed, - int &ArgGPRsLeft) const { - assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); - Ty = useFirstFieldIfTransparentUnion(Ty); - - // Structures with either a non-trivial destructor or a non-trivial - // copy constructor are always passed indirectly. - if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { - if (ArgGPRsLeft) - ArgGPRsLeft -= 1; - return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA == - CGCXXABI::RAA_DirectInMemory); - } - - // Ignore empty structs/unions. - if (isEmptyRecord(getContext(), Ty, true)) - return ABIArgInfo::getIgnore(); - - uint64_t Size = getContext().getTypeSize(Ty); - uint64_t NeededAlign = getContext().getTypeAlign(Ty); - bool MustUseStack = false; - // Determine the number of GPRs needed to pass the current argument - // according to the ABI. 2*XLen-aligned varargs are passed in "aligned" - // register pairs, so may consume 3 registers. - int NeededArgGPRs = 1; - if (!IsFixed && NeededAlign == 2 * XLen) - NeededArgGPRs = 2 + (ArgGPRsLeft % 2); - else if (Size > XLen && Size <= 2 * XLen) - NeededArgGPRs = 2; - - if (NeededArgGPRs > ArgGPRsLeft) { - MustUseStack = true; - NeededArgGPRs = ArgGPRsLeft; - } - - ArgGPRsLeft -= NeededArgGPRs; - - if (!isAggregateTypeForABI(Ty) && !Ty->isVectorType()) { - // Treat an enum type as its underlying type. - if (const EnumType *EnumTy = Ty->getAs<EnumType>()) - Ty = EnumTy->getDecl()->getIntegerType(); - - // All integral types are promoted to XLen width, unless passed on the - // stack. - if (Size < XLen && Ty->isIntegralOrEnumerationType() && !MustUseStack) { - return extendType(Ty); - } - - return ABIArgInfo::getDirect(); - } - - // Aggregates which are <= 2*XLen will be passed in registers if possible, - // so coerce to integers. - if (Size <= 2 * XLen) { - unsigned Alignment = getContext().getTypeAlign(Ty); - - // Use a single XLen int if possible, 2*XLen if 2*XLen alignment is - // required, and a 2-element XLen array if only XLen alignment is required. - if (Size <= XLen) { - return ABIArgInfo::getDirect( - llvm::IntegerType::get(getVMContext(), XLen)); - } else if (Alignment == 2 * XLen) { - return ABIArgInfo::getDirect( - llvm::IntegerType::get(getVMContext(), 2 * XLen)); - } else { - return ABIArgInfo::getDirect(llvm::ArrayType::get( - llvm::IntegerType::get(getVMContext(), XLen), 2)); - } - } - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); -} - -ABIArgInfo RISCVABIInfo::classifyReturnType(QualType RetTy) const { - if (RetTy->isVoidType()) - return ABIArgInfo::getIgnore(); - - int ArgGPRsLeft = 2; - - // The rules for return and argument types are the same, so defer to - // classifyArgumentType. - return classifyArgumentType(RetTy, /*IsFixed=*/true, ArgGPRsLeft); -} - -Address RISCVABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - QualType Ty) const { - CharUnits SlotSize = CharUnits::fromQuantity(XLen / 8); - - // Empty records are ignored for parameter passing purposes. - if (isEmptyRecord(getContext(), Ty, true)) { - Address Addr(CGF.Builder.CreateLoad(VAListAddr), SlotSize); - Addr = CGF.Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(Ty)); - return Addr; - } - - std::pair<CharUnits, CharUnits> SizeAndAlign = - getContext().getTypeInfoInChars(Ty); - - // Arguments bigger than 2*Xlen bytes are passed indirectly. - bool IsIndirect = SizeAndAlign.first > 2 * SlotSize; - - return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect, SizeAndAlign, - SlotSize, /*AllowHigherAlign=*/true); -} - -ABIArgInfo RISCVABIInfo::extendType(QualType Ty) const { - int TySize = getContext().getTypeSize(Ty); - // RV64 ABI requires unsigned 32 bit integers to be sign extended. - if (XLen == 64 && Ty->isUnsignedIntegerOrEnumerationType() && TySize == 32) - return ABIArgInfo::getSignExtend(Ty); - return ABIArgInfo::getExtend(Ty); -} - -namespace { -class RISCVTargetCodeGenInfo : public TargetCodeGenInfo { -public: - RISCVTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen) - : TargetCodeGenInfo(new RISCVABIInfo(CGT, XLen)) {} - - void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &CGM) const override { - const auto *FD = dyn_cast_or_null<FunctionDecl>(D); - if (!FD) return; - - const auto *Attr = FD->getAttr<RISCVInterruptAttr>(); - if (!Attr) - return; - - const char *Kind; - switch (Attr->getInterrupt()) { - case RISCVInterruptAttr::user: Kind = "user"; break; - case RISCVInterruptAttr::supervisor: Kind = "supervisor"; break; - case RISCVInterruptAttr::machine: Kind = "machine"; break; - } - - auto *Fn = cast<llvm::Function>(GV); - - Fn->addFnAttr("interrupt", Kind); - } -}; -} // namespace - -//===----------------------------------------------------------------------===// -// Driver code -//===----------------------------------------------------------------------===// - -bool CodeGenModule::supportsCOMDAT() const { - return getTriple().supportsCOMDAT(); -} - -const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { - if (TheTargetCodeGenInfo) - return *TheTargetCodeGenInfo; - - // Helper to set the unique_ptr while still keeping the return value. - auto SetCGInfo = [&](TargetCodeGenInfo *P) -> const TargetCodeGenInfo & { - this->TheTargetCodeGenInfo.reset(P); - return *P; - }; - - const llvm::Triple &Triple = getTarget().getTriple(); - switch (Triple.getArch()) { - default: - return SetCGInfo(new DefaultTargetCodeGenInfo(Types)); - - case llvm::Triple::le32: - return SetCGInfo(new PNaClTargetCodeGenInfo(Types)); - case llvm::Triple::mips: - case llvm::Triple::mipsel: - if (Triple.getOS() == llvm::Triple::NaCl) - return SetCGInfo(new PNaClTargetCodeGenInfo(Types)); - return SetCGInfo(new MIPSTargetCodeGenInfo(Types, true)); - - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - return SetCGInfo(new MIPSTargetCodeGenInfo(Types, false)); - - case llvm::Triple::avr: - return SetCGInfo(new AVRTargetCodeGenInfo(Types)); - - case llvm::Triple::aarch64: - case llvm::Triple::aarch64_be: { - AArch64ABIInfo::ABIKind Kind = AArch64ABIInfo::AAPCS; - if (getTarget().getABI() == "darwinpcs") - Kind = AArch64ABIInfo::DarwinPCS; - else if (Triple.isOSWindows()) - return SetCGInfo( - new WindowsAArch64TargetCodeGenInfo(Types, AArch64ABIInfo::Win64)); - - return SetCGInfo(new AArch64TargetCodeGenInfo(Types, Kind)); - } - - case llvm::Triple::wasm32: - case llvm::Triple::wasm64: - return SetCGInfo(new WebAssemblyTargetCodeGenInfo(Types)); - - case llvm::Triple::arm: - case llvm::Triple::armeb: - case llvm::Triple::thumb: - case llvm::Triple::thumbeb: { - if (Triple.getOS() == llvm::Triple::Win32) { - return SetCGInfo( - new WindowsARMTargetCodeGenInfo(Types, ARMABIInfo::AAPCS_VFP)); - } - - ARMABIInfo::ABIKind Kind = ARMABIInfo::AAPCS; - StringRef ABIStr = getTarget().getABI(); - if (ABIStr == "apcs-gnu") - Kind = ARMABIInfo::APCS; - else if (ABIStr == "aapcs16") - Kind = ARMABIInfo::AAPCS16_VFP; - else if (CodeGenOpts.FloatABI == "hard" || - (CodeGenOpts.FloatABI != "soft" && - (Triple.getEnvironment() == llvm::Triple::GNUEABIHF || - Triple.getEnvironment() == llvm::Triple::MuslEABIHF || - Triple.getEnvironment() == llvm::Triple::EABIHF))) - Kind = ARMABIInfo::AAPCS_VFP; - - return SetCGInfo(new ARMTargetCodeGenInfo(Types, Kind)); - } - - case llvm::Triple::ppc: { - bool RetSmallStructInRegABI = - PPC32TargetCodeGenInfo::isStructReturnInRegABI(Triple, CodeGenOpts); - return SetCGInfo( - new PPC32TargetCodeGenInfo(Types, CodeGenOpts.FloatABI == "soft", - RetSmallStructInRegABI)); - } - case llvm::Triple::ppc64: - if (Triple.isOSBinFormatELF()) { - PPC64_SVR4_ABIInfo::ABIKind Kind = PPC64_SVR4_ABIInfo::ELFv1; - if (getTarget().getABI() == "elfv2") - Kind = PPC64_SVR4_ABIInfo::ELFv2; - bool HasQPX = getTarget().getABI() == "elfv1-qpx"; - bool IsSoftFloat = CodeGenOpts.FloatABI == "soft"; - - return SetCGInfo(new PPC64_SVR4_TargetCodeGenInfo(Types, Kind, HasQPX, - IsSoftFloat)); - } else - return SetCGInfo(new PPC64TargetCodeGenInfo(Types)); - case llvm::Triple::ppc64le: { - assert(Triple.isOSBinFormatELF() && "PPC64 LE non-ELF not supported!"); - PPC64_SVR4_ABIInfo::ABIKind Kind = PPC64_SVR4_ABIInfo::ELFv2; - if (getTarget().getABI() == "elfv1" || getTarget().getABI() == "elfv1-qpx") - Kind = PPC64_SVR4_ABIInfo::ELFv1; - bool HasQPX = getTarget().getABI() == "elfv1-qpx"; - bool IsSoftFloat = CodeGenOpts.FloatABI == "soft"; - - return SetCGInfo(new PPC64_SVR4_TargetCodeGenInfo(Types, Kind, HasQPX, - IsSoftFloat)); - } - - case llvm::Triple::nvptx: - case llvm::Triple::nvptx64: - return SetCGInfo(new NVPTXTargetCodeGenInfo(Types)); - - case llvm::Triple::msp430: - return SetCGInfo(new MSP430TargetCodeGenInfo(Types)); - - case llvm::Triple::riscv32: - return SetCGInfo(new RISCVTargetCodeGenInfo(Types, 32)); - case llvm::Triple::riscv64: - return SetCGInfo(new RISCVTargetCodeGenInfo(Types, 64)); - - case llvm::Triple::systemz: { - bool HasVector = getTarget().getABI() == "vector"; - return SetCGInfo(new SystemZTargetCodeGenInfo(Types, HasVector)); - } - - case llvm::Triple::tce: - case llvm::Triple::tcele: - return SetCGInfo(new TCETargetCodeGenInfo(Types)); - - case llvm::Triple::x86: { - bool IsDarwinVectorABI = Triple.isOSDarwin(); - bool RetSmallStructInRegABI = - X86_32TargetCodeGenInfo::isStructReturnInRegABI(Triple, CodeGenOpts); - bool IsWin32FloatStructABI = Triple.isOSWindows() && !Triple.isOSCygMing(); - - if (Triple.getOS() == llvm::Triple::Win32) { - return SetCGInfo(new WinX86_32TargetCodeGenInfo( - Types, IsDarwinVectorABI, RetSmallStructInRegABI, - IsWin32FloatStructABI, CodeGenOpts.NumRegisterParameters)); - } else { - return SetCGInfo(new X86_32TargetCodeGenInfo( - Types, IsDarwinVectorABI, RetSmallStructInRegABI, - IsWin32FloatStructABI, CodeGenOpts.NumRegisterParameters, - CodeGenOpts.FloatABI == "soft")); - } - } - - case llvm::Triple::x86_64: { - StringRef ABI = getTarget().getABI(); - X86AVXABILevel AVXLevel = - (ABI == "avx512" - ? X86AVXABILevel::AVX512 - : ABI == "avx" ? X86AVXABILevel::AVX : X86AVXABILevel::None); - - switch (Triple.getOS()) { - case llvm::Triple::Win32: - return SetCGInfo(new WinX86_64TargetCodeGenInfo(Types, AVXLevel)); - case llvm::Triple::PS4: - return SetCGInfo(new PS4TargetCodeGenInfo(Types, AVXLevel)); - default: - return SetCGInfo(new X86_64TargetCodeGenInfo(Types, AVXLevel)); - } - } - case llvm::Triple::hexagon: - return SetCGInfo(new HexagonTargetCodeGenInfo(Types)); - case llvm::Triple::lanai: - return SetCGInfo(new LanaiTargetCodeGenInfo(Types)); - case llvm::Triple::r600: - return SetCGInfo(new AMDGPUTargetCodeGenInfo(Types)); - case llvm::Triple::amdgcn: - return SetCGInfo(new AMDGPUTargetCodeGenInfo(Types)); - case llvm::Triple::sparc: - return SetCGInfo(new SparcV8TargetCodeGenInfo(Types)); - case llvm::Triple::sparcv9: - return SetCGInfo(new SparcV9TargetCodeGenInfo(Types)); - case llvm::Triple::xcore: - return SetCGInfo(new XCoreTargetCodeGenInfo(Types)); - case llvm::Triple::arc: - return SetCGInfo(new ARCTargetCodeGenInfo(Types)); - case llvm::Triple::spir: - case llvm::Triple::spir64: - return SetCGInfo(new SPIRTargetCodeGenInfo(Types)); - } -} - -/// Create an OpenCL kernel for an enqueued block. -/// -/// The kernel has the same function type as the block invoke function. Its -/// name is the name of the block invoke function postfixed with "_kernel". -/// It simply calls the block invoke function then returns. -llvm::Function * -TargetCodeGenInfo::createEnqueuedBlockKernel(CodeGenFunction &CGF, - llvm::Function *Invoke, - llvm::Value *BlockLiteral) const { - auto *InvokeFT = Invoke->getFunctionType(); - llvm::SmallVector<llvm::Type *, 2> ArgTys; - for (auto &P : InvokeFT->params()) - ArgTys.push_back(P); - auto &C = CGF.getLLVMContext(); - std::string Name = Invoke->getName().str() + "_kernel"; - auto *FT = llvm::FunctionType::get(llvm::Type::getVoidTy(C), ArgTys, false); - auto *F = llvm::Function::Create(FT, llvm::GlobalValue::InternalLinkage, Name, - &CGF.CGM.getModule()); - auto IP = CGF.Builder.saveIP(); - auto *BB = llvm::BasicBlock::Create(C, "entry", F); - auto &Builder = CGF.Builder; - Builder.SetInsertPoint(BB); - llvm::SmallVector<llvm::Value *, 2> Args; - for (auto &A : F->args()) - Args.push_back(&A); - Builder.CreateCall(Invoke, Args); - Builder.CreateRetVoid(); - Builder.restoreIP(IP); - return F; -} - -/// Create an OpenCL kernel for an enqueued block. -/// -/// The type of the first argument (the block literal) is the struct type -/// of the block literal instead of a pointer type. The first argument -/// (block literal) is passed directly by value to the kernel. The kernel -/// allocates the same type of struct on stack and stores the block literal -/// to it and passes its pointer to the block invoke function. The kernel -/// has "enqueued-block" function attribute and kernel argument metadata. -llvm::Function *AMDGPUTargetCodeGenInfo::createEnqueuedBlockKernel( - CodeGenFunction &CGF, llvm::Function *Invoke, - llvm::Value *BlockLiteral) const { - auto &Builder = CGF.Builder; - auto &C = CGF.getLLVMContext(); - - auto *BlockTy = BlockLiteral->getType()->getPointerElementType(); - auto *InvokeFT = Invoke->getFunctionType(); - llvm::SmallVector<llvm::Type *, 2> ArgTys; - llvm::SmallVector<llvm::Metadata *, 8> AddressQuals; - llvm::SmallVector<llvm::Metadata *, 8> AccessQuals; - llvm::SmallVector<llvm::Metadata *, 8> ArgTypeNames; - llvm::SmallVector<llvm::Metadata *, 8> ArgBaseTypeNames; - llvm::SmallVector<llvm::Metadata *, 8> ArgTypeQuals; - llvm::SmallVector<llvm::Metadata *, 8> ArgNames; - - ArgTys.push_back(BlockTy); - ArgTypeNames.push_back(llvm::MDString::get(C, "__block_literal")); - AddressQuals.push_back(llvm::ConstantAsMetadata::get(Builder.getInt32(0))); - ArgBaseTypeNames.push_back(llvm::MDString::get(C, "__block_literal")); - ArgTypeQuals.push_back(llvm::MDString::get(C, "")); - AccessQuals.push_back(llvm::MDString::get(C, "none")); - ArgNames.push_back(llvm::MDString::get(C, "block_literal")); - for (unsigned I = 1, E = InvokeFT->getNumParams(); I < E; ++I) { - ArgTys.push_back(InvokeFT->getParamType(I)); - ArgTypeNames.push_back(llvm::MDString::get(C, "void*")); - AddressQuals.push_back(llvm::ConstantAsMetadata::get(Builder.getInt32(3))); - AccessQuals.push_back(llvm::MDString::get(C, "none")); - ArgBaseTypeNames.push_back(llvm::MDString::get(C, "void*")); - ArgTypeQuals.push_back(llvm::MDString::get(C, "")); - ArgNames.push_back( - llvm::MDString::get(C, (Twine("local_arg") + Twine(I)).str())); - } - std::string Name = Invoke->getName().str() + "_kernel"; - auto *FT = llvm::FunctionType::get(llvm::Type::getVoidTy(C), ArgTys, false); - auto *F = llvm::Function::Create(FT, llvm::GlobalValue::InternalLinkage, Name, - &CGF.CGM.getModule()); - F->addFnAttr("enqueued-block"); - auto IP = CGF.Builder.saveIP(); - auto *BB = llvm::BasicBlock::Create(C, "entry", F); - Builder.SetInsertPoint(BB); - unsigned BlockAlign = CGF.CGM.getDataLayout().getPrefTypeAlignment(BlockTy); - auto *BlockPtr = Builder.CreateAlloca(BlockTy, nullptr); - BlockPtr->setAlignment(BlockAlign); - Builder.CreateAlignedStore(F->arg_begin(), BlockPtr, BlockAlign); - auto *Cast = Builder.CreatePointerCast(BlockPtr, InvokeFT->getParamType(0)); - llvm::SmallVector<llvm::Value *, 2> Args; - Args.push_back(Cast); - for (auto I = F->arg_begin() + 1, E = F->arg_end(); I != E; ++I) - Args.push_back(I); - Builder.CreateCall(Invoke, Args); - Builder.CreateRetVoid(); - Builder.restoreIP(IP); - - F->setMetadata("kernel_arg_addr_space", llvm::MDNode::get(C, AddressQuals)); - F->setMetadata("kernel_arg_access_qual", llvm::MDNode::get(C, AccessQuals)); - F->setMetadata("kernel_arg_type", llvm::MDNode::get(C, ArgTypeNames)); - F->setMetadata("kernel_arg_base_type", - llvm::MDNode::get(C, ArgBaseTypeNames)); - F->setMetadata("kernel_arg_type_qual", llvm::MDNode::get(C, ArgTypeQuals)); - if (CGF.CGM.getCodeGenOpts().EmitOpenCLArgMetadata) - F->setMetadata("kernel_arg_name", llvm::MDNode::get(C, ArgNames)); - - return F; -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/TargetInfo.h b/gnu/llvm/tools/clang/lib/CodeGen/TargetInfo.h deleted file mode 100644 index b530260ea48..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/TargetInfo.h +++ /dev/null @@ -1,311 +0,0 @@ -//===---- TargetInfo.h - Encapsulate target details -------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// These classes wrap the information about a call or function -// definition used to handle ABI compliancy. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_TARGETINFO_H -#define LLVM_CLANG_LIB_CODEGEN_TARGETINFO_H - -#include "CodeGenModule.h" -#include "CGValue.h" -#include "clang/AST/Type.h" -#include "clang/Basic/LLVM.h" -#include "clang/Basic/SyncScope.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringRef.h" - -namespace llvm { -class Constant; -class GlobalValue; -class Type; -class Value; -} - -namespace clang { -class Decl; - -namespace CodeGen { -class ABIInfo; -class CallArgList; -class CodeGenFunction; -class CGBlockInfo; -class CGFunctionInfo; - -/// TargetCodeGenInfo - This class organizes various target-specific -/// codegeneration issues, like target-specific attributes, builtins and so -/// on. -class TargetCodeGenInfo { - ABIInfo *Info; - -public: - // WARNING: Acquires the ownership of ABIInfo. - TargetCodeGenInfo(ABIInfo *info = nullptr) : Info(info) {} - virtual ~TargetCodeGenInfo(); - - /// getABIInfo() - Returns ABI info helper for the target. - const ABIInfo &getABIInfo() const { return *Info; } - - /// setTargetAttributes - Provides a convenient hook to handle extra - /// target-specific attributes for the given global. - virtual void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &M) const {} - - /// emitTargetMD - Provides a convenient hook to handle extra - /// target-specific metadata for the given global. - virtual void emitTargetMD(const Decl *D, llvm::GlobalValue *GV, - CodeGen::CodeGenModule &M) const {} - - /// Determines the size of struct _Unwind_Exception on this platform, - /// in 8-bit units. The Itanium ABI defines this as: - /// struct _Unwind_Exception { - /// uint64 exception_class; - /// _Unwind_Exception_Cleanup_Fn exception_cleanup; - /// uint64 private_1; - /// uint64 private_2; - /// }; - virtual unsigned getSizeOfUnwindException() const; - - /// Controls whether __builtin_extend_pointer should sign-extend - /// pointers to uint64_t or zero-extend them (the default). Has - /// no effect for targets: - /// - that have 64-bit pointers, or - /// - that cannot address through registers larger than pointers, or - /// - that implicitly ignore/truncate the top bits when addressing - /// through such registers. - virtual bool extendPointerWithSExt() const { return false; } - - /// Determines the DWARF register number for the stack pointer, for - /// exception-handling purposes. Implements __builtin_dwarf_sp_column. - /// - /// Returns -1 if the operation is unsupported by this target. - virtual int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const { - return -1; - } - - /// Initializes the given DWARF EH register-size table, a char*. - /// Implements __builtin_init_dwarf_reg_size_table. - /// - /// Returns true if the operation is unsupported by this target. - virtual bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, - llvm::Value *Address) const { - return true; - } - - /// Performs the code-generation required to convert a return - /// address as stored by the system into the actual address of the - /// next instruction that will be executed. - /// - /// Used by __builtin_extract_return_addr(). - virtual llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF, - llvm::Value *Address) const { - return Address; - } - - /// Performs the code-generation required to convert the address - /// of an instruction into a return address suitable for storage - /// by the system in a return slot. - /// - /// Used by __builtin_frob_return_addr(). - virtual llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF, - llvm::Value *Address) const { - return Address; - } - - /// Corrects the low-level LLVM type for a given constraint and "usual" - /// type. - /// - /// \returns A pointer to a new LLVM type, possibly the same as the original - /// on success; 0 on failure. - virtual llvm::Type *adjustInlineAsmType(CodeGen::CodeGenFunction &CGF, - StringRef Constraint, - llvm::Type *Ty) const { - return Ty; - } - - /// Adds constraints and types for result registers. - virtual void addReturnRegisterOutputs( - CodeGen::CodeGenFunction &CGF, CodeGen::LValue ReturnValue, - std::string &Constraints, std::vector<llvm::Type *> &ResultRegTypes, - std::vector<llvm::Type *> &ResultTruncRegTypes, - std::vector<CodeGen::LValue> &ResultRegDests, std::string &AsmString, - unsigned NumOutputs) const {} - - /// doesReturnSlotInterfereWithArgs - Return true if the target uses an - /// argument slot for an 'sret' type. - virtual bool doesReturnSlotInterfereWithArgs() const { return true; } - - /// Retrieve the address of a function to call immediately before - /// calling objc_retainAutoreleasedReturnValue. The - /// implementation of objc_autoreleaseReturnValue sniffs the - /// instruction stream following its return address to decide - /// whether it's a call to objc_retainAutoreleasedReturnValue. - /// This can be prohibitively expensive, depending on the - /// relocation model, and so on some targets it instead sniffs for - /// a particular instruction sequence. This functions returns - /// that instruction sequence in inline assembly, which will be - /// empty if none is required. - virtual StringRef getARCRetainAutoreleasedReturnValueMarker() const { - return ""; - } - - /// Return a constant used by UBSan as a signature to identify functions - /// possessing type information, or 0 if the platform is unsupported. - virtual llvm::Constant * - getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const { - return nullptr; - } - - /// Determine whether a call to an unprototyped functions under - /// the given calling convention should use the variadic - /// convention or the non-variadic convention. - /// - /// There's a good reason to make a platform's variadic calling - /// convention be different from its non-variadic calling - /// convention: the non-variadic arguments can be passed in - /// registers (better for performance), and the variadic arguments - /// can be passed on the stack (also better for performance). If - /// this is done, however, unprototyped functions *must* use the - /// non-variadic convention, because C99 states that a call - /// through an unprototyped function type must succeed if the - /// function was defined with a non-variadic prototype with - /// compatible parameters. Therefore, splitting the conventions - /// makes it impossible to call a variadic function through an - /// unprototyped type. Since function prototypes came out in the - /// late 1970s, this is probably an acceptable trade-off. - /// Nonetheless, not all platforms are willing to make it, and in - /// particularly x86-64 bends over backwards to make the - /// conventions compatible. - /// - /// The default is false. This is correct whenever: - /// - the conventions are exactly the same, because it does not - /// matter and the resulting IR will be somewhat prettier in - /// certain cases; or - /// - the conventions are substantively different in how they pass - /// arguments, because in this case using the variadic convention - /// will lead to C99 violations. - /// - /// However, some platforms make the conventions identical except - /// for passing additional out-of-band information to a variadic - /// function: for example, x86-64 passes the number of SSE - /// arguments in %al. On these platforms, it is desirable to - /// call unprototyped functions using the variadic convention so - /// that unprototyped calls to varargs functions still succeed. - /// - /// Relatedly, platforms which pass the fixed arguments to this: - /// A foo(B, C, D); - /// differently than they would pass them to this: - /// A foo(B, C, D, ...); - /// may need to adjust the debugger-support code in Sema to do the - /// right thing when calling a function with no know signature. - virtual bool isNoProtoCallVariadic(const CodeGen::CallArgList &args, - const FunctionNoProtoType *fnType) const; - - /// Gets the linker options necessary to link a dependent library on this - /// platform. - virtual void getDependentLibraryOption(llvm::StringRef Lib, - llvm::SmallString<24> &Opt) const; - - /// Gets the linker options necessary to detect object file mismatches on - /// this platform. - virtual void getDetectMismatchOption(llvm::StringRef Name, - llvm::StringRef Value, - llvm::SmallString<32> &Opt) const {} - - /// Get LLVM calling convention for OpenCL kernel. - virtual unsigned getOpenCLKernelCallingConv() const; - - /// Get target specific null pointer. - /// \param T is the LLVM type of the null pointer. - /// \param QT is the clang QualType of the null pointer. - /// \return ConstantPointerNull with the given type \p T. - /// Each target can override it to return its own desired constant value. - virtual llvm::Constant *getNullPointer(const CodeGen::CodeGenModule &CGM, - llvm::PointerType *T, QualType QT) const; - - /// Get target favored AST address space of a global variable for languages - /// other than OpenCL and CUDA. - /// If \p D is nullptr, returns the default target favored address space - /// for global variable. - virtual LangAS getGlobalVarAddressSpace(CodeGenModule &CGM, - const VarDecl *D) const; - - /// Get the AST address space for alloca. - virtual LangAS getASTAllocaAddressSpace() const { return LangAS::Default; } - - /// Perform address space cast of an expression of pointer type. - /// \param V is the LLVM value to be casted to another address space. - /// \param SrcAddr is the language address space of \p V. - /// \param DestAddr is the targeted language address space. - /// \param DestTy is the destination LLVM pointer type. - /// \param IsNonNull is the flag indicating \p V is known to be non null. - virtual llvm::Value *performAddrSpaceCast(CodeGen::CodeGenFunction &CGF, - llvm::Value *V, LangAS SrcAddr, - LangAS DestAddr, llvm::Type *DestTy, - bool IsNonNull = false) const; - - /// Perform address space cast of a constant expression of pointer type. - /// \param V is the LLVM constant to be casted to another address space. - /// \param SrcAddr is the language address space of \p V. - /// \param DestAddr is the targeted language address space. - /// \param DestTy is the destination LLVM pointer type. - virtual llvm::Constant *performAddrSpaceCast(CodeGenModule &CGM, - llvm::Constant *V, - LangAS SrcAddr, LangAS DestAddr, - llvm::Type *DestTy) const; - - /// Get the syncscope used in LLVM IR. - virtual llvm::SyncScope::ID getLLVMSyncScopeID(SyncScope S, - llvm::LLVMContext &C) const; - - /// Interface class for filling custom fields of a block literal for OpenCL. - class TargetOpenCLBlockHelper { - public: - typedef std::pair<llvm::Value *, StringRef> ValueTy; - TargetOpenCLBlockHelper() {} - virtual ~TargetOpenCLBlockHelper() {} - /// Get the custom field types for OpenCL blocks. - virtual llvm::SmallVector<llvm::Type *, 1> getCustomFieldTypes() = 0; - /// Get the custom field values for OpenCL blocks. - virtual llvm::SmallVector<ValueTy, 1> - getCustomFieldValues(CodeGenFunction &CGF, const CGBlockInfo &Info) = 0; - virtual bool areAllCustomFieldValuesConstant(const CGBlockInfo &Info) = 0; - /// Get the custom field values for OpenCL blocks if all values are LLVM - /// constants. - virtual llvm::SmallVector<llvm::Constant *, 1> - getCustomFieldValues(CodeGenModule &CGM, const CGBlockInfo &Info) = 0; - }; - virtual TargetOpenCLBlockHelper *getTargetOpenCLBlockHelper() const { - return nullptr; - } - - /// Create an OpenCL kernel for an enqueued block. The kernel function is - /// a wrapper for the block invoke function with target-specific calling - /// convention and ABI as an OpenCL kernel. The wrapper function accepts - /// block context and block arguments in target-specific way and calls - /// the original block invoke function. - virtual llvm::Function * - createEnqueuedBlockKernel(CodeGenFunction &CGF, - llvm::Function *BlockInvokeFunc, - llvm::Value *BlockLiteral) const; - - /// \return true if the target supports alias from the unmangled name to the - /// mangled name of functions declared within an extern "C" region and marked - /// as 'used', and having internal linkage. - virtual bool shouldEmitStaticExternCAliases() const { return true; } - - virtual void setCUDAKernelCallingConvention(const FunctionType *&FT) const {} -}; - -} // namespace CodeGen -} // namespace clang - -#endif // LLVM_CLANG_LIB_CODEGEN_TARGETINFO_H diff --git a/gnu/llvm/tools/clang/lib/CodeGen/VarBypassDetector.cpp b/gnu/llvm/tools/clang/lib/CodeGen/VarBypassDetector.cpp deleted file mode 100644 index 859cdd4282c..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/VarBypassDetector.cpp +++ /dev/null @@ -1,168 +0,0 @@ -//===--- VarBypassDetector.h - Bypass jumps detector --------------*- C++ -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "VarBypassDetector.h" - -#include "clang/AST/Decl.h" -#include "clang/AST/Expr.h" -#include "clang/AST/Stmt.h" - -using namespace clang; -using namespace CodeGen; - -/// Clear the object and pre-process for the given statement, usually function -/// body statement. -void VarBypassDetector::Init(const Stmt *Body) { - FromScopes.clear(); - ToScopes.clear(); - Bypasses.clear(); - Scopes = {{~0U, nullptr}}; - unsigned ParentScope = 0; - AlwaysBypassed = !BuildScopeInformation(Body, ParentScope); - if (!AlwaysBypassed) - Detect(); -} - -/// Build scope information for a declaration that is part of a DeclStmt. -/// Returns false if we failed to build scope information and can't tell for -/// which vars are being bypassed. -bool VarBypassDetector::BuildScopeInformation(const Decl *D, - unsigned &ParentScope) { - const VarDecl *VD = dyn_cast<VarDecl>(D); - if (VD && VD->hasLocalStorage()) { - Scopes.push_back({ParentScope, VD}); - ParentScope = Scopes.size() - 1; - } - - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) - if (const Expr *Init = VD->getInit()) - return BuildScopeInformation(Init, ParentScope); - - return true; -} - -/// Walk through the statements, adding any labels or gotos to -/// LabelAndGotoScopes and recursively walking the AST as needed. -/// Returns false if we failed to build scope information and can't tell for -/// which vars are being bypassed. -bool VarBypassDetector::BuildScopeInformation(const Stmt *S, - unsigned &origParentScope) { - // If this is a statement, rather than an expression, scopes within it don't - // propagate out into the enclosing scope. Otherwise we have to worry about - // block literals, which have the lifetime of their enclosing statement. - unsigned independentParentScope = origParentScope; - unsigned &ParentScope = - ((isa<Expr>(S) && !isa<StmtExpr>(S)) ? origParentScope - : independentParentScope); - - unsigned StmtsToSkip = 0u; - - switch (S->getStmtClass()) { - case Stmt::IndirectGotoStmtClass: - return false; - - case Stmt::SwitchStmtClass: - if (const Stmt *Init = cast<SwitchStmt>(S)->getInit()) { - if (!BuildScopeInformation(Init, ParentScope)) - return false; - ++StmtsToSkip; - } - if (const VarDecl *Var = cast<SwitchStmt>(S)->getConditionVariable()) { - if (!BuildScopeInformation(Var, ParentScope)) - return false; - ++StmtsToSkip; - } - LLVM_FALLTHROUGH; - - case Stmt::GotoStmtClass: - FromScopes.push_back({S, ParentScope}); - break; - - case Stmt::DeclStmtClass: { - const DeclStmt *DS = cast<DeclStmt>(S); - for (auto *I : DS->decls()) - if (!BuildScopeInformation(I, origParentScope)) - return false; - return true; - } - - case Stmt::CaseStmtClass: - case Stmt::DefaultStmtClass: - case Stmt::LabelStmtClass: - llvm_unreachable("the loop below handles labels and cases"); - break; - - default: - break; - } - - for (const Stmt *SubStmt : S->children()) { - if (!SubStmt) - continue; - if (StmtsToSkip) { - --StmtsToSkip; - continue; - } - - // Cases, labels, and defaults aren't "scope parents". It's also - // important to handle these iteratively instead of recursively in - // order to avoid blowing out the stack. - while (true) { - const Stmt *Next; - if (const SwitchCase *SC = dyn_cast<SwitchCase>(SubStmt)) - Next = SC->getSubStmt(); - else if (const LabelStmt *LS = dyn_cast<LabelStmt>(SubStmt)) - Next = LS->getSubStmt(); - else - break; - - ToScopes[SubStmt] = ParentScope; - SubStmt = Next; - } - - // Recursively walk the AST. - if (!BuildScopeInformation(SubStmt, ParentScope)) - return false; - } - return true; -} - -/// Checks each jump and stores each variable declaration they bypass. -void VarBypassDetector::Detect() { - for (const auto &S : FromScopes) { - const Stmt *St = S.first; - unsigned from = S.second; - if (const GotoStmt *GS = dyn_cast<GotoStmt>(St)) { - if (const LabelStmt *LS = GS->getLabel()->getStmt()) - Detect(from, ToScopes[LS]); - } else if (const SwitchStmt *SS = dyn_cast<SwitchStmt>(St)) { - for (const SwitchCase *SC = SS->getSwitchCaseList(); SC; - SC = SC->getNextSwitchCase()) { - Detect(from, ToScopes[SC]); - } - } else { - llvm_unreachable("goto or switch was expected"); - } - } -} - -/// Checks the jump and stores each variable declaration it bypasses. -void VarBypassDetector::Detect(unsigned From, unsigned To) { - while (From != To) { - if (From < To) { - assert(Scopes[To].first < To); - const auto &ScopeTo = Scopes[To]; - To = ScopeTo.first; - Bypasses.insert(ScopeTo.second); - } else { - assert(Scopes[From].first < From); - From = Scopes[From].first; - } - } -} diff --git a/gnu/llvm/tools/clang/lib/CodeGen/VarBypassDetector.h b/gnu/llvm/tools/clang/lib/CodeGen/VarBypassDetector.h deleted file mode 100644 index 47fe13cfacd..00000000000 --- a/gnu/llvm/tools/clang/lib/CodeGen/VarBypassDetector.h +++ /dev/null @@ -1,71 +0,0 @@ -//===--- VarBypassDetector.cpp - Bypass jumps detector ------------*- C++ -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains VarBypassDetector class, which is used to detect -// local variable declarations which can be bypassed by jumps. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_CODEGEN_VARBYPASSDETECTOR_H -#define LLVM_CLANG_LIB_CODEGEN_VARBYPASSDETECTOR_H - -#include "clang/AST/Decl.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SmallVector.h" - -namespace clang { - -class Decl; -class Stmt; -class VarDecl; - -namespace CodeGen { - -/// The class detects jumps which bypass local variables declaration: -/// goto L; -/// int a; -/// L: -/// -/// This is simplified version of JumpScopeChecker. Primary differences: -/// * Detects only jumps into the scope local variables. -/// * Does not detect jumps out of the scope of local variables. -/// * Not limited to variables with initializers, JumpScopeChecker is limited. -class VarBypassDetector { - // Scope information. Contains a parent scope and related variable - // declaration. - llvm::SmallVector<std::pair<unsigned, const VarDecl *>, 48> Scopes; - // List of jumps with scopes. - llvm::SmallVector<std::pair<const Stmt *, unsigned>, 16> FromScopes; - // Lookup map to find scope for destinations. - llvm::DenseMap<const Stmt *, unsigned> ToScopes; - // Set of variables which were bypassed by some jump. - llvm::DenseSet<const VarDecl *> Bypasses; - // If true assume that all variables are being bypassed. - bool AlwaysBypassed = false; - -public: - void Init(const Stmt *Body); - - /// Returns true if the variable declaration was by bypassed by any goto or - /// switch statement. - bool IsBypassed(const VarDecl *D) const { - return AlwaysBypassed || Bypasses.find(D) != Bypasses.end(); - } - -private: - bool BuildScopeInformation(const Decl *D, unsigned &ParentScope); - bool BuildScopeInformation(const Stmt *S, unsigned &origParentScope); - void Detect(); - void Detect(unsigned From, unsigned To); -}; -} -} - -#endif |
