Esempio n. 1
0
bool TransferFunctions::checkImageAccess(Expr *E, MemoryAccess curMemAcc) {
  // discard implicit casts and paren expressions
  E = E->IgnoreParenImpCasts();

  // match Image(), Accessor(), Mask(), and Domain() calls
  if (isa<CXXOperatorCallExpr>(E)) {
    CXXOperatorCallExpr *COCE = dyn_cast<CXXOperatorCallExpr>(E);

    if (isa<MemberExpr>(COCE->getArg(0))) {
      MemberExpr *ME = dyn_cast<MemberExpr>(COCE->getArg(0));

      if (isa<FieldDecl>(ME->getMemberDecl())) {
        FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
        MemoryAccess memAcc = KS.imagesToAccess[FD];
        MemoryAccessDetail memAccDetail = KS.imagesToAccessDetail[FD];

        memAcc = (MemoryAccess) (memAcc|curMemAcc);
        KS.imagesToAccess[FD] = memAcc;

        // access to Image
        if (KS.compilerClasses.isTypeOfTemplateClass(FD->getType(),
              KS.compilerClasses.Image)) {
          KS.Diags.Report(E->getLocStart(), KS.DiagIDImageAccess) <<
            FD->getNameAsString();

          exit(EXIT_FAILURE);
        }

        // access to Accessor
        if (KS.compilerClasses.isTypeOfTemplateClass(FD->getType(),
              KS.compilerClasses.Accessor)) {
          if (curMemAcc & READ_ONLY) KS.num_img_loads++;
          if (curMemAcc & WRITE_ONLY) KS.num_img_stores++;

          switch (COCE->getNumArgs()) {
            default:
              break;
            case 1:
              memAccDetail = (MemoryAccessDetail) (memAccDetail|NO_STRIDE);
              if (KS.kernelType < PointOperator) KS.kernelType = PointOperator;
              break;
            case 2:
              // TODO: check for Mask or Domain as parameter and check if we
              // need only STRIDE_X or STRIDE_Y
              memAccDetail = (MemoryAccessDetail) (memAccDetail|STRIDE_XY);
              if (KS.kernelType < LocalOperator) KS.kernelType = LocalOperator;
              break;
            case 3:
              memAccDetail = (MemoryAccessDetail)
                (memAccDetail|checkStride(COCE->getArg(1), COCE->getArg(2)));
              if (memAccDetail > NO_STRIDE && KS.kernelType < LocalOperator) {
                KS.kernelType = LocalOperator;
              }
              break;
          }
          KS.imagesToAccessDetail[FD] = memAccDetail;

          return true;
        }

        // access to Mask
        if (KS.compilerClasses.isTypeOfTemplateClass(FD->getType(),
              KS.compilerClasses.Mask)) {
          if (curMemAcc & READ_ONLY) KS.num_mask_loads++;
          if (curMemAcc & WRITE_ONLY) KS.num_mask_stores++;

          if (KS.inLambdaFunction) {
            // TODO: check for Mask as parameter and check if we need only
            // STRIDE_X or STRIDE_Y
            memAccDetail = (MemoryAccessDetail) (memAccDetail|STRIDE_XY);
            if (KS.kernelType < LocalOperator) KS.kernelType = LocalOperator;
          } else {
            assert(COCE->getNumArgs()==3 &&
                "Mask access requires x and y parameters!");
            memAccDetail = (MemoryAccessDetail)
              (memAccDetail|checkStride(COCE->getArg(1), COCE->getArg(2)));
            if (memAccDetail > NO_STRIDE && KS.kernelType < LocalOperator) {
              KS.kernelType = LocalOperator;
            }
          }
          KS.imagesToAccessDetail[FD] = memAccDetail;

          return false;
        }

        // access to Domain
        if (KS.compilerClasses.isTypeOfClass(FD->getType(),
              KS.compilerClasses.Domain)) {
          if (curMemAcc & READ_ONLY) KS.num_mask_loads++;
          if (curMemAcc & WRITE_ONLY) KS.num_mask_stores++;

          if (KS.inLambdaFunction) {
            // TODO: check for Domain as parameter and check if we need only
            // STRIDE_X or STRIDE_Y
            memAccDetail = (MemoryAccessDetail) (memAccDetail|STRIDE_XY);
            if (KS.kernelType < LocalOperator) KS.kernelType = LocalOperator;
          } else {
            assert(COCE->getNumArgs()==3 &&
                "Domain access requires x and y parameters!");
            memAccDetail = (MemoryAccessDetail)
              (memAccDetail|checkStride(COCE->getArg(1), COCE->getArg(2)));
            if (memAccDetail > NO_STRIDE && KS.kernelType < LocalOperator) {
              KS.kernelType = LocalOperator;
            }
          }
          KS.imagesToAccessDetail[FD] = memAccDetail;

          return false;
        }
      }
    }
  }

  // match Image->getPixel(), output(), and outputAtPixel() calls
  if (isa<CXXMemberCallExpr>(E)) {
    CXXMemberCallExpr *CMCE = dyn_cast<CXXMemberCallExpr>(E);

    if (isa<MemberExpr>(CMCE->getCallee())) {
      MemberExpr *ME = dyn_cast<MemberExpr>(CMCE->getCallee());

      if (isa<MemberExpr>(ME->getBase())) {
        MemberExpr *MEAcc = dyn_cast<MemberExpr>(ME->getBase());

        if (isa<FieldDecl>(MEAcc->getMemberDecl())) {
          FieldDecl *FD = dyn_cast<FieldDecl>(MEAcc->getMemberDecl());

          // Image
          if (KS.compilerClasses.isTypeOfTemplateClass(FD->getType(),
                KS.compilerClasses.Image)) {
            KS.Diags.Report(E->getLocStart(), KS.DiagIDImageAccess) <<
              FD->getNameAsString();

            exit(EXIT_FAILURE);
          }

          // Accessor
          if (KS.compilerClasses.isTypeOfTemplateClass(FD->getType(),
                KS.compilerClasses.Accessor)) {
            // Accessor->getPixel()
            if (ME->getMemberNameInfo().getAsString()=="getPixel") {
              MemoryAccess memAcc = KS.imagesToAccess[FD];
              MemoryAccessDetail memAccDetail = KS.imagesToAccessDetail[FD];

              memAcc = (MemoryAccess) (memAcc|curMemAcc);
              KS.imagesToAccess[FD] = memAcc;

              memAccDetail = (MemoryAccessDetail) (memAccDetail|USER_XY);
              KS.imagesToAccessDetail[FD] = memAccDetail;
              KS.kernelType = UserOperator;

              if (curMemAcc & READ_ONLY) KS.num_img_loads++;
              if (curMemAcc & WRITE_ONLY) KS.num_img_stores++;

              return true;
            }
          }
        }
      }

      // output()
      if (ME->getMemberNameInfo().getAsString()=="output") {
        if (curMemAcc & READ_ONLY) KS.num_img_loads++;
        if (curMemAcc & WRITE_ONLY) KS.num_img_stores++;
        MemoryAccessDetail cur = KS.outputAccessDetail;
        KS.outputAccessDetail = (MemoryAccessDetail)(cur|NO_STRIDE);
        if (KS.kernelType < PointOperator) KS.kernelType = PointOperator;

        return true;
      }

      // outputAtPixel()
      if (ME->getMemberNameInfo().getAsString()=="outputAtPixel") {
        if (curMemAcc & READ_ONLY) KS.num_img_loads++;
        if (curMemAcc & WRITE_ONLY) KS.num_img_stores++;
        MemoryAccessDetail cur = KS.outputAccessDetail;
        KS.outputAccessDetail = (MemoryAccessDetail)(cur|USER_XY);
        KS.kernelType = UserOperator;

        return true;
      }
    }
  }

  return false;
}