//==-- SwiftCallingConv.h - Swift ABI lowering ------------------*- C++ -*-===//
 
//
 
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 
// See https://llvm.org/LICENSE.txt for license information.
 
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
//
 
//===----------------------------------------------------------------------===//
 
//
 
// Defines constants and types related to Swift ABI lowering. The same ABI
 
// lowering applies to both sync and async functions.
 
//
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef LLVM_CLANG_CODEGEN_SWIFTCALLINGCONV_H
 
#define LLVM_CLANG_CODEGEN_SWIFTCALLINGCONV_H
 
 
 
#include "clang/AST/CanonicalType.h"
 
#include "clang/AST/CharUnits.h"
 
#include "clang/AST/Type.h"
 
#include "llvm/Support/TrailingObjects.h"
 
#include <cassert>
 
 
 
namespace llvm {
 
  class IntegerType;
 
  class Type;
 
  class StructType;
 
  class VectorType;
 
}
 
 
 
namespace clang {
 
class FieldDecl;
 
class ASTRecordLayout;
 
 
 
namespace CodeGen {
 
class ABIArgInfo;
 
class CodeGenModule;
 
class CGFunctionInfo;
 
 
 
namespace swiftcall {
 
 
 
class SwiftAggLowering {
 
  CodeGenModule &CGM;
 
 
 
  struct StorageEntry {
 
    CharUnits Begin;
 
    CharUnits End;
 
    llvm::Type *Type;
 
 
 
    CharUnits getWidth() const {
 
      return End - Begin;
 
    }
 
  };
 
  SmallVector<StorageEntry, 4> Entries;
 
  bool Finished = false;
 
 
 
public:
 
  SwiftAggLowering(CodeGenModule &CGM) : CGM(CGM) {}
 
 
 
  void addOpaqueData(CharUnits begin, CharUnits end) {
 
    addEntry(nullptr, begin, end);
 
  }
 
 
 
  void addTypedData(QualType type, CharUnits begin);
 
  void addTypedData(const RecordDecl *record, CharUnits begin);
 
  void addTypedData(const RecordDecl *record, CharUnits begin,
 
                    const ASTRecordLayout &layout);
 
  void addTypedData(llvm::Type *type, CharUnits begin);
 
  void addTypedData(llvm::Type *type, CharUnits begin, CharUnits end);
 
 
 
  void finish();
 
 
 
  /// Does this lowering require passing any data?
 
  bool empty() const {
 
    assert(Finished && "didn't finish lowering before calling empty()");
 
    return Entries.empty();
 
  }
 
 
 
  /// According to the target Swift ABI, should a value with this lowering
 
  /// be passed indirectly?
 
  ///
 
  /// Note that this decision is based purely on the data layout of the
 
  /// value and does not consider whether the type is address-only,
 
  /// must be passed indirectly to match a function abstraction pattern, or
 
  /// anything else that is expected to be handled by high-level lowering.
 
  ///
 
  /// \param asReturnValue - if true, answer whether it should be passed
 
  ///   indirectly as a return value; if false, answer whether it should be
 
  ///   passed indirectly as an argument
 
  bool shouldPassIndirectly(bool asReturnValue) const;
 
 
 
  using EnumerationCallback =
 
    llvm::function_ref<void(CharUnits offset, CharUnits end, llvm::Type *type)>;
 
 
 
  /// Enumerate the expanded components of this type.
 
  ///
 
  /// The component types will always be legal vector, floating-point,
 
  /// integer, or pointer types.
 
  void enumerateComponents(EnumerationCallback callback) const;
 
 
 
  /// Return the types for a coerce-and-expand operation.
 
  ///
 
  /// The first type matches the memory layout of the data that's been
 
  /// added to this structure, including explicit [N x i8] arrays for any
 
  /// internal padding.
 
  ///
 
  /// The second type removes any internal padding members and, if only
 
  /// one element remains, is simply that element type.
 
  std::pair<llvm::StructType*, llvm::Type*> getCoerceAndExpandTypes() const;
 
 
 
private:
 
  void addBitFieldData(const FieldDecl *field, CharUnits begin,
 
                       uint64_t bitOffset);
 
  void addLegalTypedData(llvm::Type *type, CharUnits begin, CharUnits end);
 
  void addEntry(llvm::Type *type, CharUnits begin, CharUnits end);
 
  void splitVectorEntry(unsigned index);
 
  static bool shouldMergeEntries(const StorageEntry &first,
 
                                 const StorageEntry &second,
 
                                 CharUnits chunkSize);
 
};
 
 
 
/// Should an aggregate which expands to the given type sequence
 
/// be passed/returned indirectly under swiftcall?
 
bool shouldPassIndirectly(CodeGenModule &CGM,
 
                          ArrayRef<llvm::Type*> types,
 
                          bool asReturnValue);
 
 
 
/// Return the maximum voluntary integer size for the current target.
 
CharUnits getMaximumVoluntaryIntegerSize(CodeGenModule &CGM);
 
 
 
/// Return the Swift CC's notion of the natural alignment of a type.
 
CharUnits getNaturalAlignment(CodeGenModule &CGM, llvm::Type *type);
 
 
 
/// Is the given integer type "legal" for Swift's perspective on the
 
/// current platform?
 
bool isLegalIntegerType(CodeGenModule &CGM, llvm::IntegerType *type);
 
 
 
/// Is the given vector type "legal" for Swift's perspective on the
 
/// current platform?
 
bool isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize,
 
                       llvm::VectorType *vectorTy);
 
bool isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize,
 
                       llvm::Type *eltTy, unsigned numElts);
 
 
 
/// Minimally split a legal vector type.
 
std::pair<llvm::Type*, unsigned>
 
splitLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize,
 
                     llvm::VectorType *vectorTy);
 
 
 
/// Turn a vector type in a sequence of legal component vector types.
 
///
 
/// The caller may assume that the sum of the data sizes of the resulting
 
/// types will equal the data size of the vector type.
 
void legalizeVectorType(CodeGenModule &CGM, CharUnits vectorSize,
 
                        llvm::VectorType *vectorTy,
 
                        llvm::SmallVectorImpl<llvm::Type*> &types);
 
 
 
/// Is the given record type required to be passed and returned indirectly
 
/// because of language restrictions?
 
///
 
/// This considers *only* mandatory indirectness due to language restrictions,
 
/// such as C++'s non-trivially-copyable types and Objective-C's __weak
 
/// references.  A record for which this returns true may still be passed
 
/// indirectly for other reasons, such as being too large to fit in a
 
/// reasonable number of registers.
 
bool mustPassRecordIndirectly(CodeGenModule &CGM, const RecordDecl *record);
 
 
 
/// Classify the rules for how to return a particular type.
 
ABIArgInfo classifyReturnType(CodeGenModule &CGM, CanQualType type);
 
 
 
/// Classify the rules for how to pass a particular type.
 
ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type);
 
 
 
/// Compute the ABI information of a swiftcall function.  This is a
 
/// private interface for Clang.
 
void computeABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI);
 
 
 
/// Is swifterror lowered to a register by the target ABI?
 
bool isSwiftErrorLoweredInRegister(CodeGenModule &CGM);
 
 
 
} // end namespace swiftcall
 
} // end namespace CodeGen
 
} // end namespace clang
 
 
 
#endif