<commit_before>//===-- AsmPrinter.cpp - Common AsmPrinter code ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AsmPrinter class.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/Constants.h"
#include "llvm/Module.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;

/// SwitchSection - Switch to the specified section of the executable if we
/// are not already in it!
///
void AsmPrinter::SwitchSection(const char *NewSection, const GlobalValue *GV) {
  std::string NS;

  if (GV && GV->hasSection())
    NS = ".section " + GV->getSection();
  else
    NS = NewSection;

  if (CurrentSection != NS) {
    CurrentSection = NS;
    if (!CurrentSection.empty())
      O << "\t" << CurrentSection << "\n";
  }
}

bool AsmPrinter::doInitialization(Module &M) {
  Mang = new Mangler(M, GlobalPrefix);
  SwitchSection("", 0);   // Reset back to no section.
  return false;
}

bool AsmPrinter::doFinalization(Module &M) {
  delete Mang; Mang = 0;
  return false;
}

void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
  // What's my mangled name?
  CurrentFnName = Mang->getValueName(MF.getFunction());
}

// EmitAlignment - Emit an alignment directive to the specified power of two.
void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV) const {
  if (GV && GV->getAlignment())
    NumBits = Log2_32(GV->getAlignment());
  if (NumBits == 0) return;   // No need to emit alignment.
  if (AlignmentIsInBytes) NumBits = 1 << NumBits;
  O << AlignDirective << NumBits << "\n";
}

/// EmitZeros - Emit a block of zeros.
///
void AsmPrinter::EmitZeros(uint64_t NumZeros) const {
  if (NumZeros) {
    if (ZeroDirective)
      O << ZeroDirective << NumZeros << "\n";
    else {
      for (; NumZeros; --NumZeros)
        O << Data8bitsDirective << "0\n";
    }
  }
}

// Print out the specified constant, without a storage class.  Only the
// constants valid in constant expressions can occur here.
void AsmPrinter::EmitConstantValueOnly(const Constant *CV) {
  if (CV->isNullValue() || isa<UndefValue>(CV))
    O << "0";
  else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
    assert(CB == ConstantBool::True);
    O << "1";
  } else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
    if (((CI->getValue() << 32) >> 32) == CI->getValue())
      O << CI->getValue();
    else
      O << (uint64_t)CI->getValue();
  else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
    O << CI->getValue();
  else if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
    // This is a constant address for a global variable or function. Use the
    // name of the variable or function as the address value, possibly
    // decorating it with GlobalVarAddrPrefix/Suffix or
    // FunctionAddrPrefix/Suffix (these all default to "" )
    if (isa<Function>(GV))
      O << FunctionAddrPrefix << Mang->getValueName(GV) << FunctionAddrSuffix;
    else
      O << GlobalVarAddrPrefix << Mang->getValueName(GV) << GlobalVarAddrSuffix;
  } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
    const TargetData &TD = TM.getTargetData();
    switch(CE->getOpcode()) {
    case Instruction::GetElementPtr: {
      // generate a symbolic expression for the byte address
      const Constant *ptrVal = CE->getOperand(0);
      std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
      if (int64_t Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) {
        if (Offset)
          O << "(";
        EmitConstantValueOnly(ptrVal);
        if (Offset > 0)
          O << ") + " << Offset;
        else if (Offset < 0)
          O << ") - " << -Offset;
      } else {
        EmitConstantValueOnly(ptrVal);
      }
      break;
    }
    case Instruction::Cast: {
      // Support only non-converting or widening casts for now, that is, ones
      // that do not involve a change in value.  This assertion is really gross,
      // and may not even be a complete check.
      Constant *Op = CE->getOperand(0);
      const Type *OpTy = Op->getType(), *Ty = CE->getType();

      // Remember, kids, pointers can be losslessly converted back and forth
      // into 32-bit or wider integers, regardless of signedness. :-P
      assert(((isa<PointerType>(OpTy)
               && (Ty == Type::LongTy || Ty == Type::ULongTy
                   || Ty == Type::IntTy || Ty == Type::UIntTy))
              || (isa<PointerType>(Ty)
                  && (OpTy == Type::LongTy || OpTy == Type::ULongTy
                      || OpTy == Type::IntTy || OpTy == Type::UIntTy))
              || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
                   && OpTy->isLosslesslyConvertibleTo(Ty))))
             && "FIXME: Don't yet support this kind of constant cast expr");
      EmitConstantValueOnly(Op);
      break;
    }
    case Instruction::Add:
      O << "(";
      EmitConstantValueOnly(CE->getOperand(0));
      O << ") + (";
      EmitConstantValueOnly(CE->getOperand(1));
      O << ")";
      break;
    default:
      assert(0 && "Unsupported operator!");
    }
  } else {
    assert(0 && "Unknown constant value!");
  }
}

/// toOctal - Convert the low order bits of X into an octal digit.
///
static inline char toOctal(int X) {
  return (X&7)+'0';
}

/// printAsCString - Print the specified array as a C compatible string, only if
/// the predicate isString is true.
///
static void printAsCString(std::ostream &O, const ConstantArray *CVA,
                           unsigned LastElt) {
  assert(CVA->isString() && "Array is not string compatible!");

  O << "\"";
  for (unsigned i = 0; i != LastElt; ++i) {
    unsigned char C =
        (unsigned char)cast<ConstantInt>(CVA->getOperand(i))->getRawValue();

    if (C == '"') {
      O << "\\\"";
    } else if (C == '\\') {
      O << "\\\\";
    } else if (isprint(C)) {
      O << C;
    } else {
      switch(C) {
      case '\b': O << "\\b"; break;
      case '\f': O << "\\f"; break;
      case '\n': O << "\\n"; break;
      case '\r': O << "\\r"; break;
      case '\t': O << "\\t"; break;
      default:
        O << '\\';
        O << toOctal(C >> 6);
        O << toOctal(C >> 3);
        O << toOctal(C >> 0);
        break;
      }
    }
  }
  O << "\"";
}

/// EmitGlobalConstant - Print a general LLVM constant to the .s file.
///
void AsmPrinter::EmitGlobalConstant(const Constant *CV) {
  const TargetData &TD = TM.getTargetData();

  if (CV->isNullValue() || isa<UndefValue>(CV)) {
    EmitZeros(TD.getTypeSize(CV->getType()));
    return;
  } else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
    if (CVA->isString()) {
      unsigned NumElts = CVA->getNumOperands();
      if (AscizDirective && NumElts &&
          cast<ConstantInt>(CVA->getOperand(NumElts-1))->getRawValue() == 0) {
        O << AscizDirective;
        printAsCString(O, CVA, NumElts-1);
      } else {
        O << AsciiDirective;
        printAsCString(O, CVA, NumElts);
      }
      O << "\n";
    } else { // Not a string.  Print the values in successive locations
      for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
        EmitGlobalConstant(CVA->getOperand(i));
    }
    return;
  } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
    // Print the fields in successive locations. Pad to align if needed!
    const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
    uint64_t sizeSoFar = 0;
    for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) {
      const Constant* field = CVS->getOperand(i);

      // Check if padding is needed and insert one or more 0s.
      uint64_t fieldSize = TD.getTypeSize(field->getType());
      uint64_t padSize = ((i == e-1? cvsLayout->StructSize
                           : cvsLayout->MemberOffsets[i+1])
                          - cvsLayout->MemberOffsets[i]) - fieldSize;
      sizeSoFar += fieldSize + padSize;

      // Now print the actual field value
      EmitGlobalConstant(field);

      // Insert the field padding unless it's zero bytes...
      EmitZeros(padSize);
    }
    assert(sizeSoFar == cvsLayout->StructSize &&
           "Layout of constant struct may be incorrect!");
    return;
  } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
    // FP Constants are printed as integer constants to avoid losing
    // precision...
    double Val = CFP->getValue();
    if (CFP->getType() == Type::DoubleTy) {
      if (Data64bitsDirective)
        O << Data64bitsDirective << DoubleToBits(Val) << "\t" << CommentString
          << " double value: " << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(DoubleToBits(Val) >> 32)
          << "\t" << CommentString << " double most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(DoubleToBits(Val))
          << "\t" << CommentString << " double least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(DoubleToBits(Val))
          << "\t" << CommentString << " double least significant word " << Val
          << "\n";
        O << Data32bitsDirective << unsigned(DoubleToBits(Val) >> 32)
          << "\t" << CommentString << " double most significant word " << Val
          << "\n";
      }
      return;
    } else {
      O << Data32bitsDirective << FloatToBits(Val) << "\t" << CommentString
        << " float " << Val << "\n";
      return;
    }
  } else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) {
    if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
      uint64_t Val = CI->getRawValue();

      if (Data64bitsDirective)
        O << Data64bitsDirective << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
      }
      return;
    }
  }

  const Type *type = CV->getType();
  switch (type->getTypeID()) {
  case Type::BoolTyID:
  case Type::UByteTyID: case Type::SByteTyID:
    O << Data8bitsDirective;
    break;
  case Type::UShortTyID: case Type::ShortTyID:
    O << Data16bitsDirective;
    break;
  case Type::PointerTyID:
    if (TD.getPointerSize() == 8) {
      O << Data64bitsDirective;
      break;
    }
    //Fall through for pointer size == int size
  case Type::UIntTyID: case Type::IntTyID:
    O << Data32bitsDirective;
    break;
  case Type::ULongTyID: case Type::LongTyID:
    assert(Data64bitsDirective &&"Target cannot handle 64-bit constant exprs!");
    O << Data64bitsDirective;
    break;
  case Type::FloatTyID: case Type::DoubleTyID:
    assert (0 && "Should have already output floating point constant.");
  default:
    assert (0 && "Can't handle printing this type of thing");
    break;
  }
  EmitConstantValueOnly(CV);
  O << "\n";
}
<commit_msg>increment the function number in SetupMachineFunction<commit_after>//===-- AsmPrinter.cpp - Common AsmPrinter code ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AsmPrinter class.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/Constants.h"
#include "llvm/Module.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;

/// SwitchSection - Switch to the specified section of the executable if we
/// are not already in it!
///
void AsmPrinter::SwitchSection(const char *NewSection, const GlobalValue *GV) {
  std::string NS;

  if (GV && GV->hasSection())
    NS = ".section " + GV->getSection();
  else
    NS = NewSection;

  if (CurrentSection != NS) {
    CurrentSection = NS;
    if (!CurrentSection.empty())
      O << "\t" << CurrentSection << "\n";
  }
}

bool AsmPrinter::doInitialization(Module &M) {
  Mang = new Mangler(M, GlobalPrefix);
  SwitchSection("", 0);   // Reset back to no section.
  return false;
}

bool AsmPrinter::doFinalization(Module &M) {
  delete Mang; Mang = 0;
  return false;
}

void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
  // What's my mangled name?
  CurrentFnName = Mang->getValueName(MF.getFunction());
  IncrementFunctionNumber();
}

// EmitAlignment - Emit an alignment directive to the specified power of two.
void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV) const {
  if (GV && GV->getAlignment())
    NumBits = Log2_32(GV->getAlignment());
  if (NumBits == 0) return;   // No need to emit alignment.
  if (AlignmentIsInBytes) NumBits = 1 << NumBits;
  O << AlignDirective << NumBits << "\n";
}

/// EmitZeros - Emit a block of zeros.
///
void AsmPrinter::EmitZeros(uint64_t NumZeros) const {
  if (NumZeros) {
    if (ZeroDirective)
      O << ZeroDirective << NumZeros << "\n";
    else {
      for (; NumZeros; --NumZeros)
        O << Data8bitsDirective << "0\n";
    }
  }
}

// Print out the specified constant, without a storage class.  Only the
// constants valid in constant expressions can occur here.
void AsmPrinter::EmitConstantValueOnly(const Constant *CV) {
  if (CV->isNullValue() || isa<UndefValue>(CV))
    O << "0";
  else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
    assert(CB == ConstantBool::True);
    O << "1";
  } else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
    if (((CI->getValue() << 32) >> 32) == CI->getValue())
      O << CI->getValue();
    else
      O << (uint64_t)CI->getValue();
  else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
    O << CI->getValue();
  else if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
    // This is a constant address for a global variable or function. Use the
    // name of the variable or function as the address value, possibly
    // decorating it with GlobalVarAddrPrefix/Suffix or
    // FunctionAddrPrefix/Suffix (these all default to "" )
    if (isa<Function>(GV))
      O << FunctionAddrPrefix << Mang->getValueName(GV) << FunctionAddrSuffix;
    else
      O << GlobalVarAddrPrefix << Mang->getValueName(GV) << GlobalVarAddrSuffix;
  } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
    const TargetData &TD = TM.getTargetData();
    switch(CE->getOpcode()) {
    case Instruction::GetElementPtr: {
      // generate a symbolic expression for the byte address
      const Constant *ptrVal = CE->getOperand(0);
      std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
      if (int64_t Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) {
        if (Offset)
          O << "(";
        EmitConstantValueOnly(ptrVal);
        if (Offset > 0)
          O << ") + " << Offset;
        else if (Offset < 0)
          O << ") - " << -Offset;
      } else {
        EmitConstantValueOnly(ptrVal);
      }
      break;
    }
    case Instruction::Cast: {
      // Support only non-converting or widening casts for now, that is, ones
      // that do not involve a change in value.  This assertion is really gross,
      // and may not even be a complete check.
      Constant *Op = CE->getOperand(0);
      const Type *OpTy = Op->getType(), *Ty = CE->getType();

      // Remember, kids, pointers can be losslessly converted back and forth
      // into 32-bit or wider integers, regardless of signedness. :-P
      assert(((isa<PointerType>(OpTy)
               && (Ty == Type::LongTy || Ty == Type::ULongTy
                   || Ty == Type::IntTy || Ty == Type::UIntTy))
              || (isa<PointerType>(Ty)
                  && (OpTy == Type::LongTy || OpTy == Type::ULongTy
                      || OpTy == Type::IntTy || OpTy == Type::UIntTy))
              || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
                   && OpTy->isLosslesslyConvertibleTo(Ty))))
             && "FIXME: Don't yet support this kind of constant cast expr");
      EmitConstantValueOnly(Op);
      break;
    }
    case Instruction::Add:
      O << "(";
      EmitConstantValueOnly(CE->getOperand(0));
      O << ") + (";
      EmitConstantValueOnly(CE->getOperand(1));
      O << ")";
      break;
    default:
      assert(0 && "Unsupported operator!");
    }
  } else {
    assert(0 && "Unknown constant value!");
  }
}

/// toOctal - Convert the low order bits of X into an octal digit.
///
static inline char toOctal(int X) {
  return (X&7)+'0';
}

/// printAsCString - Print the specified array as a C compatible string, only if
/// the predicate isString is true.
///
static void printAsCString(std::ostream &O, const ConstantArray *CVA,
                           unsigned LastElt) {
  assert(CVA->isString() && "Array is not string compatible!");

  O << "\"";
  for (unsigned i = 0; i != LastElt; ++i) {
    unsigned char C =
        (unsigned char)cast<ConstantInt>(CVA->getOperand(i))->getRawValue();

    if (C == '"') {
      O << "\\\"";
    } else if (C == '\\') {
      O << "\\\\";
    } else if (isprint(C)) {
      O << C;
    } else {
      switch(C) {
      case '\b': O << "\\b"; break;
      case '\f': O << "\\f"; break;
      case '\n': O << "\\n"; break;
      case '\r': O << "\\r"; break;
      case '\t': O << "\\t"; break;
      default:
        O << '\\';
        O << toOctal(C >> 6);
        O << toOctal(C >> 3);
        O << toOctal(C >> 0);
        break;
      }
    }
  }
  O << "\"";
}

/// EmitGlobalConstant - Print a general LLVM constant to the .s file.
///
void AsmPrinter::EmitGlobalConstant(const Constant *CV) {
  const TargetData &TD = TM.getTargetData();

  if (CV->isNullValue() || isa<UndefValue>(CV)) {
    EmitZeros(TD.getTypeSize(CV->getType()));
    return;
  } else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
    if (CVA->isString()) {
      unsigned NumElts = CVA->getNumOperands();
      if (AscizDirective && NumElts &&
          cast<ConstantInt>(CVA->getOperand(NumElts-1))->getRawValue() == 0) {
        O << AscizDirective;
        printAsCString(O, CVA, NumElts-1);
      } else {
        O << AsciiDirective;
        printAsCString(O, CVA, NumElts);
      }
      O << "\n";
    } else { // Not a string.  Print the values in successive locations
      for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
        EmitGlobalConstant(CVA->getOperand(i));
    }
    return;
  } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
    // Print the fields in successive locations. Pad to align if needed!
    const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
    uint64_t sizeSoFar = 0;
    for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) {
      const Constant* field = CVS->getOperand(i);

      // Check if padding is needed and insert one or more 0s.
      uint64_t fieldSize = TD.getTypeSize(field->getType());
      uint64_t padSize = ((i == e-1? cvsLayout->StructSize
                           : cvsLayout->MemberOffsets[i+1])
                          - cvsLayout->MemberOffsets[i]) - fieldSize;
      sizeSoFar += fieldSize + padSize;

      // Now print the actual field value
      EmitGlobalConstant(field);

      // Insert the field padding unless it's zero bytes...
      EmitZeros(padSize);
    }
    assert(sizeSoFar == cvsLayout->StructSize &&
           "Layout of constant struct may be incorrect!");
    return;
  } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
    // FP Constants are printed as integer constants to avoid losing
    // precision...
    double Val = CFP->getValue();
    if (CFP->getType() == Type::DoubleTy) {
      if (Data64bitsDirective)
        O << Data64bitsDirective << DoubleToBits(Val) << "\t" << CommentString
          << " double value: " << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(DoubleToBits(Val) >> 32)
          << "\t" << CommentString << " double most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(DoubleToBits(Val))
          << "\t" << CommentString << " double least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(DoubleToBits(Val))
          << "\t" << CommentString << " double least significant word " << Val
          << "\n";
        O << Data32bitsDirective << unsigned(DoubleToBits(Val) >> 32)
          << "\t" << CommentString << " double most significant word " << Val
          << "\n";
      }
      return;
    } else {
      O << Data32bitsDirective << FloatToBits(Val) << "\t" << CommentString
        << " float " << Val << "\n";
      return;
    }
  } else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) {
    if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
      uint64_t Val = CI->getRawValue();

      if (Data64bitsDirective)
        O << Data64bitsDirective << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
      }
      return;
    }
  }

  const Type *type = CV->getType();
  switch (type->getTypeID()) {
  case Type::BoolTyID:
  case Type::UByteTyID: case Type::SByteTyID:
    O << Data8bitsDirective;
    break;
  case Type::UShortTyID: case Type::ShortTyID:
    O << Data16bitsDirective;
    break;
  case Type::PointerTyID:
    if (TD.getPointerSize() == 8) {
      O << Data64bitsDirective;
      break;
    }
    //Fall through for pointer size == int size
  case Type::UIntTyID: case Type::IntTyID:
    O << Data32bitsDirective;
    break;
  case Type::ULongTyID: case Type::LongTyID:
    assert(Data64bitsDirective &&"Target cannot handle 64-bit constant exprs!");
    O << Data64bitsDirective;
    break;
  case Type::FloatTyID: case Type::DoubleTyID:
    assert (0 && "Should have already output floating point constant.");
  default:
    assert (0 && "Can't handle printing this type of thing");
    break;
  }
  EmitConstantValueOnly(CV);
  O << "\n";
}
<|endoftext|>


<commit_before>//===- lib/Driver/GnuLdDriver.cpp -----------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
///
/// Concrete instance of the Driver for GNU's ld.
///
//===----------------------------------------------------------------------===//

#include "lld/Driver/Driver.h"
#include "lld/Driver/GnuLdInputGraph.h"

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Signals.h"

using namespace lld;

namespace {

// Create enum with OPT_xxx values for each option in GnuLdOptions.td
enum {
  OPT_INVALID = 0,
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
               HELP, META) \
          OPT_##ID,
#include "GnuLdOptions.inc"
#undef OPTION
};

// Create prefix string literals used in GnuLdOptions.td
#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
#include "GnuLdOptions.inc"
#undef PREFIX

// Create table mapping all options defined in GnuLdOptions.td
static const llvm::opt::OptTable::Info infoTable[] = {
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
               HELPTEXT, METAVAR)   \
  { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
    PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS },
#include "GnuLdOptions.inc"
#undef OPTION
};

// Create OptTable class for parsing actual command line arguments
class GnuLdOptTable : public llvm::opt::OptTable {
public:
  GnuLdOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable)){}
};

} // namespace

llvm::ErrorOr<StringRef> ELFFileNode::getPath(const LinkingContext &) const {
  if (!_isDashlPrefix)
    return _path;
  return _elfLinkingContext.searchLibrary(_path, _libraryPaths);
}

std::string ELFFileNode::errStr(llvm::error_code errc) {
  if (errc == llvm::errc::no_such_file_or_directory) {
    if (_isDashlPrefix)
      return (Twine("Unable to find library -l") + _path).str();
    return (Twine("Unable to find file ") + _path).str();
  }
  return FileNode::errStr(errc);
}

bool GnuLdDriver::linkELF(int argc, const char *argv[],
                          raw_ostream &diagnostics) {
  std::unique_ptr<ELFLinkingContext> options;
  if (!parse(argc, argv, options, diagnostics))
    return false;
  if (!options)
    return true;

  return link(*options, diagnostics);
}

bool GnuLdDriver::parse(int argc, const char *argv[],
                        std::unique_ptr<ELFLinkingContext> &context,
                        raw_ostream &diagnostics) {
  // Parse command line options using GnuLdOptions.td
  std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
  GnuLdOptTable table;
  unsigned missingIndex;
  unsigned missingCount;

  parsedArgs.reset(
      table.ParseArgs(&argv[1], &argv[argc], missingIndex, missingCount));
  if (missingCount) {
    diagnostics << "error: missing arg value for '"
                << parsedArgs->getArgString(missingIndex) << "' expected "
                << missingCount << " argument(s).\n";
    return false;
  }

  // Handle --help
  if (parsedArgs->getLastArg(OPT_help)) {
    table.PrintHelp(llvm::outs(), argv[0], "LLVM Linker", false);
    return true;
  }

  // Use -target or use default target triple to instantiate LinkingContext
  llvm::Triple triple;
  if (llvm::opt::Arg *trip = parsedArgs->getLastArg(OPT_target))
    triple = llvm::Triple(trip->getValue());
  else
    triple = getDefaultTarget(argv[0]);
  std::unique_ptr<ELFLinkingContext> ctx(ELFLinkingContext::create(triple));

  if (!ctx) {
    diagnostics << "unknown target triple\n";
    return false;
  }

  std::unique_ptr<InputGraph> inputGraph(new InputGraph());
  std::stack<InputElement *> controlNodeStack;

  // Positional options for an Input File
  std::vector<StringRef> searchPath;
  bool isWholeArchive = false;
  bool asNeeded = false;
  bool _outputOptionSet = false;

  // Create a dynamic executable by default
  ctx->setOutputELFType(llvm::ELF::ET_EXEC);
  ctx->setIsStaticExecutable(false);
  ctx->setAllowShlibUndefines(false);
  ctx->setUseShlibUndefines(true);

  int index = 0;

  // Process all the arguments and create Input Elements
  for (auto inputArg : *parsedArgs) {
    switch (inputArg->getOption().getID()) {
    case OPT_mllvm:
      ctx->appendLLVMOption(inputArg->getValue());
      break;
    case OPT_relocatable:
      ctx->setOutputELFType(llvm::ELF::ET_REL);
      ctx->setPrintRemainingUndefines(false);
      ctx->setAllowRemainingUndefines(true);
      break;
    case OPT_static:
      ctx->setOutputELFType(llvm::ELF::ET_EXEC);
      ctx->setIsStaticExecutable(true);
      break;
    case OPT_shared:
      ctx->setOutputELFType(llvm::ELF::ET_DYN);
      ctx->setAllowShlibUndefines(true);
      ctx->setUseShlibUndefines(false);
      break;
    case OPT_e:
      ctx->setEntrySymbolName(inputArg->getValue());
      break;

    case OPT_output:
      _outputOptionSet = true;
      ctx->setOutputPath(inputArg->getValue());
      break;

    case OPT_noinhibit_exec:
      ctx->setAllowRemainingUndefines(true);
      break;

    case OPT_merge_strings:
      ctx->setMergeCommonStrings(true);
      break;

    case OPT_t:
      ctx->setLogInputFiles(true);
      break;

    case OPT_no_allow_shlib_undefs:
      ctx->setAllowShlibUndefines(false);
      break;

    case OPT_allow_shlib_undefs:
      ctx->setAllowShlibUndefines(true);
      break;

    case OPT_use_shlib_undefs:
      ctx->setUseShlibUndefines(true);
      break;

    case OPT_dynamic_linker:
      ctx->setInterpreter(inputArg->getValue());
      break;

    case OPT_nmagic:
      ctx->setOutputMagic(ELFLinkingContext::OutputMagic::NMAGIC);
      ctx->setIsStaticExecutable(true);
      break;

    case OPT_omagic:
      ctx->setOutputMagic(ELFLinkingContext::OutputMagic::OMAGIC);
      ctx->setIsStaticExecutable(true);
      break;

    case OPT_no_omagic:
      ctx->setOutputMagic(ELFLinkingContext::OutputMagic::DEFAULT);
      ctx->setNoAllowDynamicLibraries();
      break;

    case OPT_u:
      ctx->addInitialUndefinedSymbol(inputArg->getValue());
      break;

    case OPT_init:
      ctx->addInitFunction(inputArg->getValue());
      break;

    case OPT_fini:
      ctx->addFiniFunction(inputArg->getValue());
      break;

    case OPT_output_filetype:
      ctx->setOutputFileType(inputArg->getValue());
      break;

    case OPT_no_whole_archive:
      isWholeArchive = false;
      break;
    case OPT_whole_archive:
      isWholeArchive = true;
      break;
    case OPT_as_needed:
      asNeeded = true;
      break;
    case OPT_no_as_needed:
      asNeeded = false;
      break;
    case OPT_L:
      searchPath.push_back(inputArg->getValue());
      break;

    case OPT_start_group: {
      std::unique_ptr<InputElement> controlStart(new ELFGroup(*ctx, index++));
      controlNodeStack.push(controlStart.get());
      (llvm::dyn_cast<ControlNode>)(controlNodeStack.top())
          ->processControlEnter();
      inputGraph->addInputElement(std::move(controlStart));
      break;
    }

    case OPT_end_group:
      (llvm::dyn_cast<ControlNode>)(controlNodeStack.top())
          ->processControlExit();
      controlNodeStack.pop();
      break;

    case OPT_INPUT:
    case OPT_l: {
      std::unique_ptr<InputElement> inputFile =
          std::move(std::unique_ptr<InputElement>(new ELFFileNode(
              *ctx, inputArg->getValue(), searchPath, index++, isWholeArchive,
              asNeeded, inputArg->getOption().getID() == OPT_l)));
      if (controlNodeStack.empty())
        inputGraph->addInputElement(std::move(inputFile));
      else
        (llvm::dyn_cast<ControlNode>)(controlNodeStack.top())
            ->processInputElement(std::move(inputFile));
      break;
    }

    case OPT_rpath: {
      SmallVector<StringRef, 2> rpaths;
      StringRef(inputArg->getValue()).split(rpaths, ":");
      for (auto path : rpaths)
        ctx->addRpath(path);
      break;
    }

    case OPT_rpath_link: {
      SmallVector<StringRef, 2> rpaths;
      StringRef(inputArg->getValue()).split(rpaths, ":");
      for (auto path : rpaths)
        ctx->addRpathLink(path);
      break;
    }

    case OPT_sysroot:
      ctx->setSysroot(inputArg->getValue());
      break;

    case OPT_soname:
      ctx->setSharedObjectName(inputArg->getValue());
      break;

    default:
      break;
    } // end switch on option ID
  }   // end for

  if (!inputGraph->size()) {
    diagnostics << "No input files\n";
    return false;
  }

  // Set default output file name if the output file was not
  // specified.
  if (!_outputOptionSet) {
    switch (ctx->outputFileType()) {
    case LinkingContext::OutputFileType::YAML:
      ctx->setOutputPath("-");
      break;
    case LinkingContext::OutputFileType::Native:
      ctx->setOutputPath("a.native");
      break;
    default:
      ctx->setOutputPath("a.out");
      break;
    }
  }

  if (ctx->outputFileType() == LinkingContext::OutputFileType::YAML)
    inputGraph->dump(diagnostics);

  // Validate the combination of options used.
  if (!ctx->validate(diagnostics))
    return false;

  ctx->setInputGraph(std::move(inputGraph));

  context.swap(ctx);

  return true;
}

/// Get the default target triple based on either the program name
/// (e.g. "x86-ibm-linux-lld") or the primary target llvm was configured for.
llvm::Triple GnuLdDriver::getDefaultTarget(const char *progName) {
  SmallVector<StringRef, 4> components;
  llvm::SplitString(llvm::sys::path::stem(progName), components, "-");
  // If has enough parts to be start with a triple.
  if (components.size() >= 4) {
    llvm::Triple triple(components[0], components[1], components[2],
                        components[3]);
    // If first component looks like an arch.
    if (triple.getArch() != llvm::Triple::UnknownArch)
      return triple;
  }

  // Fallback to use whatever default triple llvm was configured for.
  return llvm::Triple(llvm::sys::getDefaultTargetTriple());
}
<commit_msg>Simplify unique_ptr instantiation. No functionality change.<commit_after>//===- lib/Driver/GnuLdDriver.cpp -----------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
///
/// Concrete instance of the Driver for GNU's ld.
///
//===----------------------------------------------------------------------===//

#include "lld/Driver/Driver.h"
#include "lld/Driver/GnuLdInputGraph.h"

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Signals.h"

using namespace lld;

namespace {

// Create enum with OPT_xxx values for each option in GnuLdOptions.td
enum {
  OPT_INVALID = 0,
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
               HELP, META) \
          OPT_##ID,
#include "GnuLdOptions.inc"
#undef OPTION
};

// Create prefix string literals used in GnuLdOptions.td
#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
#include "GnuLdOptions.inc"
#undef PREFIX

// Create table mapping all options defined in GnuLdOptions.td
static const llvm::opt::OptTable::Info infoTable[] = {
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
               HELPTEXT, METAVAR)   \
  { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
    PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS },
#include "GnuLdOptions.inc"
#undef OPTION
};

// Create OptTable class for parsing actual command line arguments
class GnuLdOptTable : public llvm::opt::OptTable {
public:
  GnuLdOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable)){}
};

} // namespace

llvm::ErrorOr<StringRef> ELFFileNode::getPath(const LinkingContext &) const {
  if (!_isDashlPrefix)
    return _path;
  return _elfLinkingContext.searchLibrary(_path, _libraryPaths);
}

std::string ELFFileNode::errStr(llvm::error_code errc) {
  if (errc == llvm::errc::no_such_file_or_directory) {
    if (_isDashlPrefix)
      return (Twine("Unable to find library -l") + _path).str();
    return (Twine("Unable to find file ") + _path).str();
  }
  return FileNode::errStr(errc);
}

bool GnuLdDriver::linkELF(int argc, const char *argv[],
                          raw_ostream &diagnostics) {
  std::unique_ptr<ELFLinkingContext> options;
  if (!parse(argc, argv, options, diagnostics))
    return false;
  if (!options)
    return true;

  return link(*options, diagnostics);
}

bool GnuLdDriver::parse(int argc, const char *argv[],
                        std::unique_ptr<ELFLinkingContext> &context,
                        raw_ostream &diagnostics) {
  // Parse command line options using GnuLdOptions.td
  std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
  GnuLdOptTable table;
  unsigned missingIndex;
  unsigned missingCount;

  parsedArgs.reset(
      table.ParseArgs(&argv[1], &argv[argc], missingIndex, missingCount));
  if (missingCount) {
    diagnostics << "error: missing arg value for '"
                << parsedArgs->getArgString(missingIndex) << "' expected "
                << missingCount << " argument(s).\n";
    return false;
  }

  // Handle --help
  if (parsedArgs->getLastArg(OPT_help)) {
    table.PrintHelp(llvm::outs(), argv[0], "LLVM Linker", false);
    return true;
  }

  // Use -target or use default target triple to instantiate LinkingContext
  llvm::Triple triple;
  if (llvm::opt::Arg *trip = parsedArgs->getLastArg(OPT_target))
    triple = llvm::Triple(trip->getValue());
  else
    triple = getDefaultTarget(argv[0]);
  std::unique_ptr<ELFLinkingContext> ctx(ELFLinkingContext::create(triple));

  if (!ctx) {
    diagnostics << "unknown target triple\n";
    return false;
  }

  std::unique_ptr<InputGraph> inputGraph(new InputGraph());
  std::stack<InputElement *> controlNodeStack;

  // Positional options for an Input File
  std::vector<StringRef> searchPath;
  bool isWholeArchive = false;
  bool asNeeded = false;
  bool _outputOptionSet = false;

  // Create a dynamic executable by default
  ctx->setOutputELFType(llvm::ELF::ET_EXEC);
  ctx->setIsStaticExecutable(false);
  ctx->setAllowShlibUndefines(false);
  ctx->setUseShlibUndefines(true);

  int index = 0;

  // Process all the arguments and create Input Elements
  for (auto inputArg : *parsedArgs) {
    switch (inputArg->getOption().getID()) {
    case OPT_mllvm:
      ctx->appendLLVMOption(inputArg->getValue());
      break;
    case OPT_relocatable:
      ctx->setOutputELFType(llvm::ELF::ET_REL);
      ctx->setPrintRemainingUndefines(false);
      ctx->setAllowRemainingUndefines(true);
      break;
    case OPT_static:
      ctx->setOutputELFType(llvm::ELF::ET_EXEC);
      ctx->setIsStaticExecutable(true);
      break;
    case OPT_shared:
      ctx->setOutputELFType(llvm::ELF::ET_DYN);
      ctx->setAllowShlibUndefines(true);
      ctx->setUseShlibUndefines(false);
      break;
    case OPT_e:
      ctx->setEntrySymbolName(inputArg->getValue());
      break;

    case OPT_output:
      _outputOptionSet = true;
      ctx->setOutputPath(inputArg->getValue());
      break;

    case OPT_noinhibit_exec:
      ctx->setAllowRemainingUndefines(true);
      break;

    case OPT_merge_strings:
      ctx->setMergeCommonStrings(true);
      break;

    case OPT_t:
      ctx->setLogInputFiles(true);
      break;

    case OPT_no_allow_shlib_undefs:
      ctx->setAllowShlibUndefines(false);
      break;

    case OPT_allow_shlib_undefs:
      ctx->setAllowShlibUndefines(true);
      break;

    case OPT_use_shlib_undefs:
      ctx->setUseShlibUndefines(true);
      break;

    case OPT_dynamic_linker:
      ctx->setInterpreter(inputArg->getValue());
      break;

    case OPT_nmagic:
      ctx->setOutputMagic(ELFLinkingContext::OutputMagic::NMAGIC);
      ctx->setIsStaticExecutable(true);
      break;

    case OPT_omagic:
      ctx->setOutputMagic(ELFLinkingContext::OutputMagic::OMAGIC);
      ctx->setIsStaticExecutable(true);
      break;

    case OPT_no_omagic:
      ctx->setOutputMagic(ELFLinkingContext::OutputMagic::DEFAULT);
      ctx->setNoAllowDynamicLibraries();
      break;

    case OPT_u:
      ctx->addInitialUndefinedSymbol(inputArg->getValue());
      break;

    case OPT_init:
      ctx->addInitFunction(inputArg->getValue());
      break;

    case OPT_fini:
      ctx->addFiniFunction(inputArg->getValue());
      break;

    case OPT_output_filetype:
      ctx->setOutputFileType(inputArg->getValue());
      break;

    case OPT_no_whole_archive:
      isWholeArchive = false;
      break;
    case OPT_whole_archive:
      isWholeArchive = true;
      break;
    case OPT_as_needed:
      asNeeded = true;
      break;
    case OPT_no_as_needed:
      asNeeded = false;
      break;
    case OPT_L:
      searchPath.push_back(inputArg->getValue());
      break;

    case OPT_start_group: {
      std::unique_ptr<InputElement> controlStart(new ELFGroup(*ctx, index++));
      controlNodeStack.push(controlStart.get());
      (llvm::dyn_cast<ControlNode>)(controlNodeStack.top())
          ->processControlEnter();
      inputGraph->addInputElement(std::move(controlStart));
      break;
    }

    case OPT_end_group:
      (llvm::dyn_cast<ControlNode>)(controlNodeStack.top())
          ->processControlExit();
      controlNodeStack.pop();
      break;

    case OPT_INPUT:
    case OPT_l: {
      std::unique_ptr<InputElement> inputFile(new ELFFileNode(
          *ctx, inputArg->getValue(), searchPath, index++, isWholeArchive,
          asNeeded, inputArg->getOption().getID() == OPT_l));
      if (controlNodeStack.empty())
        inputGraph->addInputElement(std::move(inputFile));
      else
        (llvm::dyn_cast<ControlNode>)(controlNodeStack.top())
            ->processInputElement(std::move(inputFile));
      break;
    }

    case OPT_rpath: {
      SmallVector<StringRef, 2> rpaths;
      StringRef(inputArg->getValue()).split(rpaths, ":");
      for (auto path : rpaths)
        ctx->addRpath(path);
      break;
    }

    case OPT_rpath_link: {
      SmallVector<StringRef, 2> rpaths;
      StringRef(inputArg->getValue()).split(rpaths, ":");
      for (auto path : rpaths)
        ctx->addRpathLink(path);
      break;
    }

    case OPT_sysroot:
      ctx->setSysroot(inputArg->getValue());
      break;

    case OPT_soname:
      ctx->setSharedObjectName(inputArg->getValue());
      break;

    default:
      break;
    } // end switch on option ID
  }   // end for

  if (!inputGraph->size()) {
    diagnostics << "No input files\n";
    return false;
  }

  // Set default output file name if the output file was not
  // specified.
  if (!_outputOptionSet) {
    switch (ctx->outputFileType()) {
    case LinkingContext::OutputFileType::YAML:
      ctx->setOutputPath("-");
      break;
    case LinkingContext::OutputFileType::Native:
      ctx->setOutputPath("a.native");
      break;
    default:
      ctx->setOutputPath("a.out");
      break;
    }
  }

  if (ctx->outputFileType() == LinkingContext::OutputFileType::YAML)
    inputGraph->dump(diagnostics);

  // Validate the combination of options used.
  if (!ctx->validate(diagnostics))
    return false;

  ctx->setInputGraph(std::move(inputGraph));

  context.swap(ctx);

  return true;
}

/// Get the default target triple based on either the program name
/// (e.g. "x86-ibm-linux-lld") or the primary target llvm was configured for.
llvm::Triple GnuLdDriver::getDefaultTarget(const char *progName) {
  SmallVector<StringRef, 4> components;
  llvm::SplitString(llvm::sys::path::stem(progName), components, "-");
  // If has enough parts to be start with a triple.
  if (components.size() >= 4) {
    llvm::Triple triple(components[0], components[1], components[2],
                        components[3]);
    // If first component looks like an arch.
    if (triple.getArch() != llvm::Triple::UnknownArch)
      return triple;
  }

  // Fallback to use whatever default triple llvm was configured for.
  return llvm::Triple(llvm::sys::getDefaultTargetTriple());
}
<|endoftext|>


<commit_before>//===--- GenClangType.cpp - Swift IR Generation For Types -----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements generation of Clang AST types from Swift AST types
//  for types that are representable in Objective-C interfaces.
//
//===----------------------------------------------------------------------===//

#include "GenClangType.h"

#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/Type.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CanonicalType.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Type.h"

using namespace swift;
using namespace irgen;

static Type getNamedSwiftType(DeclContext *DC, StringRef name) {
  assert(DC && "Unexpected null declaration context!");

  auto &astContext = DC->getASTContext();
  UnqualifiedLookup lookup(astContext.getIdentifier(name), DC, nullptr);
  if (auto type = lookup.getSingleTypeResult())
    return type->getDeclaredType();

  return Type();
}

static const clang::CanQualType getClangBuiltinTypeFromKind(
  const clang::ASTContext &context,
  clang::BuiltinType::Kind kind) {
  switch (kind) {
#define BUILTIN_TYPE(Id, SingletonId) \
  case clang::BuiltinType::Id: return context.SingletonId;
#include "clang/AST/BuiltinTypes.def"
  }
}

static clang::CanQualType getClangSelectorType(
  const clang::ASTContext &clangCtx) {
  return clangCtx.getPointerType(clangCtx.ObjCBuiltinSelTy);
}

static clang::CanQualType getClangIdType(
  const clang::ASTContext &clangCtx) {
  clang::QualType clangType =
    clangCtx.getObjCObjectType(clangCtx.ObjCBuiltinIdTy, 0, 0);
  clangType = clangCtx.getObjCObjectPointerType(clangType);
  return clangCtx.getCanonicalType(clangType);
}

clang::CanQualType GenClangType::visitStructType(CanStructType type) {
  // First attempt a lookup in our map of imported structs.
  auto *decl = type->getDecl();
  if (auto *clangDecl = decl->getClangDecl()) {
    auto *typeDecl = cast<clang::TypeDecl>(clangDecl);
    return typeDecl->getTypeForDecl()->getCanonicalTypeUnqualified();
  }

  auto const &clangCtx = getClangASTContext();

#define MAP_BUILTIN_TYPE(CLANG_BUILTIN_KIND, SWIFT_TYPE_NAME) {                \
    auto lookupTy = getNamedSwiftType(decl->getDeclContext(),                  \
                                      #SWIFT_TYPE_NAME);                       \
    if (lookupTy && lookupTy->isEqual(type))                                   \
      return getClangBuiltinTypeFromKind(clangCtx,                             \
                                      clang::BuiltinType::CLANG_BUILTIN_KIND); \
  }
#include "swift/ClangImporter/BuiltinMappedTypes.def"
#undef MAP_BUILTIN_TYPE

  // Handle other imported types.

#define CHECK_CLANG_TYPE_MATCH(TYPE, NAME, RESULT)                           \
  if (auto lookupTy = getNamedSwiftType((TYPE)->getDecl()->getDeclContext(), \
                                        (NAME)))                             \
    if (lookupTy->isEqual(type))                                             \
      return (RESULT);

  CHECK_CLANG_TYPE_MATCH(type, "COpaquePointer", clangCtx.VoidPtrTy);
  CHECK_CLANG_TYPE_MATCH(type, "ObjCBool", clangCtx.ObjCBuiltinBoolTy);
  // FIXME: This is sufficient for ABI type generation, but should
  //        probably be const char* for type encoding.
  CHECK_CLANG_TYPE_MATCH(type, "CString", clangCtx.VoidPtrTy);
  CHECK_CLANG_TYPE_MATCH(type, "Selector", getClangSelectorType(clangCtx));
#undef CHECK_CLANG_TYPE_MATCH
  // FIXME: Handle other structs resulting from imported non-struct Clang types.
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitTupleType(CanTupleType type) {
  if (type->getNumElements() == 0)
    return getClangASTContext().VoidTy;

  llvm_unreachable("Unexpected tuple type in Clang type generation!");
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitProtocolType(CanProtocolType type) {
  if (auto lookupTy = getNamedSwiftType(type->getDecl()->getDeclContext(),
                                        "DynamicLookup"))
    if (lookupTy->isEqual(type))
      return getClangIdType(getClangASTContext());
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitMetatypeType(CanMetatypeType type) {
  auto const &clangCtx = getClangASTContext();
  clang::QualType clangType =
    clangCtx.getObjCObjectType(clangCtx.ObjCBuiltinClassTy, 0, 0);
  clangType = clangCtx.getObjCObjectPointerType(clangType);
  return clangCtx.getCanonicalType(clangType);
}

clang::CanQualType GenClangType::visitClassType(CanClassType type) {
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitBoundGenericStructType(
  CanBoundGenericStructType type) {
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitEnumType(CanEnumType type) {
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitFunctionType(CanFunctionType type) {
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitProtocolCompositionType(
  CanProtocolCompositionType type) {
  // Any protocol composition type in Swift that shows up in an @objc
  // method maps 1-1 to "id <SomeProto>"; with clang's encoding
  // ignoring the protocol list.
  return getClangIdType(getClangASTContext());
}

clang::CanQualType GenClangType::visitType(CanType type) {
  llvm_unreachable("Unhandled type in Clang type generation.");

  return clang::CanQualType();
}

const clang::ASTContext &GenClangType::getClangASTContext() const {
  auto *CI = static_cast<ClangImporter*>(&*Context.getClangModuleLoader());
  return CI->getClangASTContext();
}
<commit_msg>Generate the same Clang type for all protocol types.<commit_after>//===--- GenClangType.cpp - Swift IR Generation For Types -----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements generation of Clang AST types from Swift AST types
//  for types that are representable in Objective-C interfaces.
//
//===----------------------------------------------------------------------===//

#include "GenClangType.h"

#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/Type.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CanonicalType.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Type.h"

using namespace swift;
using namespace irgen;

static Type getNamedSwiftType(DeclContext *DC, StringRef name) {
  assert(DC && "Unexpected null declaration context!");

  auto &astContext = DC->getASTContext();
  UnqualifiedLookup lookup(astContext.getIdentifier(name), DC, nullptr);
  if (auto type = lookup.getSingleTypeResult())
    return type->getDeclaredType();

  return Type();
}

static const clang::CanQualType getClangBuiltinTypeFromKind(
  const clang::ASTContext &context,
  clang::BuiltinType::Kind kind) {
  switch (kind) {
#define BUILTIN_TYPE(Id, SingletonId) \
  case clang::BuiltinType::Id: return context.SingletonId;
#include "clang/AST/BuiltinTypes.def"
  }
}

static clang::CanQualType getClangSelectorType(
  const clang::ASTContext &clangCtx) {
  return clangCtx.getPointerType(clangCtx.ObjCBuiltinSelTy);
}

static clang::CanQualType getClangIdType(
  const clang::ASTContext &clangCtx) {
  clang::QualType clangType =
    clangCtx.getObjCObjectType(clangCtx.ObjCBuiltinIdTy, 0, 0);
  clangType = clangCtx.getObjCObjectPointerType(clangType);
  return clangCtx.getCanonicalType(clangType);
}

clang::CanQualType GenClangType::visitStructType(CanStructType type) {
  // First attempt a lookup in our map of imported structs.
  auto *decl = type->getDecl();
  if (auto *clangDecl = decl->getClangDecl()) {
    auto *typeDecl = cast<clang::TypeDecl>(clangDecl);
    return typeDecl->getTypeForDecl()->getCanonicalTypeUnqualified();
  }

  auto const &clangCtx = getClangASTContext();

#define MAP_BUILTIN_TYPE(CLANG_BUILTIN_KIND, SWIFT_TYPE_NAME) {                \
    auto lookupTy = getNamedSwiftType(decl->getDeclContext(),                  \
                                      #SWIFT_TYPE_NAME);                       \
    if (lookupTy && lookupTy->isEqual(type))                                   \
      return getClangBuiltinTypeFromKind(clangCtx,                             \
                                      clang::BuiltinType::CLANG_BUILTIN_KIND); \
  }
#include "swift/ClangImporter/BuiltinMappedTypes.def"
#undef MAP_BUILTIN_TYPE

  // Handle other imported types.

#define CHECK_CLANG_TYPE_MATCH(TYPE, NAME, RESULT)                           \
  if (auto lookupTy = getNamedSwiftType((TYPE)->getDecl()->getDeclContext(), \
                                        (NAME)))                             \
    if (lookupTy->isEqual(type))                                             \
      return (RESULT);

  CHECK_CLANG_TYPE_MATCH(type, "COpaquePointer", clangCtx.VoidPtrTy);
  CHECK_CLANG_TYPE_MATCH(type, "ObjCBool", clangCtx.ObjCBuiltinBoolTy);
  // FIXME: This is sufficient for ABI type generation, but should
  //        probably be const char* for type encoding.
  CHECK_CLANG_TYPE_MATCH(type, "CString", clangCtx.VoidPtrTy);
  CHECK_CLANG_TYPE_MATCH(type, "Selector", getClangSelectorType(clangCtx));
#undef CHECK_CLANG_TYPE_MATCH
  // FIXME: Handle other structs resulting from imported non-struct Clang types.
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitTupleType(CanTupleType type) {
  if (type->getNumElements() == 0)
    return getClangASTContext().VoidTy;

  llvm_unreachable("Unexpected tuple type in Clang type generation!");
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitProtocolType(CanProtocolType type) {
  return getClangIdType(getClangASTContext());
}

clang::CanQualType GenClangType::visitMetatypeType(CanMetatypeType type) {
  auto const &clangCtx = getClangASTContext();
  clang::QualType clangType =
    clangCtx.getObjCObjectType(clangCtx.ObjCBuiltinClassTy, 0, 0);
  clangType = clangCtx.getObjCObjectPointerType(clangType);
  return clangCtx.getCanonicalType(clangType);
}

clang::CanQualType GenClangType::visitClassType(CanClassType type) {
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitBoundGenericStructType(
  CanBoundGenericStructType type) {
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitEnumType(CanEnumType type) {
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitFunctionType(CanFunctionType type) {
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitProtocolCompositionType(
  CanProtocolCompositionType type) {
  // Any protocol composition type in Swift that shows up in an @objc
  // method maps 1-1 to "id <SomeProto>"; with clang's encoding
  // ignoring the protocol list.
  return getClangIdType(getClangASTContext());
}

clang::CanQualType GenClangType::visitType(CanType type) {
  llvm_unreachable("Unhandled type in Clang type generation.");

  return clang::CanQualType();
}

const clang::ASTContext &GenClangType::getClangASTContext() const {
  auto *CI = static_cast<ClangImporter*>(&*Context.getClangModuleLoader());
  return CI->getClangASTContext();
}
<|endoftext|>


<commit_before>//===--- GenClangType.cpp - Swift IR Generation For Types -----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements generation of Clang AST types from Swift AST types
//  for types that are representable in Objective-C interfaces.
//
//===----------------------------------------------------------------------===//

#include "GenClangType.h"

#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/Type.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CanonicalType.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Type.h"

using namespace swift;
using namespace irgen;

static Type getNamedSwiftType(DeclContext *DC, StringRef name) {
  assert(DC && "Unexpected null declaration context!");

  auto &astContext = DC->getASTContext();
  UnqualifiedLookup lookup(astContext.getIdentifier(name), DC, nullptr);
  if (auto type = lookup.getSingleTypeResult())
    return type->getDeclaredType();

  return Type();
}

static const clang::CanQualType getClangBuiltinTypeFromKind(
  const clang::ASTContext &context,
  clang::BuiltinType::Kind kind) {
  switch (kind) {
#define BUILTIN_TYPE(Id, SingletonId) \
  case clang::BuiltinType::Id: return context.SingletonId;
#include "clang/AST/BuiltinTypes.def"
  }
}

static clang::CanQualType getClangSelectorType(
  const clang::ASTContext &clangCtx) {
  return clangCtx.getPointerType(clangCtx.ObjCBuiltinSelTy);
}

static clang::CanQualType getClangMetatypeType(
  const clang::ASTContext &clangCtx) {
  clang::QualType clangType =
    clangCtx.getObjCObjectType(clangCtx.ObjCBuiltinClassTy, 0, 0);
  clangType = clangCtx.getObjCObjectPointerType(clangType);
  return clangCtx.getCanonicalType(clangType);
}

static clang::CanQualType getClangIdType(
  const clang::ASTContext &clangCtx) {
  clang::QualType clangType =
    clangCtx.getObjCObjectType(clangCtx.ObjCBuiltinIdTy, 0, 0);
  clangType = clangCtx.getObjCObjectPointerType(clangType);
  return clangCtx.getCanonicalType(clangType);
}

clang::CanQualType GenClangType::visitStructType(CanStructType type) {
  // First attempt a lookup in our map of imported structs.
  auto *decl = type->getDecl();
  if (auto *clangDecl = decl->getClangDecl()) {
    auto *typeDecl = cast<clang::TypeDecl>(clangDecl);
    return typeDecl->getTypeForDecl()->getCanonicalTypeUnqualified();
  }

  auto const &clangCtx = getClangASTContext();

#define MAP_BUILTIN_TYPE(CLANG_BUILTIN_KIND, SWIFT_TYPE_NAME) {                \
    auto lookupTy = getNamedSwiftType(decl->getDeclContext(),                  \
                                      #SWIFT_TYPE_NAME);                       \
    if (lookupTy && lookupTy->isEqual(type))                                   \
      return getClangBuiltinTypeFromKind(clangCtx,                             \
                                      clang::BuiltinType::CLANG_BUILTIN_KIND); \
  }
#include "swift/ClangImporter/BuiltinMappedTypes.def"
#undef MAP_BUILTIN_TYPE

  // Handle other imported types.

#define CHECK_CLANG_TYPE_MATCH(TYPE, NAME, RESULT)                           \
  if (auto lookupTy = getNamedSwiftType((TYPE)->getDecl()->getDeclContext(), \
                                        (NAME)))                             \
    if (lookupTy->isEqual(type))                                             \
      return (RESULT);

  CHECK_CLANG_TYPE_MATCH(type, "COpaquePointer", clangCtx.VoidPtrTy);
  CHECK_CLANG_TYPE_MATCH(type, "ObjCBool", clangCtx.ObjCBuiltinBoolTy);
  // FIXME: This is sufficient for ABI type generation, but should
  //        probably be const char* for type encoding.
  CHECK_CLANG_TYPE_MATCH(type, "CString", clangCtx.VoidPtrTy);
  CHECK_CLANG_TYPE_MATCH(type, "Selector", getClangSelectorType(clangCtx));
#undef CHECK_CLANG_TYPE_MATCH
  // FIXME: Handle other structs resulting from imported non-struct Clang types.
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitTupleType(CanTupleType type) {
  if (type->getNumElements() == 0)
    return getClangASTContext().VoidTy;

  llvm_unreachable("Unexpected tuple type in Clang type generation!");
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitProtocolType(CanProtocolType type) {
  return getClangIdType(getClangASTContext());
}

clang::CanQualType GenClangType::visitMetatypeType(CanMetatypeType type) {
  return getClangMetatypeType(getClangASTContext());
}

clang::CanQualType GenClangType::visitClassType(CanClassType type) {
  // Any @objc class type in Swift that shows up in an @objc method maps 1-1 to
  // "id <SomeProto>"; with clang's encoding ignoring the protocol list.
  return getClangIdType(getClangASTContext());
}

clang::CanQualType GenClangType::visitBoundGenericStructType(
  CanBoundGenericStructType type) {
  // We only expect UnsafePointer<T>.
  auto swiftStructDecl = type->getDecl();
  assert(swiftStructDecl->getName().str() == "UnsafePointer" &&
         "Unexpected bound generic struct in imported Clang module!");
  (void) swiftStructDecl;
  auto args = type->getGenericArgs();
  assert(args.size() == 1 &&
         "UnsafePointer<> should have a single generic argument!");

  // Convert the bound type to the appropriate clang type and return a
  // pointer to that type.
  auto clangCanTy = visit(args.front()->getCanonicalType());
  return getClangASTContext().getPointerType(clangCanTy);
}

clang::CanQualType GenClangType::visitEnumType(CanEnumType type) {
  // Typedef enums have a Clang Decl available.
  auto *decl = type->getDecl();
  if (auto *clangDecl = decl->getClangDecl()) {
    auto *typeDecl = cast<clang::TypeDecl>(clangDecl);
    return typeDecl->getTypeForDecl()->getCanonicalTypeUnqualified();
  }

  // Plain enums just have the raw type set.
  assert(!decl->getRawType() &&
         "Expected raw type for Clang-imported enum!");
  return visit(decl->getRawType()->getCanonicalType());
}

clang::CanQualType GenClangType::visitFunctionType(CanFunctionType type) {
  // FIXME: We hit this building Foundation, with a call on the type
  // encoding path.
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitProtocolCompositionType(
  CanProtocolCompositionType type) {
  // Any protocol composition type in Swift that shows up in an @objc
  // method maps 1-1 to "id <SomeProto>"; with clang's encoding
  // ignoring the protocol list.
  return getClangIdType(getClangASTContext());
}

clang::CanQualType GenClangType::visitBuiltinRawPointerType(
  CanBuiltinRawPointerType type) {
  return getClangASTContext().VoidPtrTy;
}

clang::CanQualType GenClangType::visitBuiltinObjCPointerType(
  CanBuiltinObjCPointerType type) {
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitArchetypeType(CanArchetypeType type) {
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitSILFunctionType(CanSILFunctionType type) {
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitDynamicSelfType(CanDynamicSelfType type) {
  // DynamicSelf is equivalent to 'instancetype', which is treated as
  // 'id' within the Objective-C type system.
  return getClangIdType(getClangASTContext());
}

// FIXME: We should not be seeing these by the time we generate Clang types.
clang::CanQualType GenClangType::visitGenericTypeParamType(
  CanGenericTypeParamType type) {
  return clang::CanQualType();
}

clang::CanQualType GenClangType::visitType(CanType type) {
  llvm_unreachable("Unexpected type in Clang type generation.");

  return clang::CanQualType();
}

const clang::ASTContext &GenClangType::getClangASTContext() const {
  auto *CI = static_cast<ClangImporter*>(&*Context.getClangModuleLoader());
  return CI->getClangASTContext();
}
<commit_msg>Add getUnhandledType() in Clang type generation.<commit_after>//===--- GenClangType.cpp - Swift IR Generation For Types -----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements generation of Clang AST types from Swift AST types
//  for types that are representable in Objective-C interfaces.
//
//===----------------------------------------------------------------------===//

#include "GenClangType.h"

#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/Type.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CanonicalType.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Type.h"

using namespace swift;
using namespace irgen;

static Type getNamedSwiftType(DeclContext *DC, StringRef name) {
  assert(DC && "Unexpected null declaration context!");

  auto &astContext = DC->getASTContext();
  UnqualifiedLookup lookup(astContext.getIdentifier(name), DC, nullptr);
  if (auto type = lookup.getSingleTypeResult())
    return type->getDeclaredType();

  return Type();
}

static const clang::CanQualType getClangBuiltinTypeFromKind(
  const clang::ASTContext &context,
  clang::BuiltinType::Kind kind) {
  switch (kind) {
#define BUILTIN_TYPE(Id, SingletonId) \
  case clang::BuiltinType::Id: return context.SingletonId;
#include "clang/AST/BuiltinTypes.def"
  }
}

static clang::CanQualType getUnhandledType() {
  return clang::CanQualType();
}

static clang::CanQualType getClangSelectorType(
  const clang::ASTContext &clangCtx) {
  return clangCtx.getPointerType(clangCtx.ObjCBuiltinSelTy);
}

static clang::CanQualType getClangMetatypeType(
  const clang::ASTContext &clangCtx) {
  clang::QualType clangType =
    clangCtx.getObjCObjectType(clangCtx.ObjCBuiltinClassTy, 0, 0);
  clangType = clangCtx.getObjCObjectPointerType(clangType);
  return clangCtx.getCanonicalType(clangType);
}

static clang::CanQualType getClangIdType(
  const clang::ASTContext &clangCtx) {
  clang::QualType clangType =
    clangCtx.getObjCObjectType(clangCtx.ObjCBuiltinIdTy, 0, 0);
  clangType = clangCtx.getObjCObjectPointerType(clangType);
  return clangCtx.getCanonicalType(clangType);
}

clang::CanQualType GenClangType::visitStructType(CanStructType type) {
  // First attempt a lookup in our map of imported structs.
  auto *decl = type->getDecl();
  if (auto *clangDecl = decl->getClangDecl()) {
    auto *typeDecl = cast<clang::TypeDecl>(clangDecl);
    return typeDecl->getTypeForDecl()->getCanonicalTypeUnqualified();
  }

  auto const &clangCtx = getClangASTContext();

#define MAP_BUILTIN_TYPE(CLANG_BUILTIN_KIND, SWIFT_TYPE_NAME) {                \
    auto lookupTy = getNamedSwiftType(decl->getDeclContext(),                  \
                                      #SWIFT_TYPE_NAME);                       \
    if (lookupTy && lookupTy->isEqual(type))                                   \
      return getClangBuiltinTypeFromKind(clangCtx,                             \
                                      clang::BuiltinType::CLANG_BUILTIN_KIND); \
  }
#include "swift/ClangImporter/BuiltinMappedTypes.def"
#undef MAP_BUILTIN_TYPE

  // Handle other imported types.

#define CHECK_CLANG_TYPE_MATCH(TYPE, NAME, RESULT)                           \
  if (auto lookupTy = getNamedSwiftType((TYPE)->getDecl()->getDeclContext(), \
                                        (NAME)))                             \
    if (lookupTy->isEqual(type))                                             \
      return (RESULT);

  CHECK_CLANG_TYPE_MATCH(type, "COpaquePointer", clangCtx.VoidPtrTy);
  CHECK_CLANG_TYPE_MATCH(type, "ObjCBool", clangCtx.ObjCBuiltinBoolTy);
  // FIXME: This is sufficient for ABI type generation, but should
  //        probably be const char* for type encoding.
  CHECK_CLANG_TYPE_MATCH(type, "CString", clangCtx.VoidPtrTy);
  CHECK_CLANG_TYPE_MATCH(type, "Selector", getClangSelectorType(clangCtx));
#undef CHECK_CLANG_TYPE_MATCH

  // FIXME: Handle other structs resulting from imported non-struct Clang types.
  return getUnhandledType();
}

clang::CanQualType GenClangType::visitTupleType(CanTupleType type) {
  if (type->getNumElements() == 0)
    return getClangASTContext().VoidTy;

  llvm_unreachable("Unexpected tuple type in Clang type generation!");
  return getUnhandledType();
}

clang::CanQualType GenClangType::visitProtocolType(CanProtocolType type) {
  return getClangIdType(getClangASTContext());
}

clang::CanQualType GenClangType::visitMetatypeType(CanMetatypeType type) {
  return getClangMetatypeType(getClangASTContext());
}

clang::CanQualType GenClangType::visitClassType(CanClassType type) {
  // Any @objc class type in Swift that shows up in an @objc method maps 1-1 to
  // "id <SomeProto>"; with clang's encoding ignoring the protocol list.
  return getClangIdType(getClangASTContext());
}

clang::CanQualType GenClangType::visitBoundGenericStructType(
  CanBoundGenericStructType type) {
  // We only expect UnsafePointer<T>.
  auto swiftStructDecl = type->getDecl();
  assert(swiftStructDecl->getName().str() == "UnsafePointer" &&
         "Unexpected bound generic struct in imported Clang module!");
  (void) swiftStructDecl;
  auto args = type->getGenericArgs();
  assert(args.size() == 1 &&
         "UnsafePointer<> should have a single generic argument!");

  // Convert the bound type to the appropriate clang type and return a
  // pointer to that type.
  auto clangCanTy = visit(args.front()->getCanonicalType());
  return getClangASTContext().getPointerType(clangCanTy);
}

clang::CanQualType GenClangType::visitEnumType(CanEnumType type) {
  // Typedef enums have a Clang Decl available.
  auto *decl = type->getDecl();
  if (auto *clangDecl = decl->getClangDecl()) {
    auto *typeDecl = cast<clang::TypeDecl>(clangDecl);
    return typeDecl->getTypeForDecl()->getCanonicalTypeUnqualified();
  }

  // Plain enums just have the raw type set.
  assert(!decl->getRawType() &&
         "Expected raw type for Clang-imported enum!");
  return visit(decl->getRawType()->getCanonicalType());
}

clang::CanQualType GenClangType::visitFunctionType(CanFunctionType type) {
  // FIXME: We hit this building Foundation, with a call on the type
  // encoding path.
  return getUnhandledType();
}

clang::CanQualType GenClangType::visitProtocolCompositionType(
  CanProtocolCompositionType type) {
  // Any protocol composition type in Swift that shows up in an @objc
  // method maps 1-1 to "id <SomeProto>"; with clang's encoding
  // ignoring the protocol list.
  return getClangIdType(getClangASTContext());
}

clang::CanQualType GenClangType::visitBuiltinRawPointerType(
  CanBuiltinRawPointerType type) {
  return getClangASTContext().VoidPtrTy;
}

clang::CanQualType GenClangType::visitBuiltinObjCPointerType(
  CanBuiltinObjCPointerType type) {
  return getUnhandledType();
}

clang::CanQualType GenClangType::visitArchetypeType(CanArchetypeType type) {
  return getUnhandledType();
}

clang::CanQualType GenClangType::visitSILFunctionType(CanSILFunctionType type) {
  return getUnhandledType();
}

clang::CanQualType GenClangType::visitDynamicSelfType(CanDynamicSelfType type) {
  // DynamicSelf is equivalent to 'instancetype', which is treated as
  // 'id' within the Objective-C type system.
  return getClangIdType(getClangASTContext());
}

// FIXME: We should not be seeing these by the time we generate Clang types.
clang::CanQualType GenClangType::visitGenericTypeParamType(
  CanGenericTypeParamType type) {
  return getUnhandledType();
}

clang::CanQualType GenClangType::visitType(CanType type) {
  llvm_unreachable("Unexpected type in Clang type generation.");

  return getUnhandledType();
}

const clang::ASTContext &GenClangType::getClangASTContext() const {
  auto *CI = static_cast<ClangImporter*>(&*Context.getClangModuleLoader());
  return CI->getClangASTContext();
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */
#include <cassert>
#include <cstdlib>
#include <vector>
#include <zlib.h>
#include "h2o.h"
#include "encode.h"

namespace {
    class brotli_context : public h2o_compress_context_t {
    protected:
        brotli::BrotliCompressor *brotli_;
        brotli::BrotliParams params_;
        std::vector<h2o_iovec_t> bufs_; // all bufs_[nnn].base must be free(3)ed
    public:
        brotli_context() : brotli_(NULL) {
            name = h2o_iovec_init(H2O_STRLIT("br"));
            compress = _compress;
        }
        ~brotli_context() {
            _clear_bufs();
            delete brotli_;
        }
        static void dispose(void *_self) {
            brotli_context *self = static_cast<brotli_context *>(_self);
            self->~brotli_context();
        }
    private:
        void _clear_bufs();
        void _duplicate_last_buf();
        void _compress_block(const void *src, size_t len, bool is_last, bool force_flush);
        void _compress(h2o_iovec_t *inbufs, size_t inbufcnt, int is_final, h2o_iovec_t **outbufs, size_t *outbufcnt);
        static void _compress(h2o_compress_context_t *self, h2o_iovec_t *inbufs, size_t inbufcnt, int is_final,
                              h2o_iovec_t **outbufs, size_t *outbufcnt) {
            static_cast<brotli_context*>(self)->_compress(inbufs, inbufcnt, is_final, outbufs, outbufcnt);
        }
    };
}

void brotli_context::_clear_bufs()
{
    for (std::vector<h2o_iovec_t>::iterator i = bufs_.begin(); i != bufs_.end(); ++i)
        free(i->base);
    bufs_.clear();
}

void brotli_context::_compress_block(const void *src, size_t len, bool is_last, bool force_flush)
{
    uint8_t *output;
    size_t out_size;

    brotli_->CopyInputToRingBuffer(len, static_cast<const uint8_t *>(src));
    bool ret = brotli_->WriteBrotliData(is_last, force_flush, &out_size, &output);
    assert(ret);

    if (out_size != 0)
        bufs_.push_back(h2o_strdup(NULL, reinterpret_cast<const char *>(output), out_size));
}

void brotli_context::_compress(h2o_iovec_t *inbufs, size_t inbufcnt, int is_final, h2o_iovec_t **outbufs, size_t *outbufcnt)
{
    if (brotli_ == NULL)
        brotli_ = new brotli::BrotliCompressor(params_);

    _clear_bufs();

    if (inbufcnt != 0) {
        size_t max_block_size = brotli_->input_block_size();
        for (size_t inbufindex = 0; inbufindex != inbufcnt; ++inbufindex) {
            for (size_t offset = 0; offset != inbufs[inbufindex].len;) {
                size_t block_size = std::min(inbufs[inbufindex].len - offset, max_block_size);
                bool is_last = inbufindex == inbufcnt - 1 && offset + block_size == inbufs[inbufindex].len;
                _compress_block(inbufs[inbufindex].base + offset, block_size, is_last && is_final, is_last && !is_final);
                offset += block_size;
            }
        }
    } else {
        if (is_final)
            _compress_block("", 0, true, false);
    }

    if (is_final) {
        delete brotli_;
        brotli_ = NULL;
    }

    *outbufs = &bufs_.front();
    *outbufcnt = bufs_.size();
}

h2o_compress_context_t *h2o_compress_brotli_open(h2o_mem_pool_t *pool)
{
    brotli_context *ctx = static_cast<brotli_context *>(h2o_mem_alloc_shared(pool, sizeof(*ctx), brotli_context::dispose));
    return new (ctx) brotli_context();
}
<commit_msg>encode as much as possible at once<commit_after>/*
 * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */
#include <cassert>
#include <cstdlib>
#include <vector>
#include <zlib.h>
#include "h2o.h"
#include "encode.h"

namespace {
    class brotli_context : public h2o_compress_context_t {
    protected:
        brotli::BrotliCompressor *brotli_;
        brotli::BrotliParams params_;
        std::vector<h2o_iovec_t> bufs_; // all bufs_[nnn].base must be free(3)ed
    public:
        brotli_context() : brotli_(NULL) {
            name = h2o_iovec_init(H2O_STRLIT("br"));
            compress = _compress;
        }
        ~brotli_context() {
            _clear_bufs();
            delete brotli_;
        }
        static void dispose(void *_self) {
            brotli_context *self = static_cast<brotli_context *>(_self);
            self->~brotli_context();
        }
    private:
        void _clear_bufs();
        void _emit(bool is_last, bool force_flush);
        void _compress(h2o_iovec_t *inbufs, size_t inbufcnt, int is_final, h2o_iovec_t **outbufs, size_t *outbufcnt);
        static void _compress(h2o_compress_context_t *self, h2o_iovec_t *inbufs, size_t inbufcnt, int is_final,
                              h2o_iovec_t **outbufs, size_t *outbufcnt) {
            static_cast<brotli_context*>(self)->_compress(inbufs, inbufcnt, is_final, outbufs, outbufcnt);
        }
    };
}

void brotli_context::_clear_bufs()
{
    for (std::vector<h2o_iovec_t>::iterator i = bufs_.begin(); i != bufs_.end(); ++i)
        free(i->base);
    bufs_.clear();
}

void brotli_context::_emit(bool is_last, bool force_flush)
{
    uint8_t *output;
    size_t out_size;
    bool ret = brotli_->WriteBrotliData(is_last, force_flush, &out_size, &output);
    assert(ret);
    if (out_size != 0)
        bufs_.push_back(h2o_strdup(NULL, reinterpret_cast<const char *>(output), out_size));
}

void brotli_context::_compress(h2o_iovec_t *inbufs, size_t inbufcnt, int is_final, h2o_iovec_t **outbufs, size_t *outbufcnt)
{
    if (brotli_ == NULL)
        brotli_ = new brotli::BrotliCompressor(params_);

    _clear_bufs();

    if (inbufcnt != 0) {
        size_t inbufindex = 0, offset = 0, block_space = brotli_->input_block_size();
        while (inbufindex != inbufcnt) {
            size_t copy_len = std::min(block_space, inbufs[inbufindex].len - offset);
            brotli_->CopyInputToRingBuffer(copy_len, reinterpret_cast<const uint8_t *>(inbufs[inbufindex].base) + offset);
            offset += copy_len;
            if (inbufs[inbufindex].len == offset)
                if (++inbufindex == inbufcnt)
                    break;
            if (block_space == 0) {
                _emit(false, false);
                block_space = brotli_->input_block_size();
            }
        }
        _emit(is_final, !is_final);
    } else {
        if (is_final)
            _emit(true, false);
    }

    if (is_final) {
        delete brotli_;
        brotli_ = NULL;
    }

    *outbufs = &bufs_.front();
    *outbufcnt = bufs_.size();
}

h2o_compress_context_t *h2o_compress_brotli_open(h2o_mem_pool_t *pool)
{
    brotli_context *ctx = static_cast<brotli_context *>(h2o_mem_alloc_shared(pool, sizeof(*ctx), brotli_context::dispose));
    return new (ctx) brotli_context();
}
<|endoftext|>