text:
//===--- Generics.cpp ---- Utilities for transforming generics ------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "generic-specializer"

#include "swift/Strings.h"
#include "swift/SILOptimizer/Utils/Generics.h"
#include "swift/SILOptimizer/Utils/GenericCloner.h"
#include "swift/SILOptimizer/Utils/SpecializationMangler.h"
#include "swift/SIL/DebugUtils.h"
#include "swift/AST/GenericSignatureBuilder.h"
#include "swift/AST/GenericEnvironment.h"

using namespace swift;

/// Set to true to enable the support for partial specialization.
llvm::cl::opt<bool> EnablePartialSpecialization(
    "sil-partial-specialization", llvm::cl::init(false),
    llvm::cl::desc("Enable partial specialization of generics"));

/// If set, then generic specialization tries to specialize using
/// all substitutions, even if they the replacement types are generic.
llvm::cl::opt<bool> SpecializeGenericSubstitutions(
    "sil-partial-specialization-with-generic-substitutions",
    llvm::cl::init(false),
    llvm::cl::desc("Enable partial specialization with generic substitutions"));

// Max depth of a type which can be processed by the generic
// specializer.
// E.g. the depth of Array<Array<Array<T>>> is 3.
// No specializations will be produced, if any of generic parameters contains
// a bound generic type with the depth higher than this threshold
static const unsigned TypeDepthThreshold = 50;
// Set the width threshold rather high, because some projects uses very wide
// tuples to model fixed size arrays.
static const unsigned TypeWidthThreshold = 2000;

// Compute the width and the depth of a type.
// We compute both, because some pathological test-cases result in very
// wide types and some others result in very deep types. It is important
// to bail as soon as we hit the threshold on any of both dimentions to
// prevent compiler hangs and crashes.
static std::pair<unsigned, unsigned> getTypeDepthAndWidth(Type t) {
  unsigned Depth = 0;
  unsigned Width = 0;
  if (auto *BGT = t->getAs<BoundGenericType>()) {
    auto *NTD = BGT->getNominalOrBoundGenericNominal();
    if (NTD) {
      auto StoredProperties = NTD->getStoredProperties();
      Width += std::distance(StoredProperties.begin(), StoredProperties.end());
    }
    Depth++;
    unsigned MaxTypeDepth = 0;
    auto GenericArgs = BGT->getGenericArgs();
    for (auto Ty : GenericArgs) {
      unsigned TypeWidth;
      unsigned TypeDepth;
      std::tie(TypeDepth, TypeWidth) = getTypeDepthAndWidth(Ty);
      if (TypeDepth > MaxTypeDepth)
        MaxTypeDepth = TypeDepth;
      Width += TypeWidth;
    }
    Depth += MaxTypeDepth;
    return std::make_pair(Depth, Width);
  }

  if (auto *TupleTy = t->getAs<TupleType>()) {
    Width += TupleTy->getNumElements();
    Depth++;
    unsigned MaxTypeDepth = 0;
    auto ElementTypes = TupleTy->getElementTypes();
    for (auto Ty : ElementTypes) {
      unsigned TypeWidth;
      unsigned TypeDepth;
      std::tie(TypeDepth, TypeWidth) = getTypeDepthAndWidth(Ty);
      if (TypeDepth > MaxTypeDepth)
        MaxTypeDepth = TypeDepth;
      Width += TypeWidth;
    }
    Depth += MaxTypeDepth;
    return std::make_pair(Depth, Width);
  }

  if (auto *FnTy = t->getAs<SILFunctionType>()) {
    Depth++;
    unsigned MaxTypeDepth = 0;
    auto Params = FnTy->getParameters();
    Width += Params.size();
    for (auto Param : Params) {
      unsigned TypeWidth;
      unsigned TypeDepth;
      std::tie(TypeDepth, TypeWidth) = getTypeDepthAndWidth(Param.getType());
      if (TypeDepth > MaxTypeDepth)
        MaxTypeDepth = TypeDepth;
      Width += TypeWidth;
    }
    auto Results = FnTy->getResults();
    Width += Results.size();
    for (auto Result : Results) {
      unsigned TypeWidth;
      unsigned TypeDepth;
      std::tie(TypeDepth, TypeWidth) = getTypeDepthAndWidth(Result.getType());
      if (TypeDepth > MaxTypeDepth)
        MaxTypeDepth = TypeDepth;
      Width += TypeWidth;
    }
    if (FnTy->hasErrorResult()) {
      Width += 1;
      unsigned TypeWidth;
      unsigned TypeDepth;
      std::tie(TypeDepth, TypeWidth) =
          getTypeDepthAndWidth(FnTy->getErrorResult().getType());
      if (TypeDepth > MaxTypeDepth)
        MaxTypeDepth = TypeDepth;
      Width += TypeWidth;
    }
    Depth += MaxTypeDepth;
    return std::make_pair(Depth, Width);
  }

  if (auto *FnTy = t->getAs<FunctionType>()) {
    Depth++;
    unsigned MaxTypeDepth = 0;
    unsigned TypeWidth;
    unsigned TypeDepth;
    std::tie(TypeDepth, TypeWidth) = getTypeDepthAndWidth(FnTy->getInput());
    if (TypeDepth > MaxTypeDepth)
      MaxTypeDepth = TypeDepth;
    Width += TypeWidth;
    std::tie(TypeDepth, TypeWidth) = getTypeDepthAndWidth(FnTy->getResult());
    if (TypeDepth > MaxTypeDepth)
      MaxTypeDepth = TypeDepth;
    Width += TypeWidth;
    Depth += MaxTypeDepth;
    return std::make_pair(Depth, Width);
  }

  if (auto *MT = t->getAs<MetatypeType>()) {
    Depth += 1;
    unsigned TypeWidth;
    unsigned TypeDepth;
    std::tie(TypeDepth, TypeWidth) = getTypeDepthAndWidth(MT->getInstanceType());
    Width += TypeWidth;
    Depth += TypeDepth;
    return std::make_pair(Depth, Width);
  }

  return std::make_pair(Depth, Width);
}

static bool isTypeTooComplex(Type t) {
  unsigned TypeWidth;
  unsigned TypeDepth;
  std::tie(TypeDepth, TypeWidth) = getTypeDepthAndWidth(t);
  return TypeWidth >= TypeWidthThreshold || TypeDepth >= TypeDepthThreshold;
}

// =============================================================================
// ReabstractionInfo
// =============================================================================

static bool shouldNotSpecializeCallee(SILFunction *Callee) {
  if (!Callee->shouldOptimize()) {
    DEBUG(llvm::dbgs() << "    Cannot specialize function " << Callee->getName()
          << " marked to be excluded from optimizations.\n");
    return true;
  }

  if (Callee->hasSemanticsAttr("optimize.sil.specialize.generic.never"))
    return true;

  return false;
}

/// Prepares the ReabstractionInfo object for further processing and checks
/// if the current function can be specialized at all.
/// Returns false, if the current function cannot be specialized.
/// Returns true otherwise.
bool ReabstractionInfo::prepareAndCheck(ApplySite Apply, SILFunction *Callee,
                                        SubstitutionList ParamSubs) {
  if (shouldNotSpecializeCallee(Callee))
    return false;

  SpecializedGenericEnv = nullptr;
  SpecializedGenericSig = nullptr;
  OriginalParamSubs = ParamSubs;
  auto CalleeGenericSig = Callee->getLoweredFunctionType()->getGenericSignature();
  auto CalleeGenericEnv = Callee->getGenericEnvironment();

  OriginalF = Callee;
  this->Apply = Apply;

  SubstitutionMap InterfaceSubs;

  // Get the original substitution map.
  if (CalleeGenericSig)
    InterfaceSubs = CalleeGenericSig->getSubstitutionMap(ParamSubs);

  // We do not support partial specialization.
  if (!EnablePartialSpecialization && InterfaceSubs.hasArchetypes()) {
    DEBUG(llvm::dbgs() << "    Partial specialization is not supported.\n");
    DEBUG(for (auto Sub : ParamSubs) { Sub.dump(); });
    return false;
  }

  // Perform some checks to see if we need to bail.
  if (InterfaceSubs.hasDynamicSelf()) {
    DEBUG(llvm::dbgs() << "    Cannot specialize with dynamic self.\n");
    return false;
  }

  // Check if the substitution contains any generic types that are too deep.
  // If this is the case, bail to avoid the explosion in the number of
  // generated specializations.
  for (auto Sub : ParamSubs) {
    auto Replacement = Sub.getReplacement();
    if (isTypeTooComplex(Replacement)) {
      DEBUG(llvm::dbgs()
            << "    Cannot specialize because the generic type is too deep.\n");
      return false;
    }
  }

  // Check if we have substitutions which replace generic type parameters with
  // concrete types or unbound generic types.
  bool HasConcreteGenericParams = false;
  bool HasNonArchetypeGenericParams = false;
  HasUnboundGenericParams = false;
  for (auto GP : CalleeGenericSig->getSubstitutableParams()) {
    // Check only the substitutions for the generic parameters.
    // Ignore any dependent types, etc.
    auto Replacement = Type(GP).subst(InterfaceSubs);
    if (!Replacement->is<ArchetypeType>())
      HasNonArchetypeGenericParams = true;

    if (Replacement->hasArchetype()) {
      HasUnboundGenericParams = true;
      // Check if the replacement is an archetype which is more specific
      // than the corresponding archetype in the original generic signature.
      // If this is the case, then specialization makes sense, because
      // it would produce something more specific.
      if (CalleeGenericEnv) {
        if (auto Archetype = Replacement->getAs<ArchetypeType>()) {
          auto OrigArchetype =
              CalleeGenericEnv->mapTypeIntoContext(GP)->castTo<ArchetypeType>();
          if (Archetype->requiresClass() && !OrigArchetype->requiresClass())
            HasNonArchetypeGenericParams = true;
          if (Archetype->getLayoutConstraint() &&
              !OrigArchetype->getLayoutConstraint())
            HasNonArchetypeGenericParams = true;
        }
      }
      continue;
    }

    HasConcreteGenericParams = true;
  }

  if (HasUnboundGenericParams) {
    if (!HasNonArchetypeGenericParams && !HasConcreteGenericParams) {
      DEBUG(llvm::dbgs() << "    Partial specialization is not supported if "
                            "all substitutions are archetypes.\n");
      DEBUG(for (auto Sub : ParamSubs) {
          Sub.dump();
        });
      return false;
    }

    // We need a generic environment for the partial specialization.
    if (!CalleeGenericEnv)
      return false;
  }

  return true;
}

bool ReabstractionInfo::canBeSpecialized(ApplySite Apply, SILFunction *Callee,
                                         SubstitutionList ParamSubs) {
  ReabstractionInfo ReInfo;
  return ReInfo.prepareAndCheck(Apply, Callee, ParamSubs);
}

ReabstractionInfo::ReabstractionInfo(ApplySite Apply, SILFunction *Callee,
                                     ArrayRef<Substitution> ParamSubs,
                                     bool ConvertIndirectToDirect) {
  if (!prepareAndCheck(Apply, Callee, ParamSubs))
    return;

  this->ConvertIndirectToDirect = ConvertIndirectToDirect;

  if (SpecializeGenericSubstitutions) {
    specializeConcreteAndGenericSubstitutions(Apply, Callee, ParamSubs);
  } else {
    specializeConcreteSubstitutions(Apply, Callee, ParamSubs);
  }

  if (SpecializedGenericSig) {
    DEBUG(llvm::dbgs() << "\n\nPartially specialized types for function: "
                       << Callee->getName() << "\n\n";
          llvm::dbgs() << "Original generic function type:\n"
                       << Callee->getLoweredFunctionType() << "\n"
                       << "Partially specialized generic function type:\n"
                       << SpecializedType << "\n\n");
  }

  // Some sanity checks.
  auto SpecializedFnTy = getSpecializedType();
  auto SpecializedSubstFnTy = SpecializedFnTy;

  if (SpecializedFnTy->isPolymorphic() &&
      !getCallerParamSubstitutions().empty()) {
    auto CalleeFnTy = Callee->getLoweredFunctionType();
    assert(CalleeFnTy->isPolymorphic());
    auto CalleeSubstFnTy = CalleeFnTy->substGenericArgs(
        Callee->getModule(), getOriginalParamSubstitutions());
    assert(!CalleeSubstFnTy->isPolymorphic() &&
           "Substituted callee type should not be polymorphic");
    assert(!CalleeSubstFnTy->hasTypeParameter() &&
           "Substituted callee type should not have type parameters");

    SpecializedSubstFnTy = SpecializedFnTy->substGenericArgs(
        Callee->getModule(), getCallerParamSubstitutions());

    assert(!SpecializedSubstFnTy->isPolymorphic() &&
           "Substituted callee type should not be polymorphic");
    assert(!SpecializedSubstFnTy->hasTypeParameter() &&
           "Substituted callee type should not have type parameters");

    auto SpecializedCalleeSubstFnTy =
        createSpecializedType(CalleeSubstFnTy, Callee->getModule());

    if (SpecializedSubstFnTy != SpecializedCalleeSubstFnTy) {
      llvm::dbgs() << "SpecializedFnTy:\n" << SpecializedFnTy << "\n";
      llvm::dbgs() << "SpecializedSubstFnTy:\n" << SpecializedSubstFnTy << "\n";
      for (auto Sub : getCallerParamSubstitutions()) {
        llvm::dbgs() << "Sub:\n";
        Sub.dump();
      }
      llvm::dbgs() << "\n\n";

      llvm::dbgs() << "CalleeFnTy:\n" << CalleeFnTy << "\n";
      llvm::dbgs() << "SpecializedCalleeSubstFnTy:\n" << SpecializedCalleeSubstFnTy << "\n";
      for (auto Sub : ParamSubs) {
        llvm::dbgs() << "Sub:\n";
        Sub.dump();
      }
      llvm::dbgs() << "\n\n";
      assert(SpecializedSubstFnTy == SpecializedCalleeSubstFnTy &&
             "Substituted function types should be the same");
    }
  }

  // If the new type is the same, there is nothing to do and
  // no specialization should be performed.
  if (getSubstitutedType() == Callee->getLoweredFunctionType()) {
    DEBUG(llvm::dbgs() << "The new specialized type is the same as "
                          "the original "
                          "type. Don't specialize!\n";
          llvm::dbgs() << "The type is: " << getSubstitutedType() << "\n");
    SpecializedType = CanSILFunctionType();
    SubstitutedType = CanSILFunctionType();
    SpecializedGenericSig = nullptr;
    SpecializedGenericEnv = nullptr;
    return;
  }

  if (SpecializedGenericSig) {
    // It is a partial specializaiton.
    DEBUG(llvm::dbgs() << "Specializing the call:\n";
          Apply.getInstruction()->dumpInContext();
          llvm::dbgs() << "\n\nPartially specialized types for function: "
                       << Callee->getName() << "\n\n";
          llvm::dbgs() << "Original generic function type:\n"
                       << Callee->getLoweredFunctionType() << "\n\n";
          llvm::dbgs() << "\nOriginal call substitution:\n";
          for (auto Sub : getOriginalParamSubstitutions()) {
            llvm::dbgs() << "Sub:\n";
            Sub.dump();
            llvm::dbgs() << "\n";
          }

          llvm::dbgs() << "Partially specialized generic function type:\n"
                       << getSpecializedType() << "\n\n";
          llvm::dbgs() << "\nSpecialization call substitution:\n";
          for (auto Sub : getCallerParamSubstitutions()) {
            llvm::dbgs() << "Sub:\n";
            Sub.dump();
            llvm::dbgs() << "\n";
          });
  }
}

bool ReabstractionInfo::canBeSpecialized() const {
  return getSpecializedType();
}

bool ReabstractionInfo::isFullSpecialization() const {
  return !hasArchetypes(getOriginalParamSubstitutions());
}

bool ReabstractionInfo::isPartialSpecialization() const {
  return hasArchetypes(getOriginalParamSubstitutions());
}

void ReabstractionInfo::createSubstitutedAndSpecializedTypes() {
  auto &M = OriginalF->getModule();

  // Find out how the function type looks like after applying the provided
  // substitutions.
  if (!SubstitutedType) {
    SubstitutedType = createSubstitutedType(
        OriginalF, CallerInterfaceSubs, HasUnboundGenericParams);
  }
  assert(!SubstitutedType->hasArchetype() &&
         "Substituted function type should not contain archetypes");

  // Check which parameters and results can be converted from
  // indirect to direct ones.
  NumFormalIndirectResults = SubstitutedType->getNumIndirectFormalResults();
  Conversions.resize(NumFormalIndirectResults +
                     SubstitutedType->getParameters().size());

  CanGenericSignature CanSig;
  if (SpecializedGenericSig)
    CanSig = SpecializedGenericSig->getCanonicalSignature();
  Lowering::GenericContextScope GenericScope(M.Types, CanSig);

  SILFunctionConventions substConv(SubstitutedType, M);

  if (SubstitutedType->getNumDirectFormalResults() == 0) {
    // The original function has no direct result yet. Try to convert the first
    // indirect result to a direct result.
    // TODO: We could also convert multiple indirect results by returning a
    // tuple type and created tuple_extract instructions at the call site.
    unsigned IdxForResult = 0;
    for (SILResultInfo RI : SubstitutedType->getIndirectFormalResults()) {
      assert(RI.isFormalIndirect());
      if (substConv.getSILType(RI).isLoadable(M) && !RI.getType()->isVoid()) {
        Conversions.set(IdxForResult);
        break;
      }
      ++IdxForResult;
    }
  }

  // Try to convert indirect incoming parameters to direct parameters.
  unsigned IdxForParam = NumFormalIndirectResults;
  for (SILParameterInfo PI : SubstitutedType->getParameters()) {
    if (substConv.getSILType(PI).isLoadable(M) &&
        PI.getConvention() == ParameterConvention::Indirect_In) {
      Conversions.set(IdxForParam);
    }
    ++IdxForParam;
  }

  // Produce a specialized type, which is the substituted type with
  // the parameters/results passing conventions adjusted according
  // to the conversions selected above.
  SpecializedType = createSpecializedType(SubstitutedType, M);
}

/// Create a new substituted type with the updated signature.
CanSILFunctionType
ReabstractionInfo::createSubstitutedType(SILFunction *OrigF,
                                         const SubstitutionMap &SubstMap,
                                         bool HasUnboundGenericParams) {
  auto &M = OrigF->getModule();
  if ((SpecializedGenericSig &&
       SpecializedGenericSig->areAllParamsConcrete()) ||
      !HasUnboundGenericParams) {
    SpecializedGenericSig = nullptr;
    SpecializedGenericEnv = nullptr;
  }

  CanGenericSignature CanSpecializedGenericSig;
  if (SpecializedGenericSig)
    CanSpecializedGenericSig = SpecializedGenericSig->getCanonicalSignature();

  // First substitute concrete types into the existing function type.
  CanSILFunctionType FnTy;
  {
    Lowering::GenericContextScope GenericScope(M.Types,
                                               CanSpecializedGenericSig);
    FnTy = OrigF->getLoweredFunctionType()->substGenericArgs(M, SubstMap);
    // FIXME: Some of the added new requirements may not have been taken into
    // account by the substGenericArgs. So, canonicalize in the context of the
    // specialized signature.
    FnTy = cast<SILFunctionType>(
        CanSpecializedGenericSig->getCanonicalTypeInContext(
            FnTy, *M.getSwiftModule()));
  }
  assert(FnTy);

  // Use the new specialized generic signature.
  auto NewFnTy = SILFunctionType::get(
      CanSpecializedGenericSig, FnTy->getExtInfo(), FnTy->getCalleeConvention(),
      FnTy->getParameters(), FnTy->getResults(), FnTy->getOptionalErrorResult(),
      M.getASTContext());

  // This is an interface type. It should not have any archetypes.
  assert(!NewFnTy->hasArchetype());
  return NewFnTy;
}

// Convert the substituted function type into a specialized function type based
// on the ReabstractionInfo.
CanSILFunctionType ReabstractionInfo::
createSpecializedType(CanSILFunctionType SubstFTy, SILModule &M) const {
  llvm::SmallVector<SILResultInfo, 8> SpecializedResults;
  llvm::SmallVector<SILParameterInfo, 8> SpecializedParams;

  unsigned IndirectResultIdx = 0;
  for (SILResultInfo RI : SubstFTy->getResults()) {
    if (RI.isFormalIndirect()) {
      if (isFormalResultConverted(IndirectResultIdx++)) {
        // Convert the indirect result to a direct result.
        SILType SILResTy = SILType::getPrimitiveObjectType(RI.getType());
        // Indirect results are passed as owned, so we also need to pass the
        // direct result as owned (except it's a trivial type).
        auto C = (SILResTy.isTrivial(M) ? ResultConvention::Unowned :
                  ResultConvention::Owned);
        SpecializedResults.push_back(SILResultInfo(RI.getType(), C));
        continue;
      }
    }
    // No conversion: re-use the original, substituted result info.
    SpecializedResults.push_back(RI);
  }
  unsigned ParamIdx = 0;
  for (SILParameterInfo PI : SubstFTy->getParameters()) {
    if (isParamConverted(ParamIdx++)) {
      // Convert the indirect parameter to a direct parameter.
      SILType SILParamTy = SILType::getPrimitiveObjectType(PI.getType());
      // Indirect parameters are passed as owned, so we also need to pass the
      // direct parameter as owned (except it's a trivial type).
      auto C = (SILParamTy.isTrivial(M) ? ParameterConvention::Direct_Unowned :
                ParameterConvention::Direct_Owned);
      SpecializedParams.push_back(SILParameterInfo(PI.getType(), C));
    } else {
      // No conversion: re-use the original, substituted parameter info.
      SpecializedParams.push_back(PI);
    }
  }
  return
    SILFunctionType::get(SubstFTy->getGenericSignature(),
                         SubstFTy->getExtInfo(),
                         SubstFTy->getCalleeConvention(), SpecializedParams,
                         SpecializedResults, SubstFTy->getOptionalErrorResult(),
                         M.getASTContext());
}

static std::pair<GenericEnvironment *, GenericSignature *>
getGenericEnvironmentAndSignature(GenericSignatureBuilder &Builder,
                                  SILModule &M) {
  auto *GenericSig =
      Builder.getGenericSignature()->getCanonicalSignature().getPointer();
  auto *GenericEnv = GenericSig->createGenericEnvironment(*M.getSwiftModule());

  // FIXME: This is a workaround for the signature minimization bug.
  GenericSignatureBuilder TmpBuilder(
      M.getASTContext(), LookUpConformanceInModule(M.getSwiftModule()));
  TmpBuilder.addGenericSignature(GenericSig);
  TmpBuilder.finalize(SourceLoc(), GenericSig->getGenericParams(),
                      /*allowConcreteGenericParams=*/true);
  GenericSig =
      TmpBuilder.getGenericSignature()->getCanonicalSignature().getPointer();
  GenericEnv = GenericSig->createGenericEnvironment(*M.getSwiftModule());

  return std::make_pair(GenericEnv, GenericSig);
}

std::pair<GenericEnvironment *, GenericSignature *>
getSignatureWithRequirements(GenericSignature *OrigGenSig,
                             GenericEnvironment *OrigGenericEnv,
                             ArrayRef<Requirement> Requirements,
                             SILModule &M) {
  // Form a new generic signature based on the old one.
  GenericSignatureBuilder Builder(M.getASTContext(),
                           LookUpConformanceInModule(M.getSwiftModule()));

  // First, add the old generic signature.
  Builder.addGenericSignature(OrigGenSig);

  auto Source =
    GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
  // For each substitution with a concrete type as a replacement,
  // add a new concrete type equality requirement.
  for (auto &Req : Requirements) {
    Builder.addRequirement(Req, Source);
  }

  Builder.finalize(SourceLoc(), OrigGenSig->getGenericParams(),
                   /*allowConcreteGenericParams=*/true);
  return getGenericEnvironmentAndSignature(Builder, M);
}

/// Perform some sanity checks for the requirements
static void
checkSpecializationRequirements(ArrayRef<Requirement> Requirements) {
  for (auto &Req : Requirements) {
    if (Req.getKind() == RequirementKind::SameType) {
      auto FirstType = Req.getFirstType();
      auto SecondType = Req.getSecondType();
      assert(FirstType && SecondType);
      assert(!FirstType->hasArchetype());
      assert(!SecondType->hasArchetype());

      // Only one of the types should be concrete.
      assert(FirstType->hasTypeParameter() != SecondType->hasTypeParameter() &&
             "Only concrete type same-type requirements are supported by "
             "generic specialization");

      (void) FirstType;
      (void) SecondType;

      continue;
    }

    if (Req.getKind() == RequirementKind::Layout) {
      continue;
    }

    llvm_unreachable("Unknown type of requirement in generic specialization");
  }
}

ReabstractionInfo::ReabstractionInfo(SILFunction *OrigF,
                                     ArrayRef<Requirement> Requirements) {
  if (shouldNotSpecializeCallee(OrigF))
    return;

  // Perform some sanity checks for the requirements
  checkSpecializationRequirements(Requirements);

  OriginalF = OrigF;
  ConvertIndirectToDirect = true;

  SILModule &M = OrigF->getModule();
  auto &Ctx = M.getASTContext();

  auto OrigGenericSig = OrigF->getLoweredFunctionType()->getGenericSignature();
  auto OrigGenericEnv = OrigF->getGenericEnvironment();

  std::tie(SpecializedGenericEnv, SpecializedGenericSig) =
      getSignatureWithRequirements(OrigGenericSig, OrigGenericEnv,
                                   Requirements, M);

  {
    SmallVector<Substitution, 4> List;

    OrigGenericSig->getSubstitutions(
      [&](SubstitutableType *type) -> Type {
        return SpecializedGenericEnv->mapTypeIntoContext(type);
      },
      LookUpConformanceInSignature(*SpecializedGenericSig),
      List);
    ClonerParamSubs = Ctx.AllocateCopy(List);
  }

  {
    SmallVector<Substitution, 4> List;

    SpecializedGenericSig->getSubstitutions(
      [&](SubstitutableType *type) -> Type {
        return OrigGenericEnv->mapTypeIntoContext(type);
      },
      LookUpConformanceInSignature(*SpecializedGenericSig),
      List);
    CallerParamSubs = Ctx.AllocateCopy(List);
  }

  {
    CallerInterfaceSubs = OrigGenericSig->getSubstitutionMap(
      [&](SubstitutableType *type) -> Type {
        return SpecializedGenericEnv->mapTypeOutOfContext(
          SpecializedGenericEnv->mapTypeIntoContext(type));
      },
      LookUpConformanceInSignature(*SpecializedGenericSig));
  }

  OriginalParamSubs = CallerParamSubs;

  HasUnboundGenericParams = !SpecializedGenericSig->areAllParamsConcrete();
  createSubstitutedAndSpecializedTypes();
}

static void verifySubstitutionList(SubstitutionList Subs) {
  for (auto Sub : Subs) {
    assert(!Sub.getReplacement()->hasError() &&
           "There should be no error types in substitutions");
  }
}

// Builds a new signature based on the old one and adds same type
// requirements for those generic type parameters that are concrete
// according to the partial substitution. This way, the signature
// has exactly the same generic parameter types, just with more
// requirements.
// Current issues:
// - If Sig2 = GenericSignatureBuilder(Sig2 + Req), then GenericSignatureBuilder(Sig2) != Sig2
// - The set of requirements is not really minimized.
// - Some requirements are lost, when you add a same type parameter to the builder.

// Initialize SpecializedType if and only if the specialization is allowed.
void ReabstractionInfo::specializeConcreteSubstitutions(
    ApplySite Apply, SILFunction *Callee, ArrayRef<Substitution> ParamSubs) {

  SILModule &M = Callee->getModule();
  auto &Ctx = M.getASTContext();

  OriginalF = Callee;

  auto OrigGenericSig = Callee->getLoweredFunctionType()->getGenericSignature();
  auto OrigGenericEnv = Callee->getGenericEnvironment();

  SubstitutionMap InterfaceSubs;
  // Get the original substitution map.
  if (Callee->getLoweredFunctionType()->getGenericSignature())
    InterfaceSubs = Callee->getLoweredFunctionType()->getGenericSignature()
      ->getSubstitutionMap(ParamSubs);

  // This is a workaround for the rdar://30610428
  if (!EnablePartialSpecialization) {
    SubstitutedType =
        Callee->getLoweredFunctionType()->substGenericArgs(M, InterfaceSubs);
    ClonerParamSubs = OriginalParamSubs;
    CallerParamSubs = {};
    createSubstitutedAndSpecializedTypes();
    return;
  }

  // Build a set of requirements.
  SmallVector<Requirement, 4> Requirements;

  for (auto DP : OrigGenericSig->getGenericParams()) {
    auto Replacement = Type(DP).subst(InterfaceSubs);
    if (Replacement->hasArchetype())
      continue;
    // Replacemengt is concrete. Add a same type requirement.
    Requirement Req(RequirementKind::SameType, DP, Replacement);
    Requirements.push_back(Req);
  }

  std::tie(SpecializedGenericEnv, SpecializedGenericSig) =
      getSignatureWithRequirements(OrigGenericSig, OrigGenericEnv,
                                   Requirements, M);
  HasUnboundGenericParams = !SpecializedGenericSig->areAllParamsConcrete();

  // No partial specializations!
  //if (HasUnboundGenericParams)
  //  return;

  {
    SmallVector<Substitution, 4> List;

    OrigGenericSig->getSubstitutions(
      [&](SubstitutableType *type) -> Type {
        return SpecializedGenericEnv->mapTypeIntoContext(type);
      },
      LookUpConformanceInSignature(*SpecializedGenericSig),
      List);
    ClonerParamSubs = Ctx.AllocateCopy(List);
    verifySubstitutionList(ClonerParamSubs);
  }

  {
    SmallVector<Substitution, 4> List;
    SpecializedGenericSig->getSubstitutions(InterfaceSubs, List);
    CallerParamSubs = Ctx.AllocateCopy(List);
    verifySubstitutionList(CallerParamSubs);
  }

  {
    CallerInterfaceSubs = OrigGenericSig->getSubstitutionMap(
      [&](SubstitutableType *type) -> Type {
        return SpecializedGenericEnv->mapTypeOutOfContext(
          SpecializedGenericEnv->mapTypeIntoContext(type));
      },
        //LookUpConformanceInSignature(*SpecializedGenericSig));
      LookUpConformanceInSignature(*OrigGenericSig));
  }

  HasUnboundGenericParams = !SpecializedGenericSig->areAllParamsConcrete();
  createSubstitutedAndSpecializedTypes();
}

// Builds a new generic and function signatures for a partial specialization.
// Allows for partial specializations even if substitututions contain
// type parameters.
//
// The new generic signature has the following generic parameters:
// - For each substitution with a concrete type CT as a replacement for a generic
// type T, it introduces a generic parameter T' and a requirement T' == CT
// - For all other substitutions that are considered for partial specialization,
// it collects first the archetypes used in the replacements. Then for each such
// archetype A a new generic parameter T' introduced.
// - If there is a substitution for type T and this substitution is execluded from
// partial specialization (e.g. because it is impossible or would result in a less
// efficient code), then a new generic parameter T' is introduced, which does not
// get any additional, more specific requirements based on the substitutions.
//
// After all generic parameters are added accoriding to the rules above,
// the requirements of the callee's signature are re-mapped by re-formulating them
// in terms of the newly introduced generic parameters. In case a remapped
// requirement does not contain any generic types, it can be omitted, because
// it is fulfilled already.

// Current issues:
// - If Sig2 = GenericSignatureBuilder(Sig2 + Req), then
// GenericSignatureBuilder(Sig2) != Sig2
// - The set of requirements is not really minimized.
// - Some requirements are lost, when you add a same type parameter to the
// builder.
void ReabstractionInfo::specializeConcreteAndGenericSubstitutions(
    ApplySite Apply, SILFunction *Callee, ArrayRef<Substitution> ParamSubs) {
  llvm_unreachable("Not implemented yet");
}

// =============================================================================
// GenericFuncSpecializer
// =============================================================================

GenericFuncSpecializer::GenericFuncSpecializer(SILFunction *GenericFunc,
                                               SubstitutionList ParamSubs,
                                               IsFragile_t Fragile,
                                               const ReabstractionInfo &ReInfo)
    : M(GenericFunc->getModule()),
      GenericFunc(GenericFunc),
      ParamSubs(ParamSubs),
      Fragile(Fragile),
      ReInfo(ReInfo) {

  assert(GenericFunc->isDefinition() && "Expected definition to specialize!");
  auto FnTy = ReInfo.getSpecializedType();

  std::string Old;

  if (ReInfo.isPartialSpecialization()) {
    Mangle::Mangler Mangler;
    PartialSpecializationMangler OldGenericMangler(Mangler, GenericFunc, FnTy,
                                                   Fragile);
    OldGenericMangler.mangle();
    Old = Mangler.finalize();
  } else {
    Mangle::Mangler Mangler;
    GenericSpecializationMangler OldGenericMangler(Mangler, GenericFunc,
                                                   ParamSubs, Fragile);
    OldGenericMangler.mangle();
    Old = Mangler.finalize();
  }

  std::string New;
  if (ReInfo.isPartialSpecialization()) {
    NewMangling::PartialSpecializationMangler NewGenericMangler(
        GenericFunc, FnTy, Fragile, /*isReAbstracted*/ true);
    New = NewGenericMangler.mangle();
  } else {
    NewMangling::GenericSpecializationMangler NewGenericMangler(
        GenericFunc, ParamSubs, Fragile, /*isReAbstracted*/ true);
    New = NewGenericMangler.mangle();
  }

  ClonedName = NewMangling::selectMangling(Old, New);

  DEBUG(llvm::dbgs() << "    Specialized function " << ClonedName << '\n');
}

// Return an existing specialization if one exists.
SILFunction *GenericFuncSpecializer::lookupSpecialization() {
  if (SILFunction *SpecializedF = M.lookUpFunction(ClonedName)) {
    assert(ReInfo.getSpecializedType()
           == SpecializedF->getLoweredFunctionType() &&
           "Previously specialized function does not match expected type.");
    DEBUG(llvm::dbgs() << "Found an existing specialization for: " << ClonedName
                       << "\n");
    return SpecializedF;
  }
  DEBUG(llvm::dbgs() << "Could not find an existing specialization for: "
                     << ClonedName << "\n");
  return nullptr;
}

// Forward decl for prespecialization support.
static bool linkSpecialization(SILModule &M, SILFunction *F);

// Create a new specialized function if possible, and cache it.
SILFunction *GenericFuncSpecializer::tryCreateSpecialization() {
  // Do not create any new specializations at Onone.
  if (M.getOptions().Optimization <= SILOptions::SILOptMode::None)
    return nullptr;

  DEBUG(
    if (M.getOptions().Optimization <= SILOptions::SILOptMode::Debug) {
      llvm::dbgs() << "Creating a specialization: " << ClonedName << "\n"; });

  // Create a new function.
  SILFunction *SpecializedF = GenericCloner::cloneFunction(
      GenericFunc, Fragile, ReInfo,
      // Use these substitutions inside the new specialized function being
      // created.
      ReInfo.getClonerParamSubstitutions(),
      ClonedName);
  assert(SpecializedF->hasUnqualifiedOwnership());
  // Check if this specialization should be linked for prespecialization.
  linkSpecialization(M, SpecializedF);
  return SpecializedF;
}

// =============================================================================
// Apply substitution
// =============================================================================

/// Fix the case where a void function returns the result of an apply, which is
/// also a call of a void-returning function.
/// We always want a void function returning a tuple _instruction_.
static void fixUsedVoidType(SILValue VoidVal, SILLocation Loc,
                            SILBuilder &Builder) {
  assert(VoidVal->getType().isVoid());
  if (VoidVal->use_empty())
    return;
  auto *NewVoidVal = Builder.createTuple(Loc, VoidVal->getType(), { });
  VoidVal->replaceAllUsesWith(NewVoidVal);
}

// Prepare call arguments. Perform re-abstraction if required.
static void prepareCallArguments(ApplySite AI, SILBuilder &Builder,
                                 const ReabstractionInfo &ReInfo,
                                 SmallVectorImpl<SILValue> &Arguments,
                                 SILValue &StoreResultTo) {
  /// SIL function conventions for the original apply site with substitutions.
  SILLocation Loc = AI.getLoc();
  auto substConv = AI.getSubstCalleeConv();
  unsigned ArgIdx = AI.getCalleeArgIndexOfFirstAppliedArg();
  for (auto &Op : AI.getArgumentOperands()) {
    auto handleConversion = [&]() {
      // Rewriting SIL arguments is only for lowered addresses.
      if (!substConv.useLoweredAddresses())
        return false;

      if (ArgIdx < substConv.getSILArgIndexOfFirstParam()) {
        // Handle result arguments.
        unsigned formalIdx =
            substConv.getIndirectFormalResultIndexForSILArg(ArgIdx);
        if (ReInfo.isFormalResultConverted(formalIdx)) {
          // The result is converted from indirect to direct. We need to insert
          // a store later.
          assert(!StoreResultTo);
          StoreResultTo = Op.get();
          return true;
        }
      } else {
        // Handle arguments for formal parameters.
        unsigned paramIdx = ArgIdx - substConv.getSILArgIndexOfFirstParam();
        if (ReInfo.isParamConverted(paramIdx)) {
          // An argument is converted from indirect to direct. Instead of the
          // address we pass the loaded value.
          SILValue Val = Builder.createLoad(
              Loc, Op.get(), LoadOwnershipQualifier::Unqualified);
          Arguments.push_back(Val);
          return true;
        }
      }
      return false;
    };
    if (!handleConversion())
      Arguments.push_back(Op.get());

    ++ArgIdx;
  }
}

/// Return a substituted callee function type.
static CanSILFunctionType
getCalleeSubstFunctionType(SILValue Callee, SubstitutionList Subs) {
  // Create a substituted callee type.
  auto CanFnTy = Callee->getType().castTo<SILFunctionType>();
  auto CalleeSubstFnTy = CanFnTy;

  if (CanFnTy->isPolymorphic() && !Subs.empty()) {
    CalleeSubstFnTy = CanFnTy->substGenericArgs(*Callee->getModule(), Subs);
    assert(!CalleeSubstFnTy->isPolymorphic() &&
           "Substituted callee type should not be polymorphic");
    assert(!CalleeSubstFnTy->hasTypeParameter() &&
           "Substituted callee type should not have type parameters");
  }

  return CalleeSubstFnTy;
}

// Create a new apply based on an old one, but with a different
// function being applied.
static ApplySite replaceWithSpecializedCallee(ApplySite AI,
                                              SILValue Callee,
                                              SILBuilder &Builder,
                                              const ReabstractionInfo &ReInfo) {
  SILLocation Loc = AI.getLoc();
  SmallVector<SILValue, 4> Arguments;
  SILValue StoreResultTo;

  prepareCallArguments(AI, Builder, ReInfo, Arguments, StoreResultTo);

  // Create a substituted callee type.
  ArrayRef<Substitution> Subs;
  if (ReInfo.getSpecializedType()->isPolymorphic()) {
    Subs = ReInfo.getCallerParamSubstitutions();
  }

  auto CalleeSubstFnTy = getCalleeSubstFunctionType(Callee, Subs);
  auto CalleeSILSubstFnTy = SILType::getPrimitiveObjectType(CalleeSubstFnTy);
  SILFunctionConventions substConv(CalleeSubstFnTy, Builder.getModule());

  if (auto *TAI = dyn_cast<TryApplyInst>(AI)) {
    SILBasicBlock *ResultBB = TAI->getNormalBB();
    assert(ResultBB->getSinglePredecessorBlock() == TAI->getParent());
    auto *NewTAI =
        Builder.createTryApply(Loc, Callee, CalleeSILSubstFnTy, Subs, Arguments,
                               ResultBB, TAI->getErrorBB());
    if (StoreResultTo) {
      assert(substConv.useLoweredAddresses());
      // The original normal result of the try_apply is an empty tuple.
      assert(ResultBB->getNumArguments() == 1);
      Builder.setInsertionPoint(ResultBB->begin());
      fixUsedVoidType(ResultBB->getArgument(0), Loc, Builder);

      SILArgument *Arg = ResultBB->replacePHIArgument(
          0, StoreResultTo->getType().getObjectType(),
          ValueOwnershipKind::Owned);
      // Store the direct result to the original result address.
      Builder.createStore(Loc, Arg, StoreResultTo,
                          StoreOwnershipQualifier::Unqualified);
    }
    return NewTAI;
  }
  if (auto *A = dyn_cast<ApplyInst>(AI)) {
    auto *NewAI = Builder.createApply(Loc, Callee, CalleeSILSubstFnTy,
                                      substConv.getSILResultType(), Subs,
                                      Arguments, A->isNonThrowing());
    if (StoreResultTo) {
      assert(substConv.useLoweredAddresses());
      // Store the direct result to the original result address.
      fixUsedVoidType(A, Loc, Builder);
      Builder.createStore(Loc, NewAI, StoreResultTo,
                          StoreOwnershipQualifier::Unqualified);
    }
    A->replaceAllUsesWith(NewAI);
    return NewAI;
  }
  if (auto *PAI = dyn_cast<PartialApplyInst>(AI)) {
    CanSILFunctionType NewPAType = ReInfo.createSpecializedType(
        PAI->getFunctionType(), Builder.getModule());
    // SILType PTy =
    // SILType::getPrimitiveObjectType(ReInfo.getSpecializedType());
    SILType PTy = CalleeSILSubstFnTy;
    auto *NewPAI =
        Builder.createPartialApply(Loc, Callee, PTy, Subs, Arguments,
                                   SILType::getPrimitiveObjectType(NewPAType));
    PAI->replaceAllUsesWith(NewPAI);
    return NewPAI;
  }
  llvm_unreachable("unhandled kind of apply");
}

// Create a new apply based on an old one, but with a different
// function being applied.
ApplySite swift::
replaceWithSpecializedFunction(ApplySite AI, SILFunction *NewF,
                               const ReabstractionInfo &ReInfo) {
  SILBuilderWithScope Builder(AI.getInstruction());
  FunctionRefInst *FRI = Builder.createFunctionRef(AI.getLoc(), NewF);
  return replaceWithSpecializedCallee(AI, FRI, Builder, ReInfo);
}

namespace {
class ReabstractionThunkGenerator {
  SILFunction *OrigF;
  SILModule &M;
  SILFunction *SpecializedFunc;
  const ReabstractionInfo &ReInfo;
  PartialApplyInst *OrigPAI;

  IsFragile_t Fragile = IsNotFragile;
  std::string ThunkName;
  RegularLocation Loc;
  SmallVector<SILValue, 4> Arguments;

public:
  ReabstractionThunkGenerator(const ReabstractionInfo &ReInfo,
                              PartialApplyInst *OrigPAI,
                              SILFunction *SpecializedFunc)
      : OrigF(OrigPAI->getCalleeFunction()), M(OrigF->getModule()),
        SpecializedFunc(SpecializedFunc), ReInfo(ReInfo), OrigPAI(OrigPAI),
        Loc(RegularLocation::getAutoGeneratedLocation()) {
    if (OrigF->isFragile() && OrigPAI->getFunction()->isFragile())
      Fragile = IsFragile;

    {
      if (!ReInfo.isPartialSpecialization()) {
        Mangle::Mangler M;
        GenericSpecializationMangler OldMangler(
            M, OrigF, ReInfo.getOriginalParamSubstitutions(), Fragile,
            GenericSpecializationMangler::NotReabstracted);
        OldMangler.mangle();
        std::string Old = M.finalize();

        NewMangling::GenericSpecializationMangler NewMangler(
            OrigF, ReInfo.getOriginalParamSubstitutions(), Fragile,
            /*isReAbstracted*/ false);

        std::string New = NewMangler.mangle();
        ThunkName = NewMangling::selectMangling(Old, New);
      } else {
        Mangle::Mangler M;
        PartialSpecializationMangler OldMangler(
            M, OrigF, ReInfo.getSpecializedType(), Fragile,
            PartialSpecializationMangler::NotReabstracted);
        OldMangler.mangle();
        std::string Old = M.finalize();

        NewMangling::PartialSpecializationMangler NewMangler(
            OrigF, ReInfo.getSpecializedType(), Fragile,
            /*isReAbstracted*/ false);

        std::string New = NewMangler.mangle();
        ThunkName = NewMangling::selectMangling(Old, New);
      }
    }
  }

  SILFunction *createThunk();

protected:
  SILValue createReabstractionThunkApply(SILBuilder &Builder);
  SILArgument *convertReabstractionThunkArguments(SILBuilder &Builder);
};
} // anonymous namespace

SILFunction *ReabstractionThunkGenerator::createThunk() {
  SILFunction *Thunk =
      M.getOrCreateSharedFunction(Loc, ThunkName, ReInfo.getSubstitutedType(),
                                  IsBare, IsTransparent, Fragile, IsThunk);
  // Re-use an existing thunk.
  if (!Thunk->empty())
    return Thunk;

  Thunk->setGenericEnvironment(ReInfo.getSpecializedGenericEnvironment());

  SILBasicBlock *EntryBB = Thunk->createBasicBlock();
  SILBuilder Builder(EntryBB);

  // If the original specialized function had unqualified ownership, set the
  // thunk to have unqualified ownership as well.
  //
  // This is a stop gap measure to allow for easy inlining. We could always make
  // the Thunk qualified, but then we would need to either fix the inliner to
  // inline qualified into unqualified functions /or/ have the
  // OwnershipModelEliminator run as part of the normal compilation pipeline
  // (which we are not doing yet).
  if (SpecializedFunc->hasUnqualifiedOwnership()) {
    Thunk->setUnqualifiedOwnership();
  }

  if (!SILModuleConventions(M).useLoweredAddresses()) {
    for (auto SpecArg : SpecializedFunc->getArguments()) {
      SILArgument *NewArg = EntryBB->createFunctionArgument(SpecArg->getType(),
                                                            SpecArg->getDecl());
      Arguments.push_back(NewArg);
    }
    SILValue ReturnValue = createReabstractionThunkApply(Builder);
    Builder.createReturn(Loc, ReturnValue);
    return Thunk;
  }
  // Handle lowered addresses.
  SILArgument *ReturnValueAddr = convertReabstractionThunkArguments(Builder);

  SILValue ReturnValue = createReabstractionThunkApply(Builder);

  if (ReturnValueAddr) {
    // Need to store the direct results to the original indirect address.
    Builder.createStore(Loc, ReturnValue, ReturnValueAddr,
                        StoreOwnershipQualifier::Unqualified);
    SILType VoidTy =
        OrigPAI->getSubstCalleeType()->getDirectFormalResultsType();
    assert(VoidTy.isVoid());
    ReturnValue = Builder.createTuple(Loc, VoidTy, {});
  }
  Builder.createReturn(Loc, ReturnValue);
  return Thunk;
}

// Create a call to a reabstraction thunk. Return the call's direct result.
SILValue ReabstractionThunkGenerator::createReabstractionThunkApply(
    SILBuilder &Builder) {
  SILFunction *Thunk = &Builder.getFunction();
  auto *FRI = Builder.createFunctionRef(Loc, SpecializedFunc);
  auto Subs = Thunk->getForwardingSubstitutions();
  auto CalleeSubstFnTy = getCalleeSubstFunctionType(FRI, Subs);
  auto CalleeSILSubstFnTy = SILType::getPrimitiveObjectType(CalleeSubstFnTy);
  auto specConv = SpecializedFunc->getConventions();
  if (!SpecializedFunc->getLoweredFunctionType()->hasErrorResult()) {
    return Builder.createApply(Loc, FRI, CalleeSILSubstFnTy,
                               specConv.getSILResultType(), Subs, Arguments,
                               false);
  }
  // Create the logic for calling a throwing function.
  SILBasicBlock *NormalBB = Thunk->createBasicBlock();
  SILBasicBlock *ErrorBB = Thunk->createBasicBlock();
  Builder.createTryApply(Loc, FRI, CalleeSILSubstFnTy, Subs,
                         Arguments, NormalBB, ErrorBB);
  auto *ErrorVal = ErrorBB->createPHIArgument(specConv.getSILErrorType(),
                                              ValueOwnershipKind::Owned);
  Builder.setInsertionPoint(ErrorBB);
  Builder.createThrow(Loc, ErrorVal);
  SILValue ReturnValue = NormalBB->createPHIArgument(
      specConv.getSILResultType(), ValueOwnershipKind::Owned);
  Builder.setInsertionPoint(NormalBB);
  return ReturnValue;
}

// Create SIL arguments for a reabstraction thunk with lowered addresses. This
// may involve replacing indirect arguments with loads and stores. Return the
// SILArgument for the address of an indirect result, or nullptr.
//
// FIXME: Remove this if we don't need to create reabstraction thunks after
// address lowering.
SILArgument *ReabstractionThunkGenerator::convertReabstractionThunkArguments(
    SILBuilder &Builder) {
  SILFunction *Thunk = &Builder.getFunction();
  CanSILFunctionType SpecType = SpecializedFunc->getLoweredFunctionType();
  CanSILFunctionType SubstType = ReInfo.getSubstitutedType();
  auto specConv = SpecializedFunc->getConventions();
  SILFunctionConventions substConv(SubstType, M);

  assert(specConv.useLoweredAddresses());

  // ReInfo.NumIndirectResults corresponds to SubstTy's formal indirect
  // results. SpecTy may have fewer formal indirect results.
  assert(SubstType->getNumIndirectFormalResults()
         >= SpecType->getNumIndirectFormalResults());

  SILBasicBlock *EntryBB = Thunk->getEntryBlock();
  SILArgument *ReturnValueAddr = nullptr;
  auto SpecArgIter = SpecializedFunc->getArguments().begin();
  auto cloneSpecializedArgument = [&]() {
    // No change to the argument.
    SILArgument *SpecArg = *SpecArgIter++;
    SILArgument *NewArg =
        EntryBB->createFunctionArgument(SpecArg->getType(), SpecArg->getDecl());
    Arguments.push_back(NewArg);
  };
  // ReInfo.NumIndirectResults corresponds to SubstTy's formal indirect
  // results. SpecTy may have fewer formal indirect results.
  assert(SubstType->getNumIndirectFormalResults()
         >= SpecType->getNumIndirectFormalResults());
  unsigned resultIdx = 0;
  for (auto substRI : SubstType->getIndirectFormalResults()) {
    if (ReInfo.isFormalResultConverted(resultIdx++)) {
      // Convert an originally indirect to direct specialized result.
      // Store the result later.
      // FIXME: This only handles a single result! Partial specialization could
      // induce some combination of direct and indirect results.
      SILType ResultTy = substConv.getSILType(substRI);
      assert(ResultTy.isAddress());
      assert(!ReturnValueAddr);
      ReturnValueAddr = EntryBB->createFunctionArgument(ResultTy);
      continue;
    }
    // If the specialized result is already indirect, simply clone the indirect
    // result argument.
    assert((*SpecArgIter)->getType().isAddress());
    cloneSpecializedArgument();
  }
  assert(SpecArgIter
         == SpecializedFunc->getArgumentsWithoutIndirectResults().begin());
  unsigned numParams = SpecType->getNumParameters();
  assert(numParams == SubstType->getNumParameters());
  for (unsigned paramIdx = 0; paramIdx < numParams; ++paramIdx) {
    if (ReInfo.isParamConverted(paramIdx)) {
      // Convert an originally indirect to direct specialized parameter.
      assert(!specConv.isSILIndirect(SpecType->getParameters()[paramIdx]));
      // Instead of passing the address, pass the loaded value.
      SILType ParamTy =
          substConv.getSILType(SubstType->getParameters()[paramIdx]);
      assert(ParamTy.isAddress());
      SILArgument *SpecArg = *SpecArgIter++;
      SILArgument *NewArg =
          EntryBB->createFunctionArgument(ParamTy, SpecArg->getDecl());
      auto *ArgVal =
          Builder.createLoad(Loc, NewArg, LoadOwnershipQualifier::Unqualified);
      Arguments.push_back(ArgVal);
      continue;
    }
    // Simply clone unconverted direct or indirect parameters.
    cloneSpecializedArgument();
  }
  assert(SpecArgIter == SpecializedFunc->getArguments().end());
  return ReturnValueAddr;
}

void swift::trySpecializeApplyOfGeneric(
    ApplySite Apply, DeadInstructionSet &DeadApplies,
    llvm::SmallVectorImpl<SILFunction *> &NewFunctions) {
  assert(Apply.hasSubstitutions() && "Expected an apply with substitutions!");

  auto *F = Apply.getInstruction()->getFunction();
  auto *RefF = cast<FunctionRefInst>(Apply.getCallee())->getReferencedFunction();

  DEBUG(llvm::dbgs() << "  ApplyInst:\n";
        Apply.getInstruction()->dumpInContext());

  // If the caller is fragile but the callee is not, bail out.
  // Specializations have shared linkage, which means they do
  // not have an external entry point, Since the callee is not
  // fragile we cannot serialize the body of the specialized
  // callee either.
  if (F->isFragile() && !RefF->hasValidLinkageForFragileInline())
      return;

  if (shouldNotSpecializeCallee(RefF))
    return;

  // If the caller and callee are both fragile, preserve the fragility when
  // cloning the callee. Otherwise, strip it off so that we can optimize
  // the body more.
  IsFragile_t Fragile = IsNotFragile;
  if (F->isFragile() && RefF->isFragile())
    Fragile = IsFragile;

  ReabstractionInfo ReInfo(Apply, RefF, Apply.getSubstitutions());
  if (!ReInfo.canBeSpecialized())
    return;

  SILModule &M = F->getModule();

  bool needAdaptUsers = false;
  bool replacePartialApplyWithoutReabstraction = false;
  auto *PAI = dyn_cast<PartialApplyInst>(Apply);

  if (PAI && ReInfo.hasConversions()) {
    // If we have a partial_apply and we converted some results/parameters from
    // indirect to direct there are 3 cases:
    // 1) All uses of the partial_apply are apply sites again. In this case
    //    we can just adapt all the apply sites which use the partial_apply.
    // 2) The result of the partial_apply is re-abstracted anyway (and the
    //    re-abstracted function type matches with our specialized type). In
    //    this case we can just skip the existing re-abstraction.
    // 3) For all other cases we need to create a new re-abstraction thunk.
    needAdaptUsers = true;
    for (Operand *Use : PAI->getUses()) {
      SILInstruction *User = Use->getUser();
      if (isa<RefCountingInst>(User))
        continue;
      if (isDebugInst(User))
        continue;

      auto FAS = FullApplySite::isa(User);
      if (FAS && FAS.getCallee() == Apply.getInstruction())
        continue;

      auto *PAIUser = dyn_cast<PartialApplyInst>(User);
      if (PAIUser && isPartialApplyOfReabstractionThunk(PAIUser)) {
        CanSILFunctionType NewPAType =
          ReInfo.createSpecializedType(PAI->getFunctionType(), M);
        if (PAIUser->getFunctionType() == NewPAType)
          continue;
      }
      replacePartialApplyWithoutReabstraction = true;
      break;
    }
  }

  GenericFuncSpecializer FuncSpecializer(RefF, Apply.getSubstitutions(),
                                         Fragile, ReInfo);
  SILFunction *SpecializedF = FuncSpecializer.lookupSpecialization();
  if (SpecializedF) {
    // Even if the pre-specialization exists already, try to preserve it
    // if it is whitelisted.
    linkSpecialization(M, SpecializedF);
  } else {
    SpecializedF = FuncSpecializer.tryCreateSpecialization();
    if (!SpecializedF)
      return;

    assert(SpecializedF->hasUnqualifiedOwnership());
    NewFunctions.push_back(SpecializedF);
  }

  assert(ReInfo.getSpecializedType()
         == SpecializedF->getLoweredFunctionType() &&
         "Previously specialized function does not match expected type.");

  // FIXME: Replace pre-specialization's "keep as public" hack with something
  // more principled
  assert((Fragile == SpecializedF->isFragile() ||
          SpecializedF->isKeepAsPublic()) &&
         "Previously specialized function does not match expected "
         "resilience level.");

  DeadApplies.insert(Apply.getInstruction());

  if (replacePartialApplyWithoutReabstraction) {
    // There are some unknown users of the partial_apply. Therefore we need a
    // thunk which converts from the re-abstracted function back to the
    // original function with indirect parameters/results.
    auto *PAI = cast<PartialApplyInst>(Apply.getInstruction());
    SILBuilderWithScope Builder(PAI);
    SILFunction *Thunk =
        ReabstractionThunkGenerator(ReInfo, PAI, SpecializedF).createThunk();
    NewFunctions.push_back(Thunk);
    auto *FRI = Builder.createFunctionRef(PAI->getLoc(), Thunk);
    SmallVector<SILValue, 4> Arguments;
    for (auto &Op : PAI->getArgumentOperands()) {
      Arguments.push_back(Op.get());
    }
    auto Subs = ReInfo.getCallerParamSubstitutions();
    auto CalleeSubstFnTy = getCalleeSubstFunctionType(FRI, Subs);
    auto CalleeSILSubstFnTy = SILType::getPrimitiveObjectType(CalleeSubstFnTy);
    auto *NewPAI = Builder.createPartialApply(PAI->getLoc(), FRI,
                                              CalleeSILSubstFnTy, Subs,
                                              Arguments, PAI->getType());
    PAI->replaceAllUsesWith(NewPAI);
    DeadApplies.insert(PAI);
    return;
  }
  // Make the required changes to the call site.
  ApplySite newApply = replaceWithSpecializedFunction(Apply, SpecializedF,
                                                      ReInfo);
  if (needAdaptUsers) {
    // Adapt all known users of the partial_apply. This is needed in case we
    // converted some indirect parameters/results to direct ones.
    auto *NewPAI = cast<PartialApplyInst>(newApply);
    ReInfo.prunePartialApplyArgs(NewPAI->getNumArguments());
    for (Operand *Use : NewPAI->getUses()) {
      SILInstruction *User = Use->getUser();
      if (auto FAS = FullApplySite::isa(User)) {
        SILBuilder Builder(User);
        replaceWithSpecializedCallee(FAS, NewPAI, Builder, ReInfo);
        DeadApplies.insert(FAS.getInstruction());
        continue;
      }
      if (auto *PAI = dyn_cast<PartialApplyInst>(User)) {
        // This is a partial_apply of a re-abstraction thunk. Just skip this.
        assert(PAI->getType() == NewPAI->getType());
        PAI->replaceAllUsesWith(NewPAI);
        DeadApplies.insert(PAI);
      }
    }
  }
}

// =============================================================================
// Prespecialized symbol lookup.
//
// This uses the SIL linker to checks for the does not load the body of the pres
// =============================================================================

static void keepSpecializationAsPublic(SILFunction *F) {
  DEBUG(auto DemangledNameString =
            swift::Demangle::demangleSymbolAsString(F->getName());
        StringRef DemangledName = DemangledNameString;
        llvm::dbgs() << "Keep specialization public: " << DemangledName << " : "
                     << F->getName() << "\n");
  // Make it public, so that others can refer to it.
  //
  // NOTE: This function may refer to non-public symbols, which may lead to
  // problems, if you ever try to inline this function. Therefore, these
  // specializations should only be used to refer to them, but should never
  // be inlined!  The general rule could be: Never inline specializations
  // from stdlib!
  //
  // NOTE: Making these specializations public at this point breaks
  // some optimizations. Therefore, just mark the function.
  // DeadFunctionElimination pass will check if the function is marked
  // and preserve it if required.
  F->setKeepAsPublic(true);
}

/// Link a specialization for generating prespecialized code.
///
/// For now, it is performed only for specializations in the
/// standard library. But in the future, one could think of
/// maintaining a cache of optimized specializations.
///
/// Mark specializations as public, so that they can be used by user
/// applications. These specializations are generated during -O compilation of
/// the library, but only used only by client code compiled at -Onone. They
/// should be never inlined.
static bool linkSpecialization(SILModule &M, SILFunction *F) {
  if (F->isKeepAsPublic())
    return true;
  // Do not remove functions from the white-list. Keep them around.
  // Change their linkage to public, so that other applications can refer to it.
  if (M.getOptions().Optimization >= SILOptions::SILOptMode::Optimize &&
      F->getModule().getSwiftModule()->getName().str() == SWIFT_ONONE_SUPPORT) {
    if (isWhitelistedSpecialization(F->getName())) {
      keepSpecializationAsPublic(F);
      return true;
    }
  }
  return false;
}

// The whitelist of classes and functions from the stdlib,
// whose specializations we want to preserve.
static const char *const WhitelistedSpecializations[] = {
    "Array",
    "_ArrayBuffer",
    "_ContiguousArrayBuffer",
    "Range",
    "RangeIterator",
    "CountableRange",
    "CountableRangeIterator",
    "ClosedRange",
    "ClosedRangeIterator",
    "CountableClosedRange",
    "CountableClosedRangeIterator",
    "IndexingIterator",
    "Collection",
    "ReversedCollection",
    "MutableCollection",
    "BidirectionalCollection",
    "RandomAccessCollection",
    "ReversedRandomAccessCollection",
    "RangeReplaceableCollection",
    "_allocateUninitializedArray",
    "UTF8",
    "UTF16",
    "String",
    "_StringBuffer",
    "_toStringReadOnlyPrintable",
};

/// Check of a given name could be a name of a white-listed
/// specialization.
bool swift::isWhitelistedSpecialization(StringRef SpecName) {
  // TODO: Once there is an efficient API to check if
  // a given symbol is a specialization of a specific type,
  // use it instead. Doing demangling just for this check
  // is just wasteful.
  auto DemangledNameString =
     swift::Demangle::demangleSymbolAsString(SpecName);

  StringRef DemangledName = DemangledNameString;

  DEBUG(llvm::dbgs() << "Check if whitelisted: " << DemangledName << "\n");

  auto pos = DemangledName.find("generic ", 0);
  auto oldpos = pos;
  if (pos == StringRef::npos)
    return false;

  // Create "of Swift"
  llvm::SmallString<64> OfString;
  llvm::raw_svector_ostream buffer(OfString);
  buffer << "of ";
  buffer << STDLIB_NAME <<'.';

  StringRef OfStr = buffer.str();
  DEBUG(llvm::dbgs() << "Check substring: " << OfStr << "\n");

  pos = DemangledName.find(OfStr, oldpos);

  if (pos == StringRef::npos) {
    // Create "of (extension in Swift).Swift"
    llvm::SmallString<64> OfString;
    llvm::raw_svector_ostream buffer(OfString);
    buffer << "of (extension in " << STDLIB_NAME << "):";
    buffer << STDLIB_NAME << '.';
    OfStr = buffer.str();
    pos = DemangledName.find(OfStr, oldpos);
    DEBUG(llvm::dbgs() << "Check substring: " << OfStr << "\n");
    if (pos == StringRef::npos)
      return false;
  }

  pos += OfStr.size();

  for (auto NameStr: WhitelistedSpecializations) {
    StringRef Name = NameStr;
    auto pos1 = DemangledName.find(Name, pos);
    if (pos1 == pos && !isalpha(DemangledName[pos1+Name.size()])) {
      return true;
    }
  }

  return false;
}

/// Try to look up an existing specialization in the specialization cache.
/// If it is found, it tries to link this specialization.
///
/// For now, it performs a lookup only in the standard library.
/// But in the future, one could think of maintaining a cache
/// of optimized specializations.
static SILFunction *lookupExistingSpecialization(SILModule &M,
                                                 StringRef FunctionName) {
  // Try to link existing specialization only in -Onone mode.
  // All other compilation modes perform specialization themselves.
  // TODO: Cache optimized specializations and perform lookup here?
  // Only check that this function exists, but don't read
  // its body. It can save some compile-time.
  if (isWhitelistedSpecialization(FunctionName))
    return M.findFunction(FunctionName, SILLinkage::PublicExternal);

  return nullptr;
}

SILFunction *swift::lookupPrespecializedSymbol(SILModule &M,
                                               StringRef FunctionName) {
  // First check if the module contains a required specialization already.
  auto *Specialization = M.lookUpFunction(FunctionName);
  if (Specialization) {
    if (Specialization->getLinkage() == SILLinkage::PublicExternal)
      return Specialization;
  }

  // Then check if the required specialization can be found elsewhere.
  Specialization = lookupExistingSpecialization(M, FunctionName);
  if (!Specialization)
    return nullptr;

  assert(hasPublicVisibility(Specialization->getLinkage()) &&
         "Pre-specializations should have public visibility");

  Specialization->setLinkage(SILLinkage::PublicExternal);

  assert(Specialization->isExternalDeclaration()  &&
         "Specialization should be a public external declaration");

  DEBUG(llvm::dbgs() << "Found existing specialization for: " << FunctionName
                     << '\n';
        llvm::dbgs() << swift::Demangle::demangleSymbolAsString(
                            Specialization->getName())
                     << "\n\n");

  return Specialization;
}


text:
Benedikt Bachmeier (* 9. Februar 1852 in Kleinhaarbach; † 30. Juni 1912 in Mitterhaarbach) war Gutsbesitzer und Mitglied des Deutschen Reichstags.

Leben
Bachmeier besuchte von 1858 bis 1864 die Volksschule in Tettenweis. Danach diente er drei Jahre beim 1. Kürassierregiment in München. Er war ab 1886 selbständiger Landwirt in Mitterhaarbach. Weiter war er Zweiter Vorsitzender des Landwirtschaftlichen Bezirksvereins Griesbach und Mitglied desselben Distriktsratsausschusses, sowie Mitglied des niederbayerischen Landrats.

Von 1893 bis 1907 und ab Januar 1912 war er Mitglied des Deutschen Reichstags für den Wahlkreis Niederbayern 4 (Pfarrkirchen, Eggenfelden, Griesbach) und den Bayerischen Bauernbund (BB). Bei der Reichstagswahl 1893 hatte Bachmeier sich verpflichtet, in kirchlichen Fragen die Position des Zentrums zu unterstützen, woraufhin er vom vornehmlich agrarisch strukturierten Wahlkreis gegen den Zentrumskandidaten mit 75 % der abgegebenen, gültigen Stimmen gewählt wurde. Zwischen 1893 und 1904 war er auch Mitglied des bayerischen Landtags.

Sein Sohn Benedikt Bachmeier war ebenfalls für den Bauernbund aktiv und war von 1919 an Mitglied der Weimarer Nationalversammlung und anschließend bis 1928 Abgeordneter des Reichstags.

Weblinks

 Regiowiki Niederbayern

Einzelnachweise

Reichstagsabgeordneter (Deutsches Kaiserreich)
Mitglied der Bayerischen Abgeordnetenkammer
BBB-Mitglied
Deutscher
Geboren 1852
Gestorben 1912
Mann

redpajama_set_name: RedPajamaWikipedia


text:
View sections
Gloucester History Festival: The 2021 Winstone Talk
Anne Boleyn and The History of England's Queens
Leading historian and broadcaster Tracy Borman explores the intriguing life of Anne Boleyn and the history of English Queens from the Tudors to the Windsors.
The British monarchy has weathered the storms of rebellion, revolution and war that brought many of Europe's royal families to an abrupt and bloody end, yet often spearheading seismic change it is an extraordinary survivor. Join her as she explores the history of the British monarchy through the lives of some of its most powerful women. Tracy Borman is a bestselling historian and TV broadcaster specialising in the Tudor period and is joint Chief Curator of Historic Royal Palaces. Her new book Crown & Sceptre exploring the British monarchy from 1066 to the present day is published this autumn.
Following in the footsteps of Janina Ramirez, Roy Strong and Kate Adie, we're thrilled that Tracy Borman is giving this year's Winstone Talk in Cirencester – speaking just ten feet away from Cirencester Parish Church's greatest treasure, the Anne Boleyn Cup, made for Henry VIII's queen in 1535 and which can still be viewed at the Church today
Saturday 2 October, 6.30 - 7.30pm
Parish Church of St. John Baptist, Cirencester, GL7 2NX
To book your ticket visit www.gloucesterhistoryfestival.co.uk/events/the-2021-winstone-talk/
The Winstone Talk is supported by The K D Winstone Charitable Trust
No comments have been left for this article
Your comments (required)
Your name (required) Email address (Not displayed)(required) Authentication
Your name will be published alongside your comment but we will not publish your email address.
All comments will be reviewed by a moderator before being published.
Please ensure you complete all fields marked as mandatory.
Gloucestershire Archives: Secrets Revealed
Gloucestershire Archives: Passport to the Past
Gloucestershire Archives: Training Event
Past talks now on You Tube
Museum of Gloucester
Gloucester History Festival September 2021

redpajama_set_name: RedPajamaCommonCrawl


News & Events - Page 5 of 9 - Lumber Dealers Association of Connecticut | Lumber Dealers Association of Connecticut - Committed to the advocacy & protection of lumber dealer rights.
NRLA announced that it has reached agreement with Allied American Insurance Agency and the American International Group (AIG) Insurance Co. to offer an insurance program to our members. Jan.1, 2001. AIG will be offering coverage binders from Jan. 1, 2001 to renewal date. Call NRLA (800) 292-6752 for more information.
The annual meeting was a great success with 130 people attending the afternoon program and the banquet honoring Jim Lyke as Lumber Person of the Year. Our speaker for the afternoon program, Ray Leone gave a dynamic and educational program. I hope next year will be a greater success.
The 2001 LDAC slate of officers was announced and Greg Branecky, The Hatch & Bailey Co., Norwalk was voted in as President while Lisa Nadeau, General Building; E. Hartford was voted in as Secretary. Also Charles Heyman, Washington Supply, Washington was voted in as Treasurer.
Lumber Dealers Association of Connecticut Board are asking all members to support AmeriCares HomeFront. AmeriCares HomeFront is a private, nonprofit humanitarian organization, which helps people who are low income, elderly, ill, disabled, or single parents by repairing their home to keep it warm, safe, and dry. We need our members to help support this rewarding project. AmeriCares HomeFront has a list of supplies needed for this wonderful project. Please call Greg Branecky (203) 866-5515 or Kris deFriesse at AmeriCares HomeFront 1-800-887-HOPE if you would like more information. AmeriCares HomeFront will help to promote your company within your community with press releases in television, radio, and newspapers, and This Old House Magazine's "Thank You" Section.
Let's make Connecticut the biggest state represented.
Posted September 3, 2015 by CTLumber & filed under Scholarship.
Posted May 14, 2015 by CTLumber & filed under Legislative.
Purpose: This Informational Publication describes how materialmen may remit sales and use taxes on certain sales of building materials and services to real property as and when actually paid by the purchasers to whom the materialmen have extended credit, instead of remitting the full amount of tax at the time of the transaction as generally required by law.
Background: Generally, sellers of tangible personal property and taxable services must remit tax on the entire amount of the gross receipts from a transaction on the return for the period in which the transaction takes place. The pay-when-paid provision allows certain sellers of building materials and services related to these materials an exception to this general rule.
Definitions: A materialman, for the pay-when-paid provision, is a person who furnishes building materials or services to a contractor for the construction, raising, removal, or repair of a building or the improvement of real property. To be considered a materialman, a person must also be entitled under Chapter 847 of the Connecticut General Statutes to file a mechanic's lien against the real property to ensure payment for the materials or services.
Building Materials means materials that are incorporated as an improvement or repair to real property. The term also includes tools and other items that are used to improve real property. The term contractor includes a general contractor, a subcontractor, a repairman, and a property owner acting as his or her own general contractor.
At least 50% of the materialman's sales of building materials (not services) were to contractors.
DRS issues Form REG-20, Application for a Materialman to Remit Sales Tax Under the Pay-When-Paid Method. A materialman must file this application by July 1 each year in order to obtain pay-when-paid status. DRS will respond to a properly completed application with a letter authorizing the materialman to use the pay-when-paid method on qualifying transactions.
Deadline to Submit Application: DRS only accepts applications filed on or before July 1 of each year. The applications are considered timely filed if received, or if the date shown by the U.S. Post Office cancellation mark is, on or before this date.
Posted March 9, 2015 by CTLumber & filed under Legislative.
After nearly six weeks of activity and multiple snowstorms, the pace at the Capitol is set to increase. Until now, most of the bills are merely "proposed" bills, which are concepts and not fully drafted. Committees are now starting to fully draft several of those, and more importantly, Governor Malloy will submit his budget proposal on February 18th.
Despite projected deficits that exceed $1.25 Billion per year, the Governor has promised not to raise taxes. He is also expected to announce a major transportation infrastructure initiative and a method of funding it. Other expected proposals in his budget may involve removing several sales tax exemptions and lowering the rate, and amending the system of taxing motor vehicles.
Besides the Governor's budget, there are several issues of specific concern to LDAC members. HB 5117 and SB 887 involve mechanics' liens. SB 887 is the Department of Consumer Protection's bill. It would prohibit anyone who doesn't have the required DCP license or registration from filing the lien/ Materialmen would not be affected. HB 5117 would change the time for filing from 90 days to 90 business days.
Two proposed bills HB 5262 and 6235 would increase the jurisdiction of Small Claims Court from $5,000 to $10,000 or $12,000.
As usual there is significant activity from the Labor Committee which include several bills that would increase payroll costs. HB 6784 would expand paid sick leave to companies with 10 or more employees, increase the amount of mandated leave from 5 to 7 days, include temporary and day workers and expand eligibility to those who worked only 120 days regardless of the number of hours.
SB 798 would require the provision of paid family and medical leave. The bill has not been fleshed out yet, but it is a major priority for organized labor.
Regarding unemployment compensation issues, the Department of Labor continues to consider ways to restore solvency to the Unemployment Compensation Trust Fund. Despite paying the highest FUTA taxes in the nation, the DOL would increase the taxable wage base from $15,000 to $26,000. LDAC is participating in a broad business coalition that will support HB 5851, which would restore solvency through a number of expense reduction measures. Those would include a one week waiting period, requiring claimants to post resumes on line, basing benefits on the annual salary, not the current two highest quarters.
Although Connecticut continues to consider a public sector retirement plan for private sector employees, legislation awaits the report of a consultant and action may be delayed this year.
Another study is being done on chemical road treatments used by the Department of Transportation. Evidence is that such chemicals are highly corrosive to vehicles and structures. The report is not due until July, so it is unlikely that any progress on this issue will come before the next legislative session.
In summary, without question, the budget debate will dominate the rest of the session. There will be major fights over spending and taxes. How the Governor can balance the budget without tax increases remains to be seen. Within the next few weeks, we will have a better picture of the fiscal issues that will affect LDAC members and which of the onerous labor / cost of doing business issues are the most serious.
Posted October 30, 2014 by CTLumber & filed under Lumber Person of the Year.
Sanford & Hawley, Unionville, Conn.
A deeply-rooted faith in God has guided Larry throughout his family life, education, and career. A graduate of not only BC but of the Archdiocese of Hartford Lay Ministry Formation program, he counts among his guiding principles a commitment to be a good husband, father, and grandfather; to be someone who makes a difference in the lives of youth in his parish; and to be honest with his customers. This commitment to his parish community is demonstrated by being a recipient of the God & Youth Award from the Archdiocese of Hartford.
Larry met his wife, Mary, at Stamford Catholic High School. They parted for a time after graduation, but reunited six years later and have now been married for 46 years. Larry counts Mary as his greatest blessing and looks forward to a continually growing relationship in retirement. Their family includes two sons, Larry Jr. and Michael, a daughter, Amy, and three grandchildren, Anthony, Marco, and Joseph.
A lifelong sports fan, from playing baseball as a kid to co-captaining his high school football team, Larry enjoys BC football, UConn women's basketball, and New York Yankees baseball games. He plans to catch up on his leisure reading in retirement, with murder mysteries and espionage novels on the top of his book list.
Posted October 3, 2014 by CTLumber & filed under Legislative.
Lowe's entered into a settlement in Northern California agreed to pay a $1.6 million due to a lawsuit alleging the inaccurate description of dimensional building products. Since the settlement was announced there has been questions concerning what our members need to do to make sure they are not sued for the same issue.
NRLA had the law firm of Bernstein Shur analyze the judge's order on the settlement, the implications for retailers, and what it means for our members going forward.
If Lowe's complies with the standards referenced above, and labels the product dimensions according to those conventions, there should be no violation of the Judgment. But, again, there is no guarantee that any jurisdiction will honor those exemptions. The Voluntary Product Standards are just that—voluntary—but compliance with those standards and labeling those products accordingly greatly reduces exposure. On the other hand, manufacturers, wholesalers, and retailers can further reduce exposure by always including actual dimensions even when products are labeled using nominal dimensions or manufacturers' dimensional descriptions (remember, when Lowe's uses popular or common labeling it already has to accompany such sales with actual dimensions).
All of the NRLA states have adopted the Uniform Deceptive Trade Practices Act, or equivalent statutes, which generally prohibit misleading descriptions of the characteristics or quantities of products. Even though many jurisdictions may end up rejecting the reasoning reflected in the Judgment, the cautious seller will take every reasonable opportunity to inform the consumer whenever there is an arguable gap between the labeling, packaging, and advertising of a product and the true characteristics of that product.
It should be noted that as more information has come to light this was not an issue of a single item or a single instance where Lowe's was found to have dimensional lumber that was below accepted standards. The suit was not just because a 2×4 isn't actually a 2×4 (nominal name), but because the dimensional lumber being sold was below standards repeatedly. The suit was filed under "misleading or deceptive practices" because the materials being sold were not acceptable for industry standards, not just because the nominal name did not match the true dimensions.
Below is the memo. We hope that this help answers questions that our members have. If you have any further questions, please contact me at either 518.880.6376 or jkeller@nrla.org.
Posted October 1, 2014 by CTLumber & filed under Membership.
The Lumber Dealers Association of Connecticut (LDAC) is in the early stages of developing a program with the idea of introducing new people to the Lumber Building Material (LBM) industry. LDAC will partner with members in the training and development of tomorrow's LBM employees by offering financial assistance in the form of a one-time stipend, up to $2,500.00 to help off-set some of the costs associated with hiring and training.
Ideally, members should seek out individuals looking to enter in the building material industry to fill a specific job requirement who may not otherwise look to our industry for employment.
These individuals could be (however not limited to) high school or college students, trade school students. Members will submit a plan for hire and development of these candidates to LDAC for eligibility of the stipend.
There are limited stipends available. Stipend disbursement will be determined bt the association board based on merits of the submitted proposal. Employment proposals will be reviewed within 3-6 weeks of receipt.
This is a brand new program for which LDAC welcomes any comments or suggestions from dealers on how best to promote and administer the program. See below for proposal form, or contact CT Regional Director: Tammy Wandler-Ginexi at: tammy@nrla.org for questions or comments.
Posted September 30, 2014 by CTLumber & filed under Scholarship.
Posted July 2, 2014 by CTLumber & filed under Legislative.
Contractors who have been certified under the Lead Renovation, Repair, and Painting (LRRP) rule are being encouraged to use a new logo that highlights them as an "EPA Lead-Safe Certified Firm." The Environmental Protection Agency (EPA) campaign includes ads that encourage parents and those that care for children to "Protect Your Family. Look for the Logo." The promotions also link to a database of local LRRP certified firms for homeowners to explore. More information can be found at EPA Lead Safe.
The EPA recently cracked down on companies for violations of the LRRP Rule. Four New England companies were fined between $2,200 and $30,000. This follows the recent fines where two firms paid a total of $14,455 for similar violations in Maine. Lowe's also recently agreed to pay the largest civil penalty ever under the LRRP Rule, $500,000, to settle claims that its contractors in at least nine states (including Connecticut, New Hampshire, New York, and Vermont) violated the LRRP Rule with both paperwork and testing non-compliance.
The EPA released its final program requirements for ENERGY STAR Version 6.0 for residential windows, doors, and skylights. The final Version 6.0 specifications include significant improvements from earlier drafts that increase ENERGY STAR qualification requirements of windows, doors, and skylights, while keeping those products more affordable for homeowners. More information on the new specifications can be found at ENERGY STAR.
The EPA and the U.S. Army Corps of Engineers unveiled a proposed rule that could greatly expand federal regulatory jurisdiction over wetlands under the Clean Water Act (CWA). Some fear the greatly expanded jurisdictional tributaries, including ditches and any other man-made conveyance that drains or connects to water sources. While the EPA has strongly denied that is their intent, large opposition is forming to oppose this overreach and make the EPA redefine their intent.
As of October 1, 2015, merchants will be subjected to new credit card terminal standards – a shift from magnetic-stripe cards to chip-and-PIN cards. American Express, Discover, MasterCard, and Visa have all announced their plans to transition to the EMV system. While the new cards will feature chip technology, at this point the cards will not require PINs in the United States. Most merchants will still require a signature when the card does not require a PIN.
Compliance with EMV is not mandated for merchants and processers, meaning retailers are not required to upgrade their credit card terminals and systems to read chip-and-PIN cards; however, merchants who do not use the new terminals and software will be liable for any fraudulent purchases. At this point there does not appear to be a shift in liability for orders taken online, via mail, or over the phone, known as card-not-present (CNP) transactions.
A new credit card terminal with the chip reader costs approximately $40, but can cost as much as $100 if it comes with a PIN keypad. More information on EMV credit cards and machines can be found at: EMV Memo.
Beginning May 21, drivers are required to receive a medical examination from a certified medical examiner. Certified medical examiners are listed on the National Registry. If your driver's medical card expires May 21 or after, it is important that you check the National Registry to ensure that the medical examiner is certified. You do not need to send your driver for a medical exam until his or her card is about to expire. To find a certified medical examiner in your area, click here. The Federal Motor Carrier Safety Administration is still processing certification information; therefore the number of certified medical examiners in your area should increase over the next couple of months.
The Federal Motor Carrier Safety Administration (FMCSA) began deactivating the U.S. Dept. of Transportation (USDOT) numbers of motor carriers who have failed to update their MCS-150 registration information as part of the biennial requirement. FMCSA will continue to deactivate USDOT numbers for those who fail to update their MCS-150 forms within two months of their assigned biennial update deadline. Motor carriers, freight forwarders, and brokers who do not fulfill their biennial update requirement on time can face penalties of up to $1,000 per day with a maximum of $10,000 total in addition to having their operating authority deactivated. Motor carrier registration updates can be completed here.
With the summer months approaching, it is important for employers to make sure employees are taking the proper precautions to avoid heat exhaustion and heat-related illnesses. The Occupational Safety & Health Administration (OSHA) continues to run its "Campaign to Prevent Heat Illness in Outdoor Workers," which includes a webpage and even a smartphone App. These are excellent tools to use for your outside workers, but it is important to remember that indoor workers can also suffer from heat-related illnesses in worksites that are not properly ventilated and cooled.
OSHA proposed a rule to expand the injury and illness reporting requirements for employers. The notice of proposed rulemaking requires electronic submission of these reports to OSHA. OSHA is proposing that establishments with 20 or more employees in certain industries with high injury and illness rates (including LBM dealers), be required to submit electronically their summary of work-related injuries and illnesses to OSHA once a year. OSHA plans to eventually post the data online.
The Obama administration is permitting more than a dozen states to not implement part of the Affordable Care Act's (ACA) small business health insurance exchange until at least 2016. The delays mean that small-business employees seeking to buy health insurance in the SHOP system will only have one option in those 18 states. The ACA intended to allow customers on the SHOP exchange to pick from a variety of options, but the rollout of that feature has been delayed several times. Included in the list of 18 states that received this delay were Maine, New Hampshire, and New Jersey.
Additionally, for companies that have 50 – 99 employees, the employer mandate is now delayed until January 2016 – when companies must either offer health insurance policies or pay a penalty. The mandate will still take effect in January 2015 for companies with 100 or more workers.
If you administer a self-insured group health plan or health reimbursement arrangement (HRA), you must file your IRS Form 720 with your Patient-Centered Outcomes Research Institute Fee (PCORI) by July 31, 2014. You can find the IRS Form 720, IRS Form 720 instructions, and information on PCORI fees at the included links.
The National Labor Relations Board (NLRB) has decided to abandon a rule requiring a new posting notice regarding employee rights to unionize. The NLRB issued the ruling in 2012, but courts have since overturned the rule and the NLRB decided not to appeal the decision to the Supreme Court.
NRLA and NLBMDA are members of a coalition representing companies suing the NLRB over this posting requirement. This is a great victory for businesses, and our members should be proud of their efforts to help defeat this rule.
Posted July 1, 2014 by CTLumber & filed under Events.


After a painting by Joseph Wright of Derby, entitled "Edwin the Minstrel." The sitter was the artist's grandfather, Thomas Haden of Derby, also a surgeon. The etching may have been based on the mezzotint reproduction of the painting. This is one of Haden's few portrait etchings, and was included in Haden's Etudes a l'eau-forte (1866).
A brilliant impression in very fine condition.


text:
The Third Episode of "DC's Legends of Tomorrow" Ranks #3 in the 8-9 Hour
The CW spins the numbers for Thursday, February 4.
[via press release from The CW]
LEGENDS and THE 100 Thursday night
The third episode of DC's LEGENDS OF TOMORROW faced heavy competition, including an all new Big Bang Theory, and ranked #3 in the 8-9 hour in A18-34 (0.7/3) and M18-34 (0.8/4) beating ABC and NBC, and #3 in M18-49 (1.0/4).
Compared to this same week a year ago, LEGENDS improved its time period by +44% in total viewers (2.33M) and by +29% in A18-49 (0.9/3).
THE 100 held steady in week three, with 1.6M viewers and 0.6/2 in A18-49, and rose in A18-34 (0.5/2).
The 100 improved its Thursday 9-10pm time period over this same week last year by +65% in total viewers, +17% in A18-49, and more than doubled the rating in A18-34.
Year to year, The CW's new Thursday lineup is up +52% in total viewers (1.96M), +20% in A18-34 (0.6/3), and +17% in A18-49 (0.7/2).
Over its first two episodes, LEGENDS is averaging a +50% gain in total viewers in Live + 3 Day delayed viewing versus its Live + Same Day totals, a +49% increase in A18-34, +52% in M18-34, +55% in A18-49, and +62% in M18-49. THE 100 grows by +45% in total viewers, +56% in A18-34, and +52% in A18-49.=
· 100, THE (CW)
· BIG BANG THEORY, THE (CBS)
· DC'S LEGENDS OF TOMORROW (CW)


We have a perfect opportunity if you love the exciting world of Wines and Spirits, and like to be "on the go"!! You will visit a set group of accounts daily as you analyze their usage, prepare and deliver presentations, manage client inventory level, ensure preferred brand visibility, obtain payments from accounts and manage customer accounts receivables. You will also complete comprehensive training and maintain industry knowledge by attending educational workshops and actively networking.
Responsible for maximizing the sales of supplier brands to the trade through effective territory planning, selling, merchandising and communication that enables the achievement of company and supplier objectives.
• Strategizes/preplans on how best to achieve sales and merchandising objectives by understanding company pricing and product programming information on a monthly basis and maintaining accurate historical account purchase information.
• Calls on accounts and covers daily routes by creating an established and efficient routing pattern.
• Analyzes entire account base by visiting each account and identifying opportunities; completes all necessary surveys and ensures national account compliance where applicable.
• Prepares and delivers professional sales presentations to customers by balancing the company's priorities and customers' needs to include selling display ideas, new products, cold box, shelf, well and back bar placements and resets, drink and wine lists, and promotions.
• Understands and works with management on inventory levels by being aware of current inventory and out of stock situations and by alerting management to possible fluctuations in demand.
• Attains standards of performance goals by achieving the distribution, volume and activity goals of supplier brands as set by management.
• Ensures maximum brand visibility within accounts by maintaining account standards as determined by management and using effective and current point of sale materials when appropriate.
• Maintains product levels in accounts by taking inventory and restocking shelves (where legally permissable).
• Obtains payments for company by collecting and delivering checks or other remittance from accounts where legally permissible.
• Educates account staff on priority brands by administering educational staff training seminars.
• Supports account openings by developing opening orders for new accounts in collaboration with Field Sales Manager.
• Manages customer account receivables by timely processing of credits and returns and communicating with accounts on aged receivables.
• Services accounts by delivering products to customers in extenuating circumstances, handling customer issues and complaints and referring these issues, as appropriate to management.
• Maintains professional relationships with all suppliers by participating in effective supplier work with sales calls, and sales blitzes.
• Remains informed of company/supplier activities and updates by attending and actively participating in weekly sales meetings.
• Completes all necessary training programs by attending, participating, and passing all required tests as defined by management. (e.g. WSSM, TOPS, FOCUS MARKETING, SFA).
• Maintains professional and industry knowledge by attending educational workshops, reviewing professional publications and establishing personal networks.
• Maintains a safe and clean working environment by complying with procedures, rules and regulations.
• Bachelor's degree in related field and/or equivalent training and work experience preferred.
• Ability to hold a Solicitor's Permit where required.
• Valid driver's license and ability to operate a motor vehicle preferred.
• A minimum of two years in sales or industry related experience.
• An understanding of wine and spirits is required. Individuals with strong accounting, computer, customer service and interpersonal expertise preferred.
• Must be a results oriented professional with excellent verbal/written communication skills; uses diplomacy and discretion.
• Ability to multi-task, work independently and/or within a team, pay attention to detail and meet deadlines.
• Proficient PC skills using MS Office and other various programs including presentation software.
• Familiarity with assigned territory is a plus.
While performing the duties of this job, the associate is regularly required to use hands to finger, handle, or feel; reach with hands and arms; stoop, kneel, crouch, or crawl; and talk or hear. The associate frequently is required to stand, walk, sit, and climb or balance. The associate must regularly lift and/or move up to 50 pounds. Specific vision abilities required by this job include close vision, distance vision, color vision, peripheral vision, depth perception, and ability to adjust focus.
While performing the duties of this job the associate is regularly exposed normal business office environment. The ability to share workspace, travel by car or train, dress in proper business attire, attend evening meetings and meet deadlines are all requirements of this position. Associate is often required to be in the market and may require exposure to inclement weather.


Originally constructed in 1927, the Saenger Theater in the New Orleans historic Canal Street district, was almost completely lost when storm water from Hurricane Katrina rose eight feet above the stage, severely damaging the building and compromising the future of this landmark structure. Thanks to a $53 million restoration and expansion project, this grand theater was fully restored and modernized to host a wide range of events and performances.
SoundCom was selected to install the high performance audio systems for this atmospheric style, 4,000 seat theater, which re-opened in grand form in September of 2013.
This project required incredible attention to detail in order to preserve the aesthetics while delivering state-of-the-art audio systems. Working closely with Connecticut-based Akustiks, SoundCom installed a complete Meyer Sound loudspeaker system that provides high performance audio throughout the entire seating area of the theater.
A Meyer MICA series compact line array system was carefully engineered to cover the large balcony space, augmented with stage left and right Meyer loudspeaker stacks, subwoofers, and stage lip speakers.
SoundCom installed an extensive production audio wiring infrastructure for touring systems equipment. This infrastructure allows easy introduction of additional equipment when sound reinforcement exceeds the capabilities of the house audio system.
A full-featured ClearCom production intercom system was installed along with facility wide background music and paging capabilities. The paging system was carefully integrated throughout the facility to comply with historic renovation requirements, and so it would not detract from the ornate finishes and decorative plaster work.
A large Listen Technologies wireless hearing assist system was also installed allowing visitors with hearing impairments to fully enjoy any event at the venue.


text:
City Without Stars
By Purity Brown
Written by Tim Baker — It seems like a long time since Tim Baker's explosive JFK assassination based debut, Fever City, hit the shelves in April 2016. Fever City was a recommended read with Crime Fiction Lover and was nominated for equally prestigious awards such as the CWA's…
By Keith Nixon
Written by Sam Hawken — Sam Hawken's The Dead Women of Juarez and Tequila Sunset set the ball rolling for this popular author who takes a look at the perils of life on both sides of the border between Mexico and Texas. We last reviewed Missing in 2014, but…
Keith Nixon: Top five books of 2014
I read far too much, and 2014 has been no exception. As well as going back to old favourites I also like to find new authors too. It's a special feeling when you read a book and immediately connect. And so this year's top five…
Written by Sam Hawken — Jack Searle lives a quiet life in Texas, near the Mexican border. He earns enough to get by as a builder, looking after his stepdaughters Lidia and Marina. Jack's wife died of cancer several years ago. Jack and the girls…
First look: Missing by Sam Hawken
Oh, this is nice. Block foil bullets, rosary beads and handguns. A creepy dia de muertos skull configuration. Silhouettes, hearts and spades, illustrative flourishes and let's not forget that tattoo-style Blackletter typeface for the book's title. Once again Serpent's Tail has done Sam Hawken proud…