lib/CodeGen/CGAMPRuntime.cpp
/// Operations:
/// For each reference-typed members, construct temporary object
/// Invoke constructor of index
/// Invoke constructor of the class
/// Invoke operator(index)
For each reference-typed members, construct temporary object
Invoke constructor of index
Invoke constructor of the class
Invoke operator(index)
For each reference - typed members construct temporary object Invoke constructor of index Invoke constructor of the class Invoke operator ( index )
void CGAMPRuntime::EmitTrampolineBody(CodeGenFunction &CGF,
  const FunctionDecl *Trampoline, FunctionArgList& Args) {
  const CXXRecordDecl *ClassDecl = dyn_cast<CXXMethodDecl>(Trampoline)->getParent();
  assert(ClassDecl);
  Address ai = CGF.CreateMemTemp(QualType(ClassDecl->getTypeForDecl(),0));
  if(ClassDecl->getCXXAMPDeserializationConstructor()!=NULL) {
    EmitCXXAMPDeserializer(CGF,Trampoline,Args,ai); 
  }
  CXXMethodDecl *KernelDecl = NULL;
  CXXMethodDecl *KernelDeclNoArg = NULL;
  const FunctionType *MT = NULL;
  QualType IndexTy;
  for (CXXRecordDecl::method_iterator Method = ClassDecl->method_begin(),
                                   MethodEnd = ClassDecl->method_end();
                                     Method != MethodEnd; ++Method) {
    CXXMethodDecl *MethodDecl = *Method;
    if (MethodDecl->isOverloadedOperator() &&
        MethodDecl->getOverloadedOperator() == OO_Call &&
        MethodDecl->hasAttr<CXXAMPRestrictAMPAttr>()) {
      if(MethodDecl->getNumParams() > 1) {
	      continue;
      }
      else if (MethodDecl->getNumParams() == 0) {
         MT = dyn_cast<FunctionType>(MethodDecl->getType().getTypePtr());
         assert(MT);
         KernelDeclNoArg = MethodDecl;
         continue;
      }
      else {
        ParmVarDecl *P = MethodDecl->getParamDecl(0);
        IndexTy = P->getType().getNonReferenceType();
        if (!findValidIndexType(IndexTy))
          continue;
        MT = dyn_cast<FunctionType>(MethodDecl->getType().getTypePtr());
        assert(MT);
        KernelDecl = MethodDecl;
        break;
      }
    }
  }
  if (!KernelDecl && !KernelDeclNoArg) {
    CGF.CGM.getDiags().Report(ClassDecl->getLocation(), diag::err_amp_ill_formed_functor);
    return;
  }
  CXXMethodDecl *Kernel = (KernelDecl != NULL) ? KernelDecl : KernelDeclNoArg;
  llvm::FunctionType *fnType =
    CGM.getTypes().GetFunctionType(CGM.getTypes().arrangeCXXMethodDeclaration(Kernel));
  llvm::Constant *fnAddr = CGM.GetAddrOfFunction(Kernel, fnType);
  CallArgList KArgs;
  KArgs.add(RValue::get(ai.getPointer()), Kernel->getThisType());
  if (KernelDecl) {
    Address index = CGF.CreateMemTemp(IndexTy);
    CXXMethodDecl *IndexConstructor = findValidIndexType(IndexTy);
    assert(IndexConstructor);
    if (!CGF.getLangOpts().AMPCPU) {
      if (CXXConstructorDecl *Constructor =
            dyn_cast <CXXConstructorDecl>(IndexConstructor)) {
        CXXConstructExpr *CXXCE = CXXConstructExpr::Create(CGM.getContext(), 
                                                           IndexTy,
                                                           SourceLocation(),
                                                           Constructor,
                                                           false,
                                                           ArrayRef<Expr*>(),
                                                           false, false, false, false,
                                                           CXXConstructExpr::CK_Complete,
                                                           SourceLocation());
        auto currAVS = AggValueSlot::forAddr(index, IndexTy.getQualifiers(),
                            		                               AggValueSlot::IsNotDestructed,
                            		                               AggValueSlot::DoesNotNeedGCBarriers,
                            		                               AggValueSlot::IsNotAliased,
                            		                               AggValueSlot::DoesNotOverlap);
        CGF.EmitCXXConstructorCall(Constructor, Ctor_Complete, false, false, currAVS, CXXCE);
      } else {
        llvm::FunctionType *indexInitType = CGM.getTypes().GetFunctionType(
                                               CGM.getTypes().arrangeCXXMethodDeclaration(IndexConstructor));
        llvm::Constant *indexInitAddr = CGM.GetAddrOfFunction(IndexConstructor, indexInitType);
        CGF.EmitCXXMemberOrOperatorCall(IndexConstructor, CGCallee::forDirect(indexInitAddr),
                                        ReturnValueSlot(), index.getPointer(), 0, 
                                        QualType(), nullptr, nullptr);
      }
    }
    KArgs.add(RValue::get(index.getPointer()),
        CGF.getContext().getLValueReferenceType(IndexTy));
  }
  const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionCall(KArgs, MT, false);
  CGF.EmitCall(FnInfo, CGCallee::forDirect(fnAddr), ReturnValueSlot(), KArgs);
  CGM.getTargetCodeGenInfo().setTargetAttributes(Kernel, CGF.CurFn, CGM);
}
void CGAMPRuntime :: EmitTrampolineBody ( CodeGenFunction & CGF , const FunctionDecl * Trampoline , FunctionArgList & Args ) { const CXXRecordDecl * ClassDecl = dyn_cast < CXXMethodDecl > ( Trampoline ) -> getParent ( ) ; assert ( ClassDecl ) ; Address ai = CGF . CreateMemTemp ( QualType ( ClassDecl -> getTypeForDecl ( ) , 0 ) ) ; if ( ClassDecl -> getCXXAMPDeserializationConstructor ( ) != NULL ) { EmitCXXAMPDeserializer ( CGF , Trampoline , Args , ai ) ; } CXXMethodDecl * KernelDecl = NULL ; CXXMethodDecl * KernelDeclNoArg = NULL ; const FunctionType * MT = NULL ; QualType IndexTy ; for ( CXXRecordDecl :: method_iterator Method = ClassDecl -> method_begin ( ) , MethodEnd = ClassDecl -> method_end ( ) ; Method != MethodEnd ; ++ Method ) { CXXMethodDecl * MethodDecl = * Method ; if ( MethodDecl -> isOverloadedOperator ( ) && MethodDecl -> getOverloadedOperator ( ) == OO_Call && MethodDecl -> hasAttr < CXXAMPRestrictAMPAttr > ( ) ) { if ( MethodDecl -> getNumParams ( ) > 1 ) { continue ; } else if ( MethodDecl -> getNumParams ( ) == 0 ) { MT = dyn_cast < FunctionType > ( MethodDecl -> getType ( ) . getTypePtr ( ) ) ; assert ( MT ) ; KernelDeclNoArg = MethodDecl ; continue ; } else { ParmVarDecl * P = MethodDecl -> getParamDecl ( 0 ) ; IndexTy = P -> getType ( ) . getNonReferenceType ( ) ; if ( ! findValidIndexType ( IndexTy ) ) continue ; MT = dyn_cast < FunctionType > ( MethodDecl -> getType ( ) . getTypePtr ( ) ) ; assert ( MT ) ; KernelDecl = MethodDecl ; break ; } } } if ( ! KernelDecl && ! KernelDeclNoArg ) { CGF . CGM . getDiags ( ) . Report ( ClassDecl -> getLocation ( ) , diag :: err_amp_ill_formed_functor ) ; return ; } CXXMethodDecl * Kernel = ( KernelDecl != NULL ) ? KernelDecl : KernelDeclNoArg ; llvm :: FunctionType * fnType = CGM . getTypes ( ) . GetFunctionType ( CGM . getTypes ( ) . arrangeCXXMethodDeclaration ( Kernel ) ) ; llvm :: Constant * fnAddr = CGM . GetAddrOfFunction ( Kernel , fnType ) ; CallArgList KArgs ; KArgs . add ( RValue :: get ( ai . getPointer ( ) ) , Kernel -> getThisType ( ) ) ; if ( KernelDecl ) { Address index = CGF . CreateMemTemp ( IndexTy ) ; CXXMethodDecl * IndexConstructor = findValidIndexType ( IndexTy ) ; assert ( IndexConstructor ) ; if ( ! CGF . getLangOpts ( ) . AMPCPU ) { if ( CXXConstructorDecl * Constructor = dyn_cast < CXXConstructorDecl > ( IndexConstructor ) ) { CXXConstructExpr * CXXCE = CXXConstructExpr :: Create ( CGM . getContext ( ) , IndexTy , SourceLocation ( ) , Constructor , false , ArrayRef < Expr * > ( ) , false , false , false , false , CXXConstructExpr :: CK_Complete , SourceLocation ( ) ) ; auto currAVS = AggValueSlot :: forAddr ( index , IndexTy . getQualifiers ( ) , AggValueSlot :: IsNotDestructed , AggValueSlot :: DoesNotNeedGCBarriers , AggValueSlot :: IsNotAliased , AggValueSlot :: DoesNotOverlap ) ; CGF . EmitCXXConstructorCall ( Constructor , Ctor_Complete , false , false , currAVS , CXXCE ) ; } else { llvm :: FunctionType * indexInitType = CGM . getTypes ( ) . GetFunctionType ( CGM . getTypes ( ) . arrangeCXXMethodDeclaration ( IndexConstructor ) ) ; llvm :: Constant * indexInitAddr = CGM . GetAddrOfFunction ( IndexConstructor , indexInitType ) ; CGF . EmitCXXMemberOrOperatorCall ( IndexConstructor , CGCallee :: forDirect ( indexInitAddr ) , ReturnValueSlot ( ) , index . getPointer ( ) , 0 , QualType ( ) , nullptr , nullptr ) ; } } KArgs . add ( RValue :: get ( index . getPointer ( ) ) , CGF . getContext ( ) . getLValueReferenceType ( IndexTy ) ) ; } const CGFunctionInfo & FnInfo = CGM . getTypes ( ) . arrangeFreeFunctionCall ( KArgs , MT , false ) ; CGF . EmitCall ( FnInfo , CGCallee :: forDirect ( fnAddr ) , ReturnValueSlot ( ) , KArgs ) ; CGM . getTargetCodeGenInfo ( ) . setTargetAttributes ( Kernel , CGF . CurFn , CGM ) ; }
Operations:
For each reference-typed members, construct temporary object
Invoke constructor of index
Invoke constructor of the class
Invoke operator(index)
Operations : For each reference - typed members construct temporary object Invoke constructor of index Invoke constructor of the class Invoke operator ( index )
// Allocate "this" // Locate the constructor to call // Locate the type of Concurrency::index<1> // Locate the operator to call //Check types. // in case we couldn't find any kernel declarator // raise error // Invoke this->operator(index) // Prepate the operator() to call // Prepare argument // this // Allocate Index // Locate the constructor to call // Emit code to call the Concurrency::index<1>::__cxxamp_opencl_index() /*ImplicitParam=*/ /*CallExpr=*/ /*RtlArgs=*/ // *index // index is of reference type of IndexTy.