<commit_before>//===--- TypeLowering.cpp - Type information for SILGen ---------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/AST/ArchetypeBuilder.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/CanTypeVisitor.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Expr.h"
#include "swift/AST/Module.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/Types.h"
#include "swift/Basic/Fallthrough.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/TypeLowering.h"
#include "llvm/Support/Debug.h"

using namespace swift;
using namespace Lowering;

namespace {
  /// A CRTP type visitor for deciding whether the metatype for a type
  /// has trivial representation.
  struct HasTrivialMetatype : CanTypeVisitor<HasTrivialMetatype, bool> {
    /// Class metatypes have non-trivial representation due to the
    /// possibility of subclassing.
    bool visitClassType(CanClassType type) {
      return false;
    }
    bool visitBoundGenericClassType(CanBoundGenericClassType type) {
      return false;
    }
    bool visitDynamicSelfType(CanDynamicSelfType type) {
      return false;
    }

    /// Dependent types have non-trivial representation in case they
    /// instantiate to a class metatype.
    bool visitGenericTypeParamType(CanGenericTypeParamType type) {
      return false;
    }
    bool visitDependentMemberType(CanDependentMemberType type) {
      return false;
    }
    
    /// Archetype metatypes have non-trivial representation in case
    /// they instantiate to a class metatype.
    bool visitArchetypeType(CanArchetypeType type) {
      return false;
    }
    
    /// All levels of class metatypes support subtyping.
    bool visitMetatypeType(CanMetatypeType type) {
      return visit(type.getInstanceType());
    }

    /// Existential metatypes have non-trivial representation because
    /// they can refer to an arbitrary metatype. Everything else is trivial.
    bool visitType(CanType type) {
      return !type->isExistentialType();
    }
  };
}

/// Does the metatype for the given type have a trivial representation?
static bool hasTrivialMetatype(CanType instanceType) {
  return HasTrivialMetatype().visit(instanceType);
}

static CanType getKnownType(Optional<CanType> &cacheSlot, ASTContext &C,
                            StringRef moduleName, StringRef typeName) {
  CanType t = cacheSlot.cache([&] {
    Optional<UnqualifiedLookup> lookup
      = UnqualifiedLookup::forModuleAndName(C, moduleName, typeName);
    if (!lookup)
      return CanType();
    if (TypeDecl *typeDecl = lookup->getSingleTypeResult()) {
      assert(typeDecl->getDeclaredType() &&
             "bridged type must be type-checked");
      return typeDecl->getDeclaredType()->getCanonicalType();
    }
    return CanType();
  });

  // It is possible that we won't find a briding type (e.g. String) when we're
  // parsing the stdlib itself.
  if (t) {
    DEBUG(llvm::dbgs() << "Bridging type " << moduleName << '.' << typeName
            << " mapped to ";
          if (t)
            t->print(llvm::dbgs());
          else
            llvm::dbgs() << "<null>";
          llvm::dbgs() << '\n');
  }
  return t;
}

#define BRIDGE_TYPE(BridgedModule,BridgedType, NativeModule,NativeType,Opt) \
  CanType TypeConverter::get##BridgedType##Type() {         \
    return getKnownType(BridgedType##Ty, M.getASTContext(), \
                        #BridgedModule, #BridgedType);      \
  }                                                         \
  CanType TypeConverter::get##NativeType##Type() {          \
    return getKnownType(NativeType##Ty, M.getASTContext(),  \
                        #NativeModule, #NativeType);        \
  }
#include "swift/SIL/BridgedTypes.def"

CaptureKind Lowering::getDeclCaptureKind(CaptureInfo::LocalCaptureTy capture) {
  if (VarDecl *var = dyn_cast<VarDecl>(capture.getPointer())) {
    // If captured directly, the variable is captured by box.
    if (capture.getInt()) {
      assert(var->hasStorage());
      return CaptureKind::Box;
    }

    auto StorageKind = var->getStorageKind();

    // Properties with trivial accessors are captured by-accessor if they are
    // @objc (since the accessors can be overriden) or captured by constant or
    // by-box if not.
    if (StorageKind == VarDecl::StoredWithTrivialAccessors)
      StorageKind = var->isObjC() ? VarDecl::Computed : VarDecl::Stored;

    switch (StorageKind) {
    case VarDecl::StoredWithTrivialAccessors:  assert(0 && "Handled above");
    case VarDecl::Computed:
      return var->getSetter()
        ? CaptureKind::GetterSetter : CaptureKind::Getter;
    case VarDecl::Observing:
      return CaptureKind::GetterSetter;
    case VarDecl::Stored:
      if (var->isLet())
        return CaptureKind::Constant;

      return CaptureKind::Box;
    }
  }
  
  // "Captured" local typealiases require no context.
  // FIXME: Is this true for dependent typealiases?
  if (isa<TypeAliasDecl>(capture.getPointer()))
    return CaptureKind::None;
  
  return CaptureKind::LocalFunction;
}

enum class LoweredTypeKind {
  /// Trivial and loadable.
  Trivial,

  /// A reference type.
  Reference,

  /// An aggregate type that contains references (potentially recursively).
  AggWithReference,

  /// Non-trivial and not loadable.
  AddressOnly
};

static LoweredTypeKind classifyType(CanType type, SILModule &M);

namespace {
  /// A CRTP helper class for doing things that depends on type<commit_msg>SIL: Don't emit capture parameters for local generic param types.<commit_after>//===--- TypeLowering.cpp - Type information for SILGen ---------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/AST/ArchetypeBuilder.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/CanTypeVisitor.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Expr.h"
#include "swift/AST/Module.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/Types.h"
#include "swift/Basic/Fallthrough.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/TypeLowering.h"
#include "llvm/Support/Debug.h"

using namespace swift;
using namespace Lowering;

namespace {
  /// A CRTP type visitor for deciding whether the metatype for a type
  /// has trivial representation.
  struct HasTrivialMetatype : CanTypeVisitor<HasTrivialMetatype, bool> {
    /// Class metatypes have non-trivial representation due to the
    /// possibility of subclassing.
    bool visitClassType(CanClassType type) {
      return false;
    }
    bool visitBoundGenericClassType(CanBoundGenericClassType type) {
      return false;
    }
    bool visitDynamicSelfType(CanDynamicSelfType type) {
      return false;
    }

    /// Dependent types have non-trivial representation in case they
    /// instantiate to a class metatype.
    bool visitGenericTypeParamType(CanGenericTypeParamType type) {
      return false;
    }
    bool visitDependentMemberType(CanDependentMemberType type) {
      return false;
    }
    
    /// Archetype metatypes have non-trivial representation in case
    /// they instantiate to a class metatype.
    bool visitArchetypeType(CanArchetypeType type) {
      return false;
    }
    
    /// All levels of class metatypes support subtyping.
    bool visitMetatypeType(CanMetatypeType type) {
      return visit(type.getInstanceType());
    }

    /// Existential metatypes have non-trivial representation because
    /// they can refer to an arbitrary metatype. Everything else is trivial.
    bool visitType(CanType type) {
      return !type->isExistentialType();
    }
  };
}

/// Does the metatype for the given type have a trivial representation?
static bool hasTrivialMetatype(CanType instanceType) {
  return HasTrivialMetatype().visit(instanceType);
}

static CanType getKnownType(Optional<CanType> &cacheSlot, ASTContext &C,
                            StringRef moduleName, StringRef typeName) {
  CanType t = cacheSlot.cache([&] {
    Optional<UnqualifiedLookup> lookup
      = UnqualifiedLookup::forModuleAndName(C, moduleName, typeName);
    if (!lookup)
      return CanType();
    if (TypeDecl *typeDecl = lookup->getSingleTypeResult()) {
      assert(typeDecl->getDeclaredType() &&
             "bridged type must be type-checked");
      return typeDecl->getDeclaredType()->getCanonicalType();
    }
    return CanType();
  });

  // It is possible that we won't find a briding type (e.g. String) when we're
  // parsing the stdlib itself.
  if (t) {
    DEBUG(llvm::dbgs() << "Bridging type " << moduleName << '.' << typeName
            << " mapped to ";
          if (t)
            t->print(llvm::dbgs());
          else
            llvm::dbgs() << "<null>";
          llvm::dbgs() << '\n');
  }
  return t;
}

#define BRIDGE_TYPE(BridgedModule,BridgedType, NativeModule,NativeType,Opt) \
  CanType TypeConverter::get##BridgedType##Type() {         \
    return getKnownType(BridgedType##Ty, M.getASTContext(), \
                        #BridgedModule, #BridgedType);      \
  }                                                         \
  CanType TypeConverter::get##NativeType##Type() {          \
    return getKnownType(NativeType##Ty, M.getASTContext(),  \
                        #NativeModule, #NativeType);        \
  }
#include "swift/SIL/BridgedTypes.def"

CaptureKind Lowering::getDeclCaptureKind(CaptureInfo::LocalCaptureTy capture) {
  if (VarDecl *var = dyn_cast<VarDecl>(capture.getPointer())) {
    // If captured directly, the variable is captured by box.
    if (capture.getInt()) {
      assert(var->hasStorage());
      return CaptureKind::Box;
    }

    auto StorageKind = var->getStorageKind();

    // Properties with trivial accessors are captured by-accessor if they are
    // @objc (since the accessors can be overriden) or captured by constant or
    // by-box if not.
    if (StorageKind == VarDecl::StoredWithTrivialAccessors)
      StorageKind = var->isObjC() ? VarDecl::Computed : VarDecl::Stored;

    switch (StorageKind) {
    case VarDecl::StoredWithTrivialAccessors:  assert(0 && "Handled above");
    case VarDecl::Computed:
      return var->getSetter()
        ? CaptureKind::GetterSetter : CaptureKind::Getter;
    case VarDecl::Observing:
      return CaptureKind::GetterSetter;
    case VarDecl::Stored:
      if (var->isLet())
        return CaptureKind::Constant;

      return CaptureKind::Box;
    }
  }
  
  // "Captured" local types require no context.
  if (isa<TypeAliasDecl>(capture.getPointer()))
    return CaptureKind::None;
  if (isa<GenericTypeParamDecl>(capture.getPointer()))
    return CaptureKind::None;
  if (isa<AssociatedTypeDecl>(capture.getPointer()))
    return CaptureKind::None;
  
  return CaptureKind::LocalFunction;
}

enum class LoweredTypeKind {
  /// Trivial and loadable.
  Trivial,

  /// A reference type.
  Reference,

  /// An aggregate type that contains references (potentially recursively).
  AggWithReference,

  /// Non-trivial and not loadable.
  AddressOnly
};

static LoweredTypeKind classifyType(CanType type, SILModule &M);

namespace {
  /// A CRTP helper class for doing things that depends on type
{'fraction_non_alphanumeric': 0.12688546328526437, 'fraction_numerical': 0.0018233051549809381, 'mean_word_length': 2.903914590747331, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3481265', 'n_tokens_mistral': 3588, 'n_tokens_neox': 3475, 'n_words': 931}