Skip to content
CodeGenModule.cpp 82.5 KiB
Newer Older
    if (cast<FunctionDecl>(D)->getDescribedFunctionTemplate())
      return;
    EmitGlobal(cast<FunctionDecl>(D));
    break;
      
  case Decl::Var:
    EmitGlobal(cast<VarDecl>(D));
  case Decl::Namespace:
    EmitNamespace(cast<NamespaceDecl>(D));
  case Decl::UsingShadow:
  case Decl::ClassTemplate:
  case Decl::FunctionTemplate:
  case Decl::NamespaceAlias:
  case Decl::CXXConstructor:
    // Skip function templates
    if (cast<FunctionDecl>(D)->getDescribedFunctionTemplate())
      return;
      
    EmitCXXConstructors(cast<CXXConstructorDecl>(D));
    break;
  case Decl::CXXDestructor:
    EmitCXXDestructors(cast<CXXDestructorDecl>(D));
    break;

  case Decl::StaticAssert:
    // Nothing to do.
    break;

  // Forward declarations, no (immediate) code generation.
  case Decl::ObjCClass:
  case Decl::ObjCForwardProtocol:
  
    case Decl::ObjCCategory: {
      ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
      if (CD->IsClassExtension() && CD->hasSynthBitfield())
        Context.ResetObjCLayout(CD->getClassInterface());
      break;
    }
      
  case Decl::ObjCProtocol:
    Runtime->GenerateProtocol(cast<ObjCProtocolDecl>(D));
    break;

  case Decl::ObjCCategoryImpl:
    // Categories have properties but don't support synthesize so we
    // can ignore them here.
    Runtime->GenerateCategory(cast<ObjCCategoryImplDecl>(D));
    break;

  case Decl::ObjCImplementation: {
    ObjCImplementationDecl *OMD = cast<ObjCImplementationDecl>(D);
    if (Features.ObjCNonFragileABI2 && OMD->hasSynthBitfield())
      Context.ResetObjCLayout(OMD->getClassInterface());
    EmitObjCPropertyImplementations(OMD);
    EmitObjCIvarInitializations(OMD);
    Runtime->GenerateClass(OMD);
  case Decl::ObjCMethod: {
    ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(D);
    // If this is not a prototype, emit the body.
      CodeGenFunction(*this).GenerateObjCMethod(OMD);
    break;
  }
  case Decl::ObjCCompatibleAlias:
    // compatibility-alias is a directive and has no code gen.
  case Decl::LinkageSpec:
    EmitLinkageSpec(cast<LinkageSpecDecl>(D));
    break;

  case Decl::FileScopeAsm: {
    FileScopeAsmDecl *AD = cast<FileScopeAsmDecl>(D);
    llvm::StringRef AsmString = AD->getAsmString()->getString();
    const std::string &S = getModule().getModuleInlineAsm();
    if (S.empty())
      getModule().setModuleInlineAsm(AsmString);
    else
      getModule().setModuleInlineAsm(S + '\n' + AsmString.str());
Mike Stump's avatar
Mike Stump committed
    // Make sure we handled everything we should, every other kind is a
    // non-top-level decl.  FIXME: Would be nice to have an isTopLevelDeclKind
    // function. Need to recode Decl::Kind to do that easily.
    assert(isa<TypeDecl>(D) && "Unsupported decl kind");
  }
}

/// Turns the given pointer into a constant.
static llvm::Constant *GetPointerConstant(llvm::LLVMContext &Context,
                                          const void *Ptr) {
  uintptr_t PtrInt = reinterpret_cast<uintptr_t>(Ptr);
  const llvm::Type *i64 = llvm::Type::getInt64Ty(Context);
  return llvm::ConstantInt::get(i64, PtrInt);
}

static void EmitGlobalDeclMetadata(CodeGenModule &CGM,
                                   llvm::NamedMDNode *&GlobalMetadata,
                                   GlobalDecl D,
                                   llvm::GlobalValue *Addr) {
  if (!GlobalMetadata)
    GlobalMetadata =
      CGM.getModule().getOrInsertNamedMetadata("clang.global.decl.ptrs");

  // TODO: should we report variant information for ctors/dtors?
  llvm::Value *Ops[] = {
    Addr,
    GetPointerConstant(CGM.getLLVMContext(), D.getDecl())
  };
  GlobalMetadata->addOperand(llvm::MDNode::get(CGM.getLLVMContext(), Ops, 2));
}

/// Emits metadata nodes associating all the global values in the
/// current module with the Decls they came from.  This is useful for
/// projects using IR gen as a subroutine.
///
/// Since there's currently no way to associate an MDNode directly
/// with an llvm::GlobalValue, we create a global named metadata
/// with the name 'clang.global.decl.ptrs'.
void CodeGenModule::EmitDeclMetadata() {
  llvm::NamedMDNode *GlobalMetadata = 0;

  // StaticLocalDeclMap
  for (llvm::DenseMap<GlobalDecl,llvm::StringRef>::iterator
         I = MangledDeclNames.begin(), E = MangledDeclNames.end();
       I != E; ++I) {
    llvm::GlobalValue *Addr = getModule().getNamedValue(I->second);
    EmitGlobalDeclMetadata(*this, GlobalMetadata, I->first, Addr);
  }
}

/// Emits metadata nodes for all the local variables in the current
/// function.
void CodeGenFunction::EmitDeclMetadata() {
  if (LocalDeclMap.empty()) return;

  llvm::LLVMContext &Context = getLLVMContext();

  // Find the unique metadata ID for this name.
  unsigned DeclPtrKind = Context.getMDKindID("clang.decl.ptr");

  llvm::NamedMDNode *GlobalMetadata = 0;

  for (llvm::DenseMap<const Decl*, llvm::Value*>::iterator
         I = LocalDeclMap.begin(), E = LocalDeclMap.end(); I != E; ++I) {
    const Decl *D = I->first;
    llvm::Value *Addr = I->second;

    if (llvm::AllocaInst *Alloca = dyn_cast<llvm::AllocaInst>(Addr)) {
      llvm::Value *DAddr = GetPointerConstant(getLLVMContext(), D);
      Alloca->setMetadata(DeclPtrKind, llvm::MDNode::get(Context, &DAddr, 1));
    } else if (llvm::GlobalValue *GV = dyn_cast<llvm::GlobalValue>(Addr)) {
      GlobalDecl GD = GlobalDecl(cast<VarDecl>(D));
      EmitGlobalDeclMetadata(CGM, GlobalMetadata, GD, GV);
    }
  }
}

///@name Custom Runtime Function Interfaces
///@{
//
// FIXME: These can be eliminated once we can have clients just get the required
// AST nodes from the builtin tables.

llvm::Constant *CodeGenModule::getBlockObjectDispose() {
  if (BlockObjectDispose)
    return BlockObjectDispose;

  // If we saw an explicit decl, use that.
  if (BlockObjectDisposeDecl) {
    return BlockObjectDispose = GetAddrOfFunction(
      BlockObjectDisposeDecl,
      getTypes().GetFunctionType(BlockObjectDisposeDecl));
  }

  // Otherwise construct the function by hand.
  const llvm::FunctionType *FTy;
  std::vector<const llvm::Type*> ArgTys;
  const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext);
  ArgTys.push_back(llvm::Type::getInt32Ty(VMContext));
  FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
  return BlockObjectDispose =
    CreateRuntimeFunction(FTy, "_Block_object_dispose");
}

llvm::Constant *CodeGenModule::getBlockObjectAssign() {
  if (BlockObjectAssign)
    return BlockObjectAssign;

  // If we saw an explicit decl, use that.
  if (BlockObjectAssignDecl) {
    return BlockObjectAssign = GetAddrOfFunction(
      BlockObjectAssignDecl,
      getTypes().GetFunctionType(BlockObjectAssignDecl));
  }

  // Otherwise construct the function by hand.
  const llvm::FunctionType *FTy;
  std::vector<const llvm::Type*> ArgTys;
  const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext);
  ArgTys.push_back(Int8PtrTy);
  ArgTys.push_back(Int8PtrTy);
  ArgTys.push_back(llvm::Type::getInt32Ty(VMContext));
  FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
  return BlockObjectAssign =
    CreateRuntimeFunction(FTy, "_Block_object_assign");
}

llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() {
  if (NSConcreteGlobalBlock)
    return NSConcreteGlobalBlock;

  // If we saw an explicit decl, use that.
  if (NSConcreteGlobalBlockDecl) {
    return NSConcreteGlobalBlock = GetAddrOfGlobalVar(
      NSConcreteGlobalBlockDecl,
      getTypes().ConvertType(NSConcreteGlobalBlockDecl->getType()));
  }

  // Otherwise construct the variable by hand.
  return NSConcreteGlobalBlock =
    CreateRuntimeVariable(Int8PtrTy, "_NSConcreteGlobalBlock");
}

llvm::Constant *CodeGenModule::getNSConcreteStackBlock() {
  if (NSConcreteStackBlock)
    return NSConcreteStackBlock;

  // If we saw an explicit decl, use that.
  if (NSConcreteStackBlockDecl) {
    return NSConcreteStackBlock = GetAddrOfGlobalVar(
      NSConcreteStackBlockDecl,
      getTypes().ConvertType(NSConcreteStackBlockDecl->getType()));
  }

  // Otherwise construct the variable by hand.
  return NSConcreteStackBlock =
    CreateRuntimeVariable(Int8PtrTy, "_NSConcreteStackBlock");