//===--- SILGenBuiltin.cpp - SIL generation for builtin call sites  -------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "SpecializedEmitter.h"

#include "ArgumentSource.h"
#include "Cleanup.h"
#include "Initialization.h"
#include "LValue.h"
#include "RValue.h"
#include "Scope.h"
#include "SILGenFunction.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Builtins.h"
#include "swift/AST/DiagnosticsSIL.h"
#include "swift/AST/FileUnit.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Module.h"
#include "swift/AST/ReferenceCounting.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILUndef.h"

using namespace swift;
using namespace Lowering;

/// Break down an expression that's the formal argument expression to
/// a builtin function, returning its individualized arguments.
///
/// Because these are builtin operations, we can make some structural
/// assumptions about the expression used to call them.
static Optional<SmallVector<Expr*, 2>>
decomposeArguments(SILGenFunction &SGF,
                   SILLocation loc,
                   PreparedArguments &&args,
                   unsigned expectedCount) {
  SmallVector<Expr*, 2> result;
  auto sources = std::move(args).getSources();

  if (sources.size() == expectedCount) {
    for (auto &&source : sources)
      result.push_back(std::move(source).asKnownExpr());
    return result;
  }

  SGF.SGM.diagnose(loc, diag::invalid_sil_builtin,
                   "argument to builtin should be a literal tuple");

  return None;
}

static ManagedValue emitBuiltinRetain(SILGenFunction &SGF,
                                      SILLocation loc,
                                      SubstitutionMap substitutions,
                                      ArrayRef<ManagedValue> args,
                                      SGFContext C) {
  // The value was produced at +1; we can produce an unbalanced retain simply by
  // disabling the cleanup. But this would violate ownership semantics. Instead,
  // we must allow for the cleanup and emit a new unmanaged retain value.
  SGF.B.createUnmanagedRetainValue(loc, args[0].getValue(),
                                   SGF.B.getDefaultAtomicity());
  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));    
}

static ManagedValue emitBuiltinRelease(SILGenFunction &SGF,
                                       SILLocation loc,
                                       SubstitutionMap substitutions,
                                       ArrayRef<ManagedValue> args,
                                       SGFContext C) {
  // The value was produced at +1, so to produce an unbalanced
  // release we need to leave the cleanup intact and then do a *second*
  // release.
  SGF.B.createUnmanagedReleaseValue(loc, args[0].getValue(),
                                    SGF.B.getDefaultAtomicity());
  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));    
}

static ManagedValue emitBuiltinAutorelease(SILGenFunction &SGF,
                                           SILLocation loc,
                                           SubstitutionMap substitutions,
                                           ArrayRef<ManagedValue> args,
                                           SGFContext C) {
  SGF.B.createUnmanagedAutoreleaseValue(loc, args[0].getValue(),
                                        SGF.B.getDefaultAtomicity());
  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));    
}

/// Specialized emitter for Builtin.load and Builtin.take.
static ManagedValue emitBuiltinLoadOrTake(SILGenFunction &SGF,
                                          SILLocation loc,
                                          SubstitutionMap substitutions,
                                          ArrayRef<ManagedValue> args,
                                          SGFContext C,
                                          IsTake_t isTake,
                                          bool isStrict,
                                          bool isInvariant) {
  assert(substitutions.getReplacementTypes().size() == 1 &&
         "load should have single substitution");
  assert(args.size() == 1 && "load should have a single argument");
  
  // The substitution gives the type of the load.  This is always a
  // first-class type; there is no way to e.g. produce a @weak load
  // with this builtin.
  auto &rvalueTL = SGF.getTypeLowering(substitutions.getReplacementTypes()[0]);
  SILType loadedType = rvalueTL.getLoweredType();

  // Convert the pointer argument to a SIL address.
  SILValue addr = SGF.B.createPointerToAddress(loc, args[0].getUnmanagedValue(),
                                               loadedType.getAddressType(),
                                               isStrict, isInvariant);
  // Perform the load.
  return SGF.emitLoad(loc, addr, rvalueTL, C, isTake);
}

static ManagedValue emitBuiltinLoad(SILGenFunction &SGF,
                                    SILLocation loc,
                                    SubstitutionMap substitutions,
                                    ArrayRef<ManagedValue> args,
                                    SGFContext C) {
  return emitBuiltinLoadOrTake(SGF, loc, substitutions, args,
                               C, IsNotTake,
                               /*isStrict*/ true, /*isInvariant*/ false);
}

static ManagedValue emitBuiltinLoadRaw(SILGenFunction &SGF,
                                       SILLocation loc,
                                       SubstitutionMap substitutions,
                                       ArrayRef<ManagedValue> args,
                                       SGFContext C) {
  return emitBuiltinLoadOrTake(SGF, loc, substitutions, args,
                               C, IsNotTake,
                               /*isStrict*/ false, /*isInvariant*/ false);
}

static ManagedValue emitBuiltinLoadInvariant(SILGenFunction &SGF,
                                             SILLocation loc,
                                             SubstitutionMap substitutions,
                                             ArrayRef<ManagedValue> args,
                                             SGFContext C) {
  return emitBuiltinLoadOrTake(SGF, loc, substitutions, args,
                               C, IsNotTake,
                               /*isStrict*/ false, /*isInvariant*/ true);
}

static ManagedValue emitBuiltinTake(SILGenFunction &SGF,
                                    SILLocation loc,
                                    SubstitutionMap substitutions,
                                    ArrayRef<ManagedValue> args,
                                    SGFContext C) {
  return emitBuiltinLoadOrTake(SGF, loc, substitutions, args,
                               C, IsTake,
                               /*isStrict*/ true, /*isInvariant*/ false);
}

/// Specialized emitter for Builtin.destroy.
static ManagedValue emitBuiltinDestroy(SILGenFunction &SGF,
                                       SILLocation loc,
                                       SubstitutionMap substitutions,
                                       ArrayRef<ManagedValue> args,
                                       SGFContext C) {
  assert(args.size() == 2 && "destroy should have two arguments");
  assert(substitutions.getReplacementTypes().size() == 1 &&
         "destroy should have a single substitution");
  // The substitution determines the type of the thing we're destroying.
  auto &ti = SGF.getTypeLowering(substitutions.getReplacementTypes()[0]);
  
  // Destroy is a no-op for trivial types.
  if (ti.isTrivial())
    return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
  
  SILType destroyType = ti.getLoweredType();

  // Convert the pointer argument to a SIL address.
  SILValue addr =
    SGF.B.createPointerToAddress(loc, args[1].getUnmanagedValue(),
                                 destroyType.getAddressType(),
                                 /*isStrict*/ true,
                                 /*isInvariant*/ false);
  
  // Destroy the value indirectly. Canonicalization will promote to loads
  // and releases if appropriate.
  SGF.B.createDestroyAddr(loc, addr);
  
  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}

static ManagedValue emitBuiltinAssign(SILGenFunction &SGF,
                                      SILLocation loc,
                                      SubstitutionMap substitutions,
                                      ArrayRef<ManagedValue> args,
                                      SGFContext C) {
  assert(args.size() >= 2 && "assign should have two arguments");
  assert(substitutions.getReplacementTypes().size() == 1 &&
         "assign should have a single substitution");

  // The substitution determines the type of the thing we're destroying.
  CanType assignFormalType =
    substitutions.getReplacementTypes()[0]->getCanonicalType();
  SILType assignType = SGF.getLoweredType(assignFormalType);
  
  // Convert the destination pointer argument to a SIL address.
  SILValue addr = SGF.B.createPointerToAddress(loc,
                                               args.back().getUnmanagedValue(),
                                               assignType.getAddressType(),
                                               /*isStrict*/ true,
                                               /*isInvariant*/ false);
  
  // Build the value to be assigned, reconstructing tuples if needed.
  auto src = RValue(SGF, args.slice(0, args.size() - 1), assignFormalType);
  
  std::move(src).ensurePlusOne(SGF, loc).assignInto(SGF, loc, addr);

  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}

/// Emit Builtin.initialize by evaluating the operand directly into
/// the address.
static ManagedValue emitBuiltinInit(SILGenFunction &SGF,
                                    SILLocation loc,
                                    SubstitutionMap substitutions,
                                    PreparedArguments &&preparedArgs,
                                    SGFContext C) {
  auto argsOrError = decomposeArguments(SGF, loc, std::move(preparedArgs), 2);
  if (!argsOrError)
    return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));

  auto args = *argsOrError;

  CanType formalType =
    substitutions.getReplacementTypes()[0]->getCanonicalType();
  auto &formalTL = SGF.getTypeLowering(formalType);

  SILValue addr = SGF.emitRValueAsSingleValue(args[1]).getUnmanagedValue();
  addr = SGF.B.createPointerToAddress(
    loc, addr, formalTL.getLoweredType().getAddressType(),
    /*isStrict*/ true,
    /*isInvariant*/ false);

  TemporaryInitialization init(addr, CleanupHandle::invalid());
  SGF.emitExprInto(args[0], &init);

  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}

/// Specialized emitter for Builtin.fixLifetime.
static ManagedValue emitBuiltinFixLifetime(SILGenFunction &SGF,
                                           SILLocation loc,
                                           SubstitutionMap substitutions,
                                           ArrayRef<ManagedValue> args,
                                           SGFContext C) {
  for (auto arg : args) {
    SGF.B.createFixLifetime(loc, arg.getValue());
  }
  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}

static ManagedValue emitCastToReferenceType(SILGenFunction &SGF,
                                            SILLocation loc,
                                            SubstitutionMap substitutions,
                                            ArrayRef<ManagedValue> args,
                                            SGFContext C,
                                            SILType objPointerType) {
  assert(args.size() == 1 && "cast should have a single argument");
  assert(substitutions.getReplacementTypes().size() == 1 &&
         "cast should have a type substitution");
  
  // Bail if the source type is not a class reference of some kind.
  Type argTy = substitutions.getReplacementTypes()[0];
  if (!argTy->mayHaveSuperclass() && !argTy->isClassExistentialType()) {
    SGF.SGM.diagnose(loc, diag::invalid_sil_builtin,
                     "castToNativeObject source must be a class");
    return SGF.emitUndef(objPointerType);
  }

  // Grab the argument.
  ManagedValue arg = args[0];

  // If the argument is existential, open it.
  if (argTy->isClassExistentialType()) {
    auto openedTy = OpenedArchetypeType::get(argTy);
    SILType loweredOpenedTy = SGF.getLoweredLoadableType(openedTy);
    arg = SGF.B.createOpenExistentialRef(loc, arg, loweredOpenedTy);
  }

  // Return the cast result.
  return SGF.B.createUncheckedRefCast(loc, arg, objPointerType);
}

/// Specialized emitter for Builtin.unsafeCastToNativeObject.
static ManagedValue emitBuiltinUnsafeCastToNativeObject(SILGenFunction &SGF,
                                         SILLocation loc,
                                         SubstitutionMap substitutions,
                                         ArrayRef<ManagedValue> args,
                                         SGFContext C) {
  return emitCastToReferenceType(SGF, loc, substitutions, args, C,
                        SILType::getNativeObjectType(SGF.F.getASTContext()));
}

/// Specialized emitter for Builtin.castToNativeObject.
static ManagedValue emitBuiltinCastToNativeObject(SILGenFunction &SGF,
                                         SILLocation loc,
                                         SubstitutionMap substitutions,
                                         ArrayRef<ManagedValue> args,
                                         SGFContext C) {
  auto ty = args[0].getType().getASTType();
  (void)ty;
  assert(ty->getReferenceCounting() == ReferenceCounting::Native &&
         "Can only cast types that use native reference counting to native "
         "object");
  return emitBuiltinUnsafeCastToNativeObject(SGF, loc, substitutions,
                                             args, C);
}


static ManagedValue emitCastFromReferenceType(SILGenFunction &SGF,
                                         SILLocation loc,
                                         SubstitutionMap substitutions,
                                         ArrayRef<ManagedValue> args,
                                         SGFContext C) {
  assert(args.size() == 1 && "cast should have a single argument");
  assert(substitutions.getReplacementTypes().size() == 1 &&
         "cast should have a single substitution");

  // The substitution determines the destination type.
  SILType destType =
    SGF.getLoweredType(substitutions.getReplacementTypes()[0]);
  
  // Bail if the source type is not a class reference of some kind.
  if (!substitutions.getReplacementTypes()[0]->isBridgeableObjectType()
      || !destType.isObject()) {
    SGF.SGM.diagnose(loc, diag::invalid_sil_builtin,
                     "castFromNativeObject dest must be an object type");
    // Recover by propagating an undef result.
    return SGF.emitUndef(destType);
  }

  return SGF.B.createUncheckedRefCast(loc, args[0], destType);
}

/// Specialized emitter for Builtin.castFromNativeObject.
static ManagedValue emitBuiltinCastFromNativeObject(SILGenFunction &SGF,
                                         SILLocation loc,
                                         SubstitutionMap substitutions,
                                         ArrayRef<ManagedValue> args,
                                         SGFContext C) {
  return emitCastFromReferenceType(SGF, loc, substitutions, args, C);
}

/// Specialized emitter for Builtin.bridgeToRawPointer.
static ManagedValue emitBuiltinBridgeToRawPointer(SILGenFunction &SGF,
                                        SILLocation loc,
                                        SubstitutionMap substitutions,
                                        ArrayRef<ManagedValue> args,
                                        SGFContext C) {
  assert(args.size() == 1 && "bridge should have a single argument");
  
  // Take the reference type argument and cast it to RawPointer.
  // RawPointers do not have ownership semantics, so the cleanup on the
  // argument remains.
  SILType rawPointerType = SILType::getRawPointerType(SGF.F.getASTContext());
  SILValue result = SGF.B.createRefToRawPointer(loc, args[0].getValue(),
                                                rawPointerType);
  return ManagedValue::forUnmanaged(result);
}

/// Specialized emitter for Builtin.bridgeFromRawPointer.
static ManagedValue emitBuiltinBridgeFromRawPointer(SILGenFunction &SGF,
                                        SILLocation loc,
                                        SubstitutionMap substitutions,
                                        ArrayRef<ManagedValue> args,
                                        SGFContext C) {
  assert(substitutions.getReplacementTypes().size() == 1 &&
         "bridge should have a single substitution");
  assert(args.size() == 1 && "bridge should have a single argument");
  
  // The substitution determines the destination type.
  // FIXME: Archetype destination type?
  auto &destLowering =
    SGF.getTypeLowering(substitutions.getReplacementTypes()[0]);
  assert(destLowering.isLoadable());
  SILType destType = destLowering.getLoweredType();

  // Take the raw pointer argument and cast it to the destination type.
  SILValue result = SGF.B.createRawPointerToRef(loc, args[0].getUnmanagedValue(),
                                                destType);
  // The result has ownership semantics, so retain it with a cleanup.
  return SGF.emitManagedRetain(loc, result, destLowering);
}

/// Specialized emitter for Builtin.addressof.
static ManagedValue emitBuiltinAddressOf(SILGenFunction &SGF,
                                         SILLocation loc,
                                         SubstitutionMap substitutions,
                                         PreparedArguments &&preparedArgs,
                                         SGFContext C) {
  SILType rawPointerType = SILType::getRawPointerType(SGF.getASTContext());

  auto argsOrError = decomposeArguments(SGF, loc, std::move(preparedArgs), 1);
  if (!argsOrError)
    return SGF.emitUndef(rawPointerType);

  auto argument = (*argsOrError)[0];

  // If the argument is inout, try forming its lvalue. This builtin only works
  // if it's trivially physically projectable.
  auto inout = cast<InOutExpr>(argument->getSemanticsProvidingExpr());
  auto lv = SGF.emitLValue(inout->getSubExpr(), SGFAccessKind::ReadWrite);
  if (!lv.isPhysical() || !lv.isLoadingPure()) {
    SGF.SGM.diagnose(argument->getLoc(), diag::non_physical_addressof);
    return SGF.emitUndef(rawPointerType);
  }
  
  auto addr = SGF.emitAddressOfLValue(argument, std::move(lv))
                 .getLValueAddress();
  
  // Take the address argument and cast it to RawPointer.
  SILValue result = SGF.B.createAddressToPointer(loc, addr,
                                                 rawPointerType);
  return ManagedValue::forUnmanaged(result);
}

/// Specialized emitter for Builtin.addressOfBorrow.
static ManagedValue emitBuiltinAddressOfBorrow(SILGenFunction &SGF,
                                               SILLocation loc,
                                               SubstitutionMap substitutions,
                                               PreparedArguments &&preparedArgs,
                                               SGFContext C) {
  SILType rawPointerType = SILType::getRawPointerType(SGF.getASTContext());

  auto argsOrError = decomposeArguments(SGF, loc, std::move(preparedArgs), 1);
  if (!argsOrError)
    return SGF.emitUndef(rawPointerType);

  auto argument = (*argsOrError)[0];

  SILValue addr;
  // Try to borrow the argument at +0. We only support if it's
  // naturally emitted borrowed in memory.
  auto borrow = SGF.emitRValue(argument, SGFContext::AllowGuaranteedPlusZero)
     .getAsSingleValue(SGF, argument);
  if (!borrow.isPlusZero() || !borrow.getType().isAddress()) {
    SGF.SGM.diagnose(argument->getLoc(), diag::non_borrowed_indirect_addressof);
    return SGF.emitUndef(rawPointerType);
  }
  
  addr = borrow.getValue();
  
  // Take the address argument and cast it to RawPointer.
  SILValue result = SGF.B.createAddressToPointer(loc, addr,
                                                 rawPointerType);
  return ManagedValue::forUnmanaged(result);
}

/// Specialized emitter for Builtin.gepRaw.
static ManagedValue emitBuiltinGepRaw(SILGenFunction &SGF,
                                      SILLocation loc,
                                      SubstitutionMap substitutions,
                                      ArrayRef<ManagedValue> args,
                                      SGFContext C) {
  assert(args.size() == 2 && "gepRaw should be given two arguments");
  
  SILValue offsetPtr = SGF.B.createIndexRawPointer(loc,
                                                 args[0].getUnmanagedValue(),
                                                 args[1].getUnmanagedValue());
  return ManagedValue::forUnmanaged(offsetPtr);
}

/// Specialized emitter for Builtin.gep.
static ManagedValue emitBuiltinGep(SILGenFunction &SGF,
                                   SILLocation loc,
                                   SubstitutionMap substitutions,
                                   ArrayRef<ManagedValue> args,
                                   SGFContext C) {
  assert(substitutions.getReplacementTypes().size() == 1 &&
         "gep should have two substitutions");
  assert(args.size() == 3 && "gep should be given three arguments");

  SILType ElemTy = SGF.getLoweredType(substitutions.getReplacementTypes()[0]);
  SILType RawPtrType = args[0].getUnmanagedValue()->getType();
  SILValue addr = SGF.B.createPointerToAddress(loc,
                                               args[0].getUnmanagedValue(),
                                               ElemTy.getAddressType(),
                                               /*strict*/ true,
                                               /*invariant*/ false);
  addr = SGF.B.createIndexAddr(loc, addr, args[1].getUnmanagedValue());
  addr = SGF.B.createAddressToPointer(loc, addr, RawPtrType);

  return ManagedValue::forUnmanaged(addr);
}

/// Specialized emitter for Builtin.getTailAddr.
static ManagedValue emitBuiltinGetTailAddr(SILGenFunction &SGF,
                                           SILLocation loc,
                                           SubstitutionMap substitutions,
                                           ArrayRef<ManagedValue> args,
                                           SGFContext C) {
  assert(substitutions.getReplacementTypes().size() == 2 &&
         "getTailAddr should have two substitutions");
  assert(args.size() == 4 && "gep should be given four arguments");

  SILType ElemTy = SGF.getLoweredType(substitutions.getReplacementTypes()[0]);
  SILType TailTy = SGF.getLoweredType(substitutions.getReplacementTypes()[1]);
  SILType RawPtrType = args[0].getUnmanagedValue()->getType();
  SILValue addr = SGF.B.createPointerToAddress(loc,
                                               args[0].getUnmanagedValue(),
                                               ElemTy.getAddressType(),
                                               /*strict*/ true,
                                               /*invariant*/ false);
  addr = SGF.B.createTailAddr(loc, addr, args[1].getUnmanagedValue(),
                              TailTy.getAddressType());
  addr = SGF.B.createAddressToPointer(loc, addr, RawPtrType);

  return ManagedValue::forUnmanaged(addr);
}

/// Specialized emitter for Builtin.beginUnpairedModifyAccess.
static ManagedValue emitBuiltinBeginUnpairedModifyAccess(SILGenFunction &SGF,
                                                    SILLocation loc,
                                           SubstitutionMap substitutions,
                                           ArrayRef<ManagedValue> args,
                                           SGFContext C) {
  assert(substitutions.getReplacementTypes().size() == 1 &&
        "Builtin.beginUnpairedModifyAccess should have one substitution");
  assert(args.size() == 3 &&
         "beginUnpairedModifyAccess should be given three arguments");

  SILType elemTy = SGF.getLoweredType(substitutions.getReplacementTypes()[0]);
  SILValue addr = SGF.B.createPointerToAddress(loc,
                                               args[0].getUnmanagedValue(),
                                               elemTy.getAddressType(),
                                               /*strict*/ true,
                                               /*invariant*/ false);

  SILType valueBufferTy =
      SGF.getLoweredType(SGF.getASTContext().TheUnsafeValueBufferType);

  SILValue buffer =
    SGF.B.createPointerToAddress(loc, args[1].getUnmanagedValue(),
                                 valueBufferTy.getAddressType(),
                                 /*strict*/ true,
                                 /*invariant*/ false);
  SGF.B.createBeginUnpairedAccess(loc, addr, buffer, SILAccessKind::Modify,
                                  SILAccessEnforcement::Dynamic,
                                  /*noNestedConflict*/ false,
                                  /*fromBuiltin*/ true);

  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}

/// Specialized emitter for Builtin.performInstantaneousReadAccess
static ManagedValue emitBuiltinPerformInstantaneousReadAccess(
  SILGenFunction &SGF, SILLocation loc, SubstitutionMap substitutions,
  ArrayRef<ManagedValue> args, SGFContext C) {

  assert(substitutions.getReplacementTypes().size() == 1 &&
         "Builtin.performInstantaneousReadAccess should have one substitution");
  assert(args.size() == 2 &&
         "Builtin.performInstantaneousReadAccess should be given "
         "two arguments");

  SILType elemTy = SGF.getLoweredType(substitutions.getReplacementTypes()[0]);
  SILValue addr = SGF.B.createPointerToAddress(loc,
                                               args[0].getUnmanagedValue(),
                                               elemTy.getAddressType(),
                                               /*strict*/ true,
                                               /*invariant*/ false);

  SILType valueBufferTy =
    SGF.getLoweredType(SGF.getASTContext().TheUnsafeValueBufferType);
  SILValue unusedBuffer = SGF.emitTemporaryAllocation(loc, valueBufferTy);

  // Begin an "unscoped" read access. No nested conflict is possible because
  // the compiler should generate the actual read for the KeyPath expression
  // immediately after the call to this builtin, which forms the address of
  // that real access. When noNestedConflict=true, no EndUnpairedAccess should
  // be emitted.
  //
  // Unpaired access is necessary because a BeginAccess/EndAccess pair with no
  // use will be trivially optimized away.
  SGF.B.createBeginUnpairedAccess(loc, addr, unusedBuffer, SILAccessKind::Read,
                                  SILAccessEnforcement::Dynamic,
                                  /*noNestedConflict*/ true,
                                  /*fromBuiltin*/ true);

  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}

/// Specialized emitter for Builtin.endUnpairedAccessModifyAccess.
static ManagedValue emitBuiltinEndUnpairedAccess(SILGenFunction &SGF,
                                                    SILLocation loc,
                                           SubstitutionMap substitutions,
                                           ArrayRef<ManagedValue> args,
                                           SGFContext C) {
  assert(substitutions.empty() &&
        "Builtin.endUnpairedAccess should have no substitutions");
  assert(args.size() == 1 &&
         "endUnpairedAccess should be given one argument");

  SILType valueBufferTy =
      SGF.getLoweredType(SGF.getASTContext().TheUnsafeValueBufferType);

  SILValue buffer = SGF.B.createPointerToAddress(loc,
                                                 args[0].getUnmanagedValue(),
                                                valueBufferTy.getAddressType(),
                                                 /*strict*/ true,
                                                 /*invariant*/ false);
  SGF.B.createEndUnpairedAccess(loc, buffer, SILAccessEnforcement::Dynamic,
                                /*aborted*/ false,
                                /*fromBuiltin*/ true);

  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}

/// Specialized emitter for the legacy Builtin.condfail.
static ManagedValue emitBuiltinLegacyCondFail(SILGenFunction &SGF,
                                              SILLocation loc,
                                              SubstitutionMap substitutions,
                                              ArrayRef<ManagedValue> args,
                                              SGFContext C) {
  assert(args.size() == 1 && "condfail should be given one argument");

  SGF.B.createCondFail(loc, args[0].getUnmanagedValue(),
    "unknown runtime failure");
  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}

/// Specialized emitter for Builtin.castReference.
static ManagedValue
emitBuiltinCastReference(SILGenFunction &SGF,
                         SILLocation loc,
                         SubstitutionMap substitutions,
                         ArrayRef<ManagedValue> args,
                         SGFContext C) {
  assert(args.size() == 1 && "castReference should be given one argument");
  assert(substitutions.getReplacementTypes().size() == 2 &&
         "castReference should have two subs");

  auto fromTy = substitutions.getReplacementTypes()[0];
  auto toTy = substitutions.getReplacementTypes()[1];
  auto &fromTL = SGF.getTypeLowering(fromTy);
  auto &toTL = SGF.getTypeLowering(toTy);
  assert(!fromTL.isTrivial() && !toTL.isTrivial() && "expected ref type");

  auto arg = args[0];

  // TODO: Fix this API.
  if (!fromTL.isAddress() || !toTL.isAddress()) {
    if (SILType::canRefCast(arg.getType(), toTL.getLoweredType(), SGF.SGM.M)) {
      // Create a reference cast, forwarding the cleanup.
      // The cast takes the source reference.
      return SGF.B.createUncheckedRefCast(loc, arg, toTL.getLoweredType());
    }
  }

  // We are either casting between address-only types, or cannot promote to a
  // cast of reference values.
  //
  // If the from/to types are invalid, then use a cast that will fail at
  // runtime. We cannot catch these errors with SIL verification because they
  // may legitimately occur during code specialization on dynamically
  // unreachable paths.
  //
  // TODO: For now, we leave invalid casts in address form so that the runtime
  // will trap. We could emit a noreturn call here instead which would provide
  // more information to the optimizer.
  SILValue srcVal = arg.ensurePlusOne(SGF, loc).forward(SGF);
  SILValue fromAddr;
  if (!fromTL.isAddress()) {
    // Move the loadable value into a "source temp".  Since the source and
    // dest are RC identical, store the reference into the source temp without
    // a retain. The cast will load the reference from the source temp and
    // store it into a dest temp effectively forwarding the cleanup.
    fromAddr = SGF.emitTemporaryAllocation(loc, srcVal->getType());
    fromTL.emitStore(SGF.B, loc, srcVal, fromAddr,
                     StoreOwnershipQualifier::Init);
  } else {
    // The cast loads directly from the source address.
    fromAddr = srcVal;
  }
  // Create a "dest temp" to hold the reference after casting it.
  SILValue toAddr = SGF.emitTemporaryAllocation(loc, toTL.getLoweredType());
  SGF.B.createUncheckedRefCastAddr(loc, fromAddr, fromTy->getCanonicalType(),
                                   toAddr, toTy->getCanonicalType());
  // Forward it along and register a cleanup.
  if (toTL.isAddress())
    return SGF.emitManagedBufferWithCleanup(toAddr);

  // Load the destination value.
  auto result = toTL.emitLoad(SGF.B, loc, toAddr, LoadOwnershipQualifier::Take);
  return SGF.emitManagedRValueWithCleanup(result);
}

/// Specialized emitter for Builtin.reinterpretCast.
static ManagedValue emitBuiltinReinterpretCast(SILGenFunction &SGF,
                                         SILLocation loc,
                                         SubstitutionMap substitutions,
                                         ArrayRef<ManagedValue> args,
                                         SGFContext C) {
  assert(args.size() == 1 && "reinterpretCast should be given one argument");
  assert(substitutions.getReplacementTypes().size() == 2 &&
         "reinterpretCast should have two subs");
  
  auto &fromTL = SGF.getTypeLowering(substitutions.getReplacementTypes()[0]);
  auto &toTL = SGF.getTypeLowering(substitutions.getReplacementTypes()[1]);
  
  // If casting between address types, cast the address.
  if (fromTL.isAddress() || toTL.isAddress()) {
    SILValue fromAddr;

    // If the from value is not an address, move it to a buffer.
    if (!fromTL.isAddress()) {
      fromAddr = SGF.emitTemporaryAllocation(loc, args[0].getValue()->getType());
      fromTL.emitStore(SGF.B, loc, args[0].getValue(), fromAddr,
                       StoreOwnershipQualifier::Init);
    } else {
      fromAddr = args[0].getValue();
    }
    auto toAddr = SGF.B.createUncheckedAddrCast(loc, fromAddr,
                                      toTL.getLoweredType().getAddressType());
    
    // Load and retain the destination value if it's loadable. Leave the cleanup
    // on the original value since we don't know anything about it's type.
    if (!toTL.isAddress()) {
      return SGF.emitManagedLoadCopy(loc, toAddr, toTL);
    }
    // Leave the cleanup on the original value.
    if (toTL.isTrivial())
      return ManagedValue::forUnmanaged(toAddr);

    // Initialize the +1 result buffer without taking the incoming value. The
    // source and destination cleanups will be independent.
    return SGF.B.bufferForExpr(
        loc, toTL.getLoweredType(), toTL, C,
        [&](SILValue bufferAddr) {
          SGF.B.createCopyAddr(loc, toAddr, bufferAddr, IsNotTake,
                               IsInitialization);
        });
  }
  // Create the appropriate bitcast based on the source and dest types.
  ManagedValue in = args[0];

  SILType resultTy = toTL.getLoweredType();
  return SGF.B.createUncheckedBitCast(loc, in, resultTy);
}

/// Specialized emitter for Builtin.castToBridgeObject.
static ManagedValue emitBuiltinCastToBridgeObject(SILGenFunction &SGF,
                                                  SILLocation loc,
                                                  SubstitutionMap subs,
                                                  ArrayRef<ManagedValue> args,
                                                  SGFContext C) {
  assert(args.size() == 2 && "cast should have two arguments");
  assert(subs.getReplacementTypes().size() == 1 &&
         "cast should have a type substitution");
  
  // Take the reference type argument and cast it to BridgeObject.
  SILType objPointerType = SILType::getBridgeObjectType(SGF.F.getASTContext());

  // Bail if the source type is not a class reference of some kind.
  auto sourceType = subs.getReplacementTypes()[0];
  if (!sourceType->mayHaveSuperclass() &&
      !sourceType->isClassExistentialType()) {
    SGF.SGM.diagnose(loc, diag::invalid_sil_builtin,
                     "castToBridgeObject source must be a class");
    return SGF.emitUndef(objPointerType);
  }

  ManagedValue ref = args[0];
  SILValue bits = args[1].getUnmanagedValue();
  
  // If the argument is existential, open it.
  if (sourceType->isClassExistentialType()) {
    auto openedTy = OpenedArchetypeType::get(sourceType);
    SILType loweredOpenedTy = SGF.getLoweredLoadableType(openedTy);
    ref = SGF.B.createOpenExistentialRef(loc, ref, loweredOpenedTy);
  }

  return SGF.B.createRefToBridgeObject(loc, ref, bits);
}

/// Specialized emitter for Builtin.castReferenceFromBridgeObject.
static ManagedValue emitBuiltinCastReferenceFromBridgeObject(
                                                  SILGenFunction &SGF,
                                                  SILLocation loc,
                                                  SubstitutionMap subs,
                                                  ArrayRef<ManagedValue> args,
                                                  SGFContext C) {
  assert(args.size() == 1 && "cast should have one argument");
  assert(subs.getReplacementTypes().size() == 1 &&
         "cast should have a type substitution");

  // The substitution determines the destination type.
  auto destTy = subs.getReplacementTypes()[0];
  SILType destType = SGF.getLoweredType(destTy);
  
  // Bail if the source type is not a class reference of some kind.
  if (!destTy->isBridgeableObjectType() || !destType.isObject()) {
    SGF.SGM.diagnose(loc, diag::invalid_sil_builtin,
                 "castReferenceFromBridgeObject dest must be an object type");
    // Recover by propagating an undef result.
    return SGF.emitUndef(destType);
  }

  return SGF.B.createBridgeObjectToRef(loc, args[0], destType);
}

static ManagedValue emitBuiltinCastBitPatternFromBridgeObject(
                                                  SILGenFunction &SGF,
                                                  SILLocation loc,
                                                  SubstitutionMap subs,
                                                  ArrayRef<ManagedValue> args,
                                                  SGFContext C) {
  assert(args.size() == 1 && "cast should have one argument");
  assert(subs.empty() && "cast should not have subs");

  SILType wordType = SILType::getBuiltinWordType(SGF.getASTContext());
  SILValue result = SGF.B.createBridgeObjectToWord(loc, args[0].getValue(),
                                                   wordType);
  return ManagedValue::forUnmanaged(result);
}

static ManagedValue emitBuiltinClassifyBridgeObject(SILGenFunction &SGF,
                                                    SILLocation loc,
                                                    SubstitutionMap subs,
                                                    ArrayRef<ManagedValue> args,
                                                    SGFContext C) {
  assert(args.size() == 1 && "classify should have one argument");
  assert(subs.empty() && "classify should not have subs");

  SILValue result = SGF.B.createClassifyBridgeObject(loc, args[0].getValue());
  return ManagedValue::forUnmanaged(result);
}

static ManagedValue emitBuiltinValueToBridgeObject(SILGenFunction &SGF,
                                                   SILLocation loc,
                                                   SubstitutionMap subs,
                                                   ArrayRef<ManagedValue> args,
                                                   SGFContext C) {
  assert(args.size() == 1 && "ValueToBridgeObject should have one argument");
  assert(subs.getReplacementTypes().size() == 1 &&
         "ValueToBridgeObject should have one sub");

  Type argTy = subs.getReplacementTypes()[0];
  if (!argTy->is<BuiltinIntegerType>()) {
    SGF.SGM.diagnose(loc, diag::invalid_sil_builtin,
                     "argument to builtin should be a builtin integer");
    SILType objPointerType = SILType::getBridgeObjectType(SGF.F.getASTContext());
    return SGF.emitUndef(objPointerType);
  }

  SILValue result = SGF.B.createValueToBridgeObject(loc, args[0].getValue());
  return SGF.emitManagedRetain(loc, result);
}

// This should only accept as an operand type single-refcounted-pointer types,
// class existentials, or single-payload enums (optional). Type checking must be
// deferred until IRGen so Builtin.isUnique can be called from a transparent
// generic wrapper (we can only type check after specialization).
static ManagedValue emitBuiltinIsUnique(SILGenFunction &SGF,
                                        SILLocation loc,
                                        SubstitutionMap subs,
                                        ArrayRef<ManagedValue> args,
                                        SGFContext C) {

  assert(subs.getReplacementTypes().size() == 1 &&
         "isUnique should have a single substitution");
  assert(args.size() == 1 && "isUnique should have a single argument");
  assert((args[0].getType().isAddress() && !args[0].hasCleanup()) &&
         "Builtin.isUnique takes an address.");

  return ManagedValue::forUnmanaged(
    SGF.B.createIsUnique(loc, args[0].getValue()));
}

// This force-casts the incoming address to NativeObject assuming the caller has
// performed all necessary checks. For example, this may directly cast a
// single-payload enum to a NativeObject reference.
static ManagedValue
emitBuiltinIsUnique_native(SILGenFunction &SGF,
                           SILLocation loc,
                           SubstitutionMap subs,
                           ArrayRef<ManagedValue> args,
                           SGFContext C) {

  assert(subs.getReplacementTypes().size() == 1 &&
         "isUnique_native should have one sub.");
  assert(args.size() == 1 && "isUnique_native should have one arg.");

  auto ToType =
    SILType::getNativeObjectType(SGF.getASTContext()).getAddressType();
  auto toAddr = SGF.B.createUncheckedAddrCast(loc, args[0].getValue(), ToType);
  SILValue result = SGF.B.createIsUnique(loc, toAddr);
  return ManagedValue::forUnmanaged(result);
}

static ManagedValue
emitBuiltinBeginCOWMutation(SILGenFunction &SGF,
                            SILLocation loc,
                            SubstitutionMap subs,
                            ArrayRef<ManagedValue> args,
                            SGFContext C) {

  assert(subs.getReplacementTypes().size() == 1 &&
         "BeginCOWMutation should have one sub.");
  assert(args.size() == 1 && "isUnique_native should have one arg.");

  SILValue refAddr = args[0].getValue();
  auto *ref = SGF.B.createLoad(loc, refAddr, LoadOwnershipQualifier::Take);
  BeginCOWMutationInst *beginCOW = SGF.B.createBeginCOWMutation(loc, ref, /*isNative*/ false);
  SGF.B.createStore(loc, beginCOW->getBufferResult(), refAddr, StoreOwnershipQualifier::Init);
  return ManagedValue::forUnmanaged(beginCOW->getUniquenessResult());
}

static ManagedValue
emitBuiltinBeginCOWMutation_native(SILGenFunction &SGF,
                            SILLocation loc,
                            SubstitutionMap subs,
                            ArrayRef<ManagedValue> args,
                            SGFContext C) {

  assert(subs.getReplacementTypes().size() == 1 &&
         "BeginCOWMutation should have one sub.");
  assert(args.size() == 1 && "isUnique_native should have one arg.");

  SILValue refAddr = args[0].getValue();
  auto *ref = SGF.B.createLoad(loc, refAddr, LoadOwnershipQualifier::Take);
  BeginCOWMutationInst *beginCOW = SGF.B.createBeginCOWMutation(loc, ref, /*isNative*/ true);
  SGF.B.createStore(loc, beginCOW->getBufferResult(), refAddr, StoreOwnershipQualifier::Init);
  return ManagedValue::forUnmanaged(beginCOW->getUniquenessResult());
}

static ManagedValue
emitBuiltinEndCOWMutation(SILGenFunction &SGF,
                           SILLocation loc,
                           SubstitutionMap subs,
                           ArrayRef<ManagedValue> args,
                           SGFContext C) {

  assert(subs.getReplacementTypes().size() == 1 &&
         "EndCOWMutation should have one sub.");
  assert(args.size() == 1 && "isUnique_native should have one arg.");

  SILValue refAddr = args[0].getValue();
  auto ref = SGF.B.createLoad(loc, refAddr, LoadOwnershipQualifier::Take);
  auto endRef = SGF.B.createEndCOWMutation(loc, ref);
  SGF.B.createStore(loc, endRef, refAddr, StoreOwnershipQualifier::Init);
  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}

static ManagedValue emitBuiltinBindMemory(SILGenFunction &SGF,
                                          SILLocation loc,
                                          SubstitutionMap subs,
                                          ArrayRef<ManagedValue> args,
                                          SGFContext C) {
  assert(subs.getReplacementTypes().size() == 1 && "bindMemory should have a single substitution");
  assert(args.size() == 3 && "bindMemory should have three argument");

  // The substitution determines the element type for bound memory.
  CanType boundFormalType = subs.getReplacementTypes()[0]->getCanonicalType();
  SILType boundType = SGF.getLoweredType(boundFormalType);

  SGF.B.createBindMemory(loc, args[0].getValue(),
                         args[1].getValue(), boundType);

  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}

static ManagedValue emitBuiltinAllocWithTailElems(SILGenFunction &SGF,
                                              SILLocation loc,
                                              SubstitutionMap subs,
                                              ArrayRef<ManagedValue> args,
                                              SGFContext C) {
  unsigned NumTailTypes = subs.getReplacementTypes().size() - 1;
  assert(args.size() == NumTailTypes * 2 + 1 &&
         "wrong number of substitutions for allocWithTailElems");

  // The substitution determines the element type for bound memory.
  auto replacementTypes = subs.getReplacementTypes();
  SILType RefType = SGF.getLoweredType(replacementTypes[0]->
                                  getCanonicalType()).getObjectType();

  SmallVector<ManagedValue, 4> Counts;
  SmallVector<SILType, 4> ElemTypes;
  for (unsigned Idx = 0; Idx < NumTailTypes; ++Idx) {
    Counts.push_back(args[Idx * 2 + 1]);
    ElemTypes.push_back(SGF.getLoweredType(replacementTypes[Idx+1]->
                                          getCanonicalType()).getObjectType());
  }
  ManagedValue Metatype = args[0];
  if (isa<MetatypeInst>(Metatype)) {
    auto InstanceType =
      Metatype.getType().castTo<MetatypeType>().getInstanceType();
    assert(InstanceType == RefType.getASTType() &&
           "substituted type does not match operand metatype");
    (void) InstanceType;
    return SGF.B.createAllocRef(loc, RefType, false, false,
                                ElemTypes, Counts);
  } else {
    return SGF.B.createAllocRefDynamic(loc, Metatype, RefType, false,
                                       ElemTypes, Counts);
  }
}

static ManagedValue emitBuiltinProjectTailElems(SILGenFunction &SGF,
                                                SILLocation loc,
                                                SubstitutionMap subs,
                                                ArrayRef<ManagedValue> args,
                                                SGFContext C) {
  assert(subs.getReplacementTypes().size() == 2 &&
         "allocWithTailElems should have two substitutions");
  assert(args.size() == 2 &&
         "allocWithTailElems should have three arguments");

  // The substitution determines the element type for bound memory.
  SILType ElemType = SGF.getLoweredType(subs.getReplacementTypes()[1]->
                                        getCanonicalType()).getObjectType();

  SILValue result = SGF.B.createRefTailAddr(
      loc, args[0].borrow(SGF, loc).getValue(), ElemType.getAddressType());
  SILType rawPointerType = SILType::getRawPointerType(SGF.F.getASTContext());
  result = SGF.B.createAddressToPointer(loc, result, rawPointerType);
  return ManagedValue::forUnmanaged(result);
}

/// Specialized emitter for type traits.
template<TypeTraitResult (TypeBase::*Trait)(),
         BuiltinValueKind Kind>
static ManagedValue emitBuiltinTypeTrait(SILGenFunction &SGF,
                                        SILLocation loc,
                                        SubstitutionMap substitutions,
                                        ArrayRef<ManagedValue> args,
                                        SGFContext C) {
  assert(substitutions.getReplacementTypes().size() == 1
         && "type trait should take a single type parameter");
  assert(args.size() == 1
         && "type trait should take a single argument");
  
  unsigned result;
  
  auto traitTy = substitutions.getReplacementTypes()[0]->getCanonicalType();
  
  switch ((traitTy.getPointer()->*Trait)()) {
  // If the type obviously has or lacks the trait, emit a constant result.
  case TypeTraitResult::IsNot:
    result = 0;
    break;
  case TypeTraitResult::Is:
    result = 1;
    break;
      
  // If not, emit the builtin call normally. Specialization may be able to
  // eliminate it later, or we'll lower it away at IRGen time.
  case TypeTraitResult::CanBe: {
    auto &C = SGF.getASTContext();
    auto int8Ty = BuiltinIntegerType::get(8, C)->getCanonicalType();
    auto apply = SGF.B.createBuiltin(loc,
                                     C.getIdentifier(getBuiltinName(Kind)),
                                     SILType::getPrimitiveObjectType(int8Ty),
                                     substitutions, args[0].getValue());
    
    return ManagedValue::forUnmanaged(apply);
  }
  }
  
  // Produce the result as an integer literal constant.
  auto val = SGF.B.createIntegerLiteral(
      loc, SILType::getBuiltinIntegerType(8, SGF.getASTContext()),
      (uintmax_t)result);
  return ManagedValue::forUnmanaged(val);
}

static ManagedValue emitBuiltinAutoDiffApplyDerivativeFunction(
    AutoDiffDerivativeFunctionKind kind, unsigned arity,
    bool throws, SILGenFunction &SGF, SILLocation loc,
    SubstitutionMap substitutions, ArrayRef<ManagedValue> args, SGFContext C) {
  // FIXME(SR-11853): Support throwing functions.
  assert(!throws && "Throwing functions are not yet supported");

  auto origFnVal = args[0].getValue();
  SmallVector<SILValue, 2> origFnArgVals;
  for (auto& arg : args.drop_front(1))
    origFnArgVals.push_back(arg.getValue());

  auto origFnType = origFnVal->getType().castTo<SILFunctionType>();
  auto origFnUnsubstType = origFnType->getUnsubstitutedType(SGF.getModule());
  if (origFnType != origFnUnsubstType) {
    origFnVal = SGF.B.createConvertFunction(
        loc, origFnVal, SILType::getPrimitiveObjectType(origFnUnsubstType),
        /*withoutActuallyEscaping*/ false);
  }

  // Get the derivative function.
  SILValue derivativeFn = SGF.B.createDifferentiableFunctionExtract(
      loc, kind, origFnVal);
  auto derivativeFnType = derivativeFn->getType().castTo<SILFunctionType>();
  assert(derivativeFnType->getNumResults() == 2);
  assert(derivativeFnType->getNumParameters() == origFnArgVals.size());

  auto derivativeFnUnsubstType =
      derivativeFnType->getUnsubstitutedType(SGF.getModule());
  if (derivativeFnType != derivativeFnUnsubstType) {
    derivativeFn = SGF.B.createConvertFunction(
        loc, derivativeFn,
        SILType::getPrimitiveObjectType(derivativeFnUnsubstType),
        /*withoutActuallyEscaping*/ false);
  }

  // We don't need to destroy the original function or retain the
  // `derivativeFn`, because they are trivial (because they are @noescape).
  assert(origFnVal->getType().isTrivial(SGF.F));
  assert(derivativeFn->getType().isTrivial(SGF.F));

  // Do the apply for the indirect result case.
  if (derivativeFnType->hasIndirectFormalResults()) {
    auto indResBuffer = SGF.getBufferForExprResult(
        loc, derivativeFnType->getAllResultsInterfaceType(), C);
    SmallVector<SILValue, 3> applyArgs;
    applyArgs.push_back(SGF.B.createTupleElementAddr(loc, indResBuffer, 0));
    for (auto origFnArgVal : origFnArgVals)
      applyArgs.push_back(origFnArgVal);
    auto differential = SGF.B.createApply(loc, derivativeFn, SubstitutionMap(),
                                          applyArgs, /*isNonThrowing*/ false);

    derivativeFn = SILValue();

    SGF.B.createStore(loc, differential,
                      SGF.B.createTupleElementAddr(loc, indResBuffer, 1),
                      StoreOwnershipQualifier::Init);
    return SGF.manageBufferForExprResult(
        indResBuffer, SGF.getTypeLowering(indResBuffer->getType()), C);
  }

  // Do the apply for the direct result case.
  auto resultTuple = SGF.B.createApply(
      loc, derivativeFn, SubstitutionMap(), origFnArgVals,
      /*isNonThrowing*/ false);

  derivativeFn = SILValue();

  return SGF.emitManagedRValueWithCleanup(resultTuple);
}

static ManagedValue emitBuiltinAutoDiffApplyTransposeFunction(
    unsigned arity, bool throws, SILGenFunction &SGF, SILLocation loc,
    SubstitutionMap substitutions, ArrayRef<ManagedValue> args, SGFContext C) {
  // FIXME(SR-11853): Support throwing functions.
  assert(!throws && "Throwing functions are not yet supported");

  auto origFnVal = args.front().getValue();
  SmallVector<SILValue, 2> origFnArgVals;
  for (auto &arg : args.drop_front(1))
    origFnArgVals.push_back(arg.getValue());

  // Get the transpose function.
  SILValue transposeFn = SGF.B.createLinearFunctionExtract(
      loc, LinearDifferentiableFunctionTypeComponent::Transpose, origFnVal);
  auto transposeFnType = transposeFn->getType().castTo<SILFunctionType>();
  auto transposeFnUnsubstType =
      transposeFnType->getUnsubstitutedType(SGF.getModule());
  if (transposeFnType != transposeFnUnsubstType) {
    transposeFn = SGF.B.createConvertFunction(
        loc, transposeFn,
        SILType::getPrimitiveObjectType(transposeFnUnsubstType),
        /*withoutActuallyEscaping*/ false);
    transposeFnType = transposeFn->getType().castTo<SILFunctionType>();
  }

  SmallVector<SILValue, 2> applyArgs;
  if (transposeFnType->hasIndirectFormalResults())
    applyArgs.push_back(
        SGF.getBufferForExprResult(
            loc, transposeFnType->getAllResultsInterfaceType(), C));
  for (auto paramArg : args.drop_front()) {
    applyArgs.push_back(paramArg.getValue());
  }
  auto *apply = SGF.B.createApply(
      loc, transposeFn, SubstitutionMap(), applyArgs);
  if (transposeFnType->hasIndirectFormalResults()) {
    auto resultAddress = applyArgs.front();
    AbstractionPattern pattern(
        SGF.F.getLoweredFunctionType()->getSubstGenericSignature(),
        resultAddress->getType().getASTType());
    auto &tl =
        SGF.getTypeLowering(pattern, resultAddress->getType().getASTType());
    return SGF.manageBufferForExprResult(resultAddress, tl, C);
  } else {
    return SGF.emitManagedRValueWithCleanup(apply);
  }
}

static ManagedValue emitBuiltinApplyDerivative(
    SILGenFunction &SGF, SILLocation loc, SubstitutionMap substitutions,
    ArrayRef<ManagedValue> args, SGFContext C) {
  auto *callExpr = loc.castToASTNode<CallExpr>();
  auto builtinDecl = cast<FuncDecl>(cast<DeclRefExpr>(
      cast<DotSyntaxBaseIgnoredExpr>(callExpr->getDirectCallee())->getRHS())
          ->getDecl());
  const auto builtinName = builtinDecl->getBaseIdentifier().str();
  AutoDiffDerivativeFunctionKind kind;
  unsigned arity;
  bool throws;
  auto successfullyParsed = autodiff::getBuiltinApplyDerivativeConfig(
      builtinName, kind, arity, throws);
  assert(successfullyParsed);
  return emitBuiltinAutoDiffApplyDerivativeFunction(
      kind, arity, throws, SGF, loc, substitutions, args, C);
}

static ManagedValue emitBuiltinApplyTranspose(
    SILGenFunction &SGF, SILLocation loc, SubstitutionMap substitutions,
    ArrayRef<ManagedValue> args, SGFContext C) {
  auto *callExpr = loc.castToASTNode<CallExpr>();
  auto builtinDecl = cast<FuncDecl>(cast<DeclRefExpr>(
      cast<DotSyntaxBaseIgnoredExpr>(callExpr->getDirectCallee())->getRHS())
          ->getDecl());
  const auto builtinName = builtinDecl->getBaseIdentifier().str();
  unsigned arity;
  bool throws;
  auto successfullyParsed = autodiff::getBuiltinApplyTransposeConfig(
      builtinName, arity, throws);
  assert(successfullyParsed);
  return emitBuiltinAutoDiffApplyTransposeFunction(
      arity, throws, SGF, loc, substitutions, args, C);
}

static ManagedValue emitBuiltinDifferentiableFunction(
    SILGenFunction &SGF, SILLocation loc, SubstitutionMap substitutions,
    ArrayRef<ManagedValue> args, SGFContext C) {
  assert(args.size() == 3);
  auto origFn = args.front();
  auto origType = origFn.getType().castTo<SILFunctionType>();
  auto numResults =
      origType->getNumResults() + origType->getNumIndirectMutatingParameters();
  auto diffFn = SGF.B.createDifferentiableFunction(
      loc,
      IndexSubset::getDefault(SGF.getASTContext(), origType->getNumParameters(),
                              /*includeAll*/ true),
      IndexSubset::getDefault(SGF.getASTContext(), numResults,
                              /*includeAll*/ true),
      origFn.forward(SGF),
      std::make_pair(args[1].forward(SGF), args[2].forward(SGF)));
  return SGF.emitManagedRValueWithCleanup(diffFn);
}

static ManagedValue emitBuiltinLinearFunction(
    SILGenFunction &SGF, SILLocation loc, SubstitutionMap substitutions,
    ArrayRef<ManagedValue> args, SGFContext C) {
  assert(args.size() == 2);
  auto origFn = args.front();
  auto origType = origFn.getType().castTo<SILFunctionType>();
  auto linearFn = SGF.B.createLinearFunction(
      loc,
      IndexSubset::getDefault(
          SGF.getASTContext(),
          origType->getNumParameters(),
          /*includeAll*/ true),
      origFn.forward(SGF), args[1].forward(SGF));
  return SGF.emitManagedRValueWithCleanup(linearFn);
}

/// Emit SIL for the named builtin: globalStringTablePointer. Unlike the default
/// ownership convention for named builtins, which is to take (non-trivial)
/// arguments as Owned, this builtin accepts owned as well as guaranteed
/// arguments, and hence doesn't require the arguments to be at +1. Therefore,
/// this builtin is emitted specially.
static ManagedValue
emitBuiltinGlobalStringTablePointer(SILGenFunction &SGF, SILLocation loc,
                                    SubstitutionMap subs,
                                    ArrayRef<ManagedValue> args, SGFContext C) {
  assert(args.size() == 1);

  SILValue argValue = args[0].getValue();
  auto &astContext = SGF.getASTContext();
  Identifier builtinId = astContext.getIdentifier(
      getBuiltinName(BuiltinValueKind::GlobalStringTablePointer));

  auto resultVal = SGF.B.createBuiltin(loc, builtinId,
                                       SILType::getRawPointerType(astContext),
                                       subs, ArrayRef<SILValue>(argValue));
  return SGF.emitManagedRValueWithCleanup(resultVal);
}

/// Emit SIL for the named builtin:
/// convertStrongToUnownedUnsafe. Unlike the default ownership
/// convention for named builtins, which is to take (non-trivial)
/// arguments as Owned, this builtin accepts owned as well as
/// guaranteed arguments, and hence doesn't require the arguments to
/// be at +1. Therefore, this builtin is emitted specially.
///
/// We assume our convention is (T, @inout @unmanaged T) -> ()
static ManagedValue emitBuiltinConvertStrongToUnownedUnsafe(
    SILGenFunction &SGF, SILLocation loc, SubstitutionMap subs,
    PreparedArguments &&preparedArgs, SGFContext C) {
  auto argsOrError = decomposeArguments(SGF, loc, std::move(preparedArgs), 2);
  if (!argsOrError)
    return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));

  auto args = *argsOrError;

  // First get our object at +0 if we can.
  auto object = SGF.emitRValue(args[0], SGFContext::AllowGuaranteedPlusZero)
                    .getAsSingleValue(SGF, args[0]);

  // Borrow it and get the value.
  SILValue objectSrcValue = object.borrow(SGF, loc).getValue();

  // Then create our inout.
  auto inout = cast<InOutExpr>(args[1]->getSemanticsProvidingExpr());
  auto lv =
      SGF.emitLValue(inout->getSubExpr(), SGFAccessKind::BorrowedAddressRead);
  lv.unsafelyDropLastComponent(PathComponent::OwnershipKind);
  if (!lv.isPhysical() || !lv.isLoadingPure()) {
    llvm::report_fatal_error("Builtin.convertStrongToUnownedUnsafe passed "
                             "non-physical, non-pure lvalue as 2nd arg");
  }

  SILValue inoutDest =
      SGF.emitAddressOfLValue(args[1], std::move(lv)).getLValueAddress();
  SILType destType = inoutDest->getType().getObjectType();

  // Make sure our types match up as we expect.
  if (objectSrcValue->getType() !=
      destType.getReferenceStorageReferentType().getObjectType()) {
    llvm::errs()
        << "Invalid usage of Builtin.convertStrongToUnownedUnsafe. lhsType "
           "must be T and rhsType must be inout unsafe(unowned) T"
        << "lhsType: " << objectSrcValue->getType() << "\n"
        << "rhsType: " << inoutDest->getType() << "\n";
    llvm::report_fatal_error("standard fatal error msg");
  }

  SILType unmanagedOptType = objectSrcValue->getType().getReferenceStorageType(
      SGF.getASTContext(), ReferenceOwnership::Unmanaged);
  SILValue unownedObjectSrcValue = SGF.B.createRefToUnmanaged(
      loc, objectSrcValue, unmanagedOptType.getObjectType());
  SGF.B.emitStoreValueOperation(loc, unownedObjectSrcValue, inoutDest,
                                StoreOwnershipQualifier::Trivial);
  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}

/// Emit SIL for the named builtin: convertUnownedUnsafeToGuaranteed.
///
/// We assume our convention is:
///
/// <BaseT, T> (BaseT, @inout @unowned(unsafe) T) -> @guaranteed T
///
static ManagedValue emitBuiltinConvertUnownedUnsafeToGuaranteed(
    SILGenFunction &SGF, SILLocation loc, SubstitutionMap subs,
    PreparedArguments &&preparedArgs, SGFContext C) {
  auto argsOrError = decomposeArguments(SGF, loc, std::move(preparedArgs), 2);
  if (!argsOrError)
    return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));

  auto args = *argsOrError;

  // First grab our base and borrow it.
  auto baseMV =
      SGF.emitRValueAsSingleValue(args[0], SGFContext::AllowGuaranteedPlusZero)
          .borrow(SGF, args[0]);

  // Then grab our LValue operand, drop the last ownership component.
  auto srcLV = SGF.emitLValue(args[1]->getSemanticsProvidingExpr(),
                              SGFAccessKind::BorrowedAddressRead);
  srcLV.unsafelyDropLastComponent(PathComponent::OwnershipKind);
  if (!srcLV.isPhysical() || !srcLV.isLoadingPure()) {
    llvm::report_fatal_error("Builtin.convertUnownedUnsafeToGuaranteed passed "
                             "non-physical, non-pure lvalue as 2nd arg");
  }

  // Grab our address and load our unmanaged and convert it to a ref.
  SILValue srcAddr =
      SGF.emitAddressOfLValue(args[1], std::move(srcLV)).getLValueAddress();
  SILValue srcValue = SGF.B.emitLoadValueOperation(
      loc, srcAddr, LoadOwnershipQualifier::Trivial);
  SILValue unownedNonTrivialRef = SGF.B.createUnmanagedToRef(
      loc, srcValue, srcValue->getType().getReferenceStorageReferentType());

  // Now convert our unownedNonTrivialRef from unowned ownership to guaranteed
  // ownership and create a cleanup for it.
  SILValue guaranteedNonTrivialRef = SGF.B.createUncheckedOwnershipConversion(
      loc, unownedNonTrivialRef, ValueOwnershipKind::Guaranteed);
  auto guaranteedNonTrivialRefMV =
      SGF.emitManagedBorrowedRValueWithCleanup(guaranteedNonTrivialRef);
  // Now create a mark dependence on our base and return the result.
  return SGF.B.createMarkDependence(loc, guaranteedNonTrivialRefMV, baseMV);
}

Optional<SpecializedEmitter>
SpecializedEmitter::forDecl(SILGenModule &SGM, SILDeclRef function) {
  // Only consider standalone declarations in the Builtin module.
  if (function.kind != SILDeclRef::Kind::Func)
    return None;
  if (!function.hasDecl())
    return None;  
  ValueDecl *decl = function.getDecl();
  if (!isa<BuiltinUnit>(decl->getDeclContext()))
    return None;

  const auto name = decl->getBaseIdentifier();
  const BuiltinInfo &builtin = SGM.M.getBuiltinInfo(name);
  switch (builtin.ID) {
  // All the non-SIL, non-type-trait builtins should use the
  // named-builtin logic, which just emits the builtin as a call to a
  // builtin function.  This includes builtins that aren't even declared
  // in Builtins.def, i.e. all of the LLVM intrinsics.
  //
  // We do this in a separate pass over Builtins.def to avoid creating
  // a bunch of identical cases.
#define BUILTIN(Id, Name, Attrs)                                            \
  case BuiltinValueKind::Id:
#define BUILTIN_SIL_OPERATION(Id, Name, Overload)
#define BUILTIN_MISC_OPERATION_WITH_SILGEN(Id, Name, Attrs, Overload)
#define BUILTIN_SANITIZER_OPERATION(Id, Name, Attrs)
#define BUILTIN_TYPE_CHECKER_OPERATION(Id, Name)
#define BUILTIN_TYPE_TRAIT_OPERATION(Id, Name)
#include "swift/AST/Builtins.def"
  case BuiltinValueKind::None:
    return SpecializedEmitter(name);

  // Do a second pass over Builtins.def, ignoring all the cases for
  // which we emitted something above.
#define BUILTIN(Id, Name, Attrs)

  // Use specialized emitters for SIL builtins.
#define BUILTIN_SIL_OPERATION(Id, Name, Overload)                           \
  case BuiltinValueKind::Id:                                                \
    return SpecializedEmitter(&emitBuiltin##Id);

#define BUILTIN_MISC_OPERATION_WITH_SILGEN(Id, Name, Attrs, Overload)          \
  case BuiltinValueKind::Id:                                                   \
    return SpecializedEmitter(&emitBuiltin##Id);

    // Sanitizer builtins should never directly be called; they should only
    // be inserted as instrumentation by SILGen.
#define BUILTIN_SANITIZER_OPERATION(Id, Name, Attrs)                        \
  case BuiltinValueKind::Id:                                                \
    llvm_unreachable("Sanitizer builtin called directly?");

#define BUILTIN_TYPE_CHECKER_OPERATION(Id, Name)                               \
  case BuiltinValueKind::Id:                                                   \
    llvm_unreachable(                                                          \
        "Compile-time type checker operation should not make it to SIL!");

    // Lower away type trait builtins when they're trivially solvable.
#define BUILTIN_TYPE_TRAIT_OPERATION(Id, Name)                              \
  case BuiltinValueKind::Id:                                                \
    return SpecializedEmitter(&emitBuiltinTypeTrait<&TypeBase::Name,        \
                                                    BuiltinValueKind::Id>);

#include "swift/AST/Builtins.def"
  }
  llvm_unreachable("bad builtin kind");
}
